From ed2ae6f69148dcf9da725364e17184f27ba04dc2 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 4 Nov 2010 20:08:04 -0700 Subject: fs/udf: Use vzalloc Signed-off-by: Joe Perches Signed-off-by: Jan Kara --- fs/udf/super.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'fs/udf/super.c') diff --git a/fs/udf/super.c b/fs/udf/super.c index 4a5c7c61836..f99ff5dbd74 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -959,9 +959,9 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index) (sizeof(struct buffer_head *) * nr_groups); if (size <= PAGE_SIZE) - bitmap = kmalloc(size, GFP_KERNEL); + bitmap = kzalloc(size, GFP_KERNEL); else - bitmap = vmalloc(size); /* TODO: get rid of vmalloc */ + bitmap = vzalloc(size); /* TODO: get rid of vzalloc */ if (bitmap == NULL) { udf_error(sb, __func__, @@ -970,7 +970,6 @@ static struct udf_bitmap *udf_sb_alloc_bitmap(struct super_block *sb, u32 index) return NULL; } - memset(bitmap, 0x00, size); bitmap->s_block_bitmap = (struct buffer_head **)(bitmap + 1); bitmap->s_nr_groups = nr_groups; return bitmap; -- cgit v1.2.3-18-g5258 From d664b6af609ecf5e7dcedf92f0bf188e3a29b3e0 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 20 Oct 2010 18:28:46 +0200 Subject: udf: Move handling of uniqueID into a helper function and protect it by a s_alloc_mutex uniqueID handling has been duplicated in three places. Move it into a common helper. Since we modify an LVID buffer with uniqueID update, we take sbi->s_alloc_mutex to protect agaist other modifications of the structure. Signed-off-by: Jan Kara --- fs/udf/super.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'fs/udf/super.c') diff --git a/fs/udf/super.c b/fs/udf/super.c index f99ff5dbd74..948e1aca0f3 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1823,6 +1823,33 @@ static void udf_close_lvid(struct super_block *sb) sbi->s_lvid_dirty = 0; } +u64 lvid_get_unique_id(struct super_block *sb) +{ + struct buffer_head *bh; + struct udf_sb_info *sbi = UDF_SB(sb); + struct logicalVolIntegrityDesc *lvid; + struct logicalVolHeaderDesc *lvhd; + u64 uniqueID; + u64 ret; + + bh = sbi->s_lvid_bh; + if (!bh) + return 0; + + lvid = (struct logicalVolIntegrityDesc *)bh->b_data; + lvhd = (struct logicalVolHeaderDesc *)lvid->logicalVolContentsUse; + + mutex_lock(&sbi->s_alloc_mutex); + ret = uniqueID = le64_to_cpu(lvhd->uniqueID); + if (!(++uniqueID & 0xFFFFFFFF)) + uniqueID += 16; + lvhd->uniqueID = cpu_to_le64(uniqueID); + mutex_unlock(&sbi->s_alloc_mutex); + mark_buffer_dirty(bh); + + return ret; +} + static void udf_sb_free_bitmap(struct udf_bitmap *bitmap) { int i; -- cgit v1.2.3-18-g5258 From 949f4a7c08bc4a050eae7aeeac3e6d019d1feafb Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 20 Oct 2010 18:49:20 +0200 Subject: udf: Protect all modifications of LVID with s_alloc_mutex udf_open_lvid() and udf_close_lvid() were modifying LVID without s_alloc_mutex. Since they can be called from remount, the modification could race with other filesystem modifications of LVID so protect them by s_alloc_mutex just to be sure. Signed-off-by: Jan Kara --- fs/udf/super.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'fs/udf/super.c') diff --git a/fs/udf/super.c b/fs/udf/super.c index 948e1aca0f3..e54960c0e96 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1773,6 +1773,8 @@ static void udf_open_lvid(struct super_block *sb) if (!bh) return; + + mutex_lock(&sbi->s_alloc_mutex); lvid = (struct logicalVolIntegrityDesc *)bh->b_data; lvidiu = udf_sb_lvidiu(sbi); @@ -1789,6 +1791,7 @@ static void udf_open_lvid(struct super_block *sb) lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); mark_buffer_dirty(bh); sbi->s_lvid_dirty = 0; + mutex_unlock(&sbi->s_alloc_mutex); } static void udf_close_lvid(struct super_block *sb) @@ -1801,6 +1804,7 @@ static void udf_close_lvid(struct super_block *sb) if (!bh) return; + mutex_lock(&sbi->s_alloc_mutex); lvid = (struct logicalVolIntegrityDesc *)bh->b_data; lvidiu = udf_sb_lvidiu(sbi); lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; @@ -1821,6 +1825,7 @@ static void udf_close_lvid(struct super_block *sb) lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); mark_buffer_dirty(bh); sbi->s_lvid_dirty = 0; + mutex_unlock(&sbi->s_alloc_mutex); } u64 lvid_get_unique_id(struct super_block *sb) -- cgit v1.2.3-18-g5258 From c03cad241af63445b751781a09faf08b3a5b77c1 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 20 Oct 2010 22:17:28 +0200 Subject: udf: Protect default inode credentials by rwlock Superblock carries credentials (uid, gid, etc.) which are used as default values in __udf_read_inode() when media does not provide these. These credentials can change during remount so we protect them by a rwlock so that each inode gets a consistent set of credentials. Signed-off-by: Jan Kara --- fs/udf/super.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs/udf/super.c') diff --git a/fs/udf/super.c b/fs/udf/super.c index e54960c0e96..f06cc67cf86 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -568,12 +568,14 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options) return -EINVAL; lock_kernel(); + write_lock(&sbi->s_cred_lock); sbi->s_flags = uopt.flags; sbi->s_uid = uopt.uid; sbi->s_gid = uopt.gid; sbi->s_umask = uopt.umask; sbi->s_fmode = uopt.fmode; sbi->s_dmode = uopt.dmode; + write_unlock(&sbi->s_cred_lock); if (sbi->s_lvid_bh) { int write_rev = le16_to_cpu(udf_sb_lvidiu(sbi)->minUDFWriteRev); @@ -1960,6 +1962,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) sbi->s_fmode = uopt.fmode; sbi->s_dmode = uopt.dmode; sbi->s_nls_map = uopt.nls_map; + rwlock_init(&sbi->s_cred_lock); if (uopt.session == 0xFFFFFFFF) sbi->s_session = udf_get_last_session(sb); -- cgit v1.2.3-18-g5258 From 0484b1cedc053cf88a046da5f08bc00747e533cb Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 20 Oct 2010 22:22:57 +0200 Subject: udf: Remove BKL from udf_put_super() and udf_remount_fs() udf_put_super() does not need BKL because the filesystem is shut down so there's nothing to race with. The credential changes in udf_remount_fs() and LVID changes are now protected by dedicated locks so we can remove BKL from this function as well. Signed-off-by: Jan Kara --- fs/udf/super.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'fs/udf/super.c') diff --git a/fs/udf/super.c b/fs/udf/super.c index f06cc67cf86..4cf6121ab41 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -567,7 +567,6 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options) if (!udf_parse_options(options, &uopt, true)) return -EINVAL; - lock_kernel(); write_lock(&sbi->s_cred_lock); sbi->s_flags = uopt.flags; sbi->s_uid = uopt.uid; @@ -592,7 +591,6 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options) udf_open_lvid(sb); out_unlock: - unlock_kernel(); return error; } @@ -2132,8 +2130,6 @@ static void udf_put_super(struct super_block *sb) sbi = UDF_SB(sb); - lock_kernel(); - if (sbi->s_vat_inode) iput(sbi->s_vat_inode); if (sbi->s_partitions) @@ -2149,8 +2145,6 @@ static void udf_put_super(struct super_block *sb) kfree(sbi->s_partmaps); kfree(sb->s_fs_info); sb->s_fs_info = NULL; - - unlock_kernel(); } static int udf_sync_fs(struct super_block *sb, int wait) -- cgit v1.2.3-18-g5258 From d1668fe390c1e84580575965684a8fa7e4626dee Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 20 Oct 2010 23:24:12 +0200 Subject: udf: Remove BKL from free space counting functions udf_count_free_bitmap() does not need BKL because bitmaps are in a fixed place on disk and so we can count set bits without serialization. udf_count_free_table() is now protected by s_alloc_mutex instead of BKL to get a consistent view of free space extents. Signed-off-by: Jan Kara --- fs/udf/super.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'fs/udf/super.c') diff --git a/fs/udf/super.c b/fs/udf/super.c index 4cf6121ab41..d2ec9f31e84 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -2207,8 +2207,6 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb, uint16_t ident; struct spaceBitmapDesc *bm; - lock_kernel(); - loc.logicalBlockNum = bitmap->s_extPosition; loc.partitionReferenceNum = UDF_SB(sb)->s_partition; bh = udf_read_ptagged(sb, &loc, 0, &ident); @@ -2245,10 +2243,7 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb, } } brelse(bh); - out: - unlock_kernel(); - return accum; } @@ -2261,8 +2256,7 @@ static unsigned int udf_count_free_table(struct super_block *sb, int8_t etype; struct extent_position epos; - lock_kernel(); - + mutex_lock(&UDF_SB(sb)->s_alloc_mutex); epos.block = UDF_I(table)->i_location; epos.offset = sizeof(struct unallocSpaceEntry); epos.bh = NULL; @@ -2271,8 +2265,7 @@ static unsigned int udf_count_free_table(struct super_block *sb, accum += (elen >> table->i_sb->s_blocksize_bits); brelse(epos.bh); - - unlock_kernel(); + mutex_unlock(&UDF_SB(sb)->s_alloc_mutex); return accum; } -- cgit v1.2.3-18-g5258 From 4d0fb621d35007c19a396f2bb629e5aeaacef2d0 Mon Sep 17 00:00:00 2001 From: Alessio Igor Bogani Date: Tue, 16 Nov 2010 18:40:47 +0100 Subject: udf: Replace bkl with the UDF_I(inode)->i_data_sem for protect udf_inode_info struct Replace bkl with the UDF_I(inode)->i_data_sem rw semaphore in udf_release_file(), udf_symlink(), udf_symlink_filler(), udf_get_block(), udf_block_map(), and udf_setattr(). The rule now is that any operation on regular file's or symlink's extents (or generally allocation information including goal block) needs to hold i_data_sem. This work was supported by a hardware donation from the CE Linux Forum. Signed-off-by: Alessio Igor Bogani Signed-off-by: Jan Kara --- fs/udf/super.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/udf/super.c') diff --git a/fs/udf/super.c b/fs/udf/super.c index d2ec9f31e84..441b892cf85 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -135,6 +135,7 @@ static struct inode *udf_alloc_inode(struct super_block *sb) ei->i_next_alloc_block = 0; ei->i_next_alloc_goal = 0; ei->i_strat4096 = 0; + init_rwsem(&ei->i_data_sem); return &ei->vfs_inode; } -- cgit v1.2.3-18-g5258 From 9db9f9e31d7661dff35a75ed01ff9fc0d6acdaf8 Mon Sep 17 00:00:00 2001 From: Alessio Igor Bogani Date: Tue, 16 Nov 2010 18:40:49 +0100 Subject: udf: Remove unnecessary bkl usages 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_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 Signed-off-by: Jan Kara --- fs/udf/super.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'fs/udf/super.c') diff --git a/fs/udf/super.c b/fs/udf/super.c index 441b892cf85..536f89da4af 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include #include @@ -1911,8 +1910,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) struct kernel_lb_addr rootdir, fileset; struct udf_sb_info *sbi; - lock_kernel(); - uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT); uopt.uid = -1; uopt.gid = -1; @@ -1921,10 +1918,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) uopt.dmode = UDF_INVALID_MODE; sbi = kzalloc(sizeof(struct udf_sb_info), GFP_KERNEL); - if (!sbi) { - unlock_kernel(); + if (!sbi) return -ENOMEM; - } sb->s_fs_info = sbi; @@ -2071,7 +2066,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) goto error_out; } sb->s_maxbytes = MAX_LFS_FILESIZE; - unlock_kernel(); return 0; error_out: @@ -2092,7 +2086,6 @@ error_out: kfree(sbi); sb->s_fs_info = NULL; - unlock_kernel(); return -EINVAL; } -- cgit v1.2.3-18-g5258