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

aufs: finfo for directory



Expand finfo to support for a directory.
For readdir(3), see VDIR and RDU in later commits.
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent c3e1eecf
......@@ -22,13 +22,29 @@ struct au_hfile {
struct au_branch *hf_br;
};
struct au_vdir;
struct au_fidir {
aufs_bindex_t fd_bbot;
aufs_bindex_t fd_nent;
struct au_vdir *fd_vdir_cache;
struct au_hfile fd_hfile[];
};
static inline int au_fidir_sz(int nent)
{
AuDebugOn(nent < 0);
return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
}
struct au_finfo {
atomic_t fi_generation;
struct au_rwsem fi_rwsem;
aufs_bindex_t fi_btop;
struct au_hfile fi_htop;
/* do not union them */
struct au_hfile fi_htop; /* for non-dir */
struct au_fidir *fi_hdir; /* for dir only */
struct rcu_head rcu;
} ____cacheline_aligned_in_smp;
......@@ -46,10 +62,12 @@ void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
struct file *h_file);
void au_update_figen(struct file *file);
struct au_fidir *au_fidir_alloc(struct super_block *sb);
int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink);
void au_fi_init_once(void *_fi);
void au_finfo_fin(struct file *file);
int au_finfo_init(struct file *file);
int au_finfo_init(struct file *file, struct au_fidir *fidir);
/* ---------------------------------------------------------------------- */
......@@ -88,18 +106,55 @@ static inline aufs_bindex_t au_fbtop(struct file *file)
return au_fi(file)->fi_btop;
}
static inline aufs_bindex_t au_fbbot_dir(struct file *file)
{
FiMustAnyLock(file);
AuDebugOn(!au_fi(file)->fi_hdir);
return au_fi(file)->fi_hdir->fd_bbot;
}
static inline struct au_vdir *au_fvdir_cache(struct file *file)
{
FiMustAnyLock(file);
AuDebugOn(!au_fi(file)->fi_hdir);
return au_fi(file)->fi_hdir->fd_vdir_cache;
}
static inline void au_set_fbtop(struct file *file, aufs_bindex_t bindex)
{
FiMustWriteLock(file);
au_fi(file)->fi_btop = bindex;
}
static inline void au_set_fbbot_dir(struct file *file, aufs_bindex_t bindex)
{
FiMustWriteLock(file);
AuDebugOn(!au_fi(file)->fi_hdir);
au_fi(file)->fi_hdir->fd_bbot = bindex;
}
static inline void au_set_fvdir_cache(struct file *file,
struct au_vdir *vdir_cache)
{
FiMustWriteLock(file);
AuDebugOn(!au_fi(file)->fi_hdir);
au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
}
static inline struct file *au_hf_top(struct file *file)
{
FiMustAnyLock(file);
AuDebugOn(au_fi(file)->fi_hdir);
return au_fi(file)->fi_htop.hf_file;
}
static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
{
FiMustAnyLock(file);
AuDebugOn(!au_fi(file)->fi_hdir);
return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
}
/* todo: memory barrier? */
static inline unsigned int au_figen(struct file *f)
{
......
......@@ -23,9 +23,14 @@ void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
{
struct au_finfo *finfo = au_fi(file);
struct au_hfile *hf;
struct au_fidir *fidir;
fidir = finfo->fi_hdir;
if (!fidir) {
AuDebugOn(finfo->fi_btop != bindex);
hf = &finfo->fi_htop;
} else
hf = fidir->fd_hfile + bindex;
if (hf && hf->hf_file)
au_hfput(hf, vfsub_file_execed(file));
......@@ -45,11 +50,52 @@ void au_update_figen(struct file *file)
/* ---------------------------------------------------------------------- */
struct au_fidir *au_fidir_alloc(struct super_block *sb)
{
struct au_fidir *fidir;
int nbr;
nbr = au_sbbot(sb) + 1;
if (nbr < 2)
nbr = 2; /* initial allocate for 2 branches */
fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
if (fidir) {
fidir->fd_bbot = -1;
fidir->fd_nent = nbr;
}
return fidir;
}
int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink)
{
int err;
struct au_fidir *fidir, *p;
AuRwMustWriteLock(&finfo->fi_rwsem);
fidir = finfo->fi_hdir;
AuDebugOn(!fidir);
err = -ENOMEM;
p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
GFP_NOFS, may_shrink);
if (p) {
p->fd_nent = nbr;
finfo->fi_hdir = p;
err = 0;
}
return err;
}
/* ---------------------------------------------------------------------- */
void au_finfo_fin(struct file *file)
{
struct au_finfo *finfo;
finfo = au_fi(file);
AuDebugOn(finfo->fi_hdir);
AuRwDestroy(&finfo->fi_rwsem);
au_cache_free_finfo(finfo);
}
......@@ -61,7 +107,7 @@ void au_fi_init_once(void *_finfo)
au_rw_init(&finfo->fi_rwsem);
}
int au_finfo_init(struct file *file)
int au_finfo_init(struct file *file, struct au_fidir *fidir)
{
int err;
struct au_finfo *finfo;
......@@ -76,6 +122,7 @@ int au_finfo_init(struct file *file)
err = 0;
au_rw_write_lock(&finfo->fi_rwsem);
finfo->fi_btop = -1;
finfo->fi_hdir = fidir;
atomic_set(&finfo->fi_generation, au_digen(dentry));
/* smp_mb(); */ /* atomic_set */
......
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