Esempio n. 1
0
void au_dir_ts(struct inode *dir, aufs_bindex_t bindex)
{
	int perm, wkq_err;
	aufs_bindex_t btop;
	struct au_dir_ts_arg *arg;
	struct dentry *dentry;
	struct super_block *sb;

	IMustLock(dir);

	dentry = d_find_any_alias(dir);
	AuDebugOn(!dentry);
	sb = dentry->d_sb;
	btop = au_ibtop(dir);
	if (btop == bindex) {
		au_cpup_attr_timesizes(dir);
		goto out;
	}

	perm = au_sbr_perm(sb, btop);
	if (!au_br_writable(perm))
		goto out;

	arg = kmalloc(sizeof(*arg), GFP_NOFS);
	if (!arg)
		goto out;

	arg->dentry = dget(dentry); /* will be dput-ted by au_do_dir_ts() */
	arg->brid = au_sbr_id(sb, bindex);
	wkq_err = au_wkq_nowait(au_do_dir_ts, arg, sb, /*flags*/0);
	if (unlikely(wkq_err)) {
		pr_err("wkq %d\n", wkq_err);
		dput(dentry);
		kfree(arg);
	}

out:
	dput(dentry);
}
Esempio n. 2
0
int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
		   unsigned int pending)
{
	int err;
	aufs_bindex_t bindex, bend;
	unsigned char do_plink, skip, do_free;
	struct au_branch *br;
	struct au_wbr *wbr;
	struct dentry *root;
	struct inode *dir, *h_dir;
	struct au_sbinfo *sbinfo;
	struct au_hinode *hdir;

	SiMustAnyLock(sb);

	sbinfo = au_sbi(sb);
	AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));

	if (!(sb_flags & MS_RDONLY)) {
		if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
			pr_warn("first branch should be rw\n");
		if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
			pr_warn("shwh should be used with ro\n");
	}

	if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
	    && !au_opt_test(sbinfo->si_mntflags, XINO))
		pr_warn("udba=*notify requires xino\n");

	err = 0;
	root = sb->s_root;
	dir = root->d_inode;
	do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
	bend = au_sbend(sb);
	for (bindex = 0; !err && bindex <= bend; bindex++) {
		skip = 0;
		h_dir = au_h_iptr(dir, bindex);
		br = au_sbr(sb, bindex);
		do_free = 0;

		wbr = br->br_wbr;
		if (wbr)
			wbr_wh_read_lock(wbr);

		if (!au_br_writable(br->br_perm)) {
			do_free = !!wbr;
			skip = (!wbr
				|| (!wbr->wbr_whbase
				    && !wbr->wbr_plink
				    && !wbr->wbr_orph));
		} else if (!au_br_wh_linkable(br->br_perm)) {
			/* skip = (!br->br_whbase && !br->br_orph); */
			skip = (!wbr || !wbr->wbr_whbase);
			if (skip && wbr) {
				if (do_plink)
					skip = !!wbr->wbr_plink;
				else
					skip = !wbr->wbr_plink;
			}
		} else {
			/* skip = (br->br_whbase && br->br_ohph); */
			skip = (wbr && wbr->wbr_whbase);
			if (skip) {
				if (do_plink)
					skip = !!wbr->wbr_plink;
				else
					skip = !wbr->wbr_plink;
			}
		}
		if (wbr)
			wbr_wh_read_unlock(wbr);

		if (skip)
			continue;

		hdir = au_hi(dir, bindex);
		au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
		if (wbr)
			wbr_wh_write_lock(wbr);
		err = au_wh_init(br, sb);
		if (wbr)
			wbr_wh_write_unlock(wbr);
		au_hn_imtx_unlock(hdir);

		if (!err && do_free) {
			kfree(wbr);
			br->br_wbr = NULL;
		}
	}

	return err;
}
Esempio n. 3
0
int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
		   unsigned int pending)
{
	int err, fhsm;
	aufs_bindex_t bindex, bend;
	unsigned char do_plink, skip, do_free;
	struct au_branch *br;
	struct au_wbr *wbr;
	struct dentry *root;
	struct inode *dir, *h_dir;
	struct au_sbinfo *sbinfo;
	struct au_hinode *hdir;

	SiMustAnyLock(sb);

	sbinfo = au_sbi(sb);
	AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));

	if (!(sb_flags & MS_RDONLY)) {
		if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
			pr_warn("first branch should be rw\n");
		if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
			pr_warn("shwh should be used with ro\n");
	}

	if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
	    && !au_opt_test(sbinfo->si_mntflags, XINO))
		pr_warn("udba=*notify requires xino\n");

	if (au_opt_test(sbinfo->si_mntflags, DIRPERM1))
		pr_warn("dirperm1 breaks the protection"
			" by the permission bits on the lower branch\n");

	err = 0;
	fhsm = 0;
	root = sb->s_root;
	dir = root->d_inode;
	do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
	bend = au_sbend(sb);
	for (bindex = 0; !err && bindex <= bend; bindex++) {
		skip = 0;
		h_dir = au_h_iptr(dir, bindex);
		br = au_sbr(sb, bindex);

		if ((br->br_perm & AuBrAttr_ICEX)
		    && !h_dir->i_op->listxattr)
			br->br_perm &= ~AuBrAttr_ICEX;
#if 0
		if ((br->br_perm & AuBrAttr_ICEX_SEC)
		    && (au_br_sb(br)->s_flags & MS_NOSEC))
			br->br_perm &= ~AuBrAttr_ICEX_SEC;
#endif

		do_free = 0;
		wbr = br->br_wbr;
		if (wbr)
			wbr_wh_read_lock(wbr);

		if (!au_br_writable(br->br_perm)) {
			do_free = !!wbr;
			skip = (!wbr
				|| (!wbr->wbr_whbase
				    && !wbr->wbr_plink
				    && !wbr->wbr_orph));
		} else if (!au_br_wh_linkable(br->br_perm)) {
			/* skip = (!br->br_whbase && !br->br_orph); */
			skip = (!wbr || !wbr->wbr_whbase);
			if (skip && wbr) {
				if (do_plink)
					skip = !!wbr->wbr_plink;
				else
					skip = !wbr->wbr_plink;
			}
		} else {
			/* skip = (br->br_whbase && br->br_ohph); */
			skip = (wbr && wbr->wbr_whbase);
			if (skip) {
				if (do_plink)
					skip = !!wbr->wbr_plink;
				else
					skip = !wbr->wbr_plink;
			}
		}
		if (wbr)
			wbr_wh_read_unlock(wbr);

		if (au_br_fhsm(br->br_perm)) {
			fhsm++;
			AuDebugOn(!br->br_fhsm);
		}

		if (skip)
			continue;

		hdir = au_hi(dir, bindex);
		au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
		if (wbr)
			wbr_wh_write_lock(wbr);
		err = au_wh_init(br, sb);
		if (wbr)
			wbr_wh_write_unlock(wbr);
		au_hn_imtx_unlock(hdir);

		if (!err && do_free) {
			kfree(wbr);
			br->br_wbr = NULL;
		}
	}

	if (fhsm >= 2) {
		au_fset_si(sbinfo, FHSM);
		for (bindex = bend; bindex >= 0; bindex--) {
			br = au_sbr(sb, bindex);
			if (au_br_fhsm(br->br_perm)) {
				au_fhsm_set_bottom(sb, bindex);
				break;
			}
		}
	} else {
		au_fclr_si(sbinfo, FHSM);
		au_fhsm_set_bottom(sb, -1);
	}

	return err;
}