UBIFS: simplify locking

This patch simplifies lock_[23]_inodes functions. We do not have
to care about locking order, because UBIFS does this for @i_mutex
and this is enough. Thanks to Al Viro for suggesting this.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
This commit is contained in:
Artem Bityutskiy 2009-01-20 16:46:02 +02:00
parent 7078202e55
commit 82c1593cad
1 changed files with 36 additions and 56 deletions

View File

@ -482,30 +482,29 @@ static int ubifs_dir_release(struct inode *dir, struct file *file)
}
/**
* lock_2_inodes - lock two UBIFS inodes.
* lock_2_inodes - a wrapper for locking two UBIFS inodes.
* @inode1: first inode
* @inode2: second inode
*
* We do not implement any tricks to guarantee strict lock ordering, because
* VFS has already done it for us on the @i_mutex. So this is just a simple
* wrapper function.
*/
static void lock_2_inodes(struct inode *inode1, struct inode *inode2)
{
if (inode1->i_ino < inode2->i_ino) {
mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_2);
mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_3);
} else {
mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_3);
}
mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
}
/**
* unlock_2_inodes - unlock two UBIFS inodes inodes.
* unlock_2_inodes - a wrapper for unlocking two UBIFS inodes.
* @inode1: first inode
* @inode2: second inode
*/
static void unlock_2_inodes(struct inode *inode1, struct inode *inode2)
{
mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
mutex_unlock(&ubifs_inode(inode2)->ui_mutex);
mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
}
static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
@ -527,6 +526,8 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
dbg_gen("dent '%.*s' to ino %lu (nlink %d) in dir ino %lu",
dentry->d_name.len, dentry->d_name.name, inode->i_ino,
inode->i_nlink, dir->i_ino);
ubifs_assert(mutex_is_locked(&dir->i_mutex));
ubifs_assert(mutex_is_locked(&inode->i_mutex));
err = dbg_check_synced_i_size(inode);
if (err)
return err;
@ -580,6 +581,8 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
dbg_gen("dent '%.*s' from ino %lu (nlink %d) in dir ino %lu",
dentry->d_name.len, dentry->d_name.name, inode->i_ino,
inode->i_nlink, dir->i_ino);
ubifs_assert(mutex_is_locked(&dir->i_mutex));
ubifs_assert(mutex_is_locked(&inode->i_mutex));
err = dbg_check_synced_i_size(inode);
if (err)
return err;
@ -667,7 +670,8 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
dbg_gen("directory '%.*s', ino %lu in dir ino %lu", dentry->d_name.len,
dentry->d_name.name, inode->i_ino, dir->i_ino);
ubifs_assert(mutex_is_locked(&dir->i_mutex));
ubifs_assert(mutex_is_locked(&inode->i_mutex));
err = check_dir_empty(c, dentry->d_inode);
if (err)
return err;
@ -922,59 +926,30 @@ out_budg:
}
/**
* lock_3_inodes - lock three UBIFS inodes for rename.
* lock_3_inodes - a wrapper for locking three UBIFS inodes.
* @inode1: first inode
* @inode2: second inode
* @inode3: third inode
*
* For 'ubifs_rename()', @inode1 may be the same as @inode2 whereas @inode3 may
* be null.
* This function is used for 'ubifs_rename()' and @inode1 may be the same as
* @inode2 whereas @inode3 may be %NULL.
*
* We do not implement any tricks to guarantee strict lock ordering, because
* VFS has already done it for us on the @i_mutex. So this is just a simple
* wrapper function.
*/
static void lock_3_inodes(struct inode *inode1, struct inode *inode2,
struct inode *inode3)
{
struct inode *i1, *i2, *i3;
if (!inode3) {
if (inode1 != inode2) {
lock_2_inodes(inode1, inode2);
return;
}
mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
return;
}
if (inode1 == inode2) {
lock_2_inodes(inode1, inode3);
return;
}
/* 3 different inodes */
if (inode1 < inode2) {
i3 = inode2;
if (inode1 < inode3) {
i1 = inode1;
i2 = inode3;
} else {
i1 = inode3;
i2 = inode1;
}
} else {
i3 = inode1;
if (inode2 < inode3) {
i1 = inode2;
i2 = inode3;
} else {
i1 = inode3;
i2 = inode2;
}
}
mutex_lock_nested(&ubifs_inode(i1)->ui_mutex, WB_MUTEX_1);
lock_2_inodes(i2, i3);
mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
if (inode2 != inode1)
mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
if (inode3)
mutex_lock_nested(&ubifs_inode(inode3)->ui_mutex, WB_MUTEX_3);
}
/**
* unlock_3_inodes - unlock three UBIFS inodes for rename.
* unlock_3_inodes - a wrapper for unlocking three UBIFS inodes for rename.
* @inode1: first inode
* @inode2: second inode
* @inode3: third inode
@ -982,11 +957,11 @@ static void lock_3_inodes(struct inode *inode1, struct inode *inode2,
static void unlock_3_inodes(struct inode *inode1, struct inode *inode2,
struct inode *inode3)
{
mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
if (inode1 != inode2)
mutex_unlock(&ubifs_inode(inode2)->ui_mutex);
if (inode3)
mutex_unlock(&ubifs_inode(inode3)->ui_mutex);
if (inode1 != inode2)
mutex_unlock(&ubifs_inode(inode2)->ui_mutex);
mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
}
static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
@ -1020,6 +995,11 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
"dir ino %lu", old_dentry->d_name.len, old_dentry->d_name.name,
old_inode->i_ino, old_dir->i_ino, new_dentry->d_name.len,
new_dentry->d_name.name, new_dir->i_ino);
ubifs_assert(mutex_is_locked(&old_dir->i_mutex));
ubifs_assert(mutex_is_locked(&new_dir->i_mutex));
if (unlink)
ubifs_assert(mutex_is_locked(&new_inode->i_mutex));
if (unlink && is_dir) {
err = check_dir_empty(c, new_inode);