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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * linux/fs/nfsd/nfsfh.c
  3.  *
  4.  * NFS server file handle treatment.
  5.  *
  6.  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  7.  * Portions Copyright (C) 1999 G. Allen Morris III <gam3@acm.org>
  8.  * Extensive rewrite by Neil Brown <neilb@cse.unsw.edu.au> Southern-Spring 1999
  9.  */
  10. #include <linux/sched.h>
  11. #include <linux/slab.h>
  12. #include <linux/fs.h>
  13. #include <linux/unistd.h>
  14. #include <linux/string.h>
  15. #include <linux/stat.h>
  16. #include <linux/dcache.h>
  17. #include <asm/pgtable.h>
  18. #include <linux/sunrpc/svc.h>
  19. #include <linux/nfsd/nfsd.h>
  20. #define NFSDDBG_FACILITY NFSDDBG_FH
  21. #define NFSD_PARANOIA 1
  22. /* #define NFSD_DEBUG_VERBOSE 1 */
  23. static int nfsd_nr_verified;
  24. static int nfsd_nr_put;
  25. struct nfsd_getdents_callback {
  26. char *name; /* name that was found. It already points to a buffer NAME_MAX+1 is size */
  27. unsigned long ino; /* the inum we are looking for */
  28. int found; /* inode matched? */
  29. int sequence; /* sequence counter */
  30. };
  31. /*
  32.  * A rather strange filldir function to capture
  33.  * the name matching the specified inode number.
  34.  */
  35. static int filldir_one(void * __buf, const char * name, int len,
  36. loff_t pos, ino_t ino, unsigned int d_type)
  37. {
  38. struct nfsd_getdents_callback *buf = __buf;
  39. int result = 0;
  40. buf->sequence++;
  41. #ifdef NFSD_DEBUG_VERBOSE
  42. dprintk("filldir_one: seq=%d, ino=%ld, name=%sn", buf->sequence, ino, name);
  43. #endif
  44. if (buf->ino == ino) {
  45. memcpy(buf->name, name, len);
  46. buf->name[len] = '';
  47. buf->found = 1;
  48. result = -1;
  49. }
  50. return result;
  51. }
  52. /**
  53.  * nfsd_get_name - default nfsd_operations->get_name function
  54.  * @dentry: the directory in which to find a name
  55.  * @name:   a pointer to a %NAME_MAX+1 char buffer to store the name
  56.  * @child:  the dentry for the child directory.
  57.  *
  58.  * calls readdir on the parent until it finds an entry with
  59.  * the same inode number as the child, and returns that.
  60.  */
  61. static int nfsd_get_name(struct dentry *dentry, char *name,
  62. struct dentry *child)
  63. {
  64. struct inode *dir = dentry->d_inode;
  65. int error;
  66. struct file file;
  67. struct nfsd_getdents_callback buffer;
  68. error = -ENOTDIR;
  69. if (!dir || !S_ISDIR(dir->i_mode))
  70. goto out;
  71. error = -EINVAL;
  72. if (!dir->i_fop)
  73. goto out;
  74. /*
  75.  * Open the directory ...
  76.  */
  77. error = init_private_file(&file, dentry, FMODE_READ);
  78. if (error)
  79. goto out;
  80. error = -EINVAL;
  81. if (!file.f_op->readdir)
  82. goto out_close;
  83. buffer.name = name;
  84. buffer.ino = child->d_inode->i_ino;
  85. buffer.found = 0;
  86. buffer.sequence = 0;
  87. while (1) {
  88. int old_seq = buffer.sequence;
  89. error = vfs_readdir(&file, filldir_one, &buffer);
  90. if (error < 0)
  91. break;
  92. error = 0;
  93. if (buffer.found)
  94. break;
  95. error = -ENOENT;
  96. if (old_seq == buffer.sequence)
  97. break;
  98. }
  99. out_close:
  100. if (file.f_op->release)
  101. file.f_op->release(dir, &file);
  102. out:
  103. return error;
  104. }
  105. /* this should be provided by each filesystem in an nfsd_operations interface as
  106.  * iget isn't really the right interface
  107.  */
  108. static struct dentry *nfsd_iget(struct super_block *sb, unsigned long ino, __u32 generation)
  109. {
  110. /* iget isn't really right if the inode is currently unallocated!!
  111.  * This should really all be done inside each filesystem
  112.  *
  113.  * ext2fs' read_inode has been strengthed to return a bad_inode if the inode
  114.  *   had been deleted.
  115.  *
  116.  * Currently we don't know the generation for parent directory, so a generation
  117.  * of 0 means "accept any"
  118.  */
  119. struct inode *inode;
  120. struct list_head *lp;
  121. struct dentry *result;
  122. if (ino == 0)
  123. return ERR_PTR(-ESTALE);
  124. inode = iget(sb, ino);
  125. if (inode == NULL)
  126. return ERR_PTR(-ENOMEM);
  127. if (is_bad_inode(inode)
  128.     || (generation && inode->i_generation != generation)
  129. ) {
  130. /* we didn't find the right inode.. */
  131. dprintk("fh_verify: Inode %lu, Bad count: %d %d or version  %u %un",
  132. inode->i_ino,
  133. inode->i_nlink, atomic_read(&inode->i_count),
  134. inode->i_generation,
  135. generation);
  136. iput(inode);
  137. return ERR_PTR(-ESTALE);
  138. }
  139. /* now to find a dentry.
  140.  * If possible, get a well-connected one
  141.  */
  142. spin_lock(&dcache_lock);
  143. for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) {
  144. result = list_entry(lp,struct dentry, d_alias);
  145. if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
  146. dget_locked(result);
  147. result->d_vfs_flags |= DCACHE_REFERENCED;
  148. spin_unlock(&dcache_lock);
  149. iput(inode);
  150. return result;
  151. }
  152. }
  153. spin_unlock(&dcache_lock);
  154. result = d_alloc_root(inode);
  155. if (result == NULL) {
  156. iput(inode);
  157. return ERR_PTR(-ENOMEM);
  158. }
  159. result->d_flags |= DCACHE_NFSD_DISCONNECTED;
  160. return result;
  161. }
  162. static struct dentry *nfsd_get_dentry(struct super_block *sb, __u32 *fh,
  163.      int len, int fhtype, int parent)
  164. {
  165. if (sb->s_op->fh_to_dentry)
  166. return sb->s_op->fh_to_dentry(sb, fh, len, fhtype, parent);
  167. switch (fhtype) {
  168. case 1:
  169. if (len < 2)
  170. break;
  171. if (parent)
  172. break;
  173. return nfsd_iget(sb, fh[0], fh[1]);
  174. case 2:
  175. if (len < 3)
  176. break;
  177. if (parent)
  178. return nfsd_iget(sb,fh[2],0);
  179. return nfsd_iget(sb,fh[0],fh[1]);
  180. default: break;
  181. }
  182. return ERR_PTR(-EINVAL);
  183. }
  184. /* this routine links an IS_ROOT dentry into the dcache tree.  It gains "parent"
  185.  * as a parent and "name" as a name
  186.  * It should possibly go in dcache.c
  187.  */
  188. int d_splice(struct dentry *target, struct dentry *parent, struct qstr *name)
  189. {
  190. struct dentry *tdentry;
  191. #ifdef NFSD_PARANOIA
  192. if (!IS_ROOT(target))
  193. printk("nfsd: d_splice with no-root target: %s/%sn", parent->d_name.name, name->name);
  194. if (!(target->d_flags & DCACHE_NFSD_DISCONNECTED))
  195. printk("nfsd: d_splice with non-DISCONNECTED target: %s/%sn", parent->d_name.name, name->name);
  196. #endif
  197. tdentry = d_alloc(parent, name);
  198. if (tdentry == NULL)
  199. return -ENOMEM;
  200. d_move(target, tdentry);
  201. /* tdentry will have been made a "child" of target (the parent of target)
  202.  * make it an IS_ROOT instead
  203.  */
  204. spin_lock(&dcache_lock);
  205. list_del_init(&tdentry->d_child);
  206. tdentry->d_parent = tdentry;
  207. spin_unlock(&dcache_lock);
  208. d_rehash(target);
  209. dput(tdentry);
  210. /* if parent is properly connected, then we can assert that
  211.  * the children are connected, but it must be a singluar (non-forking)
  212.  * branch
  213.  */
  214. if (!(parent->d_flags & DCACHE_NFSD_DISCONNECTED)) {
  215. while (target) {
  216. target->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
  217. parent = target;
  218. spin_lock(&dcache_lock);
  219. if (list_empty(&parent->d_subdirs))
  220. target = NULL;
  221. else {
  222. target = list_entry(parent->d_subdirs.next, struct dentry, d_child);
  223. #ifdef NFSD_PARANOIA
  224. /* must be only child */
  225. if (target->d_child.next != &parent->d_subdirs
  226.     || target->d_child.prev != &parent->d_subdirs)
  227. printk("nfsd: d_splice found non-singular disconnected branch: %s/%sn",
  228.        parent->d_name.name, target->d_name.name);
  229. #endif
  230. }
  231. spin_unlock(&dcache_lock);
  232. }
  233. }
  234. return 0;
  235. }
  236. /* this routine finds the dentry of the parent of a given directory
  237.  * it should be in the filesystem accessed by nfsd_operations
  238.  * it assumes lookup("..") works.
  239.  */
  240. struct dentry *nfsd_findparent(struct dentry *child)
  241. {
  242. struct dentry *tdentry, *pdentry;
  243. tdentry = d_alloc(child, &(const struct qstr) {"..", 2, 0});
  244. if (!tdentry)
  245. return ERR_PTR(-ENOMEM);
  246. /* I'm going to assume that if the returned dentry is different, then
  247.  * it is well connected.  But nobody returns different dentrys do they?
  248.  */
  249. down(&child->d_inode->i_sem);
  250. pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry);
  251. up(&child->d_inode->i_sem);
  252. d_drop(tdentry); /* we never want ".." hashed */
  253. if (!pdentry && tdentry->d_inode == NULL) {
  254. /* File system cannot find ".." ... sad but possible */
  255. pdentry = ERR_PTR(-EINVAL);
  256. }
  257. if (!pdentry) {
  258. /* I don't want to return a ".." dentry.
  259.  * I would prefer to return an unconnected "IS_ROOT" dentry,
  260.  * though a properly connected dentry is even better
  261.  */
  262. /* if first or last of alias list is not tdentry, use that
  263.  * else make a root dentry
  264.  */
  265. struct list_head *aliases = &tdentry->d_inode->i_dentry;
  266. spin_lock(&dcache_lock);
  267. if (aliases->next != aliases) {
  268. pdentry = list_entry(aliases->next, struct dentry, d_alias);
  269. if (pdentry == tdentry)
  270. pdentry = list_entry(aliases->prev, struct dentry, d_alias);
  271. if (pdentry == tdentry)
  272. pdentry = NULL;
  273. if (pdentry) dget_locked(pdentry);
  274. }
  275. spin_unlock(&dcache_lock);
  276. if (pdentry == NULL) {
  277. pdentry = d_alloc_root(tdentry->d_inode);
  278. if (pdentry) {
  279. igrab(tdentry->d_inode);
  280. pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
  281. }
  282. }
  283. if (pdentry == NULL)
  284. pdentry = ERR_PTR(-ENOMEM);
  285. }
  286. dput(tdentry); /* it is not hashed, it will be discarded */
  287. return pdentry;
  288. }
  289. static struct dentry *splice(struct dentry *child, struct dentry *parent)
  290. {
  291. int err = 0, nerr;
  292. struct qstr qs;
  293. char namebuf[256];
  294. struct list_head *lp;
  295. /* child is an IS_ROOT (anonymous) dentry, but it is hypothesised that
  296.  * it should be a child of parent.
  297.  * We see if we can find a name and, if we can - splice it in.
  298.  * We lookup the name before locking (i_sem) the directory as namelookup
  299.  * also claims i_sem.  If the name gets changed then we will loop around
  300.  * and try again in find_fh_dentry.
  301.  */
  302. nerr = nfsd_get_name(parent, namebuf, child);
  303. /*
  304.  * We now claim the parent i_sem so that no-one else tries to create
  305.  * a dentry in the parent while we are.
  306.  */
  307. down(&parent->d_inode->i_sem);
  308. /* Now, things might have changed while we waited.
  309.  * Possibly a friendly filesystem found child and spliced it in in response
  310.  * to a lookup (though nobody does this yet).  In this case, just succeed.
  311.  */
  312. if (child->d_parent == parent) goto out;
  313. /* Possibly a new dentry has been made for this child->d_inode in
  314.  * parent by a lookup.  In this case return that dentry. Caller must
  315.  * notice and act accordingly
  316.  */
  317. spin_lock(&dcache_lock);
  318. list_for_each(lp, &child->d_inode->i_dentry) {
  319. struct dentry *tmp = list_entry(lp,struct dentry, d_alias);
  320. if (!list_empty(&tmp->d_hash) &&
  321.     tmp->d_parent == parent) {
  322. child = dget_locked(tmp);
  323. spin_unlock(&dcache_lock);
  324. goto out;
  325. }
  326. }
  327. spin_unlock(&dcache_lock);
  328. /* now we need that name.  If there was an error getting it, now is th
  329.  * time to bail out.
  330.  */
  331. if ((err = nerr))
  332. goto out;
  333. qs.name = namebuf;
  334. qs.len = strlen(namebuf);
  335. if (find_inode_number(parent, &qs) != 0) {
  336. /* Now that IS odd.  I wonder what it means... */
  337. err = -EEXIST;
  338. printk("nfsd-fh: found a name that I didn't expect: %s/%sn", parent->d_name.name, qs.name);
  339. goto out;
  340. }
  341. err = d_splice(child, parent, &qs);
  342. dprintk("nfsd_fh: found name %s for ino %ldn", child->d_name.name, child->d_inode->i_ino);
  343.  out:
  344. up(&parent->d_inode->i_sem);
  345. if (err)
  346. return ERR_PTR(err);
  347. else
  348. return child;
  349. }
  350. /*
  351.  * This is the basic lookup mechanism for turning an NFS file handle
  352.  * into a dentry.
  353.  * We use nfsd_iget and if that doesn't return a suitably connected dentry,
  354.  * we try to find the parent, and the parent of that and so-on until a
  355.  * connection if made.
  356.  */
  357. static struct dentry *
  358. find_fh_dentry(struct super_block *sb, __u32 *datap, int len, int fhtype, int needpath)
  359. {
  360. struct dentry *dentry, *result = NULL;
  361. struct dentry *tmp;
  362. int err = -ESTALE;
  363. /* the sb->s_nfsd_free_path_sem semaphore is needed to make sure that only one unconnected (free)
  364.  * dcache path ever exists, as otherwise two partial paths might get
  365.  * joined together, which would be very confusing.
  366.  * If there is ever an unconnected non-root directory, then this lock
  367.  * must be held.
  368.  */
  369. nfsdstats.fh_lookup++;
  370. /*
  371.  * Attempt to find the inode.
  372.  */
  373.  retry:
  374. down(&sb->s_nfsd_free_path_sem);
  375. result = nfsd_get_dentry(sb, datap, len, fhtype, 0);
  376. if (IS_ERR(result)
  377.     || !(result->d_flags & DCACHE_NFSD_DISCONNECTED)
  378.     || (!S_ISDIR(result->d_inode->i_mode) && ! needpath)) {
  379. up(&sb->s_nfsd_free_path_sem);
  380.     
  381. err = PTR_ERR(result);
  382. if (IS_ERR(result))
  383. goto err_out;
  384. if ((result->d_flags & DCACHE_NFSD_DISCONNECTED))
  385. nfsdstats.fh_anon++;
  386. return result;
  387. }
  388. /* It's a directory, or we are required to confirm the file's
  389.  * location in the tree.
  390.  */
  391. dprintk("nfs_fh: need to look harder for %d/%dn",sb->s_dev,datap[0]);
  392. if (!S_ISDIR(result->d_inode->i_mode)) {
  393. nfsdstats.fh_nocache_nondir++;
  394. /* need to iget dirino and make sure this inode is in that directory */
  395. dentry = nfsd_get_dentry(sb, datap, len, fhtype, 1);
  396. err = PTR_ERR(dentry);
  397. if (IS_ERR(dentry))
  398. goto err_result;
  399. err = -ESTALE;
  400. if (!dentry->d_inode
  401.     || !S_ISDIR(dentry->d_inode->i_mode)) {
  402. goto err_dentry;
  403. }
  404. tmp = splice(result, dentry);
  405. err = PTR_ERR(tmp);
  406. if (IS_ERR(tmp))
  407. goto err_dentry;
  408. if (tmp != result) {
  409. /* it is safe to just use tmp instead, but we must discard result first */
  410. d_drop(result);
  411. dput(result);
  412. result = tmp;
  413. }
  414. } else {
  415. nfsdstats.fh_nocache_dir++;
  416. dentry = dget(result);
  417. }
  418. while(dentry->d_flags & DCACHE_NFSD_DISCONNECTED) {
  419. /* LOOP INVARIANT */
  420. /* haven't found a place in the tree yet, but we do have a free path
  421.  * from dentry down to result, and dentry is a directory.
  422.  * Have a hold on dentry and result */
  423. struct dentry *pdentry;
  424. struct inode *parent;
  425. pdentry = nfsd_findparent(dentry);
  426. err = PTR_ERR(pdentry);
  427. if (IS_ERR(pdentry))
  428. goto err_dentry;
  429. parent = pdentry->d_inode;
  430. err = -EACCES;
  431. if (!parent) {
  432. dput(pdentry);
  433. goto err_dentry;
  434. }
  435. tmp = splice(dentry, pdentry);
  436. if (tmp != dentry) {
  437. /* Something wrong.  We need to drop the whole dentry->result path
  438.  * whatever it was
  439.  */
  440. struct dentry *d;
  441. for (d=result ; d ; d=(d->d_parent == d)?NULL:d->d_parent)
  442. d_drop(d);
  443. }
  444. if (IS_ERR(tmp)) {
  445. err = PTR_ERR(tmp);
  446. dput(pdentry);
  447. goto err_dentry;
  448. }
  449. if (tmp != dentry) {
  450. /* we lost a race,  try again
  451.  */
  452. dput(pdentry);
  453. dput(tmp);
  454. dput(dentry);
  455. dput(result); /* this will discard the whole free path, so we can up the semaphore */
  456. up(&sb->s_nfsd_free_path_sem);
  457. goto retry;
  458. }
  459. dput(dentry);
  460. dentry = pdentry;
  461. }
  462. dput(dentry);
  463. up(&sb->s_nfsd_free_path_sem);
  464. return result;
  465. err_dentry:
  466. dput(dentry);
  467. err_result:
  468. dput(result);
  469. up(&sb->s_nfsd_free_path_sem);
  470. err_out:
  471. if (err == -ESTALE)
  472. nfsdstats.fh_stale++;
  473. return ERR_PTR(err);
  474. }
  475. /*
  476.  * Perform sanity checks on the dentry in a client's file handle.
  477.  *
  478.  * Note that the file handle dentry may need to be freed even after
  479.  * an error return.
  480.  *
  481.  * This is only called at the start of an nfsproc call, so fhp points to
  482.  * a svc_fh which is all 0 except for the over-the-wire file handle.
  483.  */
  484. u32
  485. fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
  486. {
  487. struct knfsd_fh *fh = &fhp->fh_handle;
  488. struct svc_export *exp;
  489. struct dentry *dentry;
  490. struct inode *inode;
  491. u32 error = 0;
  492. dprintk("nfsd: fh_verify(%s)n", SVCFH_fmt(fhp));
  493. /* keep this filehandle for possible reference  when encoding attributes */
  494. rqstp->rq_reffh = fh;
  495. if (!fhp->fh_dentry) {
  496. kdev_t xdev = NODEV;
  497. ino_t xino = 0;
  498. __u32 *datap=NULL;
  499. int data_left = fh->fh_size/4;
  500. int nfsdev;
  501. int fsid = 0;
  502. error = nfserr_stale;
  503. if (rqstp->rq_vers == 3)
  504. error = nfserr_badhandle;
  505. if (fh->fh_version == 1) {
  506. datap = fh->fh_auth;
  507. if (--data_left<0) goto out;
  508. switch (fh->fh_auth_type) {
  509. case 0: break;
  510. default: goto out;
  511. }
  512. switch (fh->fh_fsid_type) {
  513. case 0:
  514. if ((data_left-=2)<0) goto out;
  515. nfsdev = ntohl(*datap++);
  516. xdev = MKDEV(nfsdev>>16, nfsdev&0xFFFF);
  517. xino = *datap++;
  518. break;
  519. case 1:
  520. if ((data_left-=1)<0) goto out;
  521. fsid = *datap++;
  522. break;
  523. default:
  524. goto out;
  525. }
  526. } else {
  527. if (fh->fh_size != NFS_FHSIZE)
  528. goto out;
  529. /* assume old filehandle format */
  530. xdev = u32_to_kdev_t(fh->ofh_xdev);
  531. xino = u32_to_ino_t(fh->ofh_xino);
  532. }
  533. /*
  534.  * Look up the export entry.
  535.  */
  536. error = nfserr_stale; 
  537. if (fh->fh_version == 1 && fh->fh_fsid_type == 1)
  538. exp = exp_get_fsid(rqstp->rq_client, fsid);
  539. else
  540. exp = exp_get(rqstp->rq_client, xdev, xino);
  541. if (!exp)
  542. /* export entry revoked */
  543. goto out;
  544. /* Check if the request originated from a secure port. */
  545. error = nfserr_perm;
  546. if (!rqstp->rq_secure && EX_SECURE(exp)) {
  547. printk(KERN_WARNING
  548.        "nfsd: request from insecure port (%08x:%d)!n",
  549.        ntohl(rqstp->rq_addr.sin_addr.s_addr),
  550.        ntohs(rqstp->rq_addr.sin_port));
  551. goto out;
  552. }
  553. /* Set user creds if we haven't done so already. */
  554. nfsd_setuser(rqstp, exp);
  555. /*
  556.  * Look up the dentry using the NFS file handle.
  557.  */
  558. error = nfserr_stale;
  559. if (rqstp->rq_vers == 3)
  560. error = nfserr_badhandle;
  561. if (fh->fh_version == 1) {
  562. /* if fileid_type != 0, and super_operations provide fh_to_dentry lookup,
  563.  *  then should use that */
  564. switch (fh->fh_fileid_type) {
  565. case 0:
  566. dentry = dget(exp->ex_dentry);
  567. break;
  568. default:
  569. dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
  570. datap, data_left, fh->fh_fileid_type,
  571. !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
  572. }
  573. } else {
  574. __u32 tfh[3];
  575. tfh[0] = fh->ofh_ino;
  576. tfh[1] = fh->ofh_generation;
  577. tfh[2] = fh->ofh_dirino;
  578. dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
  579. tfh, 3, fh->ofh_dirino?2:1,
  580. !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
  581. }
  582. if (IS_ERR(dentry)) {
  583. if (PTR_ERR(dentry) != -EINVAL)
  584. error = nfserrno(PTR_ERR(dentry));
  585. goto out;
  586. }
  587. #ifdef NFSD_PARANOIA
  588. if (S_ISDIR(dentry->d_inode->i_mode) &&
  589.     (dentry->d_flags & DCACHE_NFSD_DISCONNECTED)) {
  590. printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%sn",
  591.        dentry->d_parent->d_name.name, dentry->d_name.name);
  592. }
  593. #endif
  594. fhp->fh_dentry = dentry;
  595. fhp->fh_export = exp;
  596. nfsd_nr_verified++;
  597. } else {
  598. /* just rechecking permissions
  599.  * (e.g. nfsproc_create calls fh_verify, then nfsd_create does as well)
  600.  */
  601. dprintk("nfsd: fh_verify - just checkingn");
  602. dentry = fhp->fh_dentry;
  603. exp = fhp->fh_export;
  604. }
  605. inode = dentry->d_inode;
  606. /* Type check. The correct error return for type mismatches
  607.  * does not seem to be generally agreed upon. SunOS seems to
  608.  * use EISDIR if file isn't S_IFREG; a comment in the NFSv3
  609.  * spec says this is incorrect (implementation notes for the
  610.  * write call).
  611.  */
  612. /* Type can be negative to e.g. exclude directories from linking */
  613. if (type > 0 && (inode->i_mode & S_IFMT) != type) {
  614. error = (type == S_IFDIR)? nfserr_notdir : nfserr_isdir;
  615. goto out;
  616. }
  617. if (type < 0 && (inode->i_mode & S_IFMT) == -type) {
  618. error = (type == -S_IFDIR)? nfserr_notdir : nfserr_isdir;
  619. goto out;
  620. }
  621. /*
  622.  * Security: Check that the export is valid for dentry <gam3@acm.org>
  623.  */
  624. error = 0;
  625. if (!(exp->ex_flags & NFSEXP_NOSUBTREECHECK)) {
  626. if (exp->ex_dentry != dentry) {
  627. struct dentry *tdentry = dentry;
  628. do {
  629. tdentry = tdentry->d_parent;
  630. if (exp->ex_dentry == tdentry)
  631. break;
  632. /* executable only by root and we can't be root */
  633. if (current->fsuid
  634.     && (exp->ex_flags & NFSEXP_ROOTSQUASH)
  635.     && !(tdentry->d_inode->i_uid
  636.  && (tdentry->d_inode->i_mode & S_IXUSR))
  637.     && !(tdentry->d_inode->i_gid
  638.  && (tdentry->d_inode->i_mode & S_IXGRP))
  639.     && !(tdentry->d_inode->i_mode & S_IXOTH)
  640. ) {
  641. error = nfserr_stale;
  642. dprintk("fh_verify: no root_squashed access.n");
  643. }
  644. } while ((tdentry != tdentry->d_parent));
  645. if (exp->ex_dentry != tdentry) {
  646. error = nfserr_stale;
  647. printk("nfsd Security: %s/%s bad export.n",
  648.        dentry->d_parent->d_name.name,
  649.        dentry->d_name.name);
  650. goto out;
  651. }
  652. }
  653. }
  654. /* Finally, check access permissions. */
  655. if (!error) {
  656. error = nfsd_permission(exp, dentry, access);
  657. }
  658. #ifdef NFSD_PARANOIA_EXTREME
  659. if (error) {
  660. printk("fh_verify: %s/%s permission failure, acc=%x, error=%dn",
  661.        dentry->d_parent->d_name.name, dentry->d_name.name, access, (error >> 24));
  662. }
  663. #endif
  664. out:
  665. if (error == nfserr_stale)
  666. nfsdstats.fh_stale++;
  667. return error;
  668. }
  669. /*
  670.  * Compose a file handle for an NFS reply.
  671.  *
  672.  * Note that when first composed, the dentry may not yet have
  673.  * an inode.  In this case a call to fh_update should be made
  674.  * before the fh goes out on the wire ...
  675.  */
  676. inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
  677.       __u32 *datap, int *maxsize)
  678. {
  679. struct super_block *sb = dentry->d_inode->i_sb;
  680. if (dentry == exp->ex_dentry) {
  681. *maxsize = 0;
  682. return 0;
  683. }
  684. if (sb->s_op->dentry_to_fh) {
  685. int need_parent = !S_ISDIR(dentry->d_inode->i_mode) &&
  686. !(exp->ex_flags & NFSEXP_NOSUBTREECHECK);
  687. int type = sb->s_op->dentry_to_fh(dentry, datap, maxsize, need_parent);
  688. return type;
  689. }
  690. if (*maxsize < 2)
  691. return 255;
  692. *datap++ = ino_t_to_u32(dentry->d_inode->i_ino);
  693. *datap++ = dentry->d_inode->i_generation;
  694. if (*maxsize ==2 ||
  695.     S_ISDIR(dentry->d_inode->i_mode) ||
  696.     (exp->ex_flags & NFSEXP_NOSUBTREECHECK)) {
  697. *maxsize = 2;
  698. return 1;
  699. }
  700. *datap++ = ino_t_to_u32(dentry->d_parent->d_inode->i_ino);
  701. *maxsize = 3;
  702. return 2;
  703. }
  704. /*
  705.  * for composing old style file handles
  706.  */
  707. inline void _fh_update_old(struct dentry *dentry, struct svc_export *exp,
  708.    struct knfsd_fh *fh)
  709. {
  710. fh->ofh_ino = ino_t_to_u32(dentry->d_inode->i_ino);
  711. fh->ofh_generation = dentry->d_inode->i_generation;
  712. if (S_ISDIR(dentry->d_inode->i_mode) ||
  713.     (exp->ex_flags & NFSEXP_NOSUBTREECHECK))
  714. fh->ofh_dirino = 0;
  715. }
  716. int
  717. fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh)
  718. {
  719. /* ref_fh is a reference file handle.
  720.  * if it is non-null, then we should compose a filehandle which is
  721.  * of the same version, where possible.
  722.  * Currently, that means that if ref_fh->fh_handle.fh_version == 0xca
  723.  * Then create a 32byte filehandle using nfs_fhbase_old
  724.  * But only do this if dentry_to_fh is not available
  725.  *
  726.  */
  727. struct inode * inode = dentry->d_inode;
  728. struct dentry *parent = dentry->d_parent;
  729. __u32 *datap;
  730. dprintk("nfsd: fh_compose(exp %x/%ld %s/%s, ino=%ld)n",
  731. exp->ex_dev, (long) exp->ex_ino,
  732. parent->d_name.name, dentry->d_name.name,
  733. (inode ? inode->i_ino : 0));
  734. if (fhp->fh_locked || fhp->fh_dentry) {
  735. printk(KERN_ERR "fh_compose: fh %s/%s not initialized!n",
  736. parent->d_name.name, dentry->d_name.name);
  737. }
  738. if (fhp->fh_maxsize < NFS_FHSIZE)
  739. printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%sn",
  740.        fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name);
  741. fhp->fh_dentry = dentry; /* our internal copy */
  742. fhp->fh_export = exp;
  743. if (ref_fh &&
  744.     ref_fh->fh_handle.fh_version == 0xca &&
  745.     parent->d_inode->i_sb->s_op->dentry_to_fh == NULL) {
  746. /* old style filehandle please */
  747. memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE);
  748. fhp->fh_handle.fh_size = NFS_FHSIZE;
  749. fhp->fh_handle.ofh_dcookie = 0xfeebbaca;
  750. fhp->fh_handle.ofh_dev =  htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
  751. fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev;
  752. fhp->fh_handle.ofh_xino = ino_t_to_u32(exp->ex_ino);
  753. fhp->fh_handle.ofh_dirino = ino_t_to_u32(dentry->d_parent->d_inode->i_ino);
  754. if (inode)
  755. _fh_update_old(dentry, exp, &fhp->fh_handle);
  756. } else {
  757. fhp->fh_handle.fh_version = 1;
  758. fhp->fh_handle.fh_auth_type = 0;
  759. datap = fhp->fh_handle.fh_auth+0;
  760. if ((exp->ex_flags & NFSEXP_FSID) &&
  761.     (!ref_fh || ref_fh->fh_handle.fh_fsid_type == 1)) {
  762. fhp->fh_handle.fh_fsid_type = 1;
  763. /* fsid_type 1 == 4 bytes filesystem id */
  764. *datap++ = exp->ex_fsid;
  765. fhp->fh_handle.fh_size = 2*4;
  766. } else {
  767. fhp->fh_handle.fh_fsid_type = 0;
  768. /* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */
  769. *datap++ = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
  770. *datap++ = ino_t_to_u32(exp->ex_ino);
  771. fhp->fh_handle.fh_size = 3*4;
  772. }
  773. if (inode) {
  774. int size = fhp->fh_maxsize/4 - 3;
  775. fhp->fh_handle.fh_fileid_type =
  776. _fh_update(dentry, exp, datap, &size);
  777. fhp->fh_handle.fh_size += size*4;
  778. }
  779. }
  780. nfsd_nr_verified++;
  781. if (fhp->fh_handle.fh_fileid_type == 255)
  782. return nfserr_opnotsupp;
  783. return 0;
  784. }
  785. /*
  786.  * Update file handle information after changing a dentry.
  787.  * This is only called by nfsd_create, nfsd_create_v3 and nfsd_proc_create
  788.  */
  789. int
  790. fh_update(struct svc_fh *fhp)
  791. {
  792. struct dentry *dentry;
  793. __u32 *datap;
  794. if (!fhp->fh_dentry)
  795. goto out_bad;
  796. dentry = fhp->fh_dentry;
  797. if (!dentry->d_inode)
  798. goto out_negative;
  799. if (fhp->fh_handle.fh_version != 1) {
  800. _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle);
  801. } else {
  802. int size;
  803. if (fhp->fh_handle.fh_fileid_type != 0)
  804. goto out_uptodate;
  805. datap = fhp->fh_handle.fh_auth+
  806. fhp->fh_handle.fh_size/4 -1;
  807. size = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
  808. fhp->fh_handle.fh_fileid_type =
  809. _fh_update(dentry, fhp->fh_export, datap, &size);
  810. fhp->fh_handle.fh_size += size*4;
  811. }
  812. out:
  813. return 0;
  814. out_bad:
  815. printk(KERN_ERR "fh_update: fh not verified!n");
  816. goto out;
  817. out_negative:
  818. printk(KERN_ERR "fh_update: %s/%s still negative!n",
  819. dentry->d_parent->d_name.name, dentry->d_name.name);
  820. goto out;
  821. out_uptodate:
  822. printk(KERN_ERR "fh_update: %s/%s already up-to-date!n",
  823. dentry->d_parent->d_name.name, dentry->d_name.name);
  824. goto out;
  825. }
  826. /*
  827.  * Release a file handle.
  828.  */
  829. void
  830. fh_put(struct svc_fh *fhp)
  831. {
  832. struct dentry * dentry = fhp->fh_dentry;
  833. if (dentry) {
  834. fh_unlock(fhp);
  835. fhp->fh_dentry = NULL;
  836. dput(dentry);
  837. nfsd_nr_put++;
  838. }
  839. return;
  840. }