diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/Kconfig | 9 | ||||
-rw-r--r-- | fs/nfs/client.c | 62 | ||||
-rw-r--r-- | fs/nfs/delegation.c | 7 | ||||
-rw-r--r-- | fs/nfs/delegation.h | 19 | ||||
-rw-r--r-- | fs/nfs/dir.c | 10 | ||||
-rw-r--r-- | fs/nfs/file.c | 46 | ||||
-rw-r--r-- | fs/nfs/inode.c | 4 | ||||
-rw-r--r-- | fs/nfs/internal.h | 6 | ||||
-rw-r--r-- | fs/nfs/nfs2xdr.c | 28 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 17 | ||||
-rw-r--r-- | fs/nfs/nfs3xdr.c | 43 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 7 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 6 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayoutdev.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 32 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 103 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 82 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 22 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 12 | ||||
-rw-r--r-- | fs/nfs/proc.c | 17 | ||||
-rw-r--r-- | fs/nfs/read.c | 16 | ||||
-rw-r--r-- | fs/nfs/super.c | 25 | ||||
-rw-r--r-- | fs/nfs/unlink.c | 2 | ||||
-rw-r--r-- | fs/nfs/write.c | 34 |
24 files changed, 318 insertions, 293 deletions
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index f90f4f5cd421..404c6a8ac394 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig | |||
@@ -88,9 +88,8 @@ config NFS_V4 | |||
88 | 88 | ||
89 | config NFS_V4_1 | 89 | config NFS_V4_1 |
90 | bool "NFS client support for NFSv4.1 (EXPERIMENTAL)" | 90 | bool "NFS client support for NFSv4.1 (EXPERIMENTAL)" |
91 | depends on NFS_FS && NFS_V4 && EXPERIMENTAL | 91 | depends on NFS_V4 && EXPERIMENTAL |
92 | select SUNRPC_BACKCHANNEL | 92 | select SUNRPC_BACKCHANNEL |
93 | select PNFS_FILE_LAYOUT | ||
94 | help | 93 | help |
95 | This option enables support for minor version 1 of the NFSv4 protocol | 94 | This option enables support for minor version 1 of the NFSv4 protocol |
96 | (RFC 5661) in the kernel's NFS client. | 95 | (RFC 5661) in the kernel's NFS client. |
@@ -99,15 +98,17 @@ config NFS_V4_1 | |||
99 | 98 | ||
100 | config PNFS_FILE_LAYOUT | 99 | config PNFS_FILE_LAYOUT |
101 | tristate | 100 | tristate |
101 | depends on NFS_V4_1 | ||
102 | default m | ||
102 | 103 | ||
103 | config PNFS_BLOCK | 104 | config PNFS_BLOCK |
104 | tristate | 105 | tristate |
105 | depends on NFS_FS && NFS_V4_1 && BLK_DEV_DM | 106 | depends on NFS_V4_1 && BLK_DEV_DM |
106 | default m | 107 | default m |
107 | 108 | ||
108 | config PNFS_OBJLAYOUT | 109 | config PNFS_OBJLAYOUT |
109 | tristate | 110 | tristate |
110 | depends on NFS_FS && NFS_V4_1 && SCSI_OSD_ULD | 111 | depends on NFS_V4_1 && SCSI_OSD_ULD |
111 | default m | 112 | default m |
112 | 113 | ||
113 | config NFS_V4_1_IMPLEMENTATION_ID_DOMAIN | 114 | config NFS_V4_1_IMPLEMENTATION_ID_DOMAIN |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index f005b5bebdc7..254719c4a575 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -147,7 +147,7 @@ struct nfs_client_initdata { | |||
147 | * Since these are allocated/deallocated very rarely, we don't | 147 | * Since these are allocated/deallocated very rarely, we don't |
148 | * bother putting them in a slab cache... | 148 | * bother putting them in a slab cache... |
149 | */ | 149 | */ |
150 | static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) | 150 | struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) |
151 | { | 151 | { |
152 | struct nfs_client *clp; | 152 | struct nfs_client *clp; |
153 | struct rpc_cred *cred; | 153 | struct rpc_cred *cred; |
@@ -177,18 +177,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ | |||
177 | clp->cl_proto = cl_init->proto; | 177 | clp->cl_proto = cl_init->proto; |
178 | clp->cl_net = get_net(cl_init->net); | 178 | clp->cl_net = get_net(cl_init->net); |
179 | 179 | ||
180 | #ifdef CONFIG_NFS_V4 | ||
181 | err = nfs_get_cb_ident_idr(clp, cl_init->minorversion); | ||
182 | if (err) | ||
183 | goto error_cleanup; | ||
184 | |||
185 | spin_lock_init(&clp->cl_lock); | ||
186 | INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); | ||
187 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); | ||
188 | clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; | ||
189 | clp->cl_minorversion = cl_init->minorversion; | ||
190 | clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion]; | ||
191 | #endif | ||
192 | cred = rpc_lookup_machine_cred("*"); | 180 | cred = rpc_lookup_machine_cred("*"); |
193 | if (!IS_ERR(cred)) | 181 | if (!IS_ERR(cred)) |
194 | clp->cl_machine_cred = cred; | 182 | clp->cl_machine_cred = cred; |
@@ -218,6 +206,30 @@ static void nfs4_shutdown_session(struct nfs_client *clp) | |||
218 | } | 206 | } |
219 | #endif /* CONFIG_NFS_V4_1 */ | 207 | #endif /* CONFIG_NFS_V4_1 */ |
220 | 208 | ||
209 | struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) | ||
210 | { | ||
211 | int err; | ||
212 | struct nfs_client *clp = nfs_alloc_client(cl_init); | ||
213 | if (IS_ERR(clp)) | ||
214 | return clp; | ||
215 | |||
216 | err = nfs_get_cb_ident_idr(clp, cl_init->minorversion); | ||
217 | if (err) | ||
218 | goto error; | ||
219 | |||
220 | spin_lock_init(&clp->cl_lock); | ||
221 | INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); | ||
222 | rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); | ||
223 | clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; | ||
224 | clp->cl_minorversion = cl_init->minorversion; | ||
225 | clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion]; | ||
226 | return clp; | ||
227 | |||
228 | error: | ||
229 | kfree(clp); | ||
230 | return ERR_PTR(err); | ||
231 | } | ||
232 | |||
221 | /* | 233 | /* |
222 | * Destroy the NFS4 callback service | 234 | * Destroy the NFS4 callback service |
223 | */ | 235 | */ |
@@ -242,6 +254,12 @@ static void nfs4_shutdown_client(struct nfs_client *clp) | |||
242 | kfree(clp->cl_implid); | 254 | kfree(clp->cl_implid); |
243 | } | 255 | } |
244 | 256 | ||
257 | void nfs4_free_client(struct nfs_client *clp) | ||
258 | { | ||
259 | nfs4_shutdown_client(clp); | ||
260 | nfs_free_client(clp); | ||
261 | } | ||
262 | |||
245 | /* idr_remove_all is not needed as all id's are removed by nfs_put_client */ | 263 | /* idr_remove_all is not needed as all id's are removed by nfs_put_client */ |
246 | void nfs_cleanup_cb_ident_idr(struct net *net) | 264 | void nfs_cleanup_cb_ident_idr(struct net *net) |
247 | { | 265 | { |
@@ -266,14 +284,12 @@ static void pnfs_init_server(struct nfs_server *server) | |||
266 | 284 | ||
267 | static void nfs4_destroy_server(struct nfs_server *server) | 285 | static void nfs4_destroy_server(struct nfs_server *server) |
268 | { | 286 | { |
287 | nfs_server_return_all_delegations(server); | ||
288 | unset_pnfs_layoutdriver(server); | ||
269 | nfs4_purge_state_owners(server); | 289 | nfs4_purge_state_owners(server); |
270 | } | 290 | } |
271 | 291 | ||
272 | #else | 292 | #else |
273 | static void nfs4_shutdown_client(struct nfs_client *clp) | ||
274 | { | ||
275 | } | ||
276 | |||
277 | void nfs_cleanup_cb_ident_idr(struct net *net) | 293 | void nfs_cleanup_cb_ident_idr(struct net *net) |
278 | { | 294 | { |
279 | } | 295 | } |
@@ -291,12 +307,10 @@ static void pnfs_init_server(struct nfs_server *server) | |||
291 | /* | 307 | /* |
292 | * Destroy a shared client record | 308 | * Destroy a shared client record |
293 | */ | 309 | */ |
294 | static void nfs_free_client(struct nfs_client *clp) | 310 | void nfs_free_client(struct nfs_client *clp) |
295 | { | 311 | { |
296 | dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version); | 312 | dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version); |
297 | 313 | ||
298 | nfs4_shutdown_client(clp); | ||
299 | |||
300 | nfs_fscache_release_client_cookie(clp); | 314 | nfs_fscache_release_client_cookie(clp); |
301 | 315 | ||
302 | /* -EIO all pending I/O */ | 316 | /* -EIO all pending I/O */ |
@@ -333,7 +347,7 @@ void nfs_put_client(struct nfs_client *clp) | |||
333 | 347 | ||
334 | BUG_ON(!list_empty(&clp->cl_superblocks)); | 348 | BUG_ON(!list_empty(&clp->cl_superblocks)); |
335 | 349 | ||
336 | nfs_free_client(clp); | 350 | clp->rpc_ops->free_client(clp); |
337 | } | 351 | } |
338 | } | 352 | } |
339 | EXPORT_SYMBOL_GPL(nfs_put_client); | 353 | EXPORT_SYMBOL_GPL(nfs_put_client); |
@@ -572,7 +586,7 @@ nfs_get_client(const struct nfs_client_initdata *cl_init, | |||
572 | if (clp) { | 586 | if (clp) { |
573 | spin_unlock(&nn->nfs_client_lock); | 587 | spin_unlock(&nn->nfs_client_lock); |
574 | if (new) | 588 | if (new) |
575 | nfs_free_client(new); | 589 | new->rpc_ops->free_client(new); |
576 | return nfs_found_client(cl_init, clp); | 590 | return nfs_found_client(cl_init, clp); |
577 | } | 591 | } |
578 | if (new) { | 592 | if (new) { |
@@ -586,7 +600,7 @@ nfs_get_client(const struct nfs_client_initdata *cl_init, | |||
586 | 600 | ||
587 | spin_unlock(&nn->nfs_client_lock); | 601 | spin_unlock(&nn->nfs_client_lock); |
588 | 602 | ||
589 | new = nfs_alloc_client(cl_init); | 603 | new = cl_init->rpc_ops->alloc_client(cl_init); |
590 | } while (!IS_ERR(new)); | 604 | } while (!IS_ERR(new)); |
591 | 605 | ||
592 | dprintk("<-- nfs_get_client() Failed to find %s (%ld)\n", | 606 | dprintk("<-- nfs_get_client() Failed to find %s (%ld)\n", |
@@ -975,7 +989,6 @@ static void nfs_server_set_fsinfo(struct nfs_server *server, | |||
975 | server->wsize = NFS_MAX_FILE_IO_SIZE; | 989 | server->wsize = NFS_MAX_FILE_IO_SIZE; |
976 | server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 990 | server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
977 | server->pnfs_blksize = fsinfo->blksize; | 991 | server->pnfs_blksize = fsinfo->blksize; |
978 | set_pnfs_layoutdriver(server, mntfh, fsinfo->layouttype); | ||
979 | 992 | ||
980 | server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL); | 993 | server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL); |
981 | 994 | ||
@@ -1138,7 +1151,6 @@ void nfs_free_server(struct nfs_server *server) | |||
1138 | dprintk("--> nfs_free_server()\n"); | 1151 | dprintk("--> nfs_free_server()\n"); |
1139 | 1152 | ||
1140 | nfs_server_remove_lists(server); | 1153 | nfs_server_remove_lists(server); |
1141 | unset_pnfs_layoutdriver(server); | ||
1142 | 1154 | ||
1143 | if (server->destroy != NULL) | 1155 | if (server->destroy != NULL) |
1144 | server->destroy(server); | 1156 | server->destroy(server); |
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index bd3a9601d32d..81c5eec3cf38 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -47,7 +47,7 @@ void nfs_mark_delegation_referenced(struct nfs_delegation *delegation) | |||
47 | * | 47 | * |
48 | * Returns one if inode has the indicated delegation, otherwise zero. | 48 | * Returns one if inode has the indicated delegation, otherwise zero. |
49 | */ | 49 | */ |
50 | int nfs_have_delegation(struct inode *inode, fmode_t flags) | 50 | int nfs4_have_delegation(struct inode *inode, fmode_t flags) |
51 | { | 51 | { |
52 | struct nfs_delegation *delegation; | 52 | struct nfs_delegation *delegation; |
53 | int ret = 0; | 53 | int ret = 0; |
@@ -388,7 +388,7 @@ void nfs_inode_return_delegation_noreclaim(struct inode *inode) | |||
388 | * | 388 | * |
389 | * Returns zero on success, or a negative errno value. | 389 | * Returns zero on success, or a negative errno value. |
390 | */ | 390 | */ |
391 | int nfs_inode_return_delegation(struct inode *inode) | 391 | int nfs4_inode_return_delegation(struct inode *inode) |
392 | { | 392 | { |
393 | struct nfs_server *server = NFS_SERVER(inode); | 393 | struct nfs_server *server = NFS_SERVER(inode); |
394 | struct nfs_inode *nfsi = NFS_I(inode); | 394 | struct nfs_inode *nfsi = NFS_I(inode); |
@@ -417,9 +417,8 @@ static void nfs_mark_return_delegation(struct nfs_server *server, | |||
417 | * @sb: sb to process | 417 | * @sb: sb to process |
418 | * | 418 | * |
419 | */ | 419 | */ |
420 | void nfs_super_return_all_delegations(struct super_block *sb) | 420 | void nfs_server_return_all_delegations(struct nfs_server *server) |
421 | { | 421 | { |
422 | struct nfs_server *server = NFS_SB(sb); | ||
423 | struct nfs_client *clp = server->nfs_client; | 422 | struct nfs_client *clp = server->nfs_client; |
424 | struct nfs_delegation *delegation; | 423 | struct nfs_delegation *delegation; |
425 | 424 | ||
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 72709c4193fa..1f3ccd934635 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h | |||
@@ -33,12 +33,12 @@ enum { | |||
33 | 33 | ||
34 | int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); | 34 | int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); |
35 | void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); | 35 | void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); |
36 | int nfs_inode_return_delegation(struct inode *inode); | 36 | int nfs4_inode_return_delegation(struct inode *inode); |
37 | int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid); | 37 | int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid); |
38 | void nfs_inode_return_delegation_noreclaim(struct inode *inode); | 38 | void nfs_inode_return_delegation_noreclaim(struct inode *inode); |
39 | 39 | ||
40 | struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle); | 40 | struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle); |
41 | void nfs_super_return_all_delegations(struct super_block *sb); | 41 | void nfs_server_return_all_delegations(struct nfs_server *); |
42 | void nfs_expire_all_delegations(struct nfs_client *clp); | 42 | void nfs_expire_all_delegations(struct nfs_client *clp); |
43 | void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags); | 43 | void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags); |
44 | void nfs_expire_unreferenced_delegations(struct nfs_client *clp); | 44 | void nfs_expire_unreferenced_delegations(struct nfs_client *clp); |
@@ -56,24 +56,13 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl); | |||
56 | bool nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode, fmode_t flags); | 56 | bool nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode, fmode_t flags); |
57 | 57 | ||
58 | void nfs_mark_delegation_referenced(struct nfs_delegation *delegation); | 58 | void nfs_mark_delegation_referenced(struct nfs_delegation *delegation); |
59 | int nfs_have_delegation(struct inode *inode, fmode_t flags); | 59 | int nfs4_have_delegation(struct inode *inode, fmode_t flags); |
60 | 60 | ||
61 | #else | ||
62 | static inline int nfs_have_delegation(struct inode *inode, fmode_t flags) | ||
63 | { | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static inline int nfs_inode_return_delegation(struct inode *inode) | ||
68 | { | ||
69 | nfs_wb_all(inode); | ||
70 | return 0; | ||
71 | } | ||
72 | #endif | 61 | #endif |
73 | 62 | ||
74 | static inline int nfs_have_delegated_attributes(struct inode *inode) | 63 | static inline int nfs_have_delegated_attributes(struct inode *inode) |
75 | { | 64 | { |
76 | return nfs_have_delegation(inode, FMODE_READ) && | 65 | return NFS_PROTO(inode)->have_delegation(inode, FMODE_READ) && |
77 | !(NFS_I(inode)->cache_validity & NFS_INO_REVAL_FORCED); | 66 | !(NFS_I(inode)->cache_validity & NFS_INO_REVAL_FORCED); |
78 | } | 67 | } |
79 | 68 | ||
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index a6b1c7fb8232..b7136853ca9c 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -1128,7 +1128,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) | |||
1128 | goto out_bad; | 1128 | goto out_bad; |
1129 | } | 1129 | } |
1130 | 1130 | ||
1131 | if (nfs_have_delegation(inode, FMODE_READ)) | 1131 | if (NFS_PROTO(dir)->have_delegation(inode, FMODE_READ)) |
1132 | goto out_set_verifier; | 1132 | goto out_set_verifier; |
1133 | 1133 | ||
1134 | /* Force a full look up iff the parent directory has changed */ | 1134 | /* Force a full look up iff the parent directory has changed */ |
@@ -1706,7 +1706,7 @@ static int nfs_safe_remove(struct dentry *dentry) | |||
1706 | } | 1706 | } |
1707 | 1707 | ||
1708 | if (inode != NULL) { | 1708 | if (inode != NULL) { |
1709 | nfs_inode_return_delegation(inode); | 1709 | NFS_PROTO(inode)->return_delegation(inode); |
1710 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1710 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
1711 | /* The VFS may want to delete this inode */ | 1711 | /* The VFS may want to delete this inode */ |
1712 | if (error == 0) | 1712 | if (error == 0) |
@@ -1834,7 +1834,7 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | |||
1834 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, | 1834 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, |
1835 | dentry->d_parent->d_name.name, dentry->d_name.name); | 1835 | dentry->d_parent->d_name.name, dentry->d_name.name); |
1836 | 1836 | ||
1837 | nfs_inode_return_delegation(inode); | 1837 | NFS_PROTO(inode)->return_delegation(inode); |
1838 | 1838 | ||
1839 | d_drop(dentry); | 1839 | d_drop(dentry); |
1840 | error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); | 1840 | error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); |
@@ -1918,9 +1918,9 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1918 | } | 1918 | } |
1919 | } | 1919 | } |
1920 | 1920 | ||
1921 | nfs_inode_return_delegation(old_inode); | 1921 | NFS_PROTO(old_inode)->return_delegation(old_inode); |
1922 | if (new_inode != NULL) | 1922 | if (new_inode != NULL) |
1923 | nfs_inode_return_delegation(new_inode); | 1923 | NFS_PROTO(new_inode)->return_delegation(new_inode); |
1924 | 1924 | ||
1925 | error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, | 1925 | error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, |
1926 | new_dir, &new_dentry->d_name); | 1926 | new_dir, &new_dentry->d_name); |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index a6708e6b438d..57a22a1533e2 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -178,7 +178,7 @@ nfs_file_flush(struct file *file, fl_owner_t id) | |||
178 | * If we're holding a write delegation, then just start the i/o | 178 | * If we're holding a write delegation, then just start the i/o |
179 | * but don't wait for completion (or send a commit). | 179 | * but don't wait for completion (or send a commit). |
180 | */ | 180 | */ |
181 | if (nfs_have_delegation(inode, FMODE_WRITE)) | 181 | if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE)) |
182 | return filemap_fdatawrite(file->f_mapping); | 182 | return filemap_fdatawrite(file->f_mapping); |
183 | 183 | ||
184 | /* Flush writes to the server and return any errors */ | 184 | /* Flush writes to the server and return any errors */ |
@@ -265,7 +265,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | |||
265 | * fall back to doing a synchronous write. | 265 | * fall back to doing a synchronous write. |
266 | */ | 266 | */ |
267 | static int | 267 | static int |
268 | nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) | 268 | nfs_file_fsync_commit(struct file *file, loff_t start, loff_t end, int datasync) |
269 | { | 269 | { |
270 | struct dentry *dentry = file->f_path.dentry; | 270 | struct dentry *dentry = file->f_path.dentry; |
271 | struct nfs_open_context *ctx = nfs_file_open_context(file); | 271 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
@@ -277,9 +277,6 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
277 | dentry->d_parent->d_name.name, dentry->d_name.name, | 277 | dentry->d_parent->d_name.name, dentry->d_name.name, |
278 | datasync); | 278 | datasync); |
279 | 279 | ||
280 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | ||
281 | mutex_lock(&inode->i_mutex); | ||
282 | |||
283 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); | 280 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); |
284 | have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | 281 | have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); |
285 | status = nfs_commit_inode(inode, FLUSH_SYNC); | 282 | status = nfs_commit_inode(inode, FLUSH_SYNC); |
@@ -290,10 +287,20 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
290 | ret = xchg(&ctx->error, 0); | 287 | ret = xchg(&ctx->error, 0); |
291 | if (!ret && status < 0) | 288 | if (!ret && status < 0) |
292 | ret = status; | 289 | ret = status; |
293 | if (!ret && !datasync) | 290 | return ret; |
294 | /* application has asked for meta-data sync */ | 291 | } |
295 | ret = pnfs_layoutcommit_inode(inode, true); | 292 | |
293 | static int | ||
294 | nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) | ||
295 | { | ||
296 | int ret; | ||
297 | struct inode *inode = file->f_path.dentry->d_inode; | ||
298 | |||
299 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | ||
300 | mutex_lock(&inode->i_mutex); | ||
301 | ret = nfs_file_fsync_commit(file, start, end, datasync); | ||
296 | mutex_unlock(&inode->i_mutex); | 302 | mutex_unlock(&inode->i_mutex); |
303 | |||
297 | return ret; | 304 | return ret; |
298 | } | 305 | } |
299 | 306 | ||
@@ -670,7 +677,7 @@ do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) | |||
670 | } | 677 | } |
671 | fl->fl_type = saved_type; | 678 | fl->fl_type = saved_type; |
672 | 679 | ||
673 | if (nfs_have_delegation(inode, FMODE_READ)) | 680 | if (NFS_PROTO(inode)->have_delegation(inode, FMODE_READ)) |
674 | goto out_noconflict; | 681 | goto out_noconflict; |
675 | 682 | ||
676 | if (is_local) | 683 | if (is_local) |
@@ -765,7 +772,7 @@ do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) | |||
765 | * This makes locking act as a cache coherency point. | 772 | * This makes locking act as a cache coherency point. |
766 | */ | 773 | */ |
767 | nfs_sync_mapping(filp->f_mapping); | 774 | nfs_sync_mapping(filp->f_mapping); |
768 | if (!nfs_have_delegation(inode, FMODE_READ)) { | 775 | if (!NFS_PROTO(inode)->have_delegation(inode, FMODE_READ)) { |
769 | if (is_time_granular(&NFS_SERVER(inode)->time_delta)) | 776 | if (is_time_granular(&NFS_SERVER(inode)->time_delta)) |
770 | __nfs_revalidate_inode(NFS_SERVER(inode), inode); | 777 | __nfs_revalidate_inode(NFS_SERVER(inode), inode); |
771 | else | 778 | else |
@@ -956,6 +963,23 @@ out_drop: | |||
956 | goto out_put_ctx; | 963 | goto out_put_ctx; |
957 | } | 964 | } |
958 | 965 | ||
966 | static int | ||
967 | nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) | ||
968 | { | ||
969 | int ret; | ||
970 | struct inode *inode = file->f_path.dentry->d_inode; | ||
971 | |||
972 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | ||
973 | mutex_lock(&inode->i_mutex); | ||
974 | ret = nfs_file_fsync_commit(file, start, end, datasync); | ||
975 | if (!ret && !datasync) | ||
976 | /* application has asked for meta-data sync */ | ||
977 | ret = pnfs_layoutcommit_inode(inode, true); | ||
978 | mutex_unlock(&inode->i_mutex); | ||
979 | |||
980 | return ret; | ||
981 | } | ||
982 | |||
959 | const struct file_operations nfs4_file_operations = { | 983 | const struct file_operations nfs4_file_operations = { |
960 | .llseek = nfs_file_llseek, | 984 | .llseek = nfs_file_llseek, |
961 | .read = do_sync_read, | 985 | .read = do_sync_read, |
@@ -966,7 +990,7 @@ const struct file_operations nfs4_file_operations = { | |||
966 | .open = nfs4_file_open, | 990 | .open = nfs4_file_open, |
967 | .flush = nfs_file_flush, | 991 | .flush = nfs_file_flush, |
968 | .release = nfs_file_release, | 992 | .release = nfs_file_release, |
969 | .fsync = nfs_file_fsync, | 993 | .fsync = nfs4_file_fsync, |
970 | .lock = nfs_lock, | 994 | .lock = nfs_lock, |
971 | .flock = nfs_flock, | 995 | .flock = nfs_flock, |
972 | .splice_read = nfs_file_splice_read, | 996 | .splice_read = nfs_file_splice_read, |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index f7296983eba6..28c9ebbe78a6 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -430,7 +430,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
430 | * Return any delegations if we're going to change ACLs | 430 | * Return any delegations if we're going to change ACLs |
431 | */ | 431 | */ |
432 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) | 432 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) |
433 | nfs_inode_return_delegation(inode); | 433 | NFS_PROTO(inode)->return_delegation(inode); |
434 | error = NFS_PROTO(inode)->setattr(dentry, fattr, attr); | 434 | error = NFS_PROTO(inode)->setattr(dentry, fattr, attr); |
435 | if (error == 0) | 435 | if (error == 0) |
436 | nfs_refresh_inode(inode, fattr); | 436 | nfs_refresh_inode(inode, fattr); |
@@ -1457,7 +1457,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1457 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1457 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |
1458 | || S_ISLNK(inode->i_mode))) | 1458 | || S_ISLNK(inode->i_mode))) |
1459 | invalid &= ~NFS_INO_INVALID_DATA; | 1459 | invalid &= ~NFS_INO_INVALID_DATA; |
1460 | if (!nfs_have_delegation(inode, FMODE_READ) || | 1460 | if (!NFS_PROTO(inode)->have_delegation(inode, FMODE_READ) || |
1461 | (save_cache_validity & NFS_INO_REVAL_FORCED)) | 1461 | (save_cache_validity & NFS_INO_REVAL_FORCED)) |
1462 | nfsi->cache_validity |= invalid; | 1462 | nfsi->cache_validity |= invalid; |
1463 | 1463 | ||
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 18f99ef71343..7edc172c371e 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -148,9 +148,11 @@ extern void nfs_umount(const struct nfs_mount_request *info); | |||
148 | /* client.c */ | 148 | /* client.c */ |
149 | extern const struct rpc_program nfs_program; | 149 | extern const struct rpc_program nfs_program; |
150 | extern void nfs_clients_init(struct net *net); | 150 | extern void nfs_clients_init(struct net *net); |
151 | extern struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *); | ||
151 | 152 | ||
152 | extern void nfs_cleanup_cb_ident_idr(struct net *); | 153 | extern void nfs_cleanup_cb_ident_idr(struct net *); |
153 | extern void nfs_put_client(struct nfs_client *); | 154 | extern void nfs_put_client(struct nfs_client *); |
155 | extern void nfs_free_client(struct nfs_client *); | ||
154 | extern struct nfs_client *nfs4_find_client_ident(struct net *, int); | 156 | extern struct nfs_client *nfs4_find_client_ident(struct net *, int); |
155 | extern struct nfs_client * | 157 | extern struct nfs_client * |
156 | nfs4_find_client_sessionid(struct net *, const struct sockaddr *, | 158 | nfs4_find_client_sessionid(struct net *, const struct sockaddr *, |
@@ -304,7 +306,7 @@ extern int nfs_initiate_read(struct rpc_clnt *clnt, | |||
304 | extern void nfs_read_prepare(struct rpc_task *task, void *calldata); | 306 | extern void nfs_read_prepare(struct rpc_task *task, void *calldata); |
305 | extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, | 307 | extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, |
306 | struct nfs_pgio_header *hdr); | 308 | struct nfs_pgio_header *hdr); |
307 | extern void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, | 309 | extern void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, |
308 | struct inode *inode, | 310 | struct inode *inode, |
309 | const struct nfs_pgio_completion_ops *compl_ops); | 311 | const struct nfs_pgio_completion_ops *compl_ops); |
310 | extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); | 312 | extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); |
@@ -318,7 +320,7 @@ extern struct nfs_write_header *nfs_writehdr_alloc(void); | |||
318 | extern void nfs_writehdr_free(struct nfs_pgio_header *hdr); | 320 | extern void nfs_writehdr_free(struct nfs_pgio_header *hdr); |
319 | extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc, | 321 | extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc, |
320 | struct nfs_pgio_header *hdr); | 322 | struct nfs_pgio_header *hdr); |
321 | extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, | 323 | extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, |
322 | struct inode *inode, int ioflags, | 324 | struct inode *inode, int ioflags, |
323 | const struct nfs_pgio_completion_ops *compl_ops); | 325 | const struct nfs_pgio_completion_ops *compl_ops); |
324 | extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); | 326 | extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); |
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index baf759bccd05..d04f0df7be55 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c | |||
@@ -106,19 +106,16 @@ static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | |||
106 | static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_readres *result) | 106 | static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_readres *result) |
107 | { | 107 | { |
108 | u32 recvd, count; | 108 | u32 recvd, count; |
109 | size_t hdrlen; | ||
110 | __be32 *p; | 109 | __be32 *p; |
111 | 110 | ||
112 | p = xdr_inline_decode(xdr, 4); | 111 | p = xdr_inline_decode(xdr, 4); |
113 | if (unlikely(p == NULL)) | 112 | if (unlikely(p == NULL)) |
114 | goto out_overflow; | 113 | goto out_overflow; |
115 | count = be32_to_cpup(p); | 114 | count = be32_to_cpup(p); |
116 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; | 115 | recvd = xdr_read_pages(xdr, count); |
117 | recvd = xdr->buf->len - hdrlen; | ||
118 | if (unlikely(count > recvd)) | 116 | if (unlikely(count > recvd)) |
119 | goto out_cheating; | 117 | goto out_cheating; |
120 | out: | 118 | out: |
121 | xdr_read_pages(xdr, count); | ||
122 | result->eof = 0; /* NFSv2 does not pass EOF flag on the wire. */ | 119 | result->eof = 0; /* NFSv2 does not pass EOF flag on the wire. */ |
123 | result->count = count; | 120 | result->count = count; |
124 | return count; | 121 | return count; |
@@ -440,7 +437,6 @@ static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length) | |||
440 | static int decode_path(struct xdr_stream *xdr) | 437 | static int decode_path(struct xdr_stream *xdr) |
441 | { | 438 | { |
442 | u32 length, recvd; | 439 | u32 length, recvd; |
443 | size_t hdrlen; | ||
444 | __be32 *p; | 440 | __be32 *p; |
445 | 441 | ||
446 | p = xdr_inline_decode(xdr, 4); | 442 | p = xdr_inline_decode(xdr, 4); |
@@ -449,12 +445,9 @@ static int decode_path(struct xdr_stream *xdr) | |||
449 | length = be32_to_cpup(p); | 445 | length = be32_to_cpup(p); |
450 | if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN)) | 446 | if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN)) |
451 | goto out_size; | 447 | goto out_size; |
452 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; | 448 | recvd = xdr_read_pages(xdr, length); |
453 | recvd = xdr->buf->len - hdrlen; | ||
454 | if (unlikely(length > recvd)) | 449 | if (unlikely(length > recvd)) |
455 | goto out_cheating; | 450 | goto out_cheating; |
456 | |||
457 | xdr_read_pages(xdr, length); | ||
458 | xdr_terminate_string(xdr->buf, length); | 451 | xdr_terminate_string(xdr->buf, length); |
459 | return 0; | 452 | return 0; |
460 | out_size: | 453 | out_size: |
@@ -972,22 +965,7 @@ out_overflow: | |||
972 | */ | 965 | */ |
973 | static int decode_readdirok(struct xdr_stream *xdr) | 966 | static int decode_readdirok(struct xdr_stream *xdr) |
974 | { | 967 | { |
975 | u32 recvd, pglen; | 968 | return xdr_read_pages(xdr, xdr->buf->page_len); |
976 | size_t hdrlen; | ||
977 | |||
978 | pglen = xdr->buf->page_len; | ||
979 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; | ||
980 | recvd = xdr->buf->len - hdrlen; | ||
981 | if (unlikely(pglen > recvd)) | ||
982 | goto out_cheating; | ||
983 | out: | ||
984 | xdr_read_pages(xdr, pglen); | ||
985 | return pglen; | ||
986 | out_cheating: | ||
987 | dprintk("NFS: server cheating in readdir result: " | ||
988 | "pglen %u > recvd %u\n", pglen, recvd); | ||
989 | pglen = recvd; | ||
990 | goto out; | ||
991 | } | 969 | } |
992 | 970 | ||
993 | static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req, | 971 | static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req, |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 3187e24e8f78..f580358cad62 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -877,6 +877,17 @@ nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
877 | return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl); | 877 | return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl); |
878 | } | 878 | } |
879 | 879 | ||
880 | static int nfs3_have_delegation(struct inode *inode, fmode_t flags) | ||
881 | { | ||
882 | return 0; | ||
883 | } | ||
884 | |||
885 | static int nfs3_return_delegation(struct inode *inode) | ||
886 | { | ||
887 | nfs_wb_all(inode); | ||
888 | return 0; | ||
889 | } | ||
890 | |||
880 | const struct nfs_rpc_ops nfs_v3_clientops = { | 891 | const struct nfs_rpc_ops nfs_v3_clientops = { |
881 | .version = 3, /* protocol version */ | 892 | .version = 3, /* protocol version */ |
882 | .dentry_ops = &nfs_dentry_operations, | 893 | .dentry_ops = &nfs_dentry_operations, |
@@ -910,9 +921,11 @@ const struct nfs_rpc_ops nfs_v3_clientops = { | |||
910 | .pathconf = nfs3_proc_pathconf, | 921 | .pathconf = nfs3_proc_pathconf, |
911 | .decode_dirent = nfs3_decode_dirent, | 922 | .decode_dirent = nfs3_decode_dirent, |
912 | .read_setup = nfs3_proc_read_setup, | 923 | .read_setup = nfs3_proc_read_setup, |
924 | .read_pageio_init = nfs_pageio_init_read, | ||
913 | .read_rpc_prepare = nfs3_proc_read_rpc_prepare, | 925 | .read_rpc_prepare = nfs3_proc_read_rpc_prepare, |
914 | .read_done = nfs3_read_done, | 926 | .read_done = nfs3_read_done, |
915 | .write_setup = nfs3_proc_write_setup, | 927 | .write_setup = nfs3_proc_write_setup, |
928 | .write_pageio_init = nfs_pageio_init_write, | ||
916 | .write_rpc_prepare = nfs3_proc_write_rpc_prepare, | 929 | .write_rpc_prepare = nfs3_proc_write_rpc_prepare, |
917 | .write_done = nfs3_write_done, | 930 | .write_done = nfs3_write_done, |
918 | .commit_setup = nfs3_proc_commit_setup, | 931 | .commit_setup = nfs3_proc_commit_setup, |
@@ -921,5 +934,9 @@ const struct nfs_rpc_ops nfs_v3_clientops = { | |||
921 | .lock = nfs3_proc_lock, | 934 | .lock = nfs3_proc_lock, |
922 | .clear_acl_cache = nfs3_forget_cached_acls, | 935 | .clear_acl_cache = nfs3_forget_cached_acls, |
923 | .close_context = nfs_close_context, | 936 | .close_context = nfs_close_context, |
937 | .have_delegation = nfs3_have_delegation, | ||
938 | .return_delegation = nfs3_return_delegation, | ||
939 | .alloc_client = nfs_alloc_client, | ||
924 | .init_client = nfs_init_client, | 940 | .init_client = nfs_init_client, |
941 | .free_client = nfs_free_client, | ||
925 | }; | 942 | }; |
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 902de489ec9b..6cbe89400dfc 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
@@ -246,7 +246,6 @@ static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages, | |||
246 | static int decode_nfspath3(struct xdr_stream *xdr) | 246 | static int decode_nfspath3(struct xdr_stream *xdr) |
247 | { | 247 | { |
248 | u32 recvd, count; | 248 | u32 recvd, count; |
249 | size_t hdrlen; | ||
250 | __be32 *p; | 249 | __be32 *p; |
251 | 250 | ||
252 | p = xdr_inline_decode(xdr, 4); | 251 | p = xdr_inline_decode(xdr, 4); |
@@ -255,12 +254,9 @@ static int decode_nfspath3(struct xdr_stream *xdr) | |||
255 | count = be32_to_cpup(p); | 254 | count = be32_to_cpup(p); |
256 | if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN)) | 255 | if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN)) |
257 | goto out_nametoolong; | 256 | goto out_nametoolong; |
258 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; | 257 | recvd = xdr_read_pages(xdr, count); |
259 | recvd = xdr->buf->len - hdrlen; | ||
260 | if (unlikely(count > recvd)) | 258 | if (unlikely(count > recvd)) |
261 | goto out_cheating; | 259 | goto out_cheating; |
262 | |||
263 | xdr_read_pages(xdr, count); | ||
264 | xdr_terminate_string(xdr->buf, count); | 260 | xdr_terminate_string(xdr->buf, count); |
265 | return 0; | 261 | return 0; |
266 | 262 | ||
@@ -329,14 +325,14 @@ static void encode_createverf3(struct xdr_stream *xdr, const __be32 *verifier) | |||
329 | memcpy(p, verifier, NFS3_CREATEVERFSIZE); | 325 | memcpy(p, verifier, NFS3_CREATEVERFSIZE); |
330 | } | 326 | } |
331 | 327 | ||
332 | static int decode_writeverf3(struct xdr_stream *xdr, __be32 *verifier) | 328 | static int decode_writeverf3(struct xdr_stream *xdr, struct nfs_write_verifier *verifier) |
333 | { | 329 | { |
334 | __be32 *p; | 330 | __be32 *p; |
335 | 331 | ||
336 | p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE); | 332 | p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE); |
337 | if (unlikely(p == NULL)) | 333 | if (unlikely(p == NULL)) |
338 | goto out_overflow; | 334 | goto out_overflow; |
339 | memcpy(verifier, p, NFS3_WRITEVERFSIZE); | 335 | memcpy(verifier->data, p, NFS3_WRITEVERFSIZE); |
340 | return 0; | 336 | return 0; |
341 | out_overflow: | 337 | out_overflow: |
342 | print_overflow_msg(__func__, xdr); | 338 | print_overflow_msg(__func__, xdr); |
@@ -1587,7 +1583,6 @@ static int decode_read3resok(struct xdr_stream *xdr, | |||
1587 | struct nfs_readres *result) | 1583 | struct nfs_readres *result) |
1588 | { | 1584 | { |
1589 | u32 eof, count, ocount, recvd; | 1585 | u32 eof, count, ocount, recvd; |
1590 | size_t hdrlen; | ||
1591 | __be32 *p; | 1586 | __be32 *p; |
1592 | 1587 | ||
1593 | p = xdr_inline_decode(xdr, 4 + 4 + 4); | 1588 | p = xdr_inline_decode(xdr, 4 + 4 + 4); |
@@ -1598,13 +1593,10 @@ static int decode_read3resok(struct xdr_stream *xdr, | |||
1598 | ocount = be32_to_cpup(p++); | 1593 | ocount = be32_to_cpup(p++); |
1599 | if (unlikely(ocount != count)) | 1594 | if (unlikely(ocount != count)) |
1600 | goto out_mismatch; | 1595 | goto out_mismatch; |
1601 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; | 1596 | recvd = xdr_read_pages(xdr, count); |
1602 | recvd = xdr->buf->len - hdrlen; | ||
1603 | if (unlikely(count > recvd)) | 1597 | if (unlikely(count > recvd)) |
1604 | goto out_cheating; | 1598 | goto out_cheating; |
1605 | |||
1606 | out: | 1599 | out: |
1607 | xdr_read_pages(xdr, count); | ||
1608 | result->eof = eof; | 1600 | result->eof = eof; |
1609 | result->count = count; | 1601 | result->count = count; |
1610 | return count; | 1602 | return count; |
@@ -1676,20 +1668,22 @@ static int decode_write3resok(struct xdr_stream *xdr, | |||
1676 | { | 1668 | { |
1677 | __be32 *p; | 1669 | __be32 *p; |
1678 | 1670 | ||
1679 | p = xdr_inline_decode(xdr, 4 + 4 + NFS3_WRITEVERFSIZE); | 1671 | p = xdr_inline_decode(xdr, 4 + 4); |
1680 | if (unlikely(p == NULL)) | 1672 | if (unlikely(p == NULL)) |
1681 | goto out_overflow; | 1673 | goto out_overflow; |
1682 | result->count = be32_to_cpup(p++); | 1674 | result->count = be32_to_cpup(p++); |
1683 | result->verf->committed = be32_to_cpup(p++); | 1675 | result->verf->committed = be32_to_cpup(p++); |
1684 | if (unlikely(result->verf->committed > NFS_FILE_SYNC)) | 1676 | if (unlikely(result->verf->committed > NFS_FILE_SYNC)) |
1685 | goto out_badvalue; | 1677 | goto out_badvalue; |
1686 | memcpy(result->verf->verifier, p, NFS3_WRITEVERFSIZE); | 1678 | if (decode_writeverf3(xdr, &result->verf->verifier)) |
1679 | goto out_eio; | ||
1687 | return result->count; | 1680 | return result->count; |
1688 | out_badvalue: | 1681 | out_badvalue: |
1689 | dprintk("NFS: bad stable_how value: %u\n", result->verf->committed); | 1682 | dprintk("NFS: bad stable_how value: %u\n", result->verf->committed); |
1690 | return -EIO; | 1683 | return -EIO; |
1691 | out_overflow: | 1684 | out_overflow: |
1692 | print_overflow_msg(__func__, xdr); | 1685 | print_overflow_msg(__func__, xdr); |
1686 | out_eio: | ||
1693 | return -EIO; | 1687 | return -EIO; |
1694 | } | 1688 | } |
1695 | 1689 | ||
@@ -2039,22 +2033,7 @@ out_truncated: | |||
2039 | */ | 2033 | */ |
2040 | static int decode_dirlist3(struct xdr_stream *xdr) | 2034 | static int decode_dirlist3(struct xdr_stream *xdr) |
2041 | { | 2035 | { |
2042 | u32 recvd, pglen; | 2036 | return xdr_read_pages(xdr, xdr->buf->page_len); |
2043 | size_t hdrlen; | ||
2044 | |||
2045 | pglen = xdr->buf->page_len; | ||
2046 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; | ||
2047 | recvd = xdr->buf->len - hdrlen; | ||
2048 | if (unlikely(pglen > recvd)) | ||
2049 | goto out_cheating; | ||
2050 | out: | ||
2051 | xdr_read_pages(xdr, pglen); | ||
2052 | return pglen; | ||
2053 | out_cheating: | ||
2054 | dprintk("NFS: server cheating in readdir result: " | ||
2055 | "pglen %u > recvd %u\n", pglen, recvd); | ||
2056 | pglen = recvd; | ||
2057 | goto out; | ||
2058 | } | 2037 | } |
2059 | 2038 | ||
2060 | static int decode_readdir3resok(struct xdr_stream *xdr, | 2039 | static int decode_readdir3resok(struct xdr_stream *xdr, |
@@ -2337,7 +2316,7 @@ static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req, | |||
2337 | goto out; | 2316 | goto out; |
2338 | if (status != NFS3_OK) | 2317 | if (status != NFS3_OK) |
2339 | goto out_status; | 2318 | goto out_status; |
2340 | error = decode_writeverf3(xdr, result->verf->verifier); | 2319 | error = decode_writeverf3(xdr, &result->verf->verifier); |
2341 | out: | 2320 | out: |
2342 | return error; | 2321 | return error; |
2343 | out_status: | 2322 | out_status: |
@@ -2364,7 +2343,7 @@ static inline int decode_getacl3resok(struct xdr_stream *xdr, | |||
2364 | if (result->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) | 2343 | if (result->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) |
2365 | goto out; | 2344 | goto out; |
2366 | 2345 | ||
2367 | hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; | 2346 | hdrlen = xdr_stream_pos(xdr); |
2368 | 2347 | ||
2369 | acl = NULL; | 2348 | acl = NULL; |
2370 | if (result->mask & NFS_ACL) | 2349 | if (result->mask & NFS_ACL) |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index cc5900ac61b5..3696ca7f5f4d 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -202,6 +202,9 @@ struct nfs4_state_maintenance_ops { | |||
202 | extern const struct dentry_operations nfs4_dentry_operations; | 202 | extern const struct dentry_operations nfs4_dentry_operations; |
203 | extern const struct inode_operations nfs4_dir_inode_operations; | 203 | extern const struct inode_operations nfs4_dir_inode_operations; |
204 | 204 | ||
205 | /* write.c */ | ||
206 | int nfs4_write_inode(struct inode *, struct writeback_control *); | ||
207 | |||
205 | /* nfs4namespace.c */ | 208 | /* nfs4namespace.c */ |
206 | rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *); | 209 | rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *); |
207 | struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *); | 210 | struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *); |
@@ -301,6 +304,10 @@ extern const u32 nfs4_pathconf_bitmap[2]; | |||
301 | extern const u32 nfs4_fsinfo_bitmap[3]; | 304 | extern const u32 nfs4_fsinfo_bitmap[3]; |
302 | extern const u32 nfs4_fs_locations_bitmap[2]; | 305 | extern const u32 nfs4_fs_locations_bitmap[2]; |
303 | 306 | ||
307 | void nfs4_free_client(struct nfs_client *); | ||
308 | |||
309 | struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *); | ||
310 | |||
304 | /* nfs4renewd.c */ | 311 | /* nfs4renewd.c */ |
305 | extern void nfs4_schedule_state_renewal(struct nfs_client *); | 312 | extern void nfs4_schedule_state_renewal(struct nfs_client *); |
306 | extern void nfs4_renewd_prepare_shutdown(struct nfs_server *); | 313 | extern void nfs4_renewd_prepare_shutdown(struct nfs_server *); |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index e1340293872c..85b70639921b 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -351,9 +351,9 @@ static void prepare_to_resend_writes(struct nfs_commit_data *data) | |||
351 | struct nfs_page *first = nfs_list_entry(data->pages.next); | 351 | struct nfs_page *first = nfs_list_entry(data->pages.next); |
352 | 352 | ||
353 | data->task.tk_status = 0; | 353 | data->task.tk_status = 0; |
354 | memcpy(data->verf.verifier, first->wb_verf.verifier, | 354 | memcpy(&data->verf.verifier, &first->wb_verf, |
355 | sizeof(first->wb_verf.verifier)); | 355 | sizeof(data->verf.verifier)); |
356 | data->verf.verifier[0]++; /* ensure verifier mismatch */ | 356 | data->verf.verifier.data[0]++; /* ensure verifier mismatch */ |
357 | } | 357 | } |
358 | 358 | ||
359 | static int filelayout_commit_done_cb(struct rpc_task *task, | 359 | static int filelayout_commit_done_cb(struct rpc_task *task, |
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index a1fab8da7f03..f81231f30d94 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c | |||
@@ -728,7 +728,7 @@ get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_fla | |||
728 | pdev->layout_type = LAYOUT_NFSV4_1_FILES; | 728 | pdev->layout_type = LAYOUT_NFSV4_1_FILES; |
729 | pdev->pages = pages; | 729 | pdev->pages = pages; |
730 | pdev->pgbase = 0; | 730 | pdev->pgbase = 0; |
731 | pdev->pglen = PAGE_SIZE * max_pages; | 731 | pdev->pglen = max_resp_sz; |
732 | pdev->mincount = 0; | 732 | pdev->mincount = 0; |
733 | 733 | ||
734 | rc = nfs4_proc_getdeviceinfo(server, pdev); | 734 | rc = nfs4_proc_getdeviceinfo(server, pdev); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index c157b2089b47..006e98da730a 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -294,8 +294,8 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc | |||
294 | case 0: | 294 | case 0: |
295 | return 0; | 295 | return 0; |
296 | case -NFS4ERR_OPENMODE: | 296 | case -NFS4ERR_OPENMODE: |
297 | if (inode && nfs_have_delegation(inode, FMODE_READ)) { | 297 | if (inode && nfs4_have_delegation(inode, FMODE_READ)) { |
298 | nfs_inode_return_delegation(inode); | 298 | nfs4_inode_return_delegation(inode); |
299 | exception->retry = 1; | 299 | exception->retry = 1; |
300 | return 0; | 300 | return 0; |
301 | } | 301 | } |
@@ -1065,7 +1065,7 @@ static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmo | |||
1065 | return; | 1065 | return; |
1066 | } | 1066 | } |
1067 | rcu_read_unlock(); | 1067 | rcu_read_unlock(); |
1068 | nfs_inode_return_delegation(inode); | 1068 | nfs4_inode_return_delegation(inode); |
1069 | } | 1069 | } |
1070 | 1070 | ||
1071 | static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) | 1071 | static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) |
@@ -2766,9 +2766,7 @@ static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) | |||
2766 | * | 2766 | * |
2767 | * In the case of WRITE, we also want to put the GETATTR after | 2767 | * In the case of WRITE, we also want to put the GETATTR after |
2768 | * the operation -- in this case because we want to make sure | 2768 | * the operation -- in this case because we want to make sure |
2769 | * we get the post-operation mtime and size. This means that | 2769 | * we get the post-operation mtime and size. |
2770 | * we can't use xdr_encode_pages() as written: we need a variant | ||
2771 | * of it which would leave room in the 'tail' iovec. | ||
2772 | * | 2770 | * |
2773 | * Both of these changes to the XDR layer would in fact be quite | 2771 | * Both of these changes to the XDR layer would in fact be quite |
2774 | * minor, but I decided to leave them for a subsequent patch. | 2772 | * minor, but I decided to leave them for a subsequent patch. |
@@ -2821,7 +2819,9 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
2821 | return PTR_ERR(ctx); | 2819 | return PTR_ERR(ctx); |
2822 | 2820 | ||
2823 | sattr->ia_mode &= ~current_umask(); | 2821 | sattr->ia_mode &= ~current_umask(); |
2824 | state = nfs4_do_open(dir, dentry, ctx->mode, flags, sattr, ctx->cred, NULL); | 2822 | state = nfs4_do_open(dir, dentry, ctx->mode, |
2823 | flags, sattr, ctx->cred, | ||
2824 | &ctx->mdsthreshold); | ||
2825 | d_drop(dentry); | 2825 | d_drop(dentry); |
2826 | if (IS_ERR(state)) { | 2826 | if (IS_ERR(state)) { |
2827 | status = PTR_ERR(state); | 2827 | status = PTR_ERR(state); |
@@ -3315,8 +3315,14 @@ static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, str | |||
3315 | 3315 | ||
3316 | static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) | 3316 | static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) |
3317 | { | 3317 | { |
3318 | int error; | ||
3319 | |||
3318 | nfs_fattr_init(fsinfo->fattr); | 3320 | nfs_fattr_init(fsinfo->fattr); |
3319 | return nfs4_do_fsinfo(server, fhandle, fsinfo); | 3321 | error = nfs4_do_fsinfo(server, fhandle, fsinfo); |
3322 | if (error == 0) | ||
3323 | set_pnfs_layoutdriver(server, fhandle, fsinfo->layouttype); | ||
3324 | |||
3325 | return error; | ||
3320 | } | 3326 | } |
3321 | 3327 | ||
3322 | static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | 3328 | static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, |
@@ -3443,7 +3449,7 @@ bool nfs4_write_need_cache_consistency_data(const struct nfs_write_data *data) | |||
3443 | /* Otherwise, request attributes if and only if we don't hold | 3449 | /* Otherwise, request attributes if and only if we don't hold |
3444 | * a delegation | 3450 | * a delegation |
3445 | */ | 3451 | */ |
3446 | return nfs_have_delegation(hdr->inode, FMODE_READ) == 0; | 3452 | return nfs4_have_delegation(hdr->inode, FMODE_READ) == 0; |
3447 | } | 3453 | } |
3448 | 3454 | ||
3449 | static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) | 3455 | static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) |
@@ -3847,7 +3853,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl | |||
3847 | i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase); | 3853 | i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase); |
3848 | if (i < 0) | 3854 | if (i < 0) |
3849 | return i; | 3855 | return i; |
3850 | nfs_inode_return_delegation(inode); | 3856 | nfs4_inode_return_delegation(inode); |
3851 | ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); | 3857 | ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
3852 | 3858 | ||
3853 | /* | 3859 | /* |
@@ -6769,9 +6775,11 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
6769 | .set_capabilities = nfs4_server_capabilities, | 6775 | .set_capabilities = nfs4_server_capabilities, |
6770 | .decode_dirent = nfs4_decode_dirent, | 6776 | .decode_dirent = nfs4_decode_dirent, |
6771 | .read_setup = nfs4_proc_read_setup, | 6777 | .read_setup = nfs4_proc_read_setup, |
6778 | .read_pageio_init = pnfs_pageio_init_read, | ||
6772 | .read_rpc_prepare = nfs4_proc_read_rpc_prepare, | 6779 | .read_rpc_prepare = nfs4_proc_read_rpc_prepare, |
6773 | .read_done = nfs4_read_done, | 6780 | .read_done = nfs4_read_done, |
6774 | .write_setup = nfs4_proc_write_setup, | 6781 | .write_setup = nfs4_proc_write_setup, |
6782 | .write_pageio_init = pnfs_pageio_init_write, | ||
6775 | .write_rpc_prepare = nfs4_proc_write_rpc_prepare, | 6783 | .write_rpc_prepare = nfs4_proc_write_rpc_prepare, |
6776 | .write_done = nfs4_write_done, | 6784 | .write_done = nfs4_write_done, |
6777 | .commit_setup = nfs4_proc_commit_setup, | 6785 | .commit_setup = nfs4_proc_commit_setup, |
@@ -6781,7 +6789,11 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
6781 | .clear_acl_cache = nfs4_zap_acl_attr, | 6789 | .clear_acl_cache = nfs4_zap_acl_attr, |
6782 | .close_context = nfs4_close_context, | 6790 | .close_context = nfs4_close_context, |
6783 | .open_context = nfs4_atomic_open, | 6791 | .open_context = nfs4_atomic_open, |
6792 | .have_delegation = nfs4_have_delegation, | ||
6793 | .return_delegation = nfs4_inode_return_delegation, | ||
6794 | .alloc_client = nfs4_alloc_client, | ||
6784 | .init_client = nfs4_init_client, | 6795 | .init_client = nfs4_init_client, |
6796 | .free_client = nfs4_free_client, | ||
6785 | }; | 6797 | }; |
6786 | 6798 | ||
6787 | static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { | 6799 | static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index f38300e9f171..1cfc4603fd9a 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -1642,7 +1642,7 @@ static int nfs4_handle_reclaim_lease_error(struct nfs_client *clp, int status) | |||
1642 | return 0; | 1642 | return 0; |
1643 | } | 1643 | } |
1644 | 1644 | ||
1645 | static int nfs4_reclaim_lease(struct nfs_client *clp) | 1645 | static int nfs4_establish_lease(struct nfs_client *clp) |
1646 | { | 1646 | { |
1647 | struct rpc_cred *cred; | 1647 | struct rpc_cred *cred; |
1648 | const struct nfs4_state_recovery_ops *ops = | 1648 | const struct nfs4_state_recovery_ops *ops = |
@@ -1655,7 +1655,37 @@ static int nfs4_reclaim_lease(struct nfs_client *clp) | |||
1655 | status = ops->establish_clid(clp, cred); | 1655 | status = ops->establish_clid(clp, cred); |
1656 | put_rpccred(cred); | 1656 | put_rpccred(cred); |
1657 | if (status != 0) | 1657 | if (status != 0) |
1658 | return status; | ||
1659 | pnfs_destroy_all_layouts(clp); | ||
1660 | return 0; | ||
1661 | } | ||
1662 | |||
1663 | static int nfs4_reclaim_lease(struct nfs_client *clp) | ||
1664 | { | ||
1665 | int status; | ||
1666 | |||
1667 | status = nfs4_establish_lease(clp); | ||
1668 | if (status < 0) | ||
1669 | return nfs4_handle_reclaim_lease_error(clp, status); | ||
1670 | if (test_and_clear_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state)) | ||
1671 | nfs4_state_start_reclaim_nograce(clp); | ||
1672 | if (!test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) | ||
1673 | set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state); | ||
1674 | clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); | ||
1675 | clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | ||
1676 | return 0; | ||
1677 | } | ||
1678 | |||
1679 | static int nfs4_purge_lease(struct nfs_client *clp) | ||
1680 | { | ||
1681 | int status; | ||
1682 | |||
1683 | status = nfs4_establish_lease(clp); | ||
1684 | if (status < 0) | ||
1658 | return nfs4_handle_reclaim_lease_error(clp, status); | 1685 | return nfs4_handle_reclaim_lease_error(clp, status); |
1686 | clear_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state); | ||
1687 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | ||
1688 | nfs4_state_start_reclaim_nograce(clp); | ||
1659 | return 0; | 1689 | return 0; |
1660 | } | 1690 | } |
1661 | 1691 | ||
@@ -1764,6 +1794,8 @@ static int nfs4_reset_session(struct nfs_client *clp) | |||
1764 | struct rpc_cred *cred; | 1794 | struct rpc_cred *cred; |
1765 | int status; | 1795 | int status; |
1766 | 1796 | ||
1797 | if (!nfs4_has_session(clp)) | ||
1798 | return 0; | ||
1767 | nfs4_begin_drain_session(clp); | 1799 | nfs4_begin_drain_session(clp); |
1768 | cred = nfs4_get_exchange_id_cred(clp); | 1800 | cred = nfs4_get_exchange_id_cred(clp); |
1769 | status = nfs4_proc_destroy_session(clp->cl_session, cred); | 1801 | status = nfs4_proc_destroy_session(clp->cl_session, cred); |
@@ -1792,12 +1824,14 @@ out: | |||
1792 | 1824 | ||
1793 | static int nfs4_recall_slot(struct nfs_client *clp) | 1825 | static int nfs4_recall_slot(struct nfs_client *clp) |
1794 | { | 1826 | { |
1795 | struct nfs4_slot_table *fc_tbl = &clp->cl_session->fc_slot_table; | 1827 | struct nfs4_slot_table *fc_tbl; |
1796 | struct nfs4_channel_attrs *fc_attrs = &clp->cl_session->fc_attrs; | ||
1797 | struct nfs4_slot *new, *old; | 1828 | struct nfs4_slot *new, *old; |
1798 | int i; | 1829 | int i; |
1799 | 1830 | ||
1831 | if (!nfs4_has_session(clp)) | ||
1832 | return 0; | ||
1800 | nfs4_begin_drain_session(clp); | 1833 | nfs4_begin_drain_session(clp); |
1834 | fc_tbl = &clp->cl_session->fc_slot_table; | ||
1801 | new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot), | 1835 | new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot), |
1802 | GFP_NOFS); | 1836 | GFP_NOFS); |
1803 | if (!new) | 1837 | if (!new) |
@@ -1810,11 +1844,10 @@ static int nfs4_recall_slot(struct nfs_client *clp) | |||
1810 | fc_tbl->slots = new; | 1844 | fc_tbl->slots = new; |
1811 | fc_tbl->max_slots = fc_tbl->target_max_slots; | 1845 | fc_tbl->max_slots = fc_tbl->target_max_slots; |
1812 | fc_tbl->target_max_slots = 0; | 1846 | fc_tbl->target_max_slots = 0; |
1813 | fc_attrs->max_reqs = fc_tbl->max_slots; | 1847 | clp->cl_session->fc_attrs.max_reqs = fc_tbl->max_slots; |
1814 | spin_unlock(&fc_tbl->slot_tbl_lock); | 1848 | spin_unlock(&fc_tbl->slot_tbl_lock); |
1815 | 1849 | ||
1816 | kfree(old); | 1850 | kfree(old); |
1817 | nfs4_end_drain_session(clp); | ||
1818 | return 0; | 1851 | return 0; |
1819 | } | 1852 | } |
1820 | 1853 | ||
@@ -1823,6 +1856,8 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp) | |||
1823 | struct rpc_cred *cred; | 1856 | struct rpc_cred *cred; |
1824 | int ret; | 1857 | int ret; |
1825 | 1858 | ||
1859 | if (!nfs4_has_session(clp)) | ||
1860 | return 0; | ||
1826 | nfs4_begin_drain_session(clp); | 1861 | nfs4_begin_drain_session(clp); |
1827 | cred = nfs4_get_exchange_id_cred(clp); | 1862 | cred = nfs4_get_exchange_id_cred(clp); |
1828 | ret = nfs4_proc_bind_conn_to_session(clp, cred); | 1863 | ret = nfs4_proc_bind_conn_to_session(clp, cred); |
@@ -1857,37 +1892,29 @@ static int nfs4_bind_conn_to_session(struct nfs_client *clp) | |||
1857 | static void nfs4_state_manager(struct nfs_client *clp) | 1892 | static void nfs4_state_manager(struct nfs_client *clp) |
1858 | { | 1893 | { |
1859 | int status = 0; | 1894 | int status = 0; |
1895 | const char *section = "", *section_sep = ""; | ||
1860 | 1896 | ||
1861 | /* Ensure exclusive access to NFSv4 state */ | 1897 | /* Ensure exclusive access to NFSv4 state */ |
1862 | do { | 1898 | do { |
1863 | if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) { | 1899 | if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) { |
1864 | status = nfs4_reclaim_lease(clp); | 1900 | section = "purge state"; |
1901 | status = nfs4_purge_lease(clp); | ||
1865 | if (status < 0) | 1902 | if (status < 0) |
1866 | goto out_error; | 1903 | goto out_error; |
1867 | clear_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state); | 1904 | continue; |
1868 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | ||
1869 | } | 1905 | } |
1870 | 1906 | ||
1871 | if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { | 1907 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { |
1908 | section = "lease expired"; | ||
1872 | /* We're going to have to re-establish a clientid */ | 1909 | /* We're going to have to re-establish a clientid */ |
1873 | status = nfs4_reclaim_lease(clp); | 1910 | status = nfs4_reclaim_lease(clp); |
1874 | if (status < 0) | 1911 | if (status < 0) |
1875 | goto out_error; | 1912 | goto out_error; |
1876 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) | 1913 | continue; |
1877 | continue; | ||
1878 | clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); | ||
1879 | |||
1880 | if (test_and_clear_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, | ||
1881 | &clp->cl_state)) | ||
1882 | nfs4_state_start_reclaim_nograce(clp); | ||
1883 | else | ||
1884 | set_bit(NFS4CLNT_RECLAIM_REBOOT, | ||
1885 | &clp->cl_state); | ||
1886 | |||
1887 | pnfs_destroy_all_layouts(clp); | ||
1888 | } | 1914 | } |
1889 | 1915 | ||
1890 | if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { | 1916 | if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { |
1917 | section = "check lease"; | ||
1891 | status = nfs4_check_lease(clp); | 1918 | status = nfs4_check_lease(clp); |
1892 | if (status < 0) | 1919 | if (status < 0) |
1893 | goto out_error; | 1920 | goto out_error; |
@@ -1896,8 +1923,8 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1896 | } | 1923 | } |
1897 | 1924 | ||
1898 | /* Initialize or reset the session */ | 1925 | /* Initialize or reset the session */ |
1899 | if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) | 1926 | if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) { |
1900 | && nfs4_has_session(clp)) { | 1927 | section = "reset session"; |
1901 | status = nfs4_reset_session(clp); | 1928 | status = nfs4_reset_session(clp); |
1902 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) | 1929 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) |
1903 | continue; | 1930 | continue; |
@@ -1907,15 +1934,26 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1907 | 1934 | ||
1908 | /* Send BIND_CONN_TO_SESSION */ | 1935 | /* Send BIND_CONN_TO_SESSION */ |
1909 | if (test_and_clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, | 1936 | if (test_and_clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, |
1910 | &clp->cl_state) && nfs4_has_session(clp)) { | 1937 | &clp->cl_state)) { |
1938 | section = "bind conn to session"; | ||
1911 | status = nfs4_bind_conn_to_session(clp); | 1939 | status = nfs4_bind_conn_to_session(clp); |
1912 | if (status < 0) | 1940 | if (status < 0) |
1913 | goto out_error; | 1941 | goto out_error; |
1914 | continue; | 1942 | continue; |
1915 | } | 1943 | } |
1916 | 1944 | ||
1945 | /* Recall session slots */ | ||
1946 | if (test_and_clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state)) { | ||
1947 | section = "recall slot"; | ||
1948 | status = nfs4_recall_slot(clp); | ||
1949 | if (status < 0) | ||
1950 | goto out_error; | ||
1951 | continue; | ||
1952 | } | ||
1953 | |||
1917 | /* First recover reboot state... */ | 1954 | /* First recover reboot state... */ |
1918 | if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { | 1955 | if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { |
1956 | section = "reclaim reboot"; | ||
1919 | status = nfs4_do_reclaim(clp, | 1957 | status = nfs4_do_reclaim(clp, |
1920 | clp->cl_mvops->reboot_recovery_ops); | 1958 | clp->cl_mvops->reboot_recovery_ops); |
1921 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || | 1959 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || |
@@ -1930,6 +1968,7 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1930 | 1968 | ||
1931 | /* Now recover expired state... */ | 1969 | /* Now recover expired state... */ |
1932 | if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { | 1970 | if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { |
1971 | section = "reclaim nograce"; | ||
1933 | status = nfs4_do_reclaim(clp, | 1972 | status = nfs4_do_reclaim(clp, |
1934 | clp->cl_mvops->nograce_recovery_ops); | 1973 | clp->cl_mvops->nograce_recovery_ops); |
1935 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || | 1974 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || |
@@ -1945,15 +1984,6 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1945 | nfs_client_return_marked_delegations(clp); | 1984 | nfs_client_return_marked_delegations(clp); |
1946 | continue; | 1985 | continue; |
1947 | } | 1986 | } |
1948 | /* Recall session slots */ | ||
1949 | if (test_and_clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state) | ||
1950 | && nfs4_has_session(clp)) { | ||
1951 | status = nfs4_recall_slot(clp); | ||
1952 | if (status < 0) | ||
1953 | goto out_error; | ||
1954 | continue; | ||
1955 | } | ||
1956 | |||
1957 | 1987 | ||
1958 | nfs4_clear_state_manager_bit(clp); | 1988 | nfs4_clear_state_manager_bit(clp); |
1959 | /* Did we race with an attempt to give us more work? */ | 1989 | /* Did we race with an attempt to give us more work? */ |
@@ -1964,8 +1994,11 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1964 | } while (atomic_read(&clp->cl_count) > 1); | 1994 | } while (atomic_read(&clp->cl_count) > 1); |
1965 | return; | 1995 | return; |
1966 | out_error: | 1996 | out_error: |
1967 | pr_warn_ratelimited("NFS: state manager failed on NFSv4 server %s" | 1997 | if (strlen(section)) |
1968 | " with error %d\n", clp->cl_hostname, -status); | 1998 | section_sep = ": "; |
1999 | pr_warn_ratelimited("NFS: state manager%s%s failed on NFSv4 server %s" | ||
2000 | " with error %d\n", section_sep, section, | ||
2001 | clp->cl_hostname, -status); | ||
1969 | nfs4_end_drain_session(clp); | 2002 | nfs4_end_drain_session(clp); |
1970 | nfs4_clear_state_manager_bit(clp); | 2003 | nfs4_clear_state_manager_bit(clp); |
1971 | } | 2004 | } |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 18fae29b0301..610ebccbde5d 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -3078,7 +3078,7 @@ out_overflow: | |||
3078 | return -EIO; | 3078 | return -EIO; |
3079 | } | 3079 | } |
3080 | 3080 | ||
3081 | static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, __be32 **savep) | 3081 | static int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, unsigned int *savep) |
3082 | { | 3082 | { |
3083 | __be32 *p; | 3083 | __be32 *p; |
3084 | 3084 | ||
@@ -3086,7 +3086,7 @@ static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, | |||
3086 | if (unlikely(!p)) | 3086 | if (unlikely(!p)) |
3087 | goto out_overflow; | 3087 | goto out_overflow; |
3088 | *attrlen = be32_to_cpup(p); | 3088 | *attrlen = be32_to_cpup(p); |
3089 | *savep = xdr->p; | 3089 | *savep = xdr_stream_pos(xdr); |
3090 | return 0; | 3090 | return 0; |
3091 | out_overflow: | 3091 | out_overflow: |
3092 | print_overflow_msg(__func__, xdr); | 3092 | print_overflow_msg(__func__, xdr); |
@@ -4068,10 +4068,10 @@ static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, str | |||
4068 | return status; | 4068 | return status; |
4069 | } | 4069 | } |
4070 | 4070 | ||
4071 | static int verify_attr_len(struct xdr_stream *xdr, __be32 *savep, uint32_t attrlen) | 4071 | static int verify_attr_len(struct xdr_stream *xdr, unsigned int savep, uint32_t attrlen) |
4072 | { | 4072 | { |
4073 | unsigned int attrwords = XDR_QUADLEN(attrlen); | 4073 | unsigned int attrwords = XDR_QUADLEN(attrlen); |
4074 | unsigned int nwords = xdr->p - savep; | 4074 | unsigned int nwords = (xdr_stream_pos(xdr) - savep) >> 2; |
4075 | 4075 | ||
4076 | if (unlikely(attrwords != nwords)) { | 4076 | if (unlikely(attrwords != nwords)) { |
4077 | dprintk("%s: server returned incorrect attribute length: " | 4077 | dprintk("%s: server returned incorrect attribute length: " |
@@ -4158,13 +4158,18 @@ static int decode_verifier(struct xdr_stream *xdr, void *verifier) | |||
4158 | return decode_opaque_fixed(xdr, verifier, NFS4_VERIFIER_SIZE); | 4158 | return decode_opaque_fixed(xdr, verifier, NFS4_VERIFIER_SIZE); |
4159 | } | 4159 | } |
4160 | 4160 | ||
4161 | static int decode_write_verifier(struct xdr_stream *xdr, struct nfs_write_verifier *verifier) | ||
4162 | { | ||
4163 | return decode_opaque_fixed(xdr, verifier->data, NFS4_VERIFIER_SIZE); | ||
4164 | } | ||
4165 | |||
4161 | static int decode_commit(struct xdr_stream *xdr, struct nfs_commitres *res) | 4166 | static int decode_commit(struct xdr_stream *xdr, struct nfs_commitres *res) |
4162 | { | 4167 | { |
4163 | int status; | 4168 | int status; |
4164 | 4169 | ||
4165 | status = decode_op_hdr(xdr, OP_COMMIT); | 4170 | status = decode_op_hdr(xdr, OP_COMMIT); |
4166 | if (!status) | 4171 | if (!status) |
4167 | status = decode_verifier(xdr, res->verf->verifier); | 4172 | status = decode_write_verifier(xdr, &res->verf->verifier); |
4168 | return status; | 4173 | return status; |
4169 | } | 4174 | } |
4170 | 4175 | ||
@@ -4193,7 +4198,7 @@ out_overflow: | |||
4193 | 4198 | ||
4194 | static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res) | 4199 | static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res) |
4195 | { | 4200 | { |
4196 | __be32 *savep; | 4201 | unsigned int savep; |
4197 | uint32_t attrlen, bitmap[3] = {0}; | 4202 | uint32_t attrlen, bitmap[3] = {0}; |
4198 | int status; | 4203 | int status; |
4199 | 4204 | ||
@@ -4222,7 +4227,7 @@ xdr_error: | |||
4222 | 4227 | ||
4223 | static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat) | 4228 | static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat) |
4224 | { | 4229 | { |
4225 | __be32 *savep; | 4230 | unsigned int savep; |
4226 | uint32_t attrlen, bitmap[3] = {0}; | 4231 | uint32_t attrlen, bitmap[3] = {0}; |
4227 | int status; | 4232 | int status; |
4228 | 4233 | ||
@@ -4254,7 +4259,7 @@ xdr_error: | |||
4254 | 4259 | ||
4255 | static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf) | 4260 | static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf) |
4256 | { | 4261 | { |
4257 | __be32 *savep; | 4262 | unsigned int savep; |
4258 | uint32_t attrlen, bitmap[3] = {0}; | 4263 | uint32_t attrlen, bitmap[3] = {0}; |
4259 | int status; | 4264 | int status; |
4260 | 4265 | ||
@@ -4299,7 +4304,8 @@ out_overflow: | |||
4299 | static int decode_first_threshold_item4(struct xdr_stream *xdr, | 4304 | static int decode_first_threshold_item4(struct xdr_stream *xdr, |
4300 | struct nfs4_threshold *res) | 4305 | struct nfs4_threshold *res) |
4301 | { | 4306 | { |
4302 | __be32 *p, *savep; | 4307 | __be32 *p; |
4308 | unsigned int savep; | ||
4303 | uint32_t bitmap[3] = {0,}, attrlen; | 4309 | uint32_t bitmap[3] = {0,}, attrlen; |
4304 | int status; | 4310 | int status; |
4305 | 4311 | ||
@@ -4503,7 +4509,7 @@ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fat | |||
4503 | struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc, | 4509 | struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc, |
4504 | const struct nfs_server *server) | 4510 | const struct nfs_server *server) |
4505 | { | 4511 | { |
4506 | __be32 *savep; | 4512 | unsigned int savep; |
4507 | uint32_t attrlen, | 4513 | uint32_t attrlen, |
4508 | bitmap[3] = {0}; | 4514 | bitmap[3] = {0}; |
4509 | int status; | 4515 | int status; |
@@ -4615,7 +4621,7 @@ static int decode_attr_layout_blksize(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4615 | 4621 | ||
4616 | static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) | 4622 | static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) |
4617 | { | 4623 | { |
4618 | __be32 *savep; | 4624 | unsigned int savep; |
4619 | uint32_t attrlen, bitmap[3]; | 4625 | uint32_t attrlen, bitmap[3]; |
4620 | int status; | 4626 | int status; |
4621 | 4627 | ||
@@ -4920,9 +4926,8 @@ static int decode_putrootfh(struct xdr_stream *xdr) | |||
4920 | 4926 | ||
4921 | static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res) | 4927 | static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res) |
4922 | { | 4928 | { |
4923 | struct kvec *iov = req->rq_rcv_buf.head; | ||
4924 | __be32 *p; | 4929 | __be32 *p; |
4925 | uint32_t count, eof, recvd, hdrlen; | 4930 | uint32_t count, eof, recvd; |
4926 | int status; | 4931 | int status; |
4927 | 4932 | ||
4928 | status = decode_op_hdr(xdr, OP_READ); | 4933 | status = decode_op_hdr(xdr, OP_READ); |
@@ -4933,15 +4938,13 @@ static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_ | |||
4933 | goto out_overflow; | 4938 | goto out_overflow; |
4934 | eof = be32_to_cpup(p++); | 4939 | eof = be32_to_cpup(p++); |
4935 | count = be32_to_cpup(p); | 4940 | count = be32_to_cpup(p); |
4936 | hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base; | 4941 | recvd = xdr_read_pages(xdr, count); |
4937 | recvd = req->rq_rcv_buf.len - hdrlen; | ||
4938 | if (count > recvd) { | 4942 | if (count > recvd) { |
4939 | dprintk("NFS: server cheating in read reply: " | 4943 | dprintk("NFS: server cheating in read reply: " |
4940 | "count %u > recvd %u\n", count, recvd); | 4944 | "count %u > recvd %u\n", count, recvd); |
4941 | count = recvd; | 4945 | count = recvd; |
4942 | eof = 0; | 4946 | eof = 0; |
4943 | } | 4947 | } |
4944 | xdr_read_pages(xdr, count); | ||
4945 | res->eof = eof; | 4948 | res->eof = eof; |
4946 | res->count = count; | 4949 | res->count = count; |
4947 | return 0; | 4950 | return 0; |
@@ -4952,10 +4955,6 @@ out_overflow: | |||
4952 | 4955 | ||
4953 | static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir) | 4956 | static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir) |
4954 | { | 4957 | { |
4955 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; | ||
4956 | struct kvec *iov = rcvbuf->head; | ||
4957 | size_t hdrlen; | ||
4958 | u32 recvd, pglen = rcvbuf->page_len; | ||
4959 | int status; | 4958 | int status; |
4960 | __be32 verf[2]; | 4959 | __be32 verf[2]; |
4961 | 4960 | ||
@@ -4967,22 +4966,12 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n | |||
4967 | memcpy(verf, readdir->verifier.data, sizeof(verf)); | 4966 | memcpy(verf, readdir->verifier.data, sizeof(verf)); |
4968 | dprintk("%s: verifier = %08x:%08x\n", | 4967 | dprintk("%s: verifier = %08x:%08x\n", |
4969 | __func__, verf[0], verf[1]); | 4968 | __func__, verf[0], verf[1]); |
4970 | 4969 | return xdr_read_pages(xdr, xdr->buf->page_len); | |
4971 | hdrlen = (char *) xdr->p - (char *) iov->iov_base; | ||
4972 | recvd = rcvbuf->len - hdrlen; | ||
4973 | if (pglen > recvd) | ||
4974 | pglen = recvd; | ||
4975 | xdr_read_pages(xdr, pglen); | ||
4976 | |||
4977 | |||
4978 | return pglen; | ||
4979 | } | 4970 | } |
4980 | 4971 | ||
4981 | static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) | 4972 | static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) |
4982 | { | 4973 | { |
4983 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; | 4974 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; |
4984 | struct kvec *iov = rcvbuf->head; | ||
4985 | size_t hdrlen; | ||
4986 | u32 len, recvd; | 4975 | u32 len, recvd; |
4987 | __be32 *p; | 4976 | __be32 *p; |
4988 | int status; | 4977 | int status; |
@@ -5000,14 +4989,12 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) | |||
5000 | dprintk("nfs: server returned giant symlink!\n"); | 4989 | dprintk("nfs: server returned giant symlink!\n"); |
5001 | return -ENAMETOOLONG; | 4990 | return -ENAMETOOLONG; |
5002 | } | 4991 | } |
5003 | hdrlen = (char *) xdr->p - (char *) iov->iov_base; | 4992 | recvd = xdr_read_pages(xdr, len); |
5004 | recvd = req->rq_rcv_buf.len - hdrlen; | ||
5005 | if (recvd < len) { | 4993 | if (recvd < len) { |
5006 | dprintk("NFS: server cheating in readlink reply: " | 4994 | dprintk("NFS: server cheating in readlink reply: " |
5007 | "count %u > recvd %u\n", len, recvd); | 4995 | "count %u > recvd %u\n", len, recvd); |
5008 | return -EIO; | 4996 | return -EIO; |
5009 | } | 4997 | } |
5010 | xdr_read_pages(xdr, len); | ||
5011 | /* | 4998 | /* |
5012 | * The XDR encode routine has set things up so that | 4999 | * The XDR encode routine has set things up so that |
5013 | * the link text will be copied directly into the | 5000 | * the link text will be copied directly into the |
@@ -5063,10 +5050,10 @@ decode_restorefh(struct xdr_stream *xdr) | |||
5063 | static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | 5050 | static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, |
5064 | struct nfs_getaclres *res) | 5051 | struct nfs_getaclres *res) |
5065 | { | 5052 | { |
5066 | __be32 *savep, *bm_p; | 5053 | unsigned int savep; |
5054 | __be32 *bm_p; | ||
5067 | uint32_t attrlen, | 5055 | uint32_t attrlen, |
5068 | bitmap[3] = {0}; | 5056 | bitmap[3] = {0}; |
5069 | struct kvec *iov = req->rq_rcv_buf.head; | ||
5070 | int status; | 5057 | int status; |
5071 | size_t page_len = xdr->buf->page_len; | 5058 | size_t page_len = xdr->buf->page_len; |
5072 | 5059 | ||
@@ -5089,7 +5076,6 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
5089 | if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) | 5076 | if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U))) |
5090 | return -EIO; | 5077 | return -EIO; |
5091 | if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { | 5078 | if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { |
5092 | size_t hdrlen; | ||
5093 | 5079 | ||
5094 | /* The bitmap (xdr len + bitmaps) and the attr xdr len words | 5080 | /* The bitmap (xdr len + bitmaps) and the attr xdr len words |
5095 | * are stored with the acl data to handle the problem of | 5081 | * are stored with the acl data to handle the problem of |
@@ -5098,7 +5084,6 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
5098 | 5084 | ||
5099 | /* We ignore &savep and don't do consistency checks on | 5085 | /* We ignore &savep and don't do consistency checks on |
5100 | * the attr length. Let userspace figure it out.... */ | 5086 | * the attr length. Let userspace figure it out.... */ |
5101 | hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base; | ||
5102 | attrlen += res->acl_data_offset; | 5087 | attrlen += res->acl_data_offset; |
5103 | if (attrlen > page_len) { | 5088 | if (attrlen > page_len) { |
5104 | if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { | 5089 | if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { |
@@ -5212,13 +5197,12 @@ static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res) | |||
5212 | if (status) | 5197 | if (status) |
5213 | return status; | 5198 | return status; |
5214 | 5199 | ||
5215 | p = xdr_inline_decode(xdr, 16); | 5200 | p = xdr_inline_decode(xdr, 8); |
5216 | if (unlikely(!p)) | 5201 | if (unlikely(!p)) |
5217 | goto out_overflow; | 5202 | goto out_overflow; |
5218 | res->count = be32_to_cpup(p++); | 5203 | res->count = be32_to_cpup(p++); |
5219 | res->verf->committed = be32_to_cpup(p++); | 5204 | res->verf->committed = be32_to_cpup(p++); |
5220 | memcpy(res->verf->verifier, p, NFS4_VERIFIER_SIZE); | 5205 | return decode_write_verifier(xdr, &res->verf->verifier); |
5221 | return 0; | ||
5222 | out_overflow: | 5206 | out_overflow: |
5223 | print_overflow_msg(__func__, xdr); | 5207 | print_overflow_msg(__func__, xdr); |
5224 | return -EIO; | 5208 | return -EIO; |
@@ -5599,7 +5583,7 @@ static int decode_getdevicelist(struct xdr_stream *xdr, | |||
5599 | { | 5583 | { |
5600 | __be32 *p; | 5584 | __be32 *p; |
5601 | int status, i; | 5585 | int status, i; |
5602 | struct nfs_writeverf verftemp; | 5586 | nfs4_verifier verftemp; |
5603 | 5587 | ||
5604 | status = decode_op_hdr(xdr, OP_GETDEVICELIST); | 5588 | status = decode_op_hdr(xdr, OP_GETDEVICELIST); |
5605 | if (status) | 5589 | if (status) |
@@ -5613,7 +5597,7 @@ static int decode_getdevicelist(struct xdr_stream *xdr, | |||
5613 | p += 2; | 5597 | p += 2; |
5614 | 5598 | ||
5615 | /* Read verifier */ | 5599 | /* Read verifier */ |
5616 | p = xdr_decode_opaque_fixed(p, verftemp.verifier, NFS4_VERIFIER_SIZE); | 5600 | p = xdr_decode_opaque_fixed(p, verftemp.data, NFS4_VERIFIER_SIZE); |
5617 | 5601 | ||
5618 | res->num_devs = be32_to_cpup(p); | 5602 | res->num_devs = be32_to_cpup(p); |
5619 | 5603 | ||
@@ -5707,9 +5691,7 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
5707 | __be32 *p; | 5691 | __be32 *p; |
5708 | int status; | 5692 | int status; |
5709 | u32 layout_count; | 5693 | u32 layout_count; |
5710 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; | 5694 | u32 recvd; |
5711 | struct kvec *iov = rcvbuf->head; | ||
5712 | u32 hdrlen, recvd; | ||
5713 | 5695 | ||
5714 | status = decode_op_hdr(xdr, OP_LAYOUTGET); | 5696 | status = decode_op_hdr(xdr, OP_LAYOUTGET); |
5715 | if (status) | 5697 | if (status) |
@@ -5746,8 +5728,7 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
5746 | res->type, | 5728 | res->type, |
5747 | res->layoutp->len); | 5729 | res->layoutp->len); |
5748 | 5730 | ||
5749 | hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base; | 5731 | recvd = xdr_read_pages(xdr, res->layoutp->len); |
5750 | recvd = req->rq_rcv_buf.len - hdrlen; | ||
5751 | if (res->layoutp->len > recvd) { | 5732 | if (res->layoutp->len > recvd) { |
5752 | dprintk("NFS: server cheating in layoutget reply: " | 5733 | dprintk("NFS: server cheating in layoutget reply: " |
5753 | "layout len %u > recvd %u\n", | 5734 | "layout len %u > recvd %u\n", |
@@ -5755,8 +5736,6 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
5755 | return -EINVAL; | 5736 | return -EINVAL; |
5756 | } | 5737 | } |
5757 | 5738 | ||
5758 | xdr_read_pages(xdr, res->layoutp->len); | ||
5759 | |||
5760 | if (layout_count > 1) { | 5739 | if (layout_count > 1) { |
5761 | /* We only handle a length one array at the moment. Any | 5740 | /* We only handle a length one array at the moment. Any |
5762 | * further entries are just ignored. Note that this means | 5741 | * further entries are just ignored. Note that this means |
@@ -7103,6 +7082,7 @@ out: | |||
7103 | int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | 7082 | int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, |
7104 | int plus) | 7083 | int plus) |
7105 | { | 7084 | { |
7085 | unsigned int savep; | ||
7106 | uint32_t bitmap[3] = {0}; | 7086 | uint32_t bitmap[3] = {0}; |
7107 | uint32_t len; | 7087 | uint32_t len; |
7108 | __be32 *p = xdr_inline_decode(xdr, 4); | 7088 | __be32 *p = xdr_inline_decode(xdr, 4); |
@@ -7141,7 +7121,7 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
7141 | if (decode_attr_bitmap(xdr, bitmap) < 0) | 7121 | if (decode_attr_bitmap(xdr, bitmap) < 0) |
7142 | goto out_overflow; | 7122 | goto out_overflow; |
7143 | 7123 | ||
7144 | if (decode_attr_length(xdr, &len, &p) < 0) | 7124 | if (decode_attr_length(xdr, &len, &savep) < 0) |
7145 | goto out_overflow; | 7125 | goto out_overflow; |
7146 | 7126 | ||
7147 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, | 7127 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index bbc49caa7a82..2617831afd39 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -1209,7 +1209,7 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page * | |||
1209 | } | 1209 | } |
1210 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_write); | 1210 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_write); |
1211 | 1211 | ||
1212 | bool | 1212 | void |
1213 | pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode, | 1213 | pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode, |
1214 | const struct nfs_pgio_completion_ops *compl_ops) | 1214 | const struct nfs_pgio_completion_ops *compl_ops) |
1215 | { | 1215 | { |
@@ -1217,13 +1217,12 @@ pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode, | |||
1217 | struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld; | 1217 | struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld; |
1218 | 1218 | ||
1219 | if (ld == NULL) | 1219 | if (ld == NULL) |
1220 | return false; | 1220 | nfs_pageio_init_read(pgio, inode, compl_ops); |
1221 | nfs_pageio_init(pgio, inode, ld->pg_read_ops, compl_ops, | 1221 | else |
1222 | server->rsize, 0); | 1222 | nfs_pageio_init(pgio, inode, ld->pg_read_ops, compl_ops, server->rsize, 0); |
1223 | return true; | ||
1224 | } | 1223 | } |
1225 | 1224 | ||
1226 | bool | 1225 | void |
1227 | pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, | 1226 | pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, |
1228 | int ioflags, | 1227 | int ioflags, |
1229 | const struct nfs_pgio_completion_ops *compl_ops) | 1228 | const struct nfs_pgio_completion_ops *compl_ops) |
@@ -1232,10 +1231,9 @@ pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, | |||
1232 | struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld; | 1231 | struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld; |
1233 | 1232 | ||
1234 | if (ld == NULL) | 1233 | if (ld == NULL) |
1235 | return false; | 1234 | nfs_pageio_init_write(pgio, inode, ioflags, compl_ops); |
1236 | nfs_pageio_init(pgio, inode, ld->pg_write_ops, compl_ops, | 1235 | else |
1237 | server->wsize, ioflags); | 1236 | nfs_pageio_init(pgio, inode, ld->pg_write_ops, compl_ops, server->wsize, ioflags); |
1238 | return true; | ||
1239 | } | 1237 | } |
1240 | 1238 | ||
1241 | bool | 1239 | bool |
@@ -1272,7 +1270,7 @@ int pnfs_write_done_resend_to_mds(struct inode *inode, | |||
1272 | LIST_HEAD(failed); | 1270 | LIST_HEAD(failed); |
1273 | 1271 | ||
1274 | /* Resend all requests through the MDS */ | 1272 | /* Resend all requests through the MDS */ |
1275 | nfs_pageio_init_write_mds(&pgio, inode, FLUSH_STABLE, compl_ops); | 1273 | nfs_pageio_init_write(&pgio, inode, FLUSH_STABLE, compl_ops); |
1276 | while (!list_empty(head)) { | 1274 | while (!list_empty(head)) { |
1277 | struct nfs_page *req = nfs_list_entry(head->next); | 1275 | struct nfs_page *req = nfs_list_entry(head->next); |
1278 | 1276 | ||
@@ -1427,7 +1425,7 @@ int pnfs_read_done_resend_to_mds(struct inode *inode, | |||
1427 | LIST_HEAD(failed); | 1425 | LIST_HEAD(failed); |
1428 | 1426 | ||
1429 | /* Resend all requests through the MDS */ | 1427 | /* Resend all requests through the MDS */ |
1430 | nfs_pageio_init_read_mds(&pgio, inode, compl_ops); | 1428 | nfs_pageio_init_read(&pgio, inode, compl_ops); |
1431 | while (!list_empty(head)) { | 1429 | while (!list_empty(head)) { |
1432 | struct nfs_page *req = nfs_list_entry(head->next); | 1430 | struct nfs_page *req = nfs_list_entry(head->next); |
1433 | 1431 | ||
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 64f90d845f6a..592beb02c955 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -178,9 +178,9 @@ extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); | |||
178 | void get_layout_hdr(struct pnfs_layout_hdr *lo); | 178 | void get_layout_hdr(struct pnfs_layout_hdr *lo); |
179 | void put_lseg(struct pnfs_layout_segment *lseg); | 179 | void put_lseg(struct pnfs_layout_segment *lseg); |
180 | 180 | ||
181 | bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *, | 181 | void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *, |
182 | const struct nfs_pgio_completion_ops *); | 182 | const struct nfs_pgio_completion_ops *); |
183 | bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, | 183 | void pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, |
184 | int, const struct nfs_pgio_completion_ops *); | 184 | int, const struct nfs_pgio_completion_ops *); |
185 | 185 | ||
186 | void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32); | 186 | void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32); |
@@ -438,16 +438,16 @@ static inline void unset_pnfs_layoutdriver(struct nfs_server *s) | |||
438 | { | 438 | { |
439 | } | 439 | } |
440 | 440 | ||
441 | static inline bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode, | 441 | static inline void pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode, |
442 | const struct nfs_pgio_completion_ops *compl_ops) | 442 | const struct nfs_pgio_completion_ops *compl_ops) |
443 | { | 443 | { |
444 | return false; | 444 | nfs_pageio_init_read(pgio, inode, compl_ops); |
445 | } | 445 | } |
446 | 446 | ||
447 | static inline bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, int ioflags, | 447 | static inline void pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, int ioflags, |
448 | const struct nfs_pgio_completion_ops *compl_ops) | 448 | const struct nfs_pgio_completion_ops *compl_ops) |
449 | { | 449 | { |
450 | return false; | 450 | nfs_pageio_init_write(pgio, inode, ioflags, compl_ops); |
451 | } | 451 | } |
452 | 452 | ||
453 | static inline int | 453 | static inline int |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 4433806e116f..c5ed1c0a8ab7 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -734,6 +734,17 @@ out_einval: | |||
734 | return -EINVAL; | 734 | return -EINVAL; |
735 | } | 735 | } |
736 | 736 | ||
737 | static int nfs_have_delegation(struct inode *inode, fmode_t flags) | ||
738 | { | ||
739 | return 0; | ||
740 | } | ||
741 | |||
742 | static int nfs_return_delegation(struct inode *inode) | ||
743 | { | ||
744 | nfs_wb_all(inode); | ||
745 | return 0; | ||
746 | } | ||
747 | |||
737 | const struct nfs_rpc_ops nfs_v2_clientops = { | 748 | const struct nfs_rpc_ops nfs_v2_clientops = { |
738 | .version = 2, /* protocol version */ | 749 | .version = 2, /* protocol version */ |
739 | .dentry_ops = &nfs_dentry_operations, | 750 | .dentry_ops = &nfs_dentry_operations, |
@@ -767,9 +778,11 @@ const struct nfs_rpc_ops nfs_v2_clientops = { | |||
767 | .pathconf = nfs_proc_pathconf, | 778 | .pathconf = nfs_proc_pathconf, |
768 | .decode_dirent = nfs2_decode_dirent, | 779 | .decode_dirent = nfs2_decode_dirent, |
769 | .read_setup = nfs_proc_read_setup, | 780 | .read_setup = nfs_proc_read_setup, |
781 | .read_pageio_init = nfs_pageio_init_read, | ||
770 | .read_rpc_prepare = nfs_proc_read_rpc_prepare, | 782 | .read_rpc_prepare = nfs_proc_read_rpc_prepare, |
771 | .read_done = nfs_read_done, | 783 | .read_done = nfs_read_done, |
772 | .write_setup = nfs_proc_write_setup, | 784 | .write_setup = nfs_proc_write_setup, |
785 | .write_pageio_init = nfs_pageio_init_write, | ||
773 | .write_rpc_prepare = nfs_proc_write_rpc_prepare, | 786 | .write_rpc_prepare = nfs_proc_write_rpc_prepare, |
774 | .write_done = nfs_write_done, | 787 | .write_done = nfs_write_done, |
775 | .commit_setup = nfs_proc_commit_setup, | 788 | .commit_setup = nfs_proc_commit_setup, |
@@ -777,5 +790,9 @@ const struct nfs_rpc_ops nfs_v2_clientops = { | |||
777 | .lock = nfs_proc_lock, | 790 | .lock = nfs_proc_lock, |
778 | .lock_check_bounds = nfs_lock_check_bounds, | 791 | .lock_check_bounds = nfs_lock_check_bounds, |
779 | .close_context = nfs_close_context, | 792 | .close_context = nfs_close_context, |
793 | .have_delegation = nfs_have_delegation, | ||
794 | .return_delegation = nfs_return_delegation, | ||
795 | .alloc_client = nfs_alloc_client, | ||
780 | .init_client = nfs_init_client, | 796 | .init_client = nfs_init_client, |
797 | .free_client = nfs_free_client, | ||
781 | }; | 798 | }; |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 86ced7836214..6267b873bbcb 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -20,8 +20,6 @@ | |||
20 | #include <linux/nfs_page.h> | 20 | #include <linux/nfs_page.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | 22 | ||
23 | #include "pnfs.h" | ||
24 | |||
25 | #include "nfs4_fs.h" | 23 | #include "nfs4_fs.h" |
26 | #include "internal.h" | 24 | #include "internal.h" |
27 | #include "iostat.h" | 25 | #include "iostat.h" |
@@ -108,7 +106,7 @@ int nfs_return_empty_page(struct page *page) | |||
108 | return 0; | 106 | return 0; |
109 | } | 107 | } |
110 | 108 | ||
111 | void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, | 109 | void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, |
112 | struct inode *inode, | 110 | struct inode *inode, |
113 | const struct nfs_pgio_completion_ops *compl_ops) | 111 | const struct nfs_pgio_completion_ops *compl_ops) |
114 | { | 112 | { |
@@ -123,14 +121,6 @@ void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio) | |||
123 | } | 121 | } |
124 | EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds); | 122 | EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds); |
125 | 123 | ||
126 | void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, | ||
127 | struct inode *inode, | ||
128 | const struct nfs_pgio_completion_ops *compl_ops) | ||
129 | { | ||
130 | if (!pnfs_pageio_init_read(pgio, inode, compl_ops)) | ||
131 | nfs_pageio_init_read_mds(pgio, inode, compl_ops); | ||
132 | } | ||
133 | |||
134 | int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, | 124 | int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, |
135 | struct page *page) | 125 | struct page *page) |
136 | { | 126 | { |
@@ -149,7 +139,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, | |||
149 | if (len < PAGE_CACHE_SIZE) | 139 | if (len < PAGE_CACHE_SIZE) |
150 | zero_user_segment(page, len, PAGE_CACHE_SIZE); | 140 | zero_user_segment(page, len, PAGE_CACHE_SIZE); |
151 | 141 | ||
152 | nfs_pageio_init_read(&pgio, inode, &nfs_async_read_completion_ops); | 142 | NFS_PROTO(inode)->read_pageio_init(&pgio, inode, &nfs_async_read_completion_ops); |
153 | nfs_pageio_add_request(&pgio, new); | 143 | nfs_pageio_add_request(&pgio, new); |
154 | nfs_pageio_complete(&pgio); | 144 | nfs_pageio_complete(&pgio); |
155 | NFS_I(inode)->read_io += pgio.pg_bytes_written; | 145 | NFS_I(inode)->read_io += pgio.pg_bytes_written; |
@@ -652,7 +642,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, | |||
652 | if (ret == 0) | 642 | if (ret == 0) |
653 | goto read_complete; /* all pages were read */ | 643 | goto read_complete; /* all pages were read */ |
654 | 644 | ||
655 | nfs_pageio_init_read(&pgio, inode, &nfs_async_read_completion_ops); | 645 | NFS_PROTO(inode)->read_pageio_init(&pgio, inode, &nfs_async_read_completion_ops); |
656 | 646 | ||
657 | ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc); | 647 | ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc); |
658 | 648 | ||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 8b2a2977b720..9bad4e753066 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -347,13 +347,12 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, | |||
347 | int flags, const char *dev_name, void *raw_data); | 347 | int flags, const char *dev_name, void *raw_data); |
348 | static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, | 348 | static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, |
349 | int flags, const char *dev_name, void *raw_data); | 349 | int flags, const char *dev_name, void *raw_data); |
350 | static void nfs4_kill_super(struct super_block *sb); | ||
351 | 350 | ||
352 | static struct file_system_type nfs4_fs_type = { | 351 | static struct file_system_type nfs4_fs_type = { |
353 | .owner = THIS_MODULE, | 352 | .owner = THIS_MODULE, |
354 | .name = "nfs4", | 353 | .name = "nfs4", |
355 | .mount = nfs_fs_mount, | 354 | .mount = nfs_fs_mount, |
356 | .kill_sb = nfs4_kill_super, | 355 | .kill_sb = nfs_kill_super, |
357 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 356 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
358 | }; | 357 | }; |
359 | 358 | ||
@@ -361,7 +360,7 @@ static struct file_system_type nfs4_remote_fs_type = { | |||
361 | .owner = THIS_MODULE, | 360 | .owner = THIS_MODULE, |
362 | .name = "nfs4", | 361 | .name = "nfs4", |
363 | .mount = nfs4_remote_mount, | 362 | .mount = nfs4_remote_mount, |
364 | .kill_sb = nfs4_kill_super, | 363 | .kill_sb = nfs_kill_super, |
365 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 364 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
366 | }; | 365 | }; |
367 | 366 | ||
@@ -369,7 +368,7 @@ struct file_system_type nfs4_xdev_fs_type = { | |||
369 | .owner = THIS_MODULE, | 368 | .owner = THIS_MODULE, |
370 | .name = "nfs4", | 369 | .name = "nfs4", |
371 | .mount = nfs4_xdev_mount, | 370 | .mount = nfs4_xdev_mount, |
372 | .kill_sb = nfs4_kill_super, | 371 | .kill_sb = nfs_kill_super, |
373 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 372 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
374 | }; | 373 | }; |
375 | 374 | ||
@@ -377,7 +376,7 @@ static struct file_system_type nfs4_remote_referral_fs_type = { | |||
377 | .owner = THIS_MODULE, | 376 | .owner = THIS_MODULE, |
378 | .name = "nfs4", | 377 | .name = "nfs4", |
379 | .mount = nfs4_remote_referral_mount, | 378 | .mount = nfs4_remote_referral_mount, |
380 | .kill_sb = nfs4_kill_super, | 379 | .kill_sb = nfs_kill_super, |
381 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 380 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
382 | }; | 381 | }; |
383 | 382 | ||
@@ -385,14 +384,14 @@ struct file_system_type nfs4_referral_fs_type = { | |||
385 | .owner = THIS_MODULE, | 384 | .owner = THIS_MODULE, |
386 | .name = "nfs4", | 385 | .name = "nfs4", |
387 | .mount = nfs4_referral_mount, | 386 | .mount = nfs4_referral_mount, |
388 | .kill_sb = nfs4_kill_super, | 387 | .kill_sb = nfs_kill_super, |
389 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 388 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
390 | }; | 389 | }; |
391 | 390 | ||
392 | static const struct super_operations nfs4_sops = { | 391 | static const struct super_operations nfs4_sops = { |
393 | .alloc_inode = nfs_alloc_inode, | 392 | .alloc_inode = nfs_alloc_inode, |
394 | .destroy_inode = nfs_destroy_inode, | 393 | .destroy_inode = nfs_destroy_inode, |
395 | .write_inode = nfs_write_inode, | 394 | .write_inode = nfs4_write_inode, |
396 | .put_super = nfs_put_super, | 395 | .put_super = nfs_put_super, |
397 | .statfs = nfs_statfs, | 396 | .statfs = nfs_statfs, |
398 | .evict_inode = nfs4_evict_inode, | 397 | .evict_inode = nfs4_evict_inode, |
@@ -2876,18 +2875,6 @@ static struct dentry *nfs4_try_mount(int flags, const char *dev_name, | |||
2876 | return res; | 2875 | return res; |
2877 | } | 2876 | } |
2878 | 2877 | ||
2879 | static void nfs4_kill_super(struct super_block *sb) | ||
2880 | { | ||
2881 | struct nfs_server *server = NFS_SB(sb); | ||
2882 | |||
2883 | dprintk("--> %s\n", __func__); | ||
2884 | nfs_super_return_all_delegations(sb); | ||
2885 | kill_anon_super(sb); | ||
2886 | nfs_fscache_release_super_cookie(sb); | ||
2887 | nfs_free_server(server); | ||
2888 | dprintk("<-- %s\n", __func__); | ||
2889 | } | ||
2890 | |||
2891 | /* | 2878 | /* |
2892 | * Clone an NFS4 server record on xdev traversal (FSID-change) | 2879 | * Clone an NFS4 server record on xdev traversal (FSID-change) |
2893 | */ | 2880 | */ |
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 3210a03342f9..13cea637eff8 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c | |||
@@ -501,7 +501,7 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry) | |||
501 | (unsigned long long)NFS_FILEID(dentry->d_inode)); | 501 | (unsigned long long)NFS_FILEID(dentry->d_inode)); |
502 | 502 | ||
503 | /* Return delegation in anticipation of the rename */ | 503 | /* Return delegation in anticipation of the rename */ |
504 | nfs_inode_return_delegation(dentry->d_inode); | 504 | NFS_PROTO(dentry->d_inode)->return_delegation(dentry->d_inode); |
505 | 505 | ||
506 | sdentry = NULL; | 506 | sdentry = NULL; |
507 | do { | 507 | do { |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 4d6861c0dc14..f312860c15d0 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -336,8 +336,10 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc | |||
336 | struct nfs_pageio_descriptor pgio; | 336 | struct nfs_pageio_descriptor pgio; |
337 | int err; | 337 | int err; |
338 | 338 | ||
339 | nfs_pageio_init_write(&pgio, page->mapping->host, wb_priority(wbc), | 339 | NFS_PROTO(page->mapping->host)->write_pageio_init(&pgio, |
340 | &nfs_async_write_completion_ops); | 340 | page->mapping->host, |
341 | wb_priority(wbc), | ||
342 | &nfs_async_write_completion_ops); | ||
341 | err = nfs_do_writepage(page, wbc, &pgio); | 343 | err = nfs_do_writepage(page, wbc, &pgio); |
342 | nfs_pageio_complete(&pgio); | 344 | nfs_pageio_complete(&pgio); |
343 | if (err < 0) | 345 | if (err < 0) |
@@ -380,8 +382,7 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) | |||
380 | 382 | ||
381 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); | 383 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); |
382 | 384 | ||
383 | nfs_pageio_init_write(&pgio, inode, wb_priority(wbc), | 385 | NFS_PROTO(inode)->write_pageio_init(&pgio, inode, wb_priority(wbc), &nfs_async_write_completion_ops); |
384 | &nfs_async_write_completion_ops); | ||
385 | err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio); | 386 | err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio); |
386 | nfs_pageio_complete(&pgio); | 387 | nfs_pageio_complete(&pgio); |
387 | 388 | ||
@@ -410,7 +411,7 @@ static void nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | |||
410 | nfs_lock_request(req); | 411 | nfs_lock_request(req); |
411 | 412 | ||
412 | spin_lock(&inode->i_lock); | 413 | spin_lock(&inode->i_lock); |
413 | if (!nfsi->npages && nfs_have_delegation(inode, FMODE_WRITE)) | 414 | if (!nfsi->npages && NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE)) |
414 | inode->i_version++; | 415 | inode->i_version++; |
415 | set_bit(PG_MAPPED, &req->wb_flags); | 416 | set_bit(PG_MAPPED, &req->wb_flags); |
416 | SetPagePrivate(req->wb_page); | 417 | SetPagePrivate(req->wb_page); |
@@ -620,7 +621,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr) | |||
620 | goto next; | 621 | goto next; |
621 | } | 622 | } |
622 | if (test_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags)) { | 623 | if (test_bit(NFS_IOHDR_NEED_COMMIT, &hdr->flags)) { |
623 | memcpy(&req->wb_verf, hdr->verf, sizeof(req->wb_verf)); | 624 | memcpy(&req->wb_verf, &hdr->verf->verifier, sizeof(req->wb_verf)); |
624 | nfs_mark_request_commit(req, hdr->lseg, &cinfo); | 625 | nfs_mark_request_commit(req, hdr->lseg, &cinfo); |
625 | goto next; | 626 | goto next; |
626 | } | 627 | } |
@@ -1202,7 +1203,7 @@ static const struct nfs_pageio_ops nfs_pageio_write_ops = { | |||
1202 | .pg_doio = nfs_generic_pg_writepages, | 1203 | .pg_doio = nfs_generic_pg_writepages, |
1203 | }; | 1204 | }; |
1204 | 1205 | ||
1205 | void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, | 1206 | void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, |
1206 | struct inode *inode, int ioflags, | 1207 | struct inode *inode, int ioflags, |
1207 | const struct nfs_pgio_completion_ops *compl_ops) | 1208 | const struct nfs_pgio_completion_ops *compl_ops) |
1208 | { | 1209 | { |
@@ -1217,13 +1218,6 @@ void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio) | |||
1217 | } | 1218 | } |
1218 | EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds); | 1219 | EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds); |
1219 | 1220 | ||
1220 | void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, | ||
1221 | struct inode *inode, int ioflags, | ||
1222 | const struct nfs_pgio_completion_ops *compl_ops) | ||
1223 | { | ||
1224 | if (!pnfs_pageio_init_write(pgio, inode, ioflags, compl_ops)) | ||
1225 | nfs_pageio_init_write_mds(pgio, inode, ioflags, compl_ops); | ||
1226 | } | ||
1227 | 1221 | ||
1228 | void nfs_write_prepare(struct rpc_task *task, void *calldata) | 1222 | void nfs_write_prepare(struct rpc_task *task, void *calldata) |
1229 | { | 1223 | { |
@@ -1547,7 +1541,7 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data) | |||
1547 | 1541 | ||
1548 | /* Okay, COMMIT succeeded, apparently. Check the verifier | 1542 | /* Okay, COMMIT succeeded, apparently. Check the verifier |
1549 | * returned by the server against all stored verfs. */ | 1543 | * returned by the server against all stored verfs. */ |
1550 | if (!memcmp(req->wb_verf.verifier, data->verf.verifier, sizeof(data->verf.verifier))) { | 1544 | if (!memcmp(&req->wb_verf, &data->verf.verifier, sizeof(req->wb_verf))) { |
1551 | /* We have a match */ | 1545 | /* We have a match */ |
1552 | nfs_inode_remove_request(req); | 1546 | nfs_inode_remove_request(req); |
1553 | dprintk(" OK\n"); | 1547 | dprintk(" OK\n"); |
@@ -1677,9 +1671,14 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr | |||
1677 | 1671 | ||
1678 | int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) | 1672 | int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) |
1679 | { | 1673 | { |
1680 | int ret; | 1674 | return nfs_commit_unstable_pages(inode, wbc); |
1675 | } | ||
1676 | |||
1677 | #ifdef CONFIG_NFS_V4 | ||
1678 | int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc) | ||
1679 | { | ||
1680 | int ret = nfs_write_inode(inode, wbc); | ||
1681 | 1681 | ||
1682 | ret = nfs_commit_unstable_pages(inode, wbc); | ||
1683 | if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) { | 1682 | if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) { |
1684 | int status; | 1683 | int status; |
1685 | bool sync = true; | 1684 | bool sync = true; |
@@ -1693,6 +1692,7 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
1693 | } | 1692 | } |
1694 | return ret; | 1693 | return ret; |
1695 | } | 1694 | } |
1695 | #endif | ||
1696 | 1696 | ||
1697 | /* | 1697 | /* |
1698 | * flush the inode to disk. | 1698 | * flush the inode to disk. |