Skip to content

Commit

Permalink
Merge branch 'for-linus-2' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/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
  ...
  • Loading branch information
torvalds committed Feb 23, 2015
2 parents 90c453c + 0a28096 commit be5e661
Show file tree
Hide file tree
Showing 70 changed files with 907 additions and 758 deletions.
2 changes: 0 additions & 2 deletions Documentation/filesystems/Locking
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,6 @@ the block device inode. See there for more details.

--------------------------- file_system_type ---------------------------
prototypes:
int (*get_sb) (struct file_system_type *, int,
const char *, void *, struct vfsmount *);
struct dentry *(*mount) (struct file_system_type *, int,
const char *, void *);
void (*kill_sb) (struct super_block *);
Expand Down
28 changes: 28 additions & 0 deletions Documentation/filesystems/overlayfs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,22 @@ overlay filesystem (though an operation on the name of the file such as
rename or unlink will of course be noticed and handled).


Multiple lower layers
---------------------

Multiple lower layers can now be given using the the colon (":") as a
separator character between the directory names. For example:

mount -t overlay overlay -olowerdir=/lower1:/lower2:/lower3 /merged

As the example shows, "upperdir=" and "workdir=" may be omitted. In
that case the overlay will be read-only.

The specified lower directories will be stacked beginning from the
rightmost one and going left. In the above example lower1 will be the
top, lower2 the middle and lower3 the bottom layer.


Non-standard behavior
---------------------

Expand Down Expand Up @@ -196,3 +212,15 @@ Changes to the underlying filesystems while part of a mounted overlay
filesystem are not allowed. If the underlying filesystem is changed,
the behavior of the overlay is undefined, though it will not result in
a crash or deadlock.

Testsuite
---------

There's testsuite developed by David Howells at:

git://git.infradead.org/users/dhowells/unionmount-testsuite.git

Run as root:

# cd unionmount-testsuite
# ./run --ov
53 changes: 25 additions & 28 deletions arch/s390/hypfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ static void hypfs_remove(struct dentry *dentry)
parent = dentry->d_parent;
mutex_lock(&parent->d_inode->i_mutex);
if (hypfs_positive(dentry)) {
if (S_ISDIR(dentry->d_inode->i_mode))
if (d_is_dir(dentry))
simple_rmdir(parent->d_inode, dentry);
else
simple_unlink(parent->d_inode, dentry);
Expand Down Expand Up @@ -144,36 +144,32 @@ static int hypfs_open(struct inode *inode, struct file *filp)
return nonseekable_open(inode, filp);
}

static ssize_t hypfs_aio_read(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t offset)
static ssize_t hypfs_read_iter(struct kiocb *iocb, struct iov_iter *to)
{
char *data;
ssize_t ret;
struct file *filp = iocb->ki_filp;
/* XXX: temporary */
char __user *buf = iov[0].iov_base;
size_t count = iov[0].iov_len;

if (nr_segs != 1)
return -EINVAL;

data = filp->private_data;
ret = simple_read_from_buffer(buf, count, &offset, data, strlen(data));
if (ret <= 0)
return ret;
struct file *file = iocb->ki_filp;
char *data = file->private_data;
size_t available = strlen(data);
loff_t pos = iocb->ki_pos;
size_t count;

iocb->ki_pos += ret;
file_accessed(filp);

return ret;
if (pos < 0)
return -EINVAL;
if (pos >= available || !iov_iter_count(to))
return 0;
count = copy_to_iter(data + pos, available - pos, to);
if (!count)
return -EFAULT;
iocb->ki_pos = pos + count;
file_accessed(file);
return count;
}
static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t offset)

static ssize_t hypfs_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
int rc;
struct super_block *sb = file_inode(iocb->ki_filp)->i_sb;
struct hypfs_sb_info *fs_info = sb->s_fs_info;
size_t count = iov_length(iov, nr_segs);
size_t count = iov_iter_count(from);

/*
* Currently we only allow one update per second for two reasons:
Expand Down Expand Up @@ -202,6 +198,7 @@ static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov,
}
hypfs_update_update(sb);
rc = count;
iov_iter_advance(from, count);
out:
mutex_unlock(&fs_info->lock);
return rc;
Expand Down Expand Up @@ -440,10 +437,10 @@ struct dentry *hypfs_create_str(struct dentry *dir,
static const struct file_operations hypfs_file_ops = {
.open = hypfs_open,
.release = hypfs_release,
.read = do_sync_read,
.write = do_sync_write,
.aio_read = hypfs_aio_read,
.aio_write = hypfs_aio_write,
.read = new_sync_read,
.write = new_sync_write,
.read_iter = hypfs_read_iter,
.write_iter = hypfs_write_iter,
.llseek = no_llseek,
};

Expand Down
2 changes: 1 addition & 1 deletion drivers/infiniband/hw/ipath/ipath_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ static int remove_file(struct dentry *parent, char *name)
}

spin_lock(&tmp->d_lock);
if (!(d_unhashed(tmp) && tmp->d_inode)) {
if (!d_unhashed(tmp) && tmp->d_inode) {
dget_dlock(tmp);
__d_drop(tmp);
spin_unlock(&tmp->d_lock);
Expand Down
2 changes: 1 addition & 1 deletion drivers/infiniband/hw/qib/qib_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ static int remove_file(struct dentry *parent, char *name)
}

spin_lock(&tmp->d_lock);
if (!(d_unhashed(tmp) && tmp->d_inode)) {
if (!d_unhashed(tmp) && tmp->d_inode) {
__d_drop(tmp);
spin_unlock(&tmp->d_lock);
simple_unlink(parent->d_inode, tmp);
Expand Down
12 changes: 5 additions & 7 deletions drivers/staging/lustre/lustre/llite/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ void ll_invalidate_aliases(struct inode *inode)

int ll_revalidate_it_finish(struct ptlrpc_request *request,
struct lookup_intent *it,
struct dentry *de)
struct inode *inode)
{
int rc = 0;

Expand All @@ -280,19 +280,17 @@ int ll_revalidate_it_finish(struct ptlrpc_request *request,
if (it_disposition(it, DISP_LOOKUP_NEG))
return -ENOENT;

rc = ll_prep_inode(&de->d_inode, request, NULL, it);
rc = ll_prep_inode(&inode, request, NULL, it);

return rc;
}

void ll_lookup_finish_locks(struct lookup_intent *it, struct dentry *dentry)
void ll_lookup_finish_locks(struct lookup_intent *it, struct inode *inode)
{
LASSERT(it != NULL);
LASSERT(dentry != NULL);

if (it->d.lustre.it_lock_mode && dentry->d_inode != NULL) {
struct inode *inode = dentry->d_inode;
struct ll_sb_info *sbi = ll_i2sbi(dentry->d_inode);
if (it->d.lustre.it_lock_mode && inode != NULL) {
struct ll_sb_info *sbi = ll_i2sbi(inode);

CDEBUG(D_DLMTRACE, "setting l_data to inode %p (%lu/%u)\n",
inode, inode->i_ino, inode->i_generation);
Expand Down
8 changes: 4 additions & 4 deletions drivers/staging/lustre/lustre/llite/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -2912,8 +2912,8 @@ static int __ll_inode_revalidate(struct dentry *dentry, __u64 ibits)
oit.it_op = IT_LOOKUP;

/* Call getattr by fid, so do not provide name at all. */
op_data = ll_prep_md_op_data(NULL, dentry->d_inode,
dentry->d_inode, NULL, 0, 0,
op_data = ll_prep_md_op_data(NULL, inode,
inode, NULL, 0, 0,
LUSTRE_OPC_ANY, NULL);
if (IS_ERR(op_data))
return PTR_ERR(op_data);
Expand All @@ -2931,7 +2931,7 @@ static int __ll_inode_revalidate(struct dentry *dentry, __u64 ibits)
goto out;
}

rc = ll_revalidate_it_finish(req, &oit, dentry);
rc = ll_revalidate_it_finish(req, &oit, inode);
if (rc != 0) {
ll_intent_release(&oit);
goto out;
Expand All @@ -2944,7 +2944,7 @@ static int __ll_inode_revalidate(struct dentry *dentry, __u64 ibits)
if (!dentry->d_inode->i_nlink)
d_lustre_invalidate(dentry, 0);

ll_lookup_finish_locks(&oit, dentry);
ll_lookup_finish_locks(&oit, inode);
} else if (!ll_have_md_lock(dentry->d_inode, &ibits, LCK_MINMODE)) {
struct ll_sb_info *sbi = ll_i2sbi(dentry->d_inode);
u64 valid = OBD_MD_FLGETATTR;
Expand Down
4 changes: 2 additions & 2 deletions drivers/staging/lustre/lustre/llite/llite_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -786,9 +786,9 @@ extern const struct dentry_operations ll_d_ops;
void ll_intent_drop_lock(struct lookup_intent *);
void ll_intent_release(struct lookup_intent *);
void ll_invalidate_aliases(struct inode *);
void ll_lookup_finish_locks(struct lookup_intent *it, struct dentry *dentry);
void ll_lookup_finish_locks(struct lookup_intent *it, struct inode *inode);
int ll_revalidate_it_finish(struct ptlrpc_request *request,
struct lookup_intent *it, struct dentry *de);
struct lookup_intent *it, struct inode *inode);

/* llite/llite_lib.c */
extern struct super_operations lustre_super_operations;
Expand Down
12 changes: 7 additions & 5 deletions drivers/staging/lustre/lustre/llite/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
struct lookup_intent lookup_it = { .it_op = IT_LOOKUP };
struct dentry *save = dentry, *retval;
struct ptlrpc_request *req = NULL;
struct inode *inode;
struct md_op_data *op_data;
__u32 opc;
int rc;
Expand Down Expand Up @@ -539,12 +540,13 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry,
goto out;
}

if ((it->it_op & IT_OPEN) && dentry->d_inode &&
!S_ISREG(dentry->d_inode->i_mode) &&
!S_ISDIR(dentry->d_inode->i_mode)) {
ll_release_openhandle(dentry->d_inode, it);
inode = dentry->d_inode;
if ((it->it_op & IT_OPEN) && inode &&
!S_ISREG(inode->i_mode) &&
!S_ISDIR(inode->i_mode)) {
ll_release_openhandle(inode, it);
}
ll_lookup_finish_locks(it, dentry);
ll_lookup_finish_locks(it, inode);

if (dentry == save)
retval = NULL;
Expand Down
2 changes: 1 addition & 1 deletion fs/9p/vfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1127,7 +1127,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
}

/* Write all dirty data */
if (S_ISREG(dentry->d_inode->i_mode))
if (d_is_reg(dentry))
filemap_write_and_wait(dentry->d_inode->i_mapping);

retval = p9_client_wstat(fid, &wstat);
Expand Down
6 changes: 3 additions & 3 deletions fs/aio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1285,7 +1285,7 @@ SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp)

ret = -EINVAL;
if (unlikely(ctx || nr_events == 0)) {
pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n",
pr_debug("EINVAL: ctx %lu nr_events %u\n",
ctx, nr_events);
goto out;
}
Expand Down Expand Up @@ -1333,7 +1333,7 @@ SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx)

return ret;
}
pr_debug("EINVAL: io_destroy: invalid context id\n");
pr_debug("EINVAL: invalid context id\n");
return -EINVAL;
}

Expand Down Expand Up @@ -1515,7 +1515,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
(iocb->aio_nbytes != (size_t)iocb->aio_nbytes) ||
((ssize_t)iocb->aio_nbytes < 0)
)) {
pr_debug("EINVAL: io_submit: overflow check\n");
pr_debug("EINVAL: overflow check\n");
return -EINVAL;
}

Expand Down
8 changes: 6 additions & 2 deletions fs/autofs4/dev-ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ static int check_dev_ioctl_version(int cmd, struct autofs_dev_ioctl *param)
*/
static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *in)
{
struct autofs_dev_ioctl tmp;
struct autofs_dev_ioctl tmp, *res;

if (copy_from_user(&tmp, in, sizeof(tmp)))
return ERR_PTR(-EFAULT);
Expand All @@ -106,7 +106,11 @@ static struct autofs_dev_ioctl *copy_dev_ioctl(struct autofs_dev_ioctl __user *i
if (tmp.size > (PATH_MAX + sizeof(tmp)))
return ERR_PTR(-ENAMETOOLONG);

return memdup_user(in, tmp.size);
res = memdup_user(in, tmp.size);
if (!IS_ERR(res))
res->size = tmp.size;

return res;
}

static inline void free_dev_ioctl(struct autofs_dev_ioctl *param)
Expand Down
2 changes: 1 addition & 1 deletion fs/autofs4/expire.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ static struct dentry *should_expire(struct dentry *dentry,
return NULL;
}

if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) {
if (dentry->d_inode && d_is_symlink(dentry)) {
DPRINTK("checking symlink %p %pd", dentry, dentry);
/*
* A symlink can't be "busy" in the usual sense so
Expand Down
6 changes: 3 additions & 3 deletions fs/autofs4/root.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
struct dentry *dentry = file->f_path.dentry;
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);

DPRINTK("file=%p dentry=%p %pD", file, dentry, dentry);
DPRINTK("file=%p dentry=%p %pd", file, dentry, dentry);

if (autofs4_oz_mode(sbi))
goto out;
Expand Down Expand Up @@ -371,7 +371,7 @@ static struct vfsmount *autofs4_d_automount(struct path *path)
* having d_mountpoint() true, so there's no need to call back
* to the daemon.
*/
if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) {
if (dentry->d_inode && d_is_symlink(dentry)) {
spin_unlock(&sbi->fs_lock);
goto done;
}
Expand Down Expand Up @@ -485,7 +485,7 @@ static int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
* an incorrect ELOOP error return.
*/
if ((!d_mountpoint(dentry) && !simple_empty(dentry)) ||
(dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)))
(dentry->d_inode && d_is_symlink(dentry)))
status = -EISDIR;
}
spin_unlock(&sbi->fs_lock);
Expand Down
Loading

0 comments on commit be5e661

Please sign in to comment.