diff options
author | Lars Ellenberg <lars.ellenberg@linbit.com> | 2015-03-26 15:53:55 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-11-25 11:22:02 -0500 |
commit | 63a7c8ad92af5f57d4a2c5be223d6ca424c3670b (patch) | |
tree | 4c9232f769b3fda758633add5d4ee5f559cf98a5 | |
parent | 088b70526d5b4080010147e4a6ae1252c3fc2228 (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.h | 2 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 16 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 121 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_worker.c | 2 | ||||
-rw-r--r-- | include/linux/drbd.h | 2 |
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 | |||
1126 | extern int drbd_send_bitmap(struct drbd_device *device); | 1126 | extern int drbd_send_bitmap(struct drbd_device *device); |
1127 | extern void drbd_send_sr_reply(struct drbd_peer_device *, enum drbd_state_rv retcode); | 1127 | extern void drbd_send_sr_reply(struct drbd_peer_device *, enum drbd_state_rv retcode); |
1128 | extern void conn_send_sr_reply(struct drbd_connection *connection, enum drbd_state_rv retcode); | 1128 | extern void conn_send_sr_reply(struct drbd_connection *connection, enum drbd_state_rv retcode); |
1129 | extern void drbd_free_ldev(struct drbd_backing_dev *ldev); | 1129 | extern void drbd_backing_dev_free(struct drbd_device *device, struct drbd_backing_dev *ldev); |
1130 | extern void drbd_device_cleanup(struct drbd_device *device); | 1130 | extern void drbd_device_cleanup(struct drbd_device *device); |
1131 | void drbd_print_uuids(struct drbd_device *device, const char *text); | 1131 | void 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 | ||
2967 | void 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 | |||
2979 | static void drbd_free_one_sock(struct drbd_socket *ds) | 2967 | static 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 | ||
1474 | static 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 | |||
1501 | static 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 | |||
1534 | static 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 | |||
1544 | void 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 | |||
1474 | int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info) | 1556 | int 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 | ||
53 | extern const char *drbd_buildtag(void); | 53 | extern 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 |