mirror of
https://github.com/torvalds/linux.git
synced 2026-08-01 03:59:40 +02:00
for-5.19/drivers-2022-06-02
-----BEGIN PGP SIGNATURE-----
iQJEBAABCAAuFiEEwPw5LcreJtl1+l5K99NY+ylx4KYFAmKZmkoQHGF4Ym9lQGtl
cm5lbC5kawAKCRD301j7KXHgpqyrD/4iyg2ULBPyljLoM3Ed8AONbrFBApenKDFN
FjiFRZNll8zvJLTtP0GQqJIrljPuRlqb0IkbgqXl+yvPZ+wpB9HgIe2aohkOaqqJ
KS49UNR/aIHwC2y7lwlcsdgVqqoPdc4wnZeaQvCsWPCBhCca/k0kR7s3uEhHMK92
OWpV9osl/thLfOBwwt4IEaO1Koz8PM/fCR4XA2KLbs8E4P8EcSFglqi0ap7foLNr
pQAJIlPjkmF6nw4xg5fdBjVBo//kVcuf9IBMi5/XinmUL1taFAcn5WyeOvBbi0Fs
Sqp/pKkveM8xWZKrDyA/wf8nzRNpBBl6TOQEMFtV6FkZrij3pbKHlCiyL2gBR13e
5gkbVvXgtdqDVlnqlvIV/Swfh5YQFtn7+vlHFOUjP+iObsBRo4fTvDhPTLoO/VCf
tIAA7xnq/pquRKS/QGGC7ZxRVc3T1r+EpvbBP5Dc4CDGbbbyZLCSrOh5HWIb0I3k
95GSiipTtf54KqZ9HiG/u+xNAFIdapXgU4Xm+JyDRWLdxSs5Nmy8VgpdflvxBfuo
hCvJJw3vtDusjyHc7IafxaZlJVQT9tPgPshs8GfrCMCP19RCALD/5irspFh6dD35
BQTIkhC68XNa0iNn/NTP3uxir/JwRoovxQkA9eD+r1NHsAbL8GTypfr5kKJxDaIK
UhawfyZE3Q==
=YqhC
-----END PGP SIGNATURE-----
Merge tag 'for-5.19/drivers-2022-06-02' of git://git.kernel.dk/linux-block
Pull more block driver updates from Jens Axboe:
"A collection of stragglers that were late on sending in their changes
and just followup fixes.
- NVMe fixes pull request via Christoph:
- set controller enable bit in a separate write (Niklas Cassel)
- disable namespace identifiers for the MAXIO MAP1001 (Christoph)
- fix a comment typo (Julia Lawall)"
- MD fixes pull request via Song:
- Remove uses of bdevname (Christoph Hellwig)
- Bug fixes (Guoqing Jiang, and Xiao Ni)
- bcache fixes series (Coly)
- null_blk zoned write fix (Damien)
- nbd fixes (Yu, Zhang)
- Fix for loop partition scanning (Christoph)"
* tag 'for-5.19/drivers-2022-06-02' of git://git.kernel.dk/linux-block: (23 commits)
block: null_blk: Fix null_zone_write()
nvmet: fix typo in comment
nvme: set controller enable bit in a separate write
nvme-pci: disable namespace identifiers for the MAXIO MAP1001
bcache: avoid unnecessary soft lockup in kworker update_writeback_rate()
nbd: use pr_err to output error message
nbd: fix possible overflow on 'first_minor' in nbd_dev_add()
nbd: fix io hung while disconnecting device
nbd: don't clear 'NBD_CMD_INFLIGHT' flag if request is not completed
nbd: fix race between nbd_alloc_config() and module removal
nbd: call genl_unregister_family() first in nbd_cleanup()
md: bcache: check the return value of kzalloc() in detached_dev_do_request()
bcache: memset on stack variables in bch_btree_check() and bch_sectors_dirty_init()
block, loop: support partitions without scanning
bcache: avoid journal no-space deadlock by reserving 1 journal bucket
bcache: remove incremental dirty sector counting for bch_sectors_dirty_init()
bcache: improve multithreaded bch_sectors_dirty_init()
bcache: improve multithreaded bch_btree_check()
md: fix double free of io_acct_set bioset
md: Don't set mddev private to NULL in raid0 pers->free
...
This commit is contained in:
commit
78c6499c92
|
|
@ -385,6 +385,8 @@ int disk_scan_partitions(struct gendisk *disk, fmode_t mode)
|
||||||
|
|
||||||
if (disk->flags & (GENHD_FL_NO_PART | GENHD_FL_HIDDEN))
|
if (disk->flags & (GENHD_FL_NO_PART | GENHD_FL_HIDDEN))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (test_bit(GD_SUPPRESS_PART_SCAN, &disk->state))
|
||||||
|
return -EINVAL;
|
||||||
if (disk->open_partitions)
|
if (disk->open_partitions)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1102,7 +1102,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
|
||||||
lo->lo_flags |= LO_FLAGS_PARTSCAN;
|
lo->lo_flags |= LO_FLAGS_PARTSCAN;
|
||||||
partscan = lo->lo_flags & LO_FLAGS_PARTSCAN;
|
partscan = lo->lo_flags & LO_FLAGS_PARTSCAN;
|
||||||
if (partscan)
|
if (partscan)
|
||||||
lo->lo_disk->flags &= ~GENHD_FL_NO_PART;
|
clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state);
|
||||||
|
|
||||||
loop_global_unlock(lo, is_loop);
|
loop_global_unlock(lo, is_loop);
|
||||||
if (partscan)
|
if (partscan)
|
||||||
|
|
@ -1198,7 +1198,7 @@ static void __loop_clr_fd(struct loop_device *lo, bool release)
|
||||||
*/
|
*/
|
||||||
lo->lo_flags = 0;
|
lo->lo_flags = 0;
|
||||||
if (!part_shift)
|
if (!part_shift)
|
||||||
lo->lo_disk->flags |= GENHD_FL_NO_PART;
|
set_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state);
|
||||||
mutex_lock(&lo->lo_mutex);
|
mutex_lock(&lo->lo_mutex);
|
||||||
lo->lo_state = Lo_unbound;
|
lo->lo_state = Lo_unbound;
|
||||||
mutex_unlock(&lo->lo_mutex);
|
mutex_unlock(&lo->lo_mutex);
|
||||||
|
|
@ -1308,7 +1308,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
|
||||||
|
|
||||||
if (!err && (lo->lo_flags & LO_FLAGS_PARTSCAN) &&
|
if (!err && (lo->lo_flags & LO_FLAGS_PARTSCAN) &&
|
||||||
!(prev_lo_flags & LO_FLAGS_PARTSCAN)) {
|
!(prev_lo_flags & LO_FLAGS_PARTSCAN)) {
|
||||||
lo->lo_disk->flags &= ~GENHD_FL_NO_PART;
|
clear_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state);
|
||||||
partscan = true;
|
partscan = true;
|
||||||
}
|
}
|
||||||
out_unlock:
|
out_unlock:
|
||||||
|
|
@ -2011,7 +2011,7 @@ static int loop_add(int i)
|
||||||
* userspace tools. Parameters like this in general should be avoided.
|
* userspace tools. Parameters like this in general should be avoided.
|
||||||
*/
|
*/
|
||||||
if (!part_shift)
|
if (!part_shift)
|
||||||
disk->flags |= GENHD_FL_NO_PART;
|
set_bit(GD_SUPPRESS_PART_SCAN, &disk->state);
|
||||||
mutex_init(&lo->lo_mutex);
|
mutex_init(&lo->lo_mutex);
|
||||||
lo->lo_number = i;
|
lo->lo_number = i;
|
||||||
spin_lock_init(&lo->lo_lock);
|
spin_lock_init(&lo->lo_lock);
|
||||||
|
|
|
||||||
|
|
@ -403,13 +403,14 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
|
||||||
if (!mutex_trylock(&cmd->lock))
|
if (!mutex_trylock(&cmd->lock))
|
||||||
return BLK_EH_RESET_TIMER;
|
return BLK_EH_RESET_TIMER;
|
||||||
|
|
||||||
if (!__test_and_clear_bit(NBD_CMD_INFLIGHT, &cmd->flags)) {
|
if (!test_bit(NBD_CMD_INFLIGHT, &cmd->flags)) {
|
||||||
mutex_unlock(&cmd->lock);
|
mutex_unlock(&cmd->lock);
|
||||||
return BLK_EH_DONE;
|
return BLK_EH_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!refcount_inc_not_zero(&nbd->config_refs)) {
|
if (!refcount_inc_not_zero(&nbd->config_refs)) {
|
||||||
cmd->status = BLK_STS_TIMEOUT;
|
cmd->status = BLK_STS_TIMEOUT;
|
||||||
|
__clear_bit(NBD_CMD_INFLIGHT, &cmd->flags);
|
||||||
mutex_unlock(&cmd->lock);
|
mutex_unlock(&cmd->lock);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -478,6 +479,7 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
|
||||||
dev_err_ratelimited(nbd_to_dev(nbd), "Connection timed out\n");
|
dev_err_ratelimited(nbd_to_dev(nbd), "Connection timed out\n");
|
||||||
set_bit(NBD_RT_TIMEDOUT, &config->runtime_flags);
|
set_bit(NBD_RT_TIMEDOUT, &config->runtime_flags);
|
||||||
cmd->status = BLK_STS_IOERR;
|
cmd->status = BLK_STS_IOERR;
|
||||||
|
__clear_bit(NBD_CMD_INFLIGHT, &cmd->flags);
|
||||||
mutex_unlock(&cmd->lock);
|
mutex_unlock(&cmd->lock);
|
||||||
sock_shutdown(nbd);
|
sock_shutdown(nbd);
|
||||||
nbd_config_put(nbd);
|
nbd_config_put(nbd);
|
||||||
|
|
@ -745,7 +747,7 @@ static struct nbd_cmd *nbd_handle_reply(struct nbd_device *nbd, int index,
|
||||||
cmd = blk_mq_rq_to_pdu(req);
|
cmd = blk_mq_rq_to_pdu(req);
|
||||||
|
|
||||||
mutex_lock(&cmd->lock);
|
mutex_lock(&cmd->lock);
|
||||||
if (!__test_and_clear_bit(NBD_CMD_INFLIGHT, &cmd->flags)) {
|
if (!test_bit(NBD_CMD_INFLIGHT, &cmd->flags)) {
|
||||||
dev_err(disk_to_dev(nbd->disk), "Suspicious reply %d (status %u flags %lu)",
|
dev_err(disk_to_dev(nbd->disk), "Suspicious reply %d (status %u flags %lu)",
|
||||||
tag, cmd->status, cmd->flags);
|
tag, cmd->status, cmd->flags);
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
|
|
@ -854,8 +856,16 @@ static void recv_work(struct work_struct *work)
|
||||||
}
|
}
|
||||||
|
|
||||||
rq = blk_mq_rq_from_pdu(cmd);
|
rq = blk_mq_rq_from_pdu(cmd);
|
||||||
if (likely(!blk_should_fake_timeout(rq->q)))
|
if (likely(!blk_should_fake_timeout(rq->q))) {
|
||||||
blk_mq_complete_request(rq);
|
bool complete;
|
||||||
|
|
||||||
|
mutex_lock(&cmd->lock);
|
||||||
|
complete = __test_and_clear_bit(NBD_CMD_INFLIGHT,
|
||||||
|
&cmd->flags);
|
||||||
|
mutex_unlock(&cmd->lock);
|
||||||
|
if (complete)
|
||||||
|
blk_mq_complete_request(rq);
|
||||||
|
}
|
||||||
percpu_ref_put(&q->q_usage_counter);
|
percpu_ref_put(&q->q_usage_counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1419,7 +1429,7 @@ static int nbd_start_device_ioctl(struct nbd_device *nbd)
|
||||||
static void nbd_clear_sock_ioctl(struct nbd_device *nbd,
|
static void nbd_clear_sock_ioctl(struct nbd_device *nbd,
|
||||||
struct block_device *bdev)
|
struct block_device *bdev)
|
||||||
{
|
{
|
||||||
sock_shutdown(nbd);
|
nbd_clear_sock(nbd);
|
||||||
__invalidate_device(bdev, true);
|
__invalidate_device(bdev, true);
|
||||||
nbd_bdev_reset(nbd);
|
nbd_bdev_reset(nbd);
|
||||||
if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF,
|
if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF,
|
||||||
|
|
@ -1518,15 +1528,20 @@ static struct nbd_config *nbd_alloc_config(void)
|
||||||
{
|
{
|
||||||
struct nbd_config *config;
|
struct nbd_config *config;
|
||||||
|
|
||||||
|
if (!try_module_get(THIS_MODULE))
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
config = kzalloc(sizeof(struct nbd_config), GFP_NOFS);
|
config = kzalloc(sizeof(struct nbd_config), GFP_NOFS);
|
||||||
if (!config)
|
if (!config) {
|
||||||
return NULL;
|
module_put(THIS_MODULE);
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
atomic_set(&config->recv_threads, 0);
|
atomic_set(&config->recv_threads, 0);
|
||||||
init_waitqueue_head(&config->recv_wq);
|
init_waitqueue_head(&config->recv_wq);
|
||||||
init_waitqueue_head(&config->conn_wait);
|
init_waitqueue_head(&config->conn_wait);
|
||||||
config->blksize_bits = NBD_DEF_BLKSIZE_BITS;
|
config->blksize_bits = NBD_DEF_BLKSIZE_BITS;
|
||||||
atomic_set(&config->live_connections, 0);
|
atomic_set(&config->live_connections, 0);
|
||||||
try_module_get(THIS_MODULE);
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1553,12 +1568,13 @@ static int nbd_open(struct block_device *bdev, fmode_t mode)
|
||||||
mutex_unlock(&nbd->config_lock);
|
mutex_unlock(&nbd->config_lock);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
config = nbd->config = nbd_alloc_config();
|
config = nbd_alloc_config();
|
||||||
if (!config) {
|
if (IS_ERR(config)) {
|
||||||
ret = -ENOMEM;
|
ret = PTR_ERR(config);
|
||||||
mutex_unlock(&nbd->config_lock);
|
mutex_unlock(&nbd->config_lock);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
nbd->config = config;
|
||||||
refcount_set(&nbd->config_refs, 1);
|
refcount_set(&nbd->config_refs, 1);
|
||||||
refcount_inc(&nbd->refs);
|
refcount_inc(&nbd->refs);
|
||||||
mutex_unlock(&nbd->config_lock);
|
mutex_unlock(&nbd->config_lock);
|
||||||
|
|
@ -1798,17 +1814,7 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
|
||||||
refcount_set(&nbd->refs, 0);
|
refcount_set(&nbd->refs, 0);
|
||||||
INIT_LIST_HEAD(&nbd->list);
|
INIT_LIST_HEAD(&nbd->list);
|
||||||
disk->major = NBD_MAJOR;
|
disk->major = NBD_MAJOR;
|
||||||
|
|
||||||
/* Too big first_minor can cause duplicate creation of
|
|
||||||
* sysfs files/links, since index << part_shift might overflow, or
|
|
||||||
* MKDEV() expect that the max bits of first_minor is 20.
|
|
||||||
*/
|
|
||||||
disk->first_minor = index << part_shift;
|
disk->first_minor = index << part_shift;
|
||||||
if (disk->first_minor < index || disk->first_minor > MINORMASK) {
|
|
||||||
err = -EINVAL;
|
|
||||||
goto out_free_work;
|
|
||||||
}
|
|
||||||
|
|
||||||
disk->minors = 1 << part_shift;
|
disk->minors = 1 << part_shift;
|
||||||
disk->fops = &nbd_fops;
|
disk->fops = &nbd_fops;
|
||||||
disk->private_data = nbd;
|
disk->private_data = nbd;
|
||||||
|
|
@ -1913,14 +1919,25 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
|
||||||
if (!netlink_capable(skb, CAP_SYS_ADMIN))
|
if (!netlink_capable(skb, CAP_SYS_ADMIN))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
if (info->attrs[NBD_ATTR_INDEX])
|
if (info->attrs[NBD_ATTR_INDEX]) {
|
||||||
index = nla_get_u32(info->attrs[NBD_ATTR_INDEX]);
|
index = nla_get_u32(info->attrs[NBD_ATTR_INDEX]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Too big first_minor can cause duplicate creation of
|
||||||
|
* sysfs files/links, since index << part_shift might overflow, or
|
||||||
|
* MKDEV() expect that the max bits of first_minor is 20.
|
||||||
|
*/
|
||||||
|
if (index < 0 || index > MINORMASK >> part_shift) {
|
||||||
|
pr_err("illegal input index %d\n", index);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!info->attrs[NBD_ATTR_SOCKETS]) {
|
if (!info->attrs[NBD_ATTR_SOCKETS]) {
|
||||||
printk(KERN_ERR "nbd: must specify at least one socket\n");
|
pr_err("must specify at least one socket\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (!info->attrs[NBD_ATTR_SIZE_BYTES]) {
|
if (!info->attrs[NBD_ATTR_SIZE_BYTES]) {
|
||||||
printk(KERN_ERR "nbd: must specify a size in bytes for the device\n");
|
pr_err("must specify a size in bytes for the device\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
again:
|
again:
|
||||||
|
|
@ -1956,7 +1973,7 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
|
||||||
nbd_put(nbd);
|
nbd_put(nbd);
|
||||||
if (index == -1)
|
if (index == -1)
|
||||||
goto again;
|
goto again;
|
||||||
printk(KERN_ERR "nbd: nbd%d already in use\n", index);
|
pr_err("nbd%d already in use\n", index);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
if (WARN_ON(nbd->config)) {
|
if (WARN_ON(nbd->config)) {
|
||||||
|
|
@ -1964,13 +1981,14 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
|
||||||
nbd_put(nbd);
|
nbd_put(nbd);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
config = nbd->config = nbd_alloc_config();
|
config = nbd_alloc_config();
|
||||||
if (!nbd->config) {
|
if (IS_ERR(config)) {
|
||||||
mutex_unlock(&nbd->config_lock);
|
mutex_unlock(&nbd->config_lock);
|
||||||
nbd_put(nbd);
|
nbd_put(nbd);
|
||||||
printk(KERN_ERR "nbd: couldn't allocate config\n");
|
pr_err("couldn't allocate config\n");
|
||||||
return -ENOMEM;
|
return PTR_ERR(config);
|
||||||
}
|
}
|
||||||
|
nbd->config = config;
|
||||||
refcount_set(&nbd->config_refs, 1);
|
refcount_set(&nbd->config_refs, 1);
|
||||||
set_bit(NBD_RT_BOUND, &config->runtime_flags);
|
set_bit(NBD_RT_BOUND, &config->runtime_flags);
|
||||||
|
|
||||||
|
|
@ -2023,7 +2041,7 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
|
||||||
struct nlattr *socks[NBD_SOCK_MAX+1];
|
struct nlattr *socks[NBD_SOCK_MAX+1];
|
||||||
|
|
||||||
if (nla_type(attr) != NBD_SOCK_ITEM) {
|
if (nla_type(attr) != NBD_SOCK_ITEM) {
|
||||||
printk(KERN_ERR "nbd: socks must be embedded in a SOCK_ITEM attr\n");
|
pr_err("socks must be embedded in a SOCK_ITEM attr\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
@ -2032,7 +2050,7 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
|
||||||
nbd_sock_policy,
|
nbd_sock_policy,
|
||||||
info->extack);
|
info->extack);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
printk(KERN_ERR "nbd: error processing sock list\n");
|
pr_err("error processing sock list\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
@ -2104,7 +2122,7 @@ static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
if (!info->attrs[NBD_ATTR_INDEX]) {
|
if (!info->attrs[NBD_ATTR_INDEX]) {
|
||||||
printk(KERN_ERR "nbd: must specify an index to disconnect\n");
|
pr_err("must specify an index to disconnect\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
index = nla_get_u32(info->attrs[NBD_ATTR_INDEX]);
|
index = nla_get_u32(info->attrs[NBD_ATTR_INDEX]);
|
||||||
|
|
@ -2112,14 +2130,12 @@ static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info)
|
||||||
nbd = idr_find(&nbd_index_idr, index);
|
nbd = idr_find(&nbd_index_idr, index);
|
||||||
if (!nbd) {
|
if (!nbd) {
|
||||||
mutex_unlock(&nbd_index_mutex);
|
mutex_unlock(&nbd_index_mutex);
|
||||||
printk(KERN_ERR "nbd: couldn't find device at index %d\n",
|
pr_err("couldn't find device at index %d\n", index);
|
||||||
index);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (!refcount_inc_not_zero(&nbd->refs)) {
|
if (!refcount_inc_not_zero(&nbd->refs)) {
|
||||||
mutex_unlock(&nbd_index_mutex);
|
mutex_unlock(&nbd_index_mutex);
|
||||||
printk(KERN_ERR "nbd: device at index %d is going down\n",
|
pr_err("device at index %d is going down\n", index);
|
||||||
index);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
mutex_unlock(&nbd_index_mutex);
|
mutex_unlock(&nbd_index_mutex);
|
||||||
|
|
@ -2144,7 +2160,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
if (!info->attrs[NBD_ATTR_INDEX]) {
|
if (!info->attrs[NBD_ATTR_INDEX]) {
|
||||||
printk(KERN_ERR "nbd: must specify a device to reconfigure\n");
|
pr_err("must specify a device to reconfigure\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
index = nla_get_u32(info->attrs[NBD_ATTR_INDEX]);
|
index = nla_get_u32(info->attrs[NBD_ATTR_INDEX]);
|
||||||
|
|
@ -2152,8 +2168,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
|
||||||
nbd = idr_find(&nbd_index_idr, index);
|
nbd = idr_find(&nbd_index_idr, index);
|
||||||
if (!nbd) {
|
if (!nbd) {
|
||||||
mutex_unlock(&nbd_index_mutex);
|
mutex_unlock(&nbd_index_mutex);
|
||||||
printk(KERN_ERR "nbd: couldn't find a device at index %d\n",
|
pr_err("couldn't find a device at index %d\n", index);
|
||||||
index);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (nbd->backend) {
|
if (nbd->backend) {
|
||||||
|
|
@ -2174,8 +2189,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
|
||||||
}
|
}
|
||||||
if (!refcount_inc_not_zero(&nbd->refs)) {
|
if (!refcount_inc_not_zero(&nbd->refs)) {
|
||||||
mutex_unlock(&nbd_index_mutex);
|
mutex_unlock(&nbd_index_mutex);
|
||||||
printk(KERN_ERR "nbd: device at index %d is going down\n",
|
pr_err("device at index %d is going down\n", index);
|
||||||
index);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
mutex_unlock(&nbd_index_mutex);
|
mutex_unlock(&nbd_index_mutex);
|
||||||
|
|
@ -2239,7 +2253,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
|
||||||
struct nlattr *socks[NBD_SOCK_MAX+1];
|
struct nlattr *socks[NBD_SOCK_MAX+1];
|
||||||
|
|
||||||
if (nla_type(attr) != NBD_SOCK_ITEM) {
|
if (nla_type(attr) != NBD_SOCK_ITEM) {
|
||||||
printk(KERN_ERR "nbd: socks must be embedded in a SOCK_ITEM attr\n");
|
pr_err("socks must be embedded in a SOCK_ITEM attr\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
@ -2248,7 +2262,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
|
||||||
nbd_sock_policy,
|
nbd_sock_policy,
|
||||||
info->extack);
|
info->extack);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
printk(KERN_ERR "nbd: error processing sock list\n");
|
pr_err("error processing sock list\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
@ -2465,7 +2479,7 @@ static int __init nbd_init(void)
|
||||||
BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
|
BUILD_BUG_ON(sizeof(struct nbd_request) != 28);
|
||||||
|
|
||||||
if (max_part < 0) {
|
if (max_part < 0) {
|
||||||
printk(KERN_ERR "nbd: max_part must be >= 0\n");
|
pr_err("max_part must be >= 0\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2528,6 +2542,12 @@ static void __exit nbd_cleanup(void)
|
||||||
struct nbd_device *nbd;
|
struct nbd_device *nbd;
|
||||||
LIST_HEAD(del_list);
|
LIST_HEAD(del_list);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unregister netlink interface prior to waiting
|
||||||
|
* for the completion of netlink commands.
|
||||||
|
*/
|
||||||
|
genl_unregister_family(&nbd_genl_family);
|
||||||
|
|
||||||
nbd_dbg_close();
|
nbd_dbg_close();
|
||||||
|
|
||||||
mutex_lock(&nbd_index_mutex);
|
mutex_lock(&nbd_index_mutex);
|
||||||
|
|
@ -2537,8 +2557,11 @@ static void __exit nbd_cleanup(void)
|
||||||
while (!list_empty(&del_list)) {
|
while (!list_empty(&del_list)) {
|
||||||
nbd = list_first_entry(&del_list, struct nbd_device, list);
|
nbd = list_first_entry(&del_list, struct nbd_device, list);
|
||||||
list_del_init(&nbd->list);
|
list_del_init(&nbd->list);
|
||||||
|
if (refcount_read(&nbd->config_refs))
|
||||||
|
pr_err("possibly leaking nbd_config (ref %d)\n",
|
||||||
|
refcount_read(&nbd->config_refs));
|
||||||
if (refcount_read(&nbd->refs) != 1)
|
if (refcount_read(&nbd->refs) != 1)
|
||||||
printk(KERN_ERR "nbd: possibly leaking a device\n");
|
pr_err("possibly leaking a device\n");
|
||||||
nbd_put(nbd);
|
nbd_put(nbd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2546,7 +2569,6 @@ static void __exit nbd_cleanup(void)
|
||||||
destroy_workqueue(nbd_del_wq);
|
destroy_workqueue(nbd_del_wq);
|
||||||
|
|
||||||
idr_destroy(&nbd_index_idr);
|
idr_destroy(&nbd_index_idr);
|
||||||
genl_unregister_family(&nbd_genl_family);
|
|
||||||
unregister_blkdev(NBD_MAJOR, "nbd");
|
unregister_blkdev(NBD_MAJOR, "nbd");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,12 +77,6 @@ enum {
|
||||||
NULL_IRQ_TIMER = 2,
|
NULL_IRQ_TIMER = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
|
||||||
NULL_Q_BIO = 0,
|
|
||||||
NULL_Q_RQ = 1,
|
|
||||||
NULL_Q_MQ = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool g_virt_boundary = false;
|
static bool g_virt_boundary = false;
|
||||||
module_param_named(virt_boundary, g_virt_boundary, bool, 0444);
|
module_param_named(virt_boundary, g_virt_boundary, bool, 0444);
|
||||||
MODULE_PARM_DESC(virt_boundary, "Require a virtual boundary for the device. Default: False");
|
MODULE_PARM_DESC(virt_boundary, "Require a virtual boundary for the device. Default: False");
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,13 @@ struct nullb_zone {
|
||||||
unsigned int capacity;
|
unsigned int capacity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Queue modes */
|
||||||
|
enum {
|
||||||
|
NULL_Q_BIO = 0,
|
||||||
|
NULL_Q_RQ = 1,
|
||||||
|
NULL_Q_MQ = 2,
|
||||||
|
};
|
||||||
|
|
||||||
struct nullb_device {
|
struct nullb_device {
|
||||||
struct nullb *nullb;
|
struct nullb *nullb;
|
||||||
struct config_item item;
|
struct config_item item;
|
||||||
|
|
|
||||||
|
|
@ -398,10 +398,10 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
|
||||||
*/
|
*/
|
||||||
if (append) {
|
if (append) {
|
||||||
sector = zone->wp;
|
sector = zone->wp;
|
||||||
if (cmd->bio)
|
if (dev->queue_mode == NULL_Q_MQ)
|
||||||
cmd->bio->bi_iter.bi_sector = sector;
|
|
||||||
else
|
|
||||||
cmd->rq->__sector = sector;
|
cmd->rq->__sector = sector;
|
||||||
|
else
|
||||||
|
cmd->bio->bi_iter.bi_sector = sector;
|
||||||
} else if (sector != zone->wp) {
|
} else if (sector != zone->wp) {
|
||||||
ret = BLK_STS_IOERR;
|
ret = BLK_STS_IOERR;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
|
||||||
|
|
@ -395,6 +395,13 @@ struct cached_dev {
|
||||||
atomic_t io_errors;
|
atomic_t io_errors;
|
||||||
unsigned int error_limit;
|
unsigned int error_limit;
|
||||||
unsigned int offline_seconds;
|
unsigned int offline_seconds;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retry to update writeback_rate if contention happens for
|
||||||
|
* down_read(dc->writeback_lock) in update_writeback_rate()
|
||||||
|
*/
|
||||||
|
#define BCH_WBRATE_UPDATE_MAX_SKIPS 15
|
||||||
|
unsigned int rate_update_retry;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum alloc_reserve {
|
enum alloc_reserve {
|
||||||
|
|
|
||||||
|
|
@ -2006,8 +2006,7 @@ int bch_btree_check(struct cache_set *c)
|
||||||
int i;
|
int i;
|
||||||
struct bkey *k = NULL;
|
struct bkey *k = NULL;
|
||||||
struct btree_iter iter;
|
struct btree_iter iter;
|
||||||
struct btree_check_state *check_state;
|
struct btree_check_state check_state;
|
||||||
char name[32];
|
|
||||||
|
|
||||||
/* check and mark root node keys */
|
/* check and mark root node keys */
|
||||||
for_each_key_filter(&c->root->keys, k, &iter, bch_ptr_invalid)
|
for_each_key_filter(&c->root->keys, k, &iter, bch_ptr_invalid)
|
||||||
|
|
@ -2018,63 +2017,59 @@ int bch_btree_check(struct cache_set *c)
|
||||||
if (c->root->level == 0)
|
if (c->root->level == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
check_state = kzalloc(sizeof(struct btree_check_state), GFP_KERNEL);
|
memset(&check_state, 0, sizeof(struct btree_check_state));
|
||||||
if (!check_state)
|
check_state.c = c;
|
||||||
return -ENOMEM;
|
check_state.total_threads = bch_btree_chkthread_nr();
|
||||||
|
check_state.key_idx = 0;
|
||||||
check_state->c = c;
|
spin_lock_init(&check_state.idx_lock);
|
||||||
check_state->total_threads = bch_btree_chkthread_nr();
|
atomic_set(&check_state.started, 0);
|
||||||
check_state->key_idx = 0;
|
atomic_set(&check_state.enough, 0);
|
||||||
spin_lock_init(&check_state->idx_lock);
|
init_waitqueue_head(&check_state.wait);
|
||||||
atomic_set(&check_state->started, 0);
|
|
||||||
atomic_set(&check_state->enough, 0);
|
|
||||||
init_waitqueue_head(&check_state->wait);
|
|
||||||
|
|
||||||
|
rw_lock(0, c->root, c->root->level);
|
||||||
/*
|
/*
|
||||||
* Run multiple threads to check btree nodes in parallel,
|
* Run multiple threads to check btree nodes in parallel,
|
||||||
* if check_state->enough is non-zero, it means current
|
* if check_state.enough is non-zero, it means current
|
||||||
* running check threads are enough, unncessary to create
|
* running check threads are enough, unncessary to create
|
||||||
* more.
|
* more.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < check_state->total_threads; i++) {
|
for (i = 0; i < check_state.total_threads; i++) {
|
||||||
/* fetch latest check_state->enough earlier */
|
/* fetch latest check_state.enough earlier */
|
||||||
smp_mb__before_atomic();
|
smp_mb__before_atomic();
|
||||||
if (atomic_read(&check_state->enough))
|
if (atomic_read(&check_state.enough))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
check_state->infos[i].result = 0;
|
check_state.infos[i].result = 0;
|
||||||
check_state->infos[i].state = check_state;
|
check_state.infos[i].state = &check_state;
|
||||||
snprintf(name, sizeof(name), "bch_btrchk[%u]", i);
|
|
||||||
atomic_inc(&check_state->started);
|
|
||||||
|
|
||||||
check_state->infos[i].thread =
|
check_state.infos[i].thread =
|
||||||
kthread_run(bch_btree_check_thread,
|
kthread_run(bch_btree_check_thread,
|
||||||
&check_state->infos[i],
|
&check_state.infos[i],
|
||||||
name);
|
"bch_btrchk[%d]", i);
|
||||||
if (IS_ERR(check_state->infos[i].thread)) {
|
if (IS_ERR(check_state.infos[i].thread)) {
|
||||||
pr_err("fails to run thread bch_btrchk[%d]\n", i);
|
pr_err("fails to run thread bch_btrchk[%d]\n", i);
|
||||||
for (--i; i >= 0; i--)
|
for (--i; i >= 0; i--)
|
||||||
kthread_stop(check_state->infos[i].thread);
|
kthread_stop(check_state.infos[i].thread);
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
atomic_inc(&check_state.started);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Must wait for all threads to stop.
|
* Must wait for all threads to stop.
|
||||||
*/
|
*/
|
||||||
wait_event_interruptible(check_state->wait,
|
wait_event(check_state.wait, atomic_read(&check_state.started) == 0);
|
||||||
atomic_read(&check_state->started) == 0);
|
|
||||||
|
|
||||||
for (i = 0; i < check_state->total_threads; i++) {
|
for (i = 0; i < check_state.total_threads; i++) {
|
||||||
if (check_state->infos[i].result) {
|
if (check_state.infos[i].result) {
|
||||||
ret = check_state->infos[i].result;
|
ret = check_state.infos[i].result;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
kfree(check_state);
|
rw_unlock(0, c->root);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,7 @@ struct btree_check_info {
|
||||||
int result;
|
int result;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BCH_BTR_CHKTHREAD_MAX 64
|
#define BCH_BTR_CHKTHREAD_MAX 12
|
||||||
struct btree_check_state {
|
struct btree_check_state {
|
||||||
struct cache_set *c;
|
struct cache_set *c;
|
||||||
int total_threads;
|
int total_threads;
|
||||||
|
|
|
||||||
|
|
@ -405,6 +405,11 @@ int bch_journal_replay(struct cache_set *s, struct list_head *list)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bch_journal_space_reserve(struct journal *j)
|
||||||
|
{
|
||||||
|
j->do_reserve = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Journalling */
|
/* Journalling */
|
||||||
|
|
||||||
static void btree_flush_write(struct cache_set *c)
|
static void btree_flush_write(struct cache_set *c)
|
||||||
|
|
@ -621,12 +626,30 @@ static void do_journal_discard(struct cache *ca)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int free_journal_buckets(struct cache_set *c)
|
||||||
|
{
|
||||||
|
struct journal *j = &c->journal;
|
||||||
|
struct cache *ca = c->cache;
|
||||||
|
struct journal_device *ja = &c->cache->journal;
|
||||||
|
unsigned int n;
|
||||||
|
|
||||||
|
/* In case njournal_buckets is not power of 2 */
|
||||||
|
if (ja->cur_idx >= ja->discard_idx)
|
||||||
|
n = ca->sb.njournal_buckets + ja->discard_idx - ja->cur_idx;
|
||||||
|
else
|
||||||
|
n = ja->discard_idx - ja->cur_idx;
|
||||||
|
|
||||||
|
if (n > (1 + j->do_reserve))
|
||||||
|
return n - (1 + j->do_reserve);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void journal_reclaim(struct cache_set *c)
|
static void journal_reclaim(struct cache_set *c)
|
||||||
{
|
{
|
||||||
struct bkey *k = &c->journal.key;
|
struct bkey *k = &c->journal.key;
|
||||||
struct cache *ca = c->cache;
|
struct cache *ca = c->cache;
|
||||||
uint64_t last_seq;
|
uint64_t last_seq;
|
||||||
unsigned int next;
|
|
||||||
struct journal_device *ja = &ca->journal;
|
struct journal_device *ja = &ca->journal;
|
||||||
atomic_t p __maybe_unused;
|
atomic_t p __maybe_unused;
|
||||||
|
|
||||||
|
|
@ -649,12 +672,10 @@ static void journal_reclaim(struct cache_set *c)
|
||||||
if (c->journal.blocks_free)
|
if (c->journal.blocks_free)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
next = (ja->cur_idx + 1) % ca->sb.njournal_buckets;
|
if (!free_journal_buckets(c))
|
||||||
/* No space available on this device */
|
|
||||||
if (next == ja->discard_idx)
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ja->cur_idx = next;
|
ja->cur_idx = (ja->cur_idx + 1) % ca->sb.njournal_buckets;
|
||||||
k->ptr[0] = MAKE_PTR(0,
|
k->ptr[0] = MAKE_PTR(0,
|
||||||
bucket_to_sector(c, ca->sb.d[ja->cur_idx]),
|
bucket_to_sector(c, ca->sb.d[ja->cur_idx]),
|
||||||
ca->sb.nr_this_dev);
|
ca->sb.nr_this_dev);
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,7 @@ struct journal {
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
spinlock_t flush_write_lock;
|
spinlock_t flush_write_lock;
|
||||||
bool btree_flushing;
|
bool btree_flushing;
|
||||||
|
bool do_reserve;
|
||||||
/* used when waiting because the journal was full */
|
/* used when waiting because the journal was full */
|
||||||
struct closure_waitlist wait;
|
struct closure_waitlist wait;
|
||||||
struct closure io;
|
struct closure io;
|
||||||
|
|
@ -182,5 +183,6 @@ int bch_journal_replay(struct cache_set *c, struct list_head *list);
|
||||||
|
|
||||||
void bch_journal_free(struct cache_set *c);
|
void bch_journal_free(struct cache_set *c);
|
||||||
int bch_journal_alloc(struct cache_set *c);
|
int bch_journal_alloc(struct cache_set *c);
|
||||||
|
void bch_journal_space_reserve(struct journal *j);
|
||||||
|
|
||||||
#endif /* _BCACHE_JOURNAL_H */
|
#endif /* _BCACHE_JOURNAL_H */
|
||||||
|
|
|
||||||
|
|
@ -1105,6 +1105,12 @@ static void detached_dev_do_request(struct bcache_device *d, struct bio *bio,
|
||||||
* which would call closure_get(&dc->disk.cl)
|
* which would call closure_get(&dc->disk.cl)
|
||||||
*/
|
*/
|
||||||
ddip = kzalloc(sizeof(struct detached_dev_io_private), GFP_NOIO);
|
ddip = kzalloc(sizeof(struct detached_dev_io_private), GFP_NOIO);
|
||||||
|
if (!ddip) {
|
||||||
|
bio->bi_status = BLK_STS_RESOURCE;
|
||||||
|
bio->bi_end_io(bio);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ddip->d = d;
|
ddip->d = d;
|
||||||
/* Count on the bcache device */
|
/* Count on the bcache device */
|
||||||
ddip->orig_bdev = orig_bdev;
|
ddip->orig_bdev = orig_bdev;
|
||||||
|
|
|
||||||
|
|
@ -2127,6 +2127,7 @@ static int run_cache_set(struct cache_set *c)
|
||||||
|
|
||||||
flash_devs_run(c);
|
flash_devs_run(c);
|
||||||
|
|
||||||
|
bch_journal_space_reserve(&c->journal);
|
||||||
set_bit(CACHE_SET_RUNNING, &c->flags);
|
set_bit(CACHE_SET_RUNNING, &c->flags);
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
|
|
|
||||||
|
|
@ -235,19 +235,27 @@ static void update_writeback_rate(struct work_struct *work)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atomic_read(&dc->has_dirty) && dc->writeback_percent) {
|
/*
|
||||||
/*
|
* If the whole cache set is idle, set_at_max_writeback_rate()
|
||||||
* If the whole cache set is idle, set_at_max_writeback_rate()
|
* will set writeback rate to a max number. Then it is
|
||||||
* will set writeback rate to a max number. Then it is
|
* unncessary to update writeback rate for an idle cache set
|
||||||
* unncessary to update writeback rate for an idle cache set
|
* in maximum writeback rate number(s).
|
||||||
* in maximum writeback rate number(s).
|
*/
|
||||||
*/
|
if (atomic_read(&dc->has_dirty) && dc->writeback_percent &&
|
||||||
if (!set_at_max_writeback_rate(c, dc)) {
|
!set_at_max_writeback_rate(c, dc)) {
|
||||||
down_read(&dc->writeback_lock);
|
do {
|
||||||
|
if (!down_read_trylock((&dc->writeback_lock))) {
|
||||||
|
dc->rate_update_retry++;
|
||||||
|
if (dc->rate_update_retry <=
|
||||||
|
BCH_WBRATE_UPDATE_MAX_SKIPS)
|
||||||
|
break;
|
||||||
|
down_read(&dc->writeback_lock);
|
||||||
|
dc->rate_update_retry = 0;
|
||||||
|
}
|
||||||
__update_writeback_rate(dc);
|
__update_writeback_rate(dc);
|
||||||
update_gc_after_writeback(c);
|
update_gc_after_writeback(c);
|
||||||
up_read(&dc->writeback_lock);
|
up_read(&dc->writeback_lock);
|
||||||
}
|
} while (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -805,13 +813,11 @@ static int bch_writeback_thread(void *arg)
|
||||||
|
|
||||||
/* Init */
|
/* Init */
|
||||||
#define INIT_KEYS_EACH_TIME 500000
|
#define INIT_KEYS_EACH_TIME 500000
|
||||||
#define INIT_KEYS_SLEEP_MS 100
|
|
||||||
|
|
||||||
struct sectors_dirty_init {
|
struct sectors_dirty_init {
|
||||||
struct btree_op op;
|
struct btree_op op;
|
||||||
unsigned int inode;
|
unsigned int inode;
|
||||||
size_t count;
|
size_t count;
|
||||||
struct bkey start;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int sectors_dirty_init_fn(struct btree_op *_op, struct btree *b,
|
static int sectors_dirty_init_fn(struct btree_op *_op, struct btree *b,
|
||||||
|
|
@ -827,11 +833,8 @@ static int sectors_dirty_init_fn(struct btree_op *_op, struct btree *b,
|
||||||
KEY_START(k), KEY_SIZE(k));
|
KEY_START(k), KEY_SIZE(k));
|
||||||
|
|
||||||
op->count++;
|
op->count++;
|
||||||
if (atomic_read(&b->c->search_inflight) &&
|
if (!(op->count % INIT_KEYS_EACH_TIME))
|
||||||
!(op->count % INIT_KEYS_EACH_TIME)) {
|
cond_resched();
|
||||||
bkey_copy_key(&op->start, k);
|
|
||||||
return -EAGAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MAP_CONTINUE;
|
return MAP_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
@ -846,24 +849,16 @@ static int bch_root_node_dirty_init(struct cache_set *c,
|
||||||
bch_btree_op_init(&op.op, -1);
|
bch_btree_op_init(&op.op, -1);
|
||||||
op.inode = d->id;
|
op.inode = d->id;
|
||||||
op.count = 0;
|
op.count = 0;
|
||||||
op.start = KEY(op.inode, 0, 0);
|
|
||||||
|
|
||||||
do {
|
ret = bcache_btree(map_keys_recurse,
|
||||||
ret = bcache_btree(map_keys_recurse,
|
k,
|
||||||
k,
|
c->root,
|
||||||
c->root,
|
&op.op,
|
||||||
&op.op,
|
&KEY(op.inode, 0, 0),
|
||||||
&op.start,
|
sectors_dirty_init_fn,
|
||||||
sectors_dirty_init_fn,
|
0);
|
||||||
0);
|
if (ret < 0)
|
||||||
if (ret == -EAGAIN)
|
pr_warn("sectors dirty init failed, ret=%d!\n", ret);
|
||||||
schedule_timeout_interruptible(
|
|
||||||
msecs_to_jiffies(INIT_KEYS_SLEEP_MS));
|
|
||||||
else if (ret < 0) {
|
|
||||||
pr_warn("sectors dirty init failed, ret=%d!\n", ret);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (ret == -EAGAIN);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -907,7 +902,6 @@ static int bch_dirty_init_thread(void *arg)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
skip_nr--;
|
skip_nr--;
|
||||||
cond_resched();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
|
|
@ -917,7 +911,6 @@ static int bch_dirty_init_thread(void *arg)
|
||||||
|
|
||||||
p = NULL;
|
p = NULL;
|
||||||
prev_idx = cur_idx;
|
prev_idx = cur_idx;
|
||||||
cond_resched();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
@ -948,67 +941,56 @@ void bch_sectors_dirty_init(struct bcache_device *d)
|
||||||
struct btree_iter iter;
|
struct btree_iter iter;
|
||||||
struct sectors_dirty_init op;
|
struct sectors_dirty_init op;
|
||||||
struct cache_set *c = d->c;
|
struct cache_set *c = d->c;
|
||||||
struct bch_dirty_init_state *state;
|
struct bch_dirty_init_state state;
|
||||||
char name[32];
|
|
||||||
|
|
||||||
/* Just count root keys if no leaf node */
|
/* Just count root keys if no leaf node */
|
||||||
|
rw_lock(0, c->root, c->root->level);
|
||||||
if (c->root->level == 0) {
|
if (c->root->level == 0) {
|
||||||
bch_btree_op_init(&op.op, -1);
|
bch_btree_op_init(&op.op, -1);
|
||||||
op.inode = d->id;
|
op.inode = d->id;
|
||||||
op.count = 0;
|
op.count = 0;
|
||||||
op.start = KEY(op.inode, 0, 0);
|
|
||||||
|
|
||||||
for_each_key_filter(&c->root->keys,
|
for_each_key_filter(&c->root->keys,
|
||||||
k, &iter, bch_ptr_invalid)
|
k, &iter, bch_ptr_invalid)
|
||||||
sectors_dirty_init_fn(&op.op, c->root, k);
|
sectors_dirty_init_fn(&op.op, c->root, k);
|
||||||
|
|
||||||
|
rw_unlock(0, c->root);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
state = kzalloc(sizeof(struct bch_dirty_init_state), GFP_KERNEL);
|
memset(&state, 0, sizeof(struct bch_dirty_init_state));
|
||||||
if (!state) {
|
state.c = c;
|
||||||
pr_warn("sectors dirty init failed: cannot allocate memory\n");
|
state.d = d;
|
||||||
return;
|
state.total_threads = bch_btre_dirty_init_thread_nr();
|
||||||
}
|
state.key_idx = 0;
|
||||||
|
spin_lock_init(&state.idx_lock);
|
||||||
|
atomic_set(&state.started, 0);
|
||||||
|
atomic_set(&state.enough, 0);
|
||||||
|
init_waitqueue_head(&state.wait);
|
||||||
|
|
||||||
state->c = c;
|
for (i = 0; i < state.total_threads; i++) {
|
||||||
state->d = d;
|
/* Fetch latest state.enough earlier */
|
||||||
state->total_threads = bch_btre_dirty_init_thread_nr();
|
|
||||||
state->key_idx = 0;
|
|
||||||
spin_lock_init(&state->idx_lock);
|
|
||||||
atomic_set(&state->started, 0);
|
|
||||||
atomic_set(&state->enough, 0);
|
|
||||||
init_waitqueue_head(&state->wait);
|
|
||||||
|
|
||||||
for (i = 0; i < state->total_threads; i++) {
|
|
||||||
/* Fetch latest state->enough earlier */
|
|
||||||
smp_mb__before_atomic();
|
smp_mb__before_atomic();
|
||||||
if (atomic_read(&state->enough))
|
if (atomic_read(&state.enough))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
state->infos[i].state = state;
|
state.infos[i].state = &state;
|
||||||
atomic_inc(&state->started);
|
state.infos[i].thread =
|
||||||
snprintf(name, sizeof(name), "bch_dirty_init[%d]", i);
|
kthread_run(bch_dirty_init_thread, &state.infos[i],
|
||||||
|
"bch_dirtcnt[%d]", i);
|
||||||
state->infos[i].thread =
|
if (IS_ERR(state.infos[i].thread)) {
|
||||||
kthread_run(bch_dirty_init_thread,
|
|
||||||
&state->infos[i],
|
|
||||||
name);
|
|
||||||
if (IS_ERR(state->infos[i].thread)) {
|
|
||||||
pr_err("fails to run thread bch_dirty_init[%d]\n", i);
|
pr_err("fails to run thread bch_dirty_init[%d]\n", i);
|
||||||
for (--i; i >= 0; i--)
|
for (--i; i >= 0; i--)
|
||||||
kthread_stop(state->infos[i].thread);
|
kthread_stop(state.infos[i].thread);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
atomic_inc(&state.started);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Must wait for all threads to stop.
|
|
||||||
*/
|
|
||||||
wait_event_interruptible(state->wait,
|
|
||||||
atomic_read(&state->started) == 0);
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
kfree(state);
|
/* Must wait for all threads to stop. */
|
||||||
|
wait_event(state.wait, atomic_read(&state.started) == 0);
|
||||||
|
rw_unlock(0, c->root);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bch_cached_dev_writeback_init(struct cached_dev *dc)
|
void bch_cached_dev_writeback_init(struct cached_dev *dc)
|
||||||
|
|
@ -1032,6 +1014,9 @@ void bch_cached_dev_writeback_init(struct cached_dev *dc)
|
||||||
dc->writeback_rate_fp_term_high = 1000;
|
dc->writeback_rate_fp_term_high = 1000;
|
||||||
dc->writeback_rate_i_term_inverse = 10000;
|
dc->writeback_rate_i_term_inverse = 10000;
|
||||||
|
|
||||||
|
/* For dc->writeback_lock contention in update_writeback_rate() */
|
||||||
|
dc->rate_update_retry = 0;
|
||||||
|
|
||||||
WARN_ON(test_and_clear_bit(BCACHE_DEV_WB_RUNNING, &dc->disk.flags));
|
WARN_ON(test_and_clear_bit(BCACHE_DEV_WB_RUNNING, &dc->disk.flags));
|
||||||
INIT_DELAYED_WORK(&dc->writeback_rate_update, update_writeback_rate);
|
INIT_DELAYED_WORK(&dc->writeback_rate_update, update_writeback_rate);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
#define BCH_WRITEBACK_FRAGMENT_THRESHOLD_MID 57
|
#define BCH_WRITEBACK_FRAGMENT_THRESHOLD_MID 57
|
||||||
#define BCH_WRITEBACK_FRAGMENT_THRESHOLD_HIGH 64
|
#define BCH_WRITEBACK_FRAGMENT_THRESHOLD_HIGH 64
|
||||||
|
|
||||||
#define BCH_DIRTY_INIT_THRD_MAX 64
|
#define BCH_DIRTY_INIT_THRD_MAX 12
|
||||||
/*
|
/*
|
||||||
* 14 (16384ths) is chosen here as something that each backing device
|
* 14 (16384ths) is chosen here as something that each backing device
|
||||||
* should be a reasonable fraction of the share, and not to blow up
|
* should be a reasonable fraction of the share, and not to blow up
|
||||||
|
|
|
||||||
|
|
@ -3725,7 +3725,7 @@ static int raid_message(struct dm_target *ti, unsigned int argc, char **argv,
|
||||||
if (!strcasecmp(argv[0], "idle") || !strcasecmp(argv[0], "frozen")) {
|
if (!strcasecmp(argv[0], "idle") || !strcasecmp(argv[0], "frozen")) {
|
||||||
if (mddev->sync_thread) {
|
if (mddev->sync_thread) {
|
||||||
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
||||||
md_reap_sync_thread(mddev);
|
md_reap_sync_thread(mddev, false);
|
||||||
}
|
}
|
||||||
} else if (decipher_sync_action(mddev, mddev->recovery) != st_idle)
|
} else if (decipher_sync_action(mddev, mddev->recovery) != st_idle)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,6 @@ static void linear_free(struct mddev *mddev, void *priv)
|
||||||
|
|
||||||
static bool linear_make_request(struct mddev *mddev, struct bio *bio)
|
static bool linear_make_request(struct mddev *mddev, struct bio *bio)
|
||||||
{
|
{
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
struct dev_info *tmp_dev;
|
struct dev_info *tmp_dev;
|
||||||
sector_t start_sector, end_sector, data_offset;
|
sector_t start_sector, end_sector, data_offset;
|
||||||
sector_t bio_sector = bio->bi_iter.bi_sector;
|
sector_t bio_sector = bio->bi_iter.bi_sector;
|
||||||
|
|
@ -256,10 +255,10 @@ static bool linear_make_request(struct mddev *mddev, struct bio *bio)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
out_of_bounds:
|
out_of_bounds:
|
||||||
pr_err("md/linear:%s: make_request: Sector %llu out of bounds on dev %s: %llu sectors, offset %llu\n",
|
pr_err("md/linear:%s: make_request: Sector %llu out of bounds on dev %pg: %llu sectors, offset %llu\n",
|
||||||
mdname(mddev),
|
mdname(mddev),
|
||||||
(unsigned long long)bio->bi_iter.bi_sector,
|
(unsigned long long)bio->bi_iter.bi_sector,
|
||||||
bdevname(tmp_dev->rdev->bdev, b),
|
tmp_dev->rdev->bdev,
|
||||||
(unsigned long long)tmp_dev->rdev->sectors,
|
(unsigned long long)tmp_dev->rdev->sectors,
|
||||||
(unsigned long long)start_sector);
|
(unsigned long long)start_sector);
|
||||||
bio_io_error(bio);
|
bio_io_error(bio);
|
||||||
|
|
|
||||||
|
|
@ -87,10 +87,9 @@ static void multipath_end_request(struct bio *bio)
|
||||||
/*
|
/*
|
||||||
* oops, IO error:
|
* oops, IO error:
|
||||||
*/
|
*/
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
md_error (mp_bh->mddev, rdev);
|
md_error (mp_bh->mddev, rdev);
|
||||||
pr_info("multipath: %s: rescheduling sector %llu\n",
|
pr_info("multipath: %pg: rescheduling sector %llu\n",
|
||||||
bdevname(rdev->bdev,b),
|
rdev->bdev,
|
||||||
(unsigned long long)bio->bi_iter.bi_sector);
|
(unsigned long long)bio->bi_iter.bi_sector);
|
||||||
multipath_reschedule_retry(mp_bh);
|
multipath_reschedule_retry(mp_bh);
|
||||||
} else
|
} else
|
||||||
|
|
@ -154,7 +153,6 @@ static void multipath_status(struct seq_file *seq, struct mddev *mddev)
|
||||||
static void multipath_error (struct mddev *mddev, struct md_rdev *rdev)
|
static void multipath_error (struct mddev *mddev, struct md_rdev *rdev)
|
||||||
{
|
{
|
||||||
struct mpconf *conf = mddev->private;
|
struct mpconf *conf = mddev->private;
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
|
|
||||||
if (conf->raid_disks - mddev->degraded <= 1) {
|
if (conf->raid_disks - mddev->degraded <= 1) {
|
||||||
/*
|
/*
|
||||||
|
|
@ -177,9 +175,9 @@ static void multipath_error (struct mddev *mddev, struct md_rdev *rdev)
|
||||||
}
|
}
|
||||||
set_bit(Faulty, &rdev->flags);
|
set_bit(Faulty, &rdev->flags);
|
||||||
set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
|
set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
|
||||||
pr_err("multipath: IO failure on %s, disabling IO path.\n"
|
pr_err("multipath: IO failure on %pg, disabling IO path.\n"
|
||||||
"multipath: Operation continuing on %d IO paths.\n",
|
"multipath: Operation continuing on %d IO paths.\n",
|
||||||
bdevname(rdev->bdev, b),
|
rdev->bdev,
|
||||||
conf->raid_disks - mddev->degraded);
|
conf->raid_disks - mddev->degraded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,12 +195,11 @@ static void print_multipath_conf (struct mpconf *conf)
|
||||||
conf->raid_disks);
|
conf->raid_disks);
|
||||||
|
|
||||||
for (i = 0; i < conf->raid_disks; i++) {
|
for (i = 0; i < conf->raid_disks; i++) {
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
tmp = conf->multipaths + i;
|
tmp = conf->multipaths + i;
|
||||||
if (tmp->rdev)
|
if (tmp->rdev)
|
||||||
pr_debug(" disk%d, o:%d, dev:%s\n",
|
pr_debug(" disk%d, o:%d, dev:%pg\n",
|
||||||
i,!test_bit(Faulty, &tmp->rdev->flags),
|
i,!test_bit(Faulty, &tmp->rdev->flags),
|
||||||
bdevname(tmp->rdev->bdev,b));
|
tmp->rdev->bdev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
185
drivers/md/md.c
185
drivers/md/md.c
|
|
@ -1021,8 +1021,6 @@ EXPORT_SYMBOL_GPL(sync_page_io);
|
||||||
|
|
||||||
static int read_disk_sb(struct md_rdev *rdev, int size)
|
static int read_disk_sb(struct md_rdev *rdev, int size)
|
||||||
{
|
{
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
|
|
||||||
if (rdev->sb_loaded)
|
if (rdev->sb_loaded)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -1032,8 +1030,8 @@ static int read_disk_sb(struct md_rdev *rdev, int size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
pr_err("md: disabled device %s, could not read superblock.\n",
|
pr_err("md: disabled device %pg, could not read superblock.\n",
|
||||||
bdevname(rdev->bdev,b));
|
rdev->bdev);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1179,7 +1177,6 @@ EXPORT_SYMBOL(md_check_no_bitmap);
|
||||||
*/
|
*/
|
||||||
static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_version)
|
static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_version)
|
||||||
{
|
{
|
||||||
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
|
|
||||||
mdp_super_t *sb;
|
mdp_super_t *sb;
|
||||||
int ret;
|
int ret;
|
||||||
bool spare_disk = true;
|
bool spare_disk = true;
|
||||||
|
|
@ -1198,19 +1195,19 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor
|
||||||
|
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
|
||||||
bdevname(rdev->bdev, b);
|
|
||||||
sb = page_address(rdev->sb_page);
|
sb = page_address(rdev->sb_page);
|
||||||
|
|
||||||
if (sb->md_magic != MD_SB_MAGIC) {
|
if (sb->md_magic != MD_SB_MAGIC) {
|
||||||
pr_warn("md: invalid raid superblock magic on %s\n", b);
|
pr_warn("md: invalid raid superblock magic on %pg\n",
|
||||||
|
rdev->bdev);
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sb->major_version != 0 ||
|
if (sb->major_version != 0 ||
|
||||||
sb->minor_version < 90 ||
|
sb->minor_version < 90 ||
|
||||||
sb->minor_version > 91) {
|
sb->minor_version > 91) {
|
||||||
pr_warn("Bad version number %d.%d on %s\n",
|
pr_warn("Bad version number %d.%d on %pg\n",
|
||||||
sb->major_version, sb->minor_version, b);
|
sb->major_version, sb->minor_version, rdev->bdev);
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1218,7 +1215,7 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor
|
||||||
goto abort;
|
goto abort;
|
||||||
|
|
||||||
if (md_csum_fold(calc_sb_csum(sb)) != md_csum_fold(sb->sb_csum)) {
|
if (md_csum_fold(calc_sb_csum(sb)) != md_csum_fold(sb->sb_csum)) {
|
||||||
pr_warn("md: invalid superblock checksum on %s\n", b);
|
pr_warn("md: invalid superblock checksum on %pg\n", rdev->bdev);
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1250,13 +1247,13 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor
|
||||||
__u64 ev1, ev2;
|
__u64 ev1, ev2;
|
||||||
mdp_super_t *refsb = page_address(refdev->sb_page);
|
mdp_super_t *refsb = page_address(refdev->sb_page);
|
||||||
if (!md_uuid_equal(refsb, sb)) {
|
if (!md_uuid_equal(refsb, sb)) {
|
||||||
pr_warn("md: %s has different UUID to %s\n",
|
pr_warn("md: %pg has different UUID to %pg\n",
|
||||||
b, bdevname(refdev->bdev,b2));
|
rdev->bdev, refdev->bdev);
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
if (!md_sb_equal(refsb, sb)) {
|
if (!md_sb_equal(refsb, sb)) {
|
||||||
pr_warn("md: %s has same UUID but different superblock to %s\n",
|
pr_warn("md: %pg has same UUID but different superblock to %pg\n",
|
||||||
b, bdevname(refdev->bdev, b2));
|
rdev->bdev, refdev->bdev);
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
ev1 = md_event(sb);
|
ev1 = md_event(sb);
|
||||||
|
|
@ -1620,7 +1617,6 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
|
||||||
int ret;
|
int ret;
|
||||||
sector_t sb_start;
|
sector_t sb_start;
|
||||||
sector_t sectors;
|
sector_t sectors;
|
||||||
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
|
|
||||||
int bmask;
|
int bmask;
|
||||||
bool spare_disk = true;
|
bool spare_disk = true;
|
||||||
|
|
||||||
|
|
@ -1664,13 +1660,13 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (calc_sb_1_csum(sb) != sb->sb_csum) {
|
if (calc_sb_1_csum(sb) != sb->sb_csum) {
|
||||||
pr_warn("md: invalid superblock checksum on %s\n",
|
pr_warn("md: invalid superblock checksum on %pg\n",
|
||||||
bdevname(rdev->bdev,b));
|
rdev->bdev);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (le64_to_cpu(sb->data_size) < 10) {
|
if (le64_to_cpu(sb->data_size) < 10) {
|
||||||
pr_warn("md: data_size too small on %s\n",
|
pr_warn("md: data_size too small on %pg\n",
|
||||||
bdevname(rdev->bdev,b));
|
rdev->bdev);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (sb->pad0 ||
|
if (sb->pad0 ||
|
||||||
|
|
@ -1776,9 +1772,9 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
|
||||||
sb->level != refsb->level ||
|
sb->level != refsb->level ||
|
||||||
sb->layout != refsb->layout ||
|
sb->layout != refsb->layout ||
|
||||||
sb->chunksize != refsb->chunksize) {
|
sb->chunksize != refsb->chunksize) {
|
||||||
pr_warn("md: %s has strangely different superblock to %s\n",
|
pr_warn("md: %pg has strangely different superblock to %pg\n",
|
||||||
bdevname(rdev->bdev,b),
|
rdev->bdev,
|
||||||
bdevname(refdev->bdev,b2));
|
refdev->bdev);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
ev1 = le64_to_cpu(sb->events);
|
ev1 = le64_to_cpu(sb->events);
|
||||||
|
|
@ -2365,7 +2361,6 @@ EXPORT_SYMBOL(md_integrity_register);
|
||||||
int md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
|
int md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
|
||||||
{
|
{
|
||||||
struct blk_integrity *bi_mddev;
|
struct blk_integrity *bi_mddev;
|
||||||
char name[BDEVNAME_SIZE];
|
|
||||||
|
|
||||||
if (!mddev->gendisk)
|
if (!mddev->gendisk)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -2376,8 +2371,8 @@ int md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (blk_integrity_compare(mddev->gendisk, rdev->bdev->bd_disk) != 0) {
|
if (blk_integrity_compare(mddev->gendisk, rdev->bdev->bd_disk) != 0) {
|
||||||
pr_err("%s: incompatible integrity profile for %s\n",
|
pr_err("%s: incompatible integrity profile for %pg\n",
|
||||||
mdname(mddev), bdevname(rdev->bdev, name));
|
mdname(mddev), rdev->bdev);
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2486,11 +2481,9 @@ static void rdev_delayed_delete(struct work_struct *ws)
|
||||||
|
|
||||||
static void unbind_rdev_from_array(struct md_rdev *rdev)
|
static void unbind_rdev_from_array(struct md_rdev *rdev)
|
||||||
{
|
{
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
|
|
||||||
bd_unlink_disk_holder(rdev->bdev, rdev->mddev->gendisk);
|
bd_unlink_disk_holder(rdev->bdev, rdev->mddev->gendisk);
|
||||||
list_del_rcu(&rdev->same_set);
|
list_del_rcu(&rdev->same_set);
|
||||||
pr_debug("md: unbind<%s>\n", bdevname(rdev->bdev,b));
|
pr_debug("md: unbind<%pg>\n", rdev->bdev);
|
||||||
mddev_destroy_serial_pool(rdev->mddev, rdev, false);
|
mddev_destroy_serial_pool(rdev->mddev, rdev, false);
|
||||||
rdev->mddev = NULL;
|
rdev->mddev = NULL;
|
||||||
sysfs_remove_link(&rdev->kobj, "block");
|
sysfs_remove_link(&rdev->kobj, "block");
|
||||||
|
|
@ -2543,9 +2536,7 @@ void md_autodetect_dev(dev_t dev);
|
||||||
|
|
||||||
static void export_rdev(struct md_rdev *rdev)
|
static void export_rdev(struct md_rdev *rdev)
|
||||||
{
|
{
|
||||||
char b[BDEVNAME_SIZE];
|
pr_debug("md: export_rdev(%pg)\n", rdev->bdev);
|
||||||
|
|
||||||
pr_debug("md: export_rdev(%s)\n", bdevname(rdev->bdev,b));
|
|
||||||
md_rdev_clear(rdev);
|
md_rdev_clear(rdev);
|
||||||
#ifndef MODULE
|
#ifndef MODULE
|
||||||
if (test_bit(AutoDetected, &rdev->flags))
|
if (test_bit(AutoDetected, &rdev->flags))
|
||||||
|
|
@ -2803,8 +2794,6 @@ void md_update_sb(struct mddev *mddev, int force_change)
|
||||||
rewrite:
|
rewrite:
|
||||||
md_bitmap_update_sb(mddev->bitmap);
|
md_bitmap_update_sb(mddev->bitmap);
|
||||||
rdev_for_each(rdev, mddev) {
|
rdev_for_each(rdev, mddev) {
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
|
|
||||||
if (rdev->sb_loaded != 1)
|
if (rdev->sb_loaded != 1)
|
||||||
continue; /* no noise on spare devices */
|
continue; /* no noise on spare devices */
|
||||||
|
|
||||||
|
|
@ -2812,8 +2801,8 @@ void md_update_sb(struct mddev *mddev, int force_change)
|
||||||
md_super_write(mddev,rdev,
|
md_super_write(mddev,rdev,
|
||||||
rdev->sb_start, rdev->sb_size,
|
rdev->sb_start, rdev->sb_size,
|
||||||
rdev->sb_page);
|
rdev->sb_page);
|
||||||
pr_debug("md: (write) %s's sb offset: %llu\n",
|
pr_debug("md: (write) %pg's sb offset: %llu\n",
|
||||||
bdevname(rdev->bdev, b),
|
rdev->bdev,
|
||||||
(unsigned long long)rdev->sb_start);
|
(unsigned long long)rdev->sb_start);
|
||||||
rdev->sb_events = mddev->events;
|
rdev->sb_events = mddev->events;
|
||||||
if (rdev->badblocks.size) {
|
if (rdev->badblocks.size) {
|
||||||
|
|
@ -2825,8 +2814,8 @@ void md_update_sb(struct mddev *mddev, int force_change)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else
|
} else
|
||||||
pr_debug("md: %s (skipping faulty)\n",
|
pr_debug("md: %pg (skipping faulty)\n",
|
||||||
bdevname(rdev->bdev, b));
|
rdev->bdev);
|
||||||
|
|
||||||
if (mddev->level == LEVEL_MULTIPATH)
|
if (mddev->level == LEVEL_MULTIPATH)
|
||||||
/* only need to write one superblock... */
|
/* only need to write one superblock... */
|
||||||
|
|
@ -3701,7 +3690,6 @@ EXPORT_SYMBOL_GPL(md_rdev_init);
|
||||||
*/
|
*/
|
||||||
static struct md_rdev *md_import_device(dev_t newdev, int super_format, int super_minor)
|
static struct md_rdev *md_import_device(dev_t newdev, int super_format, int super_minor)
|
||||||
{
|
{
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
int err;
|
int err;
|
||||||
struct md_rdev *rdev;
|
struct md_rdev *rdev;
|
||||||
sector_t size;
|
sector_t size;
|
||||||
|
|
@ -3725,8 +3713,8 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
|
||||||
|
|
||||||
size = bdev_nr_bytes(rdev->bdev) >> BLOCK_SIZE_BITS;
|
size = bdev_nr_bytes(rdev->bdev) >> BLOCK_SIZE_BITS;
|
||||||
if (!size) {
|
if (!size) {
|
||||||
pr_warn("md: %s has zero or unknown size, marking faulty!\n",
|
pr_warn("md: %pg has zero or unknown size, marking faulty!\n",
|
||||||
bdevname(rdev->bdev,b));
|
rdev->bdev);
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto abort_free;
|
goto abort_free;
|
||||||
}
|
}
|
||||||
|
|
@ -3735,14 +3723,14 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
|
||||||
err = super_types[super_format].
|
err = super_types[super_format].
|
||||||
load_super(rdev, NULL, super_minor);
|
load_super(rdev, NULL, super_minor);
|
||||||
if (err == -EINVAL) {
|
if (err == -EINVAL) {
|
||||||
pr_warn("md: %s does not have a valid v%d.%d superblock, not importing!\n",
|
pr_warn("md: %pg does not have a valid v%d.%d superblock, not importing!\n",
|
||||||
bdevname(rdev->bdev,b),
|
rdev->bdev,
|
||||||
super_format, super_minor);
|
super_format, super_minor);
|
||||||
goto abort_free;
|
goto abort_free;
|
||||||
}
|
}
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
pr_warn("md: could not read %s's sb, not importing!\n",
|
pr_warn("md: could not read %pg's sb, not importing!\n",
|
||||||
bdevname(rdev->bdev,b));
|
rdev->bdev);
|
||||||
goto abort_free;
|
goto abort_free;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3765,7 +3753,6 @@ static int analyze_sbs(struct mddev *mddev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct md_rdev *rdev, *freshest, *tmp;
|
struct md_rdev *rdev, *freshest, *tmp;
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
|
|
||||||
freshest = NULL;
|
freshest = NULL;
|
||||||
rdev_for_each_safe(rdev, tmp, mddev)
|
rdev_for_each_safe(rdev, tmp, mddev)
|
||||||
|
|
@ -3777,8 +3764,8 @@ static int analyze_sbs(struct mddev *mddev)
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pr_warn("md: fatal superblock inconsistency in %s -- removing from array\n",
|
pr_warn("md: fatal superblock inconsistency in %pg -- removing from array\n",
|
||||||
bdevname(rdev->bdev,b));
|
rdev->bdev);
|
||||||
md_kick_rdev_from_array(rdev);
|
md_kick_rdev_from_array(rdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3796,8 +3783,8 @@ static int analyze_sbs(struct mddev *mddev)
|
||||||
if (mddev->max_disks &&
|
if (mddev->max_disks &&
|
||||||
(rdev->desc_nr >= mddev->max_disks ||
|
(rdev->desc_nr >= mddev->max_disks ||
|
||||||
i > mddev->max_disks)) {
|
i > mddev->max_disks)) {
|
||||||
pr_warn("md: %s: %s: only %d devices permitted\n",
|
pr_warn("md: %s: %pg: only %d devices permitted\n",
|
||||||
mdname(mddev), bdevname(rdev->bdev, b),
|
mdname(mddev), rdev->bdev,
|
||||||
mddev->max_disks);
|
mddev->max_disks);
|
||||||
md_kick_rdev_from_array(rdev);
|
md_kick_rdev_from_array(rdev);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -3805,8 +3792,8 @@ static int analyze_sbs(struct mddev *mddev)
|
||||||
if (rdev != freshest) {
|
if (rdev != freshest) {
|
||||||
if (super_types[mddev->major_version].
|
if (super_types[mddev->major_version].
|
||||||
validate_super(mddev, rdev)) {
|
validate_super(mddev, rdev)) {
|
||||||
pr_warn("md: kicking non-fresh %s from array!\n",
|
pr_warn("md: kicking non-fresh %pg from array!\n",
|
||||||
bdevname(rdev->bdev,b));
|
rdev->bdev);
|
||||||
md_kick_rdev_from_array(rdev);
|
md_kick_rdev_from_array(rdev);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -4844,7 +4831,7 @@ action_store(struct mddev *mddev, const char *page, size_t len)
|
||||||
flush_workqueue(md_misc_wq);
|
flush_workqueue(md_misc_wq);
|
||||||
if (mddev->sync_thread) {
|
if (mddev->sync_thread) {
|
||||||
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
||||||
md_reap_sync_thread(mddev);
|
md_reap_sync_thread(mddev, true);
|
||||||
}
|
}
|
||||||
mddev_unlock(mddev);
|
mddev_unlock(mddev);
|
||||||
}
|
}
|
||||||
|
|
@ -5598,8 +5585,6 @@ static void md_free(struct kobject *ko)
|
||||||
|
|
||||||
bioset_exit(&mddev->bio_set);
|
bioset_exit(&mddev->bio_set);
|
||||||
bioset_exit(&mddev->sync_set);
|
bioset_exit(&mddev->sync_set);
|
||||||
if (mddev->level != 1 && mddev->level != 10)
|
|
||||||
bioset_exit(&mddev->io_acct_set);
|
|
||||||
kfree(mddev);
|
kfree(mddev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5912,7 +5897,6 @@ int md_run(struct mddev *mddev)
|
||||||
/* Warn if this is a potentially silly
|
/* Warn if this is a potentially silly
|
||||||
* configuration.
|
* configuration.
|
||||||
*/
|
*/
|
||||||
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
|
|
||||||
struct md_rdev *rdev2;
|
struct md_rdev *rdev2;
|
||||||
int warned = 0;
|
int warned = 0;
|
||||||
|
|
||||||
|
|
@ -5921,10 +5905,10 @@ int md_run(struct mddev *mddev)
|
||||||
if (rdev < rdev2 &&
|
if (rdev < rdev2 &&
|
||||||
rdev->bdev->bd_disk ==
|
rdev->bdev->bd_disk ==
|
||||||
rdev2->bdev->bd_disk) {
|
rdev2->bdev->bd_disk) {
|
||||||
pr_warn("%s: WARNING: %s appears to be on the same physical disk as %s.\n",
|
pr_warn("%s: WARNING: %pg appears to be on the same physical disk as %pg.\n",
|
||||||
mdname(mddev),
|
mdname(mddev),
|
||||||
bdevname(rdev->bdev,b),
|
rdev->bdev,
|
||||||
bdevname(rdev2->bdev,b2));
|
rdev2->bdev);
|
||||||
warned = 1;
|
warned = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6213,7 +6197,7 @@ static void __md_stop_writes(struct mddev *mddev)
|
||||||
flush_workqueue(md_misc_wq);
|
flush_workqueue(md_misc_wq);
|
||||||
if (mddev->sync_thread) {
|
if (mddev->sync_thread) {
|
||||||
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
||||||
md_reap_sync_thread(mddev);
|
md_reap_sync_thread(mddev, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
del_timer_sync(&mddev->safemode_timer);
|
del_timer_sync(&mddev->safemode_timer);
|
||||||
|
|
@ -6285,8 +6269,6 @@ void md_stop(struct mddev *mddev)
|
||||||
__md_stop(mddev);
|
__md_stop(mddev);
|
||||||
bioset_exit(&mddev->bio_set);
|
bioset_exit(&mddev->bio_set);
|
||||||
bioset_exit(&mddev->sync_set);
|
bioset_exit(&mddev->sync_set);
|
||||||
if (mddev->level != 1 && mddev->level != 10)
|
|
||||||
bioset_exit(&mddev->io_acct_set);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(md_stop);
|
EXPORT_SYMBOL_GPL(md_stop);
|
||||||
|
|
@ -6452,8 +6434,7 @@ static void autorun_array(struct mddev *mddev)
|
||||||
pr_info("md: running: ");
|
pr_info("md: running: ");
|
||||||
|
|
||||||
rdev_for_each(rdev, mddev) {
|
rdev_for_each(rdev, mddev) {
|
||||||
char b[BDEVNAME_SIZE];
|
pr_cont("<%pg>", rdev->bdev);
|
||||||
pr_cont("<%s>", bdevname(rdev->bdev,b));
|
|
||||||
}
|
}
|
||||||
pr_cont("\n");
|
pr_cont("\n");
|
||||||
|
|
||||||
|
|
@ -6480,7 +6461,6 @@ static void autorun_devices(int part)
|
||||||
{
|
{
|
||||||
struct md_rdev *rdev0, *rdev, *tmp;
|
struct md_rdev *rdev0, *rdev, *tmp;
|
||||||
struct mddev *mddev;
|
struct mddev *mddev;
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
|
|
||||||
pr_info("md: autorun ...\n");
|
pr_info("md: autorun ...\n");
|
||||||
while (!list_empty(&pending_raid_disks)) {
|
while (!list_empty(&pending_raid_disks)) {
|
||||||
|
|
@ -6490,12 +6470,12 @@ static void autorun_devices(int part)
|
||||||
rdev0 = list_entry(pending_raid_disks.next,
|
rdev0 = list_entry(pending_raid_disks.next,
|
||||||
struct md_rdev, same_set);
|
struct md_rdev, same_set);
|
||||||
|
|
||||||
pr_debug("md: considering %s ...\n", bdevname(rdev0->bdev,b));
|
pr_debug("md: considering %pg ...\n", rdev0->bdev);
|
||||||
INIT_LIST_HEAD(&candidates);
|
INIT_LIST_HEAD(&candidates);
|
||||||
rdev_for_each_list(rdev, tmp, &pending_raid_disks)
|
rdev_for_each_list(rdev, tmp, &pending_raid_disks)
|
||||||
if (super_90_load(rdev, rdev0, 0) >= 0) {
|
if (super_90_load(rdev, rdev0, 0) >= 0) {
|
||||||
pr_debug("md: adding %s ...\n",
|
pr_debug("md: adding %pg ...\n",
|
||||||
bdevname(rdev->bdev,b));
|
rdev->bdev);
|
||||||
list_move(&rdev->same_set, &candidates);
|
list_move(&rdev->same_set, &candidates);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
@ -6512,8 +6492,8 @@ static void autorun_devices(int part)
|
||||||
unit = MINOR(dev);
|
unit = MINOR(dev);
|
||||||
}
|
}
|
||||||
if (rdev0->preferred_minor != unit) {
|
if (rdev0->preferred_minor != unit) {
|
||||||
pr_warn("md: unit number in %s is bad: %d\n",
|
pr_warn("md: unit number in %pg is bad: %d\n",
|
||||||
bdevname(rdev0->bdev, b), rdev0->preferred_minor);
|
rdev0->bdev, rdev0->preferred_minor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6526,8 +6506,8 @@ static void autorun_devices(int part)
|
||||||
pr_warn("md: %s locked, cannot run\n", mdname(mddev));
|
pr_warn("md: %s locked, cannot run\n", mdname(mddev));
|
||||||
else if (mddev->raid_disks || mddev->major_version
|
else if (mddev->raid_disks || mddev->major_version
|
||||||
|| !list_empty(&mddev->disks)) {
|
|| !list_empty(&mddev->disks)) {
|
||||||
pr_warn("md: %s already running, cannot run %s\n",
|
pr_warn("md: %s already running, cannot run %pg\n",
|
||||||
mdname(mddev), bdevname(rdev0->bdev,b));
|
mdname(mddev), rdev0->bdev);
|
||||||
mddev_unlock(mddev);
|
mddev_unlock(mddev);
|
||||||
} else {
|
} else {
|
||||||
pr_debug("md: created %s\n", mdname(mddev));
|
pr_debug("md: created %s\n", mdname(mddev));
|
||||||
|
|
@ -6701,7 +6681,6 @@ static int get_disk_info(struct mddev *mddev, void __user * arg)
|
||||||
|
|
||||||
int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
|
int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
|
||||||
{
|
{
|
||||||
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
|
|
||||||
struct md_rdev *rdev;
|
struct md_rdev *rdev;
|
||||||
dev_t dev = MKDEV(info->major,info->minor);
|
dev_t dev = MKDEV(info->major,info->minor);
|
||||||
|
|
||||||
|
|
@ -6731,9 +6710,9 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
|
||||||
err = super_types[mddev->major_version]
|
err = super_types[mddev->major_version]
|
||||||
.load_super(rdev, rdev0, mddev->minor_version);
|
.load_super(rdev, rdev0, mddev->minor_version);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
pr_warn("md: %s has different UUID to %s\n",
|
pr_warn("md: %pg has different UUID to %pg\n",
|
||||||
bdevname(rdev->bdev,b),
|
rdev->bdev,
|
||||||
bdevname(rdev0->bdev,b2));
|
rdev0->bdev);
|
||||||
export_rdev(rdev);
|
export_rdev(rdev);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
@ -6908,7 +6887,6 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
|
||||||
|
|
||||||
static int hot_remove_disk(struct mddev *mddev, dev_t dev)
|
static int hot_remove_disk(struct mddev *mddev, dev_t dev)
|
||||||
{
|
{
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
struct md_rdev *rdev;
|
struct md_rdev *rdev;
|
||||||
|
|
||||||
if (!mddev->pers)
|
if (!mddev->pers)
|
||||||
|
|
@ -6943,14 +6921,13 @@ static int hot_remove_disk(struct mddev *mddev, dev_t dev)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
busy:
|
busy:
|
||||||
pr_debug("md: cannot remove active disk %s from %s ...\n",
|
pr_debug("md: cannot remove active disk %pg from %s ...\n",
|
||||||
bdevname(rdev->bdev,b), mdname(mddev));
|
rdev->bdev, mdname(mddev));
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hot_add_disk(struct mddev *mddev, dev_t dev)
|
static int hot_add_disk(struct mddev *mddev, dev_t dev)
|
||||||
{
|
{
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
int err;
|
int err;
|
||||||
struct md_rdev *rdev;
|
struct md_rdev *rdev;
|
||||||
|
|
||||||
|
|
@ -6983,8 +6960,8 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
|
||||||
rdev->sectors = rdev->sb_start;
|
rdev->sectors = rdev->sb_start;
|
||||||
|
|
||||||
if (test_bit(Faulty, &rdev->flags)) {
|
if (test_bit(Faulty, &rdev->flags)) {
|
||||||
pr_warn("md: can not hot-add faulty %s disk to %s!\n",
|
pr_warn("md: can not hot-add faulty %pg disk to %s!\n",
|
||||||
bdevname(rdev->bdev,b), mdname(mddev));
|
rdev->bdev, mdname(mddev));
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto abort_export;
|
goto abort_export;
|
||||||
}
|
}
|
||||||
|
|
@ -7011,8 +6988,8 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
|
||||||
* disable on the whole MD.
|
* disable on the whole MD.
|
||||||
*/
|
*/
|
||||||
if (!blk_queue_nowait(bdev_get_queue(rdev->bdev))) {
|
if (!blk_queue_nowait(bdev_get_queue(rdev->bdev))) {
|
||||||
pr_info("%s: Disabling nowait because %s does not support nowait\n",
|
pr_info("%s: Disabling nowait because %pg does not support nowait\n",
|
||||||
mdname(mddev), bdevname(rdev->bdev, b));
|
mdname(mddev), rdev->bdev);
|
||||||
blk_queue_flag_clear(QUEUE_FLAG_NOWAIT, mddev->queue);
|
blk_queue_flag_clear(QUEUE_FLAG_NOWAIT, mddev->queue);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
@ -7963,17 +7940,22 @@ EXPORT_SYMBOL(md_register_thread);
|
||||||
|
|
||||||
void md_unregister_thread(struct md_thread **threadp)
|
void md_unregister_thread(struct md_thread **threadp)
|
||||||
{
|
{
|
||||||
struct md_thread *thread = *threadp;
|
struct md_thread *thread;
|
||||||
if (!thread)
|
|
||||||
return;
|
/*
|
||||||
pr_debug("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk));
|
* Locking ensures that mddev_unlock does not wake_up a
|
||||||
/* Locking ensures that mddev_unlock does not wake_up a
|
|
||||||
* non-existent thread
|
* non-existent thread
|
||||||
*/
|
*/
|
||||||
spin_lock(&pers_lock);
|
spin_lock(&pers_lock);
|
||||||
|
thread = *threadp;
|
||||||
|
if (!thread) {
|
||||||
|
spin_unlock(&pers_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
*threadp = NULL;
|
*threadp = NULL;
|
||||||
spin_unlock(&pers_lock);
|
spin_unlock(&pers_lock);
|
||||||
|
|
||||||
|
pr_debug("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk));
|
||||||
kthread_stop(thread->tsk);
|
kthread_stop(thread->tsk);
|
||||||
kfree(thread);
|
kfree(thread);
|
||||||
}
|
}
|
||||||
|
|
@ -8012,10 +7994,8 @@ static void status_unused(struct seq_file *seq)
|
||||||
seq_printf(seq, "unused devices: ");
|
seq_printf(seq, "unused devices: ");
|
||||||
|
|
||||||
list_for_each_entry(rdev, &pending_raid_disks, same_set) {
|
list_for_each_entry(rdev, &pending_raid_disks, same_set) {
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
i++;
|
i++;
|
||||||
seq_printf(seq, "%s ",
|
seq_printf(seq, "%pg ", rdev->bdev);
|
||||||
bdevname(rdev->bdev,b));
|
|
||||||
}
|
}
|
||||||
if (!i)
|
if (!i)
|
||||||
seq_printf(seq, "<none>");
|
seq_printf(seq, "<none>");
|
||||||
|
|
@ -8255,9 +8235,8 @@ static int md_seq_show(struct seq_file *seq, void *v)
|
||||||
sectors = 0;
|
sectors = 0;
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
rdev_for_each_rcu(rdev, mddev) {
|
rdev_for_each_rcu(rdev, mddev) {
|
||||||
char b[BDEVNAME_SIZE];
|
seq_printf(seq, " %pg[%d]", rdev->bdev, rdev->desc_nr);
|
||||||
seq_printf(seq, " %s[%d]",
|
|
||||||
bdevname(rdev->bdev,b), rdev->desc_nr);
|
|
||||||
if (test_bit(WriteMostly, &rdev->flags))
|
if (test_bit(WriteMostly, &rdev->flags))
|
||||||
seq_printf(seq, "(W)");
|
seq_printf(seq, "(W)");
|
||||||
if (test_bit(Journal, &rdev->flags))
|
if (test_bit(Journal, &rdev->flags))
|
||||||
|
|
@ -9324,7 +9303,7 @@ void md_check_recovery(struct mddev *mddev)
|
||||||
* ->spare_active and clear saved_raid_disk
|
* ->spare_active and clear saved_raid_disk
|
||||||
*/
|
*/
|
||||||
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
||||||
md_reap_sync_thread(mddev);
|
md_reap_sync_thread(mddev, true);
|
||||||
clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
|
clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
|
||||||
clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
||||||
clear_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags);
|
clear_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags);
|
||||||
|
|
@ -9359,7 +9338,7 @@ void md_check_recovery(struct mddev *mddev)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
if (mddev->sync_thread) {
|
if (mddev->sync_thread) {
|
||||||
md_reap_sync_thread(mddev);
|
md_reap_sync_thread(mddev, true);
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
/* Set RUNNING before clearing NEEDED to avoid
|
/* Set RUNNING before clearing NEEDED to avoid
|
||||||
|
|
@ -9432,14 +9411,18 @@ void md_check_recovery(struct mddev *mddev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(md_check_recovery);
|
EXPORT_SYMBOL(md_check_recovery);
|
||||||
|
|
||||||
void md_reap_sync_thread(struct mddev *mddev)
|
void md_reap_sync_thread(struct mddev *mddev, bool reconfig_mutex_held)
|
||||||
{
|
{
|
||||||
struct md_rdev *rdev;
|
struct md_rdev *rdev;
|
||||||
sector_t old_dev_sectors = mddev->dev_sectors;
|
sector_t old_dev_sectors = mddev->dev_sectors;
|
||||||
bool is_reshaped = false;
|
bool is_reshaped = false;
|
||||||
|
|
||||||
|
if (reconfig_mutex_held)
|
||||||
|
mddev_unlock(mddev);
|
||||||
/* resync has finished, collect result */
|
/* resync has finished, collect result */
|
||||||
md_unregister_thread(&mddev->sync_thread);
|
md_unregister_thread(&mddev->sync_thread);
|
||||||
|
if (reconfig_mutex_held)
|
||||||
|
mddev_lock_nointr(mddev);
|
||||||
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
|
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
|
||||||
!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
|
!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
|
||||||
mddev->degraded != mddev->raid_disks) {
|
mddev->degraded != mddev->raid_disks) {
|
||||||
|
|
@ -9652,7 +9635,6 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev)
|
||||||
struct mdp_superblock_1 *sb = page_address(rdev->sb_page);
|
struct mdp_superblock_1 *sb = page_address(rdev->sb_page);
|
||||||
struct md_rdev *rdev2, *tmp;
|
struct md_rdev *rdev2, *tmp;
|
||||||
int role, ret;
|
int role, ret;
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If size is changed in another node then we need to
|
* If size is changed in another node then we need to
|
||||||
|
|
@ -9676,7 +9658,8 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev)
|
||||||
|
|
||||||
if (test_bit(Candidate, &rdev2->flags)) {
|
if (test_bit(Candidate, &rdev2->flags)) {
|
||||||
if (role == MD_DISK_ROLE_FAULTY) {
|
if (role == MD_DISK_ROLE_FAULTY) {
|
||||||
pr_info("md: Removing Candidate device %s because add failed\n", bdevname(rdev2->bdev,b));
|
pr_info("md: Removing Candidate device %pg because add failed\n",
|
||||||
|
rdev2->bdev);
|
||||||
md_kick_rdev_from_array(rdev2);
|
md_kick_rdev_from_array(rdev2);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -9693,8 +9676,8 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev)
|
||||||
MD_FEATURE_RESHAPE_ACTIVE)) {
|
MD_FEATURE_RESHAPE_ACTIVE)) {
|
||||||
rdev2->saved_raid_disk = role;
|
rdev2->saved_raid_disk = role;
|
||||||
ret = remove_and_add_spares(mddev, rdev2);
|
ret = remove_and_add_spares(mddev, rdev2);
|
||||||
pr_info("Activated spare: %s\n",
|
pr_info("Activated spare: %pg\n",
|
||||||
bdevname(rdev2->bdev,b));
|
rdev2->bdev);
|
||||||
/* wakeup mddev->thread here, so array could
|
/* wakeup mddev->thread here, so array could
|
||||||
* perform resync with the new activated disk */
|
* perform resync with the new activated disk */
|
||||||
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
||||||
|
|
|
||||||
|
|
@ -719,7 +719,7 @@ extern struct md_thread *md_register_thread(
|
||||||
extern void md_unregister_thread(struct md_thread **threadp);
|
extern void md_unregister_thread(struct md_thread **threadp);
|
||||||
extern void md_wakeup_thread(struct md_thread *thread);
|
extern void md_wakeup_thread(struct md_thread *thread);
|
||||||
extern void md_check_recovery(struct mddev *mddev);
|
extern void md_check_recovery(struct mddev *mddev);
|
||||||
extern void md_reap_sync_thread(struct mddev *mddev);
|
extern void md_reap_sync_thread(struct mddev *mddev, bool reconfig_mutex_held);
|
||||||
extern int mddev_init_writes_pending(struct mddev *mddev);
|
extern int mddev_init_writes_pending(struct mddev *mddev);
|
||||||
extern bool md_write_start(struct mddev *mddev, struct bio *bi);
|
extern bool md_write_start(struct mddev *mddev, struct bio *bi);
|
||||||
extern void md_write_inc(struct mddev *mddev, struct bio *bi);
|
extern void md_write_inc(struct mddev *mddev, struct bio *bi);
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ static void dump_zones(struct mddev *mddev)
|
||||||
int j, k;
|
int j, k;
|
||||||
sector_t zone_size = 0;
|
sector_t zone_size = 0;
|
||||||
sector_t zone_start = 0;
|
sector_t zone_start = 0;
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
struct r0conf *conf = mddev->private;
|
struct r0conf *conf = mddev->private;
|
||||||
int raid_disks = conf->strip_zone[0].nb_dev;
|
int raid_disks = conf->strip_zone[0].nb_dev;
|
||||||
pr_debug("md: RAID0 configuration for %s - %d zone%s\n",
|
pr_debug("md: RAID0 configuration for %s - %d zone%s\n",
|
||||||
|
|
@ -48,9 +47,8 @@ static void dump_zones(struct mddev *mddev)
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
|
for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
|
||||||
len += snprintf(line+len, 200-len, "%s%s", k?"/":"",
|
len += snprintf(line+len, 200-len, "%s%pg", k?"/":"",
|
||||||
bdevname(conf->devlist[j*raid_disks
|
conf->devlist[j * raid_disks + k]->bdev);
|
||||||
+ k]->bdev, b));
|
|
||||||
pr_debug("md: zone%d=[%s]\n", j, line);
|
pr_debug("md: zone%d=[%s]\n", j, line);
|
||||||
|
|
||||||
zone_size = conf->strip_zone[j].zone_end - zone_start;
|
zone_size = conf->strip_zone[j].zone_end - zone_start;
|
||||||
|
|
@ -69,8 +67,6 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
|
||||||
struct md_rdev *smallest, *rdev1, *rdev2, *rdev, **dev;
|
struct md_rdev *smallest, *rdev1, *rdev2, *rdev, **dev;
|
||||||
struct strip_zone *zone;
|
struct strip_zone *zone;
|
||||||
int cnt;
|
int cnt;
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
char b2[BDEVNAME_SIZE];
|
|
||||||
struct r0conf *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
|
struct r0conf *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
|
||||||
unsigned blksize = 512;
|
unsigned blksize = 512;
|
||||||
|
|
||||||
|
|
@ -78,9 +74,9 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
|
||||||
if (!conf)
|
if (!conf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
rdev_for_each(rdev1, mddev) {
|
rdev_for_each(rdev1, mddev) {
|
||||||
pr_debug("md/raid0:%s: looking at %s\n",
|
pr_debug("md/raid0:%s: looking at %pg\n",
|
||||||
mdname(mddev),
|
mdname(mddev),
|
||||||
bdevname(rdev1->bdev, b));
|
rdev1->bdev);
|
||||||
c = 0;
|
c = 0;
|
||||||
|
|
||||||
/* round size to chunk_size */
|
/* round size to chunk_size */
|
||||||
|
|
@ -92,12 +88,12 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
|
||||||
rdev1->bdev->bd_disk->queue));
|
rdev1->bdev->bd_disk->queue));
|
||||||
|
|
||||||
rdev_for_each(rdev2, mddev) {
|
rdev_for_each(rdev2, mddev) {
|
||||||
pr_debug("md/raid0:%s: comparing %s(%llu)"
|
pr_debug("md/raid0:%s: comparing %pg(%llu)"
|
||||||
" with %s(%llu)\n",
|
" with %pg(%llu)\n",
|
||||||
mdname(mddev),
|
mdname(mddev),
|
||||||
bdevname(rdev1->bdev,b),
|
rdev1->bdev,
|
||||||
(unsigned long long)rdev1->sectors,
|
(unsigned long long)rdev1->sectors,
|
||||||
bdevname(rdev2->bdev,b2),
|
rdev2->bdev,
|
||||||
(unsigned long long)rdev2->sectors);
|
(unsigned long long)rdev2->sectors);
|
||||||
if (rdev2 == rdev1) {
|
if (rdev2 == rdev1) {
|
||||||
pr_debug("md/raid0:%s: END\n",
|
pr_debug("md/raid0:%s: END\n",
|
||||||
|
|
@ -225,15 +221,15 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
|
||||||
for (j=0; j<cnt; j++) {
|
for (j=0; j<cnt; j++) {
|
||||||
rdev = conf->devlist[j];
|
rdev = conf->devlist[j];
|
||||||
if (rdev->sectors <= zone->dev_start) {
|
if (rdev->sectors <= zone->dev_start) {
|
||||||
pr_debug("md/raid0:%s: checking %s ... nope\n",
|
pr_debug("md/raid0:%s: checking %pg ... nope\n",
|
||||||
mdname(mddev),
|
mdname(mddev),
|
||||||
bdevname(rdev->bdev, b));
|
rdev->bdev);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
pr_debug("md/raid0:%s: checking %s ..."
|
pr_debug("md/raid0:%s: checking %pg ..."
|
||||||
" contained as device %d\n",
|
" contained as device %d\n",
|
||||||
mdname(mddev),
|
mdname(mddev),
|
||||||
bdevname(rdev->bdev, b), c);
|
rdev->bdev, c);
|
||||||
dev[c] = rdev;
|
dev[c] = rdev;
|
||||||
c++;
|
c++;
|
||||||
if (!smallest || rdev->sectors < smallest->sectors) {
|
if (!smallest || rdev->sectors < smallest->sectors) {
|
||||||
|
|
@ -362,7 +358,6 @@ static void free_conf(struct mddev *mddev, struct r0conf *conf)
|
||||||
kfree(conf->strip_zone);
|
kfree(conf->strip_zone);
|
||||||
kfree(conf->devlist);
|
kfree(conf->devlist);
|
||||||
kfree(conf);
|
kfree(conf);
|
||||||
mddev->private = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void raid0_free(struct mddev *mddev, void *priv)
|
static void raid0_free(struct mddev *mddev, void *priv)
|
||||||
|
|
|
||||||
|
|
@ -402,10 +402,9 @@ static void raid1_end_read_request(struct bio *bio)
|
||||||
/*
|
/*
|
||||||
* oops, read error:
|
* oops, read error:
|
||||||
*/
|
*/
|
||||||
char b[BDEVNAME_SIZE];
|
pr_err_ratelimited("md/raid1:%s: %pg: rescheduling sector %llu\n",
|
||||||
pr_err_ratelimited("md/raid1:%s: %s: rescheduling sector %llu\n",
|
|
||||||
mdname(conf->mddev),
|
mdname(conf->mddev),
|
||||||
bdevname(rdev->bdev, b),
|
rdev->bdev,
|
||||||
(unsigned long long)r1_bio->sector);
|
(unsigned long long)r1_bio->sector);
|
||||||
set_bit(R1BIO_ReadError, &r1_bio->state);
|
set_bit(R1BIO_ReadError, &r1_bio->state);
|
||||||
reschedule_retry(r1_bio);
|
reschedule_retry(r1_bio);
|
||||||
|
|
@ -1283,10 +1282,10 @@ static void raid1_read_request(struct mddev *mddev, struct bio *bio,
|
||||||
mirror = conf->mirrors + rdisk;
|
mirror = conf->mirrors + rdisk;
|
||||||
|
|
||||||
if (r1bio_existed)
|
if (r1bio_existed)
|
||||||
pr_info_ratelimited("md/raid1:%s: redirecting sector %llu to other mirror: %s\n",
|
pr_info_ratelimited("md/raid1:%s: redirecting sector %llu to other mirror: %pg\n",
|
||||||
mdname(mddev),
|
mdname(mddev),
|
||||||
(unsigned long long)r1_bio->sector,
|
(unsigned long long)r1_bio->sector,
|
||||||
bdevname(mirror->rdev->bdev, b));
|
mirror->rdev->bdev);
|
||||||
|
|
||||||
if (test_bit(WriteMostly, &mirror->rdev->flags) &&
|
if (test_bit(WriteMostly, &mirror->rdev->flags) &&
|
||||||
bitmap) {
|
bitmap) {
|
||||||
|
|
@ -1659,7 +1658,6 @@ static void raid1_status(struct seq_file *seq, struct mddev *mddev)
|
||||||
*/
|
*/
|
||||||
static void raid1_error(struct mddev *mddev, struct md_rdev *rdev)
|
static void raid1_error(struct mddev *mddev, struct md_rdev *rdev)
|
||||||
{
|
{
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
struct r1conf *conf = mddev->private;
|
struct r1conf *conf = mddev->private;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
|
@ -1686,9 +1684,9 @@ static void raid1_error(struct mddev *mddev, struct md_rdev *rdev)
|
||||||
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
||||||
set_mask_bits(&mddev->sb_flags, 0,
|
set_mask_bits(&mddev->sb_flags, 0,
|
||||||
BIT(MD_SB_CHANGE_DEVS) | BIT(MD_SB_CHANGE_PENDING));
|
BIT(MD_SB_CHANGE_DEVS) | BIT(MD_SB_CHANGE_PENDING));
|
||||||
pr_crit("md/raid1:%s: Disk failure on %s, disabling device.\n"
|
pr_crit("md/raid1:%s: Disk failure on %pg, disabling device.\n"
|
||||||
"md/raid1:%s: Operation continuing on %d devices.\n",
|
"md/raid1:%s: Operation continuing on %d devices.\n",
|
||||||
mdname(mddev), bdevname(rdev->bdev, b),
|
mdname(mddev), rdev->bdev,
|
||||||
mdname(mddev), conf->raid_disks - mddev->degraded);
|
mdname(mddev), conf->raid_disks - mddev->degraded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1706,13 +1704,12 @@ static void print_conf(struct r1conf *conf)
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
for (i = 0; i < conf->raid_disks; i++) {
|
for (i = 0; i < conf->raid_disks; i++) {
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
|
struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
|
||||||
if (rdev)
|
if (rdev)
|
||||||
pr_debug(" disk %d, wo:%d, o:%d, dev:%s\n",
|
pr_debug(" disk %d, wo:%d, o:%d, dev:%pg\n",
|
||||||
i, !test_bit(In_sync, &rdev->flags),
|
i, !test_bit(In_sync, &rdev->flags),
|
||||||
!test_bit(Faulty, &rdev->flags),
|
!test_bit(Faulty, &rdev->flags),
|
||||||
bdevname(rdev->bdev,b));
|
rdev->bdev);
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
@ -2347,7 +2344,6 @@ static void fix_read_error(struct r1conf *conf, int read_disk,
|
||||||
}
|
}
|
||||||
d = start;
|
d = start;
|
||||||
while (d != read_disk) {
|
while (d != read_disk) {
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
if (d==0)
|
if (d==0)
|
||||||
d = conf->raid_disks * 2;
|
d = conf->raid_disks * 2;
|
||||||
d--;
|
d--;
|
||||||
|
|
@ -2360,11 +2356,11 @@ static void fix_read_error(struct r1conf *conf, int read_disk,
|
||||||
if (r1_sync_page_io(rdev, sect, s,
|
if (r1_sync_page_io(rdev, sect, s,
|
||||||
conf->tmppage, READ)) {
|
conf->tmppage, READ)) {
|
||||||
atomic_add(s, &rdev->corrected_errors);
|
atomic_add(s, &rdev->corrected_errors);
|
||||||
pr_info("md/raid1:%s: read error corrected (%d sectors at %llu on %s)\n",
|
pr_info("md/raid1:%s: read error corrected (%d sectors at %llu on %pg)\n",
|
||||||
mdname(mddev), s,
|
mdname(mddev), s,
|
||||||
(unsigned long long)(sect +
|
(unsigned long long)(sect +
|
||||||
rdev->data_offset),
|
rdev->data_offset),
|
||||||
bdevname(rdev->bdev, b));
|
rdev->bdev);
|
||||||
}
|
}
|
||||||
rdev_dec_pending(rdev, mddev);
|
rdev_dec_pending(rdev, mddev);
|
||||||
} else
|
} else
|
||||||
|
|
|
||||||
|
|
@ -397,10 +397,9 @@ static void raid10_end_read_request(struct bio *bio)
|
||||||
/*
|
/*
|
||||||
* oops, read error - keep the refcount on the rdev
|
* oops, read error - keep the refcount on the rdev
|
||||||
*/
|
*/
|
||||||
char b[BDEVNAME_SIZE];
|
pr_err_ratelimited("md/raid10:%s: %pg: rescheduling sector %llu\n",
|
||||||
pr_err_ratelimited("md/raid10:%s: %s: rescheduling sector %llu\n",
|
|
||||||
mdname(conf->mddev),
|
mdname(conf->mddev),
|
||||||
bdevname(rdev->bdev, b),
|
rdev->bdev,
|
||||||
(unsigned long long)r10_bio->sector);
|
(unsigned long long)r10_bio->sector);
|
||||||
set_bit(R10BIO_ReadError, &r10_bio->state);
|
set_bit(R10BIO_ReadError, &r10_bio->state);
|
||||||
reschedule_retry(r10_bio);
|
reschedule_retry(r10_bio);
|
||||||
|
|
@ -1187,9 +1186,9 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (err_rdev)
|
if (err_rdev)
|
||||||
pr_err_ratelimited("md/raid10:%s: %s: redirecting sector %llu to another mirror\n",
|
pr_err_ratelimited("md/raid10:%s: %pg: redirecting sector %llu to another mirror\n",
|
||||||
mdname(mddev),
|
mdname(mddev),
|
||||||
bdevname(rdev->bdev, b),
|
rdev->bdev,
|
||||||
(unsigned long long)r10_bio->sector);
|
(unsigned long long)r10_bio->sector);
|
||||||
if (max_sectors < bio_sectors(bio)) {
|
if (max_sectors < bio_sectors(bio)) {
|
||||||
struct bio *split = bio_split(bio, max_sectors,
|
struct bio *split = bio_split(bio, max_sectors,
|
||||||
|
|
@ -1987,7 +1986,6 @@ static int enough(struct r10conf *conf, int ignore)
|
||||||
*/
|
*/
|
||||||
static void raid10_error(struct mddev *mddev, struct md_rdev *rdev)
|
static void raid10_error(struct mddev *mddev, struct md_rdev *rdev)
|
||||||
{
|
{
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
struct r10conf *conf = mddev->private;
|
struct r10conf *conf = mddev->private;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
|
@ -2010,9 +2008,9 @@ static void raid10_error(struct mddev *mddev, struct md_rdev *rdev)
|
||||||
set_mask_bits(&mddev->sb_flags, 0,
|
set_mask_bits(&mddev->sb_flags, 0,
|
||||||
BIT(MD_SB_CHANGE_DEVS) | BIT(MD_SB_CHANGE_PENDING));
|
BIT(MD_SB_CHANGE_DEVS) | BIT(MD_SB_CHANGE_PENDING));
|
||||||
spin_unlock_irqrestore(&conf->device_lock, flags);
|
spin_unlock_irqrestore(&conf->device_lock, flags);
|
||||||
pr_crit("md/raid10:%s: Disk failure on %s, disabling device.\n"
|
pr_crit("md/raid10:%s: Disk failure on %pg, disabling device.\n"
|
||||||
"md/raid10:%s: Operation continuing on %d devices.\n",
|
"md/raid10:%s: Operation continuing on %d devices.\n",
|
||||||
mdname(mddev), bdevname(rdev->bdev, b),
|
mdname(mddev), rdev->bdev,
|
||||||
mdname(mddev), conf->geo.raid_disks - mddev->degraded);
|
mdname(mddev), conf->geo.raid_disks - mddev->degraded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2032,13 +2030,12 @@ static void print_conf(struct r10conf *conf)
|
||||||
/* This is only called with ->reconfix_mutex held, so
|
/* This is only called with ->reconfix_mutex held, so
|
||||||
* rcu protection of rdev is not needed */
|
* rcu protection of rdev is not needed */
|
||||||
for (i = 0; i < conf->geo.raid_disks; i++) {
|
for (i = 0; i < conf->geo.raid_disks; i++) {
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
rdev = conf->mirrors[i].rdev;
|
rdev = conf->mirrors[i].rdev;
|
||||||
if (rdev)
|
if (rdev)
|
||||||
pr_debug(" disk %d, wo:%d, o:%d, dev:%s\n",
|
pr_debug(" disk %d, wo:%d, o:%d, dev:%pg\n",
|
||||||
i, !test_bit(In_sync, &rdev->flags),
|
i, !test_bit(In_sync, &rdev->flags),
|
||||||
!test_bit(Faulty, &rdev->flags),
|
!test_bit(Faulty, &rdev->flags),
|
||||||
bdevname(rdev->bdev,b));
|
rdev->bdev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2691,14 +2688,11 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
|
||||||
check_decay_read_errors(mddev, rdev);
|
check_decay_read_errors(mddev, rdev);
|
||||||
atomic_inc(&rdev->read_errors);
|
atomic_inc(&rdev->read_errors);
|
||||||
if (atomic_read(&rdev->read_errors) > max_read_errors) {
|
if (atomic_read(&rdev->read_errors) > max_read_errors) {
|
||||||
char b[BDEVNAME_SIZE];
|
pr_notice("md/raid10:%s: %pg: Raid device exceeded read_error threshold [cur %d:max %d]\n",
|
||||||
bdevname(rdev->bdev, b);
|
mdname(mddev), rdev->bdev,
|
||||||
|
|
||||||
pr_notice("md/raid10:%s: %s: Raid device exceeded read_error threshold [cur %d:max %d]\n",
|
|
||||||
mdname(mddev), b,
|
|
||||||
atomic_read(&rdev->read_errors), max_read_errors);
|
atomic_read(&rdev->read_errors), max_read_errors);
|
||||||
pr_notice("md/raid10:%s: %s: Failing raid device\n",
|
pr_notice("md/raid10:%s: %pg: Failing raid device\n",
|
||||||
mdname(mddev), b);
|
mdname(mddev), rdev->bdev);
|
||||||
md_error(mddev, rdev);
|
md_error(mddev, rdev);
|
||||||
r10_bio->devs[r10_bio->read_slot].bio = IO_BLOCKED;
|
r10_bio->devs[r10_bio->read_slot].bio = IO_BLOCKED;
|
||||||
return;
|
return;
|
||||||
|
|
@ -2768,8 +2762,6 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
|
||||||
/* write it back and re-read */
|
/* write it back and re-read */
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
while (sl != r10_bio->read_slot) {
|
while (sl != r10_bio->read_slot) {
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
|
|
||||||
if (sl==0)
|
if (sl==0)
|
||||||
sl = conf->copies;
|
sl = conf->copies;
|
||||||
sl--;
|
sl--;
|
||||||
|
|
@ -2788,24 +2780,22 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
|
||||||
s, conf->tmppage, WRITE)
|
s, conf->tmppage, WRITE)
|
||||||
== 0) {
|
== 0) {
|
||||||
/* Well, this device is dead */
|
/* Well, this device is dead */
|
||||||
pr_notice("md/raid10:%s: read correction write failed (%d sectors at %llu on %s)\n",
|
pr_notice("md/raid10:%s: read correction write failed (%d sectors at %llu on %pg)\n",
|
||||||
mdname(mddev), s,
|
mdname(mddev), s,
|
||||||
(unsigned long long)(
|
(unsigned long long)(
|
||||||
sect +
|
sect +
|
||||||
choose_data_offset(r10_bio,
|
choose_data_offset(r10_bio,
|
||||||
rdev)),
|
rdev)),
|
||||||
bdevname(rdev->bdev, b));
|
rdev->bdev);
|
||||||
pr_notice("md/raid10:%s: %s: failing drive\n",
|
pr_notice("md/raid10:%s: %pg: failing drive\n",
|
||||||
mdname(mddev),
|
mdname(mddev),
|
||||||
bdevname(rdev->bdev, b));
|
rdev->bdev);
|
||||||
}
|
}
|
||||||
rdev_dec_pending(rdev, mddev);
|
rdev_dec_pending(rdev, mddev);
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
}
|
}
|
||||||
sl = start;
|
sl = start;
|
||||||
while (sl != r10_bio->read_slot) {
|
while (sl != r10_bio->read_slot) {
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
|
|
||||||
if (sl==0)
|
if (sl==0)
|
||||||
sl = conf->copies;
|
sl = conf->copies;
|
||||||
sl--;
|
sl--;
|
||||||
|
|
@ -2825,23 +2815,23 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
|
||||||
READ)) {
|
READ)) {
|
||||||
case 0:
|
case 0:
|
||||||
/* Well, this device is dead */
|
/* Well, this device is dead */
|
||||||
pr_notice("md/raid10:%s: unable to read back corrected sectors (%d sectors at %llu on %s)\n",
|
pr_notice("md/raid10:%s: unable to read back corrected sectors (%d sectors at %llu on %pg)\n",
|
||||||
mdname(mddev), s,
|
mdname(mddev), s,
|
||||||
(unsigned long long)(
|
(unsigned long long)(
|
||||||
sect +
|
sect +
|
||||||
choose_data_offset(r10_bio, rdev)),
|
choose_data_offset(r10_bio, rdev)),
|
||||||
bdevname(rdev->bdev, b));
|
rdev->bdev);
|
||||||
pr_notice("md/raid10:%s: %s: failing drive\n",
|
pr_notice("md/raid10:%s: %pg: failing drive\n",
|
||||||
mdname(mddev),
|
mdname(mddev),
|
||||||
bdevname(rdev->bdev, b));
|
rdev->bdev);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
pr_info("md/raid10:%s: read error corrected (%d sectors at %llu on %s)\n",
|
pr_info("md/raid10:%s: read error corrected (%d sectors at %llu on %pg)\n",
|
||||||
mdname(mddev), s,
|
mdname(mddev), s,
|
||||||
(unsigned long long)(
|
(unsigned long long)(
|
||||||
sect +
|
sect +
|
||||||
choose_data_offset(r10_bio, rdev)),
|
choose_data_offset(r10_bio, rdev)),
|
||||||
bdevname(rdev->bdev, b));
|
rdev->bdev);
|
||||||
atomic_add(s, &rdev->corrected_errors);
|
atomic_add(s, &rdev->corrected_errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3064,11 +3064,10 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
|
||||||
{
|
{
|
||||||
struct request_queue *q = bdev_get_queue(rdev->bdev);
|
struct request_queue *q = bdev_get_queue(rdev->bdev);
|
||||||
struct r5l_log *log;
|
struct r5l_log *log;
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
pr_debug("md/raid:%s: using device %s as journal\n",
|
pr_debug("md/raid:%s: using device %pg as journal\n",
|
||||||
mdname(conf->mddev), bdevname(rdev->bdev, b));
|
mdname(conf->mddev), rdev->bdev);
|
||||||
|
|
||||||
if (PAGE_SIZE != 4096)
|
if (PAGE_SIZE != 4096)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
||||||
|
|
@ -798,7 +798,6 @@ static int ppl_recover_entry(struct ppl_log *log, struct ppl_header_entry *e,
|
||||||
int data_disks;
|
int data_disks;
|
||||||
int i;
|
int i;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
unsigned int pp_size = le32_to_cpu(e->pp_size);
|
unsigned int pp_size = le32_to_cpu(e->pp_size);
|
||||||
unsigned int data_size = le32_to_cpu(e->data_size);
|
unsigned int data_size = le32_to_cpu(e->data_size);
|
||||||
|
|
||||||
|
|
@ -894,8 +893,8 @@ static int ppl_recover_entry(struct ppl_log *log, struct ppl_header_entry *e,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_debug("%s:%*s reading data member disk %s sector %llu\n",
|
pr_debug("%s:%*s reading data member disk %pg sector %llu\n",
|
||||||
__func__, indent, "", bdevname(rdev->bdev, b),
|
__func__, indent, "", rdev->bdev,
|
||||||
(unsigned long long)sector);
|
(unsigned long long)sector);
|
||||||
if (!sync_page_io(rdev, sector, block_size, page2,
|
if (!sync_page_io(rdev, sector, block_size, page2,
|
||||||
REQ_OP_READ, 0, false)) {
|
REQ_OP_READ, 0, false)) {
|
||||||
|
|
@ -942,10 +941,10 @@ static int ppl_recover_entry(struct ppl_log *log, struct ppl_header_entry *e,
|
||||||
conf->disks[sh.pd_idx].rdev, 1);
|
conf->disks[sh.pd_idx].rdev, 1);
|
||||||
|
|
||||||
BUG_ON(parity_rdev->bdev->bd_dev != log->rdev->bdev->bd_dev);
|
BUG_ON(parity_rdev->bdev->bd_dev != log->rdev->bdev->bd_dev);
|
||||||
pr_debug("%s:%*s write parity at sector %llu, disk %s\n",
|
pr_debug("%s:%*s write parity at sector %llu, disk %pg\n",
|
||||||
__func__, indent, "",
|
__func__, indent, "",
|
||||||
(unsigned long long)parity_sector,
|
(unsigned long long)parity_sector,
|
||||||
bdevname(parity_rdev->bdev, b));
|
parity_rdev->bdev);
|
||||||
if (!sync_page_io(parity_rdev, parity_sector, block_size,
|
if (!sync_page_io(parity_rdev, parity_sector, block_size,
|
||||||
page1, REQ_OP_WRITE, 0, false)) {
|
page1, REQ_OP_WRITE, 0, false)) {
|
||||||
pr_debug("%s:%*s parity write error!\n", __func__,
|
pr_debug("%s:%*s parity write error!\n", __func__,
|
||||||
|
|
@ -1255,7 +1254,6 @@ void ppl_exit_log(struct r5conf *conf)
|
||||||
|
|
||||||
static int ppl_validate_rdev(struct md_rdev *rdev)
|
static int ppl_validate_rdev(struct md_rdev *rdev)
|
||||||
{
|
{
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
int ppl_data_sectors;
|
int ppl_data_sectors;
|
||||||
int ppl_size_new;
|
int ppl_size_new;
|
||||||
|
|
||||||
|
|
@ -1272,8 +1270,8 @@ static int ppl_validate_rdev(struct md_rdev *rdev)
|
||||||
RAID5_STRIPE_SECTORS((struct r5conf *)rdev->mddev->private));
|
RAID5_STRIPE_SECTORS((struct r5conf *)rdev->mddev->private));
|
||||||
|
|
||||||
if (ppl_data_sectors <= 0) {
|
if (ppl_data_sectors <= 0) {
|
||||||
pr_warn("md/raid:%s: PPL space too small on %s\n",
|
pr_warn("md/raid:%s: PPL space too small on %pg\n",
|
||||||
mdname(rdev->mddev), bdevname(rdev->bdev, b));
|
mdname(rdev->mddev), rdev->bdev);
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1283,16 +1281,16 @@ static int ppl_validate_rdev(struct md_rdev *rdev)
|
||||||
rdev->ppl.sector + ppl_size_new > rdev->data_offset) ||
|
rdev->ppl.sector + ppl_size_new > rdev->data_offset) ||
|
||||||
(rdev->ppl.sector >= rdev->data_offset &&
|
(rdev->ppl.sector >= rdev->data_offset &&
|
||||||
rdev->data_offset + rdev->sectors > rdev->ppl.sector)) {
|
rdev->data_offset + rdev->sectors > rdev->ppl.sector)) {
|
||||||
pr_warn("md/raid:%s: PPL space overlaps with data on %s\n",
|
pr_warn("md/raid:%s: PPL space overlaps with data on %pg\n",
|
||||||
mdname(rdev->mddev), bdevname(rdev->bdev, b));
|
mdname(rdev->mddev), rdev->bdev);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rdev->mddev->external &&
|
if (!rdev->mddev->external &&
|
||||||
((rdev->ppl.offset > 0 && rdev->ppl.offset < (rdev->sb_size >> 9)) ||
|
((rdev->ppl.offset > 0 && rdev->ppl.offset < (rdev->sb_size >> 9)) ||
|
||||||
(rdev->ppl.offset <= 0 && rdev->ppl.offset + ppl_size_new > 0))) {
|
(rdev->ppl.offset <= 0 && rdev->ppl.offset + ppl_size_new > 0))) {
|
||||||
pr_warn("md/raid:%s: PPL space overlaps with superblock on %s\n",
|
pr_warn("md/raid:%s: PPL space overlaps with superblock on %pg\n",
|
||||||
mdname(rdev->mddev), bdevname(rdev->bdev, b));
|
mdname(rdev->mddev), rdev->bdev);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1463,14 +1461,13 @@ int ppl_modify_log(struct r5conf *conf, struct md_rdev *rdev, bool add)
|
||||||
struct ppl_conf *ppl_conf = conf->log_private;
|
struct ppl_conf *ppl_conf = conf->log_private;
|
||||||
struct ppl_log *log;
|
struct ppl_log *log;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
|
|
||||||
if (!rdev)
|
if (!rdev)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
pr_debug("%s: disk: %d operation: %s dev: %s\n",
|
pr_debug("%s: disk: %d operation: %s dev: %pg\n",
|
||||||
__func__, rdev->raid_disk, add ? "add" : "remove",
|
__func__, rdev->raid_disk, add ? "add" : "remove",
|
||||||
bdevname(rdev->bdev, b));
|
rdev->bdev);
|
||||||
|
|
||||||
if (rdev->raid_disk < 0)
|
if (rdev->raid_disk < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -2686,7 +2686,6 @@ static void raid5_end_read_request(struct bio * bi)
|
||||||
struct stripe_head *sh = bi->bi_private;
|
struct stripe_head *sh = bi->bi_private;
|
||||||
struct r5conf *conf = sh->raid_conf;
|
struct r5conf *conf = sh->raid_conf;
|
||||||
int disks = sh->disks, i;
|
int disks = sh->disks, i;
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
struct md_rdev *rdev = NULL;
|
struct md_rdev *rdev = NULL;
|
||||||
sector_t s;
|
sector_t s;
|
||||||
|
|
||||||
|
|
@ -2723,10 +2722,10 @@ static void raid5_end_read_request(struct bio * bi)
|
||||||
* any error
|
* any error
|
||||||
*/
|
*/
|
||||||
pr_info_ratelimited(
|
pr_info_ratelimited(
|
||||||
"md/raid:%s: read error corrected (%lu sectors at %llu on %s)\n",
|
"md/raid:%s: read error corrected (%lu sectors at %llu on %pg)\n",
|
||||||
mdname(conf->mddev), RAID5_STRIPE_SECTORS(conf),
|
mdname(conf->mddev), RAID5_STRIPE_SECTORS(conf),
|
||||||
(unsigned long long)s,
|
(unsigned long long)s,
|
||||||
bdevname(rdev->bdev, b));
|
rdev->bdev);
|
||||||
atomic_add(RAID5_STRIPE_SECTORS(conf), &rdev->corrected_errors);
|
atomic_add(RAID5_STRIPE_SECTORS(conf), &rdev->corrected_errors);
|
||||||
clear_bit(R5_ReadError, &sh->dev[i].flags);
|
clear_bit(R5_ReadError, &sh->dev[i].flags);
|
||||||
clear_bit(R5_ReWrite, &sh->dev[i].flags);
|
clear_bit(R5_ReWrite, &sh->dev[i].flags);
|
||||||
|
|
@ -2743,7 +2742,6 @@ static void raid5_end_read_request(struct bio * bi)
|
||||||
if (atomic_read(&rdev->read_errors))
|
if (atomic_read(&rdev->read_errors))
|
||||||
atomic_set(&rdev->read_errors, 0);
|
atomic_set(&rdev->read_errors, 0);
|
||||||
} else {
|
} else {
|
||||||
const char *bdn = bdevname(rdev->bdev, b);
|
|
||||||
int retry = 0;
|
int retry = 0;
|
||||||
int set_bad = 0;
|
int set_bad = 0;
|
||||||
|
|
||||||
|
|
@ -2752,25 +2750,25 @@ static void raid5_end_read_request(struct bio * bi)
|
||||||
atomic_inc(&rdev->read_errors);
|
atomic_inc(&rdev->read_errors);
|
||||||
if (test_bit(R5_ReadRepl, &sh->dev[i].flags))
|
if (test_bit(R5_ReadRepl, &sh->dev[i].flags))
|
||||||
pr_warn_ratelimited(
|
pr_warn_ratelimited(
|
||||||
"md/raid:%s: read error on replacement device (sector %llu on %s).\n",
|
"md/raid:%s: read error on replacement device (sector %llu on %pg).\n",
|
||||||
mdname(conf->mddev),
|
mdname(conf->mddev),
|
||||||
(unsigned long long)s,
|
(unsigned long long)s,
|
||||||
bdn);
|
rdev->bdev);
|
||||||
else if (conf->mddev->degraded >= conf->max_degraded) {
|
else if (conf->mddev->degraded >= conf->max_degraded) {
|
||||||
set_bad = 1;
|
set_bad = 1;
|
||||||
pr_warn_ratelimited(
|
pr_warn_ratelimited(
|
||||||
"md/raid:%s: read error not correctable (sector %llu on %s).\n",
|
"md/raid:%s: read error not correctable (sector %llu on %pg).\n",
|
||||||
mdname(conf->mddev),
|
mdname(conf->mddev),
|
||||||
(unsigned long long)s,
|
(unsigned long long)s,
|
||||||
bdn);
|
rdev->bdev);
|
||||||
} else if (test_bit(R5_ReWrite, &sh->dev[i].flags)) {
|
} else if (test_bit(R5_ReWrite, &sh->dev[i].flags)) {
|
||||||
/* Oh, no!!! */
|
/* Oh, no!!! */
|
||||||
set_bad = 1;
|
set_bad = 1;
|
||||||
pr_warn_ratelimited(
|
pr_warn_ratelimited(
|
||||||
"md/raid:%s: read error NOT corrected!! (sector %llu on %s).\n",
|
"md/raid:%s: read error NOT corrected!! (sector %llu on %pg).\n",
|
||||||
mdname(conf->mddev),
|
mdname(conf->mddev),
|
||||||
(unsigned long long)s,
|
(unsigned long long)s,
|
||||||
bdn);
|
rdev->bdev);
|
||||||
} else if (atomic_read(&rdev->read_errors)
|
} else if (atomic_read(&rdev->read_errors)
|
||||||
> conf->max_nr_stripes) {
|
> conf->max_nr_stripes) {
|
||||||
if (!test_bit(Faulty, &rdev->flags)) {
|
if (!test_bit(Faulty, &rdev->flags)) {
|
||||||
|
|
@ -2778,8 +2776,8 @@ static void raid5_end_read_request(struct bio * bi)
|
||||||
mdname(conf->mddev),
|
mdname(conf->mddev),
|
||||||
atomic_read(&rdev->read_errors),
|
atomic_read(&rdev->read_errors),
|
||||||
conf->max_nr_stripes);
|
conf->max_nr_stripes);
|
||||||
pr_warn("md/raid:%s: Too many read errors, failing device %s.\n",
|
pr_warn("md/raid:%s: Too many read errors, failing device %pg.\n",
|
||||||
mdname(conf->mddev), bdn);
|
mdname(conf->mddev), rdev->bdev);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
retry = 1;
|
retry = 1;
|
||||||
|
|
@ -2891,13 +2889,12 @@ static void raid5_end_write_request(struct bio *bi)
|
||||||
|
|
||||||
static void raid5_error(struct mddev *mddev, struct md_rdev *rdev)
|
static void raid5_error(struct mddev *mddev, struct md_rdev *rdev)
|
||||||
{
|
{
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
struct r5conf *conf = mddev->private;
|
struct r5conf *conf = mddev->private;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
pr_debug("raid456: error called\n");
|
pr_debug("raid456: error called\n");
|
||||||
|
|
||||||
pr_crit("md/raid:%s: Disk failure on %s, disabling device.\n",
|
pr_crit("md/raid:%s: Disk failure on %pg, disabling device.\n",
|
||||||
mdname(mddev), bdevname(rdev->bdev, b));
|
mdname(mddev), rdev->bdev);
|
||||||
|
|
||||||
spin_lock_irqsave(&conf->device_lock, flags);
|
spin_lock_irqsave(&conf->device_lock, flags);
|
||||||
set_bit(Faulty, &rdev->flags);
|
set_bit(Faulty, &rdev->flags);
|
||||||
|
|
@ -7359,9 +7356,8 @@ static struct r5conf *setup_conf(struct mddev *mddev)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_bit(In_sync, &rdev->flags)) {
|
if (test_bit(In_sync, &rdev->flags)) {
|
||||||
char b[BDEVNAME_SIZE];
|
pr_info("md/raid:%s: device %pg operational as raid disk %d\n",
|
||||||
pr_info("md/raid:%s: device %s operational as raid disk %d\n",
|
mdname(mddev), rdev->bdev, raid_disk);
|
||||||
mdname(mddev), bdevname(rdev->bdev, b), raid_disk);
|
|
||||||
} else if (rdev->saved_raid_disk != raid_disk)
|
} else if (rdev->saved_raid_disk != raid_disk)
|
||||||
/* Cannot rely on bitmap to complete recovery */
|
/* Cannot rely on bitmap to complete recovery */
|
||||||
conf->fullsync = 1;
|
conf->fullsync = 1;
|
||||||
|
|
@ -7877,12 +7873,11 @@ static void print_raid5_conf (struct r5conf *conf)
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
for (i = 0; i < conf->raid_disks; i++) {
|
for (i = 0; i < conf->raid_disks; i++) {
|
||||||
char b[BDEVNAME_SIZE];
|
|
||||||
rdev = rcu_dereference(conf->disks[i].rdev);
|
rdev = rcu_dereference(conf->disks[i].rdev);
|
||||||
if (rdev)
|
if (rdev)
|
||||||
pr_debug(" disk %d, o:%d, dev:%s\n",
|
pr_debug(" disk %d, o:%d, dev:%pg\n",
|
||||||
i, !test_bit(Faulty, &rdev->flags),
|
i, !test_bit(Faulty, &rdev->flags),
|
||||||
bdevname(rdev->bdev, b));
|
rdev->bdev);
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2228,8 +2228,16 @@ int nvme_enable_ctrl(struct nvme_ctrl *ctrl)
|
||||||
ctrl->ctrl_config |= (NVME_CTRL_PAGE_SHIFT - 12) << NVME_CC_MPS_SHIFT;
|
ctrl->ctrl_config |= (NVME_CTRL_PAGE_SHIFT - 12) << NVME_CC_MPS_SHIFT;
|
||||||
ctrl->ctrl_config |= NVME_CC_AMS_RR | NVME_CC_SHN_NONE;
|
ctrl->ctrl_config |= NVME_CC_AMS_RR | NVME_CC_SHN_NONE;
|
||||||
ctrl->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
|
ctrl->ctrl_config |= NVME_CC_IOSQES | NVME_CC_IOCQES;
|
||||||
ctrl->ctrl_config |= NVME_CC_ENABLE;
|
ret = ctrl->ops->reg_write32(ctrl, NVME_REG_CC, ctrl->ctrl_config);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Flush write to device (required if transport is PCI) */
|
||||||
|
ret = ctrl->ops->reg_read32(ctrl, NVME_REG_CC, &ctrl->ctrl_config);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ctrl->ctrl_config |= NVME_CC_ENABLE;
|
||||||
ret = ctrl->ops->reg_write32(ctrl, NVME_REG_CC, ctrl->ctrl_config);
|
ret = ctrl->ops->reg_write32(ctrl, NVME_REG_CC, ctrl->ctrl_config);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
|
|
@ -3457,6 +3457,8 @@ static const struct pci_device_id nvme_id_table[] = {
|
||||||
.driver_data = NVME_QUIRK_NO_DEEPEST_PS, },
|
.driver_data = NVME_QUIRK_NO_DEEPEST_PS, },
|
||||||
{ PCI_DEVICE(0x2646, 0x2263), /* KINGSTON A2000 NVMe SSD */
|
{ PCI_DEVICE(0x2646, 0x2263), /* KINGSTON A2000 NVMe SSD */
|
||||||
.driver_data = NVME_QUIRK_NO_DEEPEST_PS, },
|
.driver_data = NVME_QUIRK_NO_DEEPEST_PS, },
|
||||||
|
{ PCI_DEVICE(0x1e4B, 0x1001), /* MAXIO MAP1001 */
|
||||||
|
.driver_data = NVME_QUIRK_BOGUS_NID, },
|
||||||
{ PCI_DEVICE(0x1e4B, 0x1002), /* MAXIO MAP1002 */
|
{ PCI_DEVICE(0x1e4B, 0x1002), /* MAXIO MAP1002 */
|
||||||
.driver_data = NVME_QUIRK_BOGUS_NID, },
|
.driver_data = NVME_QUIRK_BOGUS_NID, },
|
||||||
{ PCI_DEVICE(0x1e4B, 0x1202), /* MAXIO MAP1202 */
|
{ PCI_DEVICE(0x1e4B, 0x1202), /* MAXIO MAP1202 */
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ static u16 nvmet_passthru_override_id_ctrl(struct nvmet_req *req)
|
||||||
id->sgls |= cpu_to_le32(1 << 20);
|
id->sgls |= cpu_to_le32(1 << 20);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When passsthru controller is setup using nvme-loop transport it will
|
* When passthru controller is setup using nvme-loop transport it will
|
||||||
* export the passthru ctrl subsysnqn (PCIe NVMe ctrl) and will fail in
|
* export the passthru ctrl subsysnqn (PCIe NVMe ctrl) and will fail in
|
||||||
* the nvme/host/core.c in the nvme_init_subsystem()->nvme_active_ctrl()
|
* the nvme/host/core.c in the nvme_init_subsystem()->nvme_active_ctrl()
|
||||||
* code path with duplicate ctr subsynqn. In order to prevent that we
|
* code path with duplicate ctr subsynqn. In order to prevent that we
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,7 @@ struct gendisk {
|
||||||
#define GD_DEAD 2
|
#define GD_DEAD 2
|
||||||
#define GD_NATIVE_CAPACITY 3
|
#define GD_NATIVE_CAPACITY 3
|
||||||
#define GD_ADDED 4
|
#define GD_ADDED 4
|
||||||
|
#define GD_SUPPRESS_PART_SCAN 5
|
||||||
|
|
||||||
struct mutex open_mutex; /* open/close mutex */
|
struct mutex open_mutex; /* open/close mutex */
|
||||||
unsigned open_partitions; /* number of open partitions */
|
unsigned open_partitions; /* number of open partitions */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user