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

rbd: show the entire chain of parent images

Make /sys/bus/rbd/devices/<id>/parent show the entire chain of parent
images. While at it, kernel sprintf() doesn't return negative values,
casting to unsigned long long is no longer necessary and there is no
good reason to split into multiple sprintf() calls.

Signed-off-by: Ilya Dryomov <ilya.dryomov@inktank.com>
Reviewed-by: Alex Elder <elder@linaro.org>

+23 -33
+2 -2
Documentation/ABI/testing/sysfs-bus-rbd
··· 94 94 95 95 parent 96 96 97 - Information identifying the pool, image, and snapshot id for 98 - the parent image in a layered rbd image (format 2 only). 97 + Information identifying the chain of parent images in a layered rbd 98 + image. Entries are separated by empty lines.
+21 -31
drivers/block/rbd.c
··· 3685 3685 } 3686 3686 3687 3687 /* 3688 - * For an rbd v2 image, shows the pool id, image id, and snapshot id 3689 - * for the parent image. If there is no parent, simply shows 3690 - * "(no parent image)". 3688 + * For a v2 image, shows the chain of parent images, separated by empty 3689 + * lines. For v1 images or if there is no parent, shows "(no parent 3690 + * image)". 3691 3691 */ 3692 3692 static ssize_t rbd_parent_show(struct device *dev, 3693 - struct device_attribute *attr, 3694 - char *buf) 3693 + struct device_attribute *attr, 3694 + char *buf) 3695 3695 { 3696 3696 struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); 3697 - struct rbd_spec *spec = rbd_dev->parent_spec; 3698 - int count; 3699 - char *bufp = buf; 3697 + ssize_t count = 0; 3700 3698 3701 - if (!spec) 3699 + if (!rbd_dev->parent) 3702 3700 return sprintf(buf, "(no parent image)\n"); 3703 3701 3704 - count = sprintf(bufp, "pool_id %llu\npool_name %s\n", 3705 - (unsigned long long) spec->pool_id, spec->pool_name); 3706 - if (count < 0) 3707 - return count; 3708 - bufp += count; 3702 + for ( ; rbd_dev->parent; rbd_dev = rbd_dev->parent) { 3703 + struct rbd_spec *spec = rbd_dev->parent_spec; 3709 3704 3710 - count = sprintf(bufp, "image_id %s\nimage_name %s\n", spec->image_id, 3711 - spec->image_name ? spec->image_name : "(unknown)"); 3712 - if (count < 0) 3713 - return count; 3714 - bufp += count; 3705 + count += sprintf(&buf[count], "%s" 3706 + "pool_id %llu\npool_name %s\n" 3707 + "image_id %s\nimage_name %s\n" 3708 + "snap_id %llu\nsnap_name %s\n" 3709 + "overlap %llu\n", 3710 + !count ? "" : "\n", /* first? */ 3711 + spec->pool_id, spec->pool_name, 3712 + spec->image_id, spec->image_name ?: "(unknown)", 3713 + spec->snap_id, spec->snap_name, 3714 + rbd_dev->parent_overlap); 3715 + } 3715 3716 3716 - count = sprintf(bufp, "snap_id %llu\nsnap_name %s\n", 3717 - (unsigned long long) spec->snap_id, spec->snap_name); 3718 - if (count < 0) 3719 - return count; 3720 - bufp += count; 3721 - 3722 - count = sprintf(bufp, "overlap %llu\n", rbd_dev->parent_overlap); 3723 - if (count < 0) 3724 - return count; 3725 - bufp += count; 3726 - 3727 - return (ssize_t) (bufp - buf); 3717 + return count; 3728 3718 } 3729 3719 3730 3720 static ssize_t rbd_image_refresh(struct device *dev,