aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c300
1 files changed, 244 insertions, 56 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 1d84e7088af9..9bf41eab3e46 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);
71static int _nfs4_recover_proc_open(struct nfs4_opendata *data); 72static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
72static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); 73static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
73static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); 74static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *);
74static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr); 75static 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);
75static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); 78static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
76static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, 79static 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
660static int nfs4_call_sync_sequence(struct nfs_server *server, 665static 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
695int _nfs4_call_sync_session(struct nfs_server *server, 701int _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
712int _nfs4_call_sync(struct nfs_server *server, 719int _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) \ 730static inline
723 (server)->nfs_client->cl_mvops->call_sync((server), (msg), &(args)->seq_args, \ 731int 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
726static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) 742static 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
2166static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, 2182static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -2176,15 +2192,41 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
2176 return err; 2192 return err;
2177} 2193}
2178 2194
2195static 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);
2207out:
2208 return ret;
2209}
2210
2179/* 2211/*
2180 * get the file handle for the "/" directory on the server 2212 * get the file handle for the "/" directory on the server
2181 */ 2213 */
2182static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, 2214static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
2183 struct nfs_fsinfo *info) 2215 struct nfs_fsinfo *info)
2184{ 2216{
2185 int status; 2217 int i, len, status = 0;
2218 rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS + 2];
2186 2219
2187 status = nfs4_lookup_root(server, fhandle, info); 2220 flav_array[0] = RPC_AUTH_UNIX;
2221 len = gss_mech_list_pseudoflavors(&flav_array[1]);
2222 flav_array[1+len] = RPC_AUTH_NULL;
2223 len += 2;
2224
2225 for (i = 0; i < len; i++) {
2226 status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]);
2227 if (status != -EPERM)
2228 break;
2229 }
2188 if (status == 0) 2230 if (status == 0)
2189 status = nfs4_server_capabilities(server, fhandle); 2231 status = nfs4_server_capabilities(server, fhandle);
2190 if (status == 0) 2232 if (status == 0)
@@ -2249,7 +2291,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
2249 }; 2291 };
2250 2292
2251 nfs_fattr_init(fattr); 2293 nfs_fattr_init(fattr);
2252 return nfs4_call_sync(server, &msg, &args, &res, 0); 2294 return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
2253} 2295}
2254 2296
2255static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) 2297static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
@@ -2309,9 +2351,9 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
2309 return status; 2351 return status;
2310} 2352}
2311 2353
2312static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *dirfh, 2354static int _nfs4_proc_lookupfh(struct rpc_clnt *clnt, struct nfs_server *server,
2313 const struct qstr *name, struct nfs_fh *fhandle, 2355 const struct nfs_fh *dirfh, const struct qstr *name,
2314 struct nfs_fattr *fattr) 2356 struct nfs_fh *fhandle, struct nfs_fattr *fattr)
2315{ 2357{
2316 int status; 2358 int status;
2317 struct nfs4_lookup_arg args = { 2359 struct nfs4_lookup_arg args = {
@@ -2333,7 +2375,7 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d
2333 nfs_fattr_init(fattr); 2375 nfs_fattr_init(fattr);
2334 2376
2335 dprintk("NFS call lookupfh %s\n", name->name); 2377 dprintk("NFS call lookupfh %s\n", name->name);
2336 status = nfs4_call_sync(server, &msg, &args, &res, 0); 2378 status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, &res.seq_res, 0);
2337 dprintk("NFS reply lookupfh: %d\n", status); 2379 dprintk("NFS reply lookupfh: %d\n", status);
2338 return status; 2380 return status;
2339} 2381}
@@ -2345,7 +2387,7 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh,
2345 struct nfs4_exception exception = { }; 2387 struct nfs4_exception exception = { };
2346 int err; 2388 int err;
2347 do { 2389 do {
2348 err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr); 2390 err = _nfs4_proc_lookupfh(server->client, server, dirfh, name, fhandle, fattr);
2349 /* FIXME: !!!! */ 2391 /* FIXME: !!!! */
2350 if (err == -NFS4ERR_MOVED) { 2392 if (err == -NFS4ERR_MOVED) {
2351 err = -EREMOTE; 2393 err = -EREMOTE;
@@ -2356,27 +2398,41 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh,
2356 return err; 2398 return err;
2357} 2399}
2358 2400
2359static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, 2401static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir,
2360 struct nfs_fh *fhandle, struct nfs_fattr *fattr) 2402 const struct qstr *name, struct nfs_fh *fhandle,
2403 struct nfs_fattr *fattr)
2361{ 2404{
2362 int status; 2405 int status;
2363 2406
2364 dprintk("NFS call lookup %s\n", name->name); 2407 dprintk("NFS call lookup %s\n", name->name);
2365 status = _nfs4_proc_lookupfh(NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr); 2408 status = _nfs4_proc_lookupfh(clnt, NFS_SERVER(dir), NFS_FH(dir), name, fhandle, fattr);
2366 if (status == -NFS4ERR_MOVED) 2409 if (status == -NFS4ERR_MOVED)
2367 status = nfs4_get_referral(dir, name, fattr, fhandle); 2410 status = nfs4_get_referral(dir, name, fattr, fhandle);
2368 dprintk("NFS reply lookup: %d\n", status); 2411 dprintk("NFS reply lookup: %d\n", status);
2369 return status; 2412 return status;
2370} 2413}
2371 2414
2372static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) 2415void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr, struct nfs_fh *fh)
2416{
2417 memset(fh, 0, sizeof(struct nfs_fh));
2418 fattr->fsid.major = 1;
2419 fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE |
2420 NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_FSID | NFS_ATTR_FATTR_MOUNTPOINT;
2421 fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO;
2422 fattr->nlink = 2;
2423}
2424
2425static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name,
2426 struct nfs_fh *fhandle, struct nfs_fattr *fattr)
2373{ 2427{
2374 struct nfs4_exception exception = { }; 2428 struct nfs4_exception exception = { };
2375 int err; 2429 int err;
2376 do { 2430 do {
2377 err = nfs4_handle_exception(NFS_SERVER(dir), 2431 err = nfs4_handle_exception(NFS_SERVER(dir),
2378 _nfs4_proc_lookup(dir, name, fhandle, fattr), 2432 _nfs4_proc_lookup(clnt, dir, name, fhandle, fattr),
2379 &exception); 2433 &exception);
2434 if (err == -EPERM)
2435 nfs_fixup_secinfo_attributes(fattr, fhandle);
2380 } while (exception.retry); 2436 } while (exception.retry);
2381 return err; 2437 return err;
2382} 2438}
@@ -2421,7 +2477,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
2421 if (res.fattr == NULL) 2477 if (res.fattr == NULL)
2422 return -ENOMEM; 2478 return -ENOMEM;
2423 2479
2424 status = nfs4_call_sync(server, &msg, &args, &res, 0); 2480 status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
2425 if (!status) { 2481 if (!status) {
2426 entry->mask = 0; 2482 entry->mask = 0;
2427 if (res.access & NFS4_ACCESS_READ) 2483 if (res.access & NFS4_ACCESS_READ)
@@ -2488,7 +2544,7 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page,
2488 .rpc_resp = &res, 2544 .rpc_resp = &res,
2489 }; 2545 };
2490 2546
2491 return nfs4_call_sync(NFS_SERVER(inode), &msg, &args, &res, 0); 2547 return nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0);
2492} 2548}
2493 2549
2494static int nfs4_proc_readlink(struct inode *inode, struct page *page, 2550static int nfs4_proc_readlink(struct inode *inode, struct page *page,
@@ -2577,7 +2633,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
2577 if (res.dir_attr == NULL) 2633 if (res.dir_attr == NULL)
2578 goto out; 2634 goto out;
2579 2635
2580 status = nfs4_call_sync(server, &msg, &args, &res, 1); 2636 status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1);
2581 if (status == 0) { 2637 if (status == 0) {
2582 update_changeattr(dir, &res.cinfo); 2638 update_changeattr(dir, &res.cinfo);
2583 nfs_post_op_update_inode(dir, res.dir_attr); 2639 nfs_post_op_update_inode(dir, res.dir_attr);
@@ -2678,7 +2734,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
2678 if (res.old_fattr == NULL || res.new_fattr == NULL) 2734 if (res.old_fattr == NULL || res.new_fattr == NULL)
2679 goto out; 2735 goto out;
2680 2736
2681 status = nfs4_call_sync(server, &msg, &arg, &res, 1); 2737 status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
2682 if (!status) { 2738 if (!status) {
2683 update_changeattr(old_dir, &res.old_cinfo); 2739 update_changeattr(old_dir, &res.old_cinfo);
2684 nfs_post_op_update_inode(old_dir, res.old_fattr); 2740 nfs_post_op_update_inode(old_dir, res.old_fattr);
@@ -2729,7 +2785,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *
2729 if (res.fattr == NULL || res.dir_attr == NULL) 2785 if (res.fattr == NULL || res.dir_attr == NULL)
2730 goto out; 2786 goto out;
2731 2787
2732 status = nfs4_call_sync(server, &msg, &arg, &res, 1); 2788 status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
2733 if (!status) { 2789 if (!status) {
2734 update_changeattr(dir, &res.cinfo); 2790 update_changeattr(dir, &res.cinfo);
2735 nfs_post_op_update_inode(dir, res.dir_attr); 2791 nfs_post_op_update_inode(dir, res.dir_attr);
@@ -2792,8 +2848,8 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
2792 2848
2793static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data) 2849static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data)
2794{ 2850{
2795 int status = nfs4_call_sync(NFS_SERVER(dir), &data->msg, 2851 int status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &data->msg,
2796 &data->arg, &data->res, 1); 2852 &data->arg.seq_args, &data->res.seq_res, 1);
2797 if (status == 0) { 2853 if (status == 0) {
2798 update_changeattr(dir, &data->res.dir_cinfo); 2854 update_changeattr(dir, &data->res.dir_cinfo);
2799 nfs_post_op_update_inode(dir, data->res.dir_fattr); 2855 nfs_post_op_update_inode(dir, data->res.dir_fattr);
@@ -2905,7 +2961,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
2905 (unsigned long long)cookie); 2961 (unsigned long long)cookie);
2906 nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); 2962 nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args);
2907 res.pgbase = args.pgbase; 2963 res.pgbase = args.pgbase;
2908 status = nfs4_call_sync(NFS_SERVER(dir), &msg, &args, &res, 0); 2964 status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0);
2909 if (status >= 0) { 2965 if (status >= 0) {
2910 memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); 2966 memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
2911 status += args.pgbase; 2967 status += args.pgbase;
@@ -2997,7 +3053,7 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
2997 }; 3053 };
2998 3054
2999 nfs_fattr_init(fsstat->fattr); 3055 nfs_fattr_init(fsstat->fattr);
3000 return nfs4_call_sync(server, &msg, &args, &res, 0); 3056 return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
3001} 3057}
3002 3058
3003static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat) 3059static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat)
@@ -3028,7 +3084,7 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
3028 .rpc_resp = &res, 3084 .rpc_resp = &res,
3029 }; 3085 };
3030 3086
3031 return nfs4_call_sync(server, &msg, &args, &res, 0); 3087 return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
3032} 3088}
3033 3089
3034static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) 3090static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
@@ -3073,7 +3129,7 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle
3073 } 3129 }
3074 3130
3075 nfs_fattr_init(pathconf->fattr); 3131 nfs_fattr_init(pathconf->fattr);
3076 return nfs4_call_sync(server, &msg, &args, &res, 0); 3132 return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
3077} 3133}
3078 3134
3079static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, 3135static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -3195,12 +3251,9 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag
3195 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; 3251 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE];
3196} 3252}
3197 3253
3198static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) 3254static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_write_data *data)
3199{ 3255{
3200 struct inode *inode = data->inode; 3256 struct inode *inode = data->inode;
3201
3202 if (!nfs4_sequence_done(task, &data->res.seq_res))
3203 return -EAGAIN;
3204 3257
3205 if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { 3258 if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) {
3206 nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); 3259 nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
@@ -3210,11 +3263,24 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
3210 return 0; 3263 return 0;
3211} 3264}
3212 3265
3266static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
3267{
3268 if (!nfs4_sequence_done(task, &data->res.seq_res))
3269 return -EAGAIN;
3270 return data->write_done_cb(task, data);
3271}
3272
3213static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) 3273static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg)
3214{ 3274{
3215 struct nfs_server *server = NFS_SERVER(data->inode); 3275 struct nfs_server *server = NFS_SERVER(data->inode);
3216 3276
3217 data->args.bitmask = server->cache_consistency_bitmask; 3277 if (data->lseg) {
3278 data->args.bitmask = NULL;
3279 data->res.fattr = NULL;
3280 } else
3281 data->args.bitmask = server->cache_consistency_bitmask;
3282 if (!data->write_done_cb)
3283 data->write_done_cb = nfs4_commit_done_cb;
3218 data->res.server = server; 3284 data->res.server = server;
3219 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; 3285 msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT];
3220} 3286}
@@ -3452,7 +3518,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
3452 resp_buf = buf; 3518 resp_buf = buf;
3453 buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); 3519 buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
3454 } 3520 }
3455 ret = nfs4_call_sync(NFS_SERVER(inode), &msg, &args, &res, 0); 3521 ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), &msg, &args.seq_args, &res.seq_res, 0);
3456 if (ret) 3522 if (ret)
3457 goto out_free; 3523 goto out_free;
3458 if (res.acl_len > args.acl_len) 3524 if (res.acl_len > args.acl_len)
@@ -3527,7 +3593,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
3527 if (i < 0) 3593 if (i < 0)
3528 return i; 3594 return i;
3529 nfs_inode_return_delegation(inode); 3595 nfs_inode_return_delegation(inode);
3530 ret = nfs4_call_sync(server, &msg, &arg, &res, 1); 3596 ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
3531 3597
3532 /* 3598 /*
3533 * Free each page after tx, so the only ref left is 3599 * Free each page after tx, so the only ref left is
@@ -3890,7 +3956,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
3890 lsp = request->fl_u.nfs4_fl.owner; 3956 lsp = request->fl_u.nfs4_fl.owner;
3891 arg.lock_owner.id = lsp->ls_id.id; 3957 arg.lock_owner.id = lsp->ls_id.id;
3892 arg.lock_owner.s_dev = server->s_dev; 3958 arg.lock_owner.s_dev = server->s_dev;
3893 status = nfs4_call_sync(server, &msg, &arg, &res, 1); 3959 status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
3894 switch (status) { 3960 switch (status) {
3895 case 0: 3961 case 0:
3896 request->fl_type = F_UNLCK; 3962 request->fl_type = F_UNLCK;
@@ -4618,12 +4684,46 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
4618 nfs_fattr_init(&fs_locations->fattr); 4684 nfs_fattr_init(&fs_locations->fattr);
4619 fs_locations->server = server; 4685 fs_locations->server = server;
4620 fs_locations->nlocations = 0; 4686 fs_locations->nlocations = 0;
4621 status = nfs4_call_sync(server, &msg, &args, &res, 0); 4687 status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
4622 nfs_fixup_referral_attributes(&fs_locations->fattr); 4688 nfs_fixup_referral_attributes(&fs_locations->fattr);
4623 dprintk("%s: returned status = %d\n", __func__, status); 4689 dprintk("%s: returned status = %d\n", __func__, status);
4624 return status; 4690 return status;
4625} 4691}
4626 4692
4693static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors)
4694{
4695 int status;
4696 struct nfs4_secinfo_arg args = {
4697 .dir_fh = NFS_FH(dir),
4698 .name = name,
4699 };
4700 struct nfs4_secinfo_res res = {
4701 .flavors = flavors,
4702 };
4703 struct rpc_message msg = {
4704 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SECINFO],
4705 .rpc_argp = &args,
4706 .rpc_resp = &res,
4707 };
4708
4709 dprintk("NFS call secinfo %s\n", name->name);
4710 status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0);
4711 dprintk("NFS reply secinfo: %d\n", status);
4712 return status;
4713}
4714
4715int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors)
4716{
4717 struct nfs4_exception exception = { };
4718 int err;
4719 do {
4720 err = nfs4_handle_exception(NFS_SERVER(dir),
4721 _nfs4_proc_secinfo(dir, name, flavors),
4722 &exception);
4723 } while (exception.retry);
4724 return err;
4725}
4726
4627#ifdef CONFIG_NFS_V4_1 4727#ifdef CONFIG_NFS_V4_1
4628/* 4728/*
4629 * Check the exchange flags returned by the server for invalid flags, having 4729 * Check the exchange flags returned by the server for invalid flags, having
@@ -5516,8 +5616,6 @@ static void nfs4_layoutget_release(void *calldata)
5516 struct nfs4_layoutget *lgp = calldata; 5616 struct nfs4_layoutget *lgp = calldata;
5517 5617
5518 dprintk("--> %s\n", __func__); 5618 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); 5619 put_nfs_open_context(lgp->args.ctx);
5522 kfree(calldata); 5620 kfree(calldata);
5523 dprintk("<-- %s\n", __func__); 5621 dprintk("<-- %s\n", __func__);
@@ -5549,12 +5647,7 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)
5549 5647
5550 dprintk("--> %s\n", __func__); 5648 dprintk("--> %s\n", __func__);
5551 5649
5552 lgp->res.layout.buf = (void *)__get_free_page(GFP_NOFS); 5650 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; 5651 lgp->res.seq_res.sr_slot = NULL;
5559 task = rpc_run_task(&task_setup_data); 5652 task = rpc_run_task(&task_setup_data);
5560 if (IS_ERR(task)) 5653 if (IS_ERR(task))
@@ -5586,7 +5679,7 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev)
5586 int status; 5679 int status;
5587 5680
5588 dprintk("--> %s\n", __func__); 5681 dprintk("--> %s\n", __func__);
5589 status = nfs4_call_sync(server, &msg, &args, &res, 0); 5682 status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
5590 dprintk("<-- %s status=%d\n", __func__, status); 5683 dprintk("<-- %s status=%d\n", __func__, status);
5591 5684
5592 return status; 5685 return status;
@@ -5606,6 +5699,100 @@ int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev)
5606} 5699}
5607EXPORT_SYMBOL_GPL(nfs4_proc_getdeviceinfo); 5700EXPORT_SYMBOL_GPL(nfs4_proc_getdeviceinfo);
5608 5701
5702static void nfs4_layoutcommit_prepare(struct rpc_task *task, void *calldata)
5703{
5704 struct nfs4_layoutcommit_data *data = calldata;
5705 struct nfs_server *server = NFS_SERVER(data->args.inode);
5706
5707 if (nfs4_setup_sequence(server, &data->args.seq_args,
5708 &data->res.seq_res, 1, task))
5709 return;
5710 rpc_call_start(task);
5711}
5712
5713static void
5714nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
5715{
5716 struct nfs4_layoutcommit_data *data = calldata;
5717 struct nfs_server *server = NFS_SERVER(data->args.inode);
5718
5719 if (!nfs4_sequence_done(task, &data->res.seq_res))
5720 return;
5721
5722 switch (task->tk_status) { /* Just ignore these failures */
5723 case NFS4ERR_DELEG_REVOKED: /* layout was recalled */
5724 case NFS4ERR_BADIOMODE: /* no IOMODE_RW layout for range */
5725 case NFS4ERR_BADLAYOUT: /* no layout */
5726 case NFS4ERR_GRACE: /* loca_recalim always false */
5727 task->tk_status = 0;
5728 }
5729
5730 if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
5731 nfs_restart_rpc(task, server->nfs_client);
5732 return;
5733 }
5734
5735 if (task->tk_status == 0)
5736 nfs_post_op_update_inode_force_wcc(data->args.inode,
5737 data->res.fattr);
5738}
5739
5740static void nfs4_layoutcommit_release(void *calldata)
5741{
5742 struct nfs4_layoutcommit_data *data = calldata;
5743
5744 /* Matched by references in pnfs_set_layoutcommit */
5745 put_lseg(data->lseg);
5746 put_rpccred(data->cred);
5747 kfree(data);
5748}
5749
5750static const struct rpc_call_ops nfs4_layoutcommit_ops = {
5751 .rpc_call_prepare = nfs4_layoutcommit_prepare,
5752 .rpc_call_done = nfs4_layoutcommit_done,
5753 .rpc_release = nfs4_layoutcommit_release,
5754};
5755
5756int
5757nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync)
5758{
5759 struct rpc_message msg = {
5760 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTCOMMIT],
5761 .rpc_argp = &data->args,
5762 .rpc_resp = &data->res,
5763 .rpc_cred = data->cred,
5764 };
5765 struct rpc_task_setup task_setup_data = {
5766 .task = &data->task,
5767 .rpc_client = NFS_CLIENT(data->args.inode),
5768 .rpc_message = &msg,
5769 .callback_ops = &nfs4_layoutcommit_ops,
5770 .callback_data = data,
5771 .flags = RPC_TASK_ASYNC,
5772 };
5773 struct rpc_task *task;
5774 int status = 0;
5775
5776 dprintk("NFS: %4d initiating layoutcommit call. sync %d "
5777 "lbw: %llu inode %lu\n",
5778 data->task.tk_pid, sync,
5779 data->args.lastbytewritten,
5780 data->args.inode->i_ino);
5781
5782 task = rpc_run_task(&task_setup_data);
5783 if (IS_ERR(task))
5784 return PTR_ERR(task);
5785 if (sync == false)
5786 goto out;
5787 status = nfs4_wait_for_completion_rpc_task(task);
5788 if (status != 0)
5789 goto out;
5790 status = task->tk_status;
5791out:
5792 dprintk("%s: status %d\n", __func__, status);
5793 rpc_put_task(task);
5794 return status;
5795}
5609#endif /* CONFIG_NFS_V4_1 */ 5796#endif /* CONFIG_NFS_V4_1 */
5610 5797
5611struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { 5798struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
@@ -5741,6 +5928,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
5741 .close_context = nfs4_close_context, 5928 .close_context = nfs4_close_context,
5742 .open_context = nfs4_atomic_open, 5929 .open_context = nfs4_atomic_open,
5743 .init_client = nfs4_init_client, 5930 .init_client = nfs4_init_client,
5931 .secinfo = nfs4_proc_secinfo,
5744}; 5932};
5745 5933
5746static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { 5934static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {