diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-30 22:16:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-30 22:16:57 -0400 |
commit | 1fad1e9a747687a7399bf58e87974f9b1bbcae06 (patch) | |
tree | fde2dc9a35321e21c99e06d4b79d5fa06fd34679 /fs/nfs/nfs4proc.c | |
parent | bbeb0af25f493261c15ceee176c99b7fd6fd5479 (diff) | |
parent | f44106e2173f08ccb1c9195d85a6c22388b461c1 (diff) |
Merge tag 'nfs-for-3.6-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client updates from Trond Myklebust:
"Features include:
- More preparatory patches for modularising NFSv2/v3/v4. Split out
the various NFSv2/v3/v4-specific code into separate files
- More preparation for the NFSv4 migration code
- Ensure that OPEN(O_CREATE) observes the pNFS mds threshold
parameters
- pNFS fast failover when the data servers are down
- Various cleanups and debugging patches"
* tag 'nfs-for-3.6-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (67 commits)
nfs: fix fl_type tests in NFSv4 code
NFS: fix pnfs regression with directio writes
NFS: fix pnfs regression with directio reads
sunrpc: clnt: Add missing braces
nfs: fix stub return type warnings
NFS: exit_nfs_v4() shouldn't be an __exit function
SUNRPC: Add a missing spin_unlock to gss_mech_list_pseudoflavors
NFS: Split out NFS v4 client functions
NFS: Split out the NFS v4 filesystem types
NFS: Create a single nfs_clone_super() function
NFS: Split out NFS v4 server creating code
NFS: Initialize the NFS v4 client from init_nfs_v4()
NFS: Move the v4 getroot code to nfs4getroot.c
NFS: Split out NFS v4 file operations
NFS: Initialize v4 sysctls from nfs_init_v4()
NFS: Create an init_nfs_v4() function
NFS: Split out NFS v4 inode operations
NFS: Split out NFS v3 inode operations
NFS: Split out NFS v2 inode operations
NFS: Clean up nfs4_proc_setclientid() and friends
...
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 303 |
1 files changed, 218 insertions, 85 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index c157b2089b47..6843e0a37de8 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <linux/printk.h> | 43 | #include <linux/printk.h> |
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <linux/sunrpc/clnt.h> | 45 | #include <linux/sunrpc/clnt.h> |
46 | #include <linux/sunrpc/gss_api.h> | ||
47 | #include <linux/nfs.h> | 46 | #include <linux/nfs.h> |
48 | #include <linux/nfs4.h> | 47 | #include <linux/nfs4.h> |
49 | #include <linux/nfs_fs.h> | 48 | #include <linux/nfs_fs.h> |
@@ -259,7 +258,12 @@ static int nfs4_wait_clnt_recover(struct nfs_client *clp) | |||
259 | 258 | ||
260 | res = wait_on_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING, | 259 | res = wait_on_bit(&clp->cl_state, NFS4CLNT_MANAGER_RUNNING, |
261 | nfs_wait_bit_killable, TASK_KILLABLE); | 260 | nfs_wait_bit_killable, TASK_KILLABLE); |
262 | return res; | 261 | if (res) |
262 | return res; | ||
263 | |||
264 | if (clp->cl_cons_state < 0) | ||
265 | return clp->cl_cons_state; | ||
266 | return 0; | ||
263 | } | 267 | } |
264 | 268 | ||
265 | static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) | 269 | static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) |
@@ -294,8 +298,8 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc | |||
294 | case 0: | 298 | case 0: |
295 | return 0; | 299 | return 0; |
296 | case -NFS4ERR_OPENMODE: | 300 | case -NFS4ERR_OPENMODE: |
297 | if (inode && nfs_have_delegation(inode, FMODE_READ)) { | 301 | if (inode && nfs4_have_delegation(inode, FMODE_READ)) { |
298 | nfs_inode_return_delegation(inode); | 302 | nfs4_inode_return_delegation(inode); |
299 | exception->retry = 1; | 303 | exception->retry = 1; |
300 | return 0; | 304 | return 0; |
301 | } | 305 | } |
@@ -1065,7 +1069,7 @@ static void nfs4_return_incompatible_delegation(struct inode *inode, fmode_t fmo | |||
1065 | return; | 1069 | return; |
1066 | } | 1070 | } |
1067 | rcu_read_unlock(); | 1071 | rcu_read_unlock(); |
1068 | nfs_inode_return_delegation(inode); | 1072 | nfs4_inode_return_delegation(inode); |
1069 | } | 1073 | } |
1070 | 1074 | ||
1071 | static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) | 1075 | static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) |
@@ -1756,33 +1760,70 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta | |||
1756 | } | 1760 | } |
1757 | 1761 | ||
1758 | #if defined(CONFIG_NFS_V4_1) | 1762 | #if defined(CONFIG_NFS_V4_1) |
1759 | static int nfs41_check_expired_stateid(struct nfs4_state *state, nfs4_stateid *stateid, unsigned int flags) | 1763 | static void nfs41_clear_delegation_stateid(struct nfs4_state *state) |
1760 | { | 1764 | { |
1761 | int status = NFS_OK; | ||
1762 | struct nfs_server *server = NFS_SERVER(state->inode); | 1765 | struct nfs_server *server = NFS_SERVER(state->inode); |
1766 | nfs4_stateid *stateid = &state->stateid; | ||
1767 | int status; | ||
1768 | |||
1769 | /* If a state reset has been done, test_stateid is unneeded */ | ||
1770 | if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) | ||
1771 | return; | ||
1763 | 1772 | ||
1764 | if (state->flags & flags) { | 1773 | status = nfs41_test_stateid(server, stateid); |
1765 | status = nfs41_test_stateid(server, stateid); | 1774 | if (status != NFS_OK) { |
1766 | if (status != NFS_OK) { | 1775 | /* Free the stateid unless the server explicitly |
1776 | * informs us the stateid is unrecognized. */ | ||
1777 | if (status != -NFS4ERR_BAD_STATEID) | ||
1767 | nfs41_free_stateid(server, stateid); | 1778 | nfs41_free_stateid(server, stateid); |
1768 | state->flags &= ~flags; | 1779 | |
1769 | } | 1780 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
1781 | } | ||
1782 | } | ||
1783 | |||
1784 | /** | ||
1785 | * nfs41_check_open_stateid - possibly free an open stateid | ||
1786 | * | ||
1787 | * @state: NFSv4 state for an inode | ||
1788 | * | ||
1789 | * Returns NFS_OK if recovery for this stateid is now finished. | ||
1790 | * Otherwise a negative NFS4ERR value is returned. | ||
1791 | */ | ||
1792 | static int nfs41_check_open_stateid(struct nfs4_state *state) | ||
1793 | { | ||
1794 | struct nfs_server *server = NFS_SERVER(state->inode); | ||
1795 | nfs4_stateid *stateid = &state->stateid; | ||
1796 | int status; | ||
1797 | |||
1798 | /* If a state reset has been done, test_stateid is unneeded */ | ||
1799 | if ((test_bit(NFS_O_RDONLY_STATE, &state->flags) == 0) && | ||
1800 | (test_bit(NFS_O_WRONLY_STATE, &state->flags) == 0) && | ||
1801 | (test_bit(NFS_O_RDWR_STATE, &state->flags) == 0)) | ||
1802 | return -NFS4ERR_BAD_STATEID; | ||
1803 | |||
1804 | status = nfs41_test_stateid(server, stateid); | ||
1805 | if (status != NFS_OK) { | ||
1806 | /* Free the stateid unless the server explicitly | ||
1807 | * informs us the stateid is unrecognized. */ | ||
1808 | if (status != -NFS4ERR_BAD_STATEID) | ||
1809 | nfs41_free_stateid(server, stateid); | ||
1810 | |||
1811 | clear_bit(NFS_O_RDONLY_STATE, &state->flags); | ||
1812 | clear_bit(NFS_O_WRONLY_STATE, &state->flags); | ||
1813 | clear_bit(NFS_O_RDWR_STATE, &state->flags); | ||
1770 | } | 1814 | } |
1771 | return status; | 1815 | return status; |
1772 | } | 1816 | } |
1773 | 1817 | ||
1774 | static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) | 1818 | static int nfs41_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) |
1775 | { | 1819 | { |
1776 | int deleg_status, open_status; | 1820 | int status; |
1777 | int deleg_flags = 1 << NFS_DELEGATED_STATE; | ||
1778 | int open_flags = (1 << NFS_O_RDONLY_STATE) | (1 << NFS_O_WRONLY_STATE) | (1 << NFS_O_RDWR_STATE); | ||
1779 | |||
1780 | deleg_status = nfs41_check_expired_stateid(state, &state->stateid, deleg_flags); | ||
1781 | open_status = nfs41_check_expired_stateid(state, &state->open_stateid, open_flags); | ||
1782 | 1821 | ||
1783 | if ((deleg_status == NFS_OK) && (open_status == NFS_OK)) | 1822 | nfs41_clear_delegation_stateid(state); |
1784 | return NFS_OK; | 1823 | status = nfs41_check_open_stateid(state); |
1785 | return nfs4_open_expired(sp, state); | 1824 | if (status != NFS_OK) |
1825 | status = nfs4_open_expired(sp, state); | ||
1826 | return status; | ||
1786 | } | 1827 | } |
1787 | #endif | 1828 | #endif |
1788 | 1829 | ||
@@ -2375,11 +2416,15 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2375 | int i, len, status = 0; | 2416 | int i, len, status = 0; |
2376 | rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS]; | 2417 | rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS]; |
2377 | 2418 | ||
2378 | len = gss_mech_list_pseudoflavors(&flav_array[0]); | 2419 | len = rpcauth_list_flavors(flav_array, ARRAY_SIZE(flav_array)); |
2379 | flav_array[len] = RPC_AUTH_NULL; | 2420 | BUG_ON(len < 0); |
2380 | len += 1; | ||
2381 | 2421 | ||
2382 | for (i = 0; i < len; i++) { | 2422 | for (i = 0; i < len; i++) { |
2423 | /* AUTH_UNIX is the default flavor if none was specified, | ||
2424 | * thus has already been tried. */ | ||
2425 | if (flav_array[i] == RPC_AUTH_UNIX) | ||
2426 | continue; | ||
2427 | |||
2383 | status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); | 2428 | status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); |
2384 | if (status == -NFS4ERR_WRONGSEC || status == -EACCES) | 2429 | if (status == -NFS4ERR_WRONGSEC || status == -EACCES) |
2385 | continue; | 2430 | continue; |
@@ -2766,9 +2811,7 @@ static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) | |||
2766 | * | 2811 | * |
2767 | * In the case of WRITE, we also want to put the GETATTR after | 2812 | * In the case of WRITE, we also want to put the GETATTR after |
2768 | * the operation -- in this case because we want to make sure | 2813 | * the operation -- in this case because we want to make sure |
2769 | * we get the post-operation mtime and size. This means that | 2814 | * we get the post-operation mtime and size. |
2770 | * we can't use xdr_encode_pages() as written: we need a variant | ||
2771 | * of it which would leave room in the 'tail' iovec. | ||
2772 | * | 2815 | * |
2773 | * Both of these changes to the XDR layer would in fact be quite | 2816 | * Both of these changes to the XDR layer would in fact be quite |
2774 | * minor, but I decided to leave them for a subsequent patch. | 2817 | * minor, but I decided to leave them for a subsequent patch. |
@@ -2821,7 +2864,9 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
2821 | return PTR_ERR(ctx); | 2864 | return PTR_ERR(ctx); |
2822 | 2865 | ||
2823 | sattr->ia_mode &= ~current_umask(); | 2866 | sattr->ia_mode &= ~current_umask(); |
2824 | state = nfs4_do_open(dir, dentry, ctx->mode, flags, sattr, ctx->cred, NULL); | 2867 | state = nfs4_do_open(dir, dentry, ctx->mode, |
2868 | flags, sattr, ctx->cred, | ||
2869 | &ctx->mdsthreshold); | ||
2825 | d_drop(dentry); | 2870 | d_drop(dentry); |
2826 | if (IS_ERR(state)) { | 2871 | if (IS_ERR(state)) { |
2827 | status = PTR_ERR(state); | 2872 | status = PTR_ERR(state); |
@@ -3315,8 +3360,14 @@ static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, str | |||
3315 | 3360 | ||
3316 | static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) | 3361 | static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) |
3317 | { | 3362 | { |
3363 | int error; | ||
3364 | |||
3318 | nfs_fattr_init(fsinfo->fattr); | 3365 | nfs_fattr_init(fsinfo->fattr); |
3319 | return nfs4_do_fsinfo(server, fhandle, fsinfo); | 3366 | error = nfs4_do_fsinfo(server, fhandle, fsinfo); |
3367 | if (error == 0) | ||
3368 | set_pnfs_layoutdriver(server, fhandle, fsinfo->layouttype); | ||
3369 | |||
3370 | return error; | ||
3320 | } | 3371 | } |
3321 | 3372 | ||
3322 | static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | 3373 | static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, |
@@ -3443,7 +3494,7 @@ bool nfs4_write_need_cache_consistency_data(const struct nfs_write_data *data) | |||
3443 | /* Otherwise, request attributes if and only if we don't hold | 3494 | /* Otherwise, request attributes if and only if we don't hold |
3444 | * a delegation | 3495 | * a delegation |
3445 | */ | 3496 | */ |
3446 | return nfs_have_delegation(hdr->inode, FMODE_READ) == 0; | 3497 | return nfs4_have_delegation(hdr->inode, FMODE_READ) == 0; |
3447 | } | 3498 | } |
3448 | 3499 | ||
3449 | static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) | 3500 | static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) |
@@ -3732,7 +3783,8 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
3732 | .rpc_argp = &args, | 3783 | .rpc_argp = &args, |
3733 | .rpc_resp = &res, | 3784 | .rpc_resp = &res, |
3734 | }; | 3785 | }; |
3735 | int ret = -ENOMEM, npages, i, acl_len = 0; | 3786 | int ret = -ENOMEM, npages, i; |
3787 | size_t acl_len = 0; | ||
3736 | 3788 | ||
3737 | npages = (buflen + PAGE_SIZE - 1) >> PAGE_SHIFT; | 3789 | npages = (buflen + PAGE_SIZE - 1) >> PAGE_SHIFT; |
3738 | /* As long as we're doing a round trip to the server anyway, | 3790 | /* As long as we're doing a round trip to the server anyway, |
@@ -3847,7 +3899,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl | |||
3847 | i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase); | 3899 | i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase); |
3848 | if (i < 0) | 3900 | if (i < 0) |
3849 | return i; | 3901 | return i; |
3850 | nfs_inode_return_delegation(inode); | 3902 | nfs4_inode_return_delegation(inode); |
3851 | ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); | 3903 | ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
3852 | 3904 | ||
3853 | /* | 3905 | /* |
@@ -3961,6 +4013,16 @@ static void nfs4_init_boot_verifier(const struct nfs_client *clp, | |||
3961 | memcpy(bootverf->data, verf, sizeof(bootverf->data)); | 4013 | memcpy(bootverf->data, verf, sizeof(bootverf->data)); |
3962 | } | 4014 | } |
3963 | 4015 | ||
4016 | /** | ||
4017 | * nfs4_proc_setclientid - Negotiate client ID | ||
4018 | * @clp: state data structure | ||
4019 | * @program: RPC program for NFSv4 callback service | ||
4020 | * @port: IP port number for NFS4 callback service | ||
4021 | * @cred: RPC credential to use for this call | ||
4022 | * @res: where to place the result | ||
4023 | * | ||
4024 | * Returns zero, a negative errno, or a negative NFS4ERR status code. | ||
4025 | */ | ||
3964 | int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | 4026 | int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, |
3965 | unsigned short port, struct rpc_cred *cred, | 4027 | unsigned short port, struct rpc_cred *cred, |
3966 | struct nfs4_setclientid_res *res) | 4028 | struct nfs4_setclientid_res *res) |
@@ -3977,44 +4039,44 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
3977 | .rpc_resp = res, | 4039 | .rpc_resp = res, |
3978 | .rpc_cred = cred, | 4040 | .rpc_cred = cred, |
3979 | }; | 4041 | }; |
3980 | int loop = 0; | ||
3981 | int status; | 4042 | int status; |
3982 | 4043 | ||
4044 | /* nfs_client_id4 */ | ||
3983 | nfs4_init_boot_verifier(clp, &sc_verifier); | 4045 | nfs4_init_boot_verifier(clp, &sc_verifier); |
3984 | 4046 | rcu_read_lock(); | |
3985 | for(;;) { | 4047 | setclientid.sc_name_len = scnprintf(setclientid.sc_name, |
3986 | rcu_read_lock(); | 4048 | sizeof(setclientid.sc_name), "%s/%s %s", |
3987 | setclientid.sc_name_len = scnprintf(setclientid.sc_name, | 4049 | clp->cl_ipaddr, |
3988 | sizeof(setclientid.sc_name), "%s/%s %s %s %u", | 4050 | rpc_peeraddr2str(clp->cl_rpcclient, |
3989 | clp->cl_ipaddr, | 4051 | RPC_DISPLAY_ADDR), |
3990 | rpc_peeraddr2str(clp->cl_rpcclient, | 4052 | rpc_peeraddr2str(clp->cl_rpcclient, |
3991 | RPC_DISPLAY_ADDR), | 4053 | RPC_DISPLAY_PROTO)); |
3992 | rpc_peeraddr2str(clp->cl_rpcclient, | 4054 | /* cb_client4 */ |
3993 | RPC_DISPLAY_PROTO), | 4055 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, |
3994 | clp->cl_rpcclient->cl_auth->au_ops->au_name, | ||
3995 | clp->cl_id_uniquifier); | ||
3996 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, | ||
3997 | sizeof(setclientid.sc_netid), | 4056 | sizeof(setclientid.sc_netid), |
3998 | rpc_peeraddr2str(clp->cl_rpcclient, | 4057 | rpc_peeraddr2str(clp->cl_rpcclient, |
3999 | RPC_DISPLAY_NETID)); | 4058 | RPC_DISPLAY_NETID)); |
4000 | setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr, | 4059 | rcu_read_unlock(); |
4060 | setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr, | ||
4001 | sizeof(setclientid.sc_uaddr), "%s.%u.%u", | 4061 | sizeof(setclientid.sc_uaddr), "%s.%u.%u", |
4002 | clp->cl_ipaddr, port >> 8, port & 255); | 4062 | clp->cl_ipaddr, port >> 8, port & 255); |
4003 | rcu_read_unlock(); | ||
4004 | 4063 | ||
4005 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 4064 | dprintk("NFS call setclientid auth=%s, '%.*s'\n", |
4006 | if (status != -NFS4ERR_CLID_INUSE) | 4065 | clp->cl_rpcclient->cl_auth->au_ops->au_name, |
4007 | break; | 4066 | setclientid.sc_name_len, setclientid.sc_name); |
4008 | if (loop != 0) { | 4067 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
4009 | ++clp->cl_id_uniquifier; | 4068 | dprintk("NFS reply setclientid: %d\n", status); |
4010 | break; | ||
4011 | } | ||
4012 | ++loop; | ||
4013 | ssleep(clp->cl_lease_time / HZ + 1); | ||
4014 | } | ||
4015 | return status; | 4069 | return status; |
4016 | } | 4070 | } |
4017 | 4071 | ||
4072 | /** | ||
4073 | * nfs4_proc_setclientid_confirm - Confirm client ID | ||
4074 | * @clp: state data structure | ||
4075 | * @res: result of a previous SETCLIENTID | ||
4076 | * @cred: RPC credential to use for this call | ||
4077 | * | ||
4078 | * Returns zero, a negative errno, or a negative NFS4ERR status code. | ||
4079 | */ | ||
4018 | int nfs4_proc_setclientid_confirm(struct nfs_client *clp, | 4080 | int nfs4_proc_setclientid_confirm(struct nfs_client *clp, |
4019 | struct nfs4_setclientid_res *arg, | 4081 | struct nfs4_setclientid_res *arg, |
4020 | struct rpc_cred *cred) | 4082 | struct rpc_cred *cred) |
@@ -4029,6 +4091,9 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp, | |||
4029 | unsigned long now; | 4091 | unsigned long now; |
4030 | int status; | 4092 | int status; |
4031 | 4093 | ||
4094 | dprintk("NFS call setclientid_confirm auth=%s, (client ID %llx)\n", | ||
4095 | clp->cl_rpcclient->cl_auth->au_ops->au_name, | ||
4096 | clp->cl_clientid); | ||
4032 | now = jiffies; | 4097 | now = jiffies; |
4033 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 4098 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
4034 | if (status == 0) { | 4099 | if (status == 0) { |
@@ -4037,6 +4102,7 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp, | |||
4037 | clp->cl_last_renewal = now; | 4102 | clp->cl_last_renewal = now; |
4038 | spin_unlock(&clp->cl_lock); | 4103 | spin_unlock(&clp->cl_lock); |
4039 | } | 4104 | } |
4105 | dprintk("NFS reply setclientid_confirm: %d\n", status); | ||
4040 | return status; | 4106 | return status; |
4041 | } | 4107 | } |
4042 | 4108 | ||
@@ -4681,9 +4747,17 @@ out: | |||
4681 | } | 4747 | } |
4682 | 4748 | ||
4683 | #if defined(CONFIG_NFS_V4_1) | 4749 | #if defined(CONFIG_NFS_V4_1) |
4750 | /** | ||
4751 | * nfs41_check_expired_locks - possibly free a lock stateid | ||
4752 | * | ||
4753 | * @state: NFSv4 state for an inode | ||
4754 | * | ||
4755 | * Returns NFS_OK if recovery for this stateid is now finished. | ||
4756 | * Otherwise a negative NFS4ERR value is returned. | ||
4757 | */ | ||
4684 | static int nfs41_check_expired_locks(struct nfs4_state *state) | 4758 | static int nfs41_check_expired_locks(struct nfs4_state *state) |
4685 | { | 4759 | { |
4686 | int status, ret = NFS_OK; | 4760 | int status, ret = -NFS4ERR_BAD_STATEID; |
4687 | struct nfs4_lock_state *lsp; | 4761 | struct nfs4_lock_state *lsp; |
4688 | struct nfs_server *server = NFS_SERVER(state->inode); | 4762 | struct nfs_server *server = NFS_SERVER(state->inode); |
4689 | 4763 | ||
@@ -4691,7 +4765,11 @@ static int nfs41_check_expired_locks(struct nfs4_state *state) | |||
4691 | if (lsp->ls_flags & NFS_LOCK_INITIALIZED) { | 4765 | if (lsp->ls_flags & NFS_LOCK_INITIALIZED) { |
4692 | status = nfs41_test_stateid(server, &lsp->ls_stateid); | 4766 | status = nfs41_test_stateid(server, &lsp->ls_stateid); |
4693 | if (status != NFS_OK) { | 4767 | if (status != NFS_OK) { |
4694 | nfs41_free_stateid(server, &lsp->ls_stateid); | 4768 | /* Free the stateid unless the server |
4769 | * informs us the stateid is unrecognized. */ | ||
4770 | if (status != -NFS4ERR_BAD_STATEID) | ||
4771 | nfs41_free_stateid(server, | ||
4772 | &lsp->ls_stateid); | ||
4695 | lsp->ls_flags &= ~NFS_LOCK_INITIALIZED; | 4773 | lsp->ls_flags &= ~NFS_LOCK_INITIALIZED; |
4696 | ret = status; | 4774 | ret = status; |
4697 | } | 4775 | } |
@@ -4707,9 +4785,9 @@ static int nfs41_lock_expired(struct nfs4_state *state, struct file_lock *reques | |||
4707 | 4785 | ||
4708 | if (test_bit(LK_STATE_IN_USE, &state->flags)) | 4786 | if (test_bit(LK_STATE_IN_USE, &state->flags)) |
4709 | status = nfs41_check_expired_locks(state); | 4787 | status = nfs41_check_expired_locks(state); |
4710 | if (status == NFS_OK) | 4788 | if (status != NFS_OK) |
4711 | return status; | 4789 | status = nfs4_lock_expired(state, request); |
4712 | return nfs4_lock_expired(state, request); | 4790 | return status; |
4713 | } | 4791 | } |
4714 | #endif | 4792 | #endif |
4715 | 4793 | ||
@@ -4807,7 +4885,7 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request) | |||
4807 | * Don't rely on the VFS having checked the file open mode, | 4885 | * Don't rely on the VFS having checked the file open mode, |
4808 | * since it won't do this for flock() locks. | 4886 | * since it won't do this for flock() locks. |
4809 | */ | 4887 | */ |
4810 | switch (request->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) { | 4888 | switch (request->fl_type) { |
4811 | case F_RDLCK: | 4889 | case F_RDLCK: |
4812 | if (!(filp->f_mode & FMODE_READ)) | 4890 | if (!(filp->f_mode & FMODE_READ)) |
4813 | return -EBADF; | 4891 | return -EBADF; |
@@ -5168,6 +5246,8 @@ out: | |||
5168 | /* | 5246 | /* |
5169 | * nfs4_proc_exchange_id() | 5247 | * nfs4_proc_exchange_id() |
5170 | * | 5248 | * |
5249 | * Returns zero, a negative errno, or a negative NFS4ERR status code. | ||
5250 | * | ||
5171 | * Since the clientid has expired, all compounds using sessions | 5251 | * Since the clientid has expired, all compounds using sessions |
5172 | * associated with the stale clientid will be returning | 5252 | * associated with the stale clientid will be returning |
5173 | * NFS4ERR_BADSESSION in the sequence operation, and will therefore | 5253 | * NFS4ERR_BADSESSION in the sequence operation, and will therefore |
@@ -5192,16 +5272,14 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
5192 | .rpc_cred = cred, | 5272 | .rpc_cred = cred, |
5193 | }; | 5273 | }; |
5194 | 5274 | ||
5195 | dprintk("--> %s\n", __func__); | ||
5196 | BUG_ON(clp == NULL); | ||
5197 | |||
5198 | nfs4_init_boot_verifier(clp, &verifier); | 5275 | nfs4_init_boot_verifier(clp, &verifier); |
5199 | |||
5200 | args.id_len = scnprintf(args.id, sizeof(args.id), | 5276 | args.id_len = scnprintf(args.id, sizeof(args.id), |
5201 | "%s/%s/%u", | 5277 | "%s/%s", |
5202 | clp->cl_ipaddr, | 5278 | clp->cl_ipaddr, |
5203 | clp->cl_rpcclient->cl_nodename, | 5279 | clp->cl_rpcclient->cl_nodename); |
5204 | clp->cl_rpcclient->cl_auth->au_flavor); | 5280 | dprintk("NFS call exchange_id auth=%s, '%.*s'\n", |
5281 | clp->cl_rpcclient->cl_auth->au_ops->au_name, | ||
5282 | args.id_len, args.id); | ||
5205 | 5283 | ||
5206 | res.server_owner = kzalloc(sizeof(struct nfs41_server_owner), | 5284 | res.server_owner = kzalloc(sizeof(struct nfs41_server_owner), |
5207 | GFP_NOFS); | 5285 | GFP_NOFS); |
@@ -5264,12 +5342,12 @@ out_server_scope: | |||
5264 | kfree(res.server_scope); | 5342 | kfree(res.server_scope); |
5265 | out: | 5343 | out: |
5266 | if (clp->cl_implid != NULL) | 5344 | if (clp->cl_implid != NULL) |
5267 | dprintk("%s: Server Implementation ID: " | 5345 | dprintk("NFS reply exchange_id: Server Implementation ID: " |
5268 | "domain: %s, name: %s, date: %llu,%u\n", | 5346 | "domain: %s, name: %s, date: %llu,%u\n", |
5269 | __func__, clp->cl_implid->domain, clp->cl_implid->name, | 5347 | clp->cl_implid->domain, clp->cl_implid->name, |
5270 | clp->cl_implid->date.seconds, | 5348 | clp->cl_implid->date.seconds, |
5271 | clp->cl_implid->date.nseconds); | 5349 | clp->cl_implid->date.nseconds); |
5272 | dprintk("<-- %s status= %d\n", __func__, status); | 5350 | dprintk("NFS reply exchange_id: %d\n", status); |
5273 | return status; | 5351 | return status; |
5274 | } | 5352 | } |
5275 | 5353 | ||
@@ -6570,22 +6648,36 @@ static int _nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | |||
6570 | .rpc_resp = &res, | 6648 | .rpc_resp = &res, |
6571 | }; | 6649 | }; |
6572 | 6650 | ||
6651 | dprintk("NFS call test_stateid %p\n", stateid); | ||
6573 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); | 6652 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); |
6574 | status = nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); | 6653 | status = nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); |
6575 | 6654 | if (status != NFS_OK) { | |
6576 | if (status == NFS_OK) | 6655 | dprintk("NFS reply test_stateid: failed, %d\n", status); |
6577 | return res.status; | 6656 | return status; |
6578 | return status; | 6657 | } |
6658 | dprintk("NFS reply test_stateid: succeeded, %d\n", -res.status); | ||
6659 | return -res.status; | ||
6579 | } | 6660 | } |
6580 | 6661 | ||
6662 | /** | ||
6663 | * nfs41_test_stateid - perform a TEST_STATEID operation | ||
6664 | * | ||
6665 | * @server: server / transport on which to perform the operation | ||
6666 | * @stateid: state ID to test | ||
6667 | * | ||
6668 | * Returns NFS_OK if the server recognizes that "stateid" is valid. | ||
6669 | * Otherwise a negative NFS4ERR value is returned if the operation | ||
6670 | * failed or the state ID is not currently valid. | ||
6671 | */ | ||
6581 | static int nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) | 6672 | static int nfs41_test_stateid(struct nfs_server *server, nfs4_stateid *stateid) |
6582 | { | 6673 | { |
6583 | struct nfs4_exception exception = { }; | 6674 | struct nfs4_exception exception = { }; |
6584 | int err; | 6675 | int err; |
6585 | do { | 6676 | do { |
6586 | err = nfs4_handle_exception(server, | 6677 | err = _nfs41_test_stateid(server, stateid); |
6587 | _nfs41_test_stateid(server, stateid), | 6678 | if (err != -NFS4ERR_DELAY) |
6588 | &exception); | 6679 | break; |
6680 | nfs4_handle_exception(server, err, &exception); | ||
6589 | } while (exception.retry); | 6681 | } while (exception.retry); |
6590 | return err; | 6682 | return err; |
6591 | } | 6683 | } |
@@ -6601,19 +6693,34 @@ static int _nfs4_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) | |||
6601 | .rpc_argp = &args, | 6693 | .rpc_argp = &args, |
6602 | .rpc_resp = &res, | 6694 | .rpc_resp = &res, |
6603 | }; | 6695 | }; |
6696 | int status; | ||
6604 | 6697 | ||
6698 | dprintk("NFS call free_stateid %p\n", stateid); | ||
6605 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); | 6699 | nfs41_init_sequence(&args.seq_args, &res.seq_res, 0); |
6606 | return nfs4_call_sync_sequence(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); | 6700 | status = nfs4_call_sync_sequence(server->client, server, &msg, |
6701 | &args.seq_args, &res.seq_res, 1); | ||
6702 | dprintk("NFS reply free_stateid: %d\n", status); | ||
6703 | return status; | ||
6607 | } | 6704 | } |
6608 | 6705 | ||
6706 | /** | ||
6707 | * nfs41_free_stateid - perform a FREE_STATEID operation | ||
6708 | * | ||
6709 | * @server: server / transport on which to perform the operation | ||
6710 | * @stateid: state ID to release | ||
6711 | * | ||
6712 | * Returns NFS_OK if the server freed "stateid". Otherwise a | ||
6713 | * negative NFS4ERR value is returned. | ||
6714 | */ | ||
6609 | static int nfs41_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) | 6715 | static int nfs41_free_stateid(struct nfs_server *server, nfs4_stateid *stateid) |
6610 | { | 6716 | { |
6611 | struct nfs4_exception exception = { }; | 6717 | struct nfs4_exception exception = { }; |
6612 | int err; | 6718 | int err; |
6613 | do { | 6719 | do { |
6614 | err = nfs4_handle_exception(server, | 6720 | err = _nfs4_free_stateid(server, stateid); |
6615 | _nfs4_free_stateid(server, stateid), | 6721 | if (err != -NFS4ERR_DELAY) |
6616 | &exception); | 6722 | break; |
6723 | nfs4_handle_exception(server, err, &exception); | ||
6617 | } while (exception.retry); | 6724 | } while (exception.retry); |
6618 | return err; | 6725 | return err; |
6619 | } | 6726 | } |
@@ -6725,6 +6832,26 @@ const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = { | |||
6725 | #endif | 6832 | #endif |
6726 | }; | 6833 | }; |
6727 | 6834 | ||
6835 | const struct inode_operations nfs4_dir_inode_operations = { | ||
6836 | .create = nfs_create, | ||
6837 | .lookup = nfs_lookup, | ||
6838 | .atomic_open = nfs_atomic_open, | ||
6839 | .link = nfs_link, | ||
6840 | .unlink = nfs_unlink, | ||
6841 | .symlink = nfs_symlink, | ||
6842 | .mkdir = nfs_mkdir, | ||
6843 | .rmdir = nfs_rmdir, | ||
6844 | .mknod = nfs_mknod, | ||
6845 | .rename = nfs_rename, | ||
6846 | .permission = nfs_permission, | ||
6847 | .getattr = nfs_getattr, | ||
6848 | .setattr = nfs_setattr, | ||
6849 | .getxattr = generic_getxattr, | ||
6850 | .setxattr = generic_setxattr, | ||
6851 | .listxattr = generic_listxattr, | ||
6852 | .removexattr = generic_removexattr, | ||
6853 | }; | ||
6854 | |||
6728 | static const struct inode_operations nfs4_file_inode_operations = { | 6855 | static const struct inode_operations nfs4_file_inode_operations = { |
6729 | .permission = nfs_permission, | 6856 | .permission = nfs_permission, |
6730 | .getattr = nfs_getattr, | 6857 | .getattr = nfs_getattr, |
@@ -6769,9 +6896,11 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
6769 | .set_capabilities = nfs4_server_capabilities, | 6896 | .set_capabilities = nfs4_server_capabilities, |
6770 | .decode_dirent = nfs4_decode_dirent, | 6897 | .decode_dirent = nfs4_decode_dirent, |
6771 | .read_setup = nfs4_proc_read_setup, | 6898 | .read_setup = nfs4_proc_read_setup, |
6899 | .read_pageio_init = pnfs_pageio_init_read, | ||
6772 | .read_rpc_prepare = nfs4_proc_read_rpc_prepare, | 6900 | .read_rpc_prepare = nfs4_proc_read_rpc_prepare, |
6773 | .read_done = nfs4_read_done, | 6901 | .read_done = nfs4_read_done, |
6774 | .write_setup = nfs4_proc_write_setup, | 6902 | .write_setup = nfs4_proc_write_setup, |
6903 | .write_pageio_init = pnfs_pageio_init_write, | ||
6775 | .write_rpc_prepare = nfs4_proc_write_rpc_prepare, | 6904 | .write_rpc_prepare = nfs4_proc_write_rpc_prepare, |
6776 | .write_done = nfs4_write_done, | 6905 | .write_done = nfs4_write_done, |
6777 | .commit_setup = nfs4_proc_commit_setup, | 6906 | .commit_setup = nfs4_proc_commit_setup, |
@@ -6781,7 +6910,11 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
6781 | .clear_acl_cache = nfs4_zap_acl_attr, | 6910 | .clear_acl_cache = nfs4_zap_acl_attr, |
6782 | .close_context = nfs4_close_context, | 6911 | .close_context = nfs4_close_context, |
6783 | .open_context = nfs4_atomic_open, | 6912 | .open_context = nfs4_atomic_open, |
6913 | .have_delegation = nfs4_have_delegation, | ||
6914 | .return_delegation = nfs4_inode_return_delegation, | ||
6915 | .alloc_client = nfs4_alloc_client, | ||
6784 | .init_client = nfs4_init_client, | 6916 | .init_client = nfs4_init_client, |
6917 | .free_client = nfs4_free_client, | ||
6785 | }; | 6918 | }; |
6786 | 6919 | ||
6787 | static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { | 6920 | static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { |