aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/Kconfig80
-rw-r--r--fs/nfsd/auth.c7
-rw-r--r--fs/nfsd/nfs4callback.c3
-rw-r--r--fs/nfsd/nfs4proc.c5
-rw-r--r--fs/nfsd/nfs4recover.c2
-rw-r--r--fs/nfsd/nfs4state.c80
-rw-r--r--fs/nfsd/nfs4xdr.c2
-rw-r--r--fs/nfsd/nfsctl.c479
-rw-r--r--fs/nfsd/nfsfh.c36
-rw-r--r--fs/nfsd/nfsproc.c1
-rw-r--r--fs/nfsd/vfs.c9
11 files changed, 624 insertions, 80 deletions
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
new file mode 100644
index 000000000000..44d7d04dab95
--- /dev/null
+++ b/fs/nfsd/Kconfig
@@ -0,0 +1,80 @@
1config NFSD
2 tristate "NFS server support"
3 depends on INET
4 select LOCKD
5 select SUNRPC
6 select EXPORTFS
7 select NFS_ACL_SUPPORT if NFSD_V2_ACL
8 help
9 Choose Y here if you want to allow other computers to access
10 files residing on this system using Sun's Network File System
11 protocol. To compile the NFS server support as a module,
12 choose M here: the module will be called nfsd.
13
14 You may choose to use a user-space NFS server instead, in which
15 case you can choose N here.
16
17 To export local file systems using NFS, you also need to install
18 user space programs which can be found in the Linux nfs-utils
19 package, available from http://linux-nfs.org/. More detail about
20 the Linux NFS server implementation is available via the
21 exports(5) man page.
22
23 Below you can choose which versions of the NFS protocol are
24 available to clients mounting the NFS server on this system.
25 Support for NFS version 2 (RFC 1094) is always available when
26 CONFIG_NFSD is selected.
27
28 If unsure, say N.
29
30config NFSD_V2_ACL
31 bool
32 depends on NFSD
33
34config NFSD_V3
35 bool "NFS server support for NFS version 3"
36 depends on NFSD
37 help
38 This option enables support in your system's NFS server for
39 version 3 of the NFS protocol (RFC 1813).
40
41 If unsure, say Y.
42
43config NFSD_V3_ACL
44 bool "NFS server support for the NFSv3 ACL protocol extension"
45 depends on NFSD_V3
46 select NFSD_V2_ACL
47 help
48 Solaris NFS servers support an auxiliary NFSv3 ACL protocol that
49 never became an official part of the NFS version 3 protocol.
50 This protocol extension allows applications on NFS clients to
51 manipulate POSIX Access Control Lists on files residing on NFS
52 servers. NFS servers enforce POSIX ACLs on local files whether
53 this protocol is available or not.
54
55 This option enables support in your system's NFS server for the
56 NFSv3 ACL protocol extension allowing NFS clients to manipulate
57 POSIX ACLs on files exported by your system's NFS server. NFS
58 clients which support the Solaris NFSv3 ACL protocol can then
59 access and modify ACLs on your NFS server.
60
61 To store ACLs on your NFS server, you also need to enable ACL-
62 related CONFIG options for your local file systems of choice.
63
64 If unsure, say N.
65
66config NFSD_V4
67 bool "NFS server support for NFS version 4 (EXPERIMENTAL)"
68 depends on NFSD && PROC_FS && EXPERIMENTAL
69 select NFSD_V3
70 select FS_POSIX_ACL
71 select RPCSEC_GSS_KRB5
72 help
73 This option enables support in your system's NFS server for
74 version 4 of the NFS protocol (RFC 3530).
75
76 To export files using NFSv4, you need to install additional user
77 space programs which can be found in the Linux nfs-utils package,
78 available from http://linux-nfs.org/.
79
80 If unsure, say N.
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index 0184fe9b514c..5573508f707f 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -49,6 +49,8 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
49 new->fsuid = exp->ex_anon_uid; 49 new->fsuid = exp->ex_anon_uid;
50 new->fsgid = exp->ex_anon_gid; 50 new->fsgid = exp->ex_anon_gid;
51 gi = groups_alloc(0); 51 gi = groups_alloc(0);
52 if (!gi)
53 goto oom;
52 } else if (flags & NFSEXP_ROOTSQUASH) { 54 } else if (flags & NFSEXP_ROOTSQUASH) {
53 if (!new->fsuid) 55 if (!new->fsuid)
54 new->fsuid = exp->ex_anon_uid; 56 new->fsuid = exp->ex_anon_uid;
@@ -76,15 +78,16 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
76 78
77 ret = set_groups(new, gi); 79 ret = set_groups(new, gi);
78 put_group_info(gi); 80 put_group_info(gi);
79 if (!ret) 81 if (ret < 0)
80 goto error; 82 goto error;
81 83
82 if (new->uid) 84 if (new->fsuid)
83 new->cap_effective = cap_drop_nfsd_set(new->cap_effective); 85 new->cap_effective = cap_drop_nfsd_set(new->cap_effective);
84 else 86 else
85 new->cap_effective = cap_raise_nfsd_set(new->cap_effective, 87 new->cap_effective = cap_raise_nfsd_set(new->cap_effective,
86 new->cap_permitted); 88 new->cap_permitted);
87 put_cred(override_creds(new)); 89 put_cred(override_creds(new));
90 put_cred(new);
88 return 0; 91 return 0;
89 92
90oom: 93oom:
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 6d7d8c02c197..c464181b5994 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -53,9 +53,6 @@
53#define NFSPROC4_CB_NULL 0 53#define NFSPROC4_CB_NULL 0
54#define NFSPROC4_CB_COMPOUND 1 54#define NFSPROC4_CB_COMPOUND 1
55 55
56/* declarations */
57static const struct rpc_call_ops nfs4_cb_null_ops;
58
59/* Index of predefined Linux callback client operations */ 56/* Index of predefined Linux callback client operations */
60 57
61enum { 58enum {
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 669461e291ae..9fa60a3ad48c 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -946,6 +946,11 @@ encode_op:
946 nfsd4_encode_operation(resp, op); 946 nfsd4_encode_operation(resp, op);
947 status = op->status; 947 status = op->status;
948 } 948 }
949
950 dprintk("nfsv4 compound op %p opcnt %d #%d: %d: status %d\n",
951 args->ops, args->opcnt, resp->opcnt, op->opnum,
952 be32_to_cpu(status));
953
949 if (cstate->replay_owner) { 954 if (cstate->replay_owner) {
950 nfs4_put_stateowner(cstate->replay_owner); 955 nfs4_put_stateowner(cstate->replay_owner);
951 cstate->replay_owner = NULL; 956 cstate->replay_owner = NULL;
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 0f9d6efaa62b..74f7b67567fd 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -116,9 +116,9 @@ nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
116 116
117 md5_to_hex(dname, cksum.data); 117 md5_to_hex(dname, cksum.data);
118 118
119 kfree(cksum.data);
120 status = nfs_ok; 119 status = nfs_ok;
121out: 120out:
121 kfree(cksum.data);
122 crypto_free_hash(desc.tfm); 122 crypto_free_hash(desc.tfm);
123out_no_tfm: 123out_no_tfm:
124 return status; 124 return status;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 13e0e074dbb8..b6f60f48e94b 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -2416,6 +2416,26 @@ out:
2416#define LOCK_HASH_SIZE (1 << LOCK_HASH_BITS) 2416#define LOCK_HASH_SIZE (1 << LOCK_HASH_BITS)
2417#define LOCK_HASH_MASK (LOCK_HASH_SIZE - 1) 2417#define LOCK_HASH_MASK (LOCK_HASH_SIZE - 1)
2418 2418
2419static inline u64
2420end_offset(u64 start, u64 len)
2421{
2422 u64 end;
2423
2424 end = start + len;
2425 return end >= start ? end: NFS4_MAX_UINT64;
2426}
2427
2428/* last octet in a range */
2429static inline u64
2430last_byte_offset(u64 start, u64 len)
2431{
2432 u64 end;
2433
2434 BUG_ON(!len);
2435 end = start + len;
2436 return end > start ? end - 1: NFS4_MAX_UINT64;
2437}
2438
2419#define lockownerid_hashval(id) \ 2439#define lockownerid_hashval(id) \
2420 ((id) & LOCK_HASH_MASK) 2440 ((id) & LOCK_HASH_MASK)
2421 2441
@@ -2435,13 +2455,13 @@ static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE];
2435static struct nfs4_stateid * 2455static struct nfs4_stateid *
2436find_stateid(stateid_t *stid, int flags) 2456find_stateid(stateid_t *stid, int flags)
2437{ 2457{
2438 struct nfs4_stateid *local = NULL; 2458 struct nfs4_stateid *local;
2439 u32 st_id = stid->si_stateownerid; 2459 u32 st_id = stid->si_stateownerid;
2440 u32 f_id = stid->si_fileid; 2460 u32 f_id = stid->si_fileid;
2441 unsigned int hashval; 2461 unsigned int hashval;
2442 2462
2443 dprintk("NFSD: find_stateid flags 0x%x\n",flags); 2463 dprintk("NFSD: find_stateid flags 0x%x\n",flags);
2444 if ((flags & LOCK_STATE) || (flags & RD_STATE) || (flags & WR_STATE)) { 2464 if (flags & (LOCK_STATE | RD_STATE | WR_STATE)) {
2445 hashval = stateid_hashval(st_id, f_id); 2465 hashval = stateid_hashval(st_id, f_id);
2446 list_for_each_entry(local, &lockstateid_hashtbl[hashval], st_hash) { 2466 list_for_each_entry(local, &lockstateid_hashtbl[hashval], st_hash) {
2447 if ((local->st_stateid.si_stateownerid == st_id) && 2467 if ((local->st_stateid.si_stateownerid == st_id) &&
@@ -2449,7 +2469,8 @@ find_stateid(stateid_t *stid, int flags)
2449 return local; 2469 return local;
2450 } 2470 }
2451 } 2471 }
2452 if ((flags & OPEN_STATE) || (flags & RD_STATE) || (flags & WR_STATE)) { 2472
2473 if (flags & (OPEN_STATE | RD_STATE | WR_STATE)) {
2453 hashval = stateid_hashval(st_id, f_id); 2474 hashval = stateid_hashval(st_id, f_id);
2454 list_for_each_entry(local, &stateid_hashtbl[hashval], st_hash) { 2475 list_for_each_entry(local, &stateid_hashtbl[hashval], st_hash) {
2455 if ((local->st_stateid.si_stateownerid == st_id) && 2476 if ((local->st_stateid.si_stateownerid == st_id) &&
@@ -2518,8 +2539,8 @@ nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
2518 deny->ld_clientid.cl_id = 0; 2539 deny->ld_clientid.cl_id = 0;
2519 } 2540 }
2520 deny->ld_start = fl->fl_start; 2541 deny->ld_start = fl->fl_start;
2521 deny->ld_length = ~(u64)0; 2542 deny->ld_length = NFS4_MAX_UINT64;
2522 if (fl->fl_end != ~(u64)0) 2543 if (fl->fl_end != NFS4_MAX_UINT64)
2523 deny->ld_length = fl->fl_end - fl->fl_start + 1; 2544 deny->ld_length = fl->fl_end - fl->fl_start + 1;
2524 deny->ld_type = NFS4_READ_LT; 2545 deny->ld_type = NFS4_READ_LT;
2525 if (fl->fl_type != F_RDLCK) 2546 if (fl->fl_type != F_RDLCK)
@@ -2616,7 +2637,7 @@ out:
2616static int 2637static int
2617check_lock_length(u64 offset, u64 length) 2638check_lock_length(u64 offset, u64 length)
2618{ 2639{
2619 return ((length == 0) || ((length != ~(u64)0) && 2640 return ((length == 0) || ((length != NFS4_MAX_UINT64) &&
2620 LOFF_OVERFLOW(offset, length))); 2641 LOFF_OVERFLOW(offset, length)));
2621} 2642}
2622 2643
@@ -2736,11 +2757,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2736 file_lock.fl_lmops = &nfsd_posix_mng_ops; 2757 file_lock.fl_lmops = &nfsd_posix_mng_ops;
2737 2758
2738 file_lock.fl_start = lock->lk_offset; 2759 file_lock.fl_start = lock->lk_offset;
2739 if ((lock->lk_length == ~(u64)0) || 2760 file_lock.fl_end = last_byte_offset(lock->lk_offset, lock->lk_length);
2740 LOFF_OVERFLOW(lock->lk_offset, lock->lk_length))
2741 file_lock.fl_end = ~(u64)0;
2742 else
2743 file_lock.fl_end = lock->lk_offset + lock->lk_length - 1;
2744 nfs4_transform_lock_offset(&file_lock); 2761 nfs4_transform_lock_offset(&file_lock);
2745 2762
2746 /* 2763 /*
@@ -2781,6 +2798,25 @@ out:
2781} 2798}
2782 2799
2783/* 2800/*
2801 * The NFSv4 spec allows a client to do a LOCKT without holding an OPEN,
2802 * so we do a temporary open here just to get an open file to pass to
2803 * vfs_test_lock. (Arguably perhaps test_lock should be done with an
2804 * inode operation.)
2805 */
2806static int nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock)
2807{
2808 struct file *file;
2809 int err;
2810
2811 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
2812 if (err)
2813 return err;
2814 err = vfs_test_lock(file, lock);
2815 nfsd_close(file);
2816 return err;
2817}
2818
2819/*
2784 * LOCKT operation 2820 * LOCKT operation
2785 */ 2821 */
2786__be32 2822__be32
@@ -2788,7 +2824,6 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2788 struct nfsd4_lockt *lockt) 2824 struct nfsd4_lockt *lockt)
2789{ 2825{
2790 struct inode *inode; 2826 struct inode *inode;
2791 struct file file;
2792 struct file_lock file_lock; 2827 struct file_lock file_lock;
2793 int error; 2828 int error;
2794 __be32 status; 2829 __be32 status;
@@ -2836,26 +2871,14 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2836 file_lock.fl_owner = (fl_owner_t)lockt->lt_stateowner; 2871 file_lock.fl_owner = (fl_owner_t)lockt->lt_stateowner;
2837 file_lock.fl_pid = current->tgid; 2872 file_lock.fl_pid = current->tgid;
2838 file_lock.fl_flags = FL_POSIX; 2873 file_lock.fl_flags = FL_POSIX;
2839 file_lock.fl_lmops = &nfsd_posix_mng_ops;
2840 2874
2841 file_lock.fl_start = lockt->lt_offset; 2875 file_lock.fl_start = lockt->lt_offset;
2842 if ((lockt->lt_length == ~(u64)0) || LOFF_OVERFLOW(lockt->lt_offset, lockt->lt_length)) 2876 file_lock.fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length);
2843 file_lock.fl_end = ~(u64)0;
2844 else
2845 file_lock.fl_end = lockt->lt_offset + lockt->lt_length - 1;
2846 2877
2847 nfs4_transform_lock_offset(&file_lock); 2878 nfs4_transform_lock_offset(&file_lock);
2848 2879
2849 /* vfs_test_lock uses the struct file _only_ to resolve the inode.
2850 * since LOCKT doesn't require an OPEN, and therefore a struct
2851 * file may not exist, pass vfs_test_lock a struct file with
2852 * only the dentry:inode set.
2853 */
2854 memset(&file, 0, sizeof (struct file));
2855 file.f_path.dentry = cstate->current_fh.fh_dentry;
2856
2857 status = nfs_ok; 2880 status = nfs_ok;
2858 error = vfs_test_lock(&file, &file_lock); 2881 error = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock);
2859 if (error) { 2882 if (error) {
2860 status = nfserrno(error); 2883 status = nfserrno(error);
2861 goto out; 2884 goto out;
@@ -2906,10 +2929,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2906 file_lock.fl_lmops = &nfsd_posix_mng_ops; 2929 file_lock.fl_lmops = &nfsd_posix_mng_ops;
2907 file_lock.fl_start = locku->lu_offset; 2930 file_lock.fl_start = locku->lu_offset;
2908 2931
2909 if ((locku->lu_length == ~(u64)0) || LOFF_OVERFLOW(locku->lu_offset, locku->lu_length)) 2932 file_lock.fl_end = last_byte_offset(locku->lu_offset, locku->lu_length);
2910 file_lock.fl_end = ~(u64)0;
2911 else
2912 file_lock.fl_end = locku->lu_offset + locku->lu_length - 1;
2913 nfs4_transform_lock_offset(&file_lock); 2933 nfs4_transform_lock_offset(&file_lock);
2914 2934
2915 /* 2935 /*
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index afcdf4b76843..f65953be39c0 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1,6 +1,4 @@
1/* 1/*
2 * fs/nfs/nfs4xdr.c
3 *
4 * Server-side XDR for NFSv4 2 * Server-side XDR for NFSv4
5 * 3 *
6 * Copyright (c) 2002 The Regents of the University of Michigan. 4 * Copyright (c) 2002 The Regents of the University of Michigan.
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 77d7b8c531a6..3d93b2064ce5 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -84,6 +84,8 @@ static ssize_t write_unexport(struct file *file, char *buf, size_t size);
84static ssize_t write_getfd(struct file *file, char *buf, size_t size); 84static ssize_t write_getfd(struct file *file, char *buf, size_t size);
85static ssize_t write_getfs(struct file *file, char *buf, size_t size); 85static ssize_t write_getfs(struct file *file, char *buf, size_t size);
86static ssize_t write_filehandle(struct file *file, char *buf, size_t size); 86static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
87static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
88static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
87static ssize_t write_threads(struct file *file, char *buf, size_t size); 89static ssize_t write_threads(struct file *file, char *buf, size_t size);
88static ssize_t write_pool_threads(struct file *file, char *buf, size_t size); 90static ssize_t write_pool_threads(struct file *file, char *buf, size_t size);
89static ssize_t write_versions(struct file *file, char *buf, size_t size); 91static ssize_t write_versions(struct file *file, char *buf, size_t size);
@@ -94,9 +96,6 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
94static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); 96static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
95#endif 97#endif
96 98
97static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size);
98static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size);
99
100static ssize_t (*write_op[])(struct file *, char *, size_t) = { 99static ssize_t (*write_op[])(struct file *, char *, size_t) = {
101 [NFSD_Svc] = write_svc, 100 [NFSD_Svc] = write_svc,
102 [NFSD_Add] = write_add, 101 [NFSD_Add] = write_add,
@@ -106,8 +105,8 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
106 [NFSD_Getfd] = write_getfd, 105 [NFSD_Getfd] = write_getfd,
107 [NFSD_Getfs] = write_getfs, 106 [NFSD_Getfs] = write_getfs,
108 [NFSD_Fh] = write_filehandle, 107 [NFSD_Fh] = write_filehandle,
109 [NFSD_FO_UnlockIP] = failover_unlock_ip, 108 [NFSD_FO_UnlockIP] = write_unlock_ip,
110 [NFSD_FO_UnlockFS] = failover_unlock_fs, 109 [NFSD_FO_UnlockFS] = write_unlock_fs,
111 [NFSD_Threads] = write_threads, 110 [NFSD_Threads] = write_threads,
112 [NFSD_Pool_Threads] = write_pool_threads, 111 [NFSD_Pool_Threads] = write_pool_threads,
113 [NFSD_Versions] = write_versions, 112 [NFSD_Versions] = write_versions,
@@ -176,10 +175,24 @@ static const struct file_operations exports_operations = {
176/*----------------------------------------------------------------------------*/ 175/*----------------------------------------------------------------------------*/
177/* 176/*
178 * payload - write methods 177 * payload - write methods
179 * If the method has a response, the response should be put in buf,
180 * and the length returned. Otherwise return 0 or and -error.
181 */ 178 */
182 179
180/**
181 * write_svc - Start kernel's NFSD server
182 *
183 * Deprecated. /proc/fs/nfsd/threads is preferred.
184 * Function remains to support old versions of nfs-utils.
185 *
186 * Input:
187 * buf: struct nfsctl_svc
188 * svc_port: port number of this
189 * server's listener
190 * svc_nthreads: number of threads to start
191 * size: size in bytes of passed in nfsctl_svc
192 * Output:
193 * On success: returns zero
194 * On error: return code is negative errno value
195 */
183static ssize_t write_svc(struct file *file, char *buf, size_t size) 196static ssize_t write_svc(struct file *file, char *buf, size_t size)
184{ 197{
185 struct nfsctl_svc *data; 198 struct nfsctl_svc *data;
@@ -189,6 +202,30 @@ static ssize_t write_svc(struct file *file, char *buf, size_t size)
189 return nfsd_svc(data->svc_port, data->svc_nthreads); 202 return nfsd_svc(data->svc_port, data->svc_nthreads);
190} 203}
191 204
205/**
206 * write_add - Add or modify client entry in auth unix cache
207 *
208 * Deprecated. /proc/net/rpc/auth.unix.ip is preferred.
209 * Function remains to support old versions of nfs-utils.
210 *
211 * Input:
212 * buf: struct nfsctl_client
213 * cl_ident: '\0'-terminated C string
214 * containing domain name
215 * of client
216 * cl_naddr: no. of items in cl_addrlist
217 * cl_addrlist: array of client addresses
218 * cl_fhkeytype: ignored
219 * cl_fhkeylen: ignored
220 * cl_fhkey: ignored
221 * size: size in bytes of passed in nfsctl_client
222 * Output:
223 * On success: returns zero
224 * On error: return code is negative errno value
225 *
226 * Note: Only AF_INET client addresses are passed in, since
227 * nfsctl_client.cl_addrlist contains only in_addr fields for addresses.
228 */
192static ssize_t write_add(struct file *file, char *buf, size_t size) 229static ssize_t write_add(struct file *file, char *buf, size_t size)
193{ 230{
194 struct nfsctl_client *data; 231 struct nfsctl_client *data;
@@ -198,6 +235,30 @@ static ssize_t write_add(struct file *file, char *buf, size_t size)
198 return exp_addclient(data); 235 return exp_addclient(data);
199} 236}
200 237
238/**
239 * write_del - Remove client from auth unix cache
240 *
241 * Deprecated. /proc/net/rpc/auth.unix.ip is preferred.
242 * Function remains to support old versions of nfs-utils.
243 *
244 * Input:
245 * buf: struct nfsctl_client
246 * cl_ident: '\0'-terminated C string
247 * containing domain name
248 * of client
249 * cl_naddr: ignored
250 * cl_addrlist: ignored
251 * cl_fhkeytype: ignored
252 * cl_fhkeylen: ignored
253 * cl_fhkey: ignored
254 * size: size in bytes of passed in nfsctl_client
255 * Output:
256 * On success: returns zero
257 * On error: return code is negative errno value
258 *
259 * Note: Only AF_INET client addresses are passed in, since
260 * nfsctl_client.cl_addrlist contains only in_addr fields for addresses.
261 */
201static ssize_t write_del(struct file *file, char *buf, size_t size) 262static ssize_t write_del(struct file *file, char *buf, size_t size)
202{ 263{
203 struct nfsctl_client *data; 264 struct nfsctl_client *data;
@@ -207,6 +268,33 @@ static ssize_t write_del(struct file *file, char *buf, size_t size)
207 return exp_delclient(data); 268 return exp_delclient(data);
208} 269}
209 270
271/**
272 * write_export - Export part or all of a local file system
273 *
274 * Deprecated. /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred.
275 * Function remains to support old versions of nfs-utils.
276 *
277 * Input:
278 * buf: struct nfsctl_export
279 * ex_client: '\0'-terminated C string
280 * containing domain name
281 * of client allowed to access
282 * this export
283 * ex_path: '\0'-terminated C string
284 * containing pathname of
285 * directory in local file system
286 * ex_dev: fsid to use for this export
287 * ex_ino: ignored
288 * ex_flags: export flags for this export
289 * ex_anon_uid: UID to use for anonymous
290 * requests
291 * ex_anon_gid: GID to use for anonymous
292 * requests
293 * size: size in bytes of passed in nfsctl_export
294 * Output:
295 * On success: returns zero
296 * On error: return code is negative errno value
297 */
210static ssize_t write_export(struct file *file, char *buf, size_t size) 298static ssize_t write_export(struct file *file, char *buf, size_t size)
211{ 299{
212 struct nfsctl_export *data; 300 struct nfsctl_export *data;
@@ -216,6 +304,31 @@ static ssize_t write_export(struct file *file, char *buf, size_t size)
216 return exp_export(data); 304 return exp_export(data);
217} 305}
218 306
307/**
308 * write_unexport - Unexport a previously exported file system
309 *
310 * Deprecated. /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred.
311 * Function remains to support old versions of nfs-utils.
312 *
313 * Input:
314 * buf: struct nfsctl_export
315 * ex_client: '\0'-terminated C string
316 * containing domain name
317 * of client no longer allowed
318 * to access this export
319 * ex_path: '\0'-terminated C string
320 * containing pathname of
321 * directory in local file system
322 * ex_dev: ignored
323 * ex_ino: ignored
324 * ex_flags: ignored
325 * ex_anon_uid: ignored
326 * ex_anon_gid: ignored
327 * size: size in bytes of passed in nfsctl_export
328 * Output:
329 * On success: returns zero
330 * On error: return code is negative errno value
331 */
219static ssize_t write_unexport(struct file *file, char *buf, size_t size) 332static ssize_t write_unexport(struct file *file, char *buf, size_t size)
220{ 333{
221 struct nfsctl_export *data; 334 struct nfsctl_export *data;
@@ -226,6 +339,30 @@ static ssize_t write_unexport(struct file *file, char *buf, size_t size)
226 return exp_unexport(data); 339 return exp_unexport(data);
227} 340}
228 341
342/**
343 * write_getfs - Get a variable-length NFS file handle by path
344 *
345 * Deprecated. /proc/fs/nfsd/filehandle is preferred.
346 * Function remains to support old versions of nfs-utils.
347 *
348 * Input:
349 * buf: struct nfsctl_fsparm
350 * gd_addr: socket address of client
351 * gd_path: '\0'-terminated C string
352 * containing pathname of
353 * directory in local file system
354 * gd_maxlen: maximum size of returned file
355 * handle
356 * size: size in bytes of passed in nfsctl_fsparm
357 * Output:
358 * On success: passed-in buffer filled with a knfsd_fh structure
359 * (a variable-length raw NFS file handle);
360 * return code is the size in bytes of the file handle
361 * On error: return code is negative errno value
362 *
363 * Note: Only AF_INET client addresses are passed in, since gd_addr
364 * is the same size as a struct sockaddr_in.
365 */
229static ssize_t write_getfs(struct file *file, char *buf, size_t size) 366static ssize_t write_getfs(struct file *file, char *buf, size_t size)
230{ 367{
231 struct nfsctl_fsparm *data; 368 struct nfsctl_fsparm *data;
@@ -265,6 +402,29 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size)
265 return err; 402 return err;
266} 403}
267 404
405/**
406 * write_getfd - Get a fixed-length NFS file handle by path (used by mountd)
407 *
408 * Deprecated. /proc/fs/nfsd/filehandle is preferred.
409 * Function remains to support old versions of nfs-utils.
410 *
411 * Input:
412 * buf: struct nfsctl_fdparm
413 * gd_addr: socket address of client
414 * gd_path: '\0'-terminated C string
415 * containing pathname of
416 * directory in local file system
417 * gd_version: fdparm structure version
418 * size: size in bytes of passed in nfsctl_fdparm
419 * Output:
420 * On success: passed-in buffer filled with nfsctl_res
421 * (a fixed-length raw NFS file handle);
422 * return code is the size in bytes of the file handle
423 * On error: return code is negative errno value
424 *
425 * Note: Only AF_INET client addresses are passed in, since gd_addr
426 * is the same size as a struct sockaddr_in.
427 */
268static ssize_t write_getfd(struct file *file, char *buf, size_t size) 428static ssize_t write_getfd(struct file *file, char *buf, size_t size)
269{ 429{
270 struct nfsctl_fdparm *data; 430 struct nfsctl_fdparm *data;
@@ -309,7 +469,23 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
309 return err; 469 return err;
310} 470}
311 471
312static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size) 472/**
473 * write_unlock_ip - Release all locks used by a client
474 *
475 * Experimental.
476 *
477 * Input:
478 * buf: '\n'-terminated C string containing a
479 * presentation format IPv4 address
480 * size: length of C string in @buf
481 * Output:
482 * On success: returns zero if all specified locks were released;
483 * returns one if one or more locks were not released
484 * On error: return code is negative errno value
485 *
486 * Note: Only AF_INET client addresses are passed in
487 */
488static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
313{ 489{
314 struct sockaddr_in sin = { 490 struct sockaddr_in sin = {
315 .sin_family = AF_INET, 491 .sin_family = AF_INET,
@@ -339,7 +515,21 @@ static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size)
339 return nlmsvc_unlock_all_by_ip((struct sockaddr *)&sin); 515 return nlmsvc_unlock_all_by_ip((struct sockaddr *)&sin);
340} 516}
341 517
342static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size) 518/**
519 * write_unlock_fs - Release all locks on a local file system
520 *
521 * Experimental.
522 *
523 * Input:
524 * buf: '\n'-terminated C string containing the
525 * absolute pathname of a local file system
526 * size: length of C string in @buf
527 * Output:
528 * On success: returns zero if all specified locks were released;
529 * returns one if one or more locks were not released
530 * On error: return code is negative errno value
531 */
532static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size)
343{ 533{
344 struct path path; 534 struct path path;
345 char *fo_path; 535 char *fo_path;
@@ -360,21 +550,44 @@ static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size)
360 if (error) 550 if (error)
361 return error; 551 return error;
362 552
553 /*
554 * XXX: Needs better sanity checking. Otherwise we could end up
555 * releasing locks on the wrong file system.
556 *
557 * For example:
558 * 1. Does the path refer to a directory?
559 * 2. Is that directory a mount point, or
560 * 3. Is that directory the root of an exported file system?
561 */
363 error = nlmsvc_unlock_all_by_sb(path.mnt->mnt_sb); 562 error = nlmsvc_unlock_all_by_sb(path.mnt->mnt_sb);
364 563
365 path_put(&path); 564 path_put(&path);
366 return error; 565 return error;
367} 566}
368 567
568/**
569 * write_filehandle - Get a variable-length NFS file handle by path
570 *
571 * On input, the buffer contains a '\n'-terminated C string comprised of
572 * three alphanumeric words separated by whitespace. The string may
573 * contain escape sequences.
574 *
575 * Input:
576 * buf:
577 * domain: client domain name
578 * path: export pathname
579 * maxsize: numeric maximum size of
580 * @buf
581 * size: length of C string in @buf
582 * Output:
583 * On success: passed-in buffer filled with '\n'-terminated C
584 * string containing a ASCII hex text version
585 * of the NFS file handle;
586 * return code is the size in bytes of the string
587 * On error: return code is negative errno value
588 */
369static ssize_t write_filehandle(struct file *file, char *buf, size_t size) 589static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
370{ 590{
371 /* request is:
372 * domain path maxsize
373 * response is
374 * filehandle
375 *
376 * qword quoting is used, so filehandle will be \x....
377 */
378 char *dname, *path; 591 char *dname, *path;
379 int uninitialized_var(maxsize); 592 int uninitialized_var(maxsize);
380 char *mesg = buf; 593 char *mesg = buf;
@@ -391,11 +604,13 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
391 604
392 dname = mesg; 605 dname = mesg;
393 len = qword_get(&mesg, dname, size); 606 len = qword_get(&mesg, dname, size);
394 if (len <= 0) return -EINVAL; 607 if (len <= 0)
608 return -EINVAL;
395 609
396 path = dname+len+1; 610 path = dname+len+1;
397 len = qword_get(&mesg, path, size); 611 len = qword_get(&mesg, path, size);
398 if (len <= 0) return -EINVAL; 612 if (len <= 0)
613 return -EINVAL;
399 614
400 len = get_int(&mesg, &maxsize); 615 len = get_int(&mesg, &maxsize);
401 if (len) 616 if (len)
@@ -419,17 +634,43 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size)
419 if (len) 634 if (len)
420 return len; 635 return len;
421 636
422 mesg = buf; len = SIMPLE_TRANSACTION_LIMIT; 637 mesg = buf;
638 len = SIMPLE_TRANSACTION_LIMIT;
423 qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size); 639 qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size);
424 mesg[-1] = '\n'; 640 mesg[-1] = '\n';
425 return mesg - buf; 641 return mesg - buf;
426} 642}
427 643
644/**
645 * write_threads - Start NFSD, or report the current number of running threads
646 *
647 * Input:
648 * buf: ignored
649 * size: zero
650 * Output:
651 * On success: passed-in buffer filled with '\n'-terminated C
652 * string numeric value representing the number of
653 * running NFSD threads;
654 * return code is the size in bytes of the string
655 * On error: return code is zero
656 *
657 * OR
658 *
659 * Input:
660 * buf: C string containing an unsigned
661 * integer value representing the
662 * number of NFSD threads to start
663 * size: non-zero length of C string in @buf
664 * Output:
665 * On success: NFS service is started;
666 * passed-in buffer filled with '\n'-terminated C
667 * string numeric value representing the number of
668 * running NFSD threads;
669 * return code is the size in bytes of the string
670 * On error: return code is zero or a negative errno value
671 */
428static ssize_t write_threads(struct file *file, char *buf, size_t size) 672static ssize_t write_threads(struct file *file, char *buf, size_t size)
429{ 673{
430 /* if size > 0, look for a number of threads and call nfsd_svc
431 * then write out number of threads as reply
432 */
433 char *mesg = buf; 674 char *mesg = buf;
434 int rv; 675 int rv;
435 if (size > 0) { 676 if (size > 0) {
@@ -437,9 +678,9 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
437 rv = get_int(&mesg, &newthreads); 678 rv = get_int(&mesg, &newthreads);
438 if (rv) 679 if (rv)
439 return rv; 680 return rv;
440 if (newthreads <0) 681 if (newthreads < 0)
441 return -EINVAL; 682 return -EINVAL;
442 rv = nfsd_svc(2049, newthreads); 683 rv = nfsd_svc(NFS_PORT, newthreads);
443 if (rv) 684 if (rv)
444 return rv; 685 return rv;
445 } 686 }
@@ -447,6 +688,28 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
447 return strlen(buf); 688 return strlen(buf);
448} 689}
449 690
691/**
692 * write_pool_threads - Set or report the current number of threads per pool
693 *
694 * Input:
695 * buf: ignored
696 * size: zero
697 *
698 * OR
699 *
700 * Input:
701 * buf: C string containing whitespace-
702 * separated unsigned integer values
703 * representing the number of NFSD
704 * threads to start in each pool
705 * size: non-zero length of C string in @buf
706 * Output:
707 * On success: passed-in buffer filled with '\n'-terminated C
708 * string containing integer values representing the
709 * number of NFSD threads in each pool;
710 * return code is the size in bytes of the string
711 * On error: return code is zero or a negative errno value
712 */
450static ssize_t write_pool_threads(struct file *file, char *buf, size_t size) 713static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
451{ 714{
452 /* if size > 0, look for an array of number of threads per node 715 /* if size > 0, look for an array of number of threads per node
@@ -517,10 +780,6 @@ out_free:
517 780
518static ssize_t __write_versions(struct file *file, char *buf, size_t size) 781static ssize_t __write_versions(struct file *file, char *buf, size_t size)
519{ 782{
520 /*
521 * Format:
522 * [-/+]vers [-/+]vers ...
523 */
524 char *mesg = buf; 783 char *mesg = buf;
525 char *vers, sign; 784 char *vers, sign;
526 int len, num; 785 int len, num;
@@ -578,6 +837,38 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
578 return len; 837 return len;
579} 838}
580 839
840/**
841 * write_versions - Set or report the available NFS protocol versions
842 *
843 * Input:
844 * buf: ignored
845 * size: zero
846 * Output:
847 * On success: passed-in buffer filled with '\n'-terminated C
848 * string containing positive or negative integer
849 * values representing the current status of each
850 * protocol version;
851 * return code is the size in bytes of the string
852 * On error: return code is zero or a negative errno value
853 *
854 * OR
855 *
856 * Input:
857 * buf: C string containing whitespace-
858 * separated positive or negative
859 * integer values representing NFS
860 * protocol versions to enable ("+n")
861 * or disable ("-n")
862 * size: non-zero length of C string in @buf
863 * Output:
864 * On success: status of zero or more protocol versions has
865 * been updated; passed-in buffer filled with
866 * '\n'-terminated C string containing positive
867 * or negative integer values representing the
868 * current status of each protocol version;
869 * return code is the size in bytes of the string
870 * On error: return code is zero or a negative errno value
871 */
581static ssize_t write_versions(struct file *file, char *buf, size_t size) 872static ssize_t write_versions(struct file *file, char *buf, size_t size)
582{ 873{
583 ssize_t rv; 874 ssize_t rv;
@@ -687,6 +978,75 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
687 return -EINVAL; 978 return -EINVAL;
688} 979}
689 980
981/**
982 * write_ports - Pass a socket file descriptor or transport name to listen on
983 *
984 * Input:
985 * buf: ignored
986 * size: zero
987 * Output:
988 * On success: passed-in buffer filled with a '\n'-terminated C
989 * string containing a whitespace-separated list of
990 * named NFSD listeners;
991 * return code is the size in bytes of the string
992 * On error: return code is zero or a negative errno value
993 *
994 * OR
995 *
996 * Input:
997 * buf: C string containing an unsigned
998 * integer value representing a bound
999 * but unconnected socket that is to be
1000 * used as an NFSD listener
1001 * size: non-zero length of C string in @buf
1002 * Output:
1003 * On success: NFS service is started;
1004 * passed-in buffer filled with a '\n'-terminated C
1005 * string containing a unique alphanumeric name of
1006 * the listener;
1007 * return code is the size in bytes of the string
1008 * On error: return code is a negative errno value
1009 *
1010 * OR
1011 *
1012 * Input:
1013 * buf: C string containing a "-" followed
1014 * by an integer value representing a
1015 * previously passed in socket file
1016 * descriptor
1017 * size: non-zero length of C string in @buf
1018 * Output:
1019 * On success: NFS service no longer listens on that socket;
1020 * passed-in buffer filled with a '\n'-terminated C
1021 * string containing a unique name of the listener;
1022 * return code is the size in bytes of the string
1023 * On error: return code is a negative errno value
1024 *
1025 * OR
1026 *
1027 * Input:
1028 * buf: C string containing a transport
1029 * name and an unsigned integer value
1030 * representing the port to listen on,
1031 * separated by whitespace
1032 * size: non-zero length of C string in @buf
1033 * Output:
1034 * On success: returns zero; NFS service is started
1035 * On error: return code is a negative errno value
1036 *
1037 * OR
1038 *
1039 * Input:
1040 * buf: C string containing a "-" followed
1041 * by a transport name and an unsigned
1042 * integer value representing the port
1043 * to listen on, separated by whitespace
1044 * size: non-zero length of C string in @buf
1045 * Output:
1046 * On success: returns zero; NFS service no longer listens
1047 * on that transport
1048 * On error: return code is a negative errno value
1049 */
690static ssize_t write_ports(struct file *file, char *buf, size_t size) 1050static ssize_t write_ports(struct file *file, char *buf, size_t size)
691{ 1051{
692 ssize_t rv; 1052 ssize_t rv;
@@ -700,6 +1060,27 @@ static ssize_t write_ports(struct file *file, char *buf, size_t size)
700 1060
701int nfsd_max_blksize; 1061int nfsd_max_blksize;
702 1062
1063/**
1064 * write_maxblksize - Set or report the current NFS blksize
1065 *
1066 * Input:
1067 * buf: ignored
1068 * size: zero
1069 *
1070 * OR
1071 *
1072 * Input:
1073 * buf: C string containing an unsigned
1074 * integer value representing the new
1075 * NFS blksize
1076 * size: non-zero length of C string in @buf
1077 * Output:
1078 * On success: passed-in buffer filled with '\n'-terminated C string
1079 * containing numeric value of the current NFS blksize
1080 * setting;
1081 * return code is the size in bytes of the string
1082 * On error: return code is zero or a negative errno value
1083 */
703static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) 1084static ssize_t write_maxblksize(struct file *file, char *buf, size_t size)
704{ 1085{
705 char *mesg = buf; 1086 char *mesg = buf;
@@ -752,6 +1133,27 @@ static ssize_t __write_leasetime(struct file *file, char *buf, size_t size)
752 return strlen(buf); 1133 return strlen(buf);
753} 1134}
754 1135
1136/**
1137 * write_leasetime - Set or report the current NFSv4 lease time
1138 *
1139 * Input:
1140 * buf: ignored
1141 * size: zero
1142 *
1143 * OR
1144 *
1145 * Input:
1146 * buf: C string containing an unsigned
1147 * integer value representing the new
1148 * NFSv4 lease expiry time
1149 * size: non-zero length of C string in @buf
1150 * Output:
1151 * On success: passed-in buffer filled with '\n'-terminated C
1152 * string containing unsigned integer value of the
1153 * current lease expiry time;
1154 * return code is the size in bytes of the string
1155 * On error: return code is zero or a negative errno value
1156 */
755static ssize_t write_leasetime(struct file *file, char *buf, size_t size) 1157static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
756{ 1158{
757 ssize_t rv; 1159 ssize_t rv;
@@ -788,6 +1190,27 @@ static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
788 return strlen(buf); 1190 return strlen(buf);
789} 1191}
790 1192
1193/**
1194 * write_recoverydir - Set or report the pathname of the recovery directory
1195 *
1196 * Input:
1197 * buf: ignored
1198 * size: zero
1199 *
1200 * OR
1201 *
1202 * Input:
1203 * buf: C string containing the pathname
1204 * of the directory on a local file
1205 * system containing permanent NFSv4
1206 * recovery data
1207 * size: non-zero length of C string in @buf
1208 * Output:
1209 * On success: passed-in buffer filled with '\n'-terminated C string
1210 * containing the current recovery pathname setting;
1211 * return code is the size in bytes of the string
1212 * On error: return code is zero or a negative errno value
1213 */
791static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) 1214static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
792{ 1215{
793 ssize_t rv; 1216 ssize_t rv;
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index f0da7d9c3a92..9f1ca17293d3 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -258,14 +258,32 @@ out:
258 return error; 258 return error;
259} 259}
260 260
261/* 261/**
262 * Perform sanity checks on the dentry in a client's file handle. 262 * fh_verify - filehandle lookup and access checking
263 * @rqstp: pointer to current rpc request
264 * @fhp: filehandle to be verified
265 * @type: expected type of object pointed to by filehandle
266 * @access: type of access needed to object
267 *
268 * Look up a dentry from the on-the-wire filehandle, check the client's
269 * access to the export, and set the current task's credentials.
270 *
271 * Regardless of success or failure of fh_verify(), fh_put() should be
272 * called on @fhp when the caller is finished with the filehandle.
263 * 273 *
264 * Note that the file handle dentry may need to be freed even after 274 * fh_verify() may be called multiple times on a given filehandle, for
265 * an error return. 275 * example, when processing an NFSv4 compound. The first call will look
276 * up a dentry using the on-the-wire filehandle. Subsequent calls will
277 * skip the lookup and just perform the other checks and possibly change
278 * the current task's credentials.
266 * 279 *
267 * This is only called at the start of an nfsproc call, so fhp points to 280 * @type specifies the type of object expected using one of the S_IF*
268 * a svc_fh which is all 0 except for the over-the-wire file handle. 281 * constants defined in include/linux/stat.h. The caller may use zero
282 * to indicate that it doesn't care, or a negative integer to indicate
283 * that it expects something not of the given type.
284 *
285 * @access is formed from the NFSD_MAY_* constants defined in
286 * include/linux/nfsd/nfsd.h.
269 */ 287 */
270__be32 288__be32
271fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) 289fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
@@ -466,6 +484,8 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
466 goto retry; 484 goto retry;
467 break; 485 break;
468 } 486 }
487 } else if (exp->ex_flags & NFSEXP_FSID) {
488 fsid_type = FSID_NUM;
469 } else if (exp->ex_uuid) { 489 } else if (exp->ex_uuid) {
470 if (fhp->fh_maxsize >= 64) { 490 if (fhp->fh_maxsize >= 64) {
471 if (root_export) 491 if (root_export)
@@ -478,9 +498,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
478 else 498 else
479 fsid_type = FSID_UUID4_INUM; 499 fsid_type = FSID_UUID4_INUM;
480 } 500 }
481 } else if (exp->ex_flags & NFSEXP_FSID) 501 } else if (!old_valid_dev(ex_dev))
482 fsid_type = FSID_NUM;
483 else if (!old_valid_dev(ex_dev))
484 /* for newer device numbers, we must use a newer fsid format */ 502 /* for newer device numbers, we must use a newer fsid format */
485 fsid_type = FSID_ENCODE_DEV; 503 fsid_type = FSID_ENCODE_DEV;
486 else 504 else
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 5cffeca7acef..6f7f26351227 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -622,6 +622,7 @@ nfserrno (int errno)
622 { nfserr_badname, -ESRCH }, 622 { nfserr_badname, -ESRCH },
623 { nfserr_io, -ETXTBSY }, 623 { nfserr_io, -ETXTBSY },
624 { nfserr_notsupp, -EOPNOTSUPP }, 624 { nfserr_notsupp, -EOPNOTSUPP },
625 { nfserr_toosmall, -ETOOSMALL },
625 }; 626 };
626 int i; 627 int i;
627 628
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index d1c5f787b365..6e50aaa56ca2 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -764,7 +764,6 @@ static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
764 764
765 return err; 765 return err;
766} 766}
767
768 767
769static int 768static int
770nfsd_sync(struct file *filp) 769nfsd_sync(struct file *filp)
@@ -1211,7 +1210,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1211 dirp = dentry->d_inode; 1210 dirp = dentry->d_inode;
1212 1211
1213 err = nfserr_notdir; 1212 err = nfserr_notdir;
1214 if(!dirp->i_op || !dirp->i_op->lookup) 1213 if (!dirp->i_op->lookup)
1215 goto out; 1214 goto out;
1216 /* 1215 /*
1217 * Check whether the response file handle has been verified yet. 1216 * Check whether the response file handle has been verified yet.
@@ -1347,7 +1346,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1347 /* Get all the sanity checks out of the way before 1346 /* Get all the sanity checks out of the way before
1348 * we lock the parent. */ 1347 * we lock the parent. */
1349 err = nfserr_notdir; 1348 err = nfserr_notdir;
1350 if(!dirp->i_op || !dirp->i_op->lookup) 1349 if (!dirp->i_op->lookup)
1351 goto out; 1350 goto out;
1352 fh_lock_nested(fhp, I_MUTEX_PARENT); 1351 fh_lock_nested(fhp, I_MUTEX_PARENT);
1353 1352
@@ -1482,7 +1481,7 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
1482 inode = dentry->d_inode; 1481 inode = dentry->d_inode;
1483 1482
1484 err = nfserr_inval; 1483 err = nfserr_inval;
1485 if (!inode->i_op || !inode->i_op->readlink) 1484 if (!inode->i_op->readlink)
1486 goto out; 1485 goto out;
1487 1486
1488 touch_atime(fhp->fh_export->ex_path.mnt, dentry); 1487 touch_atime(fhp->fh_export->ex_path.mnt, dentry);
@@ -2162,7 +2161,7 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
2162 size_t size; 2161 size_t size;
2163 int error; 2162 int error;
2164 2163
2165 if (!IS_POSIXACL(inode) || !inode->i_op || 2164 if (!IS_POSIXACL(inode) ||
2166 !inode->i_op->setxattr || !inode->i_op->removexattr) 2165 !inode->i_op->setxattr || !inode->i_op->removexattr)
2167 return -EOPNOTSUPP; 2166 return -EOPNOTSUPP;
2168 switch(type) { 2167 switch(type) {