Skip to content
This repository has been archived by the owner on Jul 22, 2023. It is now read-only.

Commit

Permalink
Merge branch 'aufs2-32' into aufs2-33
Browse files Browse the repository at this point in the history
  • Loading branch information
J. R. Okajima committed Jun 3, 2010
2 parents 5dc4cd3 + 4c98b5f commit 5cd1d28
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 54 deletions.
18 changes: 10 additions & 8 deletions fs/aufs/cpup.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,29 +409,31 @@ static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
{
int err, symlen;
mm_segment_t old_fs;
char *sym;
union {
char *k;
char __user *u;
} sym;

err = -ENOSYS;
if (unlikely(!h_src->d_inode->i_op->readlink))
goto out;

err = -ENOMEM;
sym = __getname_gfp(GFP_NOFS);
if (unlikely(!sym))
sym.k = __getname_gfp(GFP_NOFS);
if (unlikely(!sym.k))
goto out;

old_fs = get_fs();
set_fs(KERNEL_DS);
symlen = h_src->d_inode->i_op->readlink(h_src, (char __user *)sym,
PATH_MAX);
symlen = h_src->d_inode->i_op->readlink(h_src, sym.u, PATH_MAX);
err = symlen;
set_fs(old_fs);

if (symlen > 0) {
sym[symlen] = 0;
err = vfsub_symlink(h_dir, h_path, sym);
sym.k[symlen] = 0;
err = vfsub_symlink(h_dir, h_path, sym.k);
}
__putname(sym);
__putname(sym.k);

out:
return err;
Expand Down
36 changes: 12 additions & 24 deletions fs/aufs/i_op.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,9 @@ static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
struct nameidata *nd)
{
struct dentry *ret, *parent;
struct inode *inode, *h_inode;
struct mutex *mtx;
struct inode *inode;
struct super_block *sb;
int err, npositive;
aufs_bindex_t bstart;

IMustLock(dir);

Expand All @@ -181,19 +179,7 @@ static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,

inode = NULL;
if (npositive) {
bstart = au_dbstart(dentry);
h_inode = au_h_dptr(dentry, bstart)->d_inode;
if (!S_ISDIR(h_inode->i_mode)) {
/*
* stop 'race'-ing between hardlinks under different
* parents.
*/
mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
mutex_lock(mtx);
inode = au_new_inode(dentry, /*must_new*/0);
mutex_unlock(mtx);
} else
inode = au_new_inode(dentry, /*must_new*/0);
inode = au_new_inode(dentry, /*must_new*/0);
ret = (void *)inode;
}
if (IS_ERR(inode))
Expand Down Expand Up @@ -844,29 +830,31 @@ static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
int err;
char *buf;
mm_segment_t old_fs;
union {
char *k;
char __user *u;
} buf;

err = -ENOMEM;
buf = __getname_gfp(GFP_NOFS);
if (unlikely(!buf))
buf.k = __getname_gfp(GFP_NOFS);
if (unlikely(!buf.k))
goto out;

aufs_read_lock(dentry, AuLock_IR);
old_fs = get_fs();
set_fs(KERNEL_DS);
err = h_readlink(dentry, au_dbstart(dentry), (char __user *)buf,
PATH_MAX);
err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX);
set_fs(old_fs);
aufs_read_unlock(dentry, AuLock_IR);

if (err >= 0) {
buf[err] = 0;
buf.k[err] = 0;
/* will be freed by put_link */
nd_set_link(nd, buf);
nd_set_link(nd, buf.k);
return NULL; /* success */
}
__putname(buf);
__putname(buf.k);

out:
path_put(&nd->path);
Expand Down
45 changes: 36 additions & 9 deletions fs/aufs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,10 @@ int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
{
int err;
struct mutex *mtx;
const int isdir = (d_type == DT_DIR);

/* prevent hardlinks from race condition */
/* prevent hardlinked inode number from race condition */
mtx = NULL;
if (!isdir) {
if (d_type != DT_DIR) {
mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
mutex_lock(mtx);
}
Expand All @@ -294,7 +293,7 @@ int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
}

out:
if (!isdir)
if (mtx)
mutex_unlock(mtx);
return err;
}
Expand All @@ -303,22 +302,36 @@ int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
/* todo: return with unlocked? */
struct inode *au_new_inode(struct dentry *dentry, int must_new)
{
struct inode *inode;
struct inode *inode, *h_inode;
struct dentry *h_dentry;
struct super_block *sb;
struct mutex *mtx;
ino_t h_ino, ino;
int err, match;
aufs_bindex_t bstart;

sb = dentry->d_sb;
bstart = au_dbstart(dentry);
h_dentry = au_h_dptr(dentry, bstart);
h_ino = h_dentry->d_inode->i_ino;
h_inode = h_dentry->d_inode;
h_ino = h_inode->i_ino;

/*
* stop 'race'-ing between hardlinks under different
* parents.
*/
mtx = NULL;
if (!S_ISDIR(h_inode->i_mode))
mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;

new_ino:
if (mtx)
mutex_lock(mtx);
err = au_xino_read(sb, bstart, h_ino, &ino);
inode = ERR_PTR(err);
if (unlikely(err))
goto out;
new_ino:

if (!ino) {
ino = au_xino_new_ino(sb);
if (unlikely(!ino)) {
Expand Down Expand Up @@ -346,11 +359,21 @@ struct inode *au_new_inode(struct dentry *dentry, int must_new)
iget_failed(inode);
goto out_err;
} else if (!must_new) {
/*
* horrible race condition between lookup, readdir and copyup
* (or something).
*/
if (mtx)
mutex_unlock(mtx);
err = reval_inode(inode, dentry, &match);
if (!err)
if (!err) {
mtx = NULL;
goto out; /* success */
else if (match)
} else if (match) {
mtx = NULL;
goto out_iput;
} else if (mtx)
mutex_lock(mtx);
}

if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
Expand All @@ -362,6 +385,8 @@ struct inode *au_new_inode(struct dentry *dentry, int must_new)
err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
if (!err) {
iput(inode);
if (mtx)
mutex_unlock(mtx);
goto new_ino;
}

Expand All @@ -370,6 +395,8 @@ struct inode *au_new_inode(struct dentry *dentry, int must_new)
out_err:
inode = ERR_PTR(err);
out:
if (mtx)
mutex_unlock(mtx);
return inode;
}

Expand Down
28 changes: 19 additions & 9 deletions fs/aufs/vfsub.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ int vfsub_create(struct inode *dir, struct path *path, int mode)

d = path->dentry;
path->dentry = d->d_parent;
err = security_path_mknod(path, path->dentry, mode, 0);
err = security_path_mknod(path, d, mode, 0);
path->dentry = d;
if (unlikely(err))
goto out;
Expand Down Expand Up @@ -249,7 +249,7 @@ int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)

d = path->dentry;
path->dentry = d->d_parent;
err = security_path_symlink(path, path->dentry, symname);
err = security_path_symlink(path, d, symname);
path->dentry = d;
if (unlikely(err))
goto out;
Expand Down Expand Up @@ -280,7 +280,7 @@ int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)

d = path->dentry;
path->dentry = d->d_parent;
err = security_path_mknod(path, path->dentry, mode, dev);
err = security_path_mknod(path, d, mode, dev);
path->dentry = d;
if (unlikely(err))
goto out;
Expand Down Expand Up @@ -325,7 +325,7 @@ int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)

d = path->dentry;
path->dentry = d->d_parent;
err = security_path_link(src_dentry, path, path->dentry);
err = security_path_link(src_dentry, path, d);
path->dentry = d;
if (unlikely(err))
goto out;
Expand Down Expand Up @@ -367,7 +367,7 @@ int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
d = path->dentry;
path->dentry = d->d_parent;
tmp.dentry = src_dentry->d_parent;
err = security_path_rename(&tmp, src_dentry, path, path->dentry);
err = security_path_rename(&tmp, src_dentry, path, d);
path->dentry = d;
if (unlikely(err))
goto out;
Expand Down Expand Up @@ -402,7 +402,7 @@ int vfsub_mkdir(struct inode *dir, struct path *path, int mode)

d = path->dentry;
path->dentry = d->d_parent;
err = security_path_mkdir(path, path->dentry, mode);
err = security_path_mkdir(path, d, mode);
path->dentry = d;
if (unlikely(err))
goto out;
Expand Down Expand Up @@ -433,7 +433,7 @@ int vfsub_rmdir(struct inode *dir, struct path *path)

d = path->dentry;
path->dentry = d->d_parent;
err = security_path_rmdir(path, path->dentry);
err = security_path_rmdir(path, d);
path->dentry = d;
if (unlikely(err))
goto out;
Expand Down Expand Up @@ -473,10 +473,15 @@ ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
{
ssize_t err;
mm_segment_t oldfs;
union {
void *k;
char __user *u;
} buf;

buf.k = kbuf;
oldfs = get_fs();
set_fs(KERNEL_DS);
err = vfsub_read_u(file, (char __user *)kbuf, count, ppos);
err = vfsub_read_u(file, buf.u, count, ppos);
set_fs(oldfs);
return err;
}
Expand All @@ -498,10 +503,15 @@ ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
{
ssize_t err;
mm_segment_t oldfs;
union {
void *k;
const char __user *u;
} buf;

buf.k = kbuf;
oldfs = get_fs();
set_fs(KERNEL_DS);
err = vfsub_write_u(file, (const char __user *)kbuf, count, ppos);
err = vfsub_write_u(file, buf.u, count, ppos);
set_fs(oldfs);
return err;
}
Expand Down
18 changes: 14 additions & 4 deletions fs/aufs/xino.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,22 @@
#include <linux/uaccess.h>
#include "aufs.h"

ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
loff_t *pos)
{
ssize_t err;
mm_segment_t oldfs;
union {
void *k;
char __user *u;
} buf;

buf.k = kbuf;
oldfs = get_fs();
set_fs(KERNEL_DS);
do {
/* todo: signal_pending? */
err = func(file, (char __user *)buf, size, pos);
err = func(file, buf.u, size, pos);
} while (err == -EAGAIN || err == -EINTR);
set_fs(oldfs);

Expand All @@ -49,18 +54,23 @@ ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,

/* ---------------------------------------------------------------------- */

static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *buf,
static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
size_t size, loff_t *pos)
{
ssize_t err;
mm_segment_t oldfs;
union {
void *k;
const char __user *u;
} buf;

buf.k = kbuf;
oldfs = get_fs();
set_fs(KERNEL_DS);
/* lockdep_off(); */
do {
/* todo: signal_pending? */
err = func(file, (const char __user *)buf, size, pos);
err = func(file, buf.u, size, pos);
} while (err == -EAGAIN || err == -EINTR);
/* lockdep_on(); */
set_fs(oldfs);
Expand Down

0 comments on commit 5cd1d28

Please sign in to comment.