rbd: return errors for mapped but deleted snapshot
When a snapshot is deleted, the OSD will return ENOENT when reading from it. This is normally interpreted as a hole by rbd, which will return zeroes. To minimize the time in which this can happen, stop requests early when we are notified that our snapshot no longer exists. [elder@inktank.com: updated __rbd_init_snaps_header() logic] Signed-off-by: Josh Durgin <josh.durgin@inktank.com> Reviewed-by: Alex Elder <elder@inktank.com>
This commit is contained in:
parent
048a9d2d06
commit
e88a36ec96
|
@ -172,9 +172,13 @@ struct rbd_device {
|
|||
|
||||
/* protects updating the header */
|
||||
struct rw_semaphore header_rwsem;
|
||||
/* name of the snapshot this device reads from */
|
||||
char *snap_name;
|
||||
/* id of the snapshot this device reads from */
|
||||
u64 snap_id; /* current snapshot id */
|
||||
int read_only;
|
||||
/* whether the snap_id this device reads from still exists */
|
||||
bool snap_exists;
|
||||
int read_only;
|
||||
|
||||
struct list_head node;
|
||||
|
||||
|
@ -597,6 +601,7 @@ static int rbd_header_set_snap(struct rbd_device *rbd_dev, u64 *size)
|
|||
else
|
||||
snapc->seq = 0;
|
||||
rbd_dev->snap_id = CEPH_NOSNAP;
|
||||
rbd_dev->snap_exists = false;
|
||||
rbd_dev->read_only = 0;
|
||||
if (size)
|
||||
*size = header->image_size;
|
||||
|
@ -606,6 +611,7 @@ static int rbd_header_set_snap(struct rbd_device *rbd_dev, u64 *size)
|
|||
if (ret < 0)
|
||||
goto done;
|
||||
rbd_dev->snap_id = snapc->seq;
|
||||
rbd_dev->snap_exists = true;
|
||||
rbd_dev->read_only = 1;
|
||||
}
|
||||
|
||||
|
@ -1468,6 +1474,21 @@ static void rbd_rq_fn(struct request_queue *q)
|
|||
|
||||
spin_unlock_irq(q->queue_lock);
|
||||
|
||||
if (rbd_dev->snap_id != CEPH_NOSNAP) {
|
||||
bool snap_exists;
|
||||
|
||||
down_read(&rbd_dev->header_rwsem);
|
||||
snap_exists = rbd_dev->snap_exists;
|
||||
up_read(&rbd_dev->header_rwsem);
|
||||
|
||||
if (!snap_exists) {
|
||||
dout("request for non-existent snapshot");
|
||||
spin_lock_irq(q->queue_lock);
|
||||
__blk_end_request_all(rq, -ENXIO);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
dout("%s 0x%x bytes at 0x%llx\n",
|
||||
do_write ? "write" : "read",
|
||||
size, blk_rq_pos(rq) * SECTOR_SIZE);
|
||||
|
@ -2088,7 +2109,14 @@ static int __rbd_init_snaps_header(struct rbd_device *rbd_dev)
|
|||
cur_id = rbd_dev->header.snapc->snaps[i - 1];
|
||||
|
||||
if (!i || old_snap->id < cur_id) {
|
||||
/* old_snap->id was skipped, thus was removed */
|
||||
/*
|
||||
* old_snap->id was skipped, thus was
|
||||
* removed. If this rbd_dev is mapped to
|
||||
* the removed snapshot, record that it no
|
||||
* longer exists, to prevent further I/O.
|
||||
*/
|
||||
if (rbd_dev->snap_id == old_snap->id)
|
||||
rbd_dev->snap_exists = false;
|
||||
__rbd_remove_snap_dev(rbd_dev, old_snap);
|
||||
continue;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue