Beispiel #1
0
int au_reopen_nondir(struct file *file)
{
	int err;
	aufs_bindex_t bstart;
	struct dentry *dentry;
	struct file *h_file, *h_file_tmp;

	dentry = file->f_dentry;
	AuDebugOn(au_special_file(dentry->d_inode->i_mode));
	bstart = au_dbstart(dentry);
	h_file_tmp = NULL;
	if (au_fbstart(file) == bstart) {
		h_file = au_hf_top(file);
		if (file->f_mode == h_file->f_mode)
			return 0; /* success */
		h_file_tmp = h_file;
		get_file(h_file_tmp);
		au_set_h_fptr(file, bstart, NULL);
	}
	AuDebugOn(au_fi(file)->fi_hdir);
	/*
	 * it can happen
	 * file exists on both of rw and ro
	 * open --> dbstart and fbstart are both 0
	 * prepend a branch as rw, "rw" become ro
	 * remove rw/file
	 * delete the top branch, "rw" becomes rw again
	 *	--> dbstart is 1, fbstart is still 0
	 * write --> fbstart is 0 but dbstart is 1
	 */
	/* AuDebugOn(au_fbstart(file) < bstart); */

	h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
			   file, /*force_wr*/0);
	err = PTR_ERR(h_file);
	if (IS_ERR(h_file)) {
		if (h_file_tmp) {
			atomic_inc(&au_sbr(dentry->d_sb, bstart)->br_count);
			au_set_h_fptr(file, bstart, h_file_tmp);
			h_file_tmp = NULL;
		}
		goto out; /* todo: close all? */
	}

	err = 0;
	au_set_fbstart(file, bstart);
	au_set_h_fptr(file, bstart, h_file);
	au_update_figen(file);
	/* todo: necessary? */
	/* file->f_ra = h_file->f_ra; */

out:
	if (h_file_tmp)
		fput(h_file_tmp);
	return err;
}
Beispiel #2
0
static ssize_t au_fhsm_read(struct file *file, char __user *buf, size_t count,
			   loff_t *pos)
{
	ssize_t err;
	int readable;
	aufs_bindex_t nfhsm, bindex, bend;
	struct au_sbinfo *sbinfo;
	struct au_fhsm *fhsm;
	struct au_branch *br;
	struct super_block *sb;

	err = 0;
	sbinfo = file->private_data;
	fhsm = &sbinfo->si_fhsm;
need_data:
	spin_lock_irq(&fhsm->fhsm_wqh.lock);
	if (!atomic_read(&fhsm->fhsm_readable)) {
		if (vfsub_file_flags(file) & O_NONBLOCK)
			err = -EAGAIN;
		else
			err = wait_event_interruptible_locked_irq
				(fhsm->fhsm_wqh,
				 atomic_read(&fhsm->fhsm_readable));
	}
	spin_unlock_irq(&fhsm->fhsm_wqh.lock);
	if (unlikely(err))
		goto out;

	/* sb may already be dead */
	au_rw_read_lock(&sbinfo->si_rwsem);
	readable = atomic_read(&fhsm->fhsm_readable);
	if (readable > 0) {
		sb = sbinfo->si_sb;
		AuDebugOn(!sb);
		/* exclude the bottom branch */
		nfhsm = 0;
		bend = au_fhsm_bottom(sb);
		for (bindex = 0; bindex < bend; bindex++) {
			br = au_sbr(sb, bindex);
			if (au_br_fhsm(br->br_perm))
				nfhsm++;
		}
		err = -EMSGSIZE;
		if (nfhsm * sizeof(struct aufs_stbr) <= count) {
			atomic_set(&fhsm->fhsm_readable, 0);
			err = au_fhsm_do_read(sbinfo->si_sb, (void __user *)buf,
					     count);
		}
	}
	au_rw_read_unlock(&sbinfo->si_rwsem);
	if (!readable)
		goto need_data;

out:
	return err;
}
Beispiel #3
0
void au_hfput(struct au_hfile *hf, struct file *file)
{
	/* todo: direct access f_flags */
	if (vfsub_file_flags(file) & vfsub_fmode_to_uint(FMODE_EXEC))
		allow_write_access(hf->hf_file);
	fput(hf->hf_file);
	hf->hf_file = NULL;
	atomic_dec(&hf->hf_br->br_count);
	hf->hf_br = NULL;
}
Beispiel #4
0
int au_reopen_nondir(struct file *file)
{
	int err;
	aufs_bindex_t bstart, bindex, bend;
	struct dentry *dentry;
	struct file *h_file, *h_file_tmp;

	dentry = file->f_dentry;
	AuDebugOn(au_special_file(dentry->d_inode->i_mode));
	bstart = au_dbstart(dentry);
	h_file_tmp = NULL;
	if (au_fbstart(file) == bstart) {
		h_file = au_h_fptr(file, bstart);
		if (file->f_mode == h_file->f_mode)
			return 0; /* success */
		h_file_tmp = h_file;
		get_file(h_file_tmp);
		au_set_h_fptr(file, bstart, NULL);
	}
	AuDebugOn(au_fbstart(file) < bstart
		  || au_fi(file)->fi_hfile[0 + bstart].hf_file);

	h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
			   file);
	err = PTR_ERR(h_file);
	if (IS_ERR(h_file))
		goto out; /* todo: close all? */

	err = 0;
	au_set_fbstart(file, bstart);
	au_set_h_fptr(file, bstart, h_file);
	au_update_figen(file);
	/* todo: necessary? */
	/* file->f_ra = h_file->f_ra; */

	/* close lower files */
	bend = au_fbend(file);
	for (bindex = bstart + 1; bindex <= bend; bindex++)
		au_set_h_fptr(file, bindex, NULL);
	au_set_fbend(file, bstart);

 out:
	if (h_file_tmp)
		fput(h_file_tmp);
	return err;
}
Beispiel #5
0
static int reopen_dir(struct file *file)
{
	int err;
	unsigned int flags;
	aufs_bindex_t bindex, btail, bstart;
	struct dentry *dentry, *h_dentry;
	struct file *h_file;

	/* open all lower dirs */
	dentry = file->f_dentry;
	bstart = au_dbstart(dentry);
	for (bindex = au_fbstart(file); bindex < bstart; bindex++)
		au_set_h_fptr(file, bindex, NULL);
	au_set_fbstart(file, bstart);

	btail = au_dbtaildir(dentry);
	for (bindex = au_fbend_dir(file); btail < bindex; bindex--)
		au_set_h_fptr(file, bindex, NULL);
	au_set_fbend_dir(file, btail);

	flags = vfsub_file_flags(file);
	for (bindex = bstart; bindex <= btail; bindex++) {
		h_dentry = au_h_dptr(dentry, bindex);
		if (!h_dentry)
			continue;
		h_file = au_hf_dir(file, bindex);
		if (h_file)
			continue;

		h_file = au_h_open(dentry, bindex, flags, file);
		err = PTR_ERR(h_file);
		if (IS_ERR(h_file))
			goto out; /* close all? */
		au_set_h_fptr(file, bindex, h_file);
	}
	au_update_figen(file);
	/* todo: necessary? */
	/* file->f_ra = h_file->f_ra; */
	err = 0;

out:
	return err;
}
Beispiel #6
0
int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
	       struct au_fidir *fidir)
{
	int err;
	struct dentry *dentry;

	err = au_finfo_init(file, fidir);
	if (unlikely(err))
		goto out;

	dentry = file->f_dentry;
	di_read_lock_child(dentry, AuLock_IR);
	err = open(file, vfsub_file_flags(file));
	di_read_unlock(dentry, AuLock_IR);

	fi_write_unlock(file);
	if (unlikely(err)) {
		au_fi(file)->fi_hdir = NULL;
		au_finfo_fin(file);
	}

out:
	return err;
}
Beispiel #7
0
int au_do_open(struct file *file, int (*open)(struct file *file, int flags))
{
	int err;
	struct dentry *dentry;
	struct super_block *sb;

	dentry = file->f_dentry;
	sb = dentry->d_sb;
	si_read_lock(sb, AuLock_FLUSH);
	err = au_finfo_init(file);
	if (unlikely(err))
		goto out;

	di_read_lock_child(dentry, AuLock_IR);
	err = open(file, vfsub_file_flags(file));
	di_read_unlock(dentry, AuLock_IR);

	fi_write_unlock(file);
	if (unlikely(err))
		au_finfo_fin(file);
 out:
	si_read_unlock(sb);
	return err;
}
		au_sphl_add(&finfo->fi_hlist, &au_sbi(dentry->d_sb)->si_files);
		/* todo: necessary? */
		/* file->f_ra = h_file->f_ra; */
	}

	return err;
}

static int aufs_open_nondir(struct inode *inode __maybe_unused,
			    struct file *file)
{
	int err;
	struct super_block *sb;

	AuDbg("%pD, f_flags 0x%x, f_mode 0x%x\n",
	      file, vfsub_file_flags(file), file->f_mode);

	sb = file->f_dentry->d_sb;
	si_read_lock(sb, AuLock_FLUSH);
	err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
	si_read_unlock(sb);
	return err;
}

int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
{
	struct au_finfo *finfo;
	aufs_bindex_t bindex;

	finfo = au_fi(file);
	au_sphl_del(&finfo->fi_hlist, &au_sbi(file->f_dentry->d_sb)->si_files);
Beispiel #9
0
		/* todo: necessary? */
		/* file->f_ra = h_file->f_ra; */
	}

out:
	return err;
}

static int aufs_open_nondir(struct inode *inode __maybe_unused,
			    struct file *file)
{
	int err;
	struct super_block *sb;

	AuDbg("%.*s, f_flags 0x%x, f_mode 0x%x\n",
	      AuDLNPair(file->f_dentry), vfsub_file_flags(file),
	      file->f_mode);

	sb = file->f_dentry->d_sb;
	si_read_lock(sb, AuLock_FLUSH);
	err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
	si_read_unlock(sb);
	return err;
}

int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
{
	struct au_finfo *finfo;
	aufs_bindex_t bindex;

	finfo = au_fi(file);
Beispiel #10
0
static int au_cmoo(struct dentry *dentry)
{
	int err, cmoo;
	unsigned int udba;
	struct path h_path;
	struct au_pin pin;
	struct au_cp_generic cpg = {
		.dentry	= dentry,
		.bdst	= -1,
		.bsrc	= -1,
		.len	= -1,
		.pin	= &pin,
		.flags	= AuCpup_DTIME | AuCpup_HOPEN
	};
	struct inode *inode, *delegated;
	struct super_block *sb;
	struct au_sbinfo *sbinfo;
	struct au_fhsm *fhsm;
	pid_t pid;
	struct au_branch *br;
	struct dentry *parent;
	struct au_hinode *hdir;

	DiMustWriteLock(dentry);
	inode = dentry->d_inode;
	IiMustWriteLock(inode);

	err = 0;
	if (IS_ROOT(dentry))
		goto out;
	cpg.bsrc = au_dbstart(dentry);
	if (!cpg.bsrc)
		goto out;

	sb = dentry->d_sb;
	sbinfo = au_sbi(sb);
	fhsm = &sbinfo->si_fhsm;
	pid = au_fhsm_pid(fhsm);
	if (pid
	    && (current->pid == pid
		|| current->real_parent->pid == pid))
		goto out;

	br = au_sbr(sb, cpg.bsrc);
	cmoo = au_br_cmoo(br->br_perm);
	if (!cmoo)
		goto out;
	if (!S_ISREG(inode->i_mode))
		cmoo &= AuBrAttr_COO_ALL;
	if (!cmoo)
		goto out;

	parent = dget_parent(dentry);
	di_write_lock_parent(parent);
	err = au_wbr_do_copyup_bu(dentry, cpg.bsrc - 1);
	cpg.bdst = err;
	if (unlikely(err < 0)) {
		err = 0;	/* there is no upper writable branch */
		goto out_dgrade;
	}
	AuDbg("bsrc %d, bdst %d\n", cpg.bsrc, cpg.bdst);

	/* do not respect the coo attrib for the target branch */
	err = au_cpup_dirs(dentry, cpg.bdst);
	if (unlikely(err))
		goto out_dgrade;

	di_downgrade_lock(parent, AuLock_IR);
	udba = au_opt_udba(sb);
	err = au_pin(&pin, dentry, cpg.bdst, udba,
		     AuPin_DI_LOCKED | AuPin_MNT_WRITE);
	if (unlikely(err))
		goto out_parent;

	err = au_sio_cpup_simple(&cpg);
	au_unpin(&pin);
	if (unlikely(err))
		goto out_parent;
	if (!(cmoo & AuBrWAttr_MOO))
		goto out_parent; /* success */

	err = au_pin(&pin, dentry, cpg.bsrc, udba,
		     AuPin_DI_LOCKED | AuPin_MNT_WRITE);
	if (unlikely(err))
		goto out_parent;

	h_path.mnt = au_br_mnt(br);
	h_path.dentry = au_h_dptr(dentry, cpg.bsrc);
	hdir = au_hi(parent->d_inode, cpg.bsrc);
	delegated = NULL;
	err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, /*force*/1);
	au_unpin(&pin);
	/* todo: keep h_dentry or not? */
	if (unlikely(err == -EWOULDBLOCK)) {
		pr_warn("cannot retry for NFSv4 delegation"
			" for an internal unlink\n");
		iput(delegated);
	}
	if (unlikely(err)) {
		pr_err("unlink %pd after coo failed (%d), ignored\n",
		       dentry, err);
		err = 0;
	}
	goto out_parent; /* success */

out_dgrade:
	di_downgrade_lock(parent, AuLock_IR);
out_parent:
	di_read_unlock(parent, AuLock_IR);
	dput(parent);
out:
	AuTraceErr(err);
	return err;
}

int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
	       struct au_fidir *fidir)
{
	int err;
	struct dentry *dentry;
	struct au_finfo *finfo;

	err = au_finfo_init(file, fidir);
	if (unlikely(err))
		goto out;

	dentry = file->f_path.dentry;
	di_write_lock_child(dentry);
	err = au_cmoo(dentry);
	di_downgrade_lock(dentry, AuLock_IR);
	if (!err)
		err = open(file, vfsub_file_flags(file));
	di_read_unlock(dentry, AuLock_IR);

	finfo = au_fi(file);
	if (!err) {
		finfo->fi_file = file;
		au_sphl_add(&finfo->fi_hlist,
			    &au_sbi(file->f_path.dentry->d_sb)->si_files);
	}
	fi_write_unlock(file);
	if (unlikely(err)) {
		finfo->fi_hdir = NULL;
		au_finfo_fin(file);
	}

out:
	return err;
}