Loading drivers/block/rbd.c +85 −0 Original line number Diff line number Diff line Loading @@ -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 "-" Loading Loading @@ -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 Loading Loading @@ -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", Loading Loading
drivers/block/rbd.c +85 −0 Original line number Diff line number Diff line Loading @@ -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 "-" Loading Loading @@ -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 Loading Loading @@ -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", Loading