block-7.0-20260216

-----BEGIN PGP SIGNATURE-----
 
 iQJEBAABCAAuFiEEwPw5LcreJtl1+l5K99NY+ylx4KYFAmmTrNEQHGF4Ym9lQGtl
 cm5lbC5kawAKCRD301j7KXHgpjsOEACpUk78nFmLbEgJ5UH8+Z6daDzgoasb5YRT
 Mj4g+cM2J9Xc9JxgX8QR3F2EfolweTo/H6xlhnlPDcnpB+b3qj4WHuijR/wghphj
 MBKKqNXTEC+j0ra9uk8h3RmIKaK79xcUup7XfTcuWdYpSsMyYE/m/rck3thw6yNL
 OAjmWLTP4IwYzXip2AB+J7JbDDOV/qWK0aOYdWHCdbn9X8bBel/HDOITWPdybnSR
 DNKBeoi/Yv8KwA+axogqP213ifc3Xr6ejRDkqDOf1bgXsKkELkIxcfog6MhfHhxq
 3Cqlj1pBuIBxGVU7wmBTDqL+aHrVb983tcA5x1NGZIzJao64b026o5DUhNPprwrZ
 HveU1MZ2jarAjAz85gE3S4oUY+6d47ooytfvO548Zp/1LY+fOxnjYqq5ksh8BBLk
 WyjfkJScgr17Z4SVOK8a9GboWO2WKiQJRg+hZ/TWX5fyvu5g9sbRasdwxnp1sl52
 EayzkhYFq/Rdd8slwTIaccVUPl/xeEDeRG+jTJ+4Fj54TihKiJzXVsxDkSWKf46V
 CWmzDx+n6MlGPm9mShSERZ7HJh3VcSp4No/HAjf93u9/UXwubK/SKiV71nhpgJMf
 9bWS2G3wPx/5LoME95YkF+CSgs0e/ROUusfGd8X6nIz9EBGzeabCG/mjqd5adC09
 OZahOuqrIg==
 =PVoY
 -----END PGP SIGNATURE-----

Merge tag 'block-7.0-20260216' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux

Pull more block updates from Jens Axboe:

 - Fix partial IOVA mapping cleanup in error handling

 - Minor prep series ignoring discard return value, as
   the inline value is always known

 - Ensure BLK_FEAT_STABLE_WRITES is set for drbd

 - Fix leak of folio in bio_iov_iter_bounce_read()

 - Allow IOC_PR_READ_* for read-only open

 - Another debugfs deadlock fix

 - A few doc updates

* tag 'block-7.0-20260216' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux:
  blk-mq: use NOIO context to prevent deadlock during debugfs creation
  blk-stat: convert struct blk_stat_callback to kernel-doc
  block: fix enum descriptions kernel-doc
  block: update docs for bio and bvec_iter
  block: change return type to void
  nvmet: ignore discard return value
  md: ignore discard return value
  block: fix partial IOVA mapping cleanup in blk_rq_dma_map_iova
  block: fix folio leak in bio_iov_iter_bounce_read()
  block: allow IOC_PR_READ_* ioctls with BLK_OPEN_READ
  drbd: always set BLK_FEAT_STABLE_WRITES
This commit is contained in:
Linus Torvalds 2026-02-17 08:48:45 -08:00
commit 99dfe2d4da
18 changed files with 181 additions and 104 deletions

View File

@ -1382,8 +1382,10 @@ static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter)
ret = iov_iter_extract_bvecs(iter, bio->bi_io_vec + 1, len,
&bio->bi_vcnt, bio->bi_max_vecs - 1, 0);
if (ret <= 0) {
if (!bio->bi_vcnt)
if (!bio->bi_vcnt) {
folio_put(folio);
return ret;
}
break;
}
len -= ret;

View File

@ -60,7 +60,7 @@ struct bio *blk_alloc_discard_bio(struct block_device *bdev,
return bio;
}
int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
void __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
sector_t nr_sects, gfp_t gfp_mask, struct bio **biop)
{
struct bio *bio;
@ -68,7 +68,6 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
while ((bio = blk_alloc_discard_bio(bdev, &sector, &nr_sects,
gfp_mask)))
*biop = bio_chain_and_submit(*biop, bio);
return 0;
}
EXPORT_SYMBOL(__blkdev_issue_discard);

View File

@ -613,11 +613,6 @@ static void debugfs_create_files(struct request_queue *q, struct dentry *parent,
const struct blk_mq_debugfs_attr *attr)
{
lockdep_assert_held(&q->debugfs_mutex);
/*
* Creating new debugfs entries with queue freezed has the risk of
* deadlock.
*/
WARN_ON_ONCE(q->mq_freeze_depth != 0);
/*
* debugfs_mutex should not be nested under other locks that can be
* grabbed while queue is frozen.
@ -693,12 +688,13 @@ void blk_mq_debugfs_unregister_hctx(struct blk_mq_hw_ctx *hctx)
void blk_mq_debugfs_register_hctxs(struct request_queue *q)
{
struct blk_mq_hw_ctx *hctx;
unsigned int memflags;
unsigned long i;
mutex_lock(&q->debugfs_mutex);
memflags = blk_debugfs_lock(q);
queue_for_each_hw_ctx(q, hctx, i)
blk_mq_debugfs_register_hctx(q, hctx);
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock(q, memflags);
}
void blk_mq_debugfs_unregister_hctxs(struct request_queue *q)

View File

@ -121,17 +121,20 @@ static bool blk_rq_dma_map_iova(struct request *req, struct device *dma_dev,
error = dma_iova_link(dma_dev, state, vec->paddr, mapped,
vec->len, dir, attrs);
if (error)
break;
goto out_unlink;
mapped += vec->len;
} while (blk_map_iter_next(req, &iter->iter, vec));
error = dma_iova_sync(dma_dev, state, 0, mapped);
if (error) {
iter->status = errno_to_blk_status(error);
return false;
}
if (error)
goto out_unlink;
return true;
out_unlink:
dma_iova_destroy(dma_dev, state, mapped, dir, attrs);
iter->status = errno_to_blk_status(error);
return false;
}
static inline void blk_rq_map_iter_init(struct request *rq,

View File

@ -390,13 +390,14 @@ static void blk_mq_sched_tags_teardown(struct request_queue *q, unsigned int fla
void blk_mq_sched_reg_debugfs(struct request_queue *q)
{
struct blk_mq_hw_ctx *hctx;
unsigned int memflags;
unsigned long i;
mutex_lock(&q->debugfs_mutex);
memflags = blk_debugfs_lock(q);
blk_mq_debugfs_register_sched(q);
queue_for_each_hw_ctx(q, hctx, i)
blk_mq_debugfs_register_sched_hctx(q, hctx);
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock(q, memflags);
}
void blk_mq_sched_unreg_debugfs(struct request_queue *q)
@ -404,11 +405,11 @@ void blk_mq_sched_unreg_debugfs(struct request_queue *q)
struct blk_mq_hw_ctx *hctx;
unsigned long i;
mutex_lock(&q->debugfs_mutex);
blk_debugfs_lock_nomemsave(q);
queue_for_each_hw_ctx(q, hctx, i)
blk_mq_debugfs_unregister_sched_hctx(hctx);
blk_mq_debugfs_unregister_sched(q);
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock_nomemrestore(q);
}
void blk_mq_free_sched_tags(struct elevator_tags *et,

View File

@ -17,7 +17,7 @@
* timer fires, @cpu_stat is flushed to @stat and @timer_fn is invoked.
*/
struct blk_stat_callback {
/*
/**
* @list: RCU list of callbacks for a &struct request_queue.
*/
struct list_head list;
@ -50,7 +50,7 @@ struct blk_stat_callback {
struct blk_rq_stat *stat;
/**
* @fn: Callback function.
* @timer_fn: Callback function.
*/
void (*timer_fn)(struct blk_stat_callback *);
@ -59,6 +59,9 @@ struct blk_stat_callback {
*/
void *data;
/**
* @rcu: rcu list head
*/
struct rcu_head rcu;
};
@ -126,6 +129,8 @@ void blk_stat_free_callback(struct blk_stat_callback *cb);
* blk_stat_is_active() - Check if a block statistics callback is currently
* gathering statistics.
* @cb: The callback.
*
* Returns: %true iff the callback is active.
*/
static inline bool blk_stat_is_active(struct blk_stat_callback *cb)
{

View File

@ -892,13 +892,13 @@ static void blk_debugfs_remove(struct gendisk *disk)
{
struct request_queue *q = disk->queue;
mutex_lock(&q->debugfs_mutex);
blk_debugfs_lock_nomemsave(q);
blk_trace_shutdown(q);
debugfs_remove_recursive(q->debugfs_dir);
q->debugfs_dir = NULL;
q->sched_debugfs_dir = NULL;
q->rqos_debugfs_dir = NULL;
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock_nomemrestore(q);
}
/**
@ -908,6 +908,7 @@ static void blk_debugfs_remove(struct gendisk *disk)
int blk_register_queue(struct gendisk *disk)
{
struct request_queue *q = disk->queue;
unsigned int memflags;
int ret;
ret = kobject_add(&disk->queue_kobj, &disk_to_dev(disk)->kobj, "queue");
@ -921,11 +922,11 @@ int blk_register_queue(struct gendisk *disk)
}
mutex_lock(&q->sysfs_lock);
mutex_lock(&q->debugfs_mutex);
memflags = blk_debugfs_lock(q);
q->debugfs_dir = debugfs_create_dir(disk->disk_name, blk_debugfs_root);
if (queue_is_mq(q))
blk_mq_debugfs_register(q);
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock(q, memflags);
ret = disk_register_independent_access_ranges(disk);
if (ret)

View File

@ -776,6 +776,7 @@ void wbt_init_enable_default(struct gendisk *disk)
{
struct request_queue *q = disk->queue;
struct rq_wb *rwb;
unsigned int memflags;
if (!__wbt_enable_default(disk))
return;
@ -789,9 +790,9 @@ void wbt_init_enable_default(struct gendisk *disk)
return;
}
mutex_lock(&q->debugfs_mutex);
memflags = blk_debugfs_lock(q);
blk_mq_debugfs_register_rq_qos(q);
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock(q, memflags);
}
static u64 wbt_default_latency_nsec(struct request_queue *q)
@ -1015,9 +1016,10 @@ int wbt_set_lat(struct gendisk *disk, s64 val)
blk_mq_unquiesce_queue(q);
out:
blk_mq_unfreeze_queue(q, memflags);
mutex_lock(&q->debugfs_mutex);
memflags = blk_debugfs_lock(q);
blk_mq_debugfs_register_rq_qos(q);
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock(q, memflags);
return ret;
}

View File

@ -729,4 +729,35 @@ static inline void blk_unfreeze_release_lock(struct request_queue *q)
}
#endif
/*
* debugfs directory and file creation can trigger fs reclaim, which can enter
* back into the block layer request_queue. This can cause deadlock if the
* queue is frozen. Use NOIO context together with debugfs_mutex to prevent fs
* reclaim from triggering block I/O.
*/
static inline void blk_debugfs_lock_nomemsave(struct request_queue *q)
{
mutex_lock(&q->debugfs_mutex);
}
static inline void blk_debugfs_unlock_nomemrestore(struct request_queue *q)
{
mutex_unlock(&q->debugfs_mutex);
}
static inline unsigned int __must_check blk_debugfs_lock(struct request_queue *q)
{
unsigned int memflags = memalloc_noio_save();
blk_debugfs_lock_nomemsave(q);
return memflags;
}
static inline void blk_debugfs_unlock(struct request_queue *q,
unsigned int memflags)
{
blk_debugfs_unlock_nomemrestore(q);
memalloc_noio_restore(memflags);
}
#endif /* BLK_INTERNAL_H */

View File

@ -318,7 +318,13 @@ int blkdev_compat_ptr_ioctl(struct block_device *bdev, blk_mode_t mode,
EXPORT_SYMBOL(blkdev_compat_ptr_ioctl);
#endif
static bool blkdev_pr_allowed(struct block_device *bdev, blk_mode_t mode)
enum pr_direction {
PR_IN, /* read from device */
PR_OUT, /* write to device */
};
static bool blkdev_pr_allowed(struct block_device *bdev, blk_mode_t mode,
enum pr_direction dir)
{
/* no sense to make reservations for partitions */
if (bdev_is_partition(bdev))
@ -326,11 +332,17 @@ static bool blkdev_pr_allowed(struct block_device *bdev, blk_mode_t mode)
if (capable(CAP_SYS_ADMIN))
return true;
/*
* Only allow unprivileged reservations if the file descriptor is open
* for writing.
* Only allow unprivileged reservation _out_ commands if the file
* descriptor is open for writing. Allow reservation _in_ commands if
* the file descriptor is open for reading since they do not modify the
* device.
*/
return mode & BLK_OPEN_WRITE;
if (dir == PR_IN)
return mode & BLK_OPEN_READ;
else
return mode & BLK_OPEN_WRITE;
}
static int blkdev_pr_register(struct block_device *bdev, blk_mode_t mode,
@ -339,7 +351,7 @@ static int blkdev_pr_register(struct block_device *bdev, blk_mode_t mode,
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
struct pr_registration reg;
if (!blkdev_pr_allowed(bdev, mode))
if (!blkdev_pr_allowed(bdev, mode, PR_OUT))
return -EPERM;
if (!ops || !ops->pr_register)
return -EOPNOTSUPP;
@ -357,7 +369,7 @@ static int blkdev_pr_reserve(struct block_device *bdev, blk_mode_t mode,
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
struct pr_reservation rsv;
if (!blkdev_pr_allowed(bdev, mode))
if (!blkdev_pr_allowed(bdev, mode, PR_OUT))
return -EPERM;
if (!ops || !ops->pr_reserve)
return -EOPNOTSUPP;
@ -375,7 +387,7 @@ static int blkdev_pr_release(struct block_device *bdev, blk_mode_t mode,
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
struct pr_reservation rsv;
if (!blkdev_pr_allowed(bdev, mode))
if (!blkdev_pr_allowed(bdev, mode, PR_OUT))
return -EPERM;
if (!ops || !ops->pr_release)
return -EOPNOTSUPP;
@ -393,7 +405,7 @@ static int blkdev_pr_preempt(struct block_device *bdev, blk_mode_t mode,
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
struct pr_preempt p;
if (!blkdev_pr_allowed(bdev, mode))
if (!blkdev_pr_allowed(bdev, mode, PR_OUT))
return -EPERM;
if (!ops || !ops->pr_preempt)
return -EOPNOTSUPP;
@ -411,7 +423,7 @@ static int blkdev_pr_clear(struct block_device *bdev, blk_mode_t mode,
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
struct pr_clear c;
if (!blkdev_pr_allowed(bdev, mode))
if (!blkdev_pr_allowed(bdev, mode, PR_OUT))
return -EPERM;
if (!ops || !ops->pr_clear)
return -EOPNOTSUPP;
@ -434,7 +446,7 @@ static int blkdev_pr_read_keys(struct block_device *bdev, blk_mode_t mode,
size_t keys_copy_len;
int ret;
if (!blkdev_pr_allowed(bdev, mode))
if (!blkdev_pr_allowed(bdev, mode, PR_IN))
return -EPERM;
if (!ops || !ops->pr_read_keys)
return -EOPNOTSUPP;
@ -486,7 +498,7 @@ static int blkdev_pr_read_reservation(struct block_device *bdev,
struct pr_read_reservation out = {};
int ret;
if (!blkdev_pr_allowed(bdev, mode))
if (!blkdev_pr_allowed(bdev, mode, PR_IN))
return -EPERM;
if (!ops || !ops->pr_read_reservation)
return -EOPNOTSUPP;

View File

@ -2659,9 +2659,6 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
* connect.
*/
.max_hw_sectors = DRBD_MAX_BIO_SIZE_SAFE >> 8,
.features = BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA |
BLK_FEAT_ROTATIONAL |
BLK_FEAT_STABLE_WRITES,
};
device = minor_to_device(minor);

View File

@ -1296,6 +1296,8 @@ void drbd_reconsider_queue_parameters(struct drbd_device *device,
lim.max_segments = drbd_backing_dev_max_segments(device);
} else {
lim.max_segments = BLK_MAX_SEGMENTS;
lim.features = BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA |
BLK_FEAT_ROTATIONAL | BLK_FEAT_STABLE_WRITES;
}
lim.max_hw_sectors = new >> SECTOR_SHIFT;
@ -1318,8 +1320,24 @@ void drbd_reconsider_queue_parameters(struct drbd_device *device,
lim.max_hw_discard_sectors = 0;
}
if (bdev)
if (bdev) {
blk_stack_limits(&lim, &b->limits, 0);
/*
* blk_set_stacking_limits() cleared the features, and
* blk_stack_limits() may or may not have inherited
* BLK_FEAT_STABLE_WRITES from the backing device.
*
* DRBD always requires stable writes because:
* 1. The same bio data is read for both local disk I/O and
* network transmission. If the page changes mid-flight,
* the local and remote copies could diverge.
* 2. When data integrity is enabled, DRBD calculates a
* checksum before sending the data. If the page changes
* between checksum calculation and transmission, the
* receiver will detect a checksum mismatch.
*/
lim.features |= BLK_FEAT_STABLE_WRITES;
}
/*
* If we can handle "zeroes" efficiently on the protocol, we want to do

View File

@ -9179,8 +9179,8 @@ void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,
{
struct bio *discard_bio = NULL;
if (__blkdev_issue_discard(rdev->bdev, start, size, GFP_NOIO,
&discard_bio) || !discard_bio)
__blkdev_issue_discard(rdev->bdev, start, size, GFP_NOIO, &discard_bio);
if (!discard_bio)
return;
bio_chain(discard_bio, bio);

View File

@ -363,29 +363,14 @@ u16 nvmet_bdev_flush(struct nvmet_req *req)
return 0;
}
static u16 nvmet_bdev_discard_range(struct nvmet_req *req,
struct nvme_dsm_range *range, struct bio **bio)
{
struct nvmet_ns *ns = req->ns;
int ret;
ret = __blkdev_issue_discard(ns->bdev,
nvmet_lba_to_sect(ns, range->slba),
le32_to_cpu(range->nlb) << (ns->blksize_shift - 9),
GFP_KERNEL, bio);
if (ret && ret != -EOPNOTSUPP) {
req->error_slba = le64_to_cpu(range->slba);
return errno_to_nvme_status(req, ret);
}
return NVME_SC_SUCCESS;
}
static void nvmet_bdev_execute_discard(struct nvmet_req *req)
{
struct nvmet_ns *ns = req->ns;
struct nvme_dsm_range range;
struct bio *bio = NULL;
sector_t nr_sects;
int i;
u16 status;
u16 status = NVME_SC_SUCCESS;
for (i = 0; i <= le32_to_cpu(req->cmd->dsm.nr); i++) {
status = nvmet_copy_from_sgl(req, i * sizeof(range), &range,
@ -393,9 +378,10 @@ static void nvmet_bdev_execute_discard(struct nvmet_req *req)
if (status)
break;
status = nvmet_bdev_discard_range(req, &range, &bio);
if (status)
break;
nr_sects = le32_to_cpu(range.nlb) << (ns->blksize_shift - 9);
__blkdev_issue_discard(ns->bdev,
nvmet_lba_to_sect(ns, range.slba), nr_sects,
GFP_KERNEL, &bio);
}
if (bio) {

View File

@ -273,7 +273,13 @@ struct bio {
* Everything starting with bi_max_vecs will be preserved by bio_reset()
*/
unsigned short bi_max_vecs; /* max bvl_vecs we can hold */
/*
* Number of elements in `bi_io_vec` that were allocated for this bio.
* Only used by the bio submitter to make `bio_add_page` fail once full
* and to free the `bi_io_vec` allocation. Must not be used in drivers
* and does not hold a useful value for cloned bios.
*/
unsigned short bi_max_vecs;
atomic_t __bi_cnt; /* pin count */
@ -339,32 +345,33 @@ typedef __u32 __bitwise blk_mq_req_flags_t;
* meaning.
*/
enum req_op {
/* read sectors from the device */
/** @REQ_OP_READ: read sectors from the device */
REQ_OP_READ = (__force blk_opf_t)0,
/* write sectors to the device */
/** @REQ_OP_WRITE: write sectors to the device */
REQ_OP_WRITE = (__force blk_opf_t)1,
/* flush the volatile write cache */
/** @REQ_OP_FLUSH: flush the volatile write cache */
REQ_OP_FLUSH = (__force blk_opf_t)2,
/* discard sectors */
/** @REQ_OP_DISCARD: discard sectors */
REQ_OP_DISCARD = (__force blk_opf_t)3,
/* securely erase sectors */
/** @REQ_OP_SECURE_ERASE: securely erase sectors */
REQ_OP_SECURE_ERASE = (__force blk_opf_t)5,
/* write data at the current zone write pointer */
/** @REQ_OP_ZONE_APPEND: write data at the current zone write pointer */
REQ_OP_ZONE_APPEND = (__force blk_opf_t)7,
/* write the zero filled sector many times */
/** @REQ_OP_WRITE_ZEROES: write the zero filled sector many times */
REQ_OP_WRITE_ZEROES = (__force blk_opf_t)9,
/* Open a zone */
/** @REQ_OP_ZONE_OPEN: Open a zone */
REQ_OP_ZONE_OPEN = (__force blk_opf_t)11,
/* Close a zone */
/** @REQ_OP_ZONE_CLOSE: Close a zone */
REQ_OP_ZONE_CLOSE = (__force blk_opf_t)13,
/* Transition a zone to full */
/** @REQ_OP_ZONE_FINISH: Transition a zone to full */
REQ_OP_ZONE_FINISH = (__force blk_opf_t)15,
/* reset a zone write pointer */
/** @REQ_OP_ZONE_RESET: reset a zone write pointer */
REQ_OP_ZONE_RESET = (__force blk_opf_t)17,
/* reset all the zone present on the device */
/** @REQ_OP_ZONE_RESET_ALL: reset all the zone present on the device */
REQ_OP_ZONE_RESET_ALL = (__force blk_opf_t)19,
/* Driver private requests */
/* private: */
REQ_OP_DRV_IN = (__force blk_opf_t)34,
REQ_OP_DRV_OUT = (__force blk_opf_t)35,

View File

@ -1259,7 +1259,7 @@ extern void blk_io_schedule(void);
int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
sector_t nr_sects, gfp_t gfp_mask);
int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
void __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
sector_t nr_sects, gfp_t gfp_mask, struct bio **biop);
int blkdev_issue_secure_erase(struct block_device *bdev, sector_t sector,
sector_t nr_sects, gfp_t gfp);

View File

@ -75,14 +75,27 @@ static inline void bvec_set_virt(struct bio_vec *bv, void *vaddr,
}
struct bvec_iter {
sector_t bi_sector; /* device address in 512 byte
sectors */
unsigned int bi_size; /* residual I/O count */
/*
* Current device address in 512 byte sectors. Only updated by the bio
* iter wrappers and not the bvec iterator helpers themselves.
*/
sector_t bi_sector;
unsigned int bi_idx; /* current index into bvl_vec */
/*
* Remaining size in bytes.
*/
unsigned int bi_size;
unsigned int bi_bvec_done; /* number of bytes completed in
current bvec */
/*
* Current index into the bvec array. This indexes into `bi_io_vec` when
* iterating a bvec array that is part of a `bio`.
*/
unsigned int bi_idx;
/*
* Current offset in the bvec entry pointed to by `bi_idx`.
*/
unsigned int bi_bvec_done;
} __packed __aligned(4);
struct bvec_iter_all {

View File

@ -559,9 +559,9 @@ int blk_trace_remove(struct request_queue *q)
{
int ret;
mutex_lock(&q->debugfs_mutex);
blk_debugfs_lock_nomemsave(q);
ret = __blk_trace_remove(q);
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock_nomemrestore(q);
return ret;
}
@ -767,6 +767,7 @@ int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
struct blk_user_trace_setup2 buts2;
struct blk_user_trace_setup buts;
struct blk_trace *bt;
unsigned int memflags;
int ret;
ret = copy_from_user(&buts, arg, sizeof(buts));
@ -785,16 +786,16 @@ int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
.pid = buts.pid,
};
mutex_lock(&q->debugfs_mutex);
memflags = blk_debugfs_lock(q);
bt = blk_trace_setup_prepare(q, name, dev, buts.buf_size, buts.buf_nr,
bdev);
if (IS_ERR(bt)) {
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock(q, memflags);
return PTR_ERR(bt);
}
blk_trace_setup_finalize(q, name, 1, bt, &buts2);
strscpy(buts.name, buts2.name, BLKTRACE_BDEV_SIZE);
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock(q, memflags);
if (copy_to_user(arg, &buts, sizeof(buts))) {
blk_trace_remove(q);
@ -809,6 +810,7 @@ static int blk_trace_setup2(struct request_queue *q, char *name, dev_t dev,
{
struct blk_user_trace_setup2 buts2;
struct blk_trace *bt;
unsigned int memflags;
if (copy_from_user(&buts2, arg, sizeof(buts2)))
return -EFAULT;
@ -819,15 +821,15 @@ static int blk_trace_setup2(struct request_queue *q, char *name, dev_t dev,
if (buts2.flags != 0)
return -EINVAL;
mutex_lock(&q->debugfs_mutex);
memflags = blk_debugfs_lock(q);
bt = blk_trace_setup_prepare(q, name, dev, buts2.buf_size, buts2.buf_nr,
bdev);
if (IS_ERR(bt)) {
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock(q, memflags);
return PTR_ERR(bt);
}
blk_trace_setup_finalize(q, name, 2, bt, &buts2);
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock(q, memflags);
if (copy_to_user(arg, &buts2, sizeof(buts2))) {
blk_trace_remove(q);
@ -844,6 +846,7 @@ static int compat_blk_trace_setup(struct request_queue *q, char *name,
struct blk_user_trace_setup2 buts2;
struct compat_blk_user_trace_setup cbuts;
struct blk_trace *bt;
unsigned int memflags;
if (copy_from_user(&cbuts, arg, sizeof(cbuts)))
return -EFAULT;
@ -860,15 +863,15 @@ static int compat_blk_trace_setup(struct request_queue *q, char *name,
.pid = cbuts.pid,
};
mutex_lock(&q->debugfs_mutex);
memflags = blk_debugfs_lock(q);
bt = blk_trace_setup_prepare(q, name, dev, buts2.buf_size, buts2.buf_nr,
bdev);
if (IS_ERR(bt)) {
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock(q, memflags);
return PTR_ERR(bt);
}
blk_trace_setup_finalize(q, name, 1, bt, &buts2);
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock(q, memflags);
if (copy_to_user(arg, &buts2.name, ARRAY_SIZE(buts2.name))) {
blk_trace_remove(q);
@ -898,9 +901,9 @@ int blk_trace_startstop(struct request_queue *q, int start)
{
int ret;
mutex_lock(&q->debugfs_mutex);
blk_debugfs_lock_nomemsave(q);
ret = __blk_trace_startstop(q, start);
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock_nomemrestore(q);
return ret;
}
@ -2041,7 +2044,7 @@ static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
struct blk_trace *bt;
ssize_t ret = -ENXIO;
mutex_lock(&q->debugfs_mutex);
blk_debugfs_lock_nomemsave(q);
bt = rcu_dereference_protected(q->blk_trace,
lockdep_is_held(&q->debugfs_mutex));
@ -2062,7 +2065,7 @@ static ssize_t sysfs_blk_trace_attr_show(struct device *dev,
ret = sprintf(buf, "%llu\n", bt->end_lba);
out_unlock_bdev:
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock_nomemrestore(q);
return ret;
}
@ -2073,6 +2076,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
struct block_device *bdev = dev_to_bdev(dev);
struct request_queue *q = bdev_get_queue(bdev);
struct blk_trace *bt;
unsigned int memflags;
u64 value;
ssize_t ret = -EINVAL;
@ -2092,7 +2096,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
goto out;
}
mutex_lock(&q->debugfs_mutex);
memflags = blk_debugfs_lock(q);
bt = rcu_dereference_protected(q->blk_trace,
lockdep_is_held(&q->debugfs_mutex));
@ -2127,7 +2131,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
}
out_unlock_bdev:
mutex_unlock(&q->debugfs_mutex);
blk_debugfs_unlock(q, memflags);
out:
return ret ? ret : count;
}