aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/debugfs/file.c42
-rw-r--r--fs/namei.c72
-rw-r--r--fs/super.c12
-rw-r--r--fs/sysfs/bin.c2
-rw-r--r--fs/sysfs/file.c14
-rw-r--r--fs/sysfs/group.c6
6 files changed, 110 insertions, 38 deletions
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 682f928b7f4d..2e124e0075c5 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -179,6 +179,48 @@ struct dentry *debugfs_create_u32(const char *name, mode_t mode,
179} 179}
180EXPORT_SYMBOL_GPL(debugfs_create_u32); 180EXPORT_SYMBOL_GPL(debugfs_create_u32);
181 181
182static void debugfs_u64_set(void *data, u64 val)
183{
184 *(u64 *)data = val;
185}
186
187static u64 debugfs_u64_get(void *data)
188{
189 return *(u64 *)data;
190}
191DEFINE_SIMPLE_ATTRIBUTE(fops_u64, debugfs_u64_get, debugfs_u64_set, "%llu\n");
192
193/**
194 * debugfs_create_u64 - create a debugfs file that is used to read and write an unsigned 64-bit value
195 * @name: a pointer to a string containing the name of the file to create.
196 * @mode: the permission that the file should have
197 * @parent: a pointer to the parent dentry for this file. This should be a
198 * directory dentry if set. If this parameter is %NULL, then the
199 * file will be created in the root of the debugfs filesystem.
200 * @value: a pointer to the variable that the file should read to and write
201 * from.
202 *
203 * This function creates a file in debugfs with the given name that
204 * contains the value of the variable @value. If the @mode variable is so
205 * set, it can be read from, and written to.
206 *
207 * This function will return a pointer to a dentry if it succeeds. This
208 * pointer must be passed to the debugfs_remove() function when the file is
209 * to be removed (no automatic cleanup happens if your module is unloaded,
210 * you are responsible here.) If an error occurs, %NULL will be returned.
211 *
212 * If debugfs is not enabled in the kernel, the value -%ENODEV will be
213 * returned. It is not wise to check for this value, but rather, check for
214 * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
215 * code.
216 */
217struct dentry *debugfs_create_u64(const char *name, mode_t mode,
218 struct dentry *parent, u64 *value)
219{
220 return debugfs_create_file(name, mode, parent, value, &fops_u64);
221}
222EXPORT_SYMBOL_GPL(debugfs_create_u64);
223
182static ssize_t read_file_bool(struct file *file, char __user *user_buf, 224static ssize_t read_file_bool(struct file *file, char __user *user_buf,
183 size_t count, loff_t *ppos) 225 size_t count, loff_t *ppos)
184{ 226{
diff --git a/fs/namei.c b/fs/namei.c
index ee60cc4d3453..880052cadbcd 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1243,22 +1243,13 @@ int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags,
1243 return err; 1243 return err;
1244} 1244}
1245 1245
1246/* 1246static inline struct dentry *__lookup_hash_kern(struct qstr *name, struct dentry *base, struct nameidata *nd)
1247 * Restricted form of lookup. Doesn't follow links, single-component only,
1248 * needs parent already locked. Doesn't follow mounts.
1249 * SMP-safe.
1250 */
1251static struct dentry * __lookup_hash(struct qstr *name, struct dentry * base, struct nameidata *nd)
1252{ 1247{
1253 struct dentry * dentry; 1248 struct dentry *dentry;
1254 struct inode *inode; 1249 struct inode *inode;
1255 int err; 1250 int err;
1256 1251
1257 inode = base->d_inode; 1252 inode = base->d_inode;
1258 err = permission(inode, MAY_EXEC, nd);
1259 dentry = ERR_PTR(err);
1260 if (err)
1261 goto out;
1262 1253
1263 /* 1254 /*
1264 * See if the low-level filesystem might want 1255 * See if the low-level filesystem might want
@@ -1287,35 +1278,76 @@ out:
1287 return dentry; 1278 return dentry;
1288} 1279}
1289 1280
1281/*
1282 * Restricted form of lookup. Doesn't follow links, single-component only,
1283 * needs parent already locked. Doesn't follow mounts.
1284 * SMP-safe.
1285 */
1286static inline struct dentry * __lookup_hash(struct qstr *name, struct dentry *base, struct nameidata *nd)
1287{
1288 struct dentry *dentry;
1289 struct inode *inode;
1290 int err;
1291
1292 inode = base->d_inode;
1293
1294 err = permission(inode, MAY_EXEC, nd);
1295 dentry = ERR_PTR(err);
1296 if (err)
1297 goto out;
1298
1299 dentry = __lookup_hash_kern(name, base, nd);
1300out:
1301 return dentry;
1302}
1303
1290static struct dentry *lookup_hash(struct nameidata *nd) 1304static struct dentry *lookup_hash(struct nameidata *nd)
1291{ 1305{
1292 return __lookup_hash(&nd->last, nd->dentry, nd); 1306 return __lookup_hash(&nd->last, nd->dentry, nd);
1293} 1307}
1294 1308
1295/* SMP-safe */ 1309/* SMP-safe */
1296struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) 1310static inline int __lookup_one_len(const char *name, struct qstr *this, struct dentry *base, int len)
1297{ 1311{
1298 unsigned long hash; 1312 unsigned long hash;
1299 struct qstr this;
1300 unsigned int c; 1313 unsigned int c;
1301 1314
1302 this.name = name; 1315 this->name = name;
1303 this.len = len; 1316 this->len = len;
1304 if (!len) 1317 if (!len)
1305 goto access; 1318 return -EACCES;
1306 1319
1307 hash = init_name_hash(); 1320 hash = init_name_hash();
1308 while (len--) { 1321 while (len--) {
1309 c = *(const unsigned char *)name++; 1322 c = *(const unsigned char *)name++;
1310 if (c == '/' || c == '\0') 1323 if (c == '/' || c == '\0')
1311 goto access; 1324 return -EACCES;
1312 hash = partial_name_hash(c, hash); 1325 hash = partial_name_hash(c, hash);
1313 } 1326 }
1314 this.hash = end_name_hash(hash); 1327 this->hash = end_name_hash(hash);
1328 return 0;
1329}
1315 1330
1331struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
1332{
1333 int err;
1334 struct qstr this;
1335
1336 err = __lookup_one_len(name, &this, base, len);
1337 if (err)
1338 return ERR_PTR(err);
1316 return __lookup_hash(&this, base, NULL); 1339 return __lookup_hash(&this, base, NULL);
1317access: 1340}
1318 return ERR_PTR(-EACCES); 1341
1342struct dentry *lookup_one_len_kern(const char *name, struct dentry *base, int len)
1343{
1344 int err;
1345 struct qstr this;
1346
1347 err = __lookup_one_len(name, &this, base, len);
1348 if (err)
1349 return ERR_PTR(err);
1350 return __lookup_hash_kern(&this, base, NULL);
1319} 1351}
1320 1352
1321/* 1353/*
diff --git a/fs/super.c b/fs/super.c
index 60b1e50cbf53..8341e4e1d738 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -725,16 +725,6 @@ static int test_bdev_super(struct super_block *s, void *data)
725 return (void *)s->s_bdev == data; 725 return (void *)s->s_bdev == data;
726} 726}
727 727
728static void bdev_uevent(struct block_device *bdev, enum kobject_action action)
729{
730 if (bdev->bd_disk) {
731 if (bdev->bd_part)
732 kobject_uevent(&bdev->bd_part->kobj, action);
733 else
734 kobject_uevent(&bdev->bd_disk->kobj, action);
735 }
736}
737
738int get_sb_bdev(struct file_system_type *fs_type, 728int get_sb_bdev(struct file_system_type *fs_type,
739 int flags, const char *dev_name, void *data, 729 int flags, const char *dev_name, void *data,
740 int (*fill_super)(struct super_block *, void *, int), 730 int (*fill_super)(struct super_block *, void *, int),
@@ -782,7 +772,6 @@ int get_sb_bdev(struct file_system_type *fs_type,
782 } 772 }
783 773
784 s->s_flags |= MS_ACTIVE; 774 s->s_flags |= MS_ACTIVE;
785 bdev_uevent(bdev, KOBJ_MOUNT);
786 } 775 }
787 776
788 return simple_set_mnt(mnt, s); 777 return simple_set_mnt(mnt, s);
@@ -801,7 +790,6 @@ void kill_block_super(struct super_block *sb)
801{ 790{
802 struct block_device *bdev = sb->s_bdev; 791 struct block_device *bdev = sb->s_bdev;
803 792
804 bdev_uevent(bdev, KOBJ_UMOUNT);
805 generic_shutdown_super(sb); 793 generic_shutdown_super(sb);
806 sync_blockdev(bdev); 794 sync_blockdev(bdev);
807 close_bdev_excl(bdev); 795 close_bdev_excl(bdev);
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index d3b9f5f07db1..8ea2a51ce883 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -59,7 +59,7 @@ read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
59 if (copy_to_user(userbuf, buffer, count)) 59 if (copy_to_user(userbuf, buffer, count))
60 return -EFAULT; 60 return -EFAULT;
61 61
62 pr_debug("offs = %lld, *off = %lld, count = %zd\n", offs, *off, count); 62 pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count);
63 63
64 *off = offs + count; 64 *off = offs + count;
65 65
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index fc4633378dc0..db0413a411d6 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -633,6 +633,7 @@ struct sysfs_schedule_callback_struct {
633 struct kobject *kobj; 633 struct kobject *kobj;
634 void (*func)(void *); 634 void (*func)(void *);
635 void *data; 635 void *data;
636 struct module *owner;
636 struct work_struct work; 637 struct work_struct work;
637}; 638};
638 639
@@ -643,6 +644,7 @@ static void sysfs_schedule_callback_work(struct work_struct *work)
643 644
644 (ss->func)(ss->data); 645 (ss->func)(ss->data);
645 kobject_put(ss->kobj); 646 kobject_put(ss->kobj);
647 module_put(ss->owner);
646 kfree(ss); 648 kfree(ss);
647} 649}
648 650
@@ -651,6 +653,7 @@ static void sysfs_schedule_callback_work(struct work_struct *work)
651 * @kobj: object we're acting for. 653 * @kobj: object we're acting for.
652 * @func: callback function to invoke later. 654 * @func: callback function to invoke later.
653 * @data: argument to pass to @func. 655 * @data: argument to pass to @func.
656 * @owner: module owning the callback code
654 * 657 *
655 * sysfs attribute methods must not unregister themselves or their parent 658 * sysfs attribute methods must not unregister themselves or their parent
656 * kobject (which would amount to the same thing). Attempts to do so will 659 * kobject (which would amount to the same thing). Attempts to do so will
@@ -663,20 +666,25 @@ static void sysfs_schedule_callback_work(struct work_struct *work)
663 * until @func returns. 666 * until @func returns.
664 * 667 *
665 * Returns 0 if the request was submitted, -ENOMEM if storage could not 668 * Returns 0 if the request was submitted, -ENOMEM if storage could not
666 * be allocated. 669 * be allocated, -ENODEV if a reference to @owner isn't available.
667 */ 670 */
668int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), 671int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
669 void *data) 672 void *data, struct module *owner)
670{ 673{
671 struct sysfs_schedule_callback_struct *ss; 674 struct sysfs_schedule_callback_struct *ss;
672 675
676 if (!try_module_get(owner))
677 return -ENODEV;
673 ss = kmalloc(sizeof(*ss), GFP_KERNEL); 678 ss = kmalloc(sizeof(*ss), GFP_KERNEL);
674 if (!ss) 679 if (!ss) {
680 module_put(owner);
675 return -ENOMEM; 681 return -ENOMEM;
682 }
676 kobject_get(kobj); 683 kobject_get(kobj);
677 ss->kobj = kobj; 684 ss->kobj = kobj;
678 ss->func = func; 685 ss->func = func;
679 ss->data = data; 686 ss->data = data;
687 ss->owner = owner;
680 INIT_WORK(&ss->work, sysfs_schedule_callback_work); 688 INIT_WORK(&ss->work, sysfs_schedule_callback_work);
681 schedule_work(&ss->work); 689 schedule_work(&ss->work);
682 return 0; 690 return 0;
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index b20951c93761..52eed2a7a5ef 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -70,9 +70,11 @@ void sysfs_remove_group(struct kobject * kobj,
70{ 70{
71 struct dentry * dir; 71 struct dentry * dir;
72 72
73 if (grp->name) 73 if (grp->name) {
74 dir = lookup_one_len(grp->name, kobj->dentry, 74 dir = lookup_one_len_kern(grp->name, kobj->dentry,
75 strlen(grp->name)); 75 strlen(grp->name));
76 BUG_ON(IS_ERR(dir));
77 }
76 else 78 else
77 dir = dget(kobj->dentry); 79 dir = dget(kobj->dentry);
78 80