From: Elias Oltmanns <eo@nebensachen.de>
To: Jens Axboe <jens.axboe@oracle.com>,
FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>,
Greg KH <greg@kroah.com>
Cc: linux-kernel@vger.kernel.org
Subject: Block: Trouble with kobject initialisation for blk_cmd_filter
Date: Fri, 05 Sep 2008 18:48:07 +0200 [thread overview]
Message-ID: <87od3235fc.fsf@denkblock.local> (raw)
Hi all,
current usage of the kobject in struct blk_cmd_filter is flawed. Doing
# modprobe -r sd-mod && modprobe sd-mod
while, for instance, a usb-stick is plugged in currently results in
nasty warnings and a dump_stack(). Since blk_cmd_filter is embedded in
struct request_queue, I don't see the need for a kobject anyway. What
about the much simpler option of a struct attribute_group in this
particular case?
This would imply that the cmd_filter subdirectory would appear under
sda/queue/ rather than sda/ (which is probably the right place) but,
alas, we have to keep compatibility in mind. So I've made some changes
to sysfs along the way in order to provide a legacy symlink. I'd have to
seperate these two changes for submission but I wanted to know your
opinion about it all first.
Thinking about it now makes me wonder whether this is too much for a rc
patch and whether we should just allocate the struct blk_cmd_filter
dynamically and have done with it. Anyway, tell me what you think.
Regards,
Elias
---
Applies to 2.6.27-rc5-git7.
block/blk-sysfs.c | 6 --
block/blk.h | 6 ++
block/cmd-filter.c | 113 +++++++++++++++----------------------------------
fs/sysfs/symlink.c | 48 ++++++++++++++++----
include/linux/blkdev.h | 1
include/linux/sysfs.h | 2
6 files changed, 81 insertions(+), 95 deletions(-)
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 304ec73..0120c8e 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -9,12 +9,6 @@
#include "blk.h"
-struct queue_sysfs_entry {
- struct attribute attr;
- ssize_t (*show)(struct request_queue *, char *);
- ssize_t (*store)(struct request_queue *, const char *, size_t);
-};
-
static ssize_t
queue_var_show(unsigned int var, char *page)
{
diff --git a/block/blk.h b/block/blk.h
index c79f30e..9ab0d6a 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -10,6 +10,12 @@
extern struct kmem_cache *blk_requestq_cachep;
extern struct kobj_type blk_queue_ktype;
+struct queue_sysfs_entry {
+ struct attribute attr;
+ ssize_t (*show)(struct request_queue *, char *);
+ ssize_t (*store)(struct request_queue *, const char *, size_t);
+};
+
void init_request_from_bio(struct request *req, struct bio *bio);
void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
struct bio *bio);
diff --git a/block/cmd-filter.c b/block/cmd-filter.c
index 228b644..fc0f0b2 100644
--- a/block/cmd-filter.c
+++ b/block/cmd-filter.c
@@ -26,6 +26,8 @@
#include <scsi/scsi.h>
#include <linux/cdrom.h>
+#include "blk.h"
+
int blk_verify_command(struct blk_cmd_filter *filter,
unsigned char *cmd, int has_write_perm)
{
@@ -50,9 +52,9 @@ int blk_verify_command(struct blk_cmd_filter *filter,
EXPORT_SYMBOL(blk_verify_command);
/* and now, the sysfs stuff */
-static ssize_t rcf_cmds_show(struct blk_cmd_filter *filter, char *page,
- int rw)
+static ssize_t rcf_cmds_show(struct request_queue *q, char *page, int rw)
{
+ struct blk_cmd_filter *filter = &q->cmd_filter;
char *npage = page;
unsigned long *okbits;
int i;
@@ -76,24 +78,27 @@ static ssize_t rcf_cmds_show(struct blk_cmd_filter *filter, char *page,
return npage - page;
}
-static ssize_t rcf_readcmds_show(struct blk_cmd_filter *filter, char *page)
+static ssize_t rcf_readcmds_show(struct request_queue *q, char *page)
{
- return rcf_cmds_show(filter, page, READ);
+ return rcf_cmds_show(q, page, READ);
}
-static ssize_t rcf_writecmds_show(struct blk_cmd_filter *filter,
- char *page)
+static ssize_t rcf_writecmds_show(struct request_queue *q, char *page)
{
- return rcf_cmds_show(filter, page, WRITE);
+ return rcf_cmds_show(q, page, WRITE);
}
-static ssize_t rcf_cmds_store(struct blk_cmd_filter *filter,
- const char *page, size_t count, int rw)
+static ssize_t rcf_cmds_store(struct request_queue *q, const char *page,
+ size_t count, int rw)
{
+ struct blk_cmd_filter *filter = &q->cmd_filter;
unsigned long okbits[BLK_SCSI_CMD_PER_LONG], *target_okbits;
int cmd, set;
char *p, *status;
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
if (rw == READ) {
memcpy(&okbits, filter->read_ok, sizeof(okbits));
target_okbits = filter->read_ok;
@@ -128,31 +133,25 @@ static ssize_t rcf_cmds_store(struct blk_cmd_filter *filter,
return count;
}
-static ssize_t rcf_readcmds_store(struct blk_cmd_filter *filter,
- const char *page, size_t count)
+static ssize_t rcf_readcmds_store(struct request_queue *q, const char *page,
+ size_t count)
{
- return rcf_cmds_store(filter, page, count, READ);
+ return rcf_cmds_store(q, page, count, READ);
}
-static ssize_t rcf_writecmds_store(struct blk_cmd_filter *filter,
- const char *page, size_t count)
+static ssize_t rcf_writecmds_store(struct request_queue *q, const char *page,
+ size_t count)
{
- return rcf_cmds_store(filter, page, count, WRITE);
+ return rcf_cmds_store(q, page, count, WRITE);
}
-struct rcf_sysfs_entry {
- struct attribute attr;
- ssize_t (*show)(struct blk_cmd_filter *, char *);
- ssize_t (*store)(struct blk_cmd_filter *, const char *, size_t);
-};
-
-static struct rcf_sysfs_entry rcf_readcmds_entry = {
+static struct queue_sysfs_entry rcf_readcmds_entry = {
.attr = { .name = "read_table", .mode = S_IRUGO | S_IWUSR },
.show = rcf_readcmds_show,
.store = rcf_readcmds_store,
};
-static struct rcf_sysfs_entry rcf_writecmds_entry = {
+static struct queue_sysfs_entry rcf_writecmds_entry = {
.attr = {.name = "write_table", .mode = S_IRUGO | S_IWUSR },
.show = rcf_writecmds_show,
.store = rcf_writecmds_store,
@@ -164,72 +163,30 @@ static struct attribute *default_attrs[] = {
NULL,
};
-#define to_rcf(atr) container_of((atr), struct rcf_sysfs_entry, attr)
-
-static ssize_t
-rcf_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
-{
- struct rcf_sysfs_entry *entry = to_rcf(attr);
- struct blk_cmd_filter *filter;
-
- filter = container_of(kobj, struct blk_cmd_filter, kobj);
- if (entry->show)
- return entry->show(filter, page);
-
- return 0;
-}
-
-static ssize_t
-rcf_attr_store(struct kobject *kobj, struct attribute *attr,
- const char *page, size_t length)
-{
- struct rcf_sysfs_entry *entry = to_rcf(attr);
- struct blk_cmd_filter *filter;
-
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
-
- if (!entry->store)
- return -EINVAL;
-
- filter = container_of(kobj, struct blk_cmd_filter, kobj);
- return entry->store(filter, page, length);
-}
-
-static struct sysfs_ops rcf_sysfs_ops = {
- .show = rcf_attr_show,
- .store = rcf_attr_store,
-};
-
-static struct kobj_type rcf_ktype = {
- .sysfs_ops = &rcf_sysfs_ops,
- .default_attrs = default_attrs,
+static struct attribute_group rcf_attr_group = {
+ .name = "cmd_filter",
+ .attrs = default_attrs,
};
int blk_register_filter(struct gendisk *disk)
{
+ struct kobject *kobj = &disk->queue->kobj;
int ret;
- struct blk_cmd_filter *filter = &disk->queue->cmd_filter;
- struct kobject *parent = kobject_get(disk->holder_dir->parent);
- if (!parent)
- return -ENODEV;
+ ret = sysfs_create_group(kobj, &rcf_attr_group);
+ if (!ret)
+ ret = sysfs_create_link_to_group(disk->holder_dir->parent,
+ kobj, rcf_attr_group.name,
+ rcf_attr_group.name);
+ WARN_ON(ret);
- ret = kobject_init_and_add(&filter->kobj, &rcf_ktype, parent,
- "%s", "cmd_filter");
-
- if (ret < 0)
- return ret;
-
- return 0;
+ return ret;
}
EXPORT_SYMBOL(blk_register_filter);
void blk_unregister_filter(struct gendisk *disk)
{
- struct blk_cmd_filter *filter = &disk->queue->cmd_filter;
-
- kobject_put(&filter->kobj);
- kobject_put(disk->holder_dir->parent);
+ sysfs_remove_link(disk->holder_dir->parent, rcf_attr_group.name);
+ sysfs_remove_group(&disk->queue->kobj, &rcf_attr_group);
}
EXPORT_SYMBOL(blk_unregister_filter);
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index a3ba217..d2813a1 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -19,22 +19,16 @@
#include "sysfs.h"
-static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target,
+static int sysfs_sd_create_link(struct sysfs_dirent *parent_sd,
+ struct sysfs_dirent *target_sd,
const char *name, int warn)
{
- struct sysfs_dirent *parent_sd = NULL;
- struct sysfs_dirent *target_sd = NULL;
struct sysfs_dirent *sd = NULL;
struct sysfs_addrm_cxt acxt;
int error;
BUG_ON(!name);
- if (!kobj)
- parent_sd = &sysfs_root;
- else
- parent_sd = kobj->sd;
-
error = -EFAULT;
if (!parent_sd)
goto out_put;
@@ -43,8 +37,8 @@ static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target,
* sysfs_assoc_lock. Fetch target_sd from it.
*/
spin_lock(&sysfs_assoc_lock);
- if (target->sd)
- target_sd = sysfs_get(target->sd);
+ if (target_sd)
+ target_sd = sysfs_get(target_sd);
spin_unlock(&sysfs_assoc_lock);
error = -ENOENT;
@@ -77,6 +71,19 @@ static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target,
return error;
}
+static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target,
+ const char *name, int warn)
+{
+ struct sysfs_dirent *parent_sd;
+
+ if (!kobj)
+ parent_sd = &sysfs_root;
+ else
+ parent_sd = kobj->sd;
+
+ return sysfs_sd_create_link(parent_sd, target->sd, name, warn);
+}
+
/**
* sysfs_create_link - create symlink between two objects.
* @kobj: object whose directory we're creating the link in.
@@ -104,6 +111,26 @@ int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target,
return sysfs_do_create_link(kobj, target, name, 0);
}
+int sysfs_create_link_to_group(struct kobject *kobj, struct kobject *target,
+ const char *group, const char *linkname)
+{
+ struct sysfs_dirent *sd;
+ int ret;
+
+ BUG_ON(!kobj || !target);
+
+ sd = sysfs_get_dirent(target->sd, group);
+ if (!sd) {
+ WARN(!sd, KERN_WARNING "sysfs group %p not found for "
+ "kobject '%s'\n", group, kobject_name(target));
+ return -ENOENT;
+ }
+
+ ret = sysfs_sd_create_link(kobj->sd, sd, linkname, 1);
+ sysfs_put(sd);
+ return ret;
+}
+
/**
* sysfs_remove_link - remove symlink in object's directory.
* @kobj: object we're acting for.
@@ -213,4 +240,5 @@ const struct inode_operations sysfs_symlink_inode_operations = {
EXPORT_SYMBOL_GPL(sysfs_create_link);
+EXPORT_SYMBOL_GPL(sysfs_create_link_to_group);
EXPORT_SYMBOL_GPL(sysfs_remove_link);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 44710d7..ca616b7 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -286,7 +286,6 @@ struct blk_queue_tag {
struct blk_cmd_filter {
unsigned long read_ok[BLK_SCSI_CMD_PER_LONG];
unsigned long write_ok[BLK_SCSI_CMD_PER_LONG];
- struct kobject kobj;
};
struct request_queue
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 37fa241..e9e0971 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -116,6 +116,8 @@ int sysfs_add_file_to_group(struct kobject *kobj,
const struct attribute *attr, const char *group);
void sysfs_remove_file_from_group(struct kobject *kobj,
const struct attribute *attr, const char *group);
+int sysfs_create_link_to_group(struct kobject *kobj, struct kobject *target,
+ const char *grpname, const char *linkname);
void sysfs_notify(struct kobject *kobj, char *dir, char *attr);
next reply other threads:[~2008-09-05 16:48 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-09-05 16:48 Elias Oltmanns [this message]
2008-09-09 10:28 ` Block: Trouble with kobject initialisation for blk_cmd_filter Jens Axboe
2008-09-09 12:45 ` FUJITA Tomonori
2008-09-09 13:18 ` Jens Axboe
2008-09-09 16:57 ` Elias Oltmanns
2008-09-10 2:43 ` FUJITA Tomonori
2008-09-15 19:55 ` Elias Oltmanns
2008-09-15 20:17 ` FUJITA Tomonori
2008-09-15 20:49 ` Elias Oltmanns
2008-09-15 21:31 ` FUJITA Tomonori
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87od3235fc.fsf@denkblock.local \
--to=eo@nebensachen.de \
--cc=fujita.tomonori@lab.ntt.co.jp \
--cc=greg@kroah.com \
--cc=jens.axboe@oracle.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.