Merge with 2.4.0-test3-pre4.
[linux-2.6/linux-mips.git] / fs / nfsd / nfsfh.c
blob511a14dc9e71001faca5d1e1283ce5387fa9ad52
1 /*
2 * linux/fs/nfsd/nfsfh.c
4 * NFS server file handle treatment.
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 */
11 #include <linux/config.h>
12 #include <linux/sched.h>
13 #include <linux/malloc.h>
14 #include <linux/fs.h>
15 #include <linux/unistd.h>
16 #include <linux/string.h>
17 #include <linux/stat.h>
18 #include <linux/dcache.h>
19 #include <asm/pgtable.h>
21 #include <linux/sunrpc/svc.h>
22 #include <linux/nfsd/nfsd.h>
24 #define NFSDDBG_FACILITY NFSDDBG_FH
25 #define NFSD_PARANOIA 1
26 /* #define NFSD_DEBUG_VERBOSE 1 */
29 static int nfsd_nr_verified = 0;
30 static int nfsd_nr_put = 0;
33 struct nfsd_getdents_callback {
34 struct qstr *name; /* name that was found. name->name already points to a buffer */
35 unsigned long ino; /* the inum we are looking for */
36 int found; /* inode matched? */
37 int sequence; /* sequence counter */
41 * A rather strange filldir function to capture
42 * the name matching the specified inode number.
44 static int filldir_one(void * __buf, const char * name, int len,
45 off_t pos, ino_t ino)
47 struct nfsd_getdents_callback *buf = __buf;
48 struct qstr *qs = buf->name;
49 char *nbuf = (char*)qs->name; /* cast is to get rid of "const" */
50 int result = 0;
52 buf->sequence++;
53 #ifdef NFSD_DEBUG_VERBOSE
54 dprintk("filldir_one: seq=%d, ino=%ld, name=%s\n", buf->sequence, ino, name);
55 #endif
56 if (buf->ino == ino) {
57 qs->len = len;
58 memcpy(nbuf, name, len);
59 nbuf[len] = '\0';
60 buf->found = 1;
61 result = -1;
63 return result;
67 * Read a directory and return the name of the specified entry.
68 * i_sem is already down().
69 * The whole thing is a total BS. It should not be done via readdir(), damnit!
70 * Oh, well, as soon as it will be in filesystems...
72 static int get_ino_name(struct dentry *dentry, struct qstr *name, unsigned long ino)
74 struct inode *dir = dentry->d_inode;
75 int error;
76 struct file file;
77 struct nfsd_getdents_callback buffer;
79 error = -ENOTDIR;
80 if (!dir || !S_ISDIR(dir->i_mode))
81 goto out;
82 error = -EINVAL;
83 if (!dir->i_fop)
84 goto out;
86 * Open the directory ...
88 error = init_private_file(&file, dentry, FMODE_READ);
89 if (error)
90 goto out;
91 error = -EINVAL;
92 if (!file.f_op->readdir)
93 goto out_close;
95 buffer.name = name;
96 buffer.ino = ino;
97 buffer.found = 0;
98 buffer.sequence = 0;
99 while (1) {
100 int old_seq = buffer.sequence;
101 error = file.f_op->readdir(&file, &buffer, filldir_one);
102 if (error < 0)
103 break;
105 error = 0;
106 if (buffer.found)
107 break;
108 error = -ENOENT;
109 if (old_seq == buffer.sequence)
110 break;
113 out_close:
114 if (file.f_op->release)
115 file.f_op->release(dir, &file);
116 out:
117 return error;
120 /* this should be provided by each filesystem in an nfsd_operations interface as
121 * iget isn't really the right interface
123 static struct dentry *nfsd_iget(struct super_block *sb, unsigned long ino, __u32 generation)
126 /* iget isn't really right if the inode is currently unallocated!!
127 * This should really all be done inside each filesystem
129 * ext2fs' read_inode has been strengthed to return a bad_inode if the inode
130 * had been deleted.
132 * Currently we don't know the generation for parent directory, so a generation
133 * of 0 means "accept any"
135 struct inode *inode;
136 struct list_head *lp;
137 struct dentry *result;
138 inode = iget(sb, ino);
139 if (is_bad_inode(inode)
140 || (generation && inode->i_generation != generation)
142 /* we didn't find the right inode.. */
143 dprintk("fh_verify: Inode %lu, Bad count: %d %d or version %u %u\n",
144 inode->i_ino,
145 inode->i_nlink, atomic_read(&inode->i_count),
146 inode->i_generation,
147 generation);
149 iput(inode);
150 return ERR_PTR(-ESTALE);
152 /* now to find a dentry.
153 * If possible, get a well-connected one
155 spin_lock(&dcache_lock);
156 for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) {
157 result = list_entry(lp,struct dentry, d_alias);
158 if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
159 dget(result);
160 spin_unlock(&dcache_lock);
161 iput(inode);
162 return result;
165 spin_unlock(&dcache_lock);
166 result = d_alloc_root(inode);
167 if (result == NULL) {
168 iput(inode);
169 return ERR_PTR(-ENOMEM);
171 result->d_flags |= DCACHE_NFSD_DISCONNECTED;
172 d_rehash(result); /* so a dput won't loose it */
173 return result;
176 /* this routine links an IS_ROOT dentry into the dcache tree. It gains "parent"
177 * as a parent and "name" as a name
178 * It should possibly go in dcache.c
180 int d_splice(struct dentry *target, struct dentry *parent, struct qstr *name)
182 struct dentry *tdentry;
183 #ifdef NFSD_PARANOIA
184 if (!IS_ROOT(target))
185 printk("nfsd: d_splice with no-root target: %s/%s\n", parent->d_name.name, name->name);
186 if (!(target->d_flags & DCACHE_NFSD_DISCONNECTED))
187 printk("nfsd: d_splice with non-DISCONNECTED target: %s/%s\n", parent->d_name.name, name->name);
188 #endif
189 name->hash = full_name_hash(name->name, name->len);
190 tdentry = d_alloc(parent, name);
191 if (tdentry == NULL)
192 return -ENOMEM;
193 d_move(target, tdentry);
195 /* tdentry will have been made a "child" of target (the parent of target)
196 * make it an IS_ROOT instead
198 spin_lock(&dcache_lock);
199 list_del(&tdentry->d_child);
200 tdentry->d_parent = tdentry;
201 spin_unlock(&dcache_lock);
202 d_rehash(target);
203 dput(tdentry);
205 /* if parent is properly connected, then we can assert that
206 * the children are connected, but it must be a singluar (non-forking)
207 * branch
209 if (!(parent->d_flags & DCACHE_NFSD_DISCONNECTED)) {
210 while (target) {
211 target->d_flags &= ~DCACHE_NFSD_DISCONNECTED;
212 parent = target;
213 spin_lock(&dcache_lock);
214 if (list_empty(&parent->d_subdirs))
215 target = NULL;
216 else {
217 target = list_entry(parent->d_subdirs.next, struct dentry, d_child);
218 #ifdef NFSD_PARANOIA
219 /* must be only child */
220 if (target->d_child.next != &parent->d_subdirs
221 || target->d_child.prev != &parent->d_subdirs)
222 printk("nfsd: d_splice found non-singular disconnected branch: %s/%s\n",
223 parent->d_name.name, target->d_name.name);
224 #endif
226 spin_unlock(&dcache_lock);
229 return 0;
232 /* this routine finds the dentry of the parent of a given directory
233 * it should be in the filesystem accessed by nfsd_operations
234 * it assumes lookup("..") works.
236 struct dentry *nfsd_findparent(struct dentry *child)
238 struct dentry *tdentry, *pdentry;
239 tdentry = d_alloc(child, &(const struct qstr) {"..", 2, 0});
240 if (!tdentry)
241 return ERR_PTR(-ENOMEM);
243 /* I'm going to assume that if the returned dentry is different, then
244 * it is well connected. But nobody returns different dentrys do they?
246 pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry);
247 d_drop(tdentry); /* we never want ".." hashed */
248 if (!pdentry) {
249 /* I don't want to return a ".." dentry.
250 * I would prefer to return an unconnected "IS_ROOT" dentry,
251 * though a properly connected dentry is even better
253 /* if first or last of alias list is not tdentry, use that
254 * else make a root dentry
256 struct list_head *aliases = &tdentry->d_inode->i_dentry;
257 spin_lock(&dcache_lock);
258 if (aliases->next != aliases) {
259 pdentry = list_entry(aliases->next, struct dentry, d_alias);
260 if (pdentry == tdentry)
261 pdentry = list_entry(aliases->prev, struct dentry, d_alias);
262 if (pdentry == tdentry)
263 pdentry = NULL;
264 if (pdentry) dget(pdentry);
266 spin_unlock(&dcache_lock);
267 if (pdentry == NULL) {
268 pdentry = d_alloc_root(igrab(tdentry->d_inode));
269 if (pdentry) {
270 pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
271 d_rehash(pdentry);
274 if (pdentry == NULL)
275 pdentry = ERR_PTR(-ENOMEM);
277 dput(tdentry); /* it is not hashed, it will be discarded */
278 return pdentry;
281 static struct dentry *splice(struct dentry *child, struct dentry *parent)
283 int err = 0;
284 struct qstr qs;
285 char namebuf[256];
286 struct list_head *lp;
287 struct dentry *tmp;
288 /* child is an IS_ROOT (anonymous) dentry, but it is hypothesised that
289 * it should be a child of parent.
290 * We see if we can find a name and, if we can - splice it in.
291 * We hold the i_sem on the parent the whole time to try to follow locking protocols.
293 qs.name = namebuf;
294 down(&parent->d_inode->i_sem);
296 /* Now, things might have changed while we waited.
297 * Possibly a friendly filesystem found child and spliced it in in response
298 * to a lookup (though nobody does this yet). In this case, just succeed.
300 if (child->d_parent == parent) goto out;
301 /* Possibly a new dentry has been made for this child->d_inode in
302 * parent by a lookup. In this case return that dentry. caller must
303 * notice and act accordingly
305 spin_lock(&dcache_lock);
306 for (lp = child->d_inode->i_dentry.next; lp != &child->d_inode->i_dentry ; lp=lp->next) {
307 tmp = list_entry(lp,struct dentry, d_alias);
308 if (tmp->d_parent == parent) {
309 child = dget(tmp);
310 spin_unlock(&dcache_lock);
311 goto out;
314 spin_unlock(&dcache_lock);
315 /* well, if we can find a name for child in parent, it should be safe to splice it in */
316 err = get_ino_name(parent, &qs, child->d_inode->i_ino);
317 if (err)
318 goto out;
319 tmp = d_lookup(parent, &qs);
320 if (tmp) {
321 /* Now that IS odd. I wonder what it means... */
322 err = -EEXIST;
323 printk("nfsd-fh: found a name that I didn't expect: %s/%s\n", parent->d_name.name, qs.name);
324 dput(tmp);
325 goto out;
327 err = d_splice(child, parent, &qs);
328 dprintk("nfsd_fh: found name %s for ino %ld\n", child->d_name.name, child->d_inode->i_ino);
329 out:
330 up(&parent->d_inode->i_sem);
331 if (err)
332 return ERR_PTR(err);
333 else
334 return child;
338 * This is the basic lookup mechanism for turning an NFS file handle
339 * into a dentry.
340 * We use nfsd_iget and if that doesn't return a suitably connected dentry,
341 * we try to find the parent, and the parent of that and so-on until a
342 * connection if made.
344 static struct dentry *
345 find_fh_dentry(struct super_block *sb, ino_t ino, int generation, ino_t dirino, int needpath)
347 struct dentry *dentry, *result = NULL;
348 struct dentry *tmp;
349 int found =0;
350 int err;
351 /* the sb->s_nfsd_free_path_sem semaphore is needed to make sure that only one unconnected (free)
352 * dcache path ever exists, as otherwise two partial paths might get
353 * joined together, which would be very confusing.
354 * If there is ever an unconnected non-root directory, then this lock
355 * must be held.
359 nfsdstats.fh_lookup++;
361 * Attempt to find the inode.
363 retry:
364 result = nfsd_iget(sb, ino, generation);
365 err = PTR_ERR(result);
366 if (IS_ERR(result))
367 goto err_out;
368 err = -ESTALE;
369 if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED))
370 return result;
372 /* result is now an anonymous dentry, which may be adequate as it stands, or else
373 * will get spliced into the dcache tree */
375 if (!S_ISDIR(result->d_inode->i_mode) && ! needpath) {
376 nfsdstats.fh_anon++;
377 return result;
380 /* It's a directory, or we are required to confirm the file's
381 * location in the tree.
383 dprintk("nfs_fh: need to look harder for %d/%ld\n",sb->s_dev,ino);
384 down(&sb->s_nfsd_free_path_sem);
386 /* claiming the semaphore might have allowed things to get fixed up */
387 if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
388 up(&sb->s_nfsd_free_path_sem);
389 return result;
393 found = 0;
394 if (!S_ISDIR(result->d_inode->i_mode)) {
395 nfsdstats.fh_nocache_nondir++;
396 if (dirino == 0)
397 goto err_result; /* don't know how to find parent */
398 else {
399 /* need to iget dirino and make sure this inode is in that directory */
400 dentry = nfsd_iget(sb, dirino, 0);
401 err = PTR_ERR(dentry);
402 if (IS_ERR(dentry))
403 goto err_result;
404 err = -ESTALE;
405 if (!dentry->d_inode
406 || !S_ISDIR(dentry->d_inode->i_mode)) {
407 goto err_dentry;
409 if ((!dentry->d_flags & DCACHE_NFSD_DISCONNECTED))
410 found = 1;
411 tmp = splice(result, dentry);
412 err = PTR_ERR(tmp);
413 if (IS_ERR(tmp))
414 goto err_dentry;
415 if (tmp != result) {
416 /* it is safe to just use tmp instead, but we must discard result first */
417 d_drop(result);
418 dput(result);
419 result = tmp;
420 /* If !found, then this is really wierd, but it shouldn't hurt */
423 } else {
424 nfsdstats.fh_nocache_dir++;
425 dentry = dget(result);
428 while(!found) {
429 /* LOOP INVARIANT */
430 /* haven't found a place in the tree yet, but we do have a free path
431 * from dentry down to result, and dentry is a directory.
432 * Have a hold on dentry and result */
433 struct dentry *pdentry;
434 struct inode *parent;
436 pdentry = nfsd_findparent(dentry);
437 err = PTR_ERR(pdentry);
438 if (IS_ERR(pdentry))
439 goto err_dentry;
440 parent = pdentry->d_inode;
441 err = -EACCES;
442 if (!parent) {
443 dput(pdentry);
444 goto err_dentry;
447 if (!(dentry->d_flags & DCACHE_NFSD_DISCONNECTED))
448 found = 1;
450 tmp = splice(dentry, pdentry);
451 if (tmp != dentry) {
452 /* Something wrong. We need to drop thw whole dentry->result path
453 * whatever it was
455 struct dentry *d;
456 for (d=result ; d ; d=(d->d_parent == d)?NULL:d->d_parent)
457 d_drop(d);
459 if (IS_ERR(tmp)) {
460 err = PTR_ERR(tmp);
461 dput(pdentry);
462 goto err_dentry;
464 if (tmp != dentry) {
465 /* we lost a race, try again
467 dput(tmp);
468 dput(dentry);
469 dput(result); /* this will discard the whole free path, so we can up the semaphore */
470 up(&sb->s_nfsd_free_path_sem);
471 goto retry;
473 dput(dentry);
474 dentry = pdentry;
476 dput(dentry);
477 up(&sb->s_nfsd_free_path_sem);
478 return result;
480 err_dentry:
481 dput(dentry);
482 err_result:
483 dput(result);
484 up(&sb->s_nfsd_free_path_sem);
485 err_out:
486 if (err == -ESTALE)
487 nfsdstats.fh_stale++;
488 return ERR_PTR(err);
492 * Perform sanity checks on the dentry in a client's file handle.
494 * Note that the file handle dentry may need to be freed even after
495 * an error return.
497 * This is only called at the start of an nfsproc call, so fhp points to
498 * a svc_fh which is all 0 except for the over-the-wire file handle.
501 fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
503 struct knfsd_fh *fh = &fhp->fh_handle;
504 struct svc_export *exp;
505 struct dentry *dentry;
506 struct inode *inode;
507 u32 error = 0;
509 dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
511 if (!fhp->fh_dentry) {
512 kdev_t xdev;
513 ino_t xino;
514 __u32 *datap=NULL;
515 int data_left = fh->fh_size/4;
516 int nfsdev;
517 error = nfserr_stale;
518 if (rqstp->rq_vers == 3)
519 error = nfserr_badhandle;
520 if (fh->fh_version == 1) {
522 datap = fh->fh_auth;
523 if (--data_left<0) goto out;
524 switch (fh->fh_auth_type) {
525 case 0: break;
526 default: goto out;
529 switch (fh->fh_fsid_type) {
530 case 0:
531 if ((data_left-=2)<0) goto out;
532 nfsdev = ntohl(*datap++);
533 xdev = MKDEV(nfsdev>>16, nfsdev&0xFFFF);
534 xino = *datap++;
535 break;
536 default:
537 goto out;
539 } else {
540 if (fh->fh_size != NFS_FHSIZE)
541 goto out;
542 /* assume old filehandle format */
543 xdev = u32_to_kdev_t(fh->ofh_xdev);
544 xino = u32_to_ino_t(fh->ofh_xino);
548 * Look up the export entry.
550 error = nfserr_stale;
551 exp = exp_get(rqstp->rq_client, xdev, xino);
553 if (!exp) {
554 /* export entry revoked */
555 nfsdstats.fh_stale++;
556 goto out;
559 /* Check if the request originated from a secure port. */
560 error = nfserr_perm;
561 if (!rqstp->rq_secure && EX_SECURE(exp)) {
562 printk(KERN_WARNING
563 "nfsd: request from insecure port (%08x:%d)!\n",
564 ntohl(rqstp->rq_addr.sin_addr.s_addr),
565 ntohs(rqstp->rq_addr.sin_port));
566 goto out;
569 /* Set user creds if we haven't done so already. */
570 nfsd_setuser(rqstp, exp);
573 * Look up the dentry using the NFS file handle.
575 error = nfserr_stale;
576 if (rqstp->rq_vers == 3)
577 error = nfserr_badhandle;
579 if (fh->fh_version == 1) {
580 /* if fileid_type != 0, and super_operations provide fh_to_dentry lookup,
581 * then should use that */
582 switch (fh->fh_fileid_type) {
583 case 0:
584 dentry = dget(exp->ex_dentry);
585 break;
586 case 1:
587 if ((data_left-=2)<0) goto out;
588 dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
589 datap[0], datap[1],
591 !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
592 break;
593 case 2:
594 if ((data_left-=3)<0) goto out;
595 dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
596 datap[0], datap[1],
597 datap[2],
598 !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
599 break;
600 default: goto out;
602 } else {
604 dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
605 fh->ofh_ino, fh->ofh_generation,
606 fh->ofh_dirino,
607 !(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
609 if (IS_ERR(dentry)) {
610 error = nfserrno(PTR_ERR(dentry));
611 goto out;
613 #ifdef NFSD_PARANOIA
614 if (S_ISDIR(dentry->d_inode->i_mode) &&
615 (dentry->d_flags & DCACHE_NFSD_DISCONNECTED)) {
616 printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
617 dentry->d_parent->d_name.name, dentry->d_name.name);
619 #endif
621 fhp->fh_dentry = dentry;
622 fhp->fh_export = exp;
623 nfsd_nr_verified++;
624 } else {
625 /* just rechecking permissions
626 * (e.g. nfsproc_create calls fh_verify, then nfsd_create does as well)
628 dprintk("nfsd: fh_verify - just checking\n");
629 dentry = fhp->fh_dentry;
630 exp = fhp->fh_export;
633 inode = dentry->d_inode;
635 /* Type check. The correct error return for type mismatches
636 * does not seem to be generally agreed upon. SunOS seems to
637 * use EISDIR if file isn't S_IFREG; a comment in the NFSv3
638 * spec says this is incorrect (implementation notes for the
639 * write call).
642 /* When is type ever negative? */
643 if (type > 0 && (inode->i_mode & S_IFMT) != type) {
644 error = (type == S_IFDIR)? nfserr_notdir : nfserr_isdir;
645 goto out;
647 if (type < 0 && (inode->i_mode & S_IFMT) == -type) {
648 error = (type == -S_IFDIR)? nfserr_notdir : nfserr_isdir;
649 goto out;
653 * Security: Check that the export is valid for dentry <gam3@acm.org>
655 error = 0;
657 if (!(exp->ex_flags & NFSEXP_NOSUBTREECHECK)) {
658 if (exp->ex_dentry != dentry) {
659 struct dentry *tdentry = dentry;
661 do {
662 tdentry = tdentry->d_parent;
663 if (exp->ex_dentry == tdentry)
664 break;
665 /* executable only by root and we can't be root */
666 if (current->fsuid
667 && (exp->ex_flags & NFSEXP_ROOTSQUASH)
668 && !(tdentry->d_inode->i_uid
669 && (tdentry->d_inode->i_mode & S_IXUSR))
670 && !(tdentry->d_inode->i_gid
671 && (tdentry->d_inode->i_mode & S_IXGRP))
672 && !(tdentry->d_inode->i_mode & S_IXOTH)
674 error = nfserr_stale;
675 nfsdstats.fh_stale++;
676 dprintk("fh_verify: no root_squashed access.\n");
678 } while ((tdentry != tdentry->d_parent));
679 if (exp->ex_dentry != tdentry) {
680 error = nfserr_stale;
681 nfsdstats.fh_stale++;
682 printk("nfsd Security: %s/%s bad export.\n",
683 dentry->d_parent->d_name.name,
684 dentry->d_name.name);
685 goto out;
690 /* Finally, check access permissions. */
691 if (!error) {
692 error = nfsd_permission(exp, dentry, access);
694 #ifdef NFSD_PARANOIA
695 if (error) {
696 printk("fh_verify: %s/%s permission failure, acc=%x, error=%d\n",
697 dentry->d_parent->d_name.name, dentry->d_name.name, access, (error >> 24));
699 #endif
700 out:
701 return error;
705 * Compose a file handle for an NFS reply.
707 * Note that when first composed, the dentry may not yet have
708 * an inode. In this case a call to fh_update should be made
709 * before the fh goes out on the wire ...
711 inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
712 __u32 **datapp, int maxsize)
714 __u32 *datap= *datapp;
715 if (dentry == exp->ex_dentry)
716 return 0;
717 /* if super_operations provides dentry_to_fh lookup, should use that */
719 *datap++ = ino_t_to_u32(dentry->d_inode->i_ino);
720 *datap++ = dentry->d_inode->i_generation;
721 if (S_ISDIR(dentry->d_inode->i_mode) || (exp->ex_flags & NFSEXP_NOSUBTREECHECK)){
722 *datapp = datap;
723 return 1;
725 *datap++ = ino_t_to_u32(dentry->d_parent->d_inode->i_ino);
726 *datapp = datap;
727 return 2;
731 fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry)
733 struct inode * inode = dentry->d_inode;
734 struct dentry *parent = dentry->d_parent;
735 __u32 *datap;
737 dprintk("nfsd: fh_compose(exp %x/%ld %s/%s, ino=%ld)\n",
738 exp->ex_dev, (long) exp->ex_ino,
739 parent->d_name.name, dentry->d_name.name,
740 (inode ? inode->i_ino : 0));
742 if (fhp->fh_locked || fhp->fh_dentry) {
743 printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n",
744 parent->d_name.name, dentry->d_name.name);
746 if (fhp->fh_maxsize < NFS_FHSIZE)
747 printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n",
748 fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name);
750 fhp->fh_dentry = dentry; /* our internal copy */
751 fhp->fh_export = exp;
753 fhp->fh_handle.fh_version = 1;
754 fhp->fh_handle.fh_auth_type = 0;
755 fhp->fh_handle.fh_fsid_type = 0;
756 datap = fhp->fh_handle.fh_auth+0;
757 /* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */
758 *datap++ = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
759 *datap++ = ino_t_to_u32(exp->ex_ino);
761 if (inode)
762 fhp->fh_handle.fh_fileid_type =
763 _fh_update(dentry, exp, &datap, fhp->fh_maxsize-3);
765 fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4;
768 nfsd_nr_verified++;
769 if (fhp->fh_handle.fh_fileid_type == 255)
770 return nfserr_opnotsupp;
771 return 0;
775 * Update file handle information after changing a dentry.
776 * This is only called by nfsd_create, nfsd_create_v3 and nfsd_proc_create
779 fh_update(struct svc_fh *fhp)
781 struct dentry *dentry;
782 __u32 *datap;
784 if (!fhp->fh_dentry)
785 goto out_bad;
787 dentry = fhp->fh_dentry;
788 if (!dentry->d_inode)
789 goto out_negative;
790 if (fhp->fh_handle.fh_fileid_type != 0)
791 goto out_uptodate;
792 datap = fhp->fh_handle.fh_auth+
793 fhp->fh_handle.fh_size/4 -1;
794 fhp->fh_handle.fh_fileid_type =
795 _fh_update(dentry, fhp->fh_export, &datap, fhp->fh_maxsize-fhp->fh_handle.fh_size);
796 fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4;
797 out:
798 return 0;
800 out_bad:
801 printk(KERN_ERR "fh_update: fh not verified!\n");
802 goto out;
803 out_negative:
804 printk(KERN_ERR "fh_update: %s/%s still negative!\n",
805 dentry->d_parent->d_name.name, dentry->d_name.name);
806 goto out;
807 out_uptodate:
808 printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
809 dentry->d_parent->d_name.name, dentry->d_name.name);
810 goto out;
814 * Release a file handle.
816 void
817 fh_put(struct svc_fh *fhp)
819 struct dentry * dentry = fhp->fh_dentry;
820 if (dentry) {
821 fh_unlock(fhp);
822 fhp->fh_dentry = NULL;
823 dput(dentry);
824 nfsd_nr_put++;
826 return;