diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-22 20:42:14 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-22 20:42:14 -0500 |
commit | be5e6616dd74e17fdd8e16ca015cfef94d49b467 (patch) | |
tree | a18826e557f0d6636f1e05a4ec30d584ed981a2b /fs | |
parent | 90c453ca2214394eec602d98e6cb92d151908493 (diff) | |
parent | 0a280962dc6e117e0e4baa668453f753579265d9 (diff) |
Merge branch 'for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull more vfs updates from Al Viro:
"Assorted stuff from this cycle. The big ones here are multilayer
overlayfs from Miklos and beginning of sorting ->d_inode accesses out
from David"
* 'for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (51 commits)
autofs4 copy_dev_ioctl(): keep the value of ->size we'd used for allocation
procfs: fix race between symlink removals and traversals
debugfs: leave freeing a symlink body until inode eviction
Documentation/filesystems/Locking: ->get_sb() is long gone
trylock_super(): replacement for grab_super_passive()
fanotify: Fix up scripted S_ISDIR/S_ISREG/S_ISLNK conversions
Cachefiles: Fix up scripted S_ISDIR/S_ISREG/S_ISLNK conversions
VFS: (Scripted) Convert S_ISLNK/DIR/REG(dentry->d_inode) to d_is_*(dentry)
SELinux: Use d_is_positive() rather than testing dentry->d_inode
Smack: Use d_is_positive() rather than testing dentry->d_inode
TOMOYO: Use d_is_dir() rather than d_inode and S_ISDIR()
Apparmor: Use d_is_positive/negative() rather than testing dentry->d_inode
Apparmor: mediated_filesystem() should use dentry->d_sb not inode->i_sb
VFS: Split DCACHE_FILE_TYPE into regular and special types
VFS: Add a fallthrough flag for marking virtual dentries
VFS: Add a whiteout dentry type
VFS: Introduce inode-getting helpers for layered/unioned fs environments
Infiniband: Fix potential NULL d_inode dereference
posix_acl: fix reference leaks in posix_acl_create
autofs4: Wrong format for printing dentry
...
Diffstat (limited to 'fs')
52 files changed, 715 insertions, 676 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 9ee5343d4884..3662f1d1d9cf 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -1127,7 +1127,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
1127 | } | 1127 | } |
1128 | 1128 | ||
1129 | /* Write all dirty data */ | 1129 | /* Write all dirty data */ |
1130 | if (S_ISREG(dentry->d_inode->i_mode)) | 1130 | if (d_is_reg(dentry)) |
1131 | filemap_write_and_wait(dentry->d_inode->i_mapping); | 1131 | filemap_write_and_wait(dentry->d_inode->i_mapping); |
1132 | 1132 | ||
1133 | retval = p9_client_wstat(fid, &wstat); | 1133 | retval = p9_client_wstat(fid, &wstat); |
@@ -1285,7 +1285,7 @@ SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp) | |||
1285 | 1285 | ||
1286 | ret = -EINVAL; | 1286 | ret = -EINVAL; |
1287 | if (unlikely(ctx || nr_events == 0)) { | 1287 | if (unlikely(ctx || nr_events == 0)) { |
1288 | pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n", | 1288 | pr_debug("EINVAL: ctx %lu nr_events %u\n", |
1289 | ctx, nr_events); | 1289 | ctx, nr_events); |
1290 | goto out; | 1290 | goto out; |
1291 | } | 1291 | } |
@@ -1333,7 +1333,7 @@ SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx) | |||
1333 | 1333 | ||
1334 | return ret; | 1334 | return ret; |
1335 | } | 1335 | } |
1336 | pr_debug("EINVAL: io_destroy: invalid context id\n"); | 1336 | pr_debug("EINVAL: invalid context id\n"); |
1337 | return -EINVAL; | 1337 | return -EINVAL; |
1338 | } | 1338 | } |
1339 | 1339 | ||
@@ -1515,7 +1515,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, | |||
1515 | (iocb->aio_nbytes != (size_t)iocb->aio_nbytes) || | 1515 | (iocb->aio_nbytes != (size_t)iocb->aio_nbytes) || |
1516 | ((ssize_t)iocb->aio_nbytes < 0) | 1516 | ((ssize_t)iocb->aio_nbytes < 0) |
1517 | )) { | 1517 | )) { |
1518 | pr_debug("EINVAL: io_submit: overflow check\n"); | 1518 | pr_debug("EINVAL: overflow check\n"); |
1519 | return -EINVAL; | 1519 | return -EINVAL; |
1520 | } | 1520 | } |
1521 | 1521 | ||
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index aaf96cb25452..ac7d921ed984 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c | |||
@@ -95,7 +95,7 @@ static int check_dev_ioctl_version(int cmd, struct autofs_dev_ioctl *param) | |||
95 | */ | 95 | */ |
96 | static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *in) | 96 | static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *in) |
97 | { | 97 | { |
98 | struct autofs_dev_ioctl tmp; | 98 | struct autofs_dev_ioctl tmp, *res; |
99 | 99 | ||
100 | if (copy_from_user(&tmp, in, sizeof(tmp))) | 100 | if (copy_from_user(&tmp, in, sizeof(tmp))) |
101 | return ERR_PTR(-EFAULT); | 101 | return ERR_PTR(-EFAULT); |
@@ -106,7 +106,11 @@ static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *i | |||
106 | if (tmp.size > (PATH_MAX + sizeof(tmp))) | 106 | if (tmp.size > (PATH_MAX + sizeof(tmp))) |
107 | return ERR_PTR(-ENAMETOOLONG); | 107 | return ERR_PTR(-ENAMETOOLONG); |
108 | 108 | ||
109 | return memdup_user(in, tmp.size); | 109 | res = memdup_user(in, tmp.size); |
110 | if (!IS_ERR(res)) | ||
111 | res->size = tmp.size; | ||
112 | |||
113 | return res; | ||
110 | } | 114 | } |
111 | 115 | ||
112 | static inline void free_dev_ioctl(struct autofs_dev_ioctl *param) | 116 | static inline void free_dev_ioctl(struct autofs_dev_ioctl *param) |
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index bfdbaba9c2ba..11dd118f75e2 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -374,7 +374,7 @@ static struct dentry *should_expire(struct dentry *dentry, | |||
374 | return NULL; | 374 | return NULL; |
375 | } | 375 | } |
376 | 376 | ||
377 | if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) { | 377 | if (dentry->d_inode && d_is_symlink(dentry)) { |
378 | DPRINTK("checking symlink %p %pd", dentry, dentry); | 378 | DPRINTK("checking symlink %p %pd", dentry, dentry); |
379 | /* | 379 | /* |
380 | * A symlink can't be "busy" in the usual sense so | 380 | * A symlink can't be "busy" in the usual sense so |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index dbb5b7212ce1..7e44fdd03e2d 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -108,7 +108,7 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) | |||
108 | struct dentry *dentry = file->f_path.dentry; | 108 | struct dentry *dentry = file->f_path.dentry; |
109 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 109 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
110 | 110 | ||
111 | DPRINTK("file=%p dentry=%p %pD", file, dentry, dentry); | 111 | DPRINTK("file=%p dentry=%p %pd", file, dentry, dentry); |
112 | 112 | ||
113 | if (autofs4_oz_mode(sbi)) | 113 | if (autofs4_oz_mode(sbi)) |
114 | goto out; | 114 | goto out; |
@@ -371,7 +371,7 @@ static struct vfsmount *autofs4_d_automount(struct path *path) | |||
371 | * having d_mountpoint() true, so there's no need to call back | 371 | * having d_mountpoint() true, so there's no need to call back |
372 | * to the daemon. | 372 | * to the daemon. |
373 | */ | 373 | */ |
374 | if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) { | 374 | if (dentry->d_inode && d_is_symlink(dentry)) { |
375 | spin_unlock(&sbi->fs_lock); | 375 | spin_unlock(&sbi->fs_lock); |
376 | goto done; | 376 | goto done; |
377 | } | 377 | } |
@@ -485,7 +485,7 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk) | |||
485 | * an incorrect ELOOP error return. | 485 | * an incorrect ELOOP error return. |
486 | */ | 486 | */ |
487 | if ((!d_mountpoint(dentry) && !simple_empty(dentry)) || | 487 | if ((!d_mountpoint(dentry) && !simple_empty(dentry)) || |
488 | (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode))) | 488 | (dentry->d_inode && d_is_symlink(dentry))) |
489 | status = -EISDIR; | 489 | status = -EISDIR; |
490 | } | 490 | } |
491 | spin_unlock(&sbi->fs_lock); | 491 | spin_unlock(&sbi->fs_lock); |
diff --git a/fs/bad_inode.c b/fs/bad_inode.c index afd2b4408adf..861b1e1c4777 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c | |||
@@ -15,161 +15,14 @@ | |||
15 | #include <linux/namei.h> | 15 | #include <linux/namei.h> |
16 | #include <linux/poll.h> | 16 | #include <linux/poll.h> |
17 | 17 | ||
18 | |||
19 | static loff_t bad_file_llseek(struct file *file, loff_t offset, int whence) | ||
20 | { | ||
21 | return -EIO; | ||
22 | } | ||
23 | |||
24 | static ssize_t bad_file_read(struct file *filp, char __user *buf, | ||
25 | size_t size, loff_t *ppos) | ||
26 | { | ||
27 | return -EIO; | ||
28 | } | ||
29 | |||
30 | static ssize_t bad_file_write(struct file *filp, const char __user *buf, | ||
31 | size_t siz, loff_t *ppos) | ||
32 | { | ||
33 | return -EIO; | ||
34 | } | ||
35 | |||
36 | static ssize_t bad_file_aio_read(struct kiocb *iocb, const struct iovec *iov, | ||
37 | unsigned long nr_segs, loff_t pos) | ||
38 | { | ||
39 | return -EIO; | ||
40 | } | ||
41 | |||
42 | static ssize_t bad_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | ||
43 | unsigned long nr_segs, loff_t pos) | ||
44 | { | ||
45 | return -EIO; | ||
46 | } | ||
47 | |||
48 | static int bad_file_readdir(struct file *file, struct dir_context *ctx) | ||
49 | { | ||
50 | return -EIO; | ||
51 | } | ||
52 | |||
53 | static unsigned int bad_file_poll(struct file *filp, poll_table *wait) | ||
54 | { | ||
55 | return POLLERR; | ||
56 | } | ||
57 | |||
58 | static long bad_file_unlocked_ioctl(struct file *file, unsigned cmd, | ||
59 | unsigned long arg) | ||
60 | { | ||
61 | return -EIO; | ||
62 | } | ||
63 | |||
64 | static long bad_file_compat_ioctl(struct file *file, unsigned int cmd, | ||
65 | unsigned long arg) | ||
66 | { | ||
67 | return -EIO; | ||
68 | } | ||
69 | |||
70 | static int bad_file_mmap(struct file *file, struct vm_area_struct *vma) | ||
71 | { | ||
72 | return -EIO; | ||
73 | } | ||
74 | |||
75 | static int bad_file_open(struct inode *inode, struct file *filp) | 18 | static int bad_file_open(struct inode *inode, struct file *filp) |
76 | { | 19 | { |
77 | return -EIO; | 20 | return -EIO; |
78 | } | 21 | } |
79 | 22 | ||
80 | static int bad_file_flush(struct file *file, fl_owner_t id) | ||
81 | { | ||
82 | return -EIO; | ||
83 | } | ||
84 | |||
85 | static int bad_file_release(struct inode *inode, struct file *filp) | ||
86 | { | ||
87 | return -EIO; | ||
88 | } | ||
89 | |||
90 | static int bad_file_fsync(struct file *file, loff_t start, loff_t end, | ||
91 | int datasync) | ||
92 | { | ||
93 | return -EIO; | ||
94 | } | ||
95 | |||
96 | static int bad_file_aio_fsync(struct kiocb *iocb, int datasync) | ||
97 | { | ||
98 | return -EIO; | ||
99 | } | ||
100 | |||
101 | static int bad_file_fasync(int fd, struct file *filp, int on) | ||
102 | { | ||
103 | return -EIO; | ||
104 | } | ||
105 | |||
106 | static int bad_file_lock(struct file *file, int cmd, struct file_lock *fl) | ||
107 | { | ||
108 | return -EIO; | ||
109 | } | ||
110 | |||
111 | static ssize_t bad_file_sendpage(struct file *file, struct page *page, | ||
112 | int off, size_t len, loff_t *pos, int more) | ||
113 | { | ||
114 | return -EIO; | ||
115 | } | ||
116 | |||
117 | static unsigned long bad_file_get_unmapped_area(struct file *file, | ||
118 | unsigned long addr, unsigned long len, | ||
119 | unsigned long pgoff, unsigned long flags) | ||
120 | { | ||
121 | return -EIO; | ||
122 | } | ||
123 | |||
124 | static int bad_file_check_flags(int flags) | ||
125 | { | ||
126 | return -EIO; | ||
127 | } | ||
128 | |||
129 | static int bad_file_flock(struct file *filp, int cmd, struct file_lock *fl) | ||
130 | { | ||
131 | return -EIO; | ||
132 | } | ||
133 | |||
134 | static ssize_t bad_file_splice_write(struct pipe_inode_info *pipe, | ||
135 | struct file *out, loff_t *ppos, size_t len, | ||
136 | unsigned int flags) | ||
137 | { | ||
138 | return -EIO; | ||
139 | } | ||
140 | |||
141 | static ssize_t bad_file_splice_read(struct file *in, loff_t *ppos, | ||
142 | struct pipe_inode_info *pipe, size_t len, | ||
143 | unsigned int flags) | ||
144 | { | ||
145 | return -EIO; | ||
146 | } | ||
147 | |||
148 | static const struct file_operations bad_file_ops = | 23 | static const struct file_operations bad_file_ops = |
149 | { | 24 | { |
150 | .llseek = bad_file_llseek, | ||
151 | .read = bad_file_read, | ||
152 | .write = bad_file_write, | ||
153 | .aio_read = bad_file_aio_read, | ||
154 | .aio_write = bad_file_aio_write, | ||
155 | .iterate = bad_file_readdir, | ||
156 | .poll = bad_file_poll, | ||
157 | .unlocked_ioctl = bad_file_unlocked_ioctl, | ||
158 | .compat_ioctl = bad_file_compat_ioctl, | ||
159 | .mmap = bad_file_mmap, | ||
160 | .open = bad_file_open, | 25 | .open = bad_file_open, |
161 | .flush = bad_file_flush, | ||
162 | .release = bad_file_release, | ||
163 | .fsync = bad_file_fsync, | ||
164 | .aio_fsync = bad_file_aio_fsync, | ||
165 | .fasync = bad_file_fasync, | ||
166 | .lock = bad_file_lock, | ||
167 | .sendpage = bad_file_sendpage, | ||
168 | .get_unmapped_area = bad_file_get_unmapped_area, | ||
169 | .check_flags = bad_file_check_flags, | ||
170 | .flock = bad_file_flock, | ||
171 | .splice_write = bad_file_splice_write, | ||
172 | .splice_read = bad_file_splice_read, | ||
173 | }; | 26 | }; |
174 | 27 | ||
175 | static int bad_inode_create (struct inode *dir, struct dentry *dentry, | 28 | static int bad_inode_create (struct inode *dir, struct dentry *dentry, |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index d49fe8a0f6b5..74609b931ba5 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -776,11 +776,11 @@ static int btrfs_may_delete(struct inode *dir, struct dentry *victim, int isdir) | |||
776 | IS_IMMUTABLE(victim->d_inode) || IS_SWAPFILE(victim->d_inode)) | 776 | IS_IMMUTABLE(victim->d_inode) || IS_SWAPFILE(victim->d_inode)) |
777 | return -EPERM; | 777 | return -EPERM; |
778 | if (isdir) { | 778 | if (isdir) { |
779 | if (!S_ISDIR(victim->d_inode->i_mode)) | 779 | if (!d_is_dir(victim)) |
780 | return -ENOTDIR; | 780 | return -ENOTDIR; |
781 | if (IS_ROOT(victim)) | 781 | if (IS_ROOT(victim)) |
782 | return -EBUSY; | 782 | return -EBUSY; |
783 | } else if (S_ISDIR(victim->d_inode->i_mode)) | 783 | } else if (d_is_dir(victim)) |
784 | return -EISDIR; | 784 | return -EISDIR; |
785 | if (IS_DEADDIR(dir)) | 785 | if (IS_DEADDIR(dir)) |
786 | return -ENOENT; | 786 | return -ENOENT; |
diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c index ce1b115dcc28..f601def05bdf 100644 --- a/fs/cachefiles/daemon.c +++ b/fs/cachefiles/daemon.c | |||
@@ -574,7 +574,7 @@ static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args) | |||
574 | /* extract the directory dentry from the cwd */ | 574 | /* extract the directory dentry from the cwd */ |
575 | get_fs_pwd(current->fs, &path); | 575 | get_fs_pwd(current->fs, &path); |
576 | 576 | ||
577 | if (!S_ISDIR(path.dentry->d_inode->i_mode)) | 577 | if (!d_can_lookup(path.dentry)) |
578 | goto notdir; | 578 | goto notdir; |
579 | 579 | ||
580 | cachefiles_begin_secure(cache, &saved_cred); | 580 | cachefiles_begin_secure(cache, &saved_cred); |
@@ -646,7 +646,7 @@ static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args) | |||
646 | /* extract the directory dentry from the cwd */ | 646 | /* extract the directory dentry from the cwd */ |
647 | get_fs_pwd(current->fs, &path); | 647 | get_fs_pwd(current->fs, &path); |
648 | 648 | ||
649 | if (!S_ISDIR(path.dentry->d_inode->i_mode)) | 649 | if (!d_can_lookup(path.dentry)) |
650 | goto notdir; | 650 | goto notdir; |
651 | 651 | ||
652 | cachefiles_begin_secure(cache, &saved_cred); | 652 | cachefiles_begin_secure(cache, &saved_cred); |
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index 1c7293c3a93a..232426214fdd 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c | |||
@@ -437,7 +437,7 @@ static int cachefiles_attr_changed(struct fscache_object *_object) | |||
437 | if (!object->backer) | 437 | if (!object->backer) |
438 | return -ENOBUFS; | 438 | return -ENOBUFS; |
439 | 439 | ||
440 | ASSERT(S_ISREG(object->backer->d_inode->i_mode)); | 440 | ASSERT(d_is_reg(object->backer)); |
441 | 441 | ||
442 | fscache_set_store_limit(&object->fscache, ni_size); | 442 | fscache_set_store_limit(&object->fscache, ni_size); |
443 | 443 | ||
@@ -501,7 +501,7 @@ static void cachefiles_invalidate_object(struct fscache_operation *op) | |||
501 | op->object->debug_id, (unsigned long long)ni_size); | 501 | op->object->debug_id, (unsigned long long)ni_size); |
502 | 502 | ||
503 | if (object->backer) { | 503 | if (object->backer) { |
504 | ASSERT(S_ISREG(object->backer->d_inode->i_mode)); | 504 | ASSERT(d_is_reg(object->backer)); |
505 | 505 | ||
506 | fscache_set_store_limit(&object->fscache, ni_size); | 506 | fscache_set_store_limit(&object->fscache, ni_size); |
507 | 507 | ||
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 7f8e83f9d74e..1e51714eb33e 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c | |||
@@ -277,7 +277,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache, | |||
277 | _debug("remove %p from %p", rep, dir); | 277 | _debug("remove %p from %p", rep, dir); |
278 | 278 | ||
279 | /* non-directories can just be unlinked */ | 279 | /* non-directories can just be unlinked */ |
280 | if (!S_ISDIR(rep->d_inode->i_mode)) { | 280 | if (!d_is_dir(rep)) { |
281 | _debug("unlink stale object"); | 281 | _debug("unlink stale object"); |
282 | 282 | ||
283 | path.mnt = cache->mnt; | 283 | path.mnt = cache->mnt; |
@@ -323,7 +323,7 @@ try_again: | |||
323 | return 0; | 323 | return 0; |
324 | } | 324 | } |
325 | 325 | ||
326 | if (!S_ISDIR(cache->graveyard->d_inode->i_mode)) { | 326 | if (!d_can_lookup(cache->graveyard)) { |
327 | unlock_rename(cache->graveyard, dir); | 327 | unlock_rename(cache->graveyard, dir); |
328 | cachefiles_io_error(cache, "Graveyard no longer a directory"); | 328 | cachefiles_io_error(cache, "Graveyard no longer a directory"); |
329 | return -EIO; | 329 | return -EIO; |
@@ -475,7 +475,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, | |||
475 | ASSERT(parent->dentry); | 475 | ASSERT(parent->dentry); |
476 | ASSERT(parent->dentry->d_inode); | 476 | ASSERT(parent->dentry->d_inode); |
477 | 477 | ||
478 | if (!(S_ISDIR(parent->dentry->d_inode->i_mode))) { | 478 | if (!(d_is_dir(parent->dentry))) { |
479 | // TODO: convert file to dir | 479 | // TODO: convert file to dir |
480 | _leave("looking up in none directory"); | 480 | _leave("looking up in none directory"); |
481 | return -ENOBUFS; | 481 | return -ENOBUFS; |
@@ -539,7 +539,7 @@ lookup_again: | |||
539 | _debug("mkdir -> %p{%p{ino=%lu}}", | 539 | _debug("mkdir -> %p{%p{ino=%lu}}", |
540 | next, next->d_inode, next->d_inode->i_ino); | 540 | next, next->d_inode, next->d_inode->i_ino); |
541 | 541 | ||
542 | } else if (!S_ISDIR(next->d_inode->i_mode)) { | 542 | } else if (!d_can_lookup(next)) { |
543 | pr_err("inode %lu is not a directory\n", | 543 | pr_err("inode %lu is not a directory\n", |
544 | next->d_inode->i_ino); | 544 | next->d_inode->i_ino); |
545 | ret = -ENOBUFS; | 545 | ret = -ENOBUFS; |
@@ -568,8 +568,8 @@ lookup_again: | |||
568 | _debug("create -> %p{%p{ino=%lu}}", | 568 | _debug("create -> %p{%p{ino=%lu}}", |
569 | next, next->d_inode, next->d_inode->i_ino); | 569 | next, next->d_inode, next->d_inode->i_ino); |
570 | 570 | ||
571 | } else if (!S_ISDIR(next->d_inode->i_mode) && | 571 | } else if (!d_can_lookup(next) && |
572 | !S_ISREG(next->d_inode->i_mode) | 572 | !d_is_reg(next) |
573 | ) { | 573 | ) { |
574 | pr_err("inode %lu is not a file or directory\n", | 574 | pr_err("inode %lu is not a file or directory\n", |
575 | next->d_inode->i_ino); | 575 | next->d_inode->i_ino); |
@@ -642,7 +642,7 @@ lookup_again: | |||
642 | 642 | ||
643 | /* open a file interface onto a data file */ | 643 | /* open a file interface onto a data file */ |
644 | if (object->type != FSCACHE_COOKIE_TYPE_INDEX) { | 644 | if (object->type != FSCACHE_COOKIE_TYPE_INDEX) { |
645 | if (S_ISREG(object->dentry->d_inode->i_mode)) { | 645 | if (d_is_reg(object->dentry)) { |
646 | const struct address_space_operations *aops; | 646 | const struct address_space_operations *aops; |
647 | 647 | ||
648 | ret = -EPERM; | 648 | ret = -EPERM; |
@@ -763,7 +763,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, | |||
763 | /* we need to make sure the subdir is a directory */ | 763 | /* we need to make sure the subdir is a directory */ |
764 | ASSERT(subdir->d_inode); | 764 | ASSERT(subdir->d_inode); |
765 | 765 | ||
766 | if (!S_ISDIR(subdir->d_inode->i_mode)) { | 766 | if (!d_can_lookup(subdir)) { |
767 | pr_err("%s is not a directory\n", dirname); | 767 | pr_err("%s is not a directory\n", dirname); |
768 | ret = -EIO; | 768 | ret = -EIO; |
769 | goto check_error; | 769 | goto check_error; |
diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c index 616db0e77b44..c6cd8d7a4eef 100644 --- a/fs/cachefiles/rdwr.c +++ b/fs/cachefiles/rdwr.c | |||
@@ -900,7 +900,7 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page) | |||
900 | return -ENOBUFS; | 900 | return -ENOBUFS; |
901 | } | 901 | } |
902 | 902 | ||
903 | ASSERT(S_ISREG(object->backer->d_inode->i_mode)); | 903 | ASSERT(d_is_reg(object->backer)); |
904 | 904 | ||
905 | cache = container_of(object->fscache.cache, | 905 | cache = container_of(object->fscache.cache, |
906 | struct cachefiles_cache, cache); | 906 | struct cachefiles_cache, cache); |
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 0411dbb15815..83e9976f7189 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -904,7 +904,7 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry) | |||
904 | } else if (ceph_snap(dir) == CEPH_NOSNAP) { | 904 | } else if (ceph_snap(dir) == CEPH_NOSNAP) { |
905 | dout("unlink/rmdir dir %p dn %p inode %p\n", | 905 | dout("unlink/rmdir dir %p dn %p inode %p\n", |
906 | dir, dentry, inode); | 906 | dir, dentry, inode); |
907 | op = S_ISDIR(dentry->d_inode->i_mode) ? | 907 | op = d_is_dir(dentry) ? |
908 | CEPH_MDS_OP_RMDIR : CEPH_MDS_OP_UNLINK; | 908 | CEPH_MDS_OP_RMDIR : CEPH_MDS_OP_UNLINK; |
909 | } else | 909 | } else |
910 | goto out; | 910 | goto out; |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index a3d774b35149..d533075a823d 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -292,7 +292,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry, | |||
292 | } | 292 | } |
293 | if (err) | 293 | if (err) |
294 | goto out_req; | 294 | goto out_req; |
295 | if (dn || dentry->d_inode == NULL || S_ISLNK(dentry->d_inode->i_mode)) { | 295 | if (dn || dentry->d_inode == NULL || d_is_symlink(dentry)) { |
296 | /* make vfs retry on splice, ENOENT, or symlink */ | 296 | /* make vfs retry on splice, ENOENT, or symlink */ |
297 | dout("atomic_open finish_no_open on dn %p\n", dn); | 297 | dout("atomic_open finish_no_open on dn %p\n", dn); |
298 | err = finish_no_open(file, dn); | 298 | err = finish_no_open(file, dn); |
diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 281ee011bb6a..60cb88c1dd2b 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c | |||
@@ -304,7 +304,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
304 | (const char *) old_name, (const char *)new_name); | 304 | (const char *) old_name, (const char *)new_name); |
305 | if (!error) { | 305 | if (!error) { |
306 | if (new_dentry->d_inode) { | 306 | if (new_dentry->d_inode) { |
307 | if (S_ISDIR(new_dentry->d_inode->i_mode)) { | 307 | if (d_is_dir(new_dentry)) { |
308 | coda_dir_drop_nlink(old_dir); | 308 | coda_dir_drop_nlink(old_dir); |
309 | coda_dir_inc_nlink(new_dir); | 309 | coda_dir_inc_nlink(new_dir); |
310 | } | 310 | } |
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h index a315677e44d3..b65d1ef532d5 100644 --- a/fs/configfs/configfs_internal.h +++ b/fs/configfs/configfs_internal.h | |||
@@ -69,14 +69,13 @@ extern struct kmem_cache *configfs_dir_cachep; | |||
69 | extern int configfs_is_root(struct config_item *item); | 69 | extern int configfs_is_root(struct config_item *item); |
70 | 70 | ||
71 | extern struct inode * configfs_new_inode(umode_t mode, struct configfs_dirent *, struct super_block *); | 71 | extern struct inode * configfs_new_inode(umode_t mode, struct configfs_dirent *, struct super_block *); |
72 | extern int configfs_create(struct dentry *, umode_t mode, int (*init)(struct inode *)); | 72 | extern int configfs_create(struct dentry *, umode_t mode, void (*init)(struct inode *)); |
73 | 73 | ||
74 | extern int configfs_create_file(struct config_item *, const struct configfs_attribute *); | 74 | extern int configfs_create_file(struct config_item *, const struct configfs_attribute *); |
75 | extern int configfs_make_dirent(struct configfs_dirent *, | 75 | extern int configfs_make_dirent(struct configfs_dirent *, |
76 | struct dentry *, void *, umode_t, int); | 76 | struct dentry *, void *, umode_t, int); |
77 | extern int configfs_dirent_is_ready(struct configfs_dirent *); | 77 | extern int configfs_dirent_is_ready(struct configfs_dirent *); |
78 | 78 | ||
79 | extern int configfs_add_file(struct dentry *, const struct configfs_attribute *, int); | ||
80 | extern void configfs_hash_and_remove(struct dentry * dir, const char * name); | 79 | extern void configfs_hash_and_remove(struct dentry * dir, const char * name); |
81 | 80 | ||
82 | extern const unsigned char * configfs_get_name(struct configfs_dirent *sd); | 81 | extern const unsigned char * configfs_get_name(struct configfs_dirent *sd); |
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index c9c298bd3058..cf0db005d2f5 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -240,60 +240,26 @@ int configfs_make_dirent(struct configfs_dirent * parent_sd, | |||
240 | return 0; | 240 | return 0; |
241 | } | 241 | } |
242 | 242 | ||
243 | static int init_dir(struct inode * inode) | 243 | static void init_dir(struct inode * inode) |
244 | { | 244 | { |
245 | inode->i_op = &configfs_dir_inode_operations; | 245 | inode->i_op = &configfs_dir_inode_operations; |
246 | inode->i_fop = &configfs_dir_operations; | 246 | inode->i_fop = &configfs_dir_operations; |
247 | 247 | ||
248 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | 248 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ |
249 | inc_nlink(inode); | 249 | inc_nlink(inode); |
250 | return 0; | ||
251 | } | 250 | } |
252 | 251 | ||
253 | static int configfs_init_file(struct inode * inode) | 252 | static void configfs_init_file(struct inode * inode) |
254 | { | 253 | { |
255 | inode->i_size = PAGE_SIZE; | 254 | inode->i_size = PAGE_SIZE; |
256 | inode->i_fop = &configfs_file_operations; | 255 | inode->i_fop = &configfs_file_operations; |
257 | return 0; | ||
258 | } | 256 | } |
259 | 257 | ||
260 | static int init_symlink(struct inode * inode) | 258 | static void init_symlink(struct inode * inode) |
261 | { | 259 | { |
262 | inode->i_op = &configfs_symlink_inode_operations; | 260 | inode->i_op = &configfs_symlink_inode_operations; |
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static int create_dir(struct config_item *k, struct dentry *d) | ||
267 | { | ||
268 | int error; | ||
269 | umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; | ||
270 | struct dentry *p = d->d_parent; | ||
271 | |||
272 | BUG_ON(!k); | ||
273 | |||
274 | error = configfs_dirent_exists(p->d_fsdata, d->d_name.name); | ||
275 | if (!error) | ||
276 | error = configfs_make_dirent(p->d_fsdata, d, k, mode, | ||
277 | CONFIGFS_DIR | CONFIGFS_USET_CREATING); | ||
278 | if (!error) { | ||
279 | configfs_set_dir_dirent_depth(p->d_fsdata, d->d_fsdata); | ||
280 | error = configfs_create(d, mode, init_dir); | ||
281 | if (!error) { | ||
282 | inc_nlink(p->d_inode); | ||
283 | } else { | ||
284 | struct configfs_dirent *sd = d->d_fsdata; | ||
285 | if (sd) { | ||
286 | spin_lock(&configfs_dirent_lock); | ||
287 | list_del_init(&sd->s_sibling); | ||
288 | spin_unlock(&configfs_dirent_lock); | ||
289 | configfs_put(sd); | ||
290 | } | ||
291 | } | ||
292 | } | ||
293 | return error; | ||
294 | } | 261 | } |
295 | 262 | ||
296 | |||
297 | /** | 263 | /** |
298 | * configfs_create_dir - create a directory for an config_item. | 264 | * configfs_create_dir - create a directory for an config_item. |
299 | * @item: config_itemwe're creating directory for. | 265 | * @item: config_itemwe're creating directory for. |
@@ -303,11 +269,37 @@ static int create_dir(struct config_item *k, struct dentry *d) | |||
303 | * until it is validated by configfs_dir_set_ready() | 269 | * until it is validated by configfs_dir_set_ready() |
304 | */ | 270 | */ |
305 | 271 | ||
306 | static int configfs_create_dir(struct config_item * item, struct dentry *dentry) | 272 | static int configfs_create_dir(struct config_item *item, struct dentry *dentry) |
307 | { | 273 | { |
308 | int error = create_dir(item, dentry); | 274 | int error; |
309 | if (!error) | 275 | umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; |
276 | struct dentry *p = dentry->d_parent; | ||
277 | |||
278 | BUG_ON(!item); | ||
279 | |||
280 | error = configfs_dirent_exists(p->d_fsdata, dentry->d_name.name); | ||
281 | if (unlikely(error)) | ||
282 | return error; | ||
283 | |||
284 | error = configfs_make_dirent(p->d_fsdata, dentry, item, mode, | ||
285 | CONFIGFS_DIR | CONFIGFS_USET_CREATING); | ||
286 | if (unlikely(error)) | ||
287 | return error; | ||
288 | |||
289 | configfs_set_dir_dirent_depth(p->d_fsdata, dentry->d_fsdata); | ||
290 | error = configfs_create(dentry, mode, init_dir); | ||
291 | if (!error) { | ||
292 | inc_nlink(p->d_inode); | ||
310 | item->ci_dentry = dentry; | 293 | item->ci_dentry = dentry; |
294 | } else { | ||
295 | struct configfs_dirent *sd = dentry->d_fsdata; | ||
296 | if (sd) { | ||
297 | spin_lock(&configfs_dirent_lock); | ||
298 | list_del_init(&sd->s_sibling); | ||
299 | spin_unlock(&configfs_dirent_lock); | ||
300 | configfs_put(sd); | ||
301 | } | ||
302 | } | ||
311 | return error; | 303 | return error; |
312 | } | 304 | } |
313 | 305 | ||
diff --git a/fs/configfs/file.c b/fs/configfs/file.c index 1d1c41f1014d..56d2cdc9ae0a 100644 --- a/fs/configfs/file.c +++ b/fs/configfs/file.c | |||
@@ -313,21 +313,6 @@ const struct file_operations configfs_file_operations = { | |||
313 | .release = configfs_release, | 313 | .release = configfs_release, |
314 | }; | 314 | }; |
315 | 315 | ||
316 | |||
317 | int configfs_add_file(struct dentry * dir, const struct configfs_attribute * attr, int type) | ||
318 | { | ||
319 | struct configfs_dirent * parent_sd = dir->d_fsdata; | ||
320 | umode_t mode = (attr->ca_mode & S_IALLUGO) | S_IFREG; | ||
321 | int error = 0; | ||
322 | |||
323 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_NORMAL); | ||
324 | error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode, type); | ||
325 | mutex_unlock(&dir->d_inode->i_mutex); | ||
326 | |||
327 | return error; | ||
328 | } | ||
329 | |||
330 | |||
331 | /** | 316 | /** |
332 | * configfs_create_file - create an attribute file for an item. | 317 | * configfs_create_file - create an attribute file for an item. |
333 | * @item: item we're creating for. | 318 | * @item: item we're creating for. |
@@ -336,9 +321,16 @@ int configfs_add_file(struct dentry * dir, const struct configfs_attribute * att | |||
336 | 321 | ||
337 | int configfs_create_file(struct config_item * item, const struct configfs_attribute * attr) | 322 | int configfs_create_file(struct config_item * item, const struct configfs_attribute * attr) |
338 | { | 323 | { |
339 | BUG_ON(!item || !item->ci_dentry || !attr); | 324 | struct dentry *dir = item->ci_dentry; |
325 | struct configfs_dirent *parent_sd = dir->d_fsdata; | ||
326 | umode_t mode = (attr->ca_mode & S_IALLUGO) | S_IFREG; | ||
327 | int error = 0; | ||
340 | 328 | ||
341 | return configfs_add_file(item->ci_dentry, attr, | 329 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_NORMAL); |
342 | CONFIGFS_ITEM_ATTR); | 330 | error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode, |
331 | CONFIGFS_ITEM_ATTR); | ||
332 | mutex_unlock(&dir->d_inode->i_mutex); | ||
333 | |||
334 | return error; | ||
343 | } | 335 | } |
344 | 336 | ||
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c index 65af86147154..5423a6a6ecc8 100644 --- a/fs/configfs/inode.c +++ b/fs/configfs/inode.c | |||
@@ -176,7 +176,7 @@ static void configfs_set_inode_lock_class(struct configfs_dirent *sd, | |||
176 | 176 | ||
177 | #endif /* CONFIG_LOCKDEP */ | 177 | #endif /* CONFIG_LOCKDEP */ |
178 | 178 | ||
179 | int configfs_create(struct dentry * dentry, umode_t mode, int (*init)(struct inode *)) | 179 | int configfs_create(struct dentry * dentry, umode_t mode, void (*init)(struct inode *)) |
180 | { | 180 | { |
181 | int error = 0; | 181 | int error = 0; |
182 | struct inode *inode = NULL; | 182 | struct inode *inode = NULL; |
@@ -198,13 +198,7 @@ int configfs_create(struct dentry * dentry, umode_t mode, int (*init)(struct ino | |||
198 | p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; | 198 | p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME; |
199 | configfs_set_inode_lock_class(sd, inode); | 199 | configfs_set_inode_lock_class(sd, inode); |
200 | 200 | ||
201 | if (init) { | 201 | init(inode); |
202 | error = init(inode); | ||
203 | if (error) { | ||
204 | iput(inode); | ||
205 | return error; | ||
206 | } | ||
207 | } | ||
208 | d_instantiate(dentry, inode); | 202 | d_instantiate(dentry, inode); |
209 | if (S_ISDIR(mode) || S_ISLNK(mode)) | 203 | if (S_ISDIR(mode) || S_ISLNK(mode)) |
210 | dget(dentry); /* pin link and directory dentries in core */ | 204 | dget(dentry); /* pin link and directory dentries in core */ |
@@ -242,7 +236,7 @@ void configfs_drop_dentry(struct configfs_dirent * sd, struct dentry * parent) | |||
242 | 236 | ||
243 | if (dentry) { | 237 | if (dentry) { |
244 | spin_lock(&dentry->d_lock); | 238 | spin_lock(&dentry->d_lock); |
245 | if (!(d_unhashed(dentry) && dentry->d_inode)) { | 239 | if (!d_unhashed(dentry) && dentry->d_inode) { |
246 | dget_dlock(dentry); | 240 | dget_dlock(dentry); |
247 | __d_drop(dentry); | 241 | __d_drop(dentry); |
248 | spin_unlock(&dentry->d_lock); | 242 | spin_unlock(&dentry->d_lock); |
diff --git a/fs/coredump.c b/fs/coredump.c index b5c86ffd5033..f319926ddf8c 100644 --- a/fs/coredump.c +++ b/fs/coredump.c | |||
@@ -572,7 +572,7 @@ void do_coredump(const siginfo_t *siginfo) | |||
572 | * | 572 | * |
573 | * Normally core limits are irrelevant to pipes, since | 573 | * Normally core limits are irrelevant to pipes, since |
574 | * we're not writing to the file system, but we use | 574 | * we're not writing to the file system, but we use |
575 | * cprm.limit of 1 here as a speacial value, this is a | 575 | * cprm.limit of 1 here as a special value, this is a |
576 | * consistent way to catch recursive crashes. | 576 | * consistent way to catch recursive crashes. |
577 | * We can still crash if the core_pattern binary sets | 577 | * We can still crash if the core_pattern binary sets |
578 | * RLIM_CORE = !1, but it runs as root, and can do | 578 | * RLIM_CORE = !1, but it runs as root, and can do |
diff --git a/fs/dcache.c b/fs/dcache.c index dc400fd29f4d..c71e3732e53b 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -1659,9 +1659,25 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op) | |||
1659 | } | 1659 | } |
1660 | EXPORT_SYMBOL(d_set_d_op); | 1660 | EXPORT_SYMBOL(d_set_d_op); |
1661 | 1661 | ||
1662 | |||
1663 | /* | ||
1664 | * d_set_fallthru - Mark a dentry as falling through to a lower layer | ||
1665 | * @dentry - The dentry to mark | ||
1666 | * | ||
1667 | * Mark a dentry as falling through to the lower layer (as set with | ||
1668 | * d_pin_lower()). This flag may be recorded on the medium. | ||
1669 | */ | ||
1670 | void d_set_fallthru(struct dentry *dentry) | ||
1671 | { | ||
1672 | spin_lock(&dentry->d_lock); | ||
1673 | dentry->d_flags |= DCACHE_FALLTHRU; | ||
1674 | spin_unlock(&dentry->d_lock); | ||
1675 | } | ||
1676 | EXPORT_SYMBOL(d_set_fallthru); | ||
1677 | |||
1662 | static unsigned d_flags_for_inode(struct inode *inode) | 1678 | static unsigned d_flags_for_inode(struct inode *inode) |
1663 | { | 1679 | { |
1664 | unsigned add_flags = DCACHE_FILE_TYPE; | 1680 | unsigned add_flags = DCACHE_REGULAR_TYPE; |
1665 | 1681 | ||
1666 | if (!inode) | 1682 | if (!inode) |
1667 | return DCACHE_MISS_TYPE; | 1683 | return DCACHE_MISS_TYPE; |
@@ -1674,13 +1690,21 @@ static unsigned d_flags_for_inode(struct inode *inode) | |||
1674 | else | 1690 | else |
1675 | inode->i_opflags |= IOP_LOOKUP; | 1691 | inode->i_opflags |= IOP_LOOKUP; |
1676 | } | 1692 | } |
1677 | } else if (unlikely(!(inode->i_opflags & IOP_NOFOLLOW))) { | 1693 | goto type_determined; |
1678 | if (unlikely(inode->i_op->follow_link)) | 1694 | } |
1695 | |||
1696 | if (unlikely(!(inode->i_opflags & IOP_NOFOLLOW))) { | ||
1697 | if (unlikely(inode->i_op->follow_link)) { | ||
1679 | add_flags = DCACHE_SYMLINK_TYPE; | 1698 | add_flags = DCACHE_SYMLINK_TYPE; |
1680 | else | 1699 | goto type_determined; |
1681 | inode->i_opflags |= IOP_NOFOLLOW; | 1700 | } |
1701 | inode->i_opflags |= IOP_NOFOLLOW; | ||
1682 | } | 1702 | } |
1683 | 1703 | ||
1704 | if (unlikely(!S_ISREG(inode->i_mode))) | ||
1705 | add_flags = DCACHE_SPECIAL_TYPE; | ||
1706 | |||
1707 | type_determined: | ||
1684 | if (unlikely(IS_AUTOMOUNT(inode))) | 1708 | if (unlikely(IS_AUTOMOUNT(inode))) |
1685 | add_flags |= DCACHE_NEED_AUTOMOUNT; | 1709 | add_flags |= DCACHE_NEED_AUTOMOUNT; |
1686 | return add_flags; | 1710 | return add_flags; |
@@ -1691,7 +1715,8 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode) | |||
1691 | unsigned add_flags = d_flags_for_inode(inode); | 1715 | unsigned add_flags = d_flags_for_inode(inode); |
1692 | 1716 | ||
1693 | spin_lock(&dentry->d_lock); | 1717 | spin_lock(&dentry->d_lock); |
1694 | __d_set_type(dentry, add_flags); | 1718 | dentry->d_flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU); |
1719 | dentry->d_flags |= add_flags; | ||
1695 | if (inode) | 1720 | if (inode) |
1696 | hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry); | 1721 | hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry); |
1697 | dentry->d_inode = inode; | 1722 | dentry->d_inode = inode; |
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 45b18a5e225c..96400ab42d13 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
@@ -169,10 +169,19 @@ static int debugfs_show_options(struct seq_file *m, struct dentry *root) | |||
169 | return 0; | 169 | return 0; |
170 | } | 170 | } |
171 | 171 | ||
172 | static void debugfs_evict_inode(struct inode *inode) | ||
173 | { | ||
174 | truncate_inode_pages_final(&inode->i_data); | ||
175 | clear_inode(inode); | ||
176 | if (S_ISLNK(inode->i_mode)) | ||
177 | kfree(inode->i_private); | ||
178 | } | ||
179 | |||
172 | static const struct super_operations debugfs_super_operations = { | 180 | static const struct super_operations debugfs_super_operations = { |
173 | .statfs = simple_statfs, | 181 | .statfs = simple_statfs, |
174 | .remount_fs = debugfs_remount, | 182 | .remount_fs = debugfs_remount, |
175 | .show_options = debugfs_show_options, | 183 | .show_options = debugfs_show_options, |
184 | .evict_inode = debugfs_evict_inode, | ||
176 | }; | 185 | }; |
177 | 186 | ||
178 | static struct vfsmount *debugfs_automount(struct path *path) | 187 | static struct vfsmount *debugfs_automount(struct path *path) |
@@ -511,23 +520,14 @@ static int __debugfs_remove(struct dentry *dentry, struct dentry *parent) | |||
511 | int ret = 0; | 520 | int ret = 0; |
512 | 521 | ||
513 | if (debugfs_positive(dentry)) { | 522 | if (debugfs_positive(dentry)) { |
514 | if (dentry->d_inode) { | 523 | dget(dentry); |
515 | dget(dentry); | 524 | if (S_ISDIR(dentry->d_inode->i_mode)) |
516 | switch (dentry->d_inode->i_mode & S_IFMT) { | 525 | ret = simple_rmdir(parent->d_inode, dentry); |
517 | case S_IFDIR: | 526 | else |
518 | ret = simple_rmdir(parent->d_inode, dentry); | 527 | simple_unlink(parent->d_inode, dentry); |
519 | break; | 528 | if (!ret) |
520 | case S_IFLNK: | 529 | d_delete(dentry); |
521 | kfree(dentry->d_inode->i_private); | 530 | dput(dentry); |
522 | /* fall through */ | ||
523 | default: | ||
524 | simple_unlink(parent->d_inode, dentry); | ||
525 | break; | ||
526 | } | ||
527 | if (!ret) | ||
528 | d_delete(dentry); | ||
529 | dput(dentry); | ||
530 | } | ||
531 | } | 531 | } |
532 | return ret; | 532 | return ret; |
533 | } | 533 | } |
@@ -690,7 +690,7 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, | |||
690 | } | 690 | } |
691 | d_move(old_dentry, dentry); | 691 | d_move(old_dentry, dentry); |
692 | fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name, | 692 | fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name, |
693 | S_ISDIR(old_dentry->d_inode->i_mode), | 693 | d_is_dir(old_dentry), |
694 | NULL, old_dentry); | 694 | NULL, old_dentry); |
695 | fsnotify_oldname_free(old_name); | 695 | fsnotify_oldname_free(old_name); |
696 | unlock_rename(new_dir, old_dir); | 696 | unlock_rename(new_dir, old_dir); |
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 6f4e659f508f..b07731e68c0b 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c | |||
@@ -230,7 +230,7 @@ static int ecryptfs_open(struct inode *inode, struct file *file) | |||
230 | } | 230 | } |
231 | ecryptfs_set_file_lower( | 231 | ecryptfs_set_file_lower( |
232 | file, ecryptfs_inode_to_private(inode)->lower_file); | 232 | file, ecryptfs_inode_to_private(inode)->lower_file); |
233 | if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { | 233 | if (d_is_dir(ecryptfs_dentry)) { |
234 | ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); | 234 | ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); |
235 | mutex_lock(&crypt_stat->cs_mutex); | 235 | mutex_lock(&crypt_stat->cs_mutex); |
236 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); | 236 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); |
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 34b36a504059..b08b5187f662 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -907,9 +907,9 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) | |||
907 | lower_inode = ecryptfs_inode_to_lower(inode); | 907 | lower_inode = ecryptfs_inode_to_lower(inode); |
908 | lower_dentry = ecryptfs_dentry_to_lower(dentry); | 908 | lower_dentry = ecryptfs_dentry_to_lower(dentry); |
909 | mutex_lock(&crypt_stat->cs_mutex); | 909 | mutex_lock(&crypt_stat->cs_mutex); |
910 | if (S_ISDIR(dentry->d_inode->i_mode)) | 910 | if (d_is_dir(dentry)) |
911 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); | 911 | crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); |
912 | else if (S_ISREG(dentry->d_inode->i_mode) | 912 | else if (d_is_reg(dentry) |
913 | && (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) | 913 | && (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) |
914 | || !(crypt_stat->flags & ECRYPTFS_KEY_VALID))) { | 914 | || !(crypt_stat->flags & ECRYPTFS_KEY_VALID))) { |
915 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; | 915 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat; |
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index fdfd206c737a..714cd37a6ba3 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c | |||
@@ -429,7 +429,7 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid, | |||
429 | if (IS_ERR(result)) | 429 | if (IS_ERR(result)) |
430 | return result; | 430 | return result; |
431 | 431 | ||
432 | if (S_ISDIR(result->d_inode->i_mode)) { | 432 | if (d_is_dir(result)) { |
433 | /* | 433 | /* |
434 | * This request is for a directory. | 434 | * This request is for a directory. |
435 | * | 435 | * |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 073657f755d4..e907052eeadb 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -769,9 +769,9 @@ static long __writeback_inodes_wb(struct bdi_writeback *wb, | |||
769 | struct inode *inode = wb_inode(wb->b_io.prev); | 769 | struct inode *inode = wb_inode(wb->b_io.prev); |
770 | struct super_block *sb = inode->i_sb; | 770 | struct super_block *sb = inode->i_sb; |
771 | 771 | ||
772 | if (!grab_super_passive(sb)) { | 772 | if (!trylock_super(sb)) { |
773 | /* | 773 | /* |
774 | * grab_super_passive() may fail consistently due to | 774 | * trylock_super() may fail consistently due to |
775 | * s_umount being grabbed by someone else. Don't use | 775 | * s_umount being grabbed by someone else. Don't use |
776 | * requeue_io() to avoid busy retrying the inode/sb. | 776 | * requeue_io() to avoid busy retrying the inode/sb. |
777 | */ | 777 | */ |
@@ -779,7 +779,7 @@ static long __writeback_inodes_wb(struct bdi_writeback *wb, | |||
779 | continue; | 779 | continue; |
780 | } | 780 | } |
781 | wrote += writeback_sb_inodes(sb, wb, work); | 781 | wrote += writeback_sb_inodes(sb, wb, work); |
782 | drop_super(sb); | 782 | up_read(&sb->s_umount); |
783 | 783 | ||
784 | /* refer to the same tests at the end of writeback_sb_inodes */ | 784 | /* refer to the same tests at the end of writeback_sb_inodes */ |
785 | if (wrote) { | 785 | if (wrote) { |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 08e7b1a9d5d0..1545b711ddcf 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -971,7 +971,7 @@ int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, | |||
971 | err = -EBUSY; | 971 | err = -EBUSY; |
972 | goto badentry; | 972 | goto badentry; |
973 | } | 973 | } |
974 | if (S_ISDIR(entry->d_inode->i_mode)) { | 974 | if (d_is_dir(entry)) { |
975 | shrink_dcache_parent(entry); | 975 | shrink_dcache_parent(entry); |
976 | if (!simple_empty(entry)) { | 976 | if (!simple_empty(entry)) { |
977 | err = -ENOTEMPTY; | 977 | err = -ENOTEMPTY; |
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 6371192961e2..487527b42d94 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -1809,7 +1809,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry) | |||
1809 | gfs2_consist_inode(dip); | 1809 | gfs2_consist_inode(dip); |
1810 | dip->i_entries--; | 1810 | dip->i_entries--; |
1811 | dip->i_inode.i_mtime = dip->i_inode.i_ctime = tv; | 1811 | dip->i_inode.i_mtime = dip->i_inode.i_ctime = tv; |
1812 | if (S_ISDIR(dentry->d_inode->i_mode)) | 1812 | if (d_is_dir(dentry)) |
1813 | drop_nlink(&dip->i_inode); | 1813 | drop_nlink(&dip->i_inode); |
1814 | mark_inode_dirty(&dip->i_inode); | 1814 | mark_inode_dirty(&dip->i_inode); |
1815 | 1815 | ||
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 435bea231cc6..f0235c1640af 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
@@ -530,7 +530,7 @@ static int hfsplus_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
530 | 530 | ||
531 | /* Unlink destination if it already exists */ | 531 | /* Unlink destination if it already exists */ |
532 | if (new_dentry->d_inode) { | 532 | if (new_dentry->d_inode) { |
533 | if (S_ISDIR(new_dentry->d_inode->i_mode)) | 533 | if (d_is_dir(new_dentry)) |
534 | res = hfsplus_rmdir(new_dir, new_dentry); | 534 | res = hfsplus_rmdir(new_dir, new_dentry); |
535 | else | 535 | else |
536 | res = hfsplus_unlink(new_dir, new_dentry); | 536 | res = hfsplus_unlink(new_dir, new_dentry); |
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c index 5f2755117ce7..043ac9d77262 100644 --- a/fs/hppfs/hppfs.c +++ b/fs/hppfs/hppfs.c | |||
@@ -678,10 +678,10 @@ static struct inode *get_inode(struct super_block *sb, struct dentry *dentry) | |||
678 | return NULL; | 678 | return NULL; |
679 | } | 679 | } |
680 | 680 | ||
681 | if (S_ISDIR(dentry->d_inode->i_mode)) { | 681 | if (d_is_dir(dentry)) { |
682 | inode->i_op = &hppfs_dir_iops; | 682 | inode->i_op = &hppfs_dir_iops; |
683 | inode->i_fop = &hppfs_dir_fops; | 683 | inode->i_fop = &hppfs_dir_fops; |
684 | } else if (S_ISLNK(dentry->d_inode->i_mode)) { | 684 | } else if (d_is_symlink(dentry)) { |
685 | inode->i_op = &hppfs_link_iops; | 685 | inode->i_op = &hppfs_link_iops; |
686 | inode->i_fop = &hppfs_file_fops; | 686 | inode->i_fop = &hppfs_file_fops; |
687 | } else { | 687 | } else { |
diff --git a/fs/internal.h b/fs/internal.h index 30459dab409d..01dce1d1476b 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
@@ -84,7 +84,7 @@ extern struct file *get_empty_filp(void); | |||
84 | * super.c | 84 | * super.c |
85 | */ | 85 | */ |
86 | extern int do_remount_sb(struct super_block *, int, void *, int); | 86 | extern int do_remount_sb(struct super_block *, int, void *, int); |
87 | extern bool grab_super_passive(struct super_block *sb); | 87 | extern bool trylock_super(struct super_block *sb); |
88 | extern struct dentry *mount_fs(struct file_system_type *, | 88 | extern struct dentry *mount_fs(struct file_system_type *, |
89 | int, const char *, void *); | 89 | int, const char *, void *); |
90 | extern struct super_block *user_get_super(dev_t); | 90 | extern struct super_block *user_get_super(dev_t); |
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 938556025d64..f21b6fb5e4c4 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
@@ -252,7 +252,7 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de | |||
252 | if (!f->inocache) | 252 | if (!f->inocache) |
253 | return -EIO; | 253 | return -EIO; |
254 | 254 | ||
255 | if (S_ISDIR(old_dentry->d_inode->i_mode)) | 255 | if (d_is_dir(old_dentry)) |
256 | return -EPERM; | 256 | return -EPERM; |
257 | 257 | ||
258 | /* XXX: This is ugly */ | 258 | /* XXX: This is ugly */ |
@@ -772,7 +772,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, | |||
772 | */ | 772 | */ |
773 | if (new_dentry->d_inode) { | 773 | if (new_dentry->d_inode) { |
774 | victim_f = JFFS2_INODE_INFO(new_dentry->d_inode); | 774 | victim_f = JFFS2_INODE_INFO(new_dentry->d_inode); |
775 | if (S_ISDIR(new_dentry->d_inode->i_mode)) { | 775 | if (d_is_dir(new_dentry)) { |
776 | struct jffs2_full_dirent *fd; | 776 | struct jffs2_full_dirent *fd; |
777 | 777 | ||
778 | mutex_lock(&victim_f->sem); | 778 | mutex_lock(&victim_f->sem); |
@@ -807,7 +807,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, | |||
807 | 807 | ||
808 | if (victim_f) { | 808 | if (victim_f) { |
809 | /* There was a victim. Kill it off nicely */ | 809 | /* There was a victim. Kill it off nicely */ |
810 | if (S_ISDIR(new_dentry->d_inode->i_mode)) | 810 | if (d_is_dir(new_dentry)) |
811 | clear_nlink(new_dentry->d_inode); | 811 | clear_nlink(new_dentry->d_inode); |
812 | else | 812 | else |
813 | drop_nlink(new_dentry->d_inode); | 813 | drop_nlink(new_dentry->d_inode); |
@@ -815,7 +815,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, | |||
815 | inode which didn't exist. */ | 815 | inode which didn't exist. */ |
816 | if (victim_f->inocache) { | 816 | if (victim_f->inocache) { |
817 | mutex_lock(&victim_f->sem); | 817 | mutex_lock(&victim_f->sem); |
818 | if (S_ISDIR(new_dentry->d_inode->i_mode)) | 818 | if (d_is_dir(new_dentry)) |
819 | victim_f->inocache->pino_nlink = 0; | 819 | victim_f->inocache->pino_nlink = 0; |
820 | else | 820 | else |
821 | victim_f->inocache->pino_nlink--; | 821 | victim_f->inocache->pino_nlink--; |
@@ -825,7 +825,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, | |||
825 | 825 | ||
826 | /* If it was a directory we moved, and there was no victim, | 826 | /* If it was a directory we moved, and there was no victim, |
827 | increase i_nlink on its new parent */ | 827 | increase i_nlink on its new parent */ |
828 | if (S_ISDIR(old_dentry->d_inode->i_mode) && !victim_f) | 828 | if (d_is_dir(old_dentry) && !victim_f) |
829 | inc_nlink(new_dir_i); | 829 | inc_nlink(new_dir_i); |
830 | 830 | ||
831 | /* Unlink the original */ | 831 | /* Unlink the original */ |
@@ -839,7 +839,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, | |||
839 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode); | 839 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode); |
840 | mutex_lock(&f->sem); | 840 | mutex_lock(&f->sem); |
841 | inc_nlink(old_dentry->d_inode); | 841 | inc_nlink(old_dentry->d_inode); |
842 | if (f->inocache && !S_ISDIR(old_dentry->d_inode->i_mode)) | 842 | if (f->inocache && !d_is_dir(old_dentry)) |
843 | f->inocache->pino_nlink++; | 843 | f->inocache->pino_nlink++; |
844 | mutex_unlock(&f->sem); | 844 | mutex_unlock(&f->sem); |
845 | 845 | ||
@@ -852,7 +852,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, | |||
852 | return ret; | 852 | return ret; |
853 | } | 853 | } |
854 | 854 | ||
855 | if (S_ISDIR(old_dentry->d_inode->i_mode)) | 855 | if (d_is_dir(old_dentry)) |
856 | drop_nlink(old_dir_i); | 856 | drop_nlink(old_dir_i); |
857 | 857 | ||
858 | new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now); | 858 | new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now); |
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 0918f0e2e266..3d76f28a2ba9 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c | |||
@@ -138,7 +138,7 @@ static struct dentry *jffs2_get_parent(struct dentry *child) | |||
138 | struct jffs2_inode_info *f; | 138 | struct jffs2_inode_info *f; |
139 | uint32_t pino; | 139 | uint32_t pino; |
140 | 140 | ||
141 | BUG_ON(!S_ISDIR(child->d_inode->i_mode)); | 141 | BUG_ON(!d_is_dir(child)); |
142 | 142 | ||
143 | f = JFFS2_INODE_INFO(child->d_inode); | 143 | f = JFFS2_INODE_INFO(child->d_inode); |
144 | 144 | ||
diff --git a/fs/libfs.c b/fs/libfs.c index b2ffdb045be4..0ab65122ee45 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -329,7 +329,7 @@ int simple_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
329 | struct inode *new_dir, struct dentry *new_dentry) | 329 | struct inode *new_dir, struct dentry *new_dentry) |
330 | { | 330 | { |
331 | struct inode *inode = old_dentry->d_inode; | 331 | struct inode *inode = old_dentry->d_inode; |
332 | int they_are_dirs = S_ISDIR(old_dentry->d_inode->i_mode); | 332 | int they_are_dirs = d_is_dir(old_dentry); |
333 | 333 | ||
334 | if (!simple_empty(new_dentry)) | 334 | if (!simple_empty(new_dentry)) |
335 | return -ENOTEMPTY; | 335 | return -ENOTEMPTY; |
diff --git a/fs/namei.c b/fs/namei.c index 96ca11dea4a2..c83145af4bfc 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -2814,7 +2814,7 @@ no_open: | |||
2814 | } else if (!dentry->d_inode) { | 2814 | } else if (!dentry->d_inode) { |
2815 | goto out; | 2815 | goto out; |
2816 | } else if ((open_flag & O_TRUNC) && | 2816 | } else if ((open_flag & O_TRUNC) && |
2817 | S_ISREG(dentry->d_inode->i_mode)) { | 2817 | d_is_reg(dentry)) { |
2818 | goto out; | 2818 | goto out; |
2819 | } | 2819 | } |
2820 | /* will fail later, go on to get the right error */ | 2820 | /* will fail later, go on to get the right error */ |
diff --git a/fs/namespace.c b/fs/namespace.c index 72a286e0d33e..82ef1405260e 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -1907,8 +1907,8 @@ static int graft_tree(struct mount *mnt, struct mount *p, struct mountpoint *mp) | |||
1907 | if (mnt->mnt.mnt_sb->s_flags & MS_NOUSER) | 1907 | if (mnt->mnt.mnt_sb->s_flags & MS_NOUSER) |
1908 | return -EINVAL; | 1908 | return -EINVAL; |
1909 | 1909 | ||
1910 | if (S_ISDIR(mp->m_dentry->d_inode->i_mode) != | 1910 | if (d_is_dir(mp->m_dentry) != |
1911 | S_ISDIR(mnt->mnt.mnt_root->d_inode->i_mode)) | 1911 | d_is_dir(mnt->mnt.mnt_root)) |
1912 | return -ENOTDIR; | 1912 | return -ENOTDIR; |
1913 | 1913 | ||
1914 | return attach_recursive_mnt(mnt, p, mp, NULL); | 1914 | return attach_recursive_mnt(mnt, p, mp, NULL); |
@@ -2180,8 +2180,8 @@ static int do_move_mount(struct path *path, const char *old_name) | |||
2180 | if (!mnt_has_parent(old)) | 2180 | if (!mnt_has_parent(old)) |
2181 | goto out1; | 2181 | goto out1; |
2182 | 2182 | ||
2183 | if (S_ISDIR(path->dentry->d_inode->i_mode) != | 2183 | if (d_is_dir(path->dentry) != |
2184 | S_ISDIR(old_path.dentry->d_inode->i_mode)) | 2184 | d_is_dir(old_path.dentry)) |
2185 | goto out1; | 2185 | goto out1; |
2186 | /* | 2186 | /* |
2187 | * Don't move a mount residing in a shared parent. | 2187 | * Don't move a mount residing in a shared parent. |
@@ -2271,7 +2271,7 @@ static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags) | |||
2271 | goto unlock; | 2271 | goto unlock; |
2272 | 2272 | ||
2273 | err = -EINVAL; | 2273 | err = -EINVAL; |
2274 | if (S_ISLNK(newmnt->mnt.mnt_root->d_inode->i_mode)) | 2274 | if (d_is_symlink(newmnt->mnt.mnt_root)) |
2275 | goto unlock; | 2275 | goto unlock; |
2276 | 2276 | ||
2277 | newmnt->mnt.mnt_flags = mnt_flags; | 2277 | newmnt->mnt.mnt_flags = mnt_flags; |
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index cc6a76072009..1c307f02baa8 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c | |||
@@ -583,7 +583,7 @@ nfs4_reset_recoverydir(char *recdir) | |||
583 | if (status) | 583 | if (status) |
584 | return status; | 584 | return status; |
585 | status = -ENOTDIR; | 585 | status = -ENOTDIR; |
586 | if (S_ISDIR(path.dentry->d_inode->i_mode)) { | 586 | if (d_is_dir(path.dentry)) { |
587 | strcpy(user_recovery_dirname, recdir); | 587 | strcpy(user_recovery_dirname, recdir); |
588 | status = 0; | 588 | status = 0; |
589 | } | 589 | } |
@@ -1426,7 +1426,7 @@ nfsd4_client_tracking_init(struct net *net) | |||
1426 | nn->client_tracking_ops = &nfsd4_legacy_tracking_ops; | 1426 | nn->client_tracking_ops = &nfsd4_legacy_tracking_ops; |
1427 | status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path); | 1427 | status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path); |
1428 | if (!status) { | 1428 | if (!status) { |
1429 | status = S_ISDIR(path.dentry->d_inode->i_mode); | 1429 | status = d_is_dir(path.dentry); |
1430 | path_put(&path); | 1430 | path_put(&path); |
1431 | if (status) | 1431 | if (status) |
1432 | goto do_init; | 1432 | goto do_init; |
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 965b478d50fc..e9fa966fc37f 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
@@ -114,8 +114,8 @@ static inline __be32 check_pseudo_root(struct svc_rqst *rqstp, | |||
114 | * We're exposing only the directories and symlinks that have to be | 114 | * We're exposing only the directories and symlinks that have to be |
115 | * traversed on the way to real exports: | 115 | * traversed on the way to real exports: |
116 | */ | 116 | */ |
117 | if (unlikely(!S_ISDIR(dentry->d_inode->i_mode) && | 117 | if (unlikely(!d_is_dir(dentry) && |
118 | !S_ISLNK(dentry->d_inode->i_mode))) | 118 | !d_is_symlink(dentry))) |
119 | return nfserr_stale; | 119 | return nfserr_stale; |
120 | /* | 120 | /* |
121 | * A pseudoroot export gives permission to access only one | 121 | * A pseudoroot export gives permission to access only one |
@@ -259,7 +259,7 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp) | |||
259 | goto out; | 259 | goto out; |
260 | } | 260 | } |
261 | 261 | ||
262 | if (S_ISDIR(dentry->d_inode->i_mode) && | 262 | if (d_is_dir(dentry) && |
263 | (dentry->d_flags & DCACHE_DISCONNECTED)) { | 263 | (dentry->d_flags & DCACHE_DISCONNECTED)) { |
264 | printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %pd2\n", | 264 | printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %pd2\n", |
265 | dentry); | 265 | dentry); |
@@ -414,7 +414,7 @@ static inline void _fh_update_old(struct dentry *dentry, | |||
414 | { | 414 | { |
415 | fh->ofh_ino = ino_t_to_u32(dentry->d_inode->i_ino); | 415 | fh->ofh_ino = ino_t_to_u32(dentry->d_inode->i_ino); |
416 | fh->ofh_generation = dentry->d_inode->i_generation; | 416 | fh->ofh_generation = dentry->d_inode->i_generation; |
417 | if (S_ISDIR(dentry->d_inode->i_mode) || | 417 | if (d_is_dir(dentry) || |
418 | (exp->ex_flags & NFSEXP_NOSUBTREECHECK)) | 418 | (exp->ex_flags & NFSEXP_NOSUBTREECHECK)) |
419 | fh->ofh_dirino = 0; | 419 | fh->ofh_dirino = 0; |
420 | } | 420 | } |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 5685c679dd93..368526582429 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -615,9 +615,9 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor | |||
615 | export = fhp->fh_export; | 615 | export = fhp->fh_export; |
616 | dentry = fhp->fh_dentry; | 616 | dentry = fhp->fh_dentry; |
617 | 617 | ||
618 | if (S_ISREG(dentry->d_inode->i_mode)) | 618 | if (d_is_reg(dentry)) |
619 | map = nfs3_regaccess; | 619 | map = nfs3_regaccess; |
620 | else if (S_ISDIR(dentry->d_inode->i_mode)) | 620 | else if (d_is_dir(dentry)) |
621 | map = nfs3_diraccess; | 621 | map = nfs3_diraccess; |
622 | else | 622 | else |
623 | map = nfs3_anyaccess; | 623 | map = nfs3_anyaccess; |
@@ -1402,7 +1402,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1402 | 1402 | ||
1403 | switch (createmode) { | 1403 | switch (createmode) { |
1404 | case NFS3_CREATE_UNCHECKED: | 1404 | case NFS3_CREATE_UNCHECKED: |
1405 | if (! S_ISREG(dchild->d_inode->i_mode)) | 1405 | if (! d_is_reg(dchild)) |
1406 | goto out; | 1406 | goto out; |
1407 | else if (truncp) { | 1407 | else if (truncp) { |
1408 | /* in nfsv4, we need to treat this case a little | 1408 | /* in nfsv4, we need to treat this case a little |
@@ -1615,7 +1615,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1615 | if (err) | 1615 | if (err) |
1616 | goto out; | 1616 | goto out; |
1617 | err = nfserr_isdir; | 1617 | err = nfserr_isdir; |
1618 | if (S_ISDIR(tfhp->fh_dentry->d_inode->i_mode)) | 1618 | if (d_is_dir(tfhp->fh_dentry)) |
1619 | goto out; | 1619 | goto out; |
1620 | err = nfserr_perm; | 1620 | err = nfserr_perm; |
1621 | if (!len) | 1621 | if (!len) |
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 51ceb8107284..9a66ff79ff27 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c | |||
@@ -115,8 +115,8 @@ static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark, | |||
115 | return false; | 115 | return false; |
116 | 116 | ||
117 | /* sorry, fanotify only gives a damn about files and dirs */ | 117 | /* sorry, fanotify only gives a damn about files and dirs */ |
118 | if (!S_ISREG(path->dentry->d_inode->i_mode) && | 118 | if (!d_is_reg(path->dentry) && |
119 | !S_ISDIR(path->dentry->d_inode->i_mode)) | 119 | !d_can_lookup(path->dentry)) |
120 | return false; | 120 | return false; |
121 | 121 | ||
122 | if (inode_mark && vfsmnt_mark) { | 122 | if (inode_mark && vfsmnt_mark) { |
@@ -139,7 +139,7 @@ static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark, | |||
139 | BUG(); | 139 | BUG(); |
140 | } | 140 | } |
141 | 141 | ||
142 | if (S_ISDIR(path->dentry->d_inode->i_mode) && | 142 | if (d_is_dir(path->dentry) && |
143 | !(marks_mask & FS_ISDIR & ~marks_ignored_mask)) | 143 | !(marks_mask & FS_ISDIR & ~marks_ignored_mask)) |
144 | return false; | 144 | return false; |
145 | 145 | ||
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index ea10a8719107..24f640441bd9 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c | |||
@@ -191,7 +191,6 @@ int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat) | |||
191 | ovl_set_timestamps(upperdentry, stat); | 191 | ovl_set_timestamps(upperdentry, stat); |
192 | 192 | ||
193 | return err; | 193 | return err; |
194 | |||
195 | } | 194 | } |
196 | 195 | ||
197 | static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, | 196 | static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir, |
@@ -385,7 +384,7 @@ int ovl_copy_up(struct dentry *dentry) | |||
385 | struct kstat stat; | 384 | struct kstat stat; |
386 | enum ovl_path_type type = ovl_path_type(dentry); | 385 | enum ovl_path_type type = ovl_path_type(dentry); |
387 | 386 | ||
388 | if (type != OVL_PATH_LOWER) | 387 | if (OVL_TYPE_UPPER(type)) |
389 | break; | 388 | break; |
390 | 389 | ||
391 | next = dget(dentry); | 390 | next = dget(dentry); |
@@ -394,7 +393,7 @@ int ovl_copy_up(struct dentry *dentry) | |||
394 | parent = dget_parent(next); | 393 | parent = dget_parent(next); |
395 | 394 | ||
396 | type = ovl_path_type(parent); | 395 | type = ovl_path_type(parent); |
397 | if (type != OVL_PATH_LOWER) | 396 | if (OVL_TYPE_UPPER(type)) |
398 | break; | 397 | break; |
399 | 398 | ||
400 | dput(next); | 399 | dput(next); |
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 8ffc4b980f1b..d139405d2bfa 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c | |||
@@ -19,7 +19,7 @@ void ovl_cleanup(struct inode *wdir, struct dentry *wdentry) | |||
19 | int err; | 19 | int err; |
20 | 20 | ||
21 | dget(wdentry); | 21 | dget(wdentry); |
22 | if (S_ISDIR(wdentry->d_inode->i_mode)) | 22 | if (d_is_dir(wdentry)) |
23 | err = ovl_do_rmdir(wdir, wdentry); | 23 | err = ovl_do_rmdir(wdir, wdentry); |
24 | else | 24 | else |
25 | err = ovl_do_unlink(wdir, wdentry); | 25 | err = ovl_do_unlink(wdir, wdentry); |
@@ -118,14 +118,14 @@ int ovl_create_real(struct inode *dir, struct dentry *newdentry, | |||
118 | 118 | ||
119 | static int ovl_set_opaque(struct dentry *upperdentry) | 119 | static int ovl_set_opaque(struct dentry *upperdentry) |
120 | { | 120 | { |
121 | return ovl_do_setxattr(upperdentry, ovl_opaque_xattr, "y", 1, 0); | 121 | return ovl_do_setxattr(upperdentry, OVL_XATTR_OPAQUE, "y", 1, 0); |
122 | } | 122 | } |
123 | 123 | ||
124 | static void ovl_remove_opaque(struct dentry *upperdentry) | 124 | static void ovl_remove_opaque(struct dentry *upperdentry) |
125 | { | 125 | { |
126 | int err; | 126 | int err; |
127 | 127 | ||
128 | err = ovl_do_removexattr(upperdentry, ovl_opaque_xattr); | 128 | err = ovl_do_removexattr(upperdentry, OVL_XATTR_OPAQUE); |
129 | if (err) { | 129 | if (err) { |
130 | pr_warn("overlayfs: failed to remove opaque from '%s' (%i)\n", | 130 | pr_warn("overlayfs: failed to remove opaque from '%s' (%i)\n", |
131 | upperdentry->d_name.name, err); | 131 | upperdentry->d_name.name, err); |
@@ -152,7 +152,7 @@ static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
152 | * correct link count. nlink=1 seems to pacify 'find' and | 152 | * correct link count. nlink=1 seems to pacify 'find' and |
153 | * other utilities. | 153 | * other utilities. |
154 | */ | 154 | */ |
155 | if (type == OVL_PATH_MERGE) | 155 | if (OVL_TYPE_MERGE(type)) |
156 | stat->nlink = 1; | 156 | stat->nlink = 1; |
157 | 157 | ||
158 | return 0; | 158 | return 0; |
@@ -506,7 +506,7 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir) | |||
506 | struct dentry *opaquedir = NULL; | 506 | struct dentry *opaquedir = NULL; |
507 | int err; | 507 | int err; |
508 | 508 | ||
509 | if (is_dir) { | 509 | if (is_dir && OVL_TYPE_MERGE_OR_LOWER(ovl_path_type(dentry))) { |
510 | opaquedir = ovl_check_empty_and_clear(dentry); | 510 | opaquedir = ovl_check_empty_and_clear(dentry); |
511 | err = PTR_ERR(opaquedir); | 511 | err = PTR_ERR(opaquedir); |
512 | if (IS_ERR(opaquedir)) | 512 | if (IS_ERR(opaquedir)) |
@@ -630,7 +630,7 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir) | |||
630 | goto out_drop_write; | 630 | goto out_drop_write; |
631 | 631 | ||
632 | type = ovl_path_type(dentry); | 632 | type = ovl_path_type(dentry); |
633 | if (type == OVL_PATH_PURE_UPPER) { | 633 | if (OVL_TYPE_PURE_UPPER(type)) { |
634 | err = ovl_remove_upper(dentry, is_dir); | 634 | err = ovl_remove_upper(dentry, is_dir); |
635 | } else { | 635 | } else { |
636 | const struct cred *old_cred; | 636 | const struct cred *old_cred; |
@@ -693,7 +693,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, | |||
693 | bool new_create = false; | 693 | bool new_create = false; |
694 | bool cleanup_whiteout = false; | 694 | bool cleanup_whiteout = false; |
695 | bool overwrite = !(flags & RENAME_EXCHANGE); | 695 | bool overwrite = !(flags & RENAME_EXCHANGE); |
696 | bool is_dir = S_ISDIR(old->d_inode->i_mode); | 696 | bool is_dir = d_is_dir(old); |
697 | bool new_is_dir = false; | 697 | bool new_is_dir = false; |
698 | struct dentry *opaquedir = NULL; | 698 | struct dentry *opaquedir = NULL; |
699 | const struct cred *old_cred = NULL; | 699 | const struct cred *old_cred = NULL; |
@@ -712,7 +712,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, | |||
712 | /* Don't copy up directory trees */ | 712 | /* Don't copy up directory trees */ |
713 | old_type = ovl_path_type(old); | 713 | old_type = ovl_path_type(old); |
714 | err = -EXDEV; | 714 | err = -EXDEV; |
715 | if ((old_type == OVL_PATH_LOWER || old_type == OVL_PATH_MERGE) && is_dir) | 715 | if (OVL_TYPE_MERGE_OR_LOWER(old_type) && is_dir) |
716 | goto out; | 716 | goto out; |
717 | 717 | ||
718 | if (new->d_inode) { | 718 | if (new->d_inode) { |
@@ -720,30 +720,30 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, | |||
720 | if (err) | 720 | if (err) |
721 | goto out; | 721 | goto out; |
722 | 722 | ||
723 | if (S_ISDIR(new->d_inode->i_mode)) | 723 | if (d_is_dir(new)) |
724 | new_is_dir = true; | 724 | new_is_dir = true; |
725 | 725 | ||
726 | new_type = ovl_path_type(new); | 726 | new_type = ovl_path_type(new); |
727 | err = -EXDEV; | 727 | err = -EXDEV; |
728 | if (!overwrite && (new_type == OVL_PATH_LOWER || new_type == OVL_PATH_MERGE) && new_is_dir) | 728 | if (!overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir) |
729 | goto out; | 729 | goto out; |
730 | 730 | ||
731 | err = 0; | 731 | err = 0; |
732 | if (new_type == OVL_PATH_LOWER && old_type == OVL_PATH_LOWER) { | 732 | if (!OVL_TYPE_UPPER(new_type) && !OVL_TYPE_UPPER(old_type)) { |
733 | if (ovl_dentry_lower(old)->d_inode == | 733 | if (ovl_dentry_lower(old)->d_inode == |
734 | ovl_dentry_lower(new)->d_inode) | 734 | ovl_dentry_lower(new)->d_inode) |
735 | goto out; | 735 | goto out; |
736 | } | 736 | } |
737 | if (new_type != OVL_PATH_LOWER && old_type != OVL_PATH_LOWER) { | 737 | if (OVL_TYPE_UPPER(new_type) && OVL_TYPE_UPPER(old_type)) { |
738 | if (ovl_dentry_upper(old)->d_inode == | 738 | if (ovl_dentry_upper(old)->d_inode == |
739 | ovl_dentry_upper(new)->d_inode) | 739 | ovl_dentry_upper(new)->d_inode) |
740 | goto out; | 740 | goto out; |
741 | } | 741 | } |
742 | } else { | 742 | } else { |
743 | if (ovl_dentry_is_opaque(new)) | 743 | if (ovl_dentry_is_opaque(new)) |
744 | new_type = OVL_PATH_UPPER; | 744 | new_type = __OVL_PATH_UPPER; |
745 | else | 745 | else |
746 | new_type = OVL_PATH_PURE_UPPER; | 746 | new_type = __OVL_PATH_UPPER | __OVL_PATH_PURE; |
747 | } | 747 | } |
748 | 748 | ||
749 | err = ovl_want_write(old); | 749 | err = ovl_want_write(old); |
@@ -763,8 +763,8 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, | |||
763 | goto out_drop_write; | 763 | goto out_drop_write; |
764 | } | 764 | } |
765 | 765 | ||
766 | old_opaque = old_type != OVL_PATH_PURE_UPPER; | 766 | old_opaque = !OVL_TYPE_PURE_UPPER(old_type); |
767 | new_opaque = new_type != OVL_PATH_PURE_UPPER; | 767 | new_opaque = !OVL_TYPE_PURE_UPPER(new_type); |
768 | 768 | ||
769 | if (old_opaque || new_opaque) { | 769 | if (old_opaque || new_opaque) { |
770 | err = -ENOMEM; | 770 | err = -ENOMEM; |
@@ -787,7 +787,7 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old, | |||
787 | old_cred = override_creds(override_cred); | 787 | old_cred = override_creds(override_cred); |
788 | } | 788 | } |
789 | 789 | ||
790 | if (overwrite && (new_type == OVL_PATH_LOWER || new_type == OVL_PATH_MERGE) && new_is_dir) { | 790 | if (overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir) { |
791 | opaquedir = ovl_check_empty_and_clear(new); | 791 | opaquedir = ovl_check_empty_and_clear(new); |
792 | err = PTR_ERR(opaquedir); | 792 | err = PTR_ERR(opaquedir); |
793 | if (IS_ERR(opaquedir)) { | 793 | if (IS_ERR(opaquedir)) { |
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 07d74b24913b..04f124884687 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
@@ -205,7 +205,7 @@ static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz) | |||
205 | 205 | ||
206 | static bool ovl_is_private_xattr(const char *name) | 206 | static bool ovl_is_private_xattr(const char *name) |
207 | { | 207 | { |
208 | return strncmp(name, "trusted.overlay.", 14) == 0; | 208 | return strncmp(name, OVL_XATTR_PRE_NAME, OVL_XATTR_PRE_LEN) == 0; |
209 | } | 209 | } |
210 | 210 | ||
211 | int ovl_setxattr(struct dentry *dentry, const char *name, | 211 | int ovl_setxattr(struct dentry *dentry, const char *name, |
@@ -238,7 +238,10 @@ out: | |||
238 | static bool ovl_need_xattr_filter(struct dentry *dentry, | 238 | static bool ovl_need_xattr_filter(struct dentry *dentry, |
239 | enum ovl_path_type type) | 239 | enum ovl_path_type type) |
240 | { | 240 | { |
241 | return type == OVL_PATH_UPPER && S_ISDIR(dentry->d_inode->i_mode); | 241 | if ((type & (__OVL_PATH_PURE | __OVL_PATH_UPPER)) == __OVL_PATH_UPPER) |
242 | return S_ISDIR(dentry->d_inode->i_mode); | ||
243 | else | ||
244 | return false; | ||
242 | } | 245 | } |
243 | 246 | ||
244 | ssize_t ovl_getxattr(struct dentry *dentry, const char *name, | 247 | ssize_t ovl_getxattr(struct dentry *dentry, const char *name, |
@@ -299,7 +302,7 @@ int ovl_removexattr(struct dentry *dentry, const char *name) | |||
299 | if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) | 302 | if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) |
300 | goto out_drop_write; | 303 | goto out_drop_write; |
301 | 304 | ||
302 | if (type == OVL_PATH_LOWER) { | 305 | if (!OVL_TYPE_UPPER(type)) { |
303 | err = vfs_getxattr(realpath.dentry, name, NULL, 0); | 306 | err = vfs_getxattr(realpath.dentry, name, NULL, 0); |
304 | if (err < 0) | 307 | if (err < 0) |
305 | goto out_drop_write; | 308 | goto out_drop_write; |
@@ -321,7 +324,7 @@ out: | |||
321 | static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type, | 324 | static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type, |
322 | struct dentry *realdentry) | 325 | struct dentry *realdentry) |
323 | { | 326 | { |
324 | if (type != OVL_PATH_LOWER) | 327 | if (OVL_TYPE_UPPER(type)) |
325 | return false; | 328 | return false; |
326 | 329 | ||
327 | if (special_file(realdentry->d_inode->i_mode)) | 330 | if (special_file(realdentry->d_inode->i_mode)) |
@@ -430,5 +433,4 @@ struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, | |||
430 | } | 433 | } |
431 | 434 | ||
432 | return inode; | 435 | return inode; |
433 | |||
434 | } | 436 | } |
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 814bed33dd07..17ac5afc9ffb 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h | |||
@@ -12,13 +12,20 @@ | |||
12 | struct ovl_entry; | 12 | struct ovl_entry; |
13 | 13 | ||
14 | enum ovl_path_type { | 14 | enum ovl_path_type { |
15 | OVL_PATH_PURE_UPPER, | 15 | __OVL_PATH_PURE = (1 << 0), |
16 | OVL_PATH_UPPER, | 16 | __OVL_PATH_UPPER = (1 << 1), |
17 | OVL_PATH_MERGE, | 17 | __OVL_PATH_MERGE = (1 << 2), |
18 | OVL_PATH_LOWER, | ||
19 | }; | 18 | }; |
20 | 19 | ||
21 | extern const char *ovl_opaque_xattr; | 20 | #define OVL_TYPE_UPPER(type) ((type) & __OVL_PATH_UPPER) |
21 | #define OVL_TYPE_MERGE(type) ((type) & __OVL_PATH_MERGE) | ||
22 | #define OVL_TYPE_PURE_UPPER(type) ((type) & __OVL_PATH_PURE) | ||
23 | #define OVL_TYPE_MERGE_OR_LOWER(type) \ | ||
24 | (OVL_TYPE_MERGE(type) || !OVL_TYPE_UPPER(type)) | ||
25 | |||
26 | #define OVL_XATTR_PRE_NAME "trusted.overlay." | ||
27 | #define OVL_XATTR_PRE_LEN 16 | ||
28 | #define OVL_XATTR_OPAQUE OVL_XATTR_PRE_NAME"opaque" | ||
22 | 29 | ||
23 | static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry) | 30 | static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry) |
24 | { | 31 | { |
@@ -130,6 +137,7 @@ void ovl_dentry_version_inc(struct dentry *dentry); | |||
130 | void ovl_path_upper(struct dentry *dentry, struct path *path); | 137 | void ovl_path_upper(struct dentry *dentry, struct path *path); |
131 | void ovl_path_lower(struct dentry *dentry, struct path *path); | 138 | void ovl_path_lower(struct dentry *dentry, struct path *path); |
132 | enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path); | 139 | enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path); |
140 | int ovl_path_next(int idx, struct dentry *dentry, struct path *path); | ||
133 | struct dentry *ovl_dentry_upper(struct dentry *dentry); | 141 | struct dentry *ovl_dentry_upper(struct dentry *dentry); |
134 | struct dentry *ovl_dentry_lower(struct dentry *dentry); | 142 | struct dentry *ovl_dentry_lower(struct dentry *dentry); |
135 | struct dentry *ovl_dentry_real(struct dentry *dentry); | 143 | struct dentry *ovl_dentry_real(struct dentry *dentry); |
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c index c0205990a9f5..907870e81a72 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c | |||
@@ -24,7 +24,6 @@ struct ovl_cache_entry { | |||
24 | struct list_head l_node; | 24 | struct list_head l_node; |
25 | struct rb_node node; | 25 | struct rb_node node; |
26 | bool is_whiteout; | 26 | bool is_whiteout; |
27 | bool is_cursor; | ||
28 | char name[]; | 27 | char name[]; |
29 | }; | 28 | }; |
30 | 29 | ||
@@ -40,6 +39,7 @@ struct ovl_readdir_data { | |||
40 | struct rb_root root; | 39 | struct rb_root root; |
41 | struct list_head *list; | 40 | struct list_head *list; |
42 | struct list_head middle; | 41 | struct list_head middle; |
42 | struct dentry *dir; | ||
43 | int count; | 43 | int count; |
44 | int err; | 44 | int err; |
45 | }; | 45 | }; |
@@ -48,7 +48,7 @@ struct ovl_dir_file { | |||
48 | bool is_real; | 48 | bool is_real; |
49 | bool is_upper; | 49 | bool is_upper; |
50 | struct ovl_dir_cache *cache; | 50 | struct ovl_dir_cache *cache; |
51 | struct ovl_cache_entry cursor; | 51 | struct list_head *cursor; |
52 | struct file *realfile; | 52 | struct file *realfile; |
53 | struct file *upperfile; | 53 | struct file *upperfile; |
54 | }; | 54 | }; |
@@ -79,23 +79,49 @@ static struct ovl_cache_entry *ovl_cache_entry_find(struct rb_root *root, | |||
79 | return NULL; | 79 | return NULL; |
80 | } | 80 | } |
81 | 81 | ||
82 | static struct ovl_cache_entry *ovl_cache_entry_new(const char *name, int len, | 82 | static struct ovl_cache_entry *ovl_cache_entry_new(struct dentry *dir, |
83 | const char *name, int len, | ||
83 | u64 ino, unsigned int d_type) | 84 | u64 ino, unsigned int d_type) |
84 | { | 85 | { |
85 | struct ovl_cache_entry *p; | 86 | struct ovl_cache_entry *p; |
86 | size_t size = offsetof(struct ovl_cache_entry, name[len + 1]); | 87 | size_t size = offsetof(struct ovl_cache_entry, name[len + 1]); |
87 | 88 | ||
88 | p = kmalloc(size, GFP_KERNEL); | 89 | p = kmalloc(size, GFP_KERNEL); |
89 | if (p) { | 90 | if (!p) |
90 | memcpy(p->name, name, len); | 91 | return NULL; |
91 | p->name[len] = '\0'; | 92 | |
92 | p->len = len; | 93 | memcpy(p->name, name, len); |
93 | p->type = d_type; | 94 | p->name[len] = '\0'; |
94 | p->ino = ino; | 95 | p->len = len; |
95 | p->is_whiteout = false; | 96 | p->type = d_type; |
96 | p->is_cursor = false; | 97 | p->ino = ino; |
97 | } | 98 | p->is_whiteout = false; |
99 | |||
100 | if (d_type == DT_CHR) { | ||
101 | struct dentry *dentry; | ||
102 | const struct cred *old_cred; | ||
103 | struct cred *override_cred; | ||
104 | |||
105 | override_cred = prepare_creds(); | ||
106 | if (!override_cred) { | ||
107 | kfree(p); | ||
108 | return NULL; | ||
109 | } | ||
110 | |||
111 | /* | ||
112 | * CAP_DAC_OVERRIDE for lookup | ||
113 | */ | ||
114 | cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); | ||
115 | old_cred = override_creds(override_cred); | ||
98 | 116 | ||
117 | dentry = lookup_one_len(name, dir, len); | ||
118 | if (!IS_ERR(dentry)) { | ||
119 | p->is_whiteout = ovl_is_whiteout(dentry); | ||
120 | dput(dentry); | ||
121 | } | ||
122 | revert_creds(old_cred); | ||
123 | put_cred(override_cred); | ||
124 | } | ||
99 | return p; | 125 | return p; |
100 | } | 126 | } |
101 | 127 | ||
@@ -122,7 +148,7 @@ static int ovl_cache_entry_add_rb(struct ovl_readdir_data *rdd, | |||
122 | return 0; | 148 | return 0; |
123 | } | 149 | } |
124 | 150 | ||
125 | p = ovl_cache_entry_new(name, len, ino, d_type); | 151 | p = ovl_cache_entry_new(rdd->dir, name, len, ino, d_type); |
126 | if (p == NULL) | 152 | if (p == NULL) |
127 | return -ENOMEM; | 153 | return -ENOMEM; |
128 | 154 | ||
@@ -143,7 +169,7 @@ static int ovl_fill_lower(struct ovl_readdir_data *rdd, | |||
143 | if (p) { | 169 | if (p) { |
144 | list_move_tail(&p->l_node, &rdd->middle); | 170 | list_move_tail(&p->l_node, &rdd->middle); |
145 | } else { | 171 | } else { |
146 | p = ovl_cache_entry_new(name, namelen, ino, d_type); | 172 | p = ovl_cache_entry_new(rdd->dir, name, namelen, ino, d_type); |
147 | if (p == NULL) | 173 | if (p == NULL) |
148 | rdd->err = -ENOMEM; | 174 | rdd->err = -ENOMEM; |
149 | else | 175 | else |
@@ -168,7 +194,6 @@ static void ovl_cache_put(struct ovl_dir_file *od, struct dentry *dentry) | |||
168 | { | 194 | { |
169 | struct ovl_dir_cache *cache = od->cache; | 195 | struct ovl_dir_cache *cache = od->cache; |
170 | 196 | ||
171 | list_del_init(&od->cursor.l_node); | ||
172 | WARN_ON(cache->refcount <= 0); | 197 | WARN_ON(cache->refcount <= 0); |
173 | cache->refcount--; | 198 | cache->refcount--; |
174 | if (!cache->refcount) { | 199 | if (!cache->refcount) { |
@@ -204,6 +229,7 @@ static inline int ovl_dir_read(struct path *realpath, | |||
204 | if (IS_ERR(realfile)) | 229 | if (IS_ERR(realfile)) |
205 | return PTR_ERR(realfile); | 230 | return PTR_ERR(realfile); |
206 | 231 | ||
232 | rdd->dir = realpath->dentry; | ||
207 | rdd->ctx.pos = 0; | 233 | rdd->ctx.pos = 0; |
208 | do { | 234 | do { |
209 | rdd->count = 0; | 235 | rdd->count = 0; |
@@ -227,108 +253,58 @@ static void ovl_dir_reset(struct file *file) | |||
227 | if (cache && ovl_dentry_version_get(dentry) != cache->version) { | 253 | if (cache && ovl_dentry_version_get(dentry) != cache->version) { |
228 | ovl_cache_put(od, dentry); | 254 | ovl_cache_put(od, dentry); |
229 | od->cache = NULL; | 255 | od->cache = NULL; |
256 | od->cursor = NULL; | ||
230 | } | 257 | } |
231 | WARN_ON(!od->is_real && type != OVL_PATH_MERGE); | 258 | WARN_ON(!od->is_real && !OVL_TYPE_MERGE(type)); |
232 | if (od->is_real && type == OVL_PATH_MERGE) | 259 | if (od->is_real && OVL_TYPE_MERGE(type)) |
233 | od->is_real = false; | 260 | od->is_real = false; |
234 | } | 261 | } |
235 | 262 | ||
236 | static int ovl_dir_mark_whiteouts(struct dentry *dir, | ||
237 | struct ovl_readdir_data *rdd) | ||
238 | { | ||
239 | struct ovl_cache_entry *p; | ||
240 | struct dentry *dentry; | ||
241 | const struct cred *old_cred; | ||
242 | struct cred *override_cred; | ||
243 | |||
244 | override_cred = prepare_creds(); | ||
245 | if (!override_cred) { | ||
246 | ovl_cache_free(rdd->list); | ||
247 | return -ENOMEM; | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * CAP_DAC_OVERRIDE for lookup | ||
252 | */ | ||
253 | cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); | ||
254 | old_cred = override_creds(override_cred); | ||
255 | |||
256 | mutex_lock(&dir->d_inode->i_mutex); | ||
257 | list_for_each_entry(p, rdd->list, l_node) { | ||
258 | if (p->is_cursor) | ||
259 | continue; | ||
260 | |||
261 | if (p->type != DT_CHR) | ||
262 | continue; | ||
263 | |||
264 | dentry = lookup_one_len(p->name, dir, p->len); | ||
265 | if (IS_ERR(dentry)) | ||
266 | continue; | ||
267 | |||
268 | p->is_whiteout = ovl_is_whiteout(dentry); | ||
269 | dput(dentry); | ||
270 | } | ||
271 | mutex_unlock(&dir->d_inode->i_mutex); | ||
272 | |||
273 | revert_creds(old_cred); | ||
274 | put_cred(override_cred); | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list) | 263 | static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list) |
280 | { | 264 | { |
281 | int err; | 265 | int err; |
282 | struct path lowerpath; | 266 | struct path realpath; |
283 | struct path upperpath; | ||
284 | struct ovl_readdir_data rdd = { | 267 | struct ovl_readdir_data rdd = { |
285 | .ctx.actor = ovl_fill_merge, | 268 | .ctx.actor = ovl_fill_merge, |
286 | .list = list, | 269 | .list = list, |
287 | .root = RB_ROOT, | 270 | .root = RB_ROOT, |
288 | .is_merge = false, | 271 | .is_merge = false, |
289 | }; | 272 | }; |
273 | int idx, next; | ||
290 | 274 | ||
291 | ovl_path_lower(dentry, &lowerpath); | 275 | for (idx = 0; idx != -1; idx = next) { |
292 | ovl_path_upper(dentry, &upperpath); | 276 | next = ovl_path_next(idx, dentry, &realpath); |
293 | 277 | ||
294 | if (upperpath.dentry) { | 278 | if (next != -1) { |
295 | err = ovl_dir_read(&upperpath, &rdd); | 279 | err = ovl_dir_read(&realpath, &rdd); |
296 | if (err) | ||
297 | goto out; | ||
298 | |||
299 | if (lowerpath.dentry) { | ||
300 | err = ovl_dir_mark_whiteouts(upperpath.dentry, &rdd); | ||
301 | if (err) | 280 | if (err) |
302 | goto out; | 281 | break; |
282 | } else { | ||
283 | /* | ||
284 | * Insert lowest layer entries before upper ones, this | ||
285 | * allows offsets to be reasonably constant | ||
286 | */ | ||
287 | list_add(&rdd.middle, rdd.list); | ||
288 | rdd.is_merge = true; | ||
289 | err = ovl_dir_read(&realpath, &rdd); | ||
290 | list_del(&rdd.middle); | ||
303 | } | 291 | } |
304 | } | 292 | } |
305 | if (lowerpath.dentry) { | ||
306 | /* | ||
307 | * Insert lowerpath entries before upperpath ones, this allows | ||
308 | * offsets to be reasonably constant | ||
309 | */ | ||
310 | list_add(&rdd.middle, rdd.list); | ||
311 | rdd.is_merge = true; | ||
312 | err = ovl_dir_read(&lowerpath, &rdd); | ||
313 | list_del(&rdd.middle); | ||
314 | } | ||
315 | out: | ||
316 | return err; | 293 | return err; |
317 | } | 294 | } |
318 | 295 | ||
319 | static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos) | 296 | static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos) |
320 | { | 297 | { |
321 | struct ovl_cache_entry *p; | 298 | struct list_head *p; |
322 | loff_t off = 0; | 299 | loff_t off = 0; |
323 | 300 | ||
324 | list_for_each_entry(p, &od->cache->entries, l_node) { | 301 | list_for_each(p, &od->cache->entries) { |
325 | if (p->is_cursor) | ||
326 | continue; | ||
327 | if (off >= pos) | 302 | if (off >= pos) |
328 | break; | 303 | break; |
329 | off++; | 304 | off++; |
330 | } | 305 | } |
331 | list_move_tail(&od->cursor.l_node, &p->l_node); | 306 | /* Cursor is safe since the cache is stable */ |
307 | od->cursor = p; | ||
332 | } | 308 | } |
333 | 309 | ||
334 | static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) | 310 | static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry) |
@@ -367,6 +343,7 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx) | |||
367 | { | 343 | { |
368 | struct ovl_dir_file *od = file->private_data; | 344 | struct ovl_dir_file *od = file->private_data; |
369 | struct dentry *dentry = file->f_path.dentry; | 345 | struct dentry *dentry = file->f_path.dentry; |
346 | struct ovl_cache_entry *p; | ||
370 | 347 | ||
371 | if (!ctx->pos) | 348 | if (!ctx->pos) |
372 | ovl_dir_reset(file); | 349 | ovl_dir_reset(file); |
@@ -385,19 +362,13 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx) | |||
385 | ovl_seek_cursor(od, ctx->pos); | 362 | ovl_seek_cursor(od, ctx->pos); |
386 | } | 363 | } |
387 | 364 | ||
388 | while (od->cursor.l_node.next != &od->cache->entries) { | 365 | while (od->cursor != &od->cache->entries) { |
389 | struct ovl_cache_entry *p; | 366 | p = list_entry(od->cursor, struct ovl_cache_entry, l_node); |
390 | 367 | if (!p->is_whiteout) | |
391 | p = list_entry(od->cursor.l_node.next, struct ovl_cache_entry, l_node); | 368 | if (!dir_emit(ctx, p->name, p->len, p->ino, p->type)) |
392 | /* Skip cursors */ | 369 | break; |
393 | if (!p->is_cursor) { | 370 | od->cursor = p->l_node.next; |
394 | if (!p->is_whiteout) { | 371 | ctx->pos++; |
395 | if (!dir_emit(ctx, p->name, p->len, p->ino, p->type)) | ||
396 | break; | ||
397 | } | ||
398 | ctx->pos++; | ||
399 | } | ||
400 | list_move(&od->cursor.l_node, &p->l_node); | ||
401 | } | 372 | } |
402 | return 0; | 373 | return 0; |
403 | } | 374 | } |
@@ -452,7 +423,7 @@ static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end, | |||
452 | /* | 423 | /* |
453 | * Need to check if we started out being a lower dir, but got copied up | 424 | * Need to check if we started out being a lower dir, but got copied up |
454 | */ | 425 | */ |
455 | if (!od->is_upper && ovl_path_type(dentry) != OVL_PATH_LOWER) { | 426 | if (!od->is_upper && OVL_TYPE_UPPER(ovl_path_type(dentry))) { |
456 | struct inode *inode = file_inode(file); | 427 | struct inode *inode = file_inode(file); |
457 | 428 | ||
458 | realfile = lockless_dereference(od->upperfile); | 429 | realfile = lockless_dereference(od->upperfile); |
@@ -516,11 +487,9 @@ static int ovl_dir_open(struct inode *inode, struct file *file) | |||
516 | kfree(od); | 487 | kfree(od); |
517 | return PTR_ERR(realfile); | 488 | return PTR_ERR(realfile); |
518 | } | 489 | } |
519 | INIT_LIST_HEAD(&od->cursor.l_node); | ||
520 | od->realfile = realfile; | 490 | od->realfile = realfile; |
521 | od->is_real = (type != OVL_PATH_MERGE); | 491 | od->is_real = !OVL_TYPE_MERGE(type); |
522 | od->is_upper = (type != OVL_PATH_LOWER); | 492 | od->is_upper = OVL_TYPE_UPPER(type); |
523 | od->cursor.is_cursor = true; | ||
524 | file->private_data = od; | 493 | file->private_data = od; |
525 | 494 | ||
526 | return 0; | 495 | return 0; |
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index f16d318b71f8..b90952f528b1 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
@@ -35,7 +35,8 @@ struct ovl_config { | |||
35 | /* private information held for overlayfs's superblock */ | 35 | /* private information held for overlayfs's superblock */ |
36 | struct ovl_fs { | 36 | struct ovl_fs { |
37 | struct vfsmount *upper_mnt; | 37 | struct vfsmount *upper_mnt; |
38 | struct vfsmount *lower_mnt; | 38 | unsigned numlower; |
39 | struct vfsmount **lower_mnt; | ||
39 | struct dentry *workdir; | 40 | struct dentry *workdir; |
40 | long lower_namelen; | 41 | long lower_namelen; |
41 | /* pathnames of lower and upper dirs, for show_options */ | 42 | /* pathnames of lower and upper dirs, for show_options */ |
@@ -47,7 +48,6 @@ struct ovl_dir_cache; | |||
47 | /* private information held for every overlayfs dentry */ | 48 | /* private information held for every overlayfs dentry */ |
48 | struct ovl_entry { | 49 | struct ovl_entry { |
49 | struct dentry *__upperdentry; | 50 | struct dentry *__upperdentry; |
50 | struct dentry *lowerdentry; | ||
51 | struct ovl_dir_cache *cache; | 51 | struct ovl_dir_cache *cache; |
52 | union { | 52 | union { |
53 | struct { | 53 | struct { |
@@ -56,30 +56,36 @@ struct ovl_entry { | |||
56 | }; | 56 | }; |
57 | struct rcu_head rcu; | 57 | struct rcu_head rcu; |
58 | }; | 58 | }; |
59 | unsigned numlower; | ||
60 | struct path lowerstack[]; | ||
59 | }; | 61 | }; |
60 | 62 | ||
61 | const char *ovl_opaque_xattr = "trusted.overlay.opaque"; | 63 | #define OVL_MAX_STACK 500 |
62 | 64 | ||
65 | static struct dentry *__ovl_dentry_lower(struct ovl_entry *oe) | ||
66 | { | ||
67 | return oe->numlower ? oe->lowerstack[0].dentry : NULL; | ||
68 | } | ||
63 | 69 | ||
64 | enum ovl_path_type ovl_path_type(struct dentry *dentry) | 70 | enum ovl_path_type ovl_path_type(struct dentry *dentry) |
65 | { | 71 | { |
66 | struct ovl_entry *oe = dentry->d_fsdata; | 72 | struct ovl_entry *oe = dentry->d_fsdata; |
73 | enum ovl_path_type type = 0; | ||
67 | 74 | ||
68 | if (oe->__upperdentry) { | 75 | if (oe->__upperdentry) { |
69 | if (oe->lowerdentry) { | 76 | type = __OVL_PATH_UPPER; |
77 | |||
78 | if (oe->numlower) { | ||
70 | if (S_ISDIR(dentry->d_inode->i_mode)) | 79 | if (S_ISDIR(dentry->d_inode->i_mode)) |
71 | return OVL_PATH_MERGE; | 80 | type |= __OVL_PATH_MERGE; |
72 | else | 81 | } else if (!oe->opaque) { |
73 | return OVL_PATH_UPPER; | 82 | type |= __OVL_PATH_PURE; |
74 | } else { | ||
75 | if (oe->opaque) | ||
76 | return OVL_PATH_UPPER; | ||
77 | else | ||
78 | return OVL_PATH_PURE_UPPER; | ||
79 | } | 83 | } |
80 | } else { | 84 | } else { |
81 | return OVL_PATH_LOWER; | 85 | if (oe->numlower > 1) |
86 | type |= __OVL_PATH_MERGE; | ||
82 | } | 87 | } |
88 | return type; | ||
83 | } | 89 | } |
84 | 90 | ||
85 | static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe) | 91 | static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe) |
@@ -98,10 +104,9 @@ void ovl_path_upper(struct dentry *dentry, struct path *path) | |||
98 | 104 | ||
99 | enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path) | 105 | enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path) |
100 | { | 106 | { |
101 | |||
102 | enum ovl_path_type type = ovl_path_type(dentry); | 107 | enum ovl_path_type type = ovl_path_type(dentry); |
103 | 108 | ||
104 | if (type == OVL_PATH_LOWER) | 109 | if (!OVL_TYPE_UPPER(type)) |
105 | ovl_path_lower(dentry, path); | 110 | ovl_path_lower(dentry, path); |
106 | else | 111 | else |
107 | ovl_path_upper(dentry, path); | 112 | ovl_path_upper(dentry, path); |
@@ -120,7 +125,7 @@ struct dentry *ovl_dentry_lower(struct dentry *dentry) | |||
120 | { | 125 | { |
121 | struct ovl_entry *oe = dentry->d_fsdata; | 126 | struct ovl_entry *oe = dentry->d_fsdata; |
122 | 127 | ||
123 | return oe->lowerdentry; | 128 | return __ovl_dentry_lower(oe); |
124 | } | 129 | } |
125 | 130 | ||
126 | struct dentry *ovl_dentry_real(struct dentry *dentry) | 131 | struct dentry *ovl_dentry_real(struct dentry *dentry) |
@@ -130,7 +135,7 @@ struct dentry *ovl_dentry_real(struct dentry *dentry) | |||
130 | 135 | ||
131 | realdentry = ovl_upperdentry_dereference(oe); | 136 | realdentry = ovl_upperdentry_dereference(oe); |
132 | if (!realdentry) | 137 | if (!realdentry) |
133 | realdentry = oe->lowerdentry; | 138 | realdentry = __ovl_dentry_lower(oe); |
134 | 139 | ||
135 | return realdentry; | 140 | return realdentry; |
136 | } | 141 | } |
@@ -143,7 +148,7 @@ struct dentry *ovl_entry_real(struct ovl_entry *oe, bool *is_upper) | |||
143 | if (realdentry) { | 148 | if (realdentry) { |
144 | *is_upper = true; | 149 | *is_upper = true; |
145 | } else { | 150 | } else { |
146 | realdentry = oe->lowerdentry; | 151 | realdentry = __ovl_dentry_lower(oe); |
147 | *is_upper = false; | 152 | *is_upper = false; |
148 | } | 153 | } |
149 | return realdentry; | 154 | return realdentry; |
@@ -165,11 +170,9 @@ void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache) | |||
165 | 170 | ||
166 | void ovl_path_lower(struct dentry *dentry, struct path *path) | 171 | void ovl_path_lower(struct dentry *dentry, struct path *path) |
167 | { | 172 | { |
168 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; | ||
169 | struct ovl_entry *oe = dentry->d_fsdata; | 173 | struct ovl_entry *oe = dentry->d_fsdata; |
170 | 174 | ||
171 | path->mnt = ofs->lower_mnt; | 175 | *path = oe->numlower ? oe->lowerstack[0] : (struct path) { NULL, NULL }; |
172 | path->dentry = oe->lowerdentry; | ||
173 | } | 176 | } |
174 | 177 | ||
175 | int ovl_want_write(struct dentry *dentry) | 178 | int ovl_want_write(struct dentry *dentry) |
@@ -249,7 +252,7 @@ static bool ovl_is_opaquedir(struct dentry *dentry) | |||
249 | if (!S_ISDIR(inode->i_mode) || !inode->i_op->getxattr) | 252 | if (!S_ISDIR(inode->i_mode) || !inode->i_op->getxattr) |
250 | return false; | 253 | return false; |
251 | 254 | ||
252 | res = inode->i_op->getxattr(dentry, ovl_opaque_xattr, &val, 1); | 255 | res = inode->i_op->getxattr(dentry, OVL_XATTR_OPAQUE, &val, 1); |
253 | if (res == 1 && val == 'y') | 256 | if (res == 1 && val == 'y') |
254 | return true; | 257 | return true; |
255 | 258 | ||
@@ -261,8 +264,11 @@ static void ovl_dentry_release(struct dentry *dentry) | |||
261 | struct ovl_entry *oe = dentry->d_fsdata; | 264 | struct ovl_entry *oe = dentry->d_fsdata; |
262 | 265 | ||
263 | if (oe) { | 266 | if (oe) { |
267 | unsigned int i; | ||
268 | |||
264 | dput(oe->__upperdentry); | 269 | dput(oe->__upperdentry); |
265 | dput(oe->lowerdentry); | 270 | for (i = 0; i < oe->numlower; i++) |
271 | dput(oe->lowerstack[i].dentry); | ||
266 | kfree_rcu(oe, rcu); | 272 | kfree_rcu(oe, rcu); |
267 | } | 273 | } |
268 | } | 274 | } |
@@ -271,9 +277,15 @@ static const struct dentry_operations ovl_dentry_operations = { | |||
271 | .d_release = ovl_dentry_release, | 277 | .d_release = ovl_dentry_release, |
272 | }; | 278 | }; |
273 | 279 | ||
274 | static struct ovl_entry *ovl_alloc_entry(void) | 280 | static struct ovl_entry *ovl_alloc_entry(unsigned int numlower) |
275 | { | 281 | { |
276 | return kzalloc(sizeof(struct ovl_entry), GFP_KERNEL); | 282 | size_t size = offsetof(struct ovl_entry, lowerstack[numlower]); |
283 | struct ovl_entry *oe = kzalloc(size, GFP_KERNEL); | ||
284 | |||
285 | if (oe) | ||
286 | oe->numlower = numlower; | ||
287 | |||
288 | return oe; | ||
277 | } | 289 | } |
278 | 290 | ||
279 | static inline struct dentry *ovl_lookup_real(struct dentry *dir, | 291 | static inline struct dentry *ovl_lookup_real(struct dentry *dir, |
@@ -295,82 +307,154 @@ static inline struct dentry *ovl_lookup_real(struct dentry *dir, | |||
295 | return dentry; | 307 | return dentry; |
296 | } | 308 | } |
297 | 309 | ||
310 | /* | ||
311 | * Returns next layer in stack starting from top. | ||
312 | * Returns -1 if this is the last layer. | ||
313 | */ | ||
314 | int ovl_path_next(int idx, struct dentry *dentry, struct path *path) | ||
315 | { | ||
316 | struct ovl_entry *oe = dentry->d_fsdata; | ||
317 | |||
318 | BUG_ON(idx < 0); | ||
319 | if (idx == 0) { | ||
320 | ovl_path_upper(dentry, path); | ||
321 | if (path->dentry) | ||
322 | return oe->numlower ? 1 : -1; | ||
323 | idx++; | ||
324 | } | ||
325 | BUG_ON(idx > oe->numlower); | ||
326 | *path = oe->lowerstack[idx - 1]; | ||
327 | |||
328 | return (idx < oe->numlower) ? idx + 1 : -1; | ||
329 | } | ||
330 | |||
298 | struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, | 331 | struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, |
299 | unsigned int flags) | 332 | unsigned int flags) |
300 | { | 333 | { |
301 | struct ovl_entry *oe; | 334 | struct ovl_entry *oe; |
302 | struct dentry *upperdir; | 335 | struct ovl_entry *poe = dentry->d_parent->d_fsdata; |
303 | struct dentry *lowerdir; | 336 | struct path *stack = NULL; |
304 | struct dentry *upperdentry = NULL; | 337 | struct dentry *upperdir, *upperdentry = NULL; |
305 | struct dentry *lowerdentry = NULL; | 338 | unsigned int ctr = 0; |
306 | struct inode *inode = NULL; | 339 | struct inode *inode = NULL; |
340 | bool upperopaque = false; | ||
341 | struct dentry *this, *prev = NULL; | ||
342 | unsigned int i; | ||
307 | int err; | 343 | int err; |
308 | 344 | ||
309 | err = -ENOMEM; | 345 | upperdir = ovl_upperdentry_dereference(poe); |
310 | oe = ovl_alloc_entry(); | ||
311 | if (!oe) | ||
312 | goto out; | ||
313 | |||
314 | upperdir = ovl_dentry_upper(dentry->d_parent); | ||
315 | lowerdir = ovl_dentry_lower(dentry->d_parent); | ||
316 | |||
317 | if (upperdir) { | 346 | if (upperdir) { |
318 | upperdentry = ovl_lookup_real(upperdir, &dentry->d_name); | 347 | this = ovl_lookup_real(upperdir, &dentry->d_name); |
319 | err = PTR_ERR(upperdentry); | 348 | err = PTR_ERR(this); |
320 | if (IS_ERR(upperdentry)) | 349 | if (IS_ERR(this)) |
321 | goto out_put_dir; | 350 | goto out; |
322 | 351 | ||
323 | if (lowerdir && upperdentry) { | 352 | if (this) { |
324 | if (ovl_is_whiteout(upperdentry)) { | 353 | if (ovl_is_whiteout(this)) { |
325 | dput(upperdentry); | 354 | dput(this); |
326 | upperdentry = NULL; | 355 | this = NULL; |
327 | oe->opaque = true; | 356 | upperopaque = true; |
328 | } else if (ovl_is_opaquedir(upperdentry)) { | 357 | } else if (poe->numlower && ovl_is_opaquedir(this)) { |
329 | oe->opaque = true; | 358 | upperopaque = true; |
330 | } | 359 | } |
331 | } | 360 | } |
361 | upperdentry = prev = this; | ||
332 | } | 362 | } |
333 | if (lowerdir && !oe->opaque) { | 363 | |
334 | lowerdentry = ovl_lookup_real(lowerdir, &dentry->d_name); | 364 | if (!upperopaque && poe->numlower) { |
335 | err = PTR_ERR(lowerdentry); | 365 | err = -ENOMEM; |
336 | if (IS_ERR(lowerdentry)) | 366 | stack = kcalloc(poe->numlower, sizeof(struct path), GFP_KERNEL); |
337 | goto out_dput_upper; | 367 | if (!stack) |
368 | goto out_put_upper; | ||
338 | } | 369 | } |
339 | 370 | ||
340 | if (lowerdentry && upperdentry && | 371 | for (i = 0; !upperopaque && i < poe->numlower; i++) { |
341 | (!S_ISDIR(upperdentry->d_inode->i_mode) || | 372 | bool opaque = false; |
342 | !S_ISDIR(lowerdentry->d_inode->i_mode))) { | 373 | struct path lowerpath = poe->lowerstack[i]; |
343 | dput(lowerdentry); | 374 | |
344 | lowerdentry = NULL; | 375 | this = ovl_lookup_real(lowerpath.dentry, &dentry->d_name); |
345 | oe->opaque = true; | 376 | err = PTR_ERR(this); |
377 | if (IS_ERR(this)) { | ||
378 | /* | ||
379 | * If it's positive, then treat ENAMETOOLONG as ENOENT. | ||
380 | */ | ||
381 | if (err == -ENAMETOOLONG && (upperdentry || ctr)) | ||
382 | continue; | ||
383 | goto out_put; | ||
384 | } | ||
385 | if (!this) | ||
386 | continue; | ||
387 | if (ovl_is_whiteout(this)) { | ||
388 | dput(this); | ||
389 | break; | ||
390 | } | ||
391 | /* | ||
392 | * Only makes sense to check opaque dir if this is not the | ||
393 | * lowermost layer. | ||
394 | */ | ||
395 | if (i < poe->numlower - 1 && ovl_is_opaquedir(this)) | ||
396 | opaque = true; | ||
397 | |||
398 | if (prev && (!S_ISDIR(prev->d_inode->i_mode) || | ||
399 | !S_ISDIR(this->d_inode->i_mode))) { | ||
400 | /* | ||
401 | * FIXME: check for upper-opaqueness maybe better done | ||
402 | * in remove code. | ||
403 | */ | ||
404 | if (prev == upperdentry) | ||
405 | upperopaque = true; | ||
406 | dput(this); | ||
407 | break; | ||
408 | } | ||
409 | /* | ||
410 | * If this is a non-directory then stop here. | ||
411 | */ | ||
412 | if (!S_ISDIR(this->d_inode->i_mode)) | ||
413 | opaque = true; | ||
414 | |||
415 | stack[ctr].dentry = this; | ||
416 | stack[ctr].mnt = lowerpath.mnt; | ||
417 | ctr++; | ||
418 | prev = this; | ||
419 | if (opaque) | ||
420 | break; | ||
346 | } | 421 | } |
347 | 422 | ||
348 | if (lowerdentry || upperdentry) { | 423 | oe = ovl_alloc_entry(ctr); |
424 | err = -ENOMEM; | ||
425 | if (!oe) | ||
426 | goto out_put; | ||
427 | |||
428 | if (upperdentry || ctr) { | ||
349 | struct dentry *realdentry; | 429 | struct dentry *realdentry; |
350 | 430 | ||
351 | realdentry = upperdentry ? upperdentry : lowerdentry; | 431 | realdentry = upperdentry ? upperdentry : stack[0].dentry; |
432 | |||
352 | err = -ENOMEM; | 433 | err = -ENOMEM; |
353 | inode = ovl_new_inode(dentry->d_sb, realdentry->d_inode->i_mode, | 434 | inode = ovl_new_inode(dentry->d_sb, realdentry->d_inode->i_mode, |
354 | oe); | 435 | oe); |
355 | if (!inode) | 436 | if (!inode) |
356 | goto out_dput; | 437 | goto out_free_oe; |
357 | ovl_copyattr(realdentry->d_inode, inode); | 438 | ovl_copyattr(realdentry->d_inode, inode); |
358 | } | 439 | } |
359 | 440 | ||
441 | oe->opaque = upperopaque; | ||
360 | oe->__upperdentry = upperdentry; | 442 | oe->__upperdentry = upperdentry; |
361 | oe->lowerdentry = lowerdentry; | 443 | memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr); |
362 | 444 | kfree(stack); | |
363 | dentry->d_fsdata = oe; | 445 | dentry->d_fsdata = oe; |
364 | d_add(dentry, inode); | 446 | d_add(dentry, inode); |
365 | 447 | ||
366 | return NULL; | 448 | return NULL; |
367 | 449 | ||
368 | out_dput: | 450 | out_free_oe: |
369 | dput(lowerdentry); | ||
370 | out_dput_upper: | ||
371 | dput(upperdentry); | ||
372 | out_put_dir: | ||
373 | kfree(oe); | 451 | kfree(oe); |
452 | out_put: | ||
453 | for (i = 0; i < ctr; i++) | ||
454 | dput(stack[i].dentry); | ||
455 | kfree(stack); | ||
456 | out_put_upper: | ||
457 | dput(upperdentry); | ||
374 | out: | 458 | out: |
375 | return ERR_PTR(err); | 459 | return ERR_PTR(err); |
376 | } | 460 | } |
@@ -383,10 +467,12 @@ struct file *ovl_path_open(struct path *path, int flags) | |||
383 | static void ovl_put_super(struct super_block *sb) | 467 | static void ovl_put_super(struct super_block *sb) |
384 | { | 468 | { |
385 | struct ovl_fs *ufs = sb->s_fs_info; | 469 | struct ovl_fs *ufs = sb->s_fs_info; |
470 | unsigned i; | ||
386 | 471 | ||
387 | dput(ufs->workdir); | 472 | dput(ufs->workdir); |
388 | mntput(ufs->upper_mnt); | 473 | mntput(ufs->upper_mnt); |
389 | mntput(ufs->lower_mnt); | 474 | for (i = 0; i < ufs->numlower; i++) |
475 | mntput(ufs->lower_mnt[i]); | ||
390 | 476 | ||
391 | kfree(ufs->config.lowerdir); | 477 | kfree(ufs->config.lowerdir); |
392 | kfree(ufs->config.upperdir); | 478 | kfree(ufs->config.upperdir); |
@@ -400,7 +486,7 @@ static void ovl_put_super(struct super_block *sb) | |||
400 | * @buf: The struct kstatfs to fill in with stats | 486 | * @buf: The struct kstatfs to fill in with stats |
401 | * | 487 | * |
402 | * Get the filesystem statistics. As writes always target the upper layer | 488 | * Get the filesystem statistics. As writes always target the upper layer |
403 | * filesystem pass the statfs to the same filesystem. | 489 | * filesystem pass the statfs to the upper filesystem (if it exists) |
404 | */ | 490 | */ |
405 | static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf) | 491 | static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf) |
406 | { | 492 | { |
@@ -409,7 +495,7 @@ static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
409 | struct path path; | 495 | struct path path; |
410 | int err; | 496 | int err; |
411 | 497 | ||
412 | ovl_path_upper(root_dentry, &path); | 498 | ovl_path_real(root_dentry, &path); |
413 | 499 | ||
414 | err = vfs_statfs(&path, buf); | 500 | err = vfs_statfs(&path, buf); |
415 | if (!err) { | 501 | if (!err) { |
@@ -432,8 +518,21 @@ static int ovl_show_options(struct seq_file *m, struct dentry *dentry) | |||
432 | struct ovl_fs *ufs = sb->s_fs_info; | 518 | struct ovl_fs *ufs = sb->s_fs_info; |
433 | 519 | ||
434 | seq_printf(m, ",lowerdir=%s", ufs->config.lowerdir); | 520 | seq_printf(m, ",lowerdir=%s", ufs->config.lowerdir); |
435 | seq_printf(m, ",upperdir=%s", ufs->config.upperdir); | 521 | if (ufs->config.upperdir) { |
436 | seq_printf(m, ",workdir=%s", ufs->config.workdir); | 522 | seq_printf(m, ",upperdir=%s", ufs->config.upperdir); |
523 | seq_printf(m, ",workdir=%s", ufs->config.workdir); | ||
524 | } | ||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | static int ovl_remount(struct super_block *sb, int *flags, char *data) | ||
529 | { | ||
530 | struct ovl_fs *ufs = sb->s_fs_info; | ||
531 | |||
532 | if (!(*flags & MS_RDONLY) && | ||
533 | (!ufs->upper_mnt || (ufs->upper_mnt->mnt_sb->s_flags & MS_RDONLY))) | ||
534 | return -EROFS; | ||
535 | |||
437 | return 0; | 536 | return 0; |
438 | } | 537 | } |
439 | 538 | ||
@@ -441,6 +540,7 @@ static const struct super_operations ovl_super_operations = { | |||
441 | .put_super = ovl_put_super, | 540 | .put_super = ovl_put_super, |
442 | .statfs = ovl_statfs, | 541 | .statfs = ovl_statfs, |
443 | .show_options = ovl_show_options, | 542 | .show_options = ovl_show_options, |
543 | .remount_fs = ovl_remount, | ||
444 | }; | 544 | }; |
445 | 545 | ||
446 | enum { | 546 | enum { |
@@ -585,24 +685,6 @@ static void ovl_unescape(char *s) | |||
585 | } | 685 | } |
586 | } | 686 | } |
587 | 687 | ||
588 | static int ovl_mount_dir(const char *name, struct path *path) | ||
589 | { | ||
590 | int err; | ||
591 | char *tmp = kstrdup(name, GFP_KERNEL); | ||
592 | |||
593 | if (!tmp) | ||
594 | return -ENOMEM; | ||
595 | |||
596 | ovl_unescape(tmp); | ||
597 | err = kern_path(tmp, LOOKUP_FOLLOW, path); | ||
598 | if (err) { | ||
599 | pr_err("overlayfs: failed to resolve '%s': %i\n", tmp, err); | ||
600 | err = -EINVAL; | ||
601 | } | ||
602 | kfree(tmp); | ||
603 | return err; | ||
604 | } | ||
605 | |||
606 | static bool ovl_is_allowed_fs_type(struct dentry *root) | 688 | static bool ovl_is_allowed_fs_type(struct dentry *root) |
607 | { | 689 | { |
608 | const struct dentry_operations *dop = root->d_op; | 690 | const struct dentry_operations *dop = root->d_op; |
@@ -622,6 +704,75 @@ static bool ovl_is_allowed_fs_type(struct dentry *root) | |||
622 | return true; | 704 | return true; |
623 | } | 705 | } |
624 | 706 | ||
707 | static int ovl_mount_dir_noesc(const char *name, struct path *path) | ||
708 | { | ||
709 | int err = -EINVAL; | ||
710 | |||
711 | if (!*name) { | ||
712 | pr_err("overlayfs: empty lowerdir\n"); | ||
713 | goto out; | ||
714 | } | ||
715 | err = kern_path(name, LOOKUP_FOLLOW, path); | ||
716 | if (err) { | ||
717 | pr_err("overlayfs: failed to resolve '%s': %i\n", name, err); | ||
718 | goto out; | ||
719 | } | ||
720 | err = -EINVAL; | ||
721 | if (!ovl_is_allowed_fs_type(path->dentry)) { | ||
722 | pr_err("overlayfs: filesystem on '%s' not supported\n", name); | ||
723 | goto out_put; | ||
724 | } | ||
725 | if (!S_ISDIR(path->dentry->d_inode->i_mode)) { | ||
726 | pr_err("overlayfs: '%s' not a directory\n", name); | ||
727 | goto out_put; | ||
728 | } | ||
729 | return 0; | ||
730 | |||
731 | out_put: | ||
732 | path_put(path); | ||
733 | out: | ||
734 | return err; | ||
735 | } | ||
736 | |||
737 | static int ovl_mount_dir(const char *name, struct path *path) | ||
738 | { | ||
739 | int err = -ENOMEM; | ||
740 | char *tmp = kstrdup(name, GFP_KERNEL); | ||
741 | |||
742 | if (tmp) { | ||
743 | ovl_unescape(tmp); | ||
744 | err = ovl_mount_dir_noesc(tmp, path); | ||
745 | kfree(tmp); | ||
746 | } | ||
747 | return err; | ||
748 | } | ||
749 | |||
750 | static int ovl_lower_dir(const char *name, struct path *path, long *namelen, | ||
751 | int *stack_depth) | ||
752 | { | ||
753 | int err; | ||
754 | struct kstatfs statfs; | ||
755 | |||
756 | err = ovl_mount_dir_noesc(name, path); | ||
757 | if (err) | ||
758 | goto out; | ||
759 | |||
760 | err = vfs_statfs(path, &statfs); | ||
761 | if (err) { | ||
762 | pr_err("overlayfs: statfs failed on '%s'\n", name); | ||
763 | goto out_put; | ||
764 | } | ||
765 | *namelen = max(*namelen, statfs.f_namelen); | ||
766 | *stack_depth = max(*stack_depth, path->mnt->mnt_sb->s_stack_depth); | ||
767 | |||
768 | return 0; | ||
769 | |||
770 | out_put: | ||
771 | path_put(path); | ||
772 | out: | ||
773 | return err; | ||
774 | } | ||
775 | |||
625 | /* Workdir should not be subdir of upperdir and vice versa */ | 776 | /* Workdir should not be subdir of upperdir and vice versa */ |
626 | static bool ovl_workdir_ok(struct dentry *workdir, struct dentry *upperdir) | 777 | static bool ovl_workdir_ok(struct dentry *workdir, struct dentry *upperdir) |
627 | { | 778 | { |
@@ -634,16 +785,39 @@ static bool ovl_workdir_ok(struct dentry *workdir, struct dentry *upperdir) | |||
634 | return ok; | 785 | return ok; |
635 | } | 786 | } |
636 | 787 | ||
788 | static unsigned int ovl_split_lowerdirs(char *str) | ||
789 | { | ||
790 | unsigned int ctr = 1; | ||
791 | char *s, *d; | ||
792 | |||
793 | for (s = d = str;; s++, d++) { | ||
794 | if (*s == '\\') { | ||
795 | s++; | ||
796 | } else if (*s == ':') { | ||
797 | *d = '\0'; | ||
798 | ctr++; | ||
799 | continue; | ||
800 | } | ||
801 | *d = *s; | ||
802 | if (!*s) | ||
803 | break; | ||
804 | } | ||
805 | return ctr; | ||
806 | } | ||
807 | |||
637 | static int ovl_fill_super(struct super_block *sb, void *data, int silent) | 808 | static int ovl_fill_super(struct super_block *sb, void *data, int silent) |
638 | { | 809 | { |
639 | struct path lowerpath; | 810 | struct path upperpath = { NULL, NULL }; |
640 | struct path upperpath; | 811 | struct path workpath = { NULL, NULL }; |
641 | struct path workpath; | ||
642 | struct inode *root_inode; | ||
643 | struct dentry *root_dentry; | 812 | struct dentry *root_dentry; |
644 | struct ovl_entry *oe; | 813 | struct ovl_entry *oe; |
645 | struct ovl_fs *ufs; | 814 | struct ovl_fs *ufs; |
646 | struct kstatfs statfs; | 815 | struct path *stack = NULL; |
816 | char *lowertmp; | ||
817 | char *lower; | ||
818 | unsigned int numlower; | ||
819 | unsigned int stacklen = 0; | ||
820 | unsigned int i; | ||
647 | int err; | 821 | int err; |
648 | 822 | ||
649 | err = -ENOMEM; | 823 | err = -ENOMEM; |
@@ -655,123 +829,135 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
655 | if (err) | 829 | if (err) |
656 | goto out_free_config; | 830 | goto out_free_config; |
657 | 831 | ||
658 | /* FIXME: workdir is not needed for a R/O mount */ | ||
659 | err = -EINVAL; | 832 | err = -EINVAL; |
660 | if (!ufs->config.upperdir || !ufs->config.lowerdir || | 833 | if (!ufs->config.lowerdir) { |
661 | !ufs->config.workdir) { | 834 | pr_err("overlayfs: missing 'lowerdir'\n"); |
662 | pr_err("overlayfs: missing upperdir or lowerdir or workdir\n"); | ||
663 | goto out_free_config; | 835 | goto out_free_config; |
664 | } | 836 | } |
665 | 837 | ||
666 | err = -ENOMEM; | 838 | sb->s_stack_depth = 0; |
667 | oe = ovl_alloc_entry(); | 839 | if (ufs->config.upperdir) { |
668 | if (oe == NULL) | 840 | /* FIXME: workdir is not needed for a R/O mount */ |
669 | goto out_free_config; | 841 | if (!ufs->config.workdir) { |
670 | 842 | pr_err("overlayfs: missing 'workdir'\n"); | |
671 | err = ovl_mount_dir(ufs->config.upperdir, &upperpath); | 843 | goto out_free_config; |
672 | if (err) | 844 | } |
673 | goto out_free_oe; | ||
674 | |||
675 | err = ovl_mount_dir(ufs->config.lowerdir, &lowerpath); | ||
676 | if (err) | ||
677 | goto out_put_upperpath; | ||
678 | 845 | ||
679 | err = ovl_mount_dir(ufs->config.workdir, &workpath); | 846 | err = ovl_mount_dir(ufs->config.upperdir, &upperpath); |
680 | if (err) | 847 | if (err) |
681 | goto out_put_lowerpath; | 848 | goto out_free_config; |
682 | 849 | ||
683 | err = -EINVAL; | 850 | err = ovl_mount_dir(ufs->config.workdir, &workpath); |
684 | if (!S_ISDIR(upperpath.dentry->d_inode->i_mode) || | 851 | if (err) |
685 | !S_ISDIR(lowerpath.dentry->d_inode->i_mode) || | 852 | goto out_put_upperpath; |
686 | !S_ISDIR(workpath.dentry->d_inode->i_mode)) { | ||
687 | pr_err("overlayfs: upperdir or lowerdir or workdir not a directory\n"); | ||
688 | goto out_put_workpath; | ||
689 | } | ||
690 | 853 | ||
691 | if (upperpath.mnt != workpath.mnt) { | 854 | err = -EINVAL; |
692 | pr_err("overlayfs: workdir and upperdir must reside under the same mount\n"); | 855 | if (upperpath.mnt != workpath.mnt) { |
693 | goto out_put_workpath; | 856 | pr_err("overlayfs: workdir and upperdir must reside under the same mount\n"); |
694 | } | 857 | goto out_put_workpath; |
695 | if (!ovl_workdir_ok(workpath.dentry, upperpath.dentry)) { | 858 | } |
696 | pr_err("overlayfs: workdir and upperdir must be separate subtrees\n"); | 859 | if (!ovl_workdir_ok(workpath.dentry, upperpath.dentry)) { |
697 | goto out_put_workpath; | 860 | pr_err("overlayfs: workdir and upperdir must be separate subtrees\n"); |
861 | goto out_put_workpath; | ||
862 | } | ||
863 | sb->s_stack_depth = upperpath.mnt->mnt_sb->s_stack_depth; | ||
698 | } | 864 | } |
699 | 865 | err = -ENOMEM; | |
700 | if (!ovl_is_allowed_fs_type(upperpath.dentry)) { | 866 | lowertmp = kstrdup(ufs->config.lowerdir, GFP_KERNEL); |
701 | pr_err("overlayfs: filesystem of upperdir is not supported\n"); | 867 | if (!lowertmp) |
702 | goto out_put_workpath; | 868 | goto out_put_workpath; |
703 | } | ||
704 | 869 | ||
705 | if (!ovl_is_allowed_fs_type(lowerpath.dentry)) { | 870 | err = -EINVAL; |
706 | pr_err("overlayfs: filesystem of lowerdir is not supported\n"); | 871 | stacklen = ovl_split_lowerdirs(lowertmp); |
707 | goto out_put_workpath; | 872 | if (stacklen > OVL_MAX_STACK) |
708 | } | 873 | goto out_free_lowertmp; |
874 | |||
875 | stack = kcalloc(stacklen, sizeof(struct path), GFP_KERNEL); | ||
876 | if (!stack) | ||
877 | goto out_free_lowertmp; | ||
878 | |||
879 | lower = lowertmp; | ||
880 | for (numlower = 0; numlower < stacklen; numlower++) { | ||
881 | err = ovl_lower_dir(lower, &stack[numlower], | ||
882 | &ufs->lower_namelen, &sb->s_stack_depth); | ||
883 | if (err) | ||
884 | goto out_put_lowerpath; | ||
709 | 885 | ||
710 | err = vfs_statfs(&lowerpath, &statfs); | 886 | lower = strchr(lower, '\0') + 1; |
711 | if (err) { | ||
712 | pr_err("overlayfs: statfs failed on lowerpath\n"); | ||
713 | goto out_put_workpath; | ||
714 | } | 887 | } |
715 | ufs->lower_namelen = statfs.f_namelen; | ||
716 | |||
717 | sb->s_stack_depth = max(upperpath.mnt->mnt_sb->s_stack_depth, | ||
718 | lowerpath.mnt->mnt_sb->s_stack_depth) + 1; | ||
719 | 888 | ||
720 | err = -EINVAL; | 889 | err = -EINVAL; |
890 | sb->s_stack_depth++; | ||
721 | if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) { | 891 | if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) { |
722 | pr_err("overlayfs: maximum fs stacking depth exceeded\n"); | 892 | pr_err("overlayfs: maximum fs stacking depth exceeded\n"); |
723 | goto out_put_workpath; | 893 | goto out_put_lowerpath; |
724 | } | 894 | } |
725 | 895 | ||
726 | ufs->upper_mnt = clone_private_mount(&upperpath); | 896 | if (ufs->config.upperdir) { |
727 | err = PTR_ERR(ufs->upper_mnt); | 897 | ufs->upper_mnt = clone_private_mount(&upperpath); |
728 | if (IS_ERR(ufs->upper_mnt)) { | 898 | err = PTR_ERR(ufs->upper_mnt); |
729 | pr_err("overlayfs: failed to clone upperpath\n"); | 899 | if (IS_ERR(ufs->upper_mnt)) { |
730 | goto out_put_workpath; | 900 | pr_err("overlayfs: failed to clone upperpath\n"); |
731 | } | 901 | goto out_put_lowerpath; |
902 | } | ||
732 | 903 | ||
733 | ufs->lower_mnt = clone_private_mount(&lowerpath); | 904 | ufs->workdir = ovl_workdir_create(ufs->upper_mnt, workpath.dentry); |
734 | err = PTR_ERR(ufs->lower_mnt); | 905 | err = PTR_ERR(ufs->workdir); |
735 | if (IS_ERR(ufs->lower_mnt)) { | 906 | if (IS_ERR(ufs->workdir)) { |
736 | pr_err("overlayfs: failed to clone lowerpath\n"); | 907 | pr_err("overlayfs: failed to create directory %s/%s\n", |
737 | goto out_put_upper_mnt; | 908 | ufs->config.workdir, OVL_WORKDIR_NAME); |
909 | goto out_put_upper_mnt; | ||
910 | } | ||
738 | } | 911 | } |
739 | 912 | ||
740 | ufs->workdir = ovl_workdir_create(ufs->upper_mnt, workpath.dentry); | 913 | err = -ENOMEM; |
741 | err = PTR_ERR(ufs->workdir); | 914 | ufs->lower_mnt = kcalloc(numlower, sizeof(struct vfsmount *), GFP_KERNEL); |
742 | if (IS_ERR(ufs->workdir)) { | 915 | if (ufs->lower_mnt == NULL) |
743 | pr_err("overlayfs: failed to create directory %s/%s\n", | 916 | goto out_put_workdir; |
744 | ufs->config.workdir, OVL_WORKDIR_NAME); | 917 | for (i = 0; i < numlower; i++) { |
745 | goto out_put_lower_mnt; | 918 | struct vfsmount *mnt = clone_private_mount(&stack[i]); |
746 | } | ||
747 | 919 | ||
748 | /* | 920 | err = PTR_ERR(mnt); |
749 | * Make lower_mnt R/O. That way fchmod/fchown on lower file | 921 | if (IS_ERR(mnt)) { |
750 | * will fail instead of modifying lower fs. | 922 | pr_err("overlayfs: failed to clone lowerpath\n"); |
751 | */ | 923 | goto out_put_lower_mnt; |
752 | ufs->lower_mnt->mnt_flags |= MNT_READONLY; | 924 | } |
925 | /* | ||
926 | * Make lower_mnt R/O. That way fchmod/fchown on lower file | ||
927 | * will fail instead of modifying lower fs. | ||
928 | */ | ||
929 | mnt->mnt_flags |= MNT_READONLY; | ||
930 | |||
931 | ufs->lower_mnt[ufs->numlower] = mnt; | ||
932 | ufs->numlower++; | ||
933 | } | ||
753 | 934 | ||
754 | /* If the upper fs is r/o, we mark overlayfs r/o too */ | 935 | /* If the upper fs is r/o or nonexistent, we mark overlayfs r/o too */ |
755 | if (ufs->upper_mnt->mnt_sb->s_flags & MS_RDONLY) | 936 | if (!ufs->upper_mnt || (ufs->upper_mnt->mnt_sb->s_flags & MS_RDONLY)) |
756 | sb->s_flags |= MS_RDONLY; | 937 | sb->s_flags |= MS_RDONLY; |
757 | 938 | ||
758 | sb->s_d_op = &ovl_dentry_operations; | 939 | sb->s_d_op = &ovl_dentry_operations; |
759 | 940 | ||
760 | err = -ENOMEM; | 941 | err = -ENOMEM; |
761 | root_inode = ovl_new_inode(sb, S_IFDIR, oe); | 942 | oe = ovl_alloc_entry(numlower); |
762 | if (!root_inode) | 943 | if (!oe) |
763 | goto out_put_workdir; | 944 | goto out_put_lower_mnt; |
764 | 945 | ||
765 | root_dentry = d_make_root(root_inode); | 946 | root_dentry = d_make_root(ovl_new_inode(sb, S_IFDIR, oe)); |
766 | if (!root_dentry) | 947 | if (!root_dentry) |
767 | goto out_put_workdir; | 948 | goto out_free_oe; |
768 | 949 | ||
769 | mntput(upperpath.mnt); | 950 | mntput(upperpath.mnt); |
770 | mntput(lowerpath.mnt); | 951 | for (i = 0; i < numlower; i++) |
952 | mntput(stack[i].mnt); | ||
771 | path_put(&workpath); | 953 | path_put(&workpath); |
954 | kfree(lowertmp); | ||
772 | 955 | ||
773 | oe->__upperdentry = upperpath.dentry; | 956 | oe->__upperdentry = upperpath.dentry; |
774 | oe->lowerdentry = lowerpath.dentry; | 957 | for (i = 0; i < numlower; i++) { |
958 | oe->lowerstack[i].dentry = stack[i].dentry; | ||
959 | oe->lowerstack[i].mnt = ufs->lower_mnt[i]; | ||
960 | } | ||
775 | 961 | ||
776 | root_dentry->d_fsdata = oe; | 962 | root_dentry->d_fsdata = oe; |
777 | 963 | ||
@@ -782,20 +968,26 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
782 | 968 | ||
783 | return 0; | 969 | return 0; |
784 | 970 | ||
971 | out_free_oe: | ||
972 | kfree(oe); | ||
973 | out_put_lower_mnt: | ||
974 | for (i = 0; i < ufs->numlower; i++) | ||
975 | mntput(ufs->lower_mnt[i]); | ||
976 | kfree(ufs->lower_mnt); | ||
785 | out_put_workdir: | 977 | out_put_workdir: |
786 | dput(ufs->workdir); | 978 | dput(ufs->workdir); |
787 | out_put_lower_mnt: | ||
788 | mntput(ufs->lower_mnt); | ||
789 | out_put_upper_mnt: | 979 | out_put_upper_mnt: |
790 | mntput(ufs->upper_mnt); | 980 | mntput(ufs->upper_mnt); |
981 | out_put_lowerpath: | ||
982 | for (i = 0; i < numlower; i++) | ||
983 | path_put(&stack[i]); | ||
984 | kfree(stack); | ||
985 | out_free_lowertmp: | ||
986 | kfree(lowertmp); | ||
791 | out_put_workpath: | 987 | out_put_workpath: |
792 | path_put(&workpath); | 988 | path_put(&workpath); |
793 | out_put_lowerpath: | ||
794 | path_put(&lowerpath); | ||
795 | out_put_upperpath: | 989 | out_put_upperpath: |
796 | path_put(&upperpath); | 990 | path_put(&upperpath); |
797 | out_free_oe: | ||
798 | kfree(oe); | ||
799 | out_free_config: | 991 | out_free_config: |
800 | kfree(ufs->config.lowerdir); | 992 | kfree(ufs->config.lowerdir); |
801 | kfree(ufs->config.upperdir); | 993 | kfree(ufs->config.upperdir); |
diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 0855f772cd41..3a48bb789c9f 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c | |||
@@ -564,13 +564,11 @@ posix_acl_create(struct inode *dir, umode_t *mode, | |||
564 | 564 | ||
565 | *acl = posix_acl_clone(p, GFP_NOFS); | 565 | *acl = posix_acl_clone(p, GFP_NOFS); |
566 | if (!*acl) | 566 | if (!*acl) |
567 | return -ENOMEM; | 567 | goto no_mem; |
568 | 568 | ||
569 | ret = posix_acl_create_masq(*acl, mode); | 569 | ret = posix_acl_create_masq(*acl, mode); |
570 | if (ret < 0) { | 570 | if (ret < 0) |
571 | posix_acl_release(*acl); | 571 | goto no_mem_clone; |
572 | return -ENOMEM; | ||
573 | } | ||
574 | 572 | ||
575 | if (ret == 0) { | 573 | if (ret == 0) { |
576 | posix_acl_release(*acl); | 574 | posix_acl_release(*acl); |
@@ -591,6 +589,12 @@ no_acl: | |||
591 | *default_acl = NULL; | 589 | *default_acl = NULL; |
592 | *acl = NULL; | 590 | *acl = NULL; |
593 | return 0; | 591 | return 0; |
592 | |||
593 | no_mem_clone: | ||
594 | posix_acl_release(*acl); | ||
595 | no_mem: | ||
596 | posix_acl_release(p); | ||
597 | return -ENOMEM; | ||
594 | } | 598 | } |
595 | EXPORT_SYMBOL_GPL(posix_acl_create); | 599 | EXPORT_SYMBOL_GPL(posix_acl_create); |
596 | 600 | ||
@@ -772,7 +776,7 @@ posix_acl_xattr_get(struct dentry *dentry, const char *name, | |||
772 | 776 | ||
773 | if (!IS_POSIXACL(dentry->d_inode)) | 777 | if (!IS_POSIXACL(dentry->d_inode)) |
774 | return -EOPNOTSUPP; | 778 | return -EOPNOTSUPP; |
775 | if (S_ISLNK(dentry->d_inode->i_mode)) | 779 | if (d_is_symlink(dentry)) |
776 | return -EOPNOTSUPP; | 780 | return -EOPNOTSUPP; |
777 | 781 | ||
778 | acl = get_acl(dentry->d_inode, type); | 782 | acl = get_acl(dentry->d_inode, type); |
@@ -832,7 +836,7 @@ posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size, | |||
832 | 836 | ||
833 | if (!IS_POSIXACL(dentry->d_inode)) | 837 | if (!IS_POSIXACL(dentry->d_inode)) |
834 | return -EOPNOTSUPP; | 838 | return -EOPNOTSUPP; |
835 | if (S_ISLNK(dentry->d_inode->i_mode)) | 839 | if (d_is_symlink(dentry)) |
836 | return -EOPNOTSUPP; | 840 | return -EOPNOTSUPP; |
837 | 841 | ||
838 | if (type == ACL_TYPE_ACCESS) | 842 | if (type == ACL_TYPE_ACCESS) |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 3309f59d421b..be65b2082135 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/mount.h> | 19 | #include <linux/mount.h> |
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/idr.h> | 21 | #include <linux/idr.h> |
22 | #include <linux/namei.h> | ||
23 | #include <linux/bitops.h> | 22 | #include <linux/bitops.h> |
24 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
25 | #include <linux/completion.h> | 24 | #include <linux/completion.h> |
@@ -223,17 +222,6 @@ void proc_free_inum(unsigned int inum) | |||
223 | spin_unlock_irqrestore(&proc_inum_lock, flags); | 222 | spin_unlock_irqrestore(&proc_inum_lock, flags); |
224 | } | 223 | } |
225 | 224 | ||
226 | static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
227 | { | ||
228 | nd_set_link(nd, __PDE_DATA(dentry->d_inode)); | ||
229 | return NULL; | ||
230 | } | ||
231 | |||
232 | static const struct inode_operations proc_link_inode_operations = { | ||
233 | .readlink = generic_readlink, | ||
234 | .follow_link = proc_follow_link, | ||
235 | }; | ||
236 | |||
237 | /* | 225 | /* |
238 | * Don't create negative dentries here, return -ENOENT by hand | 226 | * Don't create negative dentries here, return -ENOENT by hand |
239 | * instead. | 227 | * instead. |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 13a50a32652d..7697b6621cfd 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/mount.h> | 24 | #include <linux/mount.h> |
25 | #include <linux/magic.h> | 25 | #include <linux/magic.h> |
26 | #include <linux/namei.h> | ||
26 | 27 | ||
27 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
28 | 29 | ||
@@ -393,6 +394,26 @@ static const struct file_operations proc_reg_file_ops_no_compat = { | |||
393 | }; | 394 | }; |
394 | #endif | 395 | #endif |
395 | 396 | ||
397 | static void *proc_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
398 | { | ||
399 | struct proc_dir_entry *pde = PDE(dentry->d_inode); | ||
400 | if (unlikely(!use_pde(pde))) | ||
401 | return ERR_PTR(-EINVAL); | ||
402 | nd_set_link(nd, pde->data); | ||
403 | return pde; | ||
404 | } | ||
405 | |||
406 | static void proc_put_link(struct dentry *dentry, struct nameidata *nd, void *p) | ||
407 | { | ||
408 | unuse_pde(p); | ||
409 | } | ||
410 | |||
411 | const struct inode_operations proc_link_inode_operations = { | ||
412 | .readlink = generic_readlink, | ||
413 | .follow_link = proc_follow_link, | ||
414 | .put_link = proc_put_link, | ||
415 | }; | ||
416 | |||
396 | struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) | 417 | struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) |
397 | { | 418 | { |
398 | struct inode *inode = new_inode_pseudo(sb); | 419 | struct inode *inode = new_inode_pseudo(sb); |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 6fcdba573e0f..c835b94c0cd3 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -200,6 +200,7 @@ struct pde_opener { | |||
200 | int closing; | 200 | int closing; |
201 | struct completion *c; | 201 | struct completion *c; |
202 | }; | 202 | }; |
203 | extern const struct inode_operations proc_link_inode_operations; | ||
203 | 204 | ||
204 | extern const struct inode_operations proc_pid_link_inode_operations; | 205 | extern const struct inode_operations proc_pid_link_inode_operations; |
205 | 206 | ||
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 04b06146bae2..4e781e697c90 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -266,7 +266,7 @@ static int reiserfs_for_each_xattr(struct inode *inode, | |||
266 | for (i = 0; !err && i < buf.count && buf.dentries[i]; i++) { | 266 | for (i = 0; !err && i < buf.count && buf.dentries[i]; i++) { |
267 | struct dentry *dentry = buf.dentries[i]; | 267 | struct dentry *dentry = buf.dentries[i]; |
268 | 268 | ||
269 | if (!S_ISDIR(dentry->d_inode->i_mode)) | 269 | if (!d_is_dir(dentry)) |
270 | err = action(dentry, data); | 270 | err = action(dentry, data); |
271 | 271 | ||
272 | dput(dentry); | 272 | dput(dentry); |
@@ -322,7 +322,7 @@ static int delete_one_xattr(struct dentry *dentry, void *data) | |||
322 | struct inode *dir = dentry->d_parent->d_inode; | 322 | struct inode *dir = dentry->d_parent->d_inode; |
323 | 323 | ||
324 | /* This is the xattr dir, handle specially. */ | 324 | /* This is the xattr dir, handle specially. */ |
325 | if (S_ISDIR(dentry->d_inode->i_mode)) | 325 | if (d_is_dir(dentry)) |
326 | return xattr_rmdir(dir, dentry); | 326 | return xattr_rmdir(dir, dentry); |
327 | 327 | ||
328 | return xattr_unlink(dir, dentry); | 328 | return xattr_unlink(dir, dentry); |
diff --git a/fs/super.c b/fs/super.c index 65a53efc1cf4..2b7dc90ccdbb 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -71,7 +71,7 @@ static unsigned long super_cache_scan(struct shrinker *shrink, | |||
71 | if (!(sc->gfp_mask & __GFP_FS)) | 71 | if (!(sc->gfp_mask & __GFP_FS)) |
72 | return SHRINK_STOP; | 72 | return SHRINK_STOP; |
73 | 73 | ||
74 | if (!grab_super_passive(sb)) | 74 | if (!trylock_super(sb)) |
75 | return SHRINK_STOP; | 75 | return SHRINK_STOP; |
76 | 76 | ||
77 | if (sb->s_op->nr_cached_objects) | 77 | if (sb->s_op->nr_cached_objects) |
@@ -105,7 +105,7 @@ static unsigned long super_cache_scan(struct shrinker *shrink, | |||
105 | freed += sb->s_op->free_cached_objects(sb, sc); | 105 | freed += sb->s_op->free_cached_objects(sb, sc); |
106 | } | 106 | } |
107 | 107 | ||
108 | drop_super(sb); | 108 | up_read(&sb->s_umount); |
109 | return freed; | 109 | return freed; |
110 | } | 110 | } |
111 | 111 | ||
@@ -118,7 +118,7 @@ static unsigned long super_cache_count(struct shrinker *shrink, | |||
118 | sb = container_of(shrink, struct super_block, s_shrink); | 118 | sb = container_of(shrink, struct super_block, s_shrink); |
119 | 119 | ||
120 | /* | 120 | /* |
121 | * Don't call grab_super_passive as it is a potential | 121 | * Don't call trylock_super as it is a potential |
122 | * scalability bottleneck. The counts could get updated | 122 | * scalability bottleneck. The counts could get updated |
123 | * between super_cache_count and super_cache_scan anyway. | 123 | * between super_cache_count and super_cache_scan anyway. |
124 | * Call to super_cache_count with shrinker_rwsem held | 124 | * Call to super_cache_count with shrinker_rwsem held |
@@ -348,35 +348,31 @@ static int grab_super(struct super_block *s) __releases(sb_lock) | |||
348 | } | 348 | } |
349 | 349 | ||
350 | /* | 350 | /* |
351 | * grab_super_passive - acquire a passive reference | 351 | * trylock_super - try to grab ->s_umount shared |
352 | * @sb: reference we are trying to grab | 352 | * @sb: reference we are trying to grab |
353 | * | 353 | * |
354 | * Tries to acquire a passive reference. This is used in places where we | 354 | * Try to prevent fs shutdown. This is used in places where we |
355 | * cannot take an active reference but we need to ensure that the | 355 | * cannot take an active reference but we need to ensure that the |
356 | * superblock does not go away while we are working on it. It returns | 356 | * filesystem is not shut down while we are working on it. It returns |
357 | * false if a reference was not gained, and returns true with the s_umount | 357 | * false if we cannot acquire s_umount or if we lose the race and |
358 | * lock held in read mode if a reference is gained. On successful return, | 358 | * filesystem already got into shutdown, and returns true with the s_umount |
359 | * the caller must drop the s_umount lock and the passive reference when | 359 | * lock held in read mode in case of success. On successful return, |
360 | * done. | 360 | * the caller must drop the s_umount lock when done. |
361 | * | ||
362 | * Note that unlike get_super() et.al. this one does *not* bump ->s_count. | ||
363 | * The reason why it's safe is that we are OK with doing trylock instead | ||
364 | * of down_read(). There's a couple of places that are OK with that, but | ||
365 | * it's very much not a general-purpose interface. | ||
361 | */ | 366 | */ |
362 | bool grab_super_passive(struct super_block *sb) | 367 | bool trylock_super(struct super_block *sb) |
363 | { | 368 | { |
364 | spin_lock(&sb_lock); | ||
365 | if (hlist_unhashed(&sb->s_instances)) { | ||
366 | spin_unlock(&sb_lock); | ||
367 | return false; | ||
368 | } | ||
369 | |||
370 | sb->s_count++; | ||
371 | spin_unlock(&sb_lock); | ||
372 | |||
373 | if (down_read_trylock(&sb->s_umount)) { | 369 | if (down_read_trylock(&sb->s_umount)) { |
374 | if (sb->s_root && (sb->s_flags & MS_BORN)) | 370 | if (!hlist_unhashed(&sb->s_instances) && |
371 | sb->s_root && (sb->s_flags & MS_BORN)) | ||
375 | return true; | 372 | return true; |
376 | up_read(&sb->s_umount); | 373 | up_read(&sb->s_umount); |
377 | } | 374 | } |
378 | 375 | ||
379 | put_super(sb); | ||
380 | return false; | 376 | return false; |
381 | } | 377 | } |
382 | 378 | ||
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index bf70a2affb05..ac4feae45eb3 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c | |||
@@ -287,7 +287,7 @@ xfs_readlink_by_handle( | |||
287 | return PTR_ERR(dentry); | 287 | return PTR_ERR(dentry); |
288 | 288 | ||
289 | /* Restrict this handle operation to symlinks only. */ | 289 | /* Restrict this handle operation to symlinks only. */ |
290 | if (!S_ISLNK(dentry->d_inode->i_mode)) { | 290 | if (!d_is_symlink(dentry)) { |
291 | error = -EINVAL; | 291 | error = -EINVAL; |
292 | goto out_dput; | 292 | goto out_dput; |
293 | } | 293 | } |