diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/export.c | 33 | ||||
-rw-r--r-- | fs/nfsd/lockd.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs2acl.c | 8 | ||||
-rw-r--r-- | fs/nfsd/nfs3acl.c | 8 | ||||
-rw-r--r-- | fs/nfsd/nfs3xdr.c | 24 | ||||
-rw-r--r-- | fs/nfsd/nfs4proc.c | 625 | ||||
-rw-r--r-- | fs/nfsd/nfs4recover.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 116 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 14 | ||||
-rw-r--r-- | fs/nfsd/nfscache.c | 3 | ||||
-rw-r--r-- | fs/nfsd/nfsctl.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfsfh.c | 6 | ||||
-rw-r--r-- | fs/nfsd/nfsxdr.c | 13 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 55 |
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 | |||
1006 | finish: | 1015 | finish: |
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 | */ |
25 | static u32 | 25 | static __be32 |
26 | nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp) | 26 | nlm_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 | */ |
45 | static inline __be32 * | 41 | static __be32 * |
46 | encode_time3(__be32 *p, struct timespec *time) | 42 | encode_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 | ||
52 | static inline __be32 * | 48 | static __be32 * |
53 | decode_time3(__be32 *p, struct timespec *time) | 49 | decode_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 | ||
60 | static inline __be32 * | 56 | static __be32 * |
61 | decode_fh(__be32 *p, struct svc_fh *fhp) | 57 | decode_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 | ||
80 | static inline __be32 * | 76 | static __be32 * |
81 | encode_fh(__be32 *p, struct svc_fh *fhp) | 77 | encode_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 | */ |
94 | static inline __be32 * | 90 | static __be32 * |
95 | decode_filename(__be32 *p, char **namp, int *lenp) | 91 | decode_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 | ||
110 | static inline __be32 * | 106 | static __be32 * |
111 | decode_sattr3(__be32 *p, struct iattr *iap) | 107 | decode_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 | ||
156 | static inline __be32 * | 152 | static __be32 * |
157 | encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, | 153 | encode_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 | ||
189 | static inline __be32 * | 185 | static __be32 * |
190 | encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) | 186 | encode_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 | ||
779 | static inline __be32 * | 775 | static __be32 * |
780 | encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, | 776 | encode_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 | ||
793 | static inline __be32 * | 789 | static __be32 * |
794 | encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, | 790 | encode_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 | ||
164 | static inline __be32 | 157 | static __be32 |
165 | nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, struct nfs4_stateowner **replay_owner) | 158 | nfsd4_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(¤t_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); |
252 | out: | 248 | out: |
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 | */ |
264 | static inline __be32 | 260 | static __be32 |
265 | nfsd4_getfh(struct svc_fh *current_fh, struct svc_fh **getfh) | 261 | nfsd4_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 | ||
274 | static inline __be32 | 271 | static __be32 |
275 | nfsd4_putfh(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_putfh *putfh) | 272 | nfsd4_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(¤t_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 | ||
283 | static inline __be32 | 282 | static __be32 |
284 | nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh) | 283 | nfsd4_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 | ||
294 | static inline __be32 | 294 | static __be32 |
295 | nfsd4_restorefh(struct svc_fh *current_fh, struct svc_fh *save_fh) | 295 | nfsd4_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 | ||
304 | static inline __be32 | 305 | static __be32 |
305 | nfsd4_savefh(struct svc_fh *current_fh, struct svc_fh *save_fh) | 306 | nfsd4_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 | */ |
317 | static inline __be32 | 319 | static __be32 |
318 | nfsd4_access(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_access *access) | 320 | nfsd4_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 | ||
327 | static inline __be32 | 331 | static __be32 |
328 | nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_commit *commit) | 332 | nfsd4_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 | ||
342 | static __be32 | 348 | static __be32 |
343 | nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_create *create) | 349 | nfsd4_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 | ||
426 | static inline __be32 | 434 | static __be32 |
427 | nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_getattr *getattr) | 435 | nfsd4_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 | ||
445 | static inline __be32 | 454 | static __be32 |
446 | nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh, | 455 | nfsd4_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 | ||
459 | static __be32 | 469 | static __be32 |
460 | nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh) | 470 | nfsd4_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 | ||
477 | static inline __be32 | 489 | static __be32 |
478 | nfsd4_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lookup *lookup) | 490 | nfsd4_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 | ||
483 | static inline __be32 | 498 | static __be32 |
484 | nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read) | 499 | nfsd4_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 | |||
504 | out: | 521 | out: |
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 | ||
511 | static inline __be32 | 528 | static __be32 |
512 | nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readdir *readdir) | 529 | nfsd4_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 | ||
534 | static inline __be32 | 552 | static __be32 |
535 | nfsd4_readlink(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readlink *readlink) | 553 | nfsd4_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 | ||
542 | static inline __be32 | 561 | static __be32 |
543 | nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_remove *remove) | 562 | nfsd4_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 | ||
559 | static inline __be32 | 580 | static __be32 |
560 | nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh, | 581 | nfsd4_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 | ||
592 | static inline __be32 | 613 | static __be32 |
593 | nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr) | 614 | nfsd4_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 | ||
617 | static inline __be32 | 640 | static __be32 |
618 | nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write) | 641 | nfsd4_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 | */ |
664 | static __be32 | 688 | static __be32 |
665 | nfsd4_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 | ||
741 | static __be32 | ||
742 | nfsd4_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 | |||
751 | static __be32 | ||
752 | nfsd4_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 | ||
776 | static 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 | |||
786 | static 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 | |||
799 | typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *, | ||
800 | void *); | ||
801 | |||
802 | struct 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 | |||
811 | static 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 | ||
939 | encode_op: | 895 | encode_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 | ||
959 | out: | 915 | out: |
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 | ||
921 | static 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 | */ |
85 | static DEFINE_MUTEX(client_mutex); | 85 | static DEFINE_MUTEX(client_mutex); |
86 | 86 | ||
87 | static kmem_cache_t *stateowner_slab = NULL; | 87 | static struct kmem_cache *stateowner_slab = NULL; |
88 | static kmem_cache_t *file_slab = NULL; | 88 | static struct kmem_cache *file_slab = NULL; |
89 | static kmem_cache_t *stateid_slab = NULL; | 89 | static struct kmem_cache *stateid_slab = NULL; |
90 | static kmem_cache_t *deleg_slab = NULL; | 90 | static struct kmem_cache *deleg_slab = NULL; |
91 | 91 | ||
92 | void | 92 | void |
93 | nfs4_lock_state(void) | 93 | nfs4_lock_state(void) |
@@ -711,7 +711,8 @@ out_err: | |||
711 | * | 711 | * |
712 | */ | 712 | */ |
713 | __be32 | 713 | __be32 |
714 | nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid) | 714 | nfsd4_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 |
879 | nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm) | 880 | nfsd4_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 | ||
1005 | static void | 1008 | static void |
1006 | nfsd4_free_slab(kmem_cache_t **slab) | 1009 | nfsd4_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 | |||
1310 | nfs4_file_downgrade(struct file *filp, unsigned int share_access) | 1313 | nfs4_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 | |||
1623 | nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open) | 1626 | nfs4_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 | ||
1831 | static struct workqueue_struct *laundry_wq; | 1834 | static struct workqueue_struct *laundry_wq; |
1832 | static struct work_struct laundromat_work; | 1835 | static void laundromat_main(struct work_struct *); |
1833 | static void laundromat_main(void *); | 1836 | static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main); |
1834 | static DECLARE_WORK(laundromat_work, laundromat_main, NULL); | ||
1835 | 1837 | ||
1836 | __be32 | 1838 | __be32 |
1837 | nfsd4_renew(clientid_t *clid) | 1839 | nfsd4_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 | ||
1942 | void | 1945 | void |
1943 | laundromat_main(void *not_used) | 1946 | laundromat_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) | |||
1966 | static inline int | 1969 | static inline int |
1967 | nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp) | 1970 | nfs4_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 | ||
1972 | static int | 1975 | static int |
@@ -2242,24 +2245,25 @@ check_replay: | |||
2242 | } | 2245 | } |
2243 | 2246 | ||
2244 | __be32 | 2247 | __be32 |
2245 | nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc, struct nfs4_stateowner **replay_owner) | 2248 | nfsd4_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 | |||
2279 | out: | 2283 | out: |
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 |
2314 | nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od, struct nfs4_stateowner **replay_owner) | 2318 | nfsd4_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 | |||
2356 | out: | 2363 | out: |
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 |
2369 | nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close, struct nfs4_stateowner **replay_owner) | 2376 | nfsd4_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 | |||
2398 | out: | 2407 | out: |
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 |
2408 | nfsd4_delegreturn(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_delegreturn *dr) | 2417 | nfsd4_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(); |
2418 | out: | 2429 | out: |
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 |
2639 | nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner) | 2650 | nfsd4_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 |
2799 | nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt) | 2811 | nfsd4_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 |
2879 | nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner) | 2892 | nfsd4_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 | |||
2934 | out: | 2948 | out: |
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 | |||
2953 | check_for_locks(struct file *filp, struct nfs4_stateowner *lowner) | 2967 | check_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 |
2972 | nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner) | 2986 | nfsd4_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 | ||
112 | static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) | 112 | static 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 | ||
58 | static inline __be32 * | 53 | static __be32 * |
59 | encode_fh(__be32 *p, struct svc_fh *fhp) | 54 | encode_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 | */ |
69 | static inline __be32 * | 64 | static __be32 * |
70 | decode_filename(__be32 *p, char **namp, int *lenp) | 65 | decode_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 | ||
85 | static inline __be32 * | 80 | static __be32 * |
86 | decode_pathname(__be32 *p, char **namp, int *lenp) | 81 | decode_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 | ||
101 | static inline __be32 * | 96 | static __be32 * |
102 | decode_sattr(__be32 *p, struct iattr *iap) | 97 | decode_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 | */ |
105 | int | 105 | int |
@@ -736,10 +736,10 @@ static int | |||
736 | nfsd_sync(struct file *filp) | 736 | nfsd_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); |
889 | out: | 889 | out: |
@@ -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 | } |