aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/export.c33
-rw-r--r--fs/nfsd/lockd.c2
-rw-r--r--fs/nfsd/nfs2acl.c8
-rw-r--r--fs/nfsd/nfs3acl.c8
-rw-r--r--fs/nfsd/nfs3xdr.c24
-rw-r--r--fs/nfsd/nfs4proc.c625
-rw-r--r--fs/nfsd/nfs4recover.c2
-rw-r--r--fs/nfsd/nfs4state.c116
-rw-r--r--fs/nfsd/nfs4xdr.c14
-rw-r--r--fs/nfsd/nfscache.c3
-rw-r--r--fs/nfsd/nfsctl.c2
-rw-r--r--fs/nfsd/nfsfh.c6
-rw-r--r--fs/nfsd/nfsxdr.c13
-rw-r--r--fs/nfsd/vfs.c55
14 files changed, 496 insertions, 415 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index f37df46d2eaa..248dd92e6a56 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -787,15 +787,20 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
787 key.ex_dentry = dentry; 787 key.ex_dentry = dentry;
788 788
789 exp = svc_export_lookup(&key); 789 exp = svc_export_lookup(&key);
790 if (exp != NULL) 790 if (exp != NULL) {
791 switch (cache_check(&svc_export_cache, &exp->h, reqp)) { 791 int err;
792
793 err = cache_check(&svc_export_cache, &exp->h, reqp);
794 switch (err) {
792 case 0: break; 795 case 0: break;
793 case -EAGAIN: 796 case -EAGAIN:
794 exp = ERR_PTR(-EAGAIN); 797 case -ETIMEDOUT:
798 exp = ERR_PTR(err);
795 break; 799 break;
796 default: 800 default:
797 exp = NULL; 801 exp = NULL;
798 } 802 }
803 }
799 804
800 return exp; 805 return exp;
801} 806}
@@ -950,6 +955,8 @@ exp_export(struct nfsctl_export *nxp)
950 955
951 exp = exp_get_by_name(clp, nd.mnt, nd.dentry, NULL); 956 exp = exp_get_by_name(clp, nd.mnt, nd.dentry, NULL);
952 957
958 memset(&new, 0, sizeof(new));
959
953 /* must make sure there won't be an ex_fsid clash */ 960 /* must make sure there won't be an ex_fsid clash */
954 if ((nxp->ex_flags & NFSEXP_FSID) && 961 if ((nxp->ex_flags & NFSEXP_FSID) &&
955 (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) && 962 (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
@@ -980,6 +987,9 @@ exp_export(struct nfsctl_export *nxp)
980 987
981 new.h.expiry_time = NEVER; 988 new.h.expiry_time = NEVER;
982 new.h.flags = 0; 989 new.h.flags = 0;
990 new.ex_path = kstrdup(nxp->ex_path, GFP_KERNEL);
991 if (!new.ex_path)
992 goto finish;
983 new.ex_client = clp; 993 new.ex_client = clp;
984 new.ex_mnt = nd.mnt; 994 new.ex_mnt = nd.mnt;
985 new.ex_dentry = nd.dentry; 995 new.ex_dentry = nd.dentry;
@@ -1000,10 +1010,11 @@ exp_export(struct nfsctl_export *nxp)
1000 /* failed to create at least one index */ 1010 /* failed to create at least one index */
1001 exp_do_unexport(exp); 1011 exp_do_unexport(exp);
1002 cache_flush(); 1012 cache_flush();
1003 err = -ENOMEM; 1013 } else
1004 } 1014 err = 0;
1005
1006finish: 1015finish:
1016 if (new.ex_path)
1017 kfree(new.ex_path);
1007 if (exp) 1018 if (exp)
1008 exp_put(exp); 1019 exp_put(exp);
1009 if (fsid_key && !IS_ERR(fsid_key)) 1020 if (fsid_key && !IS_ERR(fsid_key))
@@ -1104,6 +1115,10 @@ exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
1104 path, nd.dentry, clp->name, 1115 path, nd.dentry, clp->name,
1105 inode->i_sb->s_id, inode->i_ino); 1116 inode->i_sb->s_id, inode->i_ino);
1106 exp = exp_parent(clp, nd.mnt, nd.dentry, NULL); 1117 exp = exp_parent(clp, nd.mnt, nd.dentry, NULL);
1118 if (IS_ERR(exp)) {
1119 err = PTR_ERR(exp);
1120 goto out;
1121 }
1107 if (!exp) { 1122 if (!exp) {
1108 dprintk("nfsd: exp_rootfh export not found.\n"); 1123 dprintk("nfsd: exp_rootfh export not found.\n");
1109 goto out; 1124 goto out;
@@ -1159,12 +1174,10 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
1159 mk_fsid_v1(fsidv, 0); 1174 mk_fsid_v1(fsidv, 0);
1160 1175
1161 exp = exp_find(clp, 1, fsidv, creq); 1176 exp = exp_find(clp, 1, fsidv, creq);
1162 if (IS_ERR(exp) && PTR_ERR(exp) == -EAGAIN) 1177 if (IS_ERR(exp))
1163 return nfserr_dropit; 1178 return nfserrno(PTR_ERR(exp));
1164 if (exp == NULL) 1179 if (exp == NULL)
1165 return nfserr_perm; 1180 return nfserr_perm;
1166 else if (IS_ERR(exp))
1167 return nfserrno(PTR_ERR(exp));
1168 rv = fh_compose(fhp, exp, exp->ex_dentry, NULL); 1181 rv = fh_compose(fhp, exp, exp->ex_dentry, NULL);
1169 exp_put(exp); 1182 exp_put(exp);
1170 return rv; 1183 return rv;
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 11fdaf7721b4..221acd1f11f6 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -22,7 +22,7 @@
22/* 22/*
23 * Note: we hold the dentry use count while the file is open. 23 * Note: we hold the dentry use count while the file is open.
24 */ 24 */
25static u32 25static __be32
26nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp) 26nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
27{ 27{
28 __be32 nfserr; 28 __be32 nfserr;
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index e3eca0816986..edde5dc5f796 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -222,12 +222,10 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
222{ 222{
223 struct dentry *dentry = resp->fh.fh_dentry; 223 struct dentry *dentry = resp->fh.fh_dentry;
224 struct inode *inode = dentry->d_inode; 224 struct inode *inode = dentry->d_inode;
225 int w = nfsacl_size(
226 (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
227 (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
228 struct kvec *head = rqstp->rq_res.head; 225 struct kvec *head = rqstp->rq_res.head;
229 unsigned int base; 226 unsigned int base;
230 int n; 227 int n;
228 int w;
231 229
232 if (dentry == NULL || dentry->d_inode == NULL) 230 if (dentry == NULL || dentry->d_inode == NULL)
233 return 0; 231 return 0;
@@ -239,7 +237,9 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
239 return 0; 237 return 0;
240 base = (char *)p - (char *)head->iov_base; 238 base = (char *)p - (char *)head->iov_base;
241 239
242 rqstp->rq_res.page_len = w; 240 rqstp->rq_res.page_len = w = nfsacl_size(
241 (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
242 (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
243 while (w > 0) { 243 while (w > 0) {
244 if (!rqstp->rq_respages[rqstp->rq_resused++]) 244 if (!rqstp->rq_respages[rqstp->rq_resused++])
245 return 0; 245 return 0;
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index fcad2895ddb0..3e3f2de82c36 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -171,19 +171,19 @@ static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p,
171 p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh); 171 p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
172 if (resp->status == 0 && dentry && dentry->d_inode) { 172 if (resp->status == 0 && dentry && dentry->d_inode) {
173 struct inode *inode = dentry->d_inode; 173 struct inode *inode = dentry->d_inode;
174 int w = nfsacl_size(
175 (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
176 (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
177 struct kvec *head = rqstp->rq_res.head; 174 struct kvec *head = rqstp->rq_res.head;
178 unsigned int base; 175 unsigned int base;
179 int n; 176 int n;
177 int w;
180 178
181 *p++ = htonl(resp->mask); 179 *p++ = htonl(resp->mask);
182 if (!xdr_ressize_check(rqstp, p)) 180 if (!xdr_ressize_check(rqstp, p))
183 return 0; 181 return 0;
184 base = (char *)p - (char *)head->iov_base; 182 base = (char *)p - (char *)head->iov_base;
185 183
186 rqstp->rq_res.page_len = w; 184 rqstp->rq_res.page_len = w = nfsacl_size(
185 (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
186 (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
187 while (w > 0) { 187 while (w > 0) {
188 if (!rqstp->rq_respages[rqstp->rq_resused++]) 188 if (!rqstp->rq_respages[rqstp->rq_resused++])
189 return 0; 189 return 0;
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index b4baca3053c3..277df40f098d 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -24,10 +24,6 @@
24 24
25#define NFSDDBG_FACILITY NFSDDBG_XDR 25#define NFSDDBG_FACILITY NFSDDBG_XDR
26 26
27#ifdef NFSD_OPTIMIZE_SPACE
28# define inline
29#endif
30
31 27
32/* 28/*
33 * Mapping of S_IF* types to NFS file types 29 * Mapping of S_IF* types to NFS file types
@@ -42,14 +38,14 @@ static u32 nfs3_ftypes[] = {
42/* 38/*
43 * XDR functions for basic NFS types 39 * XDR functions for basic NFS types
44 */ 40 */
45static inline __be32 * 41static __be32 *
46encode_time3(__be32 *p, struct timespec *time) 42encode_time3(__be32 *p, struct timespec *time)
47{ 43{
48 *p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec); 44 *p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec);
49 return p; 45 return p;
50} 46}
51 47
52static inline __be32 * 48static __be32 *
53decode_time3(__be32 *p, struct timespec *time) 49decode_time3(__be32 *p, struct timespec *time)
54{ 50{
55 time->tv_sec = ntohl(*p++); 51 time->tv_sec = ntohl(*p++);
@@ -57,7 +53,7 @@ decode_time3(__be32 *p, struct timespec *time)
57 return p; 53 return p;
58} 54}
59 55
60static inline __be32 * 56static __be32 *
61decode_fh(__be32 *p, struct svc_fh *fhp) 57decode_fh(__be32 *p, struct svc_fh *fhp)
62{ 58{
63 unsigned int size; 59 unsigned int size;
@@ -77,7 +73,7 @@ __be32 *nfs3svc_decode_fh(__be32 *p, struct svc_fh *fhp)
77 return decode_fh(p, fhp); 73 return decode_fh(p, fhp);
78} 74}
79 75
80static inline __be32 * 76static __be32 *
81encode_fh(__be32 *p, struct svc_fh *fhp) 77encode_fh(__be32 *p, struct svc_fh *fhp)
82{ 78{
83 unsigned int size = fhp->fh_handle.fh_size; 79 unsigned int size = fhp->fh_handle.fh_size;
@@ -91,7 +87,7 @@ encode_fh(__be32 *p, struct svc_fh *fhp)
91 * Decode a file name and make sure that the path contains 87 * Decode a file name and make sure that the path contains
92 * no slashes or null bytes. 88 * no slashes or null bytes.
93 */ 89 */
94static inline __be32 * 90static __be32 *
95decode_filename(__be32 *p, char **namp, int *lenp) 91decode_filename(__be32 *p, char **namp, int *lenp)
96{ 92{
97 char *name; 93 char *name;
@@ -107,7 +103,7 @@ decode_filename(__be32 *p, char **namp, int *lenp)
107 return p; 103 return p;
108} 104}
109 105
110static inline __be32 * 106static __be32 *
111decode_sattr3(__be32 *p, struct iattr *iap) 107decode_sattr3(__be32 *p, struct iattr *iap)
112{ 108{
113 u32 tmp; 109 u32 tmp;
@@ -153,7 +149,7 @@ decode_sattr3(__be32 *p, struct iattr *iap)
153 return p; 149 return p;
154} 150}
155 151
156static inline __be32 * 152static __be32 *
157encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, 153encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
158 struct kstat *stat) 154 struct kstat *stat)
159{ 155{
@@ -186,7 +182,7 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
186 return p; 182 return p;
187} 183}
188 184
189static inline __be32 * 185static __be32 *
190encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) 186encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
191{ 187{
192 struct inode *inode = fhp->fh_dentry->d_inode; 188 struct inode *inode = fhp->fh_dentry->d_inode;
@@ -776,7 +772,7 @@ nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p,
776 return xdr_ressize_check(rqstp, p); 772 return xdr_ressize_check(rqstp, p);
777} 773}
778 774
779static inline __be32 * 775static __be32 *
780encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, 776encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name,
781 int namlen, ino_t ino) 777 int namlen, ino_t ino)
782{ 778{
@@ -790,7 +786,7 @@ encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name,
790 return p; 786 return p;
791} 787}
792 788
793static inline __be32 * 789static __be32 *
794encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, 790encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p,
795 struct svc_fh *fhp) 791 struct svc_fh *fhp)
796{ 792{
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 50bc94243ca1..8522729830db 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -33,13 +33,6 @@
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Note: some routines in this file are just trivial wrappers
38 * (e.g. nfsd4_lookup()) defined solely for the sake of consistent
39 * naming. Since all such routines have been declared "inline",
40 * there shouldn't be any associated overhead. At some point in
41 * the future, I might inline these "by hand" to clean up a
42 * little.
43 */ 36 */
44 37
45#include <linux/param.h> 38#include <linux/param.h>
@@ -161,8 +154,9 @@ do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_
161} 154}
162 155
163 156
164static inline __be32 157static __be32
165nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, struct nfs4_stateowner **replay_owner) 158nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
159 struct nfsd4_open *open)
166{ 160{
167 __be32 status; 161 __be32 status;
168 dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n", 162 dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n",
@@ -179,11 +173,11 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
179 status = nfsd4_process_open1(open); 173 status = nfsd4_process_open1(open);
180 if (status == nfserr_replay_me) { 174 if (status == nfserr_replay_me) {
181 struct nfs4_replay *rp = &open->op_stateowner->so_replay; 175 struct nfs4_replay *rp = &open->op_stateowner->so_replay;
182 fh_put(current_fh); 176 fh_put(&cstate->current_fh);
183 current_fh->fh_handle.fh_size = rp->rp_openfh_len; 177 cstate->current_fh.fh_handle.fh_size = rp->rp_openfh_len;
184 memcpy(&current_fh->fh_handle.fh_base, rp->rp_openfh, 178 memcpy(&cstate->current_fh.fh_handle.fh_base, rp->rp_openfh,
185 rp->rp_openfh_len); 179 rp->rp_openfh_len);
186 status = fh_verify(rqstp, current_fh, 0, MAY_NOP); 180 status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
187 if (status) 181 if (status)
188 dprintk("nfsd4_open: replay failed" 182 dprintk("nfsd4_open: replay failed"
189 " restoring previous filehandle\n"); 183 " restoring previous filehandle\n");
@@ -215,7 +209,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
215 * (3) set open->op_truncate if the file is to be 209 * (3) set open->op_truncate if the file is to be
216 * truncated after opening, (4) do permission checking. 210 * truncated after opening, (4) do permission checking.
217 */ 211 */
218 status = do_open_lookup(rqstp, current_fh, open); 212 status = do_open_lookup(rqstp, &cstate->current_fh,
213 open);
219 if (status) 214 if (status)
220 goto out; 215 goto out;
221 break; 216 break;
@@ -227,7 +222,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
227 * open->op_truncate if the file is to be truncated 222 * open->op_truncate if the file is to be truncated
228 * after opening, (3) do permission checking. 223 * after opening, (3) do permission checking.
229 */ 224 */
230 status = do_open_fhandle(rqstp, current_fh, open); 225 status = do_open_fhandle(rqstp, &cstate->current_fh,
226 open);
231 if (status) 227 if (status)
232 goto out; 228 goto out;
233 break; 229 break;
@@ -248,11 +244,11 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
248 * successful, it (1) truncates the file if open->op_truncate was 244 * successful, it (1) truncates the file if open->op_truncate was
249 * set, (2) sets open->op_stateid, (3) sets open->op_delegation. 245 * set, (2) sets open->op_stateid, (3) sets open->op_delegation.
250 */ 246 */
251 status = nfsd4_process_open2(rqstp, current_fh, open); 247 status = nfsd4_process_open2(rqstp, &cstate->current_fh, open);
252out: 248out:
253 if (open->op_stateowner) { 249 if (open->op_stateowner) {
254 nfs4_get_stateowner(open->op_stateowner); 250 nfs4_get_stateowner(open->op_stateowner);
255 *replay_owner = open->op_stateowner; 251 cstate->replay_owner = open->op_stateowner;
256 } 252 }
257 nfs4_unlock_state(); 253 nfs4_unlock_state();
258 return status; 254 return status;
@@ -261,71 +257,80 @@ out:
261/* 257/*
262 * filehandle-manipulating ops. 258 * filehandle-manipulating ops.
263 */ 259 */
264static inline __be32 260static __be32
265nfsd4_getfh(struct svc_fh *current_fh, struct svc_fh **getfh) 261nfsd4_getfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
262 struct svc_fh **getfh)
266{ 263{
267 if (!current_fh->fh_dentry) 264 if (!cstate->current_fh.fh_dentry)
268 return nfserr_nofilehandle; 265 return nfserr_nofilehandle;
269 266
270 *getfh = current_fh; 267 *getfh = &cstate->current_fh;
271 return nfs_ok; 268 return nfs_ok;
272} 269}
273 270
274static inline __be32 271static __be32
275nfsd4_putfh(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_putfh *putfh) 272nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
273 struct nfsd4_putfh *putfh)
276{ 274{
277 fh_put(current_fh); 275 fh_put(&cstate->current_fh);
278 current_fh->fh_handle.fh_size = putfh->pf_fhlen; 276 cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
279 memcpy(&current_fh->fh_handle.fh_base, putfh->pf_fhval, putfh->pf_fhlen); 277 memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
280 return fh_verify(rqstp, current_fh, 0, MAY_NOP); 278 putfh->pf_fhlen);
279 return fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
281} 280}
282 281
283static inline __be32 282static __be32
284nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh) 283nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
284 void *arg)
285{ 285{
286 __be32 status; 286 __be32 status;
287 287
288 fh_put(current_fh); 288 fh_put(&cstate->current_fh);
289 status = exp_pseudoroot(rqstp->rq_client, current_fh, 289 status = exp_pseudoroot(rqstp->rq_client, &cstate->current_fh,
290 &rqstp->rq_chandle); 290 &rqstp->rq_chandle);
291 return status; 291 return status;
292} 292}
293 293
294static inline __be32 294static __be32
295nfsd4_restorefh(struct svc_fh *current_fh, struct svc_fh *save_fh) 295nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
296 void *arg)
296{ 297{
297 if (!save_fh->fh_dentry) 298 if (!cstate->save_fh.fh_dentry)
298 return nfserr_restorefh; 299 return nfserr_restorefh;
299 300
300 fh_dup2(current_fh, save_fh); 301 fh_dup2(&cstate->current_fh, &cstate->save_fh);
301 return nfs_ok; 302 return nfs_ok;
302} 303}
303 304
304static inline __be32 305static __be32
305nfsd4_savefh(struct svc_fh *current_fh, struct svc_fh *save_fh) 306nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
307 void *arg)
306{ 308{
307 if (!current_fh->fh_dentry) 309 if (!cstate->current_fh.fh_dentry)
308 return nfserr_nofilehandle; 310 return nfserr_nofilehandle;
309 311
310 fh_dup2(save_fh, current_fh); 312 fh_dup2(&cstate->save_fh, &cstate->current_fh);
311 return nfs_ok; 313 return nfs_ok;
312} 314}
313 315
314/* 316/*
315 * misc nfsv4 ops 317 * misc nfsv4 ops
316 */ 318 */
317static inline __be32 319static __be32
318nfsd4_access(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_access *access) 320nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
321 struct nfsd4_access *access)
319{ 322{
320 if (access->ac_req_access & ~NFS3_ACCESS_FULL) 323 if (access->ac_req_access & ~NFS3_ACCESS_FULL)
321 return nfserr_inval; 324 return nfserr_inval;
322 325
323 access->ac_resp_access = access->ac_req_access; 326 access->ac_resp_access = access->ac_req_access;
324 return nfsd_access(rqstp, current_fh, &access->ac_resp_access, &access->ac_supported); 327 return nfsd_access(rqstp, &cstate->current_fh, &access->ac_resp_access,
328 &access->ac_supported);
325} 329}
326 330
327static inline __be32 331static __be32
328nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_commit *commit) 332nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
333 struct nfsd4_commit *commit)
329{ 334{
330 __be32 status; 335 __be32 status;
331 336
@@ -333,14 +338,16 @@ nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_com
333 *p++ = nfssvc_boot.tv_sec; 338 *p++ = nfssvc_boot.tv_sec;
334 *p++ = nfssvc_boot.tv_usec; 339 *p++ = nfssvc_boot.tv_usec;
335 340
336 status = nfsd_commit(rqstp, current_fh, commit->co_offset, commit->co_count); 341 status = nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
342 commit->co_count);
337 if (status == nfserr_symlink) 343 if (status == nfserr_symlink)
338 status = nfserr_inval; 344 status = nfserr_inval;
339 return status; 345 return status;
340} 346}
341 347
342static __be32 348static __be32
343nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_create *create) 349nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
350 struct nfsd4_create *create)
344{ 351{
345 struct svc_fh resfh; 352 struct svc_fh resfh;
346 __be32 status; 353 __be32 status;
@@ -348,7 +355,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre
348 355
349 fh_init(&resfh, NFS4_FHSIZE); 356 fh_init(&resfh, NFS4_FHSIZE);
350 357
351 status = fh_verify(rqstp, current_fh, S_IFDIR, MAY_CREATE); 358 status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, MAY_CREATE);
352 if (status == nfserr_symlink) 359 if (status == nfserr_symlink)
353 status = nfserr_notdir; 360 status = nfserr_notdir;
354 if (status) 361 if (status)
@@ -365,9 +372,10 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre
365 */ 372 */
366 create->cr_linkname[create->cr_linklen] = 0; 373 create->cr_linkname[create->cr_linklen] = 0;
367 374
368 status = nfsd_symlink(rqstp, current_fh, create->cr_name, 375 status = nfsd_symlink(rqstp, &cstate->current_fh,
369 create->cr_namelen, create->cr_linkname, 376 create->cr_name, create->cr_namelen,
370 create->cr_linklen, &resfh, &create->cr_iattr); 377 create->cr_linkname, create->cr_linklen,
378 &resfh, &create->cr_iattr);
371 break; 379 break;
372 380
373 case NF4BLK: 381 case NF4BLK:
@@ -375,9 +383,9 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre
375 if (MAJOR(rdev) != create->cr_specdata1 || 383 if (MAJOR(rdev) != create->cr_specdata1 ||
376 MINOR(rdev) != create->cr_specdata2) 384 MINOR(rdev) != create->cr_specdata2)
377 return nfserr_inval; 385 return nfserr_inval;
378 status = nfsd_create(rqstp, current_fh, create->cr_name, 386 status = nfsd_create(rqstp, &cstate->current_fh,
379 create->cr_namelen, &create->cr_iattr, 387 create->cr_name, create->cr_namelen,
380 S_IFBLK, rdev, &resfh); 388 &create->cr_iattr, S_IFBLK, rdev, &resfh);
381 break; 389 break;
382 390
383 case NF4CHR: 391 case NF4CHR:
@@ -385,28 +393,28 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre
385 if (MAJOR(rdev) != create->cr_specdata1 || 393 if (MAJOR(rdev) != create->cr_specdata1 ||
386 MINOR(rdev) != create->cr_specdata2) 394 MINOR(rdev) != create->cr_specdata2)
387 return nfserr_inval; 395 return nfserr_inval;
388 status = nfsd_create(rqstp, current_fh, create->cr_name, 396 status = nfsd_create(rqstp, &cstate->current_fh,
389 create->cr_namelen, &create->cr_iattr, 397 create->cr_name, create->cr_namelen,
390 S_IFCHR, rdev, &resfh); 398 &create->cr_iattr,S_IFCHR, rdev, &resfh);
391 break; 399 break;
392 400
393 case NF4SOCK: 401 case NF4SOCK:
394 status = nfsd_create(rqstp, current_fh, create->cr_name, 402 status = nfsd_create(rqstp, &cstate->current_fh,
395 create->cr_namelen, &create->cr_iattr, 403 create->cr_name, create->cr_namelen,
396 S_IFSOCK, 0, &resfh); 404 &create->cr_iattr, S_IFSOCK, 0, &resfh);
397 break; 405 break;
398 406
399 case NF4FIFO: 407 case NF4FIFO:
400 status = nfsd_create(rqstp, current_fh, create->cr_name, 408 status = nfsd_create(rqstp, &cstate->current_fh,
401 create->cr_namelen, &create->cr_iattr, 409 create->cr_name, create->cr_namelen,
402 S_IFIFO, 0, &resfh); 410 &create->cr_iattr, S_IFIFO, 0, &resfh);
403 break; 411 break;
404 412
405 case NF4DIR: 413 case NF4DIR:
406 create->cr_iattr.ia_valid &= ~ATTR_SIZE; 414 create->cr_iattr.ia_valid &= ~ATTR_SIZE;
407 status = nfsd_create(rqstp, current_fh, create->cr_name, 415 status = nfsd_create(rqstp, &cstate->current_fh,
408 create->cr_namelen, &create->cr_iattr, 416 create->cr_name, create->cr_namelen,
409 S_IFDIR, 0, &resfh); 417 &create->cr_iattr, S_IFDIR, 0, &resfh);
410 break; 418 break;
411 419
412 default: 420 default:
@@ -414,21 +422,22 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre
414 } 422 }
415 423
416 if (!status) { 424 if (!status) {
417 fh_unlock(current_fh); 425 fh_unlock(&cstate->current_fh);
418 set_change_info(&create->cr_cinfo, current_fh); 426 set_change_info(&create->cr_cinfo, &cstate->current_fh);
419 fh_dup2(current_fh, &resfh); 427 fh_dup2(&cstate->current_fh, &resfh);
420 } 428 }
421 429
422 fh_put(&resfh); 430 fh_put(&resfh);
423 return status; 431 return status;
424} 432}
425 433
426static inline __be32 434static __be32
427nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_getattr *getattr) 435nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
436 struct nfsd4_getattr *getattr)
428{ 437{
429 __be32 status; 438 __be32 status;
430 439
431 status = fh_verify(rqstp, current_fh, 0, MAY_NOP); 440 status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
432 if (status) 441 if (status)
433 return status; 442 return status;
434 443
@@ -438,26 +447,28 @@ nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_ge
438 getattr->ga_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0; 447 getattr->ga_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0;
439 getattr->ga_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1; 448 getattr->ga_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
440 449
441 getattr->ga_fhp = current_fh; 450 getattr->ga_fhp = &cstate->current_fh;
442 return nfs_ok; 451 return nfs_ok;
443} 452}
444 453
445static inline __be32 454static __be32
446nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh, 455nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
447 struct svc_fh *save_fh, struct nfsd4_link *link) 456 struct nfsd4_link *link)
448{ 457{
449 __be32 status = nfserr_nofilehandle; 458 __be32 status = nfserr_nofilehandle;
450 459
451 if (!save_fh->fh_dentry) 460 if (!cstate->save_fh.fh_dentry)
452 return status; 461 return status;
453 status = nfsd_link(rqstp, current_fh, link->li_name, link->li_namelen, save_fh); 462 status = nfsd_link(rqstp, &cstate->current_fh,
463 link->li_name, link->li_namelen, &cstate->save_fh);
454 if (!status) 464 if (!status)
455 set_change_info(&link->li_cinfo, current_fh); 465 set_change_info(&link->li_cinfo, &cstate->current_fh);
456 return status; 466 return status;
457} 467}
458 468
459static __be32 469static __be32
460nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh) 470nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
471 void *arg)
461{ 472{
462 struct svc_fh tmp_fh; 473 struct svc_fh tmp_fh;
463 __be32 ret; 474 __be32 ret;
@@ -466,22 +477,27 @@ nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh)
466 if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh, 477 if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh,
467 &rqstp->rq_chandle)) != 0) 478 &rqstp->rq_chandle)) != 0)
468 return ret; 479 return ret;
469 if (tmp_fh.fh_dentry == current_fh->fh_dentry) { 480 if (tmp_fh.fh_dentry == cstate->current_fh.fh_dentry) {
470 fh_put(&tmp_fh); 481 fh_put(&tmp_fh);
471 return nfserr_noent; 482 return nfserr_noent;
472 } 483 }
473 fh_put(&tmp_fh); 484 fh_put(&tmp_fh);
474 return nfsd_lookup(rqstp, current_fh, "..", 2, current_fh); 485 return nfsd_lookup(rqstp, &cstate->current_fh,
486 "..", 2, &cstate->current_fh);
475} 487}
476 488
477static inline __be32 489static __be32
478nfsd4_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lookup *lookup) 490nfsd4_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
491 struct nfsd4_lookup *lookup)
479{ 492{
480 return nfsd_lookup(rqstp, current_fh, lookup->lo_name, lookup->lo_len, current_fh); 493 return nfsd_lookup(rqstp, &cstate->current_fh,
494 lookup->lo_name, lookup->lo_len,
495 &cstate->current_fh);
481} 496}
482 497
483static inline __be32 498static __be32
484nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read) 499nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
500 struct nfsd4_read *read)
485{ 501{
486 __be32 status; 502 __be32 status;
487 503
@@ -493,7 +509,8 @@ nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read
493 509
494 nfs4_lock_state(); 510 nfs4_lock_state();
495 /* check stateid */ 511 /* check stateid */
496 if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid, 512 if ((status = nfs4_preprocess_stateid_op(&cstate->current_fh,
513 &read->rd_stateid,
497 CHECK_FH | RD_STATE, &read->rd_filp))) { 514 CHECK_FH | RD_STATE, &read->rd_filp))) {
498 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n"); 515 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
499 goto out; 516 goto out;
@@ -504,12 +521,13 @@ nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read
504out: 521out:
505 nfs4_unlock_state(); 522 nfs4_unlock_state();
506 read->rd_rqstp = rqstp; 523 read->rd_rqstp = rqstp;
507 read->rd_fhp = current_fh; 524 read->rd_fhp = &cstate->current_fh;
508 return status; 525 return status;
509} 526}
510 527
511static inline __be32 528static __be32
512nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readdir *readdir) 529nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
530 struct nfsd4_readdir *readdir)
513{ 531{
514 u64 cookie = readdir->rd_cookie; 532 u64 cookie = readdir->rd_cookie;
515 static const nfs4_verifier zeroverf; 533 static const nfs4_verifier zeroverf;
@@ -527,48 +545,51 @@ nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_re
527 return nfserr_bad_cookie; 545 return nfserr_bad_cookie;
528 546
529 readdir->rd_rqstp = rqstp; 547 readdir->rd_rqstp = rqstp;
530 readdir->rd_fhp = current_fh; 548 readdir->rd_fhp = &cstate->current_fh;
531 return nfs_ok; 549 return nfs_ok;
532} 550}
533 551
534static inline __be32 552static __be32
535nfsd4_readlink(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readlink *readlink) 553nfsd4_readlink(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
554 struct nfsd4_readlink *readlink)
536{ 555{
537 readlink->rl_rqstp = rqstp; 556 readlink->rl_rqstp = rqstp;
538 readlink->rl_fhp = current_fh; 557 readlink->rl_fhp = &cstate->current_fh;
539 return nfs_ok; 558 return nfs_ok;
540} 559}
541 560
542static inline __be32 561static __be32
543nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_remove *remove) 562nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
563 struct nfsd4_remove *remove)
544{ 564{
545 __be32 status; 565 __be32 status;
546 566
547 if (nfs4_in_grace()) 567 if (nfs4_in_grace())
548 return nfserr_grace; 568 return nfserr_grace;
549 status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen); 569 status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
570 remove->rm_name, remove->rm_namelen);
550 if (status == nfserr_symlink) 571 if (status == nfserr_symlink)
551 return nfserr_notdir; 572 return nfserr_notdir;
552 if (!status) { 573 if (!status) {
553 fh_unlock(current_fh); 574 fh_unlock(&cstate->current_fh);
554 set_change_info(&remove->rm_cinfo, current_fh); 575 set_change_info(&remove->rm_cinfo, &cstate->current_fh);
555 } 576 }
556 return status; 577 return status;
557} 578}
558 579
559static inline __be32 580static __be32
560nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh, 581nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
561 struct svc_fh *save_fh, struct nfsd4_rename *rename) 582 struct nfsd4_rename *rename)
562{ 583{
563 __be32 status = nfserr_nofilehandle; 584 __be32 status = nfserr_nofilehandle;
564 585
565 if (!save_fh->fh_dentry) 586 if (!cstate->save_fh.fh_dentry)
566 return status; 587 return status;
567 if (nfs4_in_grace() && !(save_fh->fh_export->ex_flags 588 if (nfs4_in_grace() && !(cstate->save_fh.fh_export->ex_flags
568 & NFSEXP_NOSUBTREECHECK)) 589 & NFSEXP_NOSUBTREECHECK))
569 return nfserr_grace; 590 return nfserr_grace;
570 status = nfsd_rename(rqstp, save_fh, rename->rn_sname, 591 status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
571 rename->rn_snamelen, current_fh, 592 rename->rn_snamelen, &cstate->current_fh,
572 rename->rn_tname, rename->rn_tnamelen); 593 rename->rn_tname, rename->rn_tnamelen);
573 594
574 /* the underlying filesystem returns different error's than required 595 /* the underlying filesystem returns different error's than required
@@ -576,27 +597,28 @@ nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
576 if (status == nfserr_isdir) 597 if (status == nfserr_isdir)
577 status = nfserr_exist; 598 status = nfserr_exist;
578 else if ((status == nfserr_notdir) && 599 else if ((status == nfserr_notdir) &&
579 (S_ISDIR(save_fh->fh_dentry->d_inode->i_mode) && 600 (S_ISDIR(cstate->save_fh.fh_dentry->d_inode->i_mode) &&
580 S_ISDIR(current_fh->fh_dentry->d_inode->i_mode))) 601 S_ISDIR(cstate->current_fh.fh_dentry->d_inode->i_mode)))
581 status = nfserr_exist; 602 status = nfserr_exist;
582 else if (status == nfserr_symlink) 603 else if (status == nfserr_symlink)
583 status = nfserr_notdir; 604 status = nfserr_notdir;
584 605
585 if (!status) { 606 if (!status) {
586 set_change_info(&rename->rn_sinfo, current_fh); 607 set_change_info(&rename->rn_sinfo, &cstate->current_fh);
587 set_change_info(&rename->rn_tinfo, save_fh); 608 set_change_info(&rename->rn_tinfo, &cstate->save_fh);
588 } 609 }
589 return status; 610 return status;
590} 611}
591 612
592static inline __be32 613static __be32
593nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr) 614nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
615 struct nfsd4_setattr *setattr)
594{ 616{
595 __be32 status = nfs_ok; 617 __be32 status = nfs_ok;
596 618
597 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { 619 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
598 nfs4_lock_state(); 620 nfs4_lock_state();
599 status = nfs4_preprocess_stateid_op(current_fh, 621 status = nfs4_preprocess_stateid_op(&cstate->current_fh,
600 &setattr->sa_stateid, CHECK_FH | WR_STATE, NULL); 622 &setattr->sa_stateid, CHECK_FH | WR_STATE, NULL);
601 nfs4_unlock_state(); 623 nfs4_unlock_state();
602 if (status) { 624 if (status) {
@@ -606,16 +628,18 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
606 } 628 }
607 status = nfs_ok; 629 status = nfs_ok;
608 if (setattr->sa_acl != NULL) 630 if (setattr->sa_acl != NULL)
609 status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl); 631 status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
632 setattr->sa_acl);
610 if (status) 633 if (status)
611 return status; 634 return status;
612 status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr, 635 status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
613 0, (time_t)0); 636 0, (time_t)0);
614 return status; 637 return status;
615} 638}
616 639
617static inline __be32 640static __be32
618nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write) 641nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
642 struct nfsd4_write *write)
619{ 643{
620 stateid_t *stateid = &write->wr_stateid; 644 stateid_t *stateid = &write->wr_stateid;
621 struct file *filp = NULL; 645 struct file *filp = NULL;
@@ -628,7 +652,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
628 return nfserr_inval; 652 return nfserr_inval;
629 653
630 nfs4_lock_state(); 654 nfs4_lock_state();
631 status = nfs4_preprocess_stateid_op(current_fh, stateid, 655 status = nfs4_preprocess_stateid_op(&cstate->current_fh, stateid,
632 CHECK_FH | WR_STATE, &filp); 656 CHECK_FH | WR_STATE, &filp);
633 if (filp) 657 if (filp)
634 get_file(filp); 658 get_file(filp);
@@ -645,9 +669,9 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
645 *p++ = nfssvc_boot.tv_sec; 669 *p++ = nfssvc_boot.tv_sec;
646 *p++ = nfssvc_boot.tv_usec; 670 *p++ = nfssvc_boot.tv_usec;
647 671
648 status = nfsd_write(rqstp, current_fh, filp, write->wr_offset, 672 status = nfsd_write(rqstp, &cstate->current_fh, filp,
649 rqstp->rq_vec, write->wr_vlen, write->wr_buflen, 673 write->wr_offset, rqstp->rq_vec, write->wr_vlen,
650 &write->wr_how_written); 674 write->wr_buflen, &write->wr_how_written);
651 if (filp) 675 if (filp)
652 fput(filp); 676 fput(filp);
653 677
@@ -662,13 +686,14 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
662 * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK. 686 * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK.
663 */ 687 */
664static __be32 688static __be32
665nfsd4_verify(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_verify *verify) 689_nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
690 struct nfsd4_verify *verify)
666{ 691{
667 __be32 *buf, *p; 692 __be32 *buf, *p;
668 int count; 693 int count;
669 __be32 status; 694 __be32 status;
670 695
671 status = fh_verify(rqstp, current_fh, 0, MAY_NOP); 696 status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
672 if (status) 697 if (status)
673 return status; 698 return status;
674 699
@@ -689,8 +714,9 @@ nfsd4_verify(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_ver
689 if (!buf) 714 if (!buf)
690 return nfserr_resource; 715 return nfserr_resource;
691 716
692 status = nfsd4_encode_fattr(current_fh, current_fh->fh_export, 717 status = nfsd4_encode_fattr(&cstate->current_fh,
693 current_fh->fh_dentry, buf, 718 cstate->current_fh.fh_export,
719 cstate->current_fh.fh_dentry, buf,
694 &count, verify->ve_bmval, 720 &count, verify->ve_bmval,
695 rqstp); 721 rqstp);
696 722
@@ -712,6 +738,26 @@ out_kfree:
712 return status; 738 return status;
713} 739}
714 740
741static __be32
742nfsd4_nverify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
743 struct nfsd4_verify *verify)
744{
745 __be32 status;
746
747 status = _nfsd4_verify(rqstp, cstate, verify);
748 return status == nfserr_not_same ? nfs_ok : status;
749}
750
751static __be32
752nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
753 struct nfsd4_verify *verify)
754{
755 __be32 status;
756
757 status = _nfsd4_verify(rqstp, cstate, verify);
758 return status == nfserr_same ? nfs_ok : status;
759}
760
715/* 761/*
716 * NULL call. 762 * NULL call.
717 */ 763 */
@@ -727,6 +773,42 @@ static inline void nfsd4_increment_op_stats(u32 opnum)
727 nfsdstats.nfs4_opcount[opnum]++; 773 nfsdstats.nfs4_opcount[opnum]++;
728} 774}
729 775
776static void cstate_free(struct nfsd4_compound_state *cstate)
777{
778 if (cstate == NULL)
779 return;
780 fh_put(&cstate->current_fh);
781 fh_put(&cstate->save_fh);
782 BUG_ON(cstate->replay_owner);
783 kfree(cstate);
784}
785
786static struct nfsd4_compound_state *cstate_alloc(void)
787{
788 struct nfsd4_compound_state *cstate;
789
790 cstate = kmalloc(sizeof(struct nfsd4_compound_state), GFP_KERNEL);
791 if (cstate == NULL)
792 return NULL;
793 fh_init(&cstate->current_fh, NFS4_FHSIZE);
794 fh_init(&cstate->save_fh, NFS4_FHSIZE);
795 cstate->replay_owner = NULL;
796 return cstate;
797}
798
799typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,
800 void *);
801
802struct nfsd4_operation {
803 nfsd4op_func op_func;
804 u32 op_flags;
805/* Most ops require a valid current filehandle; a few don't: */
806#define ALLOWED_WITHOUT_FH 1
807/* GETATTR and ops not listed as returning NFS4ERR_MOVED: */
808#define ALLOWED_ON_ABSENT_FS 2
809};
810
811static struct nfsd4_operation nfsd4_ops[];
730 812
731/* 813/*
732 * COMPOUND call. 814 * COMPOUND call.
@@ -737,21 +819,15 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
737 struct nfsd4_compoundres *resp) 819 struct nfsd4_compoundres *resp)
738{ 820{
739 struct nfsd4_op *op; 821 struct nfsd4_op *op;
740 struct svc_fh *current_fh = NULL; 822 struct nfsd4_operation *opdesc;
741 struct svc_fh *save_fh = NULL; 823 struct nfsd4_compound_state *cstate = NULL;
742 struct nfs4_stateowner *replay_owner = NULL; 824 int slack_bytes;
743 int slack_space; /* in words, not bytes! */
744 __be32 status; 825 __be32 status;
745 826
746 status = nfserr_resource; 827 status = nfserr_resource;
747 current_fh = kmalloc(sizeof(*current_fh), GFP_KERNEL); 828 cstate = cstate_alloc();
748 if (current_fh == NULL) 829 if (cstate == NULL)
749 goto out;
750 fh_init(current_fh, NFS4_FHSIZE);
751 save_fh = kmalloc(sizeof(*save_fh), GFP_KERNEL);
752 if (save_fh == NULL)
753 goto out; 830 goto out;
754 fh_init(save_fh, NFS4_FHSIZE);
755 831
756 resp->xbuf = &rqstp->rq_res; 832 resp->xbuf = &rqstp->rq_res;
757 resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len; 833 resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len;
@@ -790,164 +866,44 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
790 * failed response to the next operation. If we don't 866 * failed response to the next operation. If we don't
791 * have enough room, fail with ERR_RESOURCE. 867 * have enough room, fail with ERR_RESOURCE.
792 */ 868 */
793/* FIXME - is slack_space *really* words, or bytes??? - neilb */ 869 slack_bytes = (char *)resp->end - (char *)resp->p;
794 slack_space = (char *)resp->end - (char *)resp->p; 870 if (slack_bytes < COMPOUND_SLACK_SPACE
795 if (slack_space < COMPOUND_SLACK_SPACE + COMPOUND_ERR_SLACK_SPACE) { 871 + COMPOUND_ERR_SLACK_SPACE) {
796 BUG_ON(slack_space < COMPOUND_ERR_SLACK_SPACE); 872 BUG_ON(slack_bytes < COMPOUND_ERR_SLACK_SPACE);
797 op->status = nfserr_resource; 873 op->status = nfserr_resource;
798 goto encode_op; 874 goto encode_op;
799 } 875 }
800 876
801 /* All operations except RENEW, SETCLIENTID, RESTOREFH 877 opdesc = &nfsd4_ops[op->opnum];
802 * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH 878
803 * require a valid current filehandle 879 if (!cstate->current_fh.fh_dentry) {
804 */ 880 if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
805 if (!current_fh->fh_dentry) {
806 if (!((op->opnum == OP_PUTFH) ||
807 (op->opnum == OP_PUTROOTFH) ||
808 (op->opnum == OP_SETCLIENTID) ||
809 (op->opnum == OP_SETCLIENTID_CONFIRM) ||
810 (op->opnum == OP_RENEW) ||
811 (op->opnum == OP_RESTOREFH) ||
812 (op->opnum == OP_RELEASE_LOCKOWNER))) {
813 op->status = nfserr_nofilehandle; 881 op->status = nfserr_nofilehandle;
814 goto encode_op; 882 goto encode_op;
815 } 883 }
816 } 884 } else if (cstate->current_fh.fh_export->ex_fslocs.migrated &&
817 /* Check must be done at start of each operation, except 885 !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
818 * for GETATTR and ops not listed as returning NFS4ERR_MOVED
819 */
820 else if (current_fh->fh_export->ex_fslocs.migrated &&
821 !((op->opnum == OP_GETATTR) ||
822 (op->opnum == OP_PUTROOTFH) ||
823 (op->opnum == OP_PUTPUBFH) ||
824 (op->opnum == OP_RENEW) ||
825 (op->opnum == OP_SETCLIENTID) ||
826 (op->opnum == OP_RELEASE_LOCKOWNER))) {
827 op->status = nfserr_moved; 886 op->status = nfserr_moved;
828 goto encode_op; 887 goto encode_op;
829 } 888 }
830 switch (op->opnum) { 889
831 case OP_ACCESS: 890 if (opdesc->op_func)
832 op->status = nfsd4_access(rqstp, current_fh, &op->u.access); 891 op->status = opdesc->op_func(rqstp, cstate, &op->u);
833 break; 892 else
834 case OP_CLOSE:
835 op->status = nfsd4_close(rqstp, current_fh, &op->u.close, &replay_owner);
836 break;
837 case OP_COMMIT:
838 op->status = nfsd4_commit(rqstp, current_fh, &op->u.commit);
839 break;
840 case OP_CREATE:
841 op->status = nfsd4_create(rqstp, current_fh, &op->u.create);
842 break;
843 case OP_DELEGRETURN:
844 op->status = nfsd4_delegreturn(rqstp, current_fh, &op->u.delegreturn);
845 break;
846 case OP_GETATTR:
847 op->status = nfsd4_getattr(rqstp, current_fh, &op->u.getattr);
848 break;
849 case OP_GETFH:
850 op->status = nfsd4_getfh(current_fh, &op->u.getfh);
851 break;
852 case OP_LINK:
853 op->status = nfsd4_link(rqstp, current_fh, save_fh, &op->u.link);
854 break;
855 case OP_LOCK:
856 op->status = nfsd4_lock(rqstp, current_fh, &op->u.lock, &replay_owner);
857 break;
858 case OP_LOCKT:
859 op->status = nfsd4_lockt(rqstp, current_fh, &op->u.lockt);
860 break;
861 case OP_LOCKU:
862 op->status = nfsd4_locku(rqstp, current_fh, &op->u.locku, &replay_owner);
863 break;
864 case OP_LOOKUP:
865 op->status = nfsd4_lookup(rqstp, current_fh, &op->u.lookup);
866 break;
867 case OP_LOOKUPP:
868 op->status = nfsd4_lookupp(rqstp, current_fh);
869 break;
870 case OP_NVERIFY:
871 op->status = nfsd4_verify(rqstp, current_fh, &op->u.nverify);
872 if (op->status == nfserr_not_same)
873 op->status = nfs_ok;
874 break;
875 case OP_OPEN:
876 op->status = nfsd4_open(rqstp, current_fh, &op->u.open, &replay_owner);
877 break;
878 case OP_OPEN_CONFIRM:
879 op->status = nfsd4_open_confirm(rqstp, current_fh, &op->u.open_confirm, &replay_owner);
880 break;
881 case OP_OPEN_DOWNGRADE:
882 op->status = nfsd4_open_downgrade(rqstp, current_fh, &op->u.open_downgrade, &replay_owner);
883 break;
884 case OP_PUTFH:
885 op->status = nfsd4_putfh(rqstp, current_fh, &op->u.putfh);
886 break;
887 case OP_PUTROOTFH:
888 op->status = nfsd4_putrootfh(rqstp, current_fh);
889 break;
890 case OP_READ:
891 op->status = nfsd4_read(rqstp, current_fh, &op->u.read);
892 break;
893 case OP_READDIR:
894 op->status = nfsd4_readdir(rqstp, current_fh, &op->u.readdir);
895 break;
896 case OP_READLINK:
897 op->status = nfsd4_readlink(rqstp, current_fh, &op->u.readlink);
898 break;
899 case OP_REMOVE:
900 op->status = nfsd4_remove(rqstp, current_fh, &op->u.remove);
901 break;
902 case OP_RENAME:
903 op->status = nfsd4_rename(rqstp, current_fh, save_fh, &op->u.rename);
904 break;
905 case OP_RENEW:
906 op->status = nfsd4_renew(&op->u.renew);
907 break;
908 case OP_RESTOREFH:
909 op->status = nfsd4_restorefh(current_fh, save_fh);
910 break;
911 case OP_SAVEFH:
912 op->status = nfsd4_savefh(current_fh, save_fh);
913 break;
914 case OP_SETATTR:
915 op->status = nfsd4_setattr(rqstp, current_fh, &op->u.setattr);
916 break;
917 case OP_SETCLIENTID:
918 op->status = nfsd4_setclientid(rqstp, &op->u.setclientid);
919 break;
920 case OP_SETCLIENTID_CONFIRM:
921 op->status = nfsd4_setclientid_confirm(rqstp, &op->u.setclientid_confirm);
922 break;
923 case OP_VERIFY:
924 op->status = nfsd4_verify(rqstp, current_fh, &op->u.verify);
925 if (op->status == nfserr_same)
926 op->status = nfs_ok;
927 break;
928 case OP_WRITE:
929 op->status = nfsd4_write(rqstp, current_fh, &op->u.write);
930 break;
931 case OP_RELEASE_LOCKOWNER:
932 op->status = nfsd4_release_lockowner(rqstp, &op->u.release_lockowner);
933 break;
934 default:
935 BUG_ON(op->status == nfs_ok); 893 BUG_ON(op->status == nfs_ok);
936 break;
937 }
938 894
939encode_op: 895encode_op:
940 if (op->status == nfserr_replay_me) { 896 if (op->status == nfserr_replay_me) {
941 op->replay = &replay_owner->so_replay; 897 op->replay = &cstate->replay_owner->so_replay;
942 nfsd4_encode_replay(resp, op); 898 nfsd4_encode_replay(resp, op);
943 status = op->status = op->replay->rp_status; 899 status = op->status = op->replay->rp_status;
944 } else { 900 } else {
945 nfsd4_encode_operation(resp, op); 901 nfsd4_encode_operation(resp, op);
946 status = op->status; 902 status = op->status;
947 } 903 }
948 if (replay_owner && (replay_owner != (void *)(-1))) { 904 if (cstate->replay_owner) {
949 nfs4_put_stateowner(replay_owner); 905 nfs4_put_stateowner(cstate->replay_owner);
950 replay_owner = NULL; 906 cstate->replay_owner = NULL;
951 } 907 }
952 /* XXX Ugh, we need to get rid of this kind of special case: */ 908 /* XXX Ugh, we need to get rid of this kind of special case: */
953 if (op->opnum == OP_READ && op->u.read.rd_filp) 909 if (op->opnum == OP_READ && op->u.read.rd_filp)
@@ -958,15 +914,124 @@ encode_op:
958 914
959out: 915out:
960 nfsd4_release_compoundargs(args); 916 nfsd4_release_compoundargs(args);
961 if (current_fh) 917 cstate_free(cstate);
962 fh_put(current_fh);
963 kfree(current_fh);
964 if (save_fh)
965 fh_put(save_fh);
966 kfree(save_fh);
967 return status; 918 return status;
968} 919}
969 920
921static struct nfsd4_operation nfsd4_ops[OP_RELEASE_LOCKOWNER+1] = {
922 [OP_ACCESS] = {
923 .op_func = (nfsd4op_func)nfsd4_access,
924 },
925 [OP_CLOSE] = {
926 .op_func = (nfsd4op_func)nfsd4_close,
927 },
928 [OP_COMMIT] = {
929 .op_func = (nfsd4op_func)nfsd4_commit,
930 },
931 [OP_CREATE] = {
932 .op_func = (nfsd4op_func)nfsd4_create,
933 },
934 [OP_DELEGRETURN] = {
935 .op_func = (nfsd4op_func)nfsd4_delegreturn,
936 },
937 [OP_GETATTR] = {
938 .op_func = (nfsd4op_func)nfsd4_getattr,
939 .op_flags = ALLOWED_ON_ABSENT_FS,
940 },
941 [OP_GETFH] = {
942 .op_func = (nfsd4op_func)nfsd4_getfh,
943 },
944 [OP_LINK] = {
945 .op_func = (nfsd4op_func)nfsd4_link,
946 },
947 [OP_LOCK] = {
948 .op_func = (nfsd4op_func)nfsd4_lock,
949 },
950 [OP_LOCKT] = {
951 .op_func = (nfsd4op_func)nfsd4_lockt,
952 },
953 [OP_LOCKU] = {
954 .op_func = (nfsd4op_func)nfsd4_locku,
955 },
956 [OP_LOOKUP] = {
957 .op_func = (nfsd4op_func)nfsd4_lookup,
958 },
959 [OP_LOOKUPP] = {
960 .op_func = (nfsd4op_func)nfsd4_lookupp,
961 },
962 [OP_NVERIFY] = {
963 .op_func = (nfsd4op_func)nfsd4_nverify,
964 },
965 [OP_OPEN] = {
966 .op_func = (nfsd4op_func)nfsd4_open,
967 },
968 [OP_OPEN_CONFIRM] = {
969 .op_func = (nfsd4op_func)nfsd4_open_confirm,
970 },
971 [OP_OPEN_DOWNGRADE] = {
972 .op_func = (nfsd4op_func)nfsd4_open_downgrade,
973 },
974 [OP_PUTFH] = {
975 .op_func = (nfsd4op_func)nfsd4_putfh,
976 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
977 },
978 [OP_PUTPUBFH] = {
979 /* unsupported; just for future reference: */
980 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
981 },
982 [OP_PUTROOTFH] = {
983 .op_func = (nfsd4op_func)nfsd4_putrootfh,
984 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
985 },
986 [OP_READ] = {
987 .op_func = (nfsd4op_func)nfsd4_read,
988 },
989 [OP_READDIR] = {
990 .op_func = (nfsd4op_func)nfsd4_readdir,
991 },
992 [OP_READLINK] = {
993 .op_func = (nfsd4op_func)nfsd4_readlink,
994 },
995 [OP_REMOVE] = {
996 .op_func = (nfsd4op_func)nfsd4_remove,
997 },
998 [OP_RENAME] = {
999 .op_func = (nfsd4op_func)nfsd4_rename,
1000 },
1001 [OP_RENEW] = {
1002 .op_func = (nfsd4op_func)nfsd4_renew,
1003 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1004 },
1005 [OP_RESTOREFH] = {
1006 .op_func = (nfsd4op_func)nfsd4_restorefh,
1007 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1008 },
1009 [OP_SAVEFH] = {
1010 .op_func = (nfsd4op_func)nfsd4_savefh,
1011 },
1012 [OP_SETATTR] = {
1013 .op_func = (nfsd4op_func)nfsd4_setattr,
1014 },
1015 [OP_SETCLIENTID] = {
1016 .op_func = (nfsd4op_func)nfsd4_setclientid,
1017 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1018 },
1019 [OP_SETCLIENTID_CONFIRM] = {
1020 .op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
1021 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1022 },
1023 [OP_VERIFY] = {
1024 .op_func = (nfsd4op_func)nfsd4_verify,
1025 },
1026 [OP_WRITE] = {
1027 .op_func = (nfsd4op_func)nfsd4_write,
1028 },
1029 [OP_RELEASE_LOCKOWNER] = {
1030 .op_func = (nfsd4op_func)nfsd4_release_lockowner,
1031 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1032 },
1033};
1034
970#define nfs4svc_decode_voidargs NULL 1035#define nfs4svc_decode_voidargs NULL
971#define nfs4svc_release_void NULL 1036#define nfs4svc_release_void NULL
972#define nfsd4_voidres nfsd4_voidargs 1037#define nfsd4_voidres nfsd4_voidargs
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 81b8565d3837..c7774e3a9469 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -259,7 +259,7 @@ nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry)
259 printk("nfsd4: non-file found in client recovery directory\n"); 259 printk("nfsd4: non-file found in client recovery directory\n");
260 return -EINVAL; 260 return -EINVAL;
261 } 261 }
262 mutex_lock(&dir->d_inode->i_mutex); 262 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
263 status = vfs_unlink(dir->d_inode, dentry); 263 status = vfs_unlink(dir->d_inode, dentry);
264 mutex_unlock(&dir->d_inode->i_mutex); 264 mutex_unlock(&dir->d_inode->i_mutex);
265 return status; 265 return status;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 293b6495829f..9de89df961f4 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -84,10 +84,10 @@ static void nfs4_set_recdir(char *recdir);
84 */ 84 */
85static DEFINE_MUTEX(client_mutex); 85static DEFINE_MUTEX(client_mutex);
86 86
87static kmem_cache_t *stateowner_slab = NULL; 87static struct kmem_cache *stateowner_slab = NULL;
88static kmem_cache_t *file_slab = NULL; 88static struct kmem_cache *file_slab = NULL;
89static kmem_cache_t *stateid_slab = NULL; 89static struct kmem_cache *stateid_slab = NULL;
90static kmem_cache_t *deleg_slab = NULL; 90static struct kmem_cache *deleg_slab = NULL;
91 91
92void 92void
93nfs4_lock_state(void) 93nfs4_lock_state(void)
@@ -711,7 +711,8 @@ out_err:
711 * 711 *
712 */ 712 */
713__be32 713__be32
714nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid) 714nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
715 struct nfsd4_setclientid *setclid)
715{ 716{
716 __be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr; 717 __be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
717 struct xdr_netobj clname = { 718 struct xdr_netobj clname = {
@@ -876,7 +877,9 @@ out:
876 * NOTE: callback information will be processed here in a future patch 877 * NOTE: callback information will be processed here in a future patch
877 */ 878 */
878__be32 879__be32
879nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm) 880nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
881 struct nfsd4_compound_state *cstate,
882 struct nfsd4_setclientid_confirm *setclientid_confirm)
880{ 883{
881 __be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr; 884 __be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
882 struct nfs4_client *conf, *unconf; 885 struct nfs4_client *conf, *unconf;
@@ -1003,7 +1006,7 @@ alloc_init_file(struct inode *ino)
1003} 1006}
1004 1007
1005static void 1008static void
1006nfsd4_free_slab(kmem_cache_t **slab) 1009nfsd4_free_slab(struct kmem_cache **slab)
1007{ 1010{
1008 if (*slab == NULL) 1011 if (*slab == NULL)
1009 return; 1012 return;
@@ -1310,7 +1313,7 @@ static inline void
1310nfs4_file_downgrade(struct file *filp, unsigned int share_access) 1313nfs4_file_downgrade(struct file *filp, unsigned int share_access)
1311{ 1314{
1312 if (share_access & NFS4_SHARE_ACCESS_WRITE) { 1315 if (share_access & NFS4_SHARE_ACCESS_WRITE) {
1313 put_write_access(filp->f_dentry->d_inode); 1316 put_write_access(filp->f_path.dentry->d_inode);
1314 filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE; 1317 filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE;
1315 } 1318 }
1316} 1319}
@@ -1623,7 +1626,7 @@ static __be32
1623nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open) 1626nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open)
1624{ 1627{
1625 struct file *filp = stp->st_vfs_file; 1628 struct file *filp = stp->st_vfs_file;
1626 struct inode *inode = filp->f_dentry->d_inode; 1629 struct inode *inode = filp->f_path.dentry->d_inode;
1627 unsigned int share_access, new_writer; 1630 unsigned int share_access, new_writer;
1628 __be32 status; 1631 __be32 status;
1629 1632
@@ -1829,12 +1832,12 @@ out:
1829} 1832}
1830 1833
1831static struct workqueue_struct *laundry_wq; 1834static struct workqueue_struct *laundry_wq;
1832static struct work_struct laundromat_work; 1835static void laundromat_main(struct work_struct *);
1833static void laundromat_main(void *); 1836static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main);
1834static DECLARE_WORK(laundromat_work, laundromat_main, NULL);
1835 1837
1836__be32 1838__be32
1837nfsd4_renew(clientid_t *clid) 1839nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1840 clientid_t *clid)
1838{ 1841{
1839 struct nfs4_client *clp; 1842 struct nfs4_client *clp;
1840 __be32 status; 1843 __be32 status;
@@ -1940,7 +1943,7 @@ nfs4_laundromat(void)
1940} 1943}
1941 1944
1942void 1945void
1943laundromat_main(void *not_used) 1946laundromat_main(struct work_struct *not_used)
1944{ 1947{
1945 time_t t; 1948 time_t t;
1946 1949
@@ -1966,7 +1969,7 @@ search_close_lru(u32 st_id, int flags)
1966static inline int 1969static inline int
1967nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp) 1970nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
1968{ 1971{
1969 return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_dentry->d_inode; 1972 return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_path.dentry->d_inode;
1970} 1973}
1971 1974
1972static int 1975static int
@@ -2242,24 +2245,25 @@ check_replay:
2242} 2245}
2243 2246
2244__be32 2247__be32
2245nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc, struct nfs4_stateowner **replay_owner) 2248nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2249 struct nfsd4_open_confirm *oc)
2246{ 2250{
2247 __be32 status; 2251 __be32 status;
2248 struct nfs4_stateowner *sop; 2252 struct nfs4_stateowner *sop;
2249 struct nfs4_stateid *stp; 2253 struct nfs4_stateid *stp;
2250 2254
2251 dprintk("NFSD: nfsd4_open_confirm on file %.*s\n", 2255 dprintk("NFSD: nfsd4_open_confirm on file %.*s\n",
2252 (int)current_fh->fh_dentry->d_name.len, 2256 (int)cstate->current_fh.fh_dentry->d_name.len,
2253 current_fh->fh_dentry->d_name.name); 2257 cstate->current_fh.fh_dentry->d_name.name);
2254 2258
2255 status = fh_verify(rqstp, current_fh, S_IFREG, 0); 2259 status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0);
2256 if (status) 2260 if (status)
2257 return status; 2261 return status;
2258 2262
2259 nfs4_lock_state(); 2263 nfs4_lock_state();
2260 2264
2261 if ((status = nfs4_preprocess_seqid_op(current_fh, oc->oc_seqid, 2265 if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
2262 &oc->oc_req_stateid, 2266 oc->oc_seqid, &oc->oc_req_stateid,
2263 CHECK_FH | CONFIRM | OPEN_STATE, 2267 CHECK_FH | CONFIRM | OPEN_STATE,
2264 &oc->oc_stateowner, &stp, NULL))) 2268 &oc->oc_stateowner, &stp, NULL)))
2265 goto out; 2269 goto out;
@@ -2279,7 +2283,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
2279out: 2283out:
2280 if (oc->oc_stateowner) { 2284 if (oc->oc_stateowner) {
2281 nfs4_get_stateowner(oc->oc_stateowner); 2285 nfs4_get_stateowner(oc->oc_stateowner);
2282 *replay_owner = oc->oc_stateowner; 2286 cstate->replay_owner = oc->oc_stateowner;
2283 } 2287 }
2284 nfs4_unlock_state(); 2288 nfs4_unlock_state();
2285 return status; 2289 return status;
@@ -2311,22 +2315,25 @@ reset_union_bmap_deny(unsigned long deny, unsigned long *bmap)
2311} 2315}
2312 2316
2313__be32 2317__be32
2314nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od, struct nfs4_stateowner **replay_owner) 2318nfsd4_open_downgrade(struct svc_rqst *rqstp,
2319 struct nfsd4_compound_state *cstate,
2320 struct nfsd4_open_downgrade *od)
2315{ 2321{
2316 __be32 status; 2322 __be32 status;
2317 struct nfs4_stateid *stp; 2323 struct nfs4_stateid *stp;
2318 unsigned int share_access; 2324 unsigned int share_access;
2319 2325
2320 dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n", 2326 dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n",
2321 (int)current_fh->fh_dentry->d_name.len, 2327 (int)cstate->current_fh.fh_dentry->d_name.len,
2322 current_fh->fh_dentry->d_name.name); 2328 cstate->current_fh.fh_dentry->d_name.name);
2323 2329
2324 if (!access_valid(od->od_share_access) 2330 if (!access_valid(od->od_share_access)
2325 || !deny_valid(od->od_share_deny)) 2331 || !deny_valid(od->od_share_deny))
2326 return nfserr_inval; 2332 return nfserr_inval;
2327 2333
2328 nfs4_lock_state(); 2334 nfs4_lock_state();
2329 if ((status = nfs4_preprocess_seqid_op(current_fh, od->od_seqid, 2335 if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
2336 od->od_seqid,
2330 &od->od_stateid, 2337 &od->od_stateid,
2331 CHECK_FH | OPEN_STATE, 2338 CHECK_FH | OPEN_STATE,
2332 &od->od_stateowner, &stp, NULL))) 2339 &od->od_stateowner, &stp, NULL)))
@@ -2356,7 +2363,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct n
2356out: 2363out:
2357 if (od->od_stateowner) { 2364 if (od->od_stateowner) {
2358 nfs4_get_stateowner(od->od_stateowner); 2365 nfs4_get_stateowner(od->od_stateowner);
2359 *replay_owner = od->od_stateowner; 2366 cstate->replay_owner = od->od_stateowner;
2360 } 2367 }
2361 nfs4_unlock_state(); 2368 nfs4_unlock_state();
2362 return status; 2369 return status;
@@ -2366,18 +2373,20 @@ out:
2366 * nfs4_unlock_state() called after encode 2373 * nfs4_unlock_state() called after encode
2367 */ 2374 */
2368__be32 2375__be32
2369nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close, struct nfs4_stateowner **replay_owner) 2376nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2377 struct nfsd4_close *close)
2370{ 2378{
2371 __be32 status; 2379 __be32 status;
2372 struct nfs4_stateid *stp; 2380 struct nfs4_stateid *stp;
2373 2381
2374 dprintk("NFSD: nfsd4_close on file %.*s\n", 2382 dprintk("NFSD: nfsd4_close on file %.*s\n",
2375 (int)current_fh->fh_dentry->d_name.len, 2383 (int)cstate->current_fh.fh_dentry->d_name.len,
2376 current_fh->fh_dentry->d_name.name); 2384 cstate->current_fh.fh_dentry->d_name.name);
2377 2385
2378 nfs4_lock_state(); 2386 nfs4_lock_state();
2379 /* check close_lru for replay */ 2387 /* check close_lru for replay */
2380 if ((status = nfs4_preprocess_seqid_op(current_fh, close->cl_seqid, 2388 if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
2389 close->cl_seqid,
2381 &close->cl_stateid, 2390 &close->cl_stateid,
2382 CHECK_FH | OPEN_STATE | CLOSE_STATE, 2391 CHECK_FH | OPEN_STATE | CLOSE_STATE,
2383 &close->cl_stateowner, &stp, NULL))) 2392 &close->cl_stateowner, &stp, NULL)))
@@ -2398,22 +2407,24 @@ nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_clos
2398out: 2407out:
2399 if (close->cl_stateowner) { 2408 if (close->cl_stateowner) {
2400 nfs4_get_stateowner(close->cl_stateowner); 2409 nfs4_get_stateowner(close->cl_stateowner);
2401 *replay_owner = close->cl_stateowner; 2410 cstate->replay_owner = close->cl_stateowner;
2402 } 2411 }
2403 nfs4_unlock_state(); 2412 nfs4_unlock_state();
2404 return status; 2413 return status;
2405} 2414}
2406 2415
2407__be32 2416__be32
2408nfsd4_delegreturn(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_delegreturn *dr) 2417nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2418 struct nfsd4_delegreturn *dr)
2409{ 2419{
2410 __be32 status; 2420 __be32 status;
2411 2421
2412 if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) 2422 if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
2413 goto out; 2423 goto out;
2414 2424
2415 nfs4_lock_state(); 2425 nfs4_lock_state();
2416 status = nfs4_preprocess_stateid_op(current_fh, &dr->dr_stateid, DELEG_RET, NULL); 2426 status = nfs4_preprocess_stateid_op(&cstate->current_fh,
2427 &dr->dr_stateid, DELEG_RET, NULL);
2417 nfs4_unlock_state(); 2428 nfs4_unlock_state();
2418out: 2429out:
2419 return status; 2430 return status;
@@ -2636,7 +2647,8 @@ check_lock_length(u64 offset, u64 length)
2636 * LOCK operation 2647 * LOCK operation
2637 */ 2648 */
2638__be32 2649__be32
2639nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner) 2650nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2651 struct nfsd4_lock *lock)
2640{ 2652{
2641 struct nfs4_stateowner *open_sop = NULL; 2653 struct nfs4_stateowner *open_sop = NULL;
2642 struct nfs4_stateowner *lock_sop = NULL; 2654 struct nfs4_stateowner *lock_sop = NULL;
@@ -2655,7 +2667,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2655 if (check_lock_length(lock->lk_offset, lock->lk_length)) 2667 if (check_lock_length(lock->lk_offset, lock->lk_length))
2656 return nfserr_inval; 2668 return nfserr_inval;
2657 2669
2658 if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) { 2670 if ((status = fh_verify(rqstp, &cstate->current_fh,
2671 S_IFREG, MAY_LOCK))) {
2659 dprintk("NFSD: nfsd4_lock: permission denied!\n"); 2672 dprintk("NFSD: nfsd4_lock: permission denied!\n");
2660 return status; 2673 return status;
2661 } 2674 }
@@ -2676,7 +2689,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2676 goto out; 2689 goto out;
2677 2690
2678 /* validate and update open stateid and open seqid */ 2691 /* validate and update open stateid and open seqid */
2679 status = nfs4_preprocess_seqid_op(current_fh, 2692 status = nfs4_preprocess_seqid_op(&cstate->current_fh,
2680 lock->lk_new_open_seqid, 2693 lock->lk_new_open_seqid,
2681 &lock->lk_new_open_stateid, 2694 &lock->lk_new_open_stateid,
2682 CHECK_FH | OPEN_STATE, 2695 CHECK_FH | OPEN_STATE,
@@ -2703,7 +2716,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2703 goto out; 2716 goto out;
2704 } else { 2717 } else {
2705 /* lock (lock owner + lock stateid) already exists */ 2718 /* lock (lock owner + lock stateid) already exists */
2706 status = nfs4_preprocess_seqid_op(current_fh, 2719 status = nfs4_preprocess_seqid_op(&cstate->current_fh,
2707 lock->lk_old_lock_seqid, 2720 lock->lk_old_lock_seqid,
2708 &lock->lk_old_lock_stateid, 2721 &lock->lk_old_lock_stateid,
2709 CHECK_FH | LOCK_STATE, 2722 CHECK_FH | LOCK_STATE,
@@ -2760,7 +2773,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2760 conflock.fl_ops = NULL; 2773 conflock.fl_ops = NULL;
2761 conflock.fl_lmops = NULL; 2774 conflock.fl_lmops = NULL;
2762 err = posix_lock_file_conf(filp, &file_lock, &conflock); 2775 err = posix_lock_file_conf(filp, &file_lock, &conflock);
2763 dprintk("NFSD: nfsd4_lock: posix_lock_file_conf status %d\n",status);
2764 switch (-err) { 2776 switch (-err) {
2765 case 0: /* success! */ 2777 case 0: /* success! */
2766 update_stateid(&lock_stp->st_stateid); 2778 update_stateid(&lock_stp->st_stateid);
@@ -2786,7 +2798,7 @@ out:
2786 release_stateowner(lock_sop); 2798 release_stateowner(lock_sop);
2787 if (lock->lk_replay_owner) { 2799 if (lock->lk_replay_owner) {
2788 nfs4_get_stateowner(lock->lk_replay_owner); 2800 nfs4_get_stateowner(lock->lk_replay_owner);
2789 *replay_owner = lock->lk_replay_owner; 2801 cstate->replay_owner = lock->lk_replay_owner;
2790 } 2802 }
2791 nfs4_unlock_state(); 2803 nfs4_unlock_state();
2792 return status; 2804 return status;
@@ -2796,7 +2808,8 @@ out:
2796 * LOCKT operation 2808 * LOCKT operation
2797 */ 2809 */
2798__be32 2810__be32
2799nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt) 2811nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2812 struct nfsd4_lockt *lockt)
2800{ 2813{
2801 struct inode *inode; 2814 struct inode *inode;
2802 struct file file; 2815 struct file file;
@@ -2817,14 +2830,14 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2817 if (STALE_CLIENTID(&lockt->lt_clientid)) 2830 if (STALE_CLIENTID(&lockt->lt_clientid))
2818 goto out; 2831 goto out;
2819 2832
2820 if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) { 2833 if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) {
2821 dprintk("NFSD: nfsd4_lockt: fh_verify() failed!\n"); 2834 dprintk("NFSD: nfsd4_lockt: fh_verify() failed!\n");
2822 if (status == nfserr_symlink) 2835 if (status == nfserr_symlink)
2823 status = nfserr_inval; 2836 status = nfserr_inval;
2824 goto out; 2837 goto out;
2825 } 2838 }
2826 2839
2827 inode = current_fh->fh_dentry->d_inode; 2840 inode = cstate->current_fh.fh_dentry->d_inode;
2828 locks_init_lock(&file_lock); 2841 locks_init_lock(&file_lock);
2829 switch (lockt->lt_type) { 2842 switch (lockt->lt_type) {
2830 case NFS4_READ_LT: 2843 case NFS4_READ_LT:
@@ -2863,7 +2876,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2863 * only the dentry:inode set. 2876 * only the dentry:inode set.
2864 */ 2877 */
2865 memset(&file, 0, sizeof (struct file)); 2878 memset(&file, 0, sizeof (struct file));
2866 file.f_dentry = current_fh->fh_dentry; 2879 file.f_path.dentry = cstate->current_fh.fh_dentry;
2867 2880
2868 status = nfs_ok; 2881 status = nfs_ok;
2869 if (posix_test_lock(&file, &file_lock, &conflock)) { 2882 if (posix_test_lock(&file, &file_lock, &conflock)) {
@@ -2876,7 +2889,8 @@ out:
2876} 2889}
2877 2890
2878__be32 2891__be32
2879nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner) 2892nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2893 struct nfsd4_locku *locku)
2880{ 2894{
2881 struct nfs4_stateid *stp; 2895 struct nfs4_stateid *stp;
2882 struct file *filp = NULL; 2896 struct file *filp = NULL;
@@ -2893,7 +2907,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2893 2907
2894 nfs4_lock_state(); 2908 nfs4_lock_state();
2895 2909
2896 if ((status = nfs4_preprocess_seqid_op(current_fh, 2910 if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
2897 locku->lu_seqid, 2911 locku->lu_seqid,
2898 &locku->lu_stateid, 2912 &locku->lu_stateid,
2899 CHECK_FH | LOCK_STATE, 2913 CHECK_FH | LOCK_STATE,
@@ -2934,7 +2948,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2934out: 2948out:
2935 if (locku->lu_stateowner) { 2949 if (locku->lu_stateowner) {
2936 nfs4_get_stateowner(locku->lu_stateowner); 2950 nfs4_get_stateowner(locku->lu_stateowner);
2937 *replay_owner = locku->lu_stateowner; 2951 cstate->replay_owner = locku->lu_stateowner;
2938 } 2952 }
2939 nfs4_unlock_state(); 2953 nfs4_unlock_state();
2940 return status; 2954 return status;
@@ -2953,7 +2967,7 @@ static int
2953check_for_locks(struct file *filp, struct nfs4_stateowner *lowner) 2967check_for_locks(struct file *filp, struct nfs4_stateowner *lowner)
2954{ 2968{
2955 struct file_lock **flpp; 2969 struct file_lock **flpp;
2956 struct inode *inode = filp->f_dentry->d_inode; 2970 struct inode *inode = filp->f_path.dentry->d_inode;
2957 int status = 0; 2971 int status = 0;
2958 2972
2959 lock_kernel(); 2973 lock_kernel();
@@ -2969,7 +2983,9 @@ out:
2969} 2983}
2970 2984
2971__be32 2985__be32
2972nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner) 2986nfsd4_release_lockowner(struct svc_rqst *rqstp,
2987 struct nfsd4_compound_state *cstate,
2988 struct nfsd4_release_lockowner *rlockowner)
2973{ 2989{
2974 clientid_t *clid = &rlockowner->rl_clientid; 2990 clientid_t *clid = &rlockowner->rl_clientid;
2975 struct nfs4_stateowner *sop; 2991 struct nfs4_stateowner *sop;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index f3f239db04bb..fea46368afb2 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1845,15 +1845,11 @@ nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
1845 1845
1846 exp_get(exp); 1846 exp_get(exp);
1847 if (d_mountpoint(dentry)) { 1847 if (d_mountpoint(dentry)) {
1848 if (nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp)) { 1848 int err;
1849 /* 1849
1850 * -EAGAIN is the only error returned from 1850 err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
1851 * nfsd_cross_mnt() and it indicates that an 1851 if (err) {
1852 * up-call has been initiated to fill in the export 1852 nfserr = nfserrno(err);
1853 * options on exp. When the answer comes back,
1854 * this call will be retried.
1855 */
1856 nfserr = nfserr_dropit;
1857 goto out_put; 1853 goto out_put;
1858 } 1854 }
1859 1855
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index 6100bbe27432..f90d70475854 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -66,14 +66,13 @@ nfsd_cache_init(void)
66 printk (KERN_ERR "nfsd: cannot allocate all %d cache entries, only got %d\n", 66 printk (KERN_ERR "nfsd: cannot allocate all %d cache entries, only got %d\n",
67 CACHESIZE, CACHESIZE-i); 67 CACHESIZE, CACHESIZE-i);
68 68
69 hash_list = kmalloc (HASHSIZE * sizeof(struct hlist_head), GFP_KERNEL); 69 hash_list = kcalloc (HASHSIZE, sizeof(struct hlist_head), GFP_KERNEL);
70 if (!hash_list) { 70 if (!hash_list) {
71 nfsd_cache_shutdown(); 71 nfsd_cache_shutdown();
72 printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for hash list\n", 72 printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for hash list\n",
73 HASHSIZE * sizeof(struct hlist_head)); 73 HASHSIZE * sizeof(struct hlist_head));
74 return; 74 return;
75 } 75 }
76 memset(hash_list, 0, HASHSIZE * sizeof(struct hlist_head));
77 76
78 cache_disabled = 0; 77 cache_disabled = 0;
79} 78}
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 39aed901514b..eedf2e3990a9 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -111,7 +111,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
111 111
112static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) 112static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
113{ 113{
114 ino_t ino = file->f_dentry->d_inode->i_ino; 114 ino_t ino = file->f_path.dentry->d_inode->i_ino;
115 char *data; 115 char *data;
116 ssize_t rv; 116 ssize_t rv;
117 117
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 727ab3bd450d..b06bf9f70efc 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -169,9 +169,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
169 exp = exp_find(rqstp->rq_client, 0, tfh, &rqstp->rq_chandle); 169 exp = exp_find(rqstp->rq_client, 0, tfh, &rqstp->rq_chandle);
170 } 170 }
171 171
172 error = nfserr_dropit; 172 if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN
173 if (IS_ERR(exp) && PTR_ERR(exp) == -EAGAIN) 173 || PTR_ERR(exp) == -ETIMEDOUT)) {
174 error = nfserrno(PTR_ERR(exp));
174 goto out; 175 goto out;
176 }
175 177
176 error = nfserr_stale; 178 error = nfserr_stale;
177 if (!exp || IS_ERR(exp)) 179 if (!exp || IS_ERR(exp))
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 56ebb1443e0e..f5243f943996 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -18,11 +18,6 @@
18 18
19#define NFSDDBG_FACILITY NFSDDBG_XDR 19#define NFSDDBG_FACILITY NFSDDBG_XDR
20 20
21
22#ifdef NFSD_OPTIMIZE_SPACE
23# define inline
24#endif
25
26/* 21/*
27 * Mapping of S_IF* types to NFS file types 22 * Mapping of S_IF* types to NFS file types
28 */ 23 */
@@ -55,7 +50,7 @@ __be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp)
55 return decode_fh(p, fhp); 50 return decode_fh(p, fhp);
56} 51}
57 52
58static inline __be32 * 53static __be32 *
59encode_fh(__be32 *p, struct svc_fh *fhp) 54encode_fh(__be32 *p, struct svc_fh *fhp)
60{ 55{
61 memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE); 56 memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE);
@@ -66,7 +61,7 @@ encode_fh(__be32 *p, struct svc_fh *fhp)
66 * Decode a file name and make sure that the path contains 61 * Decode a file name and make sure that the path contains
67 * no slashes or null bytes. 62 * no slashes or null bytes.
68 */ 63 */
69static inline __be32 * 64static __be32 *
70decode_filename(__be32 *p, char **namp, int *lenp) 65decode_filename(__be32 *p, char **namp, int *lenp)
71{ 66{
72 char *name; 67 char *name;
@@ -82,7 +77,7 @@ decode_filename(__be32 *p, char **namp, int *lenp)
82 return p; 77 return p;
83} 78}
84 79
85static inline __be32 * 80static __be32 *
86decode_pathname(__be32 *p, char **namp, int *lenp) 81decode_pathname(__be32 *p, char **namp, int *lenp)
87{ 82{
88 char *name; 83 char *name;
@@ -98,7 +93,7 @@ decode_pathname(__be32 *p, char **namp, int *lenp)
98 return p; 93 return p;
99} 94}
100 95
101static inline __be32 * 96static __be32 *
102decode_sattr(__be32 *p, struct iattr *iap) 97decode_sattr(__be32 *p, struct iattr *iap)
103{ 98{
104 u32 tmp, tmp1; 99 u32 tmp, tmp1;
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index bb4d926e4487..7a79c23aa6d4 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -99,7 +99,7 @@ static struct raparm_hbucket raparm_hash[RAPARM_HASH_SIZE];
99/* 99/*
100 * Called from nfsd_lookup and encode_dirent. Check if we have crossed 100 * Called from nfsd_lookup and encode_dirent. Check if we have crossed
101 * a mount point. 101 * a mount point.
102 * Returns -EAGAIN leaving *dpp and *expp unchanged, 102 * Returns -EAGAIN or -ETIMEDOUT leaving *dpp and *expp unchanged,
103 * or nfs_ok having possibly changed *dpp and *expp 103 * or nfs_ok having possibly changed *dpp and *expp
104 */ 104 */
105int 105int
@@ -736,10 +736,10 @@ static int
736nfsd_sync(struct file *filp) 736nfsd_sync(struct file *filp)
737{ 737{
738 int err; 738 int err;
739 struct inode *inode = filp->f_dentry->d_inode; 739 struct inode *inode = filp->f_path.dentry->d_inode;
740 dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name); 740 dprintk("nfsd: sync file %s\n", filp->f_path.dentry->d_name.name);
741 mutex_lock(&inode->i_mutex); 741 mutex_lock(&inode->i_mutex);
742 err=nfsd_dosync(filp, filp->f_dentry, filp->f_op); 742 err=nfsd_dosync(filp, filp->f_path.dentry, filp->f_op);
743 mutex_unlock(&inode->i_mutex); 743 mutex_unlock(&inode->i_mutex);
744 744
745 return err; 745 return err;
@@ -845,7 +845,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
845 int host_err; 845 int host_err;
846 846
847 err = nfserr_perm; 847 err = nfserr_perm;
848 inode = file->f_dentry->d_inode; 848 inode = file->f_path.dentry->d_inode;
849#ifdef MSNFS 849#ifdef MSNFS
850 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && 850 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
851 (!lock_may_read(inode, offset, *count))) 851 (!lock_may_read(inode, offset, *count)))
@@ -883,7 +883,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
883 nfsdstats.io_read += host_err; 883 nfsdstats.io_read += host_err;
884 *count = host_err; 884 *count = host_err;
885 err = 0; 885 err = 0;
886 fsnotify_access(file->f_dentry); 886 fsnotify_access(file->f_path.dentry);
887 } else 887 } else
888 err = nfserrno(host_err); 888 err = nfserrno(host_err);
889out: 889out:
@@ -917,11 +917,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
917 err = nfserr_perm; 917 err = nfserr_perm;
918 918
919 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && 919 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
920 (!lock_may_write(file->f_dentry->d_inode, offset, cnt))) 920 (!lock_may_write(file->f_path.dentry->d_inode, offset, cnt)))
921 goto out; 921 goto out;
922#endif 922#endif
923 923
924 dentry = file->f_dentry; 924 dentry = file->f_path.dentry;
925 inode = dentry->d_inode; 925 inode = dentry->d_inode;
926 exp = fhp->fh_export; 926 exp = fhp->fh_export;
927 927
@@ -950,7 +950,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
950 set_fs(oldfs); 950 set_fs(oldfs);
951 if (host_err >= 0) { 951 if (host_err >= 0) {
952 nfsdstats.io_write += cnt; 952 nfsdstats.io_write += cnt;
953 fsnotify_modify(file->f_dentry); 953 fsnotify_modify(file->f_path.dentry);
954 } 954 }
955 955
956 /* clear setuid/setgid flag after write */ 956 /* clear setuid/setgid flag after write */
@@ -1885,28 +1885,27 @@ nfsd_racache_init(int cache_size)
1885 return 0; 1885 return 0;
1886 if (cache_size < 2*RAPARM_HASH_SIZE) 1886 if (cache_size < 2*RAPARM_HASH_SIZE)
1887 cache_size = 2*RAPARM_HASH_SIZE; 1887 cache_size = 2*RAPARM_HASH_SIZE;
1888 raparml = kmalloc(sizeof(struct raparms) * cache_size, GFP_KERNEL); 1888 raparml = kcalloc(cache_size, sizeof(struct raparms), GFP_KERNEL);
1889 1889
1890 if (raparml != NULL) { 1890 if (!raparml) {
1891 dprintk("nfsd: allocating %d readahead buffers.\n",
1892 cache_size);
1893 for (i = 0 ; i < RAPARM_HASH_SIZE ; i++) {
1894 raparm_hash[i].pb_head = NULL;
1895 spin_lock_init(&raparm_hash[i].pb_lock);
1896 }
1897 nperbucket = cache_size >> RAPARM_HASH_BITS;
1898 memset(raparml, 0, sizeof(struct raparms) * cache_size);
1899 for (i = 0; i < cache_size - 1; i++) {
1900 if (i % nperbucket == 0)
1901 raparm_hash[j++].pb_head = raparml + i;
1902 if (i % nperbucket < nperbucket-1)
1903 raparml[i].p_next = raparml + i + 1;
1904 }
1905 } else {
1906 printk(KERN_WARNING 1891 printk(KERN_WARNING
1907 "nfsd: Could not allocate memory read-ahead cache.\n"); 1892 "nfsd: Could not allocate memory read-ahead cache.\n");
1908 return -ENOMEM; 1893 return -ENOMEM;
1909 } 1894 }
1895
1896 dprintk("nfsd: allocating %d readahead buffers.\n", cache_size);
1897 for (i = 0 ; i < RAPARM_HASH_SIZE ; i++) {
1898 raparm_hash[i].pb_head = NULL;
1899 spin_lock_init(&raparm_hash[i].pb_lock);
1900 }
1901 nperbucket = cache_size >> RAPARM_HASH_BITS;
1902 for (i = 0; i < cache_size - 1; i++) {
1903 if (i % nperbucket == 0)
1904 raparm_hash[j++].pb_head = raparml + i;
1905 if (i % nperbucket < nperbucket-1)
1906 raparml[i].p_next = raparml + i + 1;
1907 }
1908
1910 nfsdstats.ra_size = cache_size; 1909 nfsdstats.ra_size = cache_size;
1911 return 0; 1910 return 0;
1912} 1911}