diff options
Diffstat (limited to 'fs/nfs')
| -rw-r--r-- | fs/nfs/delegation.c | 11 | ||||
| -rw-r--r-- | fs/nfs/dir.c | 5 | ||||
| -rw-r--r-- | fs/nfs/inode.c | 14 | ||||
| -rw-r--r-- | fs/nfs/internal.h | 12 | ||||
| -rw-r--r-- | fs/nfs/nfs3acl.c | 34 | ||||
| -rw-r--r-- | fs/nfs/nfs3proc.c | 1 | ||||
| -rw-r--r-- | fs/nfs/nfs4client.c | 9 | ||||
| -rw-r--r-- | fs/nfs/nfs4filelayout.c | 10 | ||||
| -rw-r--r-- | fs/nfs/nfs4namespace.c | 12 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 32 | ||||
| -rw-r--r-- | fs/nfs/nfs4session.c | 25 | ||||
| -rw-r--r-- | fs/nfs/nfs4session.h | 2 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 19 |
13 files changed, 109 insertions, 77 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index ef792f29f831..5d8ccecf5f5c 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
| @@ -659,16 +659,19 @@ int nfs_async_inode_return_delegation(struct inode *inode, | |||
| 659 | 659 | ||
| 660 | rcu_read_lock(); | 660 | rcu_read_lock(); |
| 661 | delegation = rcu_dereference(NFS_I(inode)->delegation); | 661 | delegation = rcu_dereference(NFS_I(inode)->delegation); |
| 662 | if (delegation == NULL) | ||
| 663 | goto out_enoent; | ||
| 662 | 664 | ||
| 663 | if (!clp->cl_mvops->match_stateid(&delegation->stateid, stateid)) { | 665 | if (!clp->cl_mvops->match_stateid(&delegation->stateid, stateid)) |
| 664 | rcu_read_unlock(); | 666 | goto out_enoent; |
| 665 | return -ENOENT; | ||
| 666 | } | ||
| 667 | nfs_mark_return_delegation(server, delegation); | 667 | nfs_mark_return_delegation(server, delegation); |
| 668 | rcu_read_unlock(); | 668 | rcu_read_unlock(); |
| 669 | 669 | ||
| 670 | nfs_delegation_run_state_manager(clp); | 670 | nfs_delegation_run_state_manager(clp); |
| 671 | return 0; | 671 | return 0; |
| 672 | out_enoent: | ||
| 673 | rcu_read_unlock(); | ||
| 674 | return -ENOENT; | ||
| 672 | } | 675 | } |
| 673 | 676 | ||
| 674 | static struct inode * | 677 | static struct inode * |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index be38b573495a..4a48fe4b84b6 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -1846,6 +1846,11 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | |||
| 1846 | GFP_KERNEL)) { | 1846 | GFP_KERNEL)) { |
| 1847 | SetPageUptodate(page); | 1847 | SetPageUptodate(page); |
| 1848 | unlock_page(page); | 1848 | unlock_page(page); |
| 1849 | /* | ||
| 1850 | * add_to_page_cache_lru() grabs an extra page refcount. | ||
| 1851 | * Drop it here to avoid leaking this page later. | ||
| 1852 | */ | ||
| 1853 | page_cache_release(page); | ||
| 1849 | } else | 1854 | } else |
| 1850 | __free_page(page); | 1855 | __free_page(page); |
| 1851 | 1856 | ||
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 28a0a3cbd3b7..360114ae8b82 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -164,17 +164,16 @@ static void nfs_zap_caches_locked(struct inode *inode) | |||
| 164 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { | 164 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { |
| 165 | nfs_fscache_invalidate(inode); | 165 | nfs_fscache_invalidate(inode); |
| 166 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | 166 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR |
| 167 | | NFS_INO_INVALID_LABEL | ||
| 168 | | NFS_INO_INVALID_DATA | 167 | | NFS_INO_INVALID_DATA |
| 169 | | NFS_INO_INVALID_ACCESS | 168 | | NFS_INO_INVALID_ACCESS |
| 170 | | NFS_INO_INVALID_ACL | 169 | | NFS_INO_INVALID_ACL |
| 171 | | NFS_INO_REVAL_PAGECACHE; | 170 | | NFS_INO_REVAL_PAGECACHE; |
| 172 | } else | 171 | } else |
| 173 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | 172 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR |
| 174 | | NFS_INO_INVALID_LABEL | ||
| 175 | | NFS_INO_INVALID_ACCESS | 173 | | NFS_INO_INVALID_ACCESS |
| 176 | | NFS_INO_INVALID_ACL | 174 | | NFS_INO_INVALID_ACL |
| 177 | | NFS_INO_REVAL_PAGECACHE; | 175 | | NFS_INO_REVAL_PAGECACHE; |
| 176 | nfs_zap_label_cache_locked(nfsi); | ||
| 178 | } | 177 | } |
| 179 | 178 | ||
| 180 | void nfs_zap_caches(struct inode *inode) | 179 | void nfs_zap_caches(struct inode *inode) |
| @@ -266,6 +265,13 @@ nfs_init_locked(struct inode *inode, void *opaque) | |||
| 266 | } | 265 | } |
| 267 | 266 | ||
| 268 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | 267 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL |
| 268 | static void nfs_clear_label_invalid(struct inode *inode) | ||
| 269 | { | ||
| 270 | spin_lock(&inode->i_lock); | ||
| 271 | NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_LABEL; | ||
| 272 | spin_unlock(&inode->i_lock); | ||
| 273 | } | ||
| 274 | |||
| 269 | void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, | 275 | void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, |
| 270 | struct nfs4_label *label) | 276 | struct nfs4_label *label) |
| 271 | { | 277 | { |
| @@ -283,6 +289,7 @@ void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, | |||
| 283 | __func__, | 289 | __func__, |
| 284 | (char *)label->label, | 290 | (char *)label->label, |
| 285 | label->len, error); | 291 | label->len, error); |
| 292 | nfs_clear_label_invalid(inode); | ||
| 286 | } | 293 | } |
| 287 | } | 294 | } |
| 288 | 295 | ||
| @@ -1648,7 +1655,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1648 | inode->i_blocks = fattr->du.nfs2.blocks; | 1655 | inode->i_blocks = fattr->du.nfs2.blocks; |
| 1649 | 1656 | ||
| 1650 | /* Update attrtimeo value if we're out of the unstable period */ | 1657 | /* Update attrtimeo value if we're out of the unstable period */ |
| 1651 | if (invalid & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) { | 1658 | if (invalid & NFS_INO_INVALID_ATTR) { |
| 1652 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 1659 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
| 1653 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1660 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
| 1654 | nfsi->attrtimeo_timestamp = now; | 1661 | nfsi->attrtimeo_timestamp = now; |
| @@ -1661,7 +1668,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1661 | } | 1668 | } |
| 1662 | } | 1669 | } |
| 1663 | invalid &= ~NFS_INO_INVALID_ATTR; | 1670 | invalid &= ~NFS_INO_INVALID_ATTR; |
| 1664 | invalid &= ~NFS_INO_INVALID_LABEL; | ||
| 1665 | /* Don't invalidate the data if we were to blame */ | 1671 | /* Don't invalidate the data if we were to blame */ |
| 1666 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1672 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |
| 1667 | || S_ISLNK(inode->i_mode))) | 1673 | || S_ISLNK(inode->i_mode))) |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 8b5cc04a8611..b46cf5a67329 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -176,7 +176,8 @@ extern struct nfs_server *nfs4_create_server( | |||
| 176 | extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, | 176 | extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, |
| 177 | struct nfs_fh *); | 177 | struct nfs_fh *); |
| 178 | extern int nfs4_update_server(struct nfs_server *server, const char *hostname, | 178 | extern int nfs4_update_server(struct nfs_server *server, const char *hostname, |
| 179 | struct sockaddr *sap, size_t salen); | 179 | struct sockaddr *sap, size_t salen, |
| 180 | struct net *net); | ||
| 180 | extern void nfs_free_server(struct nfs_server *server); | 181 | extern void nfs_free_server(struct nfs_server *server); |
| 181 | extern struct nfs_server *nfs_clone_server(struct nfs_server *, | 182 | extern struct nfs_server *nfs_clone_server(struct nfs_server *, |
| 182 | struct nfs_fh *, | 183 | struct nfs_fh *, |
| @@ -279,9 +280,18 @@ static inline void nfs4_label_free(struct nfs4_label *label) | |||
| 279 | } | 280 | } |
| 280 | return; | 281 | return; |
| 281 | } | 282 | } |
| 283 | |||
| 284 | static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi) | ||
| 285 | { | ||
| 286 | if (nfs_server_capable(&nfsi->vfs_inode, NFS_CAP_SECURITY_LABEL)) | ||
| 287 | nfsi->cache_validity |= NFS_INO_INVALID_LABEL; | ||
| 288 | } | ||
| 282 | #else | 289 | #else |
| 283 | static inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; } | 290 | static inline struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) { return NULL; } |
| 284 | static inline void nfs4_label_free(void *label) {} | 291 | static inline void nfs4_label_free(void *label) {} |
| 292 | static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi) | ||
| 293 | { | ||
| 294 | } | ||
| 285 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ | 295 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ |
| 286 | 296 | ||
| 287 | /* proc.c */ | 297 | /* proc.c */ |
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index 9a5ca03fa539..871d6eda8dba 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c | |||
| @@ -80,7 +80,7 @@ struct posix_acl *nfs3_get_acl(struct inode *inode, int type) | |||
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | if (res.acl_access != NULL) { | 82 | if (res.acl_access != NULL) { |
| 83 | if (posix_acl_equiv_mode(res.acl_access, NULL) || | 83 | if ((posix_acl_equiv_mode(res.acl_access, NULL) == 0) || |
| 84 | res.acl_access->a_count == 0) { | 84 | res.acl_access->a_count == 0) { |
| 85 | posix_acl_release(res.acl_access); | 85 | posix_acl_release(res.acl_access); |
| 86 | res.acl_access = NULL; | 86 | res.acl_access = NULL; |
| @@ -113,7 +113,7 @@ getout: | |||
| 113 | return ERR_PTR(status); | 113 | return ERR_PTR(status); |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, | 116 | static int __nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, |
| 117 | struct posix_acl *dfacl) | 117 | struct posix_acl *dfacl) |
| 118 | { | 118 | { |
| 119 | struct nfs_server *server = NFS_SERVER(inode); | 119 | struct nfs_server *server = NFS_SERVER(inode); |
| @@ -198,6 +198,15 @@ out: | |||
| 198 | return status; | 198 | return status; |
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, | ||
| 202 | struct posix_acl *dfacl) | ||
| 203 | { | ||
| 204 | int ret; | ||
| 205 | ret = __nfs3_proc_setacls(inode, acl, dfacl); | ||
| 206 | return (ret == -EOPNOTSUPP) ? 0 : ret; | ||
| 207 | |||
| 208 | } | ||
| 209 | |||
| 201 | int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type) | 210 | int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type) |
| 202 | { | 211 | { |
| 203 | struct posix_acl *alloc = NULL, *dfacl = NULL; | 212 | struct posix_acl *alloc = NULL, *dfacl = NULL; |
| @@ -225,7 +234,7 @@ int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
| 225 | if (IS_ERR(alloc)) | 234 | if (IS_ERR(alloc)) |
| 226 | goto fail; | 235 | goto fail; |
| 227 | } | 236 | } |
| 228 | status = nfs3_proc_setacls(inode, acl, dfacl); | 237 | status = __nfs3_proc_setacls(inode, acl, dfacl); |
| 229 | posix_acl_release(alloc); | 238 | posix_acl_release(alloc); |
| 230 | return status; | 239 | return status; |
| 231 | 240 | ||
| @@ -233,25 +242,6 @@ fail: | |||
| 233 | return PTR_ERR(alloc); | 242 | return PTR_ERR(alloc); |
| 234 | } | 243 | } |
| 235 | 244 | ||
| 236 | int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode, | ||
| 237 | umode_t mode) | ||
| 238 | { | ||
| 239 | struct posix_acl *default_acl, *acl; | ||
| 240 | int error; | ||
| 241 | |||
| 242 | error = posix_acl_create(dir, &mode, &default_acl, &acl); | ||
| 243 | if (error) | ||
| 244 | return (error == -EOPNOTSUPP) ? 0 : error; | ||
| 245 | |||
| 246 | error = nfs3_proc_setacls(inode, acl, default_acl); | ||
| 247 | |||
| 248 | if (acl) | ||
| 249 | posix_acl_release(acl); | ||
| 250 | if (default_acl) | ||
| 251 | posix_acl_release(default_acl); | ||
| 252 | return error; | ||
| 253 | } | ||
| 254 | |||
| 255 | const struct xattr_handler *nfs3_xattr_handlers[] = { | 245 | const struct xattr_handler *nfs3_xattr_handlers[] = { |
| 256 | &posix_acl_access_xattr_handler, | 246 | &posix_acl_access_xattr_handler, |
| 257 | &posix_acl_default_xattr_handler, | 247 | &posix_acl_default_xattr_handler, |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index aa9bc973f36a..a462ef0fb5d6 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/lockd/bind.h> | 18 | #include <linux/lockd/bind.h> |
| 19 | #include <linux/nfs_mount.h> | 19 | #include <linux/nfs_mount.h> |
| 20 | #include <linux/freezer.h> | 20 | #include <linux/freezer.h> |
| 21 | #include <linux/xattr.h> | ||
| 21 | 22 | ||
| 22 | #include "iostat.h" | 23 | #include "iostat.h" |
| 23 | #include "internal.h" | 24 | #include "internal.h" |
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index dbb3e1f30c68..0e46d3d1b6cc 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
| @@ -170,7 +170,7 @@ void nfs41_shutdown_client(struct nfs_client *clp) | |||
| 170 | void nfs40_shutdown_client(struct nfs_client *clp) | 170 | void nfs40_shutdown_client(struct nfs_client *clp) |
| 171 | { | 171 | { |
| 172 | if (clp->cl_slot_tbl) { | 172 | if (clp->cl_slot_tbl) { |
| 173 | nfs4_release_slot_table(clp->cl_slot_tbl); | 173 | nfs4_shutdown_slot_table(clp->cl_slot_tbl); |
| 174 | kfree(clp->cl_slot_tbl); | 174 | kfree(clp->cl_slot_tbl); |
| 175 | } | 175 | } |
| 176 | } | 176 | } |
| @@ -1135,6 +1135,7 @@ static int nfs_probe_destination(struct nfs_server *server) | |||
| 1135 | * @hostname: new end-point's hostname | 1135 | * @hostname: new end-point's hostname |
| 1136 | * @sap: new end-point's socket address | 1136 | * @sap: new end-point's socket address |
| 1137 | * @salen: size of "sap" | 1137 | * @salen: size of "sap" |
| 1138 | * @net: net namespace | ||
| 1138 | * | 1139 | * |
| 1139 | * The nfs_server must be quiescent before this function is invoked. | 1140 | * The nfs_server must be quiescent before this function is invoked. |
| 1140 | * Either its session is drained (NFSv4.1+), or its transport is | 1141 | * Either its session is drained (NFSv4.1+), or its transport is |
| @@ -1143,13 +1144,13 @@ static int nfs_probe_destination(struct nfs_server *server) | |||
| 1143 | * Returns zero on success, or a negative errno value. | 1144 | * Returns zero on success, or a negative errno value. |
| 1144 | */ | 1145 | */ |
| 1145 | int nfs4_update_server(struct nfs_server *server, const char *hostname, | 1146 | int nfs4_update_server(struct nfs_server *server, const char *hostname, |
| 1146 | struct sockaddr *sap, size_t salen) | 1147 | struct sockaddr *sap, size_t salen, struct net *net) |
| 1147 | { | 1148 | { |
| 1148 | struct nfs_client *clp = server->nfs_client; | 1149 | struct nfs_client *clp = server->nfs_client; |
| 1149 | struct rpc_clnt *clnt = server->client; | 1150 | struct rpc_clnt *clnt = server->client; |
| 1150 | struct xprt_create xargs = { | 1151 | struct xprt_create xargs = { |
| 1151 | .ident = clp->cl_proto, | 1152 | .ident = clp->cl_proto, |
| 1152 | .net = &init_net, | 1153 | .net = net, |
| 1153 | .dstaddr = sap, | 1154 | .dstaddr = sap, |
| 1154 | .addrlen = salen, | 1155 | .addrlen = salen, |
| 1155 | .servername = hostname, | 1156 | .servername = hostname, |
| @@ -1189,7 +1190,7 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname, | |||
| 1189 | error = nfs4_set_client(server, hostname, sap, salen, buf, | 1190 | error = nfs4_set_client(server, hostname, sap, salen, buf, |
| 1190 | clp->cl_rpcclient->cl_auth->au_flavor, | 1191 | clp->cl_rpcclient->cl_auth->au_flavor, |
| 1191 | clp->cl_proto, clnt->cl_timeout, | 1192 | clp->cl_proto, clnt->cl_timeout, |
| 1192 | clp->cl_minorversion, clp->cl_net); | 1193 | clp->cl_minorversion, net); |
| 1193 | nfs_put_client(clp); | 1194 | nfs_put_client(clp); |
| 1194 | if (error != 0) { | 1195 | if (error != 0) { |
| 1195 | nfs_server_insert_lists(server); | 1196 | nfs_server_insert_lists(server); |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 12c8132ad408..b9a35c05b60f 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
| @@ -324,8 +324,9 @@ static void filelayout_read_prepare(struct rpc_task *task, void *data) | |||
| 324 | &rdata->res.seq_res, | 324 | &rdata->res.seq_res, |
| 325 | task)) | 325 | task)) |
| 326 | return; | 326 | return; |
| 327 | nfs4_set_rw_stateid(&rdata->args.stateid, rdata->args.context, | 327 | if (nfs4_set_rw_stateid(&rdata->args.stateid, rdata->args.context, |
| 328 | rdata->args.lock_context, FMODE_READ); | 328 | rdata->args.lock_context, FMODE_READ) == -EIO) |
| 329 | rpc_exit(task, -EIO); /* lost lock, terminate I/O */ | ||
| 329 | } | 330 | } |
| 330 | 331 | ||
| 331 | static void filelayout_read_call_done(struct rpc_task *task, void *data) | 332 | static void filelayout_read_call_done(struct rpc_task *task, void *data) |
| @@ -435,8 +436,9 @@ static void filelayout_write_prepare(struct rpc_task *task, void *data) | |||
| 435 | &wdata->res.seq_res, | 436 | &wdata->res.seq_res, |
| 436 | task)) | 437 | task)) |
| 437 | return; | 438 | return; |
| 438 | nfs4_set_rw_stateid(&wdata->args.stateid, wdata->args.context, | 439 | if (nfs4_set_rw_stateid(&wdata->args.stateid, wdata->args.context, |
| 439 | wdata->args.lock_context, FMODE_WRITE); | 440 | wdata->args.lock_context, FMODE_WRITE) == -EIO) |
| 441 | rpc_exit(task, -EIO); /* lost lock, terminate I/O */ | ||
| 440 | } | 442 | } |
| 441 | 443 | ||
| 442 | static void filelayout_write_call_done(struct rpc_task *task, void *data) | 444 | static void filelayout_write_call_done(struct rpc_task *task, void *data) |
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index 4e7f05d3e9db..3d5dbf80d46a 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c | |||
| @@ -121,9 +121,8 @@ static int nfs4_validate_fspath(struct dentry *dentry, | |||
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | static size_t nfs_parse_server_name(char *string, size_t len, | 123 | static size_t nfs_parse_server_name(char *string, size_t len, |
| 124 | struct sockaddr *sa, size_t salen, struct nfs_server *server) | 124 | struct sockaddr *sa, size_t salen, struct net *net) |
| 125 | { | 125 | { |
| 126 | struct net *net = rpc_net_ns(server->client); | ||
| 127 | ssize_t ret; | 126 | ssize_t ret; |
| 128 | 127 | ||
| 129 | ret = rpc_pton(net, string, len, sa, salen); | 128 | ret = rpc_pton(net, string, len, sa, salen); |
| @@ -223,6 +222,7 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, | |||
| 223 | const struct nfs4_fs_location *location) | 222 | const struct nfs4_fs_location *location) |
| 224 | { | 223 | { |
| 225 | const size_t addr_bufsize = sizeof(struct sockaddr_storage); | 224 | const size_t addr_bufsize = sizeof(struct sockaddr_storage); |
| 225 | struct net *net = rpc_net_ns(NFS_SB(mountdata->sb)->client); | ||
| 226 | struct vfsmount *mnt = ERR_PTR(-ENOENT); | 226 | struct vfsmount *mnt = ERR_PTR(-ENOENT); |
| 227 | char *mnt_path; | 227 | char *mnt_path; |
| 228 | unsigned int maxbuflen; | 228 | unsigned int maxbuflen; |
| @@ -248,8 +248,7 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, | |||
| 248 | continue; | 248 | continue; |
| 249 | 249 | ||
| 250 | mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len, | 250 | mountdata->addrlen = nfs_parse_server_name(buf->data, buf->len, |
| 251 | mountdata->addr, addr_bufsize, | 251 | mountdata->addr, addr_bufsize, net); |
| 252 | NFS_SB(mountdata->sb)); | ||
| 253 | if (mountdata->addrlen == 0) | 252 | if (mountdata->addrlen == 0) |
| 254 | continue; | 253 | continue; |
| 255 | 254 | ||
| @@ -419,6 +418,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server, | |||
| 419 | const struct nfs4_fs_location *location) | 418 | const struct nfs4_fs_location *location) |
| 420 | { | 419 | { |
| 421 | const size_t addr_bufsize = sizeof(struct sockaddr_storage); | 420 | const size_t addr_bufsize = sizeof(struct sockaddr_storage); |
| 421 | struct net *net = rpc_net_ns(server->client); | ||
| 422 | struct sockaddr *sap; | 422 | struct sockaddr *sap; |
| 423 | unsigned int s; | 423 | unsigned int s; |
| 424 | size_t salen; | 424 | size_t salen; |
| @@ -440,7 +440,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server, | |||
| 440 | continue; | 440 | continue; |
| 441 | 441 | ||
| 442 | salen = nfs_parse_server_name(buf->data, buf->len, | 442 | salen = nfs_parse_server_name(buf->data, buf->len, |
| 443 | sap, addr_bufsize, server); | 443 | sap, addr_bufsize, net); |
| 444 | if (salen == 0) | 444 | if (salen == 0) |
| 445 | continue; | 445 | continue; |
| 446 | rpc_set_port(sap, NFS_PORT); | 446 | rpc_set_port(sap, NFS_PORT); |
| @@ -450,7 +450,7 @@ static int nfs4_try_replacing_one_location(struct nfs_server *server, | |||
| 450 | if (hostname == NULL) | 450 | if (hostname == NULL) |
| 451 | break; | 451 | break; |
| 452 | 452 | ||
| 453 | error = nfs4_update_server(server, hostname, sap, salen); | 453 | error = nfs4_update_server(server, hostname, sap, salen, net); |
| 454 | kfree(hostname); | 454 | kfree(hostname); |
| 455 | if (error == 0) | 455 | if (error == 0) |
| 456 | break; | 456 | break; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 42da6af77587..450bfedbe2f4 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -1620,15 +1620,15 @@ static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata) | |||
| 1620 | { | 1620 | { |
| 1621 | struct nfs4_opendata *data = calldata; | 1621 | struct nfs4_opendata *data = calldata; |
| 1622 | 1622 | ||
| 1623 | nfs40_setup_sequence(data->o_arg.server, &data->o_arg.seq_args, | 1623 | nfs40_setup_sequence(data->o_arg.server, &data->c_arg.seq_args, |
| 1624 | &data->o_res.seq_res, task); | 1624 | &data->c_res.seq_res, task); |
| 1625 | } | 1625 | } |
| 1626 | 1626 | ||
| 1627 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) | 1627 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) |
| 1628 | { | 1628 | { |
| 1629 | struct nfs4_opendata *data = calldata; | 1629 | struct nfs4_opendata *data = calldata; |
| 1630 | 1630 | ||
| 1631 | nfs40_sequence_done(task, &data->o_res.seq_res); | 1631 | nfs40_sequence_done(task, &data->c_res.seq_res); |
| 1632 | 1632 | ||
| 1633 | data->rpc_status = task->tk_status; | 1633 | data->rpc_status = task->tk_status; |
| 1634 | if (data->rpc_status == 0) { | 1634 | if (data->rpc_status == 0) { |
| @@ -1686,7 +1686,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data) | |||
| 1686 | }; | 1686 | }; |
| 1687 | int status; | 1687 | int status; |
| 1688 | 1688 | ||
| 1689 | nfs4_init_sequence(&data->o_arg.seq_args, &data->o_res.seq_res, 1); | 1689 | nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1); |
| 1690 | kref_get(&data->kref); | 1690 | kref_get(&data->kref); |
| 1691 | data->rpc_done = 0; | 1691 | data->rpc_done = 0; |
| 1692 | data->rpc_status = 0; | 1692 | data->rpc_status = 0; |
| @@ -2398,13 +2398,16 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
| 2398 | 2398 | ||
| 2399 | if (nfs4_copy_delegation_stateid(&arg.stateid, inode, fmode)) { | 2399 | if (nfs4_copy_delegation_stateid(&arg.stateid, inode, fmode)) { |
| 2400 | /* Use that stateid */ | 2400 | /* Use that stateid */ |
| 2401 | } else if (truncate && state != NULL && nfs4_valid_open_stateid(state)) { | 2401 | } else if (truncate && state != NULL) { |
| 2402 | struct nfs_lockowner lockowner = { | 2402 | struct nfs_lockowner lockowner = { |
| 2403 | .l_owner = current->files, | 2403 | .l_owner = current->files, |
| 2404 | .l_pid = current->tgid, | 2404 | .l_pid = current->tgid, |
| 2405 | }; | 2405 | }; |
| 2406 | nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE, | 2406 | if (!nfs4_valid_open_stateid(state)) |
| 2407 | &lockowner); | 2407 | return -EBADF; |
| 2408 | if (nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE, | ||
| 2409 | &lockowner) == -EIO) | ||
| 2410 | return -EBADF; | ||
| 2408 | } else | 2411 | } else |
| 2409 | nfs4_stateid_copy(&arg.stateid, &zero_stateid); | 2412 | nfs4_stateid_copy(&arg.stateid, &zero_stateid); |
| 2410 | 2413 | ||
| @@ -4011,8 +4014,9 @@ static bool nfs4_stateid_is_current(nfs4_stateid *stateid, | |||
| 4011 | { | 4014 | { |
| 4012 | nfs4_stateid current_stateid; | 4015 | nfs4_stateid current_stateid; |
| 4013 | 4016 | ||
| 4014 | if (nfs4_set_rw_stateid(¤t_stateid, ctx, l_ctx, fmode)) | 4017 | /* If the current stateid represents a lost lock, then exit */ |
| 4015 | return false; | 4018 | if (nfs4_set_rw_stateid(¤t_stateid, ctx, l_ctx, fmode) == -EIO) |
| 4019 | return true; | ||
| 4016 | return nfs4_stateid_match(stateid, ¤t_stateid); | 4020 | return nfs4_stateid_match(stateid, ¤t_stateid); |
| 4017 | } | 4021 | } |
| 4018 | 4022 | ||
| @@ -5828,8 +5832,7 @@ struct nfs_release_lockowner_data { | |||
| 5828 | struct nfs4_lock_state *lsp; | 5832 | struct nfs4_lock_state *lsp; |
| 5829 | struct nfs_server *server; | 5833 | struct nfs_server *server; |
| 5830 | struct nfs_release_lockowner_args args; | 5834 | struct nfs_release_lockowner_args args; |
| 5831 | struct nfs4_sequence_args seq_args; | 5835 | struct nfs_release_lockowner_res res; |
| 5832 | struct nfs4_sequence_res seq_res; | ||
| 5833 | unsigned long timestamp; | 5836 | unsigned long timestamp; |
| 5834 | }; | 5837 | }; |
| 5835 | 5838 | ||
| @@ -5837,7 +5840,7 @@ static void nfs4_release_lockowner_prepare(struct rpc_task *task, void *calldata | |||
| 5837 | { | 5840 | { |
| 5838 | struct nfs_release_lockowner_data *data = calldata; | 5841 | struct nfs_release_lockowner_data *data = calldata; |
| 5839 | nfs40_setup_sequence(data->server, | 5842 | nfs40_setup_sequence(data->server, |
| 5840 | &data->seq_args, &data->seq_res, task); | 5843 | &data->args.seq_args, &data->res.seq_res, task); |
| 5841 | data->timestamp = jiffies; | 5844 | data->timestamp = jiffies; |
| 5842 | } | 5845 | } |
| 5843 | 5846 | ||
| @@ -5846,7 +5849,7 @@ static void nfs4_release_lockowner_done(struct rpc_task *task, void *calldata) | |||
| 5846 | struct nfs_release_lockowner_data *data = calldata; | 5849 | struct nfs_release_lockowner_data *data = calldata; |
| 5847 | struct nfs_server *server = data->server; | 5850 | struct nfs_server *server = data->server; |
| 5848 | 5851 | ||
| 5849 | nfs40_sequence_done(task, &data->seq_res); | 5852 | nfs40_sequence_done(task, &data->res.seq_res); |
| 5850 | 5853 | ||
| 5851 | switch (task->tk_status) { | 5854 | switch (task->tk_status) { |
| 5852 | case 0: | 5855 | case 0: |
| @@ -5887,7 +5890,6 @@ static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_st | |||
| 5887 | data = kmalloc(sizeof(*data), GFP_NOFS); | 5890 | data = kmalloc(sizeof(*data), GFP_NOFS); |
| 5888 | if (!data) | 5891 | if (!data) |
| 5889 | return -ENOMEM; | 5892 | return -ENOMEM; |
| 5890 | nfs4_init_sequence(&data->seq_args, &data->seq_res, 0); | ||
| 5891 | data->lsp = lsp; | 5893 | data->lsp = lsp; |
| 5892 | data->server = server; | 5894 | data->server = server; |
| 5893 | data->args.lock_owner.clientid = server->nfs_client->cl_clientid; | 5895 | data->args.lock_owner.clientid = server->nfs_client->cl_clientid; |
| @@ -5895,6 +5897,8 @@ static int nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_st | |||
| 5895 | data->args.lock_owner.s_dev = server->s_dev; | 5897 | data->args.lock_owner.s_dev = server->s_dev; |
| 5896 | 5898 | ||
| 5897 | msg.rpc_argp = &data->args; | 5899 | msg.rpc_argp = &data->args; |
| 5900 | msg.rpc_resp = &data->res; | ||
| 5901 | nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0); | ||
| 5898 | rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data); | 5902 | rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data); |
| 5899 | return 0; | 5903 | return 0; |
| 5900 | } | 5904 | } |
diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c index cf883c7ae053..e799dc3c3b1d 100644 --- a/fs/nfs/nfs4session.c +++ b/fs/nfs/nfs4session.c | |||
| @@ -231,14 +231,23 @@ out: | |||
| 231 | return ret; | 231 | return ret; |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | /* | ||
| 235 | * nfs4_release_slot_table - release all slot table entries | ||
| 236 | */ | ||
| 237 | static void nfs4_release_slot_table(struct nfs4_slot_table *tbl) | ||
| 238 | { | ||
| 239 | nfs4_shrink_slot_table(tbl, 0); | ||
| 240 | } | ||
| 241 | |||
| 234 | /** | 242 | /** |
| 235 | * nfs4_release_slot_table - release resources attached to a slot table | 243 | * nfs4_shutdown_slot_table - release resources attached to a slot table |
| 236 | * @tbl: slot table to shut down | 244 | * @tbl: slot table to shut down |
| 237 | * | 245 | * |
| 238 | */ | 246 | */ |
| 239 | void nfs4_release_slot_table(struct nfs4_slot_table *tbl) | 247 | void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl) |
| 240 | { | 248 | { |
| 241 | nfs4_shrink_slot_table(tbl, 0); | 249 | nfs4_release_slot_table(tbl); |
| 250 | rpc_destroy_wait_queue(&tbl->slot_tbl_waitq); | ||
| 242 | } | 251 | } |
| 243 | 252 | ||
| 244 | /** | 253 | /** |
| @@ -422,7 +431,7 @@ void nfs41_update_target_slotid(struct nfs4_slot_table *tbl, | |||
| 422 | spin_unlock(&tbl->slot_tbl_lock); | 431 | spin_unlock(&tbl->slot_tbl_lock); |
| 423 | } | 432 | } |
| 424 | 433 | ||
| 425 | static void nfs4_destroy_session_slot_tables(struct nfs4_session *session) | 434 | static void nfs4_release_session_slot_tables(struct nfs4_session *session) |
| 426 | { | 435 | { |
| 427 | nfs4_release_slot_table(&session->fc_slot_table); | 436 | nfs4_release_slot_table(&session->fc_slot_table); |
| 428 | nfs4_release_slot_table(&session->bc_slot_table); | 437 | nfs4_release_slot_table(&session->bc_slot_table); |
| @@ -450,7 +459,7 @@ int nfs4_setup_session_slot_tables(struct nfs4_session *ses) | |||
| 450 | if (status && tbl->slots == NULL) | 459 | if (status && tbl->slots == NULL) |
| 451 | /* Fore and back channel share a connection so get | 460 | /* Fore and back channel share a connection so get |
| 452 | * both slot tables or neither */ | 461 | * both slot tables or neither */ |
| 453 | nfs4_destroy_session_slot_tables(ses); | 462 | nfs4_release_session_slot_tables(ses); |
| 454 | return status; | 463 | return status; |
| 455 | } | 464 | } |
| 456 | 465 | ||
| @@ -470,6 +479,12 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | |||
| 470 | return session; | 479 | return session; |
| 471 | } | 480 | } |
| 472 | 481 | ||
| 482 | static void nfs4_destroy_session_slot_tables(struct nfs4_session *session) | ||
| 483 | { | ||
| 484 | nfs4_shutdown_slot_table(&session->fc_slot_table); | ||
| 485 | nfs4_shutdown_slot_table(&session->bc_slot_table); | ||
| 486 | } | ||
| 487 | |||
| 473 | void nfs4_destroy_session(struct nfs4_session *session) | 488 | void nfs4_destroy_session(struct nfs4_session *session) |
| 474 | { | 489 | { |
| 475 | struct rpc_xprt *xprt; | 490 | struct rpc_xprt *xprt; |
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h index 232306100651..b34ada9bc6a2 100644 --- a/fs/nfs/nfs4session.h +++ b/fs/nfs/nfs4session.h | |||
| @@ -74,7 +74,7 @@ enum nfs4_session_state { | |||
| 74 | 74 | ||
| 75 | extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, | 75 | extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, |
| 76 | unsigned int max_reqs, const char *queue); | 76 | unsigned int max_reqs, const char *queue); |
| 77 | extern void nfs4_release_slot_table(struct nfs4_slot_table *tbl); | 77 | extern void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl); |
| 78 | extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl); | 78 | extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl); |
| 79 | extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot); | 79 | extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot); |
| 80 | extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl); | 80 | extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl); |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index e5be72518bd7..0deb32105ccf 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -974,9 +974,6 @@ static int nfs4_copy_lock_stateid(nfs4_stateid *dst, | |||
| 974 | else if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) { | 974 | else if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) { |
| 975 | nfs4_stateid_copy(dst, &lsp->ls_stateid); | 975 | nfs4_stateid_copy(dst, &lsp->ls_stateid); |
| 976 | ret = 0; | 976 | ret = 0; |
| 977 | smp_rmb(); | ||
| 978 | if (!list_empty(&lsp->ls_seqid.list)) | ||
| 979 | ret = -EWOULDBLOCK; | ||
| 980 | } | 977 | } |
| 981 | spin_unlock(&state->state_lock); | 978 | spin_unlock(&state->state_lock); |
| 982 | nfs4_put_lock_state(lsp); | 979 | nfs4_put_lock_state(lsp); |
| @@ -984,10 +981,9 @@ out: | |||
| 984 | return ret; | 981 | return ret; |
| 985 | } | 982 | } |
| 986 | 983 | ||
| 987 | static int nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state) | 984 | static void nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state) |
| 988 | { | 985 | { |
| 989 | const nfs4_stateid *src; | 986 | const nfs4_stateid *src; |
| 990 | int ret; | ||
| 991 | int seq; | 987 | int seq; |
| 992 | 988 | ||
| 993 | do { | 989 | do { |
| @@ -996,12 +992,7 @@ static int nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state) | |||
| 996 | if (test_bit(NFS_OPEN_STATE, &state->flags)) | 992 | if (test_bit(NFS_OPEN_STATE, &state->flags)) |
| 997 | src = &state->open_stateid; | 993 | src = &state->open_stateid; |
| 998 | nfs4_stateid_copy(dst, src); | 994 | nfs4_stateid_copy(dst, src); |
| 999 | ret = 0; | ||
| 1000 | smp_rmb(); | ||
| 1001 | if (!list_empty(&state->owner->so_seqid.list)) | ||
| 1002 | ret = -EWOULDBLOCK; | ||
| 1003 | } while (read_seqretry(&state->seqlock, seq)); | 995 | } while (read_seqretry(&state->seqlock, seq)); |
| 1004 | return ret; | ||
| 1005 | } | 996 | } |
| 1006 | 997 | ||
| 1007 | /* | 998 | /* |
| @@ -1015,15 +1006,19 @@ int nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state, | |||
| 1015 | if (ret == -EIO) | 1006 | if (ret == -EIO) |
| 1016 | /* A lost lock - don't even consider delegations */ | 1007 | /* A lost lock - don't even consider delegations */ |
| 1017 | goto out; | 1008 | goto out; |
| 1018 | if (nfs4_copy_delegation_stateid(dst, state->inode, fmode)) | 1009 | /* returns true if delegation stateid found and copied */ |
| 1010 | if (nfs4_copy_delegation_stateid(dst, state->inode, fmode)) { | ||
| 1011 | ret = 0; | ||
| 1019 | goto out; | 1012 | goto out; |
| 1013 | } | ||
| 1020 | if (ret != -ENOENT) | 1014 | if (ret != -ENOENT) |
| 1021 | /* nfs4_copy_delegation_stateid() didn't over-write | 1015 | /* nfs4_copy_delegation_stateid() didn't over-write |
| 1022 | * dst, so it still has the lock stateid which we now | 1016 | * dst, so it still has the lock stateid which we now |
| 1023 | * choose to use. | 1017 | * choose to use. |
| 1024 | */ | 1018 | */ |
| 1025 | goto out; | 1019 | goto out; |
| 1026 | ret = nfs4_copy_open_stateid(dst, state); | 1020 | nfs4_copy_open_stateid(dst, state); |
| 1021 | ret = 0; | ||
| 1027 | out: | 1022 | out: |
| 1028 | if (nfs_server_capable(state->inode, NFS_CAP_STATEID_NFSV41)) | 1023 | if (nfs_server_capable(state->inode, NFS_CAP_STATEID_NFSV41)) |
| 1029 | dst->seqid = 0; | 1024 | dst->seqid = 0; |
