Commit 6aedfa2d authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: use the (more efficient) NFSv2/v3-like XDR scheme for generating

RENAME RPC calls.
parent c8e46334
...@@ -347,23 +347,6 @@ nfs4_setup_remove(struct nfs4_compound *cp, struct qstr *name, struct nfs4_chang ...@@ -347,23 +347,6 @@ nfs4_setup_remove(struct nfs4_compound *cp, struct qstr *name, struct nfs4_chang
cp->req_nops++; cp->req_nops++;
} }
static void
nfs4_setup_rename(struct nfs4_compound *cp, struct qstr *old, struct qstr *new,
struct nfs4_change_info *old_cinfo, struct nfs4_change_info *new_cinfo)
{
struct nfs4_rename *rename = GET_OP(cp, rename);
rename->rn_oldnamelen = old->len;
rename->rn_oldname = old->name;
rename->rn_newnamelen = new->len;
rename->rn_newname = new->name;
rename->rn_src_cinfo = old_cinfo;
rename->rn_dst_cinfo = new_cinfo;
OPNUM(cp) = OP_RENAME;
cp->req_nops++;
}
static void static void
nfs4_setup_restorefh(struct nfs4_compound *cp) nfs4_setup_restorefh(struct nfs4_compound *cp)
{ {
...@@ -1291,34 +1274,28 @@ nfs4_proc_unlink_done(struct dentry *dir, struct rpc_task *task) ...@@ -1291,34 +1274,28 @@ nfs4_proc_unlink_done(struct dentry *dir, struct rpc_task *task)
return 0; return 0;
} }
static int static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, struct inode *new_dir, struct qstr *new_name)
struct inode *new_dir, struct qstr *new_name)
{ {
struct nfs4_compound compound; struct nfs4_rename_arg arg = {
struct nfs4_op ops[7]; .old_dir = NFS_FH(old_dir),
struct nfs4_change_info old_cinfo, new_cinfo; .new_dir = NFS_FH(new_dir),
struct nfs_fattr old_dir_attr, new_dir_attr; .old_name = old_name,
.new_name = new_name,
};
struct nfs4_rename_res res = { };
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME],
.rpc_argp = &arg,
.rpc_resp = &res,
};
int status; int status;
old_dir_attr.valid = 0;
new_dir_attr.valid = 0;
nfs4_setup_compound(&compound, ops, NFS_SERVER(old_dir), "rename"); status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
nfs4_setup_putfh(&compound, NFS_FH(old_dir));
nfs4_setup_savefh(&compound);
nfs4_setup_putfh(&compound, NFS_FH(new_dir));
nfs4_setup_rename(&compound, old_name, new_name, &old_cinfo, &new_cinfo);
nfs4_setup_getattr(&compound, &new_dir_attr);
nfs4_setup_restorefh(&compound);
nfs4_setup_getattr(&compound, &old_dir_attr);
status = nfs4_call_compound(&compound, NULL, 0);
if (!status) { if (!status) {
process_cinfo(&old_cinfo, &old_dir_attr); update_changeattr(old_dir, &res.old_cinfo);
process_cinfo(&new_cinfo, &new_dir_attr); update_changeattr(new_dir, &res.new_cinfo);
nfs_refresh_inode(old_dir, &old_dir_attr);
nfs_refresh_inode(new_dir, &new_dir_attr);
} }
return nfs4_map_errors(status); return nfs4_map_errors(status);
} }
......
...@@ -113,6 +113,9 @@ static int nfs_stat_to_errno(int); ...@@ -113,6 +113,9 @@ static int nfs_stat_to_errno(int);
1 + ((3 + NFS4_FHSIZE) >> 2)) 1 + ((3 + NFS4_FHSIZE) >> 2))
#define encode_remove_maxsz (op_encode_hdr_maxsz + \ #define encode_remove_maxsz (op_encode_hdr_maxsz + \
1 + ((3 + NFS4_MAXNAMLEN) >> 2)) 1 + ((3 + NFS4_MAXNAMLEN) >> 2))
#define encode_rename_maxsz (op_encode_hdr_maxsz + \
2 * (1 + ((3 + NFS4_MAXNAMLEN) >> 2)))
#define decode_rename_maxsz (op_decode_hdr_maxsz + 5 + 5)
#define NFS4_enc_compound_sz (1024) /* XXX: large enough? */ #define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
#define NFS4_dec_compound_sz (1024) /* XXX: large enough? */ #define NFS4_dec_compound_sz (1024) /* XXX: large enough? */
#define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \ #define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \
...@@ -278,6 +281,16 @@ static int nfs_stat_to_errno(int); ...@@ -278,6 +281,16 @@ static int nfs_stat_to_errno(int);
#define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \ #define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \ decode_putfh_maxsz + \
op_decode_hdr_maxsz + 5) op_decode_hdr_maxsz + 5)
#define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_savefh_maxsz + \
encode_putfh_maxsz + \
encode_rename_maxsz)
#define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
decode_savefh_maxsz + \
decode_putfh_maxsz + \
decode_rename_maxsz)
...@@ -947,19 +960,18 @@ static int encode_remove(struct xdr_stream *xdr, const struct qstr *name) ...@@ -947,19 +960,18 @@ static int encode_remove(struct xdr_stream *xdr, const struct qstr *name)
return 0; return 0;
} }
static int static int encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname)
encode_rename(struct xdr_stream *xdr, struct nfs4_rename *rename)
{ {
uint32_t *p; uint32_t *p;
RESERVE_SPACE(8 + rename->rn_oldnamelen); RESERVE_SPACE(8 + oldname->len);
WRITE32(OP_RENAME); WRITE32(OP_RENAME);
WRITE32(rename->rn_oldnamelen); WRITE32(oldname->len);
WRITEMEM(rename->rn_oldname, rename->rn_oldnamelen); WRITEMEM(oldname->name, oldname->len);
RESERVE_SPACE(4 + rename->rn_newnamelen); RESERVE_SPACE(4 + newname->len);
WRITE32(rename->rn_newnamelen); WRITE32(newname->len);
WRITEMEM(rename->rn_newname, rename->rn_newnamelen); WRITEMEM(newname->name, newname->len);
return 0; return 0;
} }
...@@ -1115,9 +1127,6 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -1115,9 +1127,6 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
case OP_REMOVE: case OP_REMOVE:
status = encode_remove(xdr, cp->ops[i].u.remove.name); status = encode_remove(xdr, cp->ops[i].u.remove.name);
break; break;
case OP_RENAME:
status = encode_rename(xdr, &cp->ops[i].u.rename);
break;
case OP_RESTOREFH: case OP_RESTOREFH:
status = encode_restorefh(xdr); status = encode_restorefh(xdr);
break; break;
...@@ -1233,6 +1242,30 @@ static int nfs4_xdr_enc_remove(struct rpc_rqst *req, uint32_t *p, const struct n ...@@ -1233,6 +1242,30 @@ static int nfs4_xdr_enc_remove(struct rpc_rqst *req, uint32_t *p, const struct n
return status; return status;
} }
/*
* Encode RENAME request
*/
static int nfs4_xdr_enc_rename(struct rpc_rqst *req, uint32_t *p, const struct nfs4_rename_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
.nops = 4,
};
int status;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
encode_compound_hdr(&xdr, &hdr);
if ((status = encode_putfh(&xdr, args->old_dir)) != 0)
goto out;
if ((status = encode_savefh(&xdr)) != 0)
goto out;
if ((status = encode_putfh(&xdr, args->new_dir)) != 0)
goto out;
status = encode_rename(&xdr, args->old_name, args->new_name);
out:
return status;
}
/* /*
* Encode GETATTR request * Encode GETATTR request
*/ */
...@@ -2095,7 +2128,6 @@ decode_create(struct xdr_stream *xdr, struct nfs4_create *create) ...@@ -2095,7 +2128,6 @@ decode_create(struct xdr_stream *xdr, struct nfs4_create *create)
return 0; return 0;
} }
extern uint32_t nfs4_fattr_bitmap[2];
extern uint32_t nfs4_fsstat_bitmap[2]; extern uint32_t nfs4_fsstat_bitmap[2];
extern uint32_t nfs4_pathconf_bitmap[2]; extern uint32_t nfs4_pathconf_bitmap[2];
...@@ -2800,18 +2832,17 @@ static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) ...@@ -2800,18 +2832,17 @@ static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
return status; return status;
} }
static int static int decode_rename(struct xdr_stream *xdr, struct nfs4_change_info *old_cinfo,
decode_rename(struct xdr_stream *xdr, struct nfs4_rename *rename) struct nfs4_change_info *new_cinfo)
{ {
int status; int status;
status = decode_op_hdr(xdr, OP_RENAME); status = decode_op_hdr(xdr, OP_RENAME);
if (status) if (status)
goto out; goto out;
if ((status = decode_change_info(xdr, rename->rn_src_cinfo))) if ((status = decode_change_info(xdr, old_cinfo)))
goto out;
if ((status = decode_change_info(xdr, rename->rn_dst_cinfo)))
goto out; goto out;
status = decode_change_info(xdr, new_cinfo);
out: out:
return status; return status;
} }
...@@ -2964,9 +2995,6 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -2964,9 +2995,6 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
case OP_REMOVE: case OP_REMOVE:
status = decode_remove(xdr, op->u.remove.rm_cinfo); status = decode_remove(xdr, op->u.remove.rm_cinfo);
break; break;
case OP_RENAME:
status = decode_rename(xdr, &op->u.rename);
break;
case OP_SAVEFH: case OP_SAVEFH:
status = decode_savefh(xdr); status = decode_savefh(xdr);
break; break;
...@@ -3107,6 +3135,29 @@ static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ ...@@ -3107,6 +3135,29 @@ static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_
return status; return status;
} }
/*
* Decode RENAME response
*/
static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_rename_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
if ((status = decode_savefh(&xdr)) != 0)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
status = decode_rename(&xdr, &res->old_cinfo, &res->new_cinfo);
out:
return status;
}
/* /*
* Decode GETATTR response * Decode GETATTR response
*/ */
...@@ -3619,6 +3670,7 @@ struct rpc_procinfo nfs4_procedures[] = { ...@@ -3619,6 +3670,7 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(LOOKUP, enc_lookup, dec_lookup), PROC(LOOKUP, enc_lookup, dec_lookup),
PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root), PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root),
PROC(REMOVE, enc_remove, dec_remove), PROC(REMOVE, enc_remove, dec_remove),
PROC(RENAME, enc_rename, dec_rename),
}; };
struct rpc_version nfs_version4 = { struct rpc_version nfs_version4 = {
......
...@@ -308,6 +308,7 @@ enum { ...@@ -308,6 +308,7 @@ enum {
NFSPROC4_CLNT_LOOKUP, NFSPROC4_CLNT_LOOKUP,
NFSPROC4_CLNT_LOOKUP_ROOT, NFSPROC4_CLNT_LOOKUP_ROOT,
NFSPROC4_CLNT_REMOVE, NFSPROC4_CLNT_REMOVE,
NFSPROC4_CLNT_RENAME,
}; };
#endif #endif
......
...@@ -616,13 +616,16 @@ struct nfs4_remove_arg { ...@@ -616,13 +616,16 @@ struct nfs4_remove_arg {
const struct qstr * name; const struct qstr * name;
}; };
struct nfs4_rename { struct nfs4_rename_arg {
u32 rn_oldnamelen; /* request */ const struct nfs_fh * old_dir;
const char * rn_oldname; /* request */ const struct nfs_fh * new_dir;
u32 rn_newnamelen; /* request */ const struct qstr * old_name;
const char * rn_newname; /* request */ const struct qstr * new_name;
struct nfs4_change_info * rn_src_cinfo; /* response */ };
struct nfs4_change_info * rn_dst_cinfo; /* response */
struct nfs4_rename_res {
struct nfs4_change_info old_cinfo;
struct nfs4_change_info new_cinfo;
}; };
struct nfs4_setattr { struct nfs4_setattr {
...@@ -654,7 +657,6 @@ struct nfs4_op { ...@@ -654,7 +657,6 @@ struct nfs4_op {
struct nfs4_readdir readdir; struct nfs4_readdir readdir;
struct nfs4_readlink readlink; struct nfs4_readlink readlink;
struct nfs4_remove remove; struct nfs4_remove remove;
struct nfs4_rename rename;
struct nfs4_client * renew; struct nfs4_client * renew;
struct nfs4_setattr setattr; struct nfs4_setattr setattr;
} u; } u;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment