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
obj-$(CONFIG_AUFS_FS) += aufs.o
aufs-y := module.o sbinfo.o super.o \
dcsub.o \
cpup.o \
dinfo.o \
iinfo.o
......
......@@ -22,6 +22,7 @@
#include "debug.h"
#include "cpup.h"
#include "dcsub.h"
#include "dentry.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)
return;
iinfo = au_ii(inode);
dpri("i-1: btop %d, bbot %d\n",
iinfo->ii_btop, iinfo->ii_bbot);
dpri("i-1: btop %d, bbot %d, gen %d\n",
iinfo->ii_btop, iinfo->ii_bbot, au_iigen(inode));
if (iinfo->ii_btop < 0)
return;
for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; bindex++)
......@@ -138,8 +138,9 @@ void au_dpri_dentry(struct dentry *dentry)
dinfo = au_di(dentry);
if (!dinfo)
return;
dpri("d-1: btop %d, bbot %d\n",
dinfo->di_btop, dinfo->di_bbot);
dpri("d-1: btop %d, bbot %d, gen %d\n",
dinfo->di_btop, dinfo->di_bbot,
au_digen(dentry));
if (dinfo->di_btop < 0)
return;
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)
}
}
}
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);
#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_gen(struct dentry *parent, unsigned int sigen);
#define AuDbgInode(i) do { \
mutex_lock(&au_dbg_mtx); \
......@@ -98,6 +99,7 @@ void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line);
} while (0)
#else
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 AuDbgDAlias(i) do {} while (0)
......
......@@ -20,6 +20,8 @@ struct au_hdentry {
};
struct au_dinfo {
atomic_t di_generation;
struct au_rwsem di_rwsem;
aufs_bindex_t di_btop, di_bbot;
struct au_hdentry *di_hdentry;
......@@ -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,
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_dbbot(struct dentry *dentry);
......@@ -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)
{
hdentry->hd_dentry = NULL;
......
......@@ -67,9 +67,11 @@ int au_di_init(struct dentry *dentry)
err = 0;
sb = dentry->d_sb;
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;
else
} else
err = -ENOMEM;
return err;
......@@ -223,6 +225,24 @@ void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
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)
{
aufs_bindex_t bindex, bbot;
......
......@@ -48,10 +48,25 @@ void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
AuDebugOn(inode->i_mode
&& (h_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)
......@@ -59,6 +74,7 @@ void au_icntnr_init_once(void *_c)
struct au_icntnr *c = _c;
struct au_iinfo *iinfo = &c->iinfo;
spin_lock_init(&iinfo->ii_generation.ig_spin);
au_rw_init(&iinfo->ii_rwsem);
inode_init_once(&c->vfs_inode);
}
......@@ -84,6 +100,7 @@ int au_iinfo_init(struct inode *inode)
for (i = 0; i < nbr; i++, hi++)
au_hinode_init(hi);
iinfo->ii_generation.ig_generation = au_sigen(sb);
iinfo->ii_btop = -1;
iinfo->ii_bbot = -1;
return 0;
......
......@@ -19,9 +19,18 @@ struct au_hinode {
struct inode *hi_inode;
};
struct au_iigen {
spinlock_t ig_spin;
__u32 ig_generation;
};
struct au_iinfo {
struct au_iigen ii_generation;
struct super_block *ii_hsb1; /* no get/put */
struct au_rwsem ii_rwsem;
aufs_bindex_t ii_btop, ii_bbot;
__u32 ii_higen;
struct au_hinode *ii_hinode;
};
......@@ -48,6 +57,8 @@ void au_hiput(struct au_hinode *hinode);
void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
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_hinode_init(struct au_hinode *hinode);
int au_iinfo_init(struct inode *inode);
......@@ -120,6 +131,56 @@ static inline void au_icntnr_init(struct au_icntnr *c)
#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,
......
......@@ -7,6 +7,7 @@
* superblock private data
*/
#include <linux/iversion.h>
#include "aufs.h"
/*
......@@ -52,3 +53,20 @@ out_sbinfo:
out:
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 {
struct au_rwsem si_rwsem;
/* branch management */
unsigned int si_generation;
aufs_bindex_t si_bbot;
struct au_branch **si_branch;
......@@ -58,6 +60,8 @@ struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
void au_si_free(struct kobject *kobj);
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)
......@@ -95,5 +99,11 @@ static inline aufs_bindex_t au_sbbot(struct super_block *sb)
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 /* __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