summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-02-06 21:34:17 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2026-02-06 21:34:17 +0300
commit240b8d8227468344e814c6bc7eb8ae532e3b8a09 (patch)
tree1df93f5b69ef9fec16c6d36d51e4c7f67f51d862 /drivers
parent23b0d2f7c2864099fba140672017e3e69ddf88a0 (diff)
parent7987cce375ac8ce98e170a77aa2399f2cf6eb99f (diff)
downloadlinux-240b8d8227468344e814c6bc7eb8ae532e3b8a09.tar.xz
Merge tag 'ceph-for-6.19-rc9' of https://github.com/ceph/ceph-client
Pull ceph fixes from Ilya Dryomov: "One RBD and two CephFS fixes which address potential oopses. The RBD thing is more of a rare edge case that pops up in our CI, while the two CephFS scenarios are regressions that were reported by users and can be triggered trivially in normal operation. All marked for stable" * tag 'ceph-for-6.19-rc9' of https://github.com/ceph/ceph-client: ceph: fix NULL pointer dereference in ceph_mds_auth_match() ceph: fix oops due to invalid pointer for kfree() in parse_longname() rbd: check for EOD after exclusive lock is ensured to be held
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/rbd.c33
1 files changed, 21 insertions, 12 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index af0e21149dbc..8f441eb8b192 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -3495,11 +3495,29 @@ static void rbd_img_object_requests(struct rbd_img_request *img_req)
rbd_assert(!need_exclusive_lock(img_req) ||
__rbd_is_lock_owner(rbd_dev));
- if (rbd_img_is_write(img_req)) {
- rbd_assert(!img_req->snapc);
+ if (test_bit(IMG_REQ_CHILD, &img_req->flags)) {
+ rbd_assert(!rbd_img_is_write(img_req));
+ } else {
+ struct request *rq = blk_mq_rq_from_pdu(img_req);
+ u64 off = (u64)blk_rq_pos(rq) << SECTOR_SHIFT;
+ u64 len = blk_rq_bytes(rq);
+ u64 mapping_size;
+
down_read(&rbd_dev->header_rwsem);
- img_req->snapc = ceph_get_snap_context(rbd_dev->header.snapc);
+ mapping_size = rbd_dev->mapping.size;
+ if (rbd_img_is_write(img_req)) {
+ rbd_assert(!img_req->snapc);
+ img_req->snapc =
+ ceph_get_snap_context(rbd_dev->header.snapc);
+ }
up_read(&rbd_dev->header_rwsem);
+
+ if (unlikely(off + len > mapping_size)) {
+ rbd_warn(rbd_dev, "beyond EOD (%llu~%llu > %llu)",
+ off, len, mapping_size);
+ img_req->pending.result = -EIO;
+ return;
+ }
}
for_each_obj_request(img_req, obj_req) {
@@ -4725,7 +4743,6 @@ static void rbd_queue_workfn(struct work_struct *work)
struct request *rq = blk_mq_rq_from_pdu(img_request);
u64 offset = (u64)blk_rq_pos(rq) << SECTOR_SHIFT;
u64 length = blk_rq_bytes(rq);
- u64 mapping_size;
int result;
/* Ignore/skip any zero-length requests */
@@ -4738,17 +4755,9 @@ static void rbd_queue_workfn(struct work_struct *work)
blk_mq_start_request(rq);
down_read(&rbd_dev->header_rwsem);
- mapping_size = rbd_dev->mapping.size;
rbd_img_capture_header(img_request);
up_read(&rbd_dev->header_rwsem);
- if (offset + length > mapping_size) {
- rbd_warn(rbd_dev, "beyond EOD (%llu~%llu > %llu)", offset,
- length, mapping_size);
- result = -EIO;
- goto err_img_request;
- }
-
dout("%s rbd_dev %p img_req %p %s %llu~%llu\n", __func__, rbd_dev,
img_request, obj_op_name(op_type), offset, length);