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
11 #include <linux/config.h>
12 #include <linux/sched.h>
13 #include <linux/malloc.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
,
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" */
53 #ifdef NFSD_DEBUG_VERBOSE
54 dprintk("filldir_one: seq=%d, ino=%ld, name=%s\n", buf
->sequence
, ino
, name
);
56 if (buf
->ino
== ino
) {
58 memcpy(nbuf
, name
, len
);
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
;
77 struct nfsd_getdents_callback buffer
;
80 if (!dir
|| !S_ISDIR(dir
->i_mode
))
86 * Open the directory ...
88 error
= init_private_file(&file
, dentry
, FMODE_READ
);
92 if (!file
.f_op
->readdir
)
100 int old_seq
= buffer
.sequence
;
101 error
= file
.f_op
->readdir(&file
, &buffer
, filldir_one
);
109 if (old_seq
== buffer
.sequence
)
114 if (file
.f_op
->release
)
115 file
.f_op
->release(dir
, &file
);
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
132 * Currently we don't know the generation for parent directory, so a generation
133 * of 0 means "accept any"
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",
145 inode
->i_nlink
, atomic_read(&inode
->i_count
),
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
)) {
160 spin_unlock(&dcache_lock
);
165 spin_unlock(&dcache_lock
);
166 result
= d_alloc_root(inode
);
167 if (result
== NULL
) {
169 return ERR_PTR(-ENOMEM
);
171 result
->d_flags
|= DCACHE_NFSD_DISCONNECTED
;
172 d_rehash(result
); /* so a dput won't loose it */
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
;
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
);
189 name
->hash
= full_name_hash(name
->name
, name
->len
);
190 tdentry
= d_alloc(parent
, name
);
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
);
205 /* if parent is properly connected, then we can assert that
206 * the children are connected, but it must be a singluar (non-forking)
209 if (!(parent
->d_flags
& DCACHE_NFSD_DISCONNECTED
)) {
211 target
->d_flags
&= ~DCACHE_NFSD_DISCONNECTED
;
213 spin_lock(&dcache_lock
);
214 if (list_empty(&parent
->d_subdirs
))
217 target
= list_entry(parent
->d_subdirs
.next
, struct dentry
, d_child
);
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
);
226 spin_unlock(&dcache_lock
);
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});
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 */
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
)
264 if (pdentry
) dget(pdentry
);
266 spin_unlock(&dcache_lock
);
267 if (pdentry
== NULL
) {
268 pdentry
= d_alloc_root(igrab(tdentry
->d_inode
));
270 pdentry
->d_flags
|= DCACHE_NFSD_DISCONNECTED
;
275 pdentry
= ERR_PTR(-ENOMEM
);
277 dput(tdentry
); /* it is not hashed, it will be discarded */
281 static struct dentry
*splice(struct dentry
*child
, struct dentry
*parent
)
286 struct list_head
*lp
;
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.
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
) {
310 spin_unlock(&dcache_lock
);
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
);
319 tmp
= d_lookup(parent
, &qs
);
321 /* Now that IS odd. I wonder what it means... */
323 printk("nfsd-fh: found a name that I didn't expect: %s/%s\n", parent
->d_name
.name
, qs
.name
);
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
);
330 up(&parent
->d_inode
->i_sem
);
338 * This is the basic lookup mechanism for turning an NFS file handle
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
;
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
359 nfsdstats
.fh_lookup
++;
361 * Attempt to find the inode.
364 result
= nfsd_iget(sb
, ino
, generation
);
365 err
= PTR_ERR(result
);
369 if (! (result
->d_flags
& DCACHE_NFSD_DISCONNECTED
))
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
) {
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
);
394 if (!S_ISDIR(result
->d_inode
->i_mode
)) {
395 nfsdstats
.fh_nocache_nondir
++;
397 goto err_result
; /* don't know how to find parent */
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
);
406 || !S_ISDIR(dentry
->d_inode
->i_mode
)) {
409 if ((!dentry
->d_flags
& DCACHE_NFSD_DISCONNECTED
))
411 tmp
= splice(result
, dentry
);
416 /* it is safe to just use tmp instead, but we must discard result first */
420 /* If !found, then this is really wierd, but it shouldn't hurt */
424 nfsdstats
.fh_nocache_dir
++;
425 dentry
= dget(result
);
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
);
440 parent
= pdentry
->d_inode
;
447 if (!(dentry
->d_flags
& DCACHE_NFSD_DISCONNECTED
))
450 tmp
= splice(dentry
, pdentry
);
452 /* Something wrong. We need to drop thw whole dentry->result path
456 for (d
=result
; d
; d
=(d
->d_parent
== d
)?NULL
:d
->d_parent
)
465 /* we lost a race, try again
469 dput(result
); /* this will discard the whole free path, so we can up the semaphore */
470 up(&sb
->s_nfsd_free_path_sem
);
477 up(&sb
->s_nfsd_free_path_sem
);
484 up(&sb
->s_nfsd_free_path_sem
);
487 nfsdstats
.fh_stale
++;
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
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
;
509 dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp
));
511 if (!fhp
->fh_dentry
) {
515 int data_left
= fh
->fh_size
/4;
517 error
= nfserr_stale
;
518 if (rqstp
->rq_vers
== 3)
519 error
= nfserr_badhandle
;
520 if (fh
->fh_version
== 1) {
523 if (--data_left
<0) goto out
;
524 switch (fh
->fh_auth_type
) {
529 switch (fh
->fh_fsid_type
) {
531 if ((data_left
-=2)<0) goto out
;
532 nfsdev
= ntohl(*datap
++);
533 xdev
= MKDEV(nfsdev
>>16, nfsdev
&0xFFFF);
540 if (fh
->fh_size
!= NFS_FHSIZE
)
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
);
554 /* export entry revoked */
555 nfsdstats
.fh_stale
++;
559 /* Check if the request originated from a secure port. */
561 if (!rqstp
->rq_secure
&& EX_SECURE(exp
)) {
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
));
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
) {
584 dentry
= dget(exp
->ex_dentry
);
587 if ((data_left
-=2)<0) goto out
;
588 dentry
= find_fh_dentry(exp
->ex_dentry
->d_inode
->i_sb
,
591 !(exp
->ex_flags
& NFSEXP_NOSUBTREECHECK
));
594 if ((data_left
-=3)<0) goto out
;
595 dentry
= find_fh_dentry(exp
->ex_dentry
->d_inode
->i_sb
,
598 !(exp
->ex_flags
& NFSEXP_NOSUBTREECHECK
));
604 dentry
= find_fh_dentry(exp
->ex_dentry
->d_inode
->i_sb
,
605 fh
->ofh_ino
, fh
->ofh_generation
,
607 !(exp
->ex_flags
& NFSEXP_NOSUBTREECHECK
));
609 if (IS_ERR(dentry
)) {
610 error
= nfserrno(PTR_ERR(dentry
));
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
);
621 fhp
->fh_dentry
= dentry
;
622 fhp
->fh_export
= exp
;
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
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
;
647 if (type
< 0 && (inode
->i_mode
& S_IFMT
) == -type
) {
648 error
= (type
== -S_IFDIR
)? nfserr_notdir
: nfserr_isdir
;
653 * Security: Check that the export is valid for dentry <gam3@acm.org>
657 if (!(exp
->ex_flags
& NFSEXP_NOSUBTREECHECK
)) {
658 if (exp
->ex_dentry
!= dentry
) {
659 struct dentry
*tdentry
= dentry
;
662 tdentry
= tdentry
->d_parent
;
663 if (exp
->ex_dentry
== tdentry
)
665 /* executable only by root and we can't be root */
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
);
690 /* Finally, check access permissions. */
692 error
= nfsd_permission(exp
, dentry
, access
);
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));
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
)
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
)){
725 *datap
++ = ino_t_to_u32(dentry
->d_parent
->d_inode
->i_ino
);
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
;
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
);
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;
769 if (fhp
->fh_handle
.fh_fileid_type
== 255)
770 return nfserr_opnotsupp
;
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
;
787 dentry
= fhp
->fh_dentry
;
788 if (!dentry
->d_inode
)
790 if (fhp
->fh_handle
.fh_fileid_type
!= 0)
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;
801 printk(KERN_ERR
"fh_update: fh not verified!\n");
804 printk(KERN_ERR
"fh_update: %s/%s still negative!\n",
805 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
808 printk(KERN_ERR
"fh_update: %s/%s already up-to-date!\n",
809 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
);
814 * Release a file handle.
817 fh_put(struct svc_fh
*fhp
)
819 struct dentry
* dentry
= fhp
->fh_dentry
;
822 fhp
->fh_dentry
= NULL
;