diff options
author | Christoph Hellwig <hch@lst.de> | 2014-09-03 00:28:00 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-09-10 15:47:04 -0400 |
commit | 20d655d6197d02e98574208839da11684dc2ad1f (patch) | |
tree | 0212cbd41504909d6921db5a661a10058b7ab61c /fs/nfs | |
parent | 30ff0603ca4d66c8244efc80ea8470d3d04aee8b (diff) |
pnfs/blocklayout: use the device id cache
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/blocklayout/blocklayout.c | 149 | ||||
-rw-r--r-- | fs/nfs/blocklayout/blocklayout.h | 25 | ||||
-rw-r--r-- | fs/nfs/blocklayout/blocklayoutdev.c | 88 | ||||
-rw-r--r-- | fs/nfs/blocklayout/blocklayoutdm.c | 26 | ||||
-rw-r--r-- | fs/nfs/blocklayout/extent_tree.c | 27 |
5 files changed, 65 insertions, 250 deletions
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index bdd73fbacf48..25ba9e0e6fff 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c | |||
@@ -119,6 +119,8 @@ static struct bio *bl_alloc_init_bio(int npg, sector_t isect, | |||
119 | void (*end_io)(struct bio *, int err), | 119 | void (*end_io)(struct bio *, int err), |
120 | struct parallel_io *par) | 120 | struct parallel_io *par) |
121 | { | 121 | { |
122 | struct pnfs_block_dev *dev = | ||
123 | container_of(be->be_device, struct pnfs_block_dev, d_node); | ||
122 | struct bio *bio; | 124 | struct bio *bio; |
123 | 125 | ||
124 | npg = min(npg, BIO_MAX_PAGES); | 126 | npg = min(npg, BIO_MAX_PAGES); |
@@ -131,7 +133,7 @@ static struct bio *bl_alloc_init_bio(int npg, sector_t isect, | |||
131 | if (bio) { | 133 | if (bio) { |
132 | bio->bi_iter.bi_sector = isect - be->be_f_offset + | 134 | bio->bi_iter.bi_sector = isect - be->be_f_offset + |
133 | be->be_v_offset; | 135 | be->be_v_offset; |
134 | bio->bi_bdev = be->be_mdev; | 136 | bio->bi_bdev = dev->d_bdev; |
135 | bio->bi_end_io = end_io; | 137 | bio->bi_end_io = end_io; |
136 | bio->bi_private = par; | 138 | bio->bi_private = par; |
137 | } | 139 | } |
@@ -515,96 +517,9 @@ bl_cleanup_layoutcommit(struct nfs4_layoutcommit_data *lcdata) | |||
515 | ext_tree_mark_committed(BLK_LO2EXT(lo), lcdata->res.status); | 517 | ext_tree_mark_committed(BLK_LO2EXT(lo), lcdata->res.status); |
516 | } | 518 | } |
517 | 519 | ||
518 | static void free_blk_mountid(struct block_mount_id *mid) | ||
519 | { | ||
520 | if (mid) { | ||
521 | struct pnfs_block_dev *dev, *tmp; | ||
522 | |||
523 | /* No need to take bm_lock as we are last user freeing bm_devlist */ | ||
524 | list_for_each_entry_safe(dev, tmp, &mid->bm_devlist, bm_node) { | ||
525 | list_del(&dev->bm_node); | ||
526 | bl_free_block_dev(dev); | ||
527 | } | ||
528 | kfree(mid); | ||
529 | } | ||
530 | } | ||
531 | |||
532 | /* This is mostly copied from the filelayout_get_device_info function. | ||
533 | * It seems much of this should be at the generic pnfs level. | ||
534 | */ | ||
535 | static struct pnfs_block_dev * | ||
536 | nfs4_blk_get_deviceinfo(struct nfs_server *server, const struct nfs_fh *fh, | ||
537 | struct nfs4_deviceid *d_id) | ||
538 | { | ||
539 | struct pnfs_device *dev; | ||
540 | struct pnfs_block_dev *rv; | ||
541 | u32 max_resp_sz; | ||
542 | int max_pages; | ||
543 | struct page **pages = NULL; | ||
544 | int i, rc; | ||
545 | |||
546 | /* | ||
547 | * Use the session max response size as the basis for setting | ||
548 | * GETDEVICEINFO's maxcount | ||
549 | */ | ||
550 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; | ||
551 | max_pages = nfs_page_array_len(0, max_resp_sz); | ||
552 | dprintk("%s max_resp_sz %u max_pages %d\n", | ||
553 | __func__, max_resp_sz, max_pages); | ||
554 | |||
555 | dev = kmalloc(sizeof(*dev), GFP_NOFS); | ||
556 | if (!dev) { | ||
557 | dprintk("%s kmalloc failed\n", __func__); | ||
558 | return ERR_PTR(-ENOMEM); | ||
559 | } | ||
560 | |||
561 | pages = kcalloc(max_pages, sizeof(struct page *), GFP_NOFS); | ||
562 | if (pages == NULL) { | ||
563 | kfree(dev); | ||
564 | return ERR_PTR(-ENOMEM); | ||
565 | } | ||
566 | for (i = 0; i < max_pages; i++) { | ||
567 | pages[i] = alloc_page(GFP_NOFS); | ||
568 | if (!pages[i]) { | ||
569 | rv = ERR_PTR(-ENOMEM); | ||
570 | goto out_free; | ||
571 | } | ||
572 | } | ||
573 | |||
574 | memcpy(&dev->dev_id, d_id, sizeof(*d_id)); | ||
575 | dev->layout_type = LAYOUT_BLOCK_VOLUME; | ||
576 | dev->pages = pages; | ||
577 | dev->pgbase = 0; | ||
578 | dev->pglen = PAGE_SIZE * max_pages; | ||
579 | dev->mincount = 0; | ||
580 | dev->maxcount = max_resp_sz - nfs41_maxgetdevinfo_overhead; | ||
581 | |||
582 | dprintk("%s: dev_id: %s\n", __func__, dev->dev_id.data); | ||
583 | rc = nfs4_proc_getdeviceinfo(server, dev, NULL); | ||
584 | dprintk("%s getdevice info returns %d\n", __func__, rc); | ||
585 | if (rc) { | ||
586 | rv = ERR_PTR(rc); | ||
587 | goto out_free; | ||
588 | } | ||
589 | |||
590 | rv = nfs4_blk_decode_device(server, dev); | ||
591 | out_free: | ||
592 | for (i = 0; i < max_pages; i++) | ||
593 | __free_page(pages[i]); | ||
594 | kfree(pages); | ||
595 | kfree(dev); | ||
596 | return rv; | ||
597 | } | ||
598 | |||
599 | static int | 520 | static int |
600 | bl_set_layoutdriver(struct nfs_server *server, const struct nfs_fh *fh) | 521 | bl_set_layoutdriver(struct nfs_server *server, const struct nfs_fh *fh) |
601 | { | 522 | { |
602 | struct block_mount_id *b_mt_id = NULL; | ||
603 | struct pnfs_devicelist *dlist = NULL; | ||
604 | struct pnfs_block_dev *bdev; | ||
605 | LIST_HEAD(block_disklist); | ||
606 | int status, i; | ||
607 | |||
608 | dprintk("%s enter\n", __func__); | 523 | dprintk("%s enter\n", __func__); |
609 | 524 | ||
610 | if (server->pnfs_blksize == 0) { | 525 | if (server->pnfs_blksize == 0) { |
@@ -617,60 +532,7 @@ bl_set_layoutdriver(struct nfs_server *server, const struct nfs_fh *fh) | |||
617 | return -EINVAL; | 532 | return -EINVAL; |
618 | } | 533 | } |
619 | 534 | ||
620 | b_mt_id = kzalloc(sizeof(struct block_mount_id), GFP_NOFS); | 535 | return nfs4_deviceid_getdevicelist(server, fh); |
621 | if (!b_mt_id) { | ||
622 | status = -ENOMEM; | ||
623 | goto out_error; | ||
624 | } | ||
625 | /* Initialize nfs4 block layout mount id */ | ||
626 | spin_lock_init(&b_mt_id->bm_lock); | ||
627 | INIT_LIST_HEAD(&b_mt_id->bm_devlist); | ||
628 | |||
629 | dlist = kmalloc(sizeof(struct pnfs_devicelist), GFP_NOFS); | ||
630 | if (!dlist) { | ||
631 | status = -ENOMEM; | ||
632 | goto out_error; | ||
633 | } | ||
634 | dlist->eof = 0; | ||
635 | while (!dlist->eof) { | ||
636 | status = nfs4_proc_getdevicelist(server, fh, dlist); | ||
637 | if (status) | ||
638 | goto out_error; | ||
639 | dprintk("%s GETDEVICELIST numdevs=%i, eof=%i\n", | ||
640 | __func__, dlist->num_devs, dlist->eof); | ||
641 | for (i = 0; i < dlist->num_devs; i++) { | ||
642 | bdev = nfs4_blk_get_deviceinfo(server, fh, | ||
643 | &dlist->dev_id[i]); | ||
644 | if (IS_ERR(bdev)) { | ||
645 | status = PTR_ERR(bdev); | ||
646 | goto out_error; | ||
647 | } | ||
648 | spin_lock(&b_mt_id->bm_lock); | ||
649 | list_add(&bdev->bm_node, &b_mt_id->bm_devlist); | ||
650 | spin_unlock(&b_mt_id->bm_lock); | ||
651 | } | ||
652 | } | ||
653 | dprintk("%s SUCCESS\n", __func__); | ||
654 | server->pnfs_ld_data = b_mt_id; | ||
655 | |||
656 | out_return: | ||
657 | kfree(dlist); | ||
658 | return status; | ||
659 | |||
660 | out_error: | ||
661 | free_blk_mountid(b_mt_id); | ||
662 | goto out_return; | ||
663 | } | ||
664 | |||
665 | static int | ||
666 | bl_clear_layoutdriver(struct nfs_server *server) | ||
667 | { | ||
668 | struct block_mount_id *b_mt_id = server->pnfs_ld_data; | ||
669 | |||
670 | dprintk("%s enter\n", __func__); | ||
671 | free_blk_mountid(b_mt_id); | ||
672 | dprintk("%s RETURNS\n", __func__); | ||
673 | return 0; | ||
674 | } | 536 | } |
675 | 537 | ||
676 | static bool | 538 | static bool |
@@ -811,7 +673,8 @@ static struct pnfs_layoutdriver_type blocklayout_type = { | |||
811 | .encode_layoutcommit = bl_encode_layoutcommit, | 673 | .encode_layoutcommit = bl_encode_layoutcommit, |
812 | .cleanup_layoutcommit = bl_cleanup_layoutcommit, | 674 | .cleanup_layoutcommit = bl_cleanup_layoutcommit, |
813 | .set_layoutdriver = bl_set_layoutdriver, | 675 | .set_layoutdriver = bl_set_layoutdriver, |
814 | .clear_layoutdriver = bl_clear_layoutdriver, | 676 | .alloc_deviceid_node = bl_alloc_deviceid_node, |
677 | .free_deviceid_node = bl_free_deviceid_node, | ||
815 | .pg_read_ops = &bl_pg_read_ops, | 678 | .pg_read_ops = &bl_pg_read_ops, |
816 | .pg_write_ops = &bl_pg_write_ops, | 679 | .pg_write_ops = &bl_pg_write_ops, |
817 | }; | 680 | }; |
diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h index b4f66d875f12..19fae5e4c90b 100644 --- a/fs/nfs/blocklayout/blocklayout.h +++ b/fs/nfs/blocklayout/blocklayout.h | |||
@@ -44,16 +44,9 @@ | |||
44 | #define PAGE_CACHE_SECTOR_SHIFT (PAGE_CACHE_SHIFT - SECTOR_SHIFT) | 44 | #define PAGE_CACHE_SECTOR_SHIFT (PAGE_CACHE_SHIFT - SECTOR_SHIFT) |
45 | #define SECTOR_SIZE (1 << SECTOR_SHIFT) | 45 | #define SECTOR_SIZE (1 << SECTOR_SHIFT) |
46 | 46 | ||
47 | struct block_mount_id { | ||
48 | spinlock_t bm_lock; /* protects list */ | ||
49 | struct list_head bm_devlist; /* holds pnfs_block_dev */ | ||
50 | }; | ||
51 | |||
52 | struct pnfs_block_dev { | 47 | struct pnfs_block_dev { |
53 | struct list_head bm_node; | 48 | struct nfs4_deviceid_node d_node; |
54 | struct nfs4_deviceid bm_mdevid; /* associated devid */ | 49 | struct block_device *d_bdev; |
55 | struct block_device *bm_mdev; /* meta device itself */ | ||
56 | struct net *net; | ||
57 | }; | 50 | }; |
58 | 51 | ||
59 | enum exstate4 { | 52 | enum exstate4 { |
@@ -69,8 +62,7 @@ struct pnfs_block_extent { | |||
69 | struct rb_node be_node; | 62 | struct rb_node be_node; |
70 | struct list_head be_list; | 63 | struct list_head be_list; |
71 | }; | 64 | }; |
72 | struct nfs4_deviceid be_devid; /* FIXME: could use device cache instead */ | 65 | struct nfs4_deviceid_node *be_device; |
73 | struct block_device *be_mdev; | ||
74 | sector_t be_f_offset; /* the starting offset in the file */ | 66 | sector_t be_f_offset; /* the starting offset in the file */ |
75 | sector_t be_length; /* the size of the extent */ | 67 | sector_t be_length; /* the size of the extent */ |
76 | sector_t be_v_offset; /* the starting offset in the volume */ | 68 | sector_t be_v_offset; /* the starting offset in the volume */ |
@@ -87,8 +79,6 @@ struct pnfs_block_layout { | |||
87 | spinlock_t bl_ext_lock; /* Protects list manipulation */ | 79 | spinlock_t bl_ext_lock; /* Protects list manipulation */ |
88 | }; | 80 | }; |
89 | 81 | ||
90 | #define BLK_ID(lo) ((struct block_mount_id *)(NFS_SERVER(lo->plh_inode)->pnfs_ld_data)) | ||
91 | |||
92 | static inline struct pnfs_block_layout * | 82 | static inline struct pnfs_block_layout * |
93 | BLK_LO2EXT(struct pnfs_layout_hdr *lo) | 83 | BLK_LO2EXT(struct pnfs_layout_hdr *lo) |
94 | { | 84 | { |
@@ -120,14 +110,15 @@ struct bl_msg_hdr { | |||
120 | /* blocklayoutdev.c */ | 110 | /* blocklayoutdev.c */ |
121 | ssize_t bl_pipe_downcall(struct file *, const char __user *, size_t); | 111 | ssize_t bl_pipe_downcall(struct file *, const char __user *, size_t); |
122 | void bl_pipe_destroy_msg(struct rpc_pipe_msg *); | 112 | void bl_pipe_destroy_msg(struct rpc_pipe_msg *); |
123 | void nfs4_blkdev_put(struct block_device *bdev); | ||
124 | struct pnfs_block_dev *nfs4_blk_decode_device(struct nfs_server *server, | ||
125 | struct pnfs_device *dev); | ||
126 | int nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo, | 113 | int nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo, |
127 | struct nfs4_layoutget_res *lgr, gfp_t gfp_flags); | 114 | struct nfs4_layoutget_res *lgr, gfp_t gfp_flags); |
128 | 115 | ||
116 | struct nfs4_deviceid_node *bl_alloc_deviceid_node(struct nfs_server *server, | ||
117 | struct pnfs_device *pdev, gfp_t gfp_mask); | ||
118 | void bl_free_deviceid_node(struct nfs4_deviceid_node *d); | ||
119 | |||
129 | /* blocklayoutdm.c */ | 120 | /* blocklayoutdm.c */ |
130 | void bl_free_block_dev(struct pnfs_block_dev *bdev); | 121 | void bl_dm_remove(struct net *net, dev_t dev); |
131 | 122 | ||
132 | /* extent_tree.c */ | 123 | /* extent_tree.c */ |
133 | int ext_tree_insert(struct pnfs_block_layout *bl, | 124 | int ext_tree_insert(struct pnfs_block_layout *bl, |
diff --git a/fs/nfs/blocklayout/blocklayoutdev.c b/fs/nfs/blocklayout/blocklayoutdev.c index cd71b5e231ec..d6527d20c508 100644 --- a/fs/nfs/blocklayout/blocklayoutdev.c +++ b/fs/nfs/blocklayout/blocklayoutdev.c | |||
@@ -53,16 +53,6 @@ static int decode_sector_number(__be32 **rp, sector_t *sp) | |||
53 | return 0; | 53 | return 0; |
54 | } | 54 | } |
55 | 55 | ||
56 | /* | ||
57 | * Release the block device | ||
58 | */ | ||
59 | void nfs4_blkdev_put(struct block_device *bdev) | ||
60 | { | ||
61 | dprintk("%s for device %d:%d\n", __func__, MAJOR(bdev->bd_dev), | ||
62 | MINOR(bdev->bd_dev)); | ||
63 | blkdev_put(bdev, FMODE_READ); | ||
64 | } | ||
65 | |||
66 | ssize_t bl_pipe_downcall(struct file *filp, const char __user *src, | 56 | ssize_t bl_pipe_downcall(struct file *filp, const char __user *src, |
67 | size_t mlen) | 57 | size_t mlen) |
68 | { | 58 | { |
@@ -92,12 +82,12 @@ void bl_pipe_destroy_msg(struct rpc_pipe_msg *msg) | |||
92 | /* | 82 | /* |
93 | * Decodes pnfs_block_deviceaddr4 which is XDR encoded in dev->dev_addr_buf. | 83 | * Decodes pnfs_block_deviceaddr4 which is XDR encoded in dev->dev_addr_buf. |
94 | */ | 84 | */ |
95 | struct pnfs_block_dev * | 85 | struct nfs4_deviceid_node * |
96 | nfs4_blk_decode_device(struct nfs_server *server, | 86 | bl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *dev, |
97 | struct pnfs_device *dev) | 87 | gfp_t gfp_mask) |
98 | { | 88 | { |
99 | struct pnfs_block_dev *rv; | 89 | struct pnfs_block_dev *rv; |
100 | struct block_device *bd = NULL; | 90 | struct block_device *bd; |
101 | struct bl_pipe_msg bl_pipe_msg; | 91 | struct bl_pipe_msg bl_pipe_msg; |
102 | struct rpc_pipe_msg *msg = &bl_pipe_msg.msg; | 92 | struct rpc_pipe_msg *msg = &bl_pipe_msg.msg; |
103 | struct bl_msg_hdr bl_msg = { | 93 | struct bl_msg_hdr bl_msg = { |
@@ -117,11 +107,9 @@ nfs4_blk_decode_device(struct nfs_server *server, | |||
117 | 107 | ||
118 | bl_pipe_msg.bl_wq = &nn->bl_wq; | 108 | bl_pipe_msg.bl_wq = &nn->bl_wq; |
119 | memset(msg, 0, sizeof(*msg)); | 109 | memset(msg, 0, sizeof(*msg)); |
120 | msg->data = kzalloc(sizeof(bl_msg) + dev->mincount, GFP_NOFS); | 110 | msg->data = kzalloc(sizeof(bl_msg) + dev->mincount, gfp_mask); |
121 | if (!msg->data) { | 111 | if (!msg->data) |
122 | rv = ERR_PTR(-ENOMEM); | ||
123 | goto out; | 112 | goto out; |
124 | } | ||
125 | 113 | ||
126 | memcpy(msg->data, &bl_msg, sizeof(bl_msg)); | 114 | memcpy(msg->data, &bl_msg, sizeof(bl_msg)); |
127 | dataptr = (uint8_t *) msg->data; | 115 | dataptr = (uint8_t *) msg->data; |
@@ -140,7 +128,6 @@ nfs4_blk_decode_device(struct nfs_server *server, | |||
140 | rc = rpc_queue_upcall(nn->bl_device_pipe, msg); | 128 | rc = rpc_queue_upcall(nn->bl_device_pipe, msg); |
141 | if (rc < 0) { | 129 | if (rc < 0) { |
142 | remove_wait_queue(&nn->bl_wq, &wq); | 130 | remove_wait_queue(&nn->bl_wq, &wq); |
143 | rv = ERR_PTR(rc); | ||
144 | goto out; | 131 | goto out; |
145 | } | 132 | } |
146 | 133 | ||
@@ -152,7 +139,6 @@ nfs4_blk_decode_device(struct nfs_server *server, | |||
152 | if (reply->status != BL_DEVICE_REQUEST_PROC) { | 139 | if (reply->status != BL_DEVICE_REQUEST_PROC) { |
153 | printk(KERN_WARNING "%s failed to decode device: %d\n", | 140 | printk(KERN_WARNING "%s failed to decode device: %d\n", |
154 | __func__, reply->status); | 141 | __func__, reply->status); |
155 | rv = ERR_PTR(-EINVAL); | ||
156 | goto out; | 142 | goto out; |
157 | } | 143 | } |
158 | 144 | ||
@@ -162,51 +148,40 @@ nfs4_blk_decode_device(struct nfs_server *server, | |||
162 | printk(KERN_WARNING "%s failed to open device %d:%d (%ld)\n", | 148 | printk(KERN_WARNING "%s failed to open device %d:%d (%ld)\n", |
163 | __func__, reply->major, reply->minor, | 149 | __func__, reply->major, reply->minor, |
164 | PTR_ERR(bd)); | 150 | PTR_ERR(bd)); |
165 | rv = ERR_CAST(bd); | ||
166 | goto out; | 151 | goto out; |
167 | } | 152 | } |
168 | 153 | ||
169 | rv = kzalloc(sizeof(*rv), GFP_NOFS); | 154 | rv = kzalloc(sizeof(*rv), gfp_mask); |
170 | if (!rv) { | 155 | if (!rv) |
171 | rv = ERR_PTR(-ENOMEM); | ||
172 | goto out; | 156 | goto out; |
173 | } | ||
174 | 157 | ||
175 | rv->bm_mdev = bd; | 158 | nfs4_init_deviceid_node(&rv->d_node, server, &dev->dev_id); |
176 | memcpy(&rv->bm_mdevid, &dev->dev_id, sizeof(struct nfs4_deviceid)); | 159 | rv->d_bdev = bd; |
177 | rv->net = net; | 160 | |
178 | dprintk("%s Created device %s with bd_block_size %u\n", | 161 | dprintk("%s Created device %s with bd_block_size %u\n", |
179 | __func__, | 162 | __func__, |
180 | bd->bd_disk->disk_name, | 163 | bd->bd_disk->disk_name, |
181 | bd->bd_block_size); | 164 | bd->bd_block_size); |
182 | 165 | ||
166 | kfree(msg->data); | ||
167 | return &rv->d_node; | ||
168 | |||
183 | out: | 169 | out: |
184 | kfree(msg->data); | 170 | kfree(msg->data); |
185 | return rv; | 171 | return NULL; |
186 | } | 172 | } |
187 | 173 | ||
188 | /* Map deviceid returned by the server to constructed block_device */ | 174 | void |
189 | static struct block_device *translate_devid(struct pnfs_layout_hdr *lo, | 175 | bl_free_deviceid_node(struct nfs4_deviceid_node *d) |
190 | struct nfs4_deviceid *id) | ||
191 | { | 176 | { |
192 | struct block_device *rv = NULL; | 177 | struct pnfs_block_dev *dev = |
193 | struct block_mount_id *mid; | 178 | container_of(d, struct pnfs_block_dev, d_node); |
194 | struct pnfs_block_dev *dev; | 179 | struct net *net = d->nfs_client->cl_net; |
195 | 180 | ||
196 | dprintk("%s enter, lo=%p, id=%p\n", __func__, lo, id); | 181 | blkdev_put(dev->d_bdev, FMODE_READ); |
197 | mid = BLK_ID(lo); | 182 | bl_dm_remove(net, dev->d_bdev->bd_dev); |
198 | spin_lock(&mid->bm_lock); | 183 | |
199 | list_for_each_entry(dev, &mid->bm_devlist, bm_node) { | 184 | kfree(dev); |
200 | if (memcmp(id->data, dev->bm_mdevid.data, | ||
201 | NFS4_DEVICEID4_SIZE) == 0) { | ||
202 | rv = dev->bm_mdev; | ||
203 | goto out; | ||
204 | } | ||
205 | } | ||
206 | out: | ||
207 | spin_unlock(&mid->bm_lock); | ||
208 | dprintk("%s returning %p\n", __func__, rv); | ||
209 | return rv; | ||
210 | } | 185 | } |
211 | 186 | ||
212 | /* Tracks info needed to ensure extents in layout obey constraints of spec */ | 187 | /* Tracks info needed to ensure extents in layout obey constraints of spec */ |
@@ -309,15 +284,20 @@ nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo, | |||
309 | * recovery easier. | 284 | * recovery easier. |
310 | */ | 285 | */ |
311 | for (i = 0; i < count; i++) { | 286 | for (i = 0; i < count; i++) { |
287 | struct nfs4_deviceid id; | ||
288 | |||
312 | be = kzalloc(sizeof(struct pnfs_block_extent), GFP_NOFS); | 289 | be = kzalloc(sizeof(struct pnfs_block_extent), GFP_NOFS); |
313 | if (!be) { | 290 | if (!be) { |
314 | status = -ENOMEM; | 291 | status = -ENOMEM; |
315 | goto out_err; | 292 | goto out_err; |
316 | } | 293 | } |
317 | memcpy(&be->be_devid, p, NFS4_DEVICEID4_SIZE); | 294 | memcpy(&id, p, NFS4_DEVICEID4_SIZE); |
318 | p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE); | 295 | p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE); |
319 | be->be_mdev = translate_devid(lo, &be->be_devid); | 296 | |
320 | if (!be->be_mdev) | 297 | be->be_device = |
298 | nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &id, | ||
299 | lo->plh_lc_cred, gfp_flags); | ||
300 | if (!be->be_device) | ||
321 | goto out_err; | 301 | goto out_err; |
322 | 302 | ||
323 | /* The next three values are read in as bytes, | 303 | /* The next three values are read in as bytes, |
@@ -364,12 +344,14 @@ nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo, | |||
364 | return status; | 344 | return status; |
365 | 345 | ||
366 | out_err: | 346 | out_err: |
347 | nfs4_put_deviceid_node(be->be_device); | ||
367 | kfree(be); | 348 | kfree(be); |
368 | out_free_list: | 349 | out_free_list: |
369 | while (!list_empty(&extents)) { | 350 | while (!list_empty(&extents)) { |
370 | be = list_first_entry(&extents, struct pnfs_block_extent, | 351 | be = list_first_entry(&extents, struct pnfs_block_extent, |
371 | be_list); | 352 | be_list); |
372 | list_del(&be->be_list); | 353 | list_del(&be->be_list); |
354 | nfs4_put_deviceid_node(be->be_device); | ||
373 | kfree(be); | 355 | kfree(be); |
374 | } | 356 | } |
375 | goto out; | 357 | goto out; |
diff --git a/fs/nfs/blocklayout/blocklayoutdm.c b/fs/nfs/blocklayout/blocklayoutdm.c index 8999cfddd866..abc2e9e45610 100644 --- a/fs/nfs/blocklayout/blocklayoutdm.c +++ b/fs/nfs/blocklayout/blocklayoutdm.c | |||
@@ -38,7 +38,7 @@ | |||
38 | 38 | ||
39 | #define NFSDBG_FACILITY NFSDBG_PNFS_LD | 39 | #define NFSDBG_FACILITY NFSDBG_PNFS_LD |
40 | 40 | ||
41 | static void dev_remove(struct net *net, dev_t dev) | 41 | void bl_dm_remove(struct net *net, dev_t dev) |
42 | { | 42 | { |
43 | struct bl_pipe_msg bl_pipe_msg; | 43 | struct bl_pipe_msg bl_pipe_msg; |
44 | struct rpc_pipe_msg *msg = &bl_pipe_msg.msg; | 44 | struct rpc_pipe_msg *msg = &bl_pipe_msg.msg; |
@@ -82,27 +82,3 @@ static void dev_remove(struct net *net, dev_t dev) | |||
82 | out: | 82 | out: |
83 | kfree(msg->data); | 83 | kfree(msg->data); |
84 | } | 84 | } |
85 | |||
86 | /* | ||
87 | * Release meta device | ||
88 | */ | ||
89 | static void nfs4_blk_metadev_release(struct pnfs_block_dev *bdev) | ||
90 | { | ||
91 | dprintk("%s Releasing\n", __func__); | ||
92 | nfs4_blkdev_put(bdev->bm_mdev); | ||
93 | dev_remove(bdev->net, bdev->bm_mdev->bd_dev); | ||
94 | } | ||
95 | |||
96 | void bl_free_block_dev(struct pnfs_block_dev *bdev) | ||
97 | { | ||
98 | if (bdev) { | ||
99 | if (bdev->bm_mdev) { | ||
100 | dprintk("%s Removing DM device: %d:%d\n", | ||
101 | __func__, | ||
102 | MAJOR(bdev->bm_mdev->bd_dev), | ||
103 | MINOR(bdev->bm_mdev->bd_dev)); | ||
104 | nfs4_blk_metadev_release(bdev); | ||
105 | } | ||
106 | kfree(bdev); | ||
107 | } | ||
108 | } | ||
diff --git a/fs/nfs/blocklayout/extent_tree.c b/fs/nfs/blocklayout/extent_tree.c index c8c59a5b1a8f..f34f61dd0d0b 100644 --- a/fs/nfs/blocklayout/extent_tree.c +++ b/fs/nfs/blocklayout/extent_tree.c | |||
@@ -71,7 +71,7 @@ ext_can_merge(struct pnfs_block_extent *be1, struct pnfs_block_extent *be2) | |||
71 | { | 71 | { |
72 | if (be1->be_state != be2->be_state) | 72 | if (be1->be_state != be2->be_state) |
73 | return false; | 73 | return false; |
74 | if (be1->be_mdev != be2->be_mdev) | 74 | if (be1->be_device != be2->be_device) |
75 | return false; | 75 | return false; |
76 | 76 | ||
77 | if (be1->be_f_offset + be1->be_length != be2->be_f_offset) | 77 | if (be1->be_f_offset + be1->be_length != be2->be_f_offset) |
@@ -96,6 +96,7 @@ ext_try_to_merge_left(struct rb_root *root, struct pnfs_block_extent *be) | |||
96 | if (left && ext_can_merge(left, be)) { | 96 | if (left && ext_can_merge(left, be)) { |
97 | left->be_length += be->be_length; | 97 | left->be_length += be->be_length; |
98 | rb_erase(&be->be_node, root); | 98 | rb_erase(&be->be_node, root); |
99 | nfs4_put_deviceid_node(be->be_device); | ||
99 | kfree(be); | 100 | kfree(be); |
100 | return left; | 101 | return left; |
101 | } | 102 | } |
@@ -111,6 +112,7 @@ ext_try_to_merge_right(struct rb_root *root, struct pnfs_block_extent *be) | |||
111 | if (right && ext_can_merge(be, right)) { | 112 | if (right && ext_can_merge(be, right)) { |
112 | be->be_length += right->be_length; | 113 | be->be_length += right->be_length; |
113 | rb_erase(&right->be_node, root); | 114 | rb_erase(&right->be_node, root); |
115 | nfs4_put_deviceid_node(right->be_device); | ||
114 | kfree(right); | 116 | kfree(right); |
115 | } | 117 | } |
116 | 118 | ||
@@ -135,16 +137,14 @@ __ext_tree_insert(struct rb_root *root, | |||
135 | be->be_v_offset = new->be_v_offset; | 137 | be->be_v_offset = new->be_v_offset; |
136 | be->be_length += new->be_length; | 138 | be->be_length += new->be_length; |
137 | be = ext_try_to_merge_left(root, be); | 139 | be = ext_try_to_merge_left(root, be); |
138 | kfree(new); | 140 | goto free_new; |
139 | return; | ||
140 | } | 141 | } |
141 | p = &(*p)->rb_left; | 142 | p = &(*p)->rb_left; |
142 | } else if (new->be_f_offset >= ext_f_end(be)) { | 143 | } else if (new->be_f_offset >= ext_f_end(be)) { |
143 | if (merge_ok && ext_can_merge(be, new)) { | 144 | if (merge_ok && ext_can_merge(be, new)) { |
144 | be->be_length += new->be_length; | 145 | be->be_length += new->be_length; |
145 | be = ext_try_to_merge_right(root, be); | 146 | be = ext_try_to_merge_right(root, be); |
146 | kfree(new); | 147 | goto free_new; |
147 | return; | ||
148 | } | 148 | } |
149 | p = &(*p)->rb_right; | 149 | p = &(*p)->rb_right; |
150 | } else { | 150 | } else { |
@@ -154,6 +154,10 @@ __ext_tree_insert(struct rb_root *root, | |||
154 | 154 | ||
155 | rb_link_node(&new->be_node, parent, p); | 155 | rb_link_node(&new->be_node, parent, p); |
156 | rb_insert_color(&new->be_node, root); | 156 | rb_insert_color(&new->be_node, root); |
157 | return; | ||
158 | free_new: | ||
159 | nfs4_put_deviceid_node(new->be_device); | ||
160 | kfree(new); | ||
157 | } | 161 | } |
158 | 162 | ||
159 | static int | 163 | static int |
@@ -198,9 +202,7 @@ __ext_tree_remove(struct rb_root *root, sector_t start, sector_t end) | |||
198 | new->be_length = len2; | 202 | new->be_length = len2; |
199 | new->be_state = be->be_state; | 203 | new->be_state = be->be_state; |
200 | new->be_tag = be->be_tag; | 204 | new->be_tag = be->be_tag; |
201 | new->be_mdev = be->be_mdev; | 205 | new->be_device = nfs4_get_deviceid(be->be_device); |
202 | memcpy(&new->be_devid, &be->be_devid, | ||
203 | sizeof(struct nfs4_deviceid)); | ||
204 | 206 | ||
205 | __ext_tree_insert(root, new, true); | 207 | __ext_tree_insert(root, new, true); |
206 | } else { | 208 | } else { |
@@ -221,6 +223,7 @@ __ext_tree_remove(struct rb_root *root, sector_t start, sector_t end) | |||
221 | struct pnfs_block_extent *next = ext_tree_next(be); | 223 | struct pnfs_block_extent *next = ext_tree_next(be); |
222 | 224 | ||
223 | rb_erase(&be->be_node, root); | 225 | rb_erase(&be->be_node, root); |
226 | nfs4_put_deviceid_node(be->be_device); | ||
224 | kfree(be); | 227 | kfree(be); |
225 | be = next; | 228 | be = next; |
226 | } | 229 | } |
@@ -265,6 +268,7 @@ retry: | |||
265 | __ext_tree_insert(root, new, true); | 268 | __ext_tree_insert(root, new, true); |
266 | } else if (new->be_f_offset >= be->be_f_offset) { | 269 | } else if (new->be_f_offset >= be->be_f_offset) { |
267 | if (ext_f_end(new) <= ext_f_end(be)) { | 270 | if (ext_f_end(new) <= ext_f_end(be)) { |
271 | nfs4_put_deviceid_node(new->be_device); | ||
268 | kfree(new); | 272 | kfree(new); |
269 | } else { | 273 | } else { |
270 | sector_t new_len = ext_f_end(new) - ext_f_end(be); | 274 | sector_t new_len = ext_f_end(new) - ext_f_end(be); |
@@ -290,6 +294,7 @@ retry: | |||
290 | } | 294 | } |
291 | 295 | ||
292 | split->be_length = be->be_f_offset - split->be_f_offset; | 296 | split->be_length = be->be_f_offset - split->be_f_offset; |
297 | split->be_device = nfs4_get_deviceid(new->be_device); | ||
293 | __ext_tree_insert(root, split, true); | 298 | __ext_tree_insert(root, split, true); |
294 | 299 | ||
295 | new->be_f_offset += diff; | 300 | new->be_f_offset += diff; |
@@ -380,9 +385,7 @@ ext_tree_split(struct rb_root *root, struct pnfs_block_extent *be, | |||
380 | new->be_length = orig_len - be->be_length; | 385 | new->be_length = orig_len - be->be_length; |
381 | new->be_state = be->be_state; | 386 | new->be_state = be->be_state; |
382 | new->be_tag = be->be_tag; | 387 | new->be_tag = be->be_tag; |
383 | 388 | new->be_device = nfs4_get_deviceid(be->be_device); | |
384 | new->be_mdev = be->be_mdev; | ||
385 | memcpy(&new->be_devid, &be->be_devid, sizeof(struct nfs4_deviceid)); | ||
386 | 389 | ||
387 | dprintk("%s: got 0x%lx:0x%lx!\n", | 390 | dprintk("%s: got 0x%lx:0x%lx!\n", |
388 | __func__, be->be_f_offset, ext_f_end(be)); | 391 | __func__, be->be_f_offset, ext_f_end(be)); |
@@ -495,7 +498,7 @@ ext_tree_encode_commit(struct pnfs_block_layout *bl, struct xdr_stream *xdr) | |||
495 | break; | 498 | break; |
496 | } | 499 | } |
497 | 500 | ||
498 | p = xdr_encode_opaque_fixed(p, be->be_devid.data, | 501 | p = xdr_encode_opaque_fixed(p, be->be_device->deviceid.data, |
499 | NFS4_DEVICEID4_SIZE); | 502 | NFS4_DEVICEID4_SIZE); |
500 | p = xdr_encode_hyper(p, be->be_f_offset << SECTOR_SHIFT); | 503 | p = xdr_encode_hyper(p, be->be_f_offset << SECTOR_SHIFT); |
501 | p = xdr_encode_hyper(p, be->be_length << SECTOR_SHIFT); | 504 | p = xdr_encode_hyper(p, be->be_length << SECTOR_SHIFT); |