Description: The patch creates a new sysfs entry framework for nbd. The single existing sysfs entry for nbd (pid) now uses the framework. From: Paul Clements Signed-off-by: Paul Clements --- drivers/block/nbd.c | 87 ++++++++++++++++++++++++++++++++++++++-------------- include/linux/nbd.h | 1 2 files changed, 66 insertions(+), 22 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index e6fc716..23f3619 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -383,39 +383,17 @@ harderror: return NULL; } -static ssize_t pid_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gendisk *disk = dev_to_disk(dev); - - return sprintf(buf, "%ld\n", - (long) ((struct nbd_device *)disk->private_data)->pid); -} - -static struct device_attribute pid_attr = { - .attr = { .name = "pid", .mode = S_IRUGO}, - .show = pid_show, -}; - static int nbd_do_it(struct nbd_device *lo) { struct request *req; - int ret; BUG_ON(lo->magic != LO_MAGIC); lo->pid = current->pid; - ret = sysfs_create_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr); - if (ret) { - printk(KERN_ERR "nbd: sysfs_create_file failed!"); - lo->pid = 0; - return ret; - } while ((req = nbd_read_stat(lo)) != NULL) nbd_end_request(req); - sysfs_remove_file(&disk_to_dev(lo->disk)->kobj, &pid_attr.attr); lo->pid = 0; return 0; } @@ -735,6 +713,67 @@ static const struct block_device_operations nbd_fops = * (Just smiley confuses emacs :-) */ +struct nbd_sysfs_entry { + struct attribute attr; + ssize_t (*show)(struct nbd_device *, char *); + ssize_t (*store)(struct nbd_device *, const char *, size_t); +}; + +static ssize_t pid_show(struct nbd_device *lo, char *page) +{ + return sprintf(page, "%ld\n", (long)lo->pid); +} + +static struct nbd_sysfs_entry nbd_pid = +__ATTR(pid, S_IRUGO, pid_show, NULL); + +static struct attribute *nbd_default_attrs[] = { + &nbd_pid.attr, + NULL, +}; + +static ssize_t +nbd_attr_show(struct kobject *kobj, struct attribute *attr, char *page) +{ + struct nbd_sysfs_entry *entry = container_of(attr, struct nbd_sysfs_entry, attr); + struct nbd_device *lo = container_of(kobj, struct nbd_device, kobj); + ssize_t rv; + + if (!entry->show) + return -EIO; + rv = entry->show(lo, page); + return rv; +} + +static ssize_t +nbd_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + struct nbd_sysfs_entry *entry = container_of(attr, struct nbd_sysfs_entry, attr); + struct nbd_device *lo = container_of(kobj, struct nbd_device, kobj); + ssize_t rv; + + if (!entry->store) + return -EIO; + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + mutex_lock(&lo->tx_lock); + rv = entry->store(lo, page, length); + mutex_unlock(&lo->tx_lock); + + return rv; +} + +static const struct sysfs_ops nbd_sysfs_ops = { + .show = nbd_attr_show, + .store = nbd_attr_store, +}; + +static struct kobj_type nbd_ktype = { + .sysfs_ops = &nbd_sysfs_ops, + .default_attrs = nbd_default_attrs, +}; + static int __init nbd_init(void) { int err = -ENOMEM; @@ -786,6 +825,7 @@ static int __init nbd_init(void) dprintk(DBG_INIT, "nbd: debugflags=0x%x\n", debugflags); for (i = 0; i < nbds_max; i++) { + int error; struct gendisk *disk = nbd_dev[i].disk; nbd_dev[i].file = NULL; nbd_dev[i].magic = LO_MAGIC; @@ -805,6 +845,8 @@ static int __init nbd_init(void) sprintf(disk->disk_name, "nbd%d", i); set_capacity(disk, 0); add_disk(disk); + error = kobject_init_and_add(&nbd_dev[i].kobj, &nbd_ktype, + &disk_to_dev(disk)->kobj, "%s", "nbd"); } return 0; @@ -828,6 +870,7 @@ static void __exit nbd_cleanup(void) blk_cleanup_queue(disk->queue); put_disk(disk); } + kobject_del(&nbd_dev[i].kobj); } unregister_blkdev(NBD_MAJOR, "nbd"); kfree(nbd_dev); diff --git a/include/linux/nbd.h b/include/linux/nbd.h index d146ca1..c795e28 100644 --- a/include/linux/nbd.h +++ b/include/linux/nbd.h @@ -68,6 +68,7 @@ struct nbd_device { u64 bytesize; pid_t pid; /* pid of nbd-client, if attached */ int xmit_timeout; + struct kobject kobj; }; #endif