The patch titled md: fix issues with referencing rdev in md/raid1 has been removed from the -mm tree. Its filename is md-fix-issues-with-referencing-rdev-in-md-raid1.patch This patch was dropped because an updated version was merged ------------------------------------------------------ Subject: md: fix issues with referencing rdev in md/raid1 From: NeilBrown <neilb@xxxxxxx> We need to be careful when referencing mirrors[i].rdev. so it can disappear under us at various times. So: fix a couple of problem places. comment a couple of non-problem places move an 'atomic_add' which deferences rdev down a little way to some where where it is sure to not be NULL. Signed-off-by: Neil Brown <neilb@xxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxx> --- drivers/md/raid1.c | 55 ++++++++++++++++++++++++++----------------- 1 files changed, 34 insertions(+), 21 deletions(-) diff -puN drivers/md/raid1.c~md-fix-issues-with-referencing-rdev-in-md-raid1 drivers/md/raid1.c --- a/drivers/md/raid1.c~md-fix-issues-with-referencing-rdev-in-md-raid1 +++ a/drivers/md/raid1.c @@ -930,10 +930,13 @@ static void status(struct seq_file *seq, seq_printf(seq, " [%d/%d] [", conf->raid_disks, conf->raid_disks - mddev->degraded); - for (i = 0; i < conf->raid_disks; i++) + rcu_read_lock(); + for (i = 0; i < conf->raid_disks; i++) { + mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); seq_printf(seq, "%s", - conf->mirrors[i].rdev && - test_bit(In_sync, &conf->mirrors[i].rdev->flags) ? "U" : "_"); + rdev && test_bit(In_sync, &rdev->flags) ? "U" : "_"); + } + rcu_read_unlock(); seq_printf(seq, "]"); } @@ -976,7 +979,6 @@ static void error(mddev_t *mddev, mdk_rd static void print_conf(conf_t *conf) { int i; - mirror_info_t *tmp; printk("RAID1 conf printout:\n"); if (!conf) { @@ -986,14 +988,17 @@ static void print_conf(conf_t *conf) printk(" --- wd:%d rd:%d\n", conf->raid_disks - conf->mddev->degraded, conf->raid_disks); + rcu_read_lock(); for (i = 0; i < conf->raid_disks; i++) { char b[BDEVNAME_SIZE]; - tmp = conf->mirrors + i; - if (tmp->rdev) + mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); + if (rdev) printk(" disk %d, wo:%d, o:%d, dev:%s\n", - i, !test_bit(In_sync, &tmp->rdev->flags), !test_bit(Faulty, &tmp->rdev->flags), - bdevname(tmp->rdev->bdev,b)); + i, !test_bit(In_sync, &rdev->flags), + !test_bit(Faulty, &rdev->flags), + bdevname(rdev->bdev,b)); } + rcu_read_unlock(); } static void close_sync(conf_t *conf) @@ -1009,17 +1014,17 @@ static int raid1_spare_active(mddev_t *m { int i; conf_t *conf = mddev->private; - mirror_info_t *tmp; /* * Find all failed disks within the RAID1 configuration - * and mark them readable + * and mark them readable. + * Called under mddev lock, so rcu protection not needed. */ for (i = 0; i < conf->raid_disks; i++) { - tmp = conf->mirrors + i; - if (tmp->rdev - && !test_bit(Faulty, &tmp->rdev->flags) - && !test_and_set_bit(In_sync, &tmp->rdev->flags)) { + mdk_rdev_t *rdev = conf->mirrors[i].rdev; + if (rdev + && !test_bit(Faulty, &rdev->flags) + && !test_and_set_bit(In_sync, &rdev->flags)) { unsigned long flags; spin_lock_irqsave(&conf->device_lock, flags); mddev->degraded--; @@ -1239,7 +1244,7 @@ static void sync_request_write(mddev_t * /* ouch - failed to read all of that. * Try some synchronous reads of other devices to get * good data, much like with normal read errors. Only - * read into the pages we already have so they we don't + * read into the pages we already have so we don't * need to re-issue the read request. * We don't need to freeze the array, because being in an * active sync request, there is no normal IO, and @@ -1259,6 +1264,10 @@ static void sync_request_write(mddev_t * s = PAGE_SIZE >> 9; do { if (r1_bio->bios[d]->bi_end_io == end_sync_read) { + /* No rcu protection needed here devices + * can only be removed when no resync is + * active, and resync is currently active + */ rdev = conf->mirrors[d].rdev; if (sync_page_io(rdev->bdev, sect + rdev->data_offset, @@ -1376,6 +1385,11 @@ static void fix_read_error(conf_t *conf, s = PAGE_SIZE >> 9; do { + /* Note: no rcu protection needed here + * as this is synchronous in the raid1d thread + * which is the thread that might remove + * a device. If raid1d ever becomes multi-threaded.... + */ rdev = conf->mirrors[d].rdev; if (rdev && test_bit(In_sync, &rdev->flags) && @@ -1403,7 +1417,6 @@ static void fix_read_error(conf_t *conf, d = conf->raid_disks; d--; rdev = conf->mirrors[d].rdev; - atomic_add(s, &rdev->corrected_errors); if (rdev && test_bit(In_sync, &rdev->flags)) { if (sync_page_io(rdev->bdev, @@ -1429,7 +1442,8 @@ static void fix_read_error(conf_t *conf, == 0) /* Well, this device is dead */ md_error(mddev, rdev); - else + else { + atomic_add(s, &rdev->corrected_errors); printk(KERN_INFO "raid1:%s: read error corrected " "(%d sectors at %llu on %s)\n", @@ -1437,6 +1451,7 @@ static void fix_read_error(conf_t *conf, (unsigned long long)sect + rdev->data_offset, bdevname(rdev->bdev, b)); + } } } sectors -= s; @@ -1806,19 +1821,17 @@ static sector_t sync_request(mddev_t *md for (i=0; i<conf->raid_disks; i++) { bio = r1_bio->bios[i]; if (bio->bi_end_io == end_sync_read) { - md_sync_acct(conf->mirrors[i].rdev->bdev, nr_sectors); + md_sync_acct(bio->bi_bdev, nr_sectors); generic_make_request(bio); } } } else { atomic_set(&r1_bio->remaining, 1); bio = r1_bio->bios[r1_bio->read_disk]; - md_sync_acct(conf->mirrors[r1_bio->read_disk].rdev->bdev, - nr_sectors); + md_sync_acct(bio->bi_bdev, nr_sectors); generic_make_request(bio); } - return nr_sectors; } _ Patches currently in -mm which might be from neilb@xxxxxxx are lockdep-fix-blkdev_open-warning.patch md-avoid-backward-event-updates-in-md-superblock-when-degraded.patch md-fix-recent-breakage-of-md-raid1-array-checking.patch vfs-destroy-the-dentries-contributed-by-a-superblock-on-unmounting.patch knfsd-knfsd-add-some-missing-newlines-in-printks.patch knfsd-knfsd-remove-an-unused-variable-from-e_show.patch knfsd-knfsd-remove-an-unused-variable-from-auth_unix_lookup.patch knfsd-add-a-callback-for-when-last-rpc-thread-finishes.patch knfsd-add-a-callback-for-when-last-rpc-thread-finishes-tidy.patch knfsd-be-more-selective-in-which-sockets-lockd-listens-on.patch knfsd-remove-nfsd_versbits-as-intermediate-storage-for-desired-versions.patch knfsd-separate-out-some-parts-of-nfsd_svc-which-start-nfs-servers.patch knfsd-separate-out-some-parts-of-nfsd_svc-which-start-nfs-servers-tweaks.patch knfsd-define-new-nfsdfs-file-portlist-contains-list-of-ports.patch knfsd-define-new-nfsdfs-file-portlist-contains-list-of-ports-tidy.patch knfsd-define-new-nfsdfs-file-portlist-contains-list-of-ports-fix.patch knfsd-allow-sockets-to-be-passed-to-nfsd-via-portlist.patch knfsd-use-seq_start_token-instead-of-hardcoded-magic-void1.patch knfsd-have-ext2-reject-file-handles-with-bad-inode-numbers-early.patch knfsd-have-ext2-reject-file-handles-with-bad-inode-numbers-early-tidy.patch knfsd-make-ext3-reject-filehandles-referring-to-invalid-inode-numbers.patch knfsd-make-ext3-reject-filehandles-referring-to-invalid-inode-numbers-tidy.patch knfsd-drop-serv-option-to-svc_recv-and-svc_process.patch knfsd-drop-serv-option-to-svc_recv-and-svc_process-nfs-callback-fix-nfs-callback-fix.patch knfsd-check-return-value-of-lockd_up-in-write_ports.patch knfsd-move-makesock-failed-warning-into-make_socks.patch knfsd-correctly-handle-error-condition-from-lockd_up.patch knfsd-move-tempsock-aging-to-a-timer.patch knfsd-move-tempsock-aging-to-a-timer-tidy.patch knfsd-convert-sk_inuse-to-atomic_t.patch knfsd-use-new-lock-for-svc_sock-deferred-list.patch knfsd-convert-sk_reserved-to-atomic_t.patch knfsd-test-and-set-sk_busy-atomically.patch knfsd-split-svc_serv-into-pools.patch knfsd-split-svc_serv-into-pools-fix.patch knfsd-add-svc_get.patch knfsd-add-svc_set_num_threads.patch knfsd-use-svc_set_num_threads-to-manage-threads-in-knfsd.patch knfsd-make-rpc-threads-pools-numa-aware.patch knfsd-make-rpc-threads-pools-numa-aware-fix.patch knfsd-allow-admin-to-set-nthreads-per-node.patch nfsd-lockdep-annotation.patch knfsd-nfsd-lockdep-annotation-fix.patch knfsd-call-lockd_down-when-closing-a-socket-via-a-write-to-nfsd-portlist.patch knfsd-protect-update-to-sn_nrthreads-with-lock_kernel.patch knfsd-fixed-handling-of-lockd-fail-when-adding-nfsd-socket.patch knfsd-replace-two-page-lists-in-struct-svc_rqst-with-one.patch knfsd-avoid-excess-stack-usage-in-svc_tcp_recvfrom.patch knfsd-prepare-knfsd-for-support-of-rsize-wsize-of-up-to-1mb-over-tcp.patch knfsd-allow-max-size-of-nfsd-payload-to-be-configured.patch knfsd-make-nfsd-readahead-params-cache-smp-friendly.patch knfsd-knfsd-cache-ipmap-per-tcp-socket.patch md-the-scheduled-removal-of-the-start_array-ioctl-for-md.patch md-fix-a-comment-that-is-wrong-in-raid5h.patch md-factor-out-part-of-raid1d-into-a-separate-function.patch md-factor-out-part-of-raid10d-into-a-separate-function.patch md-replace-magic-numbers-in-sb_dirty-with-well-defined-bit-flags.patch md-remove-the-working_disks-and-failed_disks-from-raid5-state-data.patch md-remove-working_disks-from-raid10-state.patch md-remove-working_disks-from-raid1-state-data.patch md-improve-locking-around-error-handling.patch md-fix-issues-with-referencing-rdev-in-md-raid1.patch md-new-sysfs-interface-for-setting-bits-in-the-write-intent-bitmap.patch md-remove-unnecessary-variable-x-in-stripe_to_pdidx.patch md-dm-reduce-stack-usage-with-stacked-block-devices.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html