719f5d7f0b
Add a unique ID to each peer group using the IDR infrastructure. The identifiers are reused after the peer group dissolves. The IDR structures are protected by holding namepspace_sem for write while allocating or deallocating IDs. IDs are allocated when a previously unshared vfsmount becomes the first member of a peer group. When a new member is added to an existing group, the ID is copied from one of the old members. IDs are freed when the last member of a peer group is unshared. Setting the MNT_SHARED flag on members of a subtree is done as a separate step, after all the IDs have been allocated. This way an allocation failure can be cleaned up easilty, without affecting the propagation state. Based on design sketch by Al Viro. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
119 lines
3.6 KiB
C
119 lines
3.6 KiB
C
/*
|
|
*
|
|
* Definitions for mount interface. This describes the in the kernel build
|
|
* linkedlist with mounted filesystems.
|
|
*
|
|
* Author: Marco van Wieringen <mvw@planets.elm.net>
|
|
*
|
|
* Version: $Id: mount.h,v 2.0 1996/11/17 16:48:14 mvw Exp mvw $
|
|
*
|
|
*/
|
|
#ifndef _LINUX_MOUNT_H
|
|
#define _LINUX_MOUNT_H
|
|
#ifdef __KERNEL__
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/list.h>
|
|
#include <linux/nodemask.h>
|
|
#include <linux/spinlock.h>
|
|
#include <asm/atomic.h>
|
|
|
|
struct super_block;
|
|
struct vfsmount;
|
|
struct dentry;
|
|
struct mnt_namespace;
|
|
|
|
#define MNT_NOSUID 0x01
|
|
#define MNT_NODEV 0x02
|
|
#define MNT_NOEXEC 0x04
|
|
#define MNT_NOATIME 0x08
|
|
#define MNT_NODIRATIME 0x10
|
|
#define MNT_RELATIME 0x20
|
|
#define MNT_READONLY 0x40 /* does the user want this to be r/o? */
|
|
|
|
#define MNT_SHRINKABLE 0x100
|
|
#define MNT_IMBALANCED_WRITE_COUNT 0x200 /* just for debugging */
|
|
|
|
#define MNT_SHARED 0x1000 /* if the vfsmount is a shared mount */
|
|
#define MNT_UNBINDABLE 0x2000 /* if the vfsmount is a unbindable mount */
|
|
#define MNT_PNODE_MASK 0x3000 /* propagation flag mask */
|
|
|
|
struct vfsmount {
|
|
struct list_head mnt_hash;
|
|
struct vfsmount *mnt_parent; /* fs we are mounted on */
|
|
struct dentry *mnt_mountpoint; /* dentry of mountpoint */
|
|
struct dentry *mnt_root; /* root of the mounted tree */
|
|
struct super_block *mnt_sb; /* pointer to superblock */
|
|
struct list_head mnt_mounts; /* list of children, anchored here */
|
|
struct list_head mnt_child; /* and going through their mnt_child */
|
|
int mnt_flags;
|
|
/* 4 bytes hole on 64bits arches */
|
|
char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */
|
|
struct list_head mnt_list;
|
|
struct list_head mnt_expire; /* link in fs-specific expiry list */
|
|
struct list_head mnt_share; /* circular list of shared mounts */
|
|
struct list_head mnt_slave_list;/* list of slave mounts */
|
|
struct list_head mnt_slave; /* slave list entry */
|
|
struct vfsmount *mnt_master; /* slave is on master->mnt_slave_list */
|
|
struct mnt_namespace *mnt_ns; /* containing namespace */
|
|
int mnt_id; /* mount identifier */
|
|
int mnt_group_id; /* peer group identifier */
|
|
/*
|
|
* We put mnt_count & mnt_expiry_mark at the end of struct vfsmount
|
|
* to let these frequently modified fields in a separate cache line
|
|
* (so that reads of mnt_flags wont ping-pong on SMP machines)
|
|
*/
|
|
atomic_t mnt_count;
|
|
int mnt_expiry_mark; /* true if marked for expiry */
|
|
int mnt_pinned;
|
|
int mnt_ghosts;
|
|
/*
|
|
* This value is not stable unless all of the mnt_writers[] spinlocks
|
|
* are held, and all mnt_writer[]s on this mount have 0 as their ->count
|
|
*/
|
|
atomic_t __mnt_writers;
|
|
};
|
|
|
|
static inline struct vfsmount *mntget(struct vfsmount *mnt)
|
|
{
|
|
if (mnt)
|
|
atomic_inc(&mnt->mnt_count);
|
|
return mnt;
|
|
}
|
|
|
|
extern int mnt_want_write(struct vfsmount *mnt);
|
|
extern void mnt_drop_write(struct vfsmount *mnt);
|
|
extern void mntput_no_expire(struct vfsmount *mnt);
|
|
extern void mnt_pin(struct vfsmount *mnt);
|
|
extern void mnt_unpin(struct vfsmount *mnt);
|
|
extern int __mnt_is_readonly(struct vfsmount *mnt);
|
|
|
|
static inline void mntput(struct vfsmount *mnt)
|
|
{
|
|
if (mnt) {
|
|
mnt->mnt_expiry_mark = 0;
|
|
mntput_no_expire(mnt);
|
|
}
|
|
}
|
|
|
|
extern struct vfsmount *do_kern_mount(const char *fstype, int flags,
|
|
const char *name, void *data);
|
|
|
|
struct file_system_type;
|
|
extern struct vfsmount *vfs_kern_mount(struct file_system_type *type,
|
|
int flags, const char *name,
|
|
void *data);
|
|
|
|
struct nameidata;
|
|
|
|
extern int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd,
|
|
int mnt_flags, struct list_head *fslist);
|
|
|
|
extern void mark_mounts_for_expiry(struct list_head *mounts);
|
|
|
|
extern spinlock_t vfsmount_lock;
|
|
extern dev_t name_to_dev_t(char *name);
|
|
|
|
#endif
|
|
#endif /* _LINUX_MOUNT_H */
|