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

aufs: inode op, rename 1/2, intro



Implement i_op->rename().
This is a big monster and I don't like it.

In order to call d_move() in aufs lock section, FS_RENAME_DOES_D_MOVE is
set to fstype.f_flags.
Signed-off-by: default avatarJ. R. Okajima <hooanon05g@gmail.com>
parent 5755f006
...@@ -78,6 +78,9 @@ void di_read_unlock(struct dentry *d, int flags); ...@@ -78,6 +78,9 @@ void di_read_unlock(struct dentry *d, int flags);
void di_downgrade_lock(struct dentry *d, int flags); void di_downgrade_lock(struct dentry *d, int flags);
void di_write_lock(struct dentry *d, unsigned int lsc); void di_write_lock(struct dentry *d, unsigned int lsc);
void di_write_unlock(struct dentry *d); void di_write_unlock(struct dentry *d);
void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
void di_write_unlock2(struct dentry *d1, struct dentry *d2);
struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex); struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
aufs_bindex_t au_dbtail(struct dentry *dentry); aufs_bindex_t au_dbtail(struct dentry *dentry);
......
...@@ -258,6 +258,47 @@ void di_write_unlock(struct dentry *d) ...@@ -258,6 +258,47 @@ void di_write_unlock(struct dentry *d)
au_rw_write_unlock(&au_di(d)->di_rwsem); au_rw_write_unlock(&au_di(d)->di_rwsem);
} }
void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
{
AuDebugOn(d1 == d2
|| d_inode(d1) == d_inode(d2)
|| d1->d_sb != d2->d_sb);
if ((isdir && au_test_subdir(d1, d2))
|| d1 < d2) {
di_write_lock_child(d1);
di_write_lock_child2(d2);
} else {
di_write_lock_child(d2);
di_write_lock_child2(d1);
}
}
void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
{
AuDebugOn(d1 == d2
|| d_inode(d1) == d_inode(d2)
|| d1->d_sb != d2->d_sb);
if ((isdir && au_test_subdir(d1, d2))
|| d1 < d2) {
di_write_lock_parent(d1);
di_write_lock_parent2(d2);
} else {
di_write_lock_parent(d2);
di_write_lock_parent2(d1);
}
}
void di_write_unlock2(struct dentry *d1, struct dentry *d2)
{
di_write_unlock(d1);
if (d_inode(d1) == d_inode(d2))
au_rw_write_unlock(&au_di(d2)->di_rwsem);
else
di_write_unlock(d2);
}
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex) struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
......
...@@ -243,3 +243,38 @@ void aufs_write_unlock(struct dentry *dentry) ...@@ -243,3 +243,38 @@ void aufs_write_unlock(struct dentry *dentry)
di_write_unlock(dentry); di_write_unlock(dentry);
si_write_unlock(dentry->d_sb); si_write_unlock(dentry->d_sb);
} }
int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
{
int err;
unsigned int sigen;
struct super_block *sb;
sb = d1->d_sb;
err = si_read_lock(sb, flags);
if (unlikely(err))
goto out;
di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIRS));
if (au_ftest_lock(flags, GEN)) {
sigen = au_sigen(sb);
err = au_digen_test(d1, sigen);
AuDebugOn(!err && au_dbrange_test(d1));
if (!err) {
err = au_digen_test(d2, sigen);
AuDebugOn(!err && au_dbrange_test(d2));
}
if (unlikely(err))
aufs_read_and_write_unlock2(d1, d2);
}
out:
return err;
}
void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
{
di_write_unlock2(d1, d2);
si_read_unlock(d1->d_sb);
}
...@@ -897,6 +897,8 @@ static void aufs_kill_sb(struct super_block *sb) ...@@ -897,6 +897,8 @@ static void aufs_kill_sb(struct super_block *sb)
struct file_system_type aufs_fs_type = { struct file_system_type aufs_fs_type = {
.name = AUFS_FSTYPE, .name = AUFS_FSTYPE,
/* a race between rename and others */
.fs_flags = FS_RENAME_DOES_D_MOVE,
.mount = aufs_mount, .mount = aufs_mount,
.kill_sb = aufs_kill_sb, .kill_sb = aufs_kill_sb,
/* no need to __module_get() and module_put(). */ /* no need to __module_get() and module_put(). */
......
...@@ -188,6 +188,8 @@ static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi, ...@@ -188,6 +188,8 @@ static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
#define AuLock_IR (1 << 1) /* read-lock inode */ #define AuLock_IR (1 << 1) /* read-lock inode */
#define AuLock_IW (1 << 2) /* write-lock inode */ #define AuLock_IW (1 << 2) /* write-lock inode */
#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */ #define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
#define AuLock_DIRS (1 << 4) /* target is a pair of dirs */
/* except RENAME_EXCHANGE */
#define AuLock_NOPLM (1 << 5) /* return err in plm mode */ #define AuLock_NOPLM (1 << 5) /* return err in plm mode */
#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */ #define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
#define AuLock_GEN (1 << 7) /* test digen/iigen */ #define AuLock_GEN (1 << 7) /* test digen/iigen */
...@@ -223,6 +225,8 @@ int aufs_read_lock(struct dentry *dentry, int flags); ...@@ -223,6 +225,8 @@ int aufs_read_lock(struct dentry *dentry, int flags);
void aufs_read_unlock(struct dentry *dentry, int flags); void aufs_read_unlock(struct dentry *dentry, int flags);
void aufs_write_lock(struct dentry *dentry); void aufs_write_lock(struct dentry *dentry);
void aufs_write_unlock(struct dentry *dentry); void aufs_write_unlock(struct dentry *dentry);
int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
/* wbr_policy.c */ /* wbr_policy.c */
extern struct au_wbr_copyup_operations au_wbr_copyup_ops[]; extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
......
...@@ -101,6 +101,34 @@ void vfsub_call_lkup_one(void *args) ...@@ -101,6 +101,34 @@ void vfsub_call_lkup_one(void *args)
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
struct dentry *d2, struct au_hinode *hdir2)
{
struct dentry *d;
lockdep_off();
d = lock_rename(d1, d2);
lockdep_on();
au_hn_suspend(hdir1);
if (hdir1 != hdir2)
au_hn_suspend(hdir2);
return d;
}
void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
struct dentry *d2, struct au_hinode *hdir2)
{
au_hn_resume(hdir1);
if (hdir1 != hdir2)
au_hn_resume(hdir2);
lockdep_off();
unlock_rename(d1, d2);
lockdep_on();
}
/* ---------------------------------------------------------------------- */
int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl) int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl)
{ {
int err; int err;
......
...@@ -98,6 +98,12 @@ static inline void vfsub_mnt_drop_write(struct vfsmount *mnt) ...@@ -98,6 +98,12 @@ static inline void vfsub_mnt_drop_write(struct vfsmount *mnt)
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
struct au_hinode;
struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
struct dentry *d2, struct au_hinode *hdir2);
void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
struct dentry *d2, struct au_hinode *hdir2);
int vfsub_create(struct inode *dir, struct path *path, int mode, int vfsub_create(struct inode *dir, struct path *path, int mode,
bool want_excl); bool want_excl);
int vfsub_symlink(struct inode *dir, struct path *path, int vfsub_symlink(struct inode *dir, struct path *path,
......
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