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

aufs: sbinfo core



The structure is very similar to inode and dentry infos (in previous
commits), but the internal array is for 'struct au_branch' instead of
'superblock.' Additionally the lifetime of 'struct au_sbinfo' is managed
by kobject since it will be connected to sysfs by later commit.
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent ee166183
......@@ -9,7 +9,7 @@ ccflags-y += -DDEBUG
ccflags-y += -include ${srctree}/include/uapi/linux/aufs_type.h
obj-$(CONFIG_AUFS_FS) += aufs.o
aufs-y := module.o super.o \
aufs-y := module.o sbinfo.o super.o \
dinfo.o \
iinfo.o
......
......@@ -52,6 +52,16 @@ AuStubInt0(au_debug_test, void)
} while (0)
#define AuLabel(l) AuDbg(#l "\n")
#define AuTraceErr(e) do { \
if (unlikely((e) < 0)) \
AuDbg("err %d\n", (int)(e)); \
} while (0)
#define AuTraceErrPtr(p) do { \
if (IS_ERR(p)) \
AuDbg("err %ld\n", PTR_ERR(p)); \
} while (0)
/* ---------------------------------------------------------------------- */
struct dentry;
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2005-2019 Junjiro R. Okajima
*/
/*
* superblock private data
*/
#include "aufs.h"
/*
* they are necessary regardless sysfs is disabled.
*/
void au_si_free(struct kobject *kobj)
{
struct au_sbinfo *sbinfo;
sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
au_kfree_try_rcu(sbinfo->si_branch);
AuRwDestroy(&sbinfo->si_rwsem);
au_kfree_rcu(sbinfo);
}
int au_si_alloc(struct super_block *sb)
{
int err;
struct au_sbinfo *sbinfo;
err = -ENOMEM;
sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
if (unlikely(!sbinfo))
goto out;
/* will be reallocated separately */
sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
if (unlikely(!sbinfo->si_branch))
goto out_sbinfo;
au_rw_init_wlock(&sbinfo->si_rwsem);
sbinfo->si_bbot = -1;
/* leave other members for sysaufs and si_mnt. */
sb->s_fs_info = sbinfo;
return 0; /* success */
au_kfree_try_rcu(sbinfo->si_branch);
out_sbinfo:
au_kfree_rcu(sbinfo);
out:
return err;
}
......@@ -65,14 +65,28 @@ struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
out:
/* never return NULL */
AuDebugOn(!inode);
AuTraceErrPtr(inode);
return inode;
}
/* ---------------------------------------------------------------------- */
/* final actions when unmounting a file system */
static void aufs_put_super(struct super_block *sb)
{
struct au_sbinfo *sbinfo;
sbinfo = au_sbi(sb);
if (sbinfo)
kobject_put(&sbinfo->si_kobj);
}
/* ---------------------------------------------------------------------- */
static const struct super_operations aufs_sop = {
.alloc_inode = aufs_alloc_inode,
.destroy_inode = aufs_destroy_inode,
/* always deleting, no clearing */
.drop_inode = generic_delete_inode
.drop_inode = generic_delete_inode,
.put_super = aufs_put_super
};
......@@ -12,6 +12,33 @@
#ifdef __KERNEL__
#include <linux/fs.h>
#include <linux/kobject.h>
#include "rwsem.h"
struct au_branch;
struct au_sbinfo {
/*
* tried sb->s_umount, but failed due to the dependency between i_mutex.
* rwsem for au_sbinfo is necessary.
*/
struct au_rwsem si_rwsem;
/* branch management */
aufs_bindex_t si_bbot;
struct au_branch **si_branch;
/*
* sysfs and lifetime management.
* this is not a small structure and it may be a waste of memory in case
* of sysfs is disabled, particularly when many aufs-es are mounted.
* but using sysfs is majority.
*/
struct kobject si_kobj;
};
/* ---------------------------------------------------------------------- */
/* 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 */
......@@ -25,8 +52,48 @@
/* ---------------------------------------------------------------------- */
/* super.c */
struct super_block;
struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
/* sbinfo.c */
void au_si_free(struct kobject *kobj);
int au_si_alloc(struct super_block *sb);
/* ---------------------------------------------------------------------- */
static inline struct au_sbinfo *au_sbi(struct super_block *sb)
{
return sb->s_fs_info;
}
/* ---------------------------------------------------------------------- */
/* lock superblock. mainly for entry point functions */
#define __si_read_lock(sb) au_rw_read_lock(&au_sbi(sb)->si_rwsem)
#define __si_write_lock(sb) au_rw_write_lock(&au_sbi(sb)->si_rwsem)
#define __si_read_trylock(sb) au_rw_read_trylock(&au_sbi(sb)->si_rwsem)
#define __si_write_trylock(sb) au_rw_write_trylock(&au_sbi(sb)->si_rwsem)
/*
#define __si_read_trylock_nested(sb) \
au_rw_read_trylock_nested(&au_sbi(sb)->si_rwsem)
#define __si_write_trylock_nested(sb) \
au_rw_write_trylock_nested(&au_sbi(sb)->si_rwsem)
*/
#define __si_read_unlock(sb) au_rw_read_unlock(&au_sbi(sb)->si_rwsem)
#define __si_write_unlock(sb) au_rw_write_unlock(&au_sbi(sb)->si_rwsem)
#define __si_downgrade_lock(sb) au_rw_dgrade_lock(&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 aufs_bindex_t au_sbbot(struct super_block *sb)
{
SiMustAnyLock(sb);
return au_sbi(sb)->si_bbot;
}
#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