| From: Al Viro <viro@zeniv.linux.org.uk> |
| Date: Thu, 4 Sep 2014 09:34:14 -0400 |
| Subject: udf: merge the pieces inserting a new non-directory object into |
| directory |
| |
| commit d2be51cb34dc501791f3b8c01a99a3f2064bd8d1 upstream. |
| |
| boilerplate code in udf_{create,mknod,symlink} taken to new helper |
| |
| symlink case converted to unique id calculated by udf_new_inode() - no |
| point finding a new one. |
| |
| Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> |
| Signed-off-by: Jan Kara <jack@suse.cz> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| fs/udf/namei.c | 98 +++++++++++++++----------------------------------- |
| 1 file changed, 29 insertions(+), 69 deletions(-) |
| |
| --- a/fs/udf/namei.c |
| +++ b/fs/udf/namei.c |
| @@ -551,31 +551,16 @@ static int udf_delete_entry(struct inode |
| return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL); |
| } |
| |
| -static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
| - bool excl) |
| +static int udf_add_nondir(struct dentry *dentry, struct inode *inode) |
| { |
| + struct udf_inode_info *iinfo = UDF_I(inode); |
| + struct inode *dir = dentry->d_parent->d_inode; |
| struct udf_fileident_bh fibh; |
| - struct inode *inode; |
| struct fileIdentDesc cfi, *fi; |
| int err; |
| - struct udf_inode_info *iinfo; |
| - |
| - inode = udf_new_inode(dir, mode, &err); |
| - if (!inode) { |
| - return err; |
| - } |
| - |
| - iinfo = UDF_I(inode); |
| - if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) |
| - inode->i_data.a_ops = &udf_adinicb_aops; |
| - else |
| - inode->i_data.a_ops = &udf_aops; |
| - inode->i_op = &udf_file_inode_operations; |
| - inode->i_fop = &udf_file_operations; |
| - mark_inode_dirty(inode); |
| |
| fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); |
| - if (!fi) { |
| + if (unlikely(!fi)) { |
| inode_dec_link_count(inode); |
| iput(inode); |
| return err; |
| @@ -595,6 +580,28 @@ static int udf_create(struct inode *dir, |
| return 0; |
| } |
| |
| +static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
| + bool excl) |
| +{ |
| + struct inode *inode; |
| + int err; |
| + |
| + inode = udf_new_inode(dir, mode, &err); |
| + if (!inode) { |
| + return err; |
| + } |
| + |
| + if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) |
| + inode->i_data.a_ops = &udf_adinicb_aops; |
| + else |
| + inode->i_data.a_ops = &udf_aops; |
| + inode->i_op = &udf_file_inode_operations; |
| + inode->i_fop = &udf_file_operations; |
| + mark_inode_dirty(inode); |
| + |
| + return udf_add_nondir(dentry, inode); |
| +} |
| + |
| static int udf_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) |
| { |
| struct inode *inode; |
| @@ -622,10 +629,7 @@ static int udf_mknod(struct inode *dir, |
| dev_t rdev) |
| { |
| struct inode *inode; |
| - struct udf_fileident_bh fibh; |
| - struct fileIdentDesc cfi, *fi; |
| int err; |
| - struct udf_inode_info *iinfo; |
| |
| if (!old_valid_dev(rdev)) |
| return -EINVAL; |
| @@ -633,33 +637,10 @@ static int udf_mknod(struct inode *dir, |
| err = -EIO; |
| inode = udf_new_inode(dir, mode, &err); |
| if (!inode) |
| - goto out; |
| - |
| - iinfo = UDF_I(inode); |
| - init_special_inode(inode, mode, rdev); |
| - fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); |
| - if (!fi) { |
| - inode_dec_link_count(inode); |
| - iput(inode); |
| return err; |
| - } |
| - cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); |
| - cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location); |
| - *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = |
| - cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL); |
| - udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); |
| - if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) |
| - mark_inode_dirty(dir); |
| - mark_inode_dirty(inode); |
| - |
| - if (fibh.sbh != fibh.ebh) |
| - brelse(fibh.ebh); |
| - brelse(fibh.sbh); |
| - d_instantiate(dentry, inode); |
| - err = 0; |
| |
| -out: |
| - return err; |
| + init_special_inode(inode, mode, rdev); |
| + return udf_add_nondir(dentry, inode); |
| } |
| |
| static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) |
| @@ -880,11 +861,8 @@ static int udf_symlink(struct inode *dir |
| struct inode *inode; |
| struct pathComponent *pc; |
| const char *compstart; |
| - struct udf_fileident_bh fibh; |
| struct extent_position epos = {}; |
| int eoffset, elen = 0; |
| - struct fileIdentDesc *fi; |
| - struct fileIdentDesc cfi; |
| uint8_t *ea; |
| int err; |
| int block; |
| @@ -1013,31 +991,13 @@ static int udf_symlink(struct inode *dir |
| mark_inode_dirty(inode); |
| up_write(&iinfo->i_data_sem); |
| |
| - fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); |
| - if (!fi) |
| - goto out_fail; |
| - cfi.icb.extLength = cpu_to_le32(sb->s_blocksize); |
| - cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location); |
| - if (UDF_SB(inode->i_sb)->s_lvid_bh) { |
| - *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = |
| - cpu_to_le32(lvid_get_unique_id(sb)); |
| - } |
| - udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); |
| - if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) |
| - mark_inode_dirty(dir); |
| - if (fibh.sbh != fibh.ebh) |
| - brelse(fibh.ebh); |
| - brelse(fibh.sbh); |
| - d_instantiate(dentry, inode); |
| - err = 0; |
| - |
| + err = udf_add_nondir(dentry, inode); |
| out: |
| kfree(name); |
| return err; |
| |
| out_no_entry: |
| up_write(&iinfo->i_data_sem); |
| -out_fail: |
| inode_dec_link_count(inode); |
| iput(inode); |
| goto out; |