diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 425 |
1 files changed, 354 insertions, 71 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 0a07e353a961..dfd1e6d7e6c3 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,11 @@ 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; | ||
93 | case -NFS4ERR_BADOWNER: | ||
94 | case -NFS4ERR_BADNAME: | ||
95 | return -EINVAL; | ||
88 | default: | 96 | default: |
89 | dprintk("%s could not handle NFSv4 error %d\n", | 97 | dprintk("%s could not handle NFSv4 error %d\n", |
90 | __func__, -err); | 98 | __func__, -err); |
@@ -241,7 +249,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) | |||
241 | /* This is the error handling routine for processes that are allowed | 249 | /* This is the error handling routine for processes that are allowed |
242 | * to sleep. | 250 | * to sleep. |
243 | */ | 251 | */ |
244 | static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception) | 252 | static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception) |
245 | { | 253 | { |
246 | struct nfs_client *clp = server->nfs_client; | 254 | struct nfs_client *clp = server->nfs_client; |
247 | struct nfs4_state *state = exception->state; | 255 | struct nfs4_state *state = exception->state; |
@@ -293,6 +301,19 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, | |||
293 | break; | 301 | break; |
294 | case -NFS4ERR_OLD_STATEID: | 302 | case -NFS4ERR_OLD_STATEID: |
295 | exception->retry = 1; | 303 | exception->retry = 1; |
304 | break; | ||
305 | case -NFS4ERR_BADOWNER: | ||
306 | /* The following works around a Linux server bug! */ | ||
307 | case -NFS4ERR_BADNAME: | ||
308 | if (server->caps & NFS_CAP_UIDGID_NOMAP) { | ||
309 | server->caps &= ~NFS_CAP_UIDGID_NOMAP; | ||
310 | exception->retry = 1; | ||
311 | printk(KERN_WARNING "NFS: v4 server %s " | ||
312 | "does not accept raw " | ||
313 | "uid/gids. " | ||
314 | "Reenabling the idmapper.\n", | ||
315 | server->nfs_client->cl_hostname); | ||
316 | } | ||
296 | } | 317 | } |
297 | /* We failed to handle the error */ | 318 | /* We failed to handle the error */ |
298 | return nfs4_map_errors(ret); | 319 | return nfs4_map_errors(ret); |
@@ -505,7 +526,7 @@ out: | |||
505 | return ret_id; | 526 | return ret_id; |
506 | } | 527 | } |
507 | 528 | ||
508 | static int nfs41_setup_sequence(struct nfs4_session *session, | 529 | int nfs41_setup_sequence(struct nfs4_session *session, |
509 | struct nfs4_sequence_args *args, | 530 | struct nfs4_sequence_args *args, |
510 | struct nfs4_sequence_res *res, | 531 | struct nfs4_sequence_res *res, |
511 | int cache_reply, | 532 | int cache_reply, |
@@ -571,6 +592,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session, | |||
571 | res->sr_status = 1; | 592 | res->sr_status = 1; |
572 | return 0; | 593 | return 0; |
573 | } | 594 | } |
595 | EXPORT_SYMBOL_GPL(nfs41_setup_sequence); | ||
574 | 596 | ||
575 | int nfs4_setup_sequence(const struct nfs_server *server, | 597 | int nfs4_setup_sequence(const struct nfs_server *server, |
576 | struct nfs4_sequence_args *args, | 598 | struct nfs4_sequence_args *args, |
@@ -640,7 +662,8 @@ struct rpc_call_ops nfs41_call_priv_sync_ops = { | |||
640 | .rpc_call_done = nfs41_call_sync_done, | 662 | .rpc_call_done = nfs41_call_sync_done, |
641 | }; | 663 | }; |
642 | 664 | ||
643 | 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, | ||
644 | struct rpc_message *msg, | 667 | struct rpc_message *msg, |
645 | struct nfs4_sequence_args *args, | 668 | struct nfs4_sequence_args *args, |
646 | struct nfs4_sequence_res *res, | 669 | struct nfs4_sequence_res *res, |
@@ -656,7 +679,7 @@ static int nfs4_call_sync_sequence(struct nfs_server *server, | |||
656 | .cache_reply = cache_reply, | 679 | .cache_reply = cache_reply, |
657 | }; | 680 | }; |
658 | struct rpc_task_setup task_setup = { | 681 | struct rpc_task_setup task_setup = { |
659 | .rpc_client = server->client, | 682 | .rpc_client = clnt, |
660 | .rpc_message = msg, | 683 | .rpc_message = msg, |
661 | .callback_ops = &nfs41_call_sync_ops, | 684 | .callback_ops = &nfs41_call_sync_ops, |
662 | .callback_data = &data | 685 | .callback_data = &data |
@@ -675,13 +698,14 @@ static int nfs4_call_sync_sequence(struct nfs_server *server, | |||
675 | return ret; | 698 | return ret; |
676 | } | 699 | } |
677 | 700 | ||
678 | int _nfs4_call_sync_session(struct nfs_server *server, | 701 | int _nfs4_call_sync_session(struct rpc_clnt *clnt, |
702 | struct nfs_server *server, | ||
679 | struct rpc_message *msg, | 703 | struct rpc_message *msg, |
680 | struct nfs4_sequence_args *args, | 704 | struct nfs4_sequence_args *args, |
681 | struct nfs4_sequence_res *res, | 705 | struct nfs4_sequence_res *res, |
682 | int cache_reply) | 706 | int cache_reply) |
683 | { | 707 | { |
684 | 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); |
685 | } | 709 | } |
686 | 710 | ||
687 | #else | 711 | #else |
@@ -692,19 +716,28 @@ static int nfs4_sequence_done(struct rpc_task *task, | |||
692 | } | 716 | } |
693 | #endif /* CONFIG_NFS_V4_1 */ | 717 | #endif /* CONFIG_NFS_V4_1 */ |
694 | 718 | ||
695 | int _nfs4_call_sync(struct nfs_server *server, | 719 | int _nfs4_call_sync(struct rpc_clnt *clnt, |
720 | struct nfs_server *server, | ||
696 | struct rpc_message *msg, | 721 | struct rpc_message *msg, |
697 | struct nfs4_sequence_args *args, | 722 | struct nfs4_sequence_args *args, |
698 | struct nfs4_sequence_res *res, | 723 | struct nfs4_sequence_res *res, |
699 | int cache_reply) | 724 | int cache_reply) |
700 | { | 725 | { |
701 | args->sa_session = res->sr_session = NULL; | 726 | args->sa_session = res->sr_session = NULL; |
702 | return rpc_call_sync(server->client, msg, 0); | 727 | return rpc_call_sync(clnt, msg, 0); |
703 | } | 728 | } |
704 | 729 | ||
705 | #define nfs4_call_sync(server, msg, args, res, cache_reply) \ | 730 | static inline |
706 | (server)->nfs_client->cl_mvops->call_sync((server), (msg), &(args)->seq_args, \ | 731 | int nfs4_call_sync(struct rpc_clnt *clnt, |
707 | &(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 | } | ||
708 | 741 | ||
709 | 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) |
710 | { | 743 | { |
@@ -1573,9 +1606,8 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
1573 | return 0; | 1606 | return 0; |
1574 | } | 1607 | } |
1575 | 1608 | ||
1576 | static int nfs4_recover_expired_lease(struct nfs_server *server) | 1609 | static int nfs4_client_recover_expired_lease(struct nfs_client *clp) |
1577 | { | 1610 | { |
1578 | struct nfs_client *clp = server->nfs_client; | ||
1579 | unsigned int loop; | 1611 | unsigned int loop; |
1580 | int ret; | 1612 | int ret; |
1581 | 1613 | ||
@@ -1592,6 +1624,11 @@ static int nfs4_recover_expired_lease(struct nfs_server *server) | |||
1592 | return ret; | 1624 | return ret; |
1593 | } | 1625 | } |
1594 | 1626 | ||
1627 | static int nfs4_recover_expired_lease(struct nfs_server *server) | ||
1628 | { | ||
1629 | return nfs4_client_recover_expired_lease(server->nfs_client); | ||
1630 | } | ||
1631 | |||
1595 | /* | 1632 | /* |
1596 | * OPEN_EXPIRED: | 1633 | * OPEN_EXPIRED: |
1597 | * reclaim state on the server after a network partition. | 1634 | * reclaim state on the server after a network partition. |
@@ -1810,7 +1847,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
1810 | } else | 1847 | } else |
1811 | memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); | 1848 | memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); |
1812 | 1849 | ||
1813 | 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); |
1814 | if (status == 0 && state != NULL) | 1851 | if (status == 0 && state != NULL) |
1815 | renew_lease(server, timestamp); | 1852 | renew_lease(server, timestamp); |
1816 | return status; | 1853 | return status; |
@@ -2069,7 +2106,7 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f | |||
2069 | }; | 2106 | }; |
2070 | int status; | 2107 | int status; |
2071 | 2108 | ||
2072 | 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); |
2073 | if (status == 0) { | 2110 | if (status == 0) { |
2074 | memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask)); | 2111 | memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask)); |
2075 | server->caps &= ~(NFS_CAP_ACLS|NFS_CAP_HARDLINKS| | 2112 | server->caps &= ~(NFS_CAP_ACLS|NFS_CAP_HARDLINKS| |
@@ -2139,7 +2176,7 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2139 | }; | 2176 | }; |
2140 | 2177 | ||
2141 | nfs_fattr_init(info->fattr); | 2178 | nfs_fattr_init(info->fattr); |
2142 | 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); |
2143 | } | 2180 | } |
2144 | 2181 | ||
2145 | 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, |
@@ -2155,15 +2192,43 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2155 | return err; | 2192 | return err; |
2156 | } | 2193 | } |
2157 | 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 | |||
2158 | /* | 2213 | /* |
2159 | * get the file handle for the "/" directory on the server | 2214 | * get the file handle for the "/" directory on the server |
2160 | */ | 2215 | */ |
2161 | 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, |
2162 | struct nfs_fsinfo *info) | 2217 | struct nfs_fsinfo *info) |
2163 | { | 2218 | { |
2164 | 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; | ||
2165 | 2226 | ||
2166 | 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 | } | ||
2167 | if (status == 0) | 2232 | if (status == 0) |
2168 | status = nfs4_server_capabilities(server, fhandle); | 2233 | status = nfs4_server_capabilities(server, fhandle); |
2169 | if (status == 0) | 2234 | if (status == 0) |
@@ -2228,7 +2293,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2228 | }; | 2293 | }; |
2229 | 2294 | ||
2230 | nfs_fattr_init(fattr); | 2295 | nfs_fattr_init(fattr); |
2231 | 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); |
2232 | } | 2297 | } |
2233 | 2298 | ||
2234 | 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) |
@@ -2288,9 +2353,9 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
2288 | return status; | 2353 | return status; |
2289 | } | 2354 | } |
2290 | 2355 | ||
2291 | 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, |
2292 | const struct qstr *name, struct nfs_fh *fhandle, | 2357 | const struct nfs_fh *dirfh, const struct qstr *name, |
2293 | struct nfs_fattr *fattr) | 2358 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) |
2294 | { | 2359 | { |
2295 | int status; | 2360 | int status; |
2296 | struct nfs4_lookup_arg args = { | 2361 | struct nfs4_lookup_arg args = { |
@@ -2312,7 +2377,7 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d | |||
2312 | nfs_fattr_init(fattr); | 2377 | nfs_fattr_init(fattr); |
2313 | 2378 | ||
2314 | dprintk("NFS call lookupfh %s\n", name->name); | 2379 | dprintk("NFS call lookupfh %s\n", name->name); |
2315 | status = nfs4_call_sync(server, &msg, &args, &res, 0); | 2380 | status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, &res.seq_res, 0); |
2316 | dprintk("NFS reply lookupfh: %d\n", status); | 2381 | dprintk("NFS reply lookupfh: %d\n", status); |
2317 | return status; | 2382 | return status; |
2318 | } | 2383 | } |
@@ -2324,7 +2389,7 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, | |||
2324 | struct nfs4_exception exception = { }; | 2389 | struct nfs4_exception exception = { }; |
2325 | int err; | 2390 | int err; |
2326 | do { | 2391 | do { |
2327 | err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr); | 2392 | err = _nfs4_proc_lookupfh(server->client, server, dirfh, name, fhandle, fattr); |
2328 | /* FIXME: !!!! */ | 2393 | /* FIXME: !!!! */ |
2329 | if (err == -NFS4ERR_MOVED) { | 2394 | if (err == -NFS4ERR_MOVED) { |
2330 | err = -EREMOTE; | 2395 | err = -EREMOTE; |
@@ -2335,27 +2400,41 @@ static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, | |||
2335 | return err; | 2400 | return err; |
2336 | } | 2401 | } |
2337 | 2402 | ||
2338 | 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, |
2339 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 2404 | const struct qstr *name, struct nfs_fh *fhandle, |
2405 | struct nfs_fattr *fattr) | ||
2340 | { | 2406 | { |
2341 | int status; | 2407 | int status; |
2342 | 2408 | ||
2343 | dprintk("NFS call lookup %s\n", name->name); | 2409 | dprintk("NFS call lookup %s\n", name->name); |
2344 | 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); |
2345 | if (status == -NFS4ERR_MOVED) | 2411 | if (status == -NFS4ERR_MOVED) |
2346 | status = nfs4_get_referral(dir, name, fattr, fhandle); | 2412 | status = nfs4_get_referral(dir, name, fattr, fhandle); |
2347 | dprintk("NFS reply lookup: %d\n", status); | 2413 | dprintk("NFS reply lookup: %d\n", status); |
2348 | return status; | 2414 | return status; |
2349 | } | 2415 | } |
2350 | 2416 | ||
2351 | 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) | ||
2352 | { | 2429 | { |
2353 | struct nfs4_exception exception = { }; | 2430 | struct nfs4_exception exception = { }; |
2354 | int err; | 2431 | int err; |
2355 | do { | 2432 | do { |
2356 | err = nfs4_handle_exception(NFS_SERVER(dir), | 2433 | err = nfs4_handle_exception(NFS_SERVER(dir), |
2357 | _nfs4_proc_lookup(dir, name, fhandle, fattr), | 2434 | _nfs4_proc_lookup(clnt, dir, name, fhandle, fattr), |
2358 | &exception); | 2435 | &exception); |
2436 | if (err == -EPERM) | ||
2437 | nfs_fixup_secinfo_attributes(fattr, fhandle); | ||
2359 | } while (exception.retry); | 2438 | } while (exception.retry); |
2360 | return err; | 2439 | return err; |
2361 | } | 2440 | } |
@@ -2400,7 +2479,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry | |||
2400 | if (res.fattr == NULL) | 2479 | if (res.fattr == NULL) |
2401 | return -ENOMEM; | 2480 | return -ENOMEM; |
2402 | 2481 | ||
2403 | 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); |
2404 | if (!status) { | 2483 | if (!status) { |
2405 | entry->mask = 0; | 2484 | entry->mask = 0; |
2406 | if (res.access & NFS4_ACCESS_READ) | 2485 | if (res.access & NFS4_ACCESS_READ) |
@@ -2467,7 +2546,7 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page, | |||
2467 | .rpc_resp = &res, | 2546 | .rpc_resp = &res, |
2468 | }; | 2547 | }; |
2469 | 2548 | ||
2470 | 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); |
2471 | } | 2550 | } |
2472 | 2551 | ||
2473 | static int nfs4_proc_readlink(struct inode *inode, struct page *page, | 2552 | static int nfs4_proc_readlink(struct inode *inode, struct page *page, |
@@ -2556,7 +2635,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) | |||
2556 | if (res.dir_attr == NULL) | 2635 | if (res.dir_attr == NULL) |
2557 | goto out; | 2636 | goto out; |
2558 | 2637 | ||
2559 | 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); |
2560 | if (status == 0) { | 2639 | if (status == 0) { |
2561 | update_changeattr(dir, &res.cinfo); | 2640 | update_changeattr(dir, &res.cinfo); |
2562 | nfs_post_op_update_inode(dir, res.dir_attr); | 2641 | nfs_post_op_update_inode(dir, res.dir_attr); |
@@ -2657,7 +2736,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
2657 | if (res.old_fattr == NULL || res.new_fattr == NULL) | 2736 | if (res.old_fattr == NULL || res.new_fattr == NULL) |
2658 | goto out; | 2737 | goto out; |
2659 | 2738 | ||
2660 | 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); |
2661 | if (!status) { | 2740 | if (!status) { |
2662 | update_changeattr(old_dir, &res.old_cinfo); | 2741 | update_changeattr(old_dir, &res.old_cinfo); |
2663 | nfs_post_op_update_inode(old_dir, res.old_fattr); | 2742 | nfs_post_op_update_inode(old_dir, res.old_fattr); |
@@ -2708,7 +2787,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * | |||
2708 | if (res.fattr == NULL || res.dir_attr == NULL) | 2787 | if (res.fattr == NULL || res.dir_attr == NULL) |
2709 | goto out; | 2788 | goto out; |
2710 | 2789 | ||
2711 | 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); |
2712 | if (!status) { | 2791 | if (!status) { |
2713 | update_changeattr(dir, &res.cinfo); | 2792 | update_changeattr(dir, &res.cinfo); |
2714 | nfs_post_op_update_inode(dir, res.dir_attr); | 2793 | nfs_post_op_update_inode(dir, res.dir_attr); |
@@ -2771,8 +2850,8 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, | |||
2771 | 2850 | ||
2772 | 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) |
2773 | { | 2852 | { |
2774 | 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, |
2775 | &data->arg, &data->res, 1); | 2854 | &data->arg.seq_args, &data->res.seq_res, 1); |
2776 | if (status == 0) { | 2855 | if (status == 0) { |
2777 | update_changeattr(dir, &data->res.dir_cinfo); | 2856 | update_changeattr(dir, &data->res.dir_cinfo); |
2778 | nfs_post_op_update_inode(dir, data->res.dir_fattr); | 2857 | nfs_post_op_update_inode(dir, data->res.dir_fattr); |
@@ -2884,7 +2963,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
2884 | (unsigned long long)cookie); | 2963 | (unsigned long long)cookie); |
2885 | nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); | 2964 | nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); |
2886 | res.pgbase = args.pgbase; | 2965 | res.pgbase = args.pgbase; |
2887 | 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); |
2888 | if (status >= 0) { | 2967 | if (status >= 0) { |
2889 | memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); | 2968 | memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); |
2890 | status += args.pgbase; | 2969 | status += args.pgbase; |
@@ -2976,7 +3055,7 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2976 | }; | 3055 | }; |
2977 | 3056 | ||
2978 | nfs_fattr_init(fsstat->fattr); | 3057 | nfs_fattr_init(fsstat->fattr); |
2979 | 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); |
2980 | } | 3059 | } |
2981 | 3060 | ||
2982 | 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) |
@@ -3007,7 +3086,7 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, | |||
3007 | .rpc_resp = &res, | 3086 | .rpc_resp = &res, |
3008 | }; | 3087 | }; |
3009 | 3088 | ||
3010 | 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); |
3011 | } | 3090 | } |
3012 | 3091 | ||
3013 | 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) |
@@ -3052,7 +3131,7 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle | |||
3052 | } | 3131 | } |
3053 | 3132 | ||
3054 | nfs_fattr_init(pathconf->fattr); | 3133 | nfs_fattr_init(pathconf->fattr); |
3055 | 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); |
3056 | } | 3135 | } |
3057 | 3136 | ||
3058 | 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, |
@@ -3069,15 +3148,10 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | |||
3069 | return err; | 3148 | return err; |
3070 | } | 3149 | } |
3071 | 3150 | ||
3072 | static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) | 3151 | static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data) |
3073 | { | 3152 | { |
3074 | struct nfs_server *server = NFS_SERVER(data->inode); | 3153 | struct nfs_server *server = NFS_SERVER(data->inode); |
3075 | 3154 | ||
3076 | dprintk("--> %s\n", __func__); | ||
3077 | |||
3078 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | ||
3079 | return -EAGAIN; | ||
3080 | |||
3081 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { | 3155 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { |
3082 | nfs_restart_rpc(task, server->nfs_client); | 3156 | nfs_restart_rpc(task, server->nfs_client); |
3083 | return -EAGAIN; | 3157 | return -EAGAIN; |
@@ -3089,19 +3163,44 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) | |||
3089 | return 0; | 3163 | return 0; |
3090 | } | 3164 | } |
3091 | 3165 | ||
3166 | static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) | ||
3167 | { | ||
3168 | |||
3169 | dprintk("--> %s\n", __func__); | ||
3170 | |||
3171 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | ||
3172 | return -EAGAIN; | ||
3173 | |||
3174 | return data->read_done_cb(task, data); | ||
3175 | } | ||
3176 | |||
3092 | static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) | 3177 | static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg) |
3093 | { | 3178 | { |
3094 | data->timestamp = jiffies; | 3179 | data->timestamp = jiffies; |
3180 | data->read_done_cb = nfs4_read_done_cb; | ||
3095 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ]; | 3181 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ]; |
3096 | } | 3182 | } |
3097 | 3183 | ||
3098 | static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | 3184 | /* Reset the the nfs_read_data to send the read to the MDS. */ |
3185 | void nfs4_reset_read(struct rpc_task *task, struct nfs_read_data *data) | ||
3186 | { | ||
3187 | dprintk("%s Reset task for i/o through\n", __func__); | ||
3188 | put_lseg(data->lseg); | ||
3189 | data->lseg = NULL; | ||
3190 | /* offsets will differ in the dense stripe case */ | ||
3191 | data->args.offset = data->mds_offset; | ||
3192 | data->ds_clp = NULL; | ||
3193 | data->args.fh = NFS_FH(data->inode); | ||
3194 | data->read_done_cb = nfs4_read_done_cb; | ||
3195 | task->tk_ops = data->mds_ops; | ||
3196 | rpc_task_reset_client(task, NFS_CLIENT(data->inode)); | ||
3197 | } | ||
3198 | EXPORT_SYMBOL_GPL(nfs4_reset_read); | ||
3199 | |||
3200 | static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data) | ||
3099 | { | 3201 | { |
3100 | struct inode *inode = data->inode; | 3202 | struct inode *inode = data->inode; |
3101 | 3203 | ||
3102 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | ||
3103 | return -EAGAIN; | ||
3104 | |||
3105 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { | 3204 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { |
3106 | nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); | 3205 | nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); |
3107 | return -EAGAIN; | 3206 | return -EAGAIN; |
@@ -3113,23 +3212,50 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | |||
3113 | return 0; | 3212 | return 0; |
3114 | } | 3213 | } |
3115 | 3214 | ||
3215 | static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | ||
3216 | { | ||
3217 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | ||
3218 | return -EAGAIN; | ||
3219 | return data->write_done_cb(task, data); | ||
3220 | } | ||
3221 | |||
3222 | /* Reset the the nfs_write_data to send the write to the MDS. */ | ||
3223 | void nfs4_reset_write(struct rpc_task *task, struct nfs_write_data *data) | ||
3224 | { | ||
3225 | dprintk("%s Reset task for i/o through\n", __func__); | ||
3226 | put_lseg(data->lseg); | ||
3227 | data->lseg = NULL; | ||
3228 | data->ds_clp = NULL; | ||
3229 | data->write_done_cb = nfs4_write_done_cb; | ||
3230 | data->args.fh = NFS_FH(data->inode); | ||
3231 | data->args.bitmask = data->res.server->cache_consistency_bitmask; | ||
3232 | data->args.offset = data->mds_offset; | ||
3233 | data->res.fattr = &data->fattr; | ||
3234 | task->tk_ops = data->mds_ops; | ||
3235 | rpc_task_reset_client(task, NFS_CLIENT(data->inode)); | ||
3236 | } | ||
3237 | EXPORT_SYMBOL_GPL(nfs4_reset_write); | ||
3238 | |||
3116 | static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) | 3239 | static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) |
3117 | { | 3240 | { |
3118 | struct nfs_server *server = NFS_SERVER(data->inode); | 3241 | struct nfs_server *server = NFS_SERVER(data->inode); |
3119 | 3242 | ||
3120 | data->args.bitmask = server->cache_consistency_bitmask; | 3243 | if (data->lseg) { |
3244 | data->args.bitmask = NULL; | ||
3245 | data->res.fattr = NULL; | ||
3246 | } else | ||
3247 | data->args.bitmask = server->cache_consistency_bitmask; | ||
3248 | if (!data->write_done_cb) | ||
3249 | data->write_done_cb = nfs4_write_done_cb; | ||
3121 | data->res.server = server; | 3250 | data->res.server = server; |
3122 | data->timestamp = jiffies; | 3251 | data->timestamp = jiffies; |
3123 | 3252 | ||
3124 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; | 3253 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE]; |
3125 | } | 3254 | } |
3126 | 3255 | ||
3127 | 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) |
3128 | { | 3257 | { |
3129 | struct inode *inode = data->inode; | 3258 | struct inode *inode = data->inode; |
3130 | |||
3131 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | ||
3132 | return -EAGAIN; | ||
3133 | 3259 | ||
3134 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { | 3260 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { |
3135 | nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); | 3261 | nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); |
@@ -3139,11 +3265,24 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) | |||
3139 | return 0; | 3265 | return 0; |
3140 | } | 3266 | } |
3141 | 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 | |||
3142 | 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) |
3143 | { | 3276 | { |
3144 | struct nfs_server *server = NFS_SERVER(data->inode); | 3277 | struct nfs_server *server = NFS_SERVER(data->inode); |
3145 | 3278 | ||
3146 | 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; | ||
3147 | data->res.server = server; | 3286 | data->res.server = server; |
3148 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; | 3287 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; |
3149 | } | 3288 | } |
@@ -3381,7 +3520,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
3381 | resp_buf = buf; | 3520 | resp_buf = buf; |
3382 | buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); | 3521 | buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); |
3383 | } | 3522 | } |
3384 | 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); |
3385 | if (ret) | 3524 | if (ret) |
3386 | goto out_free; | 3525 | goto out_free; |
3387 | if (res.acl_len > args.acl_len) | 3526 | if (res.acl_len > args.acl_len) |
@@ -3456,7 +3595,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl | |||
3456 | if (i < 0) | 3595 | if (i < 0) |
3457 | return i; | 3596 | return i; |
3458 | nfs_inode_return_delegation(inode); | 3597 | nfs_inode_return_delegation(inode); |
3459 | 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); |
3460 | 3599 | ||
3461 | /* | 3600 | /* |
3462 | * Free each page after tx, so the only ref left is | 3601 | * Free each page after tx, so the only ref left is |
@@ -3819,7 +3958,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock | |||
3819 | lsp = request->fl_u.nfs4_fl.owner; | 3958 | lsp = request->fl_u.nfs4_fl.owner; |
3820 | arg.lock_owner.id = lsp->ls_id.id; | 3959 | arg.lock_owner.id = lsp->ls_id.id; |
3821 | arg.lock_owner.s_dev = server->s_dev; | 3960 | arg.lock_owner.s_dev = server->s_dev; |
3822 | 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); |
3823 | switch (status) { | 3962 | switch (status) { |
3824 | case 0: | 3963 | case 0: |
3825 | request->fl_type = F_UNLCK; | 3964 | request->fl_type = F_UNLCK; |
@@ -4547,12 +4686,46 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | |||
4547 | nfs_fattr_init(&fs_locations->fattr); | 4686 | nfs_fattr_init(&fs_locations->fattr); |
4548 | fs_locations->server = server; | 4687 | fs_locations->server = server; |
4549 | fs_locations->nlocations = 0; | 4688 | fs_locations->nlocations = 0; |
4550 | 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); |
4551 | nfs_fixup_referral_attributes(&fs_locations->fattr); | 4690 | nfs_fixup_referral_attributes(&fs_locations->fattr); |
4552 | dprintk("%s: returned status = %d\n", __func__, status); | 4691 | dprintk("%s: returned status = %d\n", __func__, status); |
4553 | return status; | 4692 | return status; |
4554 | } | 4693 | } |
4555 | 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 | |||
4556 | #ifdef CONFIG_NFS_V4_1 | 4729 | #ifdef CONFIG_NFS_V4_1 |
4557 | /* | 4730 | /* |
4558 | * 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 |
@@ -5118,6 +5291,27 @@ int nfs4_init_session(struct nfs_server *server) | |||
5118 | return ret; | 5291 | return ret; |
5119 | } | 5292 | } |
5120 | 5293 | ||
5294 | int nfs4_init_ds_session(struct nfs_client *clp) | ||
5295 | { | ||
5296 | struct nfs4_session *session = clp->cl_session; | ||
5297 | int ret; | ||
5298 | |||
5299 | if (!test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) | ||
5300 | return 0; | ||
5301 | |||
5302 | ret = nfs4_client_recover_expired_lease(clp); | ||
5303 | if (!ret) | ||
5304 | /* Test for the DS role */ | ||
5305 | if (!is_ds_client(clp)) | ||
5306 | ret = -ENODEV; | ||
5307 | if (!ret) | ||
5308 | ret = nfs4_check_client_ready(clp); | ||
5309 | return ret; | ||
5310 | |||
5311 | } | ||
5312 | EXPORT_SYMBOL_GPL(nfs4_init_ds_session); | ||
5313 | |||
5314 | |||
5121 | /* | 5315 | /* |
5122 | * Renew the cl_session lease. | 5316 | * Renew the cl_session lease. |
5123 | */ | 5317 | */ |
@@ -5424,8 +5618,6 @@ static void nfs4_layoutget_release(void *calldata) | |||
5424 | struct nfs4_layoutget *lgp = calldata; | 5618 | struct nfs4_layoutget *lgp = calldata; |
5425 | 5619 | ||
5426 | dprintk("--> %s\n", __func__); | 5620 | dprintk("--> %s\n", __func__); |
5427 | if (lgp->res.layout.buf != NULL) | ||
5428 | free_page((unsigned long) lgp->res.layout.buf); | ||
5429 | put_nfs_open_context(lgp->args.ctx); | 5621 | put_nfs_open_context(lgp->args.ctx); |
5430 | kfree(calldata); | 5622 | kfree(calldata); |
5431 | dprintk("<-- %s\n", __func__); | 5623 | dprintk("<-- %s\n", __func__); |
@@ -5457,12 +5649,7 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) | |||
5457 | 5649 | ||
5458 | dprintk("--> %s\n", __func__); | 5650 | dprintk("--> %s\n", __func__); |
5459 | 5651 | ||
5460 | lgp->res.layout.buf = (void *)__get_free_page(GFP_NOFS); | 5652 | lgp->res.layoutp = &lgp->args.layout; |
5461 | if (lgp->res.layout.buf == NULL) { | ||
5462 | nfs4_layoutget_release(lgp); | ||
5463 | return -ENOMEM; | ||
5464 | } | ||
5465 | |||
5466 | lgp->res.seq_res.sr_slot = NULL; | 5653 | lgp->res.seq_res.sr_slot = NULL; |
5467 | task = rpc_run_task(&task_setup_data); | 5654 | task = rpc_run_task(&task_setup_data); |
5468 | if (IS_ERR(task)) | 5655 | if (IS_ERR(task)) |
@@ -5494,7 +5681,7 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | |||
5494 | int status; | 5681 | int status; |
5495 | 5682 | ||
5496 | dprintk("--> %s\n", __func__); | 5683 | dprintk("--> %s\n", __func__); |
5497 | 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); |
5498 | dprintk("<-- %s status=%d\n", __func__, status); | 5685 | dprintk("<-- %s status=%d\n", __func__, status); |
5499 | 5686 | ||
5500 | return status; | 5687 | return status; |
@@ -5514,6 +5701,100 @@ int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | |||
5514 | } | 5701 | } |
5515 | EXPORT_SYMBOL_GPL(nfs4_proc_getdeviceinfo); | 5702 | EXPORT_SYMBOL_GPL(nfs4_proc_getdeviceinfo); |
5516 | 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 | } | ||
5517 | #endif /* CONFIG_NFS_V4_1 */ | 5798 | #endif /* CONFIG_NFS_V4_1 */ |
5518 | 5799 | ||
5519 | struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { | 5800 | struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { |
@@ -5648,6 +5929,8 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
5648 | .clear_acl_cache = nfs4_zap_acl_attr, | 5929 | .clear_acl_cache = nfs4_zap_acl_attr, |
5649 | .close_context = nfs4_close_context, | 5930 | .close_context = nfs4_close_context, |
5650 | .open_context = nfs4_atomic_open, | 5931 | .open_context = nfs4_atomic_open, |
5932 | .init_client = nfs4_init_client, | ||
5933 | .secinfo = nfs4_proc_secinfo, | ||
5651 | }; | 5934 | }; |
5652 | 5935 | ||
5653 | static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { | 5936 | static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { |