From: "Jun'ichi Nomura" <j-nomura@ce.jp.nec.com>
To: Alasdair Kergon <agk@redhat.com>, Neil Brown <neilb@suse.de>,
Greg KH <gregkh@suse.de>,
linux-kernel@vger.kernel.org
Cc: akpm@osdl.org, device-mapper development <dm-devel@redhat.com>,
Lars Marowsky-Bree <lmb@suse.de>
Subject: [PATCH 3/6] bd_claim_by_kobject
Date: Fri, 03 Mar 2006 19:57:43 -0500 [thread overview]
Message-ID: <4408E607.2010300@ce.jp.nec.com> (raw)
In-Reply-To: <4408E33E.1080703@ce.jp.nec.com>
[-- Attachment #1: Type: text/plain, Size: 351 bytes --]
This patch is part of dm/md sysfs dependency tree.
This adds bd_claim_by_kobject() function which takes kobject as
additional signature of holder device and creates sysfs symlinks
between holder device and claimed device.
bd_release_from_kobject() is a counter part of bd_claim_by_kobject.
Thanks,
--
Jun'ichi Nomura, NEC Solutions (America), Inc.
[-- Attachment #2: 03-bd_claim_by_kobj.patch --]
[-- Type: text/x-patch, Size: 7290 bytes --]
Adding bd_claim_by_kobject() function which takes kobject as
additional signature of holder device and creates sysfs symlinks
between holder device and claimed device.
bd_release_from_kobject() is a counter part of bd_claim_by_kobject.
Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
fs/block_dev.c | 196 +++++++++++++++++++++++++++++++++++++++++++++++++++-
include/linux/fs.h | 3
2 files changed, 197 insertions(+), 2 deletions(-)
--- linux-2.6.16-rc5.orig/include/linux/fs.h 2006-02-27 00:09:35.000000000 -0500
+++ linux-2.6.16-rc5/include/linux/fs.h 2006-03-02 10:29:55.000000000 -0500
@@ -401,6 +401,7 @@ struct block_device {
struct list_head bd_inodes;
void * bd_holder;
int bd_holders;
+ struct list_head bd_holder_list;
struct block_device * bd_contains;
unsigned bd_block_size;
struct hd_struct * bd_part;
@@ -1380,6 +1381,8 @@ extern int blkdev_get(struct block_devic
extern int blkdev_put(struct block_device *);
extern int bd_claim(struct block_device *, void *);
extern void bd_release(struct block_device *);
+extern int bd_claim_by_kobject(struct block_device *, void *, struct kobject *);
+extern void bd_release_from_kobject(struct block_device *, struct kobject *);
/* fs/char_dev.c */
extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *);
--- linux-2.6.16-rc5.orig/fs/block_dev.c 2006-02-27 00:09:35.000000000 -0500
+++ linux-2.6.16-rc5/fs/block_dev.c 2006-03-02 10:29:55.000000000 -0500
@@ -269,6 +269,7 @@ static void init_once(void * foo, kmem_c
sema_init(&bdev->bd_mount_sem, 1);
INIT_LIST_HEAD(&bdev->bd_inodes);
INIT_LIST_HEAD(&bdev->bd_list);
+ INIT_LIST_HEAD(&bdev->bd_holder_list);
inode_init_once(&ei->vfs_inode);
}
}
@@ -443,7 +444,179 @@ void bd_forget(struct inode *inode)
spin_unlock(&bdev_lock);
}
-int bd_claim(struct block_device *bdev, void *holder)
+/*
+ * Functions for bd_claim_by_kobject / bd_release_from_kobject
+ *
+ * If a kobject is passed to bd_claim_by_kobject()
+ * and the kobject has a parent directory,
+ * following symlinks are created:
+ * o from the kobject to the claimed bdev
+ * o from "holders" directory of the bdev to the parent of the kobject
+ * bd_release_from_kobject() removes these symlinks.
+ *
+ * Example:
+ * If /dev/dm-0 maps to /dev/sda, kobject corresponding to
+ * /sys/block/dm-0/slaves is passed to bd_claim_by_kobject(), then:
+ * /sys/block/dm-0/slaves/sda --> /sys/block/sda
+ * /sys/block/sda/holders/dm-0 --> /sys/block/dm-0
+ */
+
+static inline struct kobject * bdev_get_kobj(struct block_device *bdev)
+{
+ if (!bdev)
+ return NULL;
+ else if (bdev->bd_contains != bdev)
+ return kobject_get(&bdev->bd_part->kobj);
+ else
+ return kobject_get(&bdev->bd_disk->kobj);
+}
+
+static inline struct kobject * bdev_get_holder(struct block_device *bdev)
+{
+ if (!bdev)
+ return NULL;
+ else if (bdev->bd_contains != bdev)
+ return kobject_get(bdev->bd_part->holder_dir);
+ else
+ return kobject_get(bdev->bd_disk->holder_dir);
+}
+
+static inline void add_symlink(struct kobject *from, struct kobject *to)
+{
+ if (!from || !to)
+ return;
+ kobject_get(from);
+ kobject_get(to);
+ sysfs_create_link(from, to, kobject_name(to));
+}
+
+static inline void del_symlink(struct kobject *from, struct kobject *to)
+{
+ if (!from || !to)
+ return;
+ sysfs_remove_link(from, kobject_name(to));
+ kobject_put(from);
+ kobject_put(to);
+}
+
+static inline int bd_claim_grab_dirs(struct block_device *bdev,
+ struct kobject *holder,
+ struct kobject **sdir, struct kobject **sdev,
+ struct kobject **hdir, struct kobject **hdev)
+{
+ *sdir = kobject_get(holder);
+ if (!*sdir)
+ return 0;
+
+ *hdev = kobject_get((*sdir)->parent);
+ if (!*hdev)
+ goto fail_put_sdir;
+
+ *sdev = bdev_get_kobj(bdev);
+ if (!*sdev)
+ goto fail_put_hdev;
+
+ *hdir = bdev_get_holder(bdev);
+ if (!*hdir)
+ goto fail_put_sdev;
+
+ return 1;
+
+fail_put_sdev:
+ kobject_put(*sdev);
+fail_put_hdev:
+ kobject_put(*hdev);
+fail_put_sdir:
+ kobject_put(*sdir);
+
+ return 0;
+}
+
+static inline void bd_claim_release_dirs(
+ struct kobject *sdir, struct kobject *sdev,
+ struct kobject *hdir, struct kobject *hdev)
+{
+ kobject_put(hdir);
+ kobject_put(sdev);
+ kobject_put(hdev);
+ kobject_put(sdir);
+}
+
+static void link_bd_holder(struct block_device *bdev, struct kobject *holder)
+{
+ struct kobject *sdir, *sdev, *hdir, *hdev;
+
+ if (bd_claim_grab_dirs(bdev, holder, &sdir, &sdev, &hdir, &hdev)) {
+ add_symlink(sdir, sdev);
+ add_symlink(hdir, hdev);
+ bd_claim_release_dirs(sdir, sdev, hdir, hdev);
+ }
+
+ return;
+}
+
+static void unlink_bd_holder(struct block_device *bdev, struct kobject *holder)
+{
+ struct kobject *sdir, *sdev, *hdir, *hdev;
+
+ if (bd_claim_grab_dirs(bdev, holder, &sdir, &sdev, &hdir, &hdev)) {
+ del_symlink(sdir, sdev);
+ del_symlink(hdir, hdev);
+ bd_claim_release_dirs(sdir, sdev, hdir, hdev);
+ }
+}
+
+/* bd_holder_list is protected by bdev_lock */
+struct bd_holder {
+ struct list_head list; /* chain of holders of the bdev */
+ int count; /* references from the holder */
+ struct kobject *kobj; /* holder kobject */
+};
+
+static int add_bd_holder(struct block_device *bdev, struct kobject *kobj)
+{
+ struct bd_holder *bo;
+
+ list_for_each_entry(bo, &bdev->bd_holder_list, list) {
+ if (bo->kobj == kobj) {
+ bo->count++;
+ return 0;
+ }
+ }
+
+ bo = kmalloc(sizeof(*bo), GFP_KERNEL);
+ if (!bo)
+ return -ENOMEM;
+
+ bo->count = 1;
+ bo->kobj = kobj;
+ list_add_tail(&bo->list, &bdev->bd_holder_list);
+ link_bd_holder(bdev, kobj);
+
+ return 0;
+}
+
+static int del_bd_holder(struct block_device *bdev, struct kobject *kobj)
+{
+ struct bd_holder *bo;
+
+ list_for_each_entry(bo, &bdev->bd_holder_list, list) {
+ if (bo->kobj == kobj) {
+ bo->count--;
+ BUG_ON(bo->count < 0);
+ if (!bo->count) {
+ unlink_bd_holder(bdev, kobj);
+ list_del(&bo->list);
+ kfree(bo);
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int bd_claim_by_kobject(struct block_device *bdev, void *holder, struct kobject *kobj)
{
int res;
spin_lock(&bdev_lock);
@@ -464,6 +637,9 @@ int bd_claim(struct block_device *bdev,
res = 0; /* is a partition of an un-held device */
/* now impose change */
+ if (res == 0 && kobj)
+ res = add_bd_holder(bdev, kobj);
+
if (res==0) {
/* note that for a whole device bd_holders
* will be incremented twice, and bd_holder will
@@ -478,11 +654,20 @@ int bd_claim(struct block_device *bdev,
return res;
}
+EXPORT_SYMBOL(bd_claim_by_kobject);
+
+int bd_claim(struct block_device *bdev, void *holder)
+{
+ return bd_claim_by_kobject(bdev, holder, NULL);
+}
+
EXPORT_SYMBOL(bd_claim);
-void bd_release(struct block_device *bdev)
+void bd_release_from_kobject(struct block_device *bdev, struct kobject *kobj)
{
spin_lock(&bdev_lock);
+ if (kobj)
+ del_bd_holder(bdev, kobj);
if (!--bdev->bd_contains->bd_holders)
bdev->bd_contains->bd_holder = NULL;
if (!--bdev->bd_holders)
@@ -490,6 +675,13 @@ void bd_release(struct block_device *bde
spin_unlock(&bdev_lock);
}
+EXPORT_SYMBOL(bd_release_from_kobject);
+
+void bd_release(struct block_device *bdev)
+{
+ bd_release_from_kobject(bdev, NULL);
+}
+
EXPORT_SYMBOL(bd_release);
/*
[-- Attachment #3: Type: text/plain, Size: 0 bytes --]
WARNING: multiple messages have this Message-ID (diff)
From: "Jun'ichi Nomura" <j-nomura@ce.jp.nec.com>
To: Alasdair Kergon <agk@redhat.com>, Neil Brown <neilb@suse.de>,
Greg KH <gregkh@suse.de>,
linux-kernel@vger.kernel.org
Cc: Lars Marowsky-Bree <lmb@suse.de>,
akpm@osdl.org, device-mapper development <dm-devel@redhat.com>
Subject: [PATCH 3/6] bd_claim_by_kobject
Date: Fri, 03 Mar 2006 19:57:43 -0500 [thread overview]
Message-ID: <4408E607.2010300@ce.jp.nec.com> (raw)
In-Reply-To: <4408E33E.1080703@ce.jp.nec.com>
[-- Attachment #1: Type: text/plain, Size: 351 bytes --]
This patch is part of dm/md sysfs dependency tree.
This adds bd_claim_by_kobject() function which takes kobject as
additional signature of holder device and creates sysfs symlinks
between holder device and claimed device.
bd_release_from_kobject() is a counter part of bd_claim_by_kobject.
Thanks,
--
Jun'ichi Nomura, NEC Solutions (America), Inc.
[-- Attachment #2: 03-bd_claim_by_kobj.patch --]
[-- Type: text/x-patch, Size: 7290 bytes --]
Adding bd_claim_by_kobject() function which takes kobject as
additional signature of holder device and creates sysfs symlinks
between holder device and claimed device.
bd_release_from_kobject() is a counter part of bd_claim_by_kobject.
Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
fs/block_dev.c | 196 +++++++++++++++++++++++++++++++++++++++++++++++++++-
include/linux/fs.h | 3
2 files changed, 197 insertions(+), 2 deletions(-)
--- linux-2.6.16-rc5.orig/include/linux/fs.h 2006-02-27 00:09:35.000000000 -0500
+++ linux-2.6.16-rc5/include/linux/fs.h 2006-03-02 10:29:55.000000000 -0500
@@ -401,6 +401,7 @@ struct block_device {
struct list_head bd_inodes;
void * bd_holder;
int bd_holders;
+ struct list_head bd_holder_list;
struct block_device * bd_contains;
unsigned bd_block_size;
struct hd_struct * bd_part;
@@ -1380,6 +1381,8 @@ extern int blkdev_get(struct block_devic
extern int blkdev_put(struct block_device *);
extern int bd_claim(struct block_device *, void *);
extern void bd_release(struct block_device *);
+extern int bd_claim_by_kobject(struct block_device *, void *, struct kobject *);
+extern void bd_release_from_kobject(struct block_device *, struct kobject *);
/* fs/char_dev.c */
extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *);
--- linux-2.6.16-rc5.orig/fs/block_dev.c 2006-02-27 00:09:35.000000000 -0500
+++ linux-2.6.16-rc5/fs/block_dev.c 2006-03-02 10:29:55.000000000 -0500
@@ -269,6 +269,7 @@ static void init_once(void * foo, kmem_c
sema_init(&bdev->bd_mount_sem, 1);
INIT_LIST_HEAD(&bdev->bd_inodes);
INIT_LIST_HEAD(&bdev->bd_list);
+ INIT_LIST_HEAD(&bdev->bd_holder_list);
inode_init_once(&ei->vfs_inode);
}
}
@@ -443,7 +444,179 @@ void bd_forget(struct inode *inode)
spin_unlock(&bdev_lock);
}
-int bd_claim(struct block_device *bdev, void *holder)
+/*
+ * Functions for bd_claim_by_kobject / bd_release_from_kobject
+ *
+ * If a kobject is passed to bd_claim_by_kobject()
+ * and the kobject has a parent directory,
+ * following symlinks are created:
+ * o from the kobject to the claimed bdev
+ * o from "holders" directory of the bdev to the parent of the kobject
+ * bd_release_from_kobject() removes these symlinks.
+ *
+ * Example:
+ * If /dev/dm-0 maps to /dev/sda, kobject corresponding to
+ * /sys/block/dm-0/slaves is passed to bd_claim_by_kobject(), then:
+ * /sys/block/dm-0/slaves/sda --> /sys/block/sda
+ * /sys/block/sda/holders/dm-0 --> /sys/block/dm-0
+ */
+
+static inline struct kobject * bdev_get_kobj(struct block_device *bdev)
+{
+ if (!bdev)
+ return NULL;
+ else if (bdev->bd_contains != bdev)
+ return kobject_get(&bdev->bd_part->kobj);
+ else
+ return kobject_get(&bdev->bd_disk->kobj);
+}
+
+static inline struct kobject * bdev_get_holder(struct block_device *bdev)
+{
+ if (!bdev)
+ return NULL;
+ else if (bdev->bd_contains != bdev)
+ return kobject_get(bdev->bd_part->holder_dir);
+ else
+ return kobject_get(bdev->bd_disk->holder_dir);
+}
+
+static inline void add_symlink(struct kobject *from, struct kobject *to)
+{
+ if (!from || !to)
+ return;
+ kobject_get(from);
+ kobject_get(to);
+ sysfs_create_link(from, to, kobject_name(to));
+}
+
+static inline void del_symlink(struct kobject *from, struct kobject *to)
+{
+ if (!from || !to)
+ return;
+ sysfs_remove_link(from, kobject_name(to));
+ kobject_put(from);
+ kobject_put(to);
+}
+
+static inline int bd_claim_grab_dirs(struct block_device *bdev,
+ struct kobject *holder,
+ struct kobject **sdir, struct kobject **sdev,
+ struct kobject **hdir, struct kobject **hdev)
+{
+ *sdir = kobject_get(holder);
+ if (!*sdir)
+ return 0;
+
+ *hdev = kobject_get((*sdir)->parent);
+ if (!*hdev)
+ goto fail_put_sdir;
+
+ *sdev = bdev_get_kobj(bdev);
+ if (!*sdev)
+ goto fail_put_hdev;
+
+ *hdir = bdev_get_holder(bdev);
+ if (!*hdir)
+ goto fail_put_sdev;
+
+ return 1;
+
+fail_put_sdev:
+ kobject_put(*sdev);
+fail_put_hdev:
+ kobject_put(*hdev);
+fail_put_sdir:
+ kobject_put(*sdir);
+
+ return 0;
+}
+
+static inline void bd_claim_release_dirs(
+ struct kobject *sdir, struct kobject *sdev,
+ struct kobject *hdir, struct kobject *hdev)
+{
+ kobject_put(hdir);
+ kobject_put(sdev);
+ kobject_put(hdev);
+ kobject_put(sdir);
+}
+
+static void link_bd_holder(struct block_device *bdev, struct kobject *holder)
+{
+ struct kobject *sdir, *sdev, *hdir, *hdev;
+
+ if (bd_claim_grab_dirs(bdev, holder, &sdir, &sdev, &hdir, &hdev)) {
+ add_symlink(sdir, sdev);
+ add_symlink(hdir, hdev);
+ bd_claim_release_dirs(sdir, sdev, hdir, hdev);
+ }
+
+ return;
+}
+
+static void unlink_bd_holder(struct block_device *bdev, struct kobject *holder)
+{
+ struct kobject *sdir, *sdev, *hdir, *hdev;
+
+ if (bd_claim_grab_dirs(bdev, holder, &sdir, &sdev, &hdir, &hdev)) {
+ del_symlink(sdir, sdev);
+ del_symlink(hdir, hdev);
+ bd_claim_release_dirs(sdir, sdev, hdir, hdev);
+ }
+}
+
+/* bd_holder_list is protected by bdev_lock */
+struct bd_holder {
+ struct list_head list; /* chain of holders of the bdev */
+ int count; /* references from the holder */
+ struct kobject *kobj; /* holder kobject */
+};
+
+static int add_bd_holder(struct block_device *bdev, struct kobject *kobj)
+{
+ struct bd_holder *bo;
+
+ list_for_each_entry(bo, &bdev->bd_holder_list, list) {
+ if (bo->kobj == kobj) {
+ bo->count++;
+ return 0;
+ }
+ }
+
+ bo = kmalloc(sizeof(*bo), GFP_KERNEL);
+ if (!bo)
+ return -ENOMEM;
+
+ bo->count = 1;
+ bo->kobj = kobj;
+ list_add_tail(&bo->list, &bdev->bd_holder_list);
+ link_bd_holder(bdev, kobj);
+
+ return 0;
+}
+
+static int del_bd_holder(struct block_device *bdev, struct kobject *kobj)
+{
+ struct bd_holder *bo;
+
+ list_for_each_entry(bo, &bdev->bd_holder_list, list) {
+ if (bo->kobj == kobj) {
+ bo->count--;
+ BUG_ON(bo->count < 0);
+ if (!bo->count) {
+ unlink_bd_holder(bdev, kobj);
+ list_del(&bo->list);
+ kfree(bo);
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int bd_claim_by_kobject(struct block_device *bdev, void *holder, struct kobject *kobj)
{
int res;
spin_lock(&bdev_lock);
@@ -464,6 +637,9 @@ int bd_claim(struct block_device *bdev,
res = 0; /* is a partition of an un-held device */
/* now impose change */
+ if (res == 0 && kobj)
+ res = add_bd_holder(bdev, kobj);
+
if (res==0) {
/* note that for a whole device bd_holders
* will be incremented twice, and bd_holder will
@@ -478,11 +654,20 @@ int bd_claim(struct block_device *bdev,
return res;
}
+EXPORT_SYMBOL(bd_claim_by_kobject);
+
+int bd_claim(struct block_device *bdev, void *holder)
+{
+ return bd_claim_by_kobject(bdev, holder, NULL);
+}
+
EXPORT_SYMBOL(bd_claim);
-void bd_release(struct block_device *bdev)
+void bd_release_from_kobject(struct block_device *bdev, struct kobject *kobj)
{
spin_lock(&bdev_lock);
+ if (kobj)
+ del_bd_holder(bdev, kobj);
if (!--bdev->bd_contains->bd_holders)
bdev->bd_contains->bd_holder = NULL;
if (!--bdev->bd_holders)
@@ -490,6 +675,13 @@ void bd_release(struct block_device *bde
spin_unlock(&bdev_lock);
}
+EXPORT_SYMBOL(bd_release_from_kobject);
+
+void bd_release(struct block_device *bdev)
+{
+ bd_release_from_kobject(bdev, NULL);
+}
+
EXPORT_SYMBOL(bd_release);
/*
next prev parent reply other threads:[~2006-03-04 0:57 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-03-04 0:45 [PATCH 0/6] dm/md sysfs dependency tree (rev.3) Jun'ichi Nomura
2006-03-04 0:45 ` Jun'ichi Nomura
2006-03-04 0:57 ` [PATCH 1/6] kobject_add_dir Jun'ichi Nomura
2006-03-04 0:57 ` Jun'ichi Nomura
2006-03-04 0:57 ` [PATCH 2/6] add holders/slaves subdirectory to /sys/block Jun'ichi Nomura
2006-03-04 0:57 ` Jun'ichi Nomura
2006-03-04 0:57 ` Jun'ichi Nomura [this message]
2006-03-04 0:57 ` [PATCH 3/6] bd_claim_by_kobject Jun'ichi Nomura
2006-03-04 0:57 ` [PATCH 4/6] bd_claim_by_disk Jun'ichi Nomura
2006-03-04 0:57 ` Jun'ichi Nomura
2006-03-04 0:58 ` [PATCH 5/6] md to use bd_claim_by_disk Jun'ichi Nomura
2006-03-04 0:58 ` Jun'ichi Nomura
2006-03-04 0:58 ` [PATCH 6/6] dm " Jun'ichi Nomura
2006-03-04 0:58 ` Jun'ichi Nomura
2006-03-06 15:56 ` Alasdair G Kergon
2006-03-06 15:56 ` Alasdair G Kergon
2006-03-06 17:00 ` Jun'ichi Nomura
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=4408E607.2010300@ce.jp.nec.com \
--to=j-nomura@ce.jp.nec.com \
--cc=agk@redhat.com \
--cc=akpm@osdl.org \
--cc=dm-devel@redhat.com \
--cc=gregkh@suse.de \
--cc=linux-kernel@vger.kernel.org \
--cc=lmb@suse.de \
--cc=neilb@suse.de \
/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.