diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2011-04-12 01:53:32 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-11-08 10:45:16 -0500 |
commit | 695d08fa94ce5bb8d9880e260445fbcf50fa41b4 (patch) | |
tree | dda7776d2ad2db3414a9377ae485c6e33575804d /drivers/block/drbd/drbd_nl.c | |
parent | cd1d9950f69b46d88002b39652ed0cf3608d008b (diff) |
drbd: rcu_read_[un]lock() for all idr accesses that do not sleep
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block/drbd/drbd_nl.c')
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index f08fb6f49cd8..60c171b17156 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c | |||
@@ -372,12 +372,14 @@ static enum drbd_fencing_p highest_fencing_policy(struct drbd_tconn *tconn) | |||
372 | struct drbd_conf *mdev; | 372 | struct drbd_conf *mdev; |
373 | int vnr; | 373 | int vnr; |
374 | 374 | ||
375 | rcu_read_lock(); | ||
375 | idr_for_each_entry(&tconn->volumes, mdev, vnr) { | 376 | idr_for_each_entry(&tconn->volumes, mdev, vnr) { |
376 | if (get_ldev_if_state(mdev, D_CONSISTENT)) { | 377 | if (get_ldev_if_state(mdev, D_CONSISTENT)) { |
377 | fp = max_t(enum drbd_fencing_p, fp, mdev->ldev->dc.fencing); | 378 | fp = max_t(enum drbd_fencing_p, fp, mdev->ldev->dc.fencing); |
378 | put_ldev(mdev); | 379 | put_ldev(mdev); |
379 | } | 380 | } |
380 | } | 381 | } |
382 | rcu_read_unlock(); | ||
381 | 383 | ||
382 | return fp; | 384 | return fp; |
383 | } | 385 | } |
@@ -1624,29 +1626,41 @@ out: | |||
1624 | static bool conn_resync_running(struct drbd_tconn *tconn) | 1626 | static bool conn_resync_running(struct drbd_tconn *tconn) |
1625 | { | 1627 | { |
1626 | struct drbd_conf *mdev; | 1628 | struct drbd_conf *mdev; |
1629 | bool rv = false; | ||
1627 | int vnr; | 1630 | int vnr; |
1628 | 1631 | ||
1632 | rcu_read_lock(); | ||
1629 | idr_for_each_entry(&tconn->volumes, mdev, vnr) { | 1633 | idr_for_each_entry(&tconn->volumes, mdev, vnr) { |
1630 | if (mdev->state.conn == C_SYNC_SOURCE || | 1634 | if (mdev->state.conn == C_SYNC_SOURCE || |
1631 | mdev->state.conn == C_SYNC_TARGET || | 1635 | mdev->state.conn == C_SYNC_TARGET || |
1632 | mdev->state.conn == C_PAUSED_SYNC_S || | 1636 | mdev->state.conn == C_PAUSED_SYNC_S || |
1633 | mdev->state.conn == C_PAUSED_SYNC_T) | 1637 | mdev->state.conn == C_PAUSED_SYNC_T) { |
1634 | return true; | 1638 | rv = true; |
1639 | break; | ||
1640 | } | ||
1635 | } | 1641 | } |
1636 | return false; | 1642 | rcu_read_unlock(); |
1643 | |||
1644 | return rv; | ||
1637 | } | 1645 | } |
1638 | 1646 | ||
1639 | static bool conn_ov_running(struct drbd_tconn *tconn) | 1647 | static bool conn_ov_running(struct drbd_tconn *tconn) |
1640 | { | 1648 | { |
1641 | struct drbd_conf *mdev; | 1649 | struct drbd_conf *mdev; |
1650 | bool rv = false; | ||
1642 | int vnr; | 1651 | int vnr; |
1643 | 1652 | ||
1653 | rcu_read_lock(); | ||
1644 | idr_for_each_entry(&tconn->volumes, mdev, vnr) { | 1654 | idr_for_each_entry(&tconn->volumes, mdev, vnr) { |
1645 | if (mdev->state.conn == C_VERIFY_S || | 1655 | if (mdev->state.conn == C_VERIFY_S || |
1646 | mdev->state.conn == C_VERIFY_T) | 1656 | mdev->state.conn == C_VERIFY_T) { |
1647 | return true; | 1657 | rv = true; |
1658 | break; | ||
1659 | } | ||
1648 | } | 1660 | } |
1649 | return false; | 1661 | rcu_read_unlock(); |
1662 | |||
1663 | return rv; | ||
1650 | } | 1664 | } |
1651 | 1665 | ||
1652 | int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info) | 1666 | int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info) |
@@ -1858,26 +1872,28 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info) | |||
1858 | goto fail; | 1872 | goto fail; |
1859 | } | 1873 | } |
1860 | 1874 | ||
1875 | rcu_read_lock(); | ||
1861 | idr_for_each_entry(&tconn->volumes, mdev, i) { | 1876 | idr_for_each_entry(&tconn->volumes, mdev, i) { |
1862 | if (get_ldev(mdev)) { | 1877 | if (get_ldev(mdev)) { |
1863 | enum drbd_fencing_p fp = mdev->ldev->dc.fencing; | 1878 | enum drbd_fencing_p fp = mdev->ldev->dc.fencing; |
1864 | put_ldev(mdev); | 1879 | put_ldev(mdev); |
1865 | if (new_conf->wire_protocol == DRBD_PROT_A && fp == FP_STONITH) { | 1880 | if (new_conf->wire_protocol == DRBD_PROT_A && fp == FP_STONITH) { |
1866 | retcode = ERR_STONITH_AND_PROT_A; | 1881 | retcode = ERR_STONITH_AND_PROT_A; |
1867 | goto fail; | 1882 | goto fail_rcu_unlock; |
1868 | } | 1883 | } |
1869 | } | 1884 | } |
1870 | if (mdev->state.role == R_PRIMARY && new_conf->want_lose) { | 1885 | if (mdev->state.role == R_PRIMARY && new_conf->want_lose) { |
1871 | retcode = ERR_DISCARD; | 1886 | retcode = ERR_DISCARD; |
1872 | goto fail; | 1887 | goto fail_rcu_unlock; |
1873 | } | 1888 | } |
1874 | if (!mdev->bitmap) { | 1889 | if (!mdev->bitmap) { |
1875 | if(drbd_bm_init(mdev)) { | 1890 | if(drbd_bm_init(mdev)) { |
1876 | retcode = ERR_NOMEM; | 1891 | retcode = ERR_NOMEM; |
1877 | goto fail; | 1892 | goto fail_rcu_unlock; |
1878 | } | 1893 | } |
1879 | } | 1894 | } |
1880 | } | 1895 | } |
1896 | rcu_read_unlock(); | ||
1881 | 1897 | ||
1882 | if (new_conf->on_congestion != OC_BLOCK && new_conf->wire_protocol != DRBD_PROT_A) { | 1898 | if (new_conf->on_congestion != OC_BLOCK && new_conf->wire_protocol != DRBD_PROT_A) { |
1883 | retcode = ERR_CONG_NOT_PROTO_A; | 1899 | retcode = ERR_CONG_NOT_PROTO_A; |
@@ -1991,15 +2007,19 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info) | |||
1991 | retcode = _conn_request_state(tconn, NS(conn, C_UNCONNECTED), CS_VERBOSE); | 2007 | retcode = _conn_request_state(tconn, NS(conn, C_UNCONNECTED), CS_VERBOSE); |
1992 | spin_unlock_irq(&tconn->req_lock); | 2008 | spin_unlock_irq(&tconn->req_lock); |
1993 | 2009 | ||
2010 | rcu_read_lock(); | ||
1994 | idr_for_each_entry(&tconn->volumes, mdev, i) { | 2011 | idr_for_each_entry(&tconn->volumes, mdev, i) { |
1995 | mdev->send_cnt = 0; | 2012 | mdev->send_cnt = 0; |
1996 | mdev->recv_cnt = 0; | 2013 | mdev->recv_cnt = 0; |
1997 | kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE); | 2014 | kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE); |
1998 | } | 2015 | } |
2016 | rcu_read_unlock(); | ||
1999 | conn_reconfig_done(tconn); | 2017 | conn_reconfig_done(tconn); |
2000 | drbd_adm_finish(info, retcode); | 2018 | drbd_adm_finish(info, retcode); |
2001 | return 0; | 2019 | return 0; |
2002 | 2020 | ||
2021 | fail_rcu_unlock: | ||
2022 | rcu_read_unlock(); | ||
2003 | fail: | 2023 | fail: |
2004 | kfree(int_dig_in); | 2024 | kfree(int_dig_in); |
2005 | kfree(int_dig_vv); | 2025 | kfree(int_dig_vv); |
@@ -2562,8 +2582,6 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb) | |||
2562 | 2582 | ||
2563 | /* synchronize with drbd_new_tconn/drbd_free_tconn */ | 2583 | /* synchronize with drbd_new_tconn/drbd_free_tconn */ |
2564 | mutex_lock(&drbd_cfg_mutex); | 2584 | mutex_lock(&drbd_cfg_mutex); |
2565 | /* synchronize with drbd_delete_device */ | ||
2566 | rcu_read_lock(); | ||
2567 | next_tconn: | 2585 | next_tconn: |
2568 | /* revalidate iterator position */ | 2586 | /* revalidate iterator position */ |
2569 | list_for_each_entry(tmp, &drbd_tconns, all_tconn) { | 2587 | list_for_each_entry(tmp, &drbd_tconns, all_tconn) { |
@@ -2624,7 +2642,6 @@ next_tconn: | |||
2624 | } | 2642 | } |
2625 | 2643 | ||
2626 | out: | 2644 | out: |
2627 | rcu_read_unlock(); | ||
2628 | mutex_unlock(&drbd_cfg_mutex); | 2645 | mutex_unlock(&drbd_cfg_mutex); |
2629 | /* where to start the next iteration */ | 2646 | /* where to start the next iteration */ |
2630 | cb->args[0] = (long)pos; | 2647 | cb->args[0] = (long)pos; |