diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 342 |
1 files changed, 256 insertions, 86 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 1e50326d00dd..68b21d81b7ac 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -104,6 +104,8 @@ static int nfs4_map_errors(int err) | |||
104 | return -EACCES; | 104 | return -EACCES; |
105 | case -NFS4ERR_MINOR_VERS_MISMATCH: | 105 | case -NFS4ERR_MINOR_VERS_MISMATCH: |
106 | return -EPROTONOSUPPORT; | 106 | return -EPROTONOSUPPORT; |
107 | case -NFS4ERR_ACCESS: | ||
108 | return -EACCES; | ||
107 | default: | 109 | default: |
108 | dprintk("%s could not handle NFSv4 error %d\n", | 110 | dprintk("%s could not handle NFSv4 error %d\n", |
109 | __func__, -err); | 111 | __func__, -err); |
@@ -150,6 +152,12 @@ static const u32 nfs4_pnfs_open_bitmap[3] = { | |||
150 | FATTR4_WORD2_MDSTHRESHOLD | 152 | FATTR4_WORD2_MDSTHRESHOLD |
151 | }; | 153 | }; |
152 | 154 | ||
155 | static const u32 nfs4_open_noattr_bitmap[3] = { | ||
156 | FATTR4_WORD0_TYPE | ||
157 | | FATTR4_WORD0_CHANGE | ||
158 | | FATTR4_WORD0_FILEID, | ||
159 | }; | ||
160 | |||
153 | const u32 nfs4_statfs_bitmap[2] = { | 161 | const u32 nfs4_statfs_bitmap[2] = { |
154 | FATTR4_WORD0_FILES_AVAIL | 162 | FATTR4_WORD0_FILES_AVAIL |
155 | | FATTR4_WORD0_FILES_FREE | 163 | | FATTR4_WORD0_FILES_FREE |
@@ -832,6 +840,7 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p) | |||
832 | p->o_res.seqid = p->o_arg.seqid; | 840 | p->o_res.seqid = p->o_arg.seqid; |
833 | p->c_res.seqid = p->c_arg.seqid; | 841 | p->c_res.seqid = p->c_arg.seqid; |
834 | p->o_res.server = p->o_arg.server; | 842 | p->o_res.server = p->o_arg.server; |
843 | p->o_res.access_request = p->o_arg.access; | ||
835 | nfs_fattr_init(&p->f_attr); | 844 | nfs_fattr_init(&p->f_attr); |
836 | nfs_fattr_init_names(&p->f_attr, &p->owner_name, &p->group_name); | 845 | nfs_fattr_init_names(&p->f_attr, &p->owner_name, &p->group_name); |
837 | } | 846 | } |
@@ -860,6 +869,14 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
860 | p->o_arg.fh = NFS_FH(dir); | 869 | p->o_arg.fh = NFS_FH(dir); |
861 | p->o_arg.open_flags = flags; | 870 | p->o_arg.open_flags = flags; |
862 | p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE); | 871 | p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE); |
872 | /* don't put an ACCESS op in OPEN compound if O_EXCL, because ACCESS | ||
873 | * will return permission denied for all bits until close */ | ||
874 | if (!(flags & O_EXCL)) { | ||
875 | /* ask server to check for all possible rights as results | ||
876 | * are cached */ | ||
877 | p->o_arg.access = NFS4_ACCESS_READ | NFS4_ACCESS_MODIFY | | ||
878 | NFS4_ACCESS_EXTEND | NFS4_ACCESS_EXECUTE; | ||
879 | } | ||
863 | p->o_arg.clientid = server->nfs_client->cl_clientid; | 880 | p->o_arg.clientid = server->nfs_client->cl_clientid; |
864 | p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time); | 881 | p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time); |
865 | p->o_arg.id.uniquifier = sp->so_seqid.owner_id; | 882 | p->o_arg.id.uniquifier = sp->so_seqid.owner_id; |
@@ -1115,11 +1132,80 @@ out_return_state: | |||
1115 | return state; | 1132 | return state; |
1116 | } | 1133 | } |
1117 | 1134 | ||
1118 | static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data) | 1135 | static void |
1136 | nfs4_opendata_check_deleg(struct nfs4_opendata *data, struct nfs4_state *state) | ||
1137 | { | ||
1138 | struct nfs_client *clp = NFS_SERVER(state->inode)->nfs_client; | ||
1139 | struct nfs_delegation *delegation; | ||
1140 | int delegation_flags = 0; | ||
1141 | |||
1142 | rcu_read_lock(); | ||
1143 | delegation = rcu_dereference(NFS_I(state->inode)->delegation); | ||
1144 | if (delegation) | ||
1145 | delegation_flags = delegation->flags; | ||
1146 | rcu_read_unlock(); | ||
1147 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR) { | ||
1148 | pr_err_ratelimited("NFS: Broken NFSv4 server %s is " | ||
1149 | "returning a delegation for " | ||
1150 | "OPEN(CLAIM_DELEGATE_CUR)\n", | ||
1151 | clp->cl_hostname); | ||
1152 | } else if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0) | ||
1153 | nfs_inode_set_delegation(state->inode, | ||
1154 | data->owner->so_cred, | ||
1155 | &data->o_res); | ||
1156 | else | ||
1157 | nfs_inode_reclaim_delegation(state->inode, | ||
1158 | data->owner->so_cred, | ||
1159 | &data->o_res); | ||
1160 | } | ||
1161 | |||
1162 | /* | ||
1163 | * Check the inode attributes against the CLAIM_PREVIOUS returned attributes | ||
1164 | * and update the nfs4_state. | ||
1165 | */ | ||
1166 | static struct nfs4_state * | ||
1167 | _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data) | ||
1168 | { | ||
1169 | struct inode *inode = data->state->inode; | ||
1170 | struct nfs4_state *state = data->state; | ||
1171 | int ret; | ||
1172 | |||
1173 | if (!data->rpc_done) { | ||
1174 | ret = data->rpc_status; | ||
1175 | goto err; | ||
1176 | } | ||
1177 | |||
1178 | ret = -ESTALE; | ||
1179 | if (!(data->f_attr.valid & NFS_ATTR_FATTR_TYPE) || | ||
1180 | !(data->f_attr.valid & NFS_ATTR_FATTR_FILEID) || | ||
1181 | !(data->f_attr.valid & NFS_ATTR_FATTR_CHANGE)) | ||
1182 | goto err; | ||
1183 | |||
1184 | ret = -ENOMEM; | ||
1185 | state = nfs4_get_open_state(inode, data->owner); | ||
1186 | if (state == NULL) | ||
1187 | goto err; | ||
1188 | |||
1189 | ret = nfs_refresh_inode(inode, &data->f_attr); | ||
1190 | if (ret) | ||
1191 | goto err; | ||
1192 | |||
1193 | if (data->o_res.delegation_type != 0) | ||
1194 | nfs4_opendata_check_deleg(data, state); | ||
1195 | update_open_stateid(state, &data->o_res.stateid, NULL, | ||
1196 | data->o_arg.fmode); | ||
1197 | |||
1198 | return state; | ||
1199 | err: | ||
1200 | return ERR_PTR(ret); | ||
1201 | |||
1202 | } | ||
1203 | |||
1204 | static struct nfs4_state * | ||
1205 | _nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data) | ||
1119 | { | 1206 | { |
1120 | struct inode *inode; | 1207 | struct inode *inode; |
1121 | struct nfs4_state *state = NULL; | 1208 | struct nfs4_state *state = NULL; |
1122 | struct nfs_delegation *delegation; | ||
1123 | int ret; | 1209 | int ret; |
1124 | 1210 | ||
1125 | if (!data->rpc_done) { | 1211 | if (!data->rpc_done) { |
@@ -1138,30 +1224,8 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data | |||
1138 | state = nfs4_get_open_state(inode, data->owner); | 1224 | state = nfs4_get_open_state(inode, data->owner); |
1139 | if (state == NULL) | 1225 | if (state == NULL) |
1140 | goto err_put_inode; | 1226 | goto err_put_inode; |
1141 | if (data->o_res.delegation_type != 0) { | 1227 | if (data->o_res.delegation_type != 0) |
1142 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; | 1228 | nfs4_opendata_check_deleg(data, state); |
1143 | int delegation_flags = 0; | ||
1144 | |||
1145 | rcu_read_lock(); | ||
1146 | delegation = rcu_dereference(NFS_I(inode)->delegation); | ||
1147 | if (delegation) | ||
1148 | delegation_flags = delegation->flags; | ||
1149 | rcu_read_unlock(); | ||
1150 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR) { | ||
1151 | pr_err_ratelimited("NFS: Broken NFSv4 server %s is " | ||
1152 | "returning a delegation for " | ||
1153 | "OPEN(CLAIM_DELEGATE_CUR)\n", | ||
1154 | clp->cl_hostname); | ||
1155 | } else if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0) | ||
1156 | nfs_inode_set_delegation(state->inode, | ||
1157 | data->owner->so_cred, | ||
1158 | &data->o_res); | ||
1159 | else | ||
1160 | nfs_inode_reclaim_delegation(state->inode, | ||
1161 | data->owner->so_cred, | ||
1162 | &data->o_res); | ||
1163 | } | ||
1164 | |||
1165 | update_open_stateid(state, &data->o_res.stateid, NULL, | 1229 | update_open_stateid(state, &data->o_res.stateid, NULL, |
1166 | data->o_arg.fmode); | 1230 | data->o_arg.fmode); |
1167 | iput(inode); | 1231 | iput(inode); |
@@ -1173,6 +1237,14 @@ err: | |||
1173 | return ERR_PTR(ret); | 1237 | return ERR_PTR(ret); |
1174 | } | 1238 | } |
1175 | 1239 | ||
1240 | static struct nfs4_state * | ||
1241 | nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data) | ||
1242 | { | ||
1243 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) | ||
1244 | return _nfs4_opendata_reclaim_to_nfs4_state(data); | ||
1245 | return _nfs4_opendata_to_nfs4_state(data); | ||
1246 | } | ||
1247 | |||
1176 | static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *state) | 1248 | static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *state) |
1177 | { | 1249 | { |
1178 | struct nfs_inode *nfsi = NFS_I(state->inode); | 1250 | struct nfs_inode *nfsi = NFS_I(state->inode); |
@@ -1494,6 +1566,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
1494 | data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid; | 1566 | data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid; |
1495 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { | 1567 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { |
1496 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; | 1568 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; |
1569 | data->o_arg.open_bitmap = &nfs4_open_noattr_bitmap[0]; | ||
1497 | nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); | 1570 | nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); |
1498 | } | 1571 | } |
1499 | data->timestamp = jiffies; | 1572 | data->timestamp = jiffies; |
@@ -1526,7 +1599,8 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata) | |||
1526 | return; | 1599 | return; |
1527 | 1600 | ||
1528 | if (task->tk_status == 0) { | 1601 | if (task->tk_status == 0) { |
1529 | switch (data->o_res.f_attr->mode & S_IFMT) { | 1602 | if (data->o_res.f_attr->valid & NFS_ATTR_FATTR_TYPE) { |
1603 | switch (data->o_res.f_attr->mode & S_IFMT) { | ||
1530 | case S_IFREG: | 1604 | case S_IFREG: |
1531 | break; | 1605 | break; |
1532 | case S_IFLNK: | 1606 | case S_IFLNK: |
@@ -1537,6 +1611,7 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata) | |||
1537 | break; | 1611 | break; |
1538 | default: | 1612 | default: |
1539 | data->rpc_status = -ENOTDIR; | 1613 | data->rpc_status = -ENOTDIR; |
1614 | } | ||
1540 | } | 1615 | } |
1541 | renew_lease(data->o_res.server, data->timestamp); | 1616 | renew_lease(data->o_res.server, data->timestamp); |
1542 | if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)) | 1617 | if (!(data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)) |
@@ -1643,6 +1718,39 @@ static int _nfs4_recover_proc_open(struct nfs4_opendata *data) | |||
1643 | return status; | 1718 | return status; |
1644 | } | 1719 | } |
1645 | 1720 | ||
1721 | static int nfs4_opendata_access(struct rpc_cred *cred, | ||
1722 | struct nfs4_opendata *opendata, | ||
1723 | struct nfs4_state *state, fmode_t fmode) | ||
1724 | { | ||
1725 | struct nfs_access_entry cache; | ||
1726 | u32 mask; | ||
1727 | |||
1728 | /* access call failed or for some reason the server doesn't | ||
1729 | * support any access modes -- defer access call until later */ | ||
1730 | if (opendata->o_res.access_supported == 0) | ||
1731 | return 0; | ||
1732 | |||
1733 | mask = 0; | ||
1734 | /* don't check MAY_WRITE - a newly created file may not have | ||
1735 | * write mode bits, but POSIX allows the creating process to write */ | ||
1736 | if (fmode & FMODE_READ) | ||
1737 | mask |= MAY_READ; | ||
1738 | if (fmode & FMODE_EXEC) | ||
1739 | mask |= MAY_EXEC; | ||
1740 | |||
1741 | cache.cred = cred; | ||
1742 | cache.jiffies = jiffies; | ||
1743 | nfs_access_set_mask(&cache, opendata->o_res.access_result); | ||
1744 | nfs_access_add_cache(state->inode, &cache); | ||
1745 | |||
1746 | if ((mask & ~cache.mask & (MAY_READ | MAY_EXEC)) == 0) | ||
1747 | return 0; | ||
1748 | |||
1749 | /* even though OPEN succeeded, access is denied. Close the file */ | ||
1750 | nfs4_close_state(state, fmode); | ||
1751 | return -NFS4ERR_ACCESS; | ||
1752 | } | ||
1753 | |||
1646 | /* | 1754 | /* |
1647 | * Note: On error, nfs4_proc_open will free the struct nfs4_opendata | 1755 | * Note: On error, nfs4_proc_open will free the struct nfs4_opendata |
1648 | */ | 1756 | */ |
@@ -1774,7 +1882,11 @@ static void nfs41_clear_delegation_stateid(struct nfs4_state *state) | |||
1774 | * informs us the stateid is unrecognized. */ | 1882 | * informs us the stateid is unrecognized. */ |
1775 | if (status != -NFS4ERR_BAD_STATEID) | 1883 | if (status != -NFS4ERR_BAD_STATEID) |
1776 | nfs41_free_stateid(server, stateid); | 1884 | nfs41_free_stateid(server, stateid); |
1885 | nfs_remove_bad_delegation(state->inode); | ||
1777 | 1886 | ||
1887 | write_seqlock(&state->seqlock); | ||
1888 | nfs4_stateid_copy(&state->stateid, &state->open_stateid); | ||
1889 | write_sequnlock(&state->seqlock); | ||
1778 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | 1890 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
1779 | } | 1891 | } |
1780 | } | 1892 | } |
@@ -1790,7 +1902,7 @@ static void nfs41_clear_delegation_stateid(struct nfs4_state *state) | |||
1790 | static int nfs41_check_open_stateid(struct nfs4_state *state) | 1902 | static int nfs41_check_open_stateid(struct nfs4_state *state) |
1791 | { | 1903 | { |
1792 | struct nfs_server *server = NFS_SERVER(state->inode); | 1904 | struct nfs_server *server = NFS_SERVER(state->inode); |
1793 | nfs4_stateid *stateid = &state->stateid; | 1905 | nfs4_stateid *stateid = &state->open_stateid; |
1794 | int status; | 1906 | int status; |
1795 | 1907 | ||
1796 | /* If a state reset has been done, test_stateid is unneeded */ | 1908 | /* If a state reset has been done, test_stateid is unneeded */ |
@@ -1896,6 +2008,10 @@ static int _nfs4_do_open(struct inode *dir, | |||
1896 | if (server->caps & NFS_CAP_POSIX_LOCK) | 2008 | if (server->caps & NFS_CAP_POSIX_LOCK) |
1897 | set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); | 2009 | set_bit(NFS_STATE_POSIX_LOCKS, &state->flags); |
1898 | 2010 | ||
2011 | status = nfs4_opendata_access(cred, opendata, state, fmode); | ||
2012 | if (status != 0) | ||
2013 | goto err_opendata_put; | ||
2014 | |||
1899 | if (opendata->o_arg.open_flags & O_EXCL) { | 2015 | if (opendata->o_arg.open_flags & O_EXCL) { |
1900 | nfs4_exclusive_attrset(opendata, sattr); | 2016 | nfs4_exclusive_attrset(opendata, sattr); |
1901 | 2017 | ||
@@ -1941,7 +2057,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, | |||
1941 | struct nfs4_state *res; | 2057 | struct nfs4_state *res; |
1942 | int status; | 2058 | int status; |
1943 | 2059 | ||
1944 | fmode &= FMODE_READ|FMODE_WRITE; | 2060 | fmode &= FMODE_READ|FMODE_WRITE|FMODE_EXEC; |
1945 | do { | 2061 | do { |
1946 | status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred, | 2062 | status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred, |
1947 | &res, ctx_th); | 2063 | &res, ctx_th); |
@@ -2013,8 +2129,12 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
2013 | nfs_fattr_init(fattr); | 2129 | nfs_fattr_init(fattr); |
2014 | 2130 | ||
2015 | if (state != NULL) { | 2131 | if (state != NULL) { |
2132 | struct nfs_lockowner lockowner = { | ||
2133 | .l_owner = current->files, | ||
2134 | .l_pid = current->tgid, | ||
2135 | }; | ||
2016 | nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE, | 2136 | nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE, |
2017 | current->files, current->tgid); | 2137 | &lockowner); |
2018 | } else if (nfs4_copy_delegation_stateid(&arg.stateid, inode, | 2138 | } else if (nfs4_copy_delegation_stateid(&arg.stateid, inode, |
2019 | FMODE_WRITE)) { | 2139 | FMODE_WRITE)) { |
2020 | /* Use that stateid */ | 2140 | /* Use that stateid */ |
@@ -2133,6 +2253,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2133 | { | 2253 | { |
2134 | struct nfs4_closedata *calldata = data; | 2254 | struct nfs4_closedata *calldata = data; |
2135 | struct nfs4_state *state = calldata->state; | 2255 | struct nfs4_state *state = calldata->state; |
2256 | struct inode *inode = calldata->inode; | ||
2136 | int call_close = 0; | 2257 | int call_close = 0; |
2137 | 2258 | ||
2138 | dprintk("%s: begin!\n", __func__); | 2259 | dprintk("%s: begin!\n", __func__); |
@@ -2166,16 +2287,13 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
2166 | if (calldata->arg.fmode == 0) { | 2287 | if (calldata->arg.fmode == 0) { |
2167 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE]; | 2288 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE]; |
2168 | if (calldata->roc && | 2289 | if (calldata->roc && |
2169 | pnfs_roc_drain(calldata->inode, &calldata->roc_barrier)) { | 2290 | pnfs_roc_drain(inode, &calldata->roc_barrier, task)) |
2170 | rpc_sleep_on(&NFS_SERVER(calldata->inode)->roc_rpcwaitq, | ||
2171 | task, NULL); | ||
2172 | goto out; | 2291 | goto out; |
2173 | } | ||
2174 | } | 2292 | } |
2175 | 2293 | ||
2176 | nfs_fattr_init(calldata->res.fattr); | 2294 | nfs_fattr_init(calldata->res.fattr); |
2177 | calldata->timestamp = jiffies; | 2295 | calldata->timestamp = jiffies; |
2178 | if (nfs4_setup_sequence(NFS_SERVER(calldata->inode), | 2296 | if (nfs4_setup_sequence(NFS_SERVER(inode), |
2179 | &calldata->arg.seq_args, | 2297 | &calldata->arg.seq_args, |
2180 | &calldata->res.seq_res, | 2298 | &calldata->res.seq_res, |
2181 | task)) | 2299 | task)) |
@@ -2202,7 +2320,7 @@ static const struct rpc_call_ops nfs4_close_ops = { | |||
2202 | * | 2320 | * |
2203 | * NOTE: Caller must be holding the sp->so_owner semaphore! | 2321 | * NOTE: Caller must be holding the sp->so_owner semaphore! |
2204 | */ | 2322 | */ |
2205 | int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc) | 2323 | int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait) |
2206 | { | 2324 | { |
2207 | struct nfs_server *server = NFS_SERVER(state->inode); | 2325 | struct nfs_server *server = NFS_SERVER(state->inode); |
2208 | struct nfs4_closedata *calldata; | 2326 | struct nfs4_closedata *calldata; |
@@ -2238,7 +2356,7 @@ int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc) | |||
2238 | calldata->res.fattr = &calldata->fattr; | 2356 | calldata->res.fattr = &calldata->fattr; |
2239 | calldata->res.seqid = calldata->arg.seqid; | 2357 | calldata->res.seqid = calldata->arg.seqid; |
2240 | calldata->res.server = server; | 2358 | calldata->res.server = server; |
2241 | calldata->roc = roc; | 2359 | calldata->roc = pnfs_roc(state->inode); |
2242 | nfs_sb_active(calldata->inode->i_sb); | 2360 | nfs_sb_active(calldata->inode->i_sb); |
2243 | 2361 | ||
2244 | msg.rpc_argp = &calldata->arg; | 2362 | msg.rpc_argp = &calldata->arg; |
@@ -2255,8 +2373,6 @@ int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc) | |||
2255 | out_free_calldata: | 2373 | out_free_calldata: |
2256 | kfree(calldata); | 2374 | kfree(calldata); |
2257 | out: | 2375 | out: |
2258 | if (roc) | ||
2259 | pnfs_roc_release(state->inode); | ||
2260 | nfs4_put_open_state(state); | 2376 | nfs4_put_open_state(state); |
2261 | nfs4_put_state_owner(sp); | 2377 | nfs4_put_state_owner(sp); |
2262 | return status; | 2378 | return status; |
@@ -2399,7 +2515,7 @@ static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandl | |||
2399 | int ret; | 2515 | int ret; |
2400 | 2516 | ||
2401 | auth = rpcauth_create(flavor, server->client); | 2517 | auth = rpcauth_create(flavor, server->client); |
2402 | if (!auth) { | 2518 | if (IS_ERR(auth)) { |
2403 | ret = -EIO; | 2519 | ret = -EIO; |
2404 | goto out; | 2520 | goto out; |
2405 | } | 2521 | } |
@@ -2767,13 +2883,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry | |||
2767 | 2883 | ||
2768 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | 2884 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
2769 | if (!status) { | 2885 | if (!status) { |
2770 | entry->mask = 0; | 2886 | nfs_access_set_mask(entry, res.access); |
2771 | if (res.access & NFS4_ACCESS_READ) | ||
2772 | entry->mask |= MAY_READ; | ||
2773 | if (res.access & (NFS4_ACCESS_MODIFY | NFS4_ACCESS_EXTEND | NFS4_ACCESS_DELETE)) | ||
2774 | entry->mask |= MAY_WRITE; | ||
2775 | if (res.access & (NFS4_ACCESS_LOOKUP|NFS4_ACCESS_EXECUTE)) | ||
2776 | entry->mask |= MAY_EXEC; | ||
2777 | nfs_refresh_inode(inode, res.fattr); | 2887 | nfs_refresh_inode(inode, res.fattr); |
2778 | } | 2888 | } |
2779 | nfs_free_fattr(res.fattr); | 2889 | nfs_free_fattr(res.fattr); |
@@ -3362,8 +3472,11 @@ static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, s | |||
3362 | 3472 | ||
3363 | nfs_fattr_init(fsinfo->fattr); | 3473 | nfs_fattr_init(fsinfo->fattr); |
3364 | error = nfs4_do_fsinfo(server, fhandle, fsinfo); | 3474 | error = nfs4_do_fsinfo(server, fhandle, fsinfo); |
3365 | if (error == 0) | 3475 | if (error == 0) { |
3476 | /* block layout checks this! */ | ||
3477 | server->pnfs_blksize = fsinfo->blksize; | ||
3366 | set_pnfs_layoutdriver(server, fhandle, fsinfo->layouttype); | 3478 | set_pnfs_layoutdriver(server, fhandle, fsinfo->layouttype); |
3479 | } | ||
3367 | 3480 | ||
3368 | return error; | 3481 | return error; |
3369 | } | 3482 | } |
@@ -4007,6 +4120,36 @@ static void nfs4_init_boot_verifier(const struct nfs_client *clp, | |||
4007 | memcpy(bootverf->data, verf, sizeof(bootverf->data)); | 4120 | memcpy(bootverf->data, verf, sizeof(bootverf->data)); |
4008 | } | 4121 | } |
4009 | 4122 | ||
4123 | static unsigned int | ||
4124 | nfs4_init_nonuniform_client_string(const struct nfs_client *clp, | ||
4125 | char *buf, size_t len) | ||
4126 | { | ||
4127 | unsigned int result; | ||
4128 | |||
4129 | rcu_read_lock(); | ||
4130 | result = scnprintf(buf, len, "Linux NFSv4.0 %s/%s %s", | ||
4131 | clp->cl_ipaddr, | ||
4132 | rpc_peeraddr2str(clp->cl_rpcclient, | ||
4133 | RPC_DISPLAY_ADDR), | ||
4134 | rpc_peeraddr2str(clp->cl_rpcclient, | ||
4135 | RPC_DISPLAY_PROTO)); | ||
4136 | rcu_read_unlock(); | ||
4137 | return result; | ||
4138 | } | ||
4139 | |||
4140 | static unsigned int | ||
4141 | nfs4_init_uniform_client_string(const struct nfs_client *clp, | ||
4142 | char *buf, size_t len) | ||
4143 | { | ||
4144 | char *nodename = clp->cl_rpcclient->cl_nodename; | ||
4145 | |||
4146 | if (nfs4_client_id_uniquifier[0] != '\0') | ||
4147 | nodename = nfs4_client_id_uniquifier; | ||
4148 | return scnprintf(buf, len, "Linux NFSv%u.%u %s", | ||
4149 | clp->rpc_ops->version, clp->cl_minorversion, | ||
4150 | nodename); | ||
4151 | } | ||
4152 | |||
4010 | /** | 4153 | /** |
4011 | * nfs4_proc_setclientid - Negotiate client ID | 4154 | * nfs4_proc_setclientid - Negotiate client ID |
4012 | * @clp: state data structure | 4155 | * @clp: state data structure |
@@ -4037,15 +4180,18 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | |||
4037 | 4180 | ||
4038 | /* nfs_client_id4 */ | 4181 | /* nfs_client_id4 */ |
4039 | nfs4_init_boot_verifier(clp, &sc_verifier); | 4182 | nfs4_init_boot_verifier(clp, &sc_verifier); |
4040 | rcu_read_lock(); | 4183 | if (test_bit(NFS_CS_MIGRATION, &clp->cl_flags)) |
4041 | setclientid.sc_name_len = scnprintf(setclientid.sc_name, | 4184 | setclientid.sc_name_len = |
4042 | sizeof(setclientid.sc_name), "%s/%s %s", | 4185 | nfs4_init_uniform_client_string(clp, |
4043 | clp->cl_ipaddr, | 4186 | setclientid.sc_name, |
4044 | rpc_peeraddr2str(clp->cl_rpcclient, | 4187 | sizeof(setclientid.sc_name)); |
4045 | RPC_DISPLAY_ADDR), | 4188 | else |
4046 | rpc_peeraddr2str(clp->cl_rpcclient, | 4189 | setclientid.sc_name_len = |
4047 | RPC_DISPLAY_PROTO)); | 4190 | nfs4_init_nonuniform_client_string(clp, |
4191 | setclientid.sc_name, | ||
4192 | sizeof(setclientid.sc_name)); | ||
4048 | /* cb_client4 */ | 4193 | /* cb_client4 */ |
4194 | rcu_read_lock(); | ||
4049 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, | 4195 | setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, |
4050 | sizeof(setclientid.sc_netid), | 4196 | sizeof(setclientid.sc_netid), |
4051 | rpc_peeraddr2str(clp->cl_rpcclient, | 4197 | rpc_peeraddr2str(clp->cl_rpcclient, |
@@ -4391,7 +4537,7 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) | |||
4391 | 4537 | ||
4392 | if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) | 4538 | if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) |
4393 | return; | 4539 | return; |
4394 | if ((calldata->lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) { | 4540 | if (test_bit(NFS_LOCK_INITIALIZED, &calldata->lsp->ls_flags) == 0) { |
4395 | /* Note: exit _without_ running nfs4_locku_done */ | 4541 | /* Note: exit _without_ running nfs4_locku_done */ |
4396 | task->tk_action = NULL; | 4542 | task->tk_action = NULL; |
4397 | return; | 4543 | return; |
@@ -4585,7 +4731,7 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata) | |||
4585 | } | 4731 | } |
4586 | if (data->rpc_status == 0) { | 4732 | if (data->rpc_status == 0) { |
4587 | nfs4_stateid_copy(&data->lsp->ls_stateid, &data->res.stateid); | 4733 | nfs4_stateid_copy(&data->lsp->ls_stateid, &data->res.stateid); |
4588 | data->lsp->ls_flags |= NFS_LOCK_INITIALIZED; | 4734 | set_bit(NFS_LOCK_INITIALIZED, &data->lsp->ls_flags); |
4589 | renew_lease(NFS_SERVER(data->ctx->dentry->d_inode), data->timestamp); | 4735 | renew_lease(NFS_SERVER(data->ctx->dentry->d_inode), data->timestamp); |
4590 | } | 4736 | } |
4591 | out: | 4737 | out: |
@@ -4632,7 +4778,7 @@ static void nfs4_handle_setlk_error(struct nfs_server *server, struct nfs4_lock_ | |||
4632 | case -NFS4ERR_BAD_STATEID: | 4778 | case -NFS4ERR_BAD_STATEID: |
4633 | lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; | 4779 | lsp->ls_seqid.flags &= ~NFS_SEQID_CONFIRMED; |
4634 | if (new_lock_owner != 0 || | 4780 | if (new_lock_owner != 0 || |
4635 | (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) | 4781 | test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) |
4636 | nfs4_schedule_stateid_recovery(server, lsp->ls_state); | 4782 | nfs4_schedule_stateid_recovery(server, lsp->ls_state); |
4637 | break; | 4783 | break; |
4638 | case -NFS4ERR_STALE_STATEID: | 4784 | case -NFS4ERR_STALE_STATEID: |
@@ -4756,7 +4902,7 @@ static int nfs41_check_expired_locks(struct nfs4_state *state) | |||
4756 | struct nfs_server *server = NFS_SERVER(state->inode); | 4902 | struct nfs_server *server = NFS_SERVER(state->inode); |
4757 | 4903 | ||
4758 | list_for_each_entry(lsp, &state->lock_states, ls_locks) { | 4904 | list_for_each_entry(lsp, &state->lock_states, ls_locks) { |
4759 | if (lsp->ls_flags & NFS_LOCK_INITIALIZED) { | 4905 | if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) { |
4760 | status = nfs41_test_stateid(server, &lsp->ls_stateid); | 4906 | status = nfs41_test_stateid(server, &lsp->ls_stateid); |
4761 | if (status != NFS_OK) { | 4907 | if (status != NFS_OK) { |
4762 | /* Free the stateid unless the server | 4908 | /* Free the stateid unless the server |
@@ -4764,7 +4910,7 @@ static int nfs41_check_expired_locks(struct nfs4_state *state) | |||
4764 | if (status != -NFS4ERR_BAD_STATEID) | 4910 | if (status != -NFS4ERR_BAD_STATEID) |
4765 | nfs41_free_stateid(server, | 4911 | nfs41_free_stateid(server, |
4766 | &lsp->ls_stateid); | 4912 | &lsp->ls_stateid); |
4767 | lsp->ls_flags &= ~NFS_LOCK_INITIALIZED; | 4913 | clear_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags); |
4768 | ret = status; | 4914 | ret = status; |
4769 | } | 4915 | } |
4770 | } | 4916 | } |
@@ -5267,10 +5413,8 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) | |||
5267 | }; | 5413 | }; |
5268 | 5414 | ||
5269 | nfs4_init_boot_verifier(clp, &verifier); | 5415 | nfs4_init_boot_verifier(clp, &verifier); |
5270 | args.id_len = scnprintf(args.id, sizeof(args.id), | 5416 | args.id_len = nfs4_init_uniform_client_string(clp, args.id, |
5271 | "%s/%s", | 5417 | sizeof(args.id)); |
5272 | clp->cl_ipaddr, | ||
5273 | clp->cl_rpcclient->cl_nodename); | ||
5274 | dprintk("NFS call exchange_id auth=%s, '%.*s'\n", | 5418 | dprintk("NFS call exchange_id auth=%s, '%.*s'\n", |
5275 | clp->cl_rpcclient->cl_auth->au_ops->au_name, | 5419 | clp->cl_rpcclient->cl_auth->au_ops->au_name, |
5276 | args.id_len, args.id); | 5420 | args.id_len, args.id); |
@@ -5391,6 +5535,8 @@ int nfs4_destroy_clientid(struct nfs_client *clp) | |||
5391 | goto out; | 5535 | goto out; |
5392 | if (clp->cl_exchange_flags == 0) | 5536 | if (clp->cl_exchange_flags == 0) |
5393 | goto out; | 5537 | goto out; |
5538 | if (clp->cl_preserve_clid) | ||
5539 | goto out; | ||
5394 | cred = nfs4_get_exchange_id_cred(clp); | 5540 | cred = nfs4_get_exchange_id_cred(clp); |
5395 | ret = nfs4_proc_destroy_clientid(clp, cred); | 5541 | ret = nfs4_proc_destroy_clientid(clp, cred); |
5396 | if (cred) | 5542 | if (cred) |
@@ -6196,26 +6342,44 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata) | |||
6196 | static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | 6342 | static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) |
6197 | { | 6343 | { |
6198 | struct nfs4_layoutget *lgp = calldata; | 6344 | struct nfs4_layoutget *lgp = calldata; |
6199 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); | 6345 | struct inode *inode = lgp->args.inode; |
6346 | struct nfs_server *server = NFS_SERVER(inode); | ||
6347 | struct pnfs_layout_hdr *lo; | ||
6348 | struct nfs4_state *state = NULL; | ||
6200 | 6349 | ||
6201 | dprintk("--> %s\n", __func__); | 6350 | dprintk("--> %s\n", __func__); |
6202 | 6351 | ||
6203 | if (!nfs4_sequence_done(task, &lgp->res.seq_res)) | 6352 | if (!nfs4_sequence_done(task, &lgp->res.seq_res)) |
6204 | return; | 6353 | goto out; |
6205 | 6354 | ||
6206 | switch (task->tk_status) { | 6355 | switch (task->tk_status) { |
6207 | case 0: | 6356 | case 0: |
6208 | break; | 6357 | goto out; |
6209 | case -NFS4ERR_LAYOUTTRYLATER: | 6358 | case -NFS4ERR_LAYOUTTRYLATER: |
6210 | case -NFS4ERR_RECALLCONFLICT: | 6359 | case -NFS4ERR_RECALLCONFLICT: |
6211 | task->tk_status = -NFS4ERR_DELAY; | 6360 | task->tk_status = -NFS4ERR_DELAY; |
6212 | /* Fall through */ | 6361 | break; |
6213 | default: | 6362 | case -NFS4ERR_EXPIRED: |
6214 | if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { | 6363 | case -NFS4ERR_BAD_STATEID: |
6215 | rpc_restart_call_prepare(task); | 6364 | spin_lock(&inode->i_lock); |
6216 | return; | 6365 | lo = NFS_I(inode)->layout; |
6366 | if (!lo || list_empty(&lo->plh_segs)) { | ||
6367 | spin_unlock(&inode->i_lock); | ||
6368 | /* If the open stateid was bad, then recover it. */ | ||
6369 | state = lgp->args.ctx->state; | ||
6370 | } else { | ||
6371 | LIST_HEAD(head); | ||
6372 | |||
6373 | pnfs_mark_matching_lsegs_invalid(lo, &head, NULL); | ||
6374 | spin_unlock(&inode->i_lock); | ||
6375 | /* Mark the bad layout state as invalid, then | ||
6376 | * retry using the open stateid. */ | ||
6377 | pnfs_free_lseg_list(&head); | ||
6217 | } | 6378 | } |
6218 | } | 6379 | } |
6380 | if (nfs4_async_handle_error(task, server, state) == -EAGAIN) | ||
6381 | rpc_restart_call_prepare(task); | ||
6382 | out: | ||
6219 | dprintk("<-- %s\n", __func__); | 6383 | dprintk("<-- %s\n", __func__); |
6220 | } | 6384 | } |
6221 | 6385 | ||
@@ -6282,7 +6446,8 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = { | |||
6282 | .rpc_release = nfs4_layoutget_release, | 6446 | .rpc_release = nfs4_layoutget_release, |
6283 | }; | 6447 | }; |
6284 | 6448 | ||
6285 | void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | 6449 | struct pnfs_layout_segment * |
6450 | nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | ||
6286 | { | 6451 | { |
6287 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); | 6452 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); |
6288 | size_t max_pages = max_response_pages(server); | 6453 | size_t max_pages = max_response_pages(server); |
@@ -6299,6 +6464,7 @@ void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | |||
6299 | .callback_data = lgp, | 6464 | .callback_data = lgp, |
6300 | .flags = RPC_TASK_ASYNC, | 6465 | .flags = RPC_TASK_ASYNC, |
6301 | }; | 6466 | }; |
6467 | struct pnfs_layout_segment *lseg = NULL; | ||
6302 | int status = 0; | 6468 | int status = 0; |
6303 | 6469 | ||
6304 | dprintk("--> %s\n", __func__); | 6470 | dprintk("--> %s\n", __func__); |
@@ -6306,7 +6472,7 @@ void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | |||
6306 | lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); | 6472 | lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); |
6307 | if (!lgp->args.layout.pages) { | 6473 | if (!lgp->args.layout.pages) { |
6308 | nfs4_layoutget_release(lgp); | 6474 | nfs4_layoutget_release(lgp); |
6309 | return; | 6475 | return ERR_PTR(-ENOMEM); |
6310 | } | 6476 | } |
6311 | lgp->args.layout.pglen = max_pages * PAGE_SIZE; | 6477 | lgp->args.layout.pglen = max_pages * PAGE_SIZE; |
6312 | 6478 | ||
@@ -6315,15 +6481,17 @@ void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) | |||
6315 | nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); | 6481 | nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); |
6316 | task = rpc_run_task(&task_setup_data); | 6482 | task = rpc_run_task(&task_setup_data); |
6317 | if (IS_ERR(task)) | 6483 | if (IS_ERR(task)) |
6318 | return; | 6484 | return ERR_CAST(task); |
6319 | status = nfs4_wait_for_completion_rpc_task(task); | 6485 | status = nfs4_wait_for_completion_rpc_task(task); |
6320 | if (status == 0) | 6486 | if (status == 0) |
6321 | status = task->tk_status; | 6487 | status = task->tk_status; |
6322 | if (status == 0) | 6488 | if (status == 0) |
6323 | status = pnfs_layout_process(lgp); | 6489 | lseg = pnfs_layout_process(lgp); |
6324 | rpc_put_task(task); | 6490 | rpc_put_task(task); |
6325 | dprintk("<-- %s status=%d\n", __func__, status); | 6491 | dprintk("<-- %s status=%d\n", __func__, status); |
6326 | return; | 6492 | if (status) |
6493 | return ERR_PTR(status); | ||
6494 | return lseg; | ||
6327 | } | 6495 | } |
6328 | 6496 | ||
6329 | static void | 6497 | static void |
@@ -6342,7 +6510,6 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | |||
6342 | { | 6510 | { |
6343 | struct nfs4_layoutreturn *lrp = calldata; | 6511 | struct nfs4_layoutreturn *lrp = calldata; |
6344 | struct nfs_server *server; | 6512 | struct nfs_server *server; |
6345 | struct pnfs_layout_hdr *lo = lrp->args.layout; | ||
6346 | 6513 | ||
6347 | dprintk("--> %s\n", __func__); | 6514 | dprintk("--> %s\n", __func__); |
6348 | 6515 | ||
@@ -6354,20 +6521,21 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | |||
6354 | rpc_restart_call_prepare(task); | 6521 | rpc_restart_call_prepare(task); |
6355 | return; | 6522 | return; |
6356 | } | 6523 | } |
6357 | spin_lock(&lo->plh_inode->i_lock); | ||
6358 | if (task->tk_status == 0 && lrp->res.lrs_present) | ||
6359 | pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); | ||
6360 | lo->plh_block_lgets--; | ||
6361 | spin_unlock(&lo->plh_inode->i_lock); | ||
6362 | dprintk("<-- %s\n", __func__); | 6524 | dprintk("<-- %s\n", __func__); |
6363 | } | 6525 | } |
6364 | 6526 | ||
6365 | static void nfs4_layoutreturn_release(void *calldata) | 6527 | static void nfs4_layoutreturn_release(void *calldata) |
6366 | { | 6528 | { |
6367 | struct nfs4_layoutreturn *lrp = calldata; | 6529 | struct nfs4_layoutreturn *lrp = calldata; |
6530 | struct pnfs_layout_hdr *lo = lrp->args.layout; | ||
6368 | 6531 | ||
6369 | dprintk("--> %s\n", __func__); | 6532 | dprintk("--> %s\n", __func__); |
6370 | put_layout_hdr(lrp->args.layout); | 6533 | spin_lock(&lo->plh_inode->i_lock); |
6534 | if (lrp->res.lrs_present) | ||
6535 | pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); | ||
6536 | lo->plh_block_lgets--; | ||
6537 | spin_unlock(&lo->plh_inode->i_lock); | ||
6538 | pnfs_put_layout_hdr(lrp->args.layout); | ||
6371 | kfree(calldata); | 6539 | kfree(calldata); |
6372 | dprintk("<-- %s\n", __func__); | 6540 | dprintk("<-- %s\n", __func__); |
6373 | } | 6541 | } |
@@ -6541,7 +6709,7 @@ static void nfs4_layoutcommit_release(void *calldata) | |||
6541 | list_del_init(&lseg->pls_lc_list); | 6709 | list_del_init(&lseg->pls_lc_list); |
6542 | if (test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, | 6710 | if (test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, |
6543 | &lseg->pls_flags)) | 6711 | &lseg->pls_flags)) |
6544 | put_lseg(lseg); | 6712 | pnfs_put_lseg(lseg); |
6545 | } | 6713 | } |
6546 | 6714 | ||
6547 | clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock); | 6715 | clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock); |
@@ -6800,6 +6968,7 @@ static const struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = { | |||
6800 | .recover_lock = nfs4_lock_reclaim, | 6968 | .recover_lock = nfs4_lock_reclaim, |
6801 | .establish_clid = nfs4_init_clientid, | 6969 | .establish_clid = nfs4_init_clientid, |
6802 | .get_clid_cred = nfs4_get_setclientid_cred, | 6970 | .get_clid_cred = nfs4_get_setclientid_cred, |
6971 | .detect_trunking = nfs40_discover_server_trunking, | ||
6803 | }; | 6972 | }; |
6804 | 6973 | ||
6805 | #if defined(CONFIG_NFS_V4_1) | 6974 | #if defined(CONFIG_NFS_V4_1) |
@@ -6811,6 +6980,7 @@ static const struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = { | |||
6811 | .establish_clid = nfs41_init_clientid, | 6980 | .establish_clid = nfs41_init_clientid, |
6812 | .get_clid_cred = nfs4_get_exchange_id_cred, | 6981 | .get_clid_cred = nfs4_get_exchange_id_cred, |
6813 | .reclaim_complete = nfs41_proc_reclaim_complete, | 6982 | .reclaim_complete = nfs41_proc_reclaim_complete, |
6983 | .detect_trunking = nfs41_discover_server_trunking, | ||
6814 | }; | 6984 | }; |
6815 | #endif /* CONFIG_NFS_V4_1 */ | 6985 | #endif /* CONFIG_NFS_V4_1 */ |
6816 | 6986 | ||