[PATCH] nbd: nbd sysfs framework

From: Paul Clements
Date: Wed Aug 03 2011 - 19:15:59 EST


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 <paul.clements@xxxxxxxxxxxx>
Signed-off-by: Paul Clements <paul.clements@xxxxxxxxxxxx>
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 <paul.clements@xxxxxxxxxxxx>
Signed-off-by: Paul Clements <paul.clements@xxxxxxxxxxxx>
---

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