aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2014-09-03 00:28:00 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-09-10 15:47:04 -0400
commit20d655d6197d02e98574208839da11684dc2ad1f (patch)
tree0212cbd41504909d6921db5a661a10058b7ab61c /fs/nfs
parent30ff0603ca4d66c8244efc80ea8470d3d04aee8b (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.c149
-rw-r--r--fs/nfs/blocklayout/blocklayout.h25
-rw-r--r--fs/nfs/blocklayout/blocklayoutdev.c88
-rw-r--r--fs/nfs/blocklayout/blocklayoutdm.c26
-rw-r--r--fs/nfs/blocklayout/extent_tree.c27
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
518static 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 */
535static struct pnfs_block_dev *
536nfs4_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
599static int 520static int
600bl_set_layoutdriver(struct nfs_server *server, const struct nfs_fh *fh) 521bl_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
665static int
666bl_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
676static bool 538static 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
47struct block_mount_id {
48 spinlock_t bm_lock; /* protects list */
49 struct list_head bm_devlist; /* holds pnfs_block_dev */
50};
51
52struct pnfs_block_dev { 47struct 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
59enum exstate4 { 52enum 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
92static inline struct pnfs_block_layout * 82static inline struct pnfs_block_layout *
93BLK_LO2EXT(struct pnfs_layout_hdr *lo) 83BLK_LO2EXT(struct pnfs_layout_hdr *lo)
94{ 84{
@@ -120,14 +110,15 @@ struct bl_msg_hdr {
120/* blocklayoutdev.c */ 110/* blocklayoutdev.c */
121ssize_t bl_pipe_downcall(struct file *, const char __user *, size_t); 111ssize_t bl_pipe_downcall(struct file *, const char __user *, size_t);
122void bl_pipe_destroy_msg(struct rpc_pipe_msg *); 112void bl_pipe_destroy_msg(struct rpc_pipe_msg *);
123void nfs4_blkdev_put(struct block_device *bdev);
124struct pnfs_block_dev *nfs4_blk_decode_device(struct nfs_server *server,
125 struct pnfs_device *dev);
126int nfs4_blk_process_layoutget(struct pnfs_layout_hdr *lo, 113int 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
116struct nfs4_deviceid_node *bl_alloc_deviceid_node(struct nfs_server *server,
117 struct pnfs_device *pdev, gfp_t gfp_mask);
118void bl_free_deviceid_node(struct nfs4_deviceid_node *d);
119
129/* blocklayoutdm.c */ 120/* blocklayoutdm.c */
130void bl_free_block_dev(struct pnfs_block_dev *bdev); 121void bl_dm_remove(struct net *net, dev_t dev);
131 122
132/* extent_tree.c */ 123/* extent_tree.c */
133int ext_tree_insert(struct pnfs_block_layout *bl, 124int 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 */
59void 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
66ssize_t bl_pipe_downcall(struct file *filp, const char __user *src, 56ssize_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 */
95struct pnfs_block_dev * 85struct nfs4_deviceid_node *
96nfs4_blk_decode_device(struct nfs_server *server, 86bl_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
183out: 169out:
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 */ 174void
189static struct block_device *translate_devid(struct pnfs_layout_hdr *lo, 175bl_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
41static void dev_remove(struct net *net, dev_t dev) 41void 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)
82out: 82out:
83 kfree(msg->data); 83 kfree(msg->data);
84} 84}
85
86/*
87 * Release meta device
88 */
89static 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
96void 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;
158free_new:
159 nfs4_put_deviceid_node(new->be_device);
160 kfree(new);
157} 161}
158 162
159static int 163static 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);