diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-23 15:27:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-23 15:27:27 -0400 |
commit | a66d2c8f7ec1284206ca7c14569e2a607583f1e3 (patch) | |
tree | 08cf68bcef3559b370843cab8191e5cc0f740bde /fs/debugfs/inode.c | |
parent | a6be1fcbc57f95bb47ef3c8e4ee3d83731b8f21e (diff) | |
parent | 8cae6f7158ec1fa44c8a04a43db7d8020ec60437 (diff) |
Merge branch 'for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull the big VFS changes from Al Viro:
"This one is *big* and changes quite a few things around VFS. What's in there:
- the first of two really major architecture changes - death to open
intents.
The former is finally there; it was very long in making, but with
Miklos getting through really hard and messy final push in
fs/namei.c, we finally have it. Unlike his variant, this one
doesn't introduce struct opendata; what we have instead is
->atomic_open() taking preallocated struct file * and passing
everything via its fields.
Instead of returning struct file *, it returns -E... on error, 0
on success and 1 in "deal with it yourself" case (e.g. symlink
found on server, etc.).
See comments before fs/namei.c:atomic_open(). That made a lot of
goodies finally possible and quite a few are in that pile:
->lookup(), ->d_revalidate() and ->create() do not get struct
nameidata * anymore; ->lookup() and ->d_revalidate() get lookup
flags instead, ->create() gets "do we want it exclusive" flag.
With the introduction of new helper (kern_path_locked()) we are rid
of all struct nameidata instances outside of fs/namei.c; it's still
visible in namei.h, but not for long. Come the next cycle,
declaration will move either to fs/internal.h or to fs/namei.c
itself. [me, miklos, hch]
- The second major change: behaviour of final fput(). Now we have
__fput() done without any locks held by caller *and* not from deep
in call stack.
That obviously lifts a lot of constraints on the locking in there.
Moreover, it's legal now to call fput() from atomic contexts (which
has immediately simplified life for aio.c). We also don't need
anti-recursion logics in __scm_destroy() anymore.
There is a price, though - the damn thing has become partially
asynchronous. For fput() from normal process we are guaranteed
that pending __fput() will be done before the caller returns to
userland, exits or gets stopped for ptrace.
For kernel threads and atomic contexts it's done via
schedule_work(), so theoretically we might need a way to make sure
it's finished; so far only one such place had been found, but there
might be more.
There's flush_delayed_fput() (do all pending __fput()) and there's
__fput_sync() (fput() analog doing __fput() immediately). I hope
we won't need them often; see warnings in fs/file_table.c for
details. [me, based on task_work series from Oleg merged last
cycle]
- sync series from Jan
- large part of "death to sync_supers()" work from Artem; the only
bits missing here are exofs and ext4 ones. As far as I understand,
those are going via the exofs and ext4 trees resp.; once they are
in, we can put ->write_super() to the rest, along with the thread
calling it.
- preparatory bits from unionmount series (from dhowells).
- assorted cleanups and fixes all over the place, as usual.
This is not the last pile for this cycle; there's at least jlayton's
ESTALE work and fsfreeze series (the latter - in dire need of fixes,
so I'm not sure it'll make the cut this cycle). I'll probably throw
symlink/hardlink restrictions stuff from Kees into the next pile, too.
Plus there's a lot of misc patches I hadn't thrown into that one -
it's large enough as it is..."
* 'for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (127 commits)
ext4: switch EXT4_IOC_RESIZE_FS to mnt_want_write_file()
btrfs: switch btrfs_ioctl_balance() to mnt_want_write_file()
switch dentry_open() to struct path, make it grab references itself
spufs: shift dget/mntget towards dentry_open()
zoran: don't bother with struct file * in zoran_map
ecryptfs: don't reinvent the wheels, please - use struct completion
don't expose I_NEW inodes via dentry->d_inode
tidy up namei.c a bit
unobfuscate follow_up() a bit
ext3: pass custom EOF to generic_file_llseek_size()
ext4: use core vfs llseek code for dir seeks
vfs: allow custom EOF in generic_file_llseek code
vfs: Avoid unnecessary WB_SYNC_NONE writeback during sys_sync and reorder sync passes
vfs: Remove unnecessary flushing of block devices
vfs: Make sys_sync writeout also block device inodes
vfs: Create function for iterating over block devices
vfs: Reorder operations during sys_sync
quota: Move quota syncing to ->sync_fs method
quota: Split dquot_quota_sync() to writeback and cache flushing part
vfs: Move noop_backing_dev_info check from sync into writeback
...
Diffstat (limited to 'fs/debugfs/inode.c')
-rw-r--r-- | fs/debugfs/inode.c | 91 |
1 files changed, 44 insertions, 47 deletions
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index b80bc846a15a..d17c20fd74e6 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
@@ -54,13 +54,12 @@ static struct inode *debugfs_get_inode(struct super_block *sb, umode_t mode, dev | |||
54 | break; | 54 | break; |
55 | case S_IFLNK: | 55 | case S_IFLNK: |
56 | inode->i_op = &debugfs_link_operations; | 56 | inode->i_op = &debugfs_link_operations; |
57 | inode->i_fop = fops; | ||
58 | inode->i_private = data; | 57 | inode->i_private = data; |
59 | break; | 58 | break; |
60 | case S_IFDIR: | 59 | case S_IFDIR: |
61 | inode->i_op = &simple_dir_inode_operations; | 60 | inode->i_op = &simple_dir_inode_operations; |
62 | inode->i_fop = fops ? fops : &simple_dir_operations; | 61 | inode->i_fop = &simple_dir_operations; |
63 | inode->i_private = data; | 62 | inode->i_private = NULL; |
64 | 63 | ||
65 | /* directory inodes start off with i_nlink == 2 | 64 | /* directory inodes start off with i_nlink == 2 |
66 | * (for "." entry) */ | 65 | * (for "." entry) */ |
@@ -91,13 +90,12 @@ static int debugfs_mknod(struct inode *dir, struct dentry *dentry, | |||
91 | return error; | 90 | return error; |
92 | } | 91 | } |
93 | 92 | ||
94 | static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode, | 93 | static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) |
95 | void *data, const struct file_operations *fops) | ||
96 | { | 94 | { |
97 | int res; | 95 | int res; |
98 | 96 | ||
99 | mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; | 97 | mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR; |
100 | res = debugfs_mknod(dir, dentry, mode, 0, data, fops); | 98 | res = debugfs_mknod(dir, dentry, mode, 0, NULL, NULL); |
101 | if (!res) { | 99 | if (!res) { |
102 | inc_nlink(dir); | 100 | inc_nlink(dir); |
103 | fsnotify_mkdir(dir, dentry); | 101 | fsnotify_mkdir(dir, dentry); |
@@ -106,10 +104,10 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
106 | } | 104 | } |
107 | 105 | ||
108 | static int debugfs_link(struct inode *dir, struct dentry *dentry, umode_t mode, | 106 | static int debugfs_link(struct inode *dir, struct dentry *dentry, umode_t mode, |
109 | void *data, const struct file_operations *fops) | 107 | void *data) |
110 | { | 108 | { |
111 | mode = (mode & S_IALLUGO) | S_IFLNK; | 109 | mode = (mode & S_IALLUGO) | S_IFLNK; |
112 | return debugfs_mknod(dir, dentry, mode, 0, data, fops); | 110 | return debugfs_mknod(dir, dentry, mode, 0, data, NULL); |
113 | } | 111 | } |
114 | 112 | ||
115 | static int debugfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 113 | static int debugfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
@@ -293,13 +291,19 @@ static struct file_system_type debug_fs_type = { | |||
293 | .kill_sb = kill_litter_super, | 291 | .kill_sb = kill_litter_super, |
294 | }; | 292 | }; |
295 | 293 | ||
296 | static int debugfs_create_by_name(const char *name, umode_t mode, | 294 | struct dentry *__create_file(const char *name, umode_t mode, |
297 | struct dentry *parent, | 295 | struct dentry *parent, void *data, |
298 | struct dentry **dentry, | 296 | const struct file_operations *fops) |
299 | void *data, | ||
300 | const struct file_operations *fops) | ||
301 | { | 297 | { |
302 | int error = 0; | 298 | struct dentry *dentry = NULL; |
299 | int error; | ||
300 | |||
301 | pr_debug("debugfs: creating file '%s'\n",name); | ||
302 | |||
303 | error = simple_pin_fs(&debug_fs_type, &debugfs_mount, | ||
304 | &debugfs_mount_count); | ||
305 | if (error) | ||
306 | goto exit; | ||
303 | 307 | ||
304 | /* If the parent is not specified, we create it in the root. | 308 | /* If the parent is not specified, we create it in the root. |
305 | * We need the root dentry to do this, which is in the super | 309 | * We need the root dentry to do this, which is in the super |
@@ -309,30 +313,35 @@ static int debugfs_create_by_name(const char *name, umode_t mode, | |||
309 | if (!parent) | 313 | if (!parent) |
310 | parent = debugfs_mount->mnt_root; | 314 | parent = debugfs_mount->mnt_root; |
311 | 315 | ||
312 | *dentry = NULL; | 316 | dentry = NULL; |
313 | mutex_lock(&parent->d_inode->i_mutex); | 317 | mutex_lock(&parent->d_inode->i_mutex); |
314 | *dentry = lookup_one_len(name, parent, strlen(name)); | 318 | dentry = lookup_one_len(name, parent, strlen(name)); |
315 | if (!IS_ERR(*dentry)) { | 319 | if (!IS_ERR(dentry)) { |
316 | switch (mode & S_IFMT) { | 320 | switch (mode & S_IFMT) { |
317 | case S_IFDIR: | 321 | case S_IFDIR: |
318 | error = debugfs_mkdir(parent->d_inode, *dentry, mode, | 322 | error = debugfs_mkdir(parent->d_inode, dentry, mode); |
319 | data, fops); | 323 | |
320 | break; | 324 | break; |
321 | case S_IFLNK: | 325 | case S_IFLNK: |
322 | error = debugfs_link(parent->d_inode, *dentry, mode, | 326 | error = debugfs_link(parent->d_inode, dentry, mode, |
323 | data, fops); | 327 | data); |
324 | break; | 328 | break; |
325 | default: | 329 | default: |
326 | error = debugfs_create(parent->d_inode, *dentry, mode, | 330 | error = debugfs_create(parent->d_inode, dentry, mode, |
327 | data, fops); | 331 | data, fops); |
328 | break; | 332 | break; |
329 | } | 333 | } |
330 | dput(*dentry); | 334 | dput(dentry); |
331 | } else | 335 | } else |
332 | error = PTR_ERR(*dentry); | 336 | error = PTR_ERR(dentry); |
333 | mutex_unlock(&parent->d_inode->i_mutex); | 337 | mutex_unlock(&parent->d_inode->i_mutex); |
334 | 338 | ||
335 | return error; | 339 | if (error) { |
340 | dentry = NULL; | ||
341 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); | ||
342 | } | ||
343 | exit: | ||
344 | return dentry; | ||
336 | } | 345 | } |
337 | 346 | ||
338 | /** | 347 | /** |
@@ -365,25 +374,15 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode, | |||
365 | struct dentry *parent, void *data, | 374 | struct dentry *parent, void *data, |
366 | const struct file_operations *fops) | 375 | const struct file_operations *fops) |
367 | { | 376 | { |
368 | struct dentry *dentry = NULL; | 377 | switch (mode & S_IFMT) { |
369 | int error; | 378 | case S_IFREG: |
370 | 379 | case 0: | |
371 | pr_debug("debugfs: creating file '%s'\n",name); | 380 | break; |
372 | 381 | default: | |
373 | error = simple_pin_fs(&debug_fs_type, &debugfs_mount, | 382 | BUG(); |
374 | &debugfs_mount_count); | ||
375 | if (error) | ||
376 | goto exit; | ||
377 | |||
378 | error = debugfs_create_by_name(name, mode, parent, &dentry, | ||
379 | data, fops); | ||
380 | if (error) { | ||
381 | dentry = NULL; | ||
382 | simple_release_fs(&debugfs_mount, &debugfs_mount_count); | ||
383 | goto exit; | ||
384 | } | 383 | } |
385 | exit: | 384 | |
386 | return dentry; | 385 | return __create_file(name, mode, parent, data, fops); |
387 | } | 386 | } |
388 | EXPORT_SYMBOL_GPL(debugfs_create_file); | 387 | EXPORT_SYMBOL_GPL(debugfs_create_file); |
389 | 388 | ||
@@ -407,8 +406,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_file); | |||
407 | */ | 406 | */ |
408 | struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) | 407 | struct dentry *debugfs_create_dir(const char *name, struct dentry *parent) |
409 | { | 408 | { |
410 | return debugfs_create_file(name, | 409 | return __create_file(name, S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, |
411 | S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, | ||
412 | parent, NULL, NULL); | 410 | parent, NULL, NULL); |
413 | } | 411 | } |
414 | EXPORT_SYMBOL_GPL(debugfs_create_dir); | 412 | EXPORT_SYMBOL_GPL(debugfs_create_dir); |
@@ -446,8 +444,7 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent, | |||
446 | if (!link) | 444 | if (!link) |
447 | return NULL; | 445 | return NULL; |
448 | 446 | ||
449 | result = debugfs_create_file(name, S_IFLNK | S_IRWXUGO, parent, link, | 447 | result = __create_file(name, S_IFLNK | S_IRWXUGO, parent, link, NULL); |
450 | NULL); | ||
451 | if (!result) | 448 | if (!result) |
452 | kfree(link); | 449 | kfree(link); |
453 | return result; | 450 | return result; |