aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/nfs4proc.c114
-rw-r--r--fs/nfs/nfs4xdr.c2
2 files changed, 89 insertions, 27 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;
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 0d6030510fe2..40836ee5dc3a 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -2264,7 +2264,7 @@ static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req,
2264 encode_open(xdr, args, &hdr); 2264 encode_open(xdr, args, &hdr);
2265 if (args->access) 2265 if (args->access)
2266 encode_access(xdr, args->access, &hdr); 2266 encode_access(xdr, args->access, &hdr);
2267 encode_getfattr(xdr, args->bitmask, &hdr); 2267 encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
2268 encode_nops(&hdr); 2268 encode_nops(&hdr);
2269} 2269}
2270 2270