aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Ellenberg <lars.ellenberg@linbit.com>2015-03-26 15:53:55 -0400
committerJens Axboe <axboe@fb.com>2015-11-25 11:22:02 -0500
commit63a7c8ad92af5f57d4a2c5be223d6ca424c3670b (patch)
tree4c9232f769b3fda758633add5d4ee5f559cf98a5
parent088b70526d5b4080010147e4a6ae1252c3fc2228 (diff)
drbd: make drbd known to lsblk: use bd_link_disk_holder
lsblk should be able to pick up stacking device driver relations involving DRBD conveniently. Even though upstream kernel since 2011 says "DON'T USE THIS UNLESS YOU'RE ALREADY USING IT." a new user has been added since (bcache), which sets the precedences for us to use it as well. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com> Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r--drivers/block/drbd/drbd_int.h2
-rw-r--r--drivers/block/drbd/drbd_main.c16
-rw-r--r--drivers/block/drbd/drbd_nl.c121
-rw-r--r--drivers/block/drbd/drbd_worker.c2
-rw-r--r--include/linux/drbd.h2
5 files changed, 91 insertions, 52 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 08f266eab3ee..a26265375e1e 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1126,7 +1126,7 @@ extern int drbd_send_ov_request(struct drbd_peer_device *, sector_t sector, int
1126extern int drbd_send_bitmap(struct drbd_device *device); 1126extern int drbd_send_bitmap(struct drbd_device *device);
1127extern void drbd_send_sr_reply(struct drbd_peer_device *, enum drbd_state_rv retcode); 1127extern void drbd_send_sr_reply(struct drbd_peer_device *, enum drbd_state_rv retcode);
1128extern void conn_send_sr_reply(struct drbd_connection *connection, enum drbd_state_rv retcode); 1128extern void conn_send_sr_reply(struct drbd_connection *connection, enum drbd_state_rv retcode);
1129extern void drbd_free_ldev(struct drbd_backing_dev *ldev); 1129extern void drbd_backing_dev_free(struct drbd_device *device, struct drbd_backing_dev *ldev);
1130extern void drbd_device_cleanup(struct drbd_device *device); 1130extern void drbd_device_cleanup(struct drbd_device *device);
1131void drbd_print_uuids(struct drbd_device *device, const char *text); 1131void drbd_print_uuids(struct drbd_device *device, const char *text);
1132 1132
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index a4aa7eb5507d..136fa733a15e 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -1992,7 +1992,7 @@ void drbd_device_cleanup(struct drbd_device *device)
1992 drbd_bm_cleanup(device); 1992 drbd_bm_cleanup(device);
1993 } 1993 }
1994 1994
1995 drbd_free_ldev(device->ldev); 1995 drbd_backing_dev_free(device, device->ldev);
1996 device->ldev = NULL; 1996 device->ldev = NULL;
1997 1997
1998 clear_bit(AL_SUSPENDED, &device->flags); 1998 clear_bit(AL_SUSPENDED, &device->flags);
@@ -2171,7 +2171,7 @@ void drbd_destroy_device(struct kref *kref)
2171 if (device->this_bdev) 2171 if (device->this_bdev)
2172 bdput(device->this_bdev); 2172 bdput(device->this_bdev);
2173 2173
2174 drbd_free_ldev(device->ldev); 2174 drbd_backing_dev_free(device, device->ldev);
2175 device->ldev = NULL; 2175 device->ldev = NULL;
2176 2176
2177 drbd_release_all_peer_reqs(device); 2177 drbd_release_all_peer_reqs(device);
@@ -2964,18 +2964,6 @@ fail:
2964 return err; 2964 return err;
2965} 2965}
2966 2966
2967void drbd_free_ldev(struct drbd_backing_dev *ldev)
2968{
2969 if (ldev == NULL)
2970 return;
2971
2972 blkdev_put(ldev->backing_bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
2973 blkdev_put(ldev->md_bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
2974
2975 kfree(ldev->disk_conf);
2976 kfree(ldev);
2977}
2978
2979static void drbd_free_one_sock(struct drbd_socket *ds) 2967static void drbd_free_one_sock(struct drbd_socket *ds)
2980{ 2968{
2981 struct socket *s; 2969 struct socket *s;
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 4703f1ad7f92..ee34739ee9ff 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1471,6 +1471,88 @@ success:
1471 return 0; 1471 return 0;
1472} 1472}
1473 1473
1474static struct block_device *open_backing_dev(struct drbd_device *device,
1475 const char *bdev_path, void *claim_ptr, bool do_bd_link)
1476{
1477 struct block_device *bdev;
1478 int err = 0;
1479
1480 bdev = blkdev_get_by_path(bdev_path,
1481 FMODE_READ | FMODE_WRITE | FMODE_EXCL, claim_ptr);
1482 if (IS_ERR(bdev)) {
1483 drbd_err(device, "open(\"%s\") failed with %ld\n",
1484 bdev_path, PTR_ERR(bdev));
1485 return bdev;
1486 }
1487
1488 if (!do_bd_link)
1489 return bdev;
1490
1491 err = bd_link_disk_holder(bdev, device->vdisk);
1492 if (err) {
1493 blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
1494 drbd_err(device, "bd_link_disk_holder(\"%s\", ...) failed with %d\n",
1495 bdev_path, err);
1496 bdev = ERR_PTR(err);
1497 }
1498 return bdev;
1499}
1500
1501static int open_backing_devices(struct drbd_device *device,
1502 struct disk_conf *new_disk_conf,
1503 struct drbd_backing_dev *nbc)
1504{
1505 struct block_device *bdev;
1506
1507 bdev = open_backing_dev(device, new_disk_conf->backing_dev, device, true);
1508 if (IS_ERR(bdev))
1509 return ERR_OPEN_DISK;
1510 nbc->backing_bdev = bdev;
1511
1512 /*
1513 * meta_dev_idx >= 0: external fixed size, possibly multiple
1514 * drbd sharing one meta device. TODO in that case, paranoia
1515 * check that [md_bdev, meta_dev_idx] is not yet used by some
1516 * other drbd minor! (if you use drbd.conf + drbdadm, that
1517 * should check it for you already; but if you don't, or
1518 * someone fooled it, we need to double check here)
1519 */
1520 bdev = open_backing_dev(device, new_disk_conf->meta_dev,
1521 /* claim ptr: device, if claimed exclusively; shared drbd_m_holder,
1522 * if potentially shared with other drbd minors */
1523 (new_disk_conf->meta_dev_idx < 0) ? (void*)device : (void*)drbd_m_holder,
1524 /* avoid double bd_claim_by_disk() for the same (source,target) tuple,
1525 * as would happen with internal metadata. */
1526 (new_disk_conf->meta_dev_idx != DRBD_MD_INDEX_FLEX_INT &&
1527 new_disk_conf->meta_dev_idx != DRBD_MD_INDEX_INTERNAL));
1528 if (IS_ERR(bdev))
1529 return ERR_OPEN_MD_DISK;
1530 nbc->md_bdev = bdev;
1531 return NO_ERROR;
1532}
1533
1534static void close_backing_dev(struct drbd_device *device, struct block_device *bdev,
1535 bool do_bd_unlink)
1536{
1537 if (!bdev)
1538 return;
1539 if (do_bd_unlink)
1540 bd_unlink_disk_holder(bdev, device->vdisk);
1541 blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
1542}
1543
1544void drbd_backing_dev_free(struct drbd_device *device, struct drbd_backing_dev *ldev)
1545{
1546 if (ldev == NULL)
1547 return;
1548
1549 close_backing_dev(device, ldev->md_bdev, ldev->md_bdev != ldev->backing_bdev);
1550 close_backing_dev(device, ldev->backing_bdev, true);
1551
1552 kfree(ldev->disk_conf);
1553 kfree(ldev);
1554}
1555
1474int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) 1556int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
1475{ 1557{
1476 struct drbd_config_context adm_ctx; 1558 struct drbd_config_context adm_ctx;
@@ -1484,7 +1566,6 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
1484 sector_t min_md_device_sectors; 1566 sector_t min_md_device_sectors;
1485 struct drbd_backing_dev *nbc = NULL; /* new_backing_conf */ 1567 struct drbd_backing_dev *nbc = NULL; /* new_backing_conf */
1486 struct disk_conf *new_disk_conf = NULL; 1568 struct disk_conf *new_disk_conf = NULL;
1487 struct block_device *bdev;
1488 struct lru_cache *resync_lru = NULL; 1569 struct lru_cache *resync_lru = NULL;
1489 struct fifo_buffer *new_plan = NULL; 1570 struct fifo_buffer *new_plan = NULL;
1490 union drbd_state ns, os; 1571 union drbd_state ns, os;
@@ -1572,35 +1653,9 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
1572 } 1653 }
1573 rcu_read_unlock(); 1654 rcu_read_unlock();
1574 1655
1575 bdev = blkdev_get_by_path(new_disk_conf->backing_dev, 1656 retcode = open_backing_devices(device, new_disk_conf, nbc);
1576 FMODE_READ | FMODE_WRITE | FMODE_EXCL, device); 1657 if (retcode != NO_ERROR)
1577 if (IS_ERR(bdev)) {
1578 drbd_err(device, "open(\"%s\") failed with %ld\n", new_disk_conf->backing_dev,
1579 PTR_ERR(bdev));
1580 retcode = ERR_OPEN_DISK;
1581 goto fail;
1582 }
1583 nbc->backing_bdev = bdev;
1584
1585 /*
1586 * meta_dev_idx >= 0: external fixed size, possibly multiple
1587 * drbd sharing one meta device. TODO in that case, paranoia
1588 * check that [md_bdev, meta_dev_idx] is not yet used by some
1589 * other drbd minor! (if you use drbd.conf + drbdadm, that
1590 * should check it for you already; but if you don't, or
1591 * someone fooled it, we need to double check here)
1592 */
1593 bdev = blkdev_get_by_path(new_disk_conf->meta_dev,
1594 FMODE_READ | FMODE_WRITE | FMODE_EXCL,
1595 (new_disk_conf->meta_dev_idx < 0) ?
1596 (void *)device : (void *)drbd_m_holder);
1597 if (IS_ERR(bdev)) {
1598 drbd_err(device, "open(\"%s\") failed with %ld\n", new_disk_conf->meta_dev,
1599 PTR_ERR(bdev));
1600 retcode = ERR_OPEN_MD_DISK;
1601 goto fail; 1658 goto fail;
1602 }
1603 nbc->md_bdev = bdev;
1604 1659
1605 if ((nbc->backing_bdev == nbc->md_bdev) != 1660 if ((nbc->backing_bdev == nbc->md_bdev) !=
1606 (new_disk_conf->meta_dev_idx == DRBD_MD_INDEX_INTERNAL || 1661 (new_disk_conf->meta_dev_idx == DRBD_MD_INDEX_INTERNAL ||
@@ -1900,12 +1955,8 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
1900 fail: 1955 fail:
1901 conn_reconfig_done(connection); 1956 conn_reconfig_done(connection);
1902 if (nbc) { 1957 if (nbc) {
1903 if (nbc->backing_bdev) 1958 close_backing_dev(device, nbc->md_bdev, nbc->md_bdev != nbc->backing_bdev);
1904 blkdev_put(nbc->backing_bdev, 1959 close_backing_dev(device, nbc->backing_bdev, true);
1905 FMODE_READ | FMODE_WRITE | FMODE_EXCL);
1906 if (nbc->md_bdev)
1907 blkdev_put(nbc->md_bdev,
1908 FMODE_READ | FMODE_WRITE | FMODE_EXCL);
1909 kfree(nbc); 1960 kfree(nbc);
1910 } 1961 }
1911 kfree(new_disk_conf); 1962 kfree(new_disk_conf);
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 2f29bf3e4dba..eff716c27b1f 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -1841,7 +1841,7 @@ static void drbd_ldev_destroy(struct drbd_device *device)
1841 device->act_log = NULL; 1841 device->act_log = NULL;
1842 1842
1843 __acquire(local); 1843 __acquire(local);
1844 drbd_free_ldev(device->ldev); 1844 drbd_backing_dev_free(device, device->ldev);
1845 device->ldev = NULL; 1845 device->ldev = NULL;
1846 __release(local); 1846 __release(local);
1847 1847
diff --git a/include/linux/drbd.h b/include/linux/drbd.h
index 392fc0edb516..d6b3c9943a2c 100644
--- a/include/linux/drbd.h
+++ b/include/linux/drbd.h
@@ -51,7 +51,7 @@
51#endif 51#endif
52 52
53extern const char *drbd_buildtag(void); 53extern const char *drbd_buildtag(void);
54#define REL_VERSION "8.4.5" 54#define REL_VERSION "8.4.6"
55#define API_VERSION 1 55#define API_VERSION 1
56#define PRO_VERSION_MIN 86 56#define PRO_VERSION_MIN 86
57#define PRO_VERSION_MAX 101 57#define PRO_VERSION_MAX 101