NFSv4: Add directory post-op attributes to the CREATE operations.

Since the directory attributes change every time we CREATE a file,
 we might as well pick up the new directory attributes in the same
 compound.

 Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
Trond Myklebust 2005-10-27 22:12:40 -04:00
parent 0c70b50150
commit 56ae19f38f
3 changed files with 84 additions and 15 deletions

View File

@ -443,7 +443,11 @@ static int _nfs4_proc_open(struct inode *dir, struct nfs4_state_owner *sp, stru
nfs_increment_open_seqid(status, o_arg->seqid); nfs_increment_open_seqid(status, o_arg->seqid);
if (status != 0) if (status != 0)
goto out; goto out;
update_changeattr(dir, &o_res->cinfo); if (o_arg->open_flags & O_CREAT) {
update_changeattr(dir, &o_res->cinfo);
nfs_post_op_update_inode(dir, o_res->dir_attr);
} else
nfs_refresh_inode(dir, o_res->dir_attr);
if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
status = _nfs4_proc_open_confirm(server->client, &o_res->fh, status = _nfs4_proc_open_confirm(server->client, &o_res->fh,
sp, &o_res->stateid, o_arg->seqid); sp, &o_res->stateid, o_arg->seqid);
@ -497,7 +501,7 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
struct inode *inode = state->inode; struct inode *inode = state->inode;
struct nfs_server *server = NFS_SERVER(dir); struct nfs_server *server = NFS_SERVER(dir);
struct nfs_delegation *delegation = NFS_I(inode)->delegation; struct nfs_delegation *delegation = NFS_I(inode)->delegation;
struct nfs_fattr f_attr; struct nfs_fattr f_attr, dir_attr;
struct nfs_openargs o_arg = { struct nfs_openargs o_arg = {
.fh = NFS_FH(dir), .fh = NFS_FH(dir),
.open_flags = state->state, .open_flags = state->state,
@ -507,6 +511,7 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
}; };
struct nfs_openres o_res = { struct nfs_openres o_res = {
.f_attr = &f_attr, .f_attr = &f_attr,
.dir_attr = &dir_attr,
.server = server, .server = server,
}; };
int status = 0; int status = 0;
@ -524,6 +529,7 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
if (o_arg.seqid == NULL) if (o_arg.seqid == NULL)
goto out; goto out;
nfs_fattr_init(&f_attr); nfs_fattr_init(&f_attr);
nfs_fattr_init(&dir_attr);
status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
if (status != 0) if (status != 0)
goto out_nodeleg; goto out_nodeleg;
@ -694,7 +700,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
struct nfs4_client *clp = server->nfs4_state; struct nfs4_client *clp = server->nfs4_state;
struct inode *inode = NULL; struct inode *inode = NULL;
int status; int status;
struct nfs_fattr f_attr; struct nfs_fattr f_attr, dir_attr;
struct nfs_openargs o_arg = { struct nfs_openargs o_arg = {
.fh = NFS_FH(dir), .fh = NFS_FH(dir),
.open_flags = flags, .open_flags = flags,
@ -705,6 +711,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
}; };
struct nfs_openres o_res = { struct nfs_openres o_res = {
.f_attr = &f_attr, .f_attr = &f_attr,
.dir_attr = &dir_attr,
.server = server, .server = server,
}; };
@ -727,6 +734,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st
if (o_arg.seqid == NULL) if (o_arg.seqid == NULL)
return -ENOMEM; return -ENOMEM;
nfs_fattr_init(&f_attr); nfs_fattr_init(&f_attr);
nfs_fattr_init(&dir_attr);
status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
if (status != 0) if (status != 0)
goto out_err; goto out_err;
@ -1746,6 +1754,7 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name,
struct nfs_fattr *fattr) struct nfs_fattr *fattr)
{ {
struct nfs_server *server = NFS_SERVER(dir); struct nfs_server *server = NFS_SERVER(dir);
struct nfs_fattr dir_fattr;
struct nfs4_create_arg arg = { struct nfs4_create_arg arg = {
.dir_fh = NFS_FH(dir), .dir_fh = NFS_FH(dir),
.server = server, .server = server,
@ -1758,6 +1767,7 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name,
.server = server, .server = server,
.fh = fhandle, .fh = fhandle,
.fattr = fattr, .fattr = fattr,
.dir_fattr = &dir_fattr,
}; };
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK], .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK],
@ -1770,10 +1780,12 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name,
return -ENAMETOOLONG; return -ENAMETOOLONG;
arg.u.symlink = path; arg.u.symlink = path;
nfs_fattr_init(fattr); nfs_fattr_init(fattr);
nfs_fattr_init(&dir_fattr);
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
if (!status) if (!status)
update_changeattr(dir, &res.dir_cinfo); update_changeattr(dir, &res.dir_cinfo);
nfs_post_op_update_inode(dir, res.dir_fattr);
return status; return status;
} }
@ -1797,7 +1809,7 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
{ {
struct nfs_server *server = NFS_SERVER(dir); struct nfs_server *server = NFS_SERVER(dir);
struct nfs_fh fhandle; struct nfs_fh fhandle;
struct nfs_fattr fattr; struct nfs_fattr fattr, dir_fattr;
struct nfs4_create_arg arg = { struct nfs4_create_arg arg = {
.dir_fh = NFS_FH(dir), .dir_fh = NFS_FH(dir),
.server = server, .server = server,
@ -1810,6 +1822,7 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
.server = server, .server = server,
.fh = &fhandle, .fh = &fhandle,
.fattr = &fattr, .fattr = &fattr,
.dir_fattr = &dir_fattr,
}; };
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
@ -1819,10 +1832,12 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
int status; int status;
nfs_fattr_init(&fattr); nfs_fattr_init(&fattr);
nfs_fattr_init(&dir_fattr);
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
if (!status) { if (!status) {
update_changeattr(dir, &res.dir_cinfo); update_changeattr(dir, &res.dir_cinfo);
nfs_post_op_update_inode(dir, res.dir_fattr);
status = nfs_instantiate(dentry, &fhandle, &fattr); status = nfs_instantiate(dentry, &fhandle, &fattr);
} }
return status; return status;
@ -1895,7 +1910,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
{ {
struct nfs_server *server = NFS_SERVER(dir); struct nfs_server *server = NFS_SERVER(dir);
struct nfs_fh fh; struct nfs_fh fh;
struct nfs_fattr fattr; struct nfs_fattr fattr, dir_fattr;
struct nfs4_create_arg arg = { struct nfs4_create_arg arg = {
.dir_fh = NFS_FH(dir), .dir_fh = NFS_FH(dir),
.server = server, .server = server,
@ -1907,6 +1922,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
.server = server, .server = server,
.fh = &fh, .fh = &fh,
.fattr = &fattr, .fattr = &fattr,
.dir_fattr = &dir_fattr,
}; };
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
@ -1917,6 +1933,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
int mode = sattr->ia_mode; int mode = sattr->ia_mode;
nfs_fattr_init(&fattr); nfs_fattr_init(&fattr);
nfs_fattr_init(&dir_fattr);
BUG_ON(!(sattr->ia_valid & ATTR_MODE)); BUG_ON(!(sattr->ia_valid & ATTR_MODE));
BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode)); BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode));
@ -1938,6 +1955,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
if (status == 0) { if (status == 0) {
update_changeattr(dir, &res.dir_cinfo); update_changeattr(dir, &res.dir_cinfo);
nfs_post_op_update_inode(dir, res.dir_fattr);
status = nfs_instantiate(dentry, &fh, &fattr); status = nfs_instantiate(dentry, &fh, &fattr);
} }
return status; return status;

View File

@ -95,6 +95,8 @@ static int nfs_stat_to_errno(int);
#define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
#define encode_savefh_maxsz (op_encode_hdr_maxsz) #define encode_savefh_maxsz (op_encode_hdr_maxsz)
#define decode_savefh_maxsz (op_decode_hdr_maxsz) #define decode_savefh_maxsz (op_decode_hdr_maxsz)
#define encode_restorefh_maxsz (op_encode_hdr_maxsz)
#define decode_restorefh_maxsz (op_decode_hdr_maxsz)
#define encode_fsinfo_maxsz (op_encode_hdr_maxsz + 2) #define encode_fsinfo_maxsz (op_encode_hdr_maxsz + 2)
#define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11) #define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11)
#define encode_renew_maxsz (op_encode_hdr_maxsz + 3) #define encode_renew_maxsz (op_encode_hdr_maxsz + 3)
@ -336,14 +338,20 @@ static int nfs_stat_to_errno(int);
decode_getfh_maxsz) decode_getfh_maxsz)
#define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \ encode_putfh_maxsz + \
encode_savefh_maxsz + \
encode_create_maxsz + \ encode_create_maxsz + \
encode_getfh_maxsz + \
encode_getattr_maxsz + \ encode_getattr_maxsz + \
encode_getfh_maxsz) encode_restorefh_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \ decode_putfh_maxsz + \
decode_savefh_maxsz + \
decode_create_maxsz + \ decode_create_maxsz + \
decode_getfh_maxsz + \
decode_getattr_maxsz + \ decode_getattr_maxsz + \
decode_getfh_maxsz) decode_restorefh_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \ encode_putfh_maxsz + \
encode_getattr_maxsz) encode_getattr_maxsz)
@ -1112,6 +1120,17 @@ static int encode_renew(struct xdr_stream *xdr, const struct nfs4_client *client
return 0; return 0;
} }
static int
encode_restorefh(struct xdr_stream *xdr)
{
uint32_t *p;
RESERVE_SPACE(4);
WRITE32(OP_RESTOREFH);
return 0;
}
static int static int
encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg) encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg)
{ {
@ -1358,7 +1377,7 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct n
{ {
struct xdr_stream xdr; struct xdr_stream xdr;
struct compound_hdr hdr = { struct compound_hdr hdr = {
.nops = 4, .nops = 7,
}; };
int status; int status;
@ -1366,10 +1385,16 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct n
encode_compound_hdr(&xdr, &hdr); encode_compound_hdr(&xdr, &hdr);
if ((status = encode_putfh(&xdr, args->dir_fh)) != 0) if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
goto out; goto out;
if ((status = encode_savefh(&xdr)) != 0)
goto out;
if ((status = encode_create(&xdr, args)) != 0) if ((status = encode_create(&xdr, args)) != 0)
goto out; goto out;
if ((status = encode_getfh(&xdr)) != 0) if ((status = encode_getfh(&xdr)) != 0)
goto out; goto out;
if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
goto out;
if ((status = encode_restorefh(&xdr)) != 0)
goto out;
status = encode_getfattr(&xdr, args->bitmask); status = encode_getfattr(&xdr, args->bitmask);
out: out:
return status; return status;
@ -1429,7 +1454,7 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena
{ {
struct xdr_stream xdr; struct xdr_stream xdr;
struct compound_hdr hdr = { struct compound_hdr hdr = {
.nops = 4, .nops = 7,
}; };
int status; int status;
@ -1439,6 +1464,9 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena
xdr_init_encode(&xdr, &req->rq_snd_buf, p); xdr_init_encode(&xdr, &req->rq_snd_buf, p);
encode_compound_hdr(&xdr, &hdr); encode_compound_hdr(&xdr, &hdr);
status = encode_putfh(&xdr, args->fh); status = encode_putfh(&xdr, args->fh);
if (status)
goto out;
status = encode_savefh(&xdr);
if (status) if (status)
goto out; goto out;
status = encode_open(&xdr, args); status = encode_open(&xdr, args);
@ -1448,6 +1476,12 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena
if (status) if (status)
goto out; goto out;
status = encode_getfattr(&xdr, args->bitmask); status = encode_getfattr(&xdr, args->bitmask);
if (status)
goto out;
status = encode_restorefh(&xdr);
if (status)
goto out;
status = encode_getfattr(&xdr, args->bitmask);
out: out:
return status; return status;
} }
@ -3218,6 +3252,12 @@ static int decode_renew(struct xdr_stream *xdr)
return decode_op_hdr(xdr, OP_RENEW); return decode_op_hdr(xdr, OP_RENEW);
} }
static int
decode_restorefh(struct xdr_stream *xdr)
{
return decode_op_hdr(xdr, OP_RESTOREFH);
}
static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
size_t *acl_len) size_t *acl_len)
{ {
@ -3510,13 +3550,17 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_
goto out; goto out;
if ((status = decode_putfh(&xdr)) != 0) if ((status = decode_putfh(&xdr)) != 0)
goto out; goto out;
if ((status = decode_savefh(&xdr)) != 0)
goto out;
if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0) if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0)
goto out; goto out;
if ((status = decode_getfh(&xdr, res->fh)) != 0) if ((status = decode_getfh(&xdr, res->fh)) != 0)
goto out; goto out;
status = decode_getfattr(&xdr, res->fattr, res->server); if (decode_getfattr(&xdr, res->fattr, res->server) != 0)
if (status == NFS4ERR_DELAY) goto out;
status = 0; if ((status = decode_restorefh(&xdr)) != 0)
goto out;
decode_getfattr(&xdr, res->dir_fattr, res->server);
out: out:
return status; return status;
} }
@ -3654,15 +3698,20 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_ope
status = decode_putfh(&xdr); status = decode_putfh(&xdr);
if (status) if (status)
goto out; goto out;
status = decode_savefh(&xdr);
if (status)
goto out;
status = decode_open(&xdr, res); status = decode_open(&xdr, res);
if (status) if (status)
goto out; goto out;
status = decode_getfh(&xdr, &res->fh); status = decode_getfh(&xdr, &res->fh);
if (status) if (status)
goto out; goto out;
status = decode_getfattr(&xdr, res->f_attr, res->server); if (decode_getfattr(&xdr, res->f_attr, res->server) != 0)
if (status == NFS4ERR_DELAY) goto out;
status = 0; if ((status = decode_restorefh(&xdr)) != 0)
goto out;
decode_getfattr(&xdr, res->dir_attr, res->server);
out: out:
return status; return status;
} }

View File

@ -124,6 +124,7 @@ struct nfs_openres {
struct nfs4_change_info cinfo; struct nfs4_change_info cinfo;
__u32 rflags; __u32 rflags;
struct nfs_fattr * f_attr; struct nfs_fattr * f_attr;
struct nfs_fattr * dir_attr;
const struct nfs_server *server; const struct nfs_server *server;
int delegation_type; int delegation_type;
nfs4_stateid delegation; nfs4_stateid delegation;
@ -540,6 +541,7 @@ struct nfs4_create_res {
struct nfs_fh * fh; struct nfs_fh * fh;
struct nfs_fattr * fattr; struct nfs_fattr * fattr;
struct nfs4_change_info dir_cinfo; struct nfs4_change_info dir_cinfo;
struct nfs_fattr * dir_fattr;
}; };
struct nfs4_fsinfo_arg { struct nfs4_fsinfo_arg {