diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/filelayout/filelayout.c | 29 | ||||
-rw-r--r-- | fs/nfs/filelayout/filelayout.h | 7 | ||||
-rw-r--r-- | fs/nfs/filelayout/filelayoutdev.c | 108 | ||||
-rw-r--r-- | fs/nfs/objlayout/objio_osd.c | 113 | ||||
-rw-r--r-- | fs/nfs/objlayout/objlayout.c | 70 | ||||
-rw-r--r-- | fs/nfs/objlayout/objlayout.h | 5 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 13 | ||||
-rw-r--r-- | fs/nfs/pnfs_dev.c | 149 |
8 files changed, 182 insertions, 312 deletions
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c index 163cad1d4127..abc5056999d6 100644 --- a/fs/nfs/filelayout/filelayout.c +++ b/fs/nfs/filelayout/filelayout.c | |||
@@ -649,18 +649,15 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo, | |||
649 | } | 649 | } |
650 | 650 | ||
651 | /* find and reference the deviceid */ | 651 | /* find and reference the deviceid */ |
652 | d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode)->pnfs_curr_ld, | 652 | d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), id, |
653 | NFS_SERVER(lo->plh_inode)->nfs_client, id); | 653 | lo->plh_lc_cred, gfp_flags); |
654 | if (d == NULL) { | 654 | if (d == NULL) |
655 | dsaddr = filelayout_get_device_info(lo->plh_inode, id, | 655 | goto out; |
656 | lo->plh_lc_cred, gfp_flags); | 656 | |
657 | if (dsaddr == NULL) | 657 | dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node); |
658 | goto out; | ||
659 | } else | ||
660 | dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node); | ||
661 | /* Found deviceid is unavailable */ | 658 | /* Found deviceid is unavailable */ |
662 | if (filelayout_test_devid_unavailable(&dsaddr->id_node)) | 659 | if (filelayout_test_devid_unavailable(&dsaddr->id_node)) |
663 | goto out_put; | 660 | goto out_put; |
664 | 661 | ||
665 | fl->dsaddr = dsaddr; | 662 | fl->dsaddr = dsaddr; |
666 | 663 | ||
@@ -1371,6 +1368,17 @@ out: | |||
1371 | cinfo->ds->ncommitting = 0; | 1368 | cinfo->ds->ncommitting = 0; |
1372 | return PNFS_ATTEMPTED; | 1369 | return PNFS_ATTEMPTED; |
1373 | } | 1370 | } |
1371 | static struct nfs4_deviceid_node * | ||
1372 | filelayout_alloc_deviceid_node(struct nfs_server *server, | ||
1373 | struct pnfs_device *pdev, gfp_t gfp_flags) | ||
1374 | { | ||
1375 | struct nfs4_file_layout_dsaddr *dsaddr; | ||
1376 | |||
1377 | dsaddr = nfs4_fl_alloc_deviceid_node(server, pdev, gfp_flags); | ||
1378 | if (!dsaddr) | ||
1379 | return NULL; | ||
1380 | return &dsaddr->id_node; | ||
1381 | } | ||
1374 | 1382 | ||
1375 | static void | 1383 | static void |
1376 | filelayout_free_deveiceid_node(struct nfs4_deviceid_node *d) | 1384 | filelayout_free_deveiceid_node(struct nfs4_deviceid_node *d) |
@@ -1423,6 +1431,7 @@ static struct pnfs_layoutdriver_type filelayout_type = { | |||
1423 | .commit_pagelist = filelayout_commit_pagelist, | 1431 | .commit_pagelist = filelayout_commit_pagelist, |
1424 | .read_pagelist = filelayout_read_pagelist, | 1432 | .read_pagelist = filelayout_read_pagelist, |
1425 | .write_pagelist = filelayout_write_pagelist, | 1433 | .write_pagelist = filelayout_write_pagelist, |
1434 | .alloc_deviceid_node = filelayout_alloc_deviceid_node, | ||
1426 | .free_deviceid_node = filelayout_free_deveiceid_node, | 1435 | .free_deviceid_node = filelayout_free_deveiceid_node, |
1427 | }; | 1436 | }; |
1428 | 1437 | ||
diff --git a/fs/nfs/filelayout/filelayout.h b/fs/nfs/filelayout/filelayout.h index ffbddf2219ea..7c9f800c49d7 100644 --- a/fs/nfs/filelayout/filelayout.h +++ b/fs/nfs/filelayout/filelayout.h | |||
@@ -147,10 +147,11 @@ u32 nfs4_fl_calc_j_index(struct pnfs_layout_segment *lseg, loff_t offset); | |||
147 | u32 nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j); | 147 | u32 nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j); |
148 | struct nfs4_pnfs_ds *nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, | 148 | struct nfs4_pnfs_ds *nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, |
149 | u32 ds_idx); | 149 | u32 ds_idx); |
150 | |||
151 | extern struct nfs4_file_layout_dsaddr * | ||
152 | nfs4_fl_alloc_deviceid_node(struct nfs_server *server, | ||
153 | struct pnfs_device *pdev, gfp_t gfp_flags); | ||
150 | extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); | 154 | extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); |
151 | extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); | 155 | extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); |
152 | struct nfs4_file_layout_dsaddr * | ||
153 | filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, | ||
154 | struct rpc_cred *cred, gfp_t gfp_flags); | ||
155 | 156 | ||
156 | #endif /* FS_NFS_NFS4FILELAYOUT_H */ | 157 | #endif /* FS_NFS_NFS4FILELAYOUT_H */ |
diff --git a/fs/nfs/filelayout/filelayoutdev.c b/fs/nfs/filelayout/filelayoutdev.c index 8540516f4d71..9bb806a76d99 100644 --- a/fs/nfs/filelayout/filelayoutdev.c +++ b/fs/nfs/filelayout/filelayoutdev.c | |||
@@ -484,8 +484,9 @@ out_err: | |||
484 | } | 484 | } |
485 | 485 | ||
486 | /* Decode opaque device data and return the result */ | 486 | /* Decode opaque device data and return the result */ |
487 | static struct nfs4_file_layout_dsaddr* | 487 | struct nfs4_file_layout_dsaddr * |
488 | decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags) | 488 | nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, |
489 | gfp_t gfp_flags) | ||
489 | { | 490 | { |
490 | int i; | 491 | int i; |
491 | u32 cnt, num; | 492 | u32 cnt, num; |
@@ -570,10 +571,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags) | |||
570 | dsaddr->stripe_indices = stripe_indices; | 571 | dsaddr->stripe_indices = stripe_indices; |
571 | stripe_indices = NULL; | 572 | stripe_indices = NULL; |
572 | dsaddr->ds_num = num; | 573 | dsaddr->ds_num = num; |
573 | nfs4_init_deviceid_node(&dsaddr->id_node, | 574 | nfs4_init_deviceid_node(&dsaddr->id_node, server, &pdev->dev_id); |
574 | NFS_SERVER(ino)->pnfs_curr_ld, | ||
575 | NFS_SERVER(ino)->nfs_client, | ||
576 | &pdev->dev_id); | ||
577 | 575 | ||
578 | INIT_LIST_HEAD(&dsaddrs); | 576 | INIT_LIST_HEAD(&dsaddrs); |
579 | 577 | ||
@@ -587,7 +585,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags) | |||
587 | 585 | ||
588 | mp_count = be32_to_cpup(p); /* multipath count */ | 586 | mp_count = be32_to_cpup(p); /* multipath count */ |
589 | for (j = 0; j < mp_count; j++) { | 587 | for (j = 0; j < mp_count; j++) { |
590 | da = decode_ds_addr(NFS_SERVER(ino)->nfs_client->cl_net, | 588 | da = decode_ds_addr(server->nfs_client->cl_net, |
591 | &stream, gfp_flags); | 589 | &stream, gfp_flags); |
592 | if (da) | 590 | if (da) |
593 | list_add_tail(&da->da_node, &dsaddrs); | 591 | list_add_tail(&da->da_node, &dsaddrs); |
@@ -637,102 +635,6 @@ out_err: | |||
637 | return NULL; | 635 | return NULL; |
638 | } | 636 | } |
639 | 637 | ||
640 | /* | ||
641 | * Decode the opaque device specified in 'dev' and add it to the cache of | ||
642 | * available devices. | ||
643 | */ | ||
644 | static struct nfs4_file_layout_dsaddr * | ||
645 | decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_flags) | ||
646 | { | ||
647 | struct nfs4_deviceid_node *d; | ||
648 | struct nfs4_file_layout_dsaddr *n, *new; | ||
649 | |||
650 | new = decode_device(inode, dev, gfp_flags); | ||
651 | if (!new) { | ||
652 | printk(KERN_WARNING "NFS: %s: Could not decode or add device\n", | ||
653 | __func__); | ||
654 | return NULL; | ||
655 | } | ||
656 | |||
657 | d = nfs4_insert_deviceid_node(&new->id_node); | ||
658 | n = container_of(d, struct nfs4_file_layout_dsaddr, id_node); | ||
659 | if (n != new) { | ||
660 | nfs4_fl_free_deviceid(new); | ||
661 | return n; | ||
662 | } | ||
663 | |||
664 | return new; | ||
665 | } | ||
666 | |||
667 | /* | ||
668 | * Retrieve the information for dev_id, add it to the list | ||
669 | * of available devices, and return it. | ||
670 | */ | ||
671 | struct nfs4_file_layout_dsaddr * | ||
672 | filelayout_get_device_info(struct inode *inode, | ||
673 | struct nfs4_deviceid *dev_id, | ||
674 | struct rpc_cred *cred, | ||
675 | gfp_t gfp_flags) | ||
676 | { | ||
677 | struct pnfs_device *pdev = NULL; | ||
678 | u32 max_resp_sz; | ||
679 | int max_pages; | ||
680 | struct page **pages = NULL; | ||
681 | struct nfs4_file_layout_dsaddr *dsaddr = NULL; | ||
682 | int rc, i; | ||
683 | struct nfs_server *server = NFS_SERVER(inode); | ||
684 | |||
685 | /* | ||
686 | * Use the session max response size as the basis for setting | ||
687 | * GETDEVICEINFO's maxcount | ||
688 | */ | ||
689 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; | ||
690 | max_pages = nfs_page_array_len(0, max_resp_sz); | ||
691 | dprintk("%s inode %p max_resp_sz %u max_pages %d\n", | ||
692 | __func__, inode, max_resp_sz, max_pages); | ||
693 | |||
694 | pdev = kzalloc(sizeof(struct pnfs_device), gfp_flags); | ||
695 | if (pdev == NULL) | ||
696 | return NULL; | ||
697 | |||
698 | pages = kcalloc(max_pages, sizeof(struct page *), gfp_flags); | ||
699 | if (pages == NULL) { | ||
700 | kfree(pdev); | ||
701 | return NULL; | ||
702 | } | ||
703 | for (i = 0; i < max_pages; i++) { | ||
704 | pages[i] = alloc_page(gfp_flags); | ||
705 | if (!pages[i]) | ||
706 | goto out_free; | ||
707 | } | ||
708 | |||
709 | memcpy(&pdev->dev_id, dev_id, sizeof(*dev_id)); | ||
710 | pdev->layout_type = LAYOUT_NFSV4_1_FILES; | ||
711 | pdev->pages = pages; | ||
712 | pdev->pgbase = 0; | ||
713 | pdev->pglen = max_resp_sz; | ||
714 | pdev->mincount = 0; | ||
715 | pdev->maxcount = max_resp_sz - nfs41_maxgetdevinfo_overhead; | ||
716 | |||
717 | rc = nfs4_proc_getdeviceinfo(server, pdev, cred); | ||
718 | dprintk("%s getdevice info returns %d\n", __func__, rc); | ||
719 | if (rc) | ||
720 | goto out_free; | ||
721 | |||
722 | /* | ||
723 | * Found new device, need to decode it and then add it to the | ||
724 | * list of known devices for this mountpoint. | ||
725 | */ | ||
726 | dsaddr = decode_and_add_device(inode, pdev, gfp_flags); | ||
727 | out_free: | ||
728 | for (i = 0; i < max_pages; i++) | ||
729 | __free_page(pages[i]); | ||
730 | kfree(pages); | ||
731 | kfree(pdev); | ||
732 | dprintk("<-- %s dsaddr %p\n", __func__, dsaddr); | ||
733 | return dsaddr; | ||
734 | } | ||
735 | |||
736 | void | 638 | void |
737 | nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) | 639 | nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) |
738 | { | 640 | { |
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index ae05278b3761..c502f640209b 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c | |||
@@ -60,52 +60,6 @@ objio_free_deviceid_node(struct nfs4_deviceid_node *d) | |||
60 | kfree(de); | 60 | kfree(de); |
61 | } | 61 | } |
62 | 62 | ||
63 | static struct objio_dev_ent *_dev_list_find(const struct nfs_server *nfss, | ||
64 | const struct nfs4_deviceid *d_id) | ||
65 | { | ||
66 | struct nfs4_deviceid_node *d; | ||
67 | struct objio_dev_ent *de; | ||
68 | |||
69 | d = nfs4_find_get_deviceid(nfss->pnfs_curr_ld, nfss->nfs_client, d_id); | ||
70 | if (!d) | ||
71 | return NULL; | ||
72 | |||
73 | de = container_of(d, struct objio_dev_ent, id_node); | ||
74 | return de; | ||
75 | } | ||
76 | |||
77 | static struct objio_dev_ent * | ||
78 | _dev_list_add(const struct nfs_server *nfss, | ||
79 | const struct nfs4_deviceid *d_id, struct osd_dev *od, | ||
80 | gfp_t gfp_flags) | ||
81 | { | ||
82 | struct nfs4_deviceid_node *d; | ||
83 | struct objio_dev_ent *de = kzalloc(sizeof(*de), gfp_flags); | ||
84 | struct objio_dev_ent *n; | ||
85 | |||
86 | if (!de) { | ||
87 | dprintk("%s: -ENOMEM od=%p\n", __func__, od); | ||
88 | return NULL; | ||
89 | } | ||
90 | |||
91 | dprintk("%s: Adding od=%p\n", __func__, od); | ||
92 | nfs4_init_deviceid_node(&de->id_node, | ||
93 | nfss->pnfs_curr_ld, | ||
94 | nfss->nfs_client, | ||
95 | d_id); | ||
96 | de->od.od = od; | ||
97 | |||
98 | d = nfs4_insert_deviceid_node(&de->id_node); | ||
99 | n = container_of(d, struct objio_dev_ent, id_node); | ||
100 | if (n != de) { | ||
101 | dprintk("%s: Race with other n->od=%p\n", __func__, n->od.od); | ||
102 | objio_free_deviceid_node(&de->id_node); | ||
103 | de = n; | ||
104 | } | ||
105 | |||
106 | return de; | ||
107 | } | ||
108 | |||
109 | struct objio_segment { | 63 | struct objio_segment { |
110 | struct pnfs_layout_segment lseg; | 64 | struct pnfs_layout_segment lseg; |
111 | 65 | ||
@@ -130,29 +84,24 @@ struct objio_state { | |||
130 | 84 | ||
131 | /* Send and wait for a get_device_info of devices in the layout, | 85 | /* Send and wait for a get_device_info of devices in the layout, |
132 | then look them up with the osd_initiator library */ | 86 | then look them up with the osd_initiator library */ |
133 | static int objio_devices_lookup(struct pnfs_layout_hdr *pnfslay, | 87 | struct nfs4_deviceid_node * |
134 | struct objio_segment *objio_seg, unsigned c, struct nfs4_deviceid *d_id, | 88 | objio_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, |
135 | gfp_t gfp_flags) | 89 | gfp_t gfp_flags) |
136 | { | 90 | { |
137 | struct pnfs_osd_deviceaddr *deviceaddr; | 91 | struct pnfs_osd_deviceaddr *deviceaddr; |
138 | struct objio_dev_ent *ode; | 92 | struct objio_dev_ent *ode = NULL; |
139 | struct osd_dev *od; | 93 | struct osd_dev *od; |
140 | struct osd_dev_info odi; | 94 | struct osd_dev_info odi; |
141 | bool retry_flag = true; | 95 | bool retry_flag = true; |
96 | u32 *p; | ||
142 | int err; | 97 | int err; |
143 | 98 | ||
144 | ode = _dev_list_find(NFS_SERVER(pnfslay->plh_inode), d_id); | 99 | deviceaddr = kzalloc(sizeof(*deviceaddr), gfp_flags); |
145 | if (ode) { | 100 | if (!deviceaddr) |
146 | objio_seg->oc.ods[c] = &ode->od; /* must use container_of */ | 101 | return NULL; |
147 | return 0; | ||
148 | } | ||
149 | 102 | ||
150 | err = objlayout_get_deviceinfo(pnfslay, d_id, &deviceaddr, gfp_flags); | 103 | p = page_address(pdev->pages[0]); |
151 | if (unlikely(err)) { | 104 | pnfs_osd_xdr_decode_deviceaddr(deviceaddr, p); |
152 | dprintk("%s: objlayout_get_deviceinfo dev(%llx:%llx) =>%d\n", | ||
153 | __func__, _DEVID_LO(d_id), _DEVID_HI(d_id), err); | ||
154 | return err; | ||
155 | } | ||
156 | 105 | ||
157 | odi.systemid_len = deviceaddr->oda_systemid.len; | 106 | odi.systemid_len = deviceaddr->oda_systemid.len; |
158 | if (odi.systemid_len > sizeof(odi.systemid)) { | 107 | if (odi.systemid_len > sizeof(odi.systemid)) { |
@@ -188,14 +137,24 @@ retry_lookup: | |||
188 | goto out; | 137 | goto out; |
189 | } | 138 | } |
190 | 139 | ||
191 | ode = _dev_list_add(NFS_SERVER(pnfslay->plh_inode), d_id, od, | ||
192 | gfp_flags); | ||
193 | objio_seg->oc.ods[c] = &ode->od; /* must use container_of */ | ||
194 | dprintk("Adding new dev_id(%llx:%llx)\n", | 140 | dprintk("Adding new dev_id(%llx:%llx)\n", |
195 | _DEVID_LO(d_id), _DEVID_HI(d_id)); | 141 | _DEVID_LO(&pdev->dev_id), _DEVID_HI(&pdev->dev_id)); |
142 | |||
143 | ode = kzalloc(sizeof(*ode), gfp_flags); | ||
144 | if (!ode) { | ||
145 | dprintk("%s: -ENOMEM od=%p\n", __func__, od); | ||
146 | goto out; | ||
147 | } | ||
148 | |||
149 | nfs4_init_deviceid_node(&ode->id_node, server, &pdev->dev_id); | ||
150 | kfree(deviceaddr); | ||
151 | |||
152 | ode->od.od = od; | ||
153 | return &ode->id_node; | ||
154 | |||
196 | out: | 155 | out: |
197 | objlayout_put_deviceinfo(deviceaddr); | 156 | kfree(deviceaddr); |
198 | return err; | 157 | return NULL; |
199 | } | 158 | } |
200 | 159 | ||
201 | static void copy_single_comp(struct ore_components *oc, unsigned c, | 160 | static void copy_single_comp(struct ore_components *oc, unsigned c, |
@@ -254,6 +213,7 @@ int objio_alloc_lseg(struct pnfs_layout_segment **outp, | |||
254 | struct xdr_stream *xdr, | 213 | struct xdr_stream *xdr, |
255 | gfp_t gfp_flags) | 214 | gfp_t gfp_flags) |
256 | { | 215 | { |
216 | struct nfs_server *server = NFS_SERVER(pnfslay->plh_inode); | ||
257 | struct objio_segment *objio_seg; | 217 | struct objio_segment *objio_seg; |
258 | struct pnfs_osd_xdr_decode_layout_iter iter; | 218 | struct pnfs_osd_xdr_decode_layout_iter iter; |
259 | struct pnfs_osd_layout layout; | 219 | struct pnfs_osd_layout layout; |
@@ -283,13 +243,21 @@ int objio_alloc_lseg(struct pnfs_layout_segment **outp, | |||
283 | objio_seg->oc.first_dev = layout.olo_comps_index; | 243 | objio_seg->oc.first_dev = layout.olo_comps_index; |
284 | cur_comp = 0; | 244 | cur_comp = 0; |
285 | while (pnfs_osd_xdr_decode_layout_comp(&src_comp, &iter, xdr, &err)) { | 245 | while (pnfs_osd_xdr_decode_layout_comp(&src_comp, &iter, xdr, &err)) { |
246 | struct nfs4_deviceid_node *d; | ||
247 | struct objio_dev_ent *ode; | ||
248 | |||
286 | copy_single_comp(&objio_seg->oc, cur_comp, &src_comp); | 249 | copy_single_comp(&objio_seg->oc, cur_comp, &src_comp); |
287 | err = objio_devices_lookup(pnfslay, objio_seg, cur_comp, | 250 | |
288 | &src_comp.oc_object_id.oid_device_id, | 251 | d = nfs4_find_get_deviceid(server, |
289 | gfp_flags); | 252 | &src_comp.oc_object_id.oid_device_id, |
290 | if (err) | 253 | pnfslay->plh_lc_cred, gfp_flags); |
254 | if (!d) { | ||
255 | err = -ENXIO; | ||
291 | goto err; | 256 | goto err; |
292 | ++cur_comp; | 257 | } |
258 | |||
259 | ode = container_of(d, struct objio_dev_ent, id_node); | ||
260 | objio_seg->oc.ods[cur_comp++] = &ode->od; | ||
293 | } | 261 | } |
294 | /* pnfs_osd_xdr_decode_layout_comp returns false on error */ | 262 | /* pnfs_osd_xdr_decode_layout_comp returns false on error */ |
295 | if (unlikely(err)) | 263 | if (unlikely(err)) |
@@ -653,6 +621,7 @@ static struct pnfs_layoutdriver_type objlayout_type = { | |||
653 | .flags = PNFS_LAYOUTRET_ON_SETATTR | | 621 | .flags = PNFS_LAYOUTRET_ON_SETATTR | |
654 | PNFS_LAYOUTRET_ON_ERROR, | 622 | PNFS_LAYOUTRET_ON_ERROR, |
655 | 623 | ||
624 | .max_deviceinfo_size = PAGE_SIZE, | ||
656 | .owner = THIS_MODULE, | 625 | .owner = THIS_MODULE, |
657 | .alloc_layout_hdr = objlayout_alloc_layout_hdr, | 626 | .alloc_layout_hdr = objlayout_alloc_layout_hdr, |
658 | .free_layout_hdr = objlayout_free_layout_hdr, | 627 | .free_layout_hdr = objlayout_free_layout_hdr, |
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c index 697a16d11fac..c89357c7a914 100644 --- a/fs/nfs/objlayout/objlayout.c +++ b/fs/nfs/objlayout/objlayout.c | |||
@@ -574,76 +574,6 @@ loop_done: | |||
574 | dprintk("%s: Return\n", __func__); | 574 | dprintk("%s: Return\n", __func__); |
575 | } | 575 | } |
576 | 576 | ||
577 | |||
578 | /* | ||
579 | * Get Device Info API for io engines | ||
580 | */ | ||
581 | struct objlayout_deviceinfo { | ||
582 | struct page *page; | ||
583 | struct pnfs_osd_deviceaddr da; /* This must be last */ | ||
584 | }; | ||
585 | |||
586 | /* Initialize and call nfs_getdeviceinfo, then decode and return a | ||
587 | * "struct pnfs_osd_deviceaddr *" Eventually objlayout_put_deviceinfo() | ||
588 | * should be called. | ||
589 | */ | ||
590 | int objlayout_get_deviceinfo(struct pnfs_layout_hdr *pnfslay, | ||
591 | struct nfs4_deviceid *d_id, struct pnfs_osd_deviceaddr **deviceaddr, | ||
592 | gfp_t gfp_flags) | ||
593 | { | ||
594 | struct objlayout_deviceinfo *odi; | ||
595 | struct pnfs_device pd; | ||
596 | struct page *page, **pages; | ||
597 | u32 *p; | ||
598 | int err; | ||
599 | |||
600 | page = alloc_page(gfp_flags); | ||
601 | if (!page) | ||
602 | return -ENOMEM; | ||
603 | |||
604 | pages = &page; | ||
605 | pd.pages = pages; | ||
606 | |||
607 | memcpy(&pd.dev_id, d_id, sizeof(*d_id)); | ||
608 | pd.layout_type = LAYOUT_OSD2_OBJECTS; | ||
609 | pd.pages = &page; | ||
610 | pd.pgbase = 0; | ||
611 | pd.pglen = PAGE_SIZE; | ||
612 | pd.mincount = 0; | ||
613 | pd.maxcount = PAGE_SIZE; | ||
614 | |||
615 | err = nfs4_proc_getdeviceinfo(NFS_SERVER(pnfslay->plh_inode), &pd, | ||
616 | pnfslay->plh_lc_cred); | ||
617 | dprintk("%s nfs_getdeviceinfo returned %d\n", __func__, err); | ||
618 | if (err) | ||
619 | goto err_out; | ||
620 | |||
621 | p = page_address(page); | ||
622 | odi = kzalloc(sizeof(*odi), gfp_flags); | ||
623 | if (!odi) { | ||
624 | err = -ENOMEM; | ||
625 | goto err_out; | ||
626 | } | ||
627 | pnfs_osd_xdr_decode_deviceaddr(&odi->da, p); | ||
628 | odi->page = page; | ||
629 | *deviceaddr = &odi->da; | ||
630 | return 0; | ||
631 | |||
632 | err_out: | ||
633 | __free_page(page); | ||
634 | return err; | ||
635 | } | ||
636 | |||
637 | void objlayout_put_deviceinfo(struct pnfs_osd_deviceaddr *deviceaddr) | ||
638 | { | ||
639 | struct objlayout_deviceinfo *odi = container_of(deviceaddr, | ||
640 | struct objlayout_deviceinfo, | ||
641 | da); | ||
642 | |||
643 | __free_page(odi->page); | ||
644 | kfree(odi); | ||
645 | } | ||
646 | |||
647 | enum { | 577 | enum { |
648 | OBJLAYOUT_MAX_URI_LEN = 256, OBJLAYOUT_MAX_OSDNAME_LEN = 64, | 578 | OBJLAYOUT_MAX_URI_LEN = 256, OBJLAYOUT_MAX_OSDNAME_LEN = 64, |
649 | OBJLAYOUT_MAX_SYSID_HEX_LEN = OSD_SYSTEMID_LEN * 2 + 1, | 579 | OBJLAYOUT_MAX_SYSID_HEX_LEN = OSD_SYSTEMID_LEN * 2 + 1, |
diff --git a/fs/nfs/objlayout/objlayout.h b/fs/nfs/objlayout/objlayout.h index fd13f1d2f136..3a0828d57339 100644 --- a/fs/nfs/objlayout/objlayout.h +++ b/fs/nfs/objlayout/objlayout.h | |||
@@ -149,11 +149,6 @@ extern void objlayout_read_done(struct objlayout_io_res *oir, | |||
149 | extern void objlayout_write_done(struct objlayout_io_res *oir, | 149 | extern void objlayout_write_done(struct objlayout_io_res *oir, |
150 | ssize_t status, bool sync); | 150 | ssize_t status, bool sync); |
151 | 151 | ||
152 | extern int objlayout_get_deviceinfo(struct pnfs_layout_hdr *pnfslay, | ||
153 | struct nfs4_deviceid *d_id, struct pnfs_osd_deviceaddr **deviceaddr, | ||
154 | gfp_t gfp_flags); | ||
155 | extern void objlayout_put_deviceinfo(struct pnfs_osd_deviceaddr *deviceaddr); | ||
156 | |||
157 | /* | 152 | /* |
158 | * exported generic objects function vectors | 153 | * exported generic objects function vectors |
159 | */ | 154 | */ |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 2c2494225930..ce89ae364bb8 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -84,6 +84,7 @@ struct pnfs_layoutdriver_type { | |||
84 | const char *name; | 84 | const char *name; |
85 | struct module *owner; | 85 | struct module *owner; |
86 | unsigned flags; | 86 | unsigned flags; |
87 | unsigned max_deviceinfo_size; | ||
87 | 88 | ||
88 | int (*set_layoutdriver) (struct nfs_server *, const struct nfs_fh *); | 89 | int (*set_layoutdriver) (struct nfs_server *, const struct nfs_fh *); |
89 | int (*clear_layoutdriver) (struct nfs_server *); | 90 | int (*clear_layoutdriver) (struct nfs_server *); |
@@ -126,6 +127,9 @@ struct pnfs_layoutdriver_type { | |||
126 | enum pnfs_try_status (*write_pagelist)(struct nfs_pgio_header *, int); | 127 | enum pnfs_try_status (*write_pagelist)(struct nfs_pgio_header *, int); |
127 | 128 | ||
128 | void (*free_deviceid_node) (struct nfs4_deviceid_node *); | 129 | void (*free_deviceid_node) (struct nfs4_deviceid_node *); |
130 | struct nfs4_deviceid_node * (*alloc_deviceid_node) | ||
131 | (struct nfs_server *server, struct pnfs_device *pdev, | ||
132 | gfp_t gfp_flags); | ||
129 | 133 | ||
130 | void (*encode_layoutreturn) (struct pnfs_layout_hdr *layoutid, | 134 | void (*encode_layoutreturn) (struct pnfs_layout_hdr *layoutid, |
131 | struct xdr_stream *xdr, | 135 | struct xdr_stream *xdr, |
@@ -261,11 +265,12 @@ struct nfs4_deviceid_node { | |||
261 | atomic_t ref; | 265 | atomic_t ref; |
262 | }; | 266 | }; |
263 | 267 | ||
264 | struct nfs4_deviceid_node *nfs4_find_get_deviceid(const struct pnfs_layoutdriver_type *, const struct nfs_client *, const struct nfs4_deviceid *); | 268 | struct nfs4_deviceid_node * |
269 | nfs4_find_get_deviceid(struct nfs_server *server, | ||
270 | const struct nfs4_deviceid *id, struct rpc_cred *cred, | ||
271 | gfp_t gfp_mask); | ||
265 | void nfs4_delete_deviceid(const struct pnfs_layoutdriver_type *, const struct nfs_client *, const struct nfs4_deviceid *); | 272 | void nfs4_delete_deviceid(const struct pnfs_layoutdriver_type *, const struct nfs_client *, const struct nfs4_deviceid *); |
266 | void nfs4_init_deviceid_node(struct nfs4_deviceid_node *, | 273 | void nfs4_init_deviceid_node(struct nfs4_deviceid_node *, struct nfs_server *, |
267 | const struct pnfs_layoutdriver_type *, | ||
268 | const struct nfs_client *, | ||
269 | const struct nfs4_deviceid *); | 274 | const struct nfs4_deviceid *); |
270 | struct nfs4_deviceid_node *nfs4_insert_deviceid_node(struct nfs4_deviceid_node *); | 275 | struct nfs4_deviceid_node *nfs4_insert_deviceid_node(struct nfs4_deviceid_node *); |
271 | bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *); | 276 | bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *); |
diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c index 6da209bd9408..791f8b3c4cff 100644 --- a/fs/nfs/pnfs_dev.c +++ b/fs/nfs/pnfs_dev.c | |||
@@ -29,6 +29,9 @@ | |||
29 | */ | 29 | */ |
30 | 30 | ||
31 | #include <linux/export.h> | 31 | #include <linux/export.h> |
32 | #include <linux/nfs_fs.h> | ||
33 | #include "nfs4session.h" | ||
34 | #include "internal.h" | ||
32 | #include "pnfs.h" | 35 | #include "pnfs.h" |
33 | 36 | ||
34 | #define NFSDBG_FACILITY NFSDBG_PNFS | 37 | #define NFSDBG_FACILITY NFSDBG_PNFS |
@@ -89,6 +92,74 @@ _lookup_deviceid(const struct pnfs_layoutdriver_type *ld, | |||
89 | return NULL; | 92 | return NULL; |
90 | } | 93 | } |
91 | 94 | ||
95 | static struct nfs4_deviceid_node * | ||
96 | nfs4_get_device_info(struct nfs_server *server, | ||
97 | const struct nfs4_deviceid *dev_id, | ||
98 | struct rpc_cred *cred, gfp_t gfp_flags) | ||
99 | { | ||
100 | struct nfs4_deviceid_node *d = NULL; | ||
101 | struct pnfs_device *pdev = NULL; | ||
102 | struct page **pages = NULL; | ||
103 | u32 max_resp_sz; | ||
104 | int max_pages; | ||
105 | int rc, i; | ||
106 | |||
107 | /* | ||
108 | * Use the session max response size as the basis for setting | ||
109 | * GETDEVICEINFO's maxcount | ||
110 | */ | ||
111 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; | ||
112 | if (server->pnfs_curr_ld->max_deviceinfo_size && | ||
113 | server->pnfs_curr_ld->max_deviceinfo_size < max_resp_sz) | ||
114 | max_resp_sz = server->pnfs_curr_ld->max_deviceinfo_size; | ||
115 | max_pages = nfs_page_array_len(0, max_resp_sz); | ||
116 | dprintk("%s: server %p max_resp_sz %u max_pages %d\n", | ||
117 | __func__, server, max_resp_sz, max_pages); | ||
118 | |||
119 | pdev = kzalloc(sizeof(*pdev), gfp_flags); | ||
120 | if (!pdev) | ||
121 | return NULL; | ||
122 | |||
123 | pages = kcalloc(max_pages, sizeof(struct page *), gfp_flags); | ||
124 | if (!pages) | ||
125 | goto out_free_pdev; | ||
126 | |||
127 | for (i = 0; i < max_pages; i++) { | ||
128 | pages[i] = alloc_page(gfp_flags); | ||
129 | if (!pages[i]) | ||
130 | goto out_free_pages; | ||
131 | } | ||
132 | |||
133 | memcpy(&pdev->dev_id, dev_id, sizeof(*dev_id)); | ||
134 | pdev->layout_type = server->pnfs_curr_ld->id; | ||
135 | pdev->pages = pages; | ||
136 | pdev->pgbase = 0; | ||
137 | pdev->pglen = max_resp_sz; | ||
138 | pdev->mincount = 0; | ||
139 | pdev->maxcount = max_resp_sz - nfs41_maxgetdevinfo_overhead; | ||
140 | |||
141 | rc = nfs4_proc_getdeviceinfo(server, pdev, cred); | ||
142 | dprintk("%s getdevice info returns %d\n", __func__, rc); | ||
143 | if (rc) | ||
144 | goto out_free_pages; | ||
145 | |||
146 | /* | ||
147 | * Found new device, need to decode it and then add it to the | ||
148 | * list of known devices for this mountpoint. | ||
149 | */ | ||
150 | d = server->pnfs_curr_ld->alloc_deviceid_node(server, pdev, | ||
151 | gfp_flags); | ||
152 | |||
153 | out_free_pages: | ||
154 | for (i = 0; i < max_pages; i++) | ||
155 | __free_page(pages[i]); | ||
156 | kfree(pages); | ||
157 | out_free_pdev: | ||
158 | kfree(pdev); | ||
159 | dprintk("<-- %s d %p\n", __func__, d); | ||
160 | return d; | ||
161 | } | ||
162 | |||
92 | /* | 163 | /* |
93 | * Lookup a deviceid in cache and get a reference count on it if found | 164 | * Lookup a deviceid in cache and get a reference count on it if found |
94 | * | 165 | * |
@@ -96,14 +167,14 @@ _lookup_deviceid(const struct pnfs_layoutdriver_type *ld, | |||
96 | * @id deviceid to look up | 167 | * @id deviceid to look up |
97 | */ | 168 | */ |
98 | static struct nfs4_deviceid_node * | 169 | static struct nfs4_deviceid_node * |
99 | _find_get_deviceid(const struct pnfs_layoutdriver_type *ld, | 170 | __nfs4_find_get_deviceid(struct nfs_server *server, |
100 | const struct nfs_client *clp, const struct nfs4_deviceid *id, | 171 | const struct nfs4_deviceid *id, long hash) |
101 | long hash) | ||
102 | { | 172 | { |
103 | struct nfs4_deviceid_node *d; | 173 | struct nfs4_deviceid_node *d; |
104 | 174 | ||
105 | rcu_read_lock(); | 175 | rcu_read_lock(); |
106 | d = _lookup_deviceid(ld, clp, id, hash); | 176 | d = _lookup_deviceid(server->pnfs_curr_ld, server->nfs_client, id, |
177 | hash); | ||
107 | if (d != NULL) | 178 | if (d != NULL) |
108 | atomic_inc(&d->ref); | 179 | atomic_inc(&d->ref); |
109 | rcu_read_unlock(); | 180 | rcu_read_unlock(); |
@@ -111,10 +182,33 @@ _find_get_deviceid(const struct pnfs_layoutdriver_type *ld, | |||
111 | } | 182 | } |
112 | 183 | ||
113 | struct nfs4_deviceid_node * | 184 | struct nfs4_deviceid_node * |
114 | nfs4_find_get_deviceid(const struct pnfs_layoutdriver_type *ld, | 185 | nfs4_find_get_deviceid(struct nfs_server *server, |
115 | const struct nfs_client *clp, const struct nfs4_deviceid *id) | 186 | const struct nfs4_deviceid *id, struct rpc_cred *cred, |
187 | gfp_t gfp_mask) | ||
116 | { | 188 | { |
117 | return _find_get_deviceid(ld, clp, id, nfs4_deviceid_hash(id)); | 189 | long hash = nfs4_deviceid_hash(id); |
190 | struct nfs4_deviceid_node *d, *new; | ||
191 | |||
192 | d = __nfs4_find_get_deviceid(server, id, hash); | ||
193 | if (d) | ||
194 | return d; | ||
195 | |||
196 | new = nfs4_get_device_info(server, id, cred, gfp_mask); | ||
197 | if (!new) | ||
198 | return new; | ||
199 | |||
200 | spin_lock(&nfs4_deviceid_lock); | ||
201 | d = __nfs4_find_get_deviceid(server, id, hash); | ||
202 | if (d) { | ||
203 | spin_unlock(&nfs4_deviceid_lock); | ||
204 | server->pnfs_curr_ld->free_deviceid_node(new); | ||
205 | return d; | ||
206 | } | ||
207 | hlist_add_head_rcu(&new->node, &nfs4_deviceid_cache[hash]); | ||
208 | atomic_inc(&new->ref); | ||
209 | spin_unlock(&nfs4_deviceid_lock); | ||
210 | |||
211 | return new; | ||
118 | } | 212 | } |
119 | EXPORT_SYMBOL_GPL(nfs4_find_get_deviceid); | 213 | EXPORT_SYMBOL_GPL(nfs4_find_get_deviceid); |
120 | 214 | ||
@@ -151,15 +245,13 @@ nfs4_delete_deviceid(const struct pnfs_layoutdriver_type *ld, | |||
151 | EXPORT_SYMBOL_GPL(nfs4_delete_deviceid); | 245 | EXPORT_SYMBOL_GPL(nfs4_delete_deviceid); |
152 | 246 | ||
153 | void | 247 | void |
154 | nfs4_init_deviceid_node(struct nfs4_deviceid_node *d, | 248 | nfs4_init_deviceid_node(struct nfs4_deviceid_node *d, struct nfs_server *server, |
155 | const struct pnfs_layoutdriver_type *ld, | ||
156 | const struct nfs_client *nfs_client, | ||
157 | const struct nfs4_deviceid *id) | 249 | const struct nfs4_deviceid *id) |
158 | { | 250 | { |
159 | INIT_HLIST_NODE(&d->node); | 251 | INIT_HLIST_NODE(&d->node); |
160 | INIT_HLIST_NODE(&d->tmpnode); | 252 | INIT_HLIST_NODE(&d->tmpnode); |
161 | d->ld = ld; | 253 | d->ld = server->pnfs_curr_ld; |
162 | d->nfs_client = nfs_client; | 254 | d->nfs_client = server->nfs_client; |
163 | d->flags = 0; | 255 | d->flags = 0; |
164 | d->deviceid = *id; | 256 | d->deviceid = *id; |
165 | atomic_set(&d->ref, 1); | 257 | atomic_set(&d->ref, 1); |
@@ -167,39 +259,6 @@ nfs4_init_deviceid_node(struct nfs4_deviceid_node *d, | |||
167 | EXPORT_SYMBOL_GPL(nfs4_init_deviceid_node); | 259 | EXPORT_SYMBOL_GPL(nfs4_init_deviceid_node); |
168 | 260 | ||
169 | /* | 261 | /* |
170 | * Uniquely initialize and insert a deviceid node into cache | ||
171 | * | ||
172 | * @new new deviceid node | ||
173 | * Note that the caller must set up the following members: | ||
174 | * new->ld | ||
175 | * new->nfs_client | ||
176 | * new->deviceid | ||
177 | * | ||
178 | * @ret the inserted node, if none found, otherwise, the found entry. | ||
179 | */ | ||
180 | struct nfs4_deviceid_node * | ||
181 | nfs4_insert_deviceid_node(struct nfs4_deviceid_node *new) | ||
182 | { | ||
183 | struct nfs4_deviceid_node *d; | ||
184 | long hash; | ||
185 | |||
186 | spin_lock(&nfs4_deviceid_lock); | ||
187 | hash = nfs4_deviceid_hash(&new->deviceid); | ||
188 | d = _find_get_deviceid(new->ld, new->nfs_client, &new->deviceid, hash); | ||
189 | if (d) { | ||
190 | spin_unlock(&nfs4_deviceid_lock); | ||
191 | return d; | ||
192 | } | ||
193 | |||
194 | hlist_add_head_rcu(&new->node, &nfs4_deviceid_cache[hash]); | ||
195 | spin_unlock(&nfs4_deviceid_lock); | ||
196 | atomic_inc(&new->ref); | ||
197 | |||
198 | return new; | ||
199 | } | ||
200 | EXPORT_SYMBOL_GPL(nfs4_insert_deviceid_node); | ||
201 | |||
202 | /* | ||
203 | * Dereference a deviceid node and delete it when its reference count drops | 262 | * Dereference a deviceid node and delete it when its reference count drops |
204 | * to zero. | 263 | * to zero. |
205 | * | 264 | * |