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 | } |
