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

Commit 4f46acce authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
  [patch 2/3] vfs: dcache cleanups
  [patch 1/3] vfs: dcache sparse fixes
  [patch 3/3] vfs: make d_path() consistent across mount operations
  [patch 4/4] flock: remove unused fields from file_lock_operations
  [patch 3/4] vfs: fix ERR_PTR abuse in generic_readlink
  [patch 2/4] fs: make struct file arg to d_path const
  [patch 1/4] vfs: path_{get,put}() cleanups
  [patch for 2.6.26 4/4] vfs: utimensat(): fix write access check for futimens()
  [patch for 2.6.26 3/4] vfs: utimensat(): fix error checking for {UTIME_NOW,UTIME_OMIT} case
  [patch for 2.6.26 1/4] vfs: utimensat(): ignore tv_sec if tv_nsec == UTIME_OMIT or UTIME_NOW
  [patch for 2.6.26 2/4] vfs: utimensat(): be consistent with utime() for immutable and append-only files
  [PATCH] fix cgroup-inflicted breakage in block_dev.c
parents 543cf4cb cdd16d02
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -931,8 +931,16 @@ static int do_open(struct block_device *bdev, struct file *file, int for_part)
	struct gendisk *disk;
	int ret;
	int part;
	int perm = 0;

	ret = devcgroup_inode_permission(bdev->bd_inode, file->f_mode);
	if (file->f_mode & FMODE_READ)
		perm |= MAY_READ;
	if (file->f_mode & FMODE_WRITE)
		perm |= MAY_WRITE;
	/*
	 * hooks: /n/, see "layering violations".
	 */
	ret = devcgroup_inode_permission(bdev->bd_inode, perm);
	if (ret != 0)
		return ret;

+34 −34
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/syscalls.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/fdtable.h>
#include <linux/fs.h>
#include <linux/fsnotify.h>
#include <linux/slab.h>
@@ -106,9 +107,10 @@ static void dentry_lru_remove(struct dentry *dentry)
/*
 * Release the dentry's inode, using the filesystem
 * d_iput() operation if defined.
 * Called with dcache_lock and per dentry lock held, drops both.
 */
static void dentry_iput(struct dentry * dentry)
	__releases(dentry->d_lock)
	__releases(dcache_lock)
{
	struct inode *inode = dentry->d_inode;
	if (inode) {
@@ -132,12 +134,13 @@ static void dentry_iput(struct dentry * dentry)
 * d_kill - kill dentry and return parent
 * @dentry: dentry to kill
 *
 * Called with dcache_lock and d_lock, releases both.  The dentry must
 * already be unhashed and removed from the LRU.
 * The dentry must already be unhashed and removed from the LRU.
 *
 * If this is the root of the dentry tree, return NULL.
 */
static struct dentry *d_kill(struct dentry *dentry)
	__releases(dentry->d_lock)
	__releases(dcache_lock)
{
	struct dentry *parent;

@@ -383,11 +386,11 @@ void d_prune_aliases(struct inode *inode)
 * Try to prune ancestors as well.  This is necessary to prevent
 * quadratic behavior of shrink_dcache_parent(), but is also expected
 * to be beneficial in reducing dentry cache fragmentation.
 *
 * Called with dcache_lock, drops it and then regains.
 * Called with dentry->d_lock held, drops it.
 */
static void prune_one_dentry(struct dentry * dentry)
	__releases(dentry->d_lock)
	__releases(dcache_lock)
	__acquires(dcache_lock)
{
	__d_drop(dentry);
	dentry = d_kill(dentry);
@@ -1604,10 +1607,9 @@ static int d_isparent(struct dentry *p1, struct dentry *p2)
 *
 * Note: If ever the locking in lock_rename() changes, then please
 * remember to update this too...
 *
 * On return, dcache_lock will have been unlocked.
 */
static struct dentry *__d_unalias(struct dentry *dentry, struct dentry *alias)
	__releases(dcache_lock)
{
	struct mutex *m1 = NULL, *m2 = NULL;
	struct dentry *ret;
@@ -1743,11 +1745,9 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
shouldnt_be_hashed:
	spin_unlock(&dcache_lock);
	BUG();
	goto shouldnt_be_hashed;
}

static int prepend(char **buffer, int *buflen, const char *str,
			  int namelen)
static int prepend(char **buffer, int *buflen, const char *str, int namelen)
{
	*buflen -= namelen;
	if (*buflen < 0)
@@ -1757,8 +1757,13 @@ static int prepend(char **buffer, int *buflen, const char *str,
	return 0;
}

static int prepend_name(char **buffer, int *buflen, struct qstr *name)
{
	return prepend(buffer, buflen, name->name, name->len);
}

/**
 * d_path - return the path of a dentry
 * __d_path - return the path of a dentry
 * @path: the dentry/vfsmount to report
 * @root: root vfsmnt/dentry (may be modified by this function)
 * @buffer: buffer to return value in
@@ -1782,6 +1787,7 @@ char *__d_path(const struct path *path, struct path *root,
	char *end = buffer + buflen;
	char *retval;

	spin_lock(&vfsmount_lock);
	prepend(&end, &buflen, "\0", 1);
	if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
		(prepend(&end, &buflen, " (deleted)", 10) != 0))
@@ -1800,38 +1806,37 @@ char *__d_path(const struct path *path, struct path *root,
			break;
		if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
			/* Global root? */
			spin_lock(&vfsmount_lock);
			if (vfsmnt->mnt_parent == vfsmnt) {
				spin_unlock(&vfsmount_lock);
				goto global_root;
			}
			dentry = vfsmnt->mnt_mountpoint;
			vfsmnt = vfsmnt->mnt_parent;
			spin_unlock(&vfsmount_lock);
			continue;
		}
		parent = dentry->d_parent;
		prefetch(parent);
		if ((prepend(&end, &buflen, dentry->d_name.name,
				dentry->d_name.len) != 0) ||
		if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) ||
		    (prepend(&end, &buflen, "/", 1) != 0))
			goto Elong;
		retval = end;
		dentry = parent;
	}

out:
	spin_unlock(&vfsmount_lock);
	return retval;

global_root:
	retval += 1;	/* hit the slash */
	if (prepend(&retval, &buflen, dentry->d_name.name,
		    dentry->d_name.len) != 0)
	if (prepend_name(&retval, &buflen, &dentry->d_name) != 0)
		goto Elong;
	root->mnt = vfsmnt;
	root->dentry = dentry;
	return retval;
	goto out;

Elong:
	return ERR_PTR(-ENAMETOOLONG);
	retval = ERR_PTR(-ENAMETOOLONG);
	goto out;
}

/**
@@ -1845,9 +1850,9 @@ char *__d_path(const struct path *path, struct path *root,
 *
 * Returns the buffer or an error code if the path was too long.
 *
 * "buflen" should be positive. Caller holds the dcache_lock.
 * "buflen" should be positive.
 */
char *d_path(struct path *path, char *buf, int buflen)
char *d_path(const struct path *path, char *buf, int buflen)
{
	char *res;
	struct path root;
@@ -1915,16 +1920,11 @@ char *dentry_path(struct dentry *dentry, char *buf, int buflen)
	retval = end-1;
	*retval = '/';

	for (;;) {
		struct dentry *parent;
		if (IS_ROOT(dentry))
			break;
	while (!IS_ROOT(dentry)) {
		struct dentry *parent = dentry->d_parent;

		parent = dentry->d_parent;
		prefetch(parent);

		if ((prepend(&end, &buflen, dentry->d_name.name,
				dentry->d_name.len) != 0) ||
		if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) ||
		    (prepend(&end, &buflen, "/", 1) != 0))
			goto Elong;

@@ -1975,7 +1975,7 @@ asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
	error = -ENOENT;
	/* Has the current directory has been unlinked? */
	spin_lock(&dcache_lock);
	if (pwd.dentry->d_parent == pwd.dentry || !d_unhashed(pwd.dentry)) {
	if (IS_ROOT(pwd.dentry) || !d_unhashed(pwd.dentry)) {
		unsigned long len;
		struct path tmp = root;
		char * cwd;
+0 −6
Original line number Diff line number Diff line
@@ -561,9 +561,6 @@ static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl)
	/* insert into file's list */
	fl->fl_next = *pos;
	*pos = fl;

	if (fl->fl_ops && fl->fl_ops->fl_insert)
		fl->fl_ops->fl_insert(fl);
}

/*
@@ -586,9 +583,6 @@ static void locks_delete_lock(struct file_lock **thisfl_p)
		fl->fl_fasync = NULL;
	}

	if (fl->fl_ops && fl->fl_ops->fl_remove)
		fl->fl_ops->fl_remove(fl);

	if (fl->fl_nspid) {
		put_pid(fl->fl_nspid);
		fl->fl_nspid = NULL;
+13 −13
Original line number Diff line number Diff line
@@ -581,15 +581,13 @@ static __always_inline int link_path_walk(const char *name, struct nameidata *nd
	int result;

	/* make sure the stuff we saved doesn't go away */
	dget(save.dentry);
	mntget(save.mnt);
	path_get(&save);

	result = __link_path_walk(name, nd);
	if (result == -ESTALE) {
		/* nd->path had been dropped */
		nd->path = save;
		dget(nd->path.dentry);
		mntget(nd->path.mnt);
		path_get(&nd->path);
		nd->flags |= LOOKUP_REVAL;
		result = __link_path_walk(name, nd);
	}
@@ -1216,8 +1214,9 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
	nd->flags = flags;
	nd->depth = 0;

	nd->path.mnt = mntget(mnt);
	nd->path.dentry = dget(dentry);
	nd->path.dentry = dentry;
	nd->path.mnt = mnt;
	path_get(&nd->path);

	retval = path_walk(name, nd);
	if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry &&
@@ -2857,16 +2856,17 @@ int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen)
{
	struct nameidata nd;
	void *cookie;
	int res;

	nd.depth = 0;
	cookie = dentry->d_inode->i_op->follow_link(dentry, &nd);
	if (!IS_ERR(cookie)) {
		int res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd));
	if (IS_ERR(cookie))
		return PTR_ERR(cookie);

	res = vfs_readlink(dentry, buffer, buflen, nd_get_link(&nd));
	if (dentry->d_inode->i_op->put_link)
		dentry->d_inode->i_op->put_link(dentry, &nd, cookie);
		cookie = ERR_PTR(res);
	}
	return PTR_ERR(cookie);
	return res;
}

int vfs_follow_link(struct nameidata *nd, const char *link)
+4 −6
Original line number Diff line number Diff line
@@ -1003,8 +1003,7 @@ struct file *create_write_pipe(void)
void free_write_pipe(struct file *f)
{
	free_pipe_info(f->f_dentry->d_inode);
	dput(f->f_path.dentry);
	mntput(f->f_path.mnt);
	path_put(&f->f_path);
	put_filp(f);
}

@@ -1015,8 +1014,8 @@ struct file *create_read_pipe(struct file *wrf)
		return ERR_PTR(-ENFILE);

	/* Grab pipe from the writer */
	f->f_path.mnt = mntget(wrf->f_path.mnt);
	f->f_path.dentry = dget(wrf->f_path.dentry);
	f->f_path = wrf->f_path;
	path_get(&wrf->f_path);
	f->f_mapping = wrf->f_path.dentry->d_inode->i_mapping;

	f->f_pos = 0;
@@ -1068,8 +1067,7 @@ int do_pipe(int *fd)
 err_fdr:
	put_unused_fd(fdr);
 err_read_pipe:
	dput(fr->f_dentry);
	mntput(fr->f_vfsmnt);
	path_put(&fr->f_path);
	put_filp(fr);
 err_write_pipe:
	free_write_pipe(fw);
Loading