md: document lifetime of internal rdev pointer.
The rdev pointer kept in the local 'config' for each for raid1, raid10, raid4/5/6 has non-obvious lifetime rules. Sometimes RCU is needed, sometimes a lock, something nothing. Add documentation to explain this. Signed-off-by: NeilBrown <neilb@suse.com> Signed-off-by: Shaohua Li <sh.li@alibaba-inc.com>
This commit is contained in:
parent
4b6c1060ea
commit
f2785b527c
|
@ -26,6 +26,18 @@
|
||||||
#define BARRIER_BUCKETS_NR_BITS (PAGE_SHIFT - ilog2(sizeof(atomic_t)))
|
#define BARRIER_BUCKETS_NR_BITS (PAGE_SHIFT - ilog2(sizeof(atomic_t)))
|
||||||
#define BARRIER_BUCKETS_NR (1<<BARRIER_BUCKETS_NR_BITS)
|
#define BARRIER_BUCKETS_NR (1<<BARRIER_BUCKETS_NR_BITS)
|
||||||
|
|
||||||
|
/* Note: raid1_info.rdev can be set to NULL asynchronously by raid1_remove_disk.
|
||||||
|
* There are three safe ways to access raid1_info.rdev.
|
||||||
|
* 1/ when holding mddev->reconfig_mutex
|
||||||
|
* 2/ when resync/recovery is known to be happening - i.e. in code that is
|
||||||
|
* called as part of performing resync/recovery.
|
||||||
|
* 3/ while holding rcu_read_lock(), use rcu_dereference to get the pointer
|
||||||
|
* and if it is non-NULL, increment rdev->nr_pending before dropping the
|
||||||
|
* RCU lock.
|
||||||
|
* When .rdev is set to NULL, the nr_pending count checked again and if it has
|
||||||
|
* been incremented, the pointer is put back in .rdev.
|
||||||
|
*/
|
||||||
|
|
||||||
struct raid1_info {
|
struct raid1_info {
|
||||||
struct md_rdev *rdev;
|
struct md_rdev *rdev;
|
||||||
sector_t head_position;
|
sector_t head_position;
|
||||||
|
|
|
@ -2,6 +2,19 @@
|
||||||
#ifndef _RAID10_H
|
#ifndef _RAID10_H
|
||||||
#define _RAID10_H
|
#define _RAID10_H
|
||||||
|
|
||||||
|
/* Note: raid10_info.rdev can be set to NULL asynchronously by
|
||||||
|
* raid10_remove_disk.
|
||||||
|
* There are three safe ways to access raid10_info.rdev.
|
||||||
|
* 1/ when holding mddev->reconfig_mutex
|
||||||
|
* 2/ when resync/recovery/reshape is known to be happening - i.e. in code
|
||||||
|
* that is called as part of performing resync/recovery/reshape.
|
||||||
|
* 3/ while holding rcu_read_lock(), use rcu_dereference to get the pointer
|
||||||
|
* and if it is non-NULL, increment rdev->nr_pending before dropping the
|
||||||
|
* RCU lock.
|
||||||
|
* When .rdev is set to NULL, the nr_pending count checked again and if it has
|
||||||
|
* been incremented, the pointer is put back in .rdev.
|
||||||
|
*/
|
||||||
|
|
||||||
struct raid10_info {
|
struct raid10_info {
|
||||||
struct md_rdev *rdev, *replacement;
|
struct md_rdev *rdev, *replacement;
|
||||||
sector_t head_position;
|
sector_t head_position;
|
||||||
|
|
|
@ -450,6 +450,18 @@ enum {
|
||||||
* HANDLE gets cleared if stripe_handle leaves nothing locked.
|
* HANDLE gets cleared if stripe_handle leaves nothing locked.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Note: disk_info.rdev can be set to NULL asynchronously by raid5_remove_disk.
|
||||||
|
* There are three safe ways to access disk_info.rdev.
|
||||||
|
* 1/ when holding mddev->reconfig_mutex
|
||||||
|
* 2/ when resync/recovery/reshape is known to be happening - i.e. in code that
|
||||||
|
* is called as part of performing resync/recovery/reshape.
|
||||||
|
* 3/ while holding rcu_read_lock(), use rcu_dereference to get the pointer
|
||||||
|
* and if it is non-NULL, increment rdev->nr_pending before dropping the RCU
|
||||||
|
* lock.
|
||||||
|
* When .rdev is set to NULL, the nr_pending count checked again and if
|
||||||
|
* it has been incremented, the pointer is put back in .rdev.
|
||||||
|
*/
|
||||||
|
|
||||||
struct disk_info {
|
struct disk_info {
|
||||||
struct md_rdev *rdev, *replacement;
|
struct md_rdev *rdev, *replacement;
|
||||||
struct page *extra_page; /* extra page to use in prexor */
|
struct page *extra_page; /* extra page to use in prexor */
|
||||||
|
|
Loading…
Reference in New Issue