diff options
author | Jeff Layton <jeff.layton@primarydata.com> | 2017-06-29 09:34:52 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2017-07-13 16:00:15 -0400 |
commit | 5b5faaf6df73412af0278997db36dbcb51011d9d (patch) | |
tree | 62c1824135b12d6d393b853c07717c718e8f01b3 | |
parent | f174ff7a0ab6a097455a94abfc99517940041c07 (diff) |
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>
-rw-r--r-- | fs/nfs/nfs4proc.c | 49 | ||||
-rw-r--r-- | fs/nfs/nfs4trace.h | 29 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 75 | ||||
-rw-r--r-- | include/linux/nfs4.h | 1 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 17 |
5 files changed, 170 insertions, 1 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, | |||
3805 | return (client == NFS_CLIENT(dir)) ? rpc_clone_client(client) : client; | 3805 | return (client == NFS_CLIENT(dir)) ? rpc_clone_client(client) : client; |
3806 | } | 3806 | } |
3807 | 3807 | ||
3808 | static int _nfs4_proc_lookupp(struct inode *inode, | ||
3809 | struct nfs_fh *fhandle, struct nfs_fattr *fattr, | ||
3810 | struct nfs4_label *label) | ||
3811 | { | ||
3812 | struct rpc_clnt *clnt = NFS_CLIENT(inode); | ||
3813 | struct nfs_server *server = NFS_SERVER(inode); | ||
3814 | int status; | ||
3815 | struct nfs4_lookupp_arg args = { | ||
3816 | .bitmask = server->attr_bitmask, | ||
3817 | .fh = NFS_FH(inode), | ||
3818 | }; | ||
3819 | struct nfs4_lookupp_res res = { | ||
3820 | .server = server, | ||
3821 | .fattr = fattr, | ||
3822 | .label = label, | ||
3823 | .fh = fhandle, | ||
3824 | }; | ||
3825 | struct rpc_message msg = { | ||
3826 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUPP], | ||
3827 | .rpc_argp = &args, | ||
3828 | .rpc_resp = &res, | ||
3829 | }; | ||
3830 | |||
3831 | args.bitmask = nfs4_bitmask(server, label); | ||
3832 | |||
3833 | nfs_fattr_init(fattr); | ||
3834 | |||
3835 | dprintk("NFS call lookupp ino=0x%lx\n", inode->i_ino); | ||
3836 | status = nfs4_call_sync(clnt, server, &msg, &args.seq_args, | ||
3837 | &res.seq_res, 0); | ||
3838 | dprintk("NFS reply lookupp: %d\n", status); | ||
3839 | return status; | ||
3840 | } | ||
3841 | |||
3842 | static int nfs4_proc_lookupp(struct inode *inode, struct nfs_fh *fhandle, | ||
3843 | struct nfs_fattr *fattr, struct nfs4_label *label) | ||
3844 | { | ||
3845 | struct nfs4_exception exception = { }; | ||
3846 | int err; | ||
3847 | do { | ||
3848 | err = _nfs4_proc_lookupp(inode, fhandle, fattr, label); | ||
3849 | trace_nfs4_lookupp(inode, err); | ||
3850 | err = nfs4_handle_exception(NFS_SERVER(inode), err, | ||
3851 | &exception); | ||
3852 | } while (exception.retry); | ||
3853 | return err; | ||
3854 | } | ||
3855 | |||
3808 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) | 3856 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) |
3809 | { | 3857 | { |
3810 | struct nfs_server *server = NFS_SERVER(inode); | 3858 | struct nfs_server *server = NFS_SERVER(inode); |
@@ -9314,6 +9362,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = { | |||
9314 | .getattr = nfs4_proc_getattr, | 9362 | .getattr = nfs4_proc_getattr, |
9315 | .setattr = nfs4_proc_setattr, | 9363 | .setattr = nfs4_proc_setattr, |
9316 | .lookup = nfs4_proc_lookup, | 9364 | .lookup = nfs4_proc_lookup, |
9365 | .lookupp = nfs4_proc_lookupp, | ||
9317 | .access = nfs4_proc_access, | 9366 | .access = nfs4_proc_access, |
9318 | .readlink = nfs4_proc_readlink, | 9367 | .readlink = nfs4_proc_readlink, |
9319 | .create = nfs4_proc_create, | 9368 | .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); | |||
891 | DEFINE_NFS4_LOOKUP_EVENT(nfs4_get_fs_locations); | 891 | DEFINE_NFS4_LOOKUP_EVENT(nfs4_get_fs_locations); |
892 | DEFINE_NFS4_LOOKUP_EVENT(nfs4_secinfo); | 892 | DEFINE_NFS4_LOOKUP_EVENT(nfs4_secinfo); |
893 | 893 | ||
894 | TRACE_EVENT(nfs4_lookupp, | ||
895 | TP_PROTO( | ||
896 | const struct inode *inode, | ||
897 | int error | ||
898 | ), | ||
899 | |||
900 | TP_ARGS(inode, error), | ||
901 | |||
902 | TP_STRUCT__entry( | ||
903 | __field(dev_t, dev) | ||
904 | __field(u64, ino) | ||
905 | __field(int, error) | ||
906 | ), | ||
907 | |||
908 | TP_fast_assign( | ||
909 | __entry->dev = inode->i_sb->s_dev; | ||
910 | __entry->ino = NFS_FILEID(inode); | ||
911 | __entry->error = error; | ||
912 | ), | ||
913 | |||
914 | TP_printk( | ||
915 | "error=%d (%s) inode=%02x:%02x:%llu", | ||
916 | __entry->error, | ||
917 | show_nfsv4_errors(__entry->error), | ||
918 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
919 | (unsigned long long)__entry->ino | ||
920 | ) | ||
921 | ); | ||
922 | |||
894 | TRACE_EVENT(nfs4_rename, | 923 | TRACE_EVENT(nfs4_rename, |
895 | TP_PROTO( | 924 | TP_PROTO( |
896 | const struct inode *olddir, | 925 | 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); | |||
159 | (op_decode_hdr_maxsz) | 159 | (op_decode_hdr_maxsz) |
160 | #define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) | 160 | #define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) |
161 | #define decode_lookup_maxsz (op_decode_hdr_maxsz) | 161 | #define decode_lookup_maxsz (op_decode_hdr_maxsz) |
162 | #define encode_lookupp_maxsz (op_encode_hdr_maxsz) | ||
163 | #define decode_lookupp_maxsz (op_decode_hdr_maxsz) | ||
162 | #define encode_share_access_maxsz \ | 164 | #define encode_share_access_maxsz \ |
163 | (2) | 165 | (2) |
164 | #define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz) | 166 | #define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz) |
@@ -618,6 +620,18 @@ static int nfs4_stat_to_errno(int); | |||
618 | decode_lookup_maxsz + \ | 620 | decode_lookup_maxsz + \ |
619 | decode_getattr_maxsz + \ | 621 | decode_getattr_maxsz + \ |
620 | decode_getfh_maxsz) | 622 | decode_getfh_maxsz) |
623 | #define NFS4_enc_lookupp_sz (compound_encode_hdr_maxsz + \ | ||
624 | encode_sequence_maxsz + \ | ||
625 | encode_putfh_maxsz + \ | ||
626 | encode_lookupp_maxsz + \ | ||
627 | encode_getattr_maxsz + \ | ||
628 | encode_getfh_maxsz) | ||
629 | #define NFS4_dec_lookupp_sz (compound_decode_hdr_maxsz + \ | ||
630 | decode_sequence_maxsz + \ | ||
631 | decode_putfh_maxsz + \ | ||
632 | decode_lookupp_maxsz + \ | ||
633 | decode_getattr_maxsz + \ | ||
634 | decode_getfh_maxsz) | ||
621 | #define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \ | 635 | #define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \ |
622 | encode_sequence_maxsz + \ | 636 | encode_sequence_maxsz + \ |
623 | encode_putrootfh_maxsz + \ | 637 | encode_putrootfh_maxsz + \ |
@@ -1368,6 +1382,11 @@ static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struc | |||
1368 | encode_string(xdr, name->len, name->name); | 1382 | encode_string(xdr, name->len, name->name); |
1369 | } | 1383 | } |
1370 | 1384 | ||
1385 | static void encode_lookupp(struct xdr_stream *xdr, struct compound_hdr *hdr) | ||
1386 | { | ||
1387 | encode_op_hdr(xdr, OP_LOOKUPP, decode_lookupp_maxsz, hdr); | ||
1388 | } | ||
1389 | |||
1371 | static void encode_share_access(struct xdr_stream *xdr, u32 share_access) | 1390 | static void encode_share_access(struct xdr_stream *xdr, u32 share_access) |
1372 | { | 1391 | { |
1373 | __be32 *p; | 1392 | __be32 *p; |
@@ -2123,6 +2142,26 @@ static void nfs4_xdr_enc_lookup(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
2123 | } | 2142 | } |
2124 | 2143 | ||
2125 | /* | 2144 | /* |
2145 | * Encode LOOKUPP request | ||
2146 | */ | ||
2147 | static void nfs4_xdr_enc_lookupp(struct rpc_rqst *req, struct xdr_stream *xdr, | ||
2148 | const void *data) | ||
2149 | { | ||
2150 | const struct nfs4_lookupp_arg *args = data; | ||
2151 | struct compound_hdr hdr = { | ||
2152 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | ||
2153 | }; | ||
2154 | |||
2155 | encode_compound_hdr(xdr, req, &hdr); | ||
2156 | encode_sequence(xdr, &args->seq_args, &hdr); | ||
2157 | encode_putfh(xdr, args->fh, &hdr); | ||
2158 | encode_lookupp(xdr, &hdr); | ||
2159 | encode_getfh(xdr, &hdr); | ||
2160 | encode_getfattr(xdr, args->bitmask, &hdr); | ||
2161 | encode_nops(&hdr); | ||
2162 | } | ||
2163 | |||
2164 | /* | ||
2126 | * Encode LOOKUP_ROOT request | 2165 | * Encode LOOKUP_ROOT request |
2127 | */ | 2166 | */ |
2128 | static void nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, | 2167 | static void nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, |
@@ -5058,6 +5097,11 @@ static int decode_lookup(struct xdr_stream *xdr) | |||
5058 | return decode_op_hdr(xdr, OP_LOOKUP); | 5097 | return decode_op_hdr(xdr, OP_LOOKUP); |
5059 | } | 5098 | } |
5060 | 5099 | ||
5100 | static int decode_lookupp(struct xdr_stream *xdr) | ||
5101 | { | ||
5102 | return decode_op_hdr(xdr, OP_LOOKUPP); | ||
5103 | } | ||
5104 | |||
5061 | /* This is too sick! */ | 5105 | /* This is too sick! */ |
5062 | static int decode_space_limit(struct xdr_stream *xdr, | 5106 | static int decode_space_limit(struct xdr_stream *xdr, |
5063 | unsigned long *pagemod_limit) | 5107 | unsigned long *pagemod_limit) |
@@ -6238,6 +6282,36 @@ out: | |||
6238 | } | 6282 | } |
6239 | 6283 | ||
6240 | /* | 6284 | /* |
6285 | * Decode LOOKUPP response | ||
6286 | */ | ||
6287 | static int nfs4_xdr_dec_lookupp(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | ||
6288 | void *data) | ||
6289 | { | ||
6290 | struct nfs4_lookupp_res *res = data; | ||
6291 | struct compound_hdr hdr; | ||
6292 | int status; | ||
6293 | |||
6294 | status = decode_compound_hdr(xdr, &hdr); | ||
6295 | if (status) | ||
6296 | goto out; | ||
6297 | status = decode_sequence(xdr, &res->seq_res, rqstp); | ||
6298 | if (status) | ||
6299 | goto out; | ||
6300 | status = decode_putfh(xdr); | ||
6301 | if (status) | ||
6302 | goto out; | ||
6303 | status = decode_lookupp(xdr); | ||
6304 | if (status) | ||
6305 | goto out; | ||
6306 | status = decode_getfh(xdr, res->fh); | ||
6307 | if (status) | ||
6308 | goto out; | ||
6309 | status = decode_getfattr_label(xdr, res->fattr, res->label, res->server); | ||
6310 | out: | ||
6311 | return status; | ||
6312 | } | ||
6313 | |||
6314 | /* | ||
6241 | * Decode LOOKUP_ROOT response | 6315 | * Decode LOOKUP_ROOT response |
6242 | */ | 6316 | */ |
6243 | static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, | 6317 | static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, |
@@ -7614,6 +7688,7 @@ const struct rpc_procinfo nfs4_procedures[] = { | |||
7614 | PROC(ACCESS, enc_access, dec_access), | 7688 | PROC(ACCESS, enc_access, dec_access), |
7615 | PROC(GETATTR, enc_getattr, dec_getattr), | 7689 | PROC(GETATTR, enc_getattr, dec_getattr), |
7616 | PROC(LOOKUP, enc_lookup, dec_lookup), | 7690 | PROC(LOOKUP, enc_lookup, dec_lookup), |
7691 | PROC(LOOKUPP, enc_lookupp, dec_lookupp), | ||
7617 | PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root), | 7692 | PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root), |
7618 | PROC(REMOVE, enc_remove, dec_remove), | 7693 | PROC(REMOVE, enc_remove, dec_remove), |
7619 | PROC(RENAME, enc_rename, dec_rename), | 7694 | PROC(RENAME, enc_rename, dec_rename), |
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index 1b1ca04820a3..47239c336688 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h | |||
@@ -479,6 +479,7 @@ enum { | |||
479 | NFSPROC4_CLNT_ACCESS, | 479 | NFSPROC4_CLNT_ACCESS, |
480 | NFSPROC4_CLNT_GETATTR, | 480 | NFSPROC4_CLNT_GETATTR, |
481 | NFSPROC4_CLNT_LOOKUP, | 481 | NFSPROC4_CLNT_LOOKUP, |
482 | NFSPROC4_CLNT_LOOKUPP, | ||
482 | NFSPROC4_CLNT_LOOKUP_ROOT, | 483 | NFSPROC4_CLNT_LOOKUP_ROOT, |
483 | NFSPROC4_CLNT_REMOVE, | 484 | NFSPROC4_CLNT_REMOVE, |
484 | NFSPROC4_CLNT_RENAME, | 485 | NFSPROC4_CLNT_RENAME, |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 89093341f076..ca3bcc4ed4e5 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -1012,7 +1012,6 @@ struct nfs4_link_res { | |||
1012 | struct nfs_fattr * dir_attr; | 1012 | struct nfs_fattr * dir_attr; |
1013 | }; | 1013 | }; |
1014 | 1014 | ||
1015 | |||
1016 | struct nfs4_lookup_arg { | 1015 | struct nfs4_lookup_arg { |
1017 | struct nfs4_sequence_args seq_args; | 1016 | struct nfs4_sequence_args seq_args; |
1018 | const struct nfs_fh * dir_fh; | 1017 | const struct nfs_fh * dir_fh; |
@@ -1028,6 +1027,20 @@ struct nfs4_lookup_res { | |||
1028 | struct nfs4_label *label; | 1027 | struct nfs4_label *label; |
1029 | }; | 1028 | }; |
1030 | 1029 | ||
1030 | struct nfs4_lookupp_arg { | ||
1031 | struct nfs4_sequence_args seq_args; | ||
1032 | const struct nfs_fh *fh; | ||
1033 | const u32 *bitmask; | ||
1034 | }; | ||
1035 | |||
1036 | struct nfs4_lookupp_res { | ||
1037 | struct nfs4_sequence_res seq_res; | ||
1038 | const struct nfs_server *server; | ||
1039 | struct nfs_fattr *fattr; | ||
1040 | struct nfs_fh *fh; | ||
1041 | struct nfs4_label *label; | ||
1042 | }; | ||
1043 | |||
1031 | struct nfs4_lookup_root_arg { | 1044 | struct nfs4_lookup_root_arg { |
1032 | struct nfs4_sequence_args seq_args; | 1045 | struct nfs4_sequence_args seq_args; |
1033 | const u32 * bitmask; | 1046 | const u32 * bitmask; |
@@ -1569,6 +1582,8 @@ struct nfs_rpc_ops { | |||
1569 | int (*lookup) (struct inode *, const struct qstr *, | 1582 | int (*lookup) (struct inode *, const struct qstr *, |
1570 | struct nfs_fh *, struct nfs_fattr *, | 1583 | struct nfs_fh *, struct nfs_fattr *, |
1571 | struct nfs4_label *); | 1584 | struct nfs4_label *); |
1585 | int (*lookupp) (struct inode *, struct nfs_fh *, | ||
1586 | struct nfs_fattr *, struct nfs4_label *); | ||
1572 | int (*access) (struct inode *, struct nfs_access_entry *); | 1587 | int (*access) (struct inode *, struct nfs_access_entry *); |
1573 | int (*readlink)(struct inode *, struct page *, unsigned int, | 1588 | int (*readlink)(struct inode *, struct page *, unsigned int, |
1574 | unsigned int); | 1589 | unsigned int); |