diff options
Diffstat (limited to 'fs/aufs/super.h')
-rw-r--r-- | fs/aufs/super.h | 635 |
1 files changed, 0 insertions, 635 deletions
diff --git a/fs/aufs/super.h b/fs/aufs/super.h deleted file mode 100644 index 95ffbbb29..000000000 --- a/fs/aufs/super.h +++ /dev/null @@ -1,635 +0,0 @@ -/* - * Copyright (C) 2005-2015 Junjiro R. Okajima - * - * This program, aufs 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; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* - * super_block operations - */ - -#ifndef __AUFS_SUPER_H__ -#define __AUFS_SUPER_H__ - -#ifdef __KERNEL__ - -#include <linux/fs.h> -#include <linux/kobject.h> -#include "rwsem.h" -#include "spl.h" -#include "wkq.h" - -/* policies to select one among multiple writable branches */ -struct au_wbr_copyup_operations { - int (*copyup)(struct dentry *dentry); -}; - -#define AuWbr_DIR 1 /* target is a dir */ -#define AuWbr_PARENT (1 << 1) /* always require a parent */ - -#define au_ftest_wbr(flags, name) ((flags) & AuWbr_##name) -#define au_fset_wbr(flags, name) { (flags) |= AuWbr_##name; } -#define au_fclr_wbr(flags, name) { (flags) &= ~AuWbr_##name; } - -struct au_wbr_create_operations { - int (*create)(struct dentry *dentry, unsigned int flags); - int (*init)(struct super_block *sb); - int (*fin)(struct super_block *sb); -}; - -struct au_wbr_mfs { - struct mutex mfs_lock; /* protect this structure */ - unsigned long mfs_jiffy; - unsigned long mfs_expire; - aufs_bindex_t mfs_bindex; - - unsigned long long mfsrr_bytes; - unsigned long long mfsrr_watermark; -}; - -struct pseudo_link { - union { - struct hlist_node hlist; - struct rcu_head rcu; - }; - struct inode *inode; -}; - -#define AuPlink_NHASH 100 -static inline int au_plink_hash(ino_t ino) -{ - return ino % AuPlink_NHASH; -} - -/* File-based Hierarchical Storage Management */ -struct au_fhsm { -#ifdef CONFIG_AUFS_FHSM - /* allow only one process who can receive the notification */ - spinlock_t fhsm_spin; - pid_t fhsm_pid; - wait_queue_head_t fhsm_wqh; - atomic_t fhsm_readable; - - /* these are protected by si_rwsem */ - unsigned long fhsm_expire; - aufs_bindex_t fhsm_bottom; -#endif -}; - -struct au_branch; -struct au_sbinfo { - /* nowait tasks in the system-wide workqueue */ - struct au_nowait_tasks si_nowait; - - /* - * tried sb->s_umount, but failed due to the dependecy between i_mutex. - * rwsem for au_sbinfo is necessary. - */ - struct au_rwsem si_rwsem; - - /* prevent recursive locking in deleting inode */ - struct { - unsigned long *bitmap; - spinlock_t tree_lock; - struct radix_tree_root tree; - } au_si_pid; - - /* - * dirty approach to protect sb->sb_inodes and ->s_files (gone) from - * remount. - */ - atomic_long_t si_ninodes, si_nfiles; - - /* branch management */ - unsigned int si_generation; - - /* see AuSi_ flags */ - unsigned char au_si_status; - - aufs_bindex_t si_bend; - - /* dirty trick to keep br_id plus */ - unsigned int si_last_br_id : - sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1; - struct au_branch **si_branch; - - /* policy to select a writable branch */ - unsigned char si_wbr_copyup; - unsigned char si_wbr_create; - struct au_wbr_copyup_operations *si_wbr_copyup_ops; - struct au_wbr_create_operations *si_wbr_create_ops; - - /* round robin */ - atomic_t si_wbr_rr_next; - - /* most free space */ - struct au_wbr_mfs si_wbr_mfs; - - /* File-based Hierarchical Storage Management */ - struct au_fhsm si_fhsm; - - /* mount flags */ - /* include/asm-ia64/siginfo.h defines a macro named si_flags */ - unsigned int si_mntflags; - - /* external inode number (bitmap and translation table) */ - vfs_readf_t si_xread; - vfs_writef_t si_xwrite; - struct file *si_xib; - struct mutex si_xib_mtx; /* protect xib members */ - unsigned long *si_xib_buf; - unsigned long si_xib_last_pindex; - int si_xib_next_bit; - aufs_bindex_t si_xino_brid; - unsigned long si_xino_jiffy; - unsigned long si_xino_expire; - /* reserved for future use */ - /* unsigned long long si_xib_limit; */ /* Max xib file size */ - -#ifdef CONFIG_AUFS_EXPORT - /* i_generation */ - struct file *si_xigen; - atomic_t si_xigen_next; -#endif - - /* dirty trick to suppoer atomic_open */ - struct au_sphlhead si_aopen; - - /* vdir parameters */ - unsigned long si_rdcache; /* max cache time in jiffies */ - unsigned int si_rdblk; /* deblk size */ - unsigned int si_rdhash; /* hash size */ - - /* - * If the number of whiteouts are larger than si_dirwh, leave all of - * them after au_whtmp_ren to reduce the cost of rmdir(2). - * future fsck.aufs or kernel thread will remove them later. - * Otherwise, remove all whiteouts and the dir in rmdir(2). - */ - unsigned int si_dirwh; - - /* pseudo_link list */ - struct au_sphlhead si_plink[AuPlink_NHASH]; - wait_queue_head_t si_plink_wq; - spinlock_t si_plink_maint_lock; - pid_t si_plink_maint_pid; - - /* file list */ - struct au_sphlhead si_files; - - /* - * sysfs and lifetime management. - * this is not a small structure and it may be a waste of memory in case - * of sysfs is disabled, particulary when many aufs-es are mounted. - * but using sysfs is majority. - */ - struct kobject si_kobj; -#ifdef CONFIG_DEBUG_FS - struct dentry *si_dbgaufs; - struct dentry *si_dbgaufs_plink; - struct dentry *si_dbgaufs_xib; -#ifdef CONFIG_AUFS_EXPORT - struct dentry *si_dbgaufs_xigen; -#endif -#endif - -#ifdef CONFIG_AUFS_SBILIST - struct list_head si_list; -#endif - - /* dirty, necessary for unmounting, sysfs and sysrq */ - struct super_block *si_sb; -}; - -/* sbinfo status flags */ -/* - * set true when refresh_dirs() failed at remount time. - * then try refreshing dirs at access time again. - * if it is false, refreshing dirs at access time is unnecesary - */ -#define AuSi_FAILED_REFRESH_DIR 1 - -#define AuSi_FHSM (1 << 1) /* fhsm is active now */ - -#ifndef CONFIG_AUFS_FHSM -#undef AuSi_FHSM -#define AuSi_FHSM 0 -#endif - -static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi, - unsigned int flag) -{ - AuRwMustAnyLock(&sbi->si_rwsem); - return sbi->au_si_status & flag; -} -#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name) -#define au_fset_si(sbinfo, name) do { \ - AuRwMustWriteLock(&(sbinfo)->si_rwsem); \ - (sbinfo)->au_si_status |= AuSi_##name; \ -} while (0) -#define au_fclr_si(sbinfo, name) do { \ - AuRwMustWriteLock(&(sbinfo)->si_rwsem); \ - (sbinfo)->au_si_status &= ~AuSi_##name; \ -} while (0) - -/* ---------------------------------------------------------------------- */ - -/* policy to select one among writable branches */ -#define AuWbrCopyup(sbinfo, ...) \ - ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__)) -#define AuWbrCreate(sbinfo, ...) \ - ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__)) - -/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */ -#define AuLock_DW 1 /* write-lock dentry */ -#define AuLock_IR (1 << 1) /* read-lock inode */ -#define AuLock_IW (1 << 2) /* write-lock inode */ -#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */ -#define AuLock_DIR (1 << 4) /* target is a dir */ -#define AuLock_NOPLM (1 << 5) /* return err in plm mode */ -#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */ -#define AuLock_GEN (1 << 7) /* test digen/iigen */ -#define au_ftest_lock(flags, name) ((flags) & AuLock_##name) -#define au_fset_lock(flags, name) \ - do { (flags) |= AuLock_##name; } while (0) -#define au_fclr_lock(flags, name) \ - do { (flags) &= ~AuLock_##name; } while (0) - -/* ---------------------------------------------------------------------- */ - -/* super.c */ -extern struct file_system_type aufs_fs_type; -struct inode *au_iget_locked(struct super_block *sb, ino_t ino); -typedef unsigned long long (*au_arraycb_t)(void *array, unsigned long long max, - void *arg); -void au_array_free(void *array); -void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg); -struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max); -void au_iarray_free(struct inode **a, unsigned long long max); - -/* sbinfo.c */ -void au_si_free(struct kobject *kobj); -int au_si_alloc(struct super_block *sb); -int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr); - -unsigned int au_sigen_inc(struct super_block *sb); -aufs_bindex_t au_new_br_id(struct super_block *sb); - -int si_read_lock(struct super_block *sb, int flags); -int si_write_lock(struct super_block *sb, int flags); -int aufs_read_lock(struct dentry *dentry, int flags); -void aufs_read_unlock(struct dentry *dentry, int flags); -void aufs_write_lock(struct dentry *dentry); -void aufs_write_unlock(struct dentry *dentry); -int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags); -void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2); - -int si_pid_test_slow(struct super_block *sb); -void si_pid_set_slow(struct super_block *sb); -void si_pid_clr_slow(struct super_block *sb); - -/* wbr_policy.c */ -extern struct au_wbr_copyup_operations au_wbr_copyup_ops[]; -extern struct au_wbr_create_operations au_wbr_create_ops[]; -int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst); -int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex); -int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t bstart); - -/* mvdown.c */ -int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *arg); - -#ifdef CONFIG_AUFS_FHSM -/* fhsm.c */ - -static inline pid_t au_fhsm_pid(struct au_fhsm *fhsm) -{ - pid_t pid; - - spin_lock(&fhsm->fhsm_spin); - pid = fhsm->fhsm_pid; - spin_unlock(&fhsm->fhsm_spin); - - return pid; -} - -void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force); -void au_fhsm_wrote_all(struct super_block *sb, int force); -int au_fhsm_fd(struct super_block *sb, int oflags); -int au_fhsm_br_alloc(struct au_branch *br); -void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex); -void au_fhsm_fin(struct super_block *sb); -void au_fhsm_init(struct au_sbinfo *sbinfo); -void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec); -void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo); -#else -AuStubVoid(au_fhsm_wrote, struct super_block *sb, aufs_bindex_t bindex, - int force) -AuStubVoid(au_fhsm_wrote_all, struct super_block *sb, int force) -AuStub(int, au_fhsm_fd, return -EOPNOTSUPP, struct super_block *sb, int oflags) -AuStub(pid_t, au_fhsm_pid, return 0, struct au_fhsm *fhsm) -AuStubInt0(au_fhsm_br_alloc, struct au_branch *br) -AuStubVoid(au_fhsm_set_bottom, struct super_block *sb, aufs_bindex_t bindex) -AuStubVoid(au_fhsm_fin, struct super_block *sb) -AuStubVoid(au_fhsm_init, struct au_sbinfo *sbinfo) -AuStubVoid(au_fhsm_set, struct au_sbinfo *sbinfo, unsigned int sec) -AuStubVoid(au_fhsm_show, struct seq_file *seq, struct au_sbinfo *sbinfo) -#endif - -/* ---------------------------------------------------------------------- */ - -static inline struct au_sbinfo *au_sbi(struct super_block *sb) -{ - return sb->s_fs_info; -} - -/* ---------------------------------------------------------------------- */ - -#ifdef CONFIG_AUFS_EXPORT -int au_test_nfsd(void); -void au_export_init(struct super_block *sb); -void au_xigen_inc(struct inode *inode); -int au_xigen_new(struct inode *inode); -int au_xigen_set(struct super_block *sb, struct file *base); -void au_xigen_clr(struct super_block *sb); - -static inline int au_busy_or_stale(void) -{ - if (!au_test_nfsd()) - return -EBUSY; - return -ESTALE; -} -#else -AuStubInt0(au_test_nfsd, void) -AuStubVoid(au_export_init, struct super_block *sb) -AuStubVoid(au_xigen_inc, struct inode *inode) -AuStubInt0(au_xigen_new, struct inode *inode) -AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base) -AuStubVoid(au_xigen_clr, struct super_block *sb) -AuStub(int, au_busy_or_stale, return -EBUSY, void) -#endif /* CONFIG_AUFS_EXPORT */ - -/* ---------------------------------------------------------------------- */ - -#ifdef CONFIG_AUFS_SBILIST -/* module.c */ -extern struct au_splhead au_sbilist; - -static inline void au_sbilist_init(void) -{ - au_spl_init(&au_sbilist); -} - -static inline void au_sbilist_add(struct super_block *sb) -{ - au_spl_add(&au_sbi(sb)->si_list, &au_sbilist); -} - -static inline void au_sbilist_del(struct super_block *sb) -{ - au_spl_del(&au_sbi(sb)->si_list, &au_sbilist); -} - -#ifdef CONFIG_AUFS_MAGIC_SYSRQ -static inline void au_sbilist_lock(void) -{ - spin_lock(&au_sbilist.spin); -} - -static inline void au_sbilist_unlock(void) -{ - spin_unlock(&au_sbilist.spin); -} -#define AuGFP_SBILIST GFP_ATOMIC -#else -AuStubVoid(au_sbilist_lock, void) -AuStubVoid(au_sbilist_unlock, void) -#define AuGFP_SBILIST GFP_NOFS -#endif /* CONFIG_AUFS_MAGIC_SYSRQ */ -#else -AuStubVoid(au_sbilist_init, void) -AuStubVoid(au_sbilist_add, struct super_block *sb) -AuStubVoid(au_sbilist_del, struct super_block *sb) -AuStubVoid(au_sbilist_lock, void) -AuStubVoid(au_sbilist_unlock, void) -#define AuGFP_SBILIST GFP_NOFS -#endif - -/* ---------------------------------------------------------------------- */ - -static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo) -{ - /* - * This function is a dynamic '__init' function actually, - * so the tiny check for si_rwsem is unnecessary. - */ - /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ -#ifdef CONFIG_DEBUG_FS - sbinfo->si_dbgaufs = NULL; - sbinfo->si_dbgaufs_plink = NULL; - sbinfo->si_dbgaufs_xib = NULL; -#ifdef CONFIG_AUFS_EXPORT - sbinfo->si_dbgaufs_xigen = NULL; -#endif -#endif -} - -/* ---------------------------------------------------------------------- */ - -static inline pid_t si_pid_bit(void) -{ - /* the origin of pid is 1, but the bitmap's is 0 */ - return current->pid - 1; -} - -static inline int si_pid_test(struct super_block *sb) -{ - pid_t bit; - - bit = si_pid_bit(); - if (bit < PID_MAX_DEFAULT) - return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap); - return si_pid_test_slow(sb); -} - -static inline void si_pid_set(struct super_block *sb) -{ - pid_t bit; - - bit = si_pid_bit(); - if (bit < PID_MAX_DEFAULT) { - AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap)); - set_bit(bit, au_sbi(sb)->au_si_pid.bitmap); - /* smp_mb(); */ - } else - si_pid_set_slow(sb); -} - -static inline void si_pid_clr(struct super_block *sb) -{ - pid_t bit; - - bit = si_pid_bit(); - if (bit < PID_MAX_DEFAULT) { - AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap)); - clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap); - /* smp_mb(); */ - } else - si_pid_clr_slow(sb); -} - -/* ---------------------------------------------------------------------- */ - -/* lock superblock. mainly for entry point functions */ -/* - * __si_read_lock, __si_write_lock, - * __si_read_unlock, __si_write_unlock, __si_downgrade_lock - */ -AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem); - -#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem) -#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem) -#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem) - -static inline void si_noflush_read_lock(struct super_block *sb) -{ - __si_read_lock(sb); - si_pid_set(sb); -} - -static inline int si_noflush_read_trylock(struct super_block *sb) -{ - int locked; - - locked = __si_read_trylock(sb); - if (locked) - si_pid_set(sb); - return locked; -} - -static inline void si_noflush_write_lock(struct super_block *sb) -{ - __si_write_lock(sb); - si_pid_set(sb); -} - -static inline int si_noflush_write_trylock(struct super_block *sb) -{ - int locked; - - locked = __si_write_trylock(sb); - if (locked) - si_pid_set(sb); - return locked; -} - -#if 0 /* reserved */ -static inline int si_read_trylock(struct super_block *sb, int flags) -{ - if (au_ftest_lock(flags, FLUSH)) - au_nwt_flush(&au_sbi(sb)->si_nowait); - return si_noflush_read_trylock(sb); -} -#endif - -static inline void si_read_unlock(struct super_block *sb) -{ - si_pid_clr(sb); - __si_read_unlock(sb); -} - -#if 0 /* reserved */ -static inline int si_write_trylock(struct super_block *sb, int flags) -{ - if (au_ftest_lock(flags, FLUSH)) - au_nwt_flush(&au_sbi(sb)->si_nowait); - return si_noflush_write_trylock(sb); -} -#endif - -static inline void si_write_unlock(struct super_block *sb) -{ - si_pid_clr(sb); - __si_write_unlock(sb); -} - -#if 0 /* reserved */ -static inline void si_downgrade_lock(struct super_block *sb) -{ - __si_downgrade_lock(sb); -} -#endif - -/* ---------------------------------------------------------------------- */ - -static inline aufs_bindex_t au_sbend(struct super_block *sb) -{ - SiMustAnyLock(sb); - return au_sbi(sb)->si_bend; -} - -static inline unsigned int au_mntflags(struct super_block *sb) -{ - SiMustAnyLock(sb); - return au_sbi(sb)->si_mntflags; -} - -static inline unsigned int au_sigen(struct super_block *sb) -{ - SiMustAnyLock(sb); - return au_sbi(sb)->si_generation; -} - -static inline void au_ninodes_inc(struct super_block *sb) -{ - atomic_long_inc(&au_sbi(sb)->si_ninodes); -} - -static inline void au_ninodes_dec(struct super_block *sb) -{ - AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_ninodes)); - atomic_long_dec(&au_sbi(sb)->si_ninodes); -} - -static inline void au_nfiles_inc(struct super_block *sb) -{ - atomic_long_inc(&au_sbi(sb)->si_nfiles); -} - -static inline void au_nfiles_dec(struct super_block *sb) -{ - AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_nfiles)); - atomic_long_dec(&au_sbi(sb)->si_nfiles); -} - -static inline struct au_branch *au_sbr(struct super_block *sb, - aufs_bindex_t bindex) -{ - SiMustAnyLock(sb); - return au_sbi(sb)->si_branch[0 + bindex]; -} - -static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid) -{ - SiMustWriteLock(sb); - au_sbi(sb)->si_xino_brid = brid; -} - -static inline aufs_bindex_t au_xino_brid(struct super_block *sb) -{ - SiMustAnyLock(sb); - return au_sbi(sb)->si_xino_brid; -} - -#endif /* __KERNEL__ */ -#endif /* __AUFS_SUPER_H__ */ |