Replace bkl with the inode->i_alloc_sem rw semaphore in udf_release_file(),
udf_symlink(), udf_symlink_filler(), udf_get_block() and udf_block_map().
Add protection in udf_evict_inode() using the same i_alloc_sem rw semaphore.
This work was supported by a hardware donation from the CE Linux Forum.
Signed-off-by: Alessio Igor Bogani <abogani@texware.it>
---
fs/udf/file.c | 4 ++--
fs/udf/inode.c | 11 +++++++----
fs/udf/namei.c | 4 ++--
fs/udf/symlink.c | 12 +++++++-----
fs/udf/udf_i.h | 9 +++++++++
5 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 66b9e7e..4cb0f7a 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -204,10 +204,10 @@ static int udf_release_file(struct inode *inode, struct file *filp)
{
if (filp->f_mode & FMODE_WRITE) {
mutex_lock(&inode->i_mutex);
- lock_kernel();
+ down_write(&inode->i_alloc_sem);
udf_discard_prealloc(inode);
udf_truncate_tail_extent(inode);
- unlock_kernel();
+ up_write(&inode->i_alloc_sem);
mutex_unlock(&inode->i_mutex);
}
return 0;
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index fa3c154..14e3f56 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -79,7 +79,9 @@ void udf_evict_inode(struct inode *inode)
if (!inode->i_nlink && !is_bad_inode(inode)) {
want_delete = 1;
inode->i_size = 0;
+ down_write(&inode->i_alloc_sem);
udf_truncate(inode);
+ up_write(&inode->i_alloc_sem);
udf_update_inode(inode, IS_SYNC(inode));
}
invalidate_inode_buffers(inode);
@@ -302,9 +304,10 @@ static int udf_get_block(struct inode *inode, sector_t block,
new = 0;
bh = NULL;
- lock_kernel();
+ down_write(&inode->i_alloc_sem);
iinfo = UDF_I(inode);
+
if (block == iinfo->i_next_alloc_block + 1) {
iinfo->i_next_alloc_block++;
iinfo->i_next_alloc_goal++;
@@ -323,7 +326,7 @@ static int udf_get_block(struct inode *inode, sector_t block,
map_bh(bh_result, inode->i_sb, phys);
...This work was supported by a hardware donation from the CE Linux Forum.
Signed-off-by: Alessio Igor Bogani <abogani@texware.it>
---
fs/udf/partition.c | 27 +++++++++++++++++++--------
1 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/fs/udf/partition.c b/fs/udf/partition.c
index 745eb20..a71090e 100644
--- a/fs/udf/partition.c
+++ b/fs/udf/partition.c
@@ -25,6 +25,7 @@
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/buffer_head.h>
+#include <linux/mutex.h>
uint32_t udf_get_pblock(struct super_block *sb, uint32_t block,
uint16_t partition, uint32_t offset)
@@ -159,7 +160,9 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
struct udf_sb_info *sbi = UDF_SB(sb);
u16 reallocationTableLen;
struct buffer_head *bh;
+ int ret = 0;
+ mutex_lock(&sbi->s_alloc_mutex);
for (i = 0; i < sbi->s_partitions; i++) {
struct udf_part_map *map = &sbi->s_partmaps[i];
if (old_block > map->s_partition_root &&
@@ -175,8 +178,10 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
break;
}
- if (!st)
- return 1;
+ if (!st) {
+ ret = 1;
+ goto out;
+ }
reallocationTableLen =
le16_to_cpu(st->reallocationTableLen);
@@ -207,14 +212,16 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
((old_block -
map->s_partition_root) &
(sdata->s_packet_len - 1));
- return 0;
+ ret = 0;
+ goto out;
} else if (origLoc == packet) {
*new_block = le32_to_cpu(
entry->mappedLocation) +
((old_block -
map->s_partition_root) &
(sdata->s_packet_len - 1));
- return 0;
+ ret = 0;
+ goto out;
} else if (origLoc > packet)
break;
}
@@ -251,20 +258,24 @@ int udf_relocate_blocks(struct super_block *sb, long old_block, long *new_block)
st->mapEntry[k].mappedLocation) +
...The udf_readdir(), udf_lookup(), udf_create(), udf_mknod(), udf_mkdir(),
udf_rmdir(), udf_link(), udf_get_parent() and udf_unlink() seems already
adequately protected by i_mutex held by VFS invoking calls. The udf_rename()
instead should be already protected by lock_rename again by VFS. The
udf_truncate() is protected by i_alloc_sem. The udf_ioctl(), udf_fill_super()
and udf_evict_inode() don't requires any further protection.
This work was supported by a hardware donation from the CE Linux Forum.
Signed-off-by: Alessio Igor Bogani <abogani@texware.it>
---
fs/udf/dir.c | 5 -----
fs/udf/file.c | 4 ----
fs/udf/inode.c | 6 ------
fs/udf/namei.c | 27 ---------------------------
fs/udf/super.c | 9 +--------
5 files changed, 1 insertions(+), 50 deletions(-)
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
index 51552bf..eb8bfe2 100644
--- a/fs/udf/dir.c
+++ b/fs/udf/dir.c
@@ -30,7 +30,6 @@
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
#include <linux/buffer_head.h>
#include "udf_i.h"
@@ -190,18 +189,14 @@ static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
struct inode *dir = filp->f_path.dentry->d_inode;
int result;
- lock_kernel();
-
if (filp->f_pos == 0) {
if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0) {
- unlock_kernel();
return 0;
}
filp->f_pos++;
}
result = do_udf_readdir(dir, filp, filldir, dirent);
- unlock_kernel();
return result;
}
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 4cb0f7a..aa12069 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -32,7 +32,6 @@
#include <linux/string.h> /* memset */
#include <linux/capability.h>
#include <linux/errno.h>
-#include <linux/smp_lock.h>
#include <linux/pagemap.h>
#include <linux/buffer_head.h>
#include <linux/aio.h>
@@ -149,8 +148,6 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
long old_block, new_block;
int ...I'd rather prefer not to introduce new users of i_alloc_sem. It's a quite nasty beast: the only rw_semaphore that is not released by the thread acquiring it. Thomas asked me if there's a way to get rid of it, and I've come up with some schemes that I need to prototype. Adding more uses that are unrelated to the original direct I/O use case are not very helpful in doing that. --
OK, I didn't know this. It's no problem to replace i_alloc_sem with a private rw_semaphore so I can do that. I just thought we might as well use it when it's there and not waste more inode memory... Honza -- Jan Kara <jack@suse.cz> SUSE Labs, CR --
Replace bkl with the udf_inode_info's ii_alloc_sem rw semaphore in
udf_release_file(), udf_symlink(), udf_symlink_filler(), udf_get_block() and
udf_block_map(). Add protection in udf_evict_inode() using the same
ii_alloc_sem rw semaphore.
This work was supported by a hardware donation from the CE Linux Forum.
Signed-off-by: Alessio Igor Bogani <abogani@texware.it>
---
fs/udf/file.c | 6 ++++--
fs/udf/inode.c | 14 +++++++++-----
fs/udf/namei.c | 6 +++---
fs/udf/super.c | 2 ++
fs/udf/symlink.c | 12 +++++++-----
fs/udf/udf_i.h | 10 ++++++++++
6 files changed, 35 insertions(+), 15 deletions(-)
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 66b9e7e..5724eca 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -202,12 +202,14 @@ out:
static int udf_release_file(struct inode *inode, struct file *filp)
{
+ struct udf_inode_info *iinfo = UDF_I(inode);
+
if (filp->f_mode & FMODE_WRITE) {
mutex_lock(&inode->i_mutex);
- lock_kernel();
+ down_write(&iinfo->ii_alloc_sem);
udf_discard_prealloc(inode);
udf_truncate_tail_extent(inode);
- unlock_kernel();
+ up_write(&iinfo->ii_alloc_sem);
mutex_unlock(&inode->i_mutex);
}
return 0;
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index fa3c154..b7e5089 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -79,7 +79,9 @@ void udf_evict_inode(struct inode *inode)
if (!inode->i_nlink && !is_bad_inode(inode)) {
want_delete = 1;
inode->i_size = 0;
+ down_write(&iinfo->ii_alloc_sem);
udf_truncate(inode);
+ up_write(&iinfo->ii_alloc_sem);
udf_update_inode(inode, IS_SYNC(inode));
}
invalidate_inode_buffers(inode);
@@ -302,9 +304,10 @@ static int udf_get_block(struct inode *inode, sector_t block,
new = 0;
bh = NULL;
- lock_kernel();
-
iinfo = UDF_I(inode);
+
+ down_write(&iinfo->ii_alloc_sem);
+
if (block == iinfo->i_next_alloc_block + 1) {
iinfo->i_next_alloc_block++;
iinfo->i_next_alloc_goal++;
@@ -323,7 +326,7 @@ static int ...