[PATCH 1/3] udf: Replace bkl with the inode->i_alloc_sem for protect udf_inode_info struct

Previous thread: [PATCH] mmci: handle clock frequency 0 properly by Linus Walleij on Tuesday, November 16, 2010 - 10:17 am. (3 messages)

Next thread: [PATCH] powerpc: Update a comment by Alessio Igor Bogani on Tuesday, November 16, 2010 - 10:55 am. (1 message)
From: Alessio Igor Bogani
Date: Tuesday, November 16, 2010 - 10:40 am

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);
 
 ...
From: Alessio Igor Bogani
Date: Tuesday, November 16, 2010 - 10:40 am

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) +
 ...
From: Alessio Igor Bogani
Date: Tuesday, November 16, 2010 - 10:40 am

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 ...
From: Christoph Hellwig
Date: Tuesday, November 16, 2010 - 11:05 am

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.

--

From: Jan Kara
Date: Tuesday, November 16, 2010 - 2:42 pm

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
--

From: Alessio Igor Bogani
Date: Tuesday, November 16, 2010 - 4:04 pm

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 ...
Previous thread: [PATCH] mmci: handle clock frequency 0 properly by Linus Walleij on Tuesday, November 16, 2010 - 10:17 am. (3 messages)

Next thread: [PATCH] powerpc: Update a comment by Alessio Igor Bogani on Tuesday, November 16, 2010 - 10:55 am. (1 message)