diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 580 |
1 files changed, 391 insertions, 189 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 99650aaf893..15fc7e4664e 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -64,6 +64,7 @@ | |||
64 | #include "iostat.h" | 64 | #include "iostat.h" |
65 | #include "callback.h" | 65 | #include "callback.h" |
66 | #include "pnfs.h" | 66 | #include "pnfs.h" |
67 | #include "netns.h" | ||
67 | 68 | ||
68 | #define NFSDBG_FACILITY NFSDBG_PROC | 69 | #define NFSDBG_FACILITY NFSDBG_PROC |
69 | 70 | ||
@@ -80,6 +81,7 @@ static int _nfs4_recover_proc_open(struct nfs4_opendata *data); | |||
80 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 81 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); |
81 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); | 82 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); |
82 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); | 83 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); |
84 | static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *); | ||
83 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); | 85 | static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); |
84 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | 86 | static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, |
85 | struct nfs_fattr *fattr, struct iattr *sattr, | 87 | struct nfs_fattr *fattr, struct iattr *sattr, |
@@ -101,6 +103,10 @@ static int nfs4_map_errors(int err) | |||
101 | case -NFS4ERR_BADOWNER: | 103 | case -NFS4ERR_BADOWNER: |
102 | case -NFS4ERR_BADNAME: | 104 | case -NFS4ERR_BADNAME: |
103 | return -EINVAL; | 105 | return -EINVAL; |
106 | case -NFS4ERR_SHARE_DENIED: | ||
107 | return -EACCES; | ||
108 | case -NFS4ERR_MINOR_VERS_MISMATCH: | ||
109 | return -EPROTONOSUPPORT; | ||
104 | default: | 110 | default: |
105 | dprintk("%s could not handle NFSv4 error %d\n", | 111 | dprintk("%s could not handle NFSv4 error %d\n", |
106 | __func__, -err); | 112 | __func__, -err); |
@@ -112,7 +118,7 @@ static int nfs4_map_errors(int err) | |||
112 | /* | 118 | /* |
113 | * This is our standard bitmap for GETATTR requests. | 119 | * This is our standard bitmap for GETATTR requests. |
114 | */ | 120 | */ |
115 | const u32 nfs4_fattr_bitmap[2] = { | 121 | const u32 nfs4_fattr_bitmap[3] = { |
116 | FATTR4_WORD0_TYPE | 122 | FATTR4_WORD0_TYPE |
117 | | FATTR4_WORD0_CHANGE | 123 | | FATTR4_WORD0_CHANGE |
118 | | FATTR4_WORD0_SIZE | 124 | | FATTR4_WORD0_SIZE |
@@ -129,6 +135,24 @@ const u32 nfs4_fattr_bitmap[2] = { | |||
129 | | FATTR4_WORD1_TIME_MODIFY | 135 | | FATTR4_WORD1_TIME_MODIFY |
130 | }; | 136 | }; |
131 | 137 | ||
138 | static const u32 nfs4_pnfs_open_bitmap[3] = { | ||
139 | FATTR4_WORD0_TYPE | ||
140 | | FATTR4_WORD0_CHANGE | ||
141 | | FATTR4_WORD0_SIZE | ||
142 | | FATTR4_WORD0_FSID | ||
143 | | FATTR4_WORD0_FILEID, | ||
144 | FATTR4_WORD1_MODE | ||
145 | | FATTR4_WORD1_NUMLINKS | ||
146 | | FATTR4_WORD1_OWNER | ||
147 | | FATTR4_WORD1_OWNER_GROUP | ||
148 | | FATTR4_WORD1_RAWDEV | ||
149 | | FATTR4_WORD1_SPACE_USED | ||
150 | | FATTR4_WORD1_TIME_ACCESS | ||
151 | | FATTR4_WORD1_TIME_METADATA | ||
152 | | FATTR4_WORD1_TIME_MODIFY, | ||
153 | FATTR4_WORD2_MDSTHRESHOLD | ||
154 | }; | ||
155 | |||
132 | const u32 nfs4_statfs_bitmap[2] = { | 156 | const u32 nfs4_statfs_bitmap[2] = { |
133 | FATTR4_WORD0_FILES_AVAIL | 157 | FATTR4_WORD0_FILES_AVAIL |
134 | | FATTR4_WORD0_FILES_FREE | 158 | | FATTR4_WORD0_FILES_FREE |
@@ -304,7 +328,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc | |||
304 | case -NFS4ERR_SEQ_MISORDERED: | 328 | case -NFS4ERR_SEQ_MISORDERED: |
305 | dprintk("%s ERROR: %d Reset session\n", __func__, | 329 | dprintk("%s ERROR: %d Reset session\n", __func__, |
306 | errorcode); | 330 | errorcode); |
307 | nfs4_schedule_session_recovery(clp->cl_session); | 331 | nfs4_schedule_session_recovery(clp->cl_session, errorcode); |
308 | exception->retry = 1; | 332 | exception->retry = 1; |
309 | break; | 333 | break; |
310 | #endif /* defined(CONFIG_NFS_V4_1) */ | 334 | #endif /* defined(CONFIG_NFS_V4_1) */ |
@@ -772,7 +796,7 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) | |||
772 | struct nfs_inode *nfsi = NFS_I(dir); | 796 | struct nfs_inode *nfsi = NFS_I(dir); |
773 | 797 | ||
774 | spin_lock(&dir->i_lock); | 798 | spin_lock(&dir->i_lock); |
775 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA; | 799 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
776 | if (!cinfo->atomic || cinfo->before != dir->i_version) | 800 | if (!cinfo->atomic || cinfo->before != dir->i_version) |
777 | nfs_force_lookup_revalidate(dir); | 801 | nfs_force_lookup_revalidate(dir); |
778 | dir->i_version = cinfo->after; | 802 | dir->i_version = cinfo->after; |
@@ -788,7 +812,6 @@ struct nfs4_opendata { | |||
788 | struct nfs4_string owner_name; | 812 | struct nfs4_string owner_name; |
789 | struct nfs4_string group_name; | 813 | struct nfs4_string group_name; |
790 | struct nfs_fattr f_attr; | 814 | struct nfs_fattr f_attr; |
791 | struct nfs_fattr dir_attr; | ||
792 | struct dentry *dir; | 815 | struct dentry *dir; |
793 | struct dentry *dentry; | 816 | struct dentry *dentry; |
794 | struct nfs4_state_owner *owner; | 817 | struct nfs4_state_owner *owner; |
@@ -804,12 +827,10 @@ struct nfs4_opendata { | |||
804 | static void nfs4_init_opendata_res(struct nfs4_opendata *p) | 827 | static void nfs4_init_opendata_res(struct nfs4_opendata *p) |
805 | { | 828 | { |
806 | p->o_res.f_attr = &p->f_attr; | 829 | p->o_res.f_attr = &p->f_attr; |
807 | p->o_res.dir_attr = &p->dir_attr; | ||
808 | p->o_res.seqid = p->o_arg.seqid; | 830 | p->o_res.seqid = p->o_arg.seqid; |
809 | p->c_res.seqid = p->c_arg.seqid; | 831 | p->c_res.seqid = p->c_arg.seqid; |
810 | p->o_res.server = p->o_arg.server; | 832 | p->o_res.server = p->o_arg.server; |
811 | nfs_fattr_init(&p->f_attr); | 833 | nfs_fattr_init(&p->f_attr); |
812 | nfs_fattr_init(&p->dir_attr); | ||
813 | nfs_fattr_init_names(&p->f_attr, &p->owner_name, &p->group_name); | 834 | nfs_fattr_init_names(&p->f_attr, &p->owner_name, &p->group_name); |
814 | } | 835 | } |
815 | 836 | ||
@@ -843,7 +864,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
843 | p->o_arg.name = &dentry->d_name; | 864 | p->o_arg.name = &dentry->d_name; |
844 | p->o_arg.server = server; | 865 | p->o_arg.server = server; |
845 | p->o_arg.bitmask = server->attr_bitmask; | 866 | p->o_arg.bitmask = server->attr_bitmask; |
846 | p->o_arg.dir_bitmask = server->cache_consistency_bitmask; | 867 | p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0]; |
847 | p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; | 868 | p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; |
848 | if (attrs != NULL && attrs->ia_valid != 0) { | 869 | if (attrs != NULL && attrs->ia_valid != 0) { |
849 | __be32 verf[2]; | 870 | __be32 verf[2]; |
@@ -1332,7 +1353,7 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state | |||
1332 | case -NFS4ERR_BAD_HIGH_SLOT: | 1353 | case -NFS4ERR_BAD_HIGH_SLOT: |
1333 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: | 1354 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: |
1334 | case -NFS4ERR_DEADSESSION: | 1355 | case -NFS4ERR_DEADSESSION: |
1335 | nfs4_schedule_session_recovery(server->nfs_client->cl_session); | 1356 | nfs4_schedule_session_recovery(server->nfs_client->cl_session, err); |
1336 | goto out; | 1357 | goto out; |
1337 | case -NFS4ERR_STALE_CLIENTID: | 1358 | case -NFS4ERR_STALE_CLIENTID: |
1338 | case -NFS4ERR_STALE_STATEID: | 1359 | case -NFS4ERR_STALE_STATEID: |
@@ -1611,8 +1632,6 @@ static int _nfs4_recover_proc_open(struct nfs4_opendata *data) | |||
1611 | 1632 | ||
1612 | nfs_fattr_map_and_free_names(NFS_SERVER(dir), &data->f_attr); | 1633 | nfs_fattr_map_and_free_names(NFS_SERVER(dir), &data->f_attr); |
1613 | 1634 | ||
1614 | nfs_refresh_inode(dir, o_res->dir_attr); | ||
1615 | |||
1616 | if (o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { | 1635 | if (o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { |
1617 | status = _nfs4_proc_open_confirm(data); | 1636 | status = _nfs4_proc_open_confirm(data); |
1618 | if (status != 0) | 1637 | if (status != 0) |
@@ -1645,11 +1664,8 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) | |||
1645 | 1664 | ||
1646 | nfs_fattr_map_and_free_names(server, &data->f_attr); | 1665 | nfs_fattr_map_and_free_names(server, &data->f_attr); |
1647 | 1666 | ||
1648 | if (o_arg->open_flags & O_CREAT) { | 1667 | if (o_arg->open_flags & O_CREAT) |
1649 | update_changeattr(dir, &o_res->cinfo); | 1668 | update_changeattr(dir, &o_res->cinfo); |
1650 | nfs_post_op_update_inode(dir, o_res->dir_attr); | ||
1651 | } else | ||
1652 | nfs_refresh_inode(dir, o_res->dir_attr); | ||
1653 | if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0) | 1669 | if ((o_res->rflags & NFS4_OPEN_RESULT_LOCKTYPE_POSIX) == 0) |
1654 | server->caps &= ~NFS_CAP_POSIX_LOCK; | 1670 | server->caps &= ~NFS_CAP_POSIX_LOCK; |
1655 | if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { | 1671 | if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { |
@@ -1789,7 +1805,14 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct | |||
1789 | /* | 1805 | /* |
1790 | * Returns a referenced nfs4_state | 1806 | * Returns a referenced nfs4_state |
1791 | */ | 1807 | */ |
1792 | static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, fmode_t fmode, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res) | 1808 | static int _nfs4_do_open(struct inode *dir, |
1809 | struct dentry *dentry, | ||
1810 | fmode_t fmode, | ||
1811 | int flags, | ||
1812 | struct iattr *sattr, | ||
1813 | struct rpc_cred *cred, | ||
1814 | struct nfs4_state **res, | ||
1815 | struct nfs4_threshold **ctx_th) | ||
1793 | { | 1816 | { |
1794 | struct nfs4_state_owner *sp; | 1817 | struct nfs4_state_owner *sp; |
1795 | struct nfs4_state *state = NULL; | 1818 | struct nfs4_state *state = NULL; |
@@ -1814,6 +1837,12 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, fmode_t fmode | |||
1814 | if (opendata == NULL) | 1837 | if (opendata == NULL) |
1815 | goto err_put_state_owner; | 1838 | goto err_put_state_owner; |
1816 | 1839 | ||
1840 | if (ctx_th && server->attr_bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD) { | ||
1841 | opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc(); | ||
1842 | if (!opendata->f_attr.mdsthreshold) | ||
1843 | goto err_opendata_put; | ||
1844 | opendata->o_arg.open_bitmap = &nfs4_pnfs_open_bitmap[0]; | ||
1845 | } | ||
1817 | if (dentry->d_inode != NULL) | 1846 | if (dentry->d_inode != NULL) |
1818 | opendata->state = nfs4_get_open_state(dentry->d_inode, sp); | 1847 | opendata->state = nfs4_get_open_state(dentry->d_inode, sp); |
1819 | 1848 | ||
@@ -1839,11 +1868,19 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, fmode_t fmode | |||
1839 | nfs_setattr_update_inode(state->inode, sattr); | 1868 | nfs_setattr_update_inode(state->inode, sattr); |
1840 | nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr); | 1869 | nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr); |
1841 | } | 1870 | } |
1871 | |||
1872 | if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server)) | ||
1873 | *ctx_th = opendata->f_attr.mdsthreshold; | ||
1874 | else | ||
1875 | kfree(opendata->f_attr.mdsthreshold); | ||
1876 | opendata->f_attr.mdsthreshold = NULL; | ||
1877 | |||
1842 | nfs4_opendata_put(opendata); | 1878 | nfs4_opendata_put(opendata); |
1843 | nfs4_put_state_owner(sp); | 1879 | nfs4_put_state_owner(sp); |
1844 | *res = state; | 1880 | *res = state; |
1845 | return 0; | 1881 | return 0; |
1846 | err_opendata_put: | 1882 | err_opendata_put: |
1883 | kfree(opendata->f_attr.mdsthreshold); | ||
1847 | nfs4_opendata_put(opendata); | 1884 | nfs4_opendata_put(opendata); |
1848 | err_put_state_owner: | 1885 | err_put_state_owner: |
1849 | nfs4_put_state_owner(sp); | 1886 | nfs4_put_state_owner(sp); |
@@ -1853,14 +1890,22 @@ out_err: | |||
1853 | } | 1890 | } |
1854 | 1891 | ||
1855 | 1892 | ||
1856 | static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, fmode_t fmode, int flags, struct iattr *sattr, struct rpc_cred *cred) | 1893 | static struct nfs4_state *nfs4_do_open(struct inode *dir, |
1894 | struct dentry *dentry, | ||
1895 | fmode_t fmode, | ||
1896 | int flags, | ||
1897 | struct iattr *sattr, | ||
1898 | struct rpc_cred *cred, | ||
1899 | struct nfs4_threshold **ctx_th) | ||
1857 | { | 1900 | { |
1858 | struct nfs4_exception exception = { }; | 1901 | struct nfs4_exception exception = { }; |
1859 | struct nfs4_state *res; | 1902 | struct nfs4_state *res; |
1860 | int status; | 1903 | int status; |
1861 | 1904 | ||
1905 | fmode &= FMODE_READ|FMODE_WRITE; | ||
1862 | do { | 1906 | do { |
1863 | status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred, &res); | 1907 | status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred, |
1908 | &res, ctx_th); | ||
1864 | if (status == 0) | 1909 | if (status == 0) |
1865 | break; | 1910 | break; |
1866 | /* NOTE: BAD_SEQID means the server and client disagree about the | 1911 | /* NOTE: BAD_SEQID means the server and client disagree about the |
@@ -2184,7 +2229,8 @@ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags | |||
2184 | struct nfs4_state *state; | 2229 | struct nfs4_state *state; |
2185 | 2230 | ||
2186 | /* Protect against concurrent sillydeletes */ | 2231 | /* Protect against concurrent sillydeletes */ |
2187 | state = nfs4_do_open(dir, ctx->dentry, ctx->mode, open_flags, attr, ctx->cred); | 2232 | state = nfs4_do_open(dir, ctx->dentry, ctx->mode, open_flags, attr, |
2233 | ctx->cred, &ctx->mdsthreshold); | ||
2188 | if (IS_ERR(state)) | 2234 | if (IS_ERR(state)) |
2189 | return ERR_CAST(state); | 2235 | return ERR_CAST(state); |
2190 | ctx->state = state; | 2236 | ctx->state = state; |
@@ -2354,8 +2400,8 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2354 | /* | 2400 | /* |
2355 | * get the file handle for the "/" directory on the server | 2401 | * get the file handle for the "/" directory on the server |
2356 | */ | 2402 | */ |
2357 | static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | 2403 | int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle, |
2358 | struct nfs_fsinfo *info) | 2404 | struct nfs_fsinfo *info) |
2359 | { | 2405 | { |
2360 | int minor_version = server->nfs_client->cl_minorversion; | 2406 | int minor_version = server->nfs_client->cl_minorversion; |
2361 | int status = nfs4_lookup_root(server, fhandle, info); | 2407 | int status = nfs4_lookup_root(server, fhandle, info); |
@@ -2372,6 +2418,31 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2372 | return nfs4_map_errors(status); | 2418 | return nfs4_map_errors(status); |
2373 | } | 2419 | } |
2374 | 2420 | ||
2421 | static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *mntfh, | ||
2422 | struct nfs_fsinfo *info) | ||
2423 | { | ||
2424 | int error; | ||
2425 | struct nfs_fattr *fattr = info->fattr; | ||
2426 | |||
2427 | error = nfs4_server_capabilities(server, mntfh); | ||
2428 | if (error < 0) { | ||
2429 | dprintk("nfs4_get_root: getcaps error = %d\n", -error); | ||
2430 | return error; | ||
2431 | } | ||
2432 | |||
2433 | error = nfs4_proc_getattr(server, mntfh, fattr); | ||
2434 | if (error < 0) { | ||
2435 | dprintk("nfs4_get_root: getattr error = %d\n", -error); | ||
2436 | return error; | ||
2437 | } | ||
2438 | |||
2439 | if (fattr->valid & NFS_ATTR_FATTR_FSID && | ||
2440 | !nfs_fsid_equal(&server->fsid, &fattr->fsid)) | ||
2441 | memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid)); | ||
2442 | |||
2443 | return error; | ||
2444 | } | ||
2445 | |||
2375 | /* | 2446 | /* |
2376 | * Get locations and (maybe) other attributes of a referral. | 2447 | * Get locations and (maybe) other attributes of a referral. |
2377 | * Note that we'll actually follow the referral later when | 2448 | * Note that we'll actually follow the referral later when |
@@ -2478,6 +2549,14 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
2478 | 2549 | ||
2479 | nfs_fattr_init(fattr); | 2550 | nfs_fattr_init(fattr); |
2480 | 2551 | ||
2552 | /* Deal with open(O_TRUNC) */ | ||
2553 | if (sattr->ia_valid & ATTR_OPEN) | ||
2554 | sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); | ||
2555 | |||
2556 | /* Optimization: if the end result is no change, don't RPC */ | ||
2557 | if ((sattr->ia_valid & ~(ATTR_FILE)) == 0) | ||
2558 | return 0; | ||
2559 | |||
2481 | /* Search for an existing open(O_WRITE) file */ | 2560 | /* Search for an existing open(O_WRITE) file */ |
2482 | if (sattr->ia_valid & ATTR_FILE) { | 2561 | if (sattr->ia_valid & ATTR_FILE) { |
2483 | struct nfs_open_context *ctx; | 2562 | struct nfs_open_context *ctx; |
@@ -2489,10 +2568,6 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
2489 | } | 2568 | } |
2490 | } | 2569 | } |
2491 | 2570 | ||
2492 | /* Deal with open(O_TRUNC) */ | ||
2493 | if (sattr->ia_valid & ATTR_OPEN) | ||
2494 | sattr->ia_valid &= ~(ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); | ||
2495 | |||
2496 | status = nfs4_do_setattr(inode, cred, fattr, sattr, state); | 2571 | status = nfs4_do_setattr(inode, cred, fattr, sattr, state); |
2497 | if (status == 0) | 2572 | if (status == 0) |
2498 | nfs_setattr_update_inode(inode, sattr); | 2573 | nfs_setattr_update_inode(inode, sattr); |
@@ -2578,7 +2653,7 @@ out: | |||
2578 | return err; | 2653 | return err; |
2579 | } | 2654 | } |
2580 | 2655 | ||
2581 | static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, | 2656 | static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, |
2582 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 2657 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) |
2583 | { | 2658 | { |
2584 | int status; | 2659 | int status; |
@@ -2761,7 +2836,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
2761 | fmode = ctx->mode; | 2836 | fmode = ctx->mode; |
2762 | } | 2837 | } |
2763 | sattr->ia_mode &= ~current_umask(); | 2838 | sattr->ia_mode &= ~current_umask(); |
2764 | state = nfs4_do_open(dir, de, fmode, flags, sattr, cred); | 2839 | state = nfs4_do_open(dir, de, fmode, flags, sattr, cred, NULL); |
2765 | d_drop(dentry); | 2840 | d_drop(dentry); |
2766 | if (IS_ERR(state)) { | 2841 | if (IS_ERR(state)) { |
2767 | status = PTR_ERR(state); | 2842 | status = PTR_ERR(state); |
@@ -2782,9 +2857,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) | |||
2782 | struct nfs_server *server = NFS_SERVER(dir); | 2857 | struct nfs_server *server = NFS_SERVER(dir); |
2783 | struct nfs_removeargs args = { | 2858 | struct nfs_removeargs args = { |
2784 | .fh = NFS_FH(dir), | 2859 | .fh = NFS_FH(dir), |
2785 | .name.len = name->len, | 2860 | .name = *name, |
2786 | .name.name = name->name, | ||
2787 | .bitmask = server->attr_bitmask, | ||
2788 | }; | 2861 | }; |
2789 | struct nfs_removeres res = { | 2862 | struct nfs_removeres res = { |
2790 | .server = server, | 2863 | .server = server, |
@@ -2794,19 +2867,11 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) | |||
2794 | .rpc_argp = &args, | 2867 | .rpc_argp = &args, |
2795 | .rpc_resp = &res, | 2868 | .rpc_resp = &res, |
2796 | }; | 2869 | }; |
2797 | int status = -ENOMEM; | 2870 | int status; |
2798 | |||
2799 | res.dir_attr = nfs_alloc_fattr(); | ||
2800 | if (res.dir_attr == NULL) | ||
2801 | goto out; | ||
2802 | 2871 | ||
2803 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); | 2872 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 1); |
2804 | if (status == 0) { | 2873 | if (status == 0) |
2805 | update_changeattr(dir, &res.cinfo); | 2874 | update_changeattr(dir, &res.cinfo); |
2806 | nfs_post_op_update_inode(dir, res.dir_attr); | ||
2807 | } | ||
2808 | nfs_free_fattr(res.dir_attr); | ||
2809 | out: | ||
2810 | return status; | 2875 | return status; |
2811 | } | 2876 | } |
2812 | 2877 | ||
@@ -2828,7 +2893,6 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) | |||
2828 | struct nfs_removeargs *args = msg->rpc_argp; | 2893 | struct nfs_removeargs *args = msg->rpc_argp; |
2829 | struct nfs_removeres *res = msg->rpc_resp; | 2894 | struct nfs_removeres *res = msg->rpc_resp; |
2830 | 2895 | ||
2831 | args->bitmask = server->cache_consistency_bitmask; | ||
2832 | res->server = server; | 2896 | res->server = server; |
2833 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; | 2897 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; |
2834 | nfs41_init_sequence(&args->seq_args, &res->seq_res, 1); | 2898 | nfs41_init_sequence(&args->seq_args, &res->seq_res, 1); |
@@ -2853,7 +2917,6 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) | |||
2853 | if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) | 2917 | if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) |
2854 | return 0; | 2918 | return 0; |
2855 | update_changeattr(dir, &res->cinfo); | 2919 | update_changeattr(dir, &res->cinfo); |
2856 | nfs_post_op_update_inode(dir, res->dir_attr); | ||
2857 | return 1; | 2920 | return 1; |
2858 | } | 2921 | } |
2859 | 2922 | ||
@@ -2864,7 +2927,6 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir) | |||
2864 | struct nfs_renameres *res = msg->rpc_resp; | 2927 | struct nfs_renameres *res = msg->rpc_resp; |
2865 | 2928 | ||
2866 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME]; | 2929 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME]; |
2867 | arg->bitmask = server->attr_bitmask; | ||
2868 | res->server = server; | 2930 | res->server = server; |
2869 | nfs41_init_sequence(&arg->seq_args, &res->seq_res, 1); | 2931 | nfs41_init_sequence(&arg->seq_args, &res->seq_res, 1); |
2870 | } | 2932 | } |
@@ -2890,9 +2952,7 @@ static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir, | |||
2890 | return 0; | 2952 | return 0; |
2891 | 2953 | ||
2892 | update_changeattr(old_dir, &res->old_cinfo); | 2954 | update_changeattr(old_dir, &res->old_cinfo); |
2893 | nfs_post_op_update_inode(old_dir, res->old_fattr); | ||
2894 | update_changeattr(new_dir, &res->new_cinfo); | 2955 | update_changeattr(new_dir, &res->new_cinfo); |
2895 | nfs_post_op_update_inode(new_dir, res->new_fattr); | ||
2896 | return 1; | 2956 | return 1; |
2897 | } | 2957 | } |
2898 | 2958 | ||
@@ -2905,7 +2965,6 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
2905 | .new_dir = NFS_FH(new_dir), | 2965 | .new_dir = NFS_FH(new_dir), |
2906 | .old_name = old_name, | 2966 | .old_name = old_name, |
2907 | .new_name = new_name, | 2967 | .new_name = new_name, |
2908 | .bitmask = server->attr_bitmask, | ||
2909 | }; | 2968 | }; |
2910 | struct nfs_renameres res = { | 2969 | struct nfs_renameres res = { |
2911 | .server = server, | 2970 | .server = server, |
@@ -2917,21 +2976,11 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
2917 | }; | 2976 | }; |
2918 | int status = -ENOMEM; | 2977 | int status = -ENOMEM; |
2919 | 2978 | ||
2920 | res.old_fattr = nfs_alloc_fattr(); | ||
2921 | res.new_fattr = nfs_alloc_fattr(); | ||
2922 | if (res.old_fattr == NULL || res.new_fattr == NULL) | ||
2923 | goto out; | ||
2924 | |||
2925 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); | 2979 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
2926 | if (!status) { | 2980 | if (!status) { |
2927 | update_changeattr(old_dir, &res.old_cinfo); | 2981 | update_changeattr(old_dir, &res.old_cinfo); |
2928 | nfs_post_op_update_inode(old_dir, res.old_fattr); | ||
2929 | update_changeattr(new_dir, &res.new_cinfo); | 2982 | update_changeattr(new_dir, &res.new_cinfo); |
2930 | nfs_post_op_update_inode(new_dir, res.new_fattr); | ||
2931 | } | 2983 | } |
2932 | out: | ||
2933 | nfs_free_fattr(res.new_fattr); | ||
2934 | nfs_free_fattr(res.old_fattr); | ||
2935 | return status; | 2984 | return status; |
2936 | } | 2985 | } |
2937 | 2986 | ||
@@ -2969,18 +3018,15 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * | |||
2969 | int status = -ENOMEM; | 3018 | int status = -ENOMEM; |
2970 | 3019 | ||
2971 | res.fattr = nfs_alloc_fattr(); | 3020 | res.fattr = nfs_alloc_fattr(); |
2972 | res.dir_attr = nfs_alloc_fattr(); | 3021 | if (res.fattr == NULL) |
2973 | if (res.fattr == NULL || res.dir_attr == NULL) | ||
2974 | goto out; | 3022 | goto out; |
2975 | 3023 | ||
2976 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); | 3024 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
2977 | if (!status) { | 3025 | if (!status) { |
2978 | update_changeattr(dir, &res.cinfo); | 3026 | update_changeattr(dir, &res.cinfo); |
2979 | nfs_post_op_update_inode(dir, res.dir_attr); | ||
2980 | nfs_post_op_update_inode(inode, res.fattr); | 3027 | nfs_post_op_update_inode(inode, res.fattr); |
2981 | } | 3028 | } |
2982 | out: | 3029 | out: |
2983 | nfs_free_fattr(res.dir_attr); | ||
2984 | nfs_free_fattr(res.fattr); | 3030 | nfs_free_fattr(res.fattr); |
2985 | return status; | 3031 | return status; |
2986 | } | 3032 | } |
@@ -3003,7 +3049,6 @@ struct nfs4_createdata { | |||
3003 | struct nfs4_create_res res; | 3049 | struct nfs4_create_res res; |
3004 | struct nfs_fh fh; | 3050 | struct nfs_fh fh; |
3005 | struct nfs_fattr fattr; | 3051 | struct nfs_fattr fattr; |
3006 | struct nfs_fattr dir_fattr; | ||
3007 | }; | 3052 | }; |
3008 | 3053 | ||
3009 | static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, | 3054 | static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, |
@@ -3027,9 +3072,7 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, | |||
3027 | data->res.server = server; | 3072 | data->res.server = server; |
3028 | data->res.fh = &data->fh; | 3073 | data->res.fh = &data->fh; |
3029 | data->res.fattr = &data->fattr; | 3074 | data->res.fattr = &data->fattr; |
3030 | data->res.dir_fattr = &data->dir_fattr; | ||
3031 | nfs_fattr_init(data->res.fattr); | 3075 | nfs_fattr_init(data->res.fattr); |
3032 | nfs_fattr_init(data->res.dir_fattr); | ||
3033 | } | 3076 | } |
3034 | return data; | 3077 | return data; |
3035 | } | 3078 | } |
@@ -3040,7 +3083,6 @@ static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_ | |||
3040 | &data->arg.seq_args, &data->res.seq_res, 1); | 3083 | &data->arg.seq_args, &data->res.seq_res, 1); |
3041 | if (status == 0) { | 3084 | if (status == 0) { |
3042 | update_changeattr(dir, &data->res.dir_cinfo); | 3085 | update_changeattr(dir, &data->res.dir_cinfo); |
3043 | nfs_post_op_update_inode(dir, data->res.dir_fattr); | ||
3044 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); | 3086 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); |
3045 | } | 3087 | } |
3046 | return status; | 3088 | return status; |
@@ -3336,12 +3378,12 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | |||
3336 | 3378 | ||
3337 | void __nfs4_read_done_cb(struct nfs_read_data *data) | 3379 | void __nfs4_read_done_cb(struct nfs_read_data *data) |
3338 | { | 3380 | { |
3339 | nfs_invalidate_atime(data->inode); | 3381 | nfs_invalidate_atime(data->header->inode); |
3340 | } | 3382 | } |
3341 | 3383 | ||
3342 | static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data) | 3384 | static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data) |
3343 | { | 3385 | { |
3344 | struct nfs_server *server = NFS_SERVER(data->inode); | 3386 | struct nfs_server *server = NFS_SERVER(data->header->inode); |
3345 | 3387 | ||
3346 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { | 3388 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { |
3347 | rpc_restart_call_prepare(task); | 3389 | rpc_restart_call_prepare(task); |
@@ -3376,7 +3418,7 @@ static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message | |||
3376 | 3418 | ||
3377 | static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) | 3419 | static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data) |
3378 | { | 3420 | { |
3379 | if (nfs4_setup_sequence(NFS_SERVER(data->inode), | 3421 | if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), |
3380 | &data->args.seq_args, | 3422 | &data->args.seq_args, |
3381 | &data->res.seq_res, | 3423 | &data->res.seq_res, |
3382 | task)) | 3424 | task)) |
@@ -3384,25 +3426,9 @@ static void nfs4_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_da | |||
3384 | rpc_call_start(task); | 3426 | rpc_call_start(task); |
3385 | } | 3427 | } |
3386 | 3428 | ||
3387 | /* Reset the the nfs_read_data to send the read to the MDS. */ | ||
3388 | void nfs4_reset_read(struct rpc_task *task, struct nfs_read_data *data) | ||
3389 | { | ||
3390 | dprintk("%s Reset task for i/o through\n", __func__); | ||
3391 | put_lseg(data->lseg); | ||
3392 | data->lseg = NULL; | ||
3393 | /* offsets will differ in the dense stripe case */ | ||
3394 | data->args.offset = data->mds_offset; | ||
3395 | data->ds_clp = NULL; | ||
3396 | data->args.fh = NFS_FH(data->inode); | ||
3397 | data->read_done_cb = nfs4_read_done_cb; | ||
3398 | task->tk_ops = data->mds_ops; | ||
3399 | rpc_task_reset_client(task, NFS_CLIENT(data->inode)); | ||
3400 | } | ||
3401 | EXPORT_SYMBOL_GPL(nfs4_reset_read); | ||
3402 | |||
3403 | static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data) | 3429 | static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data) |
3404 | { | 3430 | { |
3405 | struct inode *inode = data->inode; | 3431 | struct inode *inode = data->header->inode; |
3406 | 3432 | ||
3407 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { | 3433 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { |
3408 | rpc_restart_call_prepare(task); | 3434 | rpc_restart_call_prepare(task); |
@@ -3410,7 +3436,7 @@ static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data | |||
3410 | } | 3436 | } |
3411 | if (task->tk_status >= 0) { | 3437 | if (task->tk_status >= 0) { |
3412 | renew_lease(NFS_SERVER(inode), data->timestamp); | 3438 | renew_lease(NFS_SERVER(inode), data->timestamp); |
3413 | nfs_post_op_update_inode_force_wcc(inode, data->res.fattr); | 3439 | nfs_post_op_update_inode_force_wcc(inode, &data->fattr); |
3414 | } | 3440 | } |
3415 | return 0; | 3441 | return 0; |
3416 | } | 3442 | } |
@@ -3423,32 +3449,30 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | |||
3423 | nfs4_write_done_cb(task, data); | 3449 | nfs4_write_done_cb(task, data); |
3424 | } | 3450 | } |
3425 | 3451 | ||
3426 | /* Reset the the nfs_write_data to send the write to the MDS. */ | 3452 | static |
3427 | void nfs4_reset_write(struct rpc_task *task, struct nfs_write_data *data) | 3453 | bool nfs4_write_need_cache_consistency_data(const struct nfs_write_data *data) |
3428 | { | 3454 | { |
3429 | dprintk("%s Reset task for i/o through\n", __func__); | 3455 | const struct nfs_pgio_header *hdr = data->header; |
3430 | put_lseg(data->lseg); | 3456 | |
3431 | data->lseg = NULL; | 3457 | /* Don't request attributes for pNFS or O_DIRECT writes */ |
3432 | data->ds_clp = NULL; | 3458 | if (data->ds_clp != NULL || hdr->dreq != NULL) |
3433 | data->write_done_cb = nfs4_write_done_cb; | 3459 | return false; |
3434 | data->args.fh = NFS_FH(data->inode); | 3460 | /* Otherwise, request attributes if and only if we don't hold |
3435 | data->args.bitmask = data->res.server->cache_consistency_bitmask; | 3461 | * a delegation |
3436 | data->args.offset = data->mds_offset; | 3462 | */ |
3437 | data->res.fattr = &data->fattr; | 3463 | return nfs_have_delegation(hdr->inode, FMODE_READ) == 0; |
3438 | task->tk_ops = data->mds_ops; | ||
3439 | rpc_task_reset_client(task, NFS_CLIENT(data->inode)); | ||
3440 | } | 3464 | } |
3441 | EXPORT_SYMBOL_GPL(nfs4_reset_write); | ||
3442 | 3465 | ||
3443 | static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) | 3466 | static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg) |
3444 | { | 3467 | { |
3445 | struct nfs_server *server = NFS_SERVER(data->inode); | 3468 | struct nfs_server *server = NFS_SERVER(data->header->inode); |
3446 | 3469 | ||
3447 | if (data->lseg) { | 3470 | if (!nfs4_write_need_cache_consistency_data(data)) { |
3448 | data->args.bitmask = NULL; | 3471 | data->args.bitmask = NULL; |
3449 | data->res.fattr = NULL; | 3472 | data->res.fattr = NULL; |
3450 | } else | 3473 | } else |
3451 | data->args.bitmask = server->cache_consistency_bitmask; | 3474 | data->args.bitmask = server->cache_consistency_bitmask; |
3475 | |||
3452 | if (!data->write_done_cb) | 3476 | if (!data->write_done_cb) |
3453 | data->write_done_cb = nfs4_write_done_cb; | 3477 | data->write_done_cb = nfs4_write_done_cb; |
3454 | data->res.server = server; | 3478 | data->res.server = server; |
@@ -3460,6 +3484,16 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag | |||
3460 | 3484 | ||
3461 | static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) | 3485 | static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_data *data) |
3462 | { | 3486 | { |
3487 | if (nfs4_setup_sequence(NFS_SERVER(data->header->inode), | ||
3488 | &data->args.seq_args, | ||
3489 | &data->res.seq_res, | ||
3490 | task)) | ||
3491 | return; | ||
3492 | rpc_call_start(task); | ||
3493 | } | ||
3494 | |||
3495 | static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data) | ||
3496 | { | ||
3463 | if (nfs4_setup_sequence(NFS_SERVER(data->inode), | 3497 | if (nfs4_setup_sequence(NFS_SERVER(data->inode), |
3464 | &data->args.seq_args, | 3498 | &data->args.seq_args, |
3465 | &data->res.seq_res, | 3499 | &data->res.seq_res, |
@@ -3468,7 +3502,7 @@ static void nfs4_proc_write_rpc_prepare(struct rpc_task *task, struct nfs_write_ | |||
3468 | rpc_call_start(task); | 3502 | rpc_call_start(task); |
3469 | } | 3503 | } |
3470 | 3504 | ||
3471 | static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_write_data *data) | 3505 | static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_commit_data *data) |
3472 | { | 3506 | { |
3473 | struct inode *inode = data->inode; | 3507 | struct inode *inode = data->inode; |
3474 | 3508 | ||
@@ -3476,28 +3510,22 @@ static int nfs4_commit_done_cb(struct rpc_task *task, struct nfs_write_data *dat | |||
3476 | rpc_restart_call_prepare(task); | 3510 | rpc_restart_call_prepare(task); |
3477 | return -EAGAIN; | 3511 | return -EAGAIN; |
3478 | } | 3512 | } |
3479 | nfs_refresh_inode(inode, data->res.fattr); | ||
3480 | return 0; | 3513 | return 0; |
3481 | } | 3514 | } |
3482 | 3515 | ||
3483 | static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) | 3516 | static int nfs4_commit_done(struct rpc_task *task, struct nfs_commit_data *data) |
3484 | { | 3517 | { |
3485 | if (!nfs4_sequence_done(task, &data->res.seq_res)) | 3518 | if (!nfs4_sequence_done(task, &data->res.seq_res)) |
3486 | return -EAGAIN; | 3519 | return -EAGAIN; |
3487 | return data->write_done_cb(task, data); | 3520 | return data->commit_done_cb(task, data); |
3488 | } | 3521 | } |
3489 | 3522 | ||
3490 | static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_message *msg) | 3523 | static void nfs4_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg) |
3491 | { | 3524 | { |
3492 | struct nfs_server *server = NFS_SERVER(data->inode); | 3525 | struct nfs_server *server = NFS_SERVER(data->inode); |
3493 | 3526 | ||
3494 | if (data->lseg) { | 3527 | if (data->commit_done_cb == NULL) |
3495 | data->args.bitmask = NULL; | 3528 | data->commit_done_cb = nfs4_commit_done_cb; |
3496 | data->res.fattr = NULL; | ||
3497 | } else | ||
3498 | data->args.bitmask = server->cache_consistency_bitmask; | ||
3499 | if (!data->write_done_cb) | ||
3500 | data->write_done_cb = nfs4_commit_done_cb; | ||
3501 | data->res.server = server; | 3529 | data->res.server = server; |
3502 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; | 3530 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT]; |
3503 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); | 3531 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); |
@@ -3906,7 +3934,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3906 | case -NFS4ERR_SEQ_MISORDERED: | 3934 | case -NFS4ERR_SEQ_MISORDERED: |
3907 | dprintk("%s ERROR %d, Reset session\n", __func__, | 3935 | dprintk("%s ERROR %d, Reset session\n", __func__, |
3908 | task->tk_status); | 3936 | task->tk_status); |
3909 | nfs4_schedule_session_recovery(clp->cl_session); | 3937 | nfs4_schedule_session_recovery(clp->cl_session, task->tk_status); |
3910 | task->tk_status = 0; | 3938 | task->tk_status = 0; |
3911 | return -EAGAIN; | 3939 | return -EAGAIN; |
3912 | #endif /* CONFIG_NFS_V4_1 */ | 3940 | #endif /* CONFIG_NFS_V4_1 */ |
@@ -3932,13 +3960,21 @@ wait_on_recovery: | |||
3932 | return -EAGAIN; | 3960 | return -EAGAIN; |
3933 | } | 3961 | } |
3934 | 3962 | ||
3935 | static void nfs4_construct_boot_verifier(struct nfs_client *clp, | 3963 | static void nfs4_init_boot_verifier(const struct nfs_client *clp, |
3936 | nfs4_verifier *bootverf) | 3964 | nfs4_verifier *bootverf) |
3937 | { | 3965 | { |
3938 | __be32 verf[2]; | 3966 | __be32 verf[2]; |
3939 | 3967 | ||
3940 | verf[0] = htonl((u32)clp->cl_boot_time.tv_sec); | 3968 | if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) { |
3941 | verf[1] = htonl((u32)clp->cl_boot_time.tv_nsec); | 3969 | /* An impossible timestamp guarantees this value |
3970 | * will never match a generated boot time. */ | ||
3971 | verf[0] = 0; | ||
3972 | verf[1] = (__be32)(NSEC_PER_SEC + 1); | ||
3973 | } else { | ||
3974 | struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); | ||
3975 | verf[0] = (__be32)nn->boot_time.tv_sec; | ||
3976 | verf[1] = (__be32)nn->boot_time.tv_nsec; | ||
3977 | } | ||
3942 | memcpy(bootverf->data, verf, sizeof(bootverf->data)); | 3978 | memcpy(bootverf->data, verf, sizeof(bootverf->data)); |
3943 | } | 3979 | } |
3944 | 3980 | ||
@@ -3961,7 +3997,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
3961 | int loop = 0; | 3997 | int loop = 0; |
3962 | int status; | 3998 | int status; |
3963 | 3999 | ||
3964 | nfs4_construct_boot_verifier(clp, &sc_verifier); | 4000 | nfs4_init_boot_verifier(clp, &sc_verifier); |
3965 | 4001 | ||
3966 | for(;;) { | 4002 | for(;;) { |
3967 | rcu_read_lock(); | 4003 | rcu_read_lock(); |
@@ -4105,7 +4141,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co | |||
4105 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); | 4141 | nfs41_init_sequence(&data->args.seq_args, &data->res.seq_res, 1); |
4106 | data->args.fhandle = &data->fh; | 4142 | data->args.fhandle = &data->fh; |
4107 | data->args.stateid = &data->stateid; | 4143 | data->args.stateid = &data->stateid; |
4108 | data->args.bitmask = server->attr_bitmask; | 4144 | data->args.bitmask = server->cache_consistency_bitmask; |
4109 | nfs_copy_fh(&data->fh, NFS_FH(inode)); | 4145 | nfs_copy_fh(&data->fh, NFS_FH(inode)); |
4110 | nfs4_stateid_copy(&data->stateid, stateid); | 4146 | nfs4_stateid_copy(&data->stateid, stateid); |
4111 | data->res.fattr = &data->fattr; | 4147 | data->res.fattr = &data->fattr; |
@@ -4126,9 +4162,10 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co | |||
4126 | if (status != 0) | 4162 | if (status != 0) |
4127 | goto out; | 4163 | goto out; |
4128 | status = data->rpc_status; | 4164 | status = data->rpc_status; |
4129 | if (status != 0) | 4165 | if (status == 0) |
4130 | goto out; | 4166 | nfs_post_op_update_inode_force_wcc(inode, &data->fattr); |
4131 | nfs_refresh_inode(inode, &data->fattr); | 4167 | else |
4168 | nfs_refresh_inode(inode, &data->fattr); | ||
4132 | out: | 4169 | out: |
4133 | rpc_put_task(task); | 4170 | rpc_put_task(task); |
4134 | return status; | 4171 | return status; |
@@ -4838,7 +4875,7 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) | |||
4838 | case -NFS4ERR_BAD_HIGH_SLOT: | 4875 | case -NFS4ERR_BAD_HIGH_SLOT: |
4839 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: | 4876 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: |
4840 | case -NFS4ERR_DEADSESSION: | 4877 | case -NFS4ERR_DEADSESSION: |
4841 | nfs4_schedule_session_recovery(server->nfs_client->cl_session); | 4878 | nfs4_schedule_session_recovery(server->nfs_client->cl_session, err); |
4842 | goto out; | 4879 | goto out; |
4843 | case -ERESTARTSYS: | 4880 | case -ERESTARTSYS: |
4844 | /* | 4881 | /* |
@@ -5080,7 +5117,8 @@ out_inval: | |||
5080 | } | 5117 | } |
5081 | 5118 | ||
5082 | static bool | 5119 | static bool |
5083 | nfs41_same_server_scope(struct server_scope *a, struct server_scope *b) | 5120 | nfs41_same_server_scope(struct nfs41_server_scope *a, |
5121 | struct nfs41_server_scope *b) | ||
5084 | { | 5122 | { |
5085 | if (a->server_scope_sz == b->server_scope_sz && | 5123 | if (a->server_scope_sz == b->server_scope_sz && |
5086 | memcmp(a->server_scope, b->server_scope, a->server_scope_sz) == 0) | 5124 | memcmp(a->server_scope, b->server_scope, a->server_scope_sz) == 0) |
@@ -5090,6 +5128,61 @@ nfs41_same_server_scope(struct server_scope *a, struct server_scope *b) | |||
5090 | } | 5128 | } |
5091 | 5129 | ||
5092 | /* | 5130 | /* |
5131 | * nfs4_proc_bind_conn_to_session() | ||
5132 | * | ||
5133 | * The 4.1 client currently uses the same TCP connection for the | ||
5134 | * fore and backchannel. | ||
5135 | */ | ||
5136 | int nfs4_proc_bind_conn_to_session(struct nfs_client *clp, struct rpc_cred *cred) | ||
5137 | { | ||
5138 | int status; | ||
5139 | struct nfs41_bind_conn_to_session_res res; | ||
5140 | struct rpc_message msg = { | ||
5141 | .rpc_proc = | ||
5142 | &nfs4_procedures[NFSPROC4_CLNT_BIND_CONN_TO_SESSION], | ||
5143 | .rpc_argp = clp, | ||
5144 | .rpc_resp = &res, | ||
5145 | .rpc_cred = cred, | ||
5146 | }; | ||
5147 | |||
5148 | dprintk("--> %s\n", __func__); | ||
5149 | BUG_ON(clp == NULL); | ||
5150 | |||
5151 | res.session = kzalloc(sizeof(struct nfs4_session), GFP_NOFS); | ||
5152 | if (unlikely(res.session == NULL)) { | ||
5153 | status = -ENOMEM; | ||
5154 | goto out; | ||
5155 | } | ||
5156 | |||
5157 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | ||
5158 | if (status == 0) { | ||
5159 | if (memcmp(res.session->sess_id.data, | ||
5160 | clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) { | ||
5161 | dprintk("NFS: %s: Session ID mismatch\n", __func__); | ||
5162 | status = -EIO; | ||
5163 | goto out_session; | ||
5164 | } | ||
5165 | if (res.dir != NFS4_CDFS4_BOTH) { | ||
5166 | dprintk("NFS: %s: Unexpected direction from server\n", | ||
5167 | __func__); | ||
5168 | status = -EIO; | ||
5169 | goto out_session; | ||
5170 | } | ||
5171 | if (res.use_conn_in_rdma_mode) { | ||
5172 | dprintk("NFS: %s: Server returned RDMA mode = true\n", | ||
5173 | __func__); | ||
5174 | status = -EIO; | ||
5175 | goto out_session; | ||
5176 | } | ||
5177 | } | ||
5178 | out_session: | ||
5179 | kfree(res.session); | ||
5180 | out: | ||
5181 | dprintk("<-- %s status= %d\n", __func__, status); | ||
5182 | return status; | ||
5183 | } | ||
5184 | |||
5185 | /* | ||
5093 | * nfs4_proc_exchange_id() | 5186 | * nfs4_proc_exchange_id() |
5094 | * | 5187 | * |
5095 | * Since the clientid has expired, all compounds using sessions | 5188 | * Since the clientid has expired, all compounds using sessions |
@@ -5106,7 +5199,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
5106 | .flags = EXCHGID4_FLAG_SUPP_MOVED_REFER, | 5199 | .flags = EXCHGID4_FLAG_SUPP_MOVED_REFER, |
5107 | }; | 5200 | }; |
5108 | struct nfs41_exchange_id_res res = { | 5201 | struct nfs41_exchange_id_res res = { |
5109 | .client = clp, | 5202 | 0 |
5110 | }; | 5203 | }; |
5111 | int status; | 5204 | int status; |
5112 | struct rpc_message msg = { | 5205 | struct rpc_message msg = { |
@@ -5119,7 +5212,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
5119 | dprintk("--> %s\n", __func__); | 5212 | dprintk("--> %s\n", __func__); |
5120 | BUG_ON(clp == NULL); | 5213 | BUG_ON(clp == NULL); |
5121 | 5214 | ||
5122 | nfs4_construct_boot_verifier(clp, &verifier); | 5215 | nfs4_init_boot_verifier(clp, &verifier); |
5123 | 5216 | ||
5124 | args.id_len = scnprintf(args.id, sizeof(args.id), | 5217 | args.id_len = scnprintf(args.id, sizeof(args.id), |
5125 | "%s/%s/%u", | 5218 | "%s/%s/%u", |
@@ -5127,59 +5220,135 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
5127 | clp->cl_rpcclient->cl_nodename, | 5220 | clp->cl_rpcclient->cl_nodename, |
5128 | clp->cl_rpcclient->cl_auth->au_flavor); | 5221 | clp->cl_rpcclient->cl_auth->au_flavor); |
5129 | 5222 | ||
5130 | res.server_scope = kzalloc(sizeof(struct server_scope), GFP_KERNEL); | 5223 | res.server_owner = kzalloc(sizeof(struct nfs41_server_owner), |
5131 | if (unlikely(!res.server_scope)) { | 5224 | GFP_NOFS); |
5225 | if (unlikely(res.server_owner == NULL)) { | ||
5132 | status = -ENOMEM; | 5226 | status = -ENOMEM; |
5133 | goto out; | 5227 | goto out; |
5134 | } | 5228 | } |
5135 | 5229 | ||
5136 | res.impl_id = kzalloc(sizeof(struct nfs41_impl_id), GFP_KERNEL); | 5230 | res.server_scope = kzalloc(sizeof(struct nfs41_server_scope), |
5137 | if (unlikely(!res.impl_id)) { | 5231 | GFP_NOFS); |
5232 | if (unlikely(res.server_scope == NULL)) { | ||
5233 | status = -ENOMEM; | ||
5234 | goto out_server_owner; | ||
5235 | } | ||
5236 | |||
5237 | res.impl_id = kzalloc(sizeof(struct nfs41_impl_id), GFP_NOFS); | ||
5238 | if (unlikely(res.impl_id == NULL)) { | ||
5138 | status = -ENOMEM; | 5239 | status = -ENOMEM; |
5139 | goto out_server_scope; | 5240 | goto out_server_scope; |
5140 | } | 5241 | } |
5141 | 5242 | ||
5142 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 5243 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
5143 | if (!status) | 5244 | if (status == 0) |
5144 | status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); | 5245 | status = nfs4_check_cl_exchange_flags(res.flags); |
5246 | |||
5247 | if (status == 0) { | ||
5248 | clp->cl_clientid = res.clientid; | ||
5249 | clp->cl_exchange_flags = (res.flags & ~EXCHGID4_FLAG_CONFIRMED_R); | ||
5250 | if (!(res.flags & EXCHGID4_FLAG_CONFIRMED_R)) | ||
5251 | clp->cl_seqid = res.seqid; | ||
5252 | |||
5253 | kfree(clp->cl_serverowner); | ||
5254 | clp->cl_serverowner = res.server_owner; | ||
5255 | res.server_owner = NULL; | ||
5145 | 5256 | ||
5146 | if (!status) { | ||
5147 | /* use the most recent implementation id */ | 5257 | /* use the most recent implementation id */ |
5148 | kfree(clp->impl_id); | 5258 | kfree(clp->cl_implid); |
5149 | clp->impl_id = res.impl_id; | 5259 | clp->cl_implid = res.impl_id; |
5150 | } else | ||
5151 | kfree(res.impl_id); | ||
5152 | 5260 | ||
5153 | if (!status) { | 5261 | if (clp->cl_serverscope != NULL && |
5154 | if (clp->server_scope && | 5262 | !nfs41_same_server_scope(clp->cl_serverscope, |
5155 | !nfs41_same_server_scope(clp->server_scope, | ||
5156 | res.server_scope)) { | 5263 | res.server_scope)) { |
5157 | dprintk("%s: server_scope mismatch detected\n", | 5264 | dprintk("%s: server_scope mismatch detected\n", |
5158 | __func__); | 5265 | __func__); |
5159 | set_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state); | 5266 | set_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state); |
5160 | kfree(clp->server_scope); | 5267 | kfree(clp->cl_serverscope); |
5161 | clp->server_scope = NULL; | 5268 | clp->cl_serverscope = NULL; |
5162 | } | 5269 | } |
5163 | 5270 | ||
5164 | if (!clp->server_scope) { | 5271 | if (clp->cl_serverscope == NULL) { |
5165 | clp->server_scope = res.server_scope; | 5272 | clp->cl_serverscope = res.server_scope; |
5166 | goto out; | 5273 | goto out; |
5167 | } | 5274 | } |
5168 | } | 5275 | } else |
5276 | kfree(res.impl_id); | ||
5169 | 5277 | ||
5278 | out_server_owner: | ||
5279 | kfree(res.server_owner); | ||
5170 | out_server_scope: | 5280 | out_server_scope: |
5171 | kfree(res.server_scope); | 5281 | kfree(res.server_scope); |
5172 | out: | 5282 | out: |
5173 | if (clp->impl_id) | 5283 | if (clp->cl_implid != NULL) |
5174 | dprintk("%s: Server Implementation ID: " | 5284 | dprintk("%s: Server Implementation ID: " |
5175 | "domain: %s, name: %s, date: %llu,%u\n", | 5285 | "domain: %s, name: %s, date: %llu,%u\n", |
5176 | __func__, clp->impl_id->domain, clp->impl_id->name, | 5286 | __func__, clp->cl_implid->domain, clp->cl_implid->name, |
5177 | clp->impl_id->date.seconds, | 5287 | clp->cl_implid->date.seconds, |
5178 | clp->impl_id->date.nseconds); | 5288 | clp->cl_implid->date.nseconds); |
5179 | dprintk("<-- %s status= %d\n", __func__, status); | 5289 | dprintk("<-- %s status= %d\n", __func__, status); |
5180 | return status; | 5290 | return status; |
5181 | } | 5291 | } |
5182 | 5292 | ||
5293 | static int _nfs4_proc_destroy_clientid(struct nfs_client *clp, | ||
5294 | struct rpc_cred *cred) | ||
5295 | { | ||
5296 | struct rpc_message msg = { | ||
5297 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DESTROY_CLIENTID], | ||
5298 | .rpc_argp = clp, | ||
5299 | .rpc_cred = cred, | ||
5300 | }; | ||
5301 | int status; | ||
5302 | |||
5303 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | ||
5304 | if (status) | ||
5305 | dprintk("NFS: Got error %d from the server %s on " | ||
5306 | "DESTROY_CLIENTID.", status, clp->cl_hostname); | ||
5307 | return status; | ||
5308 | } | ||
5309 | |||
5310 | static int nfs4_proc_destroy_clientid(struct nfs_client *clp, | ||
5311 | struct rpc_cred *cred) | ||
5312 | { | ||
5313 | unsigned int loop; | ||
5314 | int ret; | ||
5315 | |||
5316 | for (loop = NFS4_MAX_LOOP_ON_RECOVER; loop != 0; loop--) { | ||
5317 | ret = _nfs4_proc_destroy_clientid(clp, cred); | ||
5318 | switch (ret) { | ||
5319 | case -NFS4ERR_DELAY: | ||
5320 | case -NFS4ERR_CLIENTID_BUSY: | ||
5321 | ssleep(1); | ||
5322 | break; | ||
5323 | default: | ||
5324 | return ret; | ||
5325 | } | ||
5326 | } | ||
5327 | return 0; | ||
5328 | } | ||
5329 | |||
5330 | int nfs4_destroy_clientid(struct nfs_client *clp) | ||
5331 | { | ||
5332 | struct rpc_cred *cred; | ||
5333 | int ret = 0; | ||
5334 | |||
5335 | if (clp->cl_mvops->minor_version < 1) | ||
5336 | goto out; | ||
5337 | if (clp->cl_exchange_flags == 0) | ||
5338 | goto out; | ||
5339 | cred = nfs4_get_exchange_id_cred(clp); | ||
5340 | ret = nfs4_proc_destroy_clientid(clp, cred); | ||
5341 | if (cred) | ||
5342 | put_rpccred(cred); | ||
5343 | switch (ret) { | ||
5344 | case 0: | ||
5345 | case -NFS4ERR_STALE_CLIENTID: | ||
5346 | clp->cl_exchange_flags = 0; | ||
5347 | } | ||
5348 | out: | ||
5349 | return ret; | ||
5350 | } | ||
5351 | |||
5183 | struct nfs4_get_lease_time_data { | 5352 | struct nfs4_get_lease_time_data { |
5184 | struct nfs4_get_lease_time_args *args; | 5353 | struct nfs4_get_lease_time_args *args; |
5185 | struct nfs4_get_lease_time_res *res; | 5354 | struct nfs4_get_lease_time_res *res; |
@@ -5400,8 +5569,12 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | |||
5400 | void nfs4_destroy_session(struct nfs4_session *session) | 5569 | void nfs4_destroy_session(struct nfs4_session *session) |
5401 | { | 5570 | { |
5402 | struct rpc_xprt *xprt; | 5571 | struct rpc_xprt *xprt; |
5572 | struct rpc_cred *cred; | ||
5403 | 5573 | ||
5404 | nfs4_proc_destroy_session(session); | 5574 | cred = nfs4_get_exchange_id_cred(session->clp); |
5575 | nfs4_proc_destroy_session(session, cred); | ||
5576 | if (cred) | ||
5577 | put_rpccred(cred); | ||
5405 | 5578 | ||
5406 | rcu_read_lock(); | 5579 | rcu_read_lock(); |
5407 | xprt = rcu_dereference(session->clp->cl_rpcclient->cl_xprt); | 5580 | xprt = rcu_dereference(session->clp->cl_rpcclient->cl_xprt); |
@@ -5511,7 +5684,8 @@ static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args, | |||
5511 | return nfs4_verify_back_channel_attrs(args, session); | 5684 | return nfs4_verify_back_channel_attrs(args, session); |
5512 | } | 5685 | } |
5513 | 5686 | ||
5514 | static int _nfs4_proc_create_session(struct nfs_client *clp) | 5687 | static int _nfs4_proc_create_session(struct nfs_client *clp, |
5688 | struct rpc_cred *cred) | ||
5515 | { | 5689 | { |
5516 | struct nfs4_session *session = clp->cl_session; | 5690 | struct nfs4_session *session = clp->cl_session; |
5517 | struct nfs41_create_session_args args = { | 5691 | struct nfs41_create_session_args args = { |
@@ -5525,6 +5699,7 @@ static int _nfs4_proc_create_session(struct nfs_client *clp) | |||
5525 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION], | 5699 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION], |
5526 | .rpc_argp = &args, | 5700 | .rpc_argp = &args, |
5527 | .rpc_resp = &res, | 5701 | .rpc_resp = &res, |
5702 | .rpc_cred = cred, | ||
5528 | }; | 5703 | }; |
5529 | int status; | 5704 | int status; |
5530 | 5705 | ||
@@ -5549,7 +5724,7 @@ static int _nfs4_proc_create_session(struct nfs_client *clp) | |||
5549 | * It is the responsibility of the caller to verify the session is | 5724 | * It is the responsibility of the caller to verify the session is |
5550 | * expired before calling this routine. | 5725 | * expired before calling this routine. |
5551 | */ | 5726 | */ |
5552 | int nfs4_proc_create_session(struct nfs_client *clp) | 5727 | int nfs4_proc_create_session(struct nfs_client *clp, struct rpc_cred *cred) |
5553 | { | 5728 | { |
5554 | int status; | 5729 | int status; |
5555 | unsigned *ptr; | 5730 | unsigned *ptr; |
@@ -5557,7 +5732,7 @@ int nfs4_proc_create_session(struct nfs_client *clp) | |||
5557 | 5732 | ||
5558 | dprintk("--> %s clp=%p session=%p\n", __func__, clp, session); | 5733 | dprintk("--> %s clp=%p session=%p\n", __func__, clp, session); |
5559 | 5734 | ||
5560 | status = _nfs4_proc_create_session(clp); | 5735 | status = _nfs4_proc_create_session(clp, cred); |
5561 | if (status) | 5736 | if (status) |
5562 | goto out; | 5737 | goto out; |
5563 | 5738 | ||
@@ -5579,10 +5754,15 @@ out: | |||
5579 | * Issue the over-the-wire RPC DESTROY_SESSION. | 5754 | * Issue the over-the-wire RPC DESTROY_SESSION. |
5580 | * The caller must serialize access to this routine. | 5755 | * The caller must serialize access to this routine. |
5581 | */ | 5756 | */ |
5582 | int nfs4_proc_destroy_session(struct nfs4_session *session) | 5757 | int nfs4_proc_destroy_session(struct nfs4_session *session, |
5758 | struct rpc_cred *cred) | ||
5583 | { | 5759 | { |
5760 | struct rpc_message msg = { | ||
5761 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DESTROY_SESSION], | ||
5762 | .rpc_argp = session, | ||
5763 | .rpc_cred = cred, | ||
5764 | }; | ||
5584 | int status = 0; | 5765 | int status = 0; |
5585 | struct rpc_message msg; | ||
5586 | 5766 | ||
5587 | dprintk("--> nfs4_proc_destroy_session\n"); | 5767 | dprintk("--> nfs4_proc_destroy_session\n"); |
5588 | 5768 | ||
@@ -5590,68 +5770,89 @@ int nfs4_proc_destroy_session(struct nfs4_session *session) | |||
5590 | if (session->clp->cl_cons_state != NFS_CS_READY) | 5770 | if (session->clp->cl_cons_state != NFS_CS_READY) |
5591 | return status; | 5771 | return status; |
5592 | 5772 | ||
5593 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DESTROY_SESSION]; | ||
5594 | msg.rpc_argp = session; | ||
5595 | msg.rpc_resp = NULL; | ||
5596 | msg.rpc_cred = NULL; | ||
5597 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 5773 | status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
5598 | 5774 | ||
5599 | if (status) | 5775 | if (status) |
5600 | printk(KERN_WARNING | 5776 | dprintk("NFS: Got error %d from the server on DESTROY_SESSION. " |
5601 | "NFS: Got error %d from the server on DESTROY_SESSION. " | ||
5602 | "Session has been destroyed regardless...\n", status); | 5777 | "Session has been destroyed regardless...\n", status); |
5603 | 5778 | ||
5604 | dprintk("<-- nfs4_proc_destroy_session\n"); | 5779 | dprintk("<-- nfs4_proc_destroy_session\n"); |
5605 | return status; | 5780 | return status; |
5606 | } | 5781 | } |
5607 | 5782 | ||
5783 | /* | ||
5784 | * With sessions, the client is not marked ready until after a | ||
5785 | * successful EXCHANGE_ID and CREATE_SESSION. | ||
5786 | * | ||
5787 | * Map errors cl_cons_state errors to EPROTONOSUPPORT to indicate | ||
5788 | * other versions of NFS can be tried. | ||
5789 | */ | ||
5790 | static int nfs41_check_session_ready(struct nfs_client *clp) | ||
5791 | { | ||
5792 | int ret; | ||
5793 | |||
5794 | if (clp->cl_cons_state == NFS_CS_SESSION_INITING) { | ||
5795 | ret = nfs4_client_recover_expired_lease(clp); | ||
5796 | if (ret) | ||
5797 | return ret; | ||
5798 | } | ||
5799 | if (clp->cl_cons_state < NFS_CS_READY) | ||
5800 | return -EPROTONOSUPPORT; | ||
5801 | smp_rmb(); | ||
5802 | return 0; | ||
5803 | } | ||
5804 | |||
5608 | int nfs4_init_session(struct nfs_server *server) | 5805 | int nfs4_init_session(struct nfs_server *server) |
5609 | { | 5806 | { |
5610 | struct nfs_client *clp = server->nfs_client; | 5807 | struct nfs_client *clp = server->nfs_client; |
5611 | struct nfs4_session *session; | 5808 | struct nfs4_session *session; |
5612 | unsigned int rsize, wsize; | 5809 | unsigned int rsize, wsize; |
5613 | int ret; | ||
5614 | 5810 | ||
5615 | if (!nfs4_has_session(clp)) | 5811 | if (!nfs4_has_session(clp)) |
5616 | return 0; | 5812 | return 0; |
5617 | 5813 | ||
5618 | session = clp->cl_session; | 5814 | session = clp->cl_session; |
5619 | if (!test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) | 5815 | spin_lock(&clp->cl_lock); |
5620 | return 0; | 5816 | if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) { |
5621 | 5817 | ||
5622 | rsize = server->rsize; | 5818 | rsize = server->rsize; |
5623 | if (rsize == 0) | 5819 | if (rsize == 0) |
5624 | rsize = NFS_MAX_FILE_IO_SIZE; | 5820 | rsize = NFS_MAX_FILE_IO_SIZE; |
5625 | wsize = server->wsize; | 5821 | wsize = server->wsize; |
5626 | if (wsize == 0) | 5822 | if (wsize == 0) |
5627 | wsize = NFS_MAX_FILE_IO_SIZE; | 5823 | wsize = NFS_MAX_FILE_IO_SIZE; |
5628 | 5824 | ||
5629 | session->fc_attrs.max_rqst_sz = wsize + nfs41_maxwrite_overhead; | 5825 | session->fc_attrs.max_rqst_sz = wsize + nfs41_maxwrite_overhead; |
5630 | session->fc_attrs.max_resp_sz = rsize + nfs41_maxread_overhead; | 5826 | session->fc_attrs.max_resp_sz = rsize + nfs41_maxread_overhead; |
5827 | } | ||
5828 | spin_unlock(&clp->cl_lock); | ||
5631 | 5829 | ||
5632 | ret = nfs4_recover_expired_lease(server); | 5830 | return nfs41_check_session_ready(clp); |
5633 | if (!ret) | ||
5634 | ret = nfs4_check_client_ready(clp); | ||
5635 | return ret; | ||
5636 | } | 5831 | } |
5637 | 5832 | ||
5638 | int nfs4_init_ds_session(struct nfs_client *clp) | 5833 | int nfs4_init_ds_session(struct nfs_client *clp, unsigned long lease_time) |
5639 | { | 5834 | { |
5640 | struct nfs4_session *session = clp->cl_session; | 5835 | struct nfs4_session *session = clp->cl_session; |
5641 | int ret; | 5836 | int ret; |
5642 | 5837 | ||
5643 | if (!test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) | 5838 | spin_lock(&clp->cl_lock); |
5644 | return 0; | 5839 | if (test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) { |
5645 | 5840 | /* | |
5646 | ret = nfs4_client_recover_expired_lease(clp); | 5841 | * Do not set NFS_CS_CHECK_LEASE_TIME instead set the |
5647 | if (!ret) | 5842 | * DS lease to be equal to the MDS lease. |
5648 | /* Test for the DS role */ | 5843 | */ |
5649 | if (!is_ds_client(clp)) | 5844 | clp->cl_lease_time = lease_time; |
5650 | ret = -ENODEV; | 5845 | clp->cl_last_renewal = jiffies; |
5651 | if (!ret) | 5846 | } |
5652 | ret = nfs4_check_client_ready(clp); | 5847 | spin_unlock(&clp->cl_lock); |
5653 | return ret; | ||
5654 | 5848 | ||
5849 | ret = nfs41_check_session_ready(clp); | ||
5850 | if (ret) | ||
5851 | return ret; | ||
5852 | /* Test for the DS role */ | ||
5853 | if (!is_ds_client(clp)) | ||
5854 | return -ENODEV; | ||
5855 | return 0; | ||
5655 | } | 5856 | } |
5656 | EXPORT_SYMBOL_GPL(nfs4_init_ds_session); | 5857 | EXPORT_SYMBOL_GPL(nfs4_init_ds_session); |
5657 | 5858 | ||
@@ -6558,6 +6759,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
6558 | .file_inode_ops = &nfs4_file_inode_operations, | 6759 | .file_inode_ops = &nfs4_file_inode_operations, |
6559 | .file_ops = &nfs4_file_operations, | 6760 | .file_ops = &nfs4_file_operations, |
6560 | .getroot = nfs4_proc_get_root, | 6761 | .getroot = nfs4_proc_get_root, |
6762 | .submount = nfs4_submount, | ||
6561 | .getattr = nfs4_proc_getattr, | 6763 | .getattr = nfs4_proc_getattr, |
6562 | .setattr = nfs4_proc_setattr, | 6764 | .setattr = nfs4_proc_setattr, |
6563 | .lookup = nfs4_proc_lookup, | 6765 | .lookup = nfs4_proc_lookup, |
@@ -6590,13 +6792,13 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
6590 | .write_rpc_prepare = nfs4_proc_write_rpc_prepare, | 6792 | .write_rpc_prepare = nfs4_proc_write_rpc_prepare, |
6591 | .write_done = nfs4_write_done, | 6793 | .write_done = nfs4_write_done, |
6592 | .commit_setup = nfs4_proc_commit_setup, | 6794 | .commit_setup = nfs4_proc_commit_setup, |
6795 | .commit_rpc_prepare = nfs4_proc_commit_rpc_prepare, | ||
6593 | .commit_done = nfs4_commit_done, | 6796 | .commit_done = nfs4_commit_done, |
6594 | .lock = nfs4_proc_lock, | 6797 | .lock = nfs4_proc_lock, |
6595 | .clear_acl_cache = nfs4_zap_acl_attr, | 6798 | .clear_acl_cache = nfs4_zap_acl_attr, |
6596 | .close_context = nfs4_close_context, | 6799 | .close_context = nfs4_close_context, |
6597 | .open_context = nfs4_atomic_open, | 6800 | .open_context = nfs4_atomic_open, |
6598 | .init_client = nfs4_init_client, | 6801 | .init_client = nfs4_init_client, |
6599 | .secinfo = nfs4_proc_secinfo, | ||
6600 | }; | 6802 | }; |
6601 | 6803 | ||
6602 | static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { | 6804 | static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = { |