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

aufs: bugfix, protect creating XINO from concurrent mounts



At the mount-time, XINO files are created and removed very soon.  When
multiple mounts with being given the same XINO file path executed in
parallel, some of them may fail in creating XINO due to EEXIST.
Introducing a local mutex, make it serialized.
By default, XINO is created at the top dir of the first writable
branch.  In this case, the new mutex won't be used.

Obviously this is an unnecessary overhead when the XINO file path is not
same, and such lock should be done by inode_lock() for the parent dir.
Actually au_xino_create2() behaves in this manner.  Then why didn't I
apply the same way to this au_xino_create()?  It is just because of my
laziness.  Calling VFS filp_open() here is easy for me.
Reported-by: default avatarKirill Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
(cherry picked from commit 30d9273f2a1ce331b1a79b770bdb4c493919a673)
parent aabf07ba
......@@ -212,7 +212,8 @@ int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs);
static const loff_t au_loff_max = LLONG_MAX;
aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry);
struct file *au_xino_create(struct super_block *sb, char *fpath, int silent);
struct file *au_xino_create(struct super_block *sb, char *fpath, int silent,
int wbrtop);
struct file *au_xino_create2(struct super_block *sb, struct path *base,
struct file *copy_src);
struct au_xi_new {
......
......@@ -905,7 +905,7 @@ static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
int err;
struct file *file;
file = au_xino_create(sb, args[0].from, /*silent*/0);
file = au_xino_create(sb, args[0].from, /*silent*/0, /*wbrtop*/0);
err = PTR_ERR(file);
if (IS_ERR(file))
goto out;
......
......@@ -147,22 +147,28 @@ static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
/*
* create and set a new xino file
*/
struct file *au_xino_create(struct super_block *sb, char *fpath, int silent)
struct file *au_xino_create(struct super_block *sb, char *fpath, int silent,
int wbrtop)
{
struct file *file;
struct dentry *h_parent, *d;
struct inode *h_dir, *inode;
int err;
static DEFINE_MUTEX(mtx);
/*
* at mount-time, and the xino file is the default path,
* hnotify is disabled so we have no notify events to ignore.
* when a user specified the xino, we cannot get au_hdir to be ignored.
*/
if (!wbrtop)
mutex_lock(&mtx);
file = vfsub_filp_open(fpath, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
/* | __FMODE_NONOTIFY */,
0666);
if (IS_ERR(file)) {
if (!wbrtop)
mutex_unlock(&mtx);
if (!silent)
pr_err("open %s(%ld)\n", fpath, PTR_ERR(file));
return file;
......@@ -172,6 +178,8 @@ struct file *au_xino_create(struct super_block *sb, char *fpath, int silent)
err = 0;
d = file->f_path.dentry;
h_parent = au_dget_parent_lock(d, AuLsc_I_PARENT);
if (!wbrtop)
mutex_unlock(&mtx);
/* mnt_want_write() is unnecessary here */
h_dir = d_inode(h_parent);
inode = file_inode(file);
......@@ -1654,11 +1662,12 @@ struct file *au_xino_def(struct super_block *sb)
if (!IS_ERR(p)) {
strcat(p, "/" AUFS_XINO_FNAME);
AuDbg("%s\n", p);
file = au_xino_create(sb, p, /*silent*/0);
file = au_xino_create(sb, p, /*silent*/0, /*wbrtop*/1);
}
free_page((unsigned long)page);
} else {
file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0,
/*wbrtop*/0);
if (IS_ERR(file))
goto out;
h_sb = file->f_path.dentry->d_sb;
......
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