diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/block_dev.c | 8 | ||||
-rw-r--r-- | fs/char_dev.c | 6 | ||||
-rw-r--r-- | fs/coda/psdev.c | 8 | ||||
-rw-r--r-- | fs/configfs/mount.c | 13 | ||||
-rw-r--r-- | fs/debugfs/inode.c | 13 | ||||
-rw-r--r-- | fs/dlm/lockspace.c | 50 | ||||
-rw-r--r-- | fs/ecryptfs/main.c | 129 | ||||
-rw-r--r-- | fs/fuse/inode.c | 26 | ||||
-rw-r--r-- | fs/gfs2/locking/dlm/sysfs.c | 38 | ||||
-rw-r--r-- | fs/gfs2/sys.c | 29 | ||||
-rw-r--r-- | fs/namespace.c | 11 | ||||
-rw-r--r-- | fs/ocfs2/cluster/masklog.c | 4 | ||||
-rw-r--r-- | fs/ocfs2/cluster/sys.c | 83 | ||||
-rw-r--r-- | fs/partitions/check.c | 327 | ||||
-rw-r--r-- | fs/sysfs/dir.c | 2 | ||||
-rw-r--r-- | fs/sysfs/file.c | 67 | ||||
-rw-r--r-- | fs/sysfs/symlink.c | 88 |
17 files changed, 287 insertions, 615 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c index 993f78c5522..e48a630ae26 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -738,9 +738,9 @@ EXPORT_SYMBOL(bd_release); static struct kobject *bdev_get_kobj(struct block_device *bdev) { if (bdev->bd_contains != bdev) - return kobject_get(&bdev->bd_part->kobj); + return kobject_get(&bdev->bd_part->dev.kobj); else - return kobject_get(&bdev->bd_disk->kobj); + return kobject_get(&bdev->bd_disk->dev.kobj); } static struct kobject *bdev_get_holder(struct block_device *bdev) @@ -1176,7 +1176,7 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part) ret = -ENXIO; goto out_first; } - kobject_get(&p->kobj); + kobject_get(&p->dev.kobj); bdev->bd_part = p; bd_set_size(bdev, (loff_t) p->nr_sects << 9); } @@ -1299,7 +1299,7 @@ static int __blkdev_put(struct block_device *bdev, int for_part) module_put(owner); if (bdev->bd_contains != bdev) { - kobject_put(&bdev->bd_part->kobj); + kobject_put(&bdev->bd_part->dev.kobj); bdev->bd_part = NULL; } bdev->bd_disk = NULL; diff --git a/fs/char_dev.c b/fs/char_dev.c index c3bfa76765c..2c7a8b5b459 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -510,9 +510,8 @@ struct cdev *cdev_alloc(void) { struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL); if (p) { - p->kobj.ktype = &ktype_cdev_dynamic; INIT_LIST_HEAD(&p->list); - kobject_init(&p->kobj); + kobject_init(&p->kobj, &ktype_cdev_dynamic); } return p; } @@ -529,8 +528,7 @@ void cdev_init(struct cdev *cdev, const struct file_operations *fops) { memset(cdev, 0, sizeof *cdev); INIT_LIST_HEAD(&cdev->list); - cdev->kobj.ktype = &ktype_cdev_default; - kobject_init(&cdev->kobj); + kobject_init(&cdev->kobj, &ktype_cdev_default); cdev->ops = fops; } diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index dcc6aead70f..e3eb3556622 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c @@ -362,8 +362,8 @@ static int init_coda_psdev(void) goto out_chrdev; } for (i = 0; i < MAX_CODADEVS; i++) - class_device_create(coda_psdev_class, NULL, - MKDEV(CODA_PSDEV_MAJOR,i), NULL, "cfs%d", i); + device_create(coda_psdev_class, NULL, + MKDEV(CODA_PSDEV_MAJOR,i), "cfs%d", i); coda_sysctl_init(); goto out; @@ -405,7 +405,7 @@ static int __init init_coda(void) return 0; out: for (i = 0; i < MAX_CODADEVS; i++) - class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i)); + device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i)); class_destroy(coda_psdev_class); unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); coda_sysctl_clean(); @@ -424,7 +424,7 @@ static void __exit exit_coda(void) printk("coda: failed to unregister filesystem\n"); } for (i = 0; i < MAX_CODADEVS; i++) - class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i)); + device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i)); class_destroy(coda_psdev_class); unregister_chrdev(CODA_PSDEV_MAJOR, "coda"); coda_sysctl_clean(); diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c index 3bf0278ea84..de3b31d0a37 100644 --- a/fs/configfs/mount.c +++ b/fs/configfs/mount.c @@ -128,7 +128,7 @@ void configfs_release_fs(void) } -static decl_subsys(config, NULL, NULL); +static struct kobject *config_kobj; static int __init configfs_init(void) { @@ -140,9 +140,8 @@ static int __init configfs_init(void) if (!configfs_dir_cachep) goto out; - kobj_set_kset_s(&config_subsys, kernel_subsys); - err = subsystem_register(&config_subsys); - if (err) { + config_kobj = kobject_create_and_add("config", kernel_kobj); + if (!config_kobj) { kmem_cache_destroy(configfs_dir_cachep); configfs_dir_cachep = NULL; goto out; @@ -151,7 +150,7 @@ static int __init configfs_init(void) err = register_filesystem(&configfs_fs_type); if (err) { printk(KERN_ERR "configfs: Unable to register filesystem!\n"); - subsystem_unregister(&config_subsys); + kobject_put(config_kobj); kmem_cache_destroy(configfs_dir_cachep); configfs_dir_cachep = NULL; goto out; @@ -160,7 +159,7 @@ static int __init configfs_init(void) err = configfs_inode_init(); if (err) { unregister_filesystem(&configfs_fs_type); - subsystem_unregister(&config_subsys); + kobject_put(config_kobj); kmem_cache_destroy(configfs_dir_cachep); configfs_dir_cachep = NULL; } @@ -171,7 +170,7 @@ out: static void __exit configfs_exit(void) { unregister_filesystem(&configfs_fs_type); - subsystem_unregister(&config_subsys); + kobject_put(config_kobj); kmem_cache_destroy(configfs_dir_cachep); configfs_dir_cachep = NULL; configfs_inode_exit(); diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 6a713b33992..d26e2826ba5 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -426,20 +426,19 @@ exit: } EXPORT_SYMBOL_GPL(debugfs_rename); -static decl_subsys(debug, NULL, NULL); +static struct kobject *debug_kobj; static int __init debugfs_init(void) { int retval; - kobj_set_kset_s(&debug_subsys, kernel_subsys); - retval = subsystem_register(&debug_subsys); - if (retval) - return retval; + debug_kobj = kobject_create_and_add("debug", kernel_kobj); + if (!debug_kobj) + return -EINVAL; retval = register_filesystem(&debug_fs_type); if (retval) - subsystem_unregister(&debug_subsys); + kobject_put(debug_kobj); return retval; } @@ -447,7 +446,7 @@ static void __exit debugfs_exit(void) { simple_release_fs(&debugfs_mount, &debugfs_mount_count); unregister_filesystem(&debug_fs_type); - subsystem_unregister(&debug_subsys); + kobject_put(debug_kobj); } core_initcall(debugfs_init); diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index 6353a838452..5c108c49cb8 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -166,26 +166,7 @@ static struct kobj_type dlm_ktype = { .release = lockspace_kobj_release, }; -static struct kset dlm_kset = { - .ktype = &dlm_ktype, -}; - -static int kobject_setup(struct dlm_ls *ls) -{ - char lsname[DLM_LOCKSPACE_LEN]; - int error; - - memset(lsname, 0, DLM_LOCKSPACE_LEN); - snprintf(lsname, DLM_LOCKSPACE_LEN, "%s", ls->ls_name); - - error = kobject_set_name(&ls->ls_kobj, "%s", lsname); - if (error) - return error; - - ls->ls_kobj.kset = &dlm_kset; - ls->ls_kobj.ktype = &dlm_ktype; - return 0; -} +static struct kset *dlm_kset; static int do_uevent(struct dlm_ls *ls, int in) { @@ -220,24 +201,22 @@ static int do_uevent(struct dlm_ls *ls, int in) int dlm_lockspace_init(void) { - int error; - ls_count = 0; mutex_init(&ls_lock); INIT_LIST_HEAD(&lslist); spin_lock_init(&lslist_lock); - kobject_set_name(&dlm_kset.kobj, "dlm"); - kobj_set_kset_s(&dlm_kset, kernel_subsys); - error = kset_register(&dlm_kset); - if (error) - printk("dlm_lockspace_init: cannot register kset %d\n", error); - return error; + dlm_kset = kset_create_and_add("dlm", NULL, kernel_kobj); + if (!dlm_kset) { + printk(KERN_WARNING "%s: can not create kset\n", __FUNCTION__); + return -ENOMEM; + } + return 0; } void dlm_lockspace_exit(void) { - kset_unregister(&dlm_kset); + kset_unregister(dlm_kset); } static int dlm_scand(void *data) @@ -549,13 +528,12 @@ static int new_lockspace(char *name, int namelen, void **lockspace, goto out_delist; } - error = kobject_setup(ls); - if (error) - goto out_stop; - - error = kobject_register(&ls->ls_kobj); + ls->ls_kobj.kset = dlm_kset; + error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL, + "%s", ls->ls_name); if (error) goto out_stop; + kobject_uevent(&ls->ls_kobj, KOBJ_ADD); /* let kobject handle freeing of ls if there's an error */ do_unreg = 1; @@ -601,7 +579,7 @@ static int new_lockspace(char *name, int namelen, void **lockspace, kfree(ls->ls_rsbtbl); out_lsfree: if (do_unreg) - kobject_unregister(&ls->ls_kobj); + kobject_put(&ls->ls_kobj); else kfree(ls); out: @@ -750,7 +728,7 @@ static int release_lockspace(struct dlm_ls *ls, int force) dlm_clear_members(ls); dlm_clear_members_gone(ls); kfree(ls->ls_node_array); - kobject_unregister(&ls->ls_kobj); + kobject_put(&ls->ls_kobj); /* The ls structure will be freed when the kobject is done with */ mutex_lock(&ls_lock); diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index e5580bcb923..0249aa4ae18 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -734,127 +734,40 @@ static int ecryptfs_init_kmem_caches(void) return 0; } -struct ecryptfs_obj { - char *name; - struct list_head slot_list; - struct kobject kobj; -}; - -struct ecryptfs_attribute { - struct attribute attr; - ssize_t(*show) (struct ecryptfs_obj *, char *); - ssize_t(*store) (struct ecryptfs_obj *, const char *, size_t); -}; +static struct kobject *ecryptfs_kobj; -static ssize_t -ecryptfs_attr_store(struct kobject *kobj, - struct attribute *attr, const char *buf, size_t len) +static ssize_t version_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buff) { - struct ecryptfs_obj *obj = container_of(kobj, struct ecryptfs_obj, - kobj); - struct ecryptfs_attribute *attribute = - container_of(attr, struct ecryptfs_attribute, attr); - - return (attribute->store ? attribute->store(obj, buf, len) : 0); + return snprintf(buff, PAGE_SIZE, "%d\n", ECRYPTFS_VERSIONING_MASK); } -static ssize_t -ecryptfs_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) -{ - struct ecryptfs_obj *obj = container_of(kobj, struct ecryptfs_obj, - kobj); - struct ecryptfs_attribute *attribute = - container_of(attr, struct ecryptfs_attribute, attr); - - return (attribute->show ? attribute->show(obj, buf) : 0); -} +static struct kobj_attribute version_attr = __ATTR_RO(version); -static struct sysfs_ops ecryptfs_sysfs_ops = { - .show = ecryptfs_attr_show, - .store = ecryptfs_attr_store +static struct attribute *attributes[] = { + &version_attr.attr, + NULL, }; -static struct kobj_type ecryptfs_ktype = { - .sysfs_ops = &ecryptfs_sysfs_ops +static struct attribute_group attr_group = { + .attrs = attributes, }; -static decl_subsys(ecryptfs, &ecryptfs_ktype, NULL); - -static ssize_t version_show(struct ecryptfs_obj *obj, char *buff) -{ - return snprintf(buff, PAGE_SIZE, "%d\n", ECRYPTFS_VERSIONING_MASK); -} - -static struct ecryptfs_attribute sysfs_attr_version = __ATTR_RO(version); - -static struct ecryptfs_version_str_map_elem { - u32 flag; - char *str; -} ecryptfs_version_str_map[] = { - {ECRYPTFS_VERSIONING_PASSPHRASE, "passphrase"}, - {ECRYPTFS_VERSIONING_PUBKEY, "pubkey"}, - {ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH, "plaintext passthrough"}, - {ECRYPTFS_VERSIONING_POLICY, "policy"}, - {ECRYPTFS_VERSIONING_XATTR, "metadata in extended attribute"}, - {ECRYPTFS_VERSIONING_MULTKEY, "multiple keys per file"} -}; - -static ssize_t version_str_show(struct ecryptfs_obj *obj, char *buff) -{ - int i; - int remaining = PAGE_SIZE; - int total_written = 0; - - buff[0] = '\0'; - for (i = 0; i < ARRAY_SIZE(ecryptfs_version_str_map); i++) { - int entry_size; - - if (!(ECRYPTFS_VERSIONING_MASK - & ecryptfs_version_str_map[i].flag)) - continue; - entry_size = strlen(ecryptfs_version_str_map[i].str); - if ((entry_size + 2) > remaining) - goto out; - memcpy(buff, ecryptfs_version_str_map[i].str, entry_size); - buff[entry_size++] = '\n'; - buff[entry_size] = '\0'; - buff += entry_size; - total_written += entry_size; - remaining -= entry_size; - } -out: - return total_written; -} - -static struct ecryptfs_attribute sysfs_attr_version_str = __ATTR_RO(version_str); - static int do_sysfs_registration(void) { int rc; - rc = subsystem_register(&ecryptfs_subsys); - if (rc) { - printk(KERN_ERR - "Unable to register ecryptfs sysfs subsystem\n"); - goto out; - } - rc = sysfs_create_file(&ecryptfs_subsys.kobj, - &sysfs_attr_version.attr); - if (rc) { - printk(KERN_ERR - "Unable to create ecryptfs version attribute\n"); - subsystem_unregister(&ecryptfs_subsys); + ecryptfs_kobj = kobject_create_and_add("ecryptfs", fs_kobj); + if (!ecryptfs_kobj) { + printk(KERN_ERR "Unable to create ecryptfs kset\n"); + rc = -ENOMEM; goto out; } - rc = sysfs_create_file(&ecryptfs_subsys.kobj, - &sysfs_attr_version_str.attr); + rc = sysfs_create_group(ecryptfs_kobj, &attr_group); if (rc) { printk(KERN_ERR - "Unable to create ecryptfs version_str attribute\n"); - sysfs_remove_file(&ecryptfs_subsys.kobj, - &sysfs_attr_version.attr); - subsystem_unregister(&ecryptfs_subsys); - goto out; + "Unable to create ecryptfs version attributes\n"); + kobject_put(ecryptfs_kobj); } out: return rc; @@ -862,11 +775,8 @@ out: static void do_sysfs_unregistration(void) { - sysfs_remove_file(&ecryptfs_subsys.kobj, - &sysfs_attr_version.attr); - sysfs_remove_file(&ecryptfs_subsys.kobj, - &sysfs_attr_version_str.attr); - subsystem_unregister(&ecryptfs_subsys); + sysfs_remove_group(ecryptfs_kobj, &attr_group); + kobject_put(ecryptfs_kobj); } static int __init ecryptfs_init(void) @@ -894,7 +804,6 @@ static int __init ecryptfs_init(void) printk(KERN_ERR "Failed to register filesystem\n"); goto out_free_kmem_caches; } - kobj_set_kset_s(&ecryptfs_subsys, fs_subsys); rc = do_sysfs_registration(); if (rc) { printk(KERN_ERR "sysfs registration failed\n"); diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 84f9f7dfdf5..e5e80d1a468 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -744,9 +744,6 @@ static inline void unregister_fuseblk(void) } #endif -static decl_subsys(fuse, NULL, NULL); -static decl_subsys(connections, NULL, NULL); - static void fuse_inode_init_once(struct kmem_cache *cachep, void *foo) { struct inode * inode = foo; @@ -791,32 +788,37 @@ static void fuse_fs_cleanup(void) kmem_cache_destroy(fuse_inode_cachep); } +static struct kobject *fuse_kobj; +static struct kobject *connections_kobj; + static int fuse_sysfs_init(void) { int err; - kobj_set_kset_s(&fuse_subsys, fs_subsys); - err = subsystem_register(&fuse_subsys); - if (err) + fuse_kobj = kobject_create_and_add("fuse", fs_kobj); + if (!fuse_kobj) { + err = -ENOMEM; goto out_err; + } - kobj_set_kset_s(&connections_subsys, fuse_subsys); - err = subsystem_register(&connections_subsys); - if (err) + connections_kobj = kobject_create_and_add("connections", fuse_kobj); + if (!connections_kobj) { + err = -ENOMEM; goto out_fuse_unregister; + } return 0; out_fuse_unregister: - subsystem_unregister(&fuse_subsys); + kobject_put(fuse_kobj); out_err: return err; } static void fuse_sysfs_cleanup(void) { - subsystem_unregister(&connections_subsys); - subsystem_unregister(&fuse_subsys); + kobject_put(connections_kobj); + kobject_put(fuse_kobj); } static int __init fuse_init(void) diff --git a/fs/gfs2/locking/dlm/sysfs.c b/fs/gfs2/locking/dlm/sysfs.c index ae9e6a25fe2..a87b0983976 100644 --- a/fs/gfs2/locking/dlm/sysfs.c +++ b/fs/gfs2/locking/dlm/sysfs.c @@ -189,51 +189,39 @@ static struct kobj_type gdlm_ktype = { .sysfs_ops = &gdlm_attr_ops, }; -static struct kset gdlm_kset = { - .ktype = &gdlm_ktype, -}; +static struct kset *gdlm_kset; int gdlm_kobject_setup(struct gdlm_ls *ls, struct kobject *fskobj) { int error; - error = kobject_set_name(&ls->kobj, "%s", "lock_module"); - if (error) { - log_error("can't set kobj name %d", error); - return error; - } - - ls->kobj.kset = &gdlm_kset; - ls->kobj.ktype = &gdlm_ktype; - ls->kobj.parent = fskobj; - - error = kobject_register(&ls->kobj); + ls->kobj.kset = gdlm_kset; + error = kobject_init_and_add(&ls->kobj, &gdlm_ktype, fskobj, + "lock_module"); if (error) log_error("can't register kobj %d", error); + kobject_uevent(&ls->kobj, KOBJ_ADD); return error; } void gdlm_kobject_release(struct gdlm_ls *ls) { - kobject_unregister(&ls->kobj); + kobject_put(&ls->kobj); } int gdlm_sysfs_init(void) { - int error; - - kobject_set_name(&gdlm_kset.kobj, "lock_dlm"); - kobj_set_kset_s(&gdlm_kset, kernel_subsys); - error = kset_register(&gdlm_kset); - if (error) - printk("lock_dlm: cannot register kset %d\n", error); - - return error; + gdlm_kset = kset_create_and_add("lock_dlm", NULL, kernel_kobj); + if (!gdlm_kset) { + printk(KERN_WARNING "%s: can not create kset\n", __FUNCTION__); + return -ENOMEM; + } + return 0; } void gdlm_sysfs_exit(void) { - kset_unregister(&gdlm_kset); + kset_unregister(gdlm_kset); } diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 7f828a2cc85..eaa3b7b2f99 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -222,9 +222,7 @@ static struct kobj_type gfs2_ktype = { .sysfs_ops = &gfs2_attr_ops, }; -static struct kset gfs2_kset = { - .ktype = &gfs2_ktype, -}; +static struct kset *gfs2_kset; /* * display struct lm_lockstruct fields @@ -492,14 +490,9 @@ int gfs2_sys_fs_add(struct gfs2_sbd *sdp) { int error; - sdp->sd_kobj.kset = &gfs2_kset; - sdp->sd_kobj.ktype = &gfs2_ktype; - - error = kobject_set_name(&sdp->sd_kobj, "%s", sdp->sd_table_name); - if (error) - goto fail; - - error = kobject_register(&sdp->sd_kobj); + sdp->sd_kobj.kset = gfs2_kset; + error = kobject_init_and_add(&sdp->sd_kobj, &gfs2_ktype, NULL, + "%s", sdp->sd_table_name); if (error) goto fail; @@ -519,6 +512,7 @@ int gfs2_sys_fs_add(struct gfs2_sbd *sdp) if (error) goto fail_args; + kobject_uevent(&sdp->sd_kobj, KOBJ_ADD); return 0; fail_args: @@ -528,7 +522,7 @@ fail_counters: fail_lockstruct: sysfs_remove_group(&sdp->sd_kobj, &lockstruct_group); fail_reg: - kobject_unregister(&sdp->sd_kobj); + kobject_put(&sdp->sd_kobj); fail: fs_err(sdp, "error %d adding sysfs files", error); return error; @@ -540,21 +534,22 @@ void gfs2_sys_fs_del(struct gfs2_sbd *sdp) sysfs_remove_group(&sdp->sd_kobj, &args_group); sysfs_remove_group(&sdp->sd_kobj, &counters_group); sysfs_remove_group(&sdp->sd_kobj, &lockstruct_group); - kobject_unregister(&sdp->sd_kobj); + kobject_put(&sdp->sd_kobj); } int gfs2_sys_init(void) { gfs2_sys_margs = NULL; spin_lock_init(&gfs2_sys_margs_lock); - kobject_set_name(&gfs2_kset.kobj, "gfs2"); - kobj_set_kset_s(&gfs2_kset, fs_subsys); - return kset_register(&gfs2_kset); + gfs2_kset = kset_create_and_add("gfs2", NULL, fs_kobj); + if (!gfs2_kset) + return -ENOMEM; + return 0; } void gfs2_sys_uninit(void) { kfree(gfs2_sys_margs); - kset_unregister(&gfs2_kset); + kset_unregister(gfs2_kset); } diff --git a/fs/namespace.c b/fs/namespace.c index 06083885b21..61bf376e29e 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -41,8 +41,8 @@ static struct kmem_cache *mnt_cache __read_mostly; static struct rw_semaphore namespace_sem; /* /sys/fs */ -decl_subsys(fs, NULL, NULL); -EXPORT_SYMBOL_GPL(fs_subsys); +struct kobject *fs_kobj; +EXPORT_SYMBOL_GPL(fs_kobj); static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) { @@ -1861,10 +1861,9 @@ void __init mnt_init(void) if (err) printk(KERN_WARNING "%s: sysfs_init error: %d\n", __FUNCTION__, err); - err = subsystem_register(&fs_subsys); - if (err) - printk(KERN_WARNING "%s: subsystem_register error: %d\n", - __FUNCTION__, err); + fs_kobj = kobject_create_and_add("fs", NULL); + if (!fs_kobj) + printk(KERN_WARNING "%s: kobj create error\n", __FUNCTION__); init_rootfs(); init_mount_tree(); } diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index a4882c8df94..23c732f2752 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -146,7 +146,7 @@ static struct kset mlog_kset = { .kobj = {.ktype = &mlog_ktype}, }; -int mlog_sys_init(struct kset *o2cb_subsys) +int mlog_sys_init(struct kset *o2cb_kset) { int i = 0; @@ -157,7 +157,7 @@ int mlog_sys_init(struct kset *o2cb_subsys) mlog_attr_ptrs[i] = NULL; kobject_set_name(&mlog_kset.kobj, "logmask"); - kobj_set_kset_s(&mlog_kset, *o2cb_subsys); + mlog_kset.kobj.kset = o2cb_kset; return kset_register(&mlog_kset); } diff --git a/fs/ocfs2/cluster/sys.c b/fs/ocfs2/cluster/sys.c index 64f6f378fd0..a4b07730b2e 100644 --- a/fs/ocfs2/cluster/sys.c +++ b/fs/ocfs2/cluster/sys.c @@ -28,96 +28,55 @@ #include <linux/module.h> #include <linux/kobject.h> #include <linux/sysfs.h> +#include <linux/fs.h> #include "ocfs2_nodemanager.h" #include "masklog.h" #include "sys.h" -struct o2cb_attribute { - struct attribute attr; - ssize_t (*show)(char *buf); - ssize_t (*store)(const char *buf, size_t count); -}; - -#define O2CB_ATTR(_name, _mode, _show, _store) \ -struct o2cb_attribute o2cb_attr_##_name = __ATTR(_name, _mode, _show, _store) - -#define to_o2cb_attr(_attr) container_of(_attr, struct o2cb_attribute, attr) -static ssize_t o2cb_interface_revision_show(char *buf) +static ssize_t version_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) { return snprintf(buf, PAGE_SIZE, "%u\n", O2NM_API_VERSION); } - -static O2CB_ATTR(interface_revision, S_IFREG | S_IRUGO, o2cb_interface_revision_show, NULL); +static struct kobj_attribute attr_version = + __ATTR(interface_revision, S_IFREG | S_IRUGO, version_show, NULL); static struct attribute *o2cb_attrs[] = { - &o2cb_attr_interface_revision.attr, + &attr_version.attr, NULL, }; -static ssize_t -o2cb_show(struct kobject * kobj, struct attribute * attr, char * buffer); -static ssize_t -o2cb_store(struct kobject * kobj, struct attribute * attr, - const char * buffer, size_t count); -static struct sysfs_ops o2cb_sysfs_ops = { - .show = o2cb_show, - .store = o2cb_store, +static struct attribute_group o2cb_attr_group = { + .attrs = o2cb_attrs, }; -static struct kobj_type o2cb_subsys_type = { - .default_attrs = o2cb_attrs, - .sysfs_ops = &o2cb_sysfs_ops, -}; - -/* gives us o2cb_subsys */ -static decl_subsys(o2cb, NULL, NULL); - -static ssize_t -o2cb_show(struct kobject * kobj, struct attribute * attr, char * buffer) -{ - struct o2cb_attribute *o2cb_attr = to_o2cb_attr(attr); - struct kset *sbs = to_kset(kobj); - - BUG_ON(sbs != &o2cb_subsys); - - if (o2cb_attr->show) - return o2cb_attr->show(buffer); - return -EIO; -} - -static ssize_t -o2cb_store(struct kobject * kobj, struct attribute * attr, - const char * buffer, size_t count) -{ - struct o2cb_attribute *o2cb_attr = to_o2cb_attr(attr); - struct kset *sbs = to_kset(kobj); - - BUG_ON(sbs != &o2cb_subsys); - - if (o2cb_attr->store) - return o2cb_attr->store(buffer, count); - return -EIO; -} +static struct kset *o2cb_kset; void o2cb_sys_shutdown(void) { mlog_sys_shutdown(); - subsystem_unregister(&o2cb_subsys); + kset_unregister(o2cb_kset); } int o2cb_sys_init(void) { int ret; - o2cb_subsys.kobj.ktype = &o2cb_subsys_type; - ret = subsystem_register(&o2cb_subsys); + o2cb_kset = kset_create_and_add("o2cb", NULL, fs_kobj); + if (!o2cb_kset) + return -ENOMEM; + + ret = sysfs_create_group(&o2cb_kset->kobj, &o2cb_attr_group); if (ret) - return ret; + goto error; - ret = mlog_sys_init(&o2cb_subsys); + ret = mlog_sys_init(o2cb_kset); if (ret) - subsystem_unregister(&o2cb_subsys); + goto error; + return 0; +error: + kset_unregister(o2cb_kset); return ret; } diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 722e12e5acc..739da701ae7 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c @@ -195,96 +195,45 @@ check_partition(struct gendisk *hd, struct block_device *bdev) return ERR_PTR(res); } -/* - * sysfs bindings for partitions - */ - -struct part_attribute { - struct attribute attr; - ssize_t (*show)(struct hd_struct *,char *); - ssize_t (*store)(struct hd_struct *,const char *, size_t); -}; - -static ssize_t -part_attr_show(struct kobject * kobj, struct attribute * attr, char * page) +static ssize_t part_start_show(struct device *dev, + struct device_attribute *attr, char *buf) { - struct hd_struct * p = container_of(kobj,struct hd_struct,kobj); - struct part_attribute * part_attr = container_of(attr,struct part_attribute,attr); - ssize_t ret = 0; - if (part_attr->show) - ret = part_attr->show(p, page); - return ret; -} -static ssize_t -part_attr_store(struct kobject * kobj, struct attribute * attr, - const char *page, size_t count) -{ - struct hd_struct * p = container_of(kobj,struct hd_struct,kobj); - struct part_attribute * part_attr = container_of(attr,struct part_attribute,attr); - ssize_t ret = 0; + struct hd_struct *p = dev_to_part(dev); - if (part_attr->store) - ret = part_attr->store(p, page, count); - return ret; + return sprintf(buf, "%llu\n",(unsigned long long)p->start_sect); } -static struct sysfs_ops part_sysfs_ops = { - .show = part_attr_show, - .store = part_attr_store, -}; - -static ssize_t part_uevent_store(struct hd_struct * p, - const char *page, size_t count) +static ssize_t part_size_show(struct device *dev, + struct device_attribute *attr, char *buf) { - kobject_uevent(&p->kobj, KOBJ_ADD); - return count; + struct hd_struct *p = dev_to_part(dev); + return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects); } -static ssize_t part_dev_read(struct hd_struct * p, char *page) -{ - struct gendisk *disk = container_of(p->kobj.parent,struct gendisk,kobj); - dev_t dev = MKDEV(disk->major, disk->first_minor + p->partno); - return print_dev_t(page, dev); -} -static ssize_t part_start_read(struct hd_struct * p, char *page) -{ - return sprintf(page, "%llu\n",(unsigned long long)p->start_sect); -} -static ssize_t part_size_read(struct hd_struct * p, char *page) -{ - return sprintf(page, "%llu\n",(unsigned long long)p->nr_sects); -} -static ssize_t part_stat_read(struct hd_struct * p, char *page) + +static ssize_t part_stat_show(struct device *dev, + struct device_attribute *attr, char *buf) { - return sprintf(page, "%8u %8llu %8u %8llu\n", + struct hd_struct *p = dev_to_part(dev); + + return sprintf(buf, "%8u %8llu %8u %8llu\n", p->ios[0], (unsigned long long)p->sectors[0], p->ios[1], (unsigned long long)p->sectors[1]); } -static struct part_attribute part_attr_uevent = { - .attr = {.name = "uevent", .mode = S_IWUSR }, - .store = part_uevent_store -}; -static struct part_attribute part_attr_dev = { - .attr = {.name = "dev", .mode = S_IRUGO }, - .show = part_dev_read -}; -static struct part_attribute part_attr_start = { - .attr = {.name = "start", .mode = S_IRUGO }, - .show = part_start_read -}; -static struct part_attribute part_attr_size = { - .attr = {.name = "size", .mode = S_IRUGO }, - .show = part_size_read -}; -static struct part_attribute part_attr_stat = { - .attr = {.name = "stat", .mode = S_IRUGO }, - .show = part_stat_read -}; #ifdef CONFIG_FAIL_MAKE_REQUEST +static ssize_t part_fail_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hd_struct *p = dev_to_part(dev); -static ssize_t part_fail_store(struct hd_struct * p, + return sprintf(buf, "%d\n", p->make_it_fail); +} + +static ssize_t part_fail_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { + struct hd_struct *p = dev_to_part(dev); int i; if (count > 0 && sscanf(buf, "%d", &i) > 0) @@ -292,50 +241,53 @@ static ssize_t part_fail_store(struct hd_struct * p, return count; } -static ssize_t part_fail_read(struct hd_struct * p, char *page) -{ - return sprintf(page, "%d\n", p->make_it_fail); -} -static struct part_attribute part_attr_fail = { - .attr = {.name = "make-it-fail", .mode = S_IRUGO | S_IWUSR }, - .store = part_fail_store, - .show = part_fail_read -}; +#endif +static DEVICE_ATTR(start, S_IRUGO, part_start_show, NULL); +static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL); +static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL); +#ifdef CONFIG_FAIL_MAKE_REQUEST +static struct device_attribute dev_attr_fail = + __ATTR(make-it-fail, S_IRUGO|S_IWUSR, part_fail_show, part_fail_store); #endif -static struct attribute * default_attrs[] = { - &part_attr_uevent.attr, - &part_attr_dev.attr, - &part_attr_start.attr, - &part_attr_size.attr, - &part_attr_stat.attr, +static struct attribute *part_attrs[] = { + &dev_attr_start.attr, + &dev_attr_size.attr, + &dev_attr_stat.attr, #ifdef CONFIG_FAIL_MAKE_REQUEST - &part_attr_fail.attr, + &dev_attr_fail.attr, #endif - NULL, + NULL }; -extern struct kset block_subsys; +static struct attribute_group part_attr_group = { + .attrs = part_attrs, +}; -static void part_release(struct kobject *kobj) +static struct attribute_group *part_attr_groups[] = { + &part_attr_group, + NULL +}; + +static void part_release(struct device *dev) { - struct hd_struct * p = container_of(kobj,struct hd_struct,kobj); + struct hd_struct *p = dev_to_part(dev); kfree(p); } -struct kobj_type ktype_part = { +struct device_type part_type = { + .name = "partition", + .groups = part_attr_groups, .release = part_release, - .default_attrs = default_attrs, - .sysfs_ops = &part_sysfs_ops, }; static inline void partition_sysfs_add_subdir(struct hd_struct *p) { struct kobject *k; - k = kobject_get(&p->kobj); - p->holder_dir = kobject_add_dir(k, "holders"); + k = kobject_get(&p->dev.kobj); + p->holder_dir = kobject_create_and_add("holders", k); kobject_put(k); } @@ -343,15 +295,16 @@ static inline void disk_sysfs_add_subdirs(struct gendisk *disk) { struct kobject *k; - k = kobject_get(&disk->kobj); - disk->holder_dir = kobject_add_dir(k, "holders"); - disk->slave_dir = kobject_add_dir(k, "slaves"); + k = kobject_get(&disk->dev.kobj); + disk->holder_dir = kobject_create_and_add("holders", k); + disk->slave_dir = kobject_create_and_add("slaves", k); kobject_put(k); } void delete_partition(struct gendisk *disk, int part) { struct hd_struct *p = disk->part[part-1]; + if (!p) return; if (!p->nr_sects) @@ -361,113 +314,55 @@ void delete_partition(struct gendisk *disk, int part) p->nr_sects = 0; p->ios[0] = p->ios[1] = 0; p->sectors[0] = p->sectors[1] = 0; - sysfs_remove_link(&p->kobj, "subsystem"); - kobject_unregister(p->holder_dir); - kobject_uevent(&p->kobj, KOBJ_REMOVE); - kobject_del(&p->kobj); - kobject_put(&p->kobj); + kobject_put(p->holder_dir); + device_del(&p->dev); + put_device(&p->dev); } void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len, int flags) { struct hd_struct *p; + int err; p = kzalloc(sizeof(*p), GFP_KERNEL); if (!p) return; - + p->start_sect = start; p->nr_sects = len; p->partno = part; p->policy = disk->policy; - if (isdigit(disk->kobj.k_name[strlen(disk->kobj.k_name)-1])) - kobject_set_name(&p->kobj, "%sp%d", - kobject_name(&disk->kobj), part); + if (isdigit(disk->dev.bus_id[strlen(disk->dev.bus_id)-1])) + snprintf(p->dev.bus_id, BUS_ID_SIZE, + "%sp%d", disk->dev.bus_id, part); else - kobject_set_name(&p->kobj, "%s%d", - kobject_name(&disk->kobj),part); - p->kobj.parent = &disk->kobj; - p->kobj.ktype = &ktype_part; - kobject_init(&p->kobj); - kobject_add(&p->kobj); - if (!disk->part_uevent_suppress) - kobject_uevent(&p->kobj, KOBJ_ADD); - sysfs_create_link(&p->kobj, &block_subsys.kobj, "subsystem"); + snprintf(p->dev.bus_id, BUS_ID_SIZE, + "%s%d", disk->dev.bus_id, part); + + device_initialize(&p->dev); + p->dev.devt = MKDEV(disk->major, disk->first_minor + part); + p->dev.class = &block_class; + p->dev.type = &part_type; + p->dev.parent = &disk->dev; + disk->part[part-1] = p; + + /* delay uevent until 'holders' subdir is created */ + p->dev.uevent_suppress = 1; + device_add(&p->dev); + partition_sysfs_add_subdir(p); + p->dev.uevent_suppress = 0; if (flags & ADDPART_FLAG_WHOLEDISK) { static struct attribute addpartattr = { .name = "whole_disk", .mode = S_IRUSR | S_IRGRP | S_IROTH, }; - - sysfs_create_file(&p->kobj, &addpartattr); + err = sysfs_create_file(&p->dev.kobj, &addpartattr); } - partition_sysfs_add_subdir(p); - disk->part[part-1] = p; -} -static char *make_block_name(struct gendisk *disk) -{ - char *name; - static char *block_str = "block:"; - int size; - char *s; - - size = strlen(block_str) + strlen(disk->disk_name) + 1; - name = kmalloc(size, GFP_KERNEL); - if (!name) - return NULL; - strcpy(name, block_str); - strcat(name, disk->disk_name); - /* ewww... some of these buggers have / in name... */ - s = strchr(name, '/'); - if (s) - *s = '!'; - return name; -} - -static int disk_sysfs_symlinks(struct gendisk *disk) -{ - struct device *target = get_device(disk->driverfs_dev); - int err; - char *disk_name = NULL; - - if (target) { - disk_name = make_block_name(disk); - if (!disk_name) { - err = -ENOMEM; - goto err_out; - } - - err = sysfs_create_link(&disk->kobj, &target->kobj, "device"); - if (err) - goto err_out_disk_name; - - err = sysfs_create_link(&target->kobj, &disk->kobj, disk_name); - if (err) - goto err_out_dev_link; - } - - err = sysfs_create_link(&disk->kobj, &block_subsys.kobj, - "subsystem"); - if (err) - goto err_out_disk_name_lnk; - - kfree(disk_name); - - return 0; - -err_out_disk_name_lnk: - if (target) { - sysfs_remove_link(&target->kobj, disk_name); -err_out_dev_link: - sysfs_remove_link(&disk->kobj, "device"); -err_out_disk_name: - kfree(disk_name); -err_out: - put_device(target); - } - return err; + /* suppress uevent if the disk supresses it */ + if (!disk->dev.uevent_suppress) + kobject_uevent(&p->dev.kobj, KOBJ_ADD); } /* Not exported, helper to add_disk(). */ @@ -479,19 +374,29 @@ void register_disk(struct gendisk *disk) struct hd_struct *p; int err; - kobject_set_name(&disk->kobj, "%s", disk->disk_name); - /* ewww... some of these buggers have / in name... */ - s = strchr(disk->kobj.k_name, '/'); + disk->dev.parent = disk->driverfs_dev; + disk->dev.devt = MKDEV(disk->major, disk->first_minor); + + strlcpy(disk->dev.bus_id, disk->disk_name, KOBJ_NAME_LEN); + /* ewww... some of these buggers have / in the name... */ + s = strchr(disk->dev.bus_id, '/'); if (s) *s = '!'; - if ((err = kobject_add(&disk->kobj))) + + /* delay uevents, until we scanned partition table */ + disk->dev.uevent_suppress = 1; + + if (device_add(&disk->dev)) return; - err = disk_sysfs_symlinks(disk); +#ifndef CONFIG_SYSFS_DEPRECATED + err = sysfs_create_link(block_depr, &disk->dev.kobj, + kobject_name(&disk->dev.kobj)); if (err) { - kobject_del(&disk->kobj); + device_del(&disk->dev); return; } - disk_sysfs_add_subdirs(disk); +#endif + disk_sysfs_add_subdirs(disk); /* No minors to use for partitions */ if (disk->minors == 1) @@ -505,25 +410,23 @@ void register_disk(struct gendisk *disk) if (!bdev) goto exit; - /* scan partition table, but suppress uevents */ bdev->bd_invalidated = 1; - disk->part_uevent_suppress = 1; err = blkdev_get(bdev, FMODE_READ, 0); - disk->part_uevent_suppress = 0; if (err < 0) goto exit; blkdev_put(bdev); exit: - /* announce disk after possible partitions are already created */ - kobject_uevent(&disk->kobj, KOBJ_ADD); + /* announce disk after possible partitions are created */ + disk->dev.uevent_suppress = 0; + kobject_uevent(&disk->dev.kobj, KOBJ_ADD); /* announce possible partitions */ for (i = 1; i < disk->minors; i++) { p = disk->part[i-1]; if (!p || !p->nr_sects) continue; - kobject_uevent(&p->kobj, KOBJ_ADD); + kobject_uevent(&p->dev.kobj, KOBJ_ADD); } } @@ -602,19 +505,11 @@ void del_gendisk(struct gendisk *disk) disk_stat_set_all(disk, 0); disk->stamp = 0; - kobject_uevent(&disk->kobj, KOBJ_REMOVE); - kobject_unregister(disk->holder_dir); - kobject_unregister(disk->slave_dir); - if (disk->driverfs_dev) { - char *disk_name = make_block_name(disk); - sysfs_remove_link(&disk->kobj, "device"); - if (disk_name) { - sysfs_remove_link(&disk->driverfs_dev->kobj, disk_name); - kfree(disk_name); - } - put_device(disk->driverfs_dev); - disk->driverfs_dev = NULL; - } - sysfs_remove_link(&disk->kobj, "subsystem"); - kobject_del(&disk->kobj); + kobject_put(disk->holder_dir); + kobject_put(disk->slave_dir); + disk->driverfs_dev = NULL; +#ifndef CONFIG_SYSFS_DEPRECATED + sysfs_remove_link(block_depr, disk->dev.bus_id); +#endif + device_del(&disk->dev); } diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index f281cc6584b..4948d9bc405 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -440,7 +440,7 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) /** * sysfs_remove_one - remove sysfs_dirent from parent * @acxt: addrm context to use - * @sd: sysfs_dirent to be added + * @sd: sysfs_dirent to be removed * * Mark @sd removed and drop nlink of parent inode if @sd is a * directory. @sd is unlinked from the children list. diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 4045bdcc4b3..8acf82bba44 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -20,43 +20,6 @@ #include "sysfs.h" -#define to_sattr(a) container_of(a,struct subsys_attribute, attr) - -/* - * Subsystem file operations. - * These operations allow subsystems to have files that can be - * read/written. - */ -static ssize_t -subsys_attr_show(struct kobject * kobj, struct attribute * attr, char * page) -{ - struct kset *kset = to_kset(kobj); - struct subsys_attribute * sattr = to_sattr(attr); - ssize_t ret = -EIO; - - if (sattr->show) - ret = sattr->show(kset, page); - return ret; -} - -static ssize_t -subsys_attr_store(struct kobject * kobj, struct attribute * attr, - const char * page, size_t count) -{ - struct kset *kset = to_kset(kobj); - struct subsys_attribute * sattr = to_sattr(attr); - ssize_t ret = -EIO; - - if (sattr->store) - ret = sattr->store(kset, page, count); - return ret; -} - -static struct sysfs_ops subsys_sysfs_ops = { - .show = subsys_attr_show, - .store = subsys_attr_store, -}; - /* * There's one sysfs_buffer for each open file and one * sysfs_open_dirent for each sysfs_dirent with one or more open @@ -66,7 +29,7 @@ static struct sysfs_ops subsys_sysfs_ops = { * sysfs_dirent->s_attr.open points to sysfs_open_dirent. s_attr.open * is protected by sysfs_open_dirent_lock. */ -static spinlock_t sysfs_open_dirent_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(sysfs_open_dirent_lock); struct sysfs_open_dirent { atomic_t refcnt; @@ -354,31 +317,23 @@ static int sysfs_open_file(struct inode *inode, struct file *file) { struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; - struct sysfs_buffer * buffer; - struct sysfs_ops * ops = NULL; - int error; + struct sysfs_buffer *buffer; + struct sysfs_ops *ops; + int error = -EACCES; /* need attr_sd for attr and ops, its parent for kobj */ if (!sysfs_get_active_two(attr_sd)) return -ENODEV; - /* if the kobject has no ktype, then we assume that it is a subsystem - * itself, and use ops for it. - */ - if (kobj->kset && kobj->kset->ktype) - ops = kobj->kset->ktype->sysfs_ops; - else if (kobj->ktype) + /* every kobject with an attribute needs a ktype assigned */ + if (kobj->ktype && kobj->ktype->sysfs_ops) ops = kobj->ktype->sysfs_ops; - else - ops = &subsys_sysfs_ops; - - error = -EACCES; - - /* No sysfs operations, either from having no subsystem, - * or the subsystem have no operations. - */ - if (!ops) + else { + printk(KERN_ERR "missing sysfs attribute operations for " + "kobject: %s\n", kobject_name(kobj)); + WARN_ON(1); goto err_out; + } /* File needs write support. * The inode's perms must say it's ok, diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index 3eac20c63c4..5f66c446615 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c @@ -19,39 +19,6 @@ #include "sysfs.h" -static int object_depth(struct sysfs_dirent *sd) -{ - int depth = 0; - - for (; sd->s_parent; sd = sd->s_parent) - depth++; - - return depth; -} - -static int object_path_length(struct sysfs_dirent * sd) -{ - int length = 1; - - for (; sd->s_parent; sd = sd->s_parent) - length += strlen(sd->s_name) + 1; - - return length; -} - -static void fill_object_path(struct sysfs_dirent *sd, char *buffer, int length) -{ - --length; - for (; sd->s_parent; sd = sd->s_parent) { - int cur = strlen(sd->s_name); - - /* back up enough to print this bus id with '/' */ - length -= cur; - strncpy(buffer + length, sd->s_name, cur); - *(buffer + --length) = '/'; - } -} - /** * sysfs_create_link - create symlink between two objects. * @kobj: object whose directory we're creating the link in. @@ -112,7 +79,6 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char return error; } - /** * sysfs_remove_link - remove symlink in object's directory. * @kobj: object we're acting for. @@ -124,24 +90,54 @@ void sysfs_remove_link(struct kobject * kobj, const char * name) sysfs_hash_and_remove(kobj->sd, name); } -static int sysfs_get_target_path(struct sysfs_dirent * parent_sd, - struct sysfs_dirent * target_sd, char *path) +static int sysfs_get_target_path(struct sysfs_dirent *parent_sd, + struct sysfs_dirent *target_sd, char *path) { - char * s; - int depth, size; + struct sysfs_dirent *base, *sd; + char *s = path; + int len = 0; + + /* go up to the root, stop at the base */ + base = parent_sd; + while (base->s_parent) { + sd = target_sd->s_parent; + while (sd->s_parent && base != sd) + sd = sd->s_parent; + + if (base == sd) + break; + + strcpy(s, "../"); + s += 3; + base = base->s_parent; + } + + /* determine end of target string for reverse fillup */ + sd = target_sd; + while (sd->s_parent && sd != base) { + len += strlen(sd->s_name) + 1; + sd = sd->s_parent; + } - depth = object_depth(parent_sd); - size = object_path_length(target_sd) + depth * 3 - 1; - if (size > PATH_MAX) + /* check limits */ + if (len < 2) + return -EINVAL; + len--; + if ((s - path) + len > PATH_MAX) return -ENAMETOOLONG; - pr_debug("%s: depth = %d, size = %d\n", __FUNCTION__, depth, size); + /* reverse fillup of target string from target to base */ + sd = target_sd; + while (sd->s_parent && sd != base) { + int slen = strlen(sd->s_name); - for (s = path; depth--; s += 3) - strcpy(s,"../"); + len -= slen; + strncpy(s + len, sd->s_name, slen); + if (len) + s[--len] = '/'; - fill_object_path(target_sd, path, size); - pr_debug("%s: path = '%s'\n", __FUNCTION__, path); + sd = sd->s_parent; + } return 0; } |