diff options
author | Jeff Layton <jeff.layton@primarydata.com> | 2017-06-29 06:34:52 -0700 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2017-07-13 16:00:15 -0400 |
commit | 5b5faaf6df73412af0278997db36dbcb51011d9d (patch) | |
tree | 62c1824135b12d6d393b853c07717c718e8f01b3 /fs/nfs | |
parent | f174ff7a0ab6a097455a94abfc99517940041c07 (diff) | |
download | lwn-5b5faaf6df73412af0278997db36dbcb51011d9d.tar.gz lwn-5b5faaf6df73412af0278997db36dbcb51011d9d.zip |
nfs4: add NFSv4 LOOKUPP handlers
This will be needed in order to implement the get_parent export op
for nfsd.
Signed-off-by: Jeff Layton <jeff.layton@primarydata.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 49 | ||||
-rw-r--r-- | fs/nfs/nfs4trace.h | 29 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 75 |
3 files changed, 153 insertions, 0 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 01dcd4c8dc4f..e1a26c653e78 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -3805,6 +3805,54 @@ nfs4_proc_lookup_mountpoint(struct inode *dir, const struct qstr *name, return (client == NFS_CLIENT(dir)) ? rpc_clone_client(client) : client; } +static int _nfs4_proc_lookupp(struct inode *inode, + struct nfs_fh *fhandle, struct nfs_fattr *fattr, + struct nfs4_label *label) +{ + struct rpc_clnt *clnt = NFS_CLIENT(inode); + struct nfs_server *server = NFS_SERVER(inode); + int status; + struct nfs4_lookupp_arg args = { + .bitmask = server->attr_bitmask, + .fh = NFS_FH(inode), + }; + struct nfs4_lookupp_res res = { + .server = server, + .fattr = fattr, + .label = label, + .fh = fhandle, + }; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUPP], + .rpc_argp = &args, + .rpc_resp = &res, + }; + + args.bitmask = nfs4_bitmask(server, label); + + nfs_fattr_init(fattr); + + dprintk("NFS call lookupp ino=0x%lx\n", inode->i_ino); + status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, + &res.seq_res, 0); + dprintk("NFS reply lookupp: %d\n", status); + return status; +} + +static int nfs4_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle, + struct nfs_fattr *fattr, struct nfs4_label *label) +{ + struct nfs4_exception exception = { }; + int err; + do { + err = _nfs4_proc_lookupp(inode, fhandle, fattr, label); + trace_nfs4_lookupp(inode, err); + err = nfs4_handle_exception(NFS_SERVER(inode), err, + &exception); + } while (exception.retry); + return err; +} + static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) { struct nfs_server *server = NFS_SERVER(inode); @@ -9314,6 +9362,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = { .getattr = nfs4_proc_getattr, .setattr = nfs4_proc_setattr, .lookup = nfs4_proc_lookup, + .lookupp = nfs4_proc_lookupp, .access = nfs4_proc_access, .readlink = nfs4_proc_readlink, .create = nfs4_proc_create, diff --git a/fs/nfs/nfs4trace.h b/fs/nfs/nfs4trace.h index 845d0eadefc9..be1da19c65d6 100644 --- a/fs/nfs/nfs4trace.h +++ b/fs/nfs/nfs4trace.h @@ -891,6 +891,35 @@ DEFINE_NFS4_LOOKUP_EVENT(nfs4_remove); DEFINE_NFS4_LOOKUP_EVENT(nfs4_get_fs_locations); DEFINE_NFS4_LOOKUP_EVENT(nfs4_secinfo); +TRACE_EVENT(nfs4_lookupp, + TP_PROTO( + const struct inode *inode, + int error + ), + + TP_ARGS(inode, error), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(u64, ino) + __field(int, error) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = NFS_FILEID(inode); + __entry->error = error; + ), + + TP_printk( + "error=%d (%s) inode=%02x:%02x:%llu", + __entry->error, + show_nfsv4_errors(__entry->error), + MAJOR(__entry->dev), MINOR(__entry->dev), + (unsigned long long)__entry->ino + ) +); + TRACE_EVENT(nfs4_rename, TP_PROTO( const struct inode *olddir, diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 495d493d3a35..fa3eb361d4f8 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -159,6 +159,8 @@ static int nfs4_stat_to_errno(int); (op_decode_hdr_maxsz) #define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) #define decode_lookup_maxsz (op_decode_hdr_maxsz) +#define encode_lookupp_maxsz (op_encode_hdr_maxsz) +#define decode_lookupp_maxsz (op_decode_hdr_maxsz) #define encode_share_access_maxsz \ (2) #define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz) @@ -618,6 +620,18 @@ static int nfs4_stat_to_errno(int); decode_lookup_maxsz + \ decode_getattr_maxsz + \ decode_getfh_maxsz) +#define NFS4_enc_lookupp_sz (compound_encode_hdr_maxsz + \ + encode_sequence_maxsz + \ + encode_putfh_maxsz + \ + encode_lookupp_maxsz + \ + encode_getattr_maxsz + \ + encode_getfh_maxsz) +#define NFS4_dec_lookupp_sz (compound_decode_hdr_maxsz + \ + decode_sequence_maxsz + \ + decode_putfh_maxsz + \ + decode_lookupp_maxsz + \ + decode_getattr_maxsz + \ + decode_getfh_maxsz) #define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \ encode_sequence_maxsz + \ encode_putrootfh_maxsz + \ @@ -1368,6 +1382,11 @@ static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struc encode_string(xdr, name->len, name->name); } +static void encode_lookupp(struct xdr_stream *xdr, struct compound_hdr *hdr) +{ + encode_op_hdr(xdr, OP_LOOKUPP, decode_lookupp_maxsz, hdr); +} + static void encode_share_access(struct xdr_stream *xdr, u32 share_access) { __be32 *p; @@ -2123,6 +2142,26 @@ static void nfs4_xdr_enc_lookup(struct rpc_rqst *req, struct xdr_stream *xdr, } /* + * Encode LOOKUPP request + */ +static void nfs4_xdr_enc_lookupp(struct rpc_rqst *req, struct xdr_stream *xdr, + const void *data) +{ + const struct nfs4_lookupp_arg *args = data; + struct compound_hdr hdr = { + .minorversion = nfs4_xdr_minorversion(&args->seq_args), + }; + + encode_compound_hdr(xdr, req, &hdr); + encode_sequence(xdr, &args->seq_args, &hdr); + encode_putfh(xdr, args->fh, &hdr); + encode_lookupp(xdr, &hdr); + encode_getfh(xdr, &hdr); + encode_getfattr(xdr, args->bitmask, &hdr); + encode_nops(&hdr); +} + +/* * Encode LOOKUP_ROOT request */ static void nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, @@ -5058,6 +5097,11 @@ static int decode_lookup(struct xdr_stream *xdr) return decode_op_hdr(xdr, OP_LOOKUP); } +static int decode_lookupp(struct xdr_stream *xdr) +{ + return decode_op_hdr(xdr, OP_LOOKUPP); +} + /* This is too sick! */ static int decode_space_limit(struct xdr_stream *xdr, unsigned long *pagemod_limit) @@ -6238,6 +6282,36 @@ out: } /* + * Decode LOOKUPP response + */ +static int nfs4_xdr_dec_lookupp(struct rpc_rqst *rqstp, struct xdr_stream *xdr, + void *data) +{ + struct nfs4_lookupp_res *res = data; + struct compound_hdr hdr; + int status; + + status = decode_compound_hdr(xdr, &hdr); + if (status) + goto out; + status = decode_sequence(xdr, &res->seq_res, rqstp); + if (status) + goto out; + status = decode_putfh(xdr); + if (status) + goto out; + status = decode_lookupp(xdr); + if (status) + goto out; + status = decode_getfh(xdr, res->fh); + if (status) + goto out; + status = decode_getfattr_label(xdr, res->fattr, res->label, res->server); +out: + return status; +} + +/* * Decode LOOKUP_ROOT response */ static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, @@ -7614,6 +7688,7 @@ const struct rpc_procinfo nfs4_procedures[] = { PROC(ACCESS, enc_access, dec_access), PROC(GETATTR, enc_getattr, dec_getattr), PROC(LOOKUP, enc_lookup, dec_lookup), + PROC(LOOKUPP, enc_lookupp, dec_lookupp), PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root), PROC(REMOVE, enc_remove, dec_remove), PROC(RENAME, enc_rename, dec_rename), |