Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 331687
b: refs/heads/master
c: 35d489f
h: refs/heads/master
i:
  331685: f1879b9
  331683: 5f2977f
  331679: 6106380
v: v3
  • Loading branch information
Alex Elder committed Oct 1, 2012
1 parent d6a6ff0 commit 9fa3c4d
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b1b5402aa9c4a9aeb8431886e41b0a1d127318d1
refs/heads/master: 35d489f94651ac19be55661732a7ee15c6304a55
85 changes: 85 additions & 0 deletions trunk/drivers/block/rbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#define RBD_MINORS_PER_MAJOR 256 /* max minors per blkdev */

#define RBD_MAX_SNAP_NAME_LEN 32
#define RBD_MAX_SNAP_COUNT 510 /* allows max snapc to fit in 4KB */
#define RBD_MAX_OPT_LEN 1024

#define RBD_SNAP_HEAD_NAME "-"
Expand Down Expand Up @@ -2240,6 +2241,84 @@ static int rbd_dev_v2_features(struct rbd_device *rbd_dev)
&rbd_dev->header.features);
}

static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev)
{
size_t size;
int ret;
void *reply_buf;
void *p;
void *end;
u64 seq;
u32 snap_count;
struct ceph_snap_context *snapc;
u32 i;

/*
* We'll need room for the seq value (maximum snapshot id),
* snapshot count, and array of that many snapshot ids.
* For now we have a fixed upper limit on the number we're
* prepared to receive.
*/
size = sizeof (__le64) + sizeof (__le32) +
RBD_MAX_SNAP_COUNT * sizeof (__le64);
reply_buf = kzalloc(size, GFP_KERNEL);
if (!reply_buf)
return -ENOMEM;

ret = rbd_req_sync_exec(rbd_dev, rbd_dev->header_name,
"rbd", "get_snapcontext",
NULL, 0,
reply_buf, size,
CEPH_OSD_FLAG_READ, NULL);
dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret);
if (ret < 0)
goto out;

ret = -ERANGE;
p = reply_buf;
end = (char *) reply_buf + size;
ceph_decode_64_safe(&p, end, seq, out);
ceph_decode_32_safe(&p, end, snap_count, out);

/*
* Make sure the reported number of snapshot ids wouldn't go
* beyond the end of our buffer. But before checking that,
* make sure the computed size of the snapshot context we
* allocate is representable in a size_t.
*/
if (snap_count > (SIZE_MAX - sizeof (struct ceph_snap_context))
/ sizeof (u64)) {
ret = -EINVAL;
goto out;
}
if (!ceph_has_room(&p, end, snap_count * sizeof (__le64)))
goto out;

size = sizeof (struct ceph_snap_context) +
snap_count * sizeof (snapc->snaps[0]);
snapc = kmalloc(size, GFP_KERNEL);
if (!snapc) {
ret = -ENOMEM;
goto out;
}

atomic_set(&snapc->nref, 1);
snapc->seq = seq;
snapc->num_snaps = snap_count;
for (i = 0; i < snap_count; i++)
snapc->snaps[i] = ceph_decode_64(&p);

rbd_dev->header.snapc = snapc;

dout(" snap context seq = %llu, snap_count = %u\n",
(unsigned long long) seq, (unsigned int) snap_count);

out:
kfree(reply_buf);

return 0;
}

/*
* Scan the rbd device's current snapshot list and compare it to the
* newly-received snapshot context. Remove any existing snapshots
Expand Down Expand Up @@ -2779,6 +2858,12 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
ret = rbd_dev_v2_features(rbd_dev);
if (ret < 0)
goto out_err;

/* Get the snapshot context */

ret = rbd_dev_v2_snap_context(rbd_dev);
if (ret)
goto out_err;
rbd_dev->image_format = 2;

dout("discovered version 2 image, header name is %s\n",
Expand Down

0 comments on commit 9fa3c4d

Please sign in to comment.