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/file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/udf/file.c') diff --git a/fs/udf/file.c b/fs/udf/file.c index 66b9e7e7e4c5..df0c5561cc7e 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(&UDF_I(inode)->i_data_sem); udf_discard_prealloc(inode); udf_truncate_tail_extent(inode); - unlock_kernel(); + up_write(&UDF_I(inode)->i_data_sem); mutex_unlock(&inode->i_mutex); } return 0; -- cgit v1.2.3 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/dir.c | 5 ----- fs/udf/file.c | 4 ---- fs/udf/inode.c | 3 --- fs/udf/namei.c | 27 --------------------------- fs/udf/super.c | 9 +-------- 5 files changed, 1 insertion(+), 47 deletions(-) (limited to 'fs/udf/file.c') diff --git a/fs/udf/dir.c b/fs/udf/dir.c index 51552bf50225..eb8bfe2b89a5 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #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 df0c5561cc7e..4e3bbd81b57b 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -32,7 +32,6 @@ #include /* memset */ #include #include -#include #include #include #include @@ -149,8 +148,6 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) long old_block, new_block; int result = -EINVAL; - lock_kernel(); - if (file_permission(filp, MAY_READ) != 0) { udf_debug("no permission to access inode %lu\n", inode->i_ino); result = -EPERM; @@ -196,7 +193,6 @@ long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } out: - unlock_kernel(); return result; } diff --git a/fs/udf/inode.c b/fs/udf/inode.c index b2fe4d7f20eb..c6a2e782b97b 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -31,7 +31,6 @@ #include "udfdecl.h" #include -#include #include #include #include @@ -96,9 +95,7 @@ void udf_evict_inode(struct inode *inode) kfree(iinfo->i_ext.i_data); iinfo->i_ext.i_data = NULL; if (want_delete) { - lock_kernel(); udf_free_inode(inode); - unlock_kernel(); } } diff --git a/fs/udf/namei.c b/fs/udf/namei.c index d5eb000ddddd..26815a25379d 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -263,7 +262,6 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, if (dentry->d_name.len > UDF_NAME_LEN - 2) return ERR_PTR(-ENAMETOOLONG); - lock_kernel(); #ifdef UDF_RECOVERY /* temporary shorthand for specifying files by inode number */ if (!strncmp(dentry->d_name.name, ".B=", 3)) { @@ -275,7 +273,6 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, }; inode = udf_iget(dir->i_sb, lb); if (!inode) { - unlock_kernel(); return ERR_PTR(-EACCES); } } else @@ -291,11 +288,9 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, loc = lelb_to_cpu(cfi.icb.extLocation); inode = udf_iget(dir->i_sb, &loc); if (!inode) { - unlock_kernel(); return ERR_PTR(-EACCES); } } - unlock_kernel(); return d_splice_alias(inode, dentry); } @@ -562,10 +557,8 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode, int err; struct udf_inode_info *iinfo; - lock_kernel(); inode = udf_new_inode(dir, mode, &err); if (!inode) { - unlock_kernel(); return err; } @@ -583,7 +576,6 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode, inode->i_nlink--; mark_inode_dirty(inode); iput(inode); - unlock_kernel(); return err; } cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); @@ -596,7 +588,6 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode, if (fibh.sbh != fibh.ebh) brelse(fibh.ebh); brelse(fibh.sbh); - unlock_kernel(); d_instantiate(dentry, inode); return 0; @@ -614,7 +605,6 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode, if (!old_valid_dev(rdev)) return -EINVAL; - lock_kernel(); err = -EIO; inode = udf_new_inode(dir, mode, &err); if (!inode) @@ -627,7 +617,6 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode, inode->i_nlink--; mark_inode_dirty(inode); iput(inode); - unlock_kernel(); return err; } cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); @@ -646,7 +635,6 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode, err = 0; out: - unlock_kernel(); return err; } @@ -659,7 +647,6 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode) struct udf_inode_info *dinfo = UDF_I(dir); struct udf_inode_info *iinfo; - lock_kernel(); err = -EMLINK; if (dir->i_nlink >= (256 << sizeof(dir->i_nlink)) - 1) goto out; @@ -712,7 +699,6 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode) err = 0; out: - unlock_kernel(); return err; } @@ -794,7 +780,6 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry) struct kernel_lb_addr tloc; retval = -ENOENT; - lock_kernel(); fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi); if (!fi) goto out; @@ -826,7 +811,6 @@ end_rmdir: brelse(fibh.sbh); out: - unlock_kernel(); return retval; } @@ -840,7 +824,6 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry) struct kernel_lb_addr tloc; retval = -ENOENT; - lock_kernel(); fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi); if (!fi) goto out; @@ -870,7 +853,6 @@ end_unlink: brelse(fibh.sbh); out: - unlock_kernel(); return retval; } @@ -1050,15 +1032,12 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir, struct fileIdentDesc cfi, *fi; int err; - lock_kernel(); if (inode->i_nlink >= (256 << sizeof(inode->i_nlink)) - 1) { - unlock_kernel(); return -EMLINK; } fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); if (!fi) { - unlock_kernel(); return err; } cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); @@ -1079,7 +1058,6 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir, mark_inode_dirty(inode); ihold(inode); d_instantiate(dentry, inode); - unlock_kernel(); return 0; } @@ -1100,7 +1078,6 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, struct kernel_lb_addr tloc; struct udf_inode_info *old_iinfo = UDF_I(old_inode); - lock_kernel(); ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi); if (ofi) { if (ofibh.sbh != ofibh.ebh) @@ -1224,7 +1201,6 @@ end_rename: brelse(nfibh.ebh); brelse(nfibh.sbh); } - unlock_kernel(); return retval; } @@ -1237,7 +1213,6 @@ static struct dentry *udf_get_parent(struct dentry *child) struct fileIdentDesc cfi; struct udf_fileident_bh fibh; - lock_kernel(); if (!udf_find_entry(child->d_inode, &dotdot, &fibh, &cfi)) goto out_unlock; @@ -1249,11 +1224,9 @@ static struct dentry *udf_get_parent(struct dentry *child) inode = udf_iget(child->d_inode->i_sb, &tloc); if (!inode) goto out_unlock; - unlock_kernel(); return d_obtain_alias(inode); out_unlock: - unlock_kernel(); return ERR_PTR(-EACCES); } diff --git a/fs/udf/super.c b/fs/udf/super.c index 441b892cf85e..536f89da4af2 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 From 8754a3f718f08dc21b3c5eccd044f612d4bc1ab1 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 16 Nov 2010 14:33:48 +0100 Subject: udf: Protect udf_file_aio_write from possible races Code doing conversion from INICB file to a normal file in udf_file_aio_write() is not protected by any lock from other code modifying the inode. Use i_alloc_sem for that. Reported-by: Alessio Igor Bogani Signed-off-by: Jan Kara --- fs/udf/file.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs/udf/file.c') diff --git a/fs/udf/file.c b/fs/udf/file.c index 4e3bbd81b57b..89c78486cbbe 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -113,6 +113,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, size_t count = iocb->ki_left; struct udf_inode_info *iinfo = UDF_I(inode); + down_write(&iinfo->i_data_sem); if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { if (file->f_flags & O_APPEND) pos = inode->i_size; @@ -125,6 +126,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, udf_expand_file_adinicb(inode, pos + count, &err); if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { udf_debug("udf_expand_adinicb: err=%d\n", err); + up_write(&iinfo->i_data_sem); return err; } } else { @@ -134,6 +136,7 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, iinfo->i_lenAlloc = inode->i_size; } } + up_write(&iinfo->i_data_sem); retval = generic_file_aio_write(iocb, iov, nr_segs, ppos); if (retval > 0) -- cgit v1.2.3