Skip to content

Commit 3c0ee63

Browse files
committed
md: use sysfs_notify_dirent to notify changes to md/dev-xxx/state
The 'state' file for a device reports, for example, when the device has failed. Changes should be reported to userspace ASAP without the possibility of blocking on low-memory. sysfs_notify does have that possibility (as it takes a mutex which can be held across a kmalloc) so use sysfs_notify_dirent instead. Signed-off-by: NeilBrown <[email protected]>
1 parent b62b759 commit 3c0ee63

File tree

2 files changed

+15
-9
lines changed

2 files changed

+15
-9
lines changed

drivers/md/md.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,6 +1462,8 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
14621462
kobject_del(&rdev->kobj);
14631463
goto fail;
14641464
}
1465+
rdev->sysfs_state = sysfs_get_dirent(rdev->kobj.sd, "state");
1466+
14651467
list_add_rcu(&rdev->same_set, &mddev->disks);
14661468
bd_claim_by_disk(rdev->bdev, rdev->bdev->bd_holder, mddev->gendisk);
14671469
return 0;
@@ -1491,7 +1493,8 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev)
14911493
printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b));
14921494
rdev->mddev = NULL;
14931495
sysfs_remove_link(&rdev->kobj, "block");
1494-
1496+
sysfs_put(rdev->sysfs_state);
1497+
rdev->sysfs_state = NULL;
14951498
/* We need to delay this, otherwise we can deadlock when
14961499
* writing to 'remove' to "dev/state". We also need
14971500
* to delay it due to rcu usage.
@@ -1926,8 +1929,8 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
19261929

19271930
err = 0;
19281931
}
1929-
if (!err)
1930-
sysfs_notify(&rdev->kobj, NULL, "state");
1932+
if (!err && rdev->sysfs_state)
1933+
sysfs_notify_dirent(rdev->sysfs_state);
19311934
return err ? err : len;
19321935
}
19331936
static struct rdev_sysfs_entry rdev_state =
@@ -2022,7 +2025,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
20222025
rdev->raid_disk = -1;
20232026
return err;
20242027
} else
2025-
sysfs_notify(&rdev->kobj, NULL, "state");
2028+
sysfs_notify_dirent(rdev->sysfs_state);
20262029
sprintf(nm, "rd%d", rdev->raid_disk);
20272030
if (sysfs_create_link(&rdev->mddev->kobj, &rdev->kobj, nm))
20282031
printk(KERN_WARNING
@@ -2039,7 +2042,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
20392042
clear_bit(Faulty, &rdev->flags);
20402043
clear_bit(WriteMostly, &rdev->flags);
20412044
set_bit(In_sync, &rdev->flags);
2042-
sysfs_notify(&rdev->kobj, NULL, "state");
2045+
sysfs_notify_dirent(rdev->sysfs_state);
20432046
}
20442047
return len;
20452048
}
@@ -3583,7 +3586,7 @@ static int do_md_run(mddev_t * mddev)
35833586
return -EINVAL;
35843587
}
35853588
}
3586-
sysfs_notify(&rdev->kobj, NULL, "state");
3589+
sysfs_notify_dirent(rdev->sysfs_state);
35873590
}
35883591

35893592
md_probe(mddev->unit, NULL, NULL);
@@ -4302,7 +4305,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
43024305
if (err)
43034306
export_rdev(rdev);
43044307
else
4305-
sysfs_notify(&rdev->kobj, NULL, "state");
4308+
sysfs_notify_dirent(rdev->sysfs_state);
43064309

43074310
md_update_sb(mddev, 1);
43084311
if (mddev->degraded)
@@ -6113,7 +6116,7 @@ void md_check_recovery(mddev_t *mddev)
61136116

61146117
rdev_for_each(rdev, rtmp, mddev)
61156118
if (test_and_clear_bit(StateChanged, &rdev->flags))
6116-
sysfs_notify(&rdev->kobj, NULL, "state");
6119+
sysfs_notify_dirent(rdev->sysfs_state);
61176120

61186121

61196122
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
@@ -6223,7 +6226,7 @@ void md_check_recovery(mddev_t *mddev)
62236226

62246227
void md_wait_for_blocked_rdev(mdk_rdev_t *rdev, mddev_t *mddev)
62256228
{
6226-
sysfs_notify(&rdev->kobj, NULL, "state");
6229+
sysfs_notify_dirent(rdev->sysfs_state);
62276230
wait_event_timeout(rdev->blocked_wait,
62286231
!test_bit(Blocked, &rdev->flags),
62296232
msecs_to_jiffies(5000));

include/linux/raid/md_k.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ struct mdk_rdev_s
115115
* in superblock.
116116
*/
117117
struct work_struct del_work; /* used for delayed sysfs removal */
118+
119+
struct sysfs_dirent *sysfs_state; /* handle for 'state'
120+
* sysfs entry */
118121
};
119122

120123
struct mddev_s

0 commit comments

Comments
 (0)