On 07/20/2010 12:53 PM, Karel Zak wrote: > > My suggestion is to use /sys as alternative to useless > LOOP_GET_STATUS ioctl, something like: > > /sys/block/<devname>/loop/backing_file > /sys/block/<devname>/loop/offset > /sys/block/<devname>/loop/sizelimit > /sys/block/<devname>/loop/autoclear Maybe naive, but quick implementation of this idea... Milan From: Milan Broz <mbroz@xxxxxxxxxx> Subject: [PATCH] loop: add some basic read-only sysfs attributes Create /sys/block/loopX/loop directory and provide these attributes: - backing_device - readonly - autoclear - offset Signed-off-by: Milan Broz <mbroz@xxxxxxxxxx> --- drivers/block/loop.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++- include/linux/loop.h | 2 + 2 files changed, 113 insertions(+), 1 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 6120922..453c6d7 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -73,6 +73,7 @@ #include <linux/highmem.h> #include <linux/kthread.h> #include <linux/splice.h> +#include <linux/sysfs.h> #include <asm/uaccess.h> @@ -1542,8 +1543,114 @@ out: return NULL; } +/* loop sysfs attributes */ + +struct loop_sysfs_attr { + struct attribute attr; + ssize_t (*show)(struct loop_device *, char *); + ssize_t (*store)(struct loop_device *, char *); +}; + +#define LOOP_ATTR_RO(_name) \ +struct loop_sysfs_attr loop_attr_##_name = \ + __ATTR(_name, S_IRUGO, loop_attr_##_name##_show, NULL) + +static ssize_t loop_attr_show(struct kobject *kobj, + struct attribute *attr, + char *page) +{ + struct loop_device *lo; + struct loop_sysfs_attr *loop_attr; + + lo = container_of(kobj, struct loop_device, lo_kobj); + loop_attr = container_of(attr, struct loop_sysfs_attr, attr); + + if (!loop_attr->show) + return -EIO; + + return loop_attr->show(lo, page); +} + +static ssize_t loop_attr_backing_file_show(struct loop_device *lo, char *buf) +{ + ssize_t ret; + char *p; + + if (lo->lo_state != Lo_bound) + return 0; + + mutex_lock(&lo->lo_ctl_mutex); + p = d_path(&lo->lo_backing_file->f_path, buf, PAGE_SIZE - 1); + mutex_unlock(&lo->lo_ctl_mutex); + + if (IS_ERR(p)) + ret = PTR_ERR(p); + else { + ret = strlen(p); + memmove(buf, p, ret); + buf[ret++] = '\n'; + buf[ret] = 0; + } + + return ret; +} + +static ssize_t loop_attr_offset_show(struct loop_device *lo, char *buf) +{ + return sprintf(buf, "%llu\n", (unsigned long long)lo->lo_offset); +} + +static ssize_t loop_attr_readonly_show(struct loop_device *lo, char *buf) +{ + int read_only = (lo->lo_flags & LO_FLAGS_READ_ONLY); + + return sprintf(buf, "%s\n", read_only ? "1" : "0"); +} + +static ssize_t loop_attr_autoclear_show(struct loop_device *lo, char *buf) +{ + int autoclear = (lo->lo_flags & LO_FLAGS_AUTOCLEAR); + + return sprintf(buf, "%s\n", autoclear ? "1" : "0"); +} + +static LOOP_ATTR_RO(backing_file); +static LOOP_ATTR_RO(offset); +static LOOP_ATTR_RO(readonly); +static LOOP_ATTR_RO(autoclear); + +static struct attribute *loop_attrs[] = { + &loop_attr_backing_file.attr, + &loop_attr_offset.attr, + &loop_attr_readonly.attr, + &loop_attr_autoclear.attr, + NULL, +}; + +static const struct sysfs_ops loop_sysfs_ops = { + .show = loop_attr_show, +}; + +static struct kobj_type loop_ktype = { + .sysfs_ops = &loop_sysfs_ops, + .default_attrs = loop_attrs, +}; + +static int loop_sysfs_init(struct loop_device *lo) +{ + return kobject_init_and_add(&lo->lo_kobj, &loop_ktype, + &disk_to_dev(lo->lo_disk)->kobj, + "%s", "loop"); +} + +static void loop_sysfs_exit(struct loop_device *lo) +{ + kobject_put(&lo->lo_kobj); +} + static void loop_free(struct loop_device *lo) { + loop_sysfs_exit(lo); blk_cleanup_queue(lo->lo_queue); put_disk(lo->lo_disk); list_del(&lo->lo_list); @@ -1562,6 +1669,7 @@ static struct loop_device *loop_init_one(int i) lo = loop_alloc(i); if (lo) { add_disk(lo->lo_disk); + loop_sysfs_init(lo); list_add_tail(&lo->lo_list, &loop_devices); } return lo; @@ -1635,8 +1743,10 @@ static int __init loop_init(void) /* point of no return */ - list_for_each_entry(lo, &loop_devices, lo_list) + list_for_each_entry(lo, &loop_devices, lo_list) { add_disk(lo->lo_disk); + loop_sysfs_init(lo); + } blk_register_region(MKDEV(LOOP_MAJOR, 0), range, THIS_MODULE, loop_probe, NULL, NULL); diff --git a/include/linux/loop.h b/include/linux/loop.h index 66c194e..0b26385 100644 --- a/include/linux/loop.h +++ b/include/linux/loop.h @@ -65,6 +65,8 @@ struct loop_device { struct request_queue *lo_queue; struct gendisk *lo_disk; struct list_head lo_list; + + struct kobject lo_kobj; }; #endif /* __KERNEL__ */ -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html