nfs4: add NFSv4 LOOKUPP handlers
authorJeff Layton <jeff.layton@primarydata.com>
Thu, 29 Jun 2017 13:34:52 +0000 (06:34 -0700)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Thu, 13 Jul 2017 20:00:15 +0000 (16:00 -0400)
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>
fs/nfs/nfs4proc.c
fs/nfs/nfs4trace.h
fs/nfs/nfs4xdr.c
include/linux/nfs4.h
include/linux/nfs_xdr.h

index 01dcd4c8dc4f0b0833dae0c07ea602ff9d758041..e1a26c653e7860881d81fbf3a5c45eaa521047a5 100644 (file)
@@ -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,
index 845d0eadefc94f48dc6410b3bbb3a0df89caca18..be1da19c65d61e89e19f45d9bd07faaabe54d71f 100644 (file)
@@ -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,
index 495d493d3a35b1e1b872666b2f1c00a1e303f879..fa3eb361d4f863be18072272293dcbdcedfd887f 100644 (file)
@@ -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;
@@ -2122,6 +2141,26 @@ static void nfs4_xdr_enc_lookup(struct rpc_rqst *req, struct xdr_stream *xdr,
        encode_nops(&hdr);
 }
 
+/*
+ * 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
  */
@@ -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)
@@ -6237,6 +6281,36 @@ out:
        return status;
 }
 
+/*
+ * 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
  */
@@ -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),
index 1b1ca04820a306ebe5da0aa7d12035c9c3d5e8d0..47239c3366882326a95c4b509e273c58ce622806 100644 (file)
@@ -479,6 +479,7 @@ enum {
        NFSPROC4_CLNT_ACCESS,
        NFSPROC4_CLNT_GETATTR,
        NFSPROC4_CLNT_LOOKUP,
+       NFSPROC4_CLNT_LOOKUPP,
        NFSPROC4_CLNT_LOOKUP_ROOT,
        NFSPROC4_CLNT_REMOVE,
        NFSPROC4_CLNT_RENAME,
index 89093341f0761eeda2281603b8e9f48d5276c587..ca3bcc4ed4e55563ecd505fada0cc0dc1f5dbb8d 100644 (file)
@@ -1012,7 +1012,6 @@ struct nfs4_link_res {
        struct nfs_fattr *              dir_attr;
 };
 
-
 struct nfs4_lookup_arg {
        struct nfs4_sequence_args       seq_args;
        const struct nfs_fh *           dir_fh;
@@ -1028,6 +1027,20 @@ struct nfs4_lookup_res {
        struct nfs4_label               *label;
 };
 
+struct nfs4_lookupp_arg {
+       struct nfs4_sequence_args       seq_args;
+       const struct nfs_fh             *fh;
+       const u32                       *bitmask;
+};
+
+struct nfs4_lookupp_res {
+       struct nfs4_sequence_res        seq_res;
+       const struct nfs_server         *server;
+       struct nfs_fattr                *fattr;
+       struct nfs_fh                   *fh;
+       struct nfs4_label               *label;
+};
+
 struct nfs4_lookup_root_arg {
        struct nfs4_sequence_args       seq_args;
        const u32 *                     bitmask;
@@ -1569,6 +1582,8 @@ struct nfs_rpc_ops {
        int     (*lookup)  (struct inode *, const struct qstr *,
                            struct nfs_fh *, struct nfs_fattr *,
                            struct nfs4_label *);
+       int     (*lookupp) (struct inode *, struct nfs_fh *,
+                           struct nfs_fattr *, struct nfs4_label *);
        int     (*access)  (struct inode *, struct nfs_access_entry *);
        int     (*readlink)(struct inode *, struct page *, unsigned int,
                            unsigned int);