diff options
-rw-r--r-- | fs/nfs/nfs4proc.c | 48 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 131 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 12 | ||||
-rw-r--r-- | include/linux/nfs4.h | 1 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 11 |
5 files changed, 203 insertions, 0 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index efa6ae822ca8..af32d3df0544 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -5834,6 +5834,54 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp) | |||
5834 | return status; | 5834 | return status; |
5835 | } | 5835 | } |
5836 | 5836 | ||
5837 | /* | ||
5838 | * Retrieve the list of Data Server devices from the MDS. | ||
5839 | */ | ||
5840 | static int _nfs4_getdevicelist(struct nfs_server *server, | ||
5841 | const struct nfs_fh *fh, | ||
5842 | struct pnfs_devicelist *devlist) | ||
5843 | { | ||
5844 | struct nfs4_getdevicelist_args args = { | ||
5845 | .fh = fh, | ||
5846 | .layoutclass = server->pnfs_curr_ld->id, | ||
5847 | }; | ||
5848 | struct nfs4_getdevicelist_res res = { | ||
5849 | .devlist = devlist, | ||
5850 | }; | ||
5851 | struct rpc_message msg = { | ||
5852 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICELIST], | ||
5853 | .rpc_argp = &args, | ||
5854 | .rpc_resp = &res, | ||
5855 | }; | ||
5856 | int status; | ||
5857 | |||
5858 | dprintk("--> %s\n", __func__); | ||
5859 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, | ||
5860 | &res.seq_res, 0); | ||
5861 | dprintk("<-- %s status=%d\n", __func__, status); | ||
5862 | return status; | ||
5863 | } | ||
5864 | |||
5865 | int nfs4_proc_getdevicelist(struct nfs_server *server, | ||
5866 | const struct nfs_fh *fh, | ||
5867 | struct pnfs_devicelist *devlist) | ||
5868 | { | ||
5869 | struct nfs4_exception exception = { }; | ||
5870 | int err; | ||
5871 | |||
5872 | do { | ||
5873 | err = nfs4_handle_exception(server, | ||
5874 | _nfs4_getdevicelist(server, fh, devlist), | ||
5875 | &exception); | ||
5876 | } while (exception.retry); | ||
5877 | |||
5878 | dprintk("%s: err=%d, num_devs=%u\n", __func__, | ||
5879 | err, devlist->num_devs); | ||
5880 | |||
5881 | return err; | ||
5882 | } | ||
5883 | EXPORT_SYMBOL_GPL(nfs4_proc_getdevicelist); | ||
5884 | |||
5837 | static int | 5885 | static int |
5838 | _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) | 5886 | _nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev) |
5839 | { | 5887 | { |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index b851b560a6f8..5f769f8d05b0 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -314,6 +314,17 @@ static int nfs4_stat_to_errno(int); | |||
314 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) | 314 | XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) |
315 | #define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4) | 315 | #define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4) |
316 | #define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4) | 316 | #define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4) |
317 | #define encode_getdevicelist_maxsz (op_encode_hdr_maxsz + 4 + \ | ||
318 | encode_verifier_maxsz) | ||
319 | #define decode_getdevicelist_maxsz (op_decode_hdr_maxsz + \ | ||
320 | 2 /* nfs_cookie4 gdlr_cookie */ + \ | ||
321 | decode_verifier_maxsz \ | ||
322 | /* verifier4 gdlr_verifier */ + \ | ||
323 | 1 /* gdlr_deviceid_list count */ + \ | ||
324 | XDR_QUADLEN(NFS4_PNFS_GETDEVLIST_MAXNUM * \ | ||
325 | NFS4_DEVICEID4_SIZE) \ | ||
326 | /* gdlr_deviceid_list */ + \ | ||
327 | 1 /* bool gdlr_eof */) | ||
317 | #define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + 4 + \ | 328 | #define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + 4 + \ |
318 | XDR_QUADLEN(NFS4_DEVICEID4_SIZE)) | 329 | XDR_QUADLEN(NFS4_DEVICEID4_SIZE)) |
319 | #define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \ | 330 | #define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \ |
@@ -748,6 +759,14 @@ static int nfs4_stat_to_errno(int); | |||
748 | #define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \ | 759 | #define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \ |
749 | decode_sequence_maxsz + \ | 760 | decode_sequence_maxsz + \ |
750 | decode_reclaim_complete_maxsz) | 761 | decode_reclaim_complete_maxsz) |
762 | #define NFS4_enc_getdevicelist_sz (compound_encode_hdr_maxsz + \ | ||
763 | encode_sequence_maxsz + \ | ||
764 | encode_putfh_maxsz + \ | ||
765 | encode_getdevicelist_maxsz) | ||
766 | #define NFS4_dec_getdevicelist_sz (compound_decode_hdr_maxsz + \ | ||
767 | decode_sequence_maxsz + \ | ||
768 | decode_putfh_maxsz + \ | ||
769 | decode_getdevicelist_maxsz) | ||
751 | #define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz + \ | 770 | #define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz + \ |
752 | encode_sequence_maxsz +\ | 771 | encode_sequence_maxsz +\ |
753 | encode_getdeviceinfo_maxsz) | 772 | encode_getdeviceinfo_maxsz) |
@@ -1855,6 +1874,26 @@ static void encode_sequence(struct xdr_stream *xdr, | |||
1855 | 1874 | ||
1856 | #ifdef CONFIG_NFS_V4_1 | 1875 | #ifdef CONFIG_NFS_V4_1 |
1857 | static void | 1876 | static void |
1877 | encode_getdevicelist(struct xdr_stream *xdr, | ||
1878 | const struct nfs4_getdevicelist_args *args, | ||
1879 | struct compound_hdr *hdr) | ||
1880 | { | ||
1881 | __be32 *p; | ||
1882 | nfs4_verifier dummy = { | ||
1883 | .data = "dummmmmy", | ||
1884 | }; | ||
1885 | |||
1886 | p = reserve_space(xdr, 20); | ||
1887 | *p++ = cpu_to_be32(OP_GETDEVICELIST); | ||
1888 | *p++ = cpu_to_be32(args->layoutclass); | ||
1889 | *p++ = cpu_to_be32(NFS4_PNFS_GETDEVLIST_MAXNUM); | ||
1890 | xdr_encode_hyper(p, 0ULL); /* cookie */ | ||
1891 | encode_nfs4_verifier(xdr, &dummy); | ||
1892 | hdr->nops++; | ||
1893 | hdr->replen += decode_getdevicelist_maxsz; | ||
1894 | } | ||
1895 | |||
1896 | static void | ||
1858 | encode_getdeviceinfo(struct xdr_stream *xdr, | 1897 | encode_getdeviceinfo(struct xdr_stream *xdr, |
1859 | const struct nfs4_getdeviceinfo_args *args, | 1898 | const struct nfs4_getdeviceinfo_args *args, |
1860 | struct compound_hdr *hdr) | 1899 | struct compound_hdr *hdr) |
@@ -2775,6 +2814,24 @@ static void nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req, | |||
2775 | } | 2814 | } |
2776 | 2815 | ||
2777 | /* | 2816 | /* |
2817 | * Encode GETDEVICELIST request | ||
2818 | */ | ||
2819 | static void nfs4_xdr_enc_getdevicelist(struct rpc_rqst *req, | ||
2820 | struct xdr_stream *xdr, | ||
2821 | struct nfs4_getdevicelist_args *args) | ||
2822 | { | ||
2823 | struct compound_hdr hdr = { | ||
2824 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | ||
2825 | }; | ||
2826 | |||
2827 | encode_compound_hdr(xdr, req, &hdr); | ||
2828 | encode_sequence(xdr, &args->seq_args, &hdr); | ||
2829 | encode_putfh(xdr, args->fh, &hdr); | ||
2830 | encode_getdevicelist(xdr, args, &hdr); | ||
2831 | encode_nops(&hdr); | ||
2832 | } | ||
2833 | |||
2834 | /* | ||
2778 | * Encode GETDEVICEINFO request | 2835 | * Encode GETDEVICEINFO request |
2779 | */ | 2836 | */ |
2780 | static void nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req, | 2837 | static void nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req, |
@@ -5268,6 +5325,53 @@ out_overflow: | |||
5268 | } | 5325 | } |
5269 | 5326 | ||
5270 | #if defined(CONFIG_NFS_V4_1) | 5327 | #if defined(CONFIG_NFS_V4_1) |
5328 | /* | ||
5329 | * TODO: Need to handle case when EOF != true; | ||
5330 | */ | ||
5331 | static int decode_getdevicelist(struct xdr_stream *xdr, | ||
5332 | struct pnfs_devicelist *res) | ||
5333 | { | ||
5334 | __be32 *p; | ||
5335 | int status, i; | ||
5336 | struct nfs_writeverf verftemp; | ||
5337 | |||
5338 | status = decode_op_hdr(xdr, OP_GETDEVICELIST); | ||
5339 | if (status) | ||
5340 | return status; | ||
5341 | |||
5342 | p = xdr_inline_decode(xdr, 8 + 8 + 4); | ||
5343 | if (unlikely(!p)) | ||
5344 | goto out_overflow; | ||
5345 | |||
5346 | /* TODO: Skip cookie for now */ | ||
5347 | p += 2; | ||
5348 | |||
5349 | /* Read verifier */ | ||
5350 | p = xdr_decode_opaque_fixed(p, verftemp.verifier, 8); | ||
5351 | |||
5352 | res->num_devs = be32_to_cpup(p); | ||
5353 | |||
5354 | dprintk("%s: num_dev %d\n", __func__, res->num_devs); | ||
5355 | |||
5356 | if (res->num_devs > NFS4_PNFS_GETDEVLIST_MAXNUM) { | ||
5357 | printk(KERN_ERR "%s too many result dev_num %u\n", | ||
5358 | __func__, res->num_devs); | ||
5359 | return -EIO; | ||
5360 | } | ||
5361 | |||
5362 | p = xdr_inline_decode(xdr, | ||
5363 | res->num_devs * NFS4_DEVICEID4_SIZE + 4); | ||
5364 | if (unlikely(!p)) | ||
5365 | goto out_overflow; | ||
5366 | for (i = 0; i < res->num_devs; i++) | ||
5367 | p = xdr_decode_opaque_fixed(p, res->dev_id[i].data, | ||
5368 | NFS4_DEVICEID4_SIZE); | ||
5369 | res->eof = be32_to_cpup(p); | ||
5370 | return 0; | ||
5371 | out_overflow: | ||
5372 | print_overflow_msg(__func__, xdr); | ||
5373 | return -EIO; | ||
5374 | } | ||
5271 | 5375 | ||
5272 | static int decode_getdeviceinfo(struct xdr_stream *xdr, | 5376 | static int decode_getdeviceinfo(struct xdr_stream *xdr, |
5273 | struct pnfs_device *pdev) | 5377 | struct pnfs_device *pdev) |
@@ -6542,6 +6646,32 @@ static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, | |||
6542 | } | 6646 | } |
6543 | 6647 | ||
6544 | /* | 6648 | /* |
6649 | * Decode GETDEVICELIST response | ||
6650 | */ | ||
6651 | static int nfs4_xdr_dec_getdevicelist(struct rpc_rqst *rqstp, | ||
6652 | struct xdr_stream *xdr, | ||
6653 | struct nfs4_getdevicelist_res *res) | ||
6654 | { | ||
6655 | struct compound_hdr hdr; | ||
6656 | int status; | ||
6657 | |||
6658 | dprintk("encoding getdevicelist!\n"); | ||
6659 | |||
6660 | status = decode_compound_hdr(xdr, &hdr); | ||
6661 | if (status != 0) | ||
6662 | goto out; | ||
6663 | status = decode_sequence(xdr, &res->seq_res, rqstp); | ||
6664 | if (status != 0) | ||
6665 | goto out; | ||
6666 | status = decode_putfh(xdr); | ||
6667 | if (status != 0) | ||
6668 | goto out; | ||
6669 | status = decode_getdevicelist(xdr, res->devlist); | ||
6670 | out: | ||
6671 | return status; | ||
6672 | } | ||
6673 | |||
6674 | /* | ||
6545 | * Decode GETDEVINFO response | 6675 | * Decode GETDEVINFO response |
6546 | */ | 6676 | */ |
6547 | static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp, | 6677 | static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp, |
@@ -6908,6 +7038,7 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
6908 | PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name), | 7038 | PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name), |
6909 | PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid), | 7039 | PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid), |
6910 | PROC(FREE_STATEID, enc_free_stateid, dec_free_stateid), | 7040 | PROC(FREE_STATEID, enc_free_stateid, dec_free_stateid), |
7041 | PROC(GETDEVICELIST, enc_getdevicelist, dec_getdevicelist), | ||
6911 | #endif /* CONFIG_NFS_V4_1 */ | 7042 | #endif /* CONFIG_NFS_V4_1 */ |
6912 | }; | 7043 | }; |
6913 | 7044 | ||
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index b94f874886ca..7074394944a9 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -135,14 +135,26 @@ struct pnfs_device { | |||
135 | unsigned int layout_type; | 135 | unsigned int layout_type; |
136 | unsigned int mincount; | 136 | unsigned int mincount; |
137 | struct page **pages; | 137 | struct page **pages; |
138 | void *area; | ||
138 | unsigned int pgbase; | 139 | unsigned int pgbase; |
139 | unsigned int pglen; | 140 | unsigned int pglen; |
140 | }; | 141 | }; |
141 | 142 | ||
143 | #define NFS4_PNFS_GETDEVLIST_MAXNUM 16 | ||
144 | |||
145 | struct pnfs_devicelist { | ||
146 | unsigned int eof; | ||
147 | unsigned int num_devs; | ||
148 | struct nfs4_deviceid dev_id[NFS4_PNFS_GETDEVLIST_MAXNUM]; | ||
149 | }; | ||
150 | |||
142 | extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *); | 151 | extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *); |
143 | extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *); | 152 | extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *); |
144 | 153 | ||
145 | /* nfs4proc.c */ | 154 | /* nfs4proc.c */ |
155 | extern int nfs4_proc_getdevicelist(struct nfs_server *server, | ||
156 | const struct nfs_fh *fh, | ||
157 | struct pnfs_devicelist *devlist); | ||
146 | extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, | 158 | extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, |
147 | struct pnfs_device *dev); | 159 | struct pnfs_device *dev); |
148 | extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp); | 160 | extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp); |
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index a3c4bc800dce..76f99e8714f3 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h | |||
@@ -566,6 +566,7 @@ enum { | |||
566 | NFSPROC4_CLNT_SECINFO_NO_NAME, | 566 | NFSPROC4_CLNT_SECINFO_NO_NAME, |
567 | NFSPROC4_CLNT_TEST_STATEID, | 567 | NFSPROC4_CLNT_TEST_STATEID, |
568 | NFSPROC4_CLNT_FREE_STATEID, | 568 | NFSPROC4_CLNT_FREE_STATEID, |
569 | NFSPROC4_CLNT_GETDEVICELIST, | ||
569 | }; | 570 | }; |
570 | 571 | ||
571 | /* nfs41 types */ | 572 | /* nfs41 types */ |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index feb312716c07..21f333eae3c8 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -235,6 +235,17 @@ struct nfs4_layoutget { | |||
235 | gfp_t gfp_flags; | 235 | gfp_t gfp_flags; |
236 | }; | 236 | }; |
237 | 237 | ||
238 | struct nfs4_getdevicelist_args { | ||
239 | const struct nfs_fh *fh; | ||
240 | u32 layoutclass; | ||
241 | struct nfs4_sequence_args seq_args; | ||
242 | }; | ||
243 | |||
244 | struct nfs4_getdevicelist_res { | ||
245 | struct pnfs_devicelist *devlist; | ||
246 | struct nfs4_sequence_res seq_res; | ||
247 | }; | ||
248 | |||
238 | struct nfs4_getdeviceinfo_args { | 249 | struct nfs4_getdeviceinfo_args { |
239 | struct pnfs_device *pdev; | 250 | struct pnfs_device *pdev; |
240 | struct nfs4_sequence_args seq_args; | 251 | struct nfs4_sequence_args seq_args; |