|
@@ -1782,7 +1782,14 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct
|
|
|
/*
|
|
|
* Returns a referenced nfs4_state
|
|
|
*/
|
|
|
-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)
|
|
|
+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,
|
|
|
+ struct nfs4_threshold **ctx_th)
|
|
|
{
|
|
|
struct nfs4_state_owner *sp;
|
|
|
struct nfs4_state *state = NULL;
|
|
@@ -1807,6 +1814,11 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, fmode_t fmode
|
|
|
if (opendata == NULL)
|
|
|
goto err_put_state_owner;
|
|
|
|
|
|
+ if (ctx_th && server->attr_bitmask[2] & FATTR4_WORD2_MDSTHRESHOLD) {
|
|
|
+ opendata->f_attr.mdsthreshold = pnfs_mdsthreshold_alloc();
|
|
|
+ if (!opendata->f_attr.mdsthreshold)
|
|
|
+ goto err_opendata_put;
|
|
|
+ }
|
|
|
if (dentry->d_inode != NULL)
|
|
|
opendata->state = nfs4_get_open_state(dentry->d_inode, sp);
|
|
|
|
|
@@ -1832,11 +1844,19 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, fmode_t fmode
|
|
|
nfs_setattr_update_inode(state->inode, sattr);
|
|
|
nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr);
|
|
|
}
|
|
|
+
|
|
|
+ if (pnfs_use_threshold(ctx_th, opendata->f_attr.mdsthreshold, server))
|
|
|
+ *ctx_th = opendata->f_attr.mdsthreshold;
|
|
|
+ else
|
|
|
+ kfree(opendata->f_attr.mdsthreshold);
|
|
|
+ opendata->f_attr.mdsthreshold = NULL;
|
|
|
+
|
|
|
nfs4_opendata_put(opendata);
|
|
|
nfs4_put_state_owner(sp);
|
|
|
*res = state;
|
|
|
return 0;
|
|
|
err_opendata_put:
|
|
|
+ kfree(opendata->f_attr.mdsthreshold);
|
|
|
nfs4_opendata_put(opendata);
|
|
|
err_put_state_owner:
|
|
|
nfs4_put_state_owner(sp);
|
|
@@ -1846,14 +1866,21 @@ out_err:
|
|
|
}
|
|
|
|
|
|
|
|
|
-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)
|
|
|
+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,
|
|
|
+ struct nfs4_threshold **ctx_th)
|
|
|
{
|
|
|
struct nfs4_exception exception = { };
|
|
|
struct nfs4_state *res;
|
|
|
int status;
|
|
|
|
|
|
do {
|
|
|
- status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred, &res);
|
|
|
+ status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred,
|
|
|
+ &res, ctx_th);
|
|
|
if (status == 0)
|
|
|
break;
|
|
|
/* NOTE: BAD_SEQID means the server and client disagree about the
|
|
@@ -2177,7 +2204,8 @@ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags
|
|
|
struct nfs4_state *state;
|
|
|
|
|
|
/* Protect against concurrent sillydeletes */
|
|
|
- state = nfs4_do_open(dir, ctx->dentry, ctx->mode, open_flags, attr, ctx->cred);
|
|
|
+ state = nfs4_do_open(dir, ctx->dentry, ctx->mode, open_flags, attr,
|
|
|
+ ctx->cred, &ctx->mdsthreshold);
|
|
|
if (IS_ERR(state))
|
|
|
return ERR_CAST(state);
|
|
|
ctx->state = state;
|
|
@@ -2779,7 +2807,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
|
|
|
fmode = ctx->mode;
|
|
|
}
|
|
|
sattr->ia_mode &= ~current_umask();
|
|
|
- state = nfs4_do_open(dir, de, fmode, flags, sattr, cred);
|
|
|
+ state = nfs4_do_open(dir, de, fmode, flags, sattr, cred, NULL);
|
|
|
d_drop(dentry);
|
|
|
if (IS_ERR(state)) {
|
|
|
status = PTR_ERR(state);
|