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

aufs: atomic_open 4/5, introduce au_aopen_or_create()



This new function au_aopen_or_create() tries calling branch fs's
->atomic_open() first. If it is not set, call vfs_create() instead.
By putting this behaviour into aufs's add_simple(), many codes can be
shared.
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent 51a7f431
...@@ -211,8 +211,10 @@ struct simple_arg { ...@@ -211,8 +211,10 @@ struct simple_arg {
int type; int type;
union { union {
struct { struct {
umode_t mode; umode_t mode;
bool want_excl; bool want_excl;
bool try_aopen;
struct vfsub_aopen_args *aopen;
} c; } c;
struct { struct {
const char *symname; const char *symname;
...@@ -230,8 +232,13 @@ static int add_simple(struct inode *dir, struct dentry *dentry, ...@@ -230,8 +232,13 @@ static int add_simple(struct inode *dir, struct dentry *dentry,
int err, rerr; int err, rerr;
aufs_bindex_t btop; aufs_bindex_t btop;
unsigned char created; unsigned char created;
const unsigned char try_aopen
= (arg->type == Creat && arg->u.c.try_aopen);
struct vfsub_aopen_args *aopen = arg->u.c.aopen;
struct dentry *wh_dentry, *parent; struct dentry *wh_dentry, *parent;
struct inode *h_dir; struct inode *h_dir;
struct super_block *sb;
struct au_branch *br;
/* to reduce stack size */ /* to reduce stack size */
struct { struct {
struct au_dtime dt; struct au_dtime dt;
...@@ -251,13 +258,16 @@ static int add_simple(struct inode *dir, struct dentry *dentry, ...@@ -251,13 +258,16 @@ static int add_simple(struct inode *dir, struct dentry *dentry,
a->wr_dir_args.flags = AuWrDir_ADD_ENTRY; a->wr_dir_args.flags = AuWrDir_ADD_ENTRY;
parent = dentry->d_parent; /* dir inode is locked */ parent = dentry->d_parent; /* dir inode is locked */
err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN); if (!try_aopen) {
if (unlikely(err)) err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
goto out_free; if (unlikely(err))
goto out_free;
}
err = au_d_may_add(dentry); err = au_d_may_add(dentry);
if (unlikely(err)) if (unlikely(err))
goto out_unlock; goto out_unlock;
di_write_lock_parent(parent); if (!try_aopen)
di_write_lock_parent(parent);
wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL, wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
&a->pin, &a->wr_dir_args); &a->pin, &a->wr_dir_args);
err = PTR_ERR(wh_dentry); err = PTR_ERR(wh_dentry);
...@@ -265,30 +275,49 @@ static int add_simple(struct inode *dir, struct dentry *dentry, ...@@ -265,30 +275,49 @@ static int add_simple(struct inode *dir, struct dentry *dentry,
goto out_parent; goto out_parent;
btop = au_dbtop(dentry); btop = au_dbtop(dentry);
sb = dentry->d_sb;
br = au_sbr(sb, btop);
a->h_path.dentry = au_h_dptr(dentry, btop); a->h_path.dentry = au_h_dptr(dentry, btop);
a->h_path.mnt = au_sbr_mnt(dentry->d_sb, btop); a->h_path.mnt = au_br_mnt(br);
h_dir = au_pinned_h_dir(&a->pin); h_dir = au_pinned_h_dir(&a->pin);
switch (arg->type) { switch (arg->type) {
case Creat: case Creat:
err = vfsub_create(h_dir, &a->h_path, arg->u.c.mode, if (!try_aopen || !h_dir->i_op->atomic_open) {
arg->u.c.want_excl); err = vfsub_create(h_dir, &a->h_path, arg->u.c.mode,
arg->u.c.want_excl);
created = !err;
if (!err && try_aopen)
aopen->file->f_mode |= FMODE_CREATED;
} else {
aopen->br = br;
err = vfsub_atomic_open(h_dir, a->h_path.dentry, aopen);
AuDbg("err %d\n", err);
AuDbgFile(aopen->file);
created = err >= 0
&& !!(aopen->file->f_mode & FMODE_CREATED);
}
break; break;
case Symlink: case Symlink:
err = vfsub_symlink(h_dir, &a->h_path, arg->u.s.symname); err = vfsub_symlink(h_dir, &a->h_path, arg->u.s.symname);
created = !err;
break; break;
case Mknod: case Mknod:
err = vfsub_mknod(h_dir, &a->h_path, arg->u.m.mode, err = vfsub_mknod(h_dir, &a->h_path, arg->u.m.mode,
arg->u.m.dev); arg->u.m.dev);
created = !err;
break; break;
default: default:
BUG(); BUG();
} }
created = !err; if (unlikely(err < 0))
goto out_unpin;
err = epilog(dir, btop, wh_dentry, dentry);
if (!err) if (!err)
err = epilog(dir, btop, wh_dentry, dentry); goto out_unpin; /* success */
/* revert */ /* revert */
if (unlikely(created && err && d_is_positive(a->h_path.dentry))) { if (created /* && d_is_positive(a->h_path.dentry) */) {
/* no delegation since it is just created */ /* no delegation since it is just created */
rerr = vfsub_unlink(h_dir, &a->h_path, /*delegated*/NULL, rerr = vfsub_unlink(h_dir, &a->h_path, /*delegated*/NULL,
/*force*/0); /*force*/0);
...@@ -299,18 +328,24 @@ static int add_simple(struct inode *dir, struct dentry *dentry, ...@@ -299,18 +328,24 @@ static int add_simple(struct inode *dir, struct dentry *dentry,
} }
au_dtime_revert(&a->dt); au_dtime_revert(&a->dt);
} }
if (try_aopen && h_dir->i_op->atomic_open
&& (aopen->file->f_mode & FMODE_OPENED))
/* aopen->file is still opened */
au_lcnt_dec(&aopen->br->br_nfiles);
out_unpin:
au_unpin(&a->pin); au_unpin(&a->pin);
dput(wh_dentry); dput(wh_dentry);
out_parent: out_parent:
di_write_unlock(parent); if (!try_aopen)
di_write_unlock(parent);
out_unlock: out_unlock:
if (unlikely(err)) { if (unlikely(err)) {
au_update_dbtop(dentry); au_update_dbtop(dentry);
d_drop(dentry); d_drop(dentry);
} }
aufs_read_unlock(dentry, AuLock_DW); if (!try_aopen)
aufs_read_unlock(dentry, AuLock_DW);
out_free: out_free:
au_kfree_rcu(a); au_kfree_rcu(a);
out: out:
...@@ -352,6 +387,21 @@ int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, ...@@ -352,6 +387,21 @@ int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
return add_simple(dir, dentry, &arg); return add_simple(dir, dentry, &arg);
} }
int au_aopen_or_create(struct inode *dir, struct dentry *dentry,
struct vfsub_aopen_args *aopen_args)
{
struct simple_arg arg = {
.type = Creat,
.u.c = {
.mode = aopen_args->create_mode,
.want_excl = aopen_args->open_flag & O_EXCL,
.try_aopen = true,
.aopen = aopen_args
}
};
return add_simple(dir, dentry, &arg);
}
int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
{ {
int err; int err;
......
...@@ -195,6 +195,9 @@ int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, ...@@ -195,6 +195,9 @@ int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname); int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
bool want_excl); bool want_excl);
struct vfsub_aopen_args;
int au_aopen_or_create(struct inode *dir, struct dentry *dentry,
struct vfsub_aopen_args *args);
int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode); int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode);
int aufs_link(struct dentry *src_dentry, struct inode *dir, int aufs_link(struct dentry *src_dentry, struct inode *dir,
struct dentry *dentry); struct dentry *dentry);
......
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