aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2012-10-02 21:07:32 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-10-02 21:12:25 -0400
commite23008ec81ef37b7b271669ce5d2de2643b2dc75 (patch)
treedaa52b0b710384e67b387e0fd4b607ecb8435492 /fs/nfs/nfs4proc.c
parent807d66d80221920729a8d4abfa04246546a6d3fa (diff)
NFSv4 reduce attribute requests for open reclaim
We currently make no distinction in attribute requests between normal OPENs and OPEN with CLAIM_PREVIOUS. This offers more possibility of failures in the GETATTR response which foils OPEN reclaim attempts. Reduce the requested attributes to the bare minimum needed to update the reclaim open stateid and split nfs4_opendata_to_nfs4_state processing accordingly. Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c114
1 files changed, 88 insertions, 26 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 68438aa4f08e..2b62e3f79c91 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -152,6 +152,12 @@ static const u32 nfs4_pnfs_open_bitmap[3] = {
152 FATTR4_WORD2_MDSTHRESHOLD 152 FATTR4_WORD2_MDSTHRESHOLD
153}; 153};
154 154
155static const u32 nfs4_open_noattr_bitmap[3] = {
156 FATTR4_WORD0_TYPE
157 | FATTR4_WORD0_CHANGE
158 | FATTR4_WORD0_FILEID,
159};
160
155const u32 nfs4_statfs_bitmap[2] = { 161const u32 nfs4_statfs_bitmap[2] = {
156 FATTR4_WORD0_FILES_AVAIL 162 FATTR4_WORD0_FILES_AVAIL
157 | FATTR4_WORD0_FILES_FREE 163 | FATTR4_WORD0_FILES_FREE
@@ -1126,11 +1132,80 @@ out_return_state:
1126 return state; 1132 return state;
1127} 1133}
1128 1134
1129static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data) 1135static void
1136nfs4_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 */
1166static 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;
1199err:
1200 return ERR_PTR(ret);
1201
1202}
1203
1204static struct nfs4_state *
1205_nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
1130{ 1206{
1131 struct inode *inode; 1207 struct inode *inode;
1132 struct nfs4_state *state = NULL; 1208 struct nfs4_state *state = NULL;
1133 struct nfs_delegation *delegation;
1134 int ret; 1209 int ret;
1135 1210
1136 if (!data->rpc_done) { 1211 if (!data->rpc_done) {
@@ -1149,30 +1224,8 @@ static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data
1149 state = nfs4_get_open_state(inode, data->owner); 1224 state = nfs4_get_open_state(inode, data->owner);
1150 if (state == NULL) 1225 if (state == NULL)
1151 goto err_put_inode; 1226 goto err_put_inode;
1152 if (data->o_res.delegation_type != 0) { 1227 if (data->o_res.delegation_type != 0)
1153 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 1228 nfs4_opendata_check_deleg(data, state);
1154 int delegation_flags = 0;
1155
1156 rcu_read_lock();
1157 delegation = rcu_dereference(NFS_I(inode)->delegation);
1158 if (delegation)
1159 delegation_flags = delegation->flags;
1160 rcu_read_unlock();
1161 if (data->o_arg.claim == NFS4_OPEN_CLAIM_DELEGATE_CUR) {
1162 pr_err_ratelimited("NFS: Broken NFSv4 server %s is "
1163 "returning a delegation for "
1164 "OPEN(CLAIM_DELEGATE_CUR)\n",
1165 clp->cl_hostname);
1166 } else if ((delegation_flags & 1UL<<NFS_DELEGATION_NEED_RECLAIM) == 0)
1167 nfs_inode_set_delegation(state->inode,
1168 data->owner->so_cred,
1169 &data->o_res);
1170 else
1171 nfs_inode_reclaim_delegation(state->inode,
1172 data->owner->so_cred,
1173 &data->o_res);
1174 }
1175
1176 update_open_stateid(state, &data->o_res.stateid, NULL, 1229 update_open_stateid(state, &data->o_res.stateid, NULL,
1177 data->o_arg.fmode); 1230 data->o_arg.fmode);
1178 iput(inode); 1231 iput(inode);
@@ -1184,6 +1237,14 @@ err:
1184 return ERR_PTR(ret); 1237 return ERR_PTR(ret);
1185} 1238}
1186 1239
1240static struct nfs4_state *
1241nfs4_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
1187static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *state) 1248static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *state)
1188{ 1249{
1189 struct nfs_inode *nfsi = NFS_I(state->inode); 1250 struct nfs_inode *nfsi = NFS_I(state->inode);
@@ -1505,6 +1566,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
1505 data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid; 1566 data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid;
1506 if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { 1567 if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) {
1507 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];
1508 nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); 1570 nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
1509 } 1571 }
1510 data->timestamp = jiffies; 1572 data->timestamp = jiffies;