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:
parent
7078202e55
commit
82c1593cad
1 changed files with 36 additions and 56 deletions
|
@ -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 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
|
|||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
|
Loading…
Reference in a new issue