blob: 7413cb0eb542028eaff37b77279da28416797d67 [file] [log] [blame]
/* VFS-based union mounts for Linux
*
* Copyright (C) 2004-2007 IBM Corporation, IBM Deutschland Entwicklung GmbH.
* Copyright (C) 2007-2009 Novell Inc.
* Copyright (C) 2009-2012 Red Hat, Inc.
*
* Author(s): Jan Blunck (j.blunck@tu-harburg.de)
* Valerie Aurora <vaurora@redhat.com>
* David Howells <dhowells@redhat.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; version 2
* of the License.
*/
#include <linux/mount.h>
#ifdef CONFIG_UNION_MOUNT
#include <linux/dcache.h>
#include <linux/namei.h>
#include <linux/path.h>
#include <linux/bug.h>
/*
* WARNING! Confusing terminology alert.
*
* Note that the directions "up" and "down" in union mounts are the opposite of
* "up" and "down" in normal VFS operation terminology. "Up" in the rest of
* the VFS means "towards the root of the mount tree." If you mount B on top
* of A, following B "up" will get you A. In union mounts, "up" means "towards
* the most recently mounted layer of the union stack." If you union mount B
* on top of A, following A "up" will get you to B. Another way to put it is
* that "up" in the VFS means going from this mount towards the direction of
* its mnt->mnt_parent pointer, but "up" in union mounts means going in the
* opposite direction (until you run out of union layers).
*/
/*
* The union_stack structure. It is an array of struct paths of
* directories below the topmost directory in a unioned directory, The
* topmost dentry has a pointer to this structure. The topmost dentry
* can only be part of one union, so we can reference it from the
* dentry, but lower dentries can be part of multiple union stacks.
*
* The number of dirs actually allocated is kept in the superblock,
* s_union_count.
*/
struct union_stack {
struct path u_dirs[0];
};
static inline bool IS_MNT_UNION(struct vfsmount *mnt)
{
return mnt->mnt_flags & MNT_UNION;
}
static inline bool IS_MNT_LOWER(struct vfsmount *mnt)
{
return mnt->mnt_flags & MNT_UNION_LOWER;
}
static inline bool IS_DIR_UNIONED(struct dentry *dentry)
{
return !!dentry->d_union_stack;
}
extern void d_free_unions(struct dentry *);
extern int union_add_dir(struct path *, struct path *, unsigned int);
static inline
struct path *union_find_dir(struct dentry *dentry, unsigned int layer)
{
BUG_ON(layer >= dentry->d_sb->s_union_count);
return &dentry->d_union_stack->u_dirs[layer];
}
extern int union_create_topmost_dir(struct path *, struct path *, struct dentry *);
/*
* Determine whether we need to perform unionmount traversal or the copyup of a
* dentry.
*/
static inline
bool needs_lookup_union(struct nameidata *nd,
struct path *parent_path, struct path *path)
{
if (!IS_DIR_UNIONED(parent_path->dentry))
return false;
printk("UNION: is unioned\n");
/* Either already built or crossed a mountpoint to not-unioned mnt */
/* XXX are bind mounts root? think not */
if (IS_ROOT(path->dentry))
return false;
/* If this is a fallthru dentry and the caller requires the underlying
* inode to be copied up, then do so.
*/
if (nd->flags & LOOKUP_COPY_UP && d_is_fallthru(path->dentry))
return true;
/* It's okay not to have the lock; will recheck in lookup_union() */
/* XXX set for root dentry at mount? */
return !(path->dentry->d_flags & DCACHE_UNION_LOOKUP_DONE);
}
extern int __union_copyup_one_dir(struct path *);
#else /* CONFIG_UNION_MOUNT */
static inline bool IS_MNT_UNION(struct vfsmount *mnt) { return false; }
static inline bool IS_MNT_LOWER(struct vfsmount *mnt) { return false; }
static inline bool IS_DIR_UNIONED(struct dentry *dentry) { return false; }
static inline void d_free_unions(struct dentry *dentry) {}
static inline
int union_add_dir(struct path *topmost, struct path *lower, unsigned layer)
{
BUG();
return 0;
}
static inline struct path *union_find_dir(struct dentry *dentry, unsigned layer)
{
BUG();
return NULL;
}
static inline int union_create_topmost_dir(struct path *parent, struct qstr *name,
struct path *topmost, struct path *lower)
{
BUG();
return 0;
}
static inline bool needs_lookup_union(struct nameidata *nd,
struct path *parent_path, struct path *path)
{
return false;
}
static inline int __union_copyup_one_dir(struct path *topmost_path)
{
BUG();
return 0;
}
#endif /* CONFIG_UNION_MOUNT */
/*
* Make sure that an upper directory is opaque (ie. totally copied up if it is
* in fact unioned with some lower dirs).
*/
static inline int union_copyup_one_dir(struct path *path)
{
if (IS_OPAQUE(path->dentry->d_inode))
return 0;
return __union_copyup_one_dir(path);
}
extern struct inode *__union_get_inode_locked(struct dentry *parent,
struct path *upper,
struct path *_lower_cache,
struct path *_actual);
extern struct inode *__union_get_inode(struct path *upper,
struct path *_lower_cache,
struct path *_actual);
extern int __union_copy_up(struct path *path, struct path *actual,
const loff_t *truncate_to);
extern int __union_copy_up_locked(struct path *parent, struct path *path,
struct path *actual,
const loff_t *truncate_to);
static inline void path_put_maybe(struct path *path)
{
/* These optimise away if CONFIG_UNION_MOUNT=n */
if (unlikely(path->dentry))
dput(path->dentry);
if (unlikely(path->mnt))
mntput(path->mnt);
}
/**
* union_get_inode_locked - Get the actual inode and dentry for a dentry
* @parent: The locked parent of the object we're interested in.
* @path: The object we're interested in.
* @_lower_cache: Cache for lower dentry pinning.
* @_actual: The point actually corresponding to the returned inode.
*
* Gets the inode to be used for a dentry where that inode may exist on a lower
* layer in a union. Note that we don't get a ref on the inode, so to pin it
* temporarily, we may point *_lower at the lower dentry.
*
* The caller must hold i_mutex on the parent.
*
* Returns a pointer to the inode to use if a positive dentry is found, NULL if
* a negative dentry is found and an error if lookup in the lower layers
* failed.
*
* On a successful return (positive or negative dentry), *_actual will be set
* to point to the dentry that we determined was the one of interest. This
* does not hold any refs of its own.
*
* The caller should call path_put_maybe() on *_lower_cache to clear any pins
* it may contain.
*/
static inline struct inode *union_get_inode_locked(struct dentry *parent,
struct path *path,
struct path *_lower_cache,
struct path *_actual)
{
/* Optimise for the non-unionmount case. */
_lower_cache->dentry = NULL;
_lower_cache->mnt = NULL;
*_actual = *path;
#ifndef CONFIG_UNION_MOUNT
return path->dentry->d_inode;
#else
/* The normal case is that the inode is right where we expect... */
if (likely(path->dentry->d_inode))
return path->dentry->d_inode;
/* ... or the dentry is ordinarily negative. */
if (likely(!path->dentry->d_sb->s_union_lower_mnts))
return NULL;
if (d_is_whiteout(path->dentry) ||
(!d_is_fallthru(path->dentry) && IS_OPAQUE(parent->d_inode)))
return NULL;
/* We have to lock the parent and do a lookup. */
return __union_get_inode_locked(parent, path, _lower_cache, _actual);
#endif
}
/**
* union_get_inode - Get the actual inode and dentry for an object
* @path: The object we're interested in.
* @_lower_cache: Cache for lower dentry pinning.
* @_actual: The point actually corresponding to the returned inode.
*
* Gets the inode to be used for a dentry where that inode may exist on a lower
* layer in a union. Note that we don't get a ref on the inode, so to pin it
* temporarily, we may return a dentry in *_lower.
*
* Returns a pointer to the inode to use if a positive dentry is found, NULL if
* a negative dentry is found and an error if lookup in the lower layers
* failed.
*
* On a successful return (positive or negative dentry), *_actual will be set
* to point to the dentry that we determined was the one of interest. This
* does not have its own ref taken and thus does not need to be dput().
*/
static inline struct inode *union_get_inode(struct path *path,
struct path *_lower_cache,
struct path *_actual)
{
_lower_cache->mnt = NULL;
_lower_cache->dentry = NULL;
*_actual = *path;
#ifndef CONFIG_UNION_MOUNT
return path->dentry->d_inode;
#else
/* The normal case is that the inode is right where we expect... */
if (likely(path->dentry->d_inode))
return path->dentry->d_inode;
/* ... or the dentry is ordinarily negative. */
if (likely(!path->dentry->d_sb->s_union_lower_mnts))
return NULL;
if (d_is_whiteout(path->dentry))
return NULL;
/* We have to lock the parent and do a lookup. */
return __union_get_inode(path, _lower_cache, _actual);
#endif
}
/**
* union_truncated_copy_up - If needed, partially copy up a file (truncate)
* path: The target object.
* lower: The lower dentry (or NULL) from union_get_inode().
* truncate_to: The amount to copy up.
*/
static inline int union_truncated_copy_up(struct path *path, struct path *actual,
const loff_t *truncate_to)
{
#ifdef CONFIG_UNION_MOUNT
if (unlikely(!path->dentry->d_inode))
return __union_copy_up(path, actual, truncate_to);
#endif
return 0;
}
/**
* union_copy_up - If needed, copy up a file in its entirety
* path: The target object.
* lower: The lower dentry (or NULL) from union_get_inode().
*/
static inline int union_copy_up(struct path *path, struct path *actual)
{
#ifdef CONFIG_UNION_MOUNT
if (unlikely(!path->dentry->d_inode))
return __union_copy_up(path, actual, NULL);
#endif
return 0;
}
/**
* union_copy_up_locked - If needed, copy up a file, caller holds parent lock
* parent: The parent directory of the target object
* path: The target object.
* lower: The lower dentry (or NULL) from union_get_inode().
*
* The parent must hold i_mutex on the parent directory.
*/
static inline int union_copy_up_locked(struct path *parent, struct path *path,
struct path *actual)
{
#ifdef CONFIG_UNION_MOUNT
if (unlikely(!path->dentry->d_inode))
// return __union_copy_up_locked(parent, path, actual, true, 0);
return -ENOANO;
#endif
return 0;
}
extern int __union_copy_up_for_do_last(struct path *, struct path *, bool);
/**
* union_copy_up_do_last - If needed, copy up a file (maybe truncated)
* path: The target object.
* lower: The lower dentry (or NULL) from union_get_inode().
* will_truncate: Whether to honour O_TRUNC or not.
*/
static inline int union_copy_up_for_do_last(struct path *parent, struct path *path,
bool will_truncate)
{
#ifdef CONFIG_UNION_MOUNT
if (unlikely(!path->dentry->d_inode))
return __union_copy_up_for_do_last(parent, path, will_truncate);
#endif
return 0;
}
static inline bool d_is_unioned(const struct dentry *dentry, const struct path *actual)
{
#ifndef CONFIG_UNION_MOUNT
return false;
#else
return unlikely(dentry != actual->dentry);
#endif
}
static inline bool is_unioned(const struct dentry *dentry, const struct inode *inode)
{
#ifndef CONFIG_UNION_MOUNT
return false;
#else
return unlikely(dentry->d_inode != inode);
#endif
}
extern struct union_stack *union_alloc(struct path *topmost);