nfsproc.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:15k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * nfsproc2.c Process version 2 NFS requests.
  3.  * linux/fs/nfsd/nfs2proc.c
  4.  * 
  5.  * Process version 2 NFS requests.
  6.  *
  7.  * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
  8.  */
  9. #include <linux/linkage.h>
  10. #include <linux/sched.h>
  11. #include <linux/errno.h>
  12. #include <linux/locks.h>
  13. #include <linux/fs.h>
  14. #include <linux/stat.h>
  15. #include <linux/fcntl.h>
  16. #include <linux/net.h>
  17. #include <linux/in.h>
  18. #include <linux/version.h>
  19. #include <linux/unistd.h>
  20. #include <linux/slab.h>
  21. #include <linux/sunrpc/svc.h>
  22. #include <linux/nfsd/nfsd.h>
  23. #include <linux/nfsd/cache.h>
  24. #include <linux/nfsd/xdr.h>
  25. typedef struct svc_rqst svc_rqst;
  26. typedef struct svc_buf svc_buf;
  27. #define NFSDDBG_FACILITY NFSDDBG_PROC
  28. static void
  29. svcbuf_reserve(struct svc_buf *buf, u32 **ptr, int *len, int nr)
  30. {
  31. *ptr = buf->buf + nr;
  32. *len = buf->buflen - buf->len - nr;
  33. }
  34. static int
  35. nfsd_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
  36. {
  37. return nfs_ok;
  38. }
  39. /*
  40.  * Get a file's attributes
  41.  * N.B. After this call resp->fh needs an fh_put
  42.  */
  43. static int
  44. nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle  *argp,
  45.   struct nfsd_attrstat *resp)
  46. {
  47. dprintk("nfsd: GETATTR  %sn", SVCFH_fmt(&argp->fh));
  48. fh_copy(&resp->fh, &argp->fh);
  49. return fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
  50. }
  51. /*
  52.  * Set a file's attributes
  53.  * N.B. After this call resp->fh needs an fh_put
  54.  */
  55. static int
  56. nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp,
  57.   struct nfsd_attrstat  *resp)
  58. {
  59. dprintk("nfsd: SETATTR  %s, valid=%x, size=%ldn",
  60. SVCFH_fmt(&argp->fh),
  61. argp->attrs.ia_valid, (long) argp->attrs.ia_size);
  62. fh_copy(&resp->fh, &argp->fh);
  63. return nfsd_setattr(rqstp, &resp->fh, &argp->attrs,0, (time_t)0);
  64. }
  65. /*
  66.  * Look up a path name component
  67.  * Note: the dentry in the resp->fh may be negative if the file
  68.  * doesn't exist yet.
  69.  * N.B. After this call resp->fh needs an fh_put
  70.  */
  71. static int
  72. nfsd_proc_lookup(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
  73.  struct nfsd_diropres  *resp)
  74. {
  75. int nfserr;
  76. dprintk("nfsd: LOOKUP   %s %.*sn",
  77. SVCFH_fmt(&argp->fh), argp->len, argp->name);
  78. fh_init(&resp->fh, NFS_FHSIZE);
  79. nfserr = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
  80.  &resp->fh);
  81. fh_put(&argp->fh);
  82. return nfserr;
  83. }
  84. /*
  85.  * Read a symlink.
  86.  */
  87. static int
  88. nfsd_proc_readlink(struct svc_rqst *rqstp, struct nfsd_fhandle     *argp,
  89.    struct nfsd_readlinkres *resp)
  90. {
  91. u32 *path;
  92. int dummy, nfserr;
  93. dprintk("nfsd: READLINK %sn", SVCFH_fmt(&argp->fh));
  94. /* Reserve room for status and path length */
  95. svcbuf_reserve(&rqstp->rq_resbuf, &path, &dummy, 2);
  96. /* Read the symlink. */
  97. resp->len = NFS_MAXPATHLEN;
  98. nfserr = nfsd_readlink(rqstp, &argp->fh, (char *) path, &resp->len);
  99. fh_put(&argp->fh);
  100. return nfserr;
  101. }
  102. /*
  103.  * Read a portion of a file.
  104.  * N.B. After this call resp->fh needs an fh_put
  105.  */
  106. static int
  107. nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
  108.        struct nfsd_readres  *resp)
  109. {
  110. u32 * buffer;
  111. int nfserr, avail;
  112. dprintk("nfsd: READ    %s %d bytes at %dn",
  113. SVCFH_fmt(&argp->fh),
  114. argp->count, argp->offset);
  115. /* Obtain buffer pointer for payload. 19 is 1 word for
  116.  * status, 17 words for fattr, and 1 word for the byte count.
  117.  */
  118. svcbuf_reserve(&rqstp->rq_resbuf, &buffer, &avail, 19);
  119. if ((avail << 2) < argp->count) {
  120. printk(KERN_NOTICE
  121. "oversized read request from %08x:%d (%d bytes)n",
  122. ntohl(rqstp->rq_addr.sin_addr.s_addr),
  123. ntohs(rqstp->rq_addr.sin_port),
  124. argp->count);
  125. argp->count = avail << 2;
  126. }
  127. resp->count = argp->count;
  128. nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
  129.   argp->offset,
  130.   (char *) buffer,
  131.   &resp->count);
  132. return nfserr;
  133. }
  134. /*
  135.  * Write data to a file
  136.  * N.B. After this call resp->fh needs an fh_put
  137.  */
  138. static int
  139. nfsd_proc_write(struct svc_rqst *rqstp, struct nfsd_writeargs *argp,
  140. struct nfsd_attrstat  *resp)
  141. {
  142. int nfserr;
  143. int stable = 1;
  144. dprintk("nfsd: WRITE    %s %d bytes at %dn",
  145. SVCFH_fmt(&argp->fh),
  146. argp->len, argp->offset);
  147. nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
  148.    argp->offset,
  149.    argp->data,
  150.    argp->len,
  151.    &stable);
  152. return nfserr;
  153. }
  154. /*
  155.  * CREATE processing is complicated. The keyword here is `overloaded.'
  156.  * The parent directory is kept locked between the check for existence
  157.  * and the actual create() call in compliance with VFS protocols.
  158.  * N.B. After this call _both_ argp->fh and resp->fh need an fh_put
  159.  */
  160. static int
  161. nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
  162.  struct nfsd_diropres   *resp)
  163. {
  164. svc_fh *dirfhp = &argp->fh;
  165. svc_fh *newfhp = &resp->fh;
  166. struct iattr *attr = &argp->attrs;
  167. struct inode *inode;
  168. struct dentry *dchild;
  169. int nfserr, type, mode;
  170. dev_t rdev = NODEV;
  171. dprintk("nfsd: CREATE   %s %.*sn",
  172. SVCFH_fmt(dirfhp), argp->len, argp->name);
  173. /* First verify the parent file handle */
  174. nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_EXEC);
  175. if (nfserr)
  176. goto done; /* must fh_put dirfhp even on error */
  177. /* Check for MAY_WRITE in nfsd_create if necessary */
  178. nfserr = nfserr_acces;
  179. if (!argp->len)
  180. goto done;
  181. nfserr = nfserr_exist;
  182. if (isdotent(argp->name, argp->len))
  183. goto done;
  184. fh_lock(dirfhp);
  185. dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len);
  186. if (IS_ERR(dchild)) {
  187. nfserr = nfserrno(PTR_ERR(dchild));
  188. goto out_unlock;
  189. }
  190. fh_init(newfhp, NFS_FHSIZE);
  191. nfserr = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp);
  192. if (!nfserr && !dchild->d_inode)
  193. nfserr = nfserr_noent;
  194. if (nfserr) {
  195. if (nfserr != nfserr_noent)
  196. goto out_unlock;
  197. /*
  198.  * If the new file handle wasn't verified, we can't tell
  199.  * whether the file exists or not. Time to bail ...
  200.  */
  201. nfserr = nfserr_acces;
  202. if (!newfhp->fh_dentry) {
  203. printk(KERN_WARNING 
  204. "nfsd_proc_create: file handle not verifiedn");
  205. goto out_unlock;
  206. }
  207. }
  208. inode = newfhp->fh_dentry->d_inode;
  209. /* Unfudge the mode bits */
  210. if (attr->ia_valid & ATTR_MODE) { 
  211. type = attr->ia_mode & S_IFMT;
  212. mode = attr->ia_mode & ~S_IFMT;
  213. if (!type) {
  214. /* no type, so if target exists, assume same as that,
  215.  * else assume a file */
  216. if (inode) {
  217. type = inode->i_mode & S_IFMT;
  218. switch(type) {
  219. case S_IFCHR:
  220. case S_IFBLK:
  221. /* reserve rdev for later checking */
  222. attr->ia_size = inode->i_rdev;
  223. attr->ia_valid |= ATTR_SIZE;
  224. /* FALLTHROUGH */
  225. case S_IFIFO:
  226. /* this is probably a permission check..
  227.  * at least IRIX implements perm checking on
  228.  *   echo thing > device-special-file-or-pipe
  229.  * by does a CREATE with type==0
  230.  */
  231. nfserr = nfsd_permission(newfhp->fh_export,
  232.  newfhp->fh_dentry,
  233.  MAY_WRITE);
  234. if (nfserr && nfserr != nfserr_rofs)
  235. goto out_unlock;
  236. }
  237. } else
  238. type = S_IFREG;
  239. }
  240. } else if (inode) {
  241. type = inode->i_mode & S_IFMT;
  242. mode = inode->i_mode & ~S_IFMT;
  243. } else {
  244. type = S_IFREG;
  245. mode = 0; /* ??? */
  246. }
  247. attr->ia_valid |= ATTR_MODE;
  248. attr->ia_mode = mode;
  249. /* Special treatment for non-regular files according to the
  250.  * gospel of sun micro
  251.  */
  252. if (type != S_IFREG) {
  253. int is_borc = 0;
  254. u32 size = attr->ia_size;
  255. rdev = (dev_t) size;
  256. if (type != S_IFBLK && type != S_IFCHR) {
  257. rdev = 0;
  258. } else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) {
  259. /* If you think you've seen the worst, grok this. */
  260. type = S_IFIFO;
  261. } else if (size != rdev) {
  262. /* dev got truncated because of 16bit Linux dev_t */
  263. nfserr = nfserr_inval;
  264. goto out_unlock;
  265. } else {
  266. /* Okay, char or block special */
  267. is_borc = 1;
  268. }
  269. /* we've used the SIZE information, so discard it */
  270. attr->ia_valid &= ~ATTR_SIZE;
  271. /* Make sure the type and device matches */
  272. nfserr = nfserr_exist;
  273. if (inode && (type != (inode->i_mode & S_IFMT) || 
  274.     (is_borc && inode->i_rdev != rdev)))
  275. goto out_unlock;
  276. }
  277. nfserr = 0;
  278. if (!inode) {
  279. /* File doesn't exist. Create it and set attrs */
  280. nfserr = nfsd_create(rqstp, dirfhp, argp->name, argp->len,
  281. attr, type, rdev, newfhp);
  282. } else if (type == S_IFREG) {
  283. dprintk("nfsd:   existing %s, valid=%x, size=%ldn",
  284. argp->name, attr->ia_valid, (long) attr->ia_size);
  285. /* File already exists. We ignore all attributes except
  286.  * size, so that creat() behaves exactly like
  287.  * open(..., O_CREAT|O_TRUNC|O_WRONLY).
  288.  */
  289. attr->ia_valid &= ATTR_SIZE;
  290. if (attr->ia_valid)
  291. nfserr = nfsd_setattr(rqstp, newfhp, attr, 0, (time_t)0);
  292. }
  293. out_unlock:
  294. /* We don't really need to unlock, as fh_put does it. */
  295. fh_unlock(dirfhp);
  296. done:
  297. fh_put(dirfhp);
  298. return nfserr;
  299. }
  300. static int
  301. nfsd_proc_remove(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
  302.  void        *resp)
  303. {
  304. int nfserr;
  305. dprintk("nfsd: REMOVE   %s %.*sn", SVCFH_fmt(&argp->fh),
  306. argp->len, argp->name);
  307. /* Unlink. -SIFDIR means file must not be a directory */
  308. nfserr = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR, argp->name, argp->len);
  309. fh_put(&argp->fh);
  310. return nfserr;
  311. }
  312. static int
  313. nfsd_proc_rename(struct svc_rqst *rqstp, struct nfsd_renameargs *argp,
  314.     void         *resp)
  315. {
  316. int nfserr;
  317. dprintk("nfsd: RENAME   %s %.*s -> n",
  318. SVCFH_fmt(&argp->ffh), argp->flen, argp->fname);
  319. dprintk("nfsd:        ->  %s %.*sn",
  320. SVCFH_fmt(&argp->tfh), argp->tlen, argp->tname);
  321. nfserr = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen,
  322.     &argp->tfh, argp->tname, argp->tlen);
  323. fh_put(&argp->ffh);
  324. fh_put(&argp->tfh);
  325. return nfserr;
  326. }
  327. static int
  328. nfsd_proc_link(struct svc_rqst *rqstp, struct nfsd_linkargs *argp,
  329. void     *resp)
  330. {
  331. int nfserr;
  332. dprintk("nfsd: LINK     %s ->n",
  333. SVCFH_fmt(&argp->ffh));
  334. dprintk("nfsd:    %s %.*sn",
  335. SVCFH_fmt(&argp->tfh),
  336. argp->tlen,
  337. argp->tname);
  338. nfserr = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen,
  339.   &argp->ffh);
  340. fh_put(&argp->ffh);
  341. fh_put(&argp->tfh);
  342. return nfserr;
  343. }
  344. static int
  345. nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp,
  346.           void   *resp)
  347. {
  348. struct svc_fh newfh;
  349. int nfserr;
  350. dprintk("nfsd: SYMLINK  %s %.*s -> %.*sn",
  351. SVCFH_fmt(&argp->ffh), argp->flen, argp->fname,
  352. argp->tlen, argp->tname);
  353. fh_init(&newfh, NFS_FHSIZE);
  354. /*
  355.  * Create the link, look up new file and set attrs.
  356.  */
  357. nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
  358.  argp->tname, argp->tlen,
  359.    &newfh, &argp->attrs);
  360. fh_put(&argp->ffh);
  361. fh_put(&newfh);
  362. return nfserr;
  363. }
  364. /*
  365.  * Make directory. This operation is not idempotent.
  366.  * N.B. After this call resp->fh needs an fh_put
  367.  */
  368. static int
  369. nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
  370. struct nfsd_diropres   *resp)
  371. {
  372. int nfserr;
  373. dprintk("nfsd: MKDIR    %s %.*sn", SVCFH_fmt(&argp->fh), argp->len, argp->name);
  374. if (resp->fh.fh_dentry) {
  375. printk(KERN_WARNING
  376. "nfsd_proc_mkdir: response already verified??n");
  377. }
  378. argp->attrs.ia_valid &= ~ATTR_SIZE;
  379. fh_init(&resp->fh, NFS_FHSIZE);
  380. nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
  381.     &argp->attrs, S_IFDIR, 0, &resp->fh);
  382. fh_put(&argp->fh);
  383. return nfserr;
  384. }
  385. /*
  386.  * Remove a directory
  387.  */
  388. static int
  389. nfsd_proc_rmdir(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
  390.   void       *resp)
  391. {
  392. int nfserr;
  393. dprintk("nfsd: RMDIR    %s %.*sn", SVCFH_fmt(&argp->fh), argp->len, argp->name);
  394. nfserr = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, argp->name, argp->len);
  395. fh_put(&argp->fh);
  396. return nfserr;
  397. }
  398. /*
  399.  * Read a portion of a directory.
  400.  */
  401. static int
  402. nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp,
  403.   struct nfsd_readdirres  *resp)
  404. {
  405. u32 * buffer;
  406. int nfserr, count;
  407. dprintk("nfsd: READDIR  %s %d bytes at %dn",
  408. SVCFH_fmt(&argp->fh),
  409. argp->count, argp->cookie);
  410. /* Reserve buffer space for status */
  411. svcbuf_reserve(&rqstp->rq_resbuf, &buffer, &count, 1);
  412. /* Shrink to the client read size */
  413. if (count > (argp->count >> 2))
  414. count = argp->count >> 2;
  415. /* Make sure we've room for the NULL ptr & eof flag */
  416. count -= 2;
  417. if (count < 0)
  418. count = 0;
  419. /* Read directory and encode entries on the fly */
  420. nfserr = nfsd_readdir(rqstp, &argp->fh, (loff_t) argp->cookie, 
  421.       nfssvc_encode_entry,
  422.       buffer, &count, NULL);
  423. resp->count = count;
  424. fh_put(&argp->fh);
  425. return nfserr;
  426. }
  427. /*
  428.  * Get file system info
  429.  */
  430. static int
  431. nfsd_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle   *argp,
  432.   struct nfsd_statfsres *resp)
  433. {
  434. int nfserr;
  435. dprintk("nfsd: STATFS   %sn", SVCFH_fmt(&argp->fh));
  436. nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
  437. fh_put(&argp->fh);
  438. return nfserr;
  439. }
  440. /*
  441.  * NFSv2 Server procedures.
  442.  * Only the results of non-idempotent operations are cached.
  443.  */
  444. #define nfsd_proc_none NULL
  445. #define nfssvc_release_none NULL
  446. struct nfsd_void { int dummy; };
  447. #define PROC(name, argt, rest, relt, cache)
  448.  { (svc_procfunc) nfsd_proc_##name,
  449.    (kxdrproc_t) nfssvc_decode_##argt,
  450.    (kxdrproc_t) nfssvc_encode_##rest,
  451.    (kxdrproc_t) nfssvc_release_##relt,
  452.    sizeof(struct nfsd_##argt),
  453.    sizeof(struct nfsd_##rest),
  454.    0,
  455.    cache
  456.  }
  457. struct svc_procedure nfsd_procedures2[18] = {
  458.   PROC(null,  void, void, none, RC_NOCACHE),
  459.   PROC(getattr,  fhandle, attrstat, fhandle, RC_NOCACHE),
  460.   PROC(setattr,  sattrargs, attrstat, fhandle, RC_REPLBUFF),
  461.   PROC(none,  void, void, none, RC_NOCACHE),
  462.   PROC(lookup,  diropargs, diropres, fhandle, RC_NOCACHE),
  463.   PROC(readlink, fhandle, readlinkres, none, RC_NOCACHE),
  464.   PROC(read,  readargs, readres, fhandle, RC_NOCACHE),
  465.   PROC(none,  void, void, none, RC_NOCACHE),
  466.   PROC(write,  writeargs, attrstat, fhandle, RC_REPLBUFF),
  467.   PROC(create,  createargs, diropres, fhandle, RC_REPLBUFF),
  468.   PROC(remove,  diropargs, void, none, RC_REPLSTAT),
  469.   PROC(rename,  renameargs, void, none, RC_REPLSTAT),
  470.   PROC(link,  linkargs, void, none, RC_REPLSTAT),
  471.   PROC(symlink,  symlinkargs, void, none, RC_REPLSTAT),
  472.   PROC(mkdir,  createargs, diropres, fhandle, RC_REPLBUFF),
  473.   PROC(rmdir,  diropargs, void, none, RC_REPLSTAT),
  474.   PROC(readdir,  readdirargs, readdirres, none, RC_REPLBUFF),
  475.   PROC(statfs,  fhandle, statfsres, none, RC_NOCACHE),
  476. };
  477. /*
  478.  * Map errnos to NFS errnos.
  479.  */
  480. int
  481. nfserrno (int errno)
  482. {
  483. static struct {
  484. int nfserr;
  485. int syserr;
  486. } nfs_errtbl[] = {
  487. { nfs_ok, 0 },
  488. { nfserr_perm, -EPERM },
  489. { nfserr_noent, -ENOENT },
  490. { nfserr_io, -EIO },
  491. { nfserr_nxio, -ENXIO },
  492. { nfserr_acces, -EACCES },
  493. { nfserr_exist, -EEXIST },
  494. { nfserr_xdev, -EXDEV },
  495. { nfserr_mlink, -EMLINK },
  496. { nfserr_nodev, -ENODEV },
  497. { nfserr_notdir, -ENOTDIR },
  498. { nfserr_isdir, -EISDIR },
  499. { nfserr_inval, -EINVAL },
  500. { nfserr_fbig, -EFBIG },
  501. { nfserr_nospc, -ENOSPC },
  502. { nfserr_rofs, -EROFS },
  503. { nfserr_mlink, -EMLINK },
  504. { nfserr_nametoolong, -ENAMETOOLONG },
  505. { nfserr_notempty, -ENOTEMPTY },
  506. #ifdef EDQUOT
  507. { nfserr_dquot, -EDQUOT },
  508. #endif
  509. { nfserr_stale, -ESTALE },
  510. { nfserr_dropit, -ENOMEM },
  511. { -1, -EIO }
  512. };
  513. int i;
  514. for (i = 0; nfs_errtbl[i].nfserr != -1; i++) {
  515. if (nfs_errtbl[i].syserr == errno)
  516. return nfs_errtbl[i].nfserr;
  517. }
  518. printk (KERN_INFO "nfsd: non-standard errno: %dn", errno);
  519. return nfserr_io;
  520. }