Commit f2ade007 authored by J. R. Okajima's avatar J. R. Okajima
Browse files

aufs: infos generation 2/2



The generation of iinfo and dinfo inherit sbinfo's.
Also iinfo generation tracks the branch inode's generation to test the
matching after the branch management.
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent fa25dbe6
...@@ -11,6 +11,7 @@ ccflags-y += -include ${srctree}/include/uapi/linux/aufs_type.h ...@@ -11,6 +11,7 @@ ccflags-y += -include ${srctree}/include/uapi/linux/aufs_type.h
obj-$(CONFIG_AUFS_FS) += aufs.o obj-$(CONFIG_AUFS_FS) += aufs.o
aufs-y := module.o sbinfo.o super.o \ aufs-y := module.o sbinfo.o super.o \
dcsub.o \ dcsub.o \
cpup.o \
dinfo.o \ dinfo.o \
iinfo.o iinfo.o
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "debug.h" #include "debug.h"
#include "cpup.h"
#include "dcsub.h" #include "dcsub.h"
#include "dentry.h" #include "dentry.h"
#include "fstype.h" #include "fstype.h"
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2005-2019 Junjiro R. Okajima
*/
/*
* copy-up functions, see wbr_policy.c for copy-down
*/
#include "aufs.h"
void au_cpup_igen(struct inode *inode, struct inode *h_inode)
{
struct au_iinfo *iinfo = au_ii(inode);
IiMustWriteLock(inode);
iinfo->ii_higen = h_inode->i_generation;
iinfo->ii_hsb1 = h_inode->i_sb;
}
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2005-2019 Junjiro R. Okajima
*/
/*
* copy-up/down functions
*/
#ifndef __AUFS_CPUP_H__
#define __AUFS_CPUP_H__
#ifdef __KERNEL__
struct inode;
void au_cpup_igen(struct inode *inode, struct inode *h_inode);
#endif /* __KERNEL__ */
#endif /* __AUFS_CPUP_H__ */
...@@ -90,8 +90,8 @@ void au_dpri_inode(struct inode *inode) ...@@ -90,8 +90,8 @@ void au_dpri_inode(struct inode *inode)
return; return;
iinfo = au_ii(inode); iinfo = au_ii(inode);
dpri("i-1: btop %d, bbot %d\n", dpri("i-1: btop %d, bbot %d, gen %d\n",
iinfo->ii_btop, iinfo->ii_bbot); iinfo->ii_btop, iinfo->ii_bbot, au_iigen(inode));
if (iinfo->ii_btop < 0) if (iinfo->ii_btop < 0)
return; return;
for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; bindex++) for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; bindex++)
...@@ -138,8 +138,9 @@ void au_dpri_dentry(struct dentry *dentry) ...@@ -138,8 +138,9 @@ void au_dpri_dentry(struct dentry *dentry)
dinfo = au_di(dentry); dinfo = au_di(dentry);
if (!dinfo) if (!dinfo)
return; return;
dpri("d-1: btop %d, bbot %d\n", dpri("d-1: btop %d, bbot %d, gen %d\n",
dinfo->di_btop, dinfo->di_bbot); dinfo->di_btop, dinfo->di_bbot,
au_digen(dentry));
if (dinfo->di_btop < 0) if (dinfo->di_btop < 0)
return; return;
for (bindex = dinfo->di_btop; bindex <= dinfo->di_bbot; bindex++) for (bindex = dinfo->di_btop; bindex <= dinfo->di_bbot; bindex++)
...@@ -181,3 +182,23 @@ void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line) ...@@ -181,3 +182,23 @@ void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line)
} }
} }
} }
void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
{
int err, i, j;
struct au_dcsub_pages dpages;
struct au_dpage *dpage;
struct dentry **dentries;
err = au_dpages_init(&dpages, GFP_NOFS);
AuDebugOn(err);
err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1);
AuDebugOn(err);
for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
dpage = dpages.dpages + i;
dentries = dpage->dentries;
for (j = dpage->ndentry - 1; !err && j >= 0; j--)
AuDebugOn(au_digen_test(dentries[j], sigen));
}
au_dpages_free(&dpages);
}
...@@ -75,6 +75,7 @@ void au_dpri_dentry(struct dentry *dentry); ...@@ -75,6 +75,7 @@ void au_dpri_dentry(struct dentry *dentry);
#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__) #define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__)
void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line); void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line);
void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
#define AuDbgInode(i) do { \ #define AuDbgInode(i) do { \
mutex_lock(&au_dbg_mtx); \ mutex_lock(&au_dbg_mtx); \
...@@ -98,6 +99,7 @@ void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line); ...@@ -98,6 +99,7 @@ void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line);
} while (0) } while (0)
#else #else
AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry) AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry)
AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
#define AuDbgInode(i) do {} while (0) #define AuDbgInode(i) do {} while (0)
#define AuDbgDAlias(i) do {} while (0) #define AuDbgDAlias(i) do {} while (0)
......
...@@ -20,6 +20,8 @@ struct au_hdentry { ...@@ -20,6 +20,8 @@ struct au_hdentry {
}; };
struct au_dinfo { struct au_dinfo {
atomic_t di_generation;
struct au_rwsem di_rwsem; struct au_rwsem di_rwsem;
aufs_bindex_t di_btop, di_bbot; aufs_bindex_t di_btop, di_bbot;
struct au_hdentry *di_hdentry; struct au_hdentry *di_hdentry;
...@@ -45,6 +47,8 @@ struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex); ...@@ -45,6 +47,8 @@ struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex, void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
struct dentry *h_dentry); struct dentry *h_dentry);
int au_digen_test(struct dentry *dentry, unsigned int sigen);
void au_update_digen(struct dentry *dentry);
void au_update_dbtop(struct dentry *dentry); void au_update_dbtop(struct dentry *dentry);
void au_update_dbbot(struct dentry *dentry); void au_update_dbbot(struct dentry *dentry);
...@@ -105,6 +109,12 @@ AuRWLockFuncs(parent3, PARENT3); ...@@ -105,6 +109,12 @@ AuRWLockFuncs(parent3, PARENT3);
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/* todo: memory barrier? */
static inline unsigned int au_digen(struct dentry *d)
{
return atomic_read(&au_di(d)->di_generation);
}
static inline void au_h_dentry_init(struct au_hdentry *hdentry) static inline void au_h_dentry_init(struct au_hdentry *hdentry)
{ {
hdentry->hd_dentry = NULL; hdentry->hd_dentry = NULL;
......
...@@ -67,9 +67,11 @@ int au_di_init(struct dentry *dentry) ...@@ -67,9 +67,11 @@ int au_di_init(struct dentry *dentry)
err = 0; err = 0;
sb = dentry->d_sb; sb = dentry->d_sb;
dinfo = au_di_alloc(sb, AuLsc_DI_CHILD); dinfo = au_di_alloc(sb, AuLsc_DI_CHILD);
if (dinfo) if (dinfo) {
atomic_set(&dinfo->di_generation, au_sigen(sb));
/* smp_mb(); */ /* atomic_set */
dentry->d_fsdata = dinfo; dentry->d_fsdata = dinfo;
else } else
err = -ENOMEM; err = -ENOMEM;
return err; return err;
...@@ -223,6 +225,24 @@ void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex, ...@@ -223,6 +225,24 @@ void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
hd->hd_dentry = h_dentry; hd->hd_dentry = h_dentry;
} }
int au_digen_test(struct dentry *dentry, unsigned int sigen)
{
int err;
err = 0;
if (unlikely(au_digen(dentry) != sigen
|| au_iigen_test(d_inode(dentry), sigen)))
err = -EIO;
return err;
}
void au_update_digen(struct dentry *dentry)
{
atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
/* smp_mb(); */ /* atomic_set */
}
void au_update_dbtop(struct dentry *dentry) void au_update_dbtop(struct dentry *dentry)
{ {
aufs_bindex_t bindex, bbot; aufs_bindex_t bindex, bbot;
......
...@@ -48,10 +48,25 @@ void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, ...@@ -48,10 +48,25 @@ void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
AuDebugOn(inode->i_mode AuDebugOn(inode->i_mode
&& (h_inode->i_mode & S_IFMT) && (h_inode->i_mode & S_IFMT)
!= (inode->i_mode & S_IFMT)); != (inode->i_mode & S_IFMT));
/* add more later */ if (bindex == iinfo->ii_btop)
au_cpup_igen(inode, h_inode);
} }
} }
void au_update_iigen(struct inode *inode, int half)
{
struct au_iinfo *iinfo;
struct au_iigen *iigen;
unsigned int sigen;
sigen = au_sigen(inode->i_sb);
iinfo = au_ii(inode);
iigen = &iinfo->ii_generation;
spin_lock(&iigen->ig_spin);
iigen->ig_generation = sigen;
spin_unlock(&iigen->ig_spin);
}
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
void au_icntnr_init_once(void *_c) void au_icntnr_init_once(void *_c)
...@@ -59,6 +74,7 @@ void au_icntnr_init_once(void *_c) ...@@ -59,6 +74,7 @@ void au_icntnr_init_once(void *_c)
struct au_icntnr *c = _c; struct au_icntnr *c = _c;
struct au_iinfo *iinfo = &c->iinfo; struct au_iinfo *iinfo = &c->iinfo;
spin_lock_init(&iinfo->ii_generation.ig_spin);
au_rw_init(&iinfo->ii_rwsem); au_rw_init(&iinfo->ii_rwsem);
inode_init_once(&c->vfs_inode); inode_init_once(&c->vfs_inode);
} }
...@@ -84,6 +100,7 @@ int au_iinfo_init(struct inode *inode) ...@@ -84,6 +100,7 @@ int au_iinfo_init(struct inode *inode)
for (i = 0; i < nbr; i++, hi++) for (i = 0; i < nbr; i++, hi++)
au_hinode_init(hi); au_hinode_init(hi);
iinfo->ii_generation.ig_generation = au_sigen(sb);
iinfo->ii_btop = -1; iinfo->ii_btop = -1;
iinfo->ii_bbot = -1; iinfo->ii_bbot = -1;
return 0; return 0;
......
...@@ -19,9 +19,18 @@ struct au_hinode { ...@@ -19,9 +19,18 @@ struct au_hinode {
struct inode *hi_inode; struct inode *hi_inode;
}; };
struct au_iigen {
spinlock_t ig_spin;
__u32 ig_generation;
};
struct au_iinfo { struct au_iinfo {
struct au_iigen ii_generation;
struct super_block *ii_hsb1; /* no get/put */
struct au_rwsem ii_rwsem; struct au_rwsem ii_rwsem;
aufs_bindex_t ii_btop, ii_bbot; aufs_bindex_t ii_btop, ii_bbot;
__u32 ii_higen;
struct au_hinode *ii_hinode; struct au_hinode *ii_hinode;
}; };
...@@ -48,6 +57,8 @@ void au_hiput(struct au_hinode *hinode); ...@@ -48,6 +57,8 @@ void au_hiput(struct au_hinode *hinode);
void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
struct inode *h_inode, unsigned int flags); struct inode *h_inode, unsigned int flags);
void au_update_iigen(struct inode *inode, int half);
void au_icntnr_init_once(void *_c); void au_icntnr_init_once(void *_c);
void au_hinode_init(struct au_hinode *hinode); void au_hinode_init(struct au_hinode *hinode);
int au_iinfo_init(struct inode *inode); int au_iinfo_init(struct inode *inode);
...@@ -120,6 +131,56 @@ static inline void au_icntnr_init(struct au_icntnr *c) ...@@ -120,6 +131,56 @@ static inline void au_icntnr_init(struct au_icntnr *c)
#endif #endif
} }
static inline unsigned int au_iigen(struct inode *inode)
{
unsigned int gen;
struct au_iinfo *iinfo;
struct au_iigen *iigen;
iinfo = au_ii(inode);
iigen = &iinfo->ii_generation;
spin_lock(&iigen->ig_spin);
gen = iigen->ig_generation;
spin_unlock(&iigen->ig_spin);
return gen;
}
/* tiny test for inode number */
/* tmpfs generation is too rough */
static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
{
struct au_iinfo *iinfo;
iinfo = au_ii(inode);
AuRwMustAnyLock(&iinfo->ii_rwsem);
return !(iinfo->ii_hsb1 == h_inode->i_sb
&& iinfo->ii_higen == h_inode->i_generation);
}
static inline void au_iigen_dec(struct inode *inode)
{
struct au_iinfo *iinfo;
struct au_iigen *iigen;
iinfo = au_ii(inode);
iigen = &iinfo->ii_generation;
spin_lock(&iigen->ig_spin);
iigen->ig_generation--;
spin_unlock(&iigen->ig_spin);
}
static inline int au_iigen_test(struct inode *inode, unsigned int sigen)
{
int err;
err = 0;
if (unlikely(inode && au_iigen(inode) != sigen))
err = -EIO;
return err;
}
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
static inline struct au_hinode *au_hinode(struct au_iinfo *iinfo, static inline struct au_hinode *au_hinode(struct au_iinfo *iinfo,
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* superblock private data * superblock private data
*/ */
#include <linux/iversion.h>
#include "aufs.h" #include "aufs.h"
/* /*
...@@ -52,3 +53,20 @@ out_sbinfo: ...@@ -52,3 +53,20 @@ out_sbinfo:
out: out:
return err; return err;
} }
/* ---------------------------------------------------------------------- */
unsigned int au_sigen_inc(struct super_block *sb)
{
unsigned int gen;
struct inode *inode;
SiMustWriteLock(sb);
gen = ++au_sbi(sb)->si_generation;
au_update_digen(sb->s_root);
inode = d_inode(sb->s_root);
au_update_iigen(inode, /*half*/0);
inode_inc_iversion(inode);
return gen;
}
...@@ -25,6 +25,8 @@ struct au_sbinfo { ...@@ -25,6 +25,8 @@ struct au_sbinfo {
struct au_rwsem si_rwsem; struct au_rwsem si_rwsem;
/* branch management */ /* branch management */
unsigned int si_generation;
aufs_bindex_t si_bbot; aufs_bindex_t si_bbot;
struct au_branch **si_branch; struct au_branch **si_branch;
...@@ -58,6 +60,8 @@ struct inode *au_iget_locked(struct super_block *sb, ino_t ino); ...@@ -58,6 +60,8 @@ struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
void au_si_free(struct kobject *kobj); void au_si_free(struct kobject *kobj);
int au_si_alloc(struct super_block *sb); int au_si_alloc(struct super_block *sb);
unsigned int au_sigen_inc(struct super_block *sb);
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
static inline struct au_sbinfo *au_sbi(struct super_block *sb) static inline struct au_sbinfo *au_sbi(struct super_block *sb)
...@@ -95,5 +99,11 @@ static inline aufs_bindex_t au_sbbot(struct super_block *sb) ...@@ -95,5 +99,11 @@ static inline aufs_bindex_t au_sbbot(struct super_block *sb)
return au_sbi(sb)->si_bbot; return au_sbi(sb)->si_bbot;
} }
static inline unsigned int au_sigen(struct super_block *sb)
{
SiMustAnyLock(sb);
return au_sbi(sb)->si_generation;
}
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* __AUFS_SUPER_H__ */ #endif /* __AUFS_SUPER_H__ */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment