Commit 7ec62d42 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs

Pull UDF fixes from Jan Kara:
 "Fixes for UDF handling of NFS handles and one fix for proper handling
  of corrupted media"

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  udf: saner calling conventions for udf_new_inode()
  udf: fix the udf_iget() vs. udf_new_inode() races
  udf: merge the pieces inserting a new non-directory object into directory
  udf: Set i_generation field
  udf: Properly detect stale inodes
  udf: Make udf_read_inode() and udf_iget() return error
  udf: Avoid infinite loop when processing indirect ICBs
  udf: Fold udf_fill_inode() into __udf_read_inode()
  udf: Avoid dir link count to go negative
parents e874a5fe 0b93a92b
...@@ -45,7 +45,7 @@ void udf_free_inode(struct inode *inode) ...@@ -45,7 +45,7 @@ void udf_free_inode(struct inode *inode)
udf_free_blocks(sb, NULL, &UDF_I(inode)->i_location, 0, 1); udf_free_blocks(sb, NULL, &UDF_I(inode)->i_location, 0, 1);
} }
struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err) struct inode *udf_new_inode(struct inode *dir, umode_t mode)
{ {
struct super_block *sb = dir->i_sb; struct super_block *sb = dir->i_sb;
struct udf_sb_info *sbi = UDF_SB(sb); struct udf_sb_info *sbi = UDF_SB(sb);
...@@ -55,14 +55,12 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err) ...@@ -55,14 +55,12 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err)
struct udf_inode_info *iinfo; struct udf_inode_info *iinfo;
struct udf_inode_info *dinfo = UDF_I(dir); struct udf_inode_info *dinfo = UDF_I(dir);
struct logicalVolIntegrityDescImpUse *lvidiu; struct logicalVolIntegrityDescImpUse *lvidiu;
int err;
inode = new_inode(sb); inode = new_inode(sb);
if (!inode) { if (!inode)
*err = -ENOMEM; return ERR_PTR(-ENOMEM);
return NULL;
}
*err = -ENOSPC;
iinfo = UDF_I(inode); iinfo = UDF_I(inode);
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE)) { if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE)) {
...@@ -80,21 +78,22 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err) ...@@ -80,21 +78,22 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err)
} }
if (!iinfo->i_ext.i_data) { if (!iinfo->i_ext.i_data) {
iput(inode); iput(inode);
*err = -ENOMEM; return ERR_PTR(-ENOMEM);
return NULL;
} }
err = -ENOSPC;
block = udf_new_block(dir->i_sb, NULL, block = udf_new_block(dir->i_sb, NULL,
dinfo->i_location.partitionReferenceNum, dinfo->i_location.partitionReferenceNum,
start, err); start, &err);
if (*err) { if (err) {
iput(inode); iput(inode);
return NULL; return ERR_PTR(err);
} }
lvidiu = udf_sb_lvidiu(sb); lvidiu = udf_sb_lvidiu(sb);
if (lvidiu) { if (lvidiu) {
iinfo->i_unique = lvid_get_unique_id(sb); iinfo->i_unique = lvid_get_unique_id(sb);
inode->i_generation = iinfo->i_unique;
mutex_lock(&sbi->s_alloc_mutex); mutex_lock(&sbi->s_alloc_mutex);
if (S_ISDIR(mode)) if (S_ISDIR(mode))
le32_add_cpu(&lvidiu->numDirs, 1); le32_add_cpu(&lvidiu->numDirs, 1);
...@@ -123,9 +122,12 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err) ...@@ -123,9 +122,12 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err)
iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
inode->i_mtime = inode->i_atime = inode->i_ctime = inode->i_mtime = inode->i_atime = inode->i_ctime =
iinfo->i_crtime = current_fs_time(inode->i_sb); iinfo->i_crtime = current_fs_time(inode->i_sb);
insert_inode_hash(inode); if (unlikely(insert_inode_locked(inode) < 0)) {
make_bad_inode(inode);
iput(inode);
return ERR_PTR(-EIO);
}
mark_inode_dirty(inode); mark_inode_dirty(inode);
*err = 0;
return inode; return inode;
} }
...@@ -51,7 +51,6 @@ MODULE_LICENSE("GPL"); ...@@ -51,7 +51,6 @@ MODULE_LICENSE("GPL");
static umode_t udf_convert_permissions(struct fileEntry *); static umode_t udf_convert_permissions(struct fileEntry *);
static int udf_update_inode(struct inode *, int); static int udf_update_inode(struct inode *, int);
static void udf_fill_inode(struct inode *, struct buffer_head *);
static int udf_sync_inode(struct inode *inode); static int udf_sync_inode(struct inode *inode);
static int udf_alloc_i_data(struct inode *inode, size_t size); static int udf_alloc_i_data(struct inode *inode, size_t size);
static sector_t inode_getblk(struct inode *, sector_t, int *, int *); static sector_t inode_getblk(struct inode *, sector_t, int *, int *);
...@@ -1271,12 +1270,33 @@ int udf_setsize(struct inode *inode, loff_t newsize) ...@@ -1271,12 +1270,33 @@ int udf_setsize(struct inode *inode, loff_t newsize)
return 0; return 0;
} }
static void __udf_read_inode(struct inode *inode) /*
* Maximum length of linked list formed by ICB hierarchy. The chosen number is
* arbitrary - just that we hopefully don't limit any real use of rewritten
* inode on write-once media but avoid looping for too long on corrupted media.
*/
#define UDF_MAX_ICB_NESTING 1024
static int udf_read_inode(struct inode *inode)
{ {
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
struct fileEntry *fe; struct fileEntry *fe;
struct extendedFileEntry *efe;
uint16_t ident; uint16_t ident;
struct udf_inode_info *iinfo = UDF_I(inode); struct udf_inode_info *iinfo = UDF_I(inode);
struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
struct kernel_lb_addr *iloc = &iinfo->i_location;
unsigned int link_count;
unsigned int indirections = 0;
int ret = -EIO;
reread:
if (iloc->logicalBlockNum >=
sbi->s_partmaps[iloc->partitionReferenceNum].s_partition_len) {
udf_debug("block=%d, partition=%d out of range\n",
iloc->logicalBlockNum, iloc->partitionReferenceNum);
return -EIO;
}
/* /*
* Set defaults, but the inode is still incomplete! * Set defaults, but the inode is still incomplete!
...@@ -1290,78 +1310,54 @@ static void __udf_read_inode(struct inode *inode) ...@@ -1290,78 +1310,54 @@ static void __udf_read_inode(struct inode *inode)
* i_nlink = 1 * i_nlink = 1
* i_op = NULL; * i_op = NULL;
*/ */
bh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 0, &ident); bh = udf_read_ptagged(inode->i_sb, iloc, 0, &ident);
if (!bh) { if (!bh) {
udf_err(inode->i_sb, "(ino %ld) failed !bh\n", inode->i_ino); udf_err(inode->i_sb, "(ino %ld) failed !bh\n", inode->i_ino);
make_bad_inode(inode); return -EIO;
return;
} }
if (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE && if (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE &&
ident != TAG_IDENT_USE) { ident != TAG_IDENT_USE) {
udf_err(inode->i_sb, "(ino %ld) failed ident=%d\n", udf_err(inode->i_sb, "(ino %ld) failed ident=%d\n",
inode->i_ino, ident); inode->i_ino, ident);
brelse(bh); goto out;
make_bad_inode(inode);
return;
} }
fe = (struct fileEntry *)bh->b_data; fe = (struct fileEntry *)bh->b_data;
efe = (struct extendedFileEntry *)bh->b_data;
if (fe->icbTag.strategyType == cpu_to_le16(4096)) { if (fe->icbTag.strategyType == cpu_to_le16(4096)) {
struct buffer_head *ibh; struct buffer_head *ibh;
ibh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 1, ibh = udf_read_ptagged(inode->i_sb, iloc, 1, &ident);
&ident);
if (ident == TAG_IDENT_IE && ibh) { if (ident == TAG_IDENT_IE && ibh) {
struct buffer_head *nbh = NULL;
struct kernel_lb_addr loc; struct kernel_lb_addr loc;
struct indirectEntry *ie; struct indirectEntry *ie;
ie = (struct indirectEntry *)ibh->b_data; ie = (struct indirectEntry *)ibh->b_data;
loc = lelb_to_cpu(ie->indirectICB.extLocation); loc = lelb_to_cpu(ie->indirectICB.extLocation);
if (ie->indirectICB.extLength && if (ie->indirectICB.extLength) {
(nbh = udf_read_ptagged(inode->i_sb, &loc, 0, brelse(ibh);
&ident))) { memcpy(&iinfo->i_location, &loc,
if (ident == TAG_IDENT_FE || sizeof(struct kernel_lb_addr));
ident == TAG_IDENT_EFE) { if (++indirections > UDF_MAX_ICB_NESTING) {
memcpy(&iinfo->i_location, udf_err(inode->i_sb,
&loc, "too many ICBs in ICB hierarchy"
sizeof(struct kernel_lb_addr)); " (max %d supported)\n",
brelse(bh); UDF_MAX_ICB_NESTING);
brelse(ibh); goto out;
brelse(nbh);
__udf_read_inode(inode);
return;
} }
brelse(nbh); brelse(bh);
goto reread;
} }
} }
brelse(ibh); brelse(ibh);
} else if (fe->icbTag.strategyType != cpu_to_le16(4)) { } else if (fe->icbTag.strategyType != cpu_to_le16(4)) {
udf_err(inode->i_sb, "unsupported strategy type: %d\n", udf_err(inode->i_sb, "unsupported strategy type: %d\n",
le16_to_cpu(fe->icbTag.strategyType)); le16_to_cpu(fe->icbTag.strategyType));
brelse(bh); goto out;
make_bad_inode(inode);
return;
} }
udf_fill_inode(inode, bh);
brelse(bh);
}
static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
{
struct fileEntry *fe;
struct extendedFileEntry *efe;
struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
struct udf_inode_info *iinfo = UDF_I(inode);
unsigned int link_count;
fe = (struct fileEntry *)bh->b_data;
efe = (struct extendedFileEntry *)bh->b_data;
if (fe->icbTag.strategyType == cpu_to_le16(4)) if (fe->icbTag.strategyType == cpu_to_le16(4))
iinfo->i_strat4096 = 0; iinfo->i_strat4096 = 0;
else /* if (fe->icbTag.strategyType == cpu_to_le16(4096)) */ else /* if (fe->icbTag.strategyType == cpu_to_le16(4096)) */
...@@ -1378,11 +1374,10 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) ...@@ -1378,11 +1374,10 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_EFE)) { if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_EFE)) {
iinfo->i_efe = 1; iinfo->i_efe = 1;
iinfo->i_use = 0; iinfo->i_use = 0;
if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - ret = udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
sizeof(struct extendedFileEntry))) { sizeof(struct extendedFileEntry));
make_bad_inode(inode); if (ret)
return; goto out;
}
memcpy(iinfo->i_ext.i_data, memcpy(iinfo->i_ext.i_data,
bh->b_data + sizeof(struct extendedFileEntry), bh->b_data + sizeof(struct extendedFileEntry),
inode->i_sb->s_blocksize - inode->i_sb->s_blocksize -
...@@ -1390,11 +1385,10 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) ...@@ -1390,11 +1385,10 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
} else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) { } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) {
iinfo->i_efe = 0; iinfo->i_efe = 0;
iinfo->i_use = 0; iinfo->i_use = 0;
if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - ret = udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
sizeof(struct fileEntry))) { sizeof(struct fileEntry));
make_bad_inode(inode); if (ret)
return; goto out;
}
memcpy(iinfo->i_ext.i_data, memcpy(iinfo->i_ext.i_data,
bh->b_data + sizeof(struct fileEntry), bh->b_data + sizeof(struct fileEntry),
inode->i_sb->s_blocksize - sizeof(struct fileEntry)); inode->i_sb->s_blocksize - sizeof(struct fileEntry));
...@@ -1404,18 +1398,18 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) ...@@ -1404,18 +1398,18 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
iinfo->i_lenAlloc = le32_to_cpu( iinfo->i_lenAlloc = le32_to_cpu(
((struct unallocSpaceEntry *)bh->b_data)-> ((struct unallocSpaceEntry *)bh->b_data)->
lengthAllocDescs); lengthAllocDescs);
if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - ret = udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
sizeof(struct unallocSpaceEntry))) { sizeof(struct unallocSpaceEntry));
make_bad_inode(inode); if (ret)
return; goto out;
}
memcpy(iinfo->i_ext.i_data, memcpy(iinfo->i_ext.i_data,
bh->b_data + sizeof(struct unallocSpaceEntry), bh->b_data + sizeof(struct unallocSpaceEntry),
inode->i_sb->s_blocksize - inode->i_sb->s_blocksize -
sizeof(struct unallocSpaceEntry)); sizeof(struct unallocSpaceEntry));
return; return 0;
} }
ret = -EIO;
read_lock(&sbi->s_cred_lock); read_lock(&sbi->s_cred_lock);
i_uid_write(inode, le32_to_cpu(fe->uid)); i_uid_write(inode, le32_to_cpu(fe->uid));
if (!uid_valid(inode->i_uid) || if (!uid_valid(inode->i_uid) ||
...@@ -1441,8 +1435,10 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) ...@@ -1441,8 +1435,10 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
read_unlock(&sbi->s_cred_lock); read_unlock(&sbi->s_cred_lock);
link_count = le16_to_cpu(fe->fileLinkCount); link_count = le16_to_cpu(fe->fileLinkCount);
if (!link_count) if (!link_count) {
link_count = 1; ret = -ESTALE;
goto out;
}
set_nlink(inode, link_count); set_nlink(inode, link_count);
inode->i_size = le64_to_cpu(fe->informationLength); inode->i_size = le64_to_cpu(fe->informationLength);
...@@ -1488,6 +1484,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) ...@@ -1488,6 +1484,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
iinfo->i_lenAlloc = le32_to_cpu(efe->lengthAllocDescs); iinfo->i_lenAlloc = le32_to_cpu(efe->lengthAllocDescs);
iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint); iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint);
} }
inode->i_generation = iinfo->i_unique;
switch (fe->icbTag.fileType) { switch (fe->icbTag.fileType) {
case ICBTAG_FILE_TYPE_DIRECTORY: case ICBTAG_FILE_TYPE_DIRECTORY:
...@@ -1537,8 +1534,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) ...@@ -1537,8 +1534,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
default: default:
udf_err(inode->i_sb, "(ino %ld) failed unknown file type=%d\n", udf_err(inode->i_sb, "(ino %ld) failed unknown file type=%d\n",
inode->i_ino, fe->icbTag.fileType); inode->i_ino, fe->icbTag.fileType);
make_bad_inode(inode); goto out;
return;
} }
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
struct deviceSpec *dsea = struct deviceSpec *dsea =
...@@ -1549,8 +1545,12 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) ...@@ -1549,8 +1545,12 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
le32_to_cpu(dsea->minorDeviceIdent))); le32_to_cpu(dsea->minorDeviceIdent)));
/* Developer ID ??? */ /* Developer ID ??? */
} else } else
make_bad_inode(inode); goto out;
} }
ret = 0;
out:
brelse(bh);
return ret;
} }
static int udf_alloc_i_data(struct inode *inode, size_t size) static int udf_alloc_i_data(struct inode *inode, size_t size)
...@@ -1664,7 +1664,7 @@ static int udf_update_inode(struct inode *inode, int do_sync) ...@@ -1664,7 +1664,7 @@ static int udf_update_inode(struct inode *inode, int do_sync)
FE_PERM_U_DELETE | FE_PERM_U_CHATTR)); FE_PERM_U_DELETE | FE_PERM_U_CHATTR));
fe->permissions = cpu_to_le32(udfperms); fe->permissions = cpu_to_le32(udfperms);
if (S_ISDIR(inode->i_mode)) if (S_ISDIR(inode->i_mode) && inode->i_nlink > 0)
fe->fileLinkCount = cpu_to_le16(inode->i_nlink - 1); fe->fileLinkCount = cpu_to_le16(inode->i_nlink - 1);
else else
fe->fileLinkCount = cpu_to_le16(inode->i_nlink); fe->fileLinkCount = cpu_to_le16(inode->i_nlink);
...@@ -1830,32 +1830,23 @@ struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino) ...@@ -1830,32 +1830,23 @@ struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino)
{ {
unsigned long block = udf_get_lb_pblock(sb, ino, 0); unsigned long block = udf_get_lb_pblock(sb, ino, 0);
struct inode *inode = iget_locked(sb, block); struct inode *inode = iget_locked(sb, block);
int err;
if (!inode) if (!inode)
return NULL; return ERR_PTR(-ENOMEM);
if (inode->i_state & I_NEW) {
memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr));
__udf_read_inode(inode);
unlock_new_inode(inode);
}
if (is_bad_inode(inode)) if (!(inode->i_state & I_NEW))
goto out_iput; return inode;
if (ino->logicalBlockNum >= UDF_SB(sb)-> memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr));
s_partmaps[ino->partitionReferenceNum].s_partition_len) { err = udf_read_inode(inode);
udf_debug("block=%d, partition=%d out of range\n", if (err < 0) {
ino->logicalBlockNum, ino->partitionReferenceNum); iget_failed(inode);
make_bad_inode(inode); return ERR_PTR(err);
goto out_iput;
} }
unlock_new_inode(inode);
return inode; return inode;
out_iput:
iput(inode);
return NULL;
} }
int udf_add_aext(struct inode *inode, struct extent_position *epos, int udf_add_aext(struct inode *inode, struct extent_position *epos,
......
...@@ -270,9 +270,8 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, ...@@ -270,9 +270,8 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
NULL, 0), NULL, 0),
}; };
inode = udf_iget(dir->i_sb, lb); inode = udf_iget(dir->i_sb, lb);
if (!inode) { if (IS_ERR(inode))
return ERR_PTR(-EACCES); return inode;
}
} else } else
#endif /* UDF_RECOVERY */ #endif /* UDF_RECOVERY */
...@@ -285,9 +284,8 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, ...@@ -285,9 +284,8 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
loc = lelb_to_cpu(cfi.icb.extLocation); loc = lelb_to_cpu(cfi.icb.extLocation);
inode = udf_iget(dir->i_sb, &loc); inode = udf_iget(dir->i_sb, &loc);
if (!inode) { if (IS_ERR(inode))
return ERR_PTR(-EACCES); return ERR_CAST(inode);
}
} }
return d_splice_alias(inode, dentry); return d_splice_alias(inode, dentry);
...@@ -550,32 +548,18 @@ static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi, ...@@ -550,32 +548,18 @@ static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL); return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL);
} }
static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode, static int udf_add_nondir(struct dentry *dentry, struct inode *inode)
bool excl)
{ {
struct udf_inode_info *iinfo = UDF_I(inode);
struct inode *dir = dentry->d_parent->d_inode;
struct udf_fileident_bh fibh; struct udf_fileident_bh fibh;
struct inode *inode;
struct fileIdentDesc cfi, *fi; struct fileIdentDesc cfi, *fi;
int err; 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); fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
if (!fi) { if (unlikely(!fi)) {
inode_dec_link_count(inode); inode_dec_link_count(inode);
unlock_new_inode(inode);
iput(inode); iput(inode);
return err; return err;
} }
...@@ -589,23 +573,21 @@ static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode, ...@@ -589,23 +573,21 @@ static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode,
if (fibh.sbh != fibh.ebh) if (fibh.sbh != fibh.ebh)
brelse(fibh.ebh); brelse(fibh.ebh);
brelse(fibh.sbh); brelse(fibh.sbh);
unlock_new_inode(inode);
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
return 0; return 0;
} }
static int udf_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode,
bool excl)
{ {
struct inode *inode; struct inode *inode = udf_new_inode(dir, mode);
struct udf_inode_info *iinfo;
int err;
inode = udf_new_inode(dir, mode, &err); if (IS_ERR(inode))
if (!inode) return PTR_ERR(inode);
return err;
iinfo = UDF_I(inode); if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
inode->i_data.a_ops = &udf_adinicb_aops; inode->i_data.a_ops = &udf_adinicb_aops;
else else
inode->i_data.a_ops = &udf_aops; inode->i_data.a_ops = &udf_aops;
...@@ -613,7 +595,25 @@ static int udf_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) ...@@ -613,7 +595,25 @@ static int udf_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
inode->i_fop = &udf_file_operations; inode->i_fop = &udf_file_operations;
mark_inode_dirty(inode); 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 = udf_new_inode(dir, mode);
if (IS_ERR(inode))
return PTR_ERR(inode);
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);
d_tmpfile(dentry, inode); d_tmpfile(dentry, inode);
unlock_new_inode(inode);
return 0; return 0;
} }
...@@ -621,44 +621,16 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, ...@@ -621,44 +621,16 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
dev_t rdev) dev_t rdev)
{ {
struct inode *inode; struct inode *inode;
struct udf_fileident_bh fibh;
struct fileIdentDesc cfi, *fi;
int err;
struct udf_inode_info *iinfo;
if (!old_valid_dev(rdev)) if (!old_valid_dev(rdev))
return -EINVAL; return -EINVAL;
err = -EIO; inode = udf_new_inode(dir, mode);
inode = udf_new_inode(dir, mode, &err); if (IS_ERR(inode))
if (!inode) return PTR_ERR(inode);
goto out;
iinfo = UDF_I(inode);
init_special_inode(inode, mode, rdev); init_special_inode(inode, mode, rdev);
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); return udf_add_nondir(dentry, inode);
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;
} }
static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
...@@ -670,10 +642,9 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ...@@ -670,10 +642,9 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
struct udf_inode_info *dinfo = UDF_I(dir); struct udf_inode_info *dinfo = UDF_I(dir);
struct udf_inode_info *iinfo; struct udf_inode_info *iinfo;
err = -EIO; inode = udf_new_inode(dir, S_IFDIR | mode);
inode = udf_new_inode(dir, S_IFDIR | mode, &err); if (IS_ERR(inode))
if (!inode) return PTR_ERR(inode);
goto out;
iinfo = UDF_I(inode); iinfo = UDF_I(inode);
inode->i_op = &udf_dir_inode_operations; inode->i_op = &udf_dir_inode_operations;
...@@ -681,6 +652,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ...@@ -681,6 +652,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err); fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err);
if (!fi) { if (!fi) {
inode_dec_link_count(inode); inode_dec_link_count(inode);
unlock_new_inode(inode);
iput(inode); iput(inode);
goto out; goto out;
} }
...@@ -699,6 +671,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ...@@ -699,6 +671,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
if (!fi) { if (!fi) {
clear_nlink(inode); clear_nlink(inode);
mark_inode_dirty(inode); mark_inode_dirty(inode);
unlock_new_inode(inode);
iput(inode); iput(inode);
goto out; goto out;
} }
...@@ -710,6 +683,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ...@@ -710,6 +683,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
inc_nlink(dir); inc_nlink(dir);
mark_inode_dirty(dir); mark_inode_dirty(dir);
unlock_new_inode(inode);
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
if (fibh.sbh != fibh.ebh) if (fibh.sbh != fibh.ebh)
brelse(fibh.ebh); brelse(fibh.ebh);
...@@ -876,14 +850,11 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry) ...@@ -876,14 +850,11 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry)
static int udf_symlink(struct inode *dir, struct dentry *dentry, static int udf_symlink(struct inode *dir, struct dentry *dentry,
const char *symname) const char *symname)
{ {
struct inode *inode; struct inode *inode = udf_new_inode(dir, S_IFLNK | S_IRWXUGO);
struct pathComponent *pc; struct pathComponent *pc;
const char *compstart; const char *compstart;
struct udf_fileident_bh fibh;
struct extent_position epos = {}; struct extent_position epos = {};
int eoffset, elen = 0; int eoffset, elen = 0;
struct fileIdentDesc *fi;
struct fileIdentDesc cfi;
uint8_t *ea; uint8_t *ea;
int err; int err;
int block; int block;
...@@ -892,9 +863,8 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, ...@@ -892,9 +863,8 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
struct udf_inode_info *iinfo; struct udf_inode_info *iinfo;
struct super_block *sb = dir->i_sb; struct super_block *sb = dir->i_sb;
inode = udf_new_inode(dir, S_IFLNK | S_IRWXUGO, &err); if (IS_ERR(inode))
if (!inode) return PTR_ERR(inode);
goto out;
iinfo = UDF_I(inode); iinfo = UDF_I(inode);
down_write(&iinfo->i_data_sem); down_write(&iinfo->i_data_sem);
...@@ -1012,32 +982,15 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, ...@@ -1012,32 +982,15 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
mark_inode_dirty(inode); mark_inode_dirty(inode);
up_write(&iinfo->i_data_sem); up_write(&iinfo->i_data_sem);
fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); err = udf_add_nondir(dentry, inode);
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;
out: out:
kfree(name); kfree(name);
return err; return err;
out_no_entry: out_no_entry:
up_write(&iinfo->i_data_sem); up_write(&iinfo->i_data_sem);
out_fail:
inode_dec_link_count(inode); inode_dec_link_count(inode);
unlock_new_inode(inode);
iput(inode); iput(inode);
goto out; goto out;
} }
...@@ -1222,7 +1175,7 @@ static struct dentry *udf_get_parent(struct dentry *child) ...@@ -1222,7 +1175,7 @@ static struct dentry *udf_get_parent(struct dentry *child)
struct udf_fileident_bh fibh; struct udf_fileident_bh fibh;
if (!udf_find_entry(child->d_inode, &dotdot, &fibh, &cfi)) if (!udf_find_entry(child->d_inode, &dotdot, &fibh, &cfi))
goto out_unlock; return ERR_PTR(-EACCES);
if (fibh.sbh != fibh.ebh) if (fibh.sbh != fibh.ebh)
brelse(fibh.ebh); brelse(fibh.ebh);
...@@ -1230,12 +1183,10 @@ static struct dentry *udf_get_parent(struct dentry *child) ...@@ -1230,12 +1183,10 @@ static struct dentry *udf_get_parent(struct dentry *child)
tloc = lelb_to_cpu(cfi.icb.extLocation); tloc = lelb_to_cpu(cfi.icb.extLocation);
inode = udf_iget(child->d_inode->i_sb, &tloc); inode = udf_iget(child->d_inode->i_sb, &tloc);
if (!inode) if (IS_ERR(inode))
goto out_unlock; return ERR_CAST(inode);
return d_obtain_alias(inode); return d_obtain_alias(inode);
out_unlock:
return ERR_PTR(-EACCES);
} }
...@@ -1252,8 +1203,8 @@ static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block, ...@@ -1252,8 +1203,8 @@ static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block,
loc.partitionReferenceNum = partref; loc.partitionReferenceNum = partref;
inode = udf_iget(sb, &loc); inode = udf_iget(sb, &loc);
if (inode == NULL) if (IS_ERR(inode))
return ERR_PTR(-ENOMEM); return ERR_CAST(inode);
if (generation && inode->i_generation != generation) { if (generation && inode->i_generation != generation) {
iput(inode); iput(inode);
......
...@@ -961,12 +961,14 @@ struct inode *udf_find_metadata_inode_efe(struct super_block *sb, ...@@ -961,12 +961,14 @@ struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
metadata_fe = udf_iget(sb, &addr); metadata_fe = udf_iget(sb, &addr);
if (metadata_fe == NULL) if (IS_ERR(metadata_fe)) {
udf_warn(sb, "metadata inode efe not found\n"); udf_warn(sb, "metadata inode efe not found\n");
else if (UDF_I(metadata_fe)->i_alloc_type != ICBTAG_FLAG_AD_SHORT) { return metadata_fe;
}
if (UDF_I(metadata_fe)->i_alloc_type != ICBTAG_FLAG_AD_SHORT) {
udf_warn(sb, "metadata inode efe does not have short allocation descriptors!\n"); udf_warn(sb, "metadata inode efe does not have short allocation descriptors!\n");
iput(metadata_fe); iput(metadata_fe);
metadata_fe = NULL; return ERR_PTR(-EIO);
} }
return metadata_fe; return metadata_fe;
...@@ -978,6 +980,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition) ...@@ -978,6 +980,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
struct udf_part_map *map; struct udf_part_map *map;
struct udf_meta_data *mdata; struct udf_meta_data *mdata;
struct kernel_lb_addr addr; struct kernel_lb_addr addr;
struct inode *fe;
map = &sbi->s_partmaps[partition]; map = &sbi->s_partmaps[partition];
mdata = &map->s_type_specific.s_metadata; mdata = &map->s_type_specific.s_metadata;
...@@ -986,22 +989,24 @@ static int udf_load_metadata_files(struct super_block *sb, int partition) ...@@ -986,22 +989,24 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
udf_debug("Metadata file location: block = %d part = %d\n", udf_debug("Metadata file location: block = %d part = %d\n",
mdata->s_meta_file_loc, map->s_partition_num); mdata->s_meta_file_loc, map->s_partition_num);
mdata->s_metadata_fe = udf_find_metadata_inode_efe(sb, fe = udf_find_metadata_inode_efe(sb, mdata->s_meta_file_loc,
mdata->s_meta_file_loc, map->s_partition_num); map->s_partition_num);
if (IS_ERR(fe)) {
if (mdata->s_metadata_fe == NULL) {
/* mirror file entry */ /* mirror file entry */
udf_debug("Mirror metadata file location: block = %d part = %d\n", udf_debug("Mirror metadata file location: block = %d part = %d\n",
mdata->s_mirror_file_loc, map->s_partition_num); mdata->s_mirror_file_loc, map->s_partition_num);
mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb, fe = udf_find_metadata_inode_efe(sb, mdata->s_mirror_file_loc,
mdata->s_mirror_file_loc, map->s_partition_num); map->s_partition_num);
if (mdata->s_mirror_fe == NULL) { if (IS_ERR(fe)) {
udf_err(sb, "Both metadata and mirror metadata inode efe can not found\n"); udf_err(sb, "Both metadata and mirror metadata inode efe can not found\n");
return -EIO; return PTR_ERR(fe);
} }
} mdata->s_mirror_fe = fe;
} else
mdata->s_metadata_fe = fe;
/* /*
* bitmap file entry * bitmap file entry
...@@ -1015,15 +1020,16 @@ static int udf_load_metadata_files(struct super_block *sb, int partition) ...@@ -1015,15 +1020,16 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
udf_debug("Bitmap file location: block = %d part = %d\n", udf_debug("Bitmap file location: block = %d part = %d\n",
addr.logicalBlockNum, addr.partitionReferenceNum); addr.logicalBlockNum, addr.partitionReferenceNum);
mdata->s_bitmap_fe = udf_iget(sb, &addr); fe = udf_iget(sb, &addr);
if (mdata->s_bitmap_fe == NULL) { if (IS_ERR(fe)) {
if (sb->s_flags & MS_RDONLY) if (sb->s_flags & MS_RDONLY)
udf_warn(sb, "bitmap inode efe not found but it's ok since the disc is mounted read-only\n"); udf_warn(sb, "bitmap inode efe not found but it's ok since the disc is mounted read-only\n");
else { else {
udf_err(sb, "bitmap inode efe not found and attempted read-write mount\n"); udf_err(sb, "bitmap inode efe not found and attempted read-write mount\n");
return -EIO; return PTR_ERR(fe);
} }
} } else
mdata->s_bitmap_fe = fe;
} }
udf_debug("udf_load_metadata_files Ok\n"); udf_debug("udf_load_metadata_files Ok\n");
...@@ -1111,13 +1117,15 @@ static int udf_fill_partdesc_info(struct super_block *sb, ...@@ -1111,13 +1117,15 @@ static int udf_fill_partdesc_info(struct super_block *sb,
phd->unallocSpaceTable.extPosition), phd->unallocSpaceTable.extPosition),
.partitionReferenceNum = p_index, .partitionReferenceNum = p_index,
}; };
struct inode *inode;
map->s_uspace.s_table = udf_iget(sb, &loc); inode = udf_iget(sb, &loc);
if (!map->s_uspace.s_table) { if (IS_ERR(inode)) {
udf_debug("cannot load unallocSpaceTable (part %d)\n", udf_debug("cannot load unallocSpaceTable (part %d)\n",
p_index); p_index);
return -EIO; return PTR_ERR(inode);
} }
map->s_uspace.s_table = inode;
map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE; map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE;
udf_debug("unallocSpaceTable (part %d) @ %ld\n", udf_debug("unallocSpaceTable (part %d) @ %ld\n",
p_index, map->s_uspace.s_table->i_ino); p_index, map->s_uspace.s_table->i_ino);
...@@ -1144,14 +1152,15 @@ static int udf_fill_partdesc_info(struct super_block *sb, ...@@ -1144,14 +1152,15 @@ static int udf_fill_partdesc_info(struct super_block *sb,
phd->freedSpaceTable.extPosition), phd->freedSpaceTable.extPosition),
.partitionReferenceNum = p_index, .partitionReferenceNum = p_index,
}; };
struct inode *inode;
map->s_fspace.s_table = udf_iget(sb, &loc); inode = udf_iget(sb, &loc);
if (!map->s_fspace.s_table) { if (IS_ERR(inode)) {
udf_debug("cannot load freedSpaceTable (part %d)\n", udf_debug("cannot load freedSpaceTable (part %d)\n",
p_index); p_index);
return -EIO; return PTR_ERR(inode);
} }
map->s_fspace.s_table = inode;
map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE; map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE;
udf_debug("freedSpaceTable (part %d) @ %ld\n", udf_debug("freedSpaceTable (part %d) @ %ld\n",
p_index, map->s_fspace.s_table->i_ino); p_index, map->s_fspace.s_table->i_ino);
...@@ -1178,6 +1187,7 @@ static void udf_find_vat_block(struct super_block *sb, int p_index, ...@@ -1178,6 +1187,7 @@ static void udf_find_vat_block(struct super_block *sb, int p_index,
struct udf_part_map *map = &sbi->s_partmaps[p_index]; struct udf_part_map *map = &sbi->s_partmaps[p_index];
sector_t vat_block; sector_t vat_block;
struct kernel_lb_addr ino; struct kernel_lb_addr ino;
struct inode *inode;
/* /*
* VAT file entry is in the last recorded block. Some broken disks have * VAT file entry is in the last recorded block. Some broken disks have
...@@ -1186,10 +1196,13 @@ static void udf_find_vat_block(struct super_block *sb, int p_index, ...@@ -1186,10 +1196,13 @@ static void udf_find_vat_block(struct super_block *sb, int p_index,
ino.partitionReferenceNum = type1_index; ino.partitionReferenceNum = type1_index;
for (vat_block = start_block; for (vat_block = start_block;
vat_block >= map->s_partition_root && vat_block >= map->s_partition_root &&
vat_block >= start_block - 3 && vat_block >= start_block - 3; vat_block--) {
!sbi->s_vat_inode; vat_block--) {
ino.logicalBlockNum = vat_block - map->s_partition_root; ino.logicalBlockNum = vat_block - map->s_partition_root;
sbi->s_vat_inode = udf_iget(sb, &ino); inode = udf_iget(sb, &ino);
if (!IS_ERR(inode)) {
sbi->s_vat_inode = inode;
break;
}
} }
} }
...@@ -2205,10 +2218,10 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) ...@@ -2205,10 +2218,10 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
/* assign inodes by physical block number */ /* assign inodes by physical block number */
/* perhaps it's not extensible enough, but for now ... */ /* perhaps it's not extensible enough, but for now ... */
inode = udf_iget(sb, &rootdir); inode = udf_iget(sb, &rootdir);
if (!inode) { if (IS_ERR(inode)) {
udf_err(sb, "Error in udf_iget, block=%d, partition=%d\n", udf_err(sb, "Error in udf_iget, block=%d, partition=%d\n",
rootdir.logicalBlockNum, rootdir.partitionReferenceNum); rootdir.logicalBlockNum, rootdir.partitionReferenceNum);
ret = -EIO; ret = PTR_ERR(inode);
goto error_out; goto error_out;
} }
......
...@@ -143,7 +143,6 @@ extern int udf_expand_file_adinicb(struct inode *); ...@@ -143,7 +143,6 @@ extern int udf_expand_file_adinicb(struct inode *);
extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *); extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *);
extern struct buffer_head *udf_bread(struct inode *, int, int, int *); extern struct buffer_head *udf_bread(struct inode *, int, int, int *);
extern int udf_setsize(struct inode *, loff_t); extern int udf_setsize(struct inode *, loff_t);
extern void udf_read_inode(struct inode *);
extern void udf_evict_inode(struct inode *); extern void udf_evict_inode(struct inode *);
extern int udf_write_inode(struct inode *, struct writeback_control *wbc); extern int udf_write_inode(struct inode *, struct writeback_control *wbc);
extern long udf_block_map(struct inode *, sector_t); extern long udf_block_map(struct inode *, sector_t);
...@@ -209,7 +208,7 @@ extern int udf_CS0toUTF8(struct ustr *, const struct ustr *); ...@@ -209,7 +208,7 @@ extern int udf_CS0toUTF8(struct ustr *, const struct ustr *);
/* ialloc.c */ /* ialloc.c */
extern void udf_free_inode(struct inode *); extern void udf_free_inode(struct inode *);
extern struct inode *udf_new_inode(struct inode *, umode_t, int *); extern struct inode *udf_new_inode(struct inode *, umode_t);
/* truncate.c */ /* truncate.c */
extern void udf_truncate_tail_extent(struct inode *); extern void udf_truncate_tail_extent(struct inode *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment