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 | |
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
...
210 files changed, 2607 insertions, 2396 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 8e2da1e06e3b..e0cce2a5f820 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
@@ -9,7 +9,7 @@ be able to use diff(1). | |||
9 | 9 | ||
10 | --------------------------- dentry_operations -------------------------- | 10 | --------------------------- dentry_operations -------------------------- |
11 | prototypes: | 11 | prototypes: |
12 | int (*d_revalidate)(struct dentry *, struct nameidata *); | 12 | int (*d_revalidate)(struct dentry *, unsigned int); |
13 | int (*d_hash)(const struct dentry *, const struct inode *, | 13 | int (*d_hash)(const struct dentry *, const struct inode *, |
14 | struct qstr *); | 14 | struct qstr *); |
15 | int (*d_compare)(const struct dentry *, const struct inode *, | 15 | int (*d_compare)(const struct dentry *, const struct inode *, |
@@ -37,9 +37,8 @@ d_manage: no no yes (ref-walk) maybe | |||
37 | 37 | ||
38 | --------------------------- inode_operations --------------------------- | 38 | --------------------------- inode_operations --------------------------- |
39 | prototypes: | 39 | prototypes: |
40 | int (*create) (struct inode *,struct dentry *,umode_t, struct nameidata *); | 40 | int (*create) (struct inode *,struct dentry *,umode_t, bool); |
41 | struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameid | 41 | struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); |
42 | ata *); | ||
43 | int (*link) (struct dentry *,struct inode *,struct dentry *); | 42 | int (*link) (struct dentry *,struct inode *,struct dentry *); |
44 | int (*unlink) (struct inode *,struct dentry *); | 43 | int (*unlink) (struct inode *,struct dentry *); |
45 | int (*symlink) (struct inode *,struct dentry *,const char *); | 44 | int (*symlink) (struct inode *,struct dentry *,const char *); |
@@ -62,6 +61,9 @@ ata *); | |||
62 | int (*removexattr) (struct dentry *, const char *); | 61 | int (*removexattr) (struct dentry *, const char *); |
63 | int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len); | 62 | int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len); |
64 | void (*update_time)(struct inode *, struct timespec *, int); | 63 | void (*update_time)(struct inode *, struct timespec *, int); |
64 | int (*atomic_open)(struct inode *, struct dentry *, | ||
65 | struct file *, unsigned open_flag, | ||
66 | umode_t create_mode, int *opened); | ||
65 | 67 | ||
66 | locking rules: | 68 | locking rules: |
67 | all may block | 69 | all may block |
@@ -89,6 +91,7 @@ listxattr: no | |||
89 | removexattr: yes | 91 | removexattr: yes |
90 | fiemap: no | 92 | fiemap: no |
91 | update_time: no | 93 | update_time: no |
94 | atomic_open: yes | ||
92 | 95 | ||
93 | Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on | 96 | Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on |
94 | victim. | 97 | victim. |
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index 8c91d1057d9a..2bef2b3843d1 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting | |||
@@ -355,12 +355,10 @@ protects *all* the dcache state of a given dentry. | |||
355 | via rcu-walk path walk (basically, if the file can have had a path name in the | 355 | via rcu-walk path walk (basically, if the file can have had a path name in the |
356 | vfs namespace). | 356 | vfs namespace). |
357 | 357 | ||
358 | i_dentry and i_rcu share storage in a union, and the vfs expects | 358 | Even though i_dentry and i_rcu share storage in a union, we will |
359 | i_dentry to be reinitialized before it is freed, so an: | 359 | initialize the former in inode_init_always(), so just leave it alone in |
360 | 360 | the callback. It used to be necessary to clean it there, but not anymore | |
361 | INIT_LIST_HEAD(&inode->i_dentry); | 361 | (starting at 3.2). |
362 | |||
363 | must be done in the RCU callback. | ||
364 | 362 | ||
365 | -- | 363 | -- |
366 | [recommended] | 364 | [recommended] |
@@ -433,3 +431,14 @@ release it yourself. | |||
433 | d_alloc_root() is gone, along with a lot of bugs caused by code | 431 | d_alloc_root() is gone, along with a lot of bugs caused by code |
434 | misusing it. Replacement: d_make_root(inode). The difference is, | 432 | misusing it. Replacement: d_make_root(inode). The difference is, |
435 | d_make_root() drops the reference to inode if dentry allocation fails. | 433 | d_make_root() drops the reference to inode if dentry allocation fails. |
434 | |||
435 | -- | ||
436 | [mandatory] | ||
437 | The witch is dead! Well, 2/3 of it, anyway. ->d_revalidate() and | ||
438 | ->lookup() do *not* take struct nameidata anymore; just the flags. | ||
439 | -- | ||
440 | [mandatory] | ||
441 | ->create() doesn't take struct nameidata *; unlike the previous | ||
442 | two, it gets "is it an O_EXCL or equivalent?" boolean argument. Note that | ||
443 | local filesystems can ignore tha argument - they are guaranteed that the | ||
444 | object doesn't exist. It's remote/distributed ones that might care... | ||
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index efd23f481704..aa754e01464e 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
@@ -341,8 +341,8 @@ This describes how the VFS can manipulate an inode in your | |||
341 | filesystem. As of kernel 2.6.22, the following members are defined: | 341 | filesystem. As of kernel 2.6.22, the following members are defined: |
342 | 342 | ||
343 | struct inode_operations { | 343 | struct inode_operations { |
344 | int (*create) (struct inode *,struct dentry *, umode_t, struct nameidata *); | 344 | int (*create) (struct inode *,struct dentry *, umode_t, bool); |
345 | struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *); | 345 | struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); |
346 | int (*link) (struct dentry *,struct inode *,struct dentry *); | 346 | int (*link) (struct dentry *,struct inode *,struct dentry *); |
347 | int (*unlink) (struct inode *,struct dentry *); | 347 | int (*unlink) (struct inode *,struct dentry *); |
348 | int (*symlink) (struct inode *,struct dentry *,const char *); | 348 | int (*symlink) (struct inode *,struct dentry *,const char *); |
@@ -364,6 +364,9 @@ struct inode_operations { | |||
364 | ssize_t (*listxattr) (struct dentry *, char *, size_t); | 364 | ssize_t (*listxattr) (struct dentry *, char *, size_t); |
365 | int (*removexattr) (struct dentry *, const char *); | 365 | int (*removexattr) (struct dentry *, const char *); |
366 | void (*update_time)(struct inode *, struct timespec *, int); | 366 | void (*update_time)(struct inode *, struct timespec *, int); |
367 | int (*atomic_open)(struct inode *, struct dentry *, | ||
368 | struct file *, unsigned open_flag, | ||
369 | umode_t create_mode, int *opened); | ||
367 | }; | 370 | }; |
368 | 371 | ||
369 | Again, all methods are called without any locks being held, unless | 372 | Again, all methods are called without any locks being held, unless |
@@ -476,6 +479,14 @@ otherwise noted. | |||
476 | an inode. If this is not defined the VFS will update the inode itself | 479 | an inode. If this is not defined the VFS will update the inode itself |
477 | and call mark_inode_dirty_sync. | 480 | and call mark_inode_dirty_sync. |
478 | 481 | ||
482 | atomic_open: called on the last component of an open. Using this optional | ||
483 | method the filesystem can look up, possibly create and open the file in | ||
484 | one atomic operation. If it cannot perform this (e.g. the file type | ||
485 | turned out to be wrong) it may signal this by returning 1 instead of | ||
486 | usual 0 or -ve . This method is only called if the last | ||
487 | component is negative or needs lookup. Cached positive dentries are | ||
488 | still handled by f_op->open(). | ||
489 | |||
479 | The Address Space Object | 490 | The Address Space Object |
480 | ======================== | 491 | ======================== |
481 | 492 | ||
@@ -891,7 +902,7 @@ the VFS uses a default. As of kernel 2.6.22, the following members are | |||
891 | defined: | 902 | defined: |
892 | 903 | ||
893 | struct dentry_operations { | 904 | struct dentry_operations { |
894 | int (*d_revalidate)(struct dentry *, struct nameidata *); | 905 | int (*d_revalidate)(struct dentry *, unsigned int); |
895 | int (*d_hash)(const struct dentry *, const struct inode *, | 906 | int (*d_hash)(const struct dentry *, const struct inode *, |
896 | struct qstr *); | 907 | struct qstr *); |
897 | int (*d_compare)(const struct dentry *, const struct inode *, | 908 | int (*d_compare)(const struct dentry *, const struct inode *, |
@@ -910,11 +921,11 @@ struct dentry_operations { | |||
910 | dcache. Most filesystems leave this as NULL, because all their | 921 | dcache. Most filesystems leave this as NULL, because all their |
911 | dentries in the dcache are valid | 922 | dentries in the dcache are valid |
912 | 923 | ||
913 | d_revalidate may be called in rcu-walk mode (nd->flags & LOOKUP_RCU). | 924 | d_revalidate may be called in rcu-walk mode (flags & LOOKUP_RCU). |
914 | If in rcu-walk mode, the filesystem must revalidate the dentry without | 925 | If in rcu-walk mode, the filesystem must revalidate the dentry without |
915 | blocking or storing to the dentry, d_parent and d_inode should not be | 926 | blocking or storing to the dentry, d_parent and d_inode should not be |
916 | used without care (because they can go NULL), instead nd->inode should | 927 | used without care (because they can change and, in d_inode case, even |
917 | be used. | 928 | become NULL under us). |
918 | 929 | ||
919 | If a situation is encountered that rcu-walk cannot handle, return | 930 | If a situation is encountered that rcu-walk cannot handle, return |
920 | -ECHILD and it will be called again in ref-walk mode. | 931 | -ECHILD and it will be called again in ref-walk mode. |
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 66519d263da7..d544d7816df3 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -317,28 +317,23 @@ out: | |||
317 | return ret; | 317 | return ret; |
318 | } | 318 | } |
319 | 319 | ||
320 | static int spufs_context_open(struct dentry *dentry, struct vfsmount *mnt) | 320 | static int spufs_context_open(struct path *path) |
321 | { | 321 | { |
322 | int ret; | 322 | int ret; |
323 | struct file *filp; | 323 | struct file *filp; |
324 | 324 | ||
325 | ret = get_unused_fd(); | 325 | ret = get_unused_fd(); |
326 | if (ret < 0) { | 326 | if (ret < 0) |
327 | dput(dentry); | 327 | return ret; |
328 | mntput(mnt); | ||
329 | goto out; | ||
330 | } | ||
331 | 328 | ||
332 | filp = dentry_open(dentry, mnt, O_RDONLY, current_cred()); | 329 | filp = dentry_open(path, O_RDONLY, current_cred()); |
333 | if (IS_ERR(filp)) { | 330 | if (IS_ERR(filp)) { |
334 | put_unused_fd(ret); | 331 | put_unused_fd(ret); |
335 | ret = PTR_ERR(filp); | 332 | return PTR_ERR(filp); |
336 | goto out; | ||
337 | } | 333 | } |
338 | 334 | ||
339 | filp->f_op = &spufs_context_fops; | 335 | filp->f_op = &spufs_context_fops; |
340 | fd_install(ret, filp); | 336 | fd_install(ret, filp); |
341 | out: | ||
342 | return ret; | 337 | return ret; |
343 | } | 338 | } |
344 | 339 | ||
@@ -453,6 +448,7 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, | |||
453 | int affinity; | 448 | int affinity; |
454 | struct spu_gang *gang; | 449 | struct spu_gang *gang; |
455 | struct spu_context *neighbor; | 450 | struct spu_context *neighbor; |
451 | struct path path = {.mnt = mnt, .dentry = dentry}; | ||
456 | 452 | ||
457 | ret = -EPERM; | 453 | ret = -EPERM; |
458 | if ((flags & SPU_CREATE_NOSCHED) && | 454 | if ((flags & SPU_CREATE_NOSCHED) && |
@@ -495,11 +491,7 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, | |||
495 | put_spu_context(neighbor); | 491 | put_spu_context(neighbor); |
496 | } | 492 | } |
497 | 493 | ||
498 | /* | 494 | ret = spufs_context_open(&path); |
499 | * get references for dget and mntget, will be released | ||
500 | * in error path of *_open(). | ||
501 | */ | ||
502 | ret = spufs_context_open(dget(dentry), mntget(mnt)); | ||
503 | if (ret < 0) { | 495 | if (ret < 0) { |
504 | WARN_ON(spufs_rmdir(inode, dentry)); | 496 | WARN_ON(spufs_rmdir(inode, dentry)); |
505 | if (affinity) | 497 | if (affinity) |
@@ -556,28 +548,27 @@ out: | |||
556 | return ret; | 548 | return ret; |
557 | } | 549 | } |
558 | 550 | ||
559 | static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt) | 551 | static int spufs_gang_open(struct path *path) |
560 | { | 552 | { |
561 | int ret; | 553 | int ret; |
562 | struct file *filp; | 554 | struct file *filp; |
563 | 555 | ||
564 | ret = get_unused_fd(); | 556 | ret = get_unused_fd(); |
565 | if (ret < 0) { | 557 | if (ret < 0) |
566 | dput(dentry); | 558 | return ret; |
567 | mntput(mnt); | ||
568 | goto out; | ||
569 | } | ||
570 | 559 | ||
571 | filp = dentry_open(dentry, mnt, O_RDONLY, current_cred()); | 560 | /* |
561 | * get references for dget and mntget, will be released | ||
562 | * in error path of *_open(). | ||
563 | */ | ||
564 | filp = dentry_open(path, O_RDONLY, current_cred()); | ||
572 | if (IS_ERR(filp)) { | 565 | if (IS_ERR(filp)) { |
573 | put_unused_fd(ret); | 566 | put_unused_fd(ret); |
574 | ret = PTR_ERR(filp); | 567 | return PTR_ERR(filp); |
575 | goto out; | ||
576 | } | 568 | } |
577 | 569 | ||
578 | filp->f_op = &simple_dir_operations; | 570 | filp->f_op = &simple_dir_operations; |
579 | fd_install(ret, filp); | 571 | fd_install(ret, filp); |
580 | out: | ||
581 | return ret; | 572 | return ret; |
582 | } | 573 | } |
583 | 574 | ||
@@ -585,17 +576,14 @@ static int spufs_create_gang(struct inode *inode, | |||
585 | struct dentry *dentry, | 576 | struct dentry *dentry, |
586 | struct vfsmount *mnt, umode_t mode) | 577 | struct vfsmount *mnt, umode_t mode) |
587 | { | 578 | { |
579 | struct path path = {.mnt = mnt, .dentry = dentry}; | ||
588 | int ret; | 580 | int ret; |
589 | 581 | ||
590 | ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO); | 582 | ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO); |
591 | if (ret) | 583 | if (ret) |
592 | goto out; | 584 | goto out; |
593 | 585 | ||
594 | /* | 586 | ret = spufs_gang_open(&path); |
595 | * get references for dget and mntget, will be released | ||
596 | * in error path of *_open(). | ||
597 | */ | ||
598 | ret = spufs_gang_open(dget(dentry), mntget(mnt)); | ||
599 | if (ret < 0) { | 587 | if (ret < 0) { |
600 | int err = simple_rmdir(inode, dentry); | 588 | int err = simple_rmdir(inode, dentry); |
601 | WARN_ON(err); | 589 | WARN_ON(err); |
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 765c3a28077a..d91a3a0b2325 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c | |||
@@ -227,33 +227,24 @@ static int handle_create(const char *nodename, umode_t mode, struct device *dev) | |||
227 | 227 | ||
228 | static int dev_rmdir(const char *name) | 228 | static int dev_rmdir(const char *name) |
229 | { | 229 | { |
230 | struct nameidata nd; | 230 | struct path parent; |
231 | struct dentry *dentry; | 231 | struct dentry *dentry; |
232 | int err; | 232 | int err; |
233 | 233 | ||
234 | err = kern_path_parent(name, &nd); | 234 | dentry = kern_path_locked(name, &parent); |
235 | if (err) | 235 | if (IS_ERR(dentry)) |
236 | return err; | 236 | return PTR_ERR(dentry); |
237 | 237 | if (dentry->d_inode) { | |
238 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); | 238 | if (dentry->d_inode->i_private == &thread) |
239 | dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); | 239 | err = vfs_rmdir(parent.dentry->d_inode, dentry); |
240 | if (!IS_ERR(dentry)) { | 240 | else |
241 | if (dentry->d_inode) { | 241 | err = -EPERM; |
242 | if (dentry->d_inode->i_private == &thread) | ||
243 | err = vfs_rmdir(nd.path.dentry->d_inode, | ||
244 | dentry); | ||
245 | else | ||
246 | err = -EPERM; | ||
247 | } else { | ||
248 | err = -ENOENT; | ||
249 | } | ||
250 | dput(dentry); | ||
251 | } else { | 242 | } else { |
252 | err = PTR_ERR(dentry); | 243 | err = -ENOENT; |
253 | } | 244 | } |
254 | 245 | dput(dentry); | |
255 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 246 | mutex_unlock(&parent.dentry->d_inode->i_mutex); |
256 | path_put(&nd.path); | 247 | path_put(&parent); |
257 | return err; | 248 | return err; |
258 | } | 249 | } |
259 | 250 | ||
@@ -305,50 +296,43 @@ static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *sta | |||
305 | 296 | ||
306 | static int handle_remove(const char *nodename, struct device *dev) | 297 | static int handle_remove(const char *nodename, struct device *dev) |
307 | { | 298 | { |
308 | struct nameidata nd; | 299 | struct path parent; |
309 | struct dentry *dentry; | 300 | struct dentry *dentry; |
310 | struct kstat stat; | ||
311 | int deleted = 1; | 301 | int deleted = 1; |
312 | int err; | 302 | int err; |
313 | 303 | ||
314 | err = kern_path_parent(nodename, &nd); | 304 | dentry = kern_path_locked(nodename, &parent); |
315 | if (err) | 305 | if (IS_ERR(dentry)) |
316 | return err; | 306 | return PTR_ERR(dentry); |
317 | 307 | ||
318 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); | 308 | if (dentry->d_inode) { |
319 | dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); | 309 | struct kstat stat; |
320 | if (!IS_ERR(dentry)) { | 310 | err = vfs_getattr(parent.mnt, dentry, &stat); |
321 | if (dentry->d_inode) { | 311 | if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { |
322 | err = vfs_getattr(nd.path.mnt, dentry, &stat); | 312 | struct iattr newattrs; |
323 | if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { | 313 | /* |
324 | struct iattr newattrs; | 314 | * before unlinking this node, reset permissions |
325 | /* | 315 | * of possible references like hardlinks |
326 | * before unlinking this node, reset permissions | 316 | */ |
327 | * of possible references like hardlinks | 317 | newattrs.ia_uid = 0; |
328 | */ | 318 | newattrs.ia_gid = 0; |
329 | newattrs.ia_uid = 0; | 319 | newattrs.ia_mode = stat.mode & ~0777; |
330 | newattrs.ia_gid = 0; | 320 | newattrs.ia_valid = |
331 | newattrs.ia_mode = stat.mode & ~0777; | 321 | ATTR_UID|ATTR_GID|ATTR_MODE; |
332 | newattrs.ia_valid = | 322 | mutex_lock(&dentry->d_inode->i_mutex); |
333 | ATTR_UID|ATTR_GID|ATTR_MODE; | 323 | notify_change(dentry, &newattrs); |
334 | mutex_lock(&dentry->d_inode->i_mutex); | 324 | mutex_unlock(&dentry->d_inode->i_mutex); |
335 | notify_change(dentry, &newattrs); | 325 | err = vfs_unlink(parent.dentry->d_inode, dentry); |
336 | mutex_unlock(&dentry->d_inode->i_mutex); | 326 | if (!err || err == -ENOENT) |
337 | err = vfs_unlink(nd.path.dentry->d_inode, | 327 | deleted = 1; |
338 | dentry); | ||
339 | if (!err || err == -ENOENT) | ||
340 | deleted = 1; | ||
341 | } | ||
342 | } else { | ||
343 | err = -ENOENT; | ||
344 | } | 328 | } |
345 | dput(dentry); | ||
346 | } else { | 329 | } else { |
347 | err = PTR_ERR(dentry); | 330 | err = -ENOENT; |
348 | } | 331 | } |
349 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 332 | dput(dentry); |
333 | mutex_unlock(&parent.dentry->d_inode->i_mutex); | ||
350 | 334 | ||
351 | path_put(&nd.path); | 335 | path_put(&parent); |
352 | if (deleted && strchr(nodename, '/')) | 336 | if (deleted && strchr(nodename, '/')) |
353 | delete_path(nodename); | 337 | delete_path(nodename); |
354 | return err; | 338 | return err; |
diff --git a/drivers/media/video/zoran/zoran.h b/drivers/media/video/zoran/zoran.h index d7166afc255e..ca2754a3cd63 100644 --- a/drivers/media/video/zoran/zoran.h +++ b/drivers/media/video/zoran/zoran.h | |||
@@ -172,8 +172,10 @@ struct zoran_jpg_settings { | |||
172 | struct v4l2_jpegcompression jpg_comp; /* JPEG-specific capture settings */ | 172 | struct v4l2_jpegcompression jpg_comp; /* JPEG-specific capture settings */ |
173 | }; | 173 | }; |
174 | 174 | ||
175 | struct zoran_fh; | ||
176 | |||
175 | struct zoran_mapping { | 177 | struct zoran_mapping { |
176 | struct file *file; | 178 | struct zoran_fh *fh; |
177 | int count; | 179 | int count; |
178 | }; | 180 | }; |
179 | 181 | ||
diff --git a/drivers/media/video/zoran/zoran_driver.c b/drivers/media/video/zoran/zoran_driver.c index c57310931810..c6ccdeb6d8d6 100644 --- a/drivers/media/video/zoran/zoran_driver.c +++ b/drivers/media/video/zoran/zoran_driver.c | |||
@@ -2811,7 +2811,7 @@ static void | |||
2811 | zoran_vm_close (struct vm_area_struct *vma) | 2811 | zoran_vm_close (struct vm_area_struct *vma) |
2812 | { | 2812 | { |
2813 | struct zoran_mapping *map = vma->vm_private_data; | 2813 | struct zoran_mapping *map = vma->vm_private_data; |
2814 | struct zoran_fh *fh = map->file->private_data; | 2814 | struct zoran_fh *fh = map->fh; |
2815 | struct zoran *zr = fh->zr; | 2815 | struct zoran *zr = fh->zr; |
2816 | int i; | 2816 | int i; |
2817 | 2817 | ||
@@ -2938,7 +2938,7 @@ zoran_mmap (struct file *file, | |||
2938 | res = -ENOMEM; | 2938 | res = -ENOMEM; |
2939 | goto mmap_unlock_and_return; | 2939 | goto mmap_unlock_and_return; |
2940 | } | 2940 | } |
2941 | map->file = file; | 2941 | map->fh = fh; |
2942 | map->count = 1; | 2942 | map->count = 1; |
2943 | 2943 | ||
2944 | vma->vm_ops = &zoran_vm_ops; | 2944 | vma->vm_ops = &zoran_vm_ops; |
diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c index a90bfe79916d..334da5f583c0 100644 --- a/drivers/mtd/mtdsuper.c +++ b/drivers/mtd/mtdsuper.c | |||
@@ -63,7 +63,7 @@ static struct dentry *mount_mtd_aux(struct file_system_type *fs_type, int flags, | |||
63 | struct super_block *sb; | 63 | struct super_block *sb; |
64 | int ret; | 64 | int ret; |
65 | 65 | ||
66 | sb = sget(fs_type, get_sb_mtd_compare, get_sb_mtd_set, mtd); | 66 | sb = sget(fs_type, get_sb_mtd_compare, get_sb_mtd_set, flags, mtd); |
67 | if (IS_ERR(sb)) | 67 | if (IS_ERR(sb)) |
68 | goto out_error; | 68 | goto out_error; |
69 | 69 | ||
@@ -74,8 +74,6 @@ static struct dentry *mount_mtd_aux(struct file_system_type *fs_type, int flags, | |||
74 | pr_debug("MTDSB: New superblock for device %d (\"%s\")\n", | 74 | pr_debug("MTDSB: New superblock for device %d (\"%s\")\n", |
75 | mtd->index, mtd->name); | 75 | mtd->index, mtd->name); |
76 | 76 | ||
77 | sb->s_flags = flags; | ||
78 | |||
79 | ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0); | 77 | ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0); |
80 | if (ret < 0) { | 78 | if (ret < 0) { |
81 | deactivate_locked_super(sb); | 79 | deactivate_locked_super(sb); |
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index e78956cbd702..34c59f14a1c9 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h | |||
@@ -144,7 +144,7 @@ extern void v9fs_session_close(struct v9fs_session_info *v9ses); | |||
144 | extern void v9fs_session_cancel(struct v9fs_session_info *v9ses); | 144 | extern void v9fs_session_cancel(struct v9fs_session_info *v9ses); |
145 | extern void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses); | 145 | extern void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses); |
146 | extern struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | 146 | extern struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, |
147 | struct nameidata *nameidata); | 147 | unsigned int flags); |
148 | extern int v9fs_vfs_unlink(struct inode *i, struct dentry *d); | 148 | extern int v9fs_vfs_unlink(struct inode *i, struct dentry *d); |
149 | extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d); | 149 | extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d); |
150 | extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | 150 | extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, |
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index d529437ff442..64600b5d0522 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c | |||
@@ -100,13 +100,13 @@ static void v9fs_dentry_release(struct dentry *dentry) | |||
100 | } | 100 | } |
101 | } | 101 | } |
102 | 102 | ||
103 | static int v9fs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | 103 | static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags) |
104 | { | 104 | { |
105 | struct p9_fid *fid; | 105 | struct p9_fid *fid; |
106 | struct inode *inode; | 106 | struct inode *inode; |
107 | struct v9fs_inode *v9inode; | 107 | struct v9fs_inode *v9inode; |
108 | 108 | ||
109 | if (nd->flags & LOOKUP_RCU) | 109 | if (flags & LOOKUP_RCU) |
110 | return -ECHILD; | 110 | return -ECHILD; |
111 | 111 | ||
112 | inode = dentry->d_inode; | 112 | inode = dentry->d_inode; |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 57ccb7537dae..cbf9dbb1b2a2 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -712,88 +712,34 @@ error: | |||
712 | } | 712 | } |
713 | 713 | ||
714 | /** | 714 | /** |
715 | * v9fs_vfs_create - VFS hook to create files | 715 | * v9fs_vfs_create - VFS hook to create a regular file |
716 | * | ||
717 | * open(.., O_CREAT) is handled in v9fs_vfs_atomic_open(). This is only called | ||
718 | * for mknod(2). | ||
719 | * | ||
716 | * @dir: directory inode that is being created | 720 | * @dir: directory inode that is being created |
717 | * @dentry: dentry that is being deleted | 721 | * @dentry: dentry that is being deleted |
718 | * @mode: create permissions | 722 | * @mode: create permissions |
719 | * @nd: path information | ||
720 | * | 723 | * |
721 | */ | 724 | */ |
722 | 725 | ||
723 | static int | 726 | static int |
724 | v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 727 | v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
725 | struct nameidata *nd) | 728 | bool excl) |
726 | { | 729 | { |
727 | int err; | 730 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); |
728 | u32 perm; | 731 | u32 perm = unixmode2p9mode(v9ses, mode); |
729 | int flags; | 732 | struct p9_fid *fid; |
730 | struct file *filp; | ||
731 | struct v9fs_inode *v9inode; | ||
732 | struct v9fs_session_info *v9ses; | ||
733 | struct p9_fid *fid, *inode_fid; | ||
734 | |||
735 | err = 0; | ||
736 | fid = NULL; | ||
737 | v9ses = v9fs_inode2v9ses(dir); | ||
738 | perm = unixmode2p9mode(v9ses, mode); | ||
739 | if (nd) | ||
740 | flags = nd->intent.open.flags; | ||
741 | else | ||
742 | flags = O_RDWR; | ||
743 | 733 | ||
744 | fid = v9fs_create(v9ses, dir, dentry, NULL, perm, | 734 | /* P9_OEXCL? */ |
745 | v9fs_uflags2omode(flags, | 735 | fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_ORDWR); |
746 | v9fs_proto_dotu(v9ses))); | 736 | if (IS_ERR(fid)) |
747 | if (IS_ERR(fid)) { | 737 | return PTR_ERR(fid); |
748 | err = PTR_ERR(fid); | ||
749 | fid = NULL; | ||
750 | goto error; | ||
751 | } | ||
752 | 738 | ||
753 | v9fs_invalidate_inode_attr(dir); | 739 | v9fs_invalidate_inode_attr(dir); |
754 | /* if we are opening a file, assign the open fid to the file */ | 740 | p9_client_clunk(fid); |
755 | if (nd) { | ||
756 | v9inode = V9FS_I(dentry->d_inode); | ||
757 | mutex_lock(&v9inode->v_mutex); | ||
758 | if (v9ses->cache && !v9inode->writeback_fid && | ||
759 | ((flags & O_ACCMODE) != O_RDONLY)) { | ||
760 | /* | ||
761 | * clone a fid and add it to writeback_fid | ||
762 | * we do it during open time instead of | ||
763 | * page dirty time via write_begin/page_mkwrite | ||
764 | * because we want write after unlink usecase | ||
765 | * to work. | ||
766 | */ | ||
767 | inode_fid = v9fs_writeback_fid(dentry); | ||
768 | if (IS_ERR(inode_fid)) { | ||
769 | err = PTR_ERR(inode_fid); | ||
770 | mutex_unlock(&v9inode->v_mutex); | ||
771 | goto error; | ||
772 | } | ||
773 | v9inode->writeback_fid = (void *) inode_fid; | ||
774 | } | ||
775 | mutex_unlock(&v9inode->v_mutex); | ||
776 | filp = lookup_instantiate_filp(nd, dentry, generic_file_open); | ||
777 | if (IS_ERR(filp)) { | ||
778 | err = PTR_ERR(filp); | ||
779 | goto error; | ||
780 | } | ||
781 | |||
782 | filp->private_data = fid; | ||
783 | #ifdef CONFIG_9P_FSCACHE | ||
784 | if (v9ses->cache) | ||
785 | v9fs_cache_inode_set_cookie(dentry->d_inode, filp); | ||
786 | #endif | ||
787 | } else | ||
788 | p9_client_clunk(fid); | ||
789 | 741 | ||
790 | return 0; | 742 | return 0; |
791 | |||
792 | error: | ||
793 | if (fid) | ||
794 | p9_client_clunk(fid); | ||
795 | |||
796 | return err; | ||
797 | } | 743 | } |
798 | 744 | ||
799 | /** | 745 | /** |
@@ -839,7 +785,7 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode | |||
839 | */ | 785 | */ |
840 | 786 | ||
841 | struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | 787 | struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, |
842 | struct nameidata *nameidata) | 788 | unsigned int flags) |
843 | { | 789 | { |
844 | struct dentry *res; | 790 | struct dentry *res; |
845 | struct super_block *sb; | 791 | struct super_block *sb; |
@@ -849,8 +795,8 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
849 | char *name; | 795 | char *name; |
850 | int result = 0; | 796 | int result = 0; |
851 | 797 | ||
852 | p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n", | 798 | p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p flags: %x\n", |
853 | dir, dentry->d_name.name, dentry, nameidata); | 799 | dir, dentry->d_name.name, dentry, flags); |
854 | 800 | ||
855 | if (dentry->d_name.len > NAME_MAX) | 801 | if (dentry->d_name.len > NAME_MAX) |
856 | return ERR_PTR(-ENAMETOOLONG); | 802 | return ERR_PTR(-ENAMETOOLONG); |
@@ -910,6 +856,86 @@ error: | |||
910 | return ERR_PTR(result); | 856 | return ERR_PTR(result); |
911 | } | 857 | } |
912 | 858 | ||
859 | static int | ||
860 | v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, | ||
861 | struct file *file, unsigned flags, umode_t mode, | ||
862 | int *opened) | ||
863 | { | ||
864 | int err; | ||
865 | u32 perm; | ||
866 | struct v9fs_inode *v9inode; | ||
867 | struct v9fs_session_info *v9ses; | ||
868 | struct p9_fid *fid, *inode_fid; | ||
869 | struct dentry *res = NULL; | ||
870 | |||
871 | if (d_unhashed(dentry)) { | ||
872 | res = v9fs_vfs_lookup(dir, dentry, 0); | ||
873 | if (IS_ERR(res)) | ||
874 | return PTR_ERR(res); | ||
875 | |||
876 | if (res) | ||
877 | dentry = res; | ||
878 | } | ||
879 | |||
880 | /* Only creates */ | ||
881 | if (!(flags & O_CREAT) || dentry->d_inode) | ||
882 | return finish_no_open(file, res); | ||
883 | |||
884 | err = 0; | ||
885 | fid = NULL; | ||
886 | v9ses = v9fs_inode2v9ses(dir); | ||
887 | perm = unixmode2p9mode(v9ses, mode); | ||
888 | fid = v9fs_create(v9ses, dir, dentry, NULL, perm, | ||
889 | v9fs_uflags2omode(flags, | ||
890 | v9fs_proto_dotu(v9ses))); | ||
891 | if (IS_ERR(fid)) { | ||
892 | err = PTR_ERR(fid); | ||
893 | fid = NULL; | ||
894 | goto error; | ||
895 | } | ||
896 | |||
897 | v9fs_invalidate_inode_attr(dir); | ||
898 | v9inode = V9FS_I(dentry->d_inode); | ||
899 | mutex_lock(&v9inode->v_mutex); | ||
900 | if (v9ses->cache && !v9inode->writeback_fid && | ||
901 | ((flags & O_ACCMODE) != O_RDONLY)) { | ||
902 | /* | ||
903 | * clone a fid and add it to writeback_fid | ||
904 | * we do it during open time instead of | ||
905 | * page dirty time via write_begin/page_mkwrite | ||
906 | * because we want write after unlink usecase | ||
907 | * to work. | ||
908 | */ | ||
909 | inode_fid = v9fs_writeback_fid(dentry); | ||
910 | if (IS_ERR(inode_fid)) { | ||
911 | err = PTR_ERR(inode_fid); | ||
912 | mutex_unlock(&v9inode->v_mutex); | ||
913 | goto error; | ||
914 | } | ||
915 | v9inode->writeback_fid = (void *) inode_fid; | ||
916 | } | ||
917 | mutex_unlock(&v9inode->v_mutex); | ||
918 | err = finish_open(file, dentry, generic_file_open, opened); | ||
919 | if (err) | ||
920 | goto error; | ||
921 | |||
922 | file->private_data = fid; | ||
923 | #ifdef CONFIG_9P_FSCACHE | ||
924 | if (v9ses->cache) | ||
925 | v9fs_cache_inode_set_cookie(dentry->d_inode, file); | ||
926 | #endif | ||
927 | |||
928 | *opened |= FILE_CREATED; | ||
929 | out: | ||
930 | dput(res); | ||
931 | return err; | ||
932 | |||
933 | error: | ||
934 | if (fid) | ||
935 | p9_client_clunk(fid); | ||
936 | goto out; | ||
937 | } | ||
938 | |||
913 | /** | 939 | /** |
914 | * v9fs_vfs_unlink - VFS unlink hook to delete an inode | 940 | * v9fs_vfs_unlink - VFS unlink hook to delete an inode |
915 | * @i: inode that is being unlinked | 941 | * @i: inode that is being unlinked |
@@ -1488,6 +1514,7 @@ out: | |||
1488 | static const struct inode_operations v9fs_dir_inode_operations_dotu = { | 1514 | static const struct inode_operations v9fs_dir_inode_operations_dotu = { |
1489 | .create = v9fs_vfs_create, | 1515 | .create = v9fs_vfs_create, |
1490 | .lookup = v9fs_vfs_lookup, | 1516 | .lookup = v9fs_vfs_lookup, |
1517 | .atomic_open = v9fs_vfs_atomic_open, | ||
1491 | .symlink = v9fs_vfs_symlink, | 1518 | .symlink = v9fs_vfs_symlink, |
1492 | .link = v9fs_vfs_link, | 1519 | .link = v9fs_vfs_link, |
1493 | .unlink = v9fs_vfs_unlink, | 1520 | .unlink = v9fs_vfs_unlink, |
@@ -1502,6 +1529,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = { | |||
1502 | static const struct inode_operations v9fs_dir_inode_operations = { | 1529 | static const struct inode_operations v9fs_dir_inode_operations = { |
1503 | .create = v9fs_vfs_create, | 1530 | .create = v9fs_vfs_create, |
1504 | .lookup = v9fs_vfs_lookup, | 1531 | .lookup = v9fs_vfs_lookup, |
1532 | .atomic_open = v9fs_vfs_atomic_open, | ||
1505 | .unlink = v9fs_vfs_unlink, | 1533 | .unlink = v9fs_vfs_unlink, |
1506 | .mkdir = v9fs_vfs_mkdir, | 1534 | .mkdir = v9fs_vfs_mkdir, |
1507 | .rmdir = v9fs_vfs_rmdir, | 1535 | .rmdir = v9fs_vfs_rmdir, |
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index e3dd2a1e2bfc..40895546e103 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c | |||
@@ -230,20 +230,25 @@ int v9fs_open_to_dotl_flags(int flags) | |||
230 | * @dir: directory inode that is being created | 230 | * @dir: directory inode that is being created |
231 | * @dentry: dentry that is being deleted | 231 | * @dentry: dentry that is being deleted |
232 | * @mode: create permissions | 232 | * @mode: create permissions |
233 | * @nd: path information | ||
234 | * | 233 | * |
235 | */ | 234 | */ |
236 | 235 | ||
237 | static int | 236 | static int |
238 | v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, | 237 | v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, |
239 | struct nameidata *nd) | 238 | bool excl) |
239 | { | ||
240 | return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0); | ||
241 | } | ||
242 | |||
243 | static int | ||
244 | v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, | ||
245 | struct file *file, unsigned flags, umode_t omode, | ||
246 | int *opened) | ||
240 | { | 247 | { |
241 | int err = 0; | 248 | int err = 0; |
242 | gid_t gid; | 249 | gid_t gid; |
243 | int flags; | ||
244 | umode_t mode; | 250 | umode_t mode; |
245 | char *name = NULL; | 251 | char *name = NULL; |
246 | struct file *filp; | ||
247 | struct p9_qid qid; | 252 | struct p9_qid qid; |
248 | struct inode *inode; | 253 | struct inode *inode; |
249 | struct p9_fid *fid = NULL; | 254 | struct p9_fid *fid = NULL; |
@@ -251,19 +256,23 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, | |||
251 | struct p9_fid *dfid, *ofid, *inode_fid; | 256 | struct p9_fid *dfid, *ofid, *inode_fid; |
252 | struct v9fs_session_info *v9ses; | 257 | struct v9fs_session_info *v9ses; |
253 | struct posix_acl *pacl = NULL, *dacl = NULL; | 258 | struct posix_acl *pacl = NULL, *dacl = NULL; |
259 | struct dentry *res = NULL; | ||
254 | 260 | ||
255 | v9ses = v9fs_inode2v9ses(dir); | 261 | if (d_unhashed(dentry)) { |
256 | if (nd) | 262 | res = v9fs_vfs_lookup(dir, dentry, 0); |
257 | flags = nd->intent.open.flags; | 263 | if (IS_ERR(res)) |
258 | else { | 264 | return PTR_ERR(res); |
259 | /* | 265 | |
260 | * create call without LOOKUP_OPEN is due | 266 | if (res) |
261 | * to mknod of regular files. So use mknod | 267 | dentry = res; |
262 | * operation. | ||
263 | */ | ||
264 | return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0); | ||
265 | } | 268 | } |
266 | 269 | ||
270 | /* Only creates */ | ||
271 | if (!(flags & O_CREAT) || dentry->d_inode) | ||
272 | return finish_no_open(file, res); | ||
273 | |||
274 | v9ses = v9fs_inode2v9ses(dir); | ||
275 | |||
267 | name = (char *) dentry->d_name.name; | 276 | name = (char *) dentry->d_name.name; |
268 | p9_debug(P9_DEBUG_VFS, "name:%s flags:0x%x mode:0x%hx\n", | 277 | p9_debug(P9_DEBUG_VFS, "name:%s flags:0x%x mode:0x%hx\n", |
269 | name, flags, omode); | 278 | name, flags, omode); |
@@ -272,7 +281,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, | |||
272 | if (IS_ERR(dfid)) { | 281 | if (IS_ERR(dfid)) { |
273 | err = PTR_ERR(dfid); | 282 | err = PTR_ERR(dfid); |
274 | p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); | 283 | p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); |
275 | return err; | 284 | goto out; |
276 | } | 285 | } |
277 | 286 | ||
278 | /* clone a fid to use for creation */ | 287 | /* clone a fid to use for creation */ |
@@ -280,7 +289,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, | |||
280 | if (IS_ERR(ofid)) { | 289 | if (IS_ERR(ofid)) { |
281 | err = PTR_ERR(ofid); | 290 | err = PTR_ERR(ofid); |
282 | p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); | 291 | p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); |
283 | return err; | 292 | goto out; |
284 | } | 293 | } |
285 | 294 | ||
286 | gid = v9fs_get_fsgid_for_create(dir); | 295 | gid = v9fs_get_fsgid_for_create(dir); |
@@ -345,17 +354,18 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, | |||
345 | } | 354 | } |
346 | mutex_unlock(&v9inode->v_mutex); | 355 | mutex_unlock(&v9inode->v_mutex); |
347 | /* Since we are opening a file, assign the open fid to the file */ | 356 | /* Since we are opening a file, assign the open fid to the file */ |
348 | filp = lookup_instantiate_filp(nd, dentry, generic_file_open); | 357 | err = finish_open(file, dentry, generic_file_open, opened); |
349 | if (IS_ERR(filp)) { | 358 | if (err) |
350 | err = PTR_ERR(filp); | ||
351 | goto err_clunk_old_fid; | 359 | goto err_clunk_old_fid; |
352 | } | 360 | file->private_data = ofid; |
353 | filp->private_data = ofid; | ||
354 | #ifdef CONFIG_9P_FSCACHE | 361 | #ifdef CONFIG_9P_FSCACHE |
355 | if (v9ses->cache) | 362 | if (v9ses->cache) |
356 | v9fs_cache_inode_set_cookie(inode, filp); | 363 | v9fs_cache_inode_set_cookie(inode, file); |
357 | #endif | 364 | #endif |
358 | return 0; | 365 | *opened |= FILE_CREATED; |
366 | out: | ||
367 | dput(res); | ||
368 | return err; | ||
359 | 369 | ||
360 | error: | 370 | error: |
361 | if (fid) | 371 | if (fid) |
@@ -364,7 +374,7 @@ err_clunk_old_fid: | |||
364 | if (ofid) | 374 | if (ofid) |
365 | p9_client_clunk(ofid); | 375 | p9_client_clunk(ofid); |
366 | v9fs_set_create_acl(NULL, &dacl, &pacl); | 376 | v9fs_set_create_acl(NULL, &dacl, &pacl); |
367 | return err; | 377 | goto out; |
368 | } | 378 | } |
369 | 379 | ||
370 | /** | 380 | /** |
@@ -982,6 +992,7 @@ out: | |||
982 | 992 | ||
983 | const struct inode_operations v9fs_dir_inode_operations_dotl = { | 993 | const struct inode_operations v9fs_dir_inode_operations_dotl = { |
984 | .create = v9fs_vfs_create_dotl, | 994 | .create = v9fs_vfs_create_dotl, |
995 | .atomic_open = v9fs_vfs_atomic_open_dotl, | ||
985 | .lookup = v9fs_vfs_lookup, | 996 | .lookup = v9fs_vfs_lookup, |
986 | .link = v9fs_vfs_link_dotl, | 997 | .link = v9fs_vfs_link_dotl, |
987 | .symlink = v9fs_vfs_symlink_dotl, | 998 | .symlink = v9fs_vfs_symlink_dotl, |
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 8c92a9ba8330..137d50396898 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
@@ -89,7 +89,7 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, | |||
89 | if (v9ses->cache) | 89 | if (v9ses->cache) |
90 | sb->s_bdi->ra_pages = (VM_MAX_READAHEAD * 1024)/PAGE_CACHE_SIZE; | 90 | sb->s_bdi->ra_pages = (VM_MAX_READAHEAD * 1024)/PAGE_CACHE_SIZE; |
91 | 91 | ||
92 | sb->s_flags = flags | MS_ACTIVE | MS_DIRSYNC | MS_NOATIME; | 92 | sb->s_flags |= MS_ACTIVE | MS_DIRSYNC | MS_NOATIME; |
93 | if (!v9ses->cache) | 93 | if (!v9ses->cache) |
94 | sb->s_flags |= MS_SYNCHRONOUS; | 94 | sb->s_flags |= MS_SYNCHRONOUS; |
95 | 95 | ||
@@ -137,7 +137,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, | |||
137 | goto close_session; | 137 | goto close_session; |
138 | } | 138 | } |
139 | 139 | ||
140 | sb = sget(fs_type, NULL, v9fs_set_super, v9ses); | 140 | sb = sget(fs_type, NULL, v9fs_set_super, flags, v9ses); |
141 | if (IS_ERR(sb)) { | 141 | if (IS_ERR(sb)) { |
142 | retval = PTR_ERR(sb); | 142 | retval = PTR_ERR(sb); |
143 | goto clunk_fid; | 143 | goto clunk_fid; |
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index 3d83075aaa2e..b3be2e7c5643 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c | |||
@@ -266,7 +266,7 @@ const struct dentry_operations adfs_dentry_operations = { | |||
266 | }; | 266 | }; |
267 | 267 | ||
268 | static struct dentry * | 268 | static struct dentry * |
269 | adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 269 | adfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
270 | { | 270 | { |
271 | struct inode *inode = NULL; | 271 | struct inode *inode = NULL; |
272 | struct object_info obj; | 272 | struct object_info obj; |
diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 06fdcc9382c4..bdaec92353c2 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c | |||
@@ -246,7 +246,6 @@ static struct inode *adfs_alloc_inode(struct super_block *sb) | |||
246 | static void adfs_i_callback(struct rcu_head *head) | 246 | static void adfs_i_callback(struct rcu_head *head) |
247 | { | 247 | { |
248 | struct inode *inode = container_of(head, struct inode, i_rcu); | 248 | struct inode *inode = container_of(head, struct inode, i_rcu); |
249 | INIT_LIST_HEAD(&inode->i_dentry); | ||
250 | kmem_cache_free(adfs_inode_cachep, ADFS_I(inode)); | 249 | kmem_cache_free(adfs_inode_cachep, ADFS_I(inode)); |
251 | } | 250 | } |
252 | 251 | ||
diff --git a/fs/affs/affs.h b/fs/affs/affs.h index 1fceb320d2f2..6e216419f340 100644 --- a/fs/affs/affs.h +++ b/fs/affs/affs.h | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <linux/buffer_head.h> | 3 | #include <linux/buffer_head.h> |
4 | #include <linux/amigaffs.h> | 4 | #include <linux/amigaffs.h> |
5 | #include <linux/mutex.h> | 5 | #include <linux/mutex.h> |
6 | #include <linux/workqueue.h> | ||
6 | 7 | ||
7 | /* AmigaOS allows file names with up to 30 characters length. | 8 | /* AmigaOS allows file names with up to 30 characters length. |
8 | * Names longer than that will be silently truncated. If you | 9 | * Names longer than that will be silently truncated. If you |
@@ -100,6 +101,10 @@ struct affs_sb_info { | |||
100 | char *s_prefix; /* Prefix for volumes and assigns. */ | 101 | char *s_prefix; /* Prefix for volumes and assigns. */ |
101 | char s_volume[32]; /* Volume prefix for absolute symlinks. */ | 102 | char s_volume[32]; /* Volume prefix for absolute symlinks. */ |
102 | spinlock_t symlink_lock; /* protects the previous two */ | 103 | spinlock_t symlink_lock; /* protects the previous two */ |
104 | struct super_block *sb; /* the VFS superblock object */ | ||
105 | int work_queued; /* non-zero delayed work is queued */ | ||
106 | struct delayed_work sb_work; /* superblock flush delayed work */ | ||
107 | spinlock_t work_lock; /* protects sb_work and work_queued */ | ||
103 | }; | 108 | }; |
104 | 109 | ||
105 | #define SF_INTL 0x0001 /* International filesystem. */ | 110 | #define SF_INTL 0x0001 /* International filesystem. */ |
@@ -120,6 +125,8 @@ static inline struct affs_sb_info *AFFS_SB(struct super_block *sb) | |||
120 | return sb->s_fs_info; | 125 | return sb->s_fs_info; |
121 | } | 126 | } |
122 | 127 | ||
128 | void affs_mark_sb_dirty(struct super_block *sb); | ||
129 | |||
123 | /* amigaffs.c */ | 130 | /* amigaffs.c */ |
124 | 131 | ||
125 | extern int affs_insert_hash(struct inode *inode, struct buffer_head *bh); | 132 | extern int affs_insert_hash(struct inode *inode, struct buffer_head *bh); |
@@ -146,9 +153,9 @@ extern void affs_free_bitmap(struct super_block *sb); | |||
146 | /* namei.c */ | 153 | /* namei.c */ |
147 | 154 | ||
148 | extern int affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len); | 155 | extern int affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len); |
149 | extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *); | 156 | extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int); |
150 | extern int affs_unlink(struct inode *dir, struct dentry *dentry); | 157 | extern int affs_unlink(struct inode *dir, struct dentry *dentry); |
151 | extern int affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *); | 158 | extern int affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool); |
152 | extern int affs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); | 159 | extern int affs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); |
153 | extern int affs_rmdir(struct inode *dir, struct dentry *dentry); | 160 | extern int affs_rmdir(struct inode *dir, struct dentry *dentry); |
154 | extern int affs_link(struct dentry *olddentry, struct inode *dir, | 161 | extern int affs_link(struct dentry *olddentry, struct inode *dir, |
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index 52a6407682e6..eb82ee53ee0b 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c | |||
@@ -122,22 +122,16 @@ affs_remove_hash(struct inode *dir, struct buffer_head *rem_bh) | |||
122 | } | 122 | } |
123 | 123 | ||
124 | static void | 124 | static void |
125 | affs_fix_dcache(struct dentry *dentry, u32 entry_ino) | 125 | affs_fix_dcache(struct inode *inode, u32 entry_ino) |
126 | { | 126 | { |
127 | struct inode *inode = dentry->d_inode; | 127 | struct dentry *dentry; |
128 | void *data = dentry->d_fsdata; | 128 | struct hlist_node *p; |
129 | struct list_head *head, *next; | ||
130 | |||
131 | spin_lock(&inode->i_lock); | 129 | spin_lock(&inode->i_lock); |
132 | head = &inode->i_dentry; | 130 | hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) { |
133 | next = head->next; | ||
134 | while (next != head) { | ||
135 | dentry = list_entry(next, struct dentry, d_alias); | ||
136 | if (entry_ino == (u32)(long)dentry->d_fsdata) { | 131 | if (entry_ino == (u32)(long)dentry->d_fsdata) { |
137 | dentry->d_fsdata = data; | 132 | dentry->d_fsdata = (void *)inode->i_ino; |
138 | break; | 133 | break; |
139 | } | 134 | } |
140 | next = next->next; | ||
141 | } | 135 | } |
142 | spin_unlock(&inode->i_lock); | 136 | spin_unlock(&inode->i_lock); |
143 | } | 137 | } |
@@ -177,7 +171,11 @@ affs_remove_link(struct dentry *dentry) | |||
177 | } | 171 | } |
178 | 172 | ||
179 | affs_lock_dir(dir); | 173 | affs_lock_dir(dir); |
180 | affs_fix_dcache(dentry, link_ino); | 174 | /* |
175 | * if there's a dentry for that block, make it | ||
176 | * refer to inode itself. | ||
177 | */ | ||
178 | affs_fix_dcache(inode, link_ino); | ||
181 | retval = affs_remove_hash(dir, link_bh); | 179 | retval = affs_remove_hash(dir, link_bh); |
182 | if (retval) { | 180 | if (retval) { |
183 | affs_unlock_dir(dir); | 181 | affs_unlock_dir(dir); |
diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c index 3e262711ae06..6e0be43ef6ef 100644 --- a/fs/affs/bitmap.c +++ b/fs/affs/bitmap.c | |||
@@ -103,7 +103,7 @@ affs_free_block(struct super_block *sb, u32 block) | |||
103 | *(__be32 *)bh->b_data = cpu_to_be32(tmp - mask); | 103 | *(__be32 *)bh->b_data = cpu_to_be32(tmp - mask); |
104 | 104 | ||
105 | mark_buffer_dirty(bh); | 105 | mark_buffer_dirty(bh); |
106 | sb->s_dirt = 1; | 106 | affs_mark_sb_dirty(sb); |
107 | bm->bm_free++; | 107 | bm->bm_free++; |
108 | 108 | ||
109 | mutex_unlock(&sbi->s_bmlock); | 109 | mutex_unlock(&sbi->s_bmlock); |
@@ -248,7 +248,7 @@ find_bit: | |||
248 | *(__be32 *)bh->b_data = cpu_to_be32(tmp + mask); | 248 | *(__be32 *)bh->b_data = cpu_to_be32(tmp + mask); |
249 | 249 | ||
250 | mark_buffer_dirty(bh); | 250 | mark_buffer_dirty(bh); |
251 | sb->s_dirt = 1; | 251 | affs_mark_sb_dirty(sb); |
252 | 252 | ||
253 | mutex_unlock(&sbi->s_bmlock); | 253 | mutex_unlock(&sbi->s_bmlock); |
254 | 254 | ||
diff --git a/fs/affs/namei.c b/fs/affs/namei.c index 47806940aac0..ff65884a7839 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c | |||
@@ -211,7 +211,7 @@ affs_find_entry(struct inode *dir, struct dentry *dentry) | |||
211 | } | 211 | } |
212 | 212 | ||
213 | struct dentry * | 213 | struct dentry * |
214 | affs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 214 | affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
215 | { | 215 | { |
216 | struct super_block *sb = dir->i_sb; | 216 | struct super_block *sb = dir->i_sb; |
217 | struct buffer_head *bh; | 217 | struct buffer_head *bh; |
@@ -255,7 +255,7 @@ affs_unlink(struct inode *dir, struct dentry *dentry) | |||
255 | } | 255 | } |
256 | 256 | ||
257 | int | 257 | int |
258 | affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd) | 258 | affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) |
259 | { | 259 | { |
260 | struct super_block *sb = dir->i_sb; | 260 | struct super_block *sb = dir->i_sb; |
261 | struct inode *inode; | 261 | struct inode *inode; |
diff --git a/fs/affs/super.c b/fs/affs/super.c index 0782653a05a2..c70f1e5fc024 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/magic.h> | 17 | #include <linux/magic.h> |
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/writeback.h> | ||
20 | #include "affs.h" | 21 | #include "affs.h" |
21 | 22 | ||
22 | extern struct timezone sys_tz; | 23 | extern struct timezone sys_tz; |
@@ -25,15 +26,17 @@ static int affs_statfs(struct dentry *dentry, struct kstatfs *buf); | |||
25 | static int affs_remount (struct super_block *sb, int *flags, char *data); | 26 | static int affs_remount (struct super_block *sb, int *flags, char *data); |
26 | 27 | ||
27 | static void | 28 | static void |
28 | affs_commit_super(struct super_block *sb, int wait, int clean) | 29 | affs_commit_super(struct super_block *sb, int wait) |
29 | { | 30 | { |
30 | struct affs_sb_info *sbi = AFFS_SB(sb); | 31 | struct affs_sb_info *sbi = AFFS_SB(sb); |
31 | struct buffer_head *bh = sbi->s_root_bh; | 32 | struct buffer_head *bh = sbi->s_root_bh; |
32 | struct affs_root_tail *tail = AFFS_ROOT_TAIL(sb, bh); | 33 | struct affs_root_tail *tail = AFFS_ROOT_TAIL(sb, bh); |
33 | 34 | ||
34 | tail->bm_flag = cpu_to_be32(clean); | 35 | lock_buffer(bh); |
35 | secs_to_datestamp(get_seconds(), &tail->disk_change); | 36 | secs_to_datestamp(get_seconds(), &tail->disk_change); |
36 | affs_fix_checksum(sb, bh); | 37 | affs_fix_checksum(sb, bh); |
38 | unlock_buffer(bh); | ||
39 | |||
37 | mark_buffer_dirty(bh); | 40 | mark_buffer_dirty(bh); |
38 | if (wait) | 41 | if (wait) |
39 | sync_dirty_buffer(bh); | 42 | sync_dirty_buffer(bh); |
@@ -45,9 +48,7 @@ affs_put_super(struct super_block *sb) | |||
45 | struct affs_sb_info *sbi = AFFS_SB(sb); | 48 | struct affs_sb_info *sbi = AFFS_SB(sb); |
46 | pr_debug("AFFS: put_super()\n"); | 49 | pr_debug("AFFS: put_super()\n"); |
47 | 50 | ||
48 | if (!(sb->s_flags & MS_RDONLY) && sb->s_dirt) | 51 | cancel_delayed_work_sync(&sbi->sb_work); |
49 | affs_commit_super(sb, 1, 1); | ||
50 | |||
51 | kfree(sbi->s_prefix); | 52 | kfree(sbi->s_prefix); |
52 | affs_free_bitmap(sb); | 53 | affs_free_bitmap(sb); |
53 | affs_brelse(sbi->s_root_bh); | 54 | affs_brelse(sbi->s_root_bh); |
@@ -55,26 +56,43 @@ affs_put_super(struct super_block *sb) | |||
55 | sb->s_fs_info = NULL; | 56 | sb->s_fs_info = NULL; |
56 | } | 57 | } |
57 | 58 | ||
58 | static void | 59 | static int |
59 | affs_write_super(struct super_block *sb) | 60 | affs_sync_fs(struct super_block *sb, int wait) |
60 | { | 61 | { |
61 | lock_super(sb); | 62 | affs_commit_super(sb, wait); |
62 | if (!(sb->s_flags & MS_RDONLY)) | 63 | return 0; |
63 | affs_commit_super(sb, 1, 2); | 64 | } |
64 | sb->s_dirt = 0; | 65 | |
65 | unlock_super(sb); | 66 | static void flush_superblock(struct work_struct *work) |
67 | { | ||
68 | struct affs_sb_info *sbi; | ||
69 | struct super_block *sb; | ||
70 | |||
71 | sbi = container_of(work, struct affs_sb_info, sb_work.work); | ||
72 | sb = sbi->sb; | ||
66 | 73 | ||
67 | pr_debug("AFFS: write_super() at %lu, clean=2\n", get_seconds()); | 74 | spin_lock(&sbi->work_lock); |
75 | sbi->work_queued = 0; | ||
76 | spin_unlock(&sbi->work_lock); | ||
77 | |||
78 | affs_commit_super(sb, 1); | ||
68 | } | 79 | } |
69 | 80 | ||
70 | static int | 81 | void affs_mark_sb_dirty(struct super_block *sb) |
71 | affs_sync_fs(struct super_block *sb, int wait) | ||
72 | { | 82 | { |
73 | lock_super(sb); | 83 | struct affs_sb_info *sbi = AFFS_SB(sb); |
74 | affs_commit_super(sb, wait, 2); | 84 | unsigned long delay; |
75 | sb->s_dirt = 0; | 85 | |
76 | unlock_super(sb); | 86 | if (sb->s_flags & MS_RDONLY) |
77 | return 0; | 87 | return; |
88 | |||
89 | spin_lock(&sbi->work_lock); | ||
90 | if (!sbi->work_queued) { | ||
91 | delay = msecs_to_jiffies(dirty_writeback_interval * 10); | ||
92 | queue_delayed_work(system_long_wq, &sbi->sb_work, delay); | ||
93 | sbi->work_queued = 1; | ||
94 | } | ||
95 | spin_unlock(&sbi->work_lock); | ||
78 | } | 96 | } |
79 | 97 | ||
80 | static struct kmem_cache * affs_inode_cachep; | 98 | static struct kmem_cache * affs_inode_cachep; |
@@ -138,7 +156,6 @@ static const struct super_operations affs_sops = { | |||
138 | .write_inode = affs_write_inode, | 156 | .write_inode = affs_write_inode, |
139 | .evict_inode = affs_evict_inode, | 157 | .evict_inode = affs_evict_inode, |
140 | .put_super = affs_put_super, | 158 | .put_super = affs_put_super, |
141 | .write_super = affs_write_super, | ||
142 | .sync_fs = affs_sync_fs, | 159 | .sync_fs = affs_sync_fs, |
143 | .statfs = affs_statfs, | 160 | .statfs = affs_statfs, |
144 | .remount_fs = affs_remount, | 161 | .remount_fs = affs_remount, |
@@ -305,8 +322,11 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent) | |||
305 | return -ENOMEM; | 322 | return -ENOMEM; |
306 | 323 | ||
307 | sb->s_fs_info = sbi; | 324 | sb->s_fs_info = sbi; |
325 | sbi->sb = sb; | ||
308 | mutex_init(&sbi->s_bmlock); | 326 | mutex_init(&sbi->s_bmlock); |
309 | spin_lock_init(&sbi->symlink_lock); | 327 | spin_lock_init(&sbi->symlink_lock); |
328 | spin_lock_init(&sbi->work_lock); | ||
329 | INIT_DELAYED_WORK(&sbi->sb_work, flush_superblock); | ||
310 | 330 | ||
311 | if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, | 331 | if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, |
312 | &blocksize,&sbi->s_prefix, | 332 | &blocksize,&sbi->s_prefix, |
@@ -531,6 +551,7 @@ affs_remount(struct super_block *sb, int *flags, char *data) | |||
531 | return -EINVAL; | 551 | return -EINVAL; |
532 | } | 552 | } |
533 | 553 | ||
554 | flush_delayed_work_sync(&sbi->sb_work); | ||
534 | replace_mount_options(sb, new_opts); | 555 | replace_mount_options(sb, new_opts); |
535 | 556 | ||
536 | sbi->s_flags = mount_flags; | 557 | sbi->s_flags = mount_flags; |
@@ -549,10 +570,9 @@ affs_remount(struct super_block *sb, int *flags, char *data) | |||
549 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) | 570 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) |
550 | return 0; | 571 | return 0; |
551 | 572 | ||
552 | if (*flags & MS_RDONLY) { | 573 | if (*flags & MS_RDONLY) |
553 | affs_write_super(sb); | ||
554 | affs_free_bitmap(sb); | 574 | affs_free_bitmap(sb); |
555 | } else | 575 | else |
556 | res = affs_init_bitmap(sb, flags); | 576 | res = affs_init_bitmap(sb, flags); |
557 | 577 | ||
558 | return res; | 578 | return res; |
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index e22dc4b4a503..db477906ba4f 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
@@ -20,16 +20,16 @@ | |||
20 | #include "internal.h" | 20 | #include "internal.h" |
21 | 21 | ||
22 | static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, | 22 | static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, |
23 | struct nameidata *nd); | 23 | unsigned int flags); |
24 | static int afs_dir_open(struct inode *inode, struct file *file); | 24 | static int afs_dir_open(struct inode *inode, struct file *file); |
25 | static int afs_readdir(struct file *file, void *dirent, filldir_t filldir); | 25 | static int afs_readdir(struct file *file, void *dirent, filldir_t filldir); |
26 | static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd); | 26 | static int afs_d_revalidate(struct dentry *dentry, unsigned int flags); |
27 | static int afs_d_delete(const struct dentry *dentry); | 27 | static int afs_d_delete(const struct dentry *dentry); |
28 | static void afs_d_release(struct dentry *dentry); | 28 | static void afs_d_release(struct dentry *dentry); |
29 | static int afs_lookup_filldir(void *_cookie, const char *name, int nlen, | 29 | static int afs_lookup_filldir(void *_cookie, const char *name, int nlen, |
30 | loff_t fpos, u64 ino, unsigned dtype); | 30 | loff_t fpos, u64 ino, unsigned dtype); |
31 | static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 31 | static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
32 | struct nameidata *nd); | 32 | bool excl); |
33 | static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); | 33 | static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); |
34 | static int afs_rmdir(struct inode *dir, struct dentry *dentry); | 34 | static int afs_rmdir(struct inode *dir, struct dentry *dentry); |
35 | static int afs_unlink(struct inode *dir, struct dentry *dentry); | 35 | static int afs_unlink(struct inode *dir, struct dentry *dentry); |
@@ -516,7 +516,7 @@ out: | |||
516 | * look up an entry in a directory | 516 | * look up an entry in a directory |
517 | */ | 517 | */ |
518 | static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, | 518 | static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, |
519 | struct nameidata *nd) | 519 | unsigned int flags) |
520 | { | 520 | { |
521 | struct afs_vnode *vnode; | 521 | struct afs_vnode *vnode; |
522 | struct afs_fid fid; | 522 | struct afs_fid fid; |
@@ -598,7 +598,7 @@ success: | |||
598 | * - NOTE! the hit can be a negative hit too, so we can't assume we have an | 598 | * - NOTE! the hit can be a negative hit too, so we can't assume we have an |
599 | * inode | 599 | * inode |
600 | */ | 600 | */ |
601 | static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) | 601 | static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) |
602 | { | 602 | { |
603 | struct afs_vnode *vnode, *dir; | 603 | struct afs_vnode *vnode, *dir; |
604 | struct afs_fid uninitialized_var(fid); | 604 | struct afs_fid uninitialized_var(fid); |
@@ -607,7 +607,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
607 | void *dir_version; | 607 | void *dir_version; |
608 | int ret; | 608 | int ret; |
609 | 609 | ||
610 | if (nd->flags & LOOKUP_RCU) | 610 | if (flags & LOOKUP_RCU) |
611 | return -ECHILD; | 611 | return -ECHILD; |
612 | 612 | ||
613 | vnode = AFS_FS_I(dentry->d_inode); | 613 | vnode = AFS_FS_I(dentry->d_inode); |
@@ -949,7 +949,7 @@ error: | |||
949 | * create a regular file on an AFS filesystem | 949 | * create a regular file on an AFS filesystem |
950 | */ | 950 | */ |
951 | static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 951 | static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
952 | struct nameidata *nd) | 952 | bool excl) |
953 | { | 953 | { |
954 | struct afs_file_status status; | 954 | struct afs_file_status status; |
955 | struct afs_callback cb; | 955 | struct afs_callback cb; |
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index 298cf8919ec7..9682c33d5daf 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c | |||
@@ -22,7 +22,7 @@ | |||
22 | 22 | ||
23 | static struct dentry *afs_mntpt_lookup(struct inode *dir, | 23 | static struct dentry *afs_mntpt_lookup(struct inode *dir, |
24 | struct dentry *dentry, | 24 | struct dentry *dentry, |
25 | struct nameidata *nd); | 25 | unsigned int flags); |
26 | static int afs_mntpt_open(struct inode *inode, struct file *file); | 26 | static int afs_mntpt_open(struct inode *inode, struct file *file); |
27 | static void afs_mntpt_expiry_timed_out(struct work_struct *work); | 27 | static void afs_mntpt_expiry_timed_out(struct work_struct *work); |
28 | 28 | ||
@@ -104,7 +104,7 @@ out: | |||
104 | */ | 104 | */ |
105 | static struct dentry *afs_mntpt_lookup(struct inode *dir, | 105 | static struct dentry *afs_mntpt_lookup(struct inode *dir, |
106 | struct dentry *dentry, | 106 | struct dentry *dentry, |
107 | struct nameidata *nd) | 107 | unsigned int flags) |
108 | { | 108 | { |
109 | _enter("%p,%p{%p{%s},%s}", | 109 | _enter("%p,%p{%p{%s},%s}", |
110 | dir, | 110 | dir, |
diff --git a/fs/afs/super.c b/fs/afs/super.c index f02b31e7e648..df8c6047c2a1 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
@@ -395,7 +395,7 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, | |||
395 | as->volume = vol; | 395 | as->volume = vol; |
396 | 396 | ||
397 | /* allocate a deviceless superblock */ | 397 | /* allocate a deviceless superblock */ |
398 | sb = sget(fs_type, afs_test_super, afs_set_super, as); | 398 | sb = sget(fs_type, afs_test_super, afs_set_super, flags, as); |
399 | if (IS_ERR(sb)) { | 399 | if (IS_ERR(sb)) { |
400 | ret = PTR_ERR(sb); | 400 | ret = PTR_ERR(sb); |
401 | afs_put_volume(vol); | 401 | afs_put_volume(vol); |
@@ -406,7 +406,6 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, | |||
406 | if (!sb->s_root) { | 406 | if (!sb->s_root) { |
407 | /* initial superblock/root creation */ | 407 | /* initial superblock/root creation */ |
408 | _debug("create"); | 408 | _debug("create"); |
409 | sb->s_flags = flags; | ||
410 | ret = afs_fill_super(sb, ¶ms); | 409 | ret = afs_fill_super(sb, ¶ms); |
411 | if (ret < 0) { | 410 | if (ret < 0) { |
412 | deactivate_locked_super(sb); | 411 | deactivate_locked_super(sb); |
@@ -56,13 +56,6 @@ static struct kmem_cache *kioctx_cachep; | |||
56 | 56 | ||
57 | static struct workqueue_struct *aio_wq; | 57 | static struct workqueue_struct *aio_wq; |
58 | 58 | ||
59 | /* Used for rare fput completion. */ | ||
60 | static void aio_fput_routine(struct work_struct *); | ||
61 | static DECLARE_WORK(fput_work, aio_fput_routine); | ||
62 | |||
63 | static DEFINE_SPINLOCK(fput_lock); | ||
64 | static LIST_HEAD(fput_head); | ||
65 | |||
66 | static void aio_kick_handler(struct work_struct *); | 59 | static void aio_kick_handler(struct work_struct *); |
67 | static void aio_queue_work(struct kioctx *); | 60 | static void aio_queue_work(struct kioctx *); |
68 | 61 | ||
@@ -479,7 +472,6 @@ static int kiocb_batch_refill(struct kioctx *ctx, struct kiocb_batch *batch) | |||
479 | { | 472 | { |
480 | unsigned short allocated, to_alloc; | 473 | unsigned short allocated, to_alloc; |
481 | long avail; | 474 | long avail; |
482 | bool called_fput = false; | ||
483 | struct kiocb *req, *n; | 475 | struct kiocb *req, *n; |
484 | struct aio_ring *ring; | 476 | struct aio_ring *ring; |
485 | 477 | ||
@@ -495,28 +487,11 @@ static int kiocb_batch_refill(struct kioctx *ctx, struct kiocb_batch *batch) | |||
495 | if (allocated == 0) | 487 | if (allocated == 0) |
496 | goto out; | 488 | goto out; |
497 | 489 | ||
498 | retry: | ||
499 | spin_lock_irq(&ctx->ctx_lock); | 490 | spin_lock_irq(&ctx->ctx_lock); |
500 | ring = kmap_atomic(ctx->ring_info.ring_pages[0]); | 491 | ring = kmap_atomic(ctx->ring_info.ring_pages[0]); |
501 | 492 | ||
502 | avail = aio_ring_avail(&ctx->ring_info, ring) - ctx->reqs_active; | 493 | avail = aio_ring_avail(&ctx->ring_info, ring) - ctx->reqs_active; |
503 | BUG_ON(avail < 0); | 494 | BUG_ON(avail < 0); |
504 | if (avail == 0 && !called_fput) { | ||
505 | /* | ||
506 | * Handle a potential starvation case. It is possible that | ||
507 | * we hold the last reference on a struct file, causing us | ||
508 | * to delay the final fput to non-irq context. In this case, | ||
509 | * ctx->reqs_active is artificially high. Calling the fput | ||
510 | * routine here may free up a slot in the event completion | ||
511 | * ring, allowing this allocation to succeed. | ||
512 | */ | ||
513 | kunmap_atomic(ring); | ||
514 | spin_unlock_irq(&ctx->ctx_lock); | ||
515 | aio_fput_routine(NULL); | ||
516 | called_fput = true; | ||
517 | goto retry; | ||
518 | } | ||
519 | |||
520 | if (avail < allocated) { | 495 | if (avail < allocated) { |
521 | /* Trim back the number of requests. */ | 496 | /* Trim back the number of requests. */ |
522 | list_for_each_entry_safe(req, n, &batch->head, ki_batch) { | 497 | list_for_each_entry_safe(req, n, &batch->head, ki_batch) { |
@@ -570,36 +545,6 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) | |||
570 | wake_up_all(&ctx->wait); | 545 | wake_up_all(&ctx->wait); |
571 | } | 546 | } |
572 | 547 | ||
573 | static void aio_fput_routine(struct work_struct *data) | ||
574 | { | ||
575 | spin_lock_irq(&fput_lock); | ||
576 | while (likely(!list_empty(&fput_head))) { | ||
577 | struct kiocb *req = list_kiocb(fput_head.next); | ||
578 | struct kioctx *ctx = req->ki_ctx; | ||
579 | |||
580 | list_del(&req->ki_list); | ||
581 | spin_unlock_irq(&fput_lock); | ||
582 | |||
583 | /* Complete the fput(s) */ | ||
584 | if (req->ki_filp != NULL) | ||
585 | fput(req->ki_filp); | ||
586 | |||
587 | /* Link the iocb into the context's free list */ | ||
588 | rcu_read_lock(); | ||
589 | spin_lock_irq(&ctx->ctx_lock); | ||
590 | really_put_req(ctx, req); | ||
591 | /* | ||
592 | * at that point ctx might've been killed, but actual | ||
593 | * freeing is RCU'd | ||
594 | */ | ||
595 | spin_unlock_irq(&ctx->ctx_lock); | ||
596 | rcu_read_unlock(); | ||
597 | |||
598 | spin_lock_irq(&fput_lock); | ||
599 | } | ||
600 | spin_unlock_irq(&fput_lock); | ||
601 | } | ||
602 | |||
603 | /* __aio_put_req | 548 | /* __aio_put_req |
604 | * Returns true if this put was the last user of the request. | 549 | * Returns true if this put was the last user of the request. |
605 | */ | 550 | */ |
@@ -618,21 +563,9 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req) | |||
618 | req->ki_cancel = NULL; | 563 | req->ki_cancel = NULL; |
619 | req->ki_retry = NULL; | 564 | req->ki_retry = NULL; |
620 | 565 | ||
621 | /* | 566 | fput(req->ki_filp); |
622 | * Try to optimize the aio and eventfd file* puts, by avoiding to | 567 | req->ki_filp = NULL; |
623 | * schedule work in case it is not final fput() time. In normal cases, | 568 | really_put_req(ctx, req); |
624 | * we would not be holding the last reference to the file*, so | ||
625 | * this function will be executed w/out any aio kthread wakeup. | ||
626 | */ | ||
627 | if (unlikely(!fput_atomic(req->ki_filp))) { | ||
628 | spin_lock(&fput_lock); | ||
629 | list_add(&req->ki_list, &fput_head); | ||
630 | spin_unlock(&fput_lock); | ||
631 | schedule_work(&fput_work); | ||
632 | } else { | ||
633 | req->ki_filp = NULL; | ||
634 | really_put_req(ctx, req); | ||
635 | } | ||
636 | return 1; | 569 | return 1; |
637 | } | 570 | } |
638 | 571 | ||
@@ -171,6 +171,8 @@ int notify_change(struct dentry * dentry, struct iattr * attr) | |||
171 | struct timespec now; | 171 | struct timespec now; |
172 | unsigned int ia_valid = attr->ia_valid; | 172 | unsigned int ia_valid = attr->ia_valid; |
173 | 173 | ||
174 | WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex)); | ||
175 | |||
174 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_TIMES_SET)) { | 176 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_TIMES_SET)) { |
175 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 177 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
176 | return -EPERM; | 178 | return -EPERM; |
@@ -250,5 +252,4 @@ int notify_change(struct dentry * dentry, struct iattr * attr) | |||
250 | 252 | ||
251 | return error; | 253 | return error; |
252 | } | 254 | } |
253 | |||
254 | EXPORT_SYMBOL(notify_change); | 255 | EXPORT_SYMBOL(notify_change); |
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index aa9103f8f01b..abf645c1703b 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c | |||
@@ -257,8 +257,8 @@ static int autofs_dev_ioctl_open_mountpoint(const char *name, dev_t devid) | |||
257 | * corresponding to the autofs fs we want to open. | 257 | * corresponding to the autofs fs we want to open. |
258 | */ | 258 | */ |
259 | 259 | ||
260 | filp = dentry_open(path.dentry, path.mnt, O_RDONLY, | 260 | filp = dentry_open(&path, O_RDONLY, current_cred()); |
261 | current_cred()); | 261 | path_put(&path); |
262 | if (IS_ERR(filp)) { | 262 | if (IS_ERR(filp)) { |
263 | err = PTR_ERR(filp); | 263 | err = PTR_ERR(filp); |
264 | goto out; | 264 | goto out; |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 75e5f1c8e028..e7396cfdb109 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -32,7 +32,7 @@ static long autofs4_root_ioctl(struct file *,unsigned int,unsigned long); | |||
32 | static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long); | 32 | static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long); |
33 | #endif | 33 | #endif |
34 | static int autofs4_dir_open(struct inode *inode, struct file *file); | 34 | static int autofs4_dir_open(struct inode *inode, struct file *file); |
35 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); | 35 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, unsigned int); |
36 | static struct vfsmount *autofs4_d_automount(struct path *); | 36 | static struct vfsmount *autofs4_d_automount(struct path *); |
37 | static int autofs4_d_manage(struct dentry *, bool); | 37 | static int autofs4_d_manage(struct dentry *, bool); |
38 | static void autofs4_dentry_release(struct dentry *); | 38 | static void autofs4_dentry_release(struct dentry *); |
@@ -458,7 +458,7 @@ int autofs4_d_manage(struct dentry *dentry, bool rcu_walk) | |||
458 | } | 458 | } |
459 | 459 | ||
460 | /* Lookups in the root directory */ | 460 | /* Lookups in the root directory */ |
461 | static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 461 | static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
462 | { | 462 | { |
463 | struct autofs_sb_info *sbi; | 463 | struct autofs_sb_info *sbi; |
464 | struct autofs_info *ino; | 464 | struct autofs_info *ino; |
diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 1b35d6bd06b0..b1342ffb3cf6 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c | |||
@@ -173,13 +173,13 @@ static const struct file_operations bad_file_ops = | |||
173 | }; | 173 | }; |
174 | 174 | ||
175 | static int bad_inode_create (struct inode *dir, struct dentry *dentry, | 175 | static int bad_inode_create (struct inode *dir, struct dentry *dentry, |
176 | umode_t mode, struct nameidata *nd) | 176 | umode_t mode, bool excl) |
177 | { | 177 | { |
178 | return -EIO; | 178 | return -EIO; |
179 | } | 179 | } |
180 | 180 | ||
181 | static struct dentry *bad_inode_lookup(struct inode *dir, | 181 | static struct dentry *bad_inode_lookup(struct inode *dir, |
182 | struct dentry *dentry, struct nameidata *nd) | 182 | struct dentry *dentry, unsigned int flags) |
183 | { | 183 | { |
184 | return ERR_PTR(-EIO); | 184 | return ERR_PTR(-EIO); |
185 | } | 185 | } |
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index e18da23d42b5..cf7f3c67c8b7 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c | |||
@@ -34,7 +34,7 @@ static int befs_readdir(struct file *, void *, filldir_t); | |||
34 | static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int); | 34 | static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int); |
35 | static int befs_readpage(struct file *file, struct page *page); | 35 | static int befs_readpage(struct file *file, struct page *page); |
36 | static sector_t befs_bmap(struct address_space *mapping, sector_t block); | 36 | static sector_t befs_bmap(struct address_space *mapping, sector_t block); |
37 | static struct dentry *befs_lookup(struct inode *, struct dentry *, struct nameidata *); | 37 | static struct dentry *befs_lookup(struct inode *, struct dentry *, unsigned int); |
38 | static struct inode *befs_iget(struct super_block *, unsigned long); | 38 | static struct inode *befs_iget(struct super_block *, unsigned long); |
39 | static struct inode *befs_alloc_inode(struct super_block *sb); | 39 | static struct inode *befs_alloc_inode(struct super_block *sb); |
40 | static void befs_destroy_inode(struct inode *inode); | 40 | static void befs_destroy_inode(struct inode *inode); |
@@ -159,7 +159,7 @@ befs_get_block(struct inode *inode, sector_t block, | |||
159 | } | 159 | } |
160 | 160 | ||
161 | static struct dentry * | 161 | static struct dentry * |
162 | befs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 162 | befs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
163 | { | 163 | { |
164 | struct inode *inode = NULL; | 164 | struct inode *inode = NULL; |
165 | struct super_block *sb = dir->i_sb; | 165 | struct super_block *sb = dir->i_sb; |
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index d12c7966db27..2785ef91191a 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c | |||
@@ -85,7 +85,7 @@ const struct file_operations bfs_dir_operations = { | |||
85 | extern void dump_imap(const char *, struct super_block *); | 85 | extern void dump_imap(const char *, struct super_block *); |
86 | 86 | ||
87 | static int bfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 87 | static int bfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
88 | struct nameidata *nd) | 88 | bool excl) |
89 | { | 89 | { |
90 | int err; | 90 | int err; |
91 | struct inode *inode; | 91 | struct inode *inode; |
@@ -133,7 +133,7 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
133 | } | 133 | } |
134 | 134 | ||
135 | static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry, | 135 | static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry, |
136 | struct nameidata *nd) | 136 | unsigned int flags) |
137 | { | 137 | { |
138 | struct inode *inode = NULL; | 138 | struct inode *inode = NULL; |
139 | struct buffer_head *bh; | 139 | struct buffer_head *bh; |
diff --git a/fs/block_dev.c b/fs/block_dev.c index c2bbe1fb1326..1e519195d45b 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -1710,3 +1710,39 @@ int __invalidate_device(struct block_device *bdev, bool kill_dirty) | |||
1710 | return res; | 1710 | return res; |
1711 | } | 1711 | } |
1712 | EXPORT_SYMBOL(__invalidate_device); | 1712 | EXPORT_SYMBOL(__invalidate_device); |
1713 | |||
1714 | void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg) | ||
1715 | { | ||
1716 | struct inode *inode, *old_inode = NULL; | ||
1717 | |||
1718 | spin_lock(&inode_sb_list_lock); | ||
1719 | list_for_each_entry(inode, &blockdev_superblock->s_inodes, i_sb_list) { | ||
1720 | struct address_space *mapping = inode->i_mapping; | ||
1721 | |||
1722 | spin_lock(&inode->i_lock); | ||
1723 | if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW) || | ||
1724 | mapping->nrpages == 0) { | ||
1725 | spin_unlock(&inode->i_lock); | ||
1726 | continue; | ||
1727 | } | ||
1728 | __iget(inode); | ||
1729 | spin_unlock(&inode->i_lock); | ||
1730 | spin_unlock(&inode_sb_list_lock); | ||
1731 | /* | ||
1732 | * We hold a reference to 'inode' so it couldn't have been | ||
1733 | * removed from s_inodes list while we dropped the | ||
1734 | * inode_sb_list_lock. We cannot iput the inode now as we can | ||
1735 | * be holding the last reference and we cannot iput it under | ||
1736 | * inode_sb_list_lock. So we keep the reference and iput it | ||
1737 | * later. | ||
1738 | */ | ||
1739 | iput(old_inode); | ||
1740 | old_inode = inode; | ||
1741 | |||
1742 | func(I_BDEV(inode), arg); | ||
1743 | |||
1744 | spin_lock(&inode_sb_list_lock); | ||
1745 | } | ||
1746 | spin_unlock(&inode_sb_list_lock); | ||
1747 | iput(old_inode); | ||
1748 | } | ||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index a7d1921ac76b..fb8d671d00e6 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -4247,7 +4247,7 @@ static void btrfs_dentry_release(struct dentry *dentry) | |||
4247 | } | 4247 | } |
4248 | 4248 | ||
4249 | static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | 4249 | static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, |
4250 | struct nameidata *nd) | 4250 | unsigned int flags) |
4251 | { | 4251 | { |
4252 | struct dentry *ret; | 4252 | struct dentry *ret; |
4253 | 4253 | ||
@@ -4893,7 +4893,7 @@ out_unlock: | |||
4893 | } | 4893 | } |
4894 | 4894 | ||
4895 | static int btrfs_create(struct inode *dir, struct dentry *dentry, | 4895 | static int btrfs_create(struct inode *dir, struct dentry *dentry, |
4896 | umode_t mode, struct nameidata *nd) | 4896 | umode_t mode, bool excl) |
4897 | { | 4897 | { |
4898 | struct btrfs_trans_handle *trans; | 4898 | struct btrfs_trans_handle *trans; |
4899 | struct btrfs_root *root = BTRFS_I(dir)->root; | 4899 | struct btrfs_root *root = BTRFS_I(dir)->root; |
@@ -6987,7 +6987,7 @@ void btrfs_destroy_inode(struct inode *inode) | |||
6987 | struct btrfs_ordered_extent *ordered; | 6987 | struct btrfs_ordered_extent *ordered; |
6988 | struct btrfs_root *root = BTRFS_I(inode)->root; | 6988 | struct btrfs_root *root = BTRFS_I(inode)->root; |
6989 | 6989 | ||
6990 | WARN_ON(!list_empty(&inode->i_dentry)); | 6990 | WARN_ON(!hlist_empty(&inode->i_dentry)); |
6991 | WARN_ON(inode->i_data.nrpages); | 6991 | WARN_ON(inode->i_data.nrpages); |
6992 | WARN_ON(BTRFS_I(inode)->outstanding_extents); | 6992 | WARN_ON(BTRFS_I(inode)->outstanding_extents); |
6993 | WARN_ON(BTRFS_I(inode)->reserved_extents); | 6993 | WARN_ON(BTRFS_I(inode)->reserved_extents); |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 0e92e5763005..1e9f6c019ad0 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -3268,7 +3268,7 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) | |||
3268 | if (fs_info->sb->s_flags & MS_RDONLY) | 3268 | if (fs_info->sb->s_flags & MS_RDONLY) |
3269 | return -EROFS; | 3269 | return -EROFS; |
3270 | 3270 | ||
3271 | ret = mnt_want_write(file->f_path.mnt); | 3271 | ret = mnt_want_write_file(file); |
3272 | if (ret) | 3272 | if (ret) |
3273 | return ret; | 3273 | return ret; |
3274 | 3274 | ||
@@ -3338,7 +3338,7 @@ out_bargs: | |||
3338 | out: | 3338 | out: |
3339 | mutex_unlock(&fs_info->balance_mutex); | 3339 | mutex_unlock(&fs_info->balance_mutex); |
3340 | mutex_unlock(&fs_info->volume_mutex); | 3340 | mutex_unlock(&fs_info->volume_mutex); |
3341 | mnt_drop_write(file->f_path.mnt); | 3341 | mnt_drop_write_file(file); |
3342 | return ret; | 3342 | return ret; |
3343 | } | 3343 | } |
3344 | 3344 | ||
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index e23991574fdf..b19d75567728 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -1068,7 +1068,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
1068 | } | 1068 | } |
1069 | 1069 | ||
1070 | bdev = fs_devices->latest_bdev; | 1070 | bdev = fs_devices->latest_bdev; |
1071 | s = sget(fs_type, btrfs_test_super, btrfs_set_super, fs_info); | 1071 | s = sget(fs_type, btrfs_test_super, btrfs_set_super, flags | MS_NOSEC, |
1072 | fs_info); | ||
1072 | if (IS_ERR(s)) { | 1073 | if (IS_ERR(s)) { |
1073 | error = PTR_ERR(s); | 1074 | error = PTR_ERR(s); |
1074 | goto error_close_devices; | 1075 | goto error_close_devices; |
@@ -1082,7 +1083,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
1082 | } else { | 1083 | } else { |
1083 | char b[BDEVNAME_SIZE]; | 1084 | char b[BDEVNAME_SIZE]; |
1084 | 1085 | ||
1085 | s->s_flags = flags | MS_NOSEC; | ||
1086 | strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); | 1086 | strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); |
1087 | btrfs_sb(s)->bdev_holder = fs_type; | 1087 | btrfs_sb(s)->bdev_holder = fs_type; |
1088 | error = btrfs_fill_super(s, fs_devices, data, | 1088 | error = btrfs_fill_super(s, fs_devices, data, |
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 7f0771d3894e..b0b5f7cdfffa 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c | |||
@@ -567,7 +567,7 @@ lookup_again: | |||
567 | if (ret < 0) | 567 | if (ret < 0) |
568 | goto create_error; | 568 | goto create_error; |
569 | start = jiffies; | 569 | start = jiffies; |
570 | ret = vfs_create(dir->d_inode, next, S_IFREG, NULL); | 570 | ret = vfs_create(dir->d_inode, next, S_IFREG, true); |
571 | cachefiles_hist(cachefiles_create_histogram, start); | 571 | cachefiles_hist(cachefiles_create_histogram, start); |
572 | if (ret < 0) | 572 | if (ret < 0) |
573 | goto create_error; | 573 | goto create_error; |
diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c index 0e3c0924cc3a..c0353dfac51f 100644 --- a/fs/cachefiles/rdwr.c +++ b/fs/cachefiles/rdwr.c | |||
@@ -891,6 +891,7 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page) | |||
891 | struct cachefiles_cache *cache; | 891 | struct cachefiles_cache *cache; |
892 | mm_segment_t old_fs; | 892 | mm_segment_t old_fs; |
893 | struct file *file; | 893 | struct file *file; |
894 | struct path path; | ||
894 | loff_t pos, eof; | 895 | loff_t pos, eof; |
895 | size_t len; | 896 | size_t len; |
896 | void *data; | 897 | void *data; |
@@ -916,10 +917,9 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page) | |||
916 | 917 | ||
917 | /* write the page to the backing filesystem and let it store it in its | 918 | /* write the page to the backing filesystem and let it store it in its |
918 | * own time */ | 919 | * own time */ |
919 | dget(object->backer); | 920 | path.mnt = cache->mnt; |
920 | mntget(cache->mnt); | 921 | path.dentry = object->backer; |
921 | file = dentry_open(object->backer, cache->mnt, O_RDWR, | 922 | file = dentry_open(&path, O_RDWR, cache->cache_cred); |
922 | cache->cache_cred); | ||
923 | if (IS_ERR(file)) { | 923 | if (IS_ERR(file)) { |
924 | ret = PTR_ERR(file); | 924 | ret = PTR_ERR(file); |
925 | } else { | 925 | } else { |
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 3e8094be4604..00894ff9246c 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -576,7 +576,7 @@ static int is_root_ceph_dentry(struct inode *inode, struct dentry *dentry) | |||
576 | * the MDS so that it gets our 'caps wanted' value in a single op. | 576 | * the MDS so that it gets our 'caps wanted' value in a single op. |
577 | */ | 577 | */ |
578 | static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, | 578 | static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, |
579 | struct nameidata *nd) | 579 | unsigned int flags) |
580 | { | 580 | { |
581 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); | 581 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); |
582 | struct ceph_mds_client *mdsc = fsc->mdsc; | 582 | struct ceph_mds_client *mdsc = fsc->mdsc; |
@@ -594,14 +594,6 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, | |||
594 | if (err < 0) | 594 | if (err < 0) |
595 | return ERR_PTR(err); | 595 | return ERR_PTR(err); |
596 | 596 | ||
597 | /* open (but not create!) intent? */ | ||
598 | if (nd && | ||
599 | (nd->flags & LOOKUP_OPEN) && | ||
600 | !(nd->intent.open.flags & O_CREAT)) { | ||
601 | int mode = nd->intent.open.create_mode & ~current->fs->umask; | ||
602 | return ceph_lookup_open(dir, dentry, nd, mode, 1); | ||
603 | } | ||
604 | |||
605 | /* can we conclude ENOENT locally? */ | 597 | /* can we conclude ENOENT locally? */ |
606 | if (dentry->d_inode == NULL) { | 598 | if (dentry->d_inode == NULL) { |
607 | struct ceph_inode_info *ci = ceph_inode(dir); | 599 | struct ceph_inode_info *ci = ceph_inode(dir); |
@@ -642,13 +634,51 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, | |||
642 | return dentry; | 634 | return dentry; |
643 | } | 635 | } |
644 | 636 | ||
637 | int ceph_atomic_open(struct inode *dir, struct dentry *dentry, | ||
638 | struct file *file, unsigned flags, umode_t mode, | ||
639 | int *opened) | ||
640 | { | ||
641 | int err; | ||
642 | struct dentry *res = NULL; | ||
643 | |||
644 | if (!(flags & O_CREAT)) { | ||
645 | if (dentry->d_name.len > NAME_MAX) | ||
646 | return -ENAMETOOLONG; | ||
647 | |||
648 | err = ceph_init_dentry(dentry); | ||
649 | if (err < 0) | ||
650 | return err; | ||
651 | |||
652 | return ceph_lookup_open(dir, dentry, file, flags, mode, opened); | ||
653 | } | ||
654 | |||
655 | if (d_unhashed(dentry)) { | ||
656 | res = ceph_lookup(dir, dentry, 0); | ||
657 | if (IS_ERR(res)) | ||
658 | return PTR_ERR(res); | ||
659 | |||
660 | if (res) | ||
661 | dentry = res; | ||
662 | } | ||
663 | |||
664 | /* We don't deal with positive dentries here */ | ||
665 | if (dentry->d_inode) | ||
666 | return finish_no_open(file, res); | ||
667 | |||
668 | *opened |= FILE_CREATED; | ||
669 | err = ceph_lookup_open(dir, dentry, file, flags, mode, opened); | ||
670 | dput(res); | ||
671 | |||
672 | return err; | ||
673 | } | ||
674 | |||
645 | /* | 675 | /* |
646 | * If we do a create but get no trace back from the MDS, follow up with | 676 | * If we do a create but get no trace back from the MDS, follow up with |
647 | * a lookup (the VFS expects us to link up the provided dentry). | 677 | * a lookup (the VFS expects us to link up the provided dentry). |
648 | */ | 678 | */ |
649 | int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry) | 679 | int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry) |
650 | { | 680 | { |
651 | struct dentry *result = ceph_lookup(dir, dentry, NULL); | 681 | struct dentry *result = ceph_lookup(dir, dentry, 0); |
652 | 682 | ||
653 | if (result && !IS_ERR(result)) { | 683 | if (result && !IS_ERR(result)) { |
654 | /* | 684 | /* |
@@ -700,25 +730,9 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry, | |||
700 | } | 730 | } |
701 | 731 | ||
702 | static int ceph_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 732 | static int ceph_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
703 | struct nameidata *nd) | 733 | bool excl) |
704 | { | 734 | { |
705 | dout("create in dir %p dentry %p name '%.*s'\n", | 735 | return ceph_mknod(dir, dentry, mode, 0); |
706 | dir, dentry, dentry->d_name.len, dentry->d_name.name); | ||
707 | |||
708 | if (ceph_snap(dir) != CEPH_NOSNAP) | ||
709 | return -EROFS; | ||
710 | |||
711 | if (nd) { | ||
712 | BUG_ON((nd->flags & LOOKUP_OPEN) == 0); | ||
713 | dentry = ceph_lookup_open(dir, dentry, nd, mode, 0); | ||
714 | /* hrm, what should i do here if we get aliased? */ | ||
715 | if (IS_ERR(dentry)) | ||
716 | return PTR_ERR(dentry); | ||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | /* fall back to mknod */ | ||
721 | return ceph_mknod(dir, dentry, (mode & ~S_IFMT) | S_IFREG, 0); | ||
722 | } | 736 | } |
723 | 737 | ||
724 | static int ceph_symlink(struct inode *dir, struct dentry *dentry, | 738 | static int ceph_symlink(struct inode *dir, struct dentry *dentry, |
@@ -1028,12 +1042,12 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry) | |||
1028 | /* | 1042 | /* |
1029 | * Check if cached dentry can be trusted. | 1043 | * Check if cached dentry can be trusted. |
1030 | */ | 1044 | */ |
1031 | static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd) | 1045 | static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags) |
1032 | { | 1046 | { |
1033 | int valid = 0; | 1047 | int valid = 0; |
1034 | struct inode *dir; | 1048 | struct inode *dir; |
1035 | 1049 | ||
1036 | if (nd && nd->flags & LOOKUP_RCU) | 1050 | if (flags & LOOKUP_RCU) |
1037 | return -ECHILD; | 1051 | return -ECHILD; |
1038 | 1052 | ||
1039 | dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry, | 1053 | dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry, |
@@ -1080,7 +1094,7 @@ static void ceph_d_release(struct dentry *dentry) | |||
1080 | } | 1094 | } |
1081 | 1095 | ||
1082 | static int ceph_snapdir_d_revalidate(struct dentry *dentry, | 1096 | static int ceph_snapdir_d_revalidate(struct dentry *dentry, |
1083 | struct nameidata *nd) | 1097 | unsigned int flags) |
1084 | { | 1098 | { |
1085 | /* | 1099 | /* |
1086 | * Eventually, we'll want to revalidate snapped metadata | 1100 | * Eventually, we'll want to revalidate snapped metadata |
@@ -1357,6 +1371,7 @@ const struct inode_operations ceph_dir_iops = { | |||
1357 | .rmdir = ceph_unlink, | 1371 | .rmdir = ceph_unlink, |
1358 | .rename = ceph_rename, | 1372 | .rename = ceph_rename, |
1359 | .create = ceph_create, | 1373 | .create = ceph_create, |
1374 | .atomic_open = ceph_atomic_open, | ||
1360 | }; | 1375 | }; |
1361 | 1376 | ||
1362 | const struct dentry_operations ceph_dentry_ops = { | 1377 | const struct dentry_operations ceph_dentry_ops = { |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 988d4f302e48..1b81d6c31878 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -213,22 +213,15 @@ out: | |||
213 | * may_open() fails, the struct *file gets cleaned up (i.e. | 213 | * may_open() fails, the struct *file gets cleaned up (i.e. |
214 | * ceph_release gets called). So fear not! | 214 | * ceph_release gets called). So fear not! |
215 | */ | 215 | */ |
216 | /* | 216 | int ceph_lookup_open(struct inode *dir, struct dentry *dentry, |
217 | * flags | 217 | struct file *file, unsigned flags, umode_t mode, |
218 | * path_lookup_open -> LOOKUP_OPEN | 218 | int *opened) |
219 | * path_lookup_create -> LOOKUP_OPEN|LOOKUP_CREATE | ||
220 | */ | ||
221 | struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry, | ||
222 | struct nameidata *nd, int mode, | ||
223 | int locked_dir) | ||
224 | { | 219 | { |
225 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); | 220 | struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); |
226 | struct ceph_mds_client *mdsc = fsc->mdsc; | 221 | struct ceph_mds_client *mdsc = fsc->mdsc; |
227 | struct file *file; | ||
228 | struct ceph_mds_request *req; | 222 | struct ceph_mds_request *req; |
229 | struct dentry *ret; | 223 | struct dentry *ret; |
230 | int err; | 224 | int err; |
231 | int flags = nd->intent.open.flags; | ||
232 | 225 | ||
233 | dout("ceph_lookup_open dentry %p '%.*s' flags %d mode 0%o\n", | 226 | dout("ceph_lookup_open dentry %p '%.*s' flags %d mode 0%o\n", |
234 | dentry, dentry->d_name.len, dentry->d_name.name, flags, mode); | 227 | dentry, dentry->d_name.len, dentry->d_name.name, flags, mode); |
@@ -236,7 +229,7 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry, | |||
236 | /* do the open */ | 229 | /* do the open */ |
237 | req = prepare_open_request(dir->i_sb, flags, mode); | 230 | req = prepare_open_request(dir->i_sb, flags, mode); |
238 | if (IS_ERR(req)) | 231 | if (IS_ERR(req)) |
239 | return ERR_CAST(req); | 232 | return PTR_ERR(req); |
240 | req->r_dentry = dget(dentry); | 233 | req->r_dentry = dget(dentry); |
241 | req->r_num_caps = 2; | 234 | req->r_num_caps = 2; |
242 | if (flags & O_CREAT) { | 235 | if (flags & O_CREAT) { |
@@ -254,14 +247,17 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry, | |||
254 | err = ceph_handle_notrace_create(dir, dentry); | 247 | err = ceph_handle_notrace_create(dir, dentry); |
255 | if (err) | 248 | if (err) |
256 | goto out; | 249 | goto out; |
257 | file = lookup_instantiate_filp(nd, req->r_dentry, ceph_open); | 250 | err = finish_open(file, req->r_dentry, ceph_open, opened); |
258 | if (IS_ERR(file)) | ||
259 | err = PTR_ERR(file); | ||
260 | out: | 251 | out: |
261 | ret = ceph_finish_lookup(req, dentry, err); | 252 | ret = ceph_finish_lookup(req, dentry, err); |
262 | ceph_mdsc_put_request(req); | 253 | ceph_mdsc_put_request(req); |
263 | dout("ceph_lookup_open result=%p\n", ret); | 254 | dout("ceph_lookup_open result=%p\n", ret); |
264 | return ret; | 255 | |
256 | if (IS_ERR(ret)) | ||
257 | return PTR_ERR(ret); | ||
258 | |||
259 | dput(ret); | ||
260 | return err; | ||
265 | } | 261 | } |
266 | 262 | ||
267 | int ceph_release(struct inode *inode, struct file *file) | 263 | int ceph_release(struct inode *inode, struct file *file) |
diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 1e67dd7305a4..7076109f014d 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c | |||
@@ -871,7 +871,7 @@ static struct dentry *ceph_mount(struct file_system_type *fs_type, | |||
871 | 871 | ||
872 | if (ceph_test_opt(fsc->client, NOSHARE)) | 872 | if (ceph_test_opt(fsc->client, NOSHARE)) |
873 | compare_super = NULL; | 873 | compare_super = NULL; |
874 | sb = sget(fs_type, compare_super, ceph_set_super, fsc); | 874 | sb = sget(fs_type, compare_super, ceph_set_super, flags, fsc); |
875 | if (IS_ERR(sb)) { | 875 | if (IS_ERR(sb)) { |
876 | res = ERR_CAST(sb); | 876 | res = ERR_CAST(sb); |
877 | goto out; | 877 | goto out; |
diff --git a/fs/ceph/super.h b/fs/ceph/super.h index fc35036d258d..f4d5522cb619 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h | |||
@@ -806,9 +806,9 @@ extern int ceph_copy_from_page_vector(struct page **pages, | |||
806 | loff_t off, size_t len); | 806 | loff_t off, size_t len); |
807 | extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags); | 807 | extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags); |
808 | extern int ceph_open(struct inode *inode, struct file *file); | 808 | extern int ceph_open(struct inode *inode, struct file *file); |
809 | extern struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry, | 809 | extern int ceph_lookup_open(struct inode *dir, struct dentry *dentry, |
810 | struct nameidata *nd, int mode, | 810 | struct file *od, unsigned flags, |
811 | int locked_dir); | 811 | umode_t mode, int *opened); |
812 | extern int ceph_release(struct inode *inode, struct file *filp); | 812 | extern int ceph_release(struct inode *inode, struct file *filp); |
813 | 813 | ||
814 | /* dir.c */ | 814 | /* dir.c */ |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 8b6e344eb0ba..a7610cfedf0a 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -257,7 +257,6 @@ cifs_alloc_inode(struct super_block *sb) | |||
257 | static void cifs_i_callback(struct rcu_head *head) | 257 | static void cifs_i_callback(struct rcu_head *head) |
258 | { | 258 | { |
259 | struct inode *inode = container_of(head, struct inode, i_rcu); | 259 | struct inode *inode = container_of(head, struct inode, i_rcu); |
260 | INIT_LIST_HEAD(&inode->i_dentry); | ||
261 | kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); | 260 | kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); |
262 | } | 261 | } |
263 | 262 | ||
@@ -638,7 +637,10 @@ cifs_do_mount(struct file_system_type *fs_type, | |||
638 | mnt_data.cifs_sb = cifs_sb; | 637 | mnt_data.cifs_sb = cifs_sb; |
639 | mnt_data.flags = flags; | 638 | mnt_data.flags = flags; |
640 | 639 | ||
641 | sb = sget(fs_type, cifs_match_super, cifs_set_super, &mnt_data); | 640 | /* BB should we make this contingent on mount parm? */ |
641 | flags |= MS_NODIRATIME | MS_NOATIME; | ||
642 | |||
643 | sb = sget(fs_type, cifs_match_super, cifs_set_super, flags, &mnt_data); | ||
642 | if (IS_ERR(sb)) { | 644 | if (IS_ERR(sb)) { |
643 | root = ERR_CAST(sb); | 645 | root = ERR_CAST(sb); |
644 | cifs_umount(cifs_sb); | 646 | cifs_umount(cifs_sb); |
@@ -649,10 +651,6 @@ cifs_do_mount(struct file_system_type *fs_type, | |||
649 | cFYI(1, "Use existing superblock"); | 651 | cFYI(1, "Use existing superblock"); |
650 | cifs_umount(cifs_sb); | 652 | cifs_umount(cifs_sb); |
651 | } else { | 653 | } else { |
652 | sb->s_flags = flags; | ||
653 | /* BB should we make this contingent on mount parm? */ | ||
654 | sb->s_flags |= MS_NODIRATIME | MS_NOATIME; | ||
655 | |||
656 | rc = cifs_read_super(sb); | 654 | rc = cifs_read_super(sb); |
657 | if (rc) { | 655 | if (rc) { |
658 | root = ERR_PTR(rc); | 656 | root = ERR_PTR(rc); |
@@ -778,6 +776,7 @@ struct file_system_type cifs_fs_type = { | |||
778 | }; | 776 | }; |
779 | const struct inode_operations cifs_dir_inode_ops = { | 777 | const struct inode_operations cifs_dir_inode_ops = { |
780 | .create = cifs_create, | 778 | .create = cifs_create, |
779 | .atomic_open = cifs_atomic_open, | ||
781 | .lookup = cifs_lookup, | 780 | .lookup = cifs_lookup, |
782 | .getattr = cifs_getattr, | 781 | .getattr = cifs_getattr, |
783 | .unlink = cifs_unlink, | 782 | .unlink = cifs_unlink, |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 65365358c976..1c49c5a9b27a 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -45,9 +45,12 @@ extern const struct address_space_operations cifs_addr_ops_smallbuf; | |||
45 | extern const struct inode_operations cifs_dir_inode_ops; | 45 | extern const struct inode_operations cifs_dir_inode_ops; |
46 | extern struct inode *cifs_root_iget(struct super_block *); | 46 | extern struct inode *cifs_root_iget(struct super_block *); |
47 | extern int cifs_create(struct inode *, struct dentry *, umode_t, | 47 | extern int cifs_create(struct inode *, struct dentry *, umode_t, |
48 | struct nameidata *); | 48 | bool excl); |
49 | extern int cifs_atomic_open(struct inode *, struct dentry *, | ||
50 | struct file *, unsigned, umode_t, | ||
51 | int *); | ||
49 | extern struct dentry *cifs_lookup(struct inode *, struct dentry *, | 52 | extern struct dentry *cifs_lookup(struct inode *, struct dentry *, |
50 | struct nameidata *); | 53 | unsigned int); |
51 | extern int cifs_unlink(struct inode *dir, struct dentry *dentry); | 54 | extern int cifs_unlink(struct inode *dir, struct dentry *dentry); |
52 | extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *); | 55 | extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *); |
53 | extern int cifs_mknod(struct inode *, struct dentry *, umode_t, dev_t); | 56 | extern int cifs_mknod(struct inode *, struct dentry *, umode_t, dev_t); |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index ec4e9a2a12f8..a180265a10b5 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -133,108 +133,141 @@ cifs_bp_rename_retry: | |||
133 | return full_path; | 133 | return full_path; |
134 | } | 134 | } |
135 | 135 | ||
136 | /* | ||
137 | * Don't allow the separator character in a path component. | ||
138 | * The VFS will not allow "/", but "\" is allowed by posix. | ||
139 | */ | ||
140 | static int | ||
141 | check_name(struct dentry *direntry) | ||
142 | { | ||
143 | struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb); | ||
144 | int i; | ||
145 | |||
146 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) { | ||
147 | for (i = 0; i < direntry->d_name.len; i++) { | ||
148 | if (direntry->d_name.name[i] == '\\') { | ||
149 | cFYI(1, "Invalid file name"); | ||
150 | return -EINVAL; | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | |||
136 | /* Inode operations in similar order to how they appear in Linux file fs.h */ | 158 | /* Inode operations in similar order to how they appear in Linux file fs.h */ |
137 | 159 | ||
138 | int | 160 | static int cifs_do_create(struct inode *inode, struct dentry *direntry, |
139 | cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, | 161 | int xid, struct tcon_link *tlink, unsigned oflags, |
140 | struct nameidata *nd) | 162 | umode_t mode, __u32 *oplock, __u16 *fileHandle, |
163 | int *created) | ||
141 | { | 164 | { |
142 | int rc = -ENOENT; | 165 | int rc = -ENOENT; |
143 | int xid; | ||
144 | int create_options = CREATE_NOT_DIR; | 166 | int create_options = CREATE_NOT_DIR; |
145 | __u32 oplock = 0; | 167 | int desiredAccess; |
146 | int oflags; | 168 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
147 | /* | 169 | struct cifs_tcon *tcon = tlink_tcon(tlink); |
148 | * BB below access is probably too much for mknod to request | ||
149 | * but we have to do query and setpathinfo so requesting | ||
150 | * less could fail (unless we want to request getatr and setatr | ||
151 | * permissions (only). At least for POSIX we do not have to | ||
152 | * request so much. | ||
153 | */ | ||
154 | int desiredAccess = GENERIC_READ | GENERIC_WRITE; | ||
155 | __u16 fileHandle; | ||
156 | struct cifs_sb_info *cifs_sb; | ||
157 | struct tcon_link *tlink; | ||
158 | struct cifs_tcon *tcon; | ||
159 | char *full_path = NULL; | 170 | char *full_path = NULL; |
160 | FILE_ALL_INFO *buf = NULL; | 171 | FILE_ALL_INFO *buf = NULL; |
161 | struct inode *newinode = NULL; | 172 | struct inode *newinode = NULL; |
162 | int disposition = FILE_OVERWRITE_IF; | 173 | int disposition; |
163 | |||
164 | xid = GetXid(); | ||
165 | |||
166 | cifs_sb = CIFS_SB(inode->i_sb); | ||
167 | tlink = cifs_sb_tlink(cifs_sb); | ||
168 | if (IS_ERR(tlink)) { | ||
169 | FreeXid(xid); | ||
170 | return PTR_ERR(tlink); | ||
171 | } | ||
172 | tcon = tlink_tcon(tlink); | ||
173 | 174 | ||
175 | *oplock = 0; | ||
174 | if (tcon->ses->server->oplocks) | 176 | if (tcon->ses->server->oplocks) |
175 | oplock = REQ_OPLOCK; | 177 | *oplock = REQ_OPLOCK; |
176 | |||
177 | if (nd) | ||
178 | oflags = nd->intent.open.file->f_flags; | ||
179 | else | ||
180 | oflags = O_RDONLY | O_CREAT; | ||
181 | 178 | ||
182 | full_path = build_path_from_dentry(direntry); | 179 | full_path = build_path_from_dentry(direntry); |
183 | if (full_path == NULL) { | 180 | if (full_path == NULL) { |
184 | rc = -ENOMEM; | 181 | rc = -ENOMEM; |
185 | goto cifs_create_out; | 182 | goto out; |
186 | } | 183 | } |
187 | 184 | ||
188 | if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && | 185 | if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && |
186 | !tcon->broken_posix_open && | ||
189 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & | 187 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & |
190 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { | 188 | le64_to_cpu(tcon->fsUnixInfo.Capability))) { |
191 | rc = cifs_posix_open(full_path, &newinode, | 189 | rc = cifs_posix_open(full_path, &newinode, |
192 | inode->i_sb, mode, oflags, &oplock, &fileHandle, xid); | 190 | inode->i_sb, mode, oflags, oplock, fileHandle, xid); |
193 | /* EIO could indicate that (posix open) operation is not | 191 | switch (rc) { |
194 | supported, despite what server claimed in capability | 192 | case 0: |
195 | negotiation. EREMOTE indicates DFS junction, which is not | 193 | if (newinode == NULL) { |
196 | handled in posix open */ | 194 | /* query inode info */ |
197 | |||
198 | if (rc == 0) { | ||
199 | if (newinode == NULL) /* query inode info */ | ||
200 | goto cifs_create_get_file_info; | 195 | goto cifs_create_get_file_info; |
201 | else /* success, no need to query */ | 196 | } |
202 | goto cifs_create_set_dentry; | 197 | |
203 | } else if ((rc != -EIO) && (rc != -EREMOTE) && | 198 | if (!S_ISREG(newinode->i_mode)) { |
204 | (rc != -EOPNOTSUPP) && (rc != -EINVAL)) | 199 | /* |
205 | goto cifs_create_out; | 200 | * The server may allow us to open things like |
206 | /* else fallthrough to retry, using older open call, this is | 201 | * FIFOs, but the client isn't set up to deal |
207 | case where server does not support this SMB level, and | 202 | * with that. If it's not a regular file, just |
208 | falsely claims capability (also get here for DFS case | 203 | * close it and proceed as if it were a normal |
209 | which should be rare for path not covered on files) */ | 204 | * lookup. |
210 | } | 205 | */ |
206 | CIFSSMBClose(xid, tcon, *fileHandle); | ||
207 | goto cifs_create_get_file_info; | ||
208 | } | ||
209 | /* success, no need to query */ | ||
210 | goto cifs_create_set_dentry; | ||
211 | |||
212 | case -ENOENT: | ||
213 | goto cifs_create_get_file_info; | ||
214 | |||
215 | case -EIO: | ||
216 | case -EINVAL: | ||
217 | /* | ||
218 | * EIO could indicate that (posix open) operation is not | ||
219 | * supported, despite what server claimed in capability | ||
220 | * negotiation. | ||
221 | * | ||
222 | * POSIX open in samba versions 3.3.1 and earlier could | ||
223 | * incorrectly fail with invalid parameter. | ||
224 | */ | ||
225 | tcon->broken_posix_open = true; | ||
226 | break; | ||
227 | |||
228 | case -EREMOTE: | ||
229 | case -EOPNOTSUPP: | ||
230 | /* | ||
231 | * EREMOTE indicates DFS junction, which is not handled | ||
232 | * in posix open. If either that or op not supported | ||
233 | * returned, follow the normal lookup. | ||
234 | */ | ||
235 | break; | ||
211 | 236 | ||
212 | if (nd) { | 237 | default: |
213 | /* if the file is going to stay open, then we | 238 | goto out; |
214 | need to set the desired access properly */ | 239 | } |
215 | desiredAccess = 0; | 240 | /* |
216 | if (OPEN_FMODE(oflags) & FMODE_READ) | 241 | * fallthrough to retry, using older open call, this is case |
217 | desiredAccess |= GENERIC_READ; /* is this too little? */ | 242 | * where server does not support this SMB level, and falsely |
218 | if (OPEN_FMODE(oflags) & FMODE_WRITE) | 243 | * claims capability (also get here for DFS case which should be |
219 | desiredAccess |= GENERIC_WRITE; | 244 | * rare for path not covered on files) |
220 | 245 | */ | |
221 | if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) | ||
222 | disposition = FILE_CREATE; | ||
223 | else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) | ||
224 | disposition = FILE_OVERWRITE_IF; | ||
225 | else if ((oflags & O_CREAT) == O_CREAT) | ||
226 | disposition = FILE_OPEN_IF; | ||
227 | else | ||
228 | cFYI(1, "Create flag not set in create function"); | ||
229 | } | 246 | } |
230 | 247 | ||
248 | desiredAccess = 0; | ||
249 | if (OPEN_FMODE(oflags) & FMODE_READ) | ||
250 | desiredAccess |= GENERIC_READ; /* is this too little? */ | ||
251 | if (OPEN_FMODE(oflags) & FMODE_WRITE) | ||
252 | desiredAccess |= GENERIC_WRITE; | ||
253 | |||
254 | disposition = FILE_OVERWRITE_IF; | ||
255 | if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) | ||
256 | disposition = FILE_CREATE; | ||
257 | else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) | ||
258 | disposition = FILE_OVERWRITE_IF; | ||
259 | else if ((oflags & O_CREAT) == O_CREAT) | ||
260 | disposition = FILE_OPEN_IF; | ||
261 | else | ||
262 | cFYI(1, "Create flag not set in create function"); | ||
263 | |||
231 | /* BB add processing to set equivalent of mode - e.g. via CreateX with | 264 | /* BB add processing to set equivalent of mode - e.g. via CreateX with |
232 | ACLs */ | 265 | ACLs */ |
233 | 266 | ||
234 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | 267 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
235 | if (buf == NULL) { | 268 | if (buf == NULL) { |
236 | rc = -ENOMEM; | 269 | rc = -ENOMEM; |
237 | goto cifs_create_out; | 270 | goto out; |
238 | } | 271 | } |
239 | 272 | ||
240 | /* | 273 | /* |
@@ -250,7 +283,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
250 | if (tcon->ses->capabilities & CAP_NT_SMBS) | 283 | if (tcon->ses->capabilities & CAP_NT_SMBS) |
251 | rc = CIFSSMBOpen(xid, tcon, full_path, disposition, | 284 | rc = CIFSSMBOpen(xid, tcon, full_path, disposition, |
252 | desiredAccess, create_options, | 285 | desiredAccess, create_options, |
253 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | 286 | fileHandle, oplock, buf, cifs_sb->local_nls, |
254 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 287 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
255 | else | 288 | else |
256 | rc = -EIO; /* no NT SMB support fall into legacy open below */ | 289 | rc = -EIO; /* no NT SMB support fall into legacy open below */ |
@@ -259,17 +292,17 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
259 | /* old server, retry the open legacy style */ | 292 | /* old server, retry the open legacy style */ |
260 | rc = SMBLegacyOpen(xid, tcon, full_path, disposition, | 293 | rc = SMBLegacyOpen(xid, tcon, full_path, disposition, |
261 | desiredAccess, create_options, | 294 | desiredAccess, create_options, |
262 | &fileHandle, &oplock, buf, cifs_sb->local_nls, | 295 | fileHandle, oplock, buf, cifs_sb->local_nls, |
263 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 296 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
264 | } | 297 | } |
265 | if (rc) { | 298 | if (rc) { |
266 | cFYI(1, "cifs_create returned 0x%x", rc); | 299 | cFYI(1, "cifs_create returned 0x%x", rc); |
267 | goto cifs_create_out; | 300 | goto out; |
268 | } | 301 | } |
269 | 302 | ||
270 | /* If Open reported that we actually created a file | 303 | /* If Open reported that we actually created a file |
271 | then we now have to set the mode if possible */ | 304 | then we now have to set the mode if possible */ |
272 | if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) { | 305 | if ((tcon->unix_ext) && (*oplock & CIFS_CREATE_ACTION)) { |
273 | struct cifs_unix_set_info_args args = { | 306 | struct cifs_unix_set_info_args args = { |
274 | .mode = mode, | 307 | .mode = mode, |
275 | .ctime = NO_CHANGE_64, | 308 | .ctime = NO_CHANGE_64, |
@@ -278,6 +311,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
278 | .device = 0, | 311 | .device = 0, |
279 | }; | 312 | }; |
280 | 313 | ||
314 | *created |= FILE_CREATED; | ||
281 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | 315 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { |
282 | args.uid = (__u64) current_fsuid(); | 316 | args.uid = (__u64) current_fsuid(); |
283 | if (inode->i_mode & S_ISGID) | 317 | if (inode->i_mode & S_ISGID) |
@@ -288,7 +322,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, | |||
288 | args.uid = NO_CHANGE_64; | 322 | args.uid = NO_CHANGE_64; |
289 | args.gid = NO_CHANGE_64; | 323 | args.gid = NO_CHANGE_64; |
290 | } | 324 | } |
291 | CIFSSMBUnixSetFileInfo(xid, tcon, &args, fileHandle, | 325 | CIFSSMBUnixSetFileInfo(xid, tcon, &args, *fileHandle, |
292 | current->tgid); | 326 | current->tgid); |
293 | } else { | 327 | } else { |
294 | /* BB implement mode setting via Windows security | 328 | /* BB implement mode setting via Windows security |
@@ -305,11 +339,11 @@ cifs_create_get_file_info: | |||
305 | inode->i_sb, xid); | 339 | inode->i_sb, xid); |
306 | else { | 340 | else { |
307 | rc = cifs_get_inode_info(&newinode, full_path, buf, | 341 | rc = cifs_get_inode_info(&newinode, full_path, buf, |
308 | inode->i_sb, xid, &fileHandle); | 342 | inode->i_sb, xid, fileHandle); |
309 | if (newinode) { | 343 | if (newinode) { |
310 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) | 344 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) |
311 | newinode->i_mode = mode; | 345 | newinode->i_mode = mode; |
312 | if ((oplock & CIFS_CREATE_ACTION) && | 346 | if ((*oplock & CIFS_CREATE_ACTION) && |
313 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { | 347 | (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { |
314 | newinode->i_uid = current_fsuid(); | 348 | newinode->i_uid = current_fsuid(); |
315 | if (inode->i_mode & S_ISGID) | 349 | if (inode->i_mode & S_ISGID) |
@@ -321,40 +355,139 @@ cifs_create_get_file_info: | |||
321 | } | 355 | } |
322 | 356 | ||
323 | cifs_create_set_dentry: | 357 | cifs_create_set_dentry: |
324 | if (rc == 0) | 358 | if (rc != 0) { |
325 | d_instantiate(direntry, newinode); | ||
326 | else | ||
327 | cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); | 359 | cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); |
360 | goto out; | ||
361 | } | ||
362 | d_drop(direntry); | ||
363 | d_add(direntry, newinode); | ||
328 | 364 | ||
329 | if (newinode && nd) { | 365 | /* ENOENT for create? How weird... */ |
330 | struct cifsFileInfo *pfile_info; | 366 | rc = -ENOENT; |
331 | struct file *filp; | 367 | if (!newinode) { |
368 | CIFSSMBClose(xid, tcon, *fileHandle); | ||
369 | goto out; | ||
370 | } | ||
371 | rc = 0; | ||
332 | 372 | ||
333 | filp = lookup_instantiate_filp(nd, direntry, generic_file_open); | 373 | out: |
334 | if (IS_ERR(filp)) { | 374 | kfree(buf); |
335 | rc = PTR_ERR(filp); | 375 | kfree(full_path); |
336 | CIFSSMBClose(xid, tcon, fileHandle); | 376 | return rc; |
337 | goto cifs_create_out; | 377 | } |
338 | } | ||
339 | 378 | ||
340 | pfile_info = cifs_new_fileinfo(fileHandle, filp, tlink, oplock); | 379 | int |
341 | if (pfile_info == NULL) { | 380 | cifs_atomic_open(struct inode *inode, struct dentry *direntry, |
342 | fput(filp); | 381 | struct file *file, unsigned oflags, umode_t mode, |
343 | CIFSSMBClose(xid, tcon, fileHandle); | 382 | int *opened) |
344 | rc = -ENOMEM; | 383 | { |
345 | } | 384 | int rc; |
346 | } else { | 385 | int xid; |
386 | struct tcon_link *tlink; | ||
387 | struct cifs_tcon *tcon; | ||
388 | __u16 fileHandle; | ||
389 | __u32 oplock; | ||
390 | struct file *filp; | ||
391 | struct cifsFileInfo *pfile_info; | ||
392 | |||
393 | /* Posix open is only called (at lookup time) for file create now. For | ||
394 | * opens (rather than creates), because we do not know if it is a file | ||
395 | * or directory yet, and current Samba no longer allows us to do posix | ||
396 | * open on dirs, we could end up wasting an open call on what turns out | ||
397 | * to be a dir. For file opens, we wait to call posix open till | ||
398 | * cifs_open. It could be added to atomic_open in the future but the | ||
399 | * performance tradeoff of the extra network request when EISDIR or | ||
400 | * EACCES is returned would have to be weighed against the 50% reduction | ||
401 | * in network traffic in the other paths. | ||
402 | */ | ||
403 | if (!(oflags & O_CREAT)) { | ||
404 | struct dentry *res = cifs_lookup(inode, direntry, 0); | ||
405 | if (IS_ERR(res)) | ||
406 | return PTR_ERR(res); | ||
407 | |||
408 | return finish_no_open(file, res); | ||
409 | } | ||
410 | |||
411 | rc = check_name(direntry); | ||
412 | if (rc) | ||
413 | return rc; | ||
414 | |||
415 | xid = GetXid(); | ||
416 | |||
417 | cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p", | ||
418 | inode, direntry->d_name.name, direntry); | ||
419 | |||
420 | tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb)); | ||
421 | filp = ERR_CAST(tlink); | ||
422 | if (IS_ERR(tlink)) | ||
423 | goto free_xid; | ||
424 | |||
425 | tcon = tlink_tcon(tlink); | ||
426 | |||
427 | rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, | ||
428 | &oplock, &fileHandle, opened); | ||
429 | |||
430 | if (rc) | ||
431 | goto out; | ||
432 | |||
433 | rc = finish_open(file, direntry, generic_file_open, opened); | ||
434 | if (rc) { | ||
347 | CIFSSMBClose(xid, tcon, fileHandle); | 435 | CIFSSMBClose(xid, tcon, fileHandle); |
436 | goto out; | ||
348 | } | 437 | } |
349 | 438 | ||
350 | cifs_create_out: | 439 | pfile_info = cifs_new_fileinfo(fileHandle, filp, tlink, oplock); |
351 | kfree(buf); | 440 | if (pfile_info == NULL) { |
352 | kfree(full_path); | 441 | CIFSSMBClose(xid, tcon, fileHandle); |
442 | fput(filp); | ||
443 | rc = -ENOMEM; | ||
444 | } | ||
445 | |||
446 | out: | ||
353 | cifs_put_tlink(tlink); | 447 | cifs_put_tlink(tlink); |
448 | free_xid: | ||
354 | FreeXid(xid); | 449 | FreeXid(xid); |
355 | return rc; | 450 | return rc; |
356 | } | 451 | } |
357 | 452 | ||
453 | int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, | ||
454 | bool excl) | ||
455 | { | ||
456 | int rc; | ||
457 | int xid = GetXid(); | ||
458 | /* | ||
459 | * BB below access is probably too much for mknod to request | ||
460 | * but we have to do query and setpathinfo so requesting | ||
461 | * less could fail (unless we want to request getatr and setatr | ||
462 | * permissions (only). At least for POSIX we do not have to | ||
463 | * request so much. | ||
464 | */ | ||
465 | unsigned oflags = O_EXCL | O_CREAT | O_RDWR; | ||
466 | struct tcon_link *tlink; | ||
467 | __u16 fileHandle; | ||
468 | __u32 oplock; | ||
469 | int created = FILE_CREATED; | ||
470 | |||
471 | cFYI(1, "cifs_create parent inode = 0x%p name is: %s and dentry = 0x%p", | ||
472 | inode, direntry->d_name.name, direntry); | ||
473 | |||
474 | tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb)); | ||
475 | rc = PTR_ERR(tlink); | ||
476 | if (IS_ERR(tlink)) | ||
477 | goto free_xid; | ||
478 | |||
479 | rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode, | ||
480 | &oplock, &fileHandle, &created); | ||
481 | if (!rc) | ||
482 | CIFSSMBClose(xid, tlink_tcon(tlink), fileHandle); | ||
483 | |||
484 | cifs_put_tlink(tlink); | ||
485 | free_xid: | ||
486 | FreeXid(xid); | ||
487 | |||
488 | return rc; | ||
489 | } | ||
490 | |||
358 | int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, | 491 | int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, |
359 | dev_t device_number) | 492 | dev_t device_number) |
360 | { | 493 | { |
@@ -488,20 +621,15 @@ mknod_out: | |||
488 | 621 | ||
489 | struct dentry * | 622 | struct dentry * |
490 | cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | 623 | cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, |
491 | struct nameidata *nd) | 624 | unsigned int flags) |
492 | { | 625 | { |
493 | int xid; | 626 | int xid; |
494 | int rc = 0; /* to get around spurious gcc warning, set to zero here */ | 627 | int rc = 0; /* to get around spurious gcc warning, set to zero here */ |
495 | __u32 oplock; | ||
496 | __u16 fileHandle = 0; | ||
497 | bool posix_open = false; | ||
498 | struct cifs_sb_info *cifs_sb; | 628 | struct cifs_sb_info *cifs_sb; |
499 | struct tcon_link *tlink; | 629 | struct tcon_link *tlink; |
500 | struct cifs_tcon *pTcon; | 630 | struct cifs_tcon *pTcon; |
501 | struct cifsFileInfo *cfile; | ||
502 | struct inode *newInode = NULL; | 631 | struct inode *newInode = NULL; |
503 | char *full_path = NULL; | 632 | char *full_path = NULL; |
504 | struct file *filp; | ||
505 | 633 | ||
506 | xid = GetXid(); | 634 | xid = GetXid(); |
507 | 635 | ||
@@ -518,31 +646,9 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
518 | } | 646 | } |
519 | pTcon = tlink_tcon(tlink); | 647 | pTcon = tlink_tcon(tlink); |
520 | 648 | ||
521 | oplock = pTcon->ses->server->oplocks ? REQ_OPLOCK : 0; | 649 | rc = check_name(direntry); |
522 | 650 | if (rc) | |
523 | /* | ||
524 | * Don't allow the separator character in a path component. | ||
525 | * The VFS will not allow "/", but "\" is allowed by posix. | ||
526 | */ | ||
527 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) { | ||
528 | int i; | ||
529 | for (i = 0; i < direntry->d_name.len; i++) | ||
530 | if (direntry->d_name.name[i] == '\\') { | ||
531 | cFYI(1, "Invalid file name"); | ||
532 | rc = -EINVAL; | ||
533 | goto lookup_out; | ||
534 | } | ||
535 | } | ||
536 | |||
537 | /* | ||
538 | * O_EXCL: optimize away the lookup, but don't hash the dentry. Let | ||
539 | * the VFS handle the create. | ||
540 | */ | ||
541 | if (nd && (nd->flags & LOOKUP_EXCL)) { | ||
542 | d_instantiate(direntry, NULL); | ||
543 | rc = 0; | ||
544 | goto lookup_out; | 651 | goto lookup_out; |
545 | } | ||
546 | 652 | ||
547 | /* can not grab the rename sem here since it would | 653 | /* can not grab the rename sem here since it would |
548 | deadlock in the cases (beginning of sys_rename itself) | 654 | deadlock in the cases (beginning of sys_rename itself) |
@@ -560,80 +666,16 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
560 | } | 666 | } |
561 | cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode); | 667 | cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode); |
562 | 668 | ||
563 | /* Posix open is only called (at lookup time) for file create now. | ||
564 | * For opens (rather than creates), because we do not know if it | ||
565 | * is a file or directory yet, and current Samba no longer allows | ||
566 | * us to do posix open on dirs, we could end up wasting an open call | ||
567 | * on what turns out to be a dir. For file opens, we wait to call posix | ||
568 | * open till cifs_open. It could be added here (lookup) in the future | ||
569 | * but the performance tradeoff of the extra network request when EISDIR | ||
570 | * or EACCES is returned would have to be weighed against the 50% | ||
571 | * reduction in network traffic in the other paths. | ||
572 | */ | ||
573 | if (pTcon->unix_ext) { | 669 | if (pTcon->unix_ext) { |
574 | if (nd && !(nd->flags & LOOKUP_DIRECTORY) && | 670 | rc = cifs_get_inode_info_unix(&newInode, full_path, |
575 | (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && | 671 | parent_dir_inode->i_sb, xid); |
576 | (nd->intent.open.file->f_flags & O_CREAT)) { | 672 | } else { |
577 | rc = cifs_posix_open(full_path, &newInode, | ||
578 | parent_dir_inode->i_sb, | ||
579 | nd->intent.open.create_mode, | ||
580 | nd->intent.open.file->f_flags, &oplock, | ||
581 | &fileHandle, xid); | ||
582 | /* | ||
583 | * The check below works around a bug in POSIX | ||
584 | * open in samba versions 3.3.1 and earlier where | ||
585 | * open could incorrectly fail with invalid parameter. | ||
586 | * If either that or op not supported returned, follow | ||
587 | * the normal lookup. | ||
588 | */ | ||
589 | switch (rc) { | ||
590 | case 0: | ||
591 | /* | ||
592 | * The server may allow us to open things like | ||
593 | * FIFOs, but the client isn't set up to deal | ||
594 | * with that. If it's not a regular file, just | ||
595 | * close it and proceed as if it were a normal | ||
596 | * lookup. | ||
597 | */ | ||
598 | if (newInode && !S_ISREG(newInode->i_mode)) { | ||
599 | CIFSSMBClose(xid, pTcon, fileHandle); | ||
600 | break; | ||
601 | } | ||
602 | case -ENOENT: | ||
603 | posix_open = true; | ||
604 | case -EOPNOTSUPP: | ||
605 | break; | ||
606 | default: | ||
607 | pTcon->broken_posix_open = true; | ||
608 | } | ||
609 | } | ||
610 | if (!posix_open) | ||
611 | rc = cifs_get_inode_info_unix(&newInode, full_path, | ||
612 | parent_dir_inode->i_sb, xid); | ||
613 | } else | ||
614 | rc = cifs_get_inode_info(&newInode, full_path, NULL, | 673 | rc = cifs_get_inode_info(&newInode, full_path, NULL, |
615 | parent_dir_inode->i_sb, xid, NULL); | 674 | parent_dir_inode->i_sb, xid, NULL); |
675 | } | ||
616 | 676 | ||
617 | if ((rc == 0) && (newInode != NULL)) { | 677 | if ((rc == 0) && (newInode != NULL)) { |
618 | d_add(direntry, newInode); | 678 | d_add(direntry, newInode); |
619 | if (posix_open) { | ||
620 | filp = lookup_instantiate_filp(nd, direntry, | ||
621 | generic_file_open); | ||
622 | if (IS_ERR(filp)) { | ||
623 | rc = PTR_ERR(filp); | ||
624 | CIFSSMBClose(xid, pTcon, fileHandle); | ||
625 | goto lookup_out; | ||
626 | } | ||
627 | |||
628 | cfile = cifs_new_fileinfo(fileHandle, filp, tlink, | ||
629 | oplock); | ||
630 | if (cfile == NULL) { | ||
631 | fput(filp); | ||
632 | CIFSSMBClose(xid, pTcon, fileHandle); | ||
633 | rc = -ENOMEM; | ||
634 | goto lookup_out; | ||
635 | } | ||
636 | } | ||
637 | /* since paths are not looked up by component - the parent | 679 | /* since paths are not looked up by component - the parent |
638 | directories are presumed to be good here */ | 680 | directories are presumed to be good here */ |
639 | renew_parental_timestamps(direntry); | 681 | renew_parental_timestamps(direntry); |
@@ -658,9 +700,9 @@ lookup_out: | |||
658 | } | 700 | } |
659 | 701 | ||
660 | static int | 702 | static int |
661 | cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) | 703 | cifs_d_revalidate(struct dentry *direntry, unsigned int flags) |
662 | { | 704 | { |
663 | if (nd && (nd->flags & LOOKUP_RCU)) | 705 | if (flags & LOOKUP_RCU) |
664 | return -ECHILD; | 706 | return -ECHILD; |
665 | 707 | ||
666 | if (direntry->d_inode) { | 708 | if (direntry->d_inode) { |
@@ -689,7 +731,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) | |||
689 | * This may be nfsd (or something), anyway, we can't see the | 731 | * This may be nfsd (or something), anyway, we can't see the |
690 | * intent of this. So, since this can be for creation, drop it. | 732 | * intent of this. So, since this can be for creation, drop it. |
691 | */ | 733 | */ |
692 | if (!nd) | 734 | if (!flags) |
693 | return 0; | 735 | return 0; |
694 | 736 | ||
695 | /* | 737 | /* |
@@ -697,7 +739,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) | |||
697 | * case sensitive name which is specified by user if this is | 739 | * case sensitive name which is specified by user if this is |
698 | * for creation. | 740 | * for creation. |
699 | */ | 741 | */ |
700 | if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) | 742 | if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) |
701 | return 0; | 743 | return 0; |
702 | 744 | ||
703 | if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled) | 745 | if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled) |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 745da3d0653e..8e8bb49112ff 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -800,7 +800,7 @@ cifs_find_inode(struct inode *inode, void *opaque) | |||
800 | return 0; | 800 | return 0; |
801 | 801 | ||
802 | /* if it's not a directory or has no dentries, then flag it */ | 802 | /* if it's not a directory or has no dentries, then flag it */ |
803 | if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) | 803 | if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry)) |
804 | fattr->cf_flags |= CIFS_FATTR_INO_COLLISION; | 804 | fattr->cf_flags |= CIFS_FATTR_INO_COLLISION; |
805 | 805 | ||
806 | return 1; | 806 | return 1; |
@@ -825,9 +825,10 @@ static bool | |||
825 | inode_has_hashed_dentries(struct inode *inode) | 825 | inode_has_hashed_dentries(struct inode *inode) |
826 | { | 826 | { |
827 | struct dentry *dentry; | 827 | struct dentry *dentry; |
828 | struct hlist_node *p; | ||
828 | 829 | ||
829 | spin_lock(&inode->i_lock); | 830 | spin_lock(&inode->i_lock); |
830 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { | 831 | hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) { |
831 | if (!d_unhashed(dentry) || IS_ROOT(dentry)) { | 832 | if (!d_unhashed(dentry) || IS_ROOT(dentry)) { |
832 | spin_unlock(&inode->i_lock); | 833 | spin_unlock(&inode->i_lock); |
833 | return true; | 834 | return true; |
diff --git a/fs/coda/cache.c b/fs/coda/cache.c index 690157876184..958ae0e0ff8c 100644 --- a/fs/coda/cache.c +++ b/fs/coda/cache.c | |||
@@ -89,17 +89,13 @@ int coda_cache_check(struct inode *inode, int mask) | |||
89 | /* this won't do any harm: just flag all children */ | 89 | /* this won't do any harm: just flag all children */ |
90 | static void coda_flag_children(struct dentry *parent, int flag) | 90 | static void coda_flag_children(struct dentry *parent, int flag) |
91 | { | 91 | { |
92 | struct list_head *child; | ||
93 | struct dentry *de; | 92 | struct dentry *de; |
94 | 93 | ||
95 | spin_lock(&parent->d_lock); | 94 | spin_lock(&parent->d_lock); |
96 | list_for_each(child, &parent->d_subdirs) | 95 | list_for_each_entry(de, &parent->d_subdirs, d_u.d_child) { |
97 | { | ||
98 | de = list_entry(child, struct dentry, d_u.d_child); | ||
99 | /* don't know what to do with negative dentries */ | 96 | /* don't know what to do with negative dentries */ |
100 | if ( ! de->d_inode ) | 97 | if (de->d_inode ) |
101 | continue; | 98 | coda_flag_inode(de->d_inode, flag); |
102 | coda_flag_inode(de->d_inode, flag); | ||
103 | } | 99 | } |
104 | spin_unlock(&parent->d_lock); | 100 | spin_unlock(&parent->d_lock); |
105 | return; | 101 | return; |
diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 177515829062..49fe52d25600 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c | |||
@@ -30,8 +30,8 @@ | |||
30 | #include "coda_int.h" | 30 | #include "coda_int.h" |
31 | 31 | ||
32 | /* dir inode-ops */ | 32 | /* dir inode-ops */ |
33 | static int coda_create(struct inode *dir, struct dentry *new, umode_t mode, struct nameidata *nd); | 33 | static int coda_create(struct inode *dir, struct dentry *new, umode_t mode, bool excl); |
34 | static struct dentry *coda_lookup(struct inode *dir, struct dentry *target, struct nameidata *nd); | 34 | static struct dentry *coda_lookup(struct inode *dir, struct dentry *target, unsigned int flags); |
35 | static int coda_link(struct dentry *old_dentry, struct inode *dir_inode, | 35 | static int coda_link(struct dentry *old_dentry, struct inode *dir_inode, |
36 | struct dentry *entry); | 36 | struct dentry *entry); |
37 | static int coda_unlink(struct inode *dir_inode, struct dentry *entry); | 37 | static int coda_unlink(struct inode *dir_inode, struct dentry *entry); |
@@ -46,7 +46,7 @@ static int coda_rename(struct inode *old_inode, struct dentry *old_dentry, | |||
46 | static int coda_readdir(struct file *file, void *buf, filldir_t filldir); | 46 | static int coda_readdir(struct file *file, void *buf, filldir_t filldir); |
47 | 47 | ||
48 | /* dentry ops */ | 48 | /* dentry ops */ |
49 | static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd); | 49 | static int coda_dentry_revalidate(struct dentry *de, unsigned int flags); |
50 | static int coda_dentry_delete(const struct dentry *); | 50 | static int coda_dentry_delete(const struct dentry *); |
51 | 51 | ||
52 | /* support routines */ | 52 | /* support routines */ |
@@ -94,7 +94,7 @@ const struct file_operations coda_dir_operations = { | |||
94 | 94 | ||
95 | /* inode operations for directories */ | 95 | /* inode operations for directories */ |
96 | /* access routines: lookup, readlink, permission */ | 96 | /* access routines: lookup, readlink, permission */ |
97 | static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd) | 97 | static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, unsigned int flags) |
98 | { | 98 | { |
99 | struct super_block *sb = dir->i_sb; | 99 | struct super_block *sb = dir->i_sb; |
100 | const char *name = entry->d_name.name; | 100 | const char *name = entry->d_name.name; |
@@ -188,7 +188,7 @@ static inline void coda_dir_drop_nlink(struct inode *dir) | |||
188 | } | 188 | } |
189 | 189 | ||
190 | /* creation routines: create, mknod, mkdir, link, symlink */ | 190 | /* creation routines: create, mknod, mkdir, link, symlink */ |
191 | static int coda_create(struct inode *dir, struct dentry *de, umode_t mode, struct nameidata *nd) | 191 | static int coda_create(struct inode *dir, struct dentry *de, umode_t mode, bool excl) |
192 | { | 192 | { |
193 | int error; | 193 | int error; |
194 | const char *name=de->d_name.name; | 194 | const char *name=de->d_name.name; |
@@ -536,12 +536,12 @@ out: | |||
536 | } | 536 | } |
537 | 537 | ||
538 | /* called when a cache lookup succeeds */ | 538 | /* called when a cache lookup succeeds */ |
539 | static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd) | 539 | static int coda_dentry_revalidate(struct dentry *de, unsigned int flags) |
540 | { | 540 | { |
541 | struct inode *inode; | 541 | struct inode *inode; |
542 | struct coda_inode_info *cii; | 542 | struct coda_inode_info *cii; |
543 | 543 | ||
544 | if (nd->flags & LOOKUP_RCU) | 544 | if (flags & LOOKUP_RCU) |
545 | return -ECHILD; | 545 | return -ECHILD; |
546 | 546 | ||
547 | inode = de->d_inode; | 547 | inode = de->d_inode; |
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 7e6c52d8a207..7414ae24a79b 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -442,7 +442,7 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den | |||
442 | 442 | ||
443 | static struct dentry * configfs_lookup(struct inode *dir, | 443 | static struct dentry * configfs_lookup(struct inode *dir, |
444 | struct dentry *dentry, | 444 | struct dentry *dentry, |
445 | struct nameidata *nd) | 445 | unsigned int flags) |
446 | { | 446 | { |
447 | struct configfs_dirent * parent_sd = dentry->d_parent->d_fsdata; | 447 | struct configfs_dirent * parent_sd = dentry->d_parent->d_fsdata; |
448 | struct configfs_dirent * sd; | 448 | struct configfs_dirent * sd; |
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index d013c46402ed..28cca01ca9c9 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c | |||
@@ -417,7 +417,7 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
417 | /* | 417 | /* |
418 | * Lookup and fill in the inode data.. | 418 | * Lookup and fill in the inode data.. |
419 | */ | 419 | */ |
420 | static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 420 | static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
421 | { | 421 | { |
422 | unsigned int offset = 0; | 422 | unsigned int offset = 0; |
423 | struct inode *inode = NULL; | 423 | struct inode *inode = NULL; |
diff --git a/fs/dcache.c b/fs/dcache.c index 40469044088d..8086636bf796 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -218,7 +218,7 @@ static void __d_free(struct rcu_head *head) | |||
218 | { | 218 | { |
219 | struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu); | 219 | struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu); |
220 | 220 | ||
221 | WARN_ON(!list_empty(&dentry->d_alias)); | 221 | WARN_ON(!hlist_unhashed(&dentry->d_alias)); |
222 | if (dname_external(dentry)) | 222 | if (dname_external(dentry)) |
223 | kfree(dentry->d_name.name); | 223 | kfree(dentry->d_name.name); |
224 | kmem_cache_free(dentry_cache, dentry); | 224 | kmem_cache_free(dentry_cache, dentry); |
@@ -267,7 +267,7 @@ static void dentry_iput(struct dentry * dentry) | |||
267 | struct inode *inode = dentry->d_inode; | 267 | struct inode *inode = dentry->d_inode; |
268 | if (inode) { | 268 | if (inode) { |
269 | dentry->d_inode = NULL; | 269 | dentry->d_inode = NULL; |
270 | list_del_init(&dentry->d_alias); | 270 | hlist_del_init(&dentry->d_alias); |
271 | spin_unlock(&dentry->d_lock); | 271 | spin_unlock(&dentry->d_lock); |
272 | spin_unlock(&inode->i_lock); | 272 | spin_unlock(&inode->i_lock); |
273 | if (!inode->i_nlink) | 273 | if (!inode->i_nlink) |
@@ -291,7 +291,7 @@ static void dentry_unlink_inode(struct dentry * dentry) | |||
291 | { | 291 | { |
292 | struct inode *inode = dentry->d_inode; | 292 | struct inode *inode = dentry->d_inode; |
293 | dentry->d_inode = NULL; | 293 | dentry->d_inode = NULL; |
294 | list_del_init(&dentry->d_alias); | 294 | hlist_del_init(&dentry->d_alias); |
295 | dentry_rcuwalk_barrier(dentry); | 295 | dentry_rcuwalk_barrier(dentry); |
296 | spin_unlock(&dentry->d_lock); | 296 | spin_unlock(&dentry->d_lock); |
297 | spin_unlock(&inode->i_lock); | 297 | spin_unlock(&inode->i_lock); |
@@ -699,10 +699,11 @@ EXPORT_SYMBOL(dget_parent); | |||
699 | static struct dentry *__d_find_alias(struct inode *inode, int want_discon) | 699 | static struct dentry *__d_find_alias(struct inode *inode, int want_discon) |
700 | { | 700 | { |
701 | struct dentry *alias, *discon_alias; | 701 | struct dentry *alias, *discon_alias; |
702 | struct hlist_node *p; | ||
702 | 703 | ||
703 | again: | 704 | again: |
704 | discon_alias = NULL; | 705 | discon_alias = NULL; |
705 | list_for_each_entry(alias, &inode->i_dentry, d_alias) { | 706 | hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) { |
706 | spin_lock(&alias->d_lock); | 707 | spin_lock(&alias->d_lock); |
707 | if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) { | 708 | if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) { |
708 | if (IS_ROOT(alias) && | 709 | if (IS_ROOT(alias) && |
@@ -737,7 +738,7 @@ struct dentry *d_find_alias(struct inode *inode) | |||
737 | { | 738 | { |
738 | struct dentry *de = NULL; | 739 | struct dentry *de = NULL; |
739 | 740 | ||
740 | if (!list_empty(&inode->i_dentry)) { | 741 | if (!hlist_empty(&inode->i_dentry)) { |
741 | spin_lock(&inode->i_lock); | 742 | spin_lock(&inode->i_lock); |
742 | de = __d_find_alias(inode, 0); | 743 | de = __d_find_alias(inode, 0); |
743 | spin_unlock(&inode->i_lock); | 744 | spin_unlock(&inode->i_lock); |
@@ -753,9 +754,10 @@ EXPORT_SYMBOL(d_find_alias); | |||
753 | void d_prune_aliases(struct inode *inode) | 754 | void d_prune_aliases(struct inode *inode) |
754 | { | 755 | { |
755 | struct dentry *dentry; | 756 | struct dentry *dentry; |
757 | struct hlist_node *p; | ||
756 | restart: | 758 | restart: |
757 | spin_lock(&inode->i_lock); | 759 | spin_lock(&inode->i_lock); |
758 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { | 760 | hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) { |
759 | spin_lock(&dentry->d_lock); | 761 | spin_lock(&dentry->d_lock); |
760 | if (!dentry->d_count) { | 762 | if (!dentry->d_count) { |
761 | __dget_dlock(dentry); | 763 | __dget_dlock(dentry); |
@@ -977,7 +979,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) | |||
977 | inode = dentry->d_inode; | 979 | inode = dentry->d_inode; |
978 | if (inode) { | 980 | if (inode) { |
979 | dentry->d_inode = NULL; | 981 | dentry->d_inode = NULL; |
980 | list_del_init(&dentry->d_alias); | 982 | hlist_del_init(&dentry->d_alias); |
981 | if (dentry->d_op && dentry->d_op->d_iput) | 983 | if (dentry->d_op && dentry->d_op->d_iput) |
982 | dentry->d_op->d_iput(dentry, inode); | 984 | dentry->d_op->d_iput(dentry, inode); |
983 | else | 985 | else |
@@ -1312,7 +1314,7 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name) | |||
1312 | INIT_HLIST_BL_NODE(&dentry->d_hash); | 1314 | INIT_HLIST_BL_NODE(&dentry->d_hash); |
1313 | INIT_LIST_HEAD(&dentry->d_lru); | 1315 | INIT_LIST_HEAD(&dentry->d_lru); |
1314 | INIT_LIST_HEAD(&dentry->d_subdirs); | 1316 | INIT_LIST_HEAD(&dentry->d_subdirs); |
1315 | INIT_LIST_HEAD(&dentry->d_alias); | 1317 | INIT_HLIST_NODE(&dentry->d_alias); |
1316 | INIT_LIST_HEAD(&dentry->d_u.d_child); | 1318 | INIT_LIST_HEAD(&dentry->d_u.d_child); |
1317 | d_set_d_op(dentry, dentry->d_sb->s_d_op); | 1319 | d_set_d_op(dentry, dentry->d_sb->s_d_op); |
1318 | 1320 | ||
@@ -1400,7 +1402,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode) | |||
1400 | if (inode) { | 1402 | if (inode) { |
1401 | if (unlikely(IS_AUTOMOUNT(inode))) | 1403 | if (unlikely(IS_AUTOMOUNT(inode))) |
1402 | dentry->d_flags |= DCACHE_NEED_AUTOMOUNT; | 1404 | dentry->d_flags |= DCACHE_NEED_AUTOMOUNT; |
1403 | list_add(&dentry->d_alias, &inode->i_dentry); | 1405 | hlist_add_head(&dentry->d_alias, &inode->i_dentry); |
1404 | } | 1406 | } |
1405 | dentry->d_inode = inode; | 1407 | dentry->d_inode = inode; |
1406 | dentry_rcuwalk_barrier(dentry); | 1408 | dentry_rcuwalk_barrier(dentry); |
@@ -1425,7 +1427,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode) | |||
1425 | 1427 | ||
1426 | void d_instantiate(struct dentry *entry, struct inode * inode) | 1428 | void d_instantiate(struct dentry *entry, struct inode * inode) |
1427 | { | 1429 | { |
1428 | BUG_ON(!list_empty(&entry->d_alias)); | 1430 | BUG_ON(!hlist_unhashed(&entry->d_alias)); |
1429 | if (inode) | 1431 | if (inode) |
1430 | spin_lock(&inode->i_lock); | 1432 | spin_lock(&inode->i_lock); |
1431 | __d_instantiate(entry, inode); | 1433 | __d_instantiate(entry, inode); |
@@ -1458,13 +1460,14 @@ static struct dentry *__d_instantiate_unique(struct dentry *entry, | |||
1458 | int len = entry->d_name.len; | 1460 | int len = entry->d_name.len; |
1459 | const char *name = entry->d_name.name; | 1461 | const char *name = entry->d_name.name; |
1460 | unsigned int hash = entry->d_name.hash; | 1462 | unsigned int hash = entry->d_name.hash; |
1463 | struct hlist_node *p; | ||
1461 | 1464 | ||
1462 | if (!inode) { | 1465 | if (!inode) { |
1463 | __d_instantiate(entry, NULL); | 1466 | __d_instantiate(entry, NULL); |
1464 | return NULL; | 1467 | return NULL; |
1465 | } | 1468 | } |
1466 | 1469 | ||
1467 | list_for_each_entry(alias, &inode->i_dentry, d_alias) { | 1470 | hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) { |
1468 | /* | 1471 | /* |
1469 | * Don't need alias->d_lock here, because aliases with | 1472 | * Don't need alias->d_lock here, because aliases with |
1470 | * d_parent == entry->d_parent are not subject to name or | 1473 | * d_parent == entry->d_parent are not subject to name or |
@@ -1490,7 +1493,7 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode) | |||
1490 | { | 1493 | { |
1491 | struct dentry *result; | 1494 | struct dentry *result; |
1492 | 1495 | ||
1493 | BUG_ON(!list_empty(&entry->d_alias)); | 1496 | BUG_ON(!hlist_unhashed(&entry->d_alias)); |
1494 | 1497 | ||
1495 | if (inode) | 1498 | if (inode) |
1496 | spin_lock(&inode->i_lock); | 1499 | spin_lock(&inode->i_lock); |
@@ -1531,9 +1534,9 @@ static struct dentry * __d_find_any_alias(struct inode *inode) | |||
1531 | { | 1534 | { |
1532 | struct dentry *alias; | 1535 | struct dentry *alias; |
1533 | 1536 | ||
1534 | if (list_empty(&inode->i_dentry)) | 1537 | if (hlist_empty(&inode->i_dentry)) |
1535 | return NULL; | 1538 | return NULL; |
1536 | alias = list_first_entry(&inode->i_dentry, struct dentry, d_alias); | 1539 | alias = hlist_entry(inode->i_dentry.first, struct dentry, d_alias); |
1537 | __dget(alias); | 1540 | __dget(alias); |
1538 | return alias; | 1541 | return alias; |
1539 | } | 1542 | } |
@@ -1607,7 +1610,7 @@ struct dentry *d_obtain_alias(struct inode *inode) | |||
1607 | spin_lock(&tmp->d_lock); | 1610 | spin_lock(&tmp->d_lock); |
1608 | tmp->d_inode = inode; | 1611 | tmp->d_inode = inode; |
1609 | tmp->d_flags |= DCACHE_DISCONNECTED; | 1612 | tmp->d_flags |= DCACHE_DISCONNECTED; |
1610 | list_add(&tmp->d_alias, &inode->i_dentry); | 1613 | hlist_add_head(&tmp->d_alias, &inode->i_dentry); |
1611 | hlist_bl_lock(&tmp->d_sb->s_anon); | 1614 | hlist_bl_lock(&tmp->d_sb->s_anon); |
1612 | hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon); | 1615 | hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon); |
1613 | hlist_bl_unlock(&tmp->d_sb->s_anon); | 1616 | hlist_bl_unlock(&tmp->d_sb->s_anon); |
@@ -2384,14 +2387,13 @@ static struct dentry *__d_unalias(struct inode *inode, | |||
2384 | struct dentry *dentry, struct dentry *alias) | 2387 | struct dentry *dentry, struct dentry *alias) |
2385 | { | 2388 | { |
2386 | struct mutex *m1 = NULL, *m2 = NULL; | 2389 | struct mutex *m1 = NULL, *m2 = NULL; |
2387 | struct dentry *ret; | 2390 | struct dentry *ret = ERR_PTR(-EBUSY); |
2388 | 2391 | ||
2389 | /* If alias and dentry share a parent, then no extra locks required */ | 2392 | /* If alias and dentry share a parent, then no extra locks required */ |
2390 | if (alias->d_parent == dentry->d_parent) | 2393 | if (alias->d_parent == dentry->d_parent) |
2391 | goto out_unalias; | 2394 | goto out_unalias; |
2392 | 2395 | ||
2393 | /* See lock_rename() */ | 2396 | /* See lock_rename() */ |
2394 | ret = ERR_PTR(-EBUSY); | ||
2395 | if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex)) | 2397 | if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex)) |
2396 | goto out_err; | 2398 | goto out_err; |
2397 | m1 = &dentry->d_sb->s_vfs_rename_mutex; | 2399 | m1 = &dentry->d_sb->s_vfs_rename_mutex; |
@@ -2399,8 +2401,10 @@ static struct dentry *__d_unalias(struct inode *inode, | |||
2399 | goto out_err; | 2401 | goto out_err; |
2400 | m2 = &alias->d_parent->d_inode->i_mutex; | 2402 | m2 = &alias->d_parent->d_inode->i_mutex; |
2401 | out_unalias: | 2403 | out_unalias: |
2402 | __d_move(alias, dentry); | 2404 | if (likely(!d_mountpoint(alias))) { |
2403 | ret = alias; | 2405 | __d_move(alias, dentry); |
2406 | ret = alias; | ||
2407 | } | ||
2404 | out_err: | 2408 | out_err: |
2405 | spin_unlock(&inode->i_lock); | 2409 | spin_unlock(&inode->i_lock); |
2406 | if (m2) | 2410 | if (m2) |
@@ -2622,7 +2626,7 @@ global_root: | |||
2622 | if (!slash) | 2626 | if (!slash) |
2623 | error = prepend(buffer, buflen, "/", 1); | 2627 | error = prepend(buffer, buflen, "/", 1); |
2624 | if (!error) | 2628 | if (!error) |
2625 | error = real_mount(vfsmnt)->mnt_ns ? 1 : 2; | 2629 | error = is_mounted(vfsmnt) ? 1 : 2; |
2626 | goto out; | 2630 | goto out; |
2627 | } | 2631 | } |
2628 | 2632 | ||
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; |
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 979c1e309c73..14afbabe6546 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c | |||
@@ -439,15 +439,15 @@ static struct dentry *devpts_mount(struct file_system_type *fs_type, | |||
439 | return ERR_PTR(error); | 439 | return ERR_PTR(error); |
440 | 440 | ||
441 | if (opts.newinstance) | 441 | if (opts.newinstance) |
442 | s = sget(fs_type, NULL, set_anon_super, NULL); | 442 | s = sget(fs_type, NULL, set_anon_super, flags, NULL); |
443 | else | 443 | else |
444 | s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL); | 444 | s = sget(fs_type, compare_init_pts_sb, set_anon_super, flags, |
445 | NULL); | ||
445 | 446 | ||
446 | if (IS_ERR(s)) | 447 | if (IS_ERR(s)) |
447 | return ERR_CAST(s); | 448 | return ERR_CAST(s); |
448 | 449 | ||
449 | if (!s->s_root) { | 450 | if (!s->s_root) { |
450 | s->s_flags = flags; | ||
451 | error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0); | 451 | error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0); |
452 | if (error) | 452 | if (error) |
453 | goto out_undo_sget; | 453 | goto out_undo_sget; |
diff --git a/fs/direct-io.c b/fs/direct-io.c index 0c85fae37666..1faf4cb56f39 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
@@ -1258,7 +1258,7 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | |||
1258 | */ | 1258 | */ |
1259 | BUG_ON(retval == -EIOCBQUEUED); | 1259 | BUG_ON(retval == -EIOCBQUEUED); |
1260 | if (dio->is_async && retval == 0 && dio->result && | 1260 | if (dio->is_async && retval == 0 && dio->result && |
1261 | ((rw & READ) || (dio->result == sdio.size))) | 1261 | ((rw == READ) || (dio->result == sdio.size))) |
1262 | retval = -EIOCBQUEUED; | 1262 | retval = -EIOCBQUEUED; |
1263 | 1263 | ||
1264 | if (retval != -EIOCBQUEUED) | 1264 | if (retval != -EIOCBQUEUED) |
diff --git a/fs/ecryptfs/dentry.c b/fs/ecryptfs/dentry.c index 534c1d46e69e..1b5d9af937df 100644 --- a/fs/ecryptfs/dentry.c +++ b/fs/ecryptfs/dentry.c | |||
@@ -32,7 +32,7 @@ | |||
32 | /** | 32 | /** |
33 | * ecryptfs_d_revalidate - revalidate an ecryptfs dentry | 33 | * ecryptfs_d_revalidate - revalidate an ecryptfs dentry |
34 | * @dentry: The ecryptfs dentry | 34 | * @dentry: The ecryptfs dentry |
35 | * @nd: The associated nameidata | 35 | * @flags: lookup flags |
36 | * | 36 | * |
37 | * Called when the VFS needs to revalidate a dentry. This | 37 | * Called when the VFS needs to revalidate a dentry. This |
38 | * is called whenever a name lookup finds a dentry in the | 38 | * is called whenever a name lookup finds a dentry in the |
@@ -42,32 +42,20 @@ | |||
42 | * Returns 1 if valid, 0 otherwise. | 42 | * Returns 1 if valid, 0 otherwise. |
43 | * | 43 | * |
44 | */ | 44 | */ |
45 | static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd) | 45 | static int ecryptfs_d_revalidate(struct dentry *dentry, unsigned int flags) |
46 | { | 46 | { |
47 | struct dentry *lower_dentry; | 47 | struct dentry *lower_dentry; |
48 | struct vfsmount *lower_mnt; | 48 | struct vfsmount *lower_mnt; |
49 | struct dentry *dentry_save = NULL; | ||
50 | struct vfsmount *vfsmount_save = NULL; | ||
51 | int rc = 1; | 49 | int rc = 1; |
52 | 50 | ||
53 | if (nd && nd->flags & LOOKUP_RCU) | 51 | if (flags & LOOKUP_RCU) |
54 | return -ECHILD; | 52 | return -ECHILD; |
55 | 53 | ||
56 | lower_dentry = ecryptfs_dentry_to_lower(dentry); | 54 | lower_dentry = ecryptfs_dentry_to_lower(dentry); |
57 | lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); | 55 | lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); |
58 | if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate) | 56 | if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate) |
59 | goto out; | 57 | goto out; |
60 | if (nd) { | 58 | rc = lower_dentry->d_op->d_revalidate(lower_dentry, flags); |
61 | dentry_save = nd->path.dentry; | ||
62 | vfsmount_save = nd->path.mnt; | ||
63 | nd->path.dentry = lower_dentry; | ||
64 | nd->path.mnt = lower_mnt; | ||
65 | } | ||
66 | rc = lower_dentry->d_op->d_revalidate(lower_dentry, nd); | ||
67 | if (nd) { | ||
68 | nd->path.dentry = dentry_save; | ||
69 | nd->path.mnt = vfsmount_save; | ||
70 | } | ||
71 | if (dentry->d_inode) { | 59 | if (dentry->d_inode) { |
72 | struct inode *lower_inode = | 60 | struct inode *lower_inode = |
73 | ecryptfs_inode_to_lower(dentry->d_inode); | 61 | ecryptfs_inode_to_lower(dentry->d_inode); |
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 867b64c5d84f..989e034f02bd 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
@@ -550,20 +550,6 @@ extern struct kmem_cache *ecryptfs_key_record_cache; | |||
550 | extern struct kmem_cache *ecryptfs_key_sig_cache; | 550 | extern struct kmem_cache *ecryptfs_key_sig_cache; |
551 | extern struct kmem_cache *ecryptfs_global_auth_tok_cache; | 551 | extern struct kmem_cache *ecryptfs_global_auth_tok_cache; |
552 | extern struct kmem_cache *ecryptfs_key_tfm_cache; | 552 | extern struct kmem_cache *ecryptfs_key_tfm_cache; |
553 | extern struct kmem_cache *ecryptfs_open_req_cache; | ||
554 | |||
555 | struct ecryptfs_open_req { | ||
556 | #define ECRYPTFS_REQ_PROCESSED 0x00000001 | ||
557 | #define ECRYPTFS_REQ_DROPPED 0x00000002 | ||
558 | #define ECRYPTFS_REQ_ZOMBIE 0x00000004 | ||
559 | u32 flags; | ||
560 | struct file **lower_file; | ||
561 | struct dentry *lower_dentry; | ||
562 | struct vfsmount *lower_mnt; | ||
563 | wait_queue_head_t wait; | ||
564 | struct mutex mux; | ||
565 | struct list_head kthread_ctl_list; | ||
566 | }; | ||
567 | 553 | ||
568 | struct inode *ecryptfs_get_inode(struct inode *lower_inode, | 554 | struct inode *ecryptfs_get_inode(struct inode *lower_inode, |
569 | struct super_block *sb); | 555 | struct super_block *sb); |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index a07441a0a878..ffa2be57804d 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -173,7 +173,7 @@ ecryptfs_do_create(struct inode *directory_inode, | |||
173 | inode = ERR_CAST(lower_dir_dentry); | 173 | inode = ERR_CAST(lower_dir_dentry); |
174 | goto out; | 174 | goto out; |
175 | } | 175 | } |
176 | rc = vfs_create(lower_dir_dentry->d_inode, lower_dentry, mode, NULL); | 176 | rc = vfs_create(lower_dir_dentry->d_inode, lower_dentry, mode, true); |
177 | if (rc) { | 177 | if (rc) { |
178 | printk(KERN_ERR "%s: Failure to create dentry in lower fs; " | 178 | printk(KERN_ERR "%s: Failure to create dentry in lower fs; " |
179 | "rc = [%d]\n", __func__, rc); | 179 | "rc = [%d]\n", __func__, rc); |
@@ -240,7 +240,6 @@ out: | |||
240 | * @dir: The inode of the directory in which to create the file. | 240 | * @dir: The inode of the directory in which to create the file. |
241 | * @dentry: The eCryptfs dentry | 241 | * @dentry: The eCryptfs dentry |
242 | * @mode: The mode of the new file. | 242 | * @mode: The mode of the new file. |
243 | * @nd: nameidata | ||
244 | * | 243 | * |
245 | * Creates a new file. | 244 | * Creates a new file. |
246 | * | 245 | * |
@@ -248,7 +247,7 @@ out: | |||
248 | */ | 247 | */ |
249 | static int | 248 | static int |
250 | ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry, | 249 | ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry, |
251 | umode_t mode, struct nameidata *nd) | 250 | umode_t mode, bool excl) |
252 | { | 251 | { |
253 | struct inode *ecryptfs_inode; | 252 | struct inode *ecryptfs_inode; |
254 | int rc; | 253 | int rc; |
@@ -270,8 +269,8 @@ ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry, | |||
270 | iput(ecryptfs_inode); | 269 | iput(ecryptfs_inode); |
271 | goto out; | 270 | goto out; |
272 | } | 271 | } |
273 | d_instantiate(ecryptfs_dentry, ecryptfs_inode); | ||
274 | unlock_new_inode(ecryptfs_inode); | 272 | unlock_new_inode(ecryptfs_inode); |
273 | d_instantiate(ecryptfs_dentry, ecryptfs_inode); | ||
275 | out: | 274 | out: |
276 | return rc; | 275 | return rc; |
277 | } | 276 | } |
@@ -374,7 +373,7 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry, | |||
374 | */ | 373 | */ |
375 | static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, | 374 | static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode, |
376 | struct dentry *ecryptfs_dentry, | 375 | struct dentry *ecryptfs_dentry, |
377 | struct nameidata *ecryptfs_nd) | 376 | unsigned int flags) |
378 | { | 377 | { |
379 | char *encrypted_and_encoded_name = NULL; | 378 | char *encrypted_and_encoded_name = NULL; |
380 | size_t encrypted_and_encoded_name_size; | 379 | size_t encrypted_and_encoded_name_size; |
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c index 0dbe58a8b172..809e67d05ca3 100644 --- a/fs/ecryptfs/kthread.c +++ b/fs/ecryptfs/kthread.c | |||
@@ -27,7 +27,12 @@ | |||
27 | #include <linux/mount.h> | 27 | #include <linux/mount.h> |
28 | #include "ecryptfs_kernel.h" | 28 | #include "ecryptfs_kernel.h" |
29 | 29 | ||
30 | struct kmem_cache *ecryptfs_open_req_cache; | 30 | struct ecryptfs_open_req { |
31 | struct file **lower_file; | ||
32 | struct path path; | ||
33 | struct completion done; | ||
34 | struct list_head kthread_ctl_list; | ||
35 | }; | ||
31 | 36 | ||
32 | static struct ecryptfs_kthread_ctl { | 37 | static struct ecryptfs_kthread_ctl { |
33 | #define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001 | 38 | #define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001 |
@@ -67,18 +72,10 @@ static int ecryptfs_threadfn(void *ignored) | |||
67 | req = list_first_entry(&ecryptfs_kthread_ctl.req_list, | 72 | req = list_first_entry(&ecryptfs_kthread_ctl.req_list, |
68 | struct ecryptfs_open_req, | 73 | struct ecryptfs_open_req, |
69 | kthread_ctl_list); | 74 | kthread_ctl_list); |
70 | mutex_lock(&req->mux); | ||
71 | list_del(&req->kthread_ctl_list); | 75 | list_del(&req->kthread_ctl_list); |
72 | if (!(req->flags & ECRYPTFS_REQ_ZOMBIE)) { | 76 | *req->lower_file = dentry_open(&req->path, |
73 | dget(req->lower_dentry); | 77 | (O_RDWR | O_LARGEFILE), current_cred()); |
74 | mntget(req->lower_mnt); | 78 | complete(&req->done); |
75 | (*req->lower_file) = dentry_open( | ||
76 | req->lower_dentry, req->lower_mnt, | ||
77 | (O_RDWR | O_LARGEFILE), current_cred()); | ||
78 | req->flags |= ECRYPTFS_REQ_PROCESSED; | ||
79 | } | ||
80 | wake_up(&req->wait); | ||
81 | mutex_unlock(&req->mux); | ||
82 | } | 79 | } |
83 | mutex_unlock(&ecryptfs_kthread_ctl.mux); | 80 | mutex_unlock(&ecryptfs_kthread_ctl.mux); |
84 | } | 81 | } |
@@ -111,10 +108,9 @@ void ecryptfs_destroy_kthread(void) | |||
111 | ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE; | 108 | ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE; |
112 | list_for_each_entry(req, &ecryptfs_kthread_ctl.req_list, | 109 | list_for_each_entry(req, &ecryptfs_kthread_ctl.req_list, |
113 | kthread_ctl_list) { | 110 | kthread_ctl_list) { |
114 | mutex_lock(&req->mux); | 111 | list_del(&req->kthread_ctl_list); |
115 | req->flags |= ECRYPTFS_REQ_ZOMBIE; | 112 | *req->lower_file = ERR_PTR(-EIO); |
116 | wake_up(&req->wait); | 113 | complete(&req->done); |
117 | mutex_unlock(&req->mux); | ||
118 | } | 114 | } |
119 | mutex_unlock(&ecryptfs_kthread_ctl.mux); | 115 | mutex_unlock(&ecryptfs_kthread_ctl.mux); |
120 | kthread_stop(ecryptfs_kthread); | 116 | kthread_stop(ecryptfs_kthread); |
@@ -136,34 +132,26 @@ int ecryptfs_privileged_open(struct file **lower_file, | |||
136 | struct vfsmount *lower_mnt, | 132 | struct vfsmount *lower_mnt, |
137 | const struct cred *cred) | 133 | const struct cred *cred) |
138 | { | 134 | { |
139 | struct ecryptfs_open_req *req; | 135 | struct ecryptfs_open_req req; |
140 | int flags = O_LARGEFILE; | 136 | int flags = O_LARGEFILE; |
141 | int rc = 0; | 137 | int rc = 0; |
142 | 138 | ||
139 | init_completion(&req.done); | ||
140 | req.lower_file = lower_file; | ||
141 | req.path.dentry = lower_dentry; | ||
142 | req.path.mnt = lower_mnt; | ||
143 | |||
143 | /* Corresponding dput() and mntput() are done when the | 144 | /* Corresponding dput() and mntput() are done when the |
144 | * lower file is fput() when all eCryptfs files for the inode are | 145 | * lower file is fput() when all eCryptfs files for the inode are |
145 | * released. */ | 146 | * released. */ |
146 | dget(lower_dentry); | ||
147 | mntget(lower_mnt); | ||
148 | flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; | 147 | flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; |
149 | (*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred); | 148 | (*lower_file) = dentry_open(&req.path, flags, cred); |
150 | if (!IS_ERR(*lower_file)) | 149 | if (!IS_ERR(*lower_file)) |
151 | goto out; | 150 | goto out; |
152 | if ((flags & O_ACCMODE) == O_RDONLY) { | 151 | if ((flags & O_ACCMODE) == O_RDONLY) { |
153 | rc = PTR_ERR((*lower_file)); | 152 | rc = PTR_ERR((*lower_file)); |
154 | goto out; | 153 | goto out; |
155 | } | 154 | } |
156 | req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL); | ||
157 | if (!req) { | ||
158 | rc = -ENOMEM; | ||
159 | goto out; | ||
160 | } | ||
161 | mutex_init(&req->mux); | ||
162 | req->lower_file = lower_file; | ||
163 | req->lower_dentry = lower_dentry; | ||
164 | req->lower_mnt = lower_mnt; | ||
165 | init_waitqueue_head(&req->wait); | ||
166 | req->flags = 0; | ||
167 | mutex_lock(&ecryptfs_kthread_ctl.mux); | 155 | mutex_lock(&ecryptfs_kthread_ctl.mux); |
168 | if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) { | 156 | if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) { |
169 | rc = -EIO; | 157 | rc = -EIO; |
@@ -171,27 +159,14 @@ int ecryptfs_privileged_open(struct file **lower_file, | |||
171 | printk(KERN_ERR "%s: We are in the middle of shutting down; " | 159 | printk(KERN_ERR "%s: We are in the middle of shutting down; " |
172 | "aborting privileged request to open lower file\n", | 160 | "aborting privileged request to open lower file\n", |
173 | __func__); | 161 | __func__); |
174 | goto out_free; | 162 | goto out; |
175 | } | 163 | } |
176 | list_add_tail(&req->kthread_ctl_list, &ecryptfs_kthread_ctl.req_list); | 164 | list_add_tail(&req.kthread_ctl_list, &ecryptfs_kthread_ctl.req_list); |
177 | mutex_unlock(&ecryptfs_kthread_ctl.mux); | 165 | mutex_unlock(&ecryptfs_kthread_ctl.mux); |
178 | wake_up(&ecryptfs_kthread_ctl.wait); | 166 | wake_up(&ecryptfs_kthread_ctl.wait); |
179 | wait_event(req->wait, (req->flags != 0)); | 167 | wait_for_completion(&req.done); |
180 | mutex_lock(&req->mux); | 168 | if (IS_ERR(*lower_file)) |
181 | BUG_ON(req->flags == 0); | 169 | rc = PTR_ERR(*lower_file); |
182 | if (req->flags & ECRYPTFS_REQ_DROPPED | ||
183 | || req->flags & ECRYPTFS_REQ_ZOMBIE) { | ||
184 | rc = -EIO; | ||
185 | printk(KERN_WARNING "%s: Privileged open request dropped\n", | ||
186 | __func__); | ||
187 | goto out_unlock; | ||
188 | } | ||
189 | if (IS_ERR(*req->lower_file)) | ||
190 | rc = PTR_ERR(*req->lower_file); | ||
191 | out_unlock: | ||
192 | mutex_unlock(&req->mux); | ||
193 | out_free: | ||
194 | kmem_cache_free(ecryptfs_open_req_cache, req); | ||
195 | out: | 170 | out: |
196 | return rc; | 171 | return rc; |
197 | } | 172 | } |
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 68954937a071..1c0b3b6b75c6 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
@@ -499,13 +499,12 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags | |||
499 | goto out; | 499 | goto out; |
500 | } | 500 | } |
501 | 501 | ||
502 | s = sget(fs_type, NULL, set_anon_super, NULL); | 502 | s = sget(fs_type, NULL, set_anon_super, flags, NULL); |
503 | if (IS_ERR(s)) { | 503 | if (IS_ERR(s)) { |
504 | rc = PTR_ERR(s); | 504 | rc = PTR_ERR(s); |
505 | goto out; | 505 | goto out; |
506 | } | 506 | } |
507 | 507 | ||
508 | s->s_flags = flags; | ||
509 | rc = bdi_setup_and_register(&sbi->bdi, "ecryptfs", BDI_CAP_MAP_COPY); | 508 | rc = bdi_setup_and_register(&sbi->bdi, "ecryptfs", BDI_CAP_MAP_COPY); |
510 | if (rc) | 509 | if (rc) |
511 | goto out1; | 510 | goto out1; |
@@ -682,11 +681,6 @@ static struct ecryptfs_cache_info { | |||
682 | .name = "ecryptfs_key_tfm_cache", | 681 | .name = "ecryptfs_key_tfm_cache", |
683 | .size = sizeof(struct ecryptfs_key_tfm), | 682 | .size = sizeof(struct ecryptfs_key_tfm), |
684 | }, | 683 | }, |
685 | { | ||
686 | .cache = &ecryptfs_open_req_cache, | ||
687 | .name = "ecryptfs_open_req_cache", | ||
688 | .size = sizeof(struct ecryptfs_open_req), | ||
689 | }, | ||
690 | }; | 684 | }; |
691 | 685 | ||
692 | static void ecryptfs_free_kmem_caches(void) | 686 | static void ecryptfs_free_kmem_caches(void) |
diff --git a/fs/efs/efs.h b/fs/efs/efs.h index d8305b582ab0..5528926ac7f6 100644 --- a/fs/efs/efs.h +++ b/fs/efs/efs.h | |||
@@ -129,7 +129,7 @@ extern struct inode *efs_iget(struct super_block *, unsigned long); | |||
129 | extern efs_block_t efs_map_block(struct inode *, efs_block_t); | 129 | extern efs_block_t efs_map_block(struct inode *, efs_block_t); |
130 | extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int); | 130 | extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int); |
131 | 131 | ||
132 | extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *); | 132 | extern struct dentry *efs_lookup(struct inode *, struct dentry *, unsigned int); |
133 | extern struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid, | 133 | extern struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid, |
134 | int fh_len, int fh_type); | 134 | int fh_len, int fh_type); |
135 | extern struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid, | 135 | extern struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid, |
diff --git a/fs/efs/namei.c b/fs/efs/namei.c index 832b10ded82f..96f66d213a19 100644 --- a/fs/efs/namei.c +++ b/fs/efs/namei.c | |||
@@ -58,7 +58,8 @@ static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) | |||
58 | return(0); | 58 | return(0); |
59 | } | 59 | } |
60 | 60 | ||
61 | struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { | 61 | struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
62 | { | ||
62 | efs_ino_t inodenum; | 63 | efs_ino_t inodenum; |
63 | struct inode *inode = NULL; | 64 | struct inode *inode = NULL; |
64 | 65 | ||
diff --git a/fs/exofs/namei.c b/fs/exofs/namei.c index fc7161d6bf6b..4731fd991efe 100644 --- a/fs/exofs/namei.c +++ b/fs/exofs/namei.c | |||
@@ -46,7 +46,7 @@ static inline int exofs_add_nondir(struct dentry *dentry, struct inode *inode) | |||
46 | } | 46 | } |
47 | 47 | ||
48 | static struct dentry *exofs_lookup(struct inode *dir, struct dentry *dentry, | 48 | static struct dentry *exofs_lookup(struct inode *dir, struct dentry *dentry, |
49 | struct nameidata *nd) | 49 | unsigned int flags) |
50 | { | 50 | { |
51 | struct inode *inode; | 51 | struct inode *inode; |
52 | ino_t ino; | 52 | ino_t ino; |
@@ -60,7 +60,7 @@ static struct dentry *exofs_lookup(struct inode *dir, struct dentry *dentry, | |||
60 | } | 60 | } |
61 | 61 | ||
62 | static int exofs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 62 | static int exofs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
63 | struct nameidata *nd) | 63 | bool excl) |
64 | { | 64 | { |
65 | struct inode *inode = exofs_new_inode(dir, mode); | 65 | struct inode *inode = exofs_new_inode(dir, mode); |
66 | int err = PTR_ERR(inode); | 66 | int err = PTR_ERR(inode); |
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index b0201ca6e9c6..29ab099e3e08 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c | |||
@@ -19,19 +19,19 @@ | |||
19 | #define dprintk(fmt, args...) do{}while(0) | 19 | #define dprintk(fmt, args...) do{}while(0) |
20 | 20 | ||
21 | 21 | ||
22 | static int get_name(struct vfsmount *mnt, struct dentry *dentry, char *name, | 22 | static int get_name(const struct path *path, char *name, struct dentry *child); |
23 | struct dentry *child); | ||
24 | 23 | ||
25 | 24 | ||
26 | static int exportfs_get_name(struct vfsmount *mnt, struct dentry *dir, | 25 | static int exportfs_get_name(struct vfsmount *mnt, struct dentry *dir, |
27 | char *name, struct dentry *child) | 26 | char *name, struct dentry *child) |
28 | { | 27 | { |
29 | const struct export_operations *nop = dir->d_sb->s_export_op; | 28 | const struct export_operations *nop = dir->d_sb->s_export_op; |
29 | struct path path = {.mnt = mnt, .dentry = dir}; | ||
30 | 30 | ||
31 | if (nop->get_name) | 31 | if (nop->get_name) |
32 | return nop->get_name(dir, name, child); | 32 | return nop->get_name(dir, name, child); |
33 | else | 33 | else |
34 | return get_name(mnt, dir, name, child); | 34 | return get_name(&path, name, child); |
35 | } | 35 | } |
36 | 36 | ||
37 | /* | 37 | /* |
@@ -44,13 +44,14 @@ find_acceptable_alias(struct dentry *result, | |||
44 | { | 44 | { |
45 | struct dentry *dentry, *toput = NULL; | 45 | struct dentry *dentry, *toput = NULL; |
46 | struct inode *inode; | 46 | struct inode *inode; |
47 | struct hlist_node *p; | ||
47 | 48 | ||
48 | if (acceptable(context, result)) | 49 | if (acceptable(context, result)) |
49 | return result; | 50 | return result; |
50 | 51 | ||
51 | inode = result->d_inode; | 52 | inode = result->d_inode; |
52 | spin_lock(&inode->i_lock); | 53 | spin_lock(&inode->i_lock); |
53 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { | 54 | hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) { |
54 | dget(dentry); | 55 | dget(dentry); |
55 | spin_unlock(&inode->i_lock); | 56 | spin_unlock(&inode->i_lock); |
56 | if (toput) | 57 | if (toput) |
@@ -248,11 +249,10 @@ static int filldir_one(void * __buf, const char * name, int len, | |||
248 | * calls readdir on the parent until it finds an entry with | 249 | * calls readdir on the parent until it finds an entry with |
249 | * the same inode number as the child, and returns that. | 250 | * the same inode number as the child, and returns that. |
250 | */ | 251 | */ |
251 | static int get_name(struct vfsmount *mnt, struct dentry *dentry, | 252 | static int get_name(const struct path *path, char *name, struct dentry *child) |
252 | char *name, struct dentry *child) | ||
253 | { | 253 | { |
254 | const struct cred *cred = current_cred(); | 254 | const struct cred *cred = current_cred(); |
255 | struct inode *dir = dentry->d_inode; | 255 | struct inode *dir = path->dentry->d_inode; |
256 | int error; | 256 | int error; |
257 | struct file *file; | 257 | struct file *file; |
258 | struct getdents_callback buffer; | 258 | struct getdents_callback buffer; |
@@ -266,7 +266,7 @@ static int get_name(struct vfsmount *mnt, struct dentry *dentry, | |||
266 | /* | 266 | /* |
267 | * Open the directory ... | 267 | * Open the directory ... |
268 | */ | 268 | */ |
269 | file = dentry_open(dget(dentry), mntget(mnt), O_RDONLY, cred); | 269 | file = dentry_open(path, O_RDONLY, cred); |
270 | error = PTR_ERR(file); | 270 | error = PTR_ERR(file); |
271 | if (IS_ERR(file)) | 271 | if (IS_ERR(file)) |
272 | goto out; | 272 | goto out; |
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index f663a67d7bf0..73b0d9519836 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c | |||
@@ -41,8 +41,8 @@ static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode) | |||
41 | { | 41 | { |
42 | int err = ext2_add_link(dentry, inode); | 42 | int err = ext2_add_link(dentry, inode); |
43 | if (!err) { | 43 | if (!err) { |
44 | d_instantiate(dentry, inode); | ||
45 | unlock_new_inode(inode); | 44 | unlock_new_inode(inode); |
45 | d_instantiate(dentry, inode); | ||
46 | return 0; | 46 | return 0; |
47 | } | 47 | } |
48 | inode_dec_link_count(inode); | 48 | inode_dec_link_count(inode); |
@@ -55,7 +55,7 @@ static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode) | |||
55 | * Methods themselves. | 55 | * Methods themselves. |
56 | */ | 56 | */ |
57 | 57 | ||
58 | static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) | 58 | static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags) |
59 | { | 59 | { |
60 | struct inode * inode; | 60 | struct inode * inode; |
61 | ino_t ino; | 61 | ino_t ino; |
@@ -94,7 +94,7 @@ struct dentry *ext2_get_parent(struct dentry *child) | |||
94 | * If the create succeeds, we fill in the inode information | 94 | * If the create succeeds, we fill in the inode information |
95 | * with d_instantiate(). | 95 | * with d_instantiate(). |
96 | */ | 96 | */ |
97 | static int ext2_create (struct inode * dir, struct dentry * dentry, umode_t mode, struct nameidata *nd) | 97 | static int ext2_create (struct inode * dir, struct dentry * dentry, umode_t mode, bool excl) |
98 | { | 98 | { |
99 | struct inode *inode; | 99 | struct inode *inode; |
100 | 100 | ||
@@ -242,8 +242,8 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode) | |||
242 | if (err) | 242 | if (err) |
243 | goto out_fail; | 243 | goto out_fail; |
244 | 244 | ||
245 | d_instantiate(dentry, inode); | ||
246 | unlock_new_inode(inode); | 245 | unlock_new_inode(inode); |
246 | d_instantiate(dentry, inode); | ||
247 | out: | 247 | out: |
248 | return err; | 248 | return err; |
249 | 249 | ||
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index b3621cb7ea31..5df3d2d8169c 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
@@ -1184,6 +1184,12 @@ static int ext2_sync_fs(struct super_block *sb, int wait) | |||
1184 | struct ext2_sb_info *sbi = EXT2_SB(sb); | 1184 | struct ext2_sb_info *sbi = EXT2_SB(sb); |
1185 | struct ext2_super_block *es = EXT2_SB(sb)->s_es; | 1185 | struct ext2_super_block *es = EXT2_SB(sb)->s_es; |
1186 | 1186 | ||
1187 | /* | ||
1188 | * Write quota structures to quota file, sync_blockdev() will write | ||
1189 | * them to disk later | ||
1190 | */ | ||
1191 | dquot_writeback_dquots(sb, -1); | ||
1192 | |||
1187 | spin_lock(&sbi->s_lock); | 1193 | spin_lock(&sbi->s_lock); |
1188 | if (es->s_state & cpu_to_le16(EXT2_VALID_FS)) { | 1194 | if (es->s_state & cpu_to_le16(EXT2_VALID_FS)) { |
1189 | ext2_debug("setting valid to 0\n"); | 1195 | ext2_debug("setting valid to 0\n"); |
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 92490e9f85ca..c8fff930790d 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c | |||
@@ -300,10 +300,11 @@ loff_t ext3_dir_llseek(struct file *file, loff_t offset, int origin) | |||
300 | { | 300 | { |
301 | struct inode *inode = file->f_mapping->host; | 301 | struct inode *inode = file->f_mapping->host; |
302 | int dx_dir = is_dx_dir(inode); | 302 | int dx_dir = is_dx_dir(inode); |
303 | loff_t htree_max = ext3_get_htree_eof(file); | ||
303 | 304 | ||
304 | if (likely(dx_dir)) | 305 | if (likely(dx_dir)) |
305 | return generic_file_llseek_size(file, offset, origin, | 306 | return generic_file_llseek_size(file, offset, origin, |
306 | ext3_get_htree_eof(file)); | 307 | htree_max, htree_max); |
307 | else | 308 | else |
308 | return generic_file_llseek(file, offset, origin); | 309 | return generic_file_llseek(file, offset, origin); |
309 | } | 310 | } |
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index eeb63dfc5d20..8f4fddac01a6 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
@@ -1011,7 +1011,7 @@ errout: | |||
1011 | return NULL; | 1011 | return NULL; |
1012 | } | 1012 | } |
1013 | 1013 | ||
1014 | static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) | 1014 | static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags) |
1015 | { | 1015 | { |
1016 | struct inode * inode; | 1016 | struct inode * inode; |
1017 | struct ext3_dir_entry_2 * de; | 1017 | struct ext3_dir_entry_2 * de; |
@@ -1671,8 +1671,8 @@ static int ext3_add_nondir(handle_t *handle, | |||
1671 | int err = ext3_add_entry(handle, dentry, inode); | 1671 | int err = ext3_add_entry(handle, dentry, inode); |
1672 | if (!err) { | 1672 | if (!err) { |
1673 | ext3_mark_inode_dirty(handle, inode); | 1673 | ext3_mark_inode_dirty(handle, inode); |
1674 | d_instantiate(dentry, inode); | ||
1675 | unlock_new_inode(inode); | 1674 | unlock_new_inode(inode); |
1675 | d_instantiate(dentry, inode); | ||
1676 | return 0; | 1676 | return 0; |
1677 | } | 1677 | } |
1678 | drop_nlink(inode); | 1678 | drop_nlink(inode); |
@@ -1690,7 +1690,7 @@ static int ext3_add_nondir(handle_t *handle, | |||
1690 | * with d_instantiate(). | 1690 | * with d_instantiate(). |
1691 | */ | 1691 | */ |
1692 | static int ext3_create (struct inode * dir, struct dentry * dentry, umode_t mode, | 1692 | static int ext3_create (struct inode * dir, struct dentry * dentry, umode_t mode, |
1693 | struct nameidata *nd) | 1693 | bool excl) |
1694 | { | 1694 | { |
1695 | handle_t *handle; | 1695 | handle_t *handle; |
1696 | struct inode * inode; | 1696 | struct inode * inode; |
@@ -1836,8 +1836,8 @@ out_clear_inode: | |||
1836 | if (err) | 1836 | if (err) |
1837 | goto out_clear_inode; | 1837 | goto out_clear_inode; |
1838 | 1838 | ||
1839 | d_instantiate(dentry, inode); | ||
1840 | unlock_new_inode(inode); | 1839 | unlock_new_inode(inode); |
1840 | d_instantiate(dentry, inode); | ||
1841 | out_stop: | 1841 | out_stop: |
1842 | brelse(dir_block); | 1842 | brelse(dir_block); |
1843 | ext3_journal_stop(handle); | 1843 | ext3_journal_stop(handle); |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 8c3a44b7c375..4ac304c55c53 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -2526,6 +2526,11 @@ static int ext3_sync_fs(struct super_block *sb, int wait) | |||
2526 | tid_t target; | 2526 | tid_t target; |
2527 | 2527 | ||
2528 | trace_ext3_sync_fs(sb, wait); | 2528 | trace_ext3_sync_fs(sb, wait); |
2529 | /* | ||
2530 | * Writeback quota in non-journalled quota case - journalled quota has | ||
2531 | * no dirty dquots | ||
2532 | */ | ||
2533 | dquot_writeback_dquots(sb, -1); | ||
2529 | if (journal_start_commit(EXT3_SB(sb)->s_journal, &target)) { | 2534 | if (journal_start_commit(EXT3_SB(sb)->s_journal, &target)) { |
2530 | if (wait) | 2535 | if (wait) |
2531 | log_wait_commit(EXT3_SB(sb)->s_journal, target); | 2536 | log_wait_commit(EXT3_SB(sb)->s_journal, target); |
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index aa39e600d159..8e07d2a5a139 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c | |||
@@ -324,74 +324,27 @@ static inline loff_t ext4_get_htree_eof(struct file *filp) | |||
324 | 324 | ||
325 | 325 | ||
326 | /* | 326 | /* |
327 | * ext4_dir_llseek() based on generic_file_llseek() to handle both | 327 | * ext4_dir_llseek() calls generic_file_llseek_size to handle htree |
328 | * non-htree and htree directories, where the "offset" is in terms | 328 | * directories, where the "offset" is in terms of the filename hash |
329 | * of the filename hash value instead of the byte offset. | 329 | * value instead of the byte offset. |
330 | * | 330 | * |
331 | * NOTE: offsets obtained *before* ext4_set_inode_flag(dir, EXT4_INODE_INDEX) | 331 | * Because we may return a 64-bit hash that is well beyond offset limits, |
332 | * will be invalid once the directory was converted into a dx directory | 332 | * we need to pass the max hash as the maximum allowable offset in |
333 | * the htree directory case. | ||
334 | * | ||
335 | * For non-htree, ext4_llseek already chooses the proper max offset. | ||
333 | */ | 336 | */ |
334 | loff_t ext4_dir_llseek(struct file *file, loff_t offset, int origin) | 337 | loff_t ext4_dir_llseek(struct file *file, loff_t offset, int origin) |
335 | { | 338 | { |
336 | struct inode *inode = file->f_mapping->host; | 339 | struct inode *inode = file->f_mapping->host; |
337 | loff_t ret = -EINVAL; | ||
338 | int dx_dir = is_dx_dir(inode); | 340 | int dx_dir = is_dx_dir(inode); |
341 | loff_t htree_max = ext4_get_htree_eof(file); | ||
339 | 342 | ||
340 | mutex_lock(&inode->i_mutex); | 343 | if (likely(dx_dir)) |
341 | 344 | return generic_file_llseek_size(file, offset, origin, | |
342 | /* NOTE: relative offsets with dx directories might not work | 345 | htree_max, htree_max); |
343 | * as expected, as it is difficult to figure out the | 346 | else |
344 | * correct offset between dx hashes */ | 347 | return ext4_llseek(file, offset, origin); |
345 | |||
346 | switch (origin) { | ||
347 | case SEEK_END: | ||
348 | if (unlikely(offset > 0)) | ||
349 | goto out_err; /* not supported for directories */ | ||
350 | |||
351 | /* so only negative offsets are left, does that have a | ||
352 | * meaning for directories at all? */ | ||
353 | if (dx_dir) | ||
354 | offset += ext4_get_htree_eof(file); | ||
355 | else | ||
356 | offset += inode->i_size; | ||
357 | break; | ||
358 | case SEEK_CUR: | ||
359 | /* | ||
360 | * Here we special-case the lseek(fd, 0, SEEK_CUR) | ||
361 | * position-querying operation. Avoid rewriting the "same" | ||
362 | * f_pos value back to the file because a concurrent read(), | ||
363 | * write() or lseek() might have altered it | ||
364 | */ | ||
365 | if (offset == 0) { | ||
366 | offset = file->f_pos; | ||
367 | goto out_ok; | ||
368 | } | ||
369 | |||
370 | offset += file->f_pos; | ||
371 | break; | ||
372 | } | ||
373 | |||
374 | if (unlikely(offset < 0)) | ||
375 | goto out_err; | ||
376 | |||
377 | if (!dx_dir) { | ||
378 | if (offset > inode->i_sb->s_maxbytes) | ||
379 | goto out_err; | ||
380 | } else if (offset > ext4_get_htree_eof(file)) | ||
381 | goto out_err; | ||
382 | |||
383 | /* Special lock needed here? */ | ||
384 | if (offset != file->f_pos) { | ||
385 | file->f_pos = offset; | ||
386 | file->f_version = 0; | ||
387 | } | ||
388 | |||
389 | out_ok: | ||
390 | ret = offset; | ||
391 | out_err: | ||
392 | mutex_unlock(&inode->i_mutex); | ||
393 | |||
394 | return ret; | ||
395 | } | 348 | } |
396 | 349 | ||
397 | /* | 350 | /* |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 8c7642a00054..782eecb57e43 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -211,9 +211,9 @@ static int ext4_file_open(struct inode * inode, struct file * filp) | |||
211 | } | 211 | } |
212 | 212 | ||
213 | /* | 213 | /* |
214 | * ext4_llseek() copied from generic_file_llseek() to handle both | 214 | * ext4_llseek() handles both block-mapped and extent-mapped maxbytes values |
215 | * block-mapped and extent-mapped maxbytes values. This should | 215 | * by calling generic_file_llseek_size() with the appropriate maxbytes |
216 | * otherwise be identical with generic_file_llseek(). | 216 | * value for each. |
217 | */ | 217 | */ |
218 | loff_t ext4_llseek(struct file *file, loff_t offset, int origin) | 218 | loff_t ext4_llseek(struct file *file, loff_t offset, int origin) |
219 | { | 219 | { |
@@ -225,7 +225,8 @@ loff_t ext4_llseek(struct file *file, loff_t offset, int origin) | |||
225 | else | 225 | else |
226 | maxbytes = inode->i_sb->s_maxbytes; | 226 | maxbytes = inode->i_sb->s_maxbytes; |
227 | 227 | ||
228 | return generic_file_llseek_size(file, offset, origin, maxbytes); | 228 | return generic_file_llseek_size(file, offset, origin, |
229 | maxbytes, i_size_read(inode)); | ||
229 | } | 230 | } |
230 | 231 | ||
231 | const struct file_operations ext4_file_operations = { | 232 | const struct file_operations ext4_file_operations = { |
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c index bb6c7d811313..2a1dcea4f12e 100644 --- a/fs/ext4/fsync.c +++ b/fs/ext4/fsync.c | |||
@@ -135,14 +135,7 @@ static int ext4_sync_parent(struct inode *inode) | |||
135 | inode = igrab(inode); | 135 | inode = igrab(inode); |
136 | while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) { | 136 | while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) { |
137 | ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY); | 137 | ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY); |
138 | dentry = NULL; | 138 | dentry = d_find_any_alias(inode); |
139 | spin_lock(&inode->i_lock); | ||
140 | if (!list_empty(&inode->i_dentry)) { | ||
141 | dentry = list_first_entry(&inode->i_dentry, | ||
142 | struct dentry, d_alias); | ||
143 | dget(dentry); | ||
144 | } | ||
145 | spin_unlock(&inode->i_lock); | ||
146 | if (!dentry) | 139 | if (!dentry) |
147 | break; | 140 | break; |
148 | next = igrab(dentry->d_parent->d_inode); | 141 | next = igrab(dentry->d_parent->d_inode); |
@@ -232,7 +225,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
232 | 225 | ||
233 | if (!journal) { | 226 | if (!journal) { |
234 | ret = __sync_inode(inode, datasync); | 227 | ret = __sync_inode(inode, datasync); |
235 | if (!ret && !list_empty(&inode->i_dentry)) | 228 | if (!ret && !hlist_empty(&inode->i_dentry)) |
236 | ret = ext4_sync_parent(inode); | 229 | ret = ext4_sync_parent(inode); |
237 | goto out; | 230 | goto out; |
238 | } | 231 | } |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 6ec6f9ee2fec..7f7dad787603 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
@@ -389,7 +389,7 @@ group_add_out: | |||
389 | if (err) | 389 | if (err) |
390 | return err; | 390 | return err; |
391 | 391 | ||
392 | err = mnt_want_write(filp->f_path.mnt); | 392 | err = mnt_want_write_file(filp); |
393 | if (err) | 393 | if (err) |
394 | goto resizefs_out; | 394 | goto resizefs_out; |
395 | 395 | ||
@@ -401,7 +401,7 @@ group_add_out: | |||
401 | } | 401 | } |
402 | if (err == 0) | 402 | if (err == 0) |
403 | err = err2; | 403 | err = err2; |
404 | mnt_drop_write(filp->f_path.mnt); | 404 | mnt_drop_write_file(filp); |
405 | resizefs_out: | 405 | resizefs_out: |
406 | ext4_resize_end(sb); | 406 | ext4_resize_end(sb); |
407 | return err; | 407 | return err; |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 5845cd97bf8b..d0d3f0e87f99 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -1312,7 +1312,7 @@ errout: | |||
1312 | return NULL; | 1312 | return NULL; |
1313 | } | 1313 | } |
1314 | 1314 | ||
1315 | static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 1315 | static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
1316 | { | 1316 | { |
1317 | struct inode *inode; | 1317 | struct inode *inode; |
1318 | struct ext4_dir_entry_2 *de; | 1318 | struct ext4_dir_entry_2 *de; |
@@ -2072,8 +2072,8 @@ static int ext4_add_nondir(handle_t *handle, | |||
2072 | int err = ext4_add_entry(handle, dentry, inode); | 2072 | int err = ext4_add_entry(handle, dentry, inode); |
2073 | if (!err) { | 2073 | if (!err) { |
2074 | ext4_mark_inode_dirty(handle, inode); | 2074 | ext4_mark_inode_dirty(handle, inode); |
2075 | d_instantiate(dentry, inode); | ||
2076 | unlock_new_inode(inode); | 2075 | unlock_new_inode(inode); |
2076 | d_instantiate(dentry, inode); | ||
2077 | return 0; | 2077 | return 0; |
2078 | } | 2078 | } |
2079 | drop_nlink(inode); | 2079 | drop_nlink(inode); |
@@ -2091,7 +2091,7 @@ static int ext4_add_nondir(handle_t *handle, | |||
2091 | * with d_instantiate(). | 2091 | * with d_instantiate(). |
2092 | */ | 2092 | */ |
2093 | static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 2093 | static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
2094 | struct nameidata *nd) | 2094 | bool excl) |
2095 | { | 2095 | { |
2096 | handle_t *handle; | 2096 | handle_t *handle; |
2097 | struct inode *inode; | 2097 | struct inode *inode; |
@@ -2249,8 +2249,8 @@ out_clear_inode: | |||
2249 | err = ext4_mark_inode_dirty(handle, dir); | 2249 | err = ext4_mark_inode_dirty(handle, dir); |
2250 | if (err) | 2250 | if (err) |
2251 | goto out_clear_inode; | 2251 | goto out_clear_inode; |
2252 | d_instantiate(dentry, inode); | ||
2253 | unlock_new_inode(inode); | 2252 | unlock_new_inode(inode); |
2253 | d_instantiate(dentry, inode); | ||
2254 | out_stop: | 2254 | out_stop: |
2255 | brelse(dir_block); | 2255 | brelse(dir_block); |
2256 | ext4_journal_stop(handle); | 2256 | ext4_journal_stop(handle); |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index eb7aa3e4ef05..d8759401ecae 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -4325,6 +4325,11 @@ static int ext4_sync_fs(struct super_block *sb, int wait) | |||
4325 | 4325 | ||
4326 | trace_ext4_sync_fs(sb, wait); | 4326 | trace_ext4_sync_fs(sb, wait); |
4327 | flush_workqueue(sbi->dio_unwritten_wq); | 4327 | flush_workqueue(sbi->dio_unwritten_wq); |
4328 | /* | ||
4329 | * Writeback quota in non-journalled quota case - journalled quota has | ||
4330 | * no dirty dquots | ||
4331 | */ | ||
4332 | dquot_writeback_dquots(sb, -1); | ||
4328 | if (jbd2_journal_start_commit(sbi->s_journal, &target)) { | 4333 | if (jbd2_journal_start_commit(sbi->s_journal, &target)) { |
4329 | if (wait) | 4334 | if (wait) |
4330 | jbd2_log_wait_commit(sbi->s_journal, target); | 4335 | jbd2_log_wait_commit(sbi->s_journal, target); |
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c index c5938c9084b9..70d993a93805 100644 --- a/fs/fat/namei_msdos.c +++ b/fs/fat/namei_msdos.c | |||
@@ -201,7 +201,7 @@ static const struct dentry_operations msdos_dentry_operations = { | |||
201 | 201 | ||
202 | /***** Get inode using directory and name */ | 202 | /***** Get inode using directory and name */ |
203 | static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry, | 203 | static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry, |
204 | struct nameidata *nd) | 204 | unsigned int flags) |
205 | { | 205 | { |
206 | struct super_block *sb = dir->i_sb; | 206 | struct super_block *sb = dir->i_sb; |
207 | struct fat_slot_info sinfo; | 207 | struct fat_slot_info sinfo; |
@@ -265,7 +265,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name, | |||
265 | 265 | ||
266 | /***** Create a file */ | 266 | /***** Create a file */ |
267 | static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 267 | static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
268 | struct nameidata *nd) | 268 | bool excl) |
269 | { | 269 | { |
270 | struct super_block *sb = dir->i_sb; | 270 | struct super_block *sb = dir->i_sb; |
271 | struct inode *inode = NULL; | 271 | struct inode *inode = NULL; |
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index 98ae804f5273..6cc480652433 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c | |||
@@ -41,9 +41,9 @@ static int vfat_revalidate_shortname(struct dentry *dentry) | |||
41 | return ret; | 41 | return ret; |
42 | } | 42 | } |
43 | 43 | ||
44 | static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd) | 44 | static int vfat_revalidate(struct dentry *dentry, unsigned int flags) |
45 | { | 45 | { |
46 | if (nd && nd->flags & LOOKUP_RCU) | 46 | if (flags & LOOKUP_RCU) |
47 | return -ECHILD; | 47 | return -ECHILD; |
48 | 48 | ||
49 | /* This is not negative dentry. Always valid. */ | 49 | /* This is not negative dentry. Always valid. */ |
@@ -52,9 +52,9 @@ static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
52 | return vfat_revalidate_shortname(dentry); | 52 | return vfat_revalidate_shortname(dentry); |
53 | } | 53 | } |
54 | 54 | ||
55 | static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd) | 55 | static int vfat_revalidate_ci(struct dentry *dentry, unsigned int flags) |
56 | { | 56 | { |
57 | if (nd && nd->flags & LOOKUP_RCU) | 57 | if (flags & LOOKUP_RCU) |
58 | return -ECHILD; | 58 | return -ECHILD; |
59 | 59 | ||
60 | /* | 60 | /* |
@@ -74,7 +74,7 @@ static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd) | |||
74 | * This may be nfsd (or something), anyway, we can't see the | 74 | * This may be nfsd (or something), anyway, we can't see the |
75 | * intent of this. So, since this can be for creation, drop it. | 75 | * intent of this. So, since this can be for creation, drop it. |
76 | */ | 76 | */ |
77 | if (!nd) | 77 | if (!flags) |
78 | return 0; | 78 | return 0; |
79 | 79 | ||
80 | /* | 80 | /* |
@@ -82,7 +82,7 @@ static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd) | |||
82 | * case sensitive name which is specified by user if this is | 82 | * case sensitive name which is specified by user if this is |
83 | * for creation. | 83 | * for creation. |
84 | */ | 84 | */ |
85 | if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) | 85 | if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) |
86 | return 0; | 86 | return 0; |
87 | 87 | ||
88 | return vfat_revalidate_shortname(dentry); | 88 | return vfat_revalidate_shortname(dentry); |
@@ -714,7 +714,7 @@ static int vfat_d_anon_disconn(struct dentry *dentry) | |||
714 | } | 714 | } |
715 | 715 | ||
716 | static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry, | 716 | static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry, |
717 | struct nameidata *nd) | 717 | unsigned int flags) |
718 | { | 718 | { |
719 | struct super_block *sb = dir->i_sb; | 719 | struct super_block *sb = dir->i_sb; |
720 | struct fat_slot_info sinfo; | 720 | struct fat_slot_info sinfo; |
@@ -772,7 +772,7 @@ error: | |||
772 | } | 772 | } |
773 | 773 | ||
774 | static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 774 | static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
775 | struct nameidata *nd) | 775 | bool excl) |
776 | { | 776 | { |
777 | struct super_block *sb = dir->i_sb; | 777 | struct super_block *sb = dir->i_sb; |
778 | struct inode *inode; | 778 | struct inode *inode; |
diff --git a/fs/file_table.c b/fs/file_table.c index a305d9e2d1b2..b3fc4d67a26b 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/lglock.h> | 23 | #include <linux/lglock.h> |
24 | #include <linux/percpu_counter.h> | 24 | #include <linux/percpu_counter.h> |
25 | #include <linux/percpu.h> | 25 | #include <linux/percpu.h> |
26 | #include <linux/hardirq.h> | ||
27 | #include <linux/task_work.h> | ||
26 | #include <linux/ima.h> | 28 | #include <linux/ima.h> |
27 | 29 | ||
28 | #include <linux/atomic.h> | 30 | #include <linux/atomic.h> |
@@ -251,7 +253,6 @@ static void __fput(struct file *file) | |||
251 | } | 253 | } |
252 | fops_put(file->f_op); | 254 | fops_put(file->f_op); |
253 | put_pid(file->f_owner.pid); | 255 | put_pid(file->f_owner.pid); |
254 | file_sb_list_del(file); | ||
255 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | 256 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) |
256 | i_readcount_dec(inode); | 257 | i_readcount_dec(inode); |
257 | if (file->f_mode & FMODE_WRITE) | 258 | if (file->f_mode & FMODE_WRITE) |
@@ -263,10 +264,77 @@ static void __fput(struct file *file) | |||
263 | mntput(mnt); | 264 | mntput(mnt); |
264 | } | 265 | } |
265 | 266 | ||
267 | static DEFINE_SPINLOCK(delayed_fput_lock); | ||
268 | static LIST_HEAD(delayed_fput_list); | ||
269 | static void delayed_fput(struct work_struct *unused) | ||
270 | { | ||
271 | LIST_HEAD(head); | ||
272 | spin_lock_irq(&delayed_fput_lock); | ||
273 | list_splice_init(&delayed_fput_list, &head); | ||
274 | spin_unlock_irq(&delayed_fput_lock); | ||
275 | while (!list_empty(&head)) { | ||
276 | struct file *f = list_first_entry(&head, struct file, f_u.fu_list); | ||
277 | list_del_init(&f->f_u.fu_list); | ||
278 | __fput(f); | ||
279 | } | ||
280 | } | ||
281 | |||
282 | static void ____fput(struct callback_head *work) | ||
283 | { | ||
284 | __fput(container_of(work, struct file, f_u.fu_rcuhead)); | ||
285 | } | ||
286 | |||
287 | /* | ||
288 | * If kernel thread really needs to have the final fput() it has done | ||
289 | * to complete, call this. The only user right now is the boot - we | ||
290 | * *do* need to make sure our writes to binaries on initramfs has | ||
291 | * not left us with opened struct file waiting for __fput() - execve() | ||
292 | * won't work without that. Please, don't add more callers without | ||
293 | * very good reasons; in particular, never call that with locks | ||
294 | * held and never call that from a thread that might need to do | ||
295 | * some work on any kind of umount. | ||
296 | */ | ||
297 | void flush_delayed_fput(void) | ||
298 | { | ||
299 | delayed_fput(NULL); | ||
300 | } | ||
301 | |||
302 | static DECLARE_WORK(delayed_fput_work, delayed_fput); | ||
303 | |||
266 | void fput(struct file *file) | 304 | void fput(struct file *file) |
267 | { | 305 | { |
268 | if (atomic_long_dec_and_test(&file->f_count)) | 306 | if (atomic_long_dec_and_test(&file->f_count)) { |
307 | struct task_struct *task = current; | ||
308 | file_sb_list_del(file); | ||
309 | if (unlikely(in_interrupt() || task->flags & PF_KTHREAD)) { | ||
310 | unsigned long flags; | ||
311 | spin_lock_irqsave(&delayed_fput_lock, flags); | ||
312 | list_add(&file->f_u.fu_list, &delayed_fput_list); | ||
313 | schedule_work(&delayed_fput_work); | ||
314 | spin_unlock_irqrestore(&delayed_fput_lock, flags); | ||
315 | return; | ||
316 | } | ||
317 | init_task_work(&file->f_u.fu_rcuhead, ____fput); | ||
318 | task_work_add(task, &file->f_u.fu_rcuhead, true); | ||
319 | } | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * synchronous analog of fput(); for kernel threads that might be needed | ||
324 | * in some umount() (and thus can't use flush_delayed_fput() without | ||
325 | * risking deadlocks), need to wait for completion of __fput() and know | ||
326 | * for this specific struct file it won't involve anything that would | ||
327 | * need them. Use only if you really need it - at the very least, | ||
328 | * don't blindly convert fput() by kernel thread to that. | ||
329 | */ | ||
330 | void __fput_sync(struct file *file) | ||
331 | { | ||
332 | if (atomic_long_dec_and_test(&file->f_count)) { | ||
333 | struct task_struct *task = current; | ||
334 | file_sb_list_del(file); | ||
335 | BUG_ON(!(task->flags & PF_KTHREAD)); | ||
269 | __fput(file); | 336 | __fput(file); |
337 | } | ||
270 | } | 338 | } |
271 | 339 | ||
272 | EXPORT_SYMBOL(fput); | 340 | EXPORT_SYMBOL(fput); |
@@ -483,10 +551,8 @@ void mark_files_ro(struct super_block *sb) | |||
483 | { | 551 | { |
484 | struct file *f; | 552 | struct file *f; |
485 | 553 | ||
486 | retry: | ||
487 | lg_global_lock(&files_lglock); | 554 | lg_global_lock(&files_lglock); |
488 | do_file_list_for_each_entry(sb, f) { | 555 | do_file_list_for_each_entry(sb, f) { |
489 | struct vfsmount *mnt; | ||
490 | if (!S_ISREG(f->f_path.dentry->d_inode->i_mode)) | 556 | if (!S_ISREG(f->f_path.dentry->d_inode->i_mode)) |
491 | continue; | 557 | continue; |
492 | if (!file_count(f)) | 558 | if (!file_count(f)) |
@@ -499,12 +565,7 @@ retry: | |||
499 | if (file_check_writeable(f) != 0) | 565 | if (file_check_writeable(f) != 0) |
500 | continue; | 566 | continue; |
501 | file_release_write(f); | 567 | file_release_write(f); |
502 | mnt = mntget(f->f_path.mnt); | 568 | mnt_drop_write_file(f); |
503 | /* This can sleep, so we can't hold the spinlock. */ | ||
504 | lg_global_unlock(&files_lglock); | ||
505 | mnt_drop_write(mnt); | ||
506 | mntput(mnt); | ||
507 | goto retry; | ||
508 | } while_file_list_for_each_entry; | 569 | } while_file_list_for_each_entry; |
509 | lg_global_unlock(&files_lglock); | 570 | lg_global_unlock(&files_lglock); |
510 | } | 571 | } |
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c index 3360f1e678ad..bd447e88f208 100644 --- a/fs/freevxfs/vxfs_lookup.c +++ b/fs/freevxfs/vxfs_lookup.c | |||
@@ -48,7 +48,7 @@ | |||
48 | #define VXFS_BLOCK_PER_PAGE(sbp) ((PAGE_CACHE_SIZE / (sbp)->s_blocksize)) | 48 | #define VXFS_BLOCK_PER_PAGE(sbp) ((PAGE_CACHE_SIZE / (sbp)->s_blocksize)) |
49 | 49 | ||
50 | 50 | ||
51 | static struct dentry * vxfs_lookup(struct inode *, struct dentry *, struct nameidata *); | 51 | static struct dentry * vxfs_lookup(struct inode *, struct dentry *, unsigned int); |
52 | static int vxfs_readdir(struct file *, void *, filldir_t); | 52 | static int vxfs_readdir(struct file *, void *, filldir_t); |
53 | 53 | ||
54 | const struct inode_operations vxfs_dir_inode_ops = { | 54 | const struct inode_operations vxfs_dir_inode_ops = { |
@@ -203,7 +203,7 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp) | |||
203 | * in the return pointer. | 203 | * in the return pointer. |
204 | */ | 204 | */ |
205 | static struct dentry * | 205 | static struct dentry * |
206 | vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd) | 206 | vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags) |
207 | { | 207 | { |
208 | struct inode *ip = NULL; | 208 | struct inode *ip = NULL; |
209 | ino_t ino; | 209 | ino_t ino; |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 41a3ccff18d8..8f660dd6137a 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -1315,6 +1315,8 @@ void writeback_inodes_sb_nr(struct super_block *sb, | |||
1315 | .reason = reason, | 1315 | .reason = reason, |
1316 | }; | 1316 | }; |
1317 | 1317 | ||
1318 | if (sb->s_bdi == &noop_backing_dev_info) | ||
1319 | return; | ||
1318 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); | 1320 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); |
1319 | bdi_queue_work(sb->s_bdi, &work); | 1321 | bdi_queue_work(sb->s_bdi, &work); |
1320 | wait_for_completion(&done); | 1322 | wait_for_completion(&done); |
@@ -1398,6 +1400,9 @@ void sync_inodes_sb(struct super_block *sb) | |||
1398 | .reason = WB_REASON_SYNC, | 1400 | .reason = WB_REASON_SYNC, |
1399 | }; | 1401 | }; |
1400 | 1402 | ||
1403 | /* Nothing to do? */ | ||
1404 | if (sb->s_bdi == &noop_backing_dev_info) | ||
1405 | return; | ||
1401 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); | 1406 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); |
1402 | 1407 | ||
1403 | bdi_queue_work(sb->s_bdi, &work); | 1408 | bdi_queue_work(sb->s_bdi, &work); |
diff --git a/fs/fs_struct.c b/fs/fs_struct.c index e159e682ad4c..5df4775fea03 100644 --- a/fs/fs_struct.c +++ b/fs/fs_struct.c | |||
@@ -6,18 +6,6 @@ | |||
6 | #include <linux/fs_struct.h> | 6 | #include <linux/fs_struct.h> |
7 | #include "internal.h" | 7 | #include "internal.h" |
8 | 8 | ||
9 | static inline void path_get_longterm(struct path *path) | ||
10 | { | ||
11 | path_get(path); | ||
12 | mnt_make_longterm(path->mnt); | ||
13 | } | ||
14 | |||
15 | static inline void path_put_longterm(struct path *path) | ||
16 | { | ||
17 | mnt_make_shortterm(path->mnt); | ||
18 | path_put(path); | ||
19 | } | ||
20 | |||
21 | /* | 9 | /* |
22 | * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values. | 10 | * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values. |
23 | * It can block. | 11 | * It can block. |
@@ -26,7 +14,7 @@ void set_fs_root(struct fs_struct *fs, struct path *path) | |||
26 | { | 14 | { |
27 | struct path old_root; | 15 | struct path old_root; |
28 | 16 | ||
29 | path_get_longterm(path); | 17 | path_get(path); |
30 | spin_lock(&fs->lock); | 18 | spin_lock(&fs->lock); |
31 | write_seqcount_begin(&fs->seq); | 19 | write_seqcount_begin(&fs->seq); |
32 | old_root = fs->root; | 20 | old_root = fs->root; |
@@ -34,7 +22,7 @@ void set_fs_root(struct fs_struct *fs, struct path *path) | |||
34 | write_seqcount_end(&fs->seq); | 22 | write_seqcount_end(&fs->seq); |
35 | spin_unlock(&fs->lock); | 23 | spin_unlock(&fs->lock); |
36 | if (old_root.dentry) | 24 | if (old_root.dentry) |
37 | path_put_longterm(&old_root); | 25 | path_put(&old_root); |
38 | } | 26 | } |
39 | 27 | ||
40 | /* | 28 | /* |
@@ -45,7 +33,7 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path) | |||
45 | { | 33 | { |
46 | struct path old_pwd; | 34 | struct path old_pwd; |
47 | 35 | ||
48 | path_get_longterm(path); | 36 | path_get(path); |
49 | spin_lock(&fs->lock); | 37 | spin_lock(&fs->lock); |
50 | write_seqcount_begin(&fs->seq); | 38 | write_seqcount_begin(&fs->seq); |
51 | old_pwd = fs->pwd; | 39 | old_pwd = fs->pwd; |
@@ -54,7 +42,7 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path) | |||
54 | spin_unlock(&fs->lock); | 42 | spin_unlock(&fs->lock); |
55 | 43 | ||
56 | if (old_pwd.dentry) | 44 | if (old_pwd.dentry) |
57 | path_put_longterm(&old_pwd); | 45 | path_put(&old_pwd); |
58 | } | 46 | } |
59 | 47 | ||
60 | static inline int replace_path(struct path *p, const struct path *old, const struct path *new) | 48 | static inline int replace_path(struct path *p, const struct path *old, const struct path *new) |
@@ -84,7 +72,7 @@ void chroot_fs_refs(struct path *old_root, struct path *new_root) | |||
84 | write_seqcount_end(&fs->seq); | 72 | write_seqcount_end(&fs->seq); |
85 | while (hits--) { | 73 | while (hits--) { |
86 | count++; | 74 | count++; |
87 | path_get_longterm(new_root); | 75 | path_get(new_root); |
88 | } | 76 | } |
89 | spin_unlock(&fs->lock); | 77 | spin_unlock(&fs->lock); |
90 | } | 78 | } |
@@ -92,13 +80,13 @@ void chroot_fs_refs(struct path *old_root, struct path *new_root) | |||
92 | } while_each_thread(g, p); | 80 | } while_each_thread(g, p); |
93 | read_unlock(&tasklist_lock); | 81 | read_unlock(&tasklist_lock); |
94 | while (count--) | 82 | while (count--) |
95 | path_put_longterm(old_root); | 83 | path_put(old_root); |
96 | } | 84 | } |
97 | 85 | ||
98 | void free_fs_struct(struct fs_struct *fs) | 86 | void free_fs_struct(struct fs_struct *fs) |
99 | { | 87 | { |
100 | path_put_longterm(&fs->root); | 88 | path_put(&fs->root); |
101 | path_put_longterm(&fs->pwd); | 89 | path_put(&fs->pwd); |
102 | kmem_cache_free(fs_cachep, fs); | 90 | kmem_cache_free(fs_cachep, fs); |
103 | } | 91 | } |
104 | 92 | ||
@@ -132,9 +120,9 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) | |||
132 | 120 | ||
133 | spin_lock(&old->lock); | 121 | spin_lock(&old->lock); |
134 | fs->root = old->root; | 122 | fs->root = old->root; |
135 | path_get_longterm(&fs->root); | 123 | path_get(&fs->root); |
136 | fs->pwd = old->pwd; | 124 | fs->pwd = old->pwd; |
137 | path_get_longterm(&fs->pwd); | 125 | path_get(&fs->pwd); |
138 | spin_unlock(&old->lock); | 126 | spin_unlock(&old->lock); |
139 | } | 127 | } |
140 | return fs; | 128 | return fs; |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 334e0b18a014..8964cf3999b2 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -154,7 +154,7 @@ u64 fuse_get_attr_version(struct fuse_conn *fc) | |||
154 | * the lookup once more. If the lookup results in the same inode, | 154 | * the lookup once more. If the lookup results in the same inode, |
155 | * then refresh the attributes, timeouts and mark the dentry valid. | 155 | * then refresh the attributes, timeouts and mark the dentry valid. |
156 | */ | 156 | */ |
157 | static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) | 157 | static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) |
158 | { | 158 | { |
159 | struct inode *inode; | 159 | struct inode *inode; |
160 | 160 | ||
@@ -174,7 +174,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) | |||
174 | if (!inode) | 174 | if (!inode) |
175 | return 0; | 175 | return 0; |
176 | 176 | ||
177 | if (nd && (nd->flags & LOOKUP_RCU)) | 177 | if (flags & LOOKUP_RCU) |
178 | return -ECHILD; | 178 | return -ECHILD; |
179 | 179 | ||
180 | fc = get_fuse_conn(inode); | 180 | fc = get_fuse_conn(inode); |
@@ -249,7 +249,7 @@ static struct dentry *fuse_d_add_directory(struct dentry *entry, | |||
249 | /* This tries to shrink the subtree below alias */ | 249 | /* This tries to shrink the subtree below alias */ |
250 | fuse_invalidate_entry(alias); | 250 | fuse_invalidate_entry(alias); |
251 | dput(alias); | 251 | dput(alias); |
252 | if (!list_empty(&inode->i_dentry)) | 252 | if (!hlist_empty(&inode->i_dentry)) |
253 | return ERR_PTR(-EBUSY); | 253 | return ERR_PTR(-EBUSY); |
254 | } else { | 254 | } else { |
255 | dput(alias); | 255 | dput(alias); |
@@ -316,7 +316,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, | |||
316 | } | 316 | } |
317 | 317 | ||
318 | static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | 318 | static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, |
319 | struct nameidata *nd) | 319 | unsigned int flags) |
320 | { | 320 | { |
321 | int err; | 321 | int err; |
322 | struct fuse_entry_out outarg; | 322 | struct fuse_entry_out outarg; |
@@ -370,7 +370,8 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | |||
370 | * 'mknod' + 'open' requests. | 370 | * 'mknod' + 'open' requests. |
371 | */ | 371 | */ |
372 | static int fuse_create_open(struct inode *dir, struct dentry *entry, | 372 | static int fuse_create_open(struct inode *dir, struct dentry *entry, |
373 | umode_t mode, struct nameidata *nd) | 373 | struct file *file, unsigned flags, |
374 | umode_t mode, int *opened) | ||
374 | { | 375 | { |
375 | int err; | 376 | int err; |
376 | struct inode *inode; | 377 | struct inode *inode; |
@@ -381,15 +382,11 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, | |||
381 | struct fuse_open_out outopen; | 382 | struct fuse_open_out outopen; |
382 | struct fuse_entry_out outentry; | 383 | struct fuse_entry_out outentry; |
383 | struct fuse_file *ff; | 384 | struct fuse_file *ff; |
384 | struct file *file; | ||
385 | int flags = nd->intent.open.flags; | ||
386 | |||
387 | if (fc->no_create) | ||
388 | return -ENOSYS; | ||
389 | 385 | ||
390 | forget = fuse_alloc_forget(); | 386 | forget = fuse_alloc_forget(); |
387 | err = -ENOMEM; | ||
391 | if (!forget) | 388 | if (!forget) |
392 | return -ENOMEM; | 389 | goto out_err; |
393 | 390 | ||
394 | req = fuse_get_req(fc); | 391 | req = fuse_get_req(fc); |
395 | err = PTR_ERR(req); | 392 | err = PTR_ERR(req); |
@@ -428,11 +425,8 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, | |||
428 | req->out.args[1].value = &outopen; | 425 | req->out.args[1].value = &outopen; |
429 | fuse_request_send(fc, req); | 426 | fuse_request_send(fc, req); |
430 | err = req->out.h.error; | 427 | err = req->out.h.error; |
431 | if (err) { | 428 | if (err) |
432 | if (err == -ENOSYS) | ||
433 | fc->no_create = 1; | ||
434 | goto out_free_ff; | 429 | goto out_free_ff; |
435 | } | ||
436 | 430 | ||
437 | err = -EIO; | 431 | err = -EIO; |
438 | if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) | 432 | if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) |
@@ -448,28 +442,74 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, | |||
448 | flags &= ~(O_CREAT | O_EXCL | O_TRUNC); | 442 | flags &= ~(O_CREAT | O_EXCL | O_TRUNC); |
449 | fuse_sync_release(ff, flags); | 443 | fuse_sync_release(ff, flags); |
450 | fuse_queue_forget(fc, forget, outentry.nodeid, 1); | 444 | fuse_queue_forget(fc, forget, outentry.nodeid, 1); |
451 | return -ENOMEM; | 445 | err = -ENOMEM; |
446 | goto out_err; | ||
452 | } | 447 | } |
453 | kfree(forget); | 448 | kfree(forget); |
454 | d_instantiate(entry, inode); | 449 | d_instantiate(entry, inode); |
455 | fuse_change_entry_timeout(entry, &outentry); | 450 | fuse_change_entry_timeout(entry, &outentry); |
456 | fuse_invalidate_attr(dir); | 451 | fuse_invalidate_attr(dir); |
457 | file = lookup_instantiate_filp(nd, entry, generic_file_open); | 452 | err = finish_open(file, entry, generic_file_open, opened); |
458 | if (IS_ERR(file)) { | 453 | if (err) { |
459 | fuse_sync_release(ff, flags); | 454 | fuse_sync_release(ff, flags); |
460 | return PTR_ERR(file); | 455 | } else { |
456 | file->private_data = fuse_file_get(ff); | ||
457 | fuse_finish_open(inode, file); | ||
461 | } | 458 | } |
462 | file->private_data = fuse_file_get(ff); | 459 | return err; |
463 | fuse_finish_open(inode, file); | ||
464 | return 0; | ||
465 | 460 | ||
466 | out_free_ff: | 461 | out_free_ff: |
467 | fuse_file_free(ff); | 462 | fuse_file_free(ff); |
468 | out_put_request: | 463 | out_put_request: |
469 | fuse_put_request(fc, req); | 464 | fuse_put_request(fc, req); |
470 | out_put_forget_req: | 465 | out_put_forget_req: |
471 | kfree(forget); | 466 | kfree(forget); |
467 | out_err: | ||
468 | return err; | ||
469 | } | ||
470 | |||
471 | static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t); | ||
472 | static int fuse_atomic_open(struct inode *dir, struct dentry *entry, | ||
473 | struct file *file, unsigned flags, | ||
474 | umode_t mode, int *opened) | ||
475 | { | ||
476 | int err; | ||
477 | struct fuse_conn *fc = get_fuse_conn(dir); | ||
478 | struct dentry *res = NULL; | ||
479 | |||
480 | if (d_unhashed(entry)) { | ||
481 | res = fuse_lookup(dir, entry, 0); | ||
482 | if (IS_ERR(res)) | ||
483 | return PTR_ERR(res); | ||
484 | |||
485 | if (res) | ||
486 | entry = res; | ||
487 | } | ||
488 | |||
489 | if (!(flags & O_CREAT) || entry->d_inode) | ||
490 | goto no_open; | ||
491 | |||
492 | /* Only creates */ | ||
493 | *opened |= FILE_CREATED; | ||
494 | |||
495 | if (fc->no_create) | ||
496 | goto mknod; | ||
497 | |||
498 | err = fuse_create_open(dir, entry, file, flags, mode, opened); | ||
499 | if (err == -ENOSYS) { | ||
500 | fc->no_create = 1; | ||
501 | goto mknod; | ||
502 | } | ||
503 | out_dput: | ||
504 | dput(res); | ||
472 | return err; | 505 | return err; |
506 | |||
507 | mknod: | ||
508 | err = fuse_mknod(dir, entry, mode, 0); | ||
509 | if (err) | ||
510 | goto out_dput; | ||
511 | no_open: | ||
512 | return finish_no_open(file, res); | ||
473 | } | 513 | } |
474 | 514 | ||
475 | /* | 515 | /* |
@@ -571,14 +611,8 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode, | |||
571 | } | 611 | } |
572 | 612 | ||
573 | static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode, | 613 | static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode, |
574 | struct nameidata *nd) | 614 | bool excl) |
575 | { | 615 | { |
576 | if (nd) { | ||
577 | int err = fuse_create_open(dir, entry, mode, nd); | ||
578 | if (err != -ENOSYS) | ||
579 | return err; | ||
580 | /* Fall back on mknod */ | ||
581 | } | ||
582 | return fuse_mknod(dir, entry, mode, 0); | 616 | return fuse_mknod(dir, entry, mode, 0); |
583 | } | 617 | } |
584 | 618 | ||
@@ -1646,6 +1680,7 @@ static const struct inode_operations fuse_dir_inode_operations = { | |||
1646 | .link = fuse_link, | 1680 | .link = fuse_link, |
1647 | .setattr = fuse_setattr, | 1681 | .setattr = fuse_setattr, |
1648 | .create = fuse_create, | 1682 | .create = fuse_create, |
1683 | .atomic_open = fuse_atomic_open, | ||
1649 | .mknod = fuse_mknod, | 1684 | .mknod = fuse_mknod, |
1650 | .permission = fuse_permission, | 1685 | .permission = fuse_permission, |
1651 | .getattr = fuse_getattr, | 1686 | .getattr = fuse_getattr, |
diff --git a/fs/gfs2/dentry.c b/fs/gfs2/dentry.c index 0da8da2c991d..4fddb3c22d25 100644 --- a/fs/gfs2/dentry.c +++ b/fs/gfs2/dentry.c | |||
@@ -25,7 +25,7 @@ | |||
25 | /** | 25 | /** |
26 | * gfs2_drevalidate - Check directory lookup consistency | 26 | * gfs2_drevalidate - Check directory lookup consistency |
27 | * @dentry: the mapping to check | 27 | * @dentry: the mapping to check |
28 | * @nd: | 28 | * @flags: lookup flags |
29 | * | 29 | * |
30 | * Check to make sure the lookup necessary to arrive at this inode from its | 30 | * Check to make sure the lookup necessary to arrive at this inode from its |
31 | * parent is still good. | 31 | * parent is still good. |
@@ -33,7 +33,7 @@ | |||
33 | * Returns: 1 if the dentry is ok, 0 if it isn't | 33 | * Returns: 1 if the dentry is ok, 0 if it isn't |
34 | */ | 34 | */ |
35 | 35 | ||
36 | static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) | 36 | static int gfs2_drevalidate(struct dentry *dentry, unsigned int flags) |
37 | { | 37 | { |
38 | struct dentry *parent; | 38 | struct dentry *parent; |
39 | struct gfs2_sbd *sdp; | 39 | struct gfs2_sbd *sdp; |
@@ -44,7 +44,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd) | |||
44 | int error; | 44 | int error; |
45 | int had_lock = 0; | 45 | int had_lock = 0; |
46 | 46 | ||
47 | if (nd && nd->flags & LOOKUP_RCU) | 47 | if (flags & LOOKUP_RCU) |
48 | return -ECHILD; | 48 | return -ECHILD; |
49 | 49 | ||
50 | parent = dget_parent(dentry); | 50 | parent = dget_parent(dentry); |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index a9ba2444e077..867674785fcf 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -755,11 +755,8 @@ fail: | |||
755 | */ | 755 | */ |
756 | 756 | ||
757 | static int gfs2_create(struct inode *dir, struct dentry *dentry, | 757 | static int gfs2_create(struct inode *dir, struct dentry *dentry, |
758 | umode_t mode, struct nameidata *nd) | 758 | umode_t mode, bool excl) |
759 | { | 759 | { |
760 | int excl = 0; | ||
761 | if (nd && (nd->flags & LOOKUP_EXCL)) | ||
762 | excl = 1; | ||
763 | return gfs2_create_inode(dir, dentry, S_IFREG | mode, 0, NULL, 0, excl); | 760 | return gfs2_create_inode(dir, dentry, S_IFREG | mode, 0, NULL, 0, excl); |
764 | } | 761 | } |
765 | 762 | ||
@@ -775,7 +772,7 @@ static int gfs2_create(struct inode *dir, struct dentry *dentry, | |||
775 | */ | 772 | */ |
776 | 773 | ||
777 | static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry, | 774 | static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry, |
778 | struct nameidata *nd) | 775 | unsigned int flags) |
779 | { | 776 | { |
780 | struct inode *inode = gfs2_lookupi(dir, &dentry->d_name, 0); | 777 | struct inode *inode = gfs2_lookupi(dir, &dentry->d_name, 0); |
781 | if (inode && !IS_ERR(inode)) { | 778 | if (inode && !IS_ERR(inode)) { |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index b8c250fc4922..6c906078f657 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -1286,7 +1286,7 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags, | |||
1286 | error = -EBUSY; | 1286 | error = -EBUSY; |
1287 | goto error_bdev; | 1287 | goto error_bdev; |
1288 | } | 1288 | } |
1289 | s = sget(fs_type, test_gfs2_super, set_gfs2_super, bdev); | 1289 | s = sget(fs_type, test_gfs2_super, set_gfs2_super, flags, bdev); |
1290 | mutex_unlock(&bdev->bd_fsfreeze_mutex); | 1290 | mutex_unlock(&bdev->bd_fsfreeze_mutex); |
1291 | error = PTR_ERR(s); | 1291 | error = PTR_ERR(s); |
1292 | if (IS_ERR(s)) | 1292 | if (IS_ERR(s)) |
@@ -1316,7 +1316,6 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags, | |||
1316 | } else { | 1316 | } else { |
1317 | char b[BDEVNAME_SIZE]; | 1317 | char b[BDEVNAME_SIZE]; |
1318 | 1318 | ||
1319 | s->s_flags = flags; | ||
1320 | s->s_mode = mode; | 1319 | s->s_mode = mode; |
1321 | strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); | 1320 | strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); |
1322 | sb_set_blocksize(s, block_size(bdev)); | 1321 | sb_set_blocksize(s, block_size(bdev)); |
@@ -1360,7 +1359,7 @@ static struct dentry *gfs2_mount_meta(struct file_system_type *fs_type, | |||
1360 | dev_name, error); | 1359 | dev_name, error); |
1361 | return ERR_PTR(error); | 1360 | return ERR_PTR(error); |
1362 | } | 1361 | } |
1363 | s = sget(&gfs2_fs_type, test_gfs2_super, set_meta_super, | 1362 | s = sget(&gfs2_fs_type, test_gfs2_super, set_meta_super, flags, |
1364 | path.dentry->d_inode->i_sb->s_bdev); | 1363 | path.dentry->d_inode->i_sb->s_bdev); |
1365 | path_put(&path); | 1364 | path_put(&path); |
1366 | if (IS_ERR(s)) { | 1365 | if (IS_ERR(s)) { |
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index b97178e7d397..27b5cc7d6881 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
@@ -1108,7 +1108,7 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change, | |||
1108 | } | 1108 | } |
1109 | } | 1109 | } |
1110 | 1110 | ||
1111 | int gfs2_quota_sync(struct super_block *sb, int type, int wait) | 1111 | int gfs2_quota_sync(struct super_block *sb, int type) |
1112 | { | 1112 | { |
1113 | struct gfs2_sbd *sdp = sb->s_fs_info; | 1113 | struct gfs2_sbd *sdp = sb->s_fs_info; |
1114 | struct gfs2_quota_data **qda; | 1114 | struct gfs2_quota_data **qda; |
@@ -1154,7 +1154,7 @@ int gfs2_quota_sync(struct super_block *sb, int type, int wait) | |||
1154 | 1154 | ||
1155 | static int gfs2_quota_sync_timeo(struct super_block *sb, int type) | 1155 | static int gfs2_quota_sync_timeo(struct super_block *sb, int type) |
1156 | { | 1156 | { |
1157 | return gfs2_quota_sync(sb, type, 0); | 1157 | return gfs2_quota_sync(sb, type); |
1158 | } | 1158 | } |
1159 | 1159 | ||
1160 | int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id) | 1160 | int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id) |
diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h index 90bf1c302a98..f25d98b87904 100644 --- a/fs/gfs2/quota.h +++ b/fs/gfs2/quota.h | |||
@@ -26,7 +26,7 @@ extern int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid); | |||
26 | extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change, | 26 | extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change, |
27 | u32 uid, u32 gid); | 27 | u32 uid, u32 gid); |
28 | 28 | ||
29 | extern int gfs2_quota_sync(struct super_block *sb, int type, int wait); | 29 | extern int gfs2_quota_sync(struct super_block *sb, int type); |
30 | extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id); | 30 | extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id); |
31 | 31 | ||
32 | extern int gfs2_quota_init(struct gfs2_sbd *sdp); | 32 | extern int gfs2_quota_init(struct gfs2_sbd *sdp); |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 713e621c240b..f3d6bbfb32c5 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -838,7 +838,7 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) | |||
838 | int error; | 838 | int error; |
839 | 839 | ||
840 | flush_workqueue(gfs2_delete_workqueue); | 840 | flush_workqueue(gfs2_delete_workqueue); |
841 | gfs2_quota_sync(sdp->sd_vfs, 0, 1); | 841 | gfs2_quota_sync(sdp->sd_vfs, 0); |
842 | gfs2_statfs_sync(sdp->sd_vfs, 0); | 842 | gfs2_statfs_sync(sdp->sd_vfs, 0); |
843 | 843 | ||
844 | error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE, | 844 | error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE, |
@@ -952,6 +952,8 @@ restart: | |||
952 | static int gfs2_sync_fs(struct super_block *sb, int wait) | 952 | static int gfs2_sync_fs(struct super_block *sb, int wait) |
953 | { | 953 | { |
954 | struct gfs2_sbd *sdp = sb->s_fs_info; | 954 | struct gfs2_sbd *sdp = sb->s_fs_info; |
955 | |||
956 | gfs2_quota_sync(sb, -1); | ||
955 | if (wait && sdp) | 957 | if (wait && sdp) |
956 | gfs2_log_flush(sdp, NULL); | 958 | gfs2_log_flush(sdp, NULL); |
957 | return 0; | 959 | return 0; |
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 9c2592b1d5ff..73ecc34c4342 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c | |||
@@ -168,7 +168,7 @@ static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf, | |||
168 | if (simple_strtol(buf, NULL, 0) != 1) | 168 | if (simple_strtol(buf, NULL, 0) != 1) |
169 | return -EINVAL; | 169 | return -EINVAL; |
170 | 170 | ||
171 | gfs2_quota_sync(sdp->sd_vfs, 0, 1); | 171 | gfs2_quota_sync(sdp->sd_vfs, 0); |
172 | return len; | 172 | return len; |
173 | } | 173 | } |
174 | 174 | ||
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c index 62fc14ea4b73..422dde2ec0a1 100644 --- a/fs/hfs/dir.c +++ b/fs/hfs/dir.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * hfs_lookup() | 18 | * hfs_lookup() |
19 | */ | 19 | */ |
20 | static struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry, | 20 | static struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry, |
21 | struct nameidata *nd) | 21 | unsigned int flags) |
22 | { | 22 | { |
23 | hfs_cat_rec rec; | 23 | hfs_cat_rec rec; |
24 | struct hfs_find_data fd; | 24 | struct hfs_find_data fd; |
@@ -187,7 +187,7 @@ static int hfs_dir_release(struct inode *inode, struct file *file) | |||
187 | * the directory and the name (and its length) of the new file. | 187 | * the directory and the name (and its length) of the new file. |
188 | */ | 188 | */ |
189 | static int hfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 189 | static int hfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
190 | struct nameidata *nd) | 190 | bool excl) |
191 | { | 191 | { |
192 | struct inode *inode; | 192 | struct inode *inode; |
193 | int res; | 193 | int res; |
diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c index 2c16316d2917..a67955a0c36f 100644 --- a/fs/hfs/extent.c +++ b/fs/hfs/extent.c | |||
@@ -432,7 +432,7 @@ out: | |||
432 | if (inode->i_ino < HFS_FIRSTUSER_CNID) | 432 | if (inode->i_ino < HFS_FIRSTUSER_CNID) |
433 | set_bit(HFS_FLG_ALT_MDB_DIRTY, &HFS_SB(sb)->flags); | 433 | set_bit(HFS_FLG_ALT_MDB_DIRTY, &HFS_SB(sb)->flags); |
434 | set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); | 434 | set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); |
435 | sb->s_dirt = 1; | 435 | hfs_mark_mdb_dirty(sb); |
436 | } | 436 | } |
437 | return res; | 437 | return res; |
438 | 438 | ||
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h index 1bf967c6bfdc..8275175acf6e 100644 --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/mutex.h> | 14 | #include <linux/mutex.h> |
15 | #include <linux/buffer_head.h> | 15 | #include <linux/buffer_head.h> |
16 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
17 | #include <linux/workqueue.h> | ||
17 | 18 | ||
18 | #include <asm/byteorder.h> | 19 | #include <asm/byteorder.h> |
19 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
@@ -137,16 +138,15 @@ struct hfs_sb_info { | |||
137 | gid_t s_gid; /* The gid of all files */ | 138 | gid_t s_gid; /* The gid of all files */ |
138 | 139 | ||
139 | int session, part; | 140 | int session, part; |
140 | |||
141 | struct nls_table *nls_io, *nls_disk; | 141 | struct nls_table *nls_io, *nls_disk; |
142 | |||
143 | struct mutex bitmap_lock; | 142 | struct mutex bitmap_lock; |
144 | |||
145 | unsigned long flags; | 143 | unsigned long flags; |
146 | |||
147 | u16 blockoffset; | 144 | u16 blockoffset; |
148 | |||
149 | int fs_div; | 145 | int fs_div; |
146 | struct super_block *sb; | ||
147 | int work_queued; /* non-zero delayed work is queued */ | ||
148 | struct delayed_work mdb_work; /* MDB flush delayed work */ | ||
149 | spinlock_t work_lock; /* protects mdb_work and work_queued */ | ||
150 | }; | 150 | }; |
151 | 151 | ||
152 | #define HFS_FLG_BITMAP_DIRTY 0 | 152 | #define HFS_FLG_BITMAP_DIRTY 0 |
@@ -226,6 +226,9 @@ extern int hfs_compare_dentry(const struct dentry *parent, | |||
226 | extern void hfs_asc2mac(struct super_block *, struct hfs_name *, struct qstr *); | 226 | extern void hfs_asc2mac(struct super_block *, struct hfs_name *, struct qstr *); |
227 | extern int hfs_mac2asc(struct super_block *, char *, const struct hfs_name *); | 227 | extern int hfs_mac2asc(struct super_block *, char *, const struct hfs_name *); |
228 | 228 | ||
229 | /* super.c */ | ||
230 | extern void hfs_mark_mdb_dirty(struct super_block *sb); | ||
231 | |||
229 | extern struct timezone sys_tz; | 232 | extern struct timezone sys_tz; |
230 | 233 | ||
231 | /* | 234 | /* |
@@ -253,7 +256,7 @@ static inline const char *hfs_mdb_name(struct super_block *sb) | |||
253 | static inline void hfs_bitmap_dirty(struct super_block *sb) | 256 | static inline void hfs_bitmap_dirty(struct super_block *sb) |
254 | { | 257 | { |
255 | set_bit(HFS_FLG_BITMAP_DIRTY, &HFS_SB(sb)->flags); | 258 | set_bit(HFS_FLG_BITMAP_DIRTY, &HFS_SB(sb)->flags); |
256 | sb->s_dirt = 1; | 259 | hfs_mark_mdb_dirty(sb); |
257 | } | 260 | } |
258 | 261 | ||
259 | #define sb_bread512(sb, sec, data) ({ \ | 262 | #define sb_bread512(sb, sec, data) ({ \ |
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 761ec06354b4..ee1bc55677f1 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c | |||
@@ -220,7 +220,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, umode_t mode) | |||
220 | insert_inode_hash(inode); | 220 | insert_inode_hash(inode); |
221 | mark_inode_dirty(inode); | 221 | mark_inode_dirty(inode); |
222 | set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); | 222 | set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); |
223 | sb->s_dirt = 1; | 223 | hfs_mark_mdb_dirty(sb); |
224 | 224 | ||
225 | return inode; | 225 | return inode; |
226 | } | 226 | } |
@@ -235,7 +235,7 @@ void hfs_delete_inode(struct inode *inode) | |||
235 | if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID)) | 235 | if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID)) |
236 | HFS_SB(sb)->root_dirs--; | 236 | HFS_SB(sb)->root_dirs--; |
237 | set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); | 237 | set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); |
238 | sb->s_dirt = 1; | 238 | hfs_mark_mdb_dirty(sb); |
239 | return; | 239 | return; |
240 | } | 240 | } |
241 | HFS_SB(sb)->file_count--; | 241 | HFS_SB(sb)->file_count--; |
@@ -248,7 +248,7 @@ void hfs_delete_inode(struct inode *inode) | |||
248 | } | 248 | } |
249 | } | 249 | } |
250 | set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); | 250 | set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags); |
251 | sb->s_dirt = 1; | 251 | hfs_mark_mdb_dirty(sb); |
252 | } | 252 | } |
253 | 253 | ||
254 | void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext, | 254 | void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext, |
@@ -489,7 +489,7 @@ out: | |||
489 | } | 489 | } |
490 | 490 | ||
491 | static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry, | 491 | static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry, |
492 | struct nameidata *nd) | 492 | unsigned int flags) |
493 | { | 493 | { |
494 | struct inode *inode = NULL; | 494 | struct inode *inode = NULL; |
495 | hfs_cat_rec rec; | 495 | hfs_cat_rec rec; |
@@ -644,13 +644,7 @@ static int hfs_file_fsync(struct file *filp, loff_t start, loff_t end, | |||
644 | 644 | ||
645 | /* sync the superblock to buffers */ | 645 | /* sync the superblock to buffers */ |
646 | sb = inode->i_sb; | 646 | sb = inode->i_sb; |
647 | if (sb->s_dirt) { | 647 | flush_delayed_work_sync(&HFS_SB(sb)->mdb_work); |
648 | lock_super(sb); | ||
649 | sb->s_dirt = 0; | ||
650 | if (!(sb->s_flags & MS_RDONLY)) | ||
651 | hfs_mdb_commit(sb); | ||
652 | unlock_super(sb); | ||
653 | } | ||
654 | /* .. finally sync the buffers to disk */ | 648 | /* .. finally sync the buffers to disk */ |
655 | err = sync_blockdev(sb->s_bdev); | 649 | err = sync_blockdev(sb->s_bdev); |
656 | if (!ret) | 650 | if (!ret) |
diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c index 1563d5ce5764..5fd51a5833ff 100644 --- a/fs/hfs/mdb.c +++ b/fs/hfs/mdb.c | |||
@@ -260,6 +260,10 @@ void hfs_mdb_commit(struct super_block *sb) | |||
260 | { | 260 | { |
261 | struct hfs_mdb *mdb = HFS_SB(sb)->mdb; | 261 | struct hfs_mdb *mdb = HFS_SB(sb)->mdb; |
262 | 262 | ||
263 | if (sb->s_flags & MS_RDONLY) | ||
264 | return; | ||
265 | |||
266 | lock_buffer(HFS_SB(sb)->mdb_bh); | ||
263 | if (test_and_clear_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags)) { | 267 | if (test_and_clear_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags)) { |
264 | /* These parameters may have been modified, so write them back */ | 268 | /* These parameters may have been modified, so write them back */ |
265 | mdb->drLsMod = hfs_mtime(); | 269 | mdb->drLsMod = hfs_mtime(); |
@@ -283,9 +287,13 @@ void hfs_mdb_commit(struct super_block *sb) | |||
283 | &mdb->drXTFlSize, NULL); | 287 | &mdb->drXTFlSize, NULL); |
284 | hfs_inode_write_fork(HFS_SB(sb)->cat_tree->inode, mdb->drCTExtRec, | 288 | hfs_inode_write_fork(HFS_SB(sb)->cat_tree->inode, mdb->drCTExtRec, |
285 | &mdb->drCTFlSize, NULL); | 289 | &mdb->drCTFlSize, NULL); |
290 | |||
291 | lock_buffer(HFS_SB(sb)->alt_mdb_bh); | ||
286 | memcpy(HFS_SB(sb)->alt_mdb, HFS_SB(sb)->mdb, HFS_SECTOR_SIZE); | 292 | memcpy(HFS_SB(sb)->alt_mdb, HFS_SB(sb)->mdb, HFS_SECTOR_SIZE); |
287 | HFS_SB(sb)->alt_mdb->drAtrb |= cpu_to_be16(HFS_SB_ATTRIB_UNMNT); | 293 | HFS_SB(sb)->alt_mdb->drAtrb |= cpu_to_be16(HFS_SB_ATTRIB_UNMNT); |
288 | HFS_SB(sb)->alt_mdb->drAtrb &= cpu_to_be16(~HFS_SB_ATTRIB_INCNSTNT); | 294 | HFS_SB(sb)->alt_mdb->drAtrb &= cpu_to_be16(~HFS_SB_ATTRIB_INCNSTNT); |
295 | unlock_buffer(HFS_SB(sb)->alt_mdb_bh); | ||
296 | |||
289 | mark_buffer_dirty(HFS_SB(sb)->alt_mdb_bh); | 297 | mark_buffer_dirty(HFS_SB(sb)->alt_mdb_bh); |
290 | sync_dirty_buffer(HFS_SB(sb)->alt_mdb_bh); | 298 | sync_dirty_buffer(HFS_SB(sb)->alt_mdb_bh); |
291 | } | 299 | } |
@@ -308,7 +316,11 @@ void hfs_mdb_commit(struct super_block *sb) | |||
308 | break; | 316 | break; |
309 | } | 317 | } |
310 | len = min((int)sb->s_blocksize - off, size); | 318 | len = min((int)sb->s_blocksize - off, size); |
319 | |||
320 | lock_buffer(bh); | ||
311 | memcpy(bh->b_data + off, ptr, len); | 321 | memcpy(bh->b_data + off, ptr, len); |
322 | unlock_buffer(bh); | ||
323 | |||
312 | mark_buffer_dirty(bh); | 324 | mark_buffer_dirty(bh); |
313 | brelse(bh); | 325 | brelse(bh); |
314 | block++; | 326 | block++; |
@@ -317,6 +329,7 @@ void hfs_mdb_commit(struct super_block *sb) | |||
317 | size -= len; | 329 | size -= len; |
318 | } | 330 | } |
319 | } | 331 | } |
332 | unlock_buffer(HFS_SB(sb)->mdb_bh); | ||
320 | } | 333 | } |
321 | 334 | ||
322 | void hfs_mdb_close(struct super_block *sb) | 335 | void hfs_mdb_close(struct super_block *sb) |
diff --git a/fs/hfs/super.c b/fs/hfs/super.c index 7b4c537d6e13..4eb873e0c07b 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c | |||
@@ -29,43 +29,9 @@ static struct kmem_cache *hfs_inode_cachep; | |||
29 | 29 | ||
30 | MODULE_LICENSE("GPL"); | 30 | MODULE_LICENSE("GPL"); |
31 | 31 | ||
32 | /* | ||
33 | * hfs_write_super() | ||
34 | * | ||
35 | * Description: | ||
36 | * This function is called by the VFS only. When the filesystem | ||
37 | * is mounted r/w it updates the MDB on disk. | ||
38 | * Input Variable(s): | ||
39 | * struct super_block *sb: Pointer to the hfs superblock | ||
40 | * Output Variable(s): | ||
41 | * NONE | ||
42 | * Returns: | ||
43 | * void | ||
44 | * Preconditions: | ||
45 | * 'sb' points to a "valid" (struct super_block). | ||
46 | * Postconditions: | ||
47 | * The MDB is marked 'unsuccessfully unmounted' by clearing bit 8 of drAtrb | ||
48 | * (hfs_put_super() must set this flag!). Some MDB fields are updated | ||
49 | * and the MDB buffer is written to disk by calling hfs_mdb_commit(). | ||
50 | */ | ||
51 | static void hfs_write_super(struct super_block *sb) | ||
52 | { | ||
53 | lock_super(sb); | ||
54 | sb->s_dirt = 0; | ||
55 | |||
56 | /* sync everything to the buffers */ | ||
57 | if (!(sb->s_flags & MS_RDONLY)) | ||
58 | hfs_mdb_commit(sb); | ||
59 | unlock_super(sb); | ||
60 | } | ||
61 | |||
62 | static int hfs_sync_fs(struct super_block *sb, int wait) | 32 | static int hfs_sync_fs(struct super_block *sb, int wait) |
63 | { | 33 | { |
64 | lock_super(sb); | ||
65 | hfs_mdb_commit(sb); | 34 | hfs_mdb_commit(sb); |
66 | sb->s_dirt = 0; | ||
67 | unlock_super(sb); | ||
68 | |||
69 | return 0; | 35 | return 0; |
70 | } | 36 | } |
71 | 37 | ||
@@ -78,13 +44,44 @@ static int hfs_sync_fs(struct super_block *sb, int wait) | |||
78 | */ | 44 | */ |
79 | static void hfs_put_super(struct super_block *sb) | 45 | static void hfs_put_super(struct super_block *sb) |
80 | { | 46 | { |
81 | if (sb->s_dirt) | 47 | cancel_delayed_work_sync(&HFS_SB(sb)->mdb_work); |
82 | hfs_write_super(sb); | ||
83 | hfs_mdb_close(sb); | 48 | hfs_mdb_close(sb); |
84 | /* release the MDB's resources */ | 49 | /* release the MDB's resources */ |
85 | hfs_mdb_put(sb); | 50 | hfs_mdb_put(sb); |
86 | } | 51 | } |
87 | 52 | ||
53 | static void flush_mdb(struct work_struct *work) | ||
54 | { | ||
55 | struct hfs_sb_info *sbi; | ||
56 | struct super_block *sb; | ||
57 | |||
58 | sbi = container_of(work, struct hfs_sb_info, mdb_work.work); | ||
59 | sb = sbi->sb; | ||
60 | |||
61 | spin_lock(&sbi->work_lock); | ||
62 | sbi->work_queued = 0; | ||
63 | spin_unlock(&sbi->work_lock); | ||
64 | |||
65 | hfs_mdb_commit(sb); | ||
66 | } | ||
67 | |||
68 | void hfs_mark_mdb_dirty(struct super_block *sb) | ||
69 | { | ||
70 | struct hfs_sb_info *sbi = HFS_SB(sb); | ||
71 | unsigned long delay; | ||
72 | |||
73 | if (sb->s_flags & MS_RDONLY) | ||
74 | return; | ||
75 | |||
76 | spin_lock(&sbi->work_lock); | ||
77 | if (!sbi->work_queued) { | ||
78 | delay = msecs_to_jiffies(dirty_writeback_interval * 10); | ||
79 | queue_delayed_work(system_long_wq, &sbi->mdb_work, delay); | ||
80 | sbi->work_queued = 1; | ||
81 | } | ||
82 | spin_unlock(&sbi->work_lock); | ||
83 | } | ||
84 | |||
88 | /* | 85 | /* |
89 | * hfs_statfs() | 86 | * hfs_statfs() |
90 | * | 87 | * |
@@ -184,7 +181,6 @@ static const struct super_operations hfs_super_operations = { | |||
184 | .write_inode = hfs_write_inode, | 181 | .write_inode = hfs_write_inode, |
185 | .evict_inode = hfs_evict_inode, | 182 | .evict_inode = hfs_evict_inode, |
186 | .put_super = hfs_put_super, | 183 | .put_super = hfs_put_super, |
187 | .write_super = hfs_write_super, | ||
188 | .sync_fs = hfs_sync_fs, | 184 | .sync_fs = hfs_sync_fs, |
189 | .statfs = hfs_statfs, | 185 | .statfs = hfs_statfs, |
190 | .remount_fs = hfs_remount, | 186 | .remount_fs = hfs_remount, |
@@ -387,7 +383,10 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent) | |||
387 | if (!sbi) | 383 | if (!sbi) |
388 | return -ENOMEM; | 384 | return -ENOMEM; |
389 | 385 | ||
386 | sbi->sb = sb; | ||
390 | sb->s_fs_info = sbi; | 387 | sb->s_fs_info = sbi; |
388 | spin_lock_init(&sbi->work_lock); | ||
389 | INIT_DELAYED_WORK(&sbi->mdb_work, flush_mdb); | ||
391 | 390 | ||
392 | res = -EINVAL; | 391 | res = -EINVAL; |
393 | if (!parse_options((char *)data, sbi)) { | 392 | if (!parse_options((char *)data, sbi)) { |
diff --git a/fs/hfs/sysdep.c b/fs/hfs/sysdep.c index 19cf291eb91f..91b91fd3a901 100644 --- a/fs/hfs/sysdep.c +++ b/fs/hfs/sysdep.c | |||
@@ -13,12 +13,12 @@ | |||
13 | 13 | ||
14 | /* dentry case-handling: just lowercase everything */ | 14 | /* dentry case-handling: just lowercase everything */ |
15 | 15 | ||
16 | static int hfs_revalidate_dentry(struct dentry *dentry, struct nameidata *nd) | 16 | static int hfs_revalidate_dentry(struct dentry *dentry, unsigned int flags) |
17 | { | 17 | { |
18 | struct inode *inode; | 18 | struct inode *inode; |
19 | int diff; | 19 | int diff; |
20 | 20 | ||
21 | if (nd->flags & LOOKUP_RCU) | 21 | if (flags & LOOKUP_RCU) |
22 | return -ECHILD; | 22 | return -ECHILD; |
23 | 23 | ||
24 | inode = dentry->d_inode; | 24 | inode = dentry->d_inode; |
diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c index 1cad80c789cb..4cfbe2edd296 100644 --- a/fs/hfsplus/bitmap.c +++ b/fs/hfsplus/bitmap.c | |||
@@ -153,7 +153,7 @@ done: | |||
153 | kunmap(page); | 153 | kunmap(page); |
154 | *max = offset + (curr - pptr) * 32 + i - start; | 154 | *max = offset + (curr - pptr) * 32 + i - start; |
155 | sbi->free_blocks -= *max; | 155 | sbi->free_blocks -= *max; |
156 | sb->s_dirt = 1; | 156 | hfsplus_mark_mdb_dirty(sb); |
157 | dprint(DBG_BITMAP, "-> %u,%u\n", start, *max); | 157 | dprint(DBG_BITMAP, "-> %u,%u\n", start, *max); |
158 | out: | 158 | out: |
159 | mutex_unlock(&sbi->alloc_mutex); | 159 | mutex_unlock(&sbi->alloc_mutex); |
@@ -228,7 +228,7 @@ out: | |||
228 | set_page_dirty(page); | 228 | set_page_dirty(page); |
229 | kunmap(page); | 229 | kunmap(page); |
230 | sbi->free_blocks += len; | 230 | sbi->free_blocks += len; |
231 | sb->s_dirt = 1; | 231 | hfsplus_mark_mdb_dirty(sb); |
232 | mutex_unlock(&sbi->alloc_mutex); | 232 | mutex_unlock(&sbi->alloc_mutex); |
233 | 233 | ||
234 | return 0; | 234 | return 0; |
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 26b53fb09f68..6b9f921ef2fa 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
@@ -25,7 +25,7 @@ static inline void hfsplus_instantiate(struct dentry *dentry, | |||
25 | 25 | ||
26 | /* Find the entry inside dir named dentry->d_name */ | 26 | /* Find the entry inside dir named dentry->d_name */ |
27 | static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry, | 27 | static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry, |
28 | struct nameidata *nd) | 28 | unsigned int flags) |
29 | { | 29 | { |
30 | struct inode *inode = NULL; | 30 | struct inode *inode = NULL; |
31 | struct hfs_find_data fd; | 31 | struct hfs_find_data fd; |
@@ -316,7 +316,7 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir, | |||
316 | inode->i_ctime = CURRENT_TIME_SEC; | 316 | inode->i_ctime = CURRENT_TIME_SEC; |
317 | mark_inode_dirty(inode); | 317 | mark_inode_dirty(inode); |
318 | sbi->file_count++; | 318 | sbi->file_count++; |
319 | dst_dir->i_sb->s_dirt = 1; | 319 | hfsplus_mark_mdb_dirty(dst_dir->i_sb); |
320 | out: | 320 | out: |
321 | mutex_unlock(&sbi->vh_mutex); | 321 | mutex_unlock(&sbi->vh_mutex); |
322 | return res; | 322 | return res; |
@@ -465,7 +465,7 @@ out: | |||
465 | } | 465 | } |
466 | 466 | ||
467 | static int hfsplus_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 467 | static int hfsplus_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
468 | struct nameidata *nd) | 468 | bool excl) |
469 | { | 469 | { |
470 | return hfsplus_mknod(dir, dentry, mode, 0); | 470 | return hfsplus_mknod(dir, dentry, mode, 0); |
471 | } | 471 | } |
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 4e75ac646fea..558dbb463a4e 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h | |||
@@ -153,8 +153,11 @@ struct hfsplus_sb_info { | |||
153 | gid_t gid; | 153 | gid_t gid; |
154 | 154 | ||
155 | int part, session; | 155 | int part, session; |
156 | |||
157 | unsigned long flags; | 156 | unsigned long flags; |
157 | |||
158 | int work_queued; /* non-zero delayed work is queued */ | ||
159 | struct delayed_work sync_work; /* FS sync delayed work */ | ||
160 | spinlock_t work_lock; /* protects sync_work and work_queued */ | ||
158 | }; | 161 | }; |
159 | 162 | ||
160 | #define HFSPLUS_SB_WRITEBACKUP 0 | 163 | #define HFSPLUS_SB_WRITEBACKUP 0 |
@@ -428,7 +431,7 @@ int hfsplus_show_options(struct seq_file *, struct dentry *); | |||
428 | 431 | ||
429 | /* super.c */ | 432 | /* super.c */ |
430 | struct inode *hfsplus_iget(struct super_block *, unsigned long); | 433 | struct inode *hfsplus_iget(struct super_block *, unsigned long); |
431 | int hfsplus_sync_fs(struct super_block *sb, int wait); | 434 | void hfsplus_mark_mdb_dirty(struct super_block *sb); |
432 | 435 | ||
433 | /* tables.c */ | 436 | /* tables.c */ |
434 | extern u16 hfsplus_case_fold_table[]; | 437 | extern u16 hfsplus_case_fold_table[]; |
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 82b69ee4dacc..3d8b4a675ba0 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
@@ -168,7 +168,7 @@ const struct dentry_operations hfsplus_dentry_operations = { | |||
168 | }; | 168 | }; |
169 | 169 | ||
170 | static struct dentry *hfsplus_file_lookup(struct inode *dir, | 170 | static struct dentry *hfsplus_file_lookup(struct inode *dir, |
171 | struct dentry *dentry, struct nameidata *nd) | 171 | struct dentry *dentry, unsigned int flags) |
172 | { | 172 | { |
173 | struct hfs_find_data fd; | 173 | struct hfs_find_data fd; |
174 | struct super_block *sb = dir->i_sb; | 174 | struct super_block *sb = dir->i_sb; |
@@ -431,7 +431,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, umode_t mode) | |||
431 | sbi->file_count++; | 431 | sbi->file_count++; |
432 | insert_inode_hash(inode); | 432 | insert_inode_hash(inode); |
433 | mark_inode_dirty(inode); | 433 | mark_inode_dirty(inode); |
434 | sb->s_dirt = 1; | 434 | hfsplus_mark_mdb_dirty(sb); |
435 | 435 | ||
436 | return inode; | 436 | return inode; |
437 | } | 437 | } |
@@ -442,7 +442,7 @@ void hfsplus_delete_inode(struct inode *inode) | |||
442 | 442 | ||
443 | if (S_ISDIR(inode->i_mode)) { | 443 | if (S_ISDIR(inode->i_mode)) { |
444 | HFSPLUS_SB(sb)->folder_count--; | 444 | HFSPLUS_SB(sb)->folder_count--; |
445 | sb->s_dirt = 1; | 445 | hfsplus_mark_mdb_dirty(sb); |
446 | return; | 446 | return; |
447 | } | 447 | } |
448 | HFSPLUS_SB(sb)->file_count--; | 448 | HFSPLUS_SB(sb)->file_count--; |
@@ -455,7 +455,7 @@ void hfsplus_delete_inode(struct inode *inode) | |||
455 | inode->i_size = 0; | 455 | inode->i_size = 0; |
456 | hfsplus_file_truncate(inode); | 456 | hfsplus_file_truncate(inode); |
457 | } | 457 | } |
458 | sb->s_dirt = 1; | 458 | hfsplus_mark_mdb_dirty(sb); |
459 | } | 459 | } |
460 | 460 | ||
461 | void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork) | 461 | void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork) |
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index a9bca4b8768b..473332098013 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
@@ -124,7 +124,7 @@ static int hfsplus_system_write_inode(struct inode *inode) | |||
124 | 124 | ||
125 | if (fork->total_size != cpu_to_be64(inode->i_size)) { | 125 | if (fork->total_size != cpu_to_be64(inode->i_size)) { |
126 | set_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags); | 126 | set_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags); |
127 | inode->i_sb->s_dirt = 1; | 127 | hfsplus_mark_mdb_dirty(inode->i_sb); |
128 | } | 128 | } |
129 | hfsplus_inode_write_fork(inode, fork); | 129 | hfsplus_inode_write_fork(inode, fork); |
130 | if (tree) | 130 | if (tree) |
@@ -161,7 +161,7 @@ static void hfsplus_evict_inode(struct inode *inode) | |||
161 | } | 161 | } |
162 | } | 162 | } |
163 | 163 | ||
164 | int hfsplus_sync_fs(struct super_block *sb, int wait) | 164 | static int hfsplus_sync_fs(struct super_block *sb, int wait) |
165 | { | 165 | { |
166 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | 166 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); |
167 | struct hfsplus_vh *vhdr = sbi->s_vhdr; | 167 | struct hfsplus_vh *vhdr = sbi->s_vhdr; |
@@ -171,9 +171,7 @@ int hfsplus_sync_fs(struct super_block *sb, int wait) | |||
171 | if (!wait) | 171 | if (!wait) |
172 | return 0; | 172 | return 0; |
173 | 173 | ||
174 | dprint(DBG_SUPER, "hfsplus_write_super\n"); | 174 | dprint(DBG_SUPER, "hfsplus_sync_fs\n"); |
175 | |||
176 | sb->s_dirt = 0; | ||
177 | 175 | ||
178 | /* | 176 | /* |
179 | * Explicitly write out the special metadata inodes. | 177 | * Explicitly write out the special metadata inodes. |
@@ -226,12 +224,34 @@ out: | |||
226 | return error; | 224 | return error; |
227 | } | 225 | } |
228 | 226 | ||
229 | static void hfsplus_write_super(struct super_block *sb) | 227 | static void delayed_sync_fs(struct work_struct *work) |
230 | { | 228 | { |
231 | if (!(sb->s_flags & MS_RDONLY)) | 229 | struct hfsplus_sb_info *sbi; |
232 | hfsplus_sync_fs(sb, 1); | 230 | |
233 | else | 231 | sbi = container_of(work, struct hfsplus_sb_info, sync_work.work); |
234 | sb->s_dirt = 0; | 232 | |
233 | spin_lock(&sbi->work_lock); | ||
234 | sbi->work_queued = 0; | ||
235 | spin_unlock(&sbi->work_lock); | ||
236 | |||
237 | hfsplus_sync_fs(sbi->alloc_file->i_sb, 1); | ||
238 | } | ||
239 | |||
240 | void hfsplus_mark_mdb_dirty(struct super_block *sb) | ||
241 | { | ||
242 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
243 | unsigned long delay; | ||
244 | |||
245 | if (sb->s_flags & MS_RDONLY) | ||
246 | return; | ||
247 | |||
248 | spin_lock(&sbi->work_lock); | ||
249 | if (!sbi->work_queued) { | ||
250 | delay = msecs_to_jiffies(dirty_writeback_interval * 10); | ||
251 | queue_delayed_work(system_long_wq, &sbi->sync_work, delay); | ||
252 | sbi->work_queued = 1; | ||
253 | } | ||
254 | spin_unlock(&sbi->work_lock); | ||
235 | } | 255 | } |
236 | 256 | ||
237 | static void hfsplus_put_super(struct super_block *sb) | 257 | static void hfsplus_put_super(struct super_block *sb) |
@@ -240,8 +260,7 @@ static void hfsplus_put_super(struct super_block *sb) | |||
240 | 260 | ||
241 | dprint(DBG_SUPER, "hfsplus_put_super\n"); | 261 | dprint(DBG_SUPER, "hfsplus_put_super\n"); |
242 | 262 | ||
243 | if (!sb->s_fs_info) | 263 | cancel_delayed_work_sync(&sbi->sync_work); |
244 | return; | ||
245 | 264 | ||
246 | if (!(sb->s_flags & MS_RDONLY) && sbi->s_vhdr) { | 265 | if (!(sb->s_flags & MS_RDONLY) && sbi->s_vhdr) { |
247 | struct hfsplus_vh *vhdr = sbi->s_vhdr; | 266 | struct hfsplus_vh *vhdr = sbi->s_vhdr; |
@@ -328,7 +347,6 @@ static const struct super_operations hfsplus_sops = { | |||
328 | .write_inode = hfsplus_write_inode, | 347 | .write_inode = hfsplus_write_inode, |
329 | .evict_inode = hfsplus_evict_inode, | 348 | .evict_inode = hfsplus_evict_inode, |
330 | .put_super = hfsplus_put_super, | 349 | .put_super = hfsplus_put_super, |
331 | .write_super = hfsplus_write_super, | ||
332 | .sync_fs = hfsplus_sync_fs, | 350 | .sync_fs = hfsplus_sync_fs, |
333 | .statfs = hfsplus_statfs, | 351 | .statfs = hfsplus_statfs, |
334 | .remount_fs = hfsplus_remount, | 352 | .remount_fs = hfsplus_remount, |
@@ -355,6 +373,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
355 | sb->s_fs_info = sbi; | 373 | sb->s_fs_info = sbi; |
356 | mutex_init(&sbi->alloc_mutex); | 374 | mutex_init(&sbi->alloc_mutex); |
357 | mutex_init(&sbi->vh_mutex); | 375 | mutex_init(&sbi->vh_mutex); |
376 | spin_lock_init(&sbi->work_lock); | ||
377 | INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs); | ||
358 | hfsplus_fill_defaults(sbi); | 378 | hfsplus_fill_defaults(sbi); |
359 | 379 | ||
360 | err = -EINVAL; | 380 | err = -EINVAL; |
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 2afa5bbccf9b..124146543aa7 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
@@ -553,7 +553,7 @@ static int read_name(struct inode *ino, char *name) | |||
553 | } | 553 | } |
554 | 554 | ||
555 | int hostfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 555 | int hostfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
556 | struct nameidata *nd) | 556 | bool excl) |
557 | { | 557 | { |
558 | struct inode *inode; | 558 | struct inode *inode; |
559 | char *name; | 559 | char *name; |
@@ -595,7 +595,7 @@ int hostfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
595 | } | 595 | } |
596 | 596 | ||
597 | struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry, | 597 | struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry, |
598 | struct nameidata *nd) | 598 | unsigned int flags) |
599 | { | 599 | { |
600 | struct inode *inode; | 600 | struct inode *inode; |
601 | char *name; | 601 | char *name; |
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index b8472f803f4e..78e12b2e0ea2 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c | |||
@@ -189,7 +189,7 @@ out: | |||
189 | * to tell read_inode to read fnode or not. | 189 | * to tell read_inode to read fnode or not. |
190 | */ | 190 | */ |
191 | 191 | ||
192 | struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 192 | struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
193 | { | 193 | { |
194 | const unsigned char *name = dentry->d_name.name; | 194 | const unsigned char *name = dentry->d_name.name; |
195 | unsigned len = dentry->d_name.len; | 195 | unsigned len = dentry->d_name.len; |
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index c07ef1f1ced6..ac1ead194db5 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h | |||
@@ -220,7 +220,7 @@ extern const struct dentry_operations hpfs_dentry_operations; | |||
220 | 220 | ||
221 | /* dir.c */ | 221 | /* dir.c */ |
222 | 222 | ||
223 | struct dentry *hpfs_lookup(struct inode *, struct dentry *, struct nameidata *); | 223 | struct dentry *hpfs_lookup(struct inode *, struct dentry *, unsigned int); |
224 | extern const struct file_operations hpfs_dir_ops; | 224 | extern const struct file_operations hpfs_dir_ops; |
225 | 225 | ||
226 | /* dnode.c */ | 226 | /* dnode.c */ |
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c index 9083ef8af58c..bc9082482f68 100644 --- a/fs/hpfs/namei.c +++ b/fs/hpfs/namei.c | |||
@@ -115,7 +115,7 @@ bail: | |||
115 | return err; | 115 | return err; |
116 | } | 116 | } |
117 | 117 | ||
118 | static int hpfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd) | 118 | static int hpfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) |
119 | { | 119 | { |
120 | const unsigned char *name = dentry->d_name.name; | 120 | const unsigned char *name = dentry->d_name.name; |
121 | unsigned len = dentry->d_name.len; | 121 | unsigned len = dentry->d_name.len; |
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c index d4f93b52cec5..c1dffe47fde2 100644 --- a/fs/hppfs/hppfs.c +++ b/fs/hppfs/hppfs.c | |||
@@ -138,7 +138,7 @@ static int file_removed(struct dentry *dentry, const char *file) | |||
138 | } | 138 | } |
139 | 139 | ||
140 | static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, | 140 | static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, |
141 | struct nameidata *nd) | 141 | unsigned int flags) |
142 | { | 142 | { |
143 | struct dentry *proc_dentry, *parent; | 143 | struct dentry *proc_dentry, *parent; |
144 | struct qstr *name = &dentry->d_name; | 144 | struct qstr *name = &dentry->d_name; |
@@ -420,8 +420,7 @@ static int hppfs_open(struct inode *inode, struct file *file) | |||
420 | { | 420 | { |
421 | const struct cred *cred = file->f_cred; | 421 | const struct cred *cred = file->f_cred; |
422 | struct hppfs_private *data; | 422 | struct hppfs_private *data; |
423 | struct vfsmount *proc_mnt; | 423 | struct path path; |
424 | struct dentry *proc_dentry; | ||
425 | char *host_file; | 424 | char *host_file; |
426 | int err, fd, type, filter; | 425 | int err, fd, type, filter; |
427 | 426 | ||
@@ -434,12 +433,11 @@ static int hppfs_open(struct inode *inode, struct file *file) | |||
434 | if (host_file == NULL) | 433 | if (host_file == NULL) |
435 | goto out_free2; | 434 | goto out_free2; |
436 | 435 | ||
437 | proc_dentry = HPPFS_I(inode)->proc_dentry; | 436 | path.mnt = inode->i_sb->s_fs_info; |
438 | proc_mnt = inode->i_sb->s_fs_info; | 437 | path.dentry = HPPFS_I(inode)->proc_dentry; |
439 | 438 | ||
440 | /* XXX This isn't closed anywhere */ | 439 | /* XXX This isn't closed anywhere */ |
441 | data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), | 440 | data->proc_file = dentry_open(&path, file_mode(file->f_mode), cred); |
442 | file_mode(file->f_mode), cred); | ||
443 | err = PTR_ERR(data->proc_file); | 441 | err = PTR_ERR(data->proc_file); |
444 | if (IS_ERR(data->proc_file)) | 442 | if (IS_ERR(data->proc_file)) |
445 | goto out_free1; | 443 | goto out_free1; |
@@ -484,8 +482,7 @@ static int hppfs_dir_open(struct inode *inode, struct file *file) | |||
484 | { | 482 | { |
485 | const struct cred *cred = file->f_cred; | 483 | const struct cred *cred = file->f_cred; |
486 | struct hppfs_private *data; | 484 | struct hppfs_private *data; |
487 | struct vfsmount *proc_mnt; | 485 | struct path path; |
488 | struct dentry *proc_dentry; | ||
489 | int err; | 486 | int err; |
490 | 487 | ||
491 | err = -ENOMEM; | 488 | err = -ENOMEM; |
@@ -493,10 +490,9 @@ static int hppfs_dir_open(struct inode *inode, struct file *file) | |||
493 | if (data == NULL) | 490 | if (data == NULL) |
494 | goto out; | 491 | goto out; |
495 | 492 | ||
496 | proc_dentry = HPPFS_I(inode)->proc_dentry; | 493 | path.mnt = inode->i_sb->s_fs_info; |
497 | proc_mnt = inode->i_sb->s_fs_info; | 494 | path.dentry = HPPFS_I(inode)->proc_dentry; |
498 | data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), | 495 | data->proc_file = dentry_open(&path, file_mode(file->f_mode), cred); |
499 | file_mode(file->f_mode), cred); | ||
500 | err = PTR_ERR(data->proc_file); | 496 | err = PTR_ERR(data->proc_file); |
501 | if (IS_ERR(data->proc_file)) | 497 | if (IS_ERR(data->proc_file)) |
502 | goto out_free; | 498 | goto out_free; |
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index cc9281b6c628..e13e9bdb0bf5 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -565,7 +565,7 @@ static int hugetlbfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mod | |||
565 | return retval; | 565 | return retval; |
566 | } | 566 | } |
567 | 567 | ||
568 | static int hugetlbfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd) | 568 | static int hugetlbfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) |
569 | { | 569 | { |
570 | return hugetlbfs_mknod(dir, dentry, mode | S_IFREG, 0); | 570 | return hugetlbfs_mknod(dir, dentry, mode | S_IFREG, 0); |
571 | } | 571 | } |
diff --git a/fs/inode.c b/fs/inode.c index c99163b1b310..775cbabd4fa5 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -182,7 +182,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode) | |||
182 | } | 182 | } |
183 | inode->i_private = NULL; | 183 | inode->i_private = NULL; |
184 | inode->i_mapping = mapping; | 184 | inode->i_mapping = mapping; |
185 | INIT_LIST_HEAD(&inode->i_dentry); /* buggered by rcu freeing */ | 185 | INIT_HLIST_HEAD(&inode->i_dentry); /* buggered by rcu freeing */ |
186 | #ifdef CONFIG_FS_POSIX_ACL | 186 | #ifdef CONFIG_FS_POSIX_ACL |
187 | inode->i_acl = inode->i_default_acl = ACL_NOT_CACHED; | 187 | inode->i_acl = inode->i_default_acl = ACL_NOT_CACHED; |
188 | #endif | 188 | #endif |
diff --git a/fs/internal.h b/fs/internal.h index 18bc216ea09d..a6fd56c68b11 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
@@ -42,6 +42,11 @@ static inline int __sync_blockdev(struct block_device *bdev, int wait) | |||
42 | extern void __init chrdev_init(void); | 42 | extern void __init chrdev_init(void); |
43 | 43 | ||
44 | /* | 44 | /* |
45 | * namei.c | ||
46 | */ | ||
47 | extern int __inode_permission(struct inode *, int); | ||
48 | |||
49 | /* | ||
45 | * namespace.c | 50 | * namespace.c |
46 | */ | 51 | */ |
47 | extern int copy_mount_options(const void __user *, unsigned long *); | 52 | extern int copy_mount_options(const void __user *, unsigned long *); |
@@ -50,8 +55,6 @@ extern int copy_mount_string(const void __user *, char **); | |||
50 | extern struct vfsmount *lookup_mnt(struct path *); | 55 | extern struct vfsmount *lookup_mnt(struct path *); |
51 | extern int finish_automount(struct vfsmount *, struct path *); | 56 | extern int finish_automount(struct vfsmount *, struct path *); |
52 | 57 | ||
53 | extern void mnt_make_longterm(struct vfsmount *); | ||
54 | extern void mnt_make_shortterm(struct vfsmount *); | ||
55 | extern int sb_prepare_remount_readonly(struct super_block *); | 58 | extern int sb_prepare_remount_readonly(struct super_block *); |
56 | 59 | ||
57 | extern void __init mnt_init(void); | 60 | extern void __init mnt_init(void); |
@@ -84,9 +87,6 @@ extern struct super_block *user_get_super(dev_t); | |||
84 | /* | 87 | /* |
85 | * open.c | 88 | * open.c |
86 | */ | 89 | */ |
87 | struct nameidata; | ||
88 | extern struct file *nameidata_to_filp(struct nameidata *); | ||
89 | extern void release_open_intent(struct nameidata *); | ||
90 | struct open_flags { | 90 | struct open_flags { |
91 | int open_flag; | 91 | int open_flag; |
92 | umode_t mode; | 92 | umode_t mode; |
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h index 0e73f63d9274..3620ad1ea9bc 100644 --- a/fs/isofs/isofs.h +++ b/fs/isofs/isofs.h | |||
@@ -114,7 +114,7 @@ extern int isofs_name_translate(struct iso_directory_record *, char *, struct in | |||
114 | int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct inode *); | 114 | int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct inode *); |
115 | int get_acorn_filename(struct iso_directory_record *, char *, struct inode *); | 115 | int get_acorn_filename(struct iso_directory_record *, char *, struct inode *); |
116 | 116 | ||
117 | extern struct dentry *isofs_lookup(struct inode *, struct dentry *, struct nameidata *); | 117 | extern struct dentry *isofs_lookup(struct inode *, struct dentry *, unsigned int flags); |
118 | extern struct buffer_head *isofs_bread(struct inode *, sector_t); | 118 | extern struct buffer_head *isofs_bread(struct inode *, sector_t); |
119 | extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long); | 119 | extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long); |
120 | 120 | ||
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c index 1e2946f2a69e..c167028844ed 100644 --- a/fs/isofs/namei.c +++ b/fs/isofs/namei.c | |||
@@ -163,7 +163,7 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry, | |||
163 | return 0; | 163 | return 0; |
164 | } | 164 | } |
165 | 165 | ||
166 | struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 166 | struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
167 | { | 167 | { |
168 | int found; | 168 | int found; |
169 | unsigned long uninitialized_var(block); | 169 | unsigned long uninitialized_var(block); |
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index b56018896d5e..ad7774d32095 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
@@ -25,9 +25,9 @@ | |||
25 | static int jffs2_readdir (struct file *, void *, filldir_t); | 25 | static int jffs2_readdir (struct file *, void *, filldir_t); |
26 | 26 | ||
27 | static int jffs2_create (struct inode *,struct dentry *,umode_t, | 27 | static int jffs2_create (struct inode *,struct dentry *,umode_t, |
28 | struct nameidata *); | 28 | bool); |
29 | static struct dentry *jffs2_lookup (struct inode *,struct dentry *, | 29 | static struct dentry *jffs2_lookup (struct inode *,struct dentry *, |
30 | struct nameidata *); | 30 | unsigned int); |
31 | static int jffs2_link (struct dentry *,struct inode *,struct dentry *); | 31 | static int jffs2_link (struct dentry *,struct inode *,struct dentry *); |
32 | static int jffs2_unlink (struct inode *,struct dentry *); | 32 | static int jffs2_unlink (struct inode *,struct dentry *); |
33 | static int jffs2_symlink (struct inode *,struct dentry *,const char *); | 33 | static int jffs2_symlink (struct inode *,struct dentry *,const char *); |
@@ -74,7 +74,7 @@ const struct inode_operations jffs2_dir_inode_operations = | |||
74 | nice and simple | 74 | nice and simple |
75 | */ | 75 | */ |
76 | static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, | 76 | static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, |
77 | struct nameidata *nd) | 77 | unsigned int flags) |
78 | { | 78 | { |
79 | struct jffs2_inode_info *dir_f; | 79 | struct jffs2_inode_info *dir_f; |
80 | struct jffs2_full_dirent *fd = NULL, *fd_list; | 80 | struct jffs2_full_dirent *fd = NULL, *fd_list; |
@@ -175,7 +175,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
175 | 175 | ||
176 | 176 | ||
177 | static int jffs2_create(struct inode *dir_i, struct dentry *dentry, | 177 | static int jffs2_create(struct inode *dir_i, struct dentry *dentry, |
178 | umode_t mode, struct nameidata *nd) | 178 | umode_t mode, bool excl) |
179 | { | 179 | { |
180 | struct jffs2_raw_inode *ri; | 180 | struct jffs2_raw_inode *ri; |
181 | struct jffs2_inode_info *f, *dir_f; | 181 | struct jffs2_inode_info *f, *dir_f; |
@@ -226,8 +226,8 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, | |||
226 | __func__, inode->i_ino, inode->i_mode, inode->i_nlink, | 226 | __func__, inode->i_ino, inode->i_mode, inode->i_nlink, |
227 | f->inocache->pino_nlink, inode->i_mapping->nrpages); | 227 | f->inocache->pino_nlink, inode->i_mapping->nrpages); |
228 | 228 | ||
229 | d_instantiate(dentry, inode); | ||
230 | unlock_new_inode(inode); | 229 | unlock_new_inode(inode); |
230 | d_instantiate(dentry, inode); | ||
231 | return 0; | 231 | return 0; |
232 | 232 | ||
233 | fail: | 233 | fail: |
@@ -446,8 +446,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
446 | mutex_unlock(&dir_f->sem); | 446 | mutex_unlock(&dir_f->sem); |
447 | jffs2_complete_reservation(c); | 447 | jffs2_complete_reservation(c); |
448 | 448 | ||
449 | d_instantiate(dentry, inode); | ||
450 | unlock_new_inode(inode); | 449 | unlock_new_inode(inode); |
450 | d_instantiate(dentry, inode); | ||
451 | return 0; | 451 | return 0; |
452 | 452 | ||
453 | fail: | 453 | fail: |
@@ -591,8 +591,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, umode_t mode | |||
591 | mutex_unlock(&dir_f->sem); | 591 | mutex_unlock(&dir_f->sem); |
592 | jffs2_complete_reservation(c); | 592 | jffs2_complete_reservation(c); |
593 | 593 | ||
594 | d_instantiate(dentry, inode); | ||
595 | unlock_new_inode(inode); | 594 | unlock_new_inode(inode); |
595 | d_instantiate(dentry, inode); | ||
596 | return 0; | 596 | return 0; |
597 | 597 | ||
598 | fail: | 598 | fail: |
@@ -766,8 +766,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode | |||
766 | mutex_unlock(&dir_f->sem); | 766 | mutex_unlock(&dir_f->sem); |
767 | jffs2_complete_reservation(c); | 767 | jffs2_complete_reservation(c); |
768 | 768 | ||
769 | d_instantiate(dentry, inode); | ||
770 | unlock_new_inode(inode); | 769 | unlock_new_inode(inode); |
770 | d_instantiate(dentry, inode); | ||
771 | return 0; | 771 | return 0; |
772 | 772 | ||
773 | fail: | 773 | fail: |
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 07c91ca6017d..3b91a7ad6086 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c | |||
@@ -73,7 +73,7 @@ static inline void free_ea_wmap(struct inode *inode) | |||
73 | * | 73 | * |
74 | */ | 74 | */ |
75 | static int jfs_create(struct inode *dip, struct dentry *dentry, umode_t mode, | 75 | static int jfs_create(struct inode *dip, struct dentry *dentry, umode_t mode, |
76 | struct nameidata *nd) | 76 | bool excl) |
77 | { | 77 | { |
78 | int rc = 0; | 78 | int rc = 0; |
79 | tid_t tid; /* transaction id */ | 79 | tid_t tid; /* transaction id */ |
@@ -176,8 +176,8 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, umode_t mode, | |||
176 | unlock_new_inode(ip); | 176 | unlock_new_inode(ip); |
177 | iput(ip); | 177 | iput(ip); |
178 | } else { | 178 | } else { |
179 | d_instantiate(dentry, ip); | ||
180 | unlock_new_inode(ip); | 179 | unlock_new_inode(ip); |
180 | d_instantiate(dentry, ip); | ||
181 | } | 181 | } |
182 | 182 | ||
183 | out2: | 183 | out2: |
@@ -309,8 +309,8 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode) | |||
309 | unlock_new_inode(ip); | 309 | unlock_new_inode(ip); |
310 | iput(ip); | 310 | iput(ip); |
311 | } else { | 311 | } else { |
312 | d_instantiate(dentry, ip); | ||
313 | unlock_new_inode(ip); | 312 | unlock_new_inode(ip); |
313 | d_instantiate(dentry, ip); | ||
314 | } | 314 | } |
315 | 315 | ||
316 | out2: | 316 | out2: |
@@ -1043,8 +1043,8 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry, | |||
1043 | unlock_new_inode(ip); | 1043 | unlock_new_inode(ip); |
1044 | iput(ip); | 1044 | iput(ip); |
1045 | } else { | 1045 | } else { |
1046 | d_instantiate(dentry, ip); | ||
1047 | unlock_new_inode(ip); | 1046 | unlock_new_inode(ip); |
1047 | d_instantiate(dentry, ip); | ||
1048 | } | 1048 | } |
1049 | 1049 | ||
1050 | out2: | 1050 | out2: |
@@ -1424,8 +1424,8 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry, | |||
1424 | unlock_new_inode(ip); | 1424 | unlock_new_inode(ip); |
1425 | iput(ip); | 1425 | iput(ip); |
1426 | } else { | 1426 | } else { |
1427 | d_instantiate(dentry, ip); | ||
1428 | unlock_new_inode(ip); | 1427 | unlock_new_inode(ip); |
1428 | d_instantiate(dentry, ip); | ||
1429 | } | 1429 | } |
1430 | 1430 | ||
1431 | out1: | 1431 | out1: |
@@ -1436,7 +1436,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry, | |||
1436 | return rc; | 1436 | return rc; |
1437 | } | 1437 | } |
1438 | 1438 | ||
1439 | static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struct nameidata *nd) | 1439 | static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, unsigned int flags) |
1440 | { | 1440 | { |
1441 | struct btstack btstack; | 1441 | struct btstack btstack; |
1442 | ino_t inum; | 1442 | ino_t inum; |
@@ -1570,7 +1570,7 @@ out: | |||
1570 | return result; | 1570 | return result; |
1571 | } | 1571 | } |
1572 | 1572 | ||
1573 | static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd) | 1573 | static int jfs_ci_revalidate(struct dentry *dentry, unsigned int flags) |
1574 | { | 1574 | { |
1575 | /* | 1575 | /* |
1576 | * This is not negative dentry. Always valid. | 1576 | * This is not negative dentry. Always valid. |
@@ -1589,7 +1589,7 @@ static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1589 | * This may be nfsd (or something), anyway, we can't see the | 1589 | * This may be nfsd (or something), anyway, we can't see the |
1590 | * intent of this. So, since this can be for creation, drop it. | 1590 | * intent of this. So, since this can be for creation, drop it. |
1591 | */ | 1591 | */ |
1592 | if (!nd) | 1592 | if (!flags) |
1593 | return 0; | 1593 | return 0; |
1594 | 1594 | ||
1595 | /* | 1595 | /* |
@@ -1597,7 +1597,7 @@ static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1597 | * case sensitive name which is specified by user if this is | 1597 | * case sensitive name which is specified by user if this is |
1598 | * for creation. | 1598 | * for creation. |
1599 | */ | 1599 | */ |
1600 | if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) | 1600 | if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) |
1601 | return 0; | 1601 | return 0; |
1602 | return 1; | 1602 | return 1; |
1603 | } | 1603 | } |
diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 4a82950f412f..c55c7452d285 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c | |||
@@ -601,6 +601,11 @@ static int jfs_sync_fs(struct super_block *sb, int wait) | |||
601 | 601 | ||
602 | /* log == NULL indicates read-only mount */ | 602 | /* log == NULL indicates read-only mount */ |
603 | if (log) { | 603 | if (log) { |
604 | /* | ||
605 | * Write quota structures to quota file, sync_blockdev() will | ||
606 | * write them to disk later | ||
607 | */ | ||
608 | dquot_writeback_dquots(sb, -1); | ||
604 | jfs_flush_journal(log, wait); | 609 | jfs_flush_journal(log, wait); |
605 | jfs_syncpt(log, 0); | 610 | jfs_syncpt(log, 0); |
606 | } | 611 | } |
diff --git a/fs/libfs.c b/fs/libfs.c index f86ec27a4230..a74cb1725ac6 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -53,7 +53,7 @@ static int simple_delete_dentry(const struct dentry *dentry) | |||
53 | * Lookup the data. This is trivial - if the dentry didn't already | 53 | * Lookup the data. This is trivial - if the dentry didn't already |
54 | * exist, we know it is negative. Set d_op to delete negative dentries. | 54 | * exist, we know it is negative. Set d_op to delete negative dentries. |
55 | */ | 55 | */ |
56 | struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 56 | struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
57 | { | 57 | { |
58 | static const struct dentry_operations simple_dentry_operations = { | 58 | static const struct dentry_operations simple_dentry_operations = { |
59 | .d_delete = simple_delete_dentry, | 59 | .d_delete = simple_delete_dentry, |
@@ -222,15 +222,15 @@ struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name, | |||
222 | const struct super_operations *ops, | 222 | const struct super_operations *ops, |
223 | const struct dentry_operations *dops, unsigned long magic) | 223 | const struct dentry_operations *dops, unsigned long magic) |
224 | { | 224 | { |
225 | struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); | 225 | struct super_block *s; |
226 | struct dentry *dentry; | 226 | struct dentry *dentry; |
227 | struct inode *root; | 227 | struct inode *root; |
228 | struct qstr d_name = QSTR_INIT(name, strlen(name)); | 228 | struct qstr d_name = QSTR_INIT(name, strlen(name)); |
229 | 229 | ||
230 | s = sget(fs_type, NULL, set_anon_super, MS_NOUSER, NULL); | ||
230 | if (IS_ERR(s)) | 231 | if (IS_ERR(s)) |
231 | return ERR_CAST(s); | 232 | return ERR_CAST(s); |
232 | 233 | ||
233 | s->s_flags = MS_NOUSER; | ||
234 | s->s_maxbytes = MAX_LFS_FILESIZE; | 234 | s->s_maxbytes = MAX_LFS_FILESIZE; |
235 | s->s_blocksize = PAGE_SIZE; | 235 | s->s_blocksize = PAGE_SIZE; |
236 | s->s_blocksize_bits = PAGE_SHIFT; | 236 | s->s_blocksize_bits = PAGE_SHIFT; |
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c index bea5d1b9954b..26e4a941532f 100644 --- a/fs/logfs/dir.c +++ b/fs/logfs/dir.c | |||
@@ -349,7 +349,7 @@ static void logfs_set_name(struct logfs_disk_dentry *dd, struct qstr *name) | |||
349 | } | 349 | } |
350 | 350 | ||
351 | static struct dentry *logfs_lookup(struct inode *dir, struct dentry *dentry, | 351 | static struct dentry *logfs_lookup(struct inode *dir, struct dentry *dentry, |
352 | struct nameidata *nd) | 352 | unsigned int flags) |
353 | { | 353 | { |
354 | struct page *page; | 354 | struct page *page; |
355 | struct logfs_disk_dentry *dd; | 355 | struct logfs_disk_dentry *dd; |
@@ -502,7 +502,7 @@ static int logfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
502 | } | 502 | } |
503 | 503 | ||
504 | static int logfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 504 | static int logfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
505 | struct nameidata *nd) | 505 | bool excl) |
506 | { | 506 | { |
507 | struct inode *inode; | 507 | struct inode *inode; |
508 | 508 | ||
diff --git a/fs/logfs/super.c b/fs/logfs/super.c index 97bca623d893..345c24b8a6f8 100644 --- a/fs/logfs/super.c +++ b/fs/logfs/super.c | |||
@@ -519,7 +519,7 @@ static struct dentry *logfs_get_sb_device(struct logfs_super *super, | |||
519 | log_super("LogFS: Start mount %x\n", mount_count++); | 519 | log_super("LogFS: Start mount %x\n", mount_count++); |
520 | 520 | ||
521 | err = -EINVAL; | 521 | err = -EINVAL; |
522 | sb = sget(type, logfs_sb_test, logfs_sb_set, super); | 522 | sb = sget(type, logfs_sb_test, logfs_sb_set, flags | MS_NOATIME, super); |
523 | if (IS_ERR(sb)) { | 523 | if (IS_ERR(sb)) { |
524 | super->s_devops->put_device(super); | 524 | super->s_devops->put_device(super); |
525 | kfree(super); | 525 | kfree(super); |
@@ -542,7 +542,6 @@ static struct dentry *logfs_get_sb_device(struct logfs_super *super, | |||
542 | sb->s_maxbytes = (1ull << 43) - 1; | 542 | sb->s_maxbytes = (1ull << 43) - 1; |
543 | sb->s_max_links = LOGFS_LINK_MAX; | 543 | sb->s_max_links = LOGFS_LINK_MAX; |
544 | sb->s_op = &logfs_super_operations; | 544 | sb->s_op = &logfs_super_operations; |
545 | sb->s_flags = flags | MS_NOATIME; | ||
546 | 545 | ||
547 | err = logfs_read_sb(sb, sb->s_flags & MS_RDONLY); | 546 | err = logfs_read_sb(sb, sb->s_flags & MS_RDONLY); |
548 | if (err) | 547 | if (err) |
diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 2d0ee1786305..0db73d9dd668 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c | |||
@@ -18,7 +18,7 @@ static int add_nondir(struct dentry *dentry, struct inode *inode) | |||
18 | return err; | 18 | return err; |
19 | } | 19 | } |
20 | 20 | ||
21 | static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) | 21 | static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags) |
22 | { | 22 | { |
23 | struct inode * inode = NULL; | 23 | struct inode * inode = NULL; |
24 | ino_t ino; | 24 | ino_t ino; |
@@ -55,7 +55,7 @@ static int minix_mknod(struct inode * dir, struct dentry *dentry, umode_t mode, | |||
55 | } | 55 | } |
56 | 56 | ||
57 | static int minix_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 57 | static int minix_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
58 | struct nameidata *nd) | 58 | bool excl) |
59 | { | 59 | { |
60 | return minix_mknod(dir, dentry, mode, 0); | 60 | return minix_mknod(dir, dentry, mode, 0); |
61 | } | 61 | } |
diff --git a/fs/mount.h b/fs/mount.h index 4ef36d93e5a2..4f291f9de641 100644 --- a/fs/mount.h +++ b/fs/mount.h | |||
@@ -22,7 +22,6 @@ struct mount { | |||
22 | struct vfsmount mnt; | 22 | struct vfsmount mnt; |
23 | #ifdef CONFIG_SMP | 23 | #ifdef CONFIG_SMP |
24 | struct mnt_pcp __percpu *mnt_pcp; | 24 | struct mnt_pcp __percpu *mnt_pcp; |
25 | atomic_t mnt_longterm; /* how many of the refs are longterm */ | ||
26 | #else | 25 | #else |
27 | int mnt_count; | 26 | int mnt_count; |
28 | int mnt_writers; | 27 | int mnt_writers; |
@@ -49,6 +48,8 @@ struct mount { | |||
49 | int mnt_ghosts; | 48 | int mnt_ghosts; |
50 | }; | 49 | }; |
51 | 50 | ||
51 | #define MNT_NS_INTERNAL ERR_PTR(-EINVAL) /* distinct from any mnt_namespace */ | ||
52 | |||
52 | static inline struct mount *real_mount(struct vfsmount *mnt) | 53 | static inline struct mount *real_mount(struct vfsmount *mnt) |
53 | { | 54 | { |
54 | return container_of(mnt, struct mount, mnt); | 55 | return container_of(mnt, struct mount, mnt); |
@@ -59,6 +60,12 @@ static inline int mnt_has_parent(struct mount *mnt) | |||
59 | return mnt != mnt->mnt_parent; | 60 | return mnt != mnt->mnt_parent; |
60 | } | 61 | } |
61 | 62 | ||
63 | static inline int is_mounted(struct vfsmount *mnt) | ||
64 | { | ||
65 | /* neither detached nor internal? */ | ||
66 | return !IS_ERR_OR_NULL(real_mount(mnt)); | ||
67 | } | ||
68 | |||
62 | extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *, int); | 69 | extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *, int); |
63 | 70 | ||
64 | static inline void get_mnt_ns(struct mnt_namespace *ns) | 71 | static inline void get_mnt_ns(struct mnt_namespace *ns) |
@@ -67,10 +74,12 @@ static inline void get_mnt_ns(struct mnt_namespace *ns) | |||
67 | } | 74 | } |
68 | 75 | ||
69 | struct proc_mounts { | 76 | struct proc_mounts { |
70 | struct seq_file m; /* must be the first element */ | 77 | struct seq_file m; |
71 | struct mnt_namespace *ns; | 78 | struct mnt_namespace *ns; |
72 | struct path root; | 79 | struct path root; |
73 | int (*show)(struct seq_file *, struct vfsmount *); | 80 | int (*show)(struct seq_file *, struct vfsmount *); |
74 | }; | 81 | }; |
75 | 82 | ||
83 | #define proc_mounts(p) (container_of((p), struct proc_mounts, m)) | ||
84 | |||
76 | extern const struct seq_operations mounts_op; | 85 | extern const struct seq_operations mounts_op; |
diff --git a/fs/namei.c b/fs/namei.c index 7d694194024a..2ccc35c4dc24 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -315,31 +315,22 @@ static inline int do_inode_permission(struct inode *inode, int mask) | |||
315 | } | 315 | } |
316 | 316 | ||
317 | /** | 317 | /** |
318 | * inode_permission - check for access rights to a given inode | 318 | * __inode_permission - Check for access rights to a given inode |
319 | * @inode: inode to check permission on | 319 | * @inode: Inode to check permission on |
320 | * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC, ...) | 320 | * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) |
321 | * | 321 | * |
322 | * Used to check for read/write/execute permissions on an inode. | 322 | * Check for read/write/execute permissions on an inode. |
323 | * We use "fsuid" for this, letting us set arbitrary permissions | ||
324 | * for filesystem access without changing the "normal" uids which | ||
325 | * are used for other things. | ||
326 | * | 323 | * |
327 | * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask. | 324 | * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask. |
325 | * | ||
326 | * This does not check for a read-only file system. You probably want | ||
327 | * inode_permission(). | ||
328 | */ | 328 | */ |
329 | int inode_permission(struct inode *inode, int mask) | 329 | int __inode_permission(struct inode *inode, int mask) |
330 | { | 330 | { |
331 | int retval; | 331 | int retval; |
332 | 332 | ||
333 | if (unlikely(mask & MAY_WRITE)) { | 333 | if (unlikely(mask & MAY_WRITE)) { |
334 | umode_t mode = inode->i_mode; | ||
335 | |||
336 | /* | ||
337 | * Nobody gets write access to a read-only fs. | ||
338 | */ | ||
339 | if (IS_RDONLY(inode) && | ||
340 | (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) | ||
341 | return -EROFS; | ||
342 | |||
343 | /* | 334 | /* |
344 | * Nobody gets write access to an immutable file. | 335 | * Nobody gets write access to an immutable file. |
345 | */ | 336 | */ |
@@ -359,6 +350,47 @@ int inode_permission(struct inode *inode, int mask) | |||
359 | } | 350 | } |
360 | 351 | ||
361 | /** | 352 | /** |
353 | * sb_permission - Check superblock-level permissions | ||
354 | * @sb: Superblock of inode to check permission on | ||
355 | * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | ||
356 | * | ||
357 | * Separate out file-system wide checks from inode-specific permission checks. | ||
358 | */ | ||
359 | static int sb_permission(struct super_block *sb, struct inode *inode, int mask) | ||
360 | { | ||
361 | if (unlikely(mask & MAY_WRITE)) { | ||
362 | umode_t mode = inode->i_mode; | ||
363 | |||
364 | /* Nobody gets write access to a read-only fs. */ | ||
365 | if ((sb->s_flags & MS_RDONLY) && | ||
366 | (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) | ||
367 | return -EROFS; | ||
368 | } | ||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | /** | ||
373 | * inode_permission - Check for access rights to a given inode | ||
374 | * @inode: Inode to check permission on | ||
375 | * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) | ||
376 | * | ||
377 | * Check for read/write/execute permissions on an inode. We use fs[ug]id for | ||
378 | * this, letting us set arbitrary permissions for filesystem access without | ||
379 | * changing the "normal" UIDs which are used for other things. | ||
380 | * | ||
381 | * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask. | ||
382 | */ | ||
383 | int inode_permission(struct inode *inode, int mask) | ||
384 | { | ||
385 | int retval; | ||
386 | |||
387 | retval = sb_permission(inode->i_sb, inode, mask); | ||
388 | if (retval) | ||
389 | return retval; | ||
390 | return __inode_permission(inode, mask); | ||
391 | } | ||
392 | |||
393 | /** | ||
362 | * path_get - get a reference to a path | 394 | * path_get - get a reference to a path |
363 | * @path: path to get the reference to | 395 | * @path: path to get the reference to |
364 | * | 396 | * |
@@ -395,6 +427,18 @@ EXPORT_SYMBOL(path_put); | |||
395 | * to restart the path walk from the beginning in ref-walk mode. | 427 | * to restart the path walk from the beginning in ref-walk mode. |
396 | */ | 428 | */ |
397 | 429 | ||
430 | static inline void lock_rcu_walk(void) | ||
431 | { | ||
432 | br_read_lock(&vfsmount_lock); | ||
433 | rcu_read_lock(); | ||
434 | } | ||
435 | |||
436 | static inline void unlock_rcu_walk(void) | ||
437 | { | ||
438 | rcu_read_unlock(); | ||
439 | br_read_unlock(&vfsmount_lock); | ||
440 | } | ||
441 | |||
398 | /** | 442 | /** |
399 | * unlazy_walk - try to switch to ref-walk mode. | 443 | * unlazy_walk - try to switch to ref-walk mode. |
400 | * @nd: nameidata pathwalk data | 444 | * @nd: nameidata pathwalk data |
@@ -448,8 +492,7 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry) | |||
448 | } | 492 | } |
449 | mntget(nd->path.mnt); | 493 | mntget(nd->path.mnt); |
450 | 494 | ||
451 | rcu_read_unlock(); | 495 | unlock_rcu_walk(); |
452 | br_read_unlock(&vfsmount_lock); | ||
453 | nd->flags &= ~LOOKUP_RCU; | 496 | nd->flags &= ~LOOKUP_RCU; |
454 | return 0; | 497 | return 0; |
455 | 498 | ||
@@ -463,25 +506,9 @@ err_root: | |||
463 | return -ECHILD; | 506 | return -ECHILD; |
464 | } | 507 | } |
465 | 508 | ||
466 | /** | 509 | static inline int d_revalidate(struct dentry *dentry, unsigned int flags) |
467 | * release_open_intent - free up open intent resources | ||
468 | * @nd: pointer to nameidata | ||
469 | */ | ||
470 | void release_open_intent(struct nameidata *nd) | ||
471 | { | 510 | { |
472 | struct file *file = nd->intent.open.file; | 511 | return dentry->d_op->d_revalidate(dentry, flags); |
473 | |||
474 | if (file && !IS_ERR(file)) { | ||
475 | if (file->f_path.dentry == NULL) | ||
476 | put_filp(file); | ||
477 | else | ||
478 | fput(file); | ||
479 | } | ||
480 | } | ||
481 | |||
482 | static inline int d_revalidate(struct dentry *dentry, struct nameidata *nd) | ||
483 | { | ||
484 | return dentry->d_op->d_revalidate(dentry, nd); | ||
485 | } | 512 | } |
486 | 513 | ||
487 | /** | 514 | /** |
@@ -506,15 +533,13 @@ static int complete_walk(struct nameidata *nd) | |||
506 | spin_lock(&dentry->d_lock); | 533 | spin_lock(&dentry->d_lock); |
507 | if (unlikely(!__d_rcu_to_refcount(dentry, nd->seq))) { | 534 | if (unlikely(!__d_rcu_to_refcount(dentry, nd->seq))) { |
508 | spin_unlock(&dentry->d_lock); | 535 | spin_unlock(&dentry->d_lock); |
509 | rcu_read_unlock(); | 536 | unlock_rcu_walk(); |
510 | br_read_unlock(&vfsmount_lock); | ||
511 | return -ECHILD; | 537 | return -ECHILD; |
512 | } | 538 | } |
513 | BUG_ON(nd->inode != dentry->d_inode); | 539 | BUG_ON(nd->inode != dentry->d_inode); |
514 | spin_unlock(&dentry->d_lock); | 540 | spin_unlock(&dentry->d_lock); |
515 | mntget(nd->path.mnt); | 541 | mntget(nd->path.mnt); |
516 | rcu_read_unlock(); | 542 | unlock_rcu_walk(); |
517 | br_read_unlock(&vfsmount_lock); | ||
518 | } | 543 | } |
519 | 544 | ||
520 | if (likely(!(nd->flags & LOOKUP_JUMPED))) | 545 | if (likely(!(nd->flags & LOOKUP_JUMPED))) |
@@ -527,7 +552,7 @@ static int complete_walk(struct nameidata *nd) | |||
527 | return 0; | 552 | return 0; |
528 | 553 | ||
529 | /* Note: we do not d_invalidate() */ | 554 | /* Note: we do not d_invalidate() */ |
530 | status = d_revalidate(dentry, nd); | 555 | status = d_revalidate(dentry, nd->flags); |
531 | if (status > 0) | 556 | if (status > 0) |
532 | return 0; | 557 | return 0; |
533 | 558 | ||
@@ -602,10 +627,25 @@ static inline void path_to_nameidata(const struct path *path, | |||
602 | nd->path.dentry = path->dentry; | 627 | nd->path.dentry = path->dentry; |
603 | } | 628 | } |
604 | 629 | ||
630 | /* | ||
631 | * Helper to directly jump to a known parsed path from ->follow_link, | ||
632 | * caller must have taken a reference to path beforehand. | ||
633 | */ | ||
634 | void nd_jump_link(struct nameidata *nd, struct path *path) | ||
635 | { | ||
636 | path_put(&nd->path); | ||
637 | |||
638 | nd->path = *path; | ||
639 | nd->inode = nd->path.dentry->d_inode; | ||
640 | nd->flags |= LOOKUP_JUMPED; | ||
641 | |||
642 | BUG_ON(nd->inode->i_op->follow_link); | ||
643 | } | ||
644 | |||
605 | static inline void put_link(struct nameidata *nd, struct path *link, void *cookie) | 645 | static inline void put_link(struct nameidata *nd, struct path *link, void *cookie) |
606 | { | 646 | { |
607 | struct inode *inode = link->dentry->d_inode; | 647 | struct inode *inode = link->dentry->d_inode; |
608 | if (!IS_ERR(cookie) && inode->i_op->put_link) | 648 | if (inode->i_op->put_link) |
609 | inode->i_op->put_link(link->dentry, nd, cookie); | 649 | inode->i_op->put_link(link->dentry, nd, cookie); |
610 | path_put(link); | 650 | path_put(link); |
611 | } | 651 | } |
@@ -613,19 +653,19 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki | |||
613 | static __always_inline int | 653 | static __always_inline int |
614 | follow_link(struct path *link, struct nameidata *nd, void **p) | 654 | follow_link(struct path *link, struct nameidata *nd, void **p) |
615 | { | 655 | { |
616 | int error; | ||
617 | struct dentry *dentry = link->dentry; | 656 | struct dentry *dentry = link->dentry; |
657 | int error; | ||
658 | char *s; | ||
618 | 659 | ||
619 | BUG_ON(nd->flags & LOOKUP_RCU); | 660 | BUG_ON(nd->flags & LOOKUP_RCU); |
620 | 661 | ||
621 | if (link->mnt == nd->path.mnt) | 662 | if (link->mnt == nd->path.mnt) |
622 | mntget(link->mnt); | 663 | mntget(link->mnt); |
623 | 664 | ||
624 | if (unlikely(current->total_link_count >= 40)) { | 665 | error = -ELOOP; |
625 | *p = ERR_PTR(-ELOOP); /* no ->put_link(), please */ | 666 | if (unlikely(current->total_link_count >= 40)) |
626 | path_put(&nd->path); | 667 | goto out_put_nd_path; |
627 | return -ELOOP; | 668 | |
628 | } | ||
629 | cond_resched(); | 669 | cond_resched(); |
630 | current->total_link_count++; | 670 | current->total_link_count++; |
631 | 671 | ||
@@ -633,30 +673,28 @@ follow_link(struct path *link, struct nameidata *nd, void **p) | |||
633 | nd_set_link(nd, NULL); | 673 | nd_set_link(nd, NULL); |
634 | 674 | ||
635 | error = security_inode_follow_link(link->dentry, nd); | 675 | error = security_inode_follow_link(link->dentry, nd); |
636 | if (error) { | 676 | if (error) |
637 | *p = ERR_PTR(error); /* no ->put_link(), please */ | 677 | goto out_put_nd_path; |
638 | path_put(&nd->path); | ||
639 | return error; | ||
640 | } | ||
641 | 678 | ||
642 | nd->last_type = LAST_BIND; | 679 | nd->last_type = LAST_BIND; |
643 | *p = dentry->d_inode->i_op->follow_link(dentry, nd); | 680 | *p = dentry->d_inode->i_op->follow_link(dentry, nd); |
644 | error = PTR_ERR(*p); | 681 | error = PTR_ERR(*p); |
645 | if (!IS_ERR(*p)) { | 682 | if (IS_ERR(*p)) |
646 | char *s = nd_get_link(nd); | 683 | goto out_put_nd_path; |
647 | error = 0; | 684 | |
648 | if (s) | 685 | error = 0; |
649 | error = __vfs_follow_link(nd, s); | 686 | s = nd_get_link(nd); |
650 | else if (nd->last_type == LAST_BIND) { | 687 | if (s) { |
651 | nd->flags |= LOOKUP_JUMPED; | 688 | error = __vfs_follow_link(nd, s); |
652 | nd->inode = nd->path.dentry->d_inode; | 689 | if (unlikely(error)) |
653 | if (nd->inode->i_op->follow_link) { | 690 | put_link(nd, link, *p); |
654 | /* stepped on a _really_ weird one */ | ||
655 | path_put(&nd->path); | ||
656 | error = -ELOOP; | ||
657 | } | ||
658 | } | ||
659 | } | 691 | } |
692 | |||
693 | return error; | ||
694 | |||
695 | out_put_nd_path: | ||
696 | path_put(&nd->path); | ||
697 | path_put(link); | ||
660 | return error; | 698 | return error; |
661 | } | 699 | } |
662 | 700 | ||
@@ -675,6 +713,16 @@ static int follow_up_rcu(struct path *path) | |||
675 | return 1; | 713 | return 1; |
676 | } | 714 | } |
677 | 715 | ||
716 | /* | ||
717 | * follow_up - Find the mountpoint of path's vfsmount | ||
718 | * | ||
719 | * Given a path, find the mountpoint of its source file system. | ||
720 | * Replace @path with the path of the mountpoint in the parent mount. | ||
721 | * Up is towards /. | ||
722 | * | ||
723 | * Return 1 if we went up a level and 0 if we were already at the | ||
724 | * root. | ||
725 | */ | ||
678 | int follow_up(struct path *path) | 726 | int follow_up(struct path *path) |
679 | { | 727 | { |
680 | struct mount *mnt = real_mount(path->mnt); | 728 | struct mount *mnt = real_mount(path->mnt); |
@@ -683,7 +731,7 @@ int follow_up(struct path *path) | |||
683 | 731 | ||
684 | br_read_lock(&vfsmount_lock); | 732 | br_read_lock(&vfsmount_lock); |
685 | parent = mnt->mnt_parent; | 733 | parent = mnt->mnt_parent; |
686 | if (&parent->mnt == path->mnt) { | 734 | if (parent == mnt) { |
687 | br_read_unlock(&vfsmount_lock); | 735 | br_read_unlock(&vfsmount_lock); |
688 | return 0; | 736 | return 0; |
689 | } | 737 | } |
@@ -946,8 +994,7 @@ failed: | |||
946 | nd->flags &= ~LOOKUP_RCU; | 994 | nd->flags &= ~LOOKUP_RCU; |
947 | if (!(nd->flags & LOOKUP_ROOT)) | 995 | if (!(nd->flags & LOOKUP_ROOT)) |
948 | nd->root.mnt = NULL; | 996 | nd->root.mnt = NULL; |
949 | rcu_read_unlock(); | 997 | unlock_rcu_walk(); |
950 | br_read_unlock(&vfsmount_lock); | ||
951 | return -ECHILD; | 998 | return -ECHILD; |
952 | } | 999 | } |
953 | 1000 | ||
@@ -1048,7 +1095,7 @@ static void follow_dotdot(struct nameidata *nd) | |||
1048 | * dir->d_inode->i_mutex must be held | 1095 | * dir->d_inode->i_mutex must be held |
1049 | */ | 1096 | */ |
1050 | static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir, | 1097 | static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir, |
1051 | struct nameidata *nd, bool *need_lookup) | 1098 | unsigned int flags, bool *need_lookup) |
1052 | { | 1099 | { |
1053 | struct dentry *dentry; | 1100 | struct dentry *dentry; |
1054 | int error; | 1101 | int error; |
@@ -1059,7 +1106,7 @@ static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir, | |||
1059 | if (d_need_lookup(dentry)) { | 1106 | if (d_need_lookup(dentry)) { |
1060 | *need_lookup = true; | 1107 | *need_lookup = true; |
1061 | } else if (dentry->d_flags & DCACHE_OP_REVALIDATE) { | 1108 | } else if (dentry->d_flags & DCACHE_OP_REVALIDATE) { |
1062 | error = d_revalidate(dentry, nd); | 1109 | error = d_revalidate(dentry, flags); |
1063 | if (unlikely(error <= 0)) { | 1110 | if (unlikely(error <= 0)) { |
1064 | if (error < 0) { | 1111 | if (error < 0) { |
1065 | dput(dentry); | 1112 | dput(dentry); |
@@ -1089,7 +1136,7 @@ static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir, | |||
1089 | * dir->d_inode->i_mutex must be held | 1136 | * dir->d_inode->i_mutex must be held |
1090 | */ | 1137 | */ |
1091 | static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry, | 1138 | static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry, |
1092 | struct nameidata *nd) | 1139 | unsigned int flags) |
1093 | { | 1140 | { |
1094 | struct dentry *old; | 1141 | struct dentry *old; |
1095 | 1142 | ||
@@ -1099,7 +1146,7 @@ static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry, | |||
1099 | return ERR_PTR(-ENOENT); | 1146 | return ERR_PTR(-ENOENT); |
1100 | } | 1147 | } |
1101 | 1148 | ||
1102 | old = dir->i_op->lookup(dir, dentry, nd); | 1149 | old = dir->i_op->lookup(dir, dentry, flags); |
1103 | if (unlikely(old)) { | 1150 | if (unlikely(old)) { |
1104 | dput(dentry); | 1151 | dput(dentry); |
1105 | dentry = old; | 1152 | dentry = old; |
@@ -1108,16 +1155,16 @@ static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry, | |||
1108 | } | 1155 | } |
1109 | 1156 | ||
1110 | static struct dentry *__lookup_hash(struct qstr *name, | 1157 | static struct dentry *__lookup_hash(struct qstr *name, |
1111 | struct dentry *base, struct nameidata *nd) | 1158 | struct dentry *base, unsigned int flags) |
1112 | { | 1159 | { |
1113 | bool need_lookup; | 1160 | bool need_lookup; |
1114 | struct dentry *dentry; | 1161 | struct dentry *dentry; |
1115 | 1162 | ||
1116 | dentry = lookup_dcache(name, base, nd, &need_lookup); | 1163 | dentry = lookup_dcache(name, base, flags, &need_lookup); |
1117 | if (!need_lookup) | 1164 | if (!need_lookup) |
1118 | return dentry; | 1165 | return dentry; |
1119 | 1166 | ||
1120 | return lookup_real(base->d_inode, dentry, nd); | 1167 | return lookup_real(base->d_inode, dentry, flags); |
1121 | } | 1168 | } |
1122 | 1169 | ||
1123 | /* | 1170 | /* |
@@ -1167,7 +1214,7 @@ static int lookup_fast(struct nameidata *nd, struct qstr *name, | |||
1167 | if (unlikely(d_need_lookup(dentry))) | 1214 | if (unlikely(d_need_lookup(dentry))) |
1168 | goto unlazy; | 1215 | goto unlazy; |
1169 | if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) { | 1216 | if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) { |
1170 | status = d_revalidate(dentry, nd); | 1217 | status = d_revalidate(dentry, nd->flags); |
1171 | if (unlikely(status <= 0)) { | 1218 | if (unlikely(status <= 0)) { |
1172 | if (status != -ECHILD) | 1219 | if (status != -ECHILD) |
1173 | need_reval = 0; | 1220 | need_reval = 0; |
@@ -1197,7 +1244,7 @@ unlazy: | |||
1197 | } | 1244 | } |
1198 | 1245 | ||
1199 | if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE) && need_reval) | 1246 | if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE) && need_reval) |
1200 | status = d_revalidate(dentry, nd); | 1247 | status = d_revalidate(dentry, nd->flags); |
1201 | if (unlikely(status <= 0)) { | 1248 | if (unlikely(status <= 0)) { |
1202 | if (status < 0) { | 1249 | if (status < 0) { |
1203 | dput(dentry); | 1250 | dput(dentry); |
@@ -1236,7 +1283,7 @@ static int lookup_slow(struct nameidata *nd, struct qstr *name, | |||
1236 | BUG_ON(nd->inode != parent->d_inode); | 1283 | BUG_ON(nd->inode != parent->d_inode); |
1237 | 1284 | ||
1238 | mutex_lock(&parent->d_inode->i_mutex); | 1285 | mutex_lock(&parent->d_inode->i_mutex); |
1239 | dentry = __lookup_hash(name, parent, nd); | 1286 | dentry = __lookup_hash(name, parent, nd->flags); |
1240 | mutex_unlock(&parent->d_inode->i_mutex); | 1287 | mutex_unlock(&parent->d_inode->i_mutex); |
1241 | if (IS_ERR(dentry)) | 1288 | if (IS_ERR(dentry)) |
1242 | return PTR_ERR(dentry); | 1289 | return PTR_ERR(dentry); |
@@ -1284,8 +1331,7 @@ static void terminate_walk(struct nameidata *nd) | |||
1284 | nd->flags &= ~LOOKUP_RCU; | 1331 | nd->flags &= ~LOOKUP_RCU; |
1285 | if (!(nd->flags & LOOKUP_ROOT)) | 1332 | if (!(nd->flags & LOOKUP_ROOT)) |
1286 | nd->root.mnt = NULL; | 1333 | nd->root.mnt = NULL; |
1287 | rcu_read_unlock(); | 1334 | unlock_rcu_walk(); |
1288 | br_read_unlock(&vfsmount_lock); | ||
1289 | } | 1335 | } |
1290 | } | 1336 | } |
1291 | 1337 | ||
@@ -1383,9 +1429,10 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd) | |||
1383 | void *cookie; | 1429 | void *cookie; |
1384 | 1430 | ||
1385 | res = follow_link(&link, nd, &cookie); | 1431 | res = follow_link(&link, nd, &cookie); |
1386 | if (!res) | 1432 | if (res) |
1387 | res = walk_component(nd, path, &nd->last, | 1433 | break; |
1388 | nd->last_type, LOOKUP_FOLLOW); | 1434 | res = walk_component(nd, path, &nd->last, |
1435 | nd->last_type, LOOKUP_FOLLOW); | ||
1389 | put_link(nd, &link, cookie); | 1436 | put_link(nd, &link, cookie); |
1390 | } while (res > 0); | 1437 | } while (res > 0); |
1391 | 1438 | ||
@@ -1651,8 +1698,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
1651 | nd->path = nd->root; | 1698 | nd->path = nd->root; |
1652 | nd->inode = inode; | 1699 | nd->inode = inode; |
1653 | if (flags & LOOKUP_RCU) { | 1700 | if (flags & LOOKUP_RCU) { |
1654 | br_read_lock(&vfsmount_lock); | 1701 | lock_rcu_walk(); |
1655 | rcu_read_lock(); | ||
1656 | nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); | 1702 | nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); |
1657 | } else { | 1703 | } else { |
1658 | path_get(&nd->path); | 1704 | path_get(&nd->path); |
@@ -1664,8 +1710,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
1664 | 1710 | ||
1665 | if (*name=='/') { | 1711 | if (*name=='/') { |
1666 | if (flags & LOOKUP_RCU) { | 1712 | if (flags & LOOKUP_RCU) { |
1667 | br_read_lock(&vfsmount_lock); | 1713 | lock_rcu_walk(); |
1668 | rcu_read_lock(); | ||
1669 | set_root_rcu(nd); | 1714 | set_root_rcu(nd); |
1670 | } else { | 1715 | } else { |
1671 | set_root(nd); | 1716 | set_root(nd); |
@@ -1677,8 +1722,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
1677 | struct fs_struct *fs = current->fs; | 1722 | struct fs_struct *fs = current->fs; |
1678 | unsigned seq; | 1723 | unsigned seq; |
1679 | 1724 | ||
1680 | br_read_lock(&vfsmount_lock); | 1725 | lock_rcu_walk(); |
1681 | rcu_read_lock(); | ||
1682 | 1726 | ||
1683 | do { | 1727 | do { |
1684 | seq = read_seqcount_begin(&fs->seq); | 1728 | seq = read_seqcount_begin(&fs->seq); |
@@ -1713,8 +1757,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, | |||
1713 | if (fput_needed) | 1757 | if (fput_needed) |
1714 | *fp = file; | 1758 | *fp = file; |
1715 | nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); | 1759 | nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq); |
1716 | br_read_lock(&vfsmount_lock); | 1760 | lock_rcu_walk(); |
1717 | rcu_read_lock(); | ||
1718 | } else { | 1761 | } else { |
1719 | path_get(&file->f_path); | 1762 | path_get(&file->f_path); |
1720 | fput_light(file, fput_needed); | 1763 | fput_light(file, fput_needed); |
@@ -1777,8 +1820,9 @@ static int path_lookupat(int dfd, const char *name, | |||
1777 | struct path link = path; | 1820 | struct path link = path; |
1778 | nd->flags |= LOOKUP_PARENT; | 1821 | nd->flags |= LOOKUP_PARENT; |
1779 | err = follow_link(&link, nd, &cookie); | 1822 | err = follow_link(&link, nd, &cookie); |
1780 | if (!err) | 1823 | if (err) |
1781 | err = lookup_last(nd, &path); | 1824 | break; |
1825 | err = lookup_last(nd, &path); | ||
1782 | put_link(nd, &link, cookie); | 1826 | put_link(nd, &link, cookie); |
1783 | } | 1827 | } |
1784 | } | 1828 | } |
@@ -1821,9 +1865,27 @@ static int do_path_lookup(int dfd, const char *name, | |||
1821 | return retval; | 1865 | return retval; |
1822 | } | 1866 | } |
1823 | 1867 | ||
1824 | int kern_path_parent(const char *name, struct nameidata *nd) | 1868 | /* does lookup, returns the object with parent locked */ |
1869 | struct dentry *kern_path_locked(const char *name, struct path *path) | ||
1825 | { | 1870 | { |
1826 | return do_path_lookup(AT_FDCWD, name, LOOKUP_PARENT, nd); | 1871 | struct nameidata nd; |
1872 | struct dentry *d; | ||
1873 | int err = do_path_lookup(AT_FDCWD, name, LOOKUP_PARENT, &nd); | ||
1874 | if (err) | ||
1875 | return ERR_PTR(err); | ||
1876 | if (nd.last_type != LAST_NORM) { | ||
1877 | path_put(&nd.path); | ||
1878 | return ERR_PTR(-EINVAL); | ||
1879 | } | ||
1880 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); | ||
1881 | d = __lookup_hash(&nd.last, nd.path.dentry, 0); | ||
1882 | if (IS_ERR(d)) { | ||
1883 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | ||
1884 | path_put(&nd.path); | ||
1885 | return d; | ||
1886 | } | ||
1887 | *path = nd.path; | ||
1888 | return d; | ||
1827 | } | 1889 | } |
1828 | 1890 | ||
1829 | int kern_path(const char *name, unsigned int flags, struct path *path) | 1891 | int kern_path(const char *name, unsigned int flags, struct path *path) |
@@ -1866,7 +1928,7 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, | |||
1866 | */ | 1928 | */ |
1867 | static struct dentry *lookup_hash(struct nameidata *nd) | 1929 | static struct dentry *lookup_hash(struct nameidata *nd) |
1868 | { | 1930 | { |
1869 | return __lookup_hash(&nd->last, nd->path.dentry, nd); | 1931 | return __lookup_hash(&nd->last, nd->path.dentry, nd->flags); |
1870 | } | 1932 | } |
1871 | 1933 | ||
1872 | /** | 1934 | /** |
@@ -1913,7 +1975,7 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) | |||
1913 | if (err) | 1975 | if (err) |
1914 | return ERR_PTR(err); | 1976 | return ERR_PTR(err); |
1915 | 1977 | ||
1916 | return __lookup_hash(&this, base, NULL); | 1978 | return __lookup_hash(&this, base, 0); |
1917 | } | 1979 | } |
1918 | 1980 | ||
1919 | int user_path_at_empty(int dfd, const char __user *name, unsigned flags, | 1981 | int user_path_at_empty(int dfd, const char __user *name, unsigned flags, |
@@ -2086,10 +2148,9 @@ void unlock_rename(struct dentry *p1, struct dentry *p2) | |||
2086 | } | 2148 | } |
2087 | 2149 | ||
2088 | int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 2150 | int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
2089 | struct nameidata *nd) | 2151 | bool want_excl) |
2090 | { | 2152 | { |
2091 | int error = may_create(dir, dentry); | 2153 | int error = may_create(dir, dentry); |
2092 | |||
2093 | if (error) | 2154 | if (error) |
2094 | return error; | 2155 | return error; |
2095 | 2156 | ||
@@ -2100,7 +2161,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
2100 | error = security_inode_create(dir, dentry, mode); | 2161 | error = security_inode_create(dir, dentry, mode); |
2101 | if (error) | 2162 | if (error) |
2102 | return error; | 2163 | return error; |
2103 | error = dir->i_op->create(dir, dentry, mode, nd); | 2164 | error = dir->i_op->create(dir, dentry, mode, want_excl); |
2104 | if (!error) | 2165 | if (!error) |
2105 | fsnotify_create(dir, dentry); | 2166 | fsnotify_create(dir, dentry); |
2106 | return error; | 2167 | return error; |
@@ -2187,21 +2248,275 @@ static inline int open_to_namei_flags(int flag) | |||
2187 | return flag; | 2248 | return flag; |
2188 | } | 2249 | } |
2189 | 2250 | ||
2251 | static int may_o_create(struct path *dir, struct dentry *dentry, umode_t mode) | ||
2252 | { | ||
2253 | int error = security_path_mknod(dir, dentry, mode, 0); | ||
2254 | if (error) | ||
2255 | return error; | ||
2256 | |||
2257 | error = inode_permission(dir->dentry->d_inode, MAY_WRITE | MAY_EXEC); | ||
2258 | if (error) | ||
2259 | return error; | ||
2260 | |||
2261 | return security_inode_create(dir->dentry->d_inode, dentry, mode); | ||
2262 | } | ||
2263 | |||
2190 | /* | 2264 | /* |
2191 | * Handle the last step of open() | 2265 | * Attempt to atomically look up, create and open a file from a negative |
2266 | * dentry. | ||
2267 | * | ||
2268 | * Returns 0 if successful. The file will have been created and attached to | ||
2269 | * @file by the filesystem calling finish_open(). | ||
2270 | * | ||
2271 | * Returns 1 if the file was looked up only or didn't need creating. The | ||
2272 | * caller will need to perform the open themselves. @path will have been | ||
2273 | * updated to point to the new dentry. This may be negative. | ||
2274 | * | ||
2275 | * Returns an error code otherwise. | ||
2276 | */ | ||
2277 | static int atomic_open(struct nameidata *nd, struct dentry *dentry, | ||
2278 | struct path *path, struct file *file, | ||
2279 | const struct open_flags *op, | ||
2280 | bool *want_write, bool need_lookup, | ||
2281 | int *opened) | ||
2282 | { | ||
2283 | struct inode *dir = nd->path.dentry->d_inode; | ||
2284 | unsigned open_flag = open_to_namei_flags(op->open_flag); | ||
2285 | umode_t mode; | ||
2286 | int error; | ||
2287 | int acc_mode; | ||
2288 | int create_error = 0; | ||
2289 | struct dentry *const DENTRY_NOT_SET = (void *) -1UL; | ||
2290 | |||
2291 | BUG_ON(dentry->d_inode); | ||
2292 | |||
2293 | /* Don't create child dentry for a dead directory. */ | ||
2294 | if (unlikely(IS_DEADDIR(dir))) { | ||
2295 | error = -ENOENT; | ||
2296 | goto out; | ||
2297 | } | ||
2298 | |||
2299 | mode = op->mode & S_IALLUGO; | ||
2300 | if ((open_flag & O_CREAT) && !IS_POSIXACL(dir)) | ||
2301 | mode &= ~current_umask(); | ||
2302 | |||
2303 | if (open_flag & O_EXCL) { | ||
2304 | open_flag &= ~O_TRUNC; | ||
2305 | *opened |= FILE_CREATED; | ||
2306 | } | ||
2307 | |||
2308 | /* | ||
2309 | * Checking write permission is tricky, bacuse we don't know if we are | ||
2310 | * going to actually need it: O_CREAT opens should work as long as the | ||
2311 | * file exists. But checking existence breaks atomicity. The trick is | ||
2312 | * to check access and if not granted clear O_CREAT from the flags. | ||
2313 | * | ||
2314 | * Another problem is returing the "right" error value (e.g. for an | ||
2315 | * O_EXCL open we want to return EEXIST not EROFS). | ||
2316 | */ | ||
2317 | if ((open_flag & (O_CREAT | O_TRUNC)) || | ||
2318 | (open_flag & O_ACCMODE) != O_RDONLY) { | ||
2319 | error = mnt_want_write(nd->path.mnt); | ||
2320 | if (!error) { | ||
2321 | *want_write = true; | ||
2322 | } else if (!(open_flag & O_CREAT)) { | ||
2323 | /* | ||
2324 | * No O_CREATE -> atomicity not a requirement -> fall | ||
2325 | * back to lookup + open | ||
2326 | */ | ||
2327 | goto no_open; | ||
2328 | } else if (open_flag & (O_EXCL | O_TRUNC)) { | ||
2329 | /* Fall back and fail with the right error */ | ||
2330 | create_error = error; | ||
2331 | goto no_open; | ||
2332 | } else { | ||
2333 | /* No side effects, safe to clear O_CREAT */ | ||
2334 | create_error = error; | ||
2335 | open_flag &= ~O_CREAT; | ||
2336 | } | ||
2337 | } | ||
2338 | |||
2339 | if (open_flag & O_CREAT) { | ||
2340 | error = may_o_create(&nd->path, dentry, op->mode); | ||
2341 | if (error) { | ||
2342 | create_error = error; | ||
2343 | if (open_flag & O_EXCL) | ||
2344 | goto no_open; | ||
2345 | open_flag &= ~O_CREAT; | ||
2346 | } | ||
2347 | } | ||
2348 | |||
2349 | if (nd->flags & LOOKUP_DIRECTORY) | ||
2350 | open_flag |= O_DIRECTORY; | ||
2351 | |||
2352 | file->f_path.dentry = DENTRY_NOT_SET; | ||
2353 | file->f_path.mnt = nd->path.mnt; | ||
2354 | error = dir->i_op->atomic_open(dir, dentry, file, open_flag, mode, | ||
2355 | opened); | ||
2356 | if (error < 0) { | ||
2357 | if (create_error && error == -ENOENT) | ||
2358 | error = create_error; | ||
2359 | goto out; | ||
2360 | } | ||
2361 | |||
2362 | acc_mode = op->acc_mode; | ||
2363 | if (*opened & FILE_CREATED) { | ||
2364 | fsnotify_create(dir, dentry); | ||
2365 | acc_mode = MAY_OPEN; | ||
2366 | } | ||
2367 | |||
2368 | if (error) { /* returned 1, that is */ | ||
2369 | if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) { | ||
2370 | error = -EIO; | ||
2371 | goto out; | ||
2372 | } | ||
2373 | if (file->f_path.dentry) { | ||
2374 | dput(dentry); | ||
2375 | dentry = file->f_path.dentry; | ||
2376 | } | ||
2377 | goto looked_up; | ||
2378 | } | ||
2379 | |||
2380 | /* | ||
2381 | * We didn't have the inode before the open, so check open permission | ||
2382 | * here. | ||
2383 | */ | ||
2384 | error = may_open(&file->f_path, acc_mode, open_flag); | ||
2385 | if (error) | ||
2386 | fput(file); | ||
2387 | |||
2388 | out: | ||
2389 | dput(dentry); | ||
2390 | return error; | ||
2391 | |||
2392 | no_open: | ||
2393 | if (need_lookup) { | ||
2394 | dentry = lookup_real(dir, dentry, nd->flags); | ||
2395 | if (IS_ERR(dentry)) | ||
2396 | return PTR_ERR(dentry); | ||
2397 | |||
2398 | if (create_error) { | ||
2399 | int open_flag = op->open_flag; | ||
2400 | |||
2401 | error = create_error; | ||
2402 | if ((open_flag & O_EXCL)) { | ||
2403 | if (!dentry->d_inode) | ||
2404 | goto out; | ||
2405 | } else if (!dentry->d_inode) { | ||
2406 | goto out; | ||
2407 | } else if ((open_flag & O_TRUNC) && | ||
2408 | S_ISREG(dentry->d_inode->i_mode)) { | ||
2409 | goto out; | ||
2410 | } | ||
2411 | /* will fail later, go on to get the right error */ | ||
2412 | } | ||
2413 | } | ||
2414 | looked_up: | ||
2415 | path->dentry = dentry; | ||
2416 | path->mnt = nd->path.mnt; | ||
2417 | return 1; | ||
2418 | } | ||
2419 | |||
2420 | /* | ||
2421 | * Look up and maybe create and open the last component. | ||
2422 | * | ||
2423 | * Must be called with i_mutex held on parent. | ||
2424 | * | ||
2425 | * Returns 0 if the file was successfully atomically created (if necessary) and | ||
2426 | * opened. In this case the file will be returned attached to @file. | ||
2427 | * | ||
2428 | * Returns 1 if the file was not completely opened at this time, though lookups | ||
2429 | * and creations will have been performed and the dentry returned in @path will | ||
2430 | * be positive upon return if O_CREAT was specified. If O_CREAT wasn't | ||
2431 | * specified then a negative dentry may be returned. | ||
2432 | * | ||
2433 | * An error code is returned otherwise. | ||
2434 | * | ||
2435 | * FILE_CREATE will be set in @*opened if the dentry was created and will be | ||
2436 | * cleared otherwise prior to returning. | ||
2192 | */ | 2437 | */ |
2193 | static struct file *do_last(struct nameidata *nd, struct path *path, | 2438 | static int lookup_open(struct nameidata *nd, struct path *path, |
2194 | const struct open_flags *op, const char *pathname) | 2439 | struct file *file, |
2440 | const struct open_flags *op, | ||
2441 | bool *want_write, int *opened) | ||
2195 | { | 2442 | { |
2196 | struct dentry *dir = nd->path.dentry; | 2443 | struct dentry *dir = nd->path.dentry; |
2444 | struct inode *dir_inode = dir->d_inode; | ||
2197 | struct dentry *dentry; | 2445 | struct dentry *dentry; |
2446 | int error; | ||
2447 | bool need_lookup; | ||
2448 | |||
2449 | *opened &= ~FILE_CREATED; | ||
2450 | dentry = lookup_dcache(&nd->last, dir, nd->flags, &need_lookup); | ||
2451 | if (IS_ERR(dentry)) | ||
2452 | return PTR_ERR(dentry); | ||
2453 | |||
2454 | /* Cached positive dentry: will open in f_op->open */ | ||
2455 | if (!need_lookup && dentry->d_inode) | ||
2456 | goto out_no_open; | ||
2457 | |||
2458 | if ((nd->flags & LOOKUP_OPEN) && dir_inode->i_op->atomic_open) { | ||
2459 | return atomic_open(nd, dentry, path, file, op, want_write, | ||
2460 | need_lookup, opened); | ||
2461 | } | ||
2462 | |||
2463 | if (need_lookup) { | ||
2464 | BUG_ON(dentry->d_inode); | ||
2465 | |||
2466 | dentry = lookup_real(dir_inode, dentry, nd->flags); | ||
2467 | if (IS_ERR(dentry)) | ||
2468 | return PTR_ERR(dentry); | ||
2469 | } | ||
2470 | |||
2471 | /* Negative dentry, just create the file */ | ||
2472 | if (!dentry->d_inode && (op->open_flag & O_CREAT)) { | ||
2473 | umode_t mode = op->mode; | ||
2474 | if (!IS_POSIXACL(dir->d_inode)) | ||
2475 | mode &= ~current_umask(); | ||
2476 | /* | ||
2477 | * This write is needed to ensure that a | ||
2478 | * rw->ro transition does not occur between | ||
2479 | * the time when the file is created and when | ||
2480 | * a permanent write count is taken through | ||
2481 | * the 'struct file' in finish_open(). | ||
2482 | */ | ||
2483 | error = mnt_want_write(nd->path.mnt); | ||
2484 | if (error) | ||
2485 | goto out_dput; | ||
2486 | *want_write = true; | ||
2487 | *opened |= FILE_CREATED; | ||
2488 | error = security_path_mknod(&nd->path, dentry, mode, 0); | ||
2489 | if (error) | ||
2490 | goto out_dput; | ||
2491 | error = vfs_create(dir->d_inode, dentry, mode, | ||
2492 | nd->flags & LOOKUP_EXCL); | ||
2493 | if (error) | ||
2494 | goto out_dput; | ||
2495 | } | ||
2496 | out_no_open: | ||
2497 | path->dentry = dentry; | ||
2498 | path->mnt = nd->path.mnt; | ||
2499 | return 1; | ||
2500 | |||
2501 | out_dput: | ||
2502 | dput(dentry); | ||
2503 | return error; | ||
2504 | } | ||
2505 | |||
2506 | /* | ||
2507 | * Handle the last step of open() | ||
2508 | */ | ||
2509 | static int do_last(struct nameidata *nd, struct path *path, | ||
2510 | struct file *file, const struct open_flags *op, | ||
2511 | int *opened, const char *pathname) | ||
2512 | { | ||
2513 | struct dentry *dir = nd->path.dentry; | ||
2198 | int open_flag = op->open_flag; | 2514 | int open_flag = op->open_flag; |
2199 | int will_truncate = open_flag & O_TRUNC; | 2515 | bool will_truncate = (open_flag & O_TRUNC) != 0; |
2200 | int want_write = 0; | 2516 | bool want_write = false; |
2201 | int acc_mode = op->acc_mode; | 2517 | int acc_mode = op->acc_mode; |
2202 | struct file *filp; | ||
2203 | struct inode *inode; | 2518 | struct inode *inode; |
2204 | int symlink_ok = 0; | 2519 | bool symlink_ok = false; |
2205 | struct path save_parent = { .dentry = NULL, .mnt = NULL }; | 2520 | struct path save_parent = { .dentry = NULL, .mnt = NULL }; |
2206 | bool retried = false; | 2521 | bool retried = false; |
2207 | int error; | 2522 | int error; |
@@ -2214,112 +2529,99 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
2214 | case LAST_DOT: | 2529 | case LAST_DOT: |
2215 | error = handle_dots(nd, nd->last_type); | 2530 | error = handle_dots(nd, nd->last_type); |
2216 | if (error) | 2531 | if (error) |
2217 | return ERR_PTR(error); | 2532 | return error; |
2218 | /* fallthrough */ | 2533 | /* fallthrough */ |
2219 | case LAST_ROOT: | 2534 | case LAST_ROOT: |
2220 | error = complete_walk(nd); | 2535 | error = complete_walk(nd); |
2221 | if (error) | 2536 | if (error) |
2222 | return ERR_PTR(error); | 2537 | return error; |
2223 | audit_inode(pathname, nd->path.dentry); | 2538 | audit_inode(pathname, nd->path.dentry); |
2224 | if (open_flag & O_CREAT) { | 2539 | if (open_flag & O_CREAT) { |
2225 | error = -EISDIR; | 2540 | error = -EISDIR; |
2226 | goto exit; | 2541 | goto out; |
2227 | } | 2542 | } |
2228 | goto ok; | 2543 | goto finish_open; |
2229 | case LAST_BIND: | 2544 | case LAST_BIND: |
2230 | error = complete_walk(nd); | 2545 | error = complete_walk(nd); |
2231 | if (error) | 2546 | if (error) |
2232 | return ERR_PTR(error); | 2547 | return error; |
2233 | audit_inode(pathname, dir); | 2548 | audit_inode(pathname, dir); |
2234 | goto ok; | 2549 | goto finish_open; |
2235 | } | 2550 | } |
2236 | 2551 | ||
2237 | if (!(open_flag & O_CREAT)) { | 2552 | if (!(open_flag & O_CREAT)) { |
2238 | if (nd->last.name[nd->last.len]) | 2553 | if (nd->last.name[nd->last.len]) |
2239 | nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; | 2554 | nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY; |
2240 | if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW)) | 2555 | if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW)) |
2241 | symlink_ok = 1; | 2556 | symlink_ok = true; |
2242 | /* we _can_ be in RCU mode here */ | 2557 | /* we _can_ be in RCU mode here */ |
2243 | error = lookup_fast(nd, &nd->last, path, &inode); | 2558 | error = lookup_fast(nd, &nd->last, path, &inode); |
2244 | if (unlikely(error)) { | 2559 | if (likely(!error)) |
2245 | if (error < 0) | 2560 | goto finish_lookup; |
2246 | goto exit; | ||
2247 | 2561 | ||
2248 | error = lookup_slow(nd, &nd->last, path); | 2562 | if (error < 0) |
2249 | if (error < 0) | 2563 | goto out; |
2250 | goto exit; | ||
2251 | 2564 | ||
2252 | inode = path->dentry->d_inode; | 2565 | BUG_ON(nd->inode != dir->d_inode); |
2253 | } | 2566 | } else { |
2254 | goto finish_lookup; | 2567 | /* create side of things */ |
2255 | } | 2568 | /* |
2256 | 2569 | * This will *only* deal with leaving RCU mode - LOOKUP_JUMPED | |
2257 | /* create side of things */ | 2570 | * has been cleared when we got to the last component we are |
2258 | /* | 2571 | * about to look up |
2259 | * This will *only* deal with leaving RCU mode - LOOKUP_JUMPED has been | 2572 | */ |
2260 | * cleared when we got to the last component we are about to look up | 2573 | error = complete_walk(nd); |
2261 | */ | 2574 | if (error) |
2262 | error = complete_walk(nd); | 2575 | return error; |
2263 | if (error) | ||
2264 | return ERR_PTR(error); | ||
2265 | 2576 | ||
2266 | audit_inode(pathname, dir); | 2577 | audit_inode(pathname, dir); |
2267 | error = -EISDIR; | 2578 | error = -EISDIR; |
2268 | /* trailing slashes? */ | 2579 | /* trailing slashes? */ |
2269 | if (nd->last.name[nd->last.len]) | 2580 | if (nd->last.name[nd->last.len]) |
2270 | goto exit; | 2581 | goto out; |
2582 | } | ||
2271 | 2583 | ||
2272 | retry_lookup: | 2584 | retry_lookup: |
2273 | mutex_lock(&dir->d_inode->i_mutex); | 2585 | mutex_lock(&dir->d_inode->i_mutex); |
2586 | error = lookup_open(nd, path, file, op, &want_write, opened); | ||
2587 | mutex_unlock(&dir->d_inode->i_mutex); | ||
2274 | 2588 | ||
2275 | dentry = lookup_hash(nd); | 2589 | if (error <= 0) { |
2276 | error = PTR_ERR(dentry); | 2590 | if (error) |
2277 | if (IS_ERR(dentry)) { | 2591 | goto out; |
2278 | mutex_unlock(&dir->d_inode->i_mutex); | ||
2279 | goto exit; | ||
2280 | } | ||
2281 | 2592 | ||
2282 | path->dentry = dentry; | 2593 | if ((*opened & FILE_CREATED) || |
2283 | path->mnt = nd->path.mnt; | 2594 | !S_ISREG(file->f_path.dentry->d_inode->i_mode)) |
2595 | will_truncate = false; | ||
2284 | 2596 | ||
2285 | /* Negative dentry, just create the file */ | 2597 | audit_inode(pathname, file->f_path.dentry); |
2286 | if (!dentry->d_inode) { | 2598 | goto opened; |
2287 | umode_t mode = op->mode; | 2599 | } |
2288 | if (!IS_POSIXACL(dir->d_inode)) | 2600 | |
2289 | mode &= ~current_umask(); | 2601 | if (*opened & FILE_CREATED) { |
2290 | /* | ||
2291 | * This write is needed to ensure that a | ||
2292 | * rw->ro transition does not occur between | ||
2293 | * the time when the file is created and when | ||
2294 | * a permanent write count is taken through | ||
2295 | * the 'struct file' in nameidata_to_filp(). | ||
2296 | */ | ||
2297 | error = mnt_want_write(nd->path.mnt); | ||
2298 | if (error) | ||
2299 | goto exit_mutex_unlock; | ||
2300 | want_write = 1; | ||
2301 | /* Don't check for write permission, don't truncate */ | 2602 | /* Don't check for write permission, don't truncate */ |
2302 | open_flag &= ~O_TRUNC; | 2603 | open_flag &= ~O_TRUNC; |
2303 | will_truncate = 0; | 2604 | will_truncate = false; |
2304 | acc_mode = MAY_OPEN; | 2605 | acc_mode = MAY_OPEN; |
2305 | error = security_path_mknod(&nd->path, dentry, mode, 0); | 2606 | path_to_nameidata(path, nd); |
2306 | if (error) | 2607 | goto finish_open_created; |
2307 | goto exit_mutex_unlock; | ||
2308 | error = vfs_create(dir->d_inode, dentry, mode, nd); | ||
2309 | if (error) | ||
2310 | goto exit_mutex_unlock; | ||
2311 | mutex_unlock(&dir->d_inode->i_mutex); | ||
2312 | dput(nd->path.dentry); | ||
2313 | nd->path.dentry = dentry; | ||
2314 | goto common; | ||
2315 | } | 2608 | } |
2316 | 2609 | ||
2317 | /* | 2610 | /* |
2318 | * It already exists. | 2611 | * It already exists. |
2319 | */ | 2612 | */ |
2320 | mutex_unlock(&dir->d_inode->i_mutex); | ||
2321 | audit_inode(pathname, path->dentry); | 2613 | audit_inode(pathname, path->dentry); |
2322 | 2614 | ||
2615 | /* | ||
2616 | * If atomic_open() acquired write access it is dropped now due to | ||
2617 | * possible mount and symlink following (this might be optimized away if | ||
2618 | * necessary...) | ||
2619 | */ | ||
2620 | if (want_write) { | ||
2621 | mnt_drop_write(nd->path.mnt); | ||
2622 | want_write = false; | ||
2623 | } | ||
2624 | |||
2323 | error = -EEXIST; | 2625 | error = -EEXIST; |
2324 | if (open_flag & O_EXCL) | 2626 | if (open_flag & O_EXCL) |
2325 | goto exit_dput; | 2627 | goto exit_dput; |
@@ -2338,18 +2640,18 @@ finish_lookup: | |||
2338 | error = -ENOENT; | 2640 | error = -ENOENT; |
2339 | if (!inode) { | 2641 | if (!inode) { |
2340 | path_to_nameidata(path, nd); | 2642 | path_to_nameidata(path, nd); |
2341 | goto exit; | 2643 | goto out; |
2342 | } | 2644 | } |
2343 | 2645 | ||
2344 | if (should_follow_link(inode, !symlink_ok)) { | 2646 | if (should_follow_link(inode, !symlink_ok)) { |
2345 | if (nd->flags & LOOKUP_RCU) { | 2647 | if (nd->flags & LOOKUP_RCU) { |
2346 | if (unlikely(unlazy_walk(nd, path->dentry))) { | 2648 | if (unlikely(unlazy_walk(nd, path->dentry))) { |
2347 | error = -ECHILD; | 2649 | error = -ECHILD; |
2348 | goto exit; | 2650 | goto out; |
2349 | } | 2651 | } |
2350 | } | 2652 | } |
2351 | BUG_ON(inode != path->dentry->d_inode); | 2653 | BUG_ON(inode != path->dentry->d_inode); |
2352 | return NULL; | 2654 | return 1; |
2353 | } | 2655 | } |
2354 | 2656 | ||
2355 | if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path->mnt) { | 2657 | if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path->mnt) { |
@@ -2365,119 +2667,122 @@ finish_lookup: | |||
2365 | error = complete_walk(nd); | 2667 | error = complete_walk(nd); |
2366 | if (error) { | 2668 | if (error) { |
2367 | path_put(&save_parent); | 2669 | path_put(&save_parent); |
2368 | return ERR_PTR(error); | 2670 | return error; |
2369 | } | 2671 | } |
2370 | error = -EISDIR; | 2672 | error = -EISDIR; |
2371 | if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode)) | 2673 | if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode)) |
2372 | goto exit; | 2674 | goto out; |
2373 | error = -ENOTDIR; | 2675 | error = -ENOTDIR; |
2374 | if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup) | 2676 | if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup) |
2375 | goto exit; | 2677 | goto out; |
2376 | audit_inode(pathname, nd->path.dentry); | 2678 | audit_inode(pathname, nd->path.dentry); |
2377 | ok: | 2679 | finish_open: |
2378 | if (!S_ISREG(nd->inode->i_mode)) | 2680 | if (!S_ISREG(nd->inode->i_mode)) |
2379 | will_truncate = 0; | 2681 | will_truncate = false; |
2380 | 2682 | ||
2381 | if (will_truncate) { | 2683 | if (will_truncate) { |
2382 | error = mnt_want_write(nd->path.mnt); | 2684 | error = mnt_want_write(nd->path.mnt); |
2383 | if (error) | 2685 | if (error) |
2384 | goto exit; | 2686 | goto out; |
2385 | want_write = 1; | 2687 | want_write = true; |
2386 | } | 2688 | } |
2387 | common: | 2689 | finish_open_created: |
2388 | error = may_open(&nd->path, acc_mode, open_flag); | 2690 | error = may_open(&nd->path, acc_mode, open_flag); |
2389 | if (error) | 2691 | if (error) |
2390 | goto exit; | 2692 | goto out; |
2391 | filp = nameidata_to_filp(nd); | 2693 | file->f_path.mnt = nd->path.mnt; |
2392 | if (filp == ERR_PTR(-EOPENSTALE) && save_parent.dentry && !retried) { | 2694 | error = finish_open(file, nd->path.dentry, NULL, opened); |
2393 | BUG_ON(save_parent.dentry != dir); | 2695 | if (error) { |
2394 | path_put(&nd->path); | 2696 | if (error == -EOPENSTALE) |
2395 | nd->path = save_parent; | 2697 | goto stale_open; |
2396 | nd->inode = dir->d_inode; | 2698 | goto out; |
2397 | save_parent.mnt = NULL; | ||
2398 | save_parent.dentry = NULL; | ||
2399 | if (want_write) { | ||
2400 | mnt_drop_write(nd->path.mnt); | ||
2401 | want_write = 0; | ||
2402 | } | ||
2403 | retried = true; | ||
2404 | goto retry_lookup; | ||
2405 | } | ||
2406 | if (!IS_ERR(filp)) { | ||
2407 | error = ima_file_check(filp, op->acc_mode); | ||
2408 | if (error) { | ||
2409 | fput(filp); | ||
2410 | filp = ERR_PTR(error); | ||
2411 | } | ||
2412 | } | 2699 | } |
2413 | if (!IS_ERR(filp)) { | 2700 | opened: |
2414 | if (will_truncate) { | 2701 | error = open_check_o_direct(file); |
2415 | error = handle_truncate(filp); | 2702 | if (error) |
2416 | if (error) { | 2703 | goto exit_fput; |
2417 | fput(filp); | 2704 | error = ima_file_check(file, op->acc_mode); |
2418 | filp = ERR_PTR(error); | 2705 | if (error) |
2419 | } | 2706 | goto exit_fput; |
2420 | } | 2707 | |
2708 | if (will_truncate) { | ||
2709 | error = handle_truncate(file); | ||
2710 | if (error) | ||
2711 | goto exit_fput; | ||
2421 | } | 2712 | } |
2422 | out: | 2713 | out: |
2423 | if (want_write) | 2714 | if (want_write) |
2424 | mnt_drop_write(nd->path.mnt); | 2715 | mnt_drop_write(nd->path.mnt); |
2425 | path_put(&save_parent); | 2716 | path_put(&save_parent); |
2426 | terminate_walk(nd); | 2717 | terminate_walk(nd); |
2427 | return filp; | 2718 | return error; |
2428 | 2719 | ||
2429 | exit_mutex_unlock: | ||
2430 | mutex_unlock(&dir->d_inode->i_mutex); | ||
2431 | exit_dput: | 2720 | exit_dput: |
2432 | path_put_conditional(path, nd); | 2721 | path_put_conditional(path, nd); |
2433 | exit: | ||
2434 | filp = ERR_PTR(error); | ||
2435 | goto out; | 2722 | goto out; |
2723 | exit_fput: | ||
2724 | fput(file); | ||
2725 | goto out; | ||
2726 | |||
2727 | stale_open: | ||
2728 | /* If no saved parent or already retried then can't retry */ | ||
2729 | if (!save_parent.dentry || retried) | ||
2730 | goto out; | ||
2731 | |||
2732 | BUG_ON(save_parent.dentry != dir); | ||
2733 | path_put(&nd->path); | ||
2734 | nd->path = save_parent; | ||
2735 | nd->inode = dir->d_inode; | ||
2736 | save_parent.mnt = NULL; | ||
2737 | save_parent.dentry = NULL; | ||
2738 | if (want_write) { | ||
2739 | mnt_drop_write(nd->path.mnt); | ||
2740 | want_write = false; | ||
2741 | } | ||
2742 | retried = true; | ||
2743 | goto retry_lookup; | ||
2436 | } | 2744 | } |
2437 | 2745 | ||
2438 | static struct file *path_openat(int dfd, const char *pathname, | 2746 | static struct file *path_openat(int dfd, const char *pathname, |
2439 | struct nameidata *nd, const struct open_flags *op, int flags) | 2747 | struct nameidata *nd, const struct open_flags *op, int flags) |
2440 | { | 2748 | { |
2441 | struct file *base = NULL; | 2749 | struct file *base = NULL; |
2442 | struct file *filp; | 2750 | struct file *file; |
2443 | struct path path; | 2751 | struct path path; |
2752 | int opened = 0; | ||
2444 | int error; | 2753 | int error; |
2445 | 2754 | ||
2446 | filp = get_empty_filp(); | 2755 | file = get_empty_filp(); |
2447 | if (!filp) | 2756 | if (!file) |
2448 | return ERR_PTR(-ENFILE); | 2757 | return ERR_PTR(-ENFILE); |
2449 | 2758 | ||
2450 | filp->f_flags = op->open_flag; | 2759 | file->f_flags = op->open_flag; |
2451 | nd->intent.open.file = filp; | ||
2452 | nd->intent.open.flags = open_to_namei_flags(op->open_flag); | ||
2453 | nd->intent.open.create_mode = op->mode; | ||
2454 | 2760 | ||
2455 | error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base); | 2761 | error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base); |
2456 | if (unlikely(error)) | 2762 | if (unlikely(error)) |
2457 | goto out_filp; | 2763 | goto out; |
2458 | 2764 | ||
2459 | current->total_link_count = 0; | 2765 | current->total_link_count = 0; |
2460 | error = link_path_walk(pathname, nd); | 2766 | error = link_path_walk(pathname, nd); |
2461 | if (unlikely(error)) | 2767 | if (unlikely(error)) |
2462 | goto out_filp; | 2768 | goto out; |
2463 | 2769 | ||
2464 | filp = do_last(nd, &path, op, pathname); | 2770 | error = do_last(nd, &path, file, op, &opened, pathname); |
2465 | while (unlikely(!filp)) { /* trailing symlink */ | 2771 | while (unlikely(error > 0)) { /* trailing symlink */ |
2466 | struct path link = path; | 2772 | struct path link = path; |
2467 | void *cookie; | 2773 | void *cookie; |
2468 | if (!(nd->flags & LOOKUP_FOLLOW)) { | 2774 | if (!(nd->flags & LOOKUP_FOLLOW)) { |
2469 | path_put_conditional(&path, nd); | 2775 | path_put_conditional(&path, nd); |
2470 | path_put(&nd->path); | 2776 | path_put(&nd->path); |
2471 | filp = ERR_PTR(-ELOOP); | 2777 | error = -ELOOP; |
2472 | break; | 2778 | break; |
2473 | } | 2779 | } |
2474 | nd->flags |= LOOKUP_PARENT; | 2780 | nd->flags |= LOOKUP_PARENT; |
2475 | nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL); | 2781 | nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL); |
2476 | error = follow_link(&link, nd, &cookie); | 2782 | error = follow_link(&link, nd, &cookie); |
2477 | if (unlikely(error)) | 2783 | if (unlikely(error)) |
2478 | filp = ERR_PTR(error); | 2784 | break; |
2479 | else | 2785 | error = do_last(nd, &path, file, op, &opened, pathname); |
2480 | filp = do_last(nd, &path, op, pathname); | ||
2481 | put_link(nd, &link, cookie); | 2786 | put_link(nd, &link, cookie); |
2482 | } | 2787 | } |
2483 | out: | 2788 | out: |
@@ -2485,18 +2790,20 @@ out: | |||
2485 | path_put(&nd->root); | 2790 | path_put(&nd->root); |
2486 | if (base) | 2791 | if (base) |
2487 | fput(base); | 2792 | fput(base); |
2488 | release_open_intent(nd); | 2793 | if (!(opened & FILE_OPENED)) { |
2489 | if (filp == ERR_PTR(-EOPENSTALE)) { | 2794 | BUG_ON(!error); |
2490 | if (flags & LOOKUP_RCU) | 2795 | put_filp(file); |
2491 | filp = ERR_PTR(-ECHILD); | ||
2492 | else | ||
2493 | filp = ERR_PTR(-ESTALE); | ||
2494 | } | 2796 | } |
2495 | return filp; | 2797 | if (unlikely(error)) { |
2496 | 2798 | if (error == -EOPENSTALE) { | |
2497 | out_filp: | 2799 | if (flags & LOOKUP_RCU) |
2498 | filp = ERR_PTR(error); | 2800 | error = -ECHILD; |
2499 | goto out; | 2801 | else |
2802 | error = -ESTALE; | ||
2803 | } | ||
2804 | file = ERR_PTR(error); | ||
2805 | } | ||
2806 | return file; | ||
2500 | } | 2807 | } |
2501 | 2808 | ||
2502 | struct file *do_filp_open(int dfd, const char *pathname, | 2809 | struct file *do_filp_open(int dfd, const char *pathname, |
@@ -2551,7 +2858,6 @@ struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path | |||
2551 | goto out; | 2858 | goto out; |
2552 | nd.flags &= ~LOOKUP_PARENT; | 2859 | nd.flags &= ~LOOKUP_PARENT; |
2553 | nd.flags |= LOOKUP_CREATE | LOOKUP_EXCL; | 2860 | nd.flags |= LOOKUP_CREATE | LOOKUP_EXCL; |
2554 | nd.intent.open.flags = O_EXCL; | ||
2555 | 2861 | ||
2556 | /* | 2862 | /* |
2557 | * Do the final lookup. | 2863 | * Do the final lookup. |
@@ -2670,7 +2976,7 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode, | |||
2670 | goto out_drop_write; | 2976 | goto out_drop_write; |
2671 | switch (mode & S_IFMT) { | 2977 | switch (mode & S_IFMT) { |
2672 | case 0: case S_IFREG: | 2978 | case 0: case S_IFREG: |
2673 | error = vfs_create(path.dentry->d_inode,dentry,mode,NULL); | 2979 | error = vfs_create(path.dentry->d_inode,dentry,mode,true); |
2674 | break; | 2980 | break; |
2675 | case S_IFCHR: case S_IFBLK: | 2981 | case S_IFCHR: case S_IFBLK: |
2676 | error = vfs_mknod(path.dentry->d_inode,dentry,mode, | 2982 | error = vfs_mknod(path.dentry->d_inode,dentry,mode, |
diff --git a/fs/namespace.c b/fs/namespace.c index 1e4a5fe3d7b7..c53d3381b0d0 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -515,8 +515,20 @@ struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry, | |||
515 | } | 515 | } |
516 | 516 | ||
517 | /* | 517 | /* |
518 | * lookup_mnt increments the ref count before returning | 518 | * lookup_mnt - Return the first child mount mounted at path |
519 | * the vfsmount struct. | 519 | * |
520 | * "First" means first mounted chronologically. If you create the | ||
521 | * following mounts: | ||
522 | * | ||
523 | * mount /dev/sda1 /mnt | ||
524 | * mount /dev/sda2 /mnt | ||
525 | * mount /dev/sda3 /mnt | ||
526 | * | ||
527 | * Then lookup_mnt() on the base /mnt dentry in the root mount will | ||
528 | * return successively the root dentry and vfsmount of /dev/sda1, then | ||
529 | * /dev/sda2, then /dev/sda3, then NULL. | ||
530 | * | ||
531 | * lookup_mnt takes a reference to the found vfsmount. | ||
520 | */ | 532 | */ |
521 | struct vfsmount *lookup_mnt(struct path *path) | 533 | struct vfsmount *lookup_mnt(struct path *path) |
522 | { | 534 | { |
@@ -621,21 +633,6 @@ static void attach_mnt(struct mount *mnt, struct path *path) | |||
621 | list_add_tail(&mnt->mnt_child, &real_mount(path->mnt)->mnt_mounts); | 633 | list_add_tail(&mnt->mnt_child, &real_mount(path->mnt)->mnt_mounts); |
622 | } | 634 | } |
623 | 635 | ||
624 | static inline void __mnt_make_longterm(struct mount *mnt) | ||
625 | { | ||
626 | #ifdef CONFIG_SMP | ||
627 | atomic_inc(&mnt->mnt_longterm); | ||
628 | #endif | ||
629 | } | ||
630 | |||
631 | /* needs vfsmount lock for write */ | ||
632 | static inline void __mnt_make_shortterm(struct mount *mnt) | ||
633 | { | ||
634 | #ifdef CONFIG_SMP | ||
635 | atomic_dec(&mnt->mnt_longterm); | ||
636 | #endif | ||
637 | } | ||
638 | |||
639 | /* | 636 | /* |
640 | * vfsmount lock must be held for write | 637 | * vfsmount lock must be held for write |
641 | */ | 638 | */ |
@@ -649,10 +646,8 @@ static void commit_tree(struct mount *mnt) | |||
649 | BUG_ON(parent == mnt); | 646 | BUG_ON(parent == mnt); |
650 | 647 | ||
651 | list_add_tail(&head, &mnt->mnt_list); | 648 | list_add_tail(&head, &mnt->mnt_list); |
652 | list_for_each_entry(m, &head, mnt_list) { | 649 | list_for_each_entry(m, &head, mnt_list) |
653 | m->mnt_ns = n; | 650 | m->mnt_ns = n; |
654 | __mnt_make_longterm(m); | ||
655 | } | ||
656 | 651 | ||
657 | list_splice(&head, n->list.prev); | 652 | list_splice(&head, n->list.prev); |
658 | 653 | ||
@@ -725,56 +720,60 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, | |||
725 | int flag) | 720 | int flag) |
726 | { | 721 | { |
727 | struct super_block *sb = old->mnt.mnt_sb; | 722 | struct super_block *sb = old->mnt.mnt_sb; |
728 | struct mount *mnt = alloc_vfsmnt(old->mnt_devname); | 723 | struct mount *mnt; |
724 | int err; | ||
729 | 725 | ||
730 | if (mnt) { | 726 | mnt = alloc_vfsmnt(old->mnt_devname); |
731 | if (flag & (CL_SLAVE | CL_PRIVATE)) | 727 | if (!mnt) |
732 | mnt->mnt_group_id = 0; /* not a peer of original */ | 728 | return ERR_PTR(-ENOMEM); |
733 | else | ||
734 | mnt->mnt_group_id = old->mnt_group_id; | ||
735 | |||
736 | if ((flag & CL_MAKE_SHARED) && !mnt->mnt_group_id) { | ||
737 | int err = mnt_alloc_group_id(mnt); | ||
738 | if (err) | ||
739 | goto out_free; | ||
740 | } | ||
741 | 729 | ||
742 | mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~MNT_WRITE_HOLD; | 730 | if (flag & (CL_SLAVE | CL_PRIVATE)) |
743 | atomic_inc(&sb->s_active); | 731 | mnt->mnt_group_id = 0; /* not a peer of original */ |
744 | mnt->mnt.mnt_sb = sb; | 732 | else |
745 | mnt->mnt.mnt_root = dget(root); | 733 | mnt->mnt_group_id = old->mnt_group_id; |
746 | mnt->mnt_mountpoint = mnt->mnt.mnt_root; | ||
747 | mnt->mnt_parent = mnt; | ||
748 | br_write_lock(&vfsmount_lock); | ||
749 | list_add_tail(&mnt->mnt_instance, &sb->s_mounts); | ||
750 | br_write_unlock(&vfsmount_lock); | ||
751 | 734 | ||
752 | if (flag & CL_SLAVE) { | 735 | if ((flag & CL_MAKE_SHARED) && !mnt->mnt_group_id) { |
753 | list_add(&mnt->mnt_slave, &old->mnt_slave_list); | 736 | err = mnt_alloc_group_id(mnt); |
754 | mnt->mnt_master = old; | 737 | if (err) |
755 | CLEAR_MNT_SHARED(mnt); | 738 | goto out_free; |
756 | } else if (!(flag & CL_PRIVATE)) { | ||
757 | if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old)) | ||
758 | list_add(&mnt->mnt_share, &old->mnt_share); | ||
759 | if (IS_MNT_SLAVE(old)) | ||
760 | list_add(&mnt->mnt_slave, &old->mnt_slave); | ||
761 | mnt->mnt_master = old->mnt_master; | ||
762 | } | ||
763 | if (flag & CL_MAKE_SHARED) | ||
764 | set_mnt_shared(mnt); | ||
765 | |||
766 | /* stick the duplicate mount on the same expiry list | ||
767 | * as the original if that was on one */ | ||
768 | if (flag & CL_EXPIRE) { | ||
769 | if (!list_empty(&old->mnt_expire)) | ||
770 | list_add(&mnt->mnt_expire, &old->mnt_expire); | ||
771 | } | ||
772 | } | 739 | } |
740 | |||
741 | mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~MNT_WRITE_HOLD; | ||
742 | atomic_inc(&sb->s_active); | ||
743 | mnt->mnt.mnt_sb = sb; | ||
744 | mnt->mnt.mnt_root = dget(root); | ||
745 | mnt->mnt_mountpoint = mnt->mnt.mnt_root; | ||
746 | mnt->mnt_parent = mnt; | ||
747 | br_write_lock(&vfsmount_lock); | ||
748 | list_add_tail(&mnt->mnt_instance, &sb->s_mounts); | ||
749 | br_write_unlock(&vfsmount_lock); | ||
750 | |||
751 | if (flag & CL_SLAVE) { | ||
752 | list_add(&mnt->mnt_slave, &old->mnt_slave_list); | ||
753 | mnt->mnt_master = old; | ||
754 | CLEAR_MNT_SHARED(mnt); | ||
755 | } else if (!(flag & CL_PRIVATE)) { | ||
756 | if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old)) | ||
757 | list_add(&mnt->mnt_share, &old->mnt_share); | ||
758 | if (IS_MNT_SLAVE(old)) | ||
759 | list_add(&mnt->mnt_slave, &old->mnt_slave); | ||
760 | mnt->mnt_master = old->mnt_master; | ||
761 | } | ||
762 | if (flag & CL_MAKE_SHARED) | ||
763 | set_mnt_shared(mnt); | ||
764 | |||
765 | /* stick the duplicate mount on the same expiry list | ||
766 | * as the original if that was on one */ | ||
767 | if (flag & CL_EXPIRE) { | ||
768 | if (!list_empty(&old->mnt_expire)) | ||
769 | list_add(&mnt->mnt_expire, &old->mnt_expire); | ||
770 | } | ||
771 | |||
773 | return mnt; | 772 | return mnt; |
774 | 773 | ||
775 | out_free: | 774 | out_free: |
776 | free_vfsmnt(mnt); | 775 | free_vfsmnt(mnt); |
777 | return NULL; | 776 | return ERR_PTR(err); |
778 | } | 777 | } |
779 | 778 | ||
780 | static inline void mntfree(struct mount *mnt) | 779 | static inline void mntfree(struct mount *mnt) |
@@ -804,7 +803,8 @@ static void mntput_no_expire(struct mount *mnt) | |||
804 | put_again: | 803 | put_again: |
805 | #ifdef CONFIG_SMP | 804 | #ifdef CONFIG_SMP |
806 | br_read_lock(&vfsmount_lock); | 805 | br_read_lock(&vfsmount_lock); |
807 | if (likely(atomic_read(&mnt->mnt_longterm))) { | 806 | if (likely(mnt->mnt_ns)) { |
807 | /* shouldn't be the last one */ | ||
808 | mnt_add_count(mnt, -1); | 808 | mnt_add_count(mnt, -1); |
809 | br_read_unlock(&vfsmount_lock); | 809 | br_read_unlock(&vfsmount_lock); |
810 | return; | 810 | return; |
@@ -939,7 +939,7 @@ EXPORT_SYMBOL(replace_mount_options); | |||
939 | /* iterator; we want it to have access to namespace_sem, thus here... */ | 939 | /* iterator; we want it to have access to namespace_sem, thus here... */ |
940 | static void *m_start(struct seq_file *m, loff_t *pos) | 940 | static void *m_start(struct seq_file *m, loff_t *pos) |
941 | { | 941 | { |
942 | struct proc_mounts *p = container_of(m, struct proc_mounts, m); | 942 | struct proc_mounts *p = proc_mounts(m); |
943 | 943 | ||
944 | down_read(&namespace_sem); | 944 | down_read(&namespace_sem); |
945 | return seq_list_start(&p->ns->list, *pos); | 945 | return seq_list_start(&p->ns->list, *pos); |
@@ -947,7 +947,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) | |||
947 | 947 | ||
948 | static void *m_next(struct seq_file *m, void *v, loff_t *pos) | 948 | static void *m_next(struct seq_file *m, void *v, loff_t *pos) |
949 | { | 949 | { |
950 | struct proc_mounts *p = container_of(m, struct proc_mounts, m); | 950 | struct proc_mounts *p = proc_mounts(m); |
951 | 951 | ||
952 | return seq_list_next(v, &p->ns->list, pos); | 952 | return seq_list_next(v, &p->ns->list, pos); |
953 | } | 953 | } |
@@ -959,7 +959,7 @@ static void m_stop(struct seq_file *m, void *v) | |||
959 | 959 | ||
960 | static int m_show(struct seq_file *m, void *v) | 960 | static int m_show(struct seq_file *m, void *v) |
961 | { | 961 | { |
962 | struct proc_mounts *p = container_of(m, struct proc_mounts, m); | 962 | struct proc_mounts *p = proc_mounts(m); |
963 | struct mount *r = list_entry(v, struct mount, mnt_list); | 963 | struct mount *r = list_entry(v, struct mount, mnt_list); |
964 | return p->show(m, &r->mnt); | 964 | return p->show(m, &r->mnt); |
965 | } | 965 | } |
@@ -1074,8 +1074,6 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) | |||
1074 | list_del_init(&p->mnt_expire); | 1074 | list_del_init(&p->mnt_expire); |
1075 | list_del_init(&p->mnt_list); | 1075 | list_del_init(&p->mnt_list); |
1076 | __touch_mnt_namespace(p->mnt_ns); | 1076 | __touch_mnt_namespace(p->mnt_ns); |
1077 | if (p->mnt_ns) | ||
1078 | __mnt_make_shortterm(p); | ||
1079 | p->mnt_ns = NULL; | 1077 | p->mnt_ns = NULL; |
1080 | list_del_init(&p->mnt_child); | 1078 | list_del_init(&p->mnt_child); |
1081 | if (mnt_has_parent(p)) { | 1079 | if (mnt_has_parent(p)) { |
@@ -1260,11 +1258,12 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, | |||
1260 | struct path path; | 1258 | struct path path; |
1261 | 1259 | ||
1262 | if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) | 1260 | if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) |
1263 | return NULL; | 1261 | return ERR_PTR(-EINVAL); |
1264 | 1262 | ||
1265 | res = q = clone_mnt(mnt, dentry, flag); | 1263 | res = q = clone_mnt(mnt, dentry, flag); |
1266 | if (!q) | 1264 | if (IS_ERR(q)) |
1267 | goto Enomem; | 1265 | return q; |
1266 | |||
1268 | q->mnt_mountpoint = mnt->mnt_mountpoint; | 1267 | q->mnt_mountpoint = mnt->mnt_mountpoint; |
1269 | 1268 | ||
1270 | p = mnt; | 1269 | p = mnt; |
@@ -1286,8 +1285,8 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, | |||
1286 | path.mnt = &q->mnt; | 1285 | path.mnt = &q->mnt; |
1287 | path.dentry = p->mnt_mountpoint; | 1286 | path.dentry = p->mnt_mountpoint; |
1288 | q = clone_mnt(p, p->mnt.mnt_root, flag); | 1287 | q = clone_mnt(p, p->mnt.mnt_root, flag); |
1289 | if (!q) | 1288 | if (IS_ERR(q)) |
1290 | goto Enomem; | 1289 | goto out; |
1291 | br_write_lock(&vfsmount_lock); | 1290 | br_write_lock(&vfsmount_lock); |
1292 | list_add_tail(&q->mnt_list, &res->mnt_list); | 1291 | list_add_tail(&q->mnt_list, &res->mnt_list); |
1293 | attach_mnt(q, &path); | 1292 | attach_mnt(q, &path); |
@@ -1295,7 +1294,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, | |||
1295 | } | 1294 | } |
1296 | } | 1295 | } |
1297 | return res; | 1296 | return res; |
1298 | Enomem: | 1297 | out: |
1299 | if (res) { | 1298 | if (res) { |
1300 | LIST_HEAD(umount_list); | 1299 | LIST_HEAD(umount_list); |
1301 | br_write_lock(&vfsmount_lock); | 1300 | br_write_lock(&vfsmount_lock); |
@@ -1303,9 +1302,11 @@ Enomem: | |||
1303 | br_write_unlock(&vfsmount_lock); | 1302 | br_write_unlock(&vfsmount_lock); |
1304 | release_mounts(&umount_list); | 1303 | release_mounts(&umount_list); |
1305 | } | 1304 | } |
1306 | return NULL; | 1305 | return q; |
1307 | } | 1306 | } |
1308 | 1307 | ||
1308 | /* Caller should check returned pointer for errors */ | ||
1309 | |||
1309 | struct vfsmount *collect_mounts(struct path *path) | 1310 | struct vfsmount *collect_mounts(struct path *path) |
1310 | { | 1311 | { |
1311 | struct mount *tree; | 1312 | struct mount *tree; |
@@ -1313,7 +1314,9 @@ struct vfsmount *collect_mounts(struct path *path) | |||
1313 | tree = copy_tree(real_mount(path->mnt), path->dentry, | 1314 | tree = copy_tree(real_mount(path->mnt), path->dentry, |
1314 | CL_COPY_ALL | CL_PRIVATE); | 1315 | CL_COPY_ALL | CL_PRIVATE); |
1315 | up_write(&namespace_sem); | 1316 | up_write(&namespace_sem); |
1316 | return tree ? &tree->mnt : NULL; | 1317 | if (IS_ERR(tree)) |
1318 | return NULL; | ||
1319 | return &tree->mnt; | ||
1317 | } | 1320 | } |
1318 | 1321 | ||
1319 | void drop_collected_mounts(struct vfsmount *mnt) | 1322 | void drop_collected_mounts(struct vfsmount *mnt) |
@@ -1608,14 +1611,15 @@ static int do_loopback(struct path *path, char *old_name, | |||
1608 | if (!check_mnt(real_mount(path->mnt)) || !check_mnt(old)) | 1611 | if (!check_mnt(real_mount(path->mnt)) || !check_mnt(old)) |
1609 | goto out2; | 1612 | goto out2; |
1610 | 1613 | ||
1611 | err = -ENOMEM; | ||
1612 | if (recurse) | 1614 | if (recurse) |
1613 | mnt = copy_tree(old, old_path.dentry, 0); | 1615 | mnt = copy_tree(old, old_path.dentry, 0); |
1614 | else | 1616 | else |
1615 | mnt = clone_mnt(old, old_path.dentry, 0); | 1617 | mnt = clone_mnt(old, old_path.dentry, 0); |
1616 | 1618 | ||
1617 | if (!mnt) | 1619 | if (IS_ERR(mnt)) { |
1618 | goto out2; | 1620 | err = PTR_ERR(mnt); |
1621 | goto out; | ||
1622 | } | ||
1619 | 1623 | ||
1620 | err = graft_tree(mnt, path); | 1624 | err = graft_tree(mnt, path); |
1621 | if (err) { | 1625 | if (err) { |
@@ -2209,23 +2213,6 @@ static struct mnt_namespace *alloc_mnt_ns(void) | |||
2209 | return new_ns; | 2213 | return new_ns; |
2210 | } | 2214 | } |
2211 | 2215 | ||
2212 | void mnt_make_longterm(struct vfsmount *mnt) | ||
2213 | { | ||
2214 | __mnt_make_longterm(real_mount(mnt)); | ||
2215 | } | ||
2216 | |||
2217 | void mnt_make_shortterm(struct vfsmount *m) | ||
2218 | { | ||
2219 | #ifdef CONFIG_SMP | ||
2220 | struct mount *mnt = real_mount(m); | ||
2221 | if (atomic_add_unless(&mnt->mnt_longterm, -1, 1)) | ||
2222 | return; | ||
2223 | br_write_lock(&vfsmount_lock); | ||
2224 | atomic_dec(&mnt->mnt_longterm); | ||
2225 | br_write_unlock(&vfsmount_lock); | ||
2226 | #endif | ||
2227 | } | ||
2228 | |||
2229 | /* | 2216 | /* |
2230 | * Allocate a new namespace structure and populate it with contents | 2217 | * Allocate a new namespace structure and populate it with contents |
2231 | * copied from the namespace of the passed in task structure. | 2218 | * copied from the namespace of the passed in task structure. |
@@ -2246,10 +2233,10 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, | |||
2246 | down_write(&namespace_sem); | 2233 | down_write(&namespace_sem); |
2247 | /* First pass: copy the tree topology */ | 2234 | /* First pass: copy the tree topology */ |
2248 | new = copy_tree(old, old->mnt.mnt_root, CL_COPY_ALL | CL_EXPIRE); | 2235 | new = copy_tree(old, old->mnt.mnt_root, CL_COPY_ALL | CL_EXPIRE); |
2249 | if (!new) { | 2236 | if (IS_ERR(new)) { |
2250 | up_write(&namespace_sem); | 2237 | up_write(&namespace_sem); |
2251 | kfree(new_ns); | 2238 | kfree(new_ns); |
2252 | return ERR_PTR(-ENOMEM); | 2239 | return ERR_CAST(new); |
2253 | } | 2240 | } |
2254 | new_ns->root = new; | 2241 | new_ns->root = new; |
2255 | br_write_lock(&vfsmount_lock); | 2242 | br_write_lock(&vfsmount_lock); |
@@ -2265,18 +2252,13 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, | |||
2265 | q = new; | 2252 | q = new; |
2266 | while (p) { | 2253 | while (p) { |
2267 | q->mnt_ns = new_ns; | 2254 | q->mnt_ns = new_ns; |
2268 | __mnt_make_longterm(q); | ||
2269 | if (fs) { | 2255 | if (fs) { |
2270 | if (&p->mnt == fs->root.mnt) { | 2256 | if (&p->mnt == fs->root.mnt) { |
2271 | fs->root.mnt = mntget(&q->mnt); | 2257 | fs->root.mnt = mntget(&q->mnt); |
2272 | __mnt_make_longterm(q); | ||
2273 | mnt_make_shortterm(&p->mnt); | ||
2274 | rootmnt = &p->mnt; | 2258 | rootmnt = &p->mnt; |
2275 | } | 2259 | } |
2276 | if (&p->mnt == fs->pwd.mnt) { | 2260 | if (&p->mnt == fs->pwd.mnt) { |
2277 | fs->pwd.mnt = mntget(&q->mnt); | 2261 | fs->pwd.mnt = mntget(&q->mnt); |
2278 | __mnt_make_longterm(q); | ||
2279 | mnt_make_shortterm(&p->mnt); | ||
2280 | pwdmnt = &p->mnt; | 2262 | pwdmnt = &p->mnt; |
2281 | } | 2263 | } |
2282 | } | 2264 | } |
@@ -2320,7 +2302,6 @@ static struct mnt_namespace *create_mnt_ns(struct vfsmount *m) | |||
2320 | if (!IS_ERR(new_ns)) { | 2302 | if (!IS_ERR(new_ns)) { |
2321 | struct mount *mnt = real_mount(m); | 2303 | struct mount *mnt = real_mount(m); |
2322 | mnt->mnt_ns = new_ns; | 2304 | mnt->mnt_ns = new_ns; |
2323 | __mnt_make_longterm(mnt); | ||
2324 | new_ns->root = mnt; | 2305 | new_ns->root = mnt; |
2325 | list_add(&new_ns->list, &mnt->mnt_list); | 2306 | list_add(&new_ns->list, &mnt->mnt_list); |
2326 | } else { | 2307 | } else { |
@@ -2615,7 +2596,7 @@ struct vfsmount *kern_mount_data(struct file_system_type *type, void *data) | |||
2615 | * it is a longterm mount, don't release mnt until | 2596 | * it is a longterm mount, don't release mnt until |
2616 | * we unmount before file sys is unregistered | 2597 | * we unmount before file sys is unregistered |
2617 | */ | 2598 | */ |
2618 | mnt_make_longterm(mnt); | 2599 | real_mount(mnt)->mnt_ns = MNT_NS_INTERNAL; |
2619 | } | 2600 | } |
2620 | return mnt; | 2601 | return mnt; |
2621 | } | 2602 | } |
@@ -2625,7 +2606,9 @@ void kern_unmount(struct vfsmount *mnt) | |||
2625 | { | 2606 | { |
2626 | /* release long term mount so mount point can be released */ | 2607 | /* release long term mount so mount point can be released */ |
2627 | if (!IS_ERR_OR_NULL(mnt)) { | 2608 | if (!IS_ERR_OR_NULL(mnt)) { |
2628 | mnt_make_shortterm(mnt); | 2609 | br_write_lock(&vfsmount_lock); |
2610 | real_mount(mnt)->mnt_ns = NULL; | ||
2611 | br_write_unlock(&vfsmount_lock); | ||
2629 | mntput(mnt); | 2612 | mntput(mnt); |
2630 | } | 2613 | } |
2631 | } | 2614 | } |
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index aeed93a6bde0..4117e7b377bb 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c | |||
@@ -30,8 +30,8 @@ static void ncp_do_readdir(struct file *, void *, filldir_t, | |||
30 | 30 | ||
31 | static int ncp_readdir(struct file *, void *, filldir_t); | 31 | static int ncp_readdir(struct file *, void *, filldir_t); |
32 | 32 | ||
33 | static int ncp_create(struct inode *, struct dentry *, umode_t, struct nameidata *); | 33 | static int ncp_create(struct inode *, struct dentry *, umode_t, bool); |
34 | static struct dentry *ncp_lookup(struct inode *, struct dentry *, struct nameidata *); | 34 | static struct dentry *ncp_lookup(struct inode *, struct dentry *, unsigned int); |
35 | static int ncp_unlink(struct inode *, struct dentry *); | 35 | static int ncp_unlink(struct inode *, struct dentry *); |
36 | static int ncp_mkdir(struct inode *, struct dentry *, umode_t); | 36 | static int ncp_mkdir(struct inode *, struct dentry *, umode_t); |
37 | static int ncp_rmdir(struct inode *, struct dentry *); | 37 | static int ncp_rmdir(struct inode *, struct dentry *); |
@@ -72,7 +72,7 @@ const struct inode_operations ncp_dir_inode_operations = | |||
72 | /* | 72 | /* |
73 | * Dentry operations routines | 73 | * Dentry operations routines |
74 | */ | 74 | */ |
75 | static int ncp_lookup_validate(struct dentry *, struct nameidata *); | 75 | static int ncp_lookup_validate(struct dentry *, unsigned int); |
76 | static int ncp_hash_dentry(const struct dentry *, const struct inode *, | 76 | static int ncp_hash_dentry(const struct dentry *, const struct inode *, |
77 | struct qstr *); | 77 | struct qstr *); |
78 | static int ncp_compare_dentry(const struct dentry *, const struct inode *, | 78 | static int ncp_compare_dentry(const struct dentry *, const struct inode *, |
@@ -290,7 +290,7 @@ leave_me:; | |||
290 | 290 | ||
291 | 291 | ||
292 | static int | 292 | static int |
293 | ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd) | 293 | ncp_lookup_validate(struct dentry *dentry, unsigned int flags) |
294 | { | 294 | { |
295 | struct ncp_server *server; | 295 | struct ncp_server *server; |
296 | struct dentry *parent; | 296 | struct dentry *parent; |
@@ -302,7 +302,7 @@ ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd) | |||
302 | if (dentry == dentry->d_sb->s_root) | 302 | if (dentry == dentry->d_sb->s_root) |
303 | return 1; | 303 | return 1; |
304 | 304 | ||
305 | if (nd->flags & LOOKUP_RCU) | 305 | if (flags & LOOKUP_RCU) |
306 | return -ECHILD; | 306 | return -ECHILD; |
307 | 307 | ||
308 | parent = dget_parent(dentry); | 308 | parent = dget_parent(dentry); |
@@ -836,7 +836,7 @@ out: | |||
836 | return result; | 836 | return result; |
837 | } | 837 | } |
838 | 838 | ||
839 | static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 839 | static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
840 | { | 840 | { |
841 | struct ncp_server *server = NCP_SERVER(dir); | 841 | struct ncp_server *server = NCP_SERVER(dir); |
842 | struct inode *inode = NULL; | 842 | struct inode *inode = NULL; |
@@ -980,7 +980,7 @@ out: | |||
980 | } | 980 | } |
981 | 981 | ||
982 | static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 982 | static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
983 | struct nameidata *nd) | 983 | bool excl) |
984 | { | 984 | { |
985 | return ncp_create_new(dir, dentry, mode, 0, 0); | 985 | return ncp_create_new(dir, dentry, mode, 0, 0); |
986 | } | 986 | } |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index f430057ff3b3..a6b1c7fb8232 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -46,8 +46,8 @@ | |||
46 | static int nfs_opendir(struct inode *, struct file *); | 46 | static int nfs_opendir(struct inode *, struct file *); |
47 | static int nfs_closedir(struct inode *, struct file *); | 47 | static int nfs_closedir(struct inode *, struct file *); |
48 | static int nfs_readdir(struct file *, void *, filldir_t); | 48 | static int nfs_readdir(struct file *, void *, filldir_t); |
49 | static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *); | 49 | static struct dentry *nfs_lookup(struct inode *, struct dentry *, unsigned int); |
50 | static int nfs_create(struct inode *, struct dentry *, umode_t, struct nameidata *); | 50 | static int nfs_create(struct inode *, struct dentry *, umode_t, bool); |
51 | static int nfs_mkdir(struct inode *, struct dentry *, umode_t); | 51 | static int nfs_mkdir(struct inode *, struct dentry *, umode_t); |
52 | static int nfs_rmdir(struct inode *, struct dentry *); | 52 | static int nfs_rmdir(struct inode *, struct dentry *); |
53 | static int nfs_unlink(struct inode *, struct dentry *); | 53 | static int nfs_unlink(struct inode *, struct dentry *); |
@@ -111,11 +111,13 @@ const struct inode_operations nfs3_dir_inode_operations = { | |||
111 | 111 | ||
112 | #ifdef CONFIG_NFS_V4 | 112 | #ifdef CONFIG_NFS_V4 |
113 | 113 | ||
114 | static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *); | 114 | static int nfs_atomic_open(struct inode *, struct dentry *, |
115 | static int nfs_open_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd); | 115 | struct file *, unsigned, umode_t, |
116 | int *); | ||
116 | const struct inode_operations nfs4_dir_inode_operations = { | 117 | const struct inode_operations nfs4_dir_inode_operations = { |
117 | .create = nfs_open_create, | 118 | .create = nfs_create, |
118 | .lookup = nfs_atomic_lookup, | 119 | .lookup = nfs_lookup, |
120 | .atomic_open = nfs_atomic_open, | ||
119 | .link = nfs_link, | 121 | .link = nfs_link, |
120 | .unlink = nfs_unlink, | 122 | .unlink = nfs_unlink, |
121 | .symlink = nfs_symlink, | 123 | .symlink = nfs_symlink, |
@@ -1029,27 +1031,14 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry) | |||
1029 | } | 1031 | } |
1030 | 1032 | ||
1031 | /* | 1033 | /* |
1032 | * Return the intent data that applies to this particular path component | ||
1033 | * | ||
1034 | * Note that the current set of intents only apply to the very last | ||
1035 | * component of the path and none of them is set before that last | ||
1036 | * component. | ||
1037 | */ | ||
1038 | static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, | ||
1039 | unsigned int mask) | ||
1040 | { | ||
1041 | return nd->flags & mask; | ||
1042 | } | ||
1043 | |||
1044 | /* | ||
1045 | * Use intent information to check whether or not we're going to do | 1034 | * Use intent information to check whether or not we're going to do |
1046 | * an O_EXCL create using this path component. | 1035 | * an O_EXCL create using this path component. |
1047 | */ | 1036 | */ |
1048 | static int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) | 1037 | static int nfs_is_exclusive_create(struct inode *dir, unsigned int flags) |
1049 | { | 1038 | { |
1050 | if (NFS_PROTO(dir)->version == 2) | 1039 | if (NFS_PROTO(dir)->version == 2) |
1051 | return 0; | 1040 | return 0; |
1052 | return nd && nfs_lookup_check_intent(nd, LOOKUP_EXCL); | 1041 | return flags & LOOKUP_EXCL; |
1053 | } | 1042 | } |
1054 | 1043 | ||
1055 | /* | 1044 | /* |
@@ -1061,25 +1050,20 @@ static int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) | |||
1061 | * | 1050 | * |
1062 | */ | 1051 | */ |
1063 | static inline | 1052 | static inline |
1064 | int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) | 1053 | int nfs_lookup_verify_inode(struct inode *inode, unsigned int flags) |
1065 | { | 1054 | { |
1066 | struct nfs_server *server = NFS_SERVER(inode); | 1055 | struct nfs_server *server = NFS_SERVER(inode); |
1067 | 1056 | ||
1068 | if (IS_AUTOMOUNT(inode)) | 1057 | if (IS_AUTOMOUNT(inode)) |
1069 | return 0; | 1058 | return 0; |
1070 | if (nd != NULL) { | 1059 | /* VFS wants an on-the-wire revalidation */ |
1071 | /* VFS wants an on-the-wire revalidation */ | 1060 | if (flags & LOOKUP_REVAL) |
1072 | if (nd->flags & LOOKUP_REVAL) | 1061 | goto out_force; |
1073 | goto out_force; | 1062 | /* This is an open(2) */ |
1074 | /* This is an open(2) */ | 1063 | if ((flags & LOOKUP_OPEN) && !(server->flags & NFS_MOUNT_NOCTO) && |
1075 | if (nfs_lookup_check_intent(nd, LOOKUP_OPEN) != 0 && | 1064 | (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) |
1076 | !(server->flags & NFS_MOUNT_NOCTO) && | 1065 | goto out_force; |
1077 | (S_ISREG(inode->i_mode) || | 1066 | return 0; |
1078 | S_ISDIR(inode->i_mode))) | ||
1079 | goto out_force; | ||
1080 | return 0; | ||
1081 | } | ||
1082 | return nfs_revalidate_inode(server, inode); | ||
1083 | out_force: | 1067 | out_force: |
1084 | return __nfs_revalidate_inode(server, inode); | 1068 | return __nfs_revalidate_inode(server, inode); |
1085 | } | 1069 | } |
@@ -1093,10 +1077,10 @@ out_force: | |||
1093 | */ | 1077 | */ |
1094 | static inline | 1078 | static inline |
1095 | int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, | 1079 | int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, |
1096 | struct nameidata *nd) | 1080 | unsigned int flags) |
1097 | { | 1081 | { |
1098 | /* Don't revalidate a negative dentry if we're creating a new file */ | 1082 | /* Don't revalidate a negative dentry if we're creating a new file */ |
1099 | if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0) | 1083 | if (flags & LOOKUP_CREATE) |
1100 | return 0; | 1084 | return 0; |
1101 | if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG) | 1085 | if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG) |
1102 | return 1; | 1086 | return 1; |
@@ -1114,7 +1098,7 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, | |||
1114 | * If the parent directory is seen to have changed, we throw out the | 1098 | * If the parent directory is seen to have changed, we throw out the |
1115 | * cached dentry and do a new lookup. | 1099 | * cached dentry and do a new lookup. |
1116 | */ | 1100 | */ |
1117 | static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | 1101 | static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) |
1118 | { | 1102 | { |
1119 | struct inode *dir; | 1103 | struct inode *dir; |
1120 | struct inode *inode; | 1104 | struct inode *inode; |
@@ -1123,7 +1107,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1123 | struct nfs_fattr *fattr = NULL; | 1107 | struct nfs_fattr *fattr = NULL; |
1124 | int error; | 1108 | int error; |
1125 | 1109 | ||
1126 | if (nd->flags & LOOKUP_RCU) | 1110 | if (flags & LOOKUP_RCU) |
1127 | return -ECHILD; | 1111 | return -ECHILD; |
1128 | 1112 | ||
1129 | parent = dget_parent(dentry); | 1113 | parent = dget_parent(dentry); |
@@ -1132,7 +1116,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1132 | inode = dentry->d_inode; | 1116 | inode = dentry->d_inode; |
1133 | 1117 | ||
1134 | if (!inode) { | 1118 | if (!inode) { |
1135 | if (nfs_neg_need_reval(dir, dentry, nd)) | 1119 | if (nfs_neg_need_reval(dir, dentry, flags)) |
1136 | goto out_bad; | 1120 | goto out_bad; |
1137 | goto out_valid_noent; | 1121 | goto out_valid_noent; |
1138 | } | 1122 | } |
@@ -1148,8 +1132,8 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1148 | goto out_set_verifier; | 1132 | goto out_set_verifier; |
1149 | 1133 | ||
1150 | /* Force a full look up iff the parent directory has changed */ | 1134 | /* Force a full look up iff the parent directory has changed */ |
1151 | if (!nfs_is_exclusive_create(dir, nd) && nfs_check_verifier(dir, dentry)) { | 1135 | if (!nfs_is_exclusive_create(dir, flags) && nfs_check_verifier(dir, dentry)) { |
1152 | if (nfs_lookup_verify_inode(inode, nd)) | 1136 | if (nfs_lookup_verify_inode(inode, flags)) |
1153 | goto out_zap_parent; | 1137 | goto out_zap_parent; |
1154 | goto out_valid; | 1138 | goto out_valid; |
1155 | } | 1139 | } |
@@ -1286,7 +1270,7 @@ const struct dentry_operations nfs_dentry_operations = { | |||
1286 | .d_release = nfs_d_release, | 1270 | .d_release = nfs_d_release, |
1287 | }; | 1271 | }; |
1288 | 1272 | ||
1289 | static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) | 1273 | static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags) |
1290 | { | 1274 | { |
1291 | struct dentry *res; | 1275 | struct dentry *res; |
1292 | struct dentry *parent; | 1276 | struct dentry *parent; |
@@ -1307,7 +1291,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
1307 | * If we're doing an exclusive create, optimize away the lookup | 1291 | * If we're doing an exclusive create, optimize away the lookup |
1308 | * but don't hash the dentry. | 1292 | * but don't hash the dentry. |
1309 | */ | 1293 | */ |
1310 | if (nfs_is_exclusive_create(dir, nd)) { | 1294 | if (nfs_is_exclusive_create(dir, flags)) { |
1311 | d_instantiate(dentry, NULL); | 1295 | d_instantiate(dentry, NULL); |
1312 | res = NULL; | 1296 | res = NULL; |
1313 | goto out; | 1297 | goto out; |
@@ -1354,7 +1338,7 @@ out: | |||
1354 | } | 1338 | } |
1355 | 1339 | ||
1356 | #ifdef CONFIG_NFS_V4 | 1340 | #ifdef CONFIG_NFS_V4 |
1357 | static int nfs4_lookup_revalidate(struct dentry *, struct nameidata *); | 1341 | static int nfs4_lookup_revalidate(struct dentry *, unsigned int); |
1358 | 1342 | ||
1359 | const struct dentry_operations nfs4_dentry_operations = { | 1343 | const struct dentry_operations nfs4_dentry_operations = { |
1360 | .d_revalidate = nfs4_lookup_revalidate, | 1344 | .d_revalidate = nfs4_lookup_revalidate, |
@@ -1364,24 +1348,6 @@ const struct dentry_operations nfs4_dentry_operations = { | |||
1364 | .d_release = nfs_d_release, | 1348 | .d_release = nfs_d_release, |
1365 | }; | 1349 | }; |
1366 | 1350 | ||
1367 | /* | ||
1368 | * Use intent information to determine whether we need to substitute | ||
1369 | * the NFSv4-style stateful OPEN for the LOOKUP call | ||
1370 | */ | ||
1371 | static int is_atomic_open(struct nameidata *nd) | ||
1372 | { | ||
1373 | if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0) | ||
1374 | return 0; | ||
1375 | /* NFS does not (yet) have a stateful open for directories */ | ||
1376 | if (nd->flags & LOOKUP_DIRECTORY) | ||
1377 | return 0; | ||
1378 | /* Are we trying to write to a read only partition? */ | ||
1379 | if (__mnt_is_readonly(nd->path.mnt) && | ||
1380 | (nd->intent.open.flags & (O_CREAT|O_TRUNC|O_ACCMODE))) | ||
1381 | return 0; | ||
1382 | return 1; | ||
1383 | } | ||
1384 | |||
1385 | static fmode_t flags_to_mode(int flags) | 1351 | static fmode_t flags_to_mode(int flags) |
1386 | { | 1352 | { |
1387 | fmode_t res = (__force fmode_t)flags & FMODE_EXEC; | 1353 | fmode_t res = (__force fmode_t)flags & FMODE_EXEC; |
@@ -1403,136 +1369,143 @@ static int do_open(struct inode *inode, struct file *filp) | |||
1403 | return 0; | 1369 | return 0; |
1404 | } | 1370 | } |
1405 | 1371 | ||
1406 | static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ctx) | 1372 | static int nfs_finish_open(struct nfs_open_context *ctx, |
1373 | struct dentry *dentry, | ||
1374 | struct file *file, unsigned open_flags, | ||
1375 | int *opened) | ||
1407 | { | 1376 | { |
1408 | struct file *filp; | 1377 | int err; |
1409 | int ret = 0; | 1378 | |
1379 | if (ctx->dentry != dentry) { | ||
1380 | dput(ctx->dentry); | ||
1381 | ctx->dentry = dget(dentry); | ||
1382 | } | ||
1410 | 1383 | ||
1411 | /* If the open_intent is for execute, we have an extra check to make */ | 1384 | /* If the open_intent is for execute, we have an extra check to make */ |
1412 | if (ctx->mode & FMODE_EXEC) { | 1385 | if (ctx->mode & FMODE_EXEC) { |
1413 | ret = nfs_may_open(ctx->dentry->d_inode, | 1386 | err = nfs_may_open(dentry->d_inode, ctx->cred, open_flags); |
1414 | ctx->cred, | 1387 | if (err < 0) |
1415 | nd->intent.open.flags); | ||
1416 | if (ret < 0) | ||
1417 | goto out; | 1388 | goto out; |
1418 | } | 1389 | } |
1419 | filp = lookup_instantiate_filp(nd, ctx->dentry, do_open); | 1390 | |
1420 | if (IS_ERR(filp)) | 1391 | err = finish_open(file, dentry, do_open, opened); |
1421 | ret = PTR_ERR(filp); | 1392 | if (err) |
1422 | else | 1393 | goto out; |
1423 | nfs_file_set_open_context(filp, ctx); | 1394 | nfs_file_set_open_context(file, ctx); |
1395 | |||
1424 | out: | 1396 | out: |
1425 | put_nfs_open_context(ctx); | 1397 | put_nfs_open_context(ctx); |
1426 | return ret; | 1398 | return err; |
1427 | } | 1399 | } |
1428 | 1400 | ||
1429 | static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 1401 | static int nfs_atomic_open(struct inode *dir, struct dentry *dentry, |
1402 | struct file *file, unsigned open_flags, | ||
1403 | umode_t mode, int *opened) | ||
1430 | { | 1404 | { |
1431 | struct nfs_open_context *ctx; | 1405 | struct nfs_open_context *ctx; |
1432 | struct iattr attr; | 1406 | struct dentry *res; |
1433 | struct dentry *res = NULL; | 1407 | struct iattr attr = { .ia_valid = ATTR_OPEN }; |
1434 | struct inode *inode; | 1408 | struct inode *inode; |
1435 | int open_flags; | ||
1436 | int err; | 1409 | int err; |
1437 | 1410 | ||
1438 | dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n", | 1411 | /* Expect a negative dentry */ |
1412 | BUG_ON(dentry->d_inode); | ||
1413 | |||
1414 | dfprintk(VFS, "NFS: atomic_open(%s/%ld), %s\n", | ||
1439 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); | 1415 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); |
1440 | 1416 | ||
1441 | /* Check that we are indeed trying to open this file */ | 1417 | /* NFS only supports OPEN on regular files */ |
1442 | if (!is_atomic_open(nd)) | 1418 | if ((open_flags & O_DIRECTORY)) { |
1419 | if (!d_unhashed(dentry)) { | ||
1420 | /* | ||
1421 | * Hashed negative dentry with O_DIRECTORY: dentry was | ||
1422 | * revalidated and is fine, no need to perform lookup | ||
1423 | * again | ||
1424 | */ | ||
1425 | return -ENOENT; | ||
1426 | } | ||
1443 | goto no_open; | 1427 | goto no_open; |
1444 | |||
1445 | if (dentry->d_name.len > NFS_SERVER(dir)->namelen) { | ||
1446 | res = ERR_PTR(-ENAMETOOLONG); | ||
1447 | goto out; | ||
1448 | } | ||
1449 | |||
1450 | /* Let vfs_create() deal with O_EXCL. Instantiate, but don't hash | ||
1451 | * the dentry. */ | ||
1452 | if (nd->flags & LOOKUP_EXCL) { | ||
1453 | d_instantiate(dentry, NULL); | ||
1454 | goto out; | ||
1455 | } | 1428 | } |
1456 | 1429 | ||
1457 | open_flags = nd->intent.open.flags; | 1430 | if (dentry->d_name.len > NFS_SERVER(dir)->namelen) |
1458 | attr.ia_valid = ATTR_OPEN; | 1431 | return -ENAMETOOLONG; |
1459 | |||
1460 | ctx = create_nfs_open_context(dentry, open_flags); | ||
1461 | res = ERR_CAST(ctx); | ||
1462 | if (IS_ERR(ctx)) | ||
1463 | goto out; | ||
1464 | 1432 | ||
1465 | if (nd->flags & LOOKUP_CREATE) { | 1433 | if (open_flags & O_CREAT) { |
1466 | attr.ia_mode = nd->intent.open.create_mode; | ||
1467 | attr.ia_valid |= ATTR_MODE; | 1434 | attr.ia_valid |= ATTR_MODE; |
1468 | attr.ia_mode &= ~current_umask(); | 1435 | attr.ia_mode = mode & ~current_umask(); |
1469 | } else | 1436 | } |
1470 | open_flags &= ~(O_EXCL | O_CREAT); | ||
1471 | |||
1472 | if (open_flags & O_TRUNC) { | 1437 | if (open_flags & O_TRUNC) { |
1473 | attr.ia_valid |= ATTR_SIZE; | 1438 | attr.ia_valid |= ATTR_SIZE; |
1474 | attr.ia_size = 0; | 1439 | attr.ia_size = 0; |
1475 | } | 1440 | } |
1476 | 1441 | ||
1477 | /* Open the file on the server */ | 1442 | ctx = create_nfs_open_context(dentry, open_flags); |
1443 | err = PTR_ERR(ctx); | ||
1444 | if (IS_ERR(ctx)) | ||
1445 | goto out; | ||
1446 | |||
1478 | nfs_block_sillyrename(dentry->d_parent); | 1447 | nfs_block_sillyrename(dentry->d_parent); |
1479 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); | 1448 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); |
1449 | d_drop(dentry); | ||
1480 | if (IS_ERR(inode)) { | 1450 | if (IS_ERR(inode)) { |
1481 | nfs_unblock_sillyrename(dentry->d_parent); | 1451 | nfs_unblock_sillyrename(dentry->d_parent); |
1482 | put_nfs_open_context(ctx); | 1452 | put_nfs_open_context(ctx); |
1483 | switch (PTR_ERR(inode)) { | 1453 | err = PTR_ERR(inode); |
1484 | /* Make a negative dentry */ | 1454 | switch (err) { |
1485 | case -ENOENT: | 1455 | case -ENOENT: |
1486 | d_add(dentry, NULL); | 1456 | d_add(dentry, NULL); |
1487 | res = NULL; | 1457 | break; |
1488 | goto out; | 1458 | case -EISDIR: |
1489 | /* This turned out not to be a regular file */ | 1459 | case -ENOTDIR: |
1490 | case -EISDIR: | 1460 | goto no_open; |
1491 | case -ENOTDIR: | 1461 | case -ELOOP: |
1462 | if (!(open_flags & O_NOFOLLOW)) | ||
1492 | goto no_open; | 1463 | goto no_open; |
1493 | case -ELOOP: | 1464 | break; |
1494 | if (!(nd->intent.open.flags & O_NOFOLLOW)) | ||
1495 | goto no_open; | ||
1496 | /* case -EINVAL: */ | 1465 | /* case -EINVAL: */ |
1497 | default: | 1466 | default: |
1498 | res = ERR_CAST(inode); | 1467 | break; |
1499 | goto out; | ||
1500 | } | 1468 | } |
1469 | goto out; | ||
1501 | } | 1470 | } |
1502 | res = d_add_unique(dentry, inode); | 1471 | res = d_add_unique(dentry, inode); |
1503 | nfs_unblock_sillyrename(dentry->d_parent); | 1472 | if (res != NULL) |
1504 | if (res != NULL) { | ||
1505 | dput(ctx->dentry); | ||
1506 | ctx->dentry = dget(res); | ||
1507 | dentry = res; | 1473 | dentry = res; |
1508 | } | 1474 | |
1509 | err = nfs_intent_set_file(nd, ctx); | 1475 | nfs_unblock_sillyrename(dentry->d_parent); |
1510 | if (err < 0) { | ||
1511 | if (res != NULL) | ||
1512 | dput(res); | ||
1513 | return ERR_PTR(err); | ||
1514 | } | ||
1515 | out: | ||
1516 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1476 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1517 | return res; | 1477 | |
1478 | err = nfs_finish_open(ctx, dentry, file, open_flags, opened); | ||
1479 | |||
1480 | dput(res); | ||
1481 | out: | ||
1482 | return err; | ||
1483 | |||
1518 | no_open: | 1484 | no_open: |
1519 | return nfs_lookup(dir, dentry, nd); | 1485 | res = nfs_lookup(dir, dentry, 0); |
1486 | err = PTR_ERR(res); | ||
1487 | if (IS_ERR(res)) | ||
1488 | goto out; | ||
1489 | |||
1490 | return finish_no_open(file, res); | ||
1520 | } | 1491 | } |
1521 | 1492 | ||
1522 | static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | 1493 | static int nfs4_lookup_revalidate(struct dentry *dentry, unsigned int flags) |
1523 | { | 1494 | { |
1524 | struct dentry *parent = NULL; | 1495 | struct dentry *parent = NULL; |
1525 | struct inode *inode; | 1496 | struct inode *inode; |
1526 | struct inode *dir; | 1497 | struct inode *dir; |
1527 | int openflags, ret = 0; | 1498 | int ret = 0; |
1528 | 1499 | ||
1529 | if (nd->flags & LOOKUP_RCU) | 1500 | if (flags & LOOKUP_RCU) |
1530 | return -ECHILD; | 1501 | return -ECHILD; |
1531 | 1502 | ||
1532 | inode = dentry->d_inode; | 1503 | if (!(flags & LOOKUP_OPEN) || (flags & LOOKUP_DIRECTORY)) |
1533 | if (!is_atomic_open(nd) || d_mountpoint(dentry)) | 1504 | goto no_open; |
1505 | if (d_mountpoint(dentry)) | ||
1534 | goto no_open; | 1506 | goto no_open; |
1535 | 1507 | ||
1508 | inode = dentry->d_inode; | ||
1536 | parent = dget_parent(dentry); | 1509 | parent = dget_parent(dentry); |
1537 | dir = parent->d_inode; | 1510 | dir = parent->d_inode; |
1538 | 1511 | ||
@@ -1540,7 +1513,7 @@ static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1540 | * optimize away revalidation of negative dentries. | 1513 | * optimize away revalidation of negative dentries. |
1541 | */ | 1514 | */ |
1542 | if (inode == NULL) { | 1515 | if (inode == NULL) { |
1543 | if (!nfs_neg_need_reval(dir, dentry, nd)) | 1516 | if (!nfs_neg_need_reval(dir, dentry, flags)) |
1544 | ret = 1; | 1517 | ret = 1; |
1545 | goto out; | 1518 | goto out; |
1546 | } | 1519 | } |
@@ -1548,9 +1521,8 @@ static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1548 | /* NFS only supports OPEN on regular files */ | 1521 | /* NFS only supports OPEN on regular files */ |
1549 | if (!S_ISREG(inode->i_mode)) | 1522 | if (!S_ISREG(inode->i_mode)) |
1550 | goto no_open_dput; | 1523 | goto no_open_dput; |
1551 | openflags = nd->intent.open.flags; | ||
1552 | /* We cannot do exclusive creation on a positive dentry */ | 1524 | /* We cannot do exclusive creation on a positive dentry */ |
1553 | if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) | 1525 | if (flags & LOOKUP_EXCL) |
1554 | goto no_open_dput; | 1526 | goto no_open_dput; |
1555 | 1527 | ||
1556 | /* Let f_op->open() actually open (and revalidate) the file */ | 1528 | /* Let f_op->open() actually open (and revalidate) the file */ |
@@ -1563,48 +1535,7 @@ out: | |||
1563 | no_open_dput: | 1535 | no_open_dput: |
1564 | dput(parent); | 1536 | dput(parent); |
1565 | no_open: | 1537 | no_open: |
1566 | return nfs_lookup_revalidate(dentry, nd); | 1538 | return nfs_lookup_revalidate(dentry, flags); |
1567 | } | ||
1568 | |||
1569 | static int nfs_open_create(struct inode *dir, struct dentry *dentry, | ||
1570 | umode_t mode, struct nameidata *nd) | ||
1571 | { | ||
1572 | struct nfs_open_context *ctx = NULL; | ||
1573 | struct iattr attr; | ||
1574 | int error; | ||
1575 | int open_flags = O_CREAT|O_EXCL; | ||
1576 | |||
1577 | dfprintk(VFS, "NFS: create(%s/%ld), %s\n", | ||
1578 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); | ||
1579 | |||
1580 | attr.ia_mode = mode; | ||
1581 | attr.ia_valid = ATTR_MODE; | ||
1582 | |||
1583 | if (nd) | ||
1584 | open_flags = nd->intent.open.flags; | ||
1585 | |||
1586 | ctx = create_nfs_open_context(dentry, open_flags); | ||
1587 | error = PTR_ERR(ctx); | ||
1588 | if (IS_ERR(ctx)) | ||
1589 | goto out_err_drop; | ||
1590 | |||
1591 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx); | ||
1592 | if (error != 0) | ||
1593 | goto out_put_ctx; | ||
1594 | if (nd) { | ||
1595 | error = nfs_intent_set_file(nd, ctx); | ||
1596 | if (error < 0) | ||
1597 | goto out_err; | ||
1598 | } else { | ||
1599 | put_nfs_open_context(ctx); | ||
1600 | } | ||
1601 | return 0; | ||
1602 | out_put_ctx: | ||
1603 | put_nfs_open_context(ctx); | ||
1604 | out_err_drop: | ||
1605 | d_drop(dentry); | ||
1606 | out_err: | ||
1607 | return error; | ||
1608 | } | 1539 | } |
1609 | 1540 | ||
1610 | #endif /* CONFIG_NFSV4 */ | 1541 | #endif /* CONFIG_NFSV4 */ |
@@ -1658,11 +1589,11 @@ out_error: | |||
1658 | * reply path made it appear to have failed. | 1589 | * reply path made it appear to have failed. |
1659 | */ | 1590 | */ |
1660 | static int nfs_create(struct inode *dir, struct dentry *dentry, | 1591 | static int nfs_create(struct inode *dir, struct dentry *dentry, |
1661 | umode_t mode, struct nameidata *nd) | 1592 | umode_t mode, bool excl) |
1662 | { | 1593 | { |
1663 | struct iattr attr; | 1594 | struct iattr attr; |
1595 | int open_flags = excl ? O_CREAT | O_EXCL : O_CREAT; | ||
1664 | int error; | 1596 | int error; |
1665 | int open_flags = O_CREAT|O_EXCL; | ||
1666 | 1597 | ||
1667 | dfprintk(VFS, "NFS: create(%s/%ld), %s\n", | 1598 | dfprintk(VFS, "NFS: create(%s/%ld), %s\n", |
1668 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); | 1599 | dir->i_sb->s_id, dir->i_ino, dentry->d_name.name); |
@@ -1670,10 +1601,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, | |||
1670 | attr.ia_mode = mode; | 1601 | attr.ia_mode = mode; |
1671 | attr.ia_valid = ATTR_MODE; | 1602 | attr.ia_valid = ATTR_MODE; |
1672 | 1603 | ||
1673 | if (nd) | 1604 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags); |
1674 | open_flags = nd->intent.open.flags; | ||
1675 | |||
1676 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, NULL); | ||
1677 | if (error != 0) | 1605 | if (error != 0) |
1678 | goto out_err; | 1606 | goto out_err; |
1679 | return 0; | 1607 | return 0; |
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index 8abfb19bd3aa..a67990f90bd7 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
@@ -62,7 +62,7 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i | |||
62 | */ | 62 | */ |
63 | spin_lock(&sb->s_root->d_inode->i_lock); | 63 | spin_lock(&sb->s_root->d_inode->i_lock); |
64 | spin_lock(&sb->s_root->d_lock); | 64 | spin_lock(&sb->s_root->d_lock); |
65 | list_del_init(&sb->s_root->d_alias); | 65 | hlist_del_init(&sb->s_root->d_alias); |
66 | spin_unlock(&sb->s_root->d_lock); | 66 | spin_unlock(&sb->s_root->d_lock); |
67 | spin_unlock(&sb->s_root->d_inode->i_lock); | 67 | spin_unlock(&sb->s_root->d_inode->i_lock); |
68 | } | 68 | } |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 2292a0fd2bff..3187e24e8f78 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -314,7 +314,7 @@ static void nfs3_free_createdata(struct nfs3_createdata *data) | |||
314 | */ | 314 | */ |
315 | static int | 315 | static int |
316 | nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 316 | nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
317 | int flags, struct nfs_open_context *ctx) | 317 | int flags) |
318 | { | 318 | { |
319 | struct nfs3_createdata *data; | 319 | struct nfs3_createdata *data; |
320 | umode_t mode = sattr->ia_mode; | 320 | umode_t mode = sattr->ia_mode; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 15fc7e4664ed..c157b2089b47 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2806,37 +2806,22 @@ static int nfs4_proc_readlink(struct inode *inode, struct page *page, | |||
2806 | } | 2806 | } |
2807 | 2807 | ||
2808 | /* | 2808 | /* |
2809 | * Got race? | 2809 | * This is just for mknod. open(O_CREAT) will always do ->open_context(). |
2810 | * We will need to arrange for the VFS layer to provide an atomic open. | ||
2811 | * Until then, this create/open method is prone to inefficiency and race | ||
2812 | * conditions due to the lookup, create, and open VFS calls from sys_open() | ||
2813 | * placed on the wire. | ||
2814 | * | ||
2815 | * Given the above sorry state of affairs, I'm simply sending an OPEN. | ||
2816 | * The file will be opened again in the subsequent VFS open call | ||
2817 | * (nfs4_proc_file_open). | ||
2818 | * | ||
2819 | * The open for read will just hang around to be used by any process that | ||
2820 | * opens the file O_RDONLY. This will all be resolved with the VFS changes. | ||
2821 | */ | 2810 | */ |
2822 | |||
2823 | static int | 2811 | static int |
2824 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 2812 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
2825 | int flags, struct nfs_open_context *ctx) | 2813 | int flags) |
2826 | { | 2814 | { |
2827 | struct dentry *de = dentry; | 2815 | struct nfs_open_context *ctx; |
2828 | struct nfs4_state *state; | 2816 | struct nfs4_state *state; |
2829 | struct rpc_cred *cred = NULL; | ||
2830 | fmode_t fmode = 0; | ||
2831 | int status = 0; | 2817 | int status = 0; |
2832 | 2818 | ||
2833 | if (ctx != NULL) { | 2819 | ctx = alloc_nfs_open_context(dentry, FMODE_READ); |
2834 | cred = ctx->cred; | 2820 | if (IS_ERR(ctx)) |
2835 | de = ctx->dentry; | 2821 | return PTR_ERR(ctx); |
2836 | fmode = ctx->mode; | 2822 | |
2837 | } | ||
2838 | sattr->ia_mode &= ~current_umask(); | 2823 | sattr->ia_mode &= ~current_umask(); |
2839 | state = nfs4_do_open(dir, de, fmode, flags, sattr, cred, NULL); | 2824 | state = nfs4_do_open(dir, dentry, ctx->mode, flags, sattr, ctx->cred, NULL); |
2840 | d_drop(dentry); | 2825 | d_drop(dentry); |
2841 | if (IS_ERR(state)) { | 2826 | if (IS_ERR(state)) { |
2842 | status = PTR_ERR(state); | 2827 | status = PTR_ERR(state); |
@@ -2844,11 +2829,9 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
2844 | } | 2829 | } |
2845 | d_add(dentry, igrab(state->inode)); | 2830 | d_add(dentry, igrab(state->inode)); |
2846 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 2831 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
2847 | if (ctx != NULL) | 2832 | ctx->state = state; |
2848 | ctx->state = state; | ||
2849 | else | ||
2850 | nfs4_close_sync(state, fmode); | ||
2851 | out: | 2833 | out: |
2834 | put_nfs_open_context(ctx); | ||
2852 | return status; | 2835 | return status; |
2853 | } | 2836 | } |
2854 | 2837 | ||
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 617c7419a08e..4433806e116f 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -259,7 +259,7 @@ static void nfs_free_createdata(const struct nfs_createdata *data) | |||
259 | 259 | ||
260 | static int | 260 | static int |
261 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 261 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
262 | int flags, struct nfs_open_context *ctx) | 262 | int flags) |
263 | { | 263 | { |
264 | struct nfs_createdata *data; | 264 | struct nfs_createdata *data; |
265 | struct rpc_message msg = { | 265 | struct rpc_message msg = { |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 06228192f64e..8b2a2977b720 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -2419,7 +2419,7 @@ static struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type, | |||
2419 | sb_mntdata.mntflags |= MS_SYNCHRONOUS; | 2419 | sb_mntdata.mntflags |= MS_SYNCHRONOUS; |
2420 | 2420 | ||
2421 | /* Get a superblock - note that we may end up sharing one that already exists */ | 2421 | /* Get a superblock - note that we may end up sharing one that already exists */ |
2422 | s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata); | 2422 | s = sget(fs_type, compare_super, nfs_set_super, flags, &sb_mntdata); |
2423 | if (IS_ERR(s)) { | 2423 | if (IS_ERR(s)) { |
2424 | mntroot = ERR_CAST(s); | 2424 | mntroot = ERR_CAST(s); |
2425 | goto out_err_nosb; | 2425 | goto out_err_nosb; |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index c8bd9c3be7f7..4700a0a929d7 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -745,7 +745,7 @@ __be32 | |||
745 | nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, | 745 | nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, |
746 | int may_flags, struct file **filp) | 746 | int may_flags, struct file **filp) |
747 | { | 747 | { |
748 | struct dentry *dentry; | 748 | struct path path; |
749 | struct inode *inode; | 749 | struct inode *inode; |
750 | int flags = O_RDONLY|O_LARGEFILE; | 750 | int flags = O_RDONLY|O_LARGEFILE; |
751 | __be32 err; | 751 | __be32 err; |
@@ -762,8 +762,9 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, | |||
762 | if (err) | 762 | if (err) |
763 | goto out; | 763 | goto out; |
764 | 764 | ||
765 | dentry = fhp->fh_dentry; | 765 | path.mnt = fhp->fh_export->ex_path.mnt; |
766 | inode = dentry->d_inode; | 766 | path.dentry = fhp->fh_dentry; |
767 | inode = path.dentry->d_inode; | ||
767 | 768 | ||
768 | /* Disallow write access to files with the append-only bit set | 769 | /* Disallow write access to files with the append-only bit set |
769 | * or any access when mandatory locking enabled | 770 | * or any access when mandatory locking enabled |
@@ -792,8 +793,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, | |||
792 | else | 793 | else |
793 | flags = O_WRONLY|O_LARGEFILE; | 794 | flags = O_WRONLY|O_LARGEFILE; |
794 | } | 795 | } |
795 | *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt), | 796 | *filp = dentry_open(&path, flags, current_cred()); |
796 | flags, current_cred()); | ||
797 | if (IS_ERR(*filp)) | 797 | if (IS_ERR(*filp)) |
798 | host_err = PTR_ERR(*filp); | 798 | host_err = PTR_ERR(*filp); |
799 | else { | 799 | else { |
@@ -1329,7 +1329,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1329 | err = 0; | 1329 | err = 0; |
1330 | switch (type) { | 1330 | switch (type) { |
1331 | case S_IFREG: | 1331 | case S_IFREG: |
1332 | host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); | 1332 | host_err = vfs_create(dirp, dchild, iap->ia_mode, true); |
1333 | if (!host_err) | 1333 | if (!host_err) |
1334 | nfsd_check_ignore_resizing(iap); | 1334 | nfsd_check_ignore_resizing(iap); |
1335 | break; | 1335 | break; |
@@ -1492,7 +1492,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1492 | goto out; | 1492 | goto out; |
1493 | } | 1493 | } |
1494 | 1494 | ||
1495 | host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); | 1495 | host_err = vfs_create(dirp, dchild, iap->ia_mode, true); |
1496 | if (host_err < 0) { | 1496 | if (host_err < 0) { |
1497 | fh_drop_write(fhp); | 1497 | fh_drop_write(fhp); |
1498 | goto out_nfserr; | 1498 | goto out_nfserr; |
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c index b72847988b78..1d0c0b84c5a3 100644 --- a/fs/nilfs2/namei.c +++ b/fs/nilfs2/namei.c | |||
@@ -63,7 +63,7 @@ static inline int nilfs_add_nondir(struct dentry *dentry, struct inode *inode) | |||
63 | */ | 63 | */ |
64 | 64 | ||
65 | static struct dentry * | 65 | static struct dentry * |
66 | nilfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 66 | nilfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
67 | { | 67 | { |
68 | struct inode *inode; | 68 | struct inode *inode; |
69 | ino_t ino; | 69 | ino_t ino; |
@@ -85,7 +85,7 @@ nilfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
85 | * with d_instantiate(). | 85 | * with d_instantiate(). |
86 | */ | 86 | */ |
87 | static int nilfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 87 | static int nilfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
88 | struct nameidata *nd) | 88 | bool excl) |
89 | { | 89 | { |
90 | struct inode *inode; | 90 | struct inode *inode; |
91 | struct nilfs_transaction_info ti; | 91 | struct nilfs_transaction_info ti; |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 1099a76cee59..d57c42f974ea 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -1288,7 +1288,8 @@ nilfs_mount(struct file_system_type *fs_type, int flags, | |||
1288 | err = -EBUSY; | 1288 | err = -EBUSY; |
1289 | goto failed; | 1289 | goto failed; |
1290 | } | 1290 | } |
1291 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, sd.bdev); | 1291 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, flags, |
1292 | sd.bdev); | ||
1292 | mutex_unlock(&sd.bdev->bd_fsfreeze_mutex); | 1293 | mutex_unlock(&sd.bdev->bd_fsfreeze_mutex); |
1293 | if (IS_ERR(s)) { | 1294 | if (IS_ERR(s)) { |
1294 | err = PTR_ERR(s); | 1295 | err = PTR_ERR(s); |
@@ -1301,7 +1302,6 @@ nilfs_mount(struct file_system_type *fs_type, int flags, | |||
1301 | s_new = true; | 1302 | s_new = true; |
1302 | 1303 | ||
1303 | /* New superblock instance created */ | 1304 | /* New superblock instance created */ |
1304 | s->s_flags = flags; | ||
1305 | s->s_mode = mode; | 1305 | s->s_mode = mode; |
1306 | strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id)); | 1306 | strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id)); |
1307 | sb_set_blocksize(s, block_size(sd.bdev)); | 1307 | sb_set_blocksize(s, block_size(sd.bdev)); |
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 3568c8a8b138..d43803669739 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c | |||
@@ -61,8 +61,6 @@ static struct fsnotify_event *get_one_event(struct fsnotify_group *group, | |||
61 | static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event) | 61 | static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event) |
62 | { | 62 | { |
63 | int client_fd; | 63 | int client_fd; |
64 | struct dentry *dentry; | ||
65 | struct vfsmount *mnt; | ||
66 | struct file *new_file; | 64 | struct file *new_file; |
67 | 65 | ||
68 | pr_debug("%s: group=%p event=%p\n", __func__, group, event); | 66 | pr_debug("%s: group=%p event=%p\n", __func__, group, event); |
@@ -81,12 +79,10 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event) | |||
81 | * we need a new file handle for the userspace program so it can read even if it was | 79 | * we need a new file handle for the userspace program so it can read even if it was |
82 | * originally opened O_WRONLY. | 80 | * originally opened O_WRONLY. |
83 | */ | 81 | */ |
84 | dentry = dget(event->path.dentry); | ||
85 | mnt = mntget(event->path.mnt); | ||
86 | /* it's possible this event was an overflow event. in that case dentry and mnt | 82 | /* it's possible this event was an overflow event. in that case dentry and mnt |
87 | * are NULL; That's fine, just don't call dentry open */ | 83 | * are NULL; That's fine, just don't call dentry open */ |
88 | if (dentry && mnt) | 84 | if (event->path.dentry && event->path.mnt) |
89 | new_file = dentry_open(dentry, mnt, | 85 | new_file = dentry_open(&event->path, |
90 | group->fanotify_data.f_flags | FMODE_NONOTIFY, | 86 | group->fanotify_data.f_flags | FMODE_NONOTIFY, |
91 | current_cred()); | 87 | current_cred()); |
92 | else | 88 | else |
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index b39c5c161adb..6baadb5a8430 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c | |||
@@ -52,6 +52,7 @@ void __fsnotify_vfsmount_delete(struct vfsmount *mnt) | |||
52 | void __fsnotify_update_child_dentry_flags(struct inode *inode) | 52 | void __fsnotify_update_child_dentry_flags(struct inode *inode) |
53 | { | 53 | { |
54 | struct dentry *alias; | 54 | struct dentry *alias; |
55 | struct hlist_node *p; | ||
55 | int watched; | 56 | int watched; |
56 | 57 | ||
57 | if (!S_ISDIR(inode->i_mode)) | 58 | if (!S_ISDIR(inode->i_mode)) |
@@ -63,7 +64,7 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode) | |||
63 | spin_lock(&inode->i_lock); | 64 | spin_lock(&inode->i_lock); |
64 | /* run all of the dentries associated with this inode. Since this is a | 65 | /* run all of the dentries associated with this inode. Since this is a |
65 | * directory, there damn well better only be one item on this list */ | 66 | * directory, there damn well better only be one item on this list */ |
66 | list_for_each_entry(alias, &inode->i_dentry, d_alias) { | 67 | hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) { |
67 | struct dentry *child; | 68 | struct dentry *child; |
68 | 69 | ||
69 | /* run all of the children of the original inode and fix their | 70 | /* run all of the children of the original inode and fix their |
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c index 358273e59ade..436f36037e09 100644 --- a/fs/ntfs/namei.c +++ b/fs/ntfs/namei.c | |||
@@ -101,7 +101,7 @@ | |||
101 | * Locking: Caller must hold i_mutex on the directory. | 101 | * Locking: Caller must hold i_mutex on the directory. |
102 | */ | 102 | */ |
103 | static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, | 103 | static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, |
104 | struct nameidata *nd) | 104 | unsigned int flags) |
105 | { | 105 | { |
106 | ntfs_volume *vol = NTFS_SB(dir_ino->i_sb); | 106 | ntfs_volume *vol = NTFS_SB(dir_ino->i_sb); |
107 | struct inode *dent_inode; | 107 | struct inode *dent_inode; |
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index e5ba34818332..8db4b58b2e4b 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c | |||
@@ -49,14 +49,13 @@ void ocfs2_dentry_attach_gen(struct dentry *dentry) | |||
49 | } | 49 | } |
50 | 50 | ||
51 | 51 | ||
52 | static int ocfs2_dentry_revalidate(struct dentry *dentry, | 52 | static int ocfs2_dentry_revalidate(struct dentry *dentry, unsigned int flags) |
53 | struct nameidata *nd) | ||
54 | { | 53 | { |
55 | struct inode *inode; | 54 | struct inode *inode; |
56 | int ret = 0; /* if all else fails, just return false */ | 55 | int ret = 0; /* if all else fails, just return false */ |
57 | struct ocfs2_super *osb; | 56 | struct ocfs2_super *osb; |
58 | 57 | ||
59 | if (nd && nd->flags & LOOKUP_RCU) | 58 | if (flags & LOOKUP_RCU) |
60 | return -ECHILD; | 59 | return -ECHILD; |
61 | 60 | ||
62 | inode = dentry->d_inode; | 61 | inode = dentry->d_inode; |
@@ -170,13 +169,11 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode, | |||
170 | u64 parent_blkno, | 169 | u64 parent_blkno, |
171 | int skip_unhashed) | 170 | int skip_unhashed) |
172 | { | 171 | { |
173 | struct list_head *p; | 172 | struct hlist_node *p; |
174 | struct dentry *dentry = NULL; | 173 | struct dentry *dentry; |
175 | 174 | ||
176 | spin_lock(&inode->i_lock); | 175 | spin_lock(&inode->i_lock); |
177 | list_for_each(p, &inode->i_dentry) { | 176 | hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) { |
178 | dentry = list_entry(p, struct dentry, d_alias); | ||
179 | |||
180 | spin_lock(&dentry->d_lock); | 177 | spin_lock(&dentry->d_lock); |
181 | if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) { | 178 | if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) { |
182 | trace_ocfs2_find_local_alias(dentry->d_name.len, | 179 | trace_ocfs2_find_local_alias(dentry->d_name.len, |
@@ -184,16 +181,13 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode, | |||
184 | 181 | ||
185 | dget_dlock(dentry); | 182 | dget_dlock(dentry); |
186 | spin_unlock(&dentry->d_lock); | 183 | spin_unlock(&dentry->d_lock); |
187 | break; | 184 | spin_unlock(&inode->i_lock); |
185 | return dentry; | ||
188 | } | 186 | } |
189 | spin_unlock(&dentry->d_lock); | 187 | spin_unlock(&dentry->d_lock); |
190 | |||
191 | dentry = NULL; | ||
192 | } | 188 | } |
193 | |||
194 | spin_unlock(&inode->i_lock); | 189 | spin_unlock(&inode->i_lock); |
195 | 190 | return NULL; | |
196 | return dentry; | ||
197 | } | 191 | } |
198 | 192 | ||
199 | DEFINE_SPINLOCK(dentry_attach_lock); | 193 | DEFINE_SPINLOCK(dentry_attach_lock); |
diff --git a/fs/ocfs2/dlmfs/dlmfs.c b/fs/ocfs2/dlmfs/dlmfs.c index e31d6ae013ab..83b6f98e0665 100644 --- a/fs/ocfs2/dlmfs/dlmfs.c +++ b/fs/ocfs2/dlmfs/dlmfs.c | |||
@@ -526,7 +526,7 @@ bail: | |||
526 | static int dlmfs_create(struct inode *dir, | 526 | static int dlmfs_create(struct inode *dir, |
527 | struct dentry *dentry, | 527 | struct dentry *dentry, |
528 | umode_t mode, | 528 | umode_t mode, |
529 | struct nameidata *nd) | 529 | bool excl) |
530 | { | 530 | { |
531 | int status = 0; | 531 | int status = 0; |
532 | struct inode *inode; | 532 | struct inode *inode; |
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 9f39c640cddf..f1fd0741162b 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -98,7 +98,7 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb, | |||
98 | #define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64))) | 98 | #define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64))) |
99 | 99 | ||
100 | static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, | 100 | static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry, |
101 | struct nameidata *nd) | 101 | unsigned int flags) |
102 | { | 102 | { |
103 | int status; | 103 | int status; |
104 | u64 blkno; | 104 | u64 blkno; |
@@ -618,7 +618,7 @@ static int ocfs2_mkdir(struct inode *dir, | |||
618 | static int ocfs2_create(struct inode *dir, | 618 | static int ocfs2_create(struct inode *dir, |
619 | struct dentry *dentry, | 619 | struct dentry *dentry, |
620 | umode_t mode, | 620 | umode_t mode, |
621 | struct nameidata *nd) | 621 | bool excl) |
622 | { | 622 | { |
623 | int ret; | 623 | int ret; |
624 | 624 | ||
diff --git a/fs/omfs/dir.c b/fs/omfs/dir.c index f00576ec320f..fb5b3ff79dc6 100644 --- a/fs/omfs/dir.c +++ b/fs/omfs/dir.c | |||
@@ -285,13 +285,13 @@ static int omfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
285 | } | 285 | } |
286 | 286 | ||
287 | static int omfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 287 | static int omfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
288 | struct nameidata *nd) | 288 | bool excl) |
289 | { | 289 | { |
290 | return omfs_add_node(dir, dentry, mode | S_IFREG); | 290 | return omfs_add_node(dir, dentry, mode | S_IFREG); |
291 | } | 291 | } |
292 | 292 | ||
293 | static struct dentry *omfs_lookup(struct inode *dir, struct dentry *dentry, | 293 | static struct dentry *omfs_lookup(struct inode *dir, struct dentry *dentry, |
294 | struct nameidata *nd) | 294 | unsigned int flags) |
295 | { | 295 | { |
296 | struct buffer_head *bh; | 296 | struct buffer_head *bh; |
297 | struct inode *inode = NULL; | 297 | struct inode *inode = NULL; |
@@ -537,25 +537,6 @@ static int chown_common(struct path *path, uid_t user, gid_t group) | |||
537 | return error; | 537 | return error; |
538 | } | 538 | } |
539 | 539 | ||
540 | SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group) | ||
541 | { | ||
542 | struct path path; | ||
543 | int error; | ||
544 | |||
545 | error = user_path(filename, &path); | ||
546 | if (error) | ||
547 | goto out; | ||
548 | error = mnt_want_write(path.mnt); | ||
549 | if (error) | ||
550 | goto out_release; | ||
551 | error = chown_common(&path, user, group); | ||
552 | mnt_drop_write(path.mnt); | ||
553 | out_release: | ||
554 | path_put(&path); | ||
555 | out: | ||
556 | return error; | ||
557 | } | ||
558 | |||
559 | SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user, | 540 | SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user, |
560 | gid_t, group, int, flag) | 541 | gid_t, group, int, flag) |
561 | { | 542 | { |
@@ -583,23 +564,15 @@ out: | |||
583 | return error; | 564 | return error; |
584 | } | 565 | } |
585 | 566 | ||
586 | SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group) | 567 | SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group) |
587 | { | 568 | { |
588 | struct path path; | 569 | return sys_fchownat(AT_FDCWD, filename, user, group, 0); |
589 | int error; | 570 | } |
590 | 571 | ||
591 | error = user_lpath(filename, &path); | 572 | SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group) |
592 | if (error) | 573 | { |
593 | goto out; | 574 | return sys_fchownat(AT_FDCWD, filename, user, group, |
594 | error = mnt_want_write(path.mnt); | 575 | AT_SYMLINK_NOFOLLOW); |
595 | if (error) | ||
596 | goto out_release; | ||
597 | error = chown_common(&path, user, group); | ||
598 | mnt_drop_write(path.mnt); | ||
599 | out_release: | ||
600 | path_put(&path); | ||
601 | out: | ||
602 | return error; | ||
603 | } | 576 | } |
604 | 577 | ||
605 | SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) | 578 | SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) |
@@ -667,10 +640,9 @@ int open_check_o_direct(struct file *f) | |||
667 | return 0; | 640 | return 0; |
668 | } | 641 | } |
669 | 642 | ||
670 | static struct file *do_dentry_open(struct dentry *dentry, struct vfsmount *mnt, | 643 | static int do_dentry_open(struct file *f, |
671 | struct file *f, | 644 | int (*open)(struct inode *, struct file *), |
672 | int (*open)(struct inode *, struct file *), | 645 | const struct cred *cred) |
673 | const struct cred *cred) | ||
674 | { | 646 | { |
675 | static const struct file_operations empty_fops = {}; | 647 | static const struct file_operations empty_fops = {}; |
676 | struct inode *inode; | 648 | struct inode *inode; |
@@ -682,9 +654,9 @@ static struct file *do_dentry_open(struct dentry *dentry, struct vfsmount *mnt, | |||
682 | if (unlikely(f->f_flags & O_PATH)) | 654 | if (unlikely(f->f_flags & O_PATH)) |
683 | f->f_mode = FMODE_PATH; | 655 | f->f_mode = FMODE_PATH; |
684 | 656 | ||
685 | inode = dentry->d_inode; | 657 | inode = f->f_path.dentry->d_inode; |
686 | if (f->f_mode & FMODE_WRITE) { | 658 | if (f->f_mode & FMODE_WRITE) { |
687 | error = __get_file_write_access(inode, mnt); | 659 | error = __get_file_write_access(inode, f->f_path.mnt); |
688 | if (error) | 660 | if (error) |
689 | goto cleanup_file; | 661 | goto cleanup_file; |
690 | if (!special_file(inode->i_mode)) | 662 | if (!special_file(inode->i_mode)) |
@@ -692,14 +664,12 @@ static struct file *do_dentry_open(struct dentry *dentry, struct vfsmount *mnt, | |||
692 | } | 664 | } |
693 | 665 | ||
694 | f->f_mapping = inode->i_mapping; | 666 | f->f_mapping = inode->i_mapping; |
695 | f->f_path.dentry = dentry; | ||
696 | f->f_path.mnt = mnt; | ||
697 | f->f_pos = 0; | 667 | f->f_pos = 0; |
698 | file_sb_list_add(f, inode->i_sb); | 668 | file_sb_list_add(f, inode->i_sb); |
699 | 669 | ||
700 | if (unlikely(f->f_mode & FMODE_PATH)) { | 670 | if (unlikely(f->f_mode & FMODE_PATH)) { |
701 | f->f_op = &empty_fops; | 671 | f->f_op = &empty_fops; |
702 | return f; | 672 | return 0; |
703 | } | 673 | } |
704 | 674 | ||
705 | f->f_op = fops_get(inode->i_fop); | 675 | f->f_op = fops_get(inode->i_fop); |
@@ -726,10 +696,11 @@ static struct file *do_dentry_open(struct dentry *dentry, struct vfsmount *mnt, | |||
726 | 696 | ||
727 | file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping); | 697 | file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping); |
728 | 698 | ||
729 | return f; | 699 | return 0; |
730 | 700 | ||
731 | cleanup_all: | 701 | cleanup_all: |
732 | fops_put(f->f_op); | 702 | fops_put(f->f_op); |
703 | file_sb_list_del(f); | ||
733 | if (f->f_mode & FMODE_WRITE) { | 704 | if (f->f_mode & FMODE_WRITE) { |
734 | put_write_access(inode); | 705 | put_write_access(inode); |
735 | if (!special_file(inode->i_mode)) { | 706 | if (!special_file(inode->i_mode)) { |
@@ -740,124 +711,62 @@ cleanup_all: | |||
740 | * here, so just reset the state. | 711 | * here, so just reset the state. |
741 | */ | 712 | */ |
742 | file_reset_write(f); | 713 | file_reset_write(f); |
743 | mnt_drop_write(mnt); | 714 | mnt_drop_write(f->f_path.mnt); |
744 | } | 715 | } |
745 | } | 716 | } |
746 | file_sb_list_del(f); | ||
747 | f->f_path.dentry = NULL; | ||
748 | f->f_path.mnt = NULL; | ||
749 | cleanup_file: | 717 | cleanup_file: |
750 | dput(dentry); | 718 | path_put(&f->f_path); |
751 | mntput(mnt); | 719 | f->f_path.mnt = NULL; |
752 | return ERR_PTR(error); | 720 | f->f_path.dentry = NULL; |
753 | } | 721 | return error; |
754 | |||
755 | static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | ||
756 | struct file *f, | ||
757 | int (*open)(struct inode *, struct file *), | ||
758 | const struct cred *cred) | ||
759 | { | ||
760 | struct file *res = do_dentry_open(dentry, mnt, f, open, cred); | ||
761 | if (!IS_ERR(res)) { | ||
762 | int error = open_check_o_direct(f); | ||
763 | if (error) { | ||
764 | fput(res); | ||
765 | res = ERR_PTR(error); | ||
766 | } | ||
767 | } else { | ||
768 | put_filp(f); | ||
769 | } | ||
770 | return res; | ||
771 | } | 722 | } |
772 | 723 | ||
773 | /** | 724 | /** |
774 | * lookup_instantiate_filp - instantiates the open intent filp | 725 | * finish_open - finish opening a file |
775 | * @nd: pointer to nameidata | 726 | * @od: opaque open data |
776 | * @dentry: pointer to dentry | 727 | * @dentry: pointer to dentry |
777 | * @open: open callback | 728 | * @open: open callback |
778 | * | 729 | * |
779 | * Helper for filesystems that want to use lookup open intents and pass back | 730 | * This can be used to finish opening a file passed to i_op->atomic_open(). |
780 | * a fully instantiated struct file to the caller. | 731 | * |
781 | * This function is meant to be called from within a filesystem's | ||
782 | * lookup method. | ||
783 | * Beware of calling it for non-regular files! Those ->open methods might block | ||
784 | * (e.g. in fifo_open), leaving you with parent locked (and in case of fifo, | ||
785 | * leading to a deadlock, as nobody can open that fifo anymore, because | ||
786 | * another process to open fifo will block on locked parent when doing lookup). | ||
787 | * Note that in case of error, nd->intent.open.file is destroyed, but the | ||
788 | * path information remains valid. | ||
789 | * If the open callback is set to NULL, then the standard f_op->open() | 732 | * If the open callback is set to NULL, then the standard f_op->open() |
790 | * filesystem callback is substituted. | 733 | * filesystem callback is substituted. |
791 | */ | 734 | */ |
792 | struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, | 735 | int finish_open(struct file *file, struct dentry *dentry, |
793 | int (*open)(struct inode *, struct file *)) | 736 | int (*open)(struct inode *, struct file *), |
737 | int *opened) | ||
794 | { | 738 | { |
795 | const struct cred *cred = current_cred(); | 739 | int error; |
740 | BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */ | ||
796 | 741 | ||
797 | if (IS_ERR(nd->intent.open.file)) | 742 | mntget(file->f_path.mnt); |
798 | goto out; | 743 | file->f_path.dentry = dget(dentry); |
799 | if (IS_ERR(dentry)) | 744 | |
800 | goto out_err; | 745 | error = do_dentry_open(file, open, current_cred()); |
801 | nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt), | 746 | if (!error) |
802 | nd->intent.open.file, | 747 | *opened |= FILE_OPENED; |
803 | open, cred); | 748 | |
804 | out: | 749 | return error; |
805 | return nd->intent.open.file; | ||
806 | out_err: | ||
807 | release_open_intent(nd); | ||
808 | nd->intent.open.file = ERR_CAST(dentry); | ||
809 | goto out; | ||
810 | } | 750 | } |
811 | EXPORT_SYMBOL_GPL(lookup_instantiate_filp); | 751 | EXPORT_SYMBOL(finish_open); |
812 | 752 | ||
813 | /** | 753 | /** |
814 | * nameidata_to_filp - convert a nameidata to an open filp. | 754 | * finish_no_open - finish ->atomic_open() without opening the file |
815 | * @nd: pointer to nameidata | 755 | * |
816 | * @flags: open flags | 756 | * @od: opaque open data |
757 | * @dentry: dentry or NULL (as returned from ->lookup()) | ||
817 | * | 758 | * |
818 | * Note that this function destroys the original nameidata | 759 | * This can be used to set the result of a successful lookup in ->atomic_open(). |
760 | * The filesystem's atomic_open() method shall return NULL after calling this. | ||
819 | */ | 761 | */ |
820 | struct file *nameidata_to_filp(struct nameidata *nd) | 762 | int finish_no_open(struct file *file, struct dentry *dentry) |
821 | { | 763 | { |
822 | const struct cred *cred = current_cred(); | 764 | file->f_path.dentry = dentry; |
823 | struct file *filp; | 765 | return 1; |
824 | |||
825 | /* Pick up the filp from the open intent */ | ||
826 | filp = nd->intent.open.file; | ||
827 | |||
828 | /* Has the filesystem initialised the file for us? */ | ||
829 | if (filp->f_path.dentry != NULL) { | ||
830 | nd->intent.open.file = NULL; | ||
831 | } else { | ||
832 | struct file *res; | ||
833 | |||
834 | path_get(&nd->path); | ||
835 | res = do_dentry_open(nd->path.dentry, nd->path.mnt, | ||
836 | filp, NULL, cred); | ||
837 | if (!IS_ERR(res)) { | ||
838 | int error; | ||
839 | |||
840 | nd->intent.open.file = NULL; | ||
841 | BUG_ON(res != filp); | ||
842 | |||
843 | error = open_check_o_direct(filp); | ||
844 | if (error) { | ||
845 | fput(filp); | ||
846 | filp = ERR_PTR(error); | ||
847 | } | ||
848 | } else { | ||
849 | /* Allow nd->intent.open.file to be recycled */ | ||
850 | filp = res; | ||
851 | } | ||
852 | } | ||
853 | return filp; | ||
854 | } | 766 | } |
767 | EXPORT_SYMBOL(finish_no_open); | ||
855 | 768 | ||
856 | /* | 769 | struct file *dentry_open(const struct path *path, int flags, |
857 | * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an | ||
858 | * error. | ||
859 | */ | ||
860 | struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, | ||
861 | const struct cred *cred) | 770 | const struct cred *cred) |
862 | { | 771 | { |
863 | int error; | 772 | int error; |
@@ -866,18 +775,28 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, | |||
866 | validate_creds(cred); | 775 | validate_creds(cred); |
867 | 776 | ||
868 | /* We must always pass in a valid mount pointer. */ | 777 | /* We must always pass in a valid mount pointer. */ |
869 | BUG_ON(!mnt); | 778 | BUG_ON(!path->mnt); |
870 | 779 | ||
871 | error = -ENFILE; | 780 | error = -ENFILE; |
872 | f = get_empty_filp(); | 781 | f = get_empty_filp(); |
873 | if (f == NULL) { | 782 | if (f == NULL) |
874 | dput(dentry); | ||
875 | mntput(mnt); | ||
876 | return ERR_PTR(error); | 783 | return ERR_PTR(error); |
877 | } | ||
878 | 784 | ||
879 | f->f_flags = flags; | 785 | f->f_flags = flags; |
880 | return __dentry_open(dentry, mnt, f, NULL, cred); | 786 | f->f_path = *path; |
787 | path_get(&f->f_path); | ||
788 | error = do_dentry_open(f, NULL, cred); | ||
789 | if (!error) { | ||
790 | error = open_check_o_direct(f); | ||
791 | if (error) { | ||
792 | fput(f); | ||
793 | f = ERR_PTR(error); | ||
794 | } | ||
795 | } else { | ||
796 | put_filp(f); | ||
797 | f = ERR_PTR(error); | ||
798 | } | ||
799 | return f; | ||
881 | } | 800 | } |
882 | EXPORT_SYMBOL(dentry_open); | 801 | EXPORT_SYMBOL(dentry_open); |
883 | 802 | ||
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index bc49c975d501..4a3477949bca 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c | |||
@@ -170,13 +170,13 @@ static const struct file_operations openprom_operations = { | |||
170 | .llseek = generic_file_llseek, | 170 | .llseek = generic_file_llseek, |
171 | }; | 171 | }; |
172 | 172 | ||
173 | static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, struct nameidata *); | 173 | static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, unsigned int); |
174 | 174 | ||
175 | static const struct inode_operations openprom_inode_operations = { | 175 | static const struct inode_operations openprom_inode_operations = { |
176 | .lookup = openpromfs_lookup, | 176 | .lookup = openpromfs_lookup, |
177 | }; | 177 | }; |
178 | 178 | ||
179 | static struct dentry *openpromfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 179 | static struct dentry *openpromfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
180 | { | 180 | { |
181 | struct op_inode_info *ent_oi, *oi = OP_I(dir); | 181 | struct op_inode_info *ent_oi, *oi = OP_I(dir); |
182 | struct device_node *dp, *child; | 182 | struct device_node *dp, *child; |
diff --git a/fs/pnode.c b/fs/pnode.c index bed378db0758..3e000a51ac0d 100644 --- a/fs/pnode.c +++ b/fs/pnode.c | |||
@@ -237,8 +237,9 @@ int propagate_mnt(struct mount *dest_mnt, struct dentry *dest_dentry, | |||
237 | 237 | ||
238 | source = get_source(m, prev_dest_mnt, prev_src_mnt, &type); | 238 | source = get_source(m, prev_dest_mnt, prev_src_mnt, &type); |
239 | 239 | ||
240 | if (!(child = copy_tree(source, source->mnt.mnt_root, type))) { | 240 | child = copy_tree(source, source->mnt.mnt_root, type); |
241 | ret = -ENOMEM; | 241 | if (IS_ERR(child)) { |
242 | ret = PTR_ERR(child); | ||
242 | list_splice(tree_list, tmp_list.prev); | 243 | list_splice(tree_list, tmp_list.prev); |
243 | goto out; | 244 | goto out; |
244 | } | 245 | } |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 437195f204e1..2772208338f8 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1427,16 +1427,19 @@ static int proc_exe_link(struct dentry *dentry, struct path *exe_path) | |||
1427 | static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) | 1427 | static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) |
1428 | { | 1428 | { |
1429 | struct inode *inode = dentry->d_inode; | 1429 | struct inode *inode = dentry->d_inode; |
1430 | struct path path; | ||
1430 | int error = -EACCES; | 1431 | int error = -EACCES; |
1431 | 1432 | ||
1432 | /* We don't need a base pointer in the /proc filesystem */ | ||
1433 | path_put(&nd->path); | ||
1434 | |||
1435 | /* Are we allowed to snoop on the tasks file descriptors? */ | 1433 | /* Are we allowed to snoop on the tasks file descriptors? */ |
1436 | if (!proc_fd_access_allowed(inode)) | 1434 | if (!proc_fd_access_allowed(inode)) |
1437 | goto out; | 1435 | goto out; |
1438 | 1436 | ||
1439 | error = PROC_I(inode)->op.proc_get_link(dentry, &nd->path); | 1437 | error = PROC_I(inode)->op.proc_get_link(dentry, &path); |
1438 | if (error) | ||
1439 | goto out; | ||
1440 | |||
1441 | nd_jump_link(nd, &path); | ||
1442 | return NULL; | ||
1440 | out: | 1443 | out: |
1441 | return ERR_PTR(error); | 1444 | return ERR_PTR(error); |
1442 | } | 1445 | } |
@@ -1601,13 +1604,13 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
1601 | * made this apply to all per process world readable and executable | 1604 | * made this apply to all per process world readable and executable |
1602 | * directories. | 1605 | * directories. |
1603 | */ | 1606 | */ |
1604 | int pid_revalidate(struct dentry *dentry, struct nameidata *nd) | 1607 | int pid_revalidate(struct dentry *dentry, unsigned int flags) |
1605 | { | 1608 | { |
1606 | struct inode *inode; | 1609 | struct inode *inode; |
1607 | struct task_struct *task; | 1610 | struct task_struct *task; |
1608 | const struct cred *cred; | 1611 | const struct cred *cred; |
1609 | 1612 | ||
1610 | if (nd && nd->flags & LOOKUP_RCU) | 1613 | if (flags & LOOKUP_RCU) |
1611 | return -ECHILD; | 1614 | return -ECHILD; |
1612 | 1615 | ||
1613 | inode = dentry->d_inode; | 1616 | inode = dentry->d_inode; |
@@ -1781,7 +1784,7 @@ static int proc_fd_link(struct dentry *dentry, struct path *path) | |||
1781 | return proc_fd_info(dentry->d_inode, path, NULL); | 1784 | return proc_fd_info(dentry->d_inode, path, NULL); |
1782 | } | 1785 | } |
1783 | 1786 | ||
1784 | static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) | 1787 | static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags) |
1785 | { | 1788 | { |
1786 | struct inode *inode; | 1789 | struct inode *inode; |
1787 | struct task_struct *task; | 1790 | struct task_struct *task; |
@@ -1789,7 +1792,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1789 | struct files_struct *files; | 1792 | struct files_struct *files; |
1790 | const struct cred *cred; | 1793 | const struct cred *cred; |
1791 | 1794 | ||
1792 | if (nd && nd->flags & LOOKUP_RCU) | 1795 | if (flags & LOOKUP_RCU) |
1793 | return -ECHILD; | 1796 | return -ECHILD; |
1794 | 1797 | ||
1795 | inode = dentry->d_inode; | 1798 | inode = dentry->d_inode; |
@@ -1868,7 +1871,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir, | |||
1868 | d_set_d_op(dentry, &tid_fd_dentry_operations); | 1871 | d_set_d_op(dentry, &tid_fd_dentry_operations); |
1869 | d_add(dentry, inode); | 1872 | d_add(dentry, inode); |
1870 | /* Close the race of the process dying before we return the dentry */ | 1873 | /* Close the race of the process dying before we return the dentry */ |
1871 | if (tid_fd_revalidate(dentry, NULL)) | 1874 | if (tid_fd_revalidate(dentry, 0)) |
1872 | error = NULL; | 1875 | error = NULL; |
1873 | 1876 | ||
1874 | out: | 1877 | out: |
@@ -1956,7 +1959,7 @@ out_no_task: | |||
1956 | } | 1959 | } |
1957 | 1960 | ||
1958 | static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry, | 1961 | static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry, |
1959 | struct nameidata *nd) | 1962 | unsigned int flags) |
1960 | { | 1963 | { |
1961 | return proc_lookupfd_common(dir, dentry, proc_fd_instantiate); | 1964 | return proc_lookupfd_common(dir, dentry, proc_fd_instantiate); |
1962 | } | 1965 | } |
@@ -2003,7 +2006,7 @@ static int dname_to_vma_addr(struct dentry *dentry, | |||
2003 | return 0; | 2006 | return 0; |
2004 | } | 2007 | } |
2005 | 2008 | ||
2006 | static int map_files_d_revalidate(struct dentry *dentry, struct nameidata *nd) | 2009 | static int map_files_d_revalidate(struct dentry *dentry, unsigned int flags) |
2007 | { | 2010 | { |
2008 | unsigned long vm_start, vm_end; | 2011 | unsigned long vm_start, vm_end; |
2009 | bool exact_vma_exists = false; | 2012 | bool exact_vma_exists = false; |
@@ -2013,7 +2016,7 @@ static int map_files_d_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
2013 | struct inode *inode; | 2016 | struct inode *inode; |
2014 | int status = 0; | 2017 | int status = 0; |
2015 | 2018 | ||
2016 | if (nd && nd->flags & LOOKUP_RCU) | 2019 | if (flags & LOOKUP_RCU) |
2017 | return -ECHILD; | 2020 | return -ECHILD; |
2018 | 2021 | ||
2019 | if (!capable(CAP_SYS_ADMIN)) { | 2022 | if (!capable(CAP_SYS_ADMIN)) { |
@@ -2145,7 +2148,7 @@ proc_map_files_instantiate(struct inode *dir, struct dentry *dentry, | |||
2145 | } | 2148 | } |
2146 | 2149 | ||
2147 | static struct dentry *proc_map_files_lookup(struct inode *dir, | 2150 | static struct dentry *proc_map_files_lookup(struct inode *dir, |
2148 | struct dentry *dentry, struct nameidata *nd) | 2151 | struct dentry *dentry, unsigned int flags) |
2149 | { | 2152 | { |
2150 | unsigned long vm_start, vm_end; | 2153 | unsigned long vm_start, vm_end; |
2151 | struct vm_area_struct *vma; | 2154 | struct vm_area_struct *vma; |
@@ -2371,7 +2374,7 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir, | |||
2371 | d_set_d_op(dentry, &tid_fd_dentry_operations); | 2374 | d_set_d_op(dentry, &tid_fd_dentry_operations); |
2372 | d_add(dentry, inode); | 2375 | d_add(dentry, inode); |
2373 | /* Close the race of the process dying before we return the dentry */ | 2376 | /* Close the race of the process dying before we return the dentry */ |
2374 | if (tid_fd_revalidate(dentry, NULL)) | 2377 | if (tid_fd_revalidate(dentry, 0)) |
2375 | error = NULL; | 2378 | error = NULL; |
2376 | 2379 | ||
2377 | out: | 2380 | out: |
@@ -2380,7 +2383,7 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir, | |||
2380 | 2383 | ||
2381 | static struct dentry *proc_lookupfdinfo(struct inode *dir, | 2384 | static struct dentry *proc_lookupfdinfo(struct inode *dir, |
2382 | struct dentry *dentry, | 2385 | struct dentry *dentry, |
2383 | struct nameidata *nd) | 2386 | unsigned int flags) |
2384 | { | 2387 | { |
2385 | return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate); | 2388 | return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate); |
2386 | } | 2389 | } |
@@ -2430,7 +2433,7 @@ static struct dentry *proc_pident_instantiate(struct inode *dir, | |||
2430 | d_set_d_op(dentry, &pid_dentry_operations); | 2433 | d_set_d_op(dentry, &pid_dentry_operations); |
2431 | d_add(dentry, inode); | 2434 | d_add(dentry, inode); |
2432 | /* Close the race of the process dying before we return the dentry */ | 2435 | /* Close the race of the process dying before we return the dentry */ |
2433 | if (pid_revalidate(dentry, NULL)) | 2436 | if (pid_revalidate(dentry, 0)) |
2434 | error = NULL; | 2437 | error = NULL; |
2435 | out: | 2438 | out: |
2436 | return error; | 2439 | return error; |
@@ -2630,7 +2633,7 @@ static const struct file_operations proc_attr_dir_operations = { | |||
2630 | }; | 2633 | }; |
2631 | 2634 | ||
2632 | static struct dentry *proc_attr_dir_lookup(struct inode *dir, | 2635 | static struct dentry *proc_attr_dir_lookup(struct inode *dir, |
2633 | struct dentry *dentry, struct nameidata *nd) | 2636 | struct dentry *dentry, unsigned int flags) |
2634 | { | 2637 | { |
2635 | return proc_pident_lookup(dir, dentry, | 2638 | return proc_pident_lookup(dir, dentry, |
2636 | attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff)); | 2639 | attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff)); |
@@ -3114,7 +3117,8 @@ static const struct file_operations proc_tgid_base_operations = { | |||
3114 | .llseek = default_llseek, | 3117 | .llseek = default_llseek, |
3115 | }; | 3118 | }; |
3116 | 3119 | ||
3117 | static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ | 3120 | static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
3121 | { | ||
3118 | return proc_pident_lookup(dir, dentry, | 3122 | return proc_pident_lookup(dir, dentry, |
3119 | tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff)); | 3123 | tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff)); |
3120 | } | 3124 | } |
@@ -3237,13 +3241,13 @@ static struct dentry *proc_pid_instantiate(struct inode *dir, | |||
3237 | 3241 | ||
3238 | d_add(dentry, inode); | 3242 | d_add(dentry, inode); |
3239 | /* Close the race of the process dying before we return the dentry */ | 3243 | /* Close the race of the process dying before we return the dentry */ |
3240 | if (pid_revalidate(dentry, NULL)) | 3244 | if (pid_revalidate(dentry, 0)) |
3241 | error = NULL; | 3245 | error = NULL; |
3242 | out: | 3246 | out: |
3243 | return error; | 3247 | return error; |
3244 | } | 3248 | } |
3245 | 3249 | ||
3246 | struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) | 3250 | struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags) |
3247 | { | 3251 | { |
3248 | struct dentry *result; | 3252 | struct dentry *result; |
3249 | struct task_struct *task; | 3253 | struct task_struct *task; |
@@ -3470,7 +3474,8 @@ static int proc_tid_base_readdir(struct file * filp, | |||
3470 | tid_base_stuff,ARRAY_SIZE(tid_base_stuff)); | 3474 | tid_base_stuff,ARRAY_SIZE(tid_base_stuff)); |
3471 | } | 3475 | } |
3472 | 3476 | ||
3473 | static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ | 3477 | static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
3478 | { | ||
3474 | return proc_pident_lookup(dir, dentry, | 3479 | return proc_pident_lookup(dir, dentry, |
3475 | tid_base_stuff, ARRAY_SIZE(tid_base_stuff)); | 3480 | tid_base_stuff, ARRAY_SIZE(tid_base_stuff)); |
3476 | } | 3481 | } |
@@ -3508,13 +3513,13 @@ static struct dentry *proc_task_instantiate(struct inode *dir, | |||
3508 | 3513 | ||
3509 | d_add(dentry, inode); | 3514 | d_add(dentry, inode); |
3510 | /* Close the race of the process dying before we return the dentry */ | 3515 | /* Close the race of the process dying before we return the dentry */ |
3511 | if (pid_revalidate(dentry, NULL)) | 3516 | if (pid_revalidate(dentry, 0)) |
3512 | error = NULL; | 3517 | error = NULL; |
3513 | out: | 3518 | out: |
3514 | return error; | 3519 | return error; |
3515 | } | 3520 | } |
3516 | 3521 | ||
3517 | static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) | 3522 | static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags) |
3518 | { | 3523 | { |
3519 | struct dentry *result = ERR_PTR(-ENOENT); | 3524 | struct dentry *result = ERR_PTR(-ENOENT); |
3520 | struct task_struct *task; | 3525 | struct task_struct *task; |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 2edf34f2eb61..b3647fe6a608 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -446,7 +446,7 @@ out_unlock: | |||
446 | } | 446 | } |
447 | 447 | ||
448 | struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry, | 448 | struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry, |
449 | struct nameidata *nd) | 449 | unsigned int flags) |
450 | { | 450 | { |
451 | return proc_lookup_de(PDE(dir), dir, dentry); | 451 | return proc_lookup_de(PDE(dir), dir, dentry); |
452 | } | 452 | } |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index eca4aca5b6e2..e1167a1c9126 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -106,7 +106,7 @@ void pde_users_dec(struct proc_dir_entry *pde); | |||
106 | 106 | ||
107 | extern spinlock_t proc_subdir_lock; | 107 | extern spinlock_t proc_subdir_lock; |
108 | 108 | ||
109 | struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *); | 109 | struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int); |
110 | int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir); | 110 | int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir); |
111 | unsigned long task_vsize(struct mm_struct *); | 111 | unsigned long task_vsize(struct mm_struct *); |
112 | unsigned long task_statm(struct mm_struct *, | 112 | unsigned long task_statm(struct mm_struct *, |
@@ -132,7 +132,7 @@ int proc_remount(struct super_block *sb, int *flags, char *data); | |||
132 | * of the /proc/<pid> subdirectories. | 132 | * of the /proc/<pid> subdirectories. |
133 | */ | 133 | */ |
134 | int proc_readdir(struct file *, void *, filldir_t); | 134 | int proc_readdir(struct file *, void *, filldir_t); |
135 | struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *); | 135 | struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int); |
136 | 136 | ||
137 | 137 | ||
138 | 138 | ||
@@ -142,7 +142,7 @@ typedef struct dentry *instantiate_t(struct inode *, struct dentry *, | |||
142 | int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir, | 142 | int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir, |
143 | const char *name, int len, | 143 | const char *name, int len, |
144 | instantiate_t instantiate, struct task_struct *task, const void *ptr); | 144 | instantiate_t instantiate, struct task_struct *task, const void *ptr); |
145 | int pid_revalidate(struct dentry *dentry, struct nameidata *nd); | 145 | int pid_revalidate(struct dentry *dentry, unsigned int flags); |
146 | struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task); | 146 | struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task); |
147 | extern const struct dentry_operations pid_dentry_operations; | 147 | extern const struct dentry_operations pid_dentry_operations; |
148 | int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); | 148 | int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); |
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c index 0d9e23a39e49..b178ed733c36 100644 --- a/fs/proc/namespaces.c +++ b/fs/proc/namespaces.c | |||
@@ -56,7 +56,7 @@ static struct dentry *proc_ns_instantiate(struct inode *dir, | |||
56 | d_set_d_op(dentry, &pid_dentry_operations); | 56 | d_set_d_op(dentry, &pid_dentry_operations); |
57 | d_add(dentry, inode); | 57 | d_add(dentry, inode); |
58 | /* Close the race of the process dying before we return the dentry */ | 58 | /* Close the race of the process dying before we return the dentry */ |
59 | if (pid_revalidate(dentry, NULL)) | 59 | if (pid_revalidate(dentry, 0)) |
60 | error = NULL; | 60 | error = NULL; |
61 | out: | 61 | out: |
62 | return error; | 62 | return error; |
@@ -140,7 +140,7 @@ const struct file_operations proc_ns_dir_operations = { | |||
140 | }; | 140 | }; |
141 | 141 | ||
142 | static struct dentry *proc_ns_dir_lookup(struct inode *dir, | 142 | static struct dentry *proc_ns_dir_lookup(struct inode *dir, |
143 | struct dentry *dentry, struct nameidata *nd) | 143 | struct dentry *dentry, unsigned int flags) |
144 | { | 144 | { |
145 | struct dentry *error; | 145 | struct dentry *error; |
146 | struct task_struct *task = get_proc_task(dir); | 146 | struct task_struct *task = get_proc_task(dir); |
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c index 06e1cc17caf6..fe72cd073dea 100644 --- a/fs/proc/proc_net.c +++ b/fs/proc/proc_net.c | |||
@@ -119,7 +119,7 @@ static struct net *get_proc_task_net(struct inode *dir) | |||
119 | } | 119 | } |
120 | 120 | ||
121 | static struct dentry *proc_tgid_net_lookup(struct inode *dir, | 121 | static struct dentry *proc_tgid_net_lookup(struct inode *dir, |
122 | struct dentry *dentry, struct nameidata *nd) | 122 | struct dentry *dentry, unsigned int flags) |
123 | { | 123 | { |
124 | struct dentry *de; | 124 | struct dentry *de; |
125 | struct net *net; | 125 | struct net *net; |
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 3476bca8f7af..dfafeb2b05a0 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c | |||
@@ -433,7 +433,7 @@ static struct ctl_table_header *grab_header(struct inode *inode) | |||
433 | } | 433 | } |
434 | 434 | ||
435 | static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry, | 435 | static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry, |
436 | struct nameidata *nd) | 436 | unsigned int flags) |
437 | { | 437 | { |
438 | struct ctl_table_header *head = grab_header(dir); | 438 | struct ctl_table_header *head = grab_header(dir); |
439 | struct ctl_table_header *h = NULL; | 439 | struct ctl_table_header *h = NULL; |
@@ -794,9 +794,9 @@ static const struct inode_operations proc_sys_dir_operations = { | |||
794 | .getattr = proc_sys_getattr, | 794 | .getattr = proc_sys_getattr, |
795 | }; | 795 | }; |
796 | 796 | ||
797 | static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd) | 797 | static int proc_sys_revalidate(struct dentry *dentry, unsigned int flags) |
798 | { | 798 | { |
799 | if (nd->flags & LOOKUP_RCU) | 799 | if (flags & LOOKUP_RCU) |
800 | return -ECHILD; | 800 | return -ECHILD; |
801 | return !PROC_I(dentry->d_inode)->sysctl->unregistering; | 801 | return !PROC_I(dentry->d_inode)->sysctl->unregistering; |
802 | } | 802 | } |
diff --git a/fs/proc/root.c b/fs/proc/root.c index 7c30fce037c0..9a2d9fd7cadd 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -111,7 +111,7 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, | |||
111 | options = data; | 111 | options = data; |
112 | } | 112 | } |
113 | 113 | ||
114 | sb = sget(fs_type, proc_test_super, proc_set_super, ns); | 114 | sb = sget(fs_type, proc_test_super, proc_set_super, flags, ns); |
115 | if (IS_ERR(sb)) | 115 | if (IS_ERR(sb)) |
116 | return ERR_CAST(sb); | 116 | return ERR_CAST(sb); |
117 | 117 | ||
@@ -121,7 +121,6 @@ static struct dentry *proc_mount(struct file_system_type *fs_type, | |||
121 | } | 121 | } |
122 | 122 | ||
123 | if (!sb->s_root) { | 123 | if (!sb->s_root) { |
124 | sb->s_flags = flags; | ||
125 | err = proc_fill_super(sb); | 124 | err = proc_fill_super(sb); |
126 | if (err) { | 125 | if (err) { |
127 | deactivate_locked_super(sb); | 126 | deactivate_locked_super(sb); |
@@ -200,13 +199,12 @@ static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct | |||
200 | return 0; | 199 | return 0; |
201 | } | 200 | } |
202 | 201 | ||
203 | static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd) | 202 | static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags) |
204 | { | 203 | { |
205 | if (!proc_lookup(dir, dentry, nd)) { | 204 | if (!proc_lookup(dir, dentry, flags)) |
206 | return NULL; | 205 | return NULL; |
207 | } | ||
208 | 206 | ||
209 | return proc_pid_lookup(dir, dentry, nd); | 207 | return proc_pid_lookup(dir, dentry, flags); |
210 | } | 208 | } |
211 | 209 | ||
212 | static int proc_root_readdir(struct file * filp, | 210 | static int proc_root_readdir(struct file * filp, |
diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c index 5e289a7cbad1..5fe34c355e85 100644 --- a/fs/proc_namespace.c +++ b/fs/proc_namespace.c | |||
@@ -17,7 +17,7 @@ | |||
17 | 17 | ||
18 | static unsigned mounts_poll(struct file *file, poll_table *wait) | 18 | static unsigned mounts_poll(struct file *file, poll_table *wait) |
19 | { | 19 | { |
20 | struct proc_mounts *p = file->private_data; | 20 | struct proc_mounts *p = proc_mounts(file->private_data); |
21 | struct mnt_namespace *ns = p->ns; | 21 | struct mnt_namespace *ns = p->ns; |
22 | unsigned res = POLLIN | POLLRDNORM; | 22 | unsigned res = POLLIN | POLLRDNORM; |
23 | 23 | ||
@@ -121,7 +121,7 @@ out: | |||
121 | 121 | ||
122 | static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt) | 122 | static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt) |
123 | { | 123 | { |
124 | struct proc_mounts *p = m->private; | 124 | struct proc_mounts *p = proc_mounts(m); |
125 | struct mount *r = real_mount(mnt); | 125 | struct mount *r = real_mount(mnt); |
126 | struct super_block *sb = mnt->mnt_sb; | 126 | struct super_block *sb = mnt->mnt_sb; |
127 | struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; | 127 | struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; |
@@ -268,7 +268,6 @@ static int mounts_open_common(struct inode *inode, struct file *file, | |||
268 | if (ret) | 268 | if (ret) |
269 | goto err_free; | 269 | goto err_free; |
270 | 270 | ||
271 | p->m.private = p; | ||
272 | p->ns = ns; | 271 | p->ns = ns; |
273 | p->root = root; | 272 | p->root = root; |
274 | p->m.poll_event = ns->event; | 273 | p->m.poll_event = ns->event; |
@@ -288,7 +287,7 @@ static int mounts_open_common(struct inode *inode, struct file *file, | |||
288 | 287 | ||
289 | static int mounts_release(struct inode *inode, struct file *file) | 288 | static int mounts_release(struct inode *inode, struct file *file) |
290 | { | 289 | { |
291 | struct proc_mounts *p = file->private_data; | 290 | struct proc_mounts *p = proc_mounts(file->private_data); |
292 | path_put(&p->root); | 291 | path_put(&p->root); |
293 | put_mnt_ns(p->ns); | 292 | put_mnt_ns(p->ns); |
294 | return seq_release(inode, file); | 293 | return seq_release(inode, file); |
diff --git a/fs/qnx4/namei.c b/fs/qnx4/namei.c index a512c0b30e8e..d024505ba007 100644 --- a/fs/qnx4/namei.c +++ b/fs/qnx4/namei.c | |||
@@ -95,7 +95,7 @@ static struct buffer_head *qnx4_find_entry(int len, struct inode *dir, | |||
95 | return NULL; | 95 | return NULL; |
96 | } | 96 | } |
97 | 97 | ||
98 | struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 98 | struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
99 | { | 99 | { |
100 | int ino; | 100 | int ino; |
101 | struct qnx4_inode_entry *de; | 101 | struct qnx4_inode_entry *de; |
diff --git a/fs/qnx4/qnx4.h b/fs/qnx4/qnx4.h index 244d4620189b..34e2d329c97e 100644 --- a/fs/qnx4/qnx4.h +++ b/fs/qnx4/qnx4.h | |||
@@ -23,7 +23,7 @@ struct qnx4_inode_info { | |||
23 | }; | 23 | }; |
24 | 24 | ||
25 | extern struct inode *qnx4_iget(struct super_block *, unsigned long); | 25 | extern struct inode *qnx4_iget(struct super_block *, unsigned long); |
26 | extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd); | 26 | extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags); |
27 | extern unsigned long qnx4_count_free_blocks(struct super_block *sb); | 27 | extern unsigned long qnx4_count_free_blocks(struct super_block *sb); |
28 | extern unsigned long qnx4_block_map(struct inode *inode, long iblock); | 28 | extern unsigned long qnx4_block_map(struct inode *inode, long iblock); |
29 | 29 | ||
diff --git a/fs/qnx6/inode.c b/fs/qnx6/inode.c index e44012dc5645..2049c814bda4 100644 --- a/fs/qnx6/inode.c +++ b/fs/qnx6/inode.c | |||
@@ -622,7 +622,6 @@ static struct inode *qnx6_alloc_inode(struct super_block *sb) | |||
622 | static void qnx6_i_callback(struct rcu_head *head) | 622 | static void qnx6_i_callback(struct rcu_head *head) |
623 | { | 623 | { |
624 | struct inode *inode = container_of(head, struct inode, i_rcu); | 624 | struct inode *inode = container_of(head, struct inode, i_rcu); |
625 | INIT_LIST_HEAD(&inode->i_dentry); | ||
626 | kmem_cache_free(qnx6_inode_cachep, QNX6_I(inode)); | 625 | kmem_cache_free(qnx6_inode_cachep, QNX6_I(inode)); |
627 | } | 626 | } |
628 | 627 | ||
diff --git a/fs/qnx6/namei.c b/fs/qnx6/namei.c index 8a97289e04ad..0561326a94f5 100644 --- a/fs/qnx6/namei.c +++ b/fs/qnx6/namei.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include "qnx6.h" | 13 | #include "qnx6.h" |
14 | 14 | ||
15 | struct dentry *qnx6_lookup(struct inode *dir, struct dentry *dentry, | 15 | struct dentry *qnx6_lookup(struct inode *dir, struct dentry *dentry, |
16 | struct nameidata *nd) | 16 | unsigned int flags) |
17 | { | 17 | { |
18 | unsigned ino; | 18 | unsigned ino; |
19 | struct page *page; | 19 | struct page *page; |
diff --git a/fs/qnx6/qnx6.h b/fs/qnx6/qnx6.h index 6c5e02a0b6a8..b00fcc960d37 100644 --- a/fs/qnx6/qnx6.h +++ b/fs/qnx6/qnx6.h | |||
@@ -45,7 +45,7 @@ struct qnx6_inode_info { | |||
45 | 45 | ||
46 | extern struct inode *qnx6_iget(struct super_block *sb, unsigned ino); | 46 | extern struct inode *qnx6_iget(struct super_block *sb, unsigned ino); |
47 | extern struct dentry *qnx6_lookup(struct inode *dir, struct dentry *dentry, | 47 | extern struct dentry *qnx6_lookup(struct inode *dir, struct dentry *dentry, |
48 | struct nameidata *nd); | 48 | unsigned int flags); |
49 | 49 | ||
50 | #ifdef CONFIG_QNX6FS_DEBUG | 50 | #ifdef CONFIG_QNX6FS_DEBUG |
51 | extern void qnx6_superblock_debug(struct qnx6_super_block *, | 51 | extern void qnx6_superblock_debug(struct qnx6_super_block *, |
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 10cbe841cb7e..d679fc48ef27 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
@@ -595,12 +595,14 @@ out: | |||
595 | } | 595 | } |
596 | EXPORT_SYMBOL(dquot_scan_active); | 596 | EXPORT_SYMBOL(dquot_scan_active); |
597 | 597 | ||
598 | int dquot_quota_sync(struct super_block *sb, int type, int wait) | 598 | /* Write all dquot structures to quota files */ |
599 | int dquot_writeback_dquots(struct super_block *sb, int type) | ||
599 | { | 600 | { |
600 | struct list_head *dirty; | 601 | struct list_head *dirty; |
601 | struct dquot *dquot; | 602 | struct dquot *dquot; |
602 | struct quota_info *dqopt = sb_dqopt(sb); | 603 | struct quota_info *dqopt = sb_dqopt(sb); |
603 | int cnt; | 604 | int cnt; |
605 | int err, ret = 0; | ||
604 | 606 | ||
605 | mutex_lock(&dqopt->dqonoff_mutex); | 607 | mutex_lock(&dqopt->dqonoff_mutex); |
606 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { | 608 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) { |
@@ -624,7 +626,9 @@ int dquot_quota_sync(struct super_block *sb, int type, int wait) | |||
624 | atomic_inc(&dquot->dq_count); | 626 | atomic_inc(&dquot->dq_count); |
625 | spin_unlock(&dq_list_lock); | 627 | spin_unlock(&dq_list_lock); |
626 | dqstats_inc(DQST_LOOKUPS); | 628 | dqstats_inc(DQST_LOOKUPS); |
627 | sb->dq_op->write_dquot(dquot); | 629 | err = sb->dq_op->write_dquot(dquot); |
630 | if (!ret && err) | ||
631 | err = ret; | ||
628 | dqput(dquot); | 632 | dqput(dquot); |
629 | spin_lock(&dq_list_lock); | 633 | spin_lock(&dq_list_lock); |
630 | } | 634 | } |
@@ -638,7 +642,21 @@ int dquot_quota_sync(struct super_block *sb, int type, int wait) | |||
638 | dqstats_inc(DQST_SYNCS); | 642 | dqstats_inc(DQST_SYNCS); |
639 | mutex_unlock(&dqopt->dqonoff_mutex); | 643 | mutex_unlock(&dqopt->dqonoff_mutex); |
640 | 644 | ||
641 | if (!wait || (dqopt->flags & DQUOT_QUOTA_SYS_FILE)) | 645 | return ret; |
646 | } | ||
647 | EXPORT_SYMBOL(dquot_writeback_dquots); | ||
648 | |||
649 | /* Write all dquot structures to disk and make them visible from userspace */ | ||
650 | int dquot_quota_sync(struct super_block *sb, int type) | ||
651 | { | ||
652 | struct quota_info *dqopt = sb_dqopt(sb); | ||
653 | int cnt; | ||
654 | int ret; | ||
655 | |||
656 | ret = dquot_writeback_dquots(sb, type); | ||
657 | if (ret) | ||
658 | return ret; | ||
659 | if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) | ||
642 | return 0; | 660 | return 0; |
643 | 661 | ||
644 | /* This is not very clever (and fast) but currently I don't know about | 662 | /* This is not very clever (and fast) but currently I don't know about |
diff --git a/fs/quota/quota.c b/fs/quota/quota.c index 9a391204ca27..c659f92298d3 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c | |||
@@ -47,7 +47,7 @@ static int check_quotactl_permission(struct super_block *sb, int type, int cmd, | |||
47 | static void quota_sync_one(struct super_block *sb, void *arg) | 47 | static void quota_sync_one(struct super_block *sb, void *arg) |
48 | { | 48 | { |
49 | if (sb->s_qcop && sb->s_qcop->quota_sync) | 49 | if (sb->s_qcop && sb->s_qcop->quota_sync) |
50 | sb->s_qcop->quota_sync(sb, *(int *)arg, 1); | 50 | sb->s_qcop->quota_sync(sb, *(int *)arg); |
51 | } | 51 | } |
52 | 52 | ||
53 | static int quota_sync_all(int type) | 53 | static int quota_sync_all(int type) |
@@ -270,7 +270,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, | |||
270 | case Q_SYNC: | 270 | case Q_SYNC: |
271 | if (!sb->s_qcop->quota_sync) | 271 | if (!sb->s_qcop->quota_sync) |
272 | return -ENOSYS; | 272 | return -ENOSYS; |
273 | return sb->s_qcop->quota_sync(sb, type, 1); | 273 | return sb->s_qcop->quota_sync(sb, type); |
274 | case Q_XQUOTAON: | 274 | case Q_XQUOTAON: |
275 | case Q_XQUOTAOFF: | 275 | case Q_XQUOTAOFF: |
276 | case Q_XQUOTARM: | 276 | case Q_XQUOTARM: |
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index a1fdabe21dec..eab8c09d3801 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c | |||
@@ -114,7 +114,7 @@ static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode) | |||
114 | return retval; | 114 | return retval; |
115 | } | 115 | } |
116 | 116 | ||
117 | static int ramfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd) | 117 | static int ramfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) |
118 | { | 118 | { |
119 | return ramfs_mknod(dir, dentry, mode | S_IFREG, 0); | 119 | return ramfs_mknod(dir, dentry, mode | S_IFREG, 0); |
120 | } | 120 | } |
diff --git a/fs/read_write.c b/fs/read_write.c index c20614f86c01..1adfb691e4f1 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -55,10 +55,11 @@ static loff_t lseek_execute(struct file *file, struct inode *inode, | |||
55 | * @file: file structure to seek on | 55 | * @file: file structure to seek on |
56 | * @offset: file offset to seek to | 56 | * @offset: file offset to seek to |
57 | * @origin: type of seek | 57 | * @origin: type of seek |
58 | * @size: max size of file system | 58 | * @size: max size of this file in file system |
59 | * @eof: offset used for SEEK_END position | ||
59 | * | 60 | * |
60 | * This is a variant of generic_file_llseek that allows passing in a custom | 61 | * This is a variant of generic_file_llseek that allows passing in a custom |
61 | * file size. | 62 | * maximum file size and a custom EOF position, for e.g. hashed directories |
62 | * | 63 | * |
63 | * Synchronization: | 64 | * Synchronization: |
64 | * SEEK_SET and SEEK_END are unsynchronized (but atomic on 64bit platforms) | 65 | * SEEK_SET and SEEK_END are unsynchronized (but atomic on 64bit platforms) |
@@ -67,13 +68,13 @@ static loff_t lseek_execute(struct file *file, struct inode *inode, | |||
67 | */ | 68 | */ |
68 | loff_t | 69 | loff_t |
69 | generic_file_llseek_size(struct file *file, loff_t offset, int origin, | 70 | generic_file_llseek_size(struct file *file, loff_t offset, int origin, |
70 | loff_t maxsize) | 71 | loff_t maxsize, loff_t eof) |
71 | { | 72 | { |
72 | struct inode *inode = file->f_mapping->host; | 73 | struct inode *inode = file->f_mapping->host; |
73 | 74 | ||
74 | switch (origin) { | 75 | switch (origin) { |
75 | case SEEK_END: | 76 | case SEEK_END: |
76 | offset += i_size_read(inode); | 77 | offset += eof; |
77 | break; | 78 | break; |
78 | case SEEK_CUR: | 79 | case SEEK_CUR: |
79 | /* | 80 | /* |
@@ -99,7 +100,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int origin, | |||
99 | * In the generic case the entire file is data, so as long as | 100 | * In the generic case the entire file is data, so as long as |
100 | * offset isn't at the end of the file then the offset is data. | 101 | * offset isn't at the end of the file then the offset is data. |
101 | */ | 102 | */ |
102 | if (offset >= i_size_read(inode)) | 103 | if (offset >= eof) |
103 | return -ENXIO; | 104 | return -ENXIO; |
104 | break; | 105 | break; |
105 | case SEEK_HOLE: | 106 | case SEEK_HOLE: |
@@ -107,9 +108,9 @@ generic_file_llseek_size(struct file *file, loff_t offset, int origin, | |||
107 | * There is a virtual hole at the end of the file, so as long as | 108 | * There is a virtual hole at the end of the file, so as long as |
108 | * offset isn't i_size or larger, return i_size. | 109 | * offset isn't i_size or larger, return i_size. |
109 | */ | 110 | */ |
110 | if (offset >= i_size_read(inode)) | 111 | if (offset >= eof) |
111 | return -ENXIO; | 112 | return -ENXIO; |
112 | offset = i_size_read(inode); | 113 | offset = eof; |
113 | break; | 114 | break; |
114 | } | 115 | } |
115 | 116 | ||
@@ -132,7 +133,8 @@ loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) | |||
132 | struct inode *inode = file->f_mapping->host; | 133 | struct inode *inode = file->f_mapping->host; |
133 | 134 | ||
134 | return generic_file_llseek_size(file, offset, origin, | 135 | return generic_file_llseek_size(file, offset, origin, |
135 | inode->i_sb->s_maxbytes); | 136 | inode->i_sb->s_maxbytes, |
137 | i_size_read(inode)); | ||
136 | } | 138 | } |
137 | EXPORT_SYMBOL(generic_file_llseek); | 139 | EXPORT_SYMBOL(generic_file_llseek); |
138 | 140 | ||
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 84e8a69cee9d..8567fb847601 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c | |||
@@ -322,7 +322,7 @@ static int reiserfs_find_entry(struct inode *dir, const char *name, int namelen, | |||
322 | } | 322 | } |
323 | 323 | ||
324 | static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, | 324 | static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, |
325 | struct nameidata *nd) | 325 | unsigned int flags) |
326 | { | 326 | { |
327 | int retval; | 327 | int retval; |
328 | int lock_depth; | 328 | int lock_depth; |
@@ -573,7 +573,7 @@ static int new_inode_init(struct inode *inode, struct inode *dir, umode_t mode) | |||
573 | } | 573 | } |
574 | 574 | ||
575 | static int reiserfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 575 | static int reiserfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
576 | struct nameidata *nd) | 576 | bool excl) |
577 | { | 577 | { |
578 | int retval; | 578 | int retval; |
579 | struct inode *inode; | 579 | struct inode *inode; |
@@ -634,8 +634,8 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, umode_t mod | |||
634 | reiserfs_update_inode_transaction(inode); | 634 | reiserfs_update_inode_transaction(inode); |
635 | reiserfs_update_inode_transaction(dir); | 635 | reiserfs_update_inode_transaction(dir); |
636 | 636 | ||
637 | d_instantiate(dentry, inode); | ||
638 | unlock_new_inode(inode); | 637 | unlock_new_inode(inode); |
638 | d_instantiate(dentry, inode); | ||
639 | retval = journal_end(&th, dir->i_sb, jbegin_count); | 639 | retval = journal_end(&th, dir->i_sb, jbegin_count); |
640 | 640 | ||
641 | out_failed: | 641 | out_failed: |
@@ -712,8 +712,8 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode | |||
712 | goto out_failed; | 712 | goto out_failed; |
713 | } | 713 | } |
714 | 714 | ||
715 | d_instantiate(dentry, inode); | ||
716 | unlock_new_inode(inode); | 715 | unlock_new_inode(inode); |
716 | d_instantiate(dentry, inode); | ||
717 | retval = journal_end(&th, dir->i_sb, jbegin_count); | 717 | retval = journal_end(&th, dir->i_sb, jbegin_count); |
718 | 718 | ||
719 | out_failed: | 719 | out_failed: |
@@ -800,8 +800,8 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode | |||
800 | // the above add_entry did not update dir's stat data | 800 | // the above add_entry did not update dir's stat data |
801 | reiserfs_update_sd(&th, dir); | 801 | reiserfs_update_sd(&th, dir); |
802 | 802 | ||
803 | d_instantiate(dentry, inode); | ||
804 | unlock_new_inode(inode); | 803 | unlock_new_inode(inode); |
804 | d_instantiate(dentry, inode); | ||
805 | retval = journal_end(&th, dir->i_sb, jbegin_count); | 805 | retval = journal_end(&th, dir->i_sb, jbegin_count); |
806 | out_failed: | 806 | out_failed: |
807 | reiserfs_write_unlock_once(dir->i_sb, lock_depth); | 807 | reiserfs_write_unlock_once(dir->i_sb, lock_depth); |
@@ -1096,8 +1096,8 @@ static int reiserfs_symlink(struct inode *parent_dir, | |||
1096 | goto out_failed; | 1096 | goto out_failed; |
1097 | } | 1097 | } |
1098 | 1098 | ||
1099 | d_instantiate(dentry, inode); | ||
1100 | unlock_new_inode(inode); | 1099 | unlock_new_inode(inode); |
1100 | d_instantiate(dentry, inode); | ||
1101 | retval = journal_end(&th, parent_dir->i_sb, jbegin_count); | 1101 | retval = journal_end(&th, parent_dir->i_sb, jbegin_count); |
1102 | out_failed: | 1102 | out_failed: |
1103 | reiserfs_write_unlock(parent_dir->i_sb); | 1103 | reiserfs_write_unlock(parent_dir->i_sb); |
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c index 2c1ade692cc8..e60e87035bb3 100644 --- a/fs/reiserfs/procfs.c +++ b/fs/reiserfs/procfs.c | |||
@@ -403,7 +403,7 @@ static void *r_start(struct seq_file *m, loff_t * pos) | |||
403 | if (l) | 403 | if (l) |
404 | return NULL; | 404 | return NULL; |
405 | 405 | ||
406 | if (IS_ERR(sget(&reiserfs_fs_type, test_sb, set_sb, s))) | 406 | if (IS_ERR(sget(&reiserfs_fs_type, test_sb, set_sb, 0, s))) |
407 | return NULL; | 407 | return NULL; |
408 | 408 | ||
409 | up_write(&s->s_umount); | 409 | up_write(&s->s_umount); |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 651ce767b55d..7a37dabf5a96 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -68,6 +68,11 @@ static int reiserfs_sync_fs(struct super_block *s, int wait) | |||
68 | { | 68 | { |
69 | struct reiserfs_transaction_handle th; | 69 | struct reiserfs_transaction_handle th; |
70 | 70 | ||
71 | /* | ||
72 | * Writeback quota in non-journalled quota case - journalled quota has | ||
73 | * no dirty dquots | ||
74 | */ | ||
75 | dquot_writeback_dquots(s, -1); | ||
71 | reiserfs_write_lock(s); | 76 | reiserfs_write_lock(s); |
72 | if (!journal_begin(&th, s, 1)) | 77 | if (!journal_begin(&th, s, 1)) |
73 | if (!journal_end_sync(&th, s, 1)) | 78 | if (!journal_end_sync(&th, s, 1)) |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 46fc1c20a6b1..d319963aeb11 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -62,7 +62,7 @@ | |||
62 | static int xattr_create(struct inode *dir, struct dentry *dentry, int mode) | 62 | static int xattr_create(struct inode *dir, struct dentry *dentry, int mode) |
63 | { | 63 | { |
64 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); | 64 | BUG_ON(!mutex_is_locked(&dir->i_mutex)); |
65 | return dir->i_op->create(dir, dentry, mode, NULL); | 65 | return dir->i_op->create(dir, dentry, mode, true); |
66 | } | 66 | } |
67 | #endif | 67 | #endif |
68 | 68 | ||
@@ -942,7 +942,7 @@ int reiserfs_permission(struct inode *inode, int mask) | |||
942 | return generic_permission(inode, mask); | 942 | return generic_permission(inode, mask); |
943 | } | 943 | } |
944 | 944 | ||
945 | static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd) | 945 | static int xattr_hide_revalidate(struct dentry *dentry, unsigned int flags) |
946 | { | 946 | { |
947 | return -EPERM; | 947 | return -EPERM; |
948 | } | 948 | } |
diff --git a/fs/romfs/super.c b/fs/romfs/super.c index e64f6b5f7ae5..77c5f2173983 100644 --- a/fs/romfs/super.c +++ b/fs/romfs/super.c | |||
@@ -210,7 +210,7 @@ out: | |||
210 | * look up an entry in a directory | 210 | * look up an entry in a directory |
211 | */ | 211 | */ |
212 | static struct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry, | 212 | static struct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry, |
213 | struct nameidata *nd) | 213 | unsigned int flags) |
214 | { | 214 | { |
215 | unsigned long offset, maxoff; | 215 | unsigned long offset, maxoff; |
216 | struct inode *inode; | 216 | struct inode *inode; |
diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c index abcc58f3c152..7834a517f7f4 100644 --- a/fs/squashfs/namei.c +++ b/fs/squashfs/namei.c | |||
@@ -134,7 +134,7 @@ out: | |||
134 | 134 | ||
135 | 135 | ||
136 | static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry, | 136 | static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry, |
137 | struct nameidata *nd) | 137 | unsigned int flags) |
138 | { | 138 | { |
139 | const unsigned char *name = dentry->d_name.name; | 139 | const unsigned char *name = dentry->d_name.name; |
140 | int len = dentry->d_name.len; | 140 | int len = dentry->d_name.len; |
diff --git a/fs/super.c b/fs/super.c index cf001775617f..c743fb3be4b8 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -105,11 +105,12 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc) | |||
105 | /** | 105 | /** |
106 | * alloc_super - create new superblock | 106 | * alloc_super - create new superblock |
107 | * @type: filesystem type superblock should belong to | 107 | * @type: filesystem type superblock should belong to |
108 | * @flags: the mount flags | ||
108 | * | 109 | * |
109 | * Allocates and initializes a new &struct super_block. alloc_super() | 110 | * Allocates and initializes a new &struct super_block. alloc_super() |
110 | * returns a pointer new superblock or %NULL if allocation had failed. | 111 | * returns a pointer new superblock or %NULL if allocation had failed. |
111 | */ | 112 | */ |
112 | static struct super_block *alloc_super(struct file_system_type *type) | 113 | static struct super_block *alloc_super(struct file_system_type *type, int flags) |
113 | { | 114 | { |
114 | struct super_block *s = kzalloc(sizeof(struct super_block), GFP_USER); | 115 | struct super_block *s = kzalloc(sizeof(struct super_block), GFP_USER); |
115 | static const struct super_operations default_op; | 116 | static const struct super_operations default_op; |
@@ -136,6 +137,7 @@ static struct super_block *alloc_super(struct file_system_type *type) | |||
136 | #else | 137 | #else |
137 | INIT_LIST_HEAD(&s->s_files); | 138 | INIT_LIST_HEAD(&s->s_files); |
138 | #endif | 139 | #endif |
140 | s->s_flags = flags; | ||
139 | s->s_bdi = &default_backing_dev_info; | 141 | s->s_bdi = &default_backing_dev_info; |
140 | INIT_HLIST_NODE(&s->s_instances); | 142 | INIT_HLIST_NODE(&s->s_instances); |
141 | INIT_HLIST_BL_HEAD(&s->s_anon); | 143 | INIT_HLIST_BL_HEAD(&s->s_anon); |
@@ -415,11 +417,13 @@ EXPORT_SYMBOL(generic_shutdown_super); | |||
415 | * @type: filesystem type superblock should belong to | 417 | * @type: filesystem type superblock should belong to |
416 | * @test: comparison callback | 418 | * @test: comparison callback |
417 | * @set: setup callback | 419 | * @set: setup callback |
420 | * @flags: mount flags | ||
418 | * @data: argument to each of them | 421 | * @data: argument to each of them |
419 | */ | 422 | */ |
420 | struct super_block *sget(struct file_system_type *type, | 423 | struct super_block *sget(struct file_system_type *type, |
421 | int (*test)(struct super_block *,void *), | 424 | int (*test)(struct super_block *,void *), |
422 | int (*set)(struct super_block *,void *), | 425 | int (*set)(struct super_block *,void *), |
426 | int flags, | ||
423 | void *data) | 427 | void *data) |
424 | { | 428 | { |
425 | struct super_block *s = NULL; | 429 | struct super_block *s = NULL; |
@@ -450,7 +454,7 @@ retry: | |||
450 | } | 454 | } |
451 | if (!s) { | 455 | if (!s) { |
452 | spin_unlock(&sb_lock); | 456 | spin_unlock(&sb_lock); |
453 | s = alloc_super(type); | 457 | s = alloc_super(type, flags); |
454 | if (!s) | 458 | if (!s) |
455 | return ERR_PTR(-ENOMEM); | 459 | return ERR_PTR(-ENOMEM); |
456 | goto retry; | 460 | goto retry; |
@@ -925,13 +929,12 @@ struct dentry *mount_ns(struct file_system_type *fs_type, int flags, | |||
925 | { | 929 | { |
926 | struct super_block *sb; | 930 | struct super_block *sb; |
927 | 931 | ||
928 | sb = sget(fs_type, ns_test_super, ns_set_super, data); | 932 | sb = sget(fs_type, ns_test_super, ns_set_super, flags, data); |
929 | if (IS_ERR(sb)) | 933 | if (IS_ERR(sb)) |
930 | return ERR_CAST(sb); | 934 | return ERR_CAST(sb); |
931 | 935 | ||
932 | if (!sb->s_root) { | 936 | if (!sb->s_root) { |
933 | int err; | 937 | int err; |
934 | sb->s_flags = flags; | ||
935 | err = fill_super(sb, data, flags & MS_SILENT ? 1 : 0); | 938 | err = fill_super(sb, data, flags & MS_SILENT ? 1 : 0); |
936 | if (err) { | 939 | if (err) { |
937 | deactivate_locked_super(sb); | 940 | deactivate_locked_super(sb); |
@@ -992,7 +995,8 @@ struct dentry *mount_bdev(struct file_system_type *fs_type, | |||
992 | error = -EBUSY; | 995 | error = -EBUSY; |
993 | goto error_bdev; | 996 | goto error_bdev; |
994 | } | 997 | } |
995 | s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); | 998 | s = sget(fs_type, test_bdev_super, set_bdev_super, flags | MS_NOSEC, |
999 | bdev); | ||
996 | mutex_unlock(&bdev->bd_fsfreeze_mutex); | 1000 | mutex_unlock(&bdev->bd_fsfreeze_mutex); |
997 | if (IS_ERR(s)) | 1001 | if (IS_ERR(s)) |
998 | goto error_s; | 1002 | goto error_s; |
@@ -1017,7 +1021,6 @@ struct dentry *mount_bdev(struct file_system_type *fs_type, | |||
1017 | } else { | 1021 | } else { |
1018 | char b[BDEVNAME_SIZE]; | 1022 | char b[BDEVNAME_SIZE]; |
1019 | 1023 | ||
1020 | s->s_flags = flags | MS_NOSEC; | ||
1021 | s->s_mode = mode; | 1024 | s->s_mode = mode; |
1022 | strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); | 1025 | strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); |
1023 | sb_set_blocksize(s, block_size(bdev)); | 1026 | sb_set_blocksize(s, block_size(bdev)); |
@@ -1062,13 +1065,11 @@ struct dentry *mount_nodev(struct file_system_type *fs_type, | |||
1062 | int (*fill_super)(struct super_block *, void *, int)) | 1065 | int (*fill_super)(struct super_block *, void *, int)) |
1063 | { | 1066 | { |
1064 | int error; | 1067 | int error; |
1065 | struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); | 1068 | struct super_block *s = sget(fs_type, NULL, set_anon_super, flags, NULL); |
1066 | 1069 | ||
1067 | if (IS_ERR(s)) | 1070 | if (IS_ERR(s)) |
1068 | return ERR_CAST(s); | 1071 | return ERR_CAST(s); |
1069 | 1072 | ||
1070 | s->s_flags = flags; | ||
1071 | |||
1072 | error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); | 1073 | error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); |
1073 | if (error) { | 1074 | if (error) { |
1074 | deactivate_locked_super(s); | 1075 | deactivate_locked_super(s); |
@@ -1091,11 +1092,10 @@ struct dentry *mount_single(struct file_system_type *fs_type, | |||
1091 | struct super_block *s; | 1092 | struct super_block *s; |
1092 | int error; | 1093 | int error; |
1093 | 1094 | ||
1094 | s = sget(fs_type, compare_single, set_anon_super, NULL); | 1095 | s = sget(fs_type, compare_single, set_anon_super, flags, NULL); |
1095 | if (IS_ERR(s)) | 1096 | if (IS_ERR(s)) |
1096 | return ERR_CAST(s); | 1097 | return ERR_CAST(s); |
1097 | if (!s->s_root) { | 1098 | if (!s->s_root) { |
1098 | s->s_flags = flags; | ||
1099 | error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); | 1099 | error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); |
1100 | if (error) { | 1100 | if (error) { |
1101 | deactivate_locked_super(s); | 1101 | deactivate_locked_super(s); |
@@ -29,16 +29,6 @@ | |||
29 | */ | 29 | */ |
30 | static int __sync_filesystem(struct super_block *sb, int wait) | 30 | static int __sync_filesystem(struct super_block *sb, int wait) |
31 | { | 31 | { |
32 | /* | ||
33 | * This should be safe, as we require bdi backing to actually | ||
34 | * write out data in the first place | ||
35 | */ | ||
36 | if (sb->s_bdi == &noop_backing_dev_info) | ||
37 | return 0; | ||
38 | |||
39 | if (sb->s_qcop && sb->s_qcop->quota_sync) | ||
40 | sb->s_qcop->quota_sync(sb, -1, wait); | ||
41 | |||
42 | if (wait) | 32 | if (wait) |
43 | sync_inodes_sb(sb); | 33 | sync_inodes_sb(sb); |
44 | else | 34 | else |
@@ -77,29 +67,48 @@ int sync_filesystem(struct super_block *sb) | |||
77 | } | 67 | } |
78 | EXPORT_SYMBOL_GPL(sync_filesystem); | 68 | EXPORT_SYMBOL_GPL(sync_filesystem); |
79 | 69 | ||
80 | static void sync_one_sb(struct super_block *sb, void *arg) | 70 | static void sync_inodes_one_sb(struct super_block *sb, void *arg) |
81 | { | 71 | { |
82 | if (!(sb->s_flags & MS_RDONLY)) | 72 | if (!(sb->s_flags & MS_RDONLY)) |
83 | __sync_filesystem(sb, *(int *)arg); | 73 | sync_inodes_sb(sb); |
84 | } | 74 | } |
85 | /* | 75 | |
86 | * Sync all the data for all the filesystems (called by sys_sync() and | 76 | static void sync_fs_one_sb(struct super_block *sb, void *arg) |
87 | * emergency sync) | ||
88 | */ | ||
89 | static void sync_filesystems(int wait) | ||
90 | { | 77 | { |
91 | iterate_supers(sync_one_sb, &wait); | 78 | if (!(sb->s_flags & MS_RDONLY) && sb->s_op->sync_fs) |
79 | sb->s_op->sync_fs(sb, *(int *)arg); | ||
80 | } | ||
81 | |||
82 | static void fdatawrite_one_bdev(struct block_device *bdev, void *arg) | ||
83 | { | ||
84 | filemap_fdatawrite(bdev->bd_inode->i_mapping); | ||
85 | } | ||
86 | |||
87 | static void fdatawait_one_bdev(struct block_device *bdev, void *arg) | ||
88 | { | ||
89 | filemap_fdatawait(bdev->bd_inode->i_mapping); | ||
92 | } | 90 | } |
93 | 91 | ||
94 | /* | 92 | /* |
95 | * sync everything. Start out by waking pdflush, because that writes back | 93 | * Sync everything. We start by waking flusher threads so that most of |
96 | * all queues in parallel. | 94 | * writeback runs on all devices in parallel. Then we sync all inodes reliably |
95 | * which effectively also waits for all flusher threads to finish doing | ||
96 | * writeback. At this point all data is on disk so metadata should be stable | ||
97 | * and we tell filesystems to sync their metadata via ->sync_fs() calls. | ||
98 | * Finally, we writeout all block devices because some filesystems (e.g. ext2) | ||
99 | * just write metadata (such as inodes or bitmaps) to block device page cache | ||
100 | * and do not sync it on their own in ->sync_fs(). | ||
97 | */ | 101 | */ |
98 | SYSCALL_DEFINE0(sync) | 102 | SYSCALL_DEFINE0(sync) |
99 | { | 103 | { |
104 | int nowait = 0, wait = 1; | ||
105 | |||
100 | wakeup_flusher_threads(0, WB_REASON_SYNC); | 106 | wakeup_flusher_threads(0, WB_REASON_SYNC); |
101 | sync_filesystems(0); | 107 | iterate_supers(sync_inodes_one_sb, NULL); |
102 | sync_filesystems(1); | 108 | iterate_supers(sync_fs_one_sb, &nowait); |
109 | iterate_supers(sync_fs_one_sb, &wait); | ||
110 | iterate_bdevs(fdatawrite_one_bdev, NULL); | ||
111 | iterate_bdevs(fdatawait_one_bdev, NULL); | ||
103 | if (unlikely(laptop_mode)) | 112 | if (unlikely(laptop_mode)) |
104 | laptop_sync_completion(); | 113 | laptop_sync_completion(); |
105 | return 0; | 114 | return 0; |
@@ -107,12 +116,18 @@ SYSCALL_DEFINE0(sync) | |||
107 | 116 | ||
108 | static void do_sync_work(struct work_struct *work) | 117 | static void do_sync_work(struct work_struct *work) |
109 | { | 118 | { |
119 | int nowait = 0; | ||
120 | |||
110 | /* | 121 | /* |
111 | * Sync twice to reduce the possibility we skipped some inodes / pages | 122 | * Sync twice to reduce the possibility we skipped some inodes / pages |
112 | * because they were temporarily locked | 123 | * because they were temporarily locked |
113 | */ | 124 | */ |
114 | sync_filesystems(0); | 125 | iterate_supers(sync_inodes_one_sb, &nowait); |
115 | sync_filesystems(0); | 126 | iterate_supers(sync_fs_one_sb, &nowait); |
127 | iterate_bdevs(fdatawrite_one_bdev, NULL); | ||
128 | iterate_supers(sync_inodes_one_sb, &nowait); | ||
129 | iterate_supers(sync_fs_one_sb, &nowait); | ||
130 | iterate_bdevs(fdatawrite_one_bdev, NULL); | ||
116 | printk("Emergency Sync complete\n"); | 131 | printk("Emergency Sync complete\n"); |
117 | kfree(work); | 132 | kfree(work); |
118 | } | 133 | } |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index e6bb9b2a4cbe..a5cf784f9cc2 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -300,15 +300,15 @@ void release_sysfs_dirent(struct sysfs_dirent * sd) | |||
300 | static int sysfs_dentry_delete(const struct dentry *dentry) | 300 | static int sysfs_dentry_delete(const struct dentry *dentry) |
301 | { | 301 | { |
302 | struct sysfs_dirent *sd = dentry->d_fsdata; | 302 | struct sysfs_dirent *sd = dentry->d_fsdata; |
303 | return !!(sd->s_flags & SYSFS_FLAG_REMOVED); | 303 | return !(sd && !(sd->s_flags & SYSFS_FLAG_REMOVED)); |
304 | } | 304 | } |
305 | 305 | ||
306 | static int sysfs_dentry_revalidate(struct dentry *dentry, struct nameidata *nd) | 306 | static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags) |
307 | { | 307 | { |
308 | struct sysfs_dirent *sd; | 308 | struct sysfs_dirent *sd; |
309 | int is_dir; | 309 | int is_dir; |
310 | 310 | ||
311 | if (nd->flags & LOOKUP_RCU) | 311 | if (flags & LOOKUP_RCU) |
312 | return -ECHILD; | 312 | return -ECHILD; |
313 | 313 | ||
314 | sd = dentry->d_fsdata; | 314 | sd = dentry->d_fsdata; |
@@ -355,18 +355,15 @@ out_bad: | |||
355 | return 0; | 355 | return 0; |
356 | } | 356 | } |
357 | 357 | ||
358 | static void sysfs_dentry_iput(struct dentry *dentry, struct inode *inode) | 358 | static void sysfs_dentry_release(struct dentry *dentry) |
359 | { | 359 | { |
360 | struct sysfs_dirent * sd = dentry->d_fsdata; | 360 | sysfs_put(dentry->d_fsdata); |
361 | |||
362 | sysfs_put(sd); | ||
363 | iput(inode); | ||
364 | } | 361 | } |
365 | 362 | ||
366 | static const struct dentry_operations sysfs_dentry_ops = { | 363 | const struct dentry_operations sysfs_dentry_ops = { |
367 | .d_revalidate = sysfs_dentry_revalidate, | 364 | .d_revalidate = sysfs_dentry_revalidate, |
368 | .d_delete = sysfs_dentry_delete, | 365 | .d_delete = sysfs_dentry_delete, |
369 | .d_iput = sysfs_dentry_iput, | 366 | .d_release = sysfs_dentry_release, |
370 | }; | 367 | }; |
371 | 368 | ||
372 | struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) | 369 | struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) |
@@ -764,7 +761,7 @@ int sysfs_create_dir(struct kobject * kobj) | |||
764 | } | 761 | } |
765 | 762 | ||
766 | static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | 763 | static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, |
767 | struct nameidata *nd) | 764 | unsigned int flags) |
768 | { | 765 | { |
769 | struct dentry *ret = NULL; | 766 | struct dentry *ret = NULL; |
770 | struct dentry *parent = dentry->d_parent; | 767 | struct dentry *parent = dentry->d_parent; |
@@ -786,6 +783,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | |||
786 | ret = ERR_PTR(-ENOENT); | 783 | ret = ERR_PTR(-ENOENT); |
787 | goto out_unlock; | 784 | goto out_unlock; |
788 | } | 785 | } |
786 | dentry->d_fsdata = sysfs_get(sd); | ||
789 | 787 | ||
790 | /* attach dentry and inode */ | 788 | /* attach dentry and inode */ |
791 | inode = sysfs_get_inode(dir->i_sb, sd); | 789 | inode = sysfs_get_inode(dir->i_sb, sd); |
@@ -795,16 +793,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | |||
795 | } | 793 | } |
796 | 794 | ||
797 | /* instantiate and hash dentry */ | 795 | /* instantiate and hash dentry */ |
798 | ret = d_find_alias(inode); | 796 | ret = d_materialise_unique(dentry, inode); |
799 | if (!ret) { | ||
800 | d_set_d_op(dentry, &sysfs_dentry_ops); | ||
801 | dentry->d_fsdata = sysfs_get(sd); | ||
802 | d_add(dentry, inode); | ||
803 | } else { | ||
804 | d_move(ret, dentry); | ||
805 | iput(inode); | ||
806 | } | ||
807 | |||
808 | out_unlock: | 797 | out_unlock: |
809 | mutex_unlock(&sysfs_mutex); | 798 | mutex_unlock(&sysfs_mutex); |
810 | return ret; | 799 | return ret; |
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 52c3bdb66a84..71eb7e253927 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
@@ -68,6 +68,7 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) | |||
68 | } | 68 | } |
69 | root->d_fsdata = &sysfs_root; | 69 | root->d_fsdata = &sysfs_root; |
70 | sb->s_root = root; | 70 | sb->s_root = root; |
71 | sb->s_d_op = &sysfs_dentry_ops; | ||
71 | return 0; | 72 | return 0; |
72 | } | 73 | } |
73 | 74 | ||
@@ -117,13 +118,12 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, | |||
117 | for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) | 118 | for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) |
118 | info->ns[type] = kobj_ns_grab_current(type); | 119 | info->ns[type] = kobj_ns_grab_current(type); |
119 | 120 | ||
120 | sb = sget(fs_type, sysfs_test_super, sysfs_set_super, info); | 121 | sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info); |
121 | if (IS_ERR(sb) || sb->s_fs_info != info) | 122 | if (IS_ERR(sb) || sb->s_fs_info != info) |
122 | free_sysfs_super_info(info); | 123 | free_sysfs_super_info(info); |
123 | if (IS_ERR(sb)) | 124 | if (IS_ERR(sb)) |
124 | return ERR_CAST(sb); | 125 | return ERR_CAST(sb); |
125 | if (!sb->s_root) { | 126 | if (!sb->s_root) { |
126 | sb->s_flags = flags; | ||
127 | error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); | 127 | error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); |
128 | if (error) { | 128 | if (error) { |
129 | deactivate_locked_super(sb); | 129 | deactivate_locked_super(sb); |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 661a9639570b..d73c0932bbd6 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -157,6 +157,7 @@ extern struct kmem_cache *sysfs_dir_cachep; | |||
157 | */ | 157 | */ |
158 | extern struct mutex sysfs_mutex; | 158 | extern struct mutex sysfs_mutex; |
159 | extern spinlock_t sysfs_assoc_lock; | 159 | extern spinlock_t sysfs_assoc_lock; |
160 | extern const struct dentry_operations sysfs_dentry_ops; | ||
160 | 161 | ||
161 | extern const struct file_operations sysfs_dir_operations; | 162 | extern const struct file_operations sysfs_dir_operations; |
162 | extern const struct inode_operations sysfs_dir_inode_operations; | 163 | extern const struct inode_operations sysfs_dir_inode_operations; |
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 08d0b2568cd3..80e1e2b18df1 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c | |||
@@ -43,7 +43,6 @@ static int sysv_sync_fs(struct super_block *sb, int wait) | |||
43 | * then attach current time stamp. | 43 | * then attach current time stamp. |
44 | * But if the filesystem was marked clean, keep it clean. | 44 | * But if the filesystem was marked clean, keep it clean. |
45 | */ | 45 | */ |
46 | sb->s_dirt = 0; | ||
47 | old_time = fs32_to_cpu(sbi, *sbi->s_sb_time); | 46 | old_time = fs32_to_cpu(sbi, *sbi->s_sb_time); |
48 | if (sbi->s_type == FSTYPE_SYSV4) { | 47 | if (sbi->s_type == FSTYPE_SYSV4) { |
49 | if (*sbi->s_sb_state == cpu_to_fs32(sbi, 0x7c269d38 - old_time)) | 48 | if (*sbi->s_sb_state == cpu_to_fs32(sbi, 0x7c269d38 - old_time)) |
@@ -57,23 +56,12 @@ static int sysv_sync_fs(struct super_block *sb, int wait) | |||
57 | return 0; | 56 | return 0; |
58 | } | 57 | } |
59 | 58 | ||
60 | static void sysv_write_super(struct super_block *sb) | ||
61 | { | ||
62 | if (!(sb->s_flags & MS_RDONLY)) | ||
63 | sysv_sync_fs(sb, 1); | ||
64 | else | ||
65 | sb->s_dirt = 0; | ||
66 | } | ||
67 | |||
68 | static int sysv_remount(struct super_block *sb, int *flags, char *data) | 59 | static int sysv_remount(struct super_block *sb, int *flags, char *data) |
69 | { | 60 | { |
70 | struct sysv_sb_info *sbi = SYSV_SB(sb); | 61 | struct sysv_sb_info *sbi = SYSV_SB(sb); |
71 | lock_super(sb); | 62 | |
72 | if (sbi->s_forced_ro) | 63 | if (sbi->s_forced_ro) |
73 | *flags |= MS_RDONLY; | 64 | *flags |= MS_RDONLY; |
74 | if (*flags & MS_RDONLY) | ||
75 | sysv_write_super(sb); | ||
76 | unlock_super(sb); | ||
77 | return 0; | 65 | return 0; |
78 | } | 66 | } |
79 | 67 | ||
@@ -81,9 +69,6 @@ static void sysv_put_super(struct super_block *sb) | |||
81 | { | 69 | { |
82 | struct sysv_sb_info *sbi = SYSV_SB(sb); | 70 | struct sysv_sb_info *sbi = SYSV_SB(sb); |
83 | 71 | ||
84 | if (sb->s_dirt) | ||
85 | sysv_write_super(sb); | ||
86 | |||
87 | if (!(sb->s_flags & MS_RDONLY)) { | 72 | if (!(sb->s_flags & MS_RDONLY)) { |
88 | /* XXX ext2 also updates the state here */ | 73 | /* XXX ext2 also updates the state here */ |
89 | mark_buffer_dirty(sbi->s_bh1); | 74 | mark_buffer_dirty(sbi->s_bh1); |
@@ -357,7 +342,6 @@ const struct super_operations sysv_sops = { | |||
357 | .write_inode = sysv_write_inode, | 342 | .write_inode = sysv_write_inode, |
358 | .evict_inode = sysv_evict_inode, | 343 | .evict_inode = sysv_evict_inode, |
359 | .put_super = sysv_put_super, | 344 | .put_super = sysv_put_super, |
360 | .write_super = sysv_write_super, | ||
361 | .sync_fs = sysv_sync_fs, | 345 | .sync_fs = sysv_sync_fs, |
362 | .remount_fs = sysv_remount, | 346 | .remount_fs = sysv_remount, |
363 | .statfs = sysv_statfs, | 347 | .statfs = sysv_statfs, |
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c index d7466e293614..1c0d5f264767 100644 --- a/fs/sysv/namei.c +++ b/fs/sysv/namei.c | |||
@@ -43,7 +43,7 @@ const struct dentry_operations sysv_dentry_operations = { | |||
43 | .d_hash = sysv_hash, | 43 | .d_hash = sysv_hash, |
44 | }; | 44 | }; |
45 | 45 | ||
46 | static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd) | 46 | static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags) |
47 | { | 47 | { |
48 | struct inode * inode = NULL; | 48 | struct inode * inode = NULL; |
49 | ino_t ino; | 49 | ino_t ino; |
@@ -80,7 +80,7 @@ static int sysv_mknod(struct inode * dir, struct dentry * dentry, umode_t mode, | |||
80 | return err; | 80 | return err; |
81 | } | 81 | } |
82 | 82 | ||
83 | static int sysv_create(struct inode * dir, struct dentry * dentry, umode_t mode, struct nameidata *nd) | 83 | static int sysv_create(struct inode * dir, struct dentry * dentry, umode_t mode, bool excl) |
84 | { | 84 | { |
85 | return sysv_mknod(dir, dentry, mode, 0); | 85 | return sysv_mknod(dir, dentry, mode, 0); |
86 | } | 86 | } |
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h index 11b07672f6c5..0bc35fdc58e2 100644 --- a/fs/sysv/sysv.h +++ b/fs/sysv/sysv.h | |||
@@ -117,7 +117,6 @@ static inline void dirty_sb(struct super_block *sb) | |||
117 | mark_buffer_dirty(sbi->s_bh1); | 117 | mark_buffer_dirty(sbi->s_bh1); |
118 | if (sbi->s_bh1 != sbi->s_bh2) | 118 | if (sbi->s_bh1 != sbi->s_bh2) |
119 | mark_buffer_dirty(sbi->s_bh2); | 119 | mark_buffer_dirty(sbi->s_bh2); |
120 | sb->s_dirt = 1; | ||
121 | } | 120 | } |
122 | 121 | ||
123 | 122 | ||
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index a6d42efc76d2..b1cca89aeb68 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c | |||
@@ -184,7 +184,7 @@ static int dbg_check_name(const struct ubifs_info *c, | |||
184 | } | 184 | } |
185 | 185 | ||
186 | static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, | 186 | static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, |
187 | struct nameidata *nd) | 187 | unsigned int flags) |
188 | { | 188 | { |
189 | int err; | 189 | int err; |
190 | union ubifs_key key; | 190 | union ubifs_key key; |
@@ -246,7 +246,7 @@ out: | |||
246 | } | 246 | } |
247 | 247 | ||
248 | static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 248 | static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
249 | struct nameidata *nd) | 249 | bool excl) |
250 | { | 250 | { |
251 | struct inode *inode; | 251 | struct inode *inode; |
252 | struct ubifs_info *c = dir->i_sb->s_fs_info; | 252 | struct ubifs_info *c = dir->i_sb->s_fs_info; |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 5862dd9d2784..1c766c39c038 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
@@ -2136,7 +2136,7 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, | |||
2136 | 2136 | ||
2137 | dbg_gen("opened ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); | 2137 | dbg_gen("opened ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); |
2138 | 2138 | ||
2139 | sb = sget(fs_type, sb_test, sb_set, c); | 2139 | sb = sget(fs_type, sb_test, sb_set, flags, c); |
2140 | if (IS_ERR(sb)) { | 2140 | if (IS_ERR(sb)) { |
2141 | err = PTR_ERR(sb); | 2141 | err = PTR_ERR(sb); |
2142 | kfree(c); | 2142 | kfree(c); |
@@ -2153,7 +2153,6 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, | |||
2153 | goto out_deact; | 2153 | goto out_deact; |
2154 | } | 2154 | } |
2155 | } else { | 2155 | } else { |
2156 | sb->s_flags = flags; | ||
2157 | err = ubifs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); | 2156 | err = ubifs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); |
2158 | if (err) | 2157 | if (err) |
2159 | goto out_deact; | 2158 | goto out_deact; |
diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 18024178ac4c..544b2799a911 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c | |||
@@ -251,7 +251,7 @@ out_ok: | |||
251 | } | 251 | } |
252 | 252 | ||
253 | static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, | 253 | static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, |
254 | struct nameidata *nd) | 254 | unsigned int flags) |
255 | { | 255 | { |
256 | struct inode *inode = NULL; | 256 | struct inode *inode = NULL; |
257 | struct fileIdentDesc cfi; | 257 | struct fileIdentDesc cfi; |
@@ -551,7 +551,7 @@ static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi, | |||
551 | } | 551 | } |
552 | 552 | ||
553 | static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 553 | static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
554 | struct nameidata *nd) | 554 | bool excl) |
555 | { | 555 | { |
556 | struct udf_fileident_bh fibh; | 556 | struct udf_fileident_bh fibh; |
557 | struct inode *inode; | 557 | struct inode *inode; |
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 42694e11c23d..1b3e410bf334 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c | |||
@@ -116,7 +116,7 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count) | |||
116 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); | 116 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); |
117 | if (sb->s_flags & MS_SYNCHRONOUS) | 117 | if (sb->s_flags & MS_SYNCHRONOUS) |
118 | ubh_sync_block(UCPI_UBH(ucpi)); | 118 | ubh_sync_block(UCPI_UBH(ucpi)); |
119 | sb->s_dirt = 1; | 119 | ufs_mark_sb_dirty(sb); |
120 | 120 | ||
121 | unlock_super (sb); | 121 | unlock_super (sb); |
122 | UFSD("EXIT\n"); | 122 | UFSD("EXIT\n"); |
@@ -214,7 +214,7 @@ do_more: | |||
214 | goto do_more; | 214 | goto do_more; |
215 | } | 215 | } |
216 | 216 | ||
217 | sb->s_dirt = 1; | 217 | ufs_mark_sb_dirty(sb); |
218 | unlock_super (sb); | 218 | unlock_super (sb); |
219 | UFSD("EXIT\n"); | 219 | UFSD("EXIT\n"); |
220 | return; | 220 | return; |
@@ -557,7 +557,7 @@ static u64 ufs_add_fragments(struct inode *inode, u64 fragment, | |||
557 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); | 557 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); |
558 | if (sb->s_flags & MS_SYNCHRONOUS) | 558 | if (sb->s_flags & MS_SYNCHRONOUS) |
559 | ubh_sync_block(UCPI_UBH(ucpi)); | 559 | ubh_sync_block(UCPI_UBH(ucpi)); |
560 | sb->s_dirt = 1; | 560 | ufs_mark_sb_dirty(sb); |
561 | 561 | ||
562 | UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment); | 562 | UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment); |
563 | 563 | ||
@@ -677,7 +677,7 @@ succed: | |||
677 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); | 677 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); |
678 | if (sb->s_flags & MS_SYNCHRONOUS) | 678 | if (sb->s_flags & MS_SYNCHRONOUS) |
679 | ubh_sync_block(UCPI_UBH(ucpi)); | 679 | ubh_sync_block(UCPI_UBH(ucpi)); |
680 | sb->s_dirt = 1; | 680 | ufs_mark_sb_dirty(sb); |
681 | 681 | ||
682 | result += cgno * uspi->s_fpg; | 682 | result += cgno * uspi->s_fpg; |
683 | UFSD("EXIT3, result %llu\n", (unsigned long long)result); | 683 | UFSD("EXIT3, result %llu\n", (unsigned long long)result); |
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 4ec5c1085a87..e84cbe21b986 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c | |||
@@ -116,7 +116,7 @@ void ufs_free_inode (struct inode * inode) | |||
116 | if (sb->s_flags & MS_SYNCHRONOUS) | 116 | if (sb->s_flags & MS_SYNCHRONOUS) |
117 | ubh_sync_block(UCPI_UBH(ucpi)); | 117 | ubh_sync_block(UCPI_UBH(ucpi)); |
118 | 118 | ||
119 | sb->s_dirt = 1; | 119 | ufs_mark_sb_dirty(sb); |
120 | unlock_super (sb); | 120 | unlock_super (sb); |
121 | UFSD("EXIT\n"); | 121 | UFSD("EXIT\n"); |
122 | } | 122 | } |
@@ -288,7 +288,7 @@ cg_found: | |||
288 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); | 288 | ubh_mark_buffer_dirty (UCPI_UBH(ucpi)); |
289 | if (sb->s_flags & MS_SYNCHRONOUS) | 289 | if (sb->s_flags & MS_SYNCHRONOUS) |
290 | ubh_sync_block(UCPI_UBH(ucpi)); | 290 | ubh_sync_block(UCPI_UBH(ucpi)); |
291 | sb->s_dirt = 1; | 291 | ufs_mark_sb_dirty(sb); |
292 | 292 | ||
293 | inode->i_ino = cg * uspi->s_ipg + bit; | 293 | inode->i_ino = cg * uspi->s_ipg + bit; |
294 | inode_init_owner(inode, dir, mode); | 294 | inode_init_owner(inode, dir, mode); |
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index a2281cadefa1..90d74b8f8eba 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c | |||
@@ -46,7 +46,7 @@ static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode) | |||
46 | return err; | 46 | return err; |
47 | } | 47 | } |
48 | 48 | ||
49 | static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) | 49 | static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags) |
50 | { | 50 | { |
51 | struct inode * inode = NULL; | 51 | struct inode * inode = NULL; |
52 | ino_t ino; | 52 | ino_t ino; |
@@ -71,7 +71,7 @@ static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, stru | |||
71 | * with d_instantiate(). | 71 | * with d_instantiate(). |
72 | */ | 72 | */ |
73 | static int ufs_create (struct inode * dir, struct dentry * dentry, umode_t mode, | 73 | static int ufs_create (struct inode * dir, struct dentry * dentry, umode_t mode, |
74 | struct nameidata *nd) | 74 | bool excl) |
75 | { | 75 | { |
76 | struct inode *inode; | 76 | struct inode *inode; |
77 | int err; | 77 | int err; |
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 302f340d0071..444927e5706b 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c | |||
@@ -302,7 +302,7 @@ void ufs_error (struct super_block * sb, const char * function, | |||
302 | if (!(sb->s_flags & MS_RDONLY)) { | 302 | if (!(sb->s_flags & MS_RDONLY)) { |
303 | usb1->fs_clean = UFS_FSBAD; | 303 | usb1->fs_clean = UFS_FSBAD; |
304 | ubh_mark_buffer_dirty(USPI_UBH(uspi)); | 304 | ubh_mark_buffer_dirty(USPI_UBH(uspi)); |
305 | sb->s_dirt = 1; | 305 | ufs_mark_sb_dirty(sb); |
306 | sb->s_flags |= MS_RDONLY; | 306 | sb->s_flags |= MS_RDONLY; |
307 | } | 307 | } |
308 | va_start (args, fmt); | 308 | va_start (args, fmt); |
@@ -334,7 +334,7 @@ void ufs_panic (struct super_block * sb, const char * function, | |||
334 | if (!(sb->s_flags & MS_RDONLY)) { | 334 | if (!(sb->s_flags & MS_RDONLY)) { |
335 | usb1->fs_clean = UFS_FSBAD; | 335 | usb1->fs_clean = UFS_FSBAD; |
336 | ubh_mark_buffer_dirty(USPI_UBH(uspi)); | 336 | ubh_mark_buffer_dirty(USPI_UBH(uspi)); |
337 | sb->s_dirt = 1; | 337 | ufs_mark_sb_dirty(sb); |
338 | } | 338 | } |
339 | va_start (args, fmt); | 339 | va_start (args, fmt); |
340 | vsnprintf (error_buf, sizeof(error_buf), fmt, args); | 340 | vsnprintf (error_buf, sizeof(error_buf), fmt, args); |
@@ -691,6 +691,83 @@ static void ufs_put_super_internal(struct super_block *sb) | |||
691 | UFSD("EXIT\n"); | 691 | UFSD("EXIT\n"); |
692 | } | 692 | } |
693 | 693 | ||
694 | static int ufs_sync_fs(struct super_block *sb, int wait) | ||
695 | { | ||
696 | struct ufs_sb_private_info * uspi; | ||
697 | struct ufs_super_block_first * usb1; | ||
698 | struct ufs_super_block_third * usb3; | ||
699 | unsigned flags; | ||
700 | |||
701 | lock_ufs(sb); | ||
702 | lock_super(sb); | ||
703 | |||
704 | UFSD("ENTER\n"); | ||
705 | |||
706 | flags = UFS_SB(sb)->s_flags; | ||
707 | uspi = UFS_SB(sb)->s_uspi; | ||
708 | usb1 = ubh_get_usb_first(uspi); | ||
709 | usb3 = ubh_get_usb_third(uspi); | ||
710 | |||
711 | usb1->fs_time = cpu_to_fs32(sb, get_seconds()); | ||
712 | if ((flags & UFS_ST_MASK) == UFS_ST_SUN || | ||
713 | (flags & UFS_ST_MASK) == UFS_ST_SUNOS || | ||
714 | (flags & UFS_ST_MASK) == UFS_ST_SUNx86) | ||
715 | ufs_set_fs_state(sb, usb1, usb3, | ||
716 | UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)); | ||
717 | ufs_put_cstotal(sb); | ||
718 | |||
719 | UFSD("EXIT\n"); | ||
720 | unlock_super(sb); | ||
721 | unlock_ufs(sb); | ||
722 | |||
723 | return 0; | ||
724 | } | ||
725 | |||
726 | static void delayed_sync_fs(struct work_struct *work) | ||
727 | { | ||
728 | struct ufs_sb_info *sbi; | ||
729 | |||
730 | sbi = container_of(work, struct ufs_sb_info, sync_work.work); | ||
731 | |||
732 | spin_lock(&sbi->work_lock); | ||
733 | sbi->work_queued = 0; | ||
734 | spin_unlock(&sbi->work_lock); | ||
735 | |||
736 | ufs_sync_fs(sbi->sb, 1); | ||
737 | } | ||
738 | |||
739 | void ufs_mark_sb_dirty(struct super_block *sb) | ||
740 | { | ||
741 | struct ufs_sb_info *sbi = UFS_SB(sb); | ||
742 | unsigned long delay; | ||
743 | |||
744 | spin_lock(&sbi->work_lock); | ||
745 | if (!sbi->work_queued) { | ||
746 | delay = msecs_to_jiffies(dirty_writeback_interval * 10); | ||
747 | queue_delayed_work(system_long_wq, &sbi->sync_work, delay); | ||
748 | sbi->work_queued = 1; | ||
749 | } | ||
750 | spin_unlock(&sbi->work_lock); | ||
751 | } | ||
752 | |||
753 | static void ufs_put_super(struct super_block *sb) | ||
754 | { | ||
755 | struct ufs_sb_info * sbi = UFS_SB(sb); | ||
756 | |||
757 | UFSD("ENTER\n"); | ||
758 | |||
759 | if (!(sb->s_flags & MS_RDONLY)) | ||
760 | ufs_put_super_internal(sb); | ||
761 | cancel_delayed_work_sync(&sbi->sync_work); | ||
762 | |||
763 | ubh_brelse_uspi (sbi->s_uspi); | ||
764 | kfree (sbi->s_uspi); | ||
765 | kfree (sbi); | ||
766 | sb->s_fs_info = NULL; | ||
767 | UFSD("EXIT\n"); | ||
768 | return; | ||
769 | } | ||
770 | |||
694 | static int ufs_fill_super(struct super_block *sb, void *data, int silent) | 771 | static int ufs_fill_super(struct super_block *sb, void *data, int silent) |
695 | { | 772 | { |
696 | struct ufs_sb_info * sbi; | 773 | struct ufs_sb_info * sbi; |
@@ -716,6 +793,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
716 | if (!sbi) | 793 | if (!sbi) |
717 | goto failed_nomem; | 794 | goto failed_nomem; |
718 | sb->s_fs_info = sbi; | 795 | sb->s_fs_info = sbi; |
796 | sbi->sb = sb; | ||
719 | 797 | ||
720 | UFSD("flag %u\n", (int)(sb->s_flags & MS_RDONLY)); | 798 | UFSD("flag %u\n", (int)(sb->s_flags & MS_RDONLY)); |
721 | 799 | ||
@@ -727,6 +805,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent) | |||
727 | } | 805 | } |
728 | #endif | 806 | #endif |
729 | mutex_init(&sbi->mutex); | 807 | mutex_init(&sbi->mutex); |
808 | spin_lock_init(&sbi->work_lock); | ||
809 | INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs); | ||
730 | /* | 810 | /* |
731 | * Set default mount options | 811 | * Set default mount options |
732 | * Parse mount options | 812 | * Parse mount options |
@@ -1191,68 +1271,6 @@ failed_nomem: | |||
1191 | return -ENOMEM; | 1271 | return -ENOMEM; |
1192 | } | 1272 | } |
1193 | 1273 | ||
1194 | static int ufs_sync_fs(struct super_block *sb, int wait) | ||
1195 | { | ||
1196 | struct ufs_sb_private_info * uspi; | ||
1197 | struct ufs_super_block_first * usb1; | ||
1198 | struct ufs_super_block_third * usb3; | ||
1199 | unsigned flags; | ||
1200 | |||
1201 | lock_ufs(sb); | ||
1202 | lock_super(sb); | ||
1203 | |||
1204 | UFSD("ENTER\n"); | ||
1205 | |||
1206 | flags = UFS_SB(sb)->s_flags; | ||
1207 | uspi = UFS_SB(sb)->s_uspi; | ||
1208 | usb1 = ubh_get_usb_first(uspi); | ||
1209 | usb3 = ubh_get_usb_third(uspi); | ||
1210 | |||
1211 | usb1->fs_time = cpu_to_fs32(sb, get_seconds()); | ||
1212 | if ((flags & UFS_ST_MASK) == UFS_ST_SUN || | ||
1213 | (flags & UFS_ST_MASK) == UFS_ST_SUNOS || | ||
1214 | (flags & UFS_ST_MASK) == UFS_ST_SUNx86) | ||
1215 | ufs_set_fs_state(sb, usb1, usb3, | ||
1216 | UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)); | ||
1217 | ufs_put_cstotal(sb); | ||
1218 | sb->s_dirt = 0; | ||
1219 | |||
1220 | UFSD("EXIT\n"); | ||
1221 | unlock_super(sb); | ||
1222 | unlock_ufs(sb); | ||
1223 | |||
1224 | return 0; | ||
1225 | } | ||
1226 | |||
1227 | static void ufs_write_super(struct super_block *sb) | ||
1228 | { | ||
1229 | if (!(sb->s_flags & MS_RDONLY)) | ||
1230 | ufs_sync_fs(sb, 1); | ||
1231 | else | ||
1232 | sb->s_dirt = 0; | ||
1233 | } | ||
1234 | |||
1235 | static void ufs_put_super(struct super_block *sb) | ||
1236 | { | ||
1237 | struct ufs_sb_info * sbi = UFS_SB(sb); | ||
1238 | |||
1239 | UFSD("ENTER\n"); | ||
1240 | |||
1241 | if (sb->s_dirt) | ||
1242 | ufs_write_super(sb); | ||
1243 | |||
1244 | if (!(sb->s_flags & MS_RDONLY)) | ||
1245 | ufs_put_super_internal(sb); | ||
1246 | |||
1247 | ubh_brelse_uspi (sbi->s_uspi); | ||
1248 | kfree (sbi->s_uspi); | ||
1249 | kfree (sbi); | ||
1250 | sb->s_fs_info = NULL; | ||
1251 | UFSD("EXIT\n"); | ||
1252 | return; | ||
1253 | } | ||
1254 | |||
1255 | |||
1256 | static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | 1274 | static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) |
1257 | { | 1275 | { |
1258 | struct ufs_sb_private_info * uspi; | 1276 | struct ufs_sb_private_info * uspi; |
@@ -1308,7 +1326,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
1308 | ufs_set_fs_state(sb, usb1, usb3, | 1326 | ufs_set_fs_state(sb, usb1, usb3, |
1309 | UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)); | 1327 | UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time)); |
1310 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); | 1328 | ubh_mark_buffer_dirty (USPI_UBH(uspi)); |
1311 | sb->s_dirt = 0; | ||
1312 | sb->s_flags |= MS_RDONLY; | 1329 | sb->s_flags |= MS_RDONLY; |
1313 | } else { | 1330 | } else { |
1314 | /* | 1331 | /* |
@@ -1458,7 +1475,6 @@ static const struct super_operations ufs_super_ops = { | |||
1458 | .write_inode = ufs_write_inode, | 1475 | .write_inode = ufs_write_inode, |
1459 | .evict_inode = ufs_evict_inode, | 1476 | .evict_inode = ufs_evict_inode, |
1460 | .put_super = ufs_put_super, | 1477 | .put_super = ufs_put_super, |
1461 | .write_super = ufs_write_super, | ||
1462 | .sync_fs = ufs_sync_fs, | 1478 | .sync_fs = ufs_sync_fs, |
1463 | .statfs = ufs_statfs, | 1479 | .statfs = ufs_statfs, |
1464 | .remount_fs = ufs_remount, | 1480 | .remount_fs = ufs_remount, |
diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h index 528750b7e701..343e6fc571e5 100644 --- a/fs/ufs/ufs.h +++ b/fs/ufs/ufs.h | |||
@@ -20,6 +20,10 @@ struct ufs_sb_info { | |||
20 | unsigned s_mount_opt; | 20 | unsigned s_mount_opt; |
21 | struct mutex mutex; | 21 | struct mutex mutex; |
22 | struct task_struct *mutex_owner; | 22 | struct task_struct *mutex_owner; |
23 | struct super_block *sb; | ||
24 | int work_queued; /* non-zero if the delayed work is queued */ | ||
25 | struct delayed_work sync_work; /* FS sync delayed work */ | ||
26 | spinlock_t work_lock; /* protects sync_work and work_queued */ | ||
23 | }; | 27 | }; |
24 | 28 | ||
25 | struct ufs_inode_info { | 29 | struct ufs_inode_info { |
@@ -123,6 +127,7 @@ extern __printf(3, 4) | |||
123 | void ufs_error(struct super_block *, const char *, const char *, ...); | 127 | void ufs_error(struct super_block *, const char *, const char *, ...); |
124 | extern __printf(3, 4) | 128 | extern __printf(3, 4) |
125 | void ufs_panic(struct super_block *, const char *, const char *, ...); | 129 | void ufs_panic(struct super_block *, const char *, const char *, ...); |
130 | void ufs_mark_sb_dirty(struct super_block *sb); | ||
126 | 131 | ||
127 | /* symlink.c */ | 132 | /* symlink.c */ |
128 | extern const struct inode_operations ufs_fast_symlink_inode_operations; | 133 | extern const struct inode_operations ufs_fast_symlink_inode_operations; |
diff --git a/fs/ufs/ufs_fs.h b/fs/ufs/ufs_fs.h index 8aba544f9fad..0cbd5d340b67 100644 --- a/fs/ufs/ufs_fs.h +++ b/fs/ufs/ufs_fs.h | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
35 | #include <linux/stat.h> | 35 | #include <linux/stat.h> |
36 | #include <linux/fs.h> | 36 | #include <linux/fs.h> |
37 | #include <linux/workqueue.h> | ||
37 | 38 | ||
38 | #include <asm/div64.h> | 39 | #include <asm/div64.h> |
39 | typedef __u64 __bitwise __fs64; | 40 | typedef __u64 __bitwise __fs64; |
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 3a05a41b5d76..1f1535d25a9b 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c | |||
@@ -208,6 +208,7 @@ xfs_open_by_handle( | |||
208 | struct inode *inode; | 208 | struct inode *inode; |
209 | struct dentry *dentry; | 209 | struct dentry *dentry; |
210 | fmode_t fmode; | 210 | fmode_t fmode; |
211 | struct path path; | ||
211 | 212 | ||
212 | if (!capable(CAP_SYS_ADMIN)) | 213 | if (!capable(CAP_SYS_ADMIN)) |
213 | return -XFS_ERROR(EPERM); | 214 | return -XFS_ERROR(EPERM); |
@@ -252,8 +253,10 @@ xfs_open_by_handle( | |||
252 | goto out_dput; | 253 | goto out_dput; |
253 | } | 254 | } |
254 | 255 | ||
255 | filp = dentry_open(dentry, mntget(parfilp->f_path.mnt), | 256 | path.mnt = parfilp->f_path.mnt; |
256 | hreq->oflags, cred); | 257 | path.dentry = dentry; |
258 | filp = dentry_open(&path, hreq->oflags, cred); | ||
259 | dput(dentry); | ||
257 | if (IS_ERR(filp)) { | 260 | if (IS_ERR(filp)) { |
258 | put_unused_fd(fd); | 261 | put_unused_fd(fd); |
259 | return PTR_ERR(filp); | 262 | return PTR_ERR(filp); |
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 1a25fd802798..9c4340f5c3e0 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c | |||
@@ -179,7 +179,7 @@ xfs_vn_create( | |||
179 | struct inode *dir, | 179 | struct inode *dir, |
180 | struct dentry *dentry, | 180 | struct dentry *dentry, |
181 | umode_t mode, | 181 | umode_t mode, |
182 | struct nameidata *nd) | 182 | bool flags) |
183 | { | 183 | { |
184 | return xfs_vn_mknod(dir, dentry, mode, 0); | 184 | return xfs_vn_mknod(dir, dentry, mode, 0); |
185 | } | 185 | } |
@@ -197,7 +197,7 @@ STATIC struct dentry * | |||
197 | xfs_vn_lookup( | 197 | xfs_vn_lookup( |
198 | struct inode *dir, | 198 | struct inode *dir, |
199 | struct dentry *dentry, | 199 | struct dentry *dentry, |
200 | struct nameidata *nd) | 200 | unsigned int flags) |
201 | { | 201 | { |
202 | struct xfs_inode *cip; | 202 | struct xfs_inode *cip; |
203 | struct xfs_name name; | 203 | struct xfs_name name; |
@@ -222,7 +222,7 @@ STATIC struct dentry * | |||
222 | xfs_vn_ci_lookup( | 222 | xfs_vn_ci_lookup( |
223 | struct inode *dir, | 223 | struct inode *dir, |
224 | struct dentry *dentry, | 224 | struct dentry *dentry, |
225 | struct nameidata *nd) | 225 | unsigned int flags) |
226 | { | 226 | { |
227 | struct xfs_inode *ip; | 227 | struct xfs_inode *ip; |
228 | struct xfs_name xname; | 228 | struct xfs_name xname; |
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 094789ff3e9f..caa34e50537e 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
@@ -128,7 +128,7 @@ struct dentry { | |||
128 | struct rcu_head d_rcu; | 128 | struct rcu_head d_rcu; |
129 | } d_u; | 129 | } d_u; |
130 | struct list_head d_subdirs; /* our children */ | 130 | struct list_head d_subdirs; /* our children */ |
131 | struct list_head d_alias; /* inode alias list */ | 131 | struct hlist_node d_alias; /* inode alias list */ |
132 | }; | 132 | }; |
133 | 133 | ||
134 | /* | 134 | /* |
@@ -144,7 +144,7 @@ enum dentry_d_lock_class | |||
144 | }; | 144 | }; |
145 | 145 | ||
146 | struct dentry_operations { | 146 | struct dentry_operations { |
147 | int (*d_revalidate)(struct dentry *, struct nameidata *); | 147 | int (*d_revalidate)(struct dentry *, unsigned int); |
148 | int (*d_hash)(const struct dentry *, const struct inode *, | 148 | int (*d_hash)(const struct dentry *, const struct inode *, |
149 | struct qstr *); | 149 | struct qstr *); |
150 | int (*d_compare)(const struct dentry *, const struct inode *, | 150 | int (*d_compare)(const struct dentry *, const struct inode *, |
diff --git a/include/linux/file.h b/include/linux/file.h index 58bf158c53d9..a22408bac0d0 100644 --- a/include/linux/file.h +++ b/include/linux/file.h | |||
@@ -39,4 +39,7 @@ extern void put_unused_fd(unsigned int fd); | |||
39 | 39 | ||
40 | extern void fd_install(unsigned int fd, struct file *file); | 40 | extern void fd_install(unsigned int fd, struct file *file); |
41 | 41 | ||
42 | extern void flush_delayed_fput(void); | ||
43 | extern void __fput_sync(struct file *); | ||
44 | |||
42 | #endif /* __LINUX_FILE_H */ | 45 | #endif /* __LINUX_FILE_H */ |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 17fd887c798f..8fabb037a48d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -826,7 +826,7 @@ struct inode { | |||
826 | struct list_head i_lru; /* inode LRU list */ | 826 | struct list_head i_lru; /* inode LRU list */ |
827 | struct list_head i_sb_list; | 827 | struct list_head i_sb_list; |
828 | union { | 828 | union { |
829 | struct list_head i_dentry; | 829 | struct hlist_head i_dentry; |
830 | struct rcu_head i_rcu; | 830 | struct rcu_head i_rcu; |
831 | }; | 831 | }; |
832 | u64 i_version; | 832 | u64 i_version; |
@@ -1571,7 +1571,7 @@ extern void unlock_super(struct super_block *); | |||
1571 | /* | 1571 | /* |
1572 | * VFS helper functions.. | 1572 | * VFS helper functions.. |
1573 | */ | 1573 | */ |
1574 | extern int vfs_create(struct inode *, struct dentry *, umode_t, struct nameidata *); | 1574 | extern int vfs_create(struct inode *, struct dentry *, umode_t, bool); |
1575 | extern int vfs_mkdir(struct inode *, struct dentry *, umode_t); | 1575 | extern int vfs_mkdir(struct inode *, struct dentry *, umode_t); |
1576 | extern int vfs_mknod(struct inode *, struct dentry *, umode_t, dev_t); | 1576 | extern int vfs_mknod(struct inode *, struct dentry *, umode_t, dev_t); |
1577 | extern int vfs_symlink(struct inode *, struct dentry *, const char *); | 1577 | extern int vfs_symlink(struct inode *, struct dentry *, const char *); |
@@ -1666,7 +1666,7 @@ struct file_operations { | |||
1666 | }; | 1666 | }; |
1667 | 1667 | ||
1668 | struct inode_operations { | 1668 | struct inode_operations { |
1669 | struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *); | 1669 | struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int); |
1670 | void * (*follow_link) (struct dentry *, struct nameidata *); | 1670 | void * (*follow_link) (struct dentry *, struct nameidata *); |
1671 | int (*permission) (struct inode *, int); | 1671 | int (*permission) (struct inode *, int); |
1672 | struct posix_acl * (*get_acl)(struct inode *, int); | 1672 | struct posix_acl * (*get_acl)(struct inode *, int); |
@@ -1674,7 +1674,7 @@ struct inode_operations { | |||
1674 | int (*readlink) (struct dentry *, char __user *,int); | 1674 | int (*readlink) (struct dentry *, char __user *,int); |
1675 | void (*put_link) (struct dentry *, struct nameidata *, void *); | 1675 | void (*put_link) (struct dentry *, struct nameidata *, void *); |
1676 | 1676 | ||
1677 | int (*create) (struct inode *,struct dentry *,umode_t,struct nameidata *); | 1677 | int (*create) (struct inode *,struct dentry *, umode_t, bool); |
1678 | int (*link) (struct dentry *,struct inode *,struct dentry *); | 1678 | int (*link) (struct dentry *,struct inode *,struct dentry *); |
1679 | int (*unlink) (struct inode *,struct dentry *); | 1679 | int (*unlink) (struct inode *,struct dentry *); |
1680 | int (*symlink) (struct inode *,struct dentry *,const char *); | 1680 | int (*symlink) (struct inode *,struct dentry *,const char *); |
@@ -1693,6 +1693,9 @@ struct inode_operations { | |||
1693 | int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, | 1693 | int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, |
1694 | u64 len); | 1694 | u64 len); |
1695 | int (*update_time)(struct inode *, struct timespec *, int); | 1695 | int (*update_time)(struct inode *, struct timespec *, int); |
1696 | int (*atomic_open)(struct inode *, struct dentry *, | ||
1697 | struct file *, unsigned open_flag, | ||
1698 | umode_t create_mode, int *opened); | ||
1696 | } ____cacheline_aligned; | 1699 | } ____cacheline_aligned; |
1697 | 1700 | ||
1698 | struct seq_file; | 1701 | struct seq_file; |
@@ -1911,7 +1914,7 @@ void free_anon_bdev(dev_t); | |||
1911 | struct super_block *sget(struct file_system_type *type, | 1914 | struct super_block *sget(struct file_system_type *type, |
1912 | int (*test)(struct super_block *,void *), | 1915 | int (*test)(struct super_block *,void *), |
1913 | int (*set)(struct super_block *,void *), | 1916 | int (*set)(struct super_block *,void *), |
1914 | void *data); | 1917 | int flags, void *data); |
1915 | extern struct dentry *mount_pseudo(struct file_system_type *, char *, | 1918 | extern struct dentry *mount_pseudo(struct file_system_type *, char *, |
1916 | const struct super_operations *ops, | 1919 | const struct super_operations *ops, |
1917 | const struct dentry_operations *dops, | 1920 | const struct dentry_operations *dops, |
@@ -2057,10 +2060,17 @@ extern long do_sys_open(int dfd, const char __user *filename, int flags, | |||
2057 | extern struct file *filp_open(const char *, int, umode_t); | 2060 | extern struct file *filp_open(const char *, int, umode_t); |
2058 | extern struct file *file_open_root(struct dentry *, struct vfsmount *, | 2061 | extern struct file *file_open_root(struct dentry *, struct vfsmount *, |
2059 | const char *, int); | 2062 | const char *, int); |
2060 | extern struct file * dentry_open(struct dentry *, struct vfsmount *, int, | 2063 | extern struct file * dentry_open(const struct path *, int, const struct cred *); |
2061 | const struct cred *); | ||
2062 | extern int filp_close(struct file *, fl_owner_t id); | 2064 | extern int filp_close(struct file *, fl_owner_t id); |
2063 | extern char * getname(const char __user *); | 2065 | extern char * getname(const char __user *); |
2066 | enum { | ||
2067 | FILE_CREATED = 1, | ||
2068 | FILE_OPENED = 2 | ||
2069 | }; | ||
2070 | extern int finish_open(struct file *file, struct dentry *dentry, | ||
2071 | int (*open)(struct inode *, struct file *), | ||
2072 | int *opened); | ||
2073 | extern int finish_no_open(struct file *file, struct dentry *dentry); | ||
2064 | 2074 | ||
2065 | /* fs/ioctl.c */ | 2075 | /* fs/ioctl.c */ |
2066 | 2076 | ||
@@ -2091,6 +2101,7 @@ extern sector_t blkdev_max_block(struct block_device *bdev); | |||
2091 | extern void bd_forget(struct inode *inode); | 2101 | extern void bd_forget(struct inode *inode); |
2092 | extern void bdput(struct block_device *); | 2102 | extern void bdput(struct block_device *); |
2093 | extern void invalidate_bdev(struct block_device *); | 2103 | extern void invalidate_bdev(struct block_device *); |
2104 | extern void iterate_bdevs(void (*)(struct block_device *, void *), void *); | ||
2094 | extern int sync_blockdev(struct block_device *bdev); | 2105 | extern int sync_blockdev(struct block_device *bdev); |
2095 | extern void kill_bdev(struct block_device *); | 2106 | extern void kill_bdev(struct block_device *); |
2096 | extern struct super_block *freeze_bdev(struct block_device *); | 2107 | extern struct super_block *freeze_bdev(struct block_device *); |
@@ -2112,6 +2123,10 @@ static inline int thaw_bdev(struct block_device *bdev, struct super_block *sb) | |||
2112 | { | 2123 | { |
2113 | return 0; | 2124 | return 0; |
2114 | } | 2125 | } |
2126 | |||
2127 | static inline void iterate_bdevs(void (*f)(struct block_device *, void *), void *arg) | ||
2128 | { | ||
2129 | } | ||
2115 | #endif | 2130 | #endif |
2116 | extern int sync_filesystem(struct super_block *); | 2131 | extern int sync_filesystem(struct super_block *); |
2117 | extern const struct file_operations def_blk_fops; | 2132 | extern const struct file_operations def_blk_fops; |
@@ -2438,7 +2453,7 @@ extern loff_t noop_llseek(struct file *file, loff_t offset, int origin); | |||
2438 | extern loff_t no_llseek(struct file *file, loff_t offset, int origin); | 2453 | extern loff_t no_llseek(struct file *file, loff_t offset, int origin); |
2439 | extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin); | 2454 | extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin); |
2440 | extern loff_t generic_file_llseek_size(struct file *file, loff_t offset, | 2455 | extern loff_t generic_file_llseek_size(struct file *file, loff_t offset, |
2441 | int origin, loff_t maxsize); | 2456 | int origin, loff_t maxsize, loff_t eof); |
2442 | extern int generic_file_open(struct inode * inode, struct file * filp); | 2457 | extern int generic_file_open(struct inode * inode, struct file * filp); |
2443 | extern int nonseekable_open(struct inode * inode, struct file * filp); | 2458 | extern int nonseekable_open(struct inode * inode, struct file * filp); |
2444 | 2459 | ||
@@ -2560,7 +2575,7 @@ extern int simple_write_end(struct file *file, struct address_space *mapping, | |||
2560 | loff_t pos, unsigned len, unsigned copied, | 2575 | loff_t pos, unsigned len, unsigned copied, |
2561 | struct page *page, void *fsdata); | 2576 | struct page *page, void *fsdata); |
2562 | 2577 | ||
2563 | extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *); | 2578 | extern struct dentry *simple_lookup(struct inode *, struct dentry *, unsigned int flags); |
2564 | extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *); | 2579 | extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *); |
2565 | extern const struct file_operations simple_dir_operations; | 2580 | extern const struct file_operations simple_dir_operations; |
2566 | extern const struct inode_operations simple_dir_inode_operations; | 2581 | extern const struct inode_operations simple_dir_inode_operations; |
diff --git a/include/linux/namei.h b/include/linux/namei.h index ffc02135c483..d2ef8b34b967 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h | |||
@@ -7,12 +7,6 @@ | |||
7 | 7 | ||
8 | struct vfsmount; | 8 | struct vfsmount; |
9 | 9 | ||
10 | struct open_intent { | ||
11 | int flags; | ||
12 | int create_mode; | ||
13 | struct file *file; | ||
14 | }; | ||
15 | |||
16 | enum { MAX_NESTED_LINKS = 8 }; | 10 | enum { MAX_NESTED_LINKS = 8 }; |
17 | 11 | ||
18 | struct nameidata { | 12 | struct nameidata { |
@@ -25,11 +19,6 @@ struct nameidata { | |||
25 | int last_type; | 19 | int last_type; |
26 | unsigned depth; | 20 | unsigned depth; |
27 | char *saved_names[MAX_NESTED_LINKS + 1]; | 21 | char *saved_names[MAX_NESTED_LINKS + 1]; |
28 | |||
29 | /* Intent data */ | ||
30 | union { | ||
31 | struct open_intent open; | ||
32 | } intent; | ||
33 | }; | 22 | }; |
34 | 23 | ||
35 | /* | 24 | /* |
@@ -78,13 +67,10 @@ extern int kern_path(const char *, unsigned, struct path *); | |||
78 | 67 | ||
79 | extern struct dentry *kern_path_create(int, const char *, struct path *, int); | 68 | extern struct dentry *kern_path_create(int, const char *, struct path *, int); |
80 | extern struct dentry *user_path_create(int, const char __user *, struct path *, int); | 69 | extern struct dentry *user_path_create(int, const char __user *, struct path *, int); |
81 | extern int kern_path_parent(const char *, struct nameidata *); | 70 | extern struct dentry *kern_path_locked(const char *, struct path *); |
82 | extern int vfs_path_lookup(struct dentry *, struct vfsmount *, | 71 | extern int vfs_path_lookup(struct dentry *, struct vfsmount *, |
83 | const char *, unsigned int, struct path *); | 72 | const char *, unsigned int, struct path *); |
84 | 73 | ||
85 | extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, | ||
86 | int (*open)(struct inode *, struct file *)); | ||
87 | |||
88 | extern struct dentry *lookup_one_len(const char *, struct dentry *, int); | 74 | extern struct dentry *lookup_one_len(const char *, struct dentry *, int); |
89 | 75 | ||
90 | extern int follow_down_one(struct path *); | 76 | extern int follow_down_one(struct path *); |
@@ -94,6 +80,8 @@ extern int follow_up(struct path *); | |||
94 | extern struct dentry *lock_rename(struct dentry *, struct dentry *); | 80 | extern struct dentry *lock_rename(struct dentry *, struct dentry *); |
95 | extern void unlock_rename(struct dentry *, struct dentry *); | 81 | extern void unlock_rename(struct dentry *, struct dentry *); |
96 | 82 | ||
83 | extern void nd_jump_link(struct nameidata *nd, struct path *path); | ||
84 | |||
97 | static inline void nd_set_link(struct nameidata *nd, char *path) | 85 | static inline void nd_set_link(struct nameidata *nd, char *path) |
98 | { | 86 | { |
99 | nd->saved_names[nd->depth] = path; | 87 | nd->saved_names[nd->depth] = path; |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 8aadd90b808a..d3b7c18b18f4 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -1374,7 +1374,7 @@ struct nfs_rpc_ops { | |||
1374 | int (*readlink)(struct inode *, struct page *, unsigned int, | 1374 | int (*readlink)(struct inode *, struct page *, unsigned int, |
1375 | unsigned int); | 1375 | unsigned int); |
1376 | int (*create) (struct inode *, struct dentry *, | 1376 | int (*create) (struct inode *, struct dentry *, |
1377 | struct iattr *, int, struct nfs_open_context *); | 1377 | struct iattr *, int); |
1378 | int (*remove) (struct inode *, struct qstr *); | 1378 | int (*remove) (struct inode *, struct qstr *); |
1379 | void (*unlink_setup) (struct rpc_message *, struct inode *dir); | 1379 | void (*unlink_setup) (struct rpc_message *, struct inode *dir); |
1380 | void (*unlink_rpc_prepare) (struct rpc_task *, struct nfs_unlinkdata *); | 1380 | void (*unlink_rpc_prepare) (struct rpc_task *, struct nfs_unlinkdata *); |
diff --git a/include/linux/quota.h b/include/linux/quota.h index c09fa042b5ea..524ede8a160a 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h | |||
@@ -333,7 +333,7 @@ struct quotactl_ops { | |||
333 | int (*quota_on)(struct super_block *, int, int, struct path *); | 333 | int (*quota_on)(struct super_block *, int, int, struct path *); |
334 | int (*quota_on_meta)(struct super_block *, int, int); | 334 | int (*quota_on_meta)(struct super_block *, int, int); |
335 | int (*quota_off)(struct super_block *, int); | 335 | int (*quota_off)(struct super_block *, int); |
336 | int (*quota_sync)(struct super_block *, int, int); | 336 | int (*quota_sync)(struct super_block *, int); |
337 | int (*get_info)(struct super_block *, int, struct if_dqinfo *); | 337 | int (*get_info)(struct super_block *, int, struct if_dqinfo *); |
338 | int (*set_info)(struct super_block *, int, struct if_dqinfo *); | 338 | int (*set_info)(struct super_block *, int, struct if_dqinfo *); |
339 | int (*get_dqblk)(struct super_block *, int, qid_t, struct fs_disk_quota *); | 339 | int (*get_dqblk)(struct super_block *, int, qid_t, struct fs_disk_quota *); |
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 17b977304a09..ec6b65feaaba 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h | |||
@@ -83,7 +83,8 @@ int dquot_quota_on(struct super_block *sb, int type, int format_id, | |||
83 | int dquot_quota_on_mount(struct super_block *sb, char *qf_name, | 83 | int dquot_quota_on_mount(struct super_block *sb, char *qf_name, |
84 | int format_id, int type); | 84 | int format_id, int type); |
85 | int dquot_quota_off(struct super_block *sb, int type); | 85 | int dquot_quota_off(struct super_block *sb, int type); |
86 | int dquot_quota_sync(struct super_block *sb, int type, int wait); | 86 | int dquot_writeback_dquots(struct super_block *sb, int type); |
87 | int dquot_quota_sync(struct super_block *sb, int type); | ||
87 | int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); | 88 | int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); |
88 | int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); | 89 | int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); |
89 | int dquot_get_dqblk(struct super_block *sb, int type, qid_t id, | 90 | int dquot_get_dqblk(struct super_block *sb, int type, qid_t id, |
@@ -255,6 +256,11 @@ static inline int dquot_resume(struct super_block *sb, int type) | |||
255 | 256 | ||
256 | #define dquot_file_open generic_file_open | 257 | #define dquot_file_open generic_file_open |
257 | 258 | ||
259 | static inline int dquot_writeback_dquots(struct super_block *sb, int type) | ||
260 | { | ||
261 | return 0; | ||
262 | } | ||
263 | |||
258 | #endif /* CONFIG_QUOTA */ | 264 | #endif /* CONFIG_QUOTA */ |
259 | 265 | ||
260 | static inline int dquot_alloc_space_nodirty(struct inode *inode, qsize_t nr) | 266 | static inline int dquot_alloc_space_nodirty(struct inode *inode, qsize_t nr) |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 64d9df5c3a49..1a2ebd39b800 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1405,7 +1405,7 @@ struct task_struct { | |||
1405 | int (*notifier)(void *priv); | 1405 | int (*notifier)(void *priv); |
1406 | void *notifier_data; | 1406 | void *notifier_data; |
1407 | sigset_t *notifier_mask; | 1407 | sigset_t *notifier_mask; |
1408 | struct hlist_head task_works; | 1408 | struct callback_head *task_works; |
1409 | 1409 | ||
1410 | struct audit_context *audit_context; | 1410 | struct audit_context *audit_context; |
1411 | #ifdef CONFIG_AUDITSYSCALL | 1411 | #ifdef CONFIG_AUDITSYSCALL |
@@ -1546,7 +1546,6 @@ struct task_struct { | |||
1546 | unsigned long timer_slack_ns; | 1546 | unsigned long timer_slack_ns; |
1547 | unsigned long default_timer_slack_ns; | 1547 | unsigned long default_timer_slack_ns; |
1548 | 1548 | ||
1549 | struct list_head *scm_work_list; | ||
1550 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 1549 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
1551 | /* Index of current stored address in ret_stack */ | 1550 | /* Index of current stored address in ret_stack */ |
1552 | int curr_ret_stack; | 1551 | int curr_ret_stack; |
diff --git a/include/linux/task_work.h b/include/linux/task_work.h index 294d5d5e90b1..fb46b03b1852 100644 --- a/include/linux/task_work.h +++ b/include/linux/task_work.h | |||
@@ -4,29 +4,21 @@ | |||
4 | #include <linux/list.h> | 4 | #include <linux/list.h> |
5 | #include <linux/sched.h> | 5 | #include <linux/sched.h> |
6 | 6 | ||
7 | struct task_work; | 7 | typedef void (*task_work_func_t)(struct callback_head *); |
8 | typedef void (*task_work_func_t)(struct task_work *); | ||
9 | |||
10 | struct task_work { | ||
11 | struct hlist_node hlist; | ||
12 | task_work_func_t func; | ||
13 | void *data; | ||
14 | }; | ||
15 | 8 | ||
16 | static inline void | 9 | static inline void |
17 | init_task_work(struct task_work *twork, task_work_func_t func, void *data) | 10 | init_task_work(struct callback_head *twork, task_work_func_t func) |
18 | { | 11 | { |
19 | twork->func = func; | 12 | twork->func = func; |
20 | twork->data = data; | ||
21 | } | 13 | } |
22 | 14 | ||
23 | int task_work_add(struct task_struct *task, struct task_work *twork, bool); | 15 | int task_work_add(struct task_struct *task, struct callback_head *twork, bool); |
24 | struct task_work *task_work_cancel(struct task_struct *, task_work_func_t); | 16 | struct callback_head *task_work_cancel(struct task_struct *, task_work_func_t); |
25 | void task_work_run(void); | 17 | void task_work_run(void); |
26 | 18 | ||
27 | static inline void exit_task_work(struct task_struct *task) | 19 | static inline void exit_task_work(struct task_struct *task) |
28 | { | 20 | { |
29 | if (unlikely(!hlist_empty(&task->task_works))) | 21 | if (unlikely(task->task_works)) |
30 | task_work_run(); | 22 | task_work_run(); |
31 | } | 23 | } |
32 | 24 | ||
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h index 6a4d82bedb03..1e98b5530425 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h | |||
@@ -192,7 +192,7 @@ static inline void tracehook_notify_resume(struct pt_regs *regs) | |||
192 | * hlist_add_head(task->task_works); | 192 | * hlist_add_head(task->task_works); |
193 | */ | 193 | */ |
194 | smp_mb__after_clear_bit(); | 194 | smp_mb__after_clear_bit(); |
195 | if (unlikely(!hlist_empty(¤t->task_works))) | 195 | if (unlikely(current->task_works)) |
196 | task_work_run(); | 196 | task_work_run(); |
197 | } | 197 | } |
198 | 198 | ||
diff --git a/include/linux/types.h b/include/linux/types.h index 9c1bd539ea70..bf0dd7524b2a 100644 --- a/include/linux/types.h +++ b/include/linux/types.h | |||
@@ -246,14 +246,15 @@ struct ustat { | |||
246 | }; | 246 | }; |
247 | 247 | ||
248 | /** | 248 | /** |
249 | * struct rcu_head - callback structure for use with RCU | 249 | * struct callback_head - callback structure for use with RCU and task_work |
250 | * @next: next update requests in a list | 250 | * @next: next update requests in a list |
251 | * @func: actual update function to call after the grace period. | 251 | * @func: actual update function to call after the grace period. |
252 | */ | 252 | */ |
253 | struct rcu_head { | 253 | struct callback_head { |
254 | struct rcu_head *next; | 254 | struct callback_head *next; |
255 | void (*func)(struct rcu_head *head); | 255 | void (*func)(struct callback_head *head); |
256 | }; | 256 | }; |
257 | #define rcu_head callback_head | ||
257 | 258 | ||
258 | #endif /* __KERNEL__ */ | 259 | #endif /* __KERNEL__ */ |
259 | #endif /* __ASSEMBLY__ */ | 260 | #endif /* __ASSEMBLY__ */ |
diff --git a/include/net/scm.h b/include/net/scm.h index d456f4c71a32..079d7887dac1 100644 --- a/include/net/scm.h +++ b/include/net/scm.h | |||
@@ -13,7 +13,6 @@ | |||
13 | #define SCM_MAX_FD 253 | 13 | #define SCM_MAX_FD 253 |
14 | 14 | ||
15 | struct scm_fp_list { | 15 | struct scm_fp_list { |
16 | struct list_head list; | ||
17 | short count; | 16 | short count; |
18 | short max; | 17 | short max; |
19 | struct file *fp[SCM_MAX_FD]; | 18 | struct file *fp[SCM_MAX_FD]; |
diff --git a/init/main.c b/init/main.c index b5cc0a7c4708..3f151f6c6da7 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -68,6 +68,7 @@ | |||
68 | #include <linux/shmem_fs.h> | 68 | #include <linux/shmem_fs.h> |
69 | #include <linux/slab.h> | 69 | #include <linux/slab.h> |
70 | #include <linux/perf_event.h> | 70 | #include <linux/perf_event.h> |
71 | #include <linux/file.h> | ||
71 | 72 | ||
72 | #include <asm/io.h> | 73 | #include <asm/io.h> |
73 | #include <asm/bugs.h> | 74 | #include <asm/bugs.h> |
@@ -804,8 +805,8 @@ static noinline int init_post(void) | |||
804 | system_state = SYSTEM_RUNNING; | 805 | system_state = SYSTEM_RUNNING; |
805 | numa_default_policy(); | 806 | numa_default_policy(); |
806 | 807 | ||
807 | |||
808 | current->signal->flags |= SIGNAL_UNKILLABLE; | 808 | current->signal->flags |= SIGNAL_UNKILLABLE; |
809 | flush_delayed_fput(); | ||
809 | 810 | ||
810 | if (ramdisk_execute_command) { | 811 | if (ramdisk_execute_command) { |
811 | run_init_process(ramdisk_execute_command); | 812 | run_init_process(ramdisk_execute_command); |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 8ce57691e7b6..f8e54f5b9080 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -413,7 +413,7 @@ static void mqueue_evict_inode(struct inode *inode) | |||
413 | } | 413 | } |
414 | 414 | ||
415 | static int mqueue_create(struct inode *dir, struct dentry *dentry, | 415 | static int mqueue_create(struct inode *dir, struct dentry *dentry, |
416 | umode_t mode, struct nameidata *nd) | 416 | umode_t mode, bool excl) |
417 | { | 417 | { |
418 | struct inode *inode; | 418 | struct inode *inode; |
419 | struct mq_attr *attr = dentry->d_fsdata; | 419 | struct mq_attr *attr = dentry->d_fsdata; |
@@ -721,8 +721,8 @@ static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr) | |||
721 | /* | 721 | /* |
722 | * Invoked when creating a new queue via sys_mq_open | 722 | * Invoked when creating a new queue via sys_mq_open |
723 | */ | 723 | */ |
724 | static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir, | 724 | static struct file *do_create(struct ipc_namespace *ipc_ns, struct inode *dir, |
725 | struct dentry *dentry, int oflag, umode_t mode, | 725 | struct path *path, int oflag, umode_t mode, |
726 | struct mq_attr *attr) | 726 | struct mq_attr *attr) |
727 | { | 727 | { |
728 | const struct cred *cred = current_cred(); | 728 | const struct cred *cred = current_cred(); |
@@ -732,9 +732,9 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir, | |||
732 | if (attr) { | 732 | if (attr) { |
733 | ret = mq_attr_ok(ipc_ns, attr); | 733 | ret = mq_attr_ok(ipc_ns, attr); |
734 | if (ret) | 734 | if (ret) |
735 | goto out; | 735 | return ERR_PTR(ret); |
736 | /* store for use during create */ | 736 | /* store for use during create */ |
737 | dentry->d_fsdata = attr; | 737 | path->dentry->d_fsdata = attr; |
738 | } else { | 738 | } else { |
739 | struct mq_attr def_attr; | 739 | struct mq_attr def_attr; |
740 | 740 | ||
@@ -744,71 +744,51 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir, | |||
744 | ipc_ns->mq_msgsize_default); | 744 | ipc_ns->mq_msgsize_default); |
745 | ret = mq_attr_ok(ipc_ns, &def_attr); | 745 | ret = mq_attr_ok(ipc_ns, &def_attr); |
746 | if (ret) | 746 | if (ret) |
747 | goto out; | 747 | return ERR_PTR(ret); |
748 | } | 748 | } |
749 | 749 | ||
750 | mode &= ~current_umask(); | 750 | mode &= ~current_umask(); |
751 | ret = mnt_want_write(ipc_ns->mq_mnt); | 751 | ret = mnt_want_write(path->mnt); |
752 | if (ret) | 752 | if (ret) |
753 | goto out; | 753 | return ERR_PTR(ret); |
754 | ret = vfs_create(dir->d_inode, dentry, mode, NULL); | 754 | ret = vfs_create(dir, path->dentry, mode, true); |
755 | dentry->d_fsdata = NULL; | 755 | path->dentry->d_fsdata = NULL; |
756 | if (ret) | 756 | if (!ret) |
757 | goto out_drop_write; | 757 | result = dentry_open(path, oflag, cred); |
758 | 758 | else | |
759 | result = dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred); | 759 | result = ERR_PTR(ret); |
760 | /* | 760 | /* |
761 | * dentry_open() took a persistent mnt_want_write(), | 761 | * dentry_open() took a persistent mnt_want_write(), |
762 | * so we can now drop this one. | 762 | * so we can now drop this one. |
763 | */ | 763 | */ |
764 | mnt_drop_write(ipc_ns->mq_mnt); | 764 | mnt_drop_write(path->mnt); |
765 | return result; | 765 | return result; |
766 | |||
767 | out_drop_write: | ||
768 | mnt_drop_write(ipc_ns->mq_mnt); | ||
769 | out: | ||
770 | dput(dentry); | ||
771 | mntput(ipc_ns->mq_mnt); | ||
772 | return ERR_PTR(ret); | ||
773 | } | 766 | } |
774 | 767 | ||
775 | /* Opens existing queue */ | 768 | /* Opens existing queue */ |
776 | static struct file *do_open(struct ipc_namespace *ipc_ns, | 769 | static struct file *do_open(struct path *path, int oflag) |
777 | struct dentry *dentry, int oflag) | ||
778 | { | 770 | { |
779 | int ret; | ||
780 | const struct cred *cred = current_cred(); | ||
781 | |||
782 | static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, | 771 | static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, |
783 | MAY_READ | MAY_WRITE }; | 772 | MAY_READ | MAY_WRITE }; |
784 | 773 | int acc; | |
785 | if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { | 774 | if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) |
786 | ret = -EINVAL; | 775 | return ERR_PTR(-EINVAL); |
787 | goto err; | 776 | acc = oflag2acc[oflag & O_ACCMODE]; |
788 | } | 777 | if (inode_permission(path->dentry->d_inode, acc)) |
789 | 778 | return ERR_PTR(-EACCES); | |
790 | if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) { | 779 | return dentry_open(path, oflag, current_cred()); |
791 | ret = -EACCES; | ||
792 | goto err; | ||
793 | } | ||
794 | |||
795 | return dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred); | ||
796 | |||
797 | err: | ||
798 | dput(dentry); | ||
799 | mntput(ipc_ns->mq_mnt); | ||
800 | return ERR_PTR(ret); | ||
801 | } | 780 | } |
802 | 781 | ||
803 | SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, | 782 | SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, |
804 | struct mq_attr __user *, u_attr) | 783 | struct mq_attr __user *, u_attr) |
805 | { | 784 | { |
806 | struct dentry *dentry; | 785 | struct path path; |
807 | struct file *filp; | 786 | struct file *filp; |
808 | char *name; | 787 | char *name; |
809 | struct mq_attr attr; | 788 | struct mq_attr attr; |
810 | int fd, error; | 789 | int fd, error; |
811 | struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; | 790 | struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; |
791 | struct dentry *root = ipc_ns->mq_mnt->mnt_root; | ||
812 | 792 | ||
813 | if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr))) | 793 | if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr))) |
814 | return -EFAULT; | 794 | return -EFAULT; |
@@ -822,52 +802,49 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, | |||
822 | if (fd < 0) | 802 | if (fd < 0) |
823 | goto out_putname; | 803 | goto out_putname; |
824 | 804 | ||
825 | mutex_lock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex); | 805 | error = 0; |
826 | dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name)); | 806 | mutex_lock(&root->d_inode->i_mutex); |
827 | if (IS_ERR(dentry)) { | 807 | path.dentry = lookup_one_len(name, root, strlen(name)); |
828 | error = PTR_ERR(dentry); | 808 | if (IS_ERR(path.dentry)) { |
809 | error = PTR_ERR(path.dentry); | ||
829 | goto out_putfd; | 810 | goto out_putfd; |
830 | } | 811 | } |
831 | mntget(ipc_ns->mq_mnt); | 812 | path.mnt = mntget(ipc_ns->mq_mnt); |
832 | 813 | ||
833 | if (oflag & O_CREAT) { | 814 | if (oflag & O_CREAT) { |
834 | if (dentry->d_inode) { /* entry already exists */ | 815 | if (path.dentry->d_inode) { /* entry already exists */ |
835 | audit_inode(name, dentry); | 816 | audit_inode(name, path.dentry); |
836 | if (oflag & O_EXCL) { | 817 | if (oflag & O_EXCL) { |
837 | error = -EEXIST; | 818 | error = -EEXIST; |
838 | goto out; | 819 | goto out; |
839 | } | 820 | } |
840 | filp = do_open(ipc_ns, dentry, oflag); | 821 | filp = do_open(&path, oflag); |
841 | } else { | 822 | } else { |
842 | filp = do_create(ipc_ns, ipc_ns->mq_mnt->mnt_root, | 823 | filp = do_create(ipc_ns, root->d_inode, |
843 | dentry, oflag, mode, | 824 | &path, oflag, mode, |
844 | u_attr ? &attr : NULL); | 825 | u_attr ? &attr : NULL); |
845 | } | 826 | } |
846 | } else { | 827 | } else { |
847 | if (!dentry->d_inode) { | 828 | if (!path.dentry->d_inode) { |
848 | error = -ENOENT; | 829 | error = -ENOENT; |
849 | goto out; | 830 | goto out; |
850 | } | 831 | } |
851 | audit_inode(name, dentry); | 832 | audit_inode(name, path.dentry); |
852 | filp = do_open(ipc_ns, dentry, oflag); | 833 | filp = do_open(&path, oflag); |
853 | } | 834 | } |
854 | 835 | ||
855 | if (IS_ERR(filp)) { | 836 | if (!IS_ERR(filp)) |
837 | fd_install(fd, filp); | ||
838 | else | ||
856 | error = PTR_ERR(filp); | 839 | error = PTR_ERR(filp); |
857 | goto out_putfd; | ||
858 | } | ||
859 | |||
860 | fd_install(fd, filp); | ||
861 | goto out_upsem; | ||
862 | |||
863 | out: | 840 | out: |
864 | dput(dentry); | 841 | path_put(&path); |
865 | mntput(ipc_ns->mq_mnt); | ||
866 | out_putfd: | 842 | out_putfd: |
867 | put_unused_fd(fd); | 843 | if (error) { |
868 | fd = error; | 844 | put_unused_fd(fd); |
869 | out_upsem: | 845 | fd = error; |
870 | mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex); | 846 | } |
847 | mutex_unlock(&root->d_inode->i_mutex); | ||
871 | out_putname: | 848 | out_putname: |
872 | putname(name); | 849 | putname(name); |
873 | return fd; | 850 | return fd; |
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 5bf0790497e7..3a5ca582ba1e 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c | |||
@@ -595,7 +595,7 @@ void audit_trim_trees(void) | |||
595 | 595 | ||
596 | root_mnt = collect_mounts(&path); | 596 | root_mnt = collect_mounts(&path); |
597 | path_put(&path); | 597 | path_put(&path); |
598 | if (!root_mnt) | 598 | if (IS_ERR(root_mnt)) |
599 | goto skip_it; | 599 | goto skip_it; |
600 | 600 | ||
601 | spin_lock(&hash_lock); | 601 | spin_lock(&hash_lock); |
@@ -669,8 +669,8 @@ int audit_add_tree_rule(struct audit_krule *rule) | |||
669 | goto Err; | 669 | goto Err; |
670 | mnt = collect_mounts(&path); | 670 | mnt = collect_mounts(&path); |
671 | path_put(&path); | 671 | path_put(&path); |
672 | if (!mnt) { | 672 | if (IS_ERR(mnt)) { |
673 | err = -ENOMEM; | 673 | err = PTR_ERR(mnt); |
674 | goto Err; | 674 | goto Err; |
675 | } | 675 | } |
676 | 676 | ||
@@ -719,8 +719,8 @@ int audit_tag_tree(char *old, char *new) | |||
719 | return err; | 719 | return err; |
720 | tagged = collect_mounts(&path2); | 720 | tagged = collect_mounts(&path2); |
721 | path_put(&path2); | 721 | path_put(&path2); |
722 | if (!tagged) | 722 | if (IS_ERR(tagged)) |
723 | return -ENOMEM; | 723 | return PTR_ERR(tagged); |
724 | 724 | ||
725 | err = kern_path(old, 0, &path1); | 725 | err = kern_path(old, 0, &path1); |
726 | if (err) { | 726 | if (err) { |
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index e683869365d9..3823281401b5 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c | |||
@@ -355,34 +355,15 @@ static void audit_remove_parent_watches(struct audit_parent *parent) | |||
355 | /* Get path information necessary for adding watches. */ | 355 | /* Get path information necessary for adding watches. */ |
356 | static int audit_get_nd(struct audit_watch *watch, struct path *parent) | 356 | static int audit_get_nd(struct audit_watch *watch, struct path *parent) |
357 | { | 357 | { |
358 | struct nameidata nd; | 358 | struct dentry *d = kern_path_locked(watch->path, parent); |
359 | struct dentry *d; | 359 | if (IS_ERR(d)) |
360 | int err; | ||
361 | |||
362 | err = kern_path_parent(watch->path, &nd); | ||
363 | if (err) | ||
364 | return err; | ||
365 | |||
366 | if (nd.last_type != LAST_NORM) { | ||
367 | path_put(&nd.path); | ||
368 | return -EINVAL; | ||
369 | } | ||
370 | |||
371 | mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); | ||
372 | d = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); | ||
373 | if (IS_ERR(d)) { | ||
374 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | ||
375 | path_put(&nd.path); | ||
376 | return PTR_ERR(d); | 360 | return PTR_ERR(d); |
377 | } | 361 | mutex_unlock(&parent->dentry->d_inode->i_mutex); |
378 | if (d->d_inode) { | 362 | if (d->d_inode) { |
379 | /* update watch filter fields */ | 363 | /* update watch filter fields */ |
380 | watch->dev = d->d_inode->i_sb->s_dev; | 364 | watch->dev = d->d_inode->i_sb->s_dev; |
381 | watch->ino = d->d_inode->i_ino; | 365 | watch->ino = d->d_inode->i_ino; |
382 | } | 366 | } |
383 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | ||
384 | |||
385 | *parent = nd.path; | ||
386 | dput(d); | 367 | dput(d); |
387 | return 0; | 368 | return 0; |
388 | } | 369 | } |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index b303dfc7dce0..af2b5641fc8b 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -822,7 +822,7 @@ EXPORT_SYMBOL_GPL(cgroup_unlock); | |||
822 | */ | 822 | */ |
823 | 823 | ||
824 | static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); | 824 | static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); |
825 | static struct dentry *cgroup_lookup(struct inode *, struct dentry *, struct nameidata *); | 825 | static struct dentry *cgroup_lookup(struct inode *, struct dentry *, unsigned int); |
826 | static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry); | 826 | static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry); |
827 | static int cgroup_populate_dir(struct cgroup *cgrp); | 827 | static int cgroup_populate_dir(struct cgroup *cgrp); |
828 | static const struct inode_operations cgroup_dir_inode_operations; | 828 | static const struct inode_operations cgroup_dir_inode_operations; |
@@ -1587,7 +1587,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, | |||
1587 | opts.new_root = new_root; | 1587 | opts.new_root = new_root; |
1588 | 1588 | ||
1589 | /* Locate an existing or new sb for this hierarchy */ | 1589 | /* Locate an existing or new sb for this hierarchy */ |
1590 | sb = sget(fs_type, cgroup_test_super, cgroup_set_super, &opts); | 1590 | sb = sget(fs_type, cgroup_test_super, cgroup_set_super, 0, &opts); |
1591 | if (IS_ERR(sb)) { | 1591 | if (IS_ERR(sb)) { |
1592 | ret = PTR_ERR(sb); | 1592 | ret = PTR_ERR(sb); |
1593 | cgroup_drop_root(opts.new_root); | 1593 | cgroup_drop_root(opts.new_root); |
@@ -2570,7 +2570,7 @@ static const struct inode_operations cgroup_dir_inode_operations = { | |||
2570 | .rename = cgroup_rename, | 2570 | .rename = cgroup_rename, |
2571 | }; | 2571 | }; |
2572 | 2572 | ||
2573 | static struct dentry *cgroup_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 2573 | static struct dentry *cgroup_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) |
2574 | { | 2574 | { |
2575 | if (dentry->d_name.len > NAME_MAX) | 2575 | if (dentry->d_name.len > NAME_MAX) |
2576 | return ERR_PTR(-ENAMETOOLONG); | 2576 | return ERR_PTR(-ENAMETOOLONG); |
diff --git a/kernel/exit.c b/kernel/exit.c index 2f59cc334516..d17f6c4ddfa9 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -953,14 +953,11 @@ void do_exit(long code) | |||
953 | exit_signals(tsk); /* sets PF_EXITING */ | 953 | exit_signals(tsk); /* sets PF_EXITING */ |
954 | /* | 954 | /* |
955 | * tsk->flags are checked in the futex code to protect against | 955 | * tsk->flags are checked in the futex code to protect against |
956 | * an exiting task cleaning up the robust pi futexes, and in | 956 | * an exiting task cleaning up the robust pi futexes. |
957 | * task_work_add() to avoid the race with exit_task_work(). | ||
958 | */ | 957 | */ |
959 | smp_mb(); | 958 | smp_mb(); |
960 | raw_spin_unlock_wait(&tsk->pi_lock); | 959 | raw_spin_unlock_wait(&tsk->pi_lock); |
961 | 960 | ||
962 | exit_task_work(tsk); | ||
963 | |||
964 | if (unlikely(in_atomic())) | 961 | if (unlikely(in_atomic())) |
965 | printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n", | 962 | printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n", |
966 | current->comm, task_pid_nr(current), | 963 | current->comm, task_pid_nr(current), |
@@ -995,6 +992,7 @@ void do_exit(long code) | |||
995 | exit_shm(tsk); | 992 | exit_shm(tsk); |
996 | exit_files(tsk); | 993 | exit_files(tsk); |
997 | exit_fs(tsk); | 994 | exit_fs(tsk); |
995 | exit_task_work(tsk); | ||
998 | check_stack_usage(); | 996 | check_stack_usage(); |
999 | exit_thread(); | 997 | exit_thread(); |
1000 | 998 | ||
diff --git a/kernel/fork.c b/kernel/fork.c index f00e319d8376..ff1cad3b7bdc 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1420,7 +1420,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1420 | */ | 1420 | */ |
1421 | p->group_leader = p; | 1421 | p->group_leader = p; |
1422 | INIT_LIST_HEAD(&p->thread_group); | 1422 | INIT_LIST_HEAD(&p->thread_group); |
1423 | INIT_HLIST_HEAD(&p->task_works); | 1423 | p->task_works = NULL; |
1424 | 1424 | ||
1425 | /* Now that the task is set up, run cgroup callbacks if | 1425 | /* Now that the task is set up, run cgroup callbacks if |
1426 | * necessary. We need to run them before the task is visible | 1426 | * necessary. We need to run them before the task is visible |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 8c548232ba39..814c9ef6bba1 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -781,7 +781,7 @@ static void wake_threads_waitq(struct irq_desc *desc) | |||
781 | wake_up(&desc->wait_for_threads); | 781 | wake_up(&desc->wait_for_threads); |
782 | } | 782 | } |
783 | 783 | ||
784 | static void irq_thread_dtor(struct task_work *unused) | 784 | static void irq_thread_dtor(struct callback_head *unused) |
785 | { | 785 | { |
786 | struct task_struct *tsk = current; | 786 | struct task_struct *tsk = current; |
787 | struct irq_desc *desc; | 787 | struct irq_desc *desc; |
@@ -813,7 +813,7 @@ static void irq_thread_dtor(struct task_work *unused) | |||
813 | */ | 813 | */ |
814 | static int irq_thread(void *data) | 814 | static int irq_thread(void *data) |
815 | { | 815 | { |
816 | struct task_work on_exit_work; | 816 | struct callback_head on_exit_work; |
817 | static const struct sched_param param = { | 817 | static const struct sched_param param = { |
818 | .sched_priority = MAX_USER_RT_PRIO/2, | 818 | .sched_priority = MAX_USER_RT_PRIO/2, |
819 | }; | 819 | }; |
@@ -830,7 +830,7 @@ static int irq_thread(void *data) | |||
830 | 830 | ||
831 | sched_setscheduler(current, SCHED_FIFO, ¶m); | 831 | sched_setscheduler(current, SCHED_FIFO, ¶m); |
832 | 832 | ||
833 | init_task_work(&on_exit_work, irq_thread_dtor, NULL); | 833 | init_task_work(&on_exit_work, irq_thread_dtor); |
834 | task_work_add(current, &on_exit_work, false); | 834 | task_work_add(current, &on_exit_work, false); |
835 | 835 | ||
836 | while (!irq_wait_for_interrupt(action)) { | 836 | while (!irq_wait_for_interrupt(action)) { |
diff --git a/kernel/signal.c b/kernel/signal.c index 677102789cf2..be4f856d52f8 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -1971,6 +1971,13 @@ static void ptrace_do_notify(int signr, int exit_code, int why) | |||
1971 | void ptrace_notify(int exit_code) | 1971 | void ptrace_notify(int exit_code) |
1972 | { | 1972 | { |
1973 | BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP); | 1973 | BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP); |
1974 | if (unlikely(current->task_works)) { | ||
1975 | if (test_and_clear_ti_thread_flag(current_thread_info(), | ||
1976 | TIF_NOTIFY_RESUME)) { | ||
1977 | smp_mb__after_clear_bit(); | ||
1978 | task_work_run(); | ||
1979 | } | ||
1980 | } | ||
1974 | 1981 | ||
1975 | spin_lock_irq(¤t->sighand->siglock); | 1982 | spin_lock_irq(¤t->sighand->siglock); |
1976 | ptrace_do_notify(SIGTRAP, exit_code, CLD_TRAPPED); | 1983 | ptrace_do_notify(SIGTRAP, exit_code, CLD_TRAPPED); |
@@ -2191,6 +2198,14 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, | |||
2191 | struct signal_struct *signal = current->signal; | 2198 | struct signal_struct *signal = current->signal; |
2192 | int signr; | 2199 | int signr; |
2193 | 2200 | ||
2201 | if (unlikely(current->task_works)) { | ||
2202 | if (test_and_clear_ti_thread_flag(current_thread_info(), | ||
2203 | TIF_NOTIFY_RESUME)) { | ||
2204 | smp_mb__after_clear_bit(); | ||
2205 | task_work_run(); | ||
2206 | } | ||
2207 | } | ||
2208 | |||
2194 | if (unlikely(uprobe_deny_signal())) | 2209 | if (unlikely(uprobe_deny_signal())) |
2195 | return 0; | 2210 | return 0; |
2196 | 2211 | ||
diff --git a/kernel/task_work.c b/kernel/task_work.c index 82d1c794066d..91d4e1742a0c 100644 --- a/kernel/task_work.c +++ b/kernel/task_work.c | |||
@@ -3,82 +3,78 @@ | |||
3 | #include <linux/tracehook.h> | 3 | #include <linux/tracehook.h> |
4 | 4 | ||
5 | int | 5 | int |
6 | task_work_add(struct task_struct *task, struct task_work *twork, bool notify) | 6 | task_work_add(struct task_struct *task, struct callback_head *twork, bool notify) |
7 | { | 7 | { |
8 | struct callback_head *last, *first; | ||
8 | unsigned long flags; | 9 | unsigned long flags; |
9 | int err = -ESRCH; | ||
10 | 10 | ||
11 | #ifndef TIF_NOTIFY_RESUME | ||
12 | if (notify) | ||
13 | return -ENOTSUPP; | ||
14 | #endif | ||
15 | /* | 11 | /* |
16 | * We must not insert the new work if the task has already passed | 12 | * Not inserting the new work if the task has already passed |
17 | * exit_task_work(). We rely on do_exit()->raw_spin_unlock_wait() | 13 | * exit_task_work() is the responisbility of callers. |
18 | * and check PF_EXITING under pi_lock. | ||
19 | */ | 14 | */ |
20 | raw_spin_lock_irqsave(&task->pi_lock, flags); | 15 | raw_spin_lock_irqsave(&task->pi_lock, flags); |
21 | if (likely(!(task->flags & PF_EXITING))) { | 16 | last = task->task_works; |
22 | hlist_add_head(&twork->hlist, &task->task_works); | 17 | first = last ? last->next : twork; |
23 | err = 0; | 18 | twork->next = first; |
24 | } | 19 | if (last) |
20 | last->next = twork; | ||
21 | task->task_works = twork; | ||
25 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); | 22 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); |
26 | 23 | ||
27 | /* test_and_set_bit() implies mb(), see tracehook_notify_resume(). */ | 24 | /* test_and_set_bit() implies mb(), see tracehook_notify_resume(). */ |
28 | if (likely(!err) && notify) | 25 | if (notify) |
29 | set_notify_resume(task); | 26 | set_notify_resume(task); |
30 | return err; | 27 | return 0; |
31 | } | 28 | } |
32 | 29 | ||
33 | struct task_work * | 30 | struct callback_head * |
34 | task_work_cancel(struct task_struct *task, task_work_func_t func) | 31 | task_work_cancel(struct task_struct *task, task_work_func_t func) |
35 | { | 32 | { |
36 | unsigned long flags; | 33 | unsigned long flags; |
37 | struct task_work *twork; | 34 | struct callback_head *last, *res = NULL; |
38 | struct hlist_node *pos; | ||
39 | 35 | ||
40 | raw_spin_lock_irqsave(&task->pi_lock, flags); | 36 | raw_spin_lock_irqsave(&task->pi_lock, flags); |
41 | hlist_for_each_entry(twork, pos, &task->task_works, hlist) { | 37 | last = task->task_works; |
42 | if (twork->func == func) { | 38 | if (last) { |
43 | hlist_del(&twork->hlist); | 39 | struct callback_head *q = last, *p = q->next; |
44 | goto found; | 40 | while (1) { |
41 | if (p->func == func) { | ||
42 | q->next = p->next; | ||
43 | if (p == last) | ||
44 | task->task_works = q == p ? NULL : q; | ||
45 | res = p; | ||
46 | break; | ||
47 | } | ||
48 | if (p == last) | ||
49 | break; | ||
50 | q = p; | ||
51 | p = q->next; | ||
45 | } | 52 | } |
46 | } | 53 | } |
47 | twork = NULL; | ||
48 | found: | ||
49 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); | 54 | raw_spin_unlock_irqrestore(&task->pi_lock, flags); |
50 | 55 | return res; | |
51 | return twork; | ||
52 | } | 56 | } |
53 | 57 | ||
54 | void task_work_run(void) | 58 | void task_work_run(void) |
55 | { | 59 | { |
56 | struct task_struct *task = current; | 60 | struct task_struct *task = current; |
57 | struct hlist_head task_works; | 61 | struct callback_head *p, *q; |
58 | struct hlist_node *pos; | ||
59 | 62 | ||
60 | raw_spin_lock_irq(&task->pi_lock); | 63 | while (1) { |
61 | hlist_move_list(&task->task_works, &task_works); | 64 | raw_spin_lock_irq(&task->pi_lock); |
62 | raw_spin_unlock_irq(&task->pi_lock); | 65 | p = task->task_works; |
66 | task->task_works = NULL; | ||
67 | raw_spin_unlock_irq(&task->pi_lock); | ||
63 | 68 | ||
64 | if (unlikely(hlist_empty(&task_works))) | 69 | if (unlikely(!p)) |
65 | return; | 70 | return; |
66 | /* | ||
67 | * We use hlist to save the space in task_struct, but we want fifo. | ||
68 | * Find the last entry, the list should be short, then process them | ||
69 | * in reverse order. | ||
70 | */ | ||
71 | for (pos = task_works.first; pos->next; pos = pos->next) | ||
72 | ; | ||
73 | 71 | ||
74 | for (;;) { | 72 | q = p->next; /* head */ |
75 | struct hlist_node **pprev = pos->pprev; | 73 | p->next = NULL; /* cut it */ |
76 | struct task_work *twork = container_of(pos, struct task_work, | 74 | while (q) { |
77 | hlist); | 75 | p = q->next; |
78 | twork->func(twork); | 76 | q->func(q); |
79 | 77 | q = p; | |
80 | if (pprev == &task_works.first) | 78 | } |
81 | break; | ||
82 | pos = container_of(pprev, struct hlist_node, next); | ||
83 | } | 79 | } |
84 | } | 80 | } |
diff --git a/mm/shmem.c b/mm/shmem.c index bd106361be4b..c15b998e5a86 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -1877,7 +1877,7 @@ static int shmem_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
1877 | } | 1877 | } |
1878 | 1878 | ||
1879 | static int shmem_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 1879 | static int shmem_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
1880 | struct nameidata *nd) | 1880 | bool excl) |
1881 | { | 1881 | { |
1882 | return shmem_mknod(dir, dentry, mode | S_IFREG, 0); | 1882 | return shmem_mknod(dir, dentry, mode | S_IFREG, 0); |
1883 | } | 1883 | } |
diff --git a/net/core/scm.c b/net/core/scm.c index 611c5efd4cb0..8f6ccfd68ef4 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
@@ -109,25 +109,9 @@ void __scm_destroy(struct scm_cookie *scm) | |||
109 | 109 | ||
110 | if (fpl) { | 110 | if (fpl) { |
111 | scm->fp = NULL; | 111 | scm->fp = NULL; |
112 | if (current->scm_work_list) { | 112 | for (i=fpl->count-1; i>=0; i--) |
113 | list_add_tail(&fpl->list, current->scm_work_list); | 113 | fput(fpl->fp[i]); |
114 | } else { | 114 | kfree(fpl); |
115 | LIST_HEAD(work_list); | ||
116 | |||
117 | current->scm_work_list = &work_list; | ||
118 | |||
119 | list_add(&fpl->list, &work_list); | ||
120 | while (!list_empty(&work_list)) { | ||
121 | fpl = list_first_entry(&work_list, struct scm_fp_list, list); | ||
122 | |||
123 | list_del(&fpl->list); | ||
124 | for (i=fpl->count-1; i>=0; i--) | ||
125 | fput(fpl->fp[i]); | ||
126 | kfree(fpl); | ||
127 | } | ||
128 | |||
129 | current->scm_work_list = NULL; | ||
130 | } | ||
131 | } | 115 | } |
132 | } | 116 | } |
133 | EXPORT_SYMBOL(__scm_destroy); | 117 | EXPORT_SYMBOL(__scm_destroy); |
diff --git a/security/keys/internal.h b/security/keys/internal.h index 3dcbf86b0d31..c246ba5d43ab 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -149,7 +149,7 @@ extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags, | |||
149 | #define KEY_LOOKUP_FOR_UNLINK 0x04 | 149 | #define KEY_LOOKUP_FOR_UNLINK 0x04 |
150 | 150 | ||
151 | extern long join_session_keyring(const char *name); | 151 | extern long join_session_keyring(const char *name); |
152 | extern void key_change_session_keyring(struct task_work *twork); | 152 | extern void key_change_session_keyring(struct callback_head *twork); |
153 | 153 | ||
154 | extern struct work_struct key_gc_work; | 154 | extern struct work_struct key_gc_work; |
155 | extern unsigned key_gc_delay; | 155 | extern unsigned key_gc_delay; |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 0f5b3f027299..f1b59ae39d7e 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -1456,7 +1456,7 @@ long keyctl_session_to_parent(void) | |||
1456 | { | 1456 | { |
1457 | struct task_struct *me, *parent; | 1457 | struct task_struct *me, *parent; |
1458 | const struct cred *mycred, *pcred; | 1458 | const struct cred *mycred, *pcred; |
1459 | struct task_work *newwork, *oldwork; | 1459 | struct callback_head *newwork, *oldwork; |
1460 | key_ref_t keyring_r; | 1460 | key_ref_t keyring_r; |
1461 | struct cred *cred; | 1461 | struct cred *cred; |
1462 | int ret; | 1462 | int ret; |
@@ -1466,19 +1466,17 @@ long keyctl_session_to_parent(void) | |||
1466 | return PTR_ERR(keyring_r); | 1466 | return PTR_ERR(keyring_r); |
1467 | 1467 | ||
1468 | ret = -ENOMEM; | 1468 | ret = -ENOMEM; |
1469 | newwork = kmalloc(sizeof(struct task_work), GFP_KERNEL); | ||
1470 | if (!newwork) | ||
1471 | goto error_keyring; | ||
1472 | 1469 | ||
1473 | /* our parent is going to need a new cred struct, a new tgcred struct | 1470 | /* our parent is going to need a new cred struct, a new tgcred struct |
1474 | * and new security data, so we allocate them here to prevent ENOMEM in | 1471 | * and new security data, so we allocate them here to prevent ENOMEM in |
1475 | * our parent */ | 1472 | * our parent */ |
1476 | cred = cred_alloc_blank(); | 1473 | cred = cred_alloc_blank(); |
1477 | if (!cred) | 1474 | if (!cred) |
1478 | goto error_newwork; | 1475 | goto error_keyring; |
1476 | newwork = &cred->rcu; | ||
1479 | 1477 | ||
1480 | cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r); | 1478 | cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r); |
1481 | init_task_work(newwork, key_change_session_keyring, cred); | 1479 | init_task_work(newwork, key_change_session_keyring); |
1482 | 1480 | ||
1483 | me = current; | 1481 | me = current; |
1484 | rcu_read_lock(); | 1482 | rcu_read_lock(); |
@@ -1488,6 +1486,7 @@ long keyctl_session_to_parent(void) | |||
1488 | oldwork = NULL; | 1486 | oldwork = NULL; |
1489 | parent = me->real_parent; | 1487 | parent = me->real_parent; |
1490 | 1488 | ||
1489 | task_lock(parent); | ||
1491 | /* the parent mustn't be init and mustn't be a kernel thread */ | 1490 | /* the parent mustn't be init and mustn't be a kernel thread */ |
1492 | if (parent->pid <= 1 || !parent->mm) | 1491 | if (parent->pid <= 1 || !parent->mm) |
1493 | goto unlock; | 1492 | goto unlock; |
@@ -1531,20 +1530,15 @@ long keyctl_session_to_parent(void) | |||
1531 | if (!ret) | 1530 | if (!ret) |
1532 | newwork = NULL; | 1531 | newwork = NULL; |
1533 | unlock: | 1532 | unlock: |
1533 | task_unlock(parent); | ||
1534 | write_unlock_irq(&tasklist_lock); | 1534 | write_unlock_irq(&tasklist_lock); |
1535 | rcu_read_unlock(); | 1535 | rcu_read_unlock(); |
1536 | if (oldwork) { | 1536 | if (oldwork) |
1537 | put_cred(oldwork->data); | 1537 | put_cred(container_of(oldwork, struct cred, rcu)); |
1538 | kfree(oldwork); | 1538 | if (newwork) |
1539 | } | 1539 | put_cred(cred); |
1540 | if (newwork) { | ||
1541 | put_cred(newwork->data); | ||
1542 | kfree(newwork); | ||
1543 | } | ||
1544 | return ret; | 1540 | return ret; |
1545 | 1541 | ||
1546 | error_newwork: | ||
1547 | kfree(newwork); | ||
1548 | error_keyring: | 1542 | error_keyring: |
1549 | key_ref_put(keyring_r); | 1543 | key_ref_put(keyring_r); |
1550 | return ret; | 1544 | return ret; |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 4ad54eea1ea4..54339cfd6734 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -834,12 +834,11 @@ error: | |||
834 | * Replace a process's session keyring on behalf of one of its children when | 834 | * Replace a process's session keyring on behalf of one of its children when |
835 | * the target process is about to resume userspace execution. | 835 | * the target process is about to resume userspace execution. |
836 | */ | 836 | */ |
837 | void key_change_session_keyring(struct task_work *twork) | 837 | void key_change_session_keyring(struct callback_head *twork) |
838 | { | 838 | { |
839 | const struct cred *old = current_cred(); | 839 | const struct cred *old = current_cred(); |
840 | struct cred *new = twork->data; | 840 | struct cred *new = container_of(twork, struct cred, rcu); |
841 | 841 | ||
842 | kfree(twork); | ||
843 | if (unlikely(current->flags & PF_EXITING)) { | 842 | if (unlikely(current->flags & PF_EXITING)) { |
844 | put_cred(new); | 843 | put_cred(new); |
845 | return; | 844 | return; |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ffd8900a38e8..9292a8971e66 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -2157,8 +2157,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2157 | get_file(devnull); | 2157 | get_file(devnull); |
2158 | } else { | 2158 | } else { |
2159 | devnull = dentry_open( | 2159 | devnull = dentry_open( |
2160 | dget(selinux_null), | 2160 | &selinux_null, |
2161 | mntget(selinuxfs_mount), | ||
2162 | O_RDWR, cred); | 2161 | O_RDWR, cred); |
2163 | if (IS_ERR(devnull)) { | 2162 | if (IS_ERR(devnull)) { |
2164 | devnull = NULL; | 2163 | devnull = NULL; |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index dde2005407aa..6d3885165d14 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -221,7 +221,7 @@ extern void selinux_status_update_policyload(int seqno); | |||
221 | extern void selinux_complete_init(void); | 221 | extern void selinux_complete_init(void); |
222 | extern int selinux_disable(void); | 222 | extern int selinux_disable(void); |
223 | extern void exit_sel_fs(void); | 223 | extern void exit_sel_fs(void); |
224 | extern struct dentry *selinux_null; | 224 | extern struct path selinux_null; |
225 | extern struct vfsmount *selinuxfs_mount; | 225 | extern struct vfsmount *selinuxfs_mount; |
226 | extern void selnl_notify_setenforce(int val); | 226 | extern void selnl_notify_setenforce(int val); |
227 | extern void selnl_notify_policyload(u32 seqno); | 227 | extern void selnl_notify_policyload(u32 seqno); |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 3ad290251288..298e695d6822 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
@@ -1297,7 +1297,7 @@ out: | |||
1297 | 1297 | ||
1298 | #define NULL_FILE_NAME "null" | 1298 | #define NULL_FILE_NAME "null" |
1299 | 1299 | ||
1300 | struct dentry *selinux_null; | 1300 | struct path selinux_null; |
1301 | 1301 | ||
1302 | static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf, | 1302 | static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf, |
1303 | size_t count, loff_t *ppos) | 1303 | size_t count, loff_t *ppos) |
@@ -1838,7 +1838,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1838 | 1838 | ||
1839 | init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3)); | 1839 | init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3)); |
1840 | d_add(dentry, inode); | 1840 | d_add(dentry, inode); |
1841 | selinux_null = dentry; | 1841 | selinux_null.dentry = dentry; |
1842 | 1842 | ||
1843 | dentry = sel_make_dir(sb->s_root, "avc", &sel_last_ino); | 1843 | dentry = sel_make_dir(sb->s_root, "avc", &sel_last_ino); |
1844 | if (IS_ERR(dentry)) { | 1844 | if (IS_ERR(dentry)) { |
@@ -1912,7 +1912,7 @@ static int __init init_sel_fs(void) | |||
1912 | return err; | 1912 | return err; |
1913 | } | 1913 | } |
1914 | 1914 | ||
1915 | selinuxfs_mount = kern_mount(&sel_fs_type); | 1915 | selinux_null.mnt = selinuxfs_mount = kern_mount(&sel_fs_type); |
1916 | if (IS_ERR(selinuxfs_mount)) { | 1916 | if (IS_ERR(selinuxfs_mount)) { |
1917 | printk(KERN_ERR "selinuxfs: could not mount!\n"); | 1917 | printk(KERN_ERR "selinuxfs: could not mount!\n"); |
1918 | err = PTR_ERR(selinuxfs_mount); | 1918 | err = PTR_ERR(selinuxfs_mount); |