diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 302 |
1 files changed, 246 insertions, 56 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 1d84e7088af..dfd1e6d7e6c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/string.h> | 41 | #include <linux/string.h> |
42 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
43 | #include <linux/sunrpc/clnt.h> | 43 | #include <linux/sunrpc/clnt.h> |
44 | #include <linux/sunrpc/gss_api.h> | ||
44 | #include <linux/nfs.h> | 45 | #include <linux/nfs.h> |
45 | #include <linux/nfs4.h> | 46 | #include <linux/nfs4.h> |
46 | #include <linux/nfs_fs.h> | 47 | #include <linux/nfs_fs.h> |
@@ -71,7 +72,9 @@ static int _nfs4_proc_open(struct nfs4_opendata *data); | |||
71 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); | 72 | static int _nfs4_recover_proc_open(struct nfs4_opendata *data); |
72 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 73 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); |
73 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); | 74 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); |
74 | static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr); | 75 | static int _nfs4_proc_lookup(struct rpc_clnt *client, struct inode *dir, |
76 | const struct qstr *name, struct nfs_fh *fhandle, | ||
77 | struct nfs_fattr *fattr); | ||
75 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); | 78 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); |
76 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | 79 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, |
77 | struct nfs_fattr *fattr, struct iattr *sattr, | 80 | struct nfs_fattr *fattr, struct iattr *sattr, |
@@ -85,6 +88,8 @@ static int nfs4_map_errors(int err) | |||
85 | switch (err) { | 88 | switch (err) { |
86 | case -NFS4ERR_RESOURCE: | 89 | case -NFS4ERR_RESOURCE: |
87 | return -EREMOTEIO; | 90 | return -EREMOTEIO; |
91 | case -NFS4ERR_WRONGSEC: | ||
92 | return -EPERM; | ||
88 | case -NFS4ERR_BADOWNER: | 93 | case -NFS4ERR_BADOWNER: |
89 | case -NFS4ERR_BADNAME: | 94 | case -NFS4ERR_BADNAME: |
90 | return -EINVAL; | 95 | return -EINVAL; |
@@ -657,7 +662,8 @@ struct rpc_call_ops nfs41_call_priv_sync_ops = { | |||
657 | .rpc_call_done = nfs41_call_sync_done, | 662 | .rpc_call_done = nfs41_call_sync_done, |
658 | }; | 663 | }; |
659 | 664 | ||
660 | static int nfs4_call_sync_sequence(struct nfs_server *server, | 665 | static int nfs4_call_sync_sequence(struct rpc_clnt *clnt, |
666 | struct nfs_server *server, | ||
661 | struct rpc_message *msg, | 667 | struct rpc_message *msg, |
662 | struct nfs4_sequence_args *args, | 668 | struct nfs4_sequence_args *args, |
663 | struct nfs4_sequence_res *res, | 669 | struct nfs4_sequence_res *res, |
@@ -673,7 +679,7 @@ static int nfs4_call_sync_sequence(struct nfs_server *server, | |||
673 | .cache_reply = cache_reply, | 679 | .cache_reply = cache_reply, |
674 | }; | 680 | }; |
675 | struct rpc_task_setup task_setup = { | 681 | struct rpc_task_setup task_setup = { |
676 | .rpc_client = server->client, | 682 | .rpc_client = clnt, |
677 | .rpc_message = msg, | 683 | .rpc_message = msg, |
678 | .callback_ops = &nfs41_call_sync_ops, | 684 | .callback_ops = &nfs41_call_sync_ops, |
679 | .callback_data = &data | 685 | .callback_data = &data |
@@ -692,13 +698,14 @@ static int nfs4_call_sync_sequence(struct nfs_server *server, | |||
692 | return ret; | 698 | return ret; |
693 | } | 699 | } |
694 | 700 | ||
695 | int _nfs4_call_sync_session(struct nfs_server *server, | 701 | int _nfs4_call_sync_session(struct rpc_clnt *clnt, |
702 | struct nfs_server *server, | ||
696 | struct rpc_message *msg, | 703 | struct rpc_message *msg, |
697 | struct nfs4_sequence_args *args, | 704 | struct nfs4_sequence_args *args, |
698 | struct nfs4_sequence_res *res, | 705 | struct nfs4_sequence_res *res, |
699 | int cache_reply) | 706 | int cache_reply) |
700 | { | 707 | { |
701 | return nfs4_call_sync_sequence(server, msg, args, res, cache_reply, 0); | 708 | return nfs4_call_sync_sequence(clnt, server, msg, args, res, cache_reply, 0); |
702 | } | 709 | } |
703 | 710 | ||
704 | #else | 711 | #else |
@@ -709,19 +716,28 @@ static int nfs4_sequence_done(struct rpc_task *task, | |||
709 | } | 716 | } |
710 | #endif /* CONFIG_NFS_V4_1 */ | 717 | #endif /* CONFIG_NFS_V4_1 */ |
711 | 718 | ||
712 | int _nfs4_call_sync(struct nfs_server *server, | 719 | int _nfs4_call_sync(struct rpc_clnt *clnt, |
720 | struct nfs_server *server, | ||
713 | struct rpc_message *msg, | 721 | struct rpc_message *msg, |
714 | struct nfs4_sequence_args *args, | 722 | struct nfs4_sequence_args *args, |
715 | struct nfs4_sequence_res *res, | 723 | struct nfs4_sequence_res *res, |
716 | int cache_reply) | 724 | int cache_reply) |
717 | { | 725 | { |
718 | args->sa_session = res->sr_session = NULL; | 726 | args->sa_session = res->sr_session = NULL; |
719 | return rpc_call_sync(server->client, msg, 0); | 727 | return rpc_call_sync(clnt, msg, 0); |
720 | } | 728 | } |
721 | 729 | ||
722 | #define nfs4_call_sync(server, msg, args, res, cache_reply) \ | 730 | static inline |
723 | (server)->nfs_client->cl_mvops->call_sync((server), (msg), &(args)->seq_args, \ | 731 | int nfs4_call_sync(struct rpc_clnt *clnt, |
724 | &(res)->seq_res, (cache_reply)) | 732 | struct nfs_server *server, |
733 | struct rpc_message *msg, | ||
734 | struct nfs4_sequence_args *args, | ||
735 | struct nfs4_sequence_res *res, | ||
736 | int cache_reply) | ||
737 | { | ||
738 | return server->nfs_client->cl_mvops->call_sync(clnt, server, msg, | ||
739 | args, res, cache_reply); | ||
740 | } | ||
725 | 741 | ||
726 | static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) | 742 | static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) |
727 | { | 743 | { |
@@ -1831,7 +1847,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
1831 | } else | 1847 | } else |
1832 | memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); | 1848 | memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); |
1833 | 1849 | ||
1834 | status = nfs4_call_sync(server, &msg, &arg, &res, 1); | 1850 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
1835 | if (status == 0 && state != NULL) | 1851 | if (status == 0 && state != NULL) |
1836 | renew_lease(server, timestamp); | 1852 | renew_lease(server, timestamp); |
1837 | return status; | 1853 | return status; |
@@ -2090,7 +2106,7 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f | |||
2090 | }; | 2106 | }; |
2091 | int status; | 2107 | int status; |
2092 | 2108 | ||
2093 | status = nfs4_call_sync(server, &msg, &args, &res, 0); | 2109 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
2094 | if (status == 0) { | 2110 | if (status == 0) { |
2095 | memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask)); | 2111 | memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask)); |
2096 | server->caps &= ~(NFS_CAP_ACLS|NFS_CAP_HARDLINKS| | 2112 | server->caps &= ~(NFS_CAP_ACLS|NFS_CAP_HARDLINKS| |
@@ -2160,7 +2176,7 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2160 | }; | 2176 | }; |
2161 | 2177 | ||
2162 | nfs_fattr_init(info->fattr); | 2178 | nfs_fattr_init(info->fattr); |
2163 | return nfs4_call_sync(server, &msg, &args, &res, 0); | 2179 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
2164 | } | 2180 | } |
2165 | 2181 | ||
2166 | static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | 2182 | static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, |
@@ -2176,15 +2192,43 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2176 | return err; | 2192 | return err; |
2177 | } | 2193 | } |
2178 | 2194 | ||
2195 | static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, | ||
2196 | struct nfs_fsinfo *info, rpc_authflavor_t flavor) | ||
2197 | { | ||
2198 | struct rpc_auth *auth; | ||
2199 | int ret; | ||
2200 | |||
2201 | auth = rpcauth_create(flavor, server->client); | ||
2202 | if (!auth) { | ||
2203 | ret = -EIO; | ||
2204 | goto out; | ||
2205 | } | ||
2206 | ret = nfs4_lookup_root(server, fhandle, info); | ||
2207 | if (ret < 0) | ||
2208 | ret = -EAGAIN; | ||
2209 | out: | ||
2210 | return ret; | ||
2211 | } | ||
2212 | |||
2179 | /* | 2213 | /* |
2180 | * get the file handle for the "/" directory on the server | 2214 | * get the file handle for the "/" directory on the server |
2181 | */ | 2215 | */ |
2182 | static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | 2216 | static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, |
2183 | struct nfs_fsinfo *info) | 2217 | struct nfs_fsinfo *info) |
2184 | { | 2218 | { |
2185 | int status; | 2219 | int i, len, status = 0; |
2220 | rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS + 2]; | ||
2221 | |||
2222 | flav_array[0] = RPC_AUTH_UNIX; | ||
2223 | len = gss_mech_list_pseudoflavors(&flav_array[1]); | ||
2224 | flav_array[1+len] = RPC_AUTH_NULL; | ||
2225 | len += 2; | ||
2186 | 2226 | ||
2187 | status = nfs4_lookup_root(server, fhandle, info); | 2227 | for (i = 0; i < len; i++) { |
2228 | status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); | ||
2229 | if (status == 0) | ||
2230 | break; | ||
2231 | } | ||
2188 | if (status == 0) | 2232 | if (status == 0) |
2189 | status = nfs4_server_capabilities(server, fhandle); | 2233 | status = nfs4_server_capabilities(server, fhandle); |
2190 | if (status == 0) | 2234 | if (status == 0) |
@@ -2249,7 +2293,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2249 | }; | 2293 | }; |
2250 | 2294 | ||
2251 | nfs_fattr_init(fattr); | 2295 | nfs_fattr_init(fattr); |
2252 | return nfs4_call_sync(server, &msg, &args, &res, 0); | 2296 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
2253 | } | 2297 | } |
2254 | 2298 | ||
2255 | static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 2299 | static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) |
@@ -2309,9 +2353,9 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
2309 | return status; | 2353 | return status; |
2310 | } | 2354 | } |
2311 | 2355 | ||
2312 | static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *dirfh, | 2356 | static int _nfs4_proc_lookupfh(struct rpc_clnt *clnt, struct nfs_server *server, |
2313 | const struct qstr *name, struct nfs_fh *fhandle, | 2357 | const struct nfs_fh *dirfh, const struct qstr *name, |
2314 | struct nfs_fattr *fattr) | 2358 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) |
2315 | { | 2359 | { |
2316 | int status; | 2360 | int status; |
2317 | struct nfs4_lookup_arg args = { | 2361 | struct nfs4_lookup_arg args = { |
@@ -2333,7 +2377,7 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d | |||
2333 | nfs_fattr_init(fattr); | 2377 | nfs_fattr_init(fattr); |
2334 | 2378 | ||
2335 | dprintk("NFS call lookupfh %s\n", name->name); | 2379 | dprintk("NFS call lookupfh %s\n", name->name); |
2336 | status = nfs4_call_sync(server, &msg, &args, &res, 0); | 2380 | status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, &res.seq_res, 0); |
2337 | dprintk("NFS reply lookupfh: %d\n", status); | 2381 | dprintk("NFS reply lookupfh: %d\n", status); |
2338 | return status; | 2382 | return status; |
2339 | } | 2383 | } |
@@ -2345,7 +2389,7 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, | |||
2345 | struct nfs4_exception exception = { }; | 2389 | struct nfs4_exception exception = { }; |
2346 | int err; | 2390 | int err; |
2347 | do { | 2391 | do { |
2348 | err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr); | 2392 | err = _nfs4_proc_lookupfh(server->client, server, dirfh, name, fhandle, fattr); |
2349 | /* FIXME: !!!! */ | 2393 | /* FIXME: !!!! */ |
2350 | if (err == -NFS4ERR_MOVED) { | 2394 | if (err == -NFS4ERR_MOVED) { |
2351 | err = -EREMOTE; | 2395 | err = -EREMOTE; |
@@ -2356,27 +2400,41 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, | |||
2356 | return err; | 2400 | return err; |
2357 | } | 2401 | } |
2358 | 2402 | ||
2359 | static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, | 2403 | static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, |
2360 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 2404 | const struct qstr *name, struct nfs_fh *fhandle, |
2405 | struct nfs_fattr *fattr) | ||
2361 | { | 2406 | { |
2362 | int status; | 2407 | int status; |
2363 | 2408 | ||
2364 | dprintk("NFS call lookup %s\n", name->name); | 2409 | dprintk("NFS call lookup %s\n", name->name); |
2365 | status = _nfs4_proc_lookupfh(NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr); | 2410 | status = _nfs4_proc_lookupfh(clnt, NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr); |
2366 | if (status == -NFS4ERR_MOVED) | 2411 | if (status == -NFS4ERR_MOVED) |
2367 | status = nfs4_get_referral(dir, name, fattr, fhandle); | 2412 | status = nfs4_get_referral(dir, name, fattr, fhandle); |
2368 | dprintk("NFS reply lookup: %d\n", status); | 2413 | dprintk("NFS reply lookup: %d\n", status); |
2369 | return status; | 2414 | return status; |
2370 | } | 2415 | } |
2371 | 2416 | ||
2372 | static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 2417 | void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr, struct nfs_fh *fh) |
2418 | { | ||
2419 | memset(fh, 0, sizeof(struct nfs_fh)); | ||
2420 | fattr->fsid.major = 1; | ||
2421 | fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | | ||
2422 | NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_FSID | NFS_ATTR_FATTR_MOUNTPOINT; | ||
2423 | fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO; | ||
2424 | fattr->nlink = 2; | ||
2425 | } | ||
2426 | |||
2427 | static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, | ||
2428 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | ||
2373 | { | 2429 | { |
2374 | struct nfs4_exception exception = { }; | 2430 | struct nfs4_exception exception = { }; |
2375 | int err; | 2431 | int err; |
2376 | do { | 2432 | do { |
2377 | err = nfs4_handle_exception(NFS_SERVER(dir), | 2433 | err = nfs4_handle_exception(NFS_SERVER(dir), |
2378 | _nfs4_proc_lookup(dir, name, fhandle, fattr), | 2434 | _nfs4_proc_lookup(clnt, dir, name, fhandle, fattr), |
2379 | &exception); | 2435 | &exception); |
2436 | if (err == -EPERM) | ||
2437 | nfs_fixup_secinfo_attributes(fattr, fhandle); | ||
2380 | } while (exception.retry); | 2438 | } while (exception.retry); |
2381 | return err; | 2439 | return err; |
2382 | } | 2440 | } |
@@ -2421,7 +2479,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry | |||
2421 | if (res.fattr == NULL) | 2479 | if (res.fattr == NULL) |
2422 | return -ENOMEM; | 2480 | return -ENOMEM; |
2423 | 2481 | ||
2424 | status = nfs4_call_sync(server, &msg, &args, &res, 0); | 2482 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
2425 | if (!status) { | 2483 | if (!status) { |
2426 | entry->mask = 0; | 2484 | entry->mask = 0; |
2427 | if (res.access & NFS4_ACCESS_READ) | 2485 | if (res.access & NFS4_ACCESS_READ) |
@@ -2488,7 +2546,7 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page, | |||
2488 | .rpc_resp = &res, | 2546 | .rpc_resp = &res, |
2489 | }; | 2547 | }; |
2490 | 2548 | ||
2491 | return nfs4_call_sync(NFS_SERVER(inode), &msg, &args, &res, 0); | 2549 | return nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0); |
2492 | } | 2550 | } |
2493 | 2551 | ||
2494 | static int nfs4_proc_readlink(struct inode *inode, struct page *page, | 2552 | static int nfs4_proc_readlink(struct inode *inode, struct page *page, |
@@ -2577,7 +2635,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) | |||
2577 | if (res.dir_attr == NULL) | 2635 | if (res.dir_attr == NULL) |
2578 | goto out; | 2636 | goto out; |
2579 | 2637 | ||
2580 | status = nfs4_call_sync(server, &msg, &args, &res, 1); | 2638 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); |
2581 | if (status == 0) { | 2639 | if (status == 0) { |
2582 | update_changeattr(dir, &res.cinfo); | 2640 | update_changeattr(dir, &res.cinfo); |
2583 | nfs_post_op_update_inode(dir, res.dir_attr); | 2641 | nfs_post_op_update_inode(dir, res.dir_attr); |
@@ -2678,7 +2736,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
2678 | if (res.old_fattr == NULL || res.new_fattr == NULL) | 2736 | if (res.old_fattr == NULL || res.new_fattr == NULL) |
2679 | goto out; | 2737 | goto out; |
2680 | 2738 | ||
2681 | status = nfs4_call_sync(server, &msg, &arg, &res, 1); | 2739 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
2682 | if (!status) { | 2740 | if (!status) { |
2683 | update_changeattr(old_dir, &res.old_cinfo); | 2741 | update_changeattr(old_dir, &res.old_cinfo); |
2684 | nfs_post_op_update_inode(old_dir, res.old_fattr); | 2742 | nfs_post_op_update_inode(old_dir, res.old_fattr); |
@@ -2729,7 +2787,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * | |||
2729 | if (res.fattr == NULL || res.dir_attr == NULL) | 2787 | if (res.fattr == NULL || res.dir_attr == NULL) |
2730 | goto out; | 2788 | goto out; |
2731 | 2789 | ||
2732 | status = nfs4_call_sync(server, &msg, &arg, &res, 1); | 2790 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
2733 | if (!status) { | 2791 | if (!status) { |
2734 | update_changeattr(dir, &res.cinfo); | 2792 | update_changeattr(dir, &res.cinfo); |
2735 | nfs_post_op_update_inode(dir, res.dir_attr); | 2793 | nfs_post_op_update_inode(dir, res.dir_attr); |
@@ -2792,8 +2850,8 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, | |||
2792 | 2850 | ||
2793 | static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) | 2851 | static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) |
2794 | { | 2852 | { |
2795 | int status = nfs4_call_sync(NFS_SERVER(dir), &data->msg, | 2853 | int status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &data->msg, |
2796 | &data->arg, &data->res, 1); | 2854 | &data->arg.seq_args, &data->res.seq_res, 1); |
2797 | if (status == 0) { | 2855 | if (status == 0) { |
2798 | update_changeattr(dir, &data->res.dir_cinfo); | 2856 | update_changeattr(dir, &data->res.dir_cinfo); |
2799 | nfs_post_op_update_inode(dir, data->res.dir_fattr); | 2857 | nfs_post_op_update_inode(dir, data->res.dir_fattr); |
@@ -2905,7 +2963,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
2905 | (unsigned long long)cookie); | 2963 | (unsigned long long)cookie); |
2906 | nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); | 2964 | nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); |
2907 | res.pgbase = args.pgbase; | 2965 | res.pgbase = args.pgbase; |
2908 | status = nfs4_call_sync(NFS_SERVER(dir), &msg, &args, &res, 0); | 2966 | status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); |
2909 | if (status >= 0) { | 2967 | if (status >= 0) { |
2910 | memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); | 2968 | memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); |
2911 | status += args.pgbase; | 2969 | status += args.pgbase; |
@@ -2997,7 +3055,7 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2997 | }; | 3055 | }; |
2998 | 3056 | ||
2999 | nfs_fattr_init(fsstat->fattr); | 3057 | nfs_fattr_init(fsstat->fattr); |
3000 | return nfs4_call_sync(server, &msg, &args, &res, 0); | 3058 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
3001 | } | 3059 | } |
3002 | 3060 | ||
3003 | static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat) | 3061 | static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat) |
@@ -3028,7 +3086,7 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, | |||
3028 | .rpc_resp = &res, | 3086 | .rpc_resp = &res, |
3029 | }; | 3087 | }; |
3030 | 3088 | ||
3031 | return nfs4_call_sync(server, &msg, &args, &res, 0); | 3089 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
3032 | } | 3090 | } |
3033 | 3091 | ||
3034 | static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) | 3092 | static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) |
@@ -3073,7 +3131,7 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle | |||
3073 | } | 3131 | } |
3074 | 3132 | ||
3075 | nfs_fattr_init(pathconf->fattr); | 3133 | nfs_fattr_init(pathconf->fattr); |
3076 | return nfs4_call_sync(server, &msg, &args, &res, 0); | 3134 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
3077 | } | 3135 | } |
3078 | 3136 | ||
3079 | static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | 3137 | static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, |
@@ -3195,12 +3253,9 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag | |||
3195 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; | 3253 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; |
3196 | } | 3254 | } |
3197 | 3255 | ||
3198 | static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) | 3256 | static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_write_data *data) |
3199 | { | 3257 | { |
3200 | struct inode *inode = data->inode; | 3258 | struct inode *inode = data->inode; |
3201 | |||
3202 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | ||
3203 | return -EAGAIN; | ||
3204 | 3259 | ||
3205 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { | 3260 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { |
3206 | nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); | 3261 | nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); |
@@ -3210,11 +3265,24 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) | |||
3210 | return 0; | 3265 | return 0; |
3211 | } | 3266 | } |
3212 | 3267 | ||
3268 | static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) | ||
3269 | { | ||
3270 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | ||
3271 | return -EAGAIN; | ||
3272 | return data->write_done_cb(task, data); | ||
3273 | } | ||
3274 | |||
3213 | static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) | 3275 | static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) |
3214 | { | 3276 | { |
3215 | struct nfs_server *server = NFS_SERVER(data->inode); | 3277 | struct nfs_server *server = NFS_SERVER(data->inode); |
3216 | 3278 | ||
3217 | data->args.bitmask = server->cache_consistency_bitmask; | 3279 | if (data->lseg) { |
3280 | data->args.bitmask = NULL; | ||
3281 | data->res.fattr = NULL; | ||
3282 | } else | ||
3283 | data->args.bitmask = server->cache_consistency_bitmask; | ||
3284 | if (!data->write_done_cb) | ||
3285 | data->write_done_cb = nfs4_commit_done_cb; | ||
3218 | data->res.server = server; | 3286 | data->res.server = server; |
3219 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; | 3287 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; |
3220 | } | 3288 | } |
@@ -3452,7 +3520,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
3452 | resp_buf = buf; | 3520 | resp_buf = buf; |
3453 | buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); | 3521 | buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); |
3454 | } | 3522 | } |
3455 | ret = nfs4_call_sync(NFS_SERVER(inode), &msg, &args, &res, 0); | 3523 | ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0); |
3456 | if (ret) | 3524 | if (ret) |
3457 | goto out_free; | 3525 | goto out_free; |
3458 | if (res.acl_len > args.acl_len) | 3526 | if (res.acl_len > args.acl_len) |
@@ -3527,7 +3595,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl | |||
3527 | if (i < 0) | 3595 | if (i < 0) |
3528 | return i; | 3596 | return i; |
3529 | nfs_inode_return_delegation(inode); | 3597 | nfs_inode_return_delegation(inode); |
3530 | ret = nfs4_call_sync(server, &msg, &arg, &res, 1); | 3598 | ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
3531 | 3599 | ||
3532 | /* | 3600 | /* |
3533 | * Free each page after tx, so the only ref left is | 3601 | * Free each page after tx, so the only ref left is |
@@ -3890,7 +3958,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock | |||
3890 | lsp = request->fl_u.nfs4_fl.owner; | 3958 | lsp = request->fl_u.nfs4_fl.owner; |
3891 | arg.lock_owner.id = lsp->ls_id.id; | 3959 | arg.lock_owner.id = lsp->ls_id.id; |
3892 | arg.lock_owner.s_dev = server->s_dev; | 3960 | arg.lock_owner.s_dev = server->s_dev; |
3893 | status = nfs4_call_sync(server, &msg, &arg, &res, 1); | 3961 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
3894 | switch (status) { | 3962 | switch (status) { |
3895 | case 0: | 3963 | case 0: |
3896 | request->fl_type = F_UNLCK; | 3964 | request->fl_type = F_UNLCK; |
@@ -4618,12 +4686,46 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | |||
4618 | nfs_fattr_init(&fs_locations->fattr); | 4686 | nfs_fattr_init(&fs_locations->fattr); |
4619 | fs_locations->server = server; | 4687 | fs_locations->server = server; |
4620 | fs_locations->nlocations = 0; | 4688 | fs_locations->nlocations = 0; |
4621 | status = nfs4_call_sync(server, &msg, &args, &res, 0); | 4689 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
4622 | nfs_fixup_referral_attributes(&fs_locations->fattr); | 4690 | nfs_fixup_referral_attributes(&fs_locations->fattr); |
4623 | dprintk("%s: returned status = %d\n", __func__, status); | 4691 | dprintk("%s: returned status = %d\n", __func__, status); |
4624 | return status; | 4692 | return status; |
4625 | } | 4693 | } |
4626 | 4694 | ||
4695 | static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors) | ||
4696 | { | ||
4697 | int status; | ||
4698 | struct nfs4_secinfo_arg args = { | ||
4699 | .dir_fh = NFS_FH(dir), | ||
4700 | .name = name, | ||
4701 | }; | ||
4702 | struct nfs4_secinfo_res res = { | ||
4703 | .flavors = flavors, | ||
4704 | }; | ||
4705 | struct rpc_message msg = { | ||
4706 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SECINFO], | ||
4707 | .rpc_argp = &args, | ||
4708 | .rpc_resp = &res, | ||
4709 | }; | ||
4710 | |||
4711 | dprintk("NFS call secinfo %s\n", name->name); | ||
4712 | status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); | ||
4713 | dprintk("NFS reply secinfo: %d\n", status); | ||
4714 | return status; | ||
4715 | } | ||
4716 | |||
4717 | int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors) | ||
4718 | { | ||
4719 | struct nfs4_exception exception = { }; | ||
4720 | int err; | ||
4721 | do { | ||
4722 | err = nfs4_handle_exception(NFS_SERVER(dir), | ||
4723 | _nfs4_proc_secinfo(dir, name, flavors), | ||
4724 | &exception); | ||
4725 | } while (exception.retry); | ||
4726 | return err; | ||
4727 | } | ||
4728 | |||
4627 | #ifdef CONFIG_NFS_V4_1 | 4729 | #ifdef CONFIG_NFS_V4_1 |
4628 | /* | 4730 | /* |
4629 | * Check the exchange flags returned by the server for invalid flags, having | 4731 | * Check the exchange flags returned by the server for invalid flags, having |
@@ -5516,8 +5618,6 @@ static void nfs4_layoutget_release(void *calldata) | |||
5516 | struct nfs4_layoutget *lgp = calldata; | 5618 | struct nfs4_layoutget *lgp = calldata; |
5517 | 5619 | ||
5518 | dprintk("--> %s\n", __func__); | 5620 | dprintk("--> %s\n", __func__); |
5519 | if (lgp->res.layout.buf != NULL) | ||
5520 | free_page((unsigned long) lgp->res.layout.buf); | ||
5521 | put_nfs_open_context(lgp->args.ctx); | 5621 | put_nfs_open_context(lgp->args.ctx); |
5522 | kfree(calldata); | 5622 | kfree(calldata); |
5523 | dprintk("<-- %s\n", __func__); | 5623 | dprintk("<-- %s\n", __func__); |
@@ -5549,12 +5649,7 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) | |||
5549 | 5649 | ||
5550 | dprintk("--> %s\n", __func__); | 5650 | dprintk("--> %s\n", __func__); |
5551 | 5651 | ||
5552 | lgp->res.layout.buf = (void *)__get_free_page(GFP_NOFS); | 5652 | lgp->res.layoutp = &lgp->args.layout; |
5553 | if (lgp->res.layout.buf == NULL) { | ||
5554 | nfs4_layoutget_release(lgp); | ||
5555 | return -ENOMEM; | ||
5556 | } | ||
5557 | |||
5558 | lgp->res.seq_res.sr_slot = NULL; | 5653 | lgp->res.seq_res.sr_slot = NULL; |
5559 | task = rpc_run_task(&task_setup_data); | 5654 | task = rpc_run_task(&task_setup_data); |
5560 | if (IS_ERR(task)) | 5655 | if (IS_ERR(task)) |
@@ -5586,7 +5681,7 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | |||
5586 | int status; | 5681 | int status; |
5587 | 5682 | ||
5588 | dprintk("--> %s\n", __func__); | 5683 | dprintk("--> %s\n", __func__); |
5589 | status = nfs4_call_sync(server, &msg, &args, &res, 0); | 5684 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
5590 | dprintk("<-- %s status=%d\n", __func__, status); | 5685 | dprintk("<-- %s status=%d\n", __func__, status); |
5591 | 5686 | ||
5592 | return status; | 5687 | return status; |
@@ -5606,6 +5701,100 @@ int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | |||
5606 | } | 5701 | } |
5607 | EXPORT_SYMBOL_GPL(nfs4_proc_getdeviceinfo); | 5702 | EXPORT_SYMBOL_GPL(nfs4_proc_getdeviceinfo); |
5608 | 5703 | ||
5704 | static void nfs4_layoutcommit_prepare(struct rpc_task *task, void *calldata) | ||
5705 | { | ||
5706 | struct nfs4_layoutcommit_data *data = calldata; | ||
5707 | struct nfs_server *server = NFS_SERVER(data->args.inode); | ||
5708 | |||
5709 | if (nfs4_setup_sequence(server, &data->args.seq_args, | ||
5710 | &data->res.seq_res, 1, task)) | ||
5711 | return; | ||
5712 | rpc_call_start(task); | ||
5713 | } | ||
5714 | |||
5715 | static void | ||
5716 | nfs4_layoutcommit_done(struct rpc_task *task, void *calldata) | ||
5717 | { | ||
5718 | struct nfs4_layoutcommit_data *data = calldata; | ||
5719 | struct nfs_server *server = NFS_SERVER(data->args.inode); | ||
5720 | |||
5721 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | ||
5722 | return; | ||
5723 | |||
5724 | switch (task->tk_status) { /* Just ignore these failures */ | ||
5725 | case NFS4ERR_DELEG_REVOKED: /* layout was recalled */ | ||
5726 | case NFS4ERR_BADIOMODE: /* no IOMODE_RW layout for range */ | ||
5727 | case NFS4ERR_BADLAYOUT: /* no layout */ | ||
5728 | case NFS4ERR_GRACE: /* loca_recalim always false */ | ||
5729 | task->tk_status = 0; | ||
5730 | } | ||
5731 | |||
5732 | if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { | ||
5733 | nfs_restart_rpc(task, server->nfs_client); | ||
5734 | return; | ||
5735 | } | ||
5736 | |||
5737 | if (task->tk_status == 0) | ||
5738 | nfs_post_op_update_inode_force_wcc(data->args.inode, | ||
5739 | data->res.fattr); | ||
5740 | } | ||
5741 | |||
5742 | static void nfs4_layoutcommit_release(void *calldata) | ||
5743 | { | ||
5744 | struct nfs4_layoutcommit_data *data = calldata; | ||
5745 | |||
5746 | /* Matched by references in pnfs_set_layoutcommit */ | ||
5747 | put_lseg(data->lseg); | ||
5748 | put_rpccred(data->cred); | ||
5749 | kfree(data); | ||
5750 | } | ||
5751 | |||
5752 | static const struct rpc_call_ops nfs4_layoutcommit_ops = { | ||
5753 | .rpc_call_prepare = nfs4_layoutcommit_prepare, | ||
5754 | .rpc_call_done = nfs4_layoutcommit_done, | ||
5755 | .rpc_release = nfs4_layoutcommit_release, | ||
5756 | }; | ||
5757 | |||
5758 | int | ||
5759 | nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync) | ||
5760 | { | ||
5761 | struct rpc_message msg = { | ||
5762 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTCOMMIT], | ||
5763 | .rpc_argp = &data->args, | ||
5764 | .rpc_resp = &data->res, | ||
5765 | .rpc_cred = data->cred, | ||
5766 | }; | ||
5767 | struct rpc_task_setup task_setup_data = { | ||
5768 | .task = &data->task, | ||
5769 | .rpc_client = NFS_CLIENT(data->args.inode), | ||
5770 | .rpc_message = &msg, | ||
5771 | .callback_ops = &nfs4_layoutcommit_ops, | ||
5772 | .callback_data = data, | ||
5773 | .flags = RPC_TASK_ASYNC, | ||
5774 | }; | ||
5775 | struct rpc_task *task; | ||
5776 | int status = 0; | ||
5777 | |||
5778 | dprintk("NFS: %4d initiating layoutcommit call. sync %d " | ||
5779 | "lbw: %llu inode %lu\n", | ||
5780 | data->task.tk_pid, sync, | ||
5781 | data->args.lastbytewritten, | ||
5782 | data->args.inode->i_ino); | ||
5783 | |||
5784 | task = rpc_run_task(&task_setup_data); | ||
5785 | if (IS_ERR(task)) | ||
5786 | return PTR_ERR(task); | ||
5787 | if (sync == false) | ||
5788 | goto out; | ||
5789 | status = nfs4_wait_for_completion_rpc_task(task); | ||
5790 | if (status != 0) | ||
5791 | goto out; | ||
5792 | status = task->tk_status; | ||
5793 | out: | ||
5794 | dprintk("%s: status %d\n", __func__, status); | ||
5795 | rpc_put_task(task); | ||
5796 | return status; | ||
5797 | } | ||
5609 | #endif /* CONFIG_NFS_V4_1 */ | 5798 | #endif /* CONFIG_NFS_V4_1 */ |
5610 | 5799 | ||
5611 | struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { | 5800 | struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { |
@@ -5741,6 +5930,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
5741 | .close_context = nfs4_close_context, | 5930 | .close_context = nfs4_close_context, |
5742 | .open_context = nfs4_atomic_open, | 5931 | .open_context = nfs4_atomic_open, |
5743 | .init_client = nfs4_init_client, | 5932 | .init_client = nfs4_init_client, |
5933 | .secinfo = nfs4_proc_secinfo, | ||
5744 | }; | 5934 | }; |
5745 | 5935 | ||
5746 | static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { | 5936 | static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { |