Commit 4e7473b8 authored by Trond Myklebust's avatar Trond Myklebust

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

parent 6aedfa2d
...@@ -238,20 +238,6 @@ nfs4_setup_getfh(struct nfs4_compound *cp, struct nfs_fh *fhandle) ...@@ -238,20 +238,6 @@ nfs4_setup_getfh(struct nfs4_compound *cp, struct nfs_fh *fhandle)
cp->req_nops++; cp->req_nops++;
} }
static void
nfs4_setup_link(struct nfs4_compound *cp, struct qstr *name,
struct nfs4_change_info *info)
{
struct nfs4_link *link = GET_OP(cp, link);
link->ln_namelen = name->len;
link->ln_name = name->name;
link->ln_cinfo = info;
OPNUM(cp) = OP_LINK;
cp->req_nops++;
}
static void static void
nfs4_setup_putfh(struct nfs4_compound *cp, struct nfs_fh *fhandle) nfs4_setup_putfh(struct nfs4_compound *cp, struct nfs_fh *fhandle)
{ {
...@@ -1300,33 +1286,25 @@ static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, ...@@ -1300,33 +1286,25 @@ static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
return nfs4_map_errors(status); return nfs4_map_errors(status);
} }
static int static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
{ {
struct nfs4_compound compound; struct nfs4_link_arg arg = {
struct nfs4_op ops[7]; .fh = NFS_FH(inode),
struct nfs4_change_info dir_cinfo; .dir_fh = NFS_FH(dir),
struct nfs_fattr dir_attr, fattr; .name = name,
};
struct nfs4_change_info cinfo = { };
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK],
.rpc_argp = &arg,
.rpc_resp = &cinfo,
};
int status; int status;
dir_attr.valid = 0; status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
fattr.valid = 0; if (!status)
update_changeattr(dir, &cinfo);
nfs4_setup_compound(&compound, ops, NFS_SERVER(inode), "link");
nfs4_setup_putfh(&compound, NFS_FH(inode));
nfs4_setup_savefh(&compound);
nfs4_setup_putfh(&compound, NFS_FH(dir));
nfs4_setup_link(&compound, name, &dir_cinfo);
nfs4_setup_getattr(&compound, &dir_attr);
nfs4_setup_restorefh(&compound);
nfs4_setup_getattr(&compound, &fattr);
status = nfs4_call_compound(&compound, NULL, 0);
if (!status) {
process_cinfo(&dir_cinfo, &dir_attr);
nfs_refresh_inode(dir, &dir_attr);
nfs_refresh_inode(inode, &fattr);
}
return nfs4_map_errors(status); return nfs4_map_errors(status);
} }
......
...@@ -116,6 +116,9 @@ static int nfs_stat_to_errno(int); ...@@ -116,6 +116,9 @@ static int nfs_stat_to_errno(int);
#define encode_rename_maxsz (op_encode_hdr_maxsz + \ #define encode_rename_maxsz (op_encode_hdr_maxsz + \
2 * (1 + ((3 + NFS4_MAXNAMLEN) >> 2))) 2 * (1 + ((3 + NFS4_MAXNAMLEN) >> 2)))
#define decode_rename_maxsz (op_decode_hdr_maxsz + 5 + 5) #define decode_rename_maxsz (op_decode_hdr_maxsz + 5 + 5)
#define encode_link_maxsz (op_encode_hdr_maxsz + \
1 + ((3 + NFS4_MAXNAMLEN) >> 2))
#define decode_link_maxsz (op_decode_hdr_maxsz + 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 + \
...@@ -291,6 +294,16 @@ static int nfs_stat_to_errno(int); ...@@ -291,6 +294,16 @@ static int nfs_stat_to_errno(int);
decode_savefh_maxsz + \ decode_savefh_maxsz + \
decode_putfh_maxsz + \ decode_putfh_maxsz + \
decode_rename_maxsz) decode_rename_maxsz)
#define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_savefh_maxsz + \
encode_putfh_maxsz + \
encode_link_maxsz)
#define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
decode_savefh_maxsz + \
decode_putfh_maxsz + \
decode_link_maxsz)
...@@ -618,15 +631,14 @@ encode_getfh(struct xdr_stream *xdr) ...@@ -618,15 +631,14 @@ encode_getfh(struct xdr_stream *xdr)
return 0; return 0;
} }
static int static int encode_link(struct xdr_stream *xdr, const struct qstr *name)
encode_link(struct xdr_stream *xdr, struct nfs4_link *link)
{ {
uint32_t *p; uint32_t *p;
RESERVE_SPACE(8 + link->ln_namelen); RESERVE_SPACE(8 + name->len);
WRITE32(OP_LINK); WRITE32(OP_LINK);
WRITE32(link->ln_namelen); WRITE32(name->len);
WRITEMEM(link->ln_name, link->ln_namelen); WRITEMEM(name->name, name->len);
return 0; return 0;
} }
...@@ -1112,9 +1124,6 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -1112,9 +1124,6 @@ encode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
case OP_GETFH: case OP_GETFH:
status = encode_getfh(xdr); status = encode_getfh(xdr);
break; break;
case OP_LINK:
status = encode_link(xdr, &cp->ops[i].u.link);
break;
case OP_PUTFH: case OP_PUTFH:
status = encode_putfh(xdr, cp->ops[i].u.putfh.pf_fhandle); status = encode_putfh(xdr, cp->ops[i].u.putfh.pf_fhandle);
break; break;
...@@ -1266,6 +1275,30 @@ static int nfs4_xdr_enc_rename(struct rpc_rqst *req, uint32_t *p, const struct n ...@@ -1266,6 +1275,30 @@ static int nfs4_xdr_enc_rename(struct rpc_rqst *req, uint32_t *p, const struct n
return status; return status;
} }
/*
* Encode LINK request
*/
static int nfs4_xdr_enc_link(struct rpc_rqst *req, uint32_t *p, const struct nfs4_link_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->fh)) != 0)
goto out;
if ((status = encode_savefh(&xdr)) != 0)
goto out;
if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
goto out;
status = encode_link(&xdr, args->name);
out:
return status;
}
/* /*
* Encode GETATTR request * Encode GETATTR request
*/ */
...@@ -2512,15 +2545,14 @@ static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh) ...@@ -2512,15 +2545,14 @@ static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
return 0; return 0;
} }
static int static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
decode_link(struct xdr_stream *xdr, struct nfs4_link *link)
{ {
int status; int status;
status = decode_op_hdr(xdr, OP_LINK); status = decode_op_hdr(xdr, OP_LINK);
if (status) if (status)
return status; return status;
return decode_change_info(xdr, link->ln_cinfo); return decode_change_info(xdr, cinfo);
} }
/* /*
...@@ -2977,9 +3009,6 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs ...@@ -2977,9 +3009,6 @@ decode_compound(struct xdr_stream *xdr, struct nfs4_compound *cp, struct rpc_rqs
case OP_GETFH: case OP_GETFH:
status = decode_getfh(xdr, op->u.getfh.gf_fhandle); status = decode_getfh(xdr, op->u.getfh.gf_fhandle);
break; break;
case OP_LINK:
status = decode_link(xdr, &op->u.link);
break;
case OP_PUTFH: case OP_PUTFH:
status = decode_putfh(xdr); status = decode_putfh(xdr);
break; break;
...@@ -3158,6 +3187,29 @@ static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ ...@@ -3158,6 +3187,29 @@ static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_
return status; return status;
} }
/*
* Decode LINK response
*/
static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_change_info *cinfo)
{
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_link(&xdr, cinfo);
out:
return status;
}
/* /*
* Decode GETATTR response * Decode GETATTR response
*/ */
...@@ -3671,6 +3723,7 @@ struct rpc_procinfo nfs4_procedures[] = { ...@@ -3671,6 +3723,7 @@ struct rpc_procinfo nfs4_procedures[] = {
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), PROC(RENAME, enc_rename, dec_rename),
PROC(LINK, enc_link, dec_link),
}; };
struct rpc_version nfs_version4 = { struct rpc_version nfs_version4 = {
......
...@@ -309,6 +309,7 @@ enum { ...@@ -309,6 +309,7 @@ enum {
NFSPROC4_CLNT_LOOKUP_ROOT, NFSPROC4_CLNT_LOOKUP_ROOT,
NFSPROC4_CLNT_REMOVE, NFSPROC4_CLNT_REMOVE,
NFSPROC4_CLNT_RENAME, NFSPROC4_CLNT_RENAME,
NFSPROC4_CLNT_LINK,
}; };
#endif #endif
......
...@@ -544,10 +544,10 @@ struct nfs4_getfh { ...@@ -544,10 +544,10 @@ struct nfs4_getfh {
struct nfs_fh * gf_fhandle; /* response */ struct nfs_fh * gf_fhandle; /* response */
}; };
struct nfs4_link { struct nfs4_link_arg {
u32 ln_namelen; /* request */ const struct nfs_fh * fh;
const char * ln_name; /* request */ const struct nfs_fh * dir_fh;
struct nfs4_change_info * ln_cinfo; /* response */ const struct qstr * name;
}; };
struct nfs4_lookup_arg { struct nfs4_lookup_arg {
...@@ -650,7 +650,6 @@ struct nfs4_op { ...@@ -650,7 +650,6 @@ struct nfs4_op {
struct nfs4_create create; struct nfs4_create create;
struct nfs4_getattr getattr; struct nfs4_getattr getattr;
struct nfs4_getfh getfh; struct nfs4_getfh getfh;
struct nfs4_link link;
struct nfs4_open open; struct nfs4_open open;
struct nfs4_open_confirm open_confirm; struct nfs4_open_confirm open_confirm;
struct nfs4_putfh putfh; struct nfs4_putfh putfh;
......
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