aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4proc.c48
-rw-r--r--fs/nfs/nfs4xdr.c131
-rw-r--r--fs/nfs/pnfs.h12
-rw-r--r--include/linux/nfs4.h1
-rw-r--r--include/linux/nfs_xdr.h11
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 */
5840static 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
5865int 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}
5883EXPORT_SYMBOL_GPL(nfs4_proc_getdevicelist);
5884
5837static int 5885static 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
1857static void 1876static void
1877encode_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
1896static void
1858encode_getdeviceinfo(struct xdr_stream *xdr, 1897encode_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 */
2819static 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 */
2780static void nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req, 2837static 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 */
5331static 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;
5371out_overflow:
5372 print_overflow_msg(__func__, xdr);
5373 return -EIO;
5374}
5271 5375
5272static int decode_getdeviceinfo(struct xdr_stream *xdr, 5376static 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 */
6651static 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);
6670out:
6671 return status;
6672}
6673
6674/*
6545 * Decode GETDEVINFO response 6675 * Decode GETDEVINFO response
6546 */ 6676 */
6547static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp, 6677static 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
145struct pnfs_devicelist {
146 unsigned int eof;
147 unsigned int num_devs;
148 struct nfs4_deviceid dev_id[NFS4_PNFS_GETDEVLIST_MAXNUM];
149};
150
142extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *); 151extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *);
143extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *); 152extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);
144 153
145/* nfs4proc.c */ 154/* nfs4proc.c */
155extern int nfs4_proc_getdevicelist(struct nfs_server *server,
156 const struct nfs_fh *fh,
157 struct pnfs_devicelist *devlist);
146extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, 158extern int nfs4_proc_getdeviceinfo(struct nfs_server *server,
147 struct pnfs_device *dev); 159 struct pnfs_device *dev);
148extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp); 160extern 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
238struct nfs4_getdevicelist_args {
239 const struct nfs_fh *fh;
240 u32 layoutclass;
241 struct nfs4_sequence_args seq_args;
242};
243
244struct nfs4_getdevicelist_res {
245 struct pnfs_devicelist *devlist;
246 struct nfs4_sequence_res seq_res;
247};
248
238struct nfs4_getdeviceinfo_args { 249struct 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;