From: Alex Elder <elder@inktank.com>
To: "ceph-devel@vger.kernel.org" <ceph-devel@vger.kernel.org>
Subject: [PATCH 2/2] rbd: only get snap context for write requests
Date: Fri, 09 Nov 2012 21:06:39 -0600 [thread overview]
Message-ID: <509DC4BF.7080405@inktank.com> (raw)
In-Reply-To: <509DC473.805@inktank.com>
Right now we get and release the header semaphore every time we
process a request for an rbd image. We do this because for write
requests we need to supply the snapshot context, and we can't
safely get a reference to it without holding that semaphore.
There's no need to get the snap context if we're doing a read,
so avoid doing so in that case.
The rbd_device->exists field can be updated asynchronously, changing
from set to clear if a mapped snapshot disappears from the base
image's snapshot context. Although I don't think synchronizing
access to this carefully is that critical, it is converted here to
be an atomic variable so a request is aware the flag is clear as
soon as that is known.
Signed-off-by: Alex Elder <elder@inktank.com>
---
drivers/block/rbd.c | 25 ++++++++++++-------------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index b86f5e5..bac4304 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -229,7 +229,7 @@ struct rbd_device {
spinlock_t lock; /* queue lock */
struct rbd_image_header header;
- bool exists;
+ atomic_t exists;
struct rbd_spec *spec;
char *header_name;
@@ -753,7 +753,7 @@ static int rbd_dev_set_mapping(struct rbd_device
*rbd_dev)
goto done;
rbd_dev->mapping.read_only = true;
}
- rbd_dev->exists = true;
+ atomic_set(&rbd_dev->exists, 1);
done:
return ret;
}
@@ -1333,8 +1333,7 @@ static int rbd_do_op(struct request *rq,
} else {
opcode = CEPH_OSD_OP_READ;
flags = CEPH_OSD_FLAG_READ;
- ceph_put_snap_context(snapc);
- snapc = NULL;
+ rbd_assert(!snapc);
snapid = rbd_dev->spec->snap_id;
payload_len = 0;
}
@@ -1652,6 +1651,7 @@ static void rbd_rq_fn(struct request_queue *q)
while ((rq = blk_fetch_request(q))) {
struct ceph_snap_context *snapc = NULL;
+ bool write_request = rq_data_dir(rq) == WRITE;
int result;
dout("fetched request\n");
@@ -1667,19 +1667,17 @@ static void rbd_rq_fn(struct request_queue *q)
/* Stop writes to a read-only device */
result = -EROFS;
- if (read_only && rq_data_dir(rq) == WRITE)
+ if (read_only && write_request)
goto out_end_request;
- /* Grab a reference to the snapshot context */
+ /* Grab a reference to the snapshot context if needed */
- down_read(&rbd_dev->header_rwsem);
- if (rbd_dev->exists) {
+ if (write_request) {
+ down_read(&rbd_dev->header_rwsem);
snapc = ceph_get_snap_context(rbd_dev->header.snapc);
rbd_assert(snapc != NULL);
- }
- up_read(&rbd_dev->header_rwsem);
-
- if (!snapc) {
+ up_read(&rbd_dev->header_rwsem);
+ } else if (!atomic_read(&rbd_dev->exists)) {
rbd_assert(rbd_dev->spec->snap_id != CEPH_NOSNAP);
dout("request for non-existent snapshot");
result = -ENXIO;
@@ -2295,6 +2293,7 @@ struct rbd_device *rbd_dev_create(struct
rbd_client *rbdc,
return NULL;
spin_lock_init(&rbd_dev->lock);
+ atomic_set(&rbd_dev->exists, 0);
INIT_LIST_HEAD(&rbd_dev->node);
INIT_LIST_HEAD(&rbd_dev->snaps);
init_rwsem(&rbd_dev->header_rwsem);
@@ -2919,7 +2918,7 @@ static int rbd_dev_snaps_update(struct rbd_device
*rbd_dev)
/* Existing snapshot not in the new snap context */
if (rbd_dev->spec->snap_id == snap->id)
- rbd_dev->exists = false;
+ atomic_set(&rbd_dev->exists, 0);
rbd_remove_snap_dev(snap);
dout("%ssnap id %llu has been removed\n",
rbd_dev->spec->snap_id == snap->id ?
--
1.7.9.5
prev parent reply other threads:[~2012-11-10 3:06 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-11-10 3:05 [PATCH 0/2] rbd: snap context references Alex Elder
2012-11-10 3:06 ` [PATCH 1/2] rbd: fix reference leak in rbd_do_op() Alex Elder
2012-11-10 3:06 ` Alex Elder [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=509DC4BF.7080405@inktank.com \
--to=elder@inktank.com \
--cc=ceph-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.