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

aufs: finfo core



The structure is very similar to iinfo and dinfo (in previous commits).
This commit is for non-dir files. For a directory, see later commit.
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent f3457eb3
......@@ -15,7 +15,7 @@ aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
cpup.o whout.o wbr_policy.o \
dinfo.o dentry.o \
dynop.o \
file.o \
finfo.o file.o \
dir.o \
iinfo.o inode.o i_op.o
......
......@@ -180,6 +180,48 @@ void au_dpri_dentry(struct dentry *dentry)
do_pri_dentry(bindex, au_hdentry(dinfo, bindex)->hd_dentry);
}
static int do_pri_file(aufs_bindex_t bindex, struct file *file)
{
char a[32];
if (!file || IS_ERR(file)) {
dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
return -1;
}
a[0] = 0;
if (bindex < 0
&& !IS_ERR_OR_NULL(file->f_path.dentry)
&& au_test_aufs(file->f_path.dentry->d_sb)
&& au_fi(file))
snprintf(a, sizeof(a), ", gen %d",
au_figen(file));
dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
bindex, file->f_mode, file->f_flags, (long)file_count(file),
file->f_version, file->f_pos, a);
if (!IS_ERR_OR_NULL(file->f_path.dentry))
do_pri_dentry(bindex, file->f_path.dentry);
return 0;
}
void au_dpri_file(struct file *file)
{
struct au_finfo *finfo;
int err;
err = do_pri_file(-1, file);
if (err
|| IS_ERR_OR_NULL(file->f_path.dentry)
|| !au_test_aufs(file->f_path.dentry->d_sb))
return;
finfo = au_fi(file);
if (!finfo)
return;
if (finfo->fi_btop < 0)
return;
do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
}
static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
{
struct vfsmount *mnt;
......
......@@ -101,6 +101,8 @@ struct inode;
void au_dpri_inode(struct inode *inode);
void au_dpri_dalias(struct inode *inode);
void au_dpri_dentry(struct dentry *dentry);
struct file;
void au_dpri_file(struct file *filp);
struct super_block;
void au_dpri_sb(struct super_block *sb);
......@@ -130,6 +132,13 @@ void au_dbg_verify_kthread(void);
mutex_unlock(&au_dbg_mtx); \
} while (0)
#define AuDbgFile(f) do { \
mutex_lock(&au_dbg_mtx); \
AuDbg(#f "\n"); \
au_dpri_file(f); \
mutex_unlock(&au_dbg_mtx); \
} while (0)
#define AuDbgSb(sb) do { \
mutex_lock(&au_dbg_mtx); \
AuDbg(#sb "\n"); \
......@@ -150,6 +159,7 @@ AuStubVoid(au_dbg_verify_kthread, void)
#define AuDbgInode(i) do {} while (0)
#define AuDbgDAlias(i) do {} while (0)
#define AuDbgDentry(d) do {} while (0)
#define AuDbgFile(f) do {} while (0)
#define AuDbgSb(sb) do {} while (0)
#define AuDbgSym(addr) do {} while (0)
#endif /* CONFIG_AUFS_DEBUG */
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2005-2019 Junjiro R. Okajima
*/
/*
* file private data
*/
#include "aufs.h"
void au_hfput(struct au_hfile *hf, int execed)
{
if (execed)
allow_write_access(hf->hf_file);
fput(hf->hf_file);
hf->hf_file = NULL;
au_lcnt_dec(&hf->hf_br->br_nfiles);
hf->hf_br = NULL;
}
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;
AuDebugOn(finfo->fi_btop != bindex);
hf = &finfo->fi_htop;
if (hf && hf->hf_file)
au_hfput(hf, vfsub_file_execed(file));
if (val) {
FiMustWriteLock(file);
AuDebugOn(IS_ERR_OR_NULL(file->f_path.dentry));
hf->hf_file = val;
hf->hf_br = au_sbr(file->f_path.dentry->d_sb, bindex);
}
}
void au_update_figen(struct file *file)
{
atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_path.dentry));
/* smp_mb(); */ /* atomic_set */
}
/* ---------------------------------------------------------------------- */
void au_finfo_fin(struct file *file)
{
struct au_finfo *finfo;
finfo = au_fi(file);
AuRwDestroy(&finfo->fi_rwsem);
au_cache_free_finfo(finfo);
}
void au_fi_init_once(void *_finfo)
{
struct au_finfo *finfo = _finfo;
au_rw_init(&finfo->fi_rwsem);
}
int au_finfo_init(struct file *file)
{
int err;
struct au_finfo *finfo;
struct dentry *dentry;
err = -ENOMEM;
dentry = file->f_path.dentry;
finfo = au_cache_alloc_finfo();
if (unlikely(!finfo))
goto out;
err = 0;
au_rw_write_lock(&finfo->fi_rwsem);
finfo->fi_btop = -1;
atomic_set(&finfo->fi_generation, au_digen(dentry));
/* smp_mb(); */ /* atomic_set */
file->private_data = finfo;
out:
return err;
}
......@@ -98,6 +98,9 @@ static int __init au_cache_init(void)
au_cache[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
au_icntnr_init_once);
if (au_cache[AuCache_ICNTNR])
au_cache[AuCache_FINFO] = AuCacheCtor(au_finfo,
au_fi_init_once);
if (au_cache[AuCache_FINFO])
return 0;
au_cache_fin();
......
......@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include "debug.h"
#include "dentry.h"
#include "file.h"
#include "inode.h"
struct path;
......@@ -104,6 +105,7 @@ AuStubVoid(au_procfs_fin, void);
enum {
AuCache_DINFO,
AuCache_ICNTNR,
AuCache_FINFO,
AuCache_HNOTIFY, /* must be last */
AuCache_Last
};
......@@ -136,6 +138,7 @@ extern struct kmem_cache *au_cache[AuCache_Last];
AuCacheFuncs(dinfo, DINFO);
AuCacheFuncs(icntnr, ICNTNR);
AuCacheFuncs(finfo, FINFO);
#ifdef CONFIG_AUFS_HNOTIFY
AuCacheFuncs(hnotify, HNOTIFY);
#endif
......
......@@ -111,6 +111,23 @@ static inline loff_t vfsub_f_size_read(struct file *file)
return i_size_read(file_inode(file));
}
static inline unsigned int vfsub_file_flags(struct file *file)
{
unsigned int flags;
spin_lock(&file->f_lock);
flags = file->f_flags;
spin_unlock(&file->f_lock);
return flags;
}
static inline int vfsub_file_execed(struct file *file)
{
/* todo: direct access f_flags */
return !!(vfsub_file_flags(file) & __FMODE_EXEC);
}
/*
* re-use branch fs's ioctl(FICLONE) while aufs itself doesn't support such
* ioctl.
......
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