Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'ceph-for-6.4-rc6' of https://github.com/ceph/ceph-client

Pull ceph fixes from Ilya Dryomov:
"A fix for a potential data corruption in differential backup and
snapshot-based mirroring scenarios in RBD and a reference counting
fixup to avoid use-after-free in CephFS, all marked for stable"

* tag 'ceph-for-6.4-rc6' of https://github.com/ceph/ceph-client:
ceph: fix use-after-free bug for inodes when flushing capsnaps
rbd: get snapshot context after exclusive lock is ensured to be held
rbd: move RBD_OBJ_FLAG_COPYUP_ENABLED flag setting

+53 -19
+44 -18
drivers/block/rbd.c
··· 1334 1334 /* 1335 1335 * Must be called after rbd_obj_calc_img_extents(). 1336 1336 */ 1337 - static bool rbd_obj_copyup_enabled(struct rbd_obj_request *obj_req) 1337 + static void rbd_obj_set_copyup_enabled(struct rbd_obj_request *obj_req) 1338 1338 { 1339 - if (!obj_req->num_img_extents || 1340 - (rbd_obj_is_entire(obj_req) && 1341 - !obj_req->img_request->snapc->num_snaps)) 1342 - return false; 1339 + rbd_assert(obj_req->img_request->snapc); 1343 1340 1344 - return true; 1341 + if (obj_req->img_request->op_type == OBJ_OP_DISCARD) { 1342 + dout("%s %p objno %llu discard\n", __func__, obj_req, 1343 + obj_req->ex.oe_objno); 1344 + return; 1345 + } 1346 + 1347 + if (!obj_req->num_img_extents) { 1348 + dout("%s %p objno %llu not overlapping\n", __func__, obj_req, 1349 + obj_req->ex.oe_objno); 1350 + return; 1351 + } 1352 + 1353 + if (rbd_obj_is_entire(obj_req) && 1354 + !obj_req->img_request->snapc->num_snaps) { 1355 + dout("%s %p objno %llu entire\n", __func__, obj_req, 1356 + obj_req->ex.oe_objno); 1357 + return; 1358 + } 1359 + 1360 + obj_req->flags |= RBD_OBJ_FLAG_COPYUP_ENABLED; 1345 1361 } 1346 1362 1347 1363 static u64 rbd_obj_img_extents_bytes(struct rbd_obj_request *obj_req) ··· 1458 1442 static struct ceph_osd_request * 1459 1443 rbd_obj_add_osd_request(struct rbd_obj_request *obj_req, int num_ops) 1460 1444 { 1445 + rbd_assert(obj_req->img_request->snapc); 1461 1446 return __rbd_obj_add_osd_request(obj_req, obj_req->img_request->snapc, 1462 1447 num_ops); 1463 1448 } ··· 1595 1578 mutex_init(&img_request->state_mutex); 1596 1579 } 1597 1580 1581 + /* 1582 + * Only snap_id is captured here, for reads. For writes, snapshot 1583 + * context is captured in rbd_img_object_requests() after exclusive 1584 + * lock is ensured to be held. 1585 + */ 1598 1586 static void rbd_img_capture_header(struct rbd_img_request *img_req) 1599 1587 { 1600 1588 struct rbd_device *rbd_dev = img_req->rbd_dev; 1601 1589 1602 1590 lockdep_assert_held(&rbd_dev->header_rwsem); 1603 1591 1604 - if (rbd_img_is_write(img_req)) 1605 - img_req->snapc = ceph_get_snap_context(rbd_dev->header.snapc); 1606 - else 1592 + if (!rbd_img_is_write(img_req)) 1607 1593 img_req->snap_id = rbd_dev->spec->snap_id; 1608 1594 1609 1595 if (rbd_dev_parent_get(rbd_dev)) ··· 2253 2233 if (ret) 2254 2234 return ret; 2255 2235 2256 - if (rbd_obj_copyup_enabled(obj_req)) 2257 - obj_req->flags |= RBD_OBJ_FLAG_COPYUP_ENABLED; 2258 - 2259 2236 obj_req->write_state = RBD_OBJ_WRITE_START; 2260 2237 return 0; 2261 2238 } ··· 2358 2341 if (ret) 2359 2342 return ret; 2360 2343 2361 - if (rbd_obj_copyup_enabled(obj_req)) 2362 - obj_req->flags |= RBD_OBJ_FLAG_COPYUP_ENABLED; 2363 2344 if (!obj_req->num_img_extents) { 2364 2345 obj_req->flags |= RBD_OBJ_FLAG_NOOP_FOR_NONEXISTENT; 2365 2346 if (rbd_obj_is_entire(obj_req)) ··· 3301 3286 case RBD_OBJ_WRITE_START: 3302 3287 rbd_assert(!*result); 3303 3288 3289 + rbd_obj_set_copyup_enabled(obj_req); 3304 3290 if (rbd_obj_write_is_noop(obj_req)) 3305 3291 return true; 3306 3292 ··· 3488 3472 3489 3473 static void rbd_img_object_requests(struct rbd_img_request *img_req) 3490 3474 { 3475 + struct rbd_device *rbd_dev = img_req->rbd_dev; 3491 3476 struct rbd_obj_request *obj_req; 3492 3477 3493 3478 rbd_assert(!img_req->pending.result && !img_req->pending.num_pending); 3479 + rbd_assert(!need_exclusive_lock(img_req) || 3480 + __rbd_is_lock_owner(rbd_dev)); 3481 + 3482 + if (rbd_img_is_write(img_req)) { 3483 + rbd_assert(!img_req->snapc); 3484 + down_read(&rbd_dev->header_rwsem); 3485 + img_req->snapc = ceph_get_snap_context(rbd_dev->header.snapc); 3486 + up_read(&rbd_dev->header_rwsem); 3487 + } 3494 3488 3495 3489 for_each_obj_request(img_req, obj_req) { 3496 3490 int result = 0; ··· 3518 3492 3519 3493 static bool rbd_img_advance(struct rbd_img_request *img_req, int *result) 3520 3494 { 3521 - struct rbd_device *rbd_dev = img_req->rbd_dev; 3522 3495 int ret; 3523 3496 3524 3497 again: ··· 3537 3512 case RBD_IMG_EXCLUSIVE_LOCK: 3538 3513 if (*result) 3539 3514 return true; 3540 - 3541 - rbd_assert(!need_exclusive_lock(img_req) || 3542 - __rbd_is_lock_owner(rbd_dev)); 3543 3515 3544 3516 rbd_img_object_requests(img_req); 3545 3517 if (!img_req->pending.num_pending) { ··· 3998 3976 static int rbd_post_acquire_action(struct rbd_device *rbd_dev) 3999 3977 { 4000 3978 int ret; 3979 + 3980 + ret = rbd_dev_refresh(rbd_dev); 3981 + if (ret) 3982 + return ret; 4001 3983 4002 3984 if (rbd_dev->header.features & RBD_FEATURE_OBJECT_MAP) { 4003 3985 ret = rbd_object_map_open(rbd_dev);
+6
fs/ceph/caps.c
··· 1627 1627 struct inode *inode = &ci->netfs.inode; 1628 1628 struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; 1629 1629 struct ceph_mds_session *session = NULL; 1630 + bool need_put = false; 1630 1631 int mds; 1631 1632 1632 1633 dout("ceph_flush_snaps %p\n", inode); ··· 1672 1671 ceph_put_mds_session(session); 1673 1672 /* we flushed them all; remove this inode from the queue */ 1674 1673 spin_lock(&mdsc->snap_flush_lock); 1674 + if (!list_empty(&ci->i_snap_flush_item)) 1675 + need_put = true; 1675 1676 list_del_init(&ci->i_snap_flush_item); 1676 1677 spin_unlock(&mdsc->snap_flush_lock); 1678 + 1679 + if (need_put) 1680 + iput(inode); 1677 1681 } 1678 1682 1679 1683 /*
+3 -1
fs/ceph/snap.c
··· 693 693 capsnap->size); 694 694 695 695 spin_lock(&mdsc->snap_flush_lock); 696 - if (list_empty(&ci->i_snap_flush_item)) 696 + if (list_empty(&ci->i_snap_flush_item)) { 697 + ihold(inode); 697 698 list_add_tail(&ci->i_snap_flush_item, &mdsc->snap_flush_list); 699 + } 698 700 spin_unlock(&mdsc->snap_flush_lock); 699 701 return 1; /* caller may want to ceph_flush_snaps */ 700 702 }