linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: hooanon05@yahoo.co.jp
To: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Junjiro Okajima <hooanon05@yahoo.co.jp>
Subject: [PATCH 10/67] aufs mount and super_block operations
Date: Fri, 16 May 2008 23:32:24 +0900	[thread overview]
Message-ID: <12109484012724-git-send-email-hooanon05@yahoo.co.jp> (raw)
In-Reply-To: <12109484013156-git-send-email-hooanon05@yahoo.co.jp>

From: Junjiro Okajima <hooanon05@yahoo.co.jp>

	initial commit
	aufs mount and super_block operations

Signed-off-by: Junjiro Okajima <hooanon05@yahoo.co.jp>
---
 fs/aufs/super.c |  891 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 891 insertions(+), 0 deletions(-)

diff --git a/fs/aufs/super.c b/fs/aufs/super.c
new file mode 100644
index 0000000..491f75f
--- /dev/null
+++ b/fs/aufs/super.c
@@ -0,0 +1,891 @@
+/*
+ * Copyright (C) 2005-2008 Junjiro Okajima
+ *
+ * This program, aufs is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+ * mount and super_block operations
+ *
+ * $Id: super.c,v 1.5 2008/05/12 00:28:35 sfjro Exp $
+ */
+
+#include <linux/module.h>
+#include <linux/buffer_head.h>
+#include <linux/seq_file.h>
+#include <linux/smp_lock.h>
+#include <linux/statfs.h>
+
+#include "aufs.h"
+
+/*
+ * super_operations
+ */
+static struct inode *aufs_alloc_inode(struct super_block *sb)
+{
+	struct aufs_icntnr *c;
+
+	AuTraceEnter();
+
+	c = au_cache_alloc_icntnr();
+	//if (LktrCond) {au_cache_free_icntnr(c); c = NULL;}
+	if (c) {
+		inode_init_once(&c->vfs_inode);
+		c->vfs_inode.i_version = 1; //sigen(sb);
+		c->iinfo.ii_hinode = NULL;
+		return &c->vfs_inode;
+	}
+	return NULL;
+}
+
+static void aufs_destroy_inode(struct inode *inode)
+{
+	LKTRTrace("i%lu\n", inode->i_ino);
+	au_iinfo_fin(inode);
+	au_cache_free_icntnr(container_of(inode, struct aufs_icntnr,
+					  vfs_inode));
+}
+
+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
+{
+	struct inode *inode;
+	int err;
+#if 0
+	static struct backing_dev_info bdi = {
+		.ra_pages	= 0,	/* No readahead */
+		.capabilities	= BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK
+	};
+#endif
+
+	LKTRTrace("i%lu\n", ino);
+
+	inode = iget_locked(sb, ino);
+	if (unlikely(!inode)) {
+		inode = ERR_PTR(-ENOMEM);
+		goto out;
+	}
+	AuDebugOn(IS_ERR(inode));
+	if (unlikely(!(inode->i_state & I_NEW)))
+		goto out;
+
+	err = au_iinfo_init(inode);
+	//if (LktrCond) err = -1;
+	if (!err) {
+		inode->i_version++;
+		inode->i_op = &aufs_iop;
+		inode->i_fop = &aufs_file_fop;
+		inode->i_mapping->a_ops = &aufs_aop;
+		//inode->i_mapping->backing_dev_info = &bdi;
+	} else {
+		iget_failed(inode);
+		inode = ERR_PTR(err);
+	}
+
+ out:
+	/* never return NULL */
+	AuDebugOn(!inode);
+	AuTraceErrPtr(inode);
+	return inode;
+}
+
+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
+{
+	int err;
+	aufs_bindex_t bindex, bend;
+	struct dentry *root;
+	struct path path;
+
+	AuTraceEnter();
+
+	err = 0;
+	root = sb->s_root;
+	bend = au_sbend(sb);
+	for (bindex = 0; !err && bindex <= bend; bindex++) {
+		path.mnt = au_sbr_mnt(sb, bindex);
+		path.dentry = au_h_dptr(root, bindex);
+		err = seq_path(seq, &path, au_esc_chars);
+		if (err > 0)
+			err = seq_printf
+				(seq, "=%s",
+				 au_optstr_br_perm(au_sbr_perm(sb, bindex)));
+		if (!err && bindex != bend)
+			err = seq_putc(seq, ':');
+	}
+
+	AuTraceErr(err);
+	return err;
+}
+
+static void au_show_wbr_create(struct seq_file *m, int v,
+			       struct au_sbinfo *sbinfo)
+{
+	const char *pat;
+
+	AuDebugOn(v == AuWbrCreate_Def);
+
+	seq_printf(m, ",create=");
+	pat = au_optstr_wbr_create(v);
+	switch (v) {
+	case AuWbrCreate_TDP:
+	case AuWbrCreate_RR:
+	case AuWbrCreate_MFS:
+	case AuWbrCreate_PMFS:
+		seq_printf(m, pat);
+		break;
+	case AuWbrCreate_MFSV:
+		seq_printf(m, /*pat*/"mfs:%lu",
+			   sbinfo->si_wbr_mfs.mfs_expire / HZ);
+		break;
+	case AuWbrCreate_PMFSV:
+		seq_printf(m, /*pat*/"pmfs:%lu",
+			   sbinfo->si_wbr_mfs.mfs_expire / HZ);
+		break;
+	case AuWbrCreate_MFSRR:
+		seq_printf(m, /*pat*/"mfsrr:%Lu",
+			   sbinfo->si_wbr_mfs.mfsrr_watermark);
+		break;
+	case AuWbrCreate_MFSRRV:
+		seq_printf(m, /*pat*/"mfsrr:%Lu:%lu",
+			   sbinfo->si_wbr_mfs.mfsrr_watermark,
+			   sbinfo->si_wbr_mfs.mfs_expire / HZ);
+		break;
+	}
+}
+
+/* seq_file will re-call me in case of too long string */
+static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
+{
+	int err, n;
+	struct super_block *sb;
+	struct au_sbinfo *sbinfo;
+	struct dentry *root;
+	struct file *xino;
+	unsigned int mnt_flags, v;
+	struct path path;
+
+	//au_debug_on();
+	AuTraceEnter();
+
+	sb = mnt->mnt_sb;
+	root = sb->s_root;
+	if (!sysaufs_brs)
+		aufs_read_lock(root, !AuLock_IR);
+	else
+		si_noflush_read_lock(sb);
+	sbinfo = au_sbi(sb);
+	seq_printf(m, ",si=%p", sbinfo);
+	mnt_flags = au_mntflags(sb);
+	if (au_opt_test(mnt_flags, XINO)) {
+		seq_puts(m, ",xino=");
+		xino = sbinfo->si_xib;
+		path.mnt = xino->f_vfsmnt;
+		path.dentry = xino->f_dentry;
+		err = seq_path(m, &path, au_esc_chars);
+		if (unlikely(err <= 0))
+			goto out;
+		err = 0;
+#define Deleted "\\040(deleted)"
+		m->count -= sizeof(Deleted) - 1;
+		AuDebugOn(memcmp(m->buf + m->count, Deleted,
+				 sizeof(Deleted) - 1));
+#undef Deleted
+	} else
+		seq_puts(m, ",noxino");
+
+#define AuBool(name, str) do { \
+	v = au_opt_test(mnt_flags, name); \
+	if (v != au_opt_test(AuOpt_Def, name)) \
+		seq_printf(m, ",%s" #str, v ? "" : "no"); \
+} while (0)
+
+#define AuStr(name, str) do { \
+	v = mnt_flags & AuOptMask_##name; \
+	if (v != (AuOpt_Def & AuOptMask_##name)) \
+		seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
+} while (0)
+
+#ifdef CONFIG_AUFS_COMPAT
+#define AuStr_BrOpt	"dirs="
+#else
+#define AuStr_BrOpt	"br:"
+#endif
+
+	AuBool(TRUNC_XINO, trunc_xino);
+	AuBool(DIRPERM1, dirperm1);
+	AuBool(SHWH, shwh);
+	AuBool(PLINK, plink);
+	AuStr(UDBA, udba);
+
+	v = sbinfo->si_wbr_create;
+	if (v != AuWbrCreate_Def)
+		au_show_wbr_create(m, v, sbinfo);
+
+	v = sbinfo->si_wbr_copyup;
+	if (v != AuWbrCopyup_Def)
+		seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
+
+	v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
+	if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
+		seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
+	AuBool(REFROF, refrof);
+	AuBool(DLGT, dlgt);
+	AuBool(WARN_PERM, warn_perm);
+	AuBool(VERBOSE, verbose);
+
+	n = sbinfo->si_dirwh;
+	if (n != AUFS_DIRWH_DEF)
+		seq_printf(m, ",dirwh=%d", n);
+	n = sbinfo->si_rdcache / HZ;
+	if (n != AUFS_RDCACHE_DEF)
+		seq_printf(m, ",rdcache=%d", n);
+
+	AuStr(COO, coo);
+
+ out:
+	if (!sysaufs_brs) {
+		seq_puts(m, "," AuStr_BrOpt);
+		au_show_brs(m, sb);
+		aufs_read_unlock(root, !AuLock_IR);
+	} else
+		si_read_unlock(sb);
+	//au_debug_off();
+	return 0;
+
+#undef AuBool
+#undef AuStr
+#undef AuStr_BrOpt
+}
+
+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+	int err;
+
+	AuTraceEnter();
+
+	aufs_read_lock(dentry->d_sb->s_root, 0);
+	err = vfsub_statfs(au_h_dptr(dentry->d_sb->s_root, 0), buf,
+			   !!au_opt_test_dlgt(au_mntflags(dentry->d_sb)));
+	//if (LktrCond) err = -1;
+	aufs_read_unlock(dentry->d_sb->s_root, 0);
+	if (!err) {
+		buf->f_type = AUFS_SUPER_MAGIC;
+		buf->f_namelen -= AUFS_WH_PFX_LEN;
+		//todo: support uuid?
+		memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
+	}
+	/* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
+
+	AuTraceErr(err);
+	return err;
+}
+
+static void au_fsync_br(struct super_block *sb)
+{
+#ifdef CONFIG_AUFS_FSYNC_SUPER_PATCH
+	aufs_bindex_t bend, bindex;
+	int brperm;
+	struct super_block *h_sb;
+
+	AuTraceEnter();
+
+	si_write_lock(sb);
+	bend = au_sbend(sb);
+	for (bindex = 0; bindex < bend; bindex++) {
+		brperm = au_sbr_perm(sb, bindex);
+		if (brperm == AuBr_RR || brperm == AuBr_RRWH)
+			continue;
+		h_sb = au_sbr_sb(sb, bindex);
+		if (bdev_read_only(h_sb->s_bdev))
+			continue;
+
+		lockdep_off();
+		down_write(&h_sb->s_umount);
+		shrink_dcache_sb(h_sb);
+		fsync_super(h_sb);
+		up_write(&h_sb->s_umount);
+		lockdep_on();
+	}
+	si_write_unlock(sb);
+#endif
+}
+
+static void aufs_umount_begin(struct vfsmount *mnt, int flags)
+{
+	struct super_block *sb = mnt->mnt_sb;
+	struct au_sbinfo *sbinfo;
+
+	AuTraceEnter();
+	//todo: dont trust BKL.
+	AuDebugOn(!kernel_locked());
+
+	sbinfo = au_sbi(sb);
+	if (unlikely(!sbinfo))
+		return;
+
+	au_fsync_br(sb);
+
+	si_write_lock(sb);
+	if (au_opt_test(au_mntflags(sb), PLINK))
+		au_plink_put(sb);
+#if 0 // remove
+	if (unlikely(au_opt_test(au_mntflags(sb), UDBA_INOTIFY)))
+		shrink_dcache_sb(sb);
+#endif
+	spin_lock(&sbinfo->si_mntcache_lock);
+	sbinfo->si_mntcache = NULL;
+	spin_unlock(&sbinfo->si_mntcache_lock);
+#if 0
+	if (sbinfo->si_wbr_create_ops->fin)
+		sbinfo->si_wbr_create_ops->fin(sb);
+#endif
+	si_write_unlock(sb);
+}
+
+/* final actions when unmounting a file system */
+static void aufs_put_super(struct super_block *sb)
+{
+	struct au_sbinfo *sbinfo;
+
+	AuTraceEnter();
+
+	sbinfo = au_sbi(sb);
+	if (unlikely(!sbinfo))
+		return;
+	kobject_put(&sbinfo->si_kobj);
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * refresh dentry and inode at remount time.
+ */
+static int do_refresh(struct dentry *dentry, mode_t type,
+		      unsigned int dir_flags)
+{
+	int err;
+	struct dentry *parent;
+	struct inode *inode;
+
+	LKTRTrace("%.*s, 0%o\n", AuDLNPair(dentry), type);
+	inode = dentry->d_inode;
+	AuDebugOn(!inode);
+
+	di_write_lock_child(dentry);
+	parent = dget_parent(dentry);
+	di_read_lock_parent(parent, AuLock_IR);
+	/* returns a number of positive dentries */
+	err = au_refresh_hdentry(dentry, type);
+	//err = -1;
+	if (err >= 0) {
+		err = au_refresh_hinode(inode, dentry);
+		//err = -1;
+		if (!err && type == S_IFDIR)
+			au_reset_hinotify(inode, dir_flags);
+	}
+	if (unlikely(err))
+		AuErr("unrecoverable error %d, %.*s\n", err, AuDLNPair(dentry));
+	di_read_unlock(parent, AuLock_IR);
+	dput(parent);
+	di_write_unlock(dentry);
+
+	AuTraceErr(err);
+	return err;
+}
+
+static int test_dir(struct dentry *dentry, void *arg)
+{
+	return S_ISDIR(dentry->d_inode->i_mode);
+}
+
+//todo: merge with refresh_nondir()
+static int refresh_dir(struct dentry *root, au_gen_t sgen)
+{
+	int err, i, j, ndentry, e;
+	const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
+	struct au_dcsub_pages dpages;
+	struct au_dpage *dpage;
+	struct dentry **dentries;
+	struct inode *inode;
+
+	LKTRTrace("sgen %d\n", sgen);
+	SiMustWriteLock(root->d_sb);
+	//todo: dont trust BKL.
+	AuDebugOn(au_digen(root) != sgen || !kernel_locked());
+
+	err = 0;
+	list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
+		if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sgen) {
+			ii_write_lock_child(inode);
+			e = au_refresh_hinode_self(inode);
+			//e = -1;
+			ii_write_unlock(inode);
+			if (unlikely(e)) {
+				LKTRTrace("e %d, i%lu\n", e, inode->i_ino);
+				if (!err)
+					err = e;
+				/* go on even if err */
+			}
+		}
+
+	e = au_dpages_init(&dpages, GFP_TEMPORARY);
+	if (unlikely(e)) {
+		if (!err)
+			err = e;
+		goto out;
+	}
+	e = au_dcsub_pages(&dpages, root, test_dir, NULL);
+	if (unlikely(e)) {
+		if (!err)
+			err = e;
+		goto out_dpages;
+	}
+
+	for (i = 0; !e && i < dpages.ndpage; i++) {
+		dpage = dpages.dpages + i;
+		dentries = dpage->dentries;
+		ndentry = dpage->ndentry;
+		for (j = 0; !e && j < ndentry; j++) {
+			struct dentry *d;
+			d = dentries[j];
+#ifdef CONFIG_AUFS_DEBUG
+			{
+				struct dentry *parent;
+				parent = dget_parent(d);
+				AuDebugOn(!S_ISDIR(d->d_inode->i_mode)
+					  || IS_ROOT(d)
+					  || au_digen(parent) != sgen);
+				dput(parent);
+			}
+#endif
+			if (au_digen(d) != sgen) {
+				e = do_refresh(d, S_IFDIR, flags);
+				//e = -1;
+				if (unlikely(e && !err))
+					err = e;
+				/* break on err */
+			}
+		}
+	}
+
+ out_dpages:
+	au_dpages_free(&dpages);
+ out:
+	AuTraceErr(err);
+	return err;
+}
+
+static int test_nondir(struct dentry *dentry, void *arg)
+{
+	return !S_ISDIR(dentry->d_inode->i_mode);
+}
+
+static int refresh_nondir(struct dentry *root, au_gen_t sgen, int do_dentry)
+{
+	int err, i, j, ndentry, e;
+	struct au_dcsub_pages dpages;
+	struct au_dpage *dpage;
+	struct dentry **dentries;
+	struct inode *inode;
+
+	LKTRTrace("sgen %d\n", sgen);
+	SiMustWriteLock(root->d_sb);
+	//todo: dont trust BKL.
+	AuDebugOn(au_digen(root) != sgen || !kernel_locked());
+
+	err = 0;
+	list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
+		if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sgen) {
+			ii_write_lock_child(inode);
+			e = au_refresh_hinode_self(inode);
+			//e = -1;
+			ii_write_unlock(inode);
+			if (unlikely(e)) {
+				LKTRTrace("e %d, i%lu\n", e, inode->i_ino);
+				if (!err)
+					err = e;
+				/* go on even if err */
+			}
+		}
+
+	if (!do_dentry)
+		goto out;
+
+	e = au_dpages_init(&dpages, GFP_TEMPORARY);
+	if (unlikely(e)) {
+		if (!err)
+			err = e;
+		goto out;
+	}
+	e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
+	if (unlikely(e)) {
+		if (!err)
+			err = e;
+		goto out_dpages;
+	}
+
+	for (i = 0; i < dpages.ndpage; i++) {
+		dpage = dpages.dpages + i;
+		dentries = dpage->dentries;
+		ndentry = dpage->ndentry;
+		for (j = 0; j < ndentry; j++) {
+			struct dentry *d;
+			d = dentries[j];
+#ifdef CONFIG_AUFS_DEBUG
+			{
+				struct dentry *parent;
+				parent = dget_parent(d);
+				AuDebugOn(S_ISDIR(d->d_inode->i_mode)
+					  || au_digen(parent) != sgen);
+				dput(parent);
+			}
+#endif
+			inode = d->d_inode;
+			if (inode && au_digen(d) != sgen) {
+				e = do_refresh(d, inode->i_mode & S_IFMT, 0);
+				//e = -1;
+				if (unlikely(e && !err))
+					err = e;
+				/* go on even err */
+			}
+		}
+	}
+
+ out_dpages:
+	au_dpages_free(&dpages);
+ out:
+	AuTraceErr(err);
+	return err;
+}
+
+/* stop extra interpretation of errno in mount(8), and strange error messages */
+static int cvt_err(int err)
+{
+	AuTraceErr(err);
+
+	switch (err) {
+	case -ENOENT:
+	case -ENOTDIR:
+	case -EEXIST:
+	case -EIO:
+		err = -EINVAL;
+	}
+	return err;
+}
+
+/* protected by s_umount */
+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
+{
+	int err;
+	struct dentry *root;
+	struct inode *inode;
+	struct au_opts opts;
+	unsigned int dlgt;
+	struct au_sbinfo *sbinfo;
+
+	//au_debug_on();
+	LKTRTrace("flags 0x%x, data %s, len %lu\n",
+		  *flags, data ? data : "NULL",
+		  (unsigned long)(data ? strlen(data) : 0));
+
+	au_fsync_br(sb);
+	err = 0;
+	if (!data || !*data)
+		goto out; /* success */
+
+	err = -ENOMEM;
+	memset(&opts, 0, sizeof(opts));
+	opts.opt = (void *)__get_free_page(GFP_TEMPORARY);
+	//if (LktrCond) {free_page((unsigned long)opts.opt); opts.opt = NULL;}
+	if (unlikely(!opts.opt))
+		goto out;
+	opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
+	opts.flags = AuOpts_REMOUNT;
+
+	/* parse it before aufs lock */
+	err = au_opts_parse(sb, *flags, data, &opts);
+	//if (LktrCond) {au_free_opts(&opts); err = -1;}
+	if (unlikely(err))
+		goto out_opts;
+
+	sbinfo = au_sbi(sb);
+	root = sb->s_root;
+	inode = root->d_inode;
+	mutex_lock(&inode->i_mutex);
+	aufs_write_lock(root);
+
+	//DbgSleep(3);
+
+	/* au_do_opts() may return an error */
+	err = au_opts_remount(sb, &opts);
+	//if (LktrCond) err = -1;
+	au_opts_free(&opts);
+
+	if (au_ftest_opts(opts.flags, REFRESH_DIR)
+	    || au_ftest_opts(opts.flags, REFRESH_NONDIR)) {
+		int rerr;
+		au_gen_t sigen;
+
+		dlgt = !!au_opt_test_dlgt(sbinfo->si_mntflags);
+		au_opt_clr(sbinfo->si_mntflags, DLGT);
+		au_sigen_inc(sb);
+		au_reset_hinotify(inode, au_hi_flags(inode, /*isdir*/1));
+		sigen = au_sigen(sb);
+		au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
+
+		DiMustNoWaiters(root);
+		IiMustNoWaiters(root->d_inode);
+		di_write_unlock(root);
+
+		rerr = refresh_dir(root, sigen);
+		if (unlikely(rerr)) {
+			au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
+			AuWarn("Refreshing directories failed, ignores (%d)\n",
+			       rerr);
+		}
+
+		if (unlikely(au_ftest_opts(opts.flags, REFRESH_NONDIR))) {
+			//au_debug_on();
+			rerr = refresh_nondir(root, sigen, !rerr);
+			if (unlikely(rerr))
+				AuWarn("Refreshing non-directories failed,"
+				       " ignores (%d)\n", rerr);
+			//au_debug_off();
+		}
+
+		/* aufs_write_lock() calls ..._child() */
+		di_write_lock_child(root);
+
+		au_cpup_attr_all(inode);
+		if (unlikely(dlgt))
+			au_opt_set(sbinfo->si_mntflags, DLGT);
+	}
+
+	aufs_write_unlock(root);
+	mutex_unlock(&inode->i_mutex);
+
+ out_opts:
+	free_page((unsigned long)opts.opt);
+ out:
+	err = cvt_err(err);
+	AuTraceErr(err);
+	//au_debug_off();
+	return err;
+}
+
+static struct super_operations aufs_sop = {
+	.alloc_inode	= aufs_alloc_inode,
+	.destroy_inode	= aufs_destroy_inode,
+	//.dirty_inode	= aufs_dirty_inode,
+	//.write_inode	= aufs_write_inode,
+	//void (*put_inode) (struct inode *);
+	.drop_inode	= generic_delete_inode,
+	//.delete_inode	= aufs_delete_inode,
+	//.clear_inode	= aufs_clear_inode,
+
+	.show_options	= aufs_show_options,
+	.statfs		= aufs_statfs,
+
+	.put_super	= aufs_put_super,
+	//void (*write_super) (struct super_block *);
+	//int (*sync_fs)(struct super_block *sb, int wait);
+	//void (*write_super_lockfs) (struct super_block *);
+	//void (*unlockfs) (struct super_block *);
+	.remount_fs	= aufs_remount_fs,
+	/* depends upon umount flags. also use put_super() (< 2.6.18) */
+	.umount_begin	= aufs_umount_begin
+};
+
+/* ---------------------------------------------------------------------- */
+
+static int alloc_root(struct super_block *sb)
+{
+	int err;
+	struct inode *inode;
+	struct dentry *root;
+
+	AuTraceEnter();
+
+	err = -ENOMEM;
+	inode = au_iget_locked(sb, AUFS_ROOT_INO);
+	//if (LktrCond) {iput(inode); inode = NULL;}
+	err = PTR_ERR(inode);
+	if (IS_ERR(inode))
+		goto out;
+	unlock_new_inode(inode);
+	inode->i_mode = S_IFDIR;
+	root = d_alloc_root(inode);
+	//if (LktrCond) {igrab(inode); dput(root); root = NULL;}
+	if (unlikely(!root))
+		goto out_iput;
+	err = PTR_ERR(root);
+	if (IS_ERR(root))
+		goto out_iput;
+
+	err = au_alloc_dinfo(root);
+	//if (LktrCond){au_rw_write_unlock(&au_di(root)->di_rwsem);err=-1;}
+	if (!err) {
+		sb->s_root = root;
+		return 0; /* success */
+	}
+	dput(root);
+	goto out; /* do not iput */
+
+ out_iput:
+	iget_failed(inode);
+	iput(inode);
+ out:
+	AuTraceErr(err);
+	return err;
+
+}
+
+static int aufs_fill_super(struct super_block *sb, void *raw_data, int silent)
+{
+	int err;
+	struct dentry *root;
+	struct inode *inode;
+	struct au_opts opts;
+	char *arg = raw_data;
+
+	//au_debug_on();
+	if (unlikely(!arg || !*arg)) {
+		err = -EINVAL;
+		AuErr("no arg\n");
+		goto out;
+	}
+	LKTRTrace("%s, silent %d\n", arg, silent);
+
+	err = -ENOMEM;
+	memset(&opts, 0, sizeof(opts));
+	opts.opt = (void *)__get_free_page(GFP_TEMPORARY);
+	//if (LktrCond) {free_page((unsigned long)opts.opt); opts.opt = NULL;}
+	if (unlikely(!opts.opt))
+		goto out;
+	opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
+
+	err = au_si_alloc(sb);
+	//if (LktrCond) {si_write_unlock(sb);free_sbinfo(sb);err=-1;}
+	if (unlikely(err))
+		goto out_opts;
+	SiMustWriteLock(sb);
+	/* all timestamps always follow the ones on the branch */
+	sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
+	sb->s_op = &aufs_sop;
+	sb->s_magic = AUFS_SUPER_MAGIC;
+	au_init_export_op(sb);
+
+	err = alloc_root(sb);
+	//if (LktrCond) {au_rw_write_unlock(&au_di(sb->s_root)->di_rwsem);
+	//dput(sb->s_root);sb->s_root=NULL;err=-1;}
+	if (unlikely(err)) {
+		AuDebugOn(sb->s_root);
+		si_write_unlock(sb);
+		goto out_info;
+	}
+	root = sb->s_root;
+	DiMustWriteLock(root);
+	inode = root->d_inode;
+	inode->i_nlink = 2;
+
+	/*
+	 * actually we can parse options regardless aufs lock here.
+	 * but at remount time, parsing must be done before aufs lock.
+	 * so we follow the same rule.
+	 */
+	ii_write_lock_parent(inode);
+	aufs_write_unlock(root);
+	err = au_opts_parse(sb, sb->s_flags, arg, &opts);
+	//if (LktrCond) {au_opts_free(&opts); err = -1;}
+	if (unlikely(err))
+		goto out_root;
+
+	/* lock vfs_inode first, then aufs. */
+	mutex_lock(&inode->i_mutex);
+	inode->i_op = &aufs_dir_iop;
+	inode->i_fop = &aufs_dir_fop;
+	aufs_write_lock(root);
+
+	sb->s_maxbytes = 0;
+	err = au_opts_mount(sb, &opts);
+	//if (LktrCond) err = -1;
+	au_opts_free(&opts);
+	if (unlikely(err))
+		goto out_unlock;
+	AuDebugOn(!sb->s_maxbytes);
+
+	//AuDbgDentry(root);
+	aufs_write_unlock(root);
+	mutex_unlock(&inode->i_mutex);
+	//AuDbgSb(sb);
+	goto out_opts; /* success */
+
+ out_unlock:
+	aufs_write_unlock(root);
+	mutex_unlock(&inode->i_mutex);
+ out_root:
+	dput(root);
+	sb->s_root = NULL;
+ out_info:
+	au_fset_si(au_sbi(sb), FAILED_INIT);
+	kobject_put(&au_sbi(sb)->si_kobj);
+	sb->s_fs_info = NULL;
+ out_opts:
+	free_page((unsigned long)opts.opt);
+ out:
+	AuTraceErr(err);
+	err = cvt_err(err);
+	AuTraceErr(err);
+	//au_debug_off();
+	return err;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int aufs_get_sb(struct file_system_type *fs_type, int flags,
+		       const char *dev_name, void *raw_data,
+		       struct vfsmount *mnt)
+{
+	int err;
+
+	/* all timestamps always follow the ones on the branch */
+	/* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
+	err = get_sb_nodev(fs_type, flags, raw_data, aufs_fill_super, mnt);
+	if (!err) {
+		struct super_block *sb = mnt->mnt_sb;
+		struct au_sbinfo *sbinfo = au_sbi(sb);
+
+		/* no get/put */
+		spin_lock_init(&sbinfo->si_mntcache_lock);
+		sbinfo->si_mntcache = mnt;
+
+		au_sbilist_lock();
+		au_sbilist_add(sbinfo);
+		si_write_lock(sb);
+		sysaufs_brs_add(sb, 0);
+		si_write_unlock(sb);
+		au_sbilist_unlock();
+	}
+	return err;
+}
+
+struct file_system_type aufs_fs_type = {
+	.name		= AUFS_FSTYPE,
+	.fs_flags	= FS_REVAL_DOT, /* for UDBA and NFS branch */
+	.get_sb		= aufs_get_sb,
+	.kill_sb	= generic_shutdown_super,
+	//.kill_sb	= kill_anon_super,
+	/* no need to __module_get() and module_put(). */
+	.owner		= THIS_MODULE,
+};
-- 
1.4.4.4


  reply	other threads:[~2008-05-16 14:42 UTC|newest]

Thread overview: 80+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-05-16 14:32 [PATCH 1/67] aufs document hooanon05
2008-05-16 14:32 ` [PATCH 2/67] aufs manual hooanon05
2008-05-16 14:32   ` [PATCH 3/67] aufs global header file hooanon05
2008-05-16 14:32     ` [PATCH 4/67] aufs configuration hooanon05
2008-05-16 14:32       ` [PATCH 5/67] aufs Makefile hooanon05
2008-05-16 14:32         ` [PATCH 6/67] aufs main header file hooanon05
2008-05-16 14:32           ` [PATCH 7/67] aufs module initialization and module-global hooanon05
2008-05-16 14:32             ` [PATCH 8/67] aufs module global variables and operations hooanon05
2008-05-16 14:32               ` [PATCH 9/67] aufs super_block operations hooanon05
2008-05-16 14:32                 ` hooanon05 [this message]
2008-05-16 14:32                   ` [PATCH 11/67] aufs superblock private data hooanon05
2008-05-16 14:32                     ` [PATCH 12/67] aufs branch filesystems and xino for them hooanon05
2008-05-16 14:32                       ` [PATCH 13/67] aufs branch management hooanon05
2008-05-16 14:32                         ` [PATCH 14/67] aufs external inode number translation table and bitmap hooanon05
2008-05-16 14:32                           ` [PATCH 15/67] aufs special handling for inode attributes on FUSE branch hooanon05
2008-05-16 14:32                             ` [PATCH 16/67] aufs lookup functions for NFS branch in linux-2.6.19 and later hooanon05
2008-05-16 14:32                               ` [PATCH 17/67] aufs special handling inode attributes on XFS branch in linux-2.6.24 " hooanon05
2008-05-16 14:32                                 ` [PATCH 18/67] aufs sysfs interface and lifetime management, header hooanon05
2008-05-16 14:32                                   ` [PATCH 19/67] aufs sysfs interface and lifetime management, source hooanon05
2008-05-16 14:32                                     ` [PATCH 20/67] aufs mount options/flags, header hooanon05
2008-05-16 14:32                                       ` [PATCH 21/67] aufs mount options/flags, source hooanon05
2008-05-16 14:32                                         ` [PATCH 22/67] aufs workqueue for asynchronous/super-io/delegated operations, header hooanon05
2008-05-16 14:32                                           ` [PATCH 23/67] aufs workqueue for asynchronous/super-io/delegated operations, source hooanon05
2008-05-16 14:32                                             ` [PATCH 24/67] aufs sub-VFS, header hooanon05
2008-05-16 14:32                                               ` [PATCH 25/67] aufs sub-VFS, source hooanon05
2008-05-16 14:32                                                 ` [PATCH 26/67] aufs sub-dcache, header hooanon05
2008-05-16 14:32                                                   ` [PATCH 27/67] aufs sub-dcache, source hooanon05
2008-05-16 14:32                                                     ` [PATCH 28/67] aufs copy-up/down functions hooanon05
2008-05-16 14:32                                                       ` [PATCH 29/67] aufs copy-up functions, see wbr_policy.c for copy-down hooanon05
2008-05-16 14:32                                                         ` [PATCH 30/67] aufs whiteout for logical deletion and opaque directory, header hooanon05
2008-05-16 14:32                                                           ` [PATCH 31/67] aufs whiteout for logical deletion and opaque directory, source hooanon05
2008-05-16 14:32                                                             ` [PATCH 32/67] aufs pseudo-link hooanon05
2008-05-16 14:32                                                               ` [PATCH 33/67] aufs policies for selecting one among multiple writable branches hooanon05
2008-05-16 14:32                                                                 ` [PATCH 34/67] aufs lookup and dentry operations, header hooanon05
2008-05-16 14:32                                                                   ` [PATCH 35/67] aufs lookup and dentry operations, source hooanon05
2008-05-16 14:32                                                                     ` [PATCH 36/67] aufs dentry private data hooanon05
2008-05-16 14:32                                                                       ` [PATCH 37/67] aufs file operations hooanon05
2008-05-16 14:32                                                                         ` [PATCH 38/67] aufs handling file/dir, and address_space operation hooanon05
2008-05-16 14:32                                                                           ` [PATCH 39/67] aufs file private data hooanon05
2008-05-16 14:32                                                                             ` [PATCH 40/67] aufs file and vm operations hooanon05
2008-05-16 14:32                                                                               ` [PATCH 41/67] aufs directory operations, header hooanon05
2008-05-16 14:32                                                                                 ` [PATCH 42/67] aufs directory operations, source hooanon05
2008-05-16 14:32                                                                                   ` [PATCH 43/67] aufs virtual or vertical directory hooanon05
2008-05-16 14:32                                                                                     ` [PATCH 44/67] aufs inode operations hooanon05
2008-05-16 14:32                                                                                       ` [PATCH 45/67] aufs inode functions hooanon05
2008-05-16 14:33                                                                                         ` [PATCH 46/67] aufs inode private data hooanon05
2008-05-16 14:33                                                                                           ` [PATCH 47/67] aufs inode operations (except add/del/rename) hooanon05
2008-05-16 14:33                                                                                             ` [PATCH 48/67] aufs inode operations (add entry) hooanon05
2008-05-16 14:33                                                                                               ` [PATCH 49/67] aufs inode operations (del entry) hooanon05
2008-05-16 14:33                                                                                                 ` [PATCH 50/67] aufs inode operation (rename entry) hooanon05
2008-05-16 14:33                                                                                                   ` [PATCH 51/67] aufs lower (branch filesystem) inode and setting inotify hooanon05
2008-05-16 14:33                                                                                                     ` [PATCH 52/67] aufs inotify handler hooanon05
2008-05-16 14:33                                                                                                       ` [PATCH 53/67] aufs sub-routines for vfs in hinotify or dlgt mode hooanon05
2008-05-16 14:33                                                                                                         ` [PATCH 54/67] aufs lookup functions in 'delegate' mode hooanon05
2008-05-16 14:33                                                                                                           ` [PATCH 55/67] aufs export via nfs hooanon05
2008-05-16 14:33                                                                                                             ` [PATCH 56/67] aufs 'robr', aufs as readonly branch of another aufs hooanon05
2008-05-16 14:33                                                                                                               ` [PATCH 57/67] aufs sysfs interface hooanon05
2008-05-16 14:33                                                                                                                 ` [PATCH 58/67] aufs misc functions, header hooanon05
2008-05-16 14:33                                                                                                                   ` [PATCH 59/67] aufs misc functions, source hooanon05
2008-05-16 14:33                                                                                                                     ` [PATCH 60/67] aufs debug print functions, header hooanon05
2008-05-16 14:33                                                                                                                       ` [PATCH 61/67] aufs debug print functions, source hooanon05
2008-05-16 14:33                                                                                                                         ` [PATCH 62/67] aufs magic sysrq handler hooanon05
2008-05-16 14:33                                                                                                                           ` [PATCH 63/67] aufs mount helper hooanon05
2008-05-16 14:33                                                                                                                             ` [PATCH 64/67] aufs pseudo-link helper hooanon05
2008-05-16 14:33                                                                                                                               ` [PATCH 65/67] aufs pseudo-link helper for symlink hooanon05
2008-05-16 14:33                                                                                                                                 ` [PATCH 66/67] aufs umount helper hooanon05
2008-05-16 14:33                                                                                                                                   ` [PATCH 67/67] merge aufs hooanon05
2008-05-16 15:36               ` [PATCH 8/67] aufs module global variables and operations Jan Engelhardt
2008-05-16 15:33           ` [PATCH 6/67] aufs main header file Jan Engelhardt
2008-05-16 17:25         ` [PATCH 5/67] aufs Makefile Sam Ravnborg
2008-05-19  2:27           ` hooanon05
2008-05-16 15:28       ` [PATCH 4/67] aufs configuration Jan Engelhardt
2008-05-19  2:23         ` hooanon05
2008-05-16 14:59 ` [PATCH 1/67] aufs document Dave Quigley
2008-05-16 15:32   ` Jan Engelhardt
2008-05-16 21:07     ` Josef 'Jeff' Sipek
2008-05-19  2:25     ` hooanon05
2008-05-16 15:45   ` hooanon05
2008-05-16 16:09     ` Dave Quigley
2008-05-17  2:06       ` hooanon05

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=12109484012724-git-send-email-hooanon05@yahoo.co.jp \
    --to=hooanon05@yahoo.co.jp \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).