Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit be5e6616 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
  ...
parents 90c453ca 0a280962
Loading
Loading
Loading
Loading
+0 −2
Original line number Original line Diff line number Diff line
@@ -164,8 +164,6 @@ the block device inode. See there for more details.


--------------------------- file_system_type ---------------------------
--------------------------- file_system_type ---------------------------
prototypes:
prototypes:
	int (*get_sb) (struct file_system_type *, int,
		       const char *, void *, struct vfsmount *);
	struct dentry *(*mount) (struct file_system_type *, int,
	struct dentry *(*mount) (struct file_system_type *, int,
		       const char *, void *);
		       const char *, void *);
	void (*kill_sb) (struct super_block *);
	void (*kill_sb) (struct super_block *);
+28 −0
Original line number Original line Diff line number Diff line
@@ -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).
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
Non-standard behavior
---------------------
---------------------


@@ -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,
filesystem are not allowed.  If the underlying filesystem is changed,
the behavior of the overlay is undefined, though it will not result in
the behavior of the overlay is undefined, though it will not result in
a crash or deadlock.
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
+25 −28
Original line number Original line Diff line number Diff line
@@ -74,7 +74,7 @@ static void hypfs_remove(struct dentry *dentry)
	parent = dentry->d_parent;
	parent = dentry->d_parent;
	mutex_lock(&parent->d_inode->i_mutex);
	mutex_lock(&parent->d_inode->i_mutex);
	if (hypfs_positive(dentry)) {
	if (hypfs_positive(dentry)) {
		if (S_ISDIR(dentry->d_inode->i_mode))
		if (d_is_dir(dentry))
			simple_rmdir(parent->d_inode, dentry);
			simple_rmdir(parent->d_inode, dentry);
		else
		else
			simple_unlink(parent->d_inode, dentry);
			simple_unlink(parent->d_inode, dentry);
@@ -144,36 +144,32 @@ static int hypfs_open(struct inode *inode, struct file *filp)
	return nonseekable_open(inode, filp);
	return nonseekable_open(inode, filp);
}
}


static ssize_t hypfs_aio_read(struct kiocb *iocb, const struct iovec *iov,
static ssize_t hypfs_read_iter(struct kiocb *iocb, struct iov_iter *to)
			      unsigned long nr_segs, loff_t offset)
{
{
	char *data;
	struct file *file = iocb->ki_filp;
	ssize_t ret;
	char *data = file->private_data;
	struct file *filp = iocb->ki_filp;
	size_t available = strlen(data);
	/* XXX: temporary */
	loff_t pos = iocb->ki_pos;
	char __user *buf = iov[0].iov_base;
	size_t count;
	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;

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


+1 −1
Original line number Original line Diff line number Diff line
@@ -277,7 +277,7 @@ static int remove_file(struct dentry *parent, char *name)
	}
	}


	spin_lock(&tmp->d_lock);
	spin_lock(&tmp->d_lock);
	if (!(d_unhashed(tmp) && tmp->d_inode)) {
	if (!d_unhashed(tmp) && tmp->d_inode) {
		dget_dlock(tmp);
		dget_dlock(tmp);
		__d_drop(tmp);
		__d_drop(tmp);
		spin_unlock(&tmp->d_lock);
		spin_unlock(&tmp->d_lock);
+1 −1
Original line number Original line Diff line number Diff line
@@ -455,7 +455,7 @@ static int remove_file(struct dentry *parent, char *name)
	}
	}


	spin_lock(&tmp->d_lock);
	spin_lock(&tmp->d_lock);
	if (!(d_unhashed(tmp) && tmp->d_inode)) {
	if (!d_unhashed(tmp) && tmp->d_inode) {
		__d_drop(tmp);
		__d_drop(tmp);
		spin_unlock(&tmp->d_lock);
		spin_unlock(&tmp->d_lock);
		simple_unlink(parent->d_inode, tmp);
		simple_unlink(parent->d_inode, tmp);
Loading