nfsproc.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:15k
源码类别:

Linux/Unix编程

开发平台:

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. svc_reserve(rqstp, (19<<2) + argp->count + 4);
  128. resp->count = argp->count;
  129. nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
  130.   argp->offset,
  131.   (char *) buffer,
  132.   &resp->count);
  133. return nfserr;
  134. }
  135. /*
  136.  * Write data to a file
  137.  * N.B. After this call resp->fh needs an fh_put
  138.  */
  139. static int
  140. nfsd_proc_write(struct svc_rqst *rqstp, struct nfsd_writeargs *argp,
  141. struct nfsd_attrstat  *resp)
  142. {
  143. int nfserr;
  144. int stable = 1;
  145. dprintk("nfsd: WRITE    %s %d bytes at %dn",
  146. SVCFH_fmt(&argp->fh),
  147. argp->len, argp->offset);
  148. nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
  149.    argp->offset,
  150.    argp->data,
  151.    argp->len,
  152.    &stable);
  153. return nfserr;
  154. }
  155. /*
  156.  * CREATE processing is complicated. The keyword here is `overloaded.'
  157.  * The parent directory is kept locked between the check for existence
  158.  * and the actual create() call in compliance with VFS protocols.
  159.  * N.B. After this call _both_ argp->fh and resp->fh need an fh_put
  160.  */
  161. static int
  162. nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
  163.  struct nfsd_diropres   *resp)
  164. {
  165. svc_fh *dirfhp = &argp->fh;
  166. svc_fh *newfhp = &resp->fh;
  167. struct iattr *attr = &argp->attrs;
  168. struct inode *inode;
  169. struct dentry *dchild;
  170. int nfserr, type, mode;
  171. dev_t rdev = NODEV;
  172. dprintk("nfsd: CREATE   %s %.*sn",
  173. SVCFH_fmt(dirfhp), argp->len, argp->name);
  174. /* First verify the parent file handle */
  175. nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_EXEC);
  176. if (nfserr)
  177. goto done; /* must fh_put dirfhp even on error */
  178. /* Check for MAY_WRITE in nfsd_create if necessary */
  179. nfserr = nfserr_acces;
  180. if (!argp->len)
  181. goto done;
  182. nfserr = nfserr_exist;
  183. if (isdotent(argp->name, argp->len))
  184. goto done;
  185. fh_lock(dirfhp);
  186. dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len);
  187. if (IS_ERR(dchild)) {
  188. nfserr = nfserrno(PTR_ERR(dchild));
  189. goto out_unlock;
  190. }
  191. fh_init(newfhp, NFS_FHSIZE);
  192. nfserr = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp);
  193. if (!nfserr && !dchild->d_inode)
  194. nfserr = nfserr_noent;
  195. if (nfserr) {
  196. if (nfserr != nfserr_noent)
  197. goto out_unlock;
  198. /*
  199.  * If the new file handle wasn't verified, we can't tell
  200.  * whether the file exists or not. Time to bail ...
  201.  */
  202. nfserr = nfserr_acces;
  203. if (!newfhp->fh_dentry) {
  204. printk(KERN_WARNING 
  205. "nfsd_proc_create: file handle not verifiedn");
  206. goto out_unlock;
  207. }
  208. }
  209. inode = newfhp->fh_dentry->d_inode;
  210. /* Unfudge the mode bits */
  211. if (attr->ia_valid & ATTR_MODE) { 
  212. type = attr->ia_mode & S_IFMT;
  213. mode = attr->ia_mode & ~S_IFMT;
  214. if (!type) {
  215. /* no type, so if target exists, assume same as that,
  216.  * else assume a file */
  217. if (inode) {
  218. type = inode->i_mode & S_IFMT;
  219. switch(type) {
  220. case S_IFCHR:
  221. case S_IFBLK:
  222. /* reserve rdev for later checking */
  223. attr->ia_size = inode->i_rdev;
  224. attr->ia_valid |= ATTR_SIZE;
  225. /* FALLTHROUGH */
  226. case S_IFIFO:
  227. /* this is probably a permission check..
  228.  * at least IRIX implements perm checking on
  229.  *   echo thing > device-special-file-or-pipe
  230.  * by doing a CREATE with type==0
  231.  */
  232. nfserr = nfsd_permission(newfhp->fh_export,
  233.  newfhp->fh_dentry,
  234.  MAY_WRITE|_NFSD_IRIX_BOGOSITY);
  235. if (nfserr && nfserr != nfserr_rofs)
  236. goto out_unlock;
  237. }
  238. } else
  239. type = S_IFREG;
  240. }
  241. } else if (inode) {
  242. type = inode->i_mode & S_IFMT;
  243. mode = inode->i_mode & ~S_IFMT;
  244. } else {
  245. type = S_IFREG;
  246. mode = 0; /* ??? */
  247. }
  248. attr->ia_valid |= ATTR_MODE;
  249. attr->ia_mode = mode;
  250. /* Special treatment for non-regular files according to the
  251.  * gospel of sun micro
  252.  */
  253. if (type != S_IFREG) {
  254. int is_borc = 0;
  255. u32 size = attr->ia_size;
  256. rdev = (dev_t) size;
  257. if (type != S_IFBLK && type != S_IFCHR) {
  258. rdev = 0;
  259. } else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) {
  260. /* If you think you've seen the worst, grok this. */
  261. type = S_IFIFO;
  262. } else if (size != rdev) {
  263. /* dev got truncated because of 16bit Linux dev_t */
  264. nfserr = nfserr_inval;
  265. goto out_unlock;
  266. } else {
  267. /* Okay, char or block special */
  268. is_borc = 1;
  269. }
  270. /* we've used the SIZE information, so discard it */
  271. attr->ia_valid &= ~ATTR_SIZE;
  272. /* Make sure the type and device matches */
  273. nfserr = nfserr_exist;
  274. if (inode && (type != (inode->i_mode & S_IFMT) || 
  275.     (is_borc && inode->i_rdev != rdev)))
  276. goto out_unlock;
  277. }
  278. nfserr = 0;
  279. if (!inode) {
  280. /* File doesn't exist. Create it and set attrs */
  281. nfserr = nfsd_create(rqstp, dirfhp, argp->name, argp->len,
  282. attr, type, rdev, newfhp);
  283. } else if (type == S_IFREG) {
  284. dprintk("nfsd:   existing %s, valid=%x, size=%ldn",
  285. argp->name, attr->ia_valid, (long) attr->ia_size);
  286. /* File already exists. We ignore all attributes except
  287.  * size, so that creat() behaves exactly like
  288.  * open(..., O_CREAT|O_TRUNC|O_WRONLY).
  289.  */
  290. attr->ia_valid &= ATTR_SIZE;
  291. if (attr->ia_valid)
  292. nfserr = nfsd_setattr(rqstp, newfhp, attr, 0, (time_t)0);
  293. }
  294. out_unlock:
  295. /* We don't really need to unlock, as fh_put does it. */
  296. fh_unlock(dirfhp);
  297. done:
  298. fh_put(dirfhp);
  299. return nfserr;
  300. }
  301. static int
  302. nfsd_proc_remove(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
  303.  void        *resp)
  304. {
  305. int nfserr;
  306. dprintk("nfsd: REMOVE   %s %.*sn", SVCFH_fmt(&argp->fh),
  307. argp->len, argp->name);
  308. /* Unlink. -SIFDIR means file must not be a directory */
  309. nfserr = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR, argp->name, argp->len);
  310. fh_put(&argp->fh);
  311. return nfserr;
  312. }
  313. static int
  314. nfsd_proc_rename(struct svc_rqst *rqstp, struct nfsd_renameargs *argp,
  315.     void         *resp)
  316. {
  317. int nfserr;
  318. dprintk("nfsd: RENAME   %s %.*s -> n",
  319. SVCFH_fmt(&argp->ffh), argp->flen, argp->fname);
  320. dprintk("nfsd:        ->  %s %.*sn",
  321. SVCFH_fmt(&argp->tfh), argp->tlen, argp->tname);
  322. nfserr = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen,
  323.     &argp->tfh, argp->tname, argp->tlen);
  324. fh_put(&argp->ffh);
  325. fh_put(&argp->tfh);
  326. return nfserr;
  327. }
  328. static int
  329. nfsd_proc_link(struct svc_rqst *rqstp, struct nfsd_linkargs *argp,
  330. void     *resp)
  331. {
  332. int nfserr;
  333. dprintk("nfsd: LINK     %s ->n",
  334. SVCFH_fmt(&argp->ffh));
  335. dprintk("nfsd:    %s %.*sn",
  336. SVCFH_fmt(&argp->tfh),
  337. argp->tlen,
  338. argp->tname);
  339. nfserr = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen,
  340.   &argp->ffh);
  341. fh_put(&argp->ffh);
  342. fh_put(&argp->tfh);
  343. return nfserr;
  344. }
  345. static int
  346. nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp,
  347.           void   *resp)
  348. {
  349. struct svc_fh newfh;
  350. int nfserr;
  351. dprintk("nfsd: SYMLINK  %s %.*s -> %.*sn",
  352. SVCFH_fmt(&argp->ffh), argp->flen, argp->fname,
  353. argp->tlen, argp->tname);
  354. fh_init(&newfh, NFS_FHSIZE);
  355. /*
  356.  * Create the link, look up new file and set attrs.
  357.  */
  358. nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
  359.  argp->tname, argp->tlen,
  360.    &newfh, &argp->attrs);
  361. fh_put(&argp->ffh);
  362. fh_put(&newfh);
  363. return nfserr;
  364. }
  365. /*
  366.  * Make directory. This operation is not idempotent.
  367.  * N.B. After this call resp->fh needs an fh_put
  368.  */
  369. static int
  370. nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
  371. struct nfsd_diropres   *resp)
  372. {
  373. int nfserr;
  374. dprintk("nfsd: MKDIR    %s %.*sn", SVCFH_fmt(&argp->fh), argp->len, argp->name);
  375. if (resp->fh.fh_dentry) {
  376. printk(KERN_WARNING
  377. "nfsd_proc_mkdir: response already verified??n");
  378. }
  379. argp->attrs.ia_valid &= ~ATTR_SIZE;
  380. fh_init(&resp->fh, NFS_FHSIZE);
  381. nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
  382.     &argp->attrs, S_IFDIR, 0, &resp->fh);
  383. fh_put(&argp->fh);
  384. return nfserr;
  385. }
  386. /*
  387.  * Remove a directory
  388.  */
  389. static int
  390. nfsd_proc_rmdir(struct svc_rqst *rqstp, struct nfsd_diropargs *argp,
  391.   void       *resp)
  392. {
  393. int nfserr;
  394. dprintk("nfsd: RMDIR    %s %.*sn", SVCFH_fmt(&argp->fh), argp->len, argp->name);
  395. nfserr = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, argp->name, argp->len);
  396. fh_put(&argp->fh);
  397. return nfserr;
  398. }
  399. /*
  400.  * Read a portion of a directory.
  401.  */
  402. static int
  403. nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp,
  404.   struct nfsd_readdirres  *resp)
  405. {
  406. u32 * buffer;
  407. int nfserr, count;
  408. dprintk("nfsd: READDIR  %s %d bytes at %dn",
  409. SVCFH_fmt(&argp->fh),
  410. argp->count, argp->cookie);
  411. /* Reserve buffer space for status */
  412. svcbuf_reserve(&rqstp->rq_resbuf, &buffer, &count, 1);
  413. /* Shrink to the client read size */
  414. if (count > (argp->count >> 2))
  415. count = argp->count >> 2;
  416. /* Make sure we've room for the NULL ptr & eof flag */
  417. count -= 2;
  418. if (count < 0)
  419. count = 0;
  420. /* Read directory and encode entries on the fly */
  421. nfserr = nfsd_readdir(rqstp, &argp->fh, (loff_t) argp->cookie, 
  422.       nfssvc_encode_entry,
  423.       buffer, &count, NULL);
  424. resp->count = count;
  425. fh_put(&argp->fh);
  426. return nfserr;
  427. }
  428. /*
  429.  * Get file system info
  430.  */
  431. static int
  432. nfsd_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle   *argp,
  433.   struct nfsd_statfsres *resp)
  434. {
  435. int nfserr;
  436. dprintk("nfsd: STATFS   %sn", SVCFH_fmt(&argp->fh));
  437. nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
  438. fh_put(&argp->fh);
  439. return nfserr;
  440. }
  441. /*
  442.  * NFSv2 Server procedures.
  443.  * Only the results of non-idempotent operations are cached.
  444.  */
  445. #define nfsd_proc_none NULL
  446. #define nfssvc_release_none NULL
  447. struct nfsd_void { int dummy; };
  448. #define PROC(name, argt, rest, relt, cache, respsize)
  449.  { (svc_procfunc) nfsd_proc_##name,
  450.    (kxdrproc_t) nfssvc_decode_##argt,
  451.    (kxdrproc_t) nfssvc_encode_##rest,
  452.    (kxdrproc_t) nfssvc_release_##relt,
  453.    sizeof(struct nfsd_##argt),
  454.    sizeof(struct nfsd_##rest),
  455.    0,
  456.    cache,
  457.    respsize,        
  458.  }
  459. #define ST 1 /* status */
  460. #define FH 8 /* filehandle */
  461. #define AT 18 /* attributes */
  462. struct svc_procedure nfsd_procedures2[18] = {
  463.   PROC(null,  void, void, none, RC_NOCACHE, ST),
  464.   PROC(getattr,  fhandle, attrstat, fhandle, RC_NOCACHE, ST+AT),
  465.   PROC(setattr,  sattrargs, attrstat, fhandle, RC_REPLBUFF, ST+AT),
  466.   PROC(none,  void, void, none, RC_NOCACHE, ST),
  467.   PROC(lookup,  diropargs, diropres, fhandle, RC_NOCACHE, ST+FH+AT),
  468.   PROC(readlink, fhandle, readlinkres, none, RC_NOCACHE, ST+1+256),
  469.   PROC(read,  readargs, readres, fhandle, RC_NOCACHE, ST+AT+1+NFSSVC_MAXBLKSIZE),
  470.   PROC(none,  void, void, none, RC_NOCACHE, ST),
  471.   PROC(write,  writeargs, attrstat, fhandle, RC_REPLBUFF, ST+AT),
  472.   PROC(create,  createargs, diropres, fhandle, RC_REPLBUFF, ST+FH+AT),
  473.   PROC(remove,  diropargs, void, none, RC_REPLSTAT, ST),
  474.   PROC(rename,  renameargs, void, none, RC_REPLSTAT, ST),
  475.   PROC(link,  linkargs, void, none, RC_REPLSTAT, ST),
  476.   PROC(symlink,  symlinkargs, void, none, RC_REPLSTAT, ST),
  477.   PROC(mkdir,  createargs, diropres, fhandle, RC_REPLBUFF, ST+FH+AT),
  478.   PROC(rmdir,  diropargs, void, none, RC_REPLSTAT, ST),
  479.   PROC(readdir,  readdirargs, readdirres, none, RC_REPLBUFF, 0),
  480.   PROC(statfs,  fhandle, statfsres, none, RC_NOCACHE, ST+5),
  481. };
  482. /*
  483.  * Map errnos to NFS errnos.
  484.  */
  485. int
  486. nfserrno (int errno)
  487. {
  488. static struct {
  489. int nfserr;
  490. int syserr;
  491. } nfs_errtbl[] = {
  492. { nfs_ok, 0 },
  493. { nfserr_perm, -EPERM },
  494. { nfserr_noent, -ENOENT },
  495. { nfserr_io, -EIO },
  496. { nfserr_nxio, -ENXIO },
  497. { nfserr_acces, -EACCES },
  498. { nfserr_exist, -EEXIST },
  499. { nfserr_xdev, -EXDEV },
  500. { nfserr_mlink, -EMLINK },
  501. { nfserr_nodev, -ENODEV },
  502. { nfserr_notdir, -ENOTDIR },
  503. { nfserr_isdir, -EISDIR },
  504. { nfserr_inval, -EINVAL },
  505. { nfserr_fbig, -EFBIG },
  506. { nfserr_nospc, -ENOSPC },
  507. { nfserr_rofs, -EROFS },
  508. { nfserr_mlink, -EMLINK },
  509. { nfserr_nametoolong, -ENAMETOOLONG },
  510. { nfserr_notempty, -ENOTEMPTY },
  511. #ifdef EDQUOT
  512. { nfserr_dquot, -EDQUOT },
  513. #endif
  514. { nfserr_stale, -ESTALE },
  515. { nfserr_dropit, -ENOMEM },
  516. { -1, -EIO }
  517. };
  518. int i;
  519. for (i = 0; nfs_errtbl[i].nfserr != -1; i++) {
  520. if (nfs_errtbl[i].syserr == errno)
  521. return nfs_errtbl[i].nfserr;
  522. }
  523. printk (KERN_INFO "nfsd: non-standard errno: %dn", errno);
  524. return nfserr_io;
  525. }