|
@@ -27,7 +27,6 @@
|
|
|
#include <linux/errno.h>
|
|
|
#include <linux/mm.h>
|
|
|
#include <linux/slab.h>
|
|
|
-#include <linux/smp_lock.h>
|
|
|
#include <linux/buffer_head.h>
|
|
|
#include <linux/sched.h>
|
|
|
#include <linux/crc-itu-t.h>
|
|
@@ -228,10 +227,8 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
|
|
|
}
|
|
|
|
|
|
if ((cfi->fileCharacteristics & FID_FILE_CHAR_PARENT) &&
|
|
|
- isdotdot) {
|
|
|
- brelse(epos.bh);
|
|
|
- return fi;
|
|
|
- }
|
|
|
+ isdotdot)
|
|
|
+ goto out_ok;
|
|
|
|
|
|
if (!lfi)
|
|
|
continue;
|
|
@@ -263,7 +260,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 +271,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 +286,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);
|
|
|
}
|
|
@@ -476,15 +469,19 @@ add:
|
|
|
f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
|
|
|
if (!fibh->ebh)
|
|
|
goto out_err;
|
|
|
+ /* Extents could have been merged, invalidate our position */
|
|
|
+ brelse(epos.bh);
|
|
|
+ epos.bh = NULL;
|
|
|
+ epos.block = dinfo->i_location;
|
|
|
+ epos.offset = udf_file_entry_alloc_offset(dir);
|
|
|
|
|
|
if (!fibh->soffset) {
|
|
|
- if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
|
|
|
- (EXT_RECORDED_ALLOCATED >> 30)) {
|
|
|
- block = eloc.logicalBlockNum + ((elen - 1) >>
|
|
|
+ /* Find the freshly allocated block */
|
|
|
+ while (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
|
|
|
+ (EXT_RECORDED_ALLOCATED >> 30))
|
|
|
+ ;
|
|
|
+ block = eloc.logicalBlockNum + ((elen - 1) >>
|
|
|
dir->i_sb->s_blocksize_bits);
|
|
|
- } else
|
|
|
- block++;
|
|
|
-
|
|
|
brelse(fibh->sbh);
|
|
|
fibh->sbh = fibh->ebh;
|
|
|
fi = (struct fileIdentDesc *)(fibh->sbh->b_data);
|
|
@@ -562,10 +559,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 +578,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 +590,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 +607,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 +619,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 +637,6 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, int mode,
|
|
|
err = 0;
|
|
|
|
|
|
out:
|
|
|
- unlock_kernel();
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -659,7 +649,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 +701,6 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, int mode)
|
|
|
err = 0;
|
|
|
|
|
|
out:
|
|
|
- unlock_kernel();
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -794,7 +782,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 +813,6 @@ end_rmdir:
|
|
|
brelse(fibh.sbh);
|
|
|
|
|
|
out:
|
|
|
- unlock_kernel();
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
@@ -840,7 +826,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 +855,6 @@ end_unlink:
|
|
|
brelse(fibh.sbh);
|
|
|
|
|
|
out:
|
|
|
- unlock_kernel();
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
@@ -890,21 +874,21 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|
|
int block;
|
|
|
unsigned char *name = NULL;
|
|
|
int namelen;
|
|
|
- struct buffer_head *bh;
|
|
|
struct udf_inode_info *iinfo;
|
|
|
+ struct super_block *sb = dir->i_sb;
|
|
|
|
|
|
- lock_kernel();
|
|
|
inode = udf_new_inode(dir, S_IFLNK | S_IRWXUGO, &err);
|
|
|
if (!inode)
|
|
|
goto out;
|
|
|
|
|
|
+ iinfo = UDF_I(inode);
|
|
|
+ down_write(&iinfo->i_data_sem);
|
|
|
name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
|
|
|
if (!name) {
|
|
|
err = -ENOMEM;
|
|
|
goto out_no_entry;
|
|
|
}
|
|
|
|
|
|
- iinfo = UDF_I(inode);
|
|
|
inode->i_data.a_ops = &udf_symlink_aops;
|
|
|
inode->i_op = &udf_symlink_inode_operations;
|
|
|
|
|
@@ -912,7 +896,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|
|
struct kernel_lb_addr eloc;
|
|
|
uint32_t bsize;
|
|
|
|
|
|
- block = udf_new_block(inode->i_sb, inode,
|
|
|
+ block = udf_new_block(sb, inode,
|
|
|
iinfo->i_location.partitionReferenceNum,
|
|
|
iinfo->i_location.logicalBlockNum, &err);
|
|
|
if (!block)
|
|
@@ -923,17 +907,17 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|
|
eloc.logicalBlockNum = block;
|
|
|
eloc.partitionReferenceNum =
|
|
|
iinfo->i_location.partitionReferenceNum;
|
|
|
- bsize = inode->i_sb->s_blocksize;
|
|
|
+ bsize = sb->s_blocksize;
|
|
|
iinfo->i_lenExtents = bsize;
|
|
|
udf_add_aext(inode, &epos, &eloc, bsize, 0);
|
|
|
brelse(epos.bh);
|
|
|
|
|
|
- block = udf_get_pblock(inode->i_sb, block,
|
|
|
+ block = udf_get_pblock(sb, block,
|
|
|
iinfo->i_location.partitionReferenceNum,
|
|
|
0);
|
|
|
- epos.bh = udf_tgetblk(inode->i_sb, block);
|
|
|
+ epos.bh = udf_tgetblk(sb, block);
|
|
|
lock_buffer(epos.bh);
|
|
|
- memset(epos.bh->b_data, 0x00, inode->i_sb->s_blocksize);
|
|
|
+ memset(epos.bh->b_data, 0x00, bsize);
|
|
|
set_buffer_uptodate(epos.bh);
|
|
|
unlock_buffer(epos.bh);
|
|
|
mark_buffer_dirty_inode(epos.bh, inode);
|
|
@@ -941,7 +925,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|
|
} else
|
|
|
ea = iinfo->i_ext.i_data + iinfo->i_lenEAttr;
|
|
|
|
|
|
- eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode);
|
|
|
+ eoffset = sb->s_blocksize - udf_ext0_offset(inode);
|
|
|
pc = (struct pathComponent *)ea;
|
|
|
|
|
|
if (*symname == '/') {
|
|
@@ -981,7 +965,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|
|
}
|
|
|
|
|
|
if (pc->componentType == 5) {
|
|
|
- namelen = udf_put_filename(inode->i_sb, compstart, name,
|
|
|
+ namelen = udf_put_filename(sb, compstart, name,
|
|
|
symname - compstart);
|
|
|
if (!namelen)
|
|
|
goto out_no_entry;
|
|
@@ -1015,27 +999,16 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|
|
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
|
|
|
if (!fi)
|
|
|
goto out_no_entry;
|
|
|
- cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
|
|
|
+ cfi.icb.extLength = cpu_to_le32(sb->s_blocksize);
|
|
|
cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
|
|
|
- bh = UDF_SB(inode->i_sb)->s_lvid_bh;
|
|
|
- if (bh) {
|
|
|
- struct logicalVolIntegrityDesc *lvid =
|
|
|
- (struct logicalVolIntegrityDesc *)bh->b_data;
|
|
|
- struct logicalVolHeaderDesc *lvhd;
|
|
|
- uint64_t uniqueID;
|
|
|
- lvhd = (struct logicalVolHeaderDesc *)
|
|
|
- lvid->logicalVolContentsUse;
|
|
|
- uniqueID = le64_to_cpu(lvhd->uniqueID);
|
|
|
+ if (UDF_SB(inode->i_sb)->s_lvid_bh) {
|
|
|
*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
|
|
|
- cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);
|
|
|
- if (!(++uniqueID & 0x00000000FFFFFFFFUL))
|
|
|
- uniqueID += 16;
|
|
|
- lvhd->uniqueID = cpu_to_le64(uniqueID);
|
|
|
- mark_buffer_dirty(bh);
|
|
|
+ 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);
|
|
|
+ up_write(&iinfo->i_data_sem);
|
|
|
if (fibh.sbh != fibh.ebh)
|
|
|
brelse(fibh.ebh);
|
|
|
brelse(fibh.sbh);
|
|
@@ -1044,10 +1017,10 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
|
|
|
|
|
|
out:
|
|
|
kfree(name);
|
|
|
- unlock_kernel();
|
|
|
return err;
|
|
|
|
|
|
out_no_entry:
|
|
|
+ up_write(&iinfo->i_data_sem);
|
|
|
inode_dec_link_count(inode);
|
|
|
iput(inode);
|
|
|
goto out;
|
|
@@ -1060,36 +1033,20 @@ static int udf_link(struct dentry *old_dentry, struct inode *dir,
|
|
|
struct udf_fileident_bh fibh;
|
|
|
struct fileIdentDesc cfi, *fi;
|
|
|
int err;
|
|
|
- struct buffer_head *bh;
|
|
|
|
|
|
- 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);
|
|
|
cfi.icb.extLocation = cpu_to_lelb(UDF_I(inode)->i_location);
|
|
|
- bh = UDF_SB(inode->i_sb)->s_lvid_bh;
|
|
|
- if (bh) {
|
|
|
- struct logicalVolIntegrityDesc *lvid =
|
|
|
- (struct logicalVolIntegrityDesc *)bh->b_data;
|
|
|
- struct logicalVolHeaderDesc *lvhd;
|
|
|
- uint64_t uniqueID;
|
|
|
- lvhd = (struct logicalVolHeaderDesc *)
|
|
|
- (lvid->logicalVolContentsUse);
|
|
|
- uniqueID = le64_to_cpu(lvhd->uniqueID);
|
|
|
+ if (UDF_SB(inode->i_sb)->s_lvid_bh) {
|
|
|
*(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
|
|
|
- cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);
|
|
|
- if (!(++uniqueID & 0x00000000FFFFFFFFUL))
|
|
|
- uniqueID += 16;
|
|
|
- lvhd->uniqueID = cpu_to_le64(uniqueID);
|
|
|
- mark_buffer_dirty(bh);
|
|
|
+ cpu_to_le32(lvid_get_unique_id(inode->i_sb));
|
|
|
}
|
|
|
udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
|
|
|
if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
|
|
@@ -1103,7 +1060,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;
|
|
|
}
|
|
@@ -1124,7 +1080,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)
|
|
@@ -1248,7 +1203,6 @@ end_rename:
|
|
|
brelse(nfibh.ebh);
|
|
|
brelse(nfibh.sbh);
|
|
|
}
|
|
|
- unlock_kernel();
|
|
|
|
|
|
return retval;
|
|
|
}
|
|
@@ -1261,7 +1215,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;
|
|
|
|
|
@@ -1273,11 +1226,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);
|
|
|
}
|
|
|
|