Commit b80697c1 authored by Jan Kara's avatar Jan Kara

udf: Remove declarations of arrays of size UDF_NAME_LEN (256 bytes)

There are several places in UDF where we declared temporary arrays of
UDF_NAME_LEN bytes on stack. This is not nice to stack usage so this patch
changes those places to use kmalloc() instead. Also clean up bail-out paths
in those functions when we are changing them.
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 9bf2c6b8
......@@ -39,13 +39,13 @@
static int do_udf_readdir(struct inode *dir, struct file *filp,
filldir_t filldir, void *dirent)
{
struct udf_fileident_bh fibh;
struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL};
struct fileIdentDesc *fi = NULL;
struct fileIdentDesc cfi;
int block, iblock;
loff_t nf_pos = (filp->f_pos - 1) << 2;
int flen;
char fname[UDF_NAME_LEN];
char *fname = NULL;
char *nameptr;
uint16_t liu;
uint8_t lfi;
......@@ -54,23 +54,32 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
kernel_lb_addr eloc;
uint32_t elen;
sector_t offset;
int i, num;
int i, num, ret = 0;
unsigned int dt_type;
struct extent_position epos = { NULL, 0, {0, 0} };
struct udf_inode_info *iinfo;
if (nf_pos >= size)
return 0;
goto out;
fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
if (!fname) {
ret = -ENOMEM;
goto out;
}
if (nf_pos == 0)
nf_pos = udf_ext0_offset(dir);
fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1);
iinfo = UDF_I(dir);
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
fibh.sbh = fibh.ebh = NULL;
} else if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
&epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) {
if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
&epos, &eloc, &elen, &offset)
!= (EXT_RECORDED_ALLOCATED >> 30)) {
ret = -ENOENT;
goto out;
}
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
......@@ -83,8 +92,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
}
if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) {
brelse(epos.bh);
return -EIO;
ret = -EIO;
goto out;
}
if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9)) - 1))) {
......@@ -105,9 +114,6 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
brelse(bha[i]);
}
}
} else {
brelse(epos.bh);
return -ENOENT;
}
while (nf_pos < size) {
......@@ -115,13 +121,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc,
&elen, &offset);
if (!fi) {
if (fibh.sbh != fibh.ebh)
brelse(fibh.ebh);
brelse(fibh.sbh);
brelse(epos.bh);
return 0;
}
if (!fi)
goto out;
liu = le16_to_cpu(cfi.lengthOfImpUse);
lfi = cfi.lengthFileIdent;
......@@ -167,25 +168,21 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
dt_type = DT_UNKNOWN;
}
if (flen) {
if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0) {
if (fibh.sbh != fibh.ebh)
brelse(fibh.ebh);
brelse(fibh.sbh);
brelse(epos.bh);
return 0;
}
}
if (flen && filldir(dirent, fname, flen, filp->f_pos,
iblock, dt_type) < 0)
goto out;
} /* end while */
filp->f_pos = (nf_pos >> 2) + 1;
out:
if (fibh.sbh != fibh.ebh)
brelse(fibh.ebh);
brelse(fibh.sbh);
brelse(epos.bh);
kfree(fname);
return 0;
return ret;
}
static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
......
......@@ -149,7 +149,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
struct fileIdentDesc *fi = NULL;
loff_t f_pos;
int block, flen;
char fname[UDF_NAME_LEN];
char *fname = NULL;
char *nameptr;
uint8_t lfi;
uint16_t liu;
......@@ -163,12 +163,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
size = udf_ext0_offset(dir) + dir->i_size;
f_pos = udf_ext0_offset(dir);
fibh->sbh = fibh->ebh = NULL;
fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
fibh->sbh = fibh->ebh = NULL;
else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits,
&epos, &eloc, &elen, &offset) ==
(EXT_RECORDED_ALLOCATED >> 30)) {
if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
&eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30))
goto out_err;
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
......@@ -179,25 +179,19 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
offset = 0;
fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
if (!fibh->sbh) {
brelse(epos.bh);
return NULL;
}
} else {
brelse(epos.bh);
return NULL;
if (!fibh->sbh)
goto out_err;
}
fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
if (!fname)
goto out_err;
while (f_pos < size) {
fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
&elen, &offset);
if (!fi) {
if (fibh->sbh != fibh->ebh)
brelse(fibh->ebh);
brelse(fibh->sbh);
brelse(epos.bh);
return NULL;
}
if (!fi)
goto out_err;
liu = le16_to_cpu(cfi->lengthOfImpUse);
lfi = cfi->lengthFileIdent;
......@@ -237,18 +231,20 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
if (flen && udf_match(flen, fname, dentry->d_name.len,
dentry->d_name.name)) {
brelse(epos.bh);
return fi;
}
dentry->d_name.name))
goto out_ok;
}
out_err:
fi = NULL;
if (fibh->sbh != fibh->ebh)
brelse(fibh->ebh);
brelse(fibh->sbh);
out_ok:
brelse(epos.bh);
kfree(fname);
return NULL;
return fi;
}
static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
......@@ -303,7 +299,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
{
struct super_block *sb = dir->i_sb;
struct fileIdentDesc *fi = NULL;
char name[UDF_NAME_LEN];
char *name = NULL;
int namelen;
loff_t f_pos;
loff_t size = udf_ext0_offset(dir) + dir->i_size;
......@@ -317,16 +313,23 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
struct extent_position epos = {};
struct udf_inode_info *dinfo;
fibh->sbh = fibh->ebh = NULL;
name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
if (!name) {
*err = -ENOMEM;
goto out_err;
}
if (dentry) {
if (!dentry->d_name.len) {
*err = -EINVAL;
return NULL;
goto out_err;
}
namelen = udf_put_filename(sb, dentry->d_name.name, name,
dentry->d_name.len);
if (!namelen) {
*err = -ENAMETOOLONG;
return NULL;
goto out_err;
}
} else {
namelen = 0;
......@@ -338,11 +341,14 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
dinfo = UDF_I(dir);
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
fibh->sbh = fibh->ebh = NULL;
else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits,
&epos, &eloc, &elen, &offset) ==
(EXT_RECORDED_ALLOCATED >> 30)) {
if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
&eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) {
block = udf_get_lb_pblock(dir->i_sb,
dinfo->i_location, 0);
fibh->soffset = fibh->eoffset = sb->s_blocksize;
goto add;
}
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
......@@ -354,17 +360,11 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
if (!fibh->sbh) {
brelse(epos.bh);
*err = -EIO;
return NULL;
goto out_err;
}
block = dinfo->i_location.logicalBlockNum;
} else {
block = udf_get_lb_pblock(dir->i_sb, dinfo->i_location, 0);
fibh->sbh = fibh->ebh = NULL;
fibh->soffset = fibh->eoffset = sb->s_blocksize;
goto add;
}
while (f_pos < size) {
......@@ -372,12 +372,8 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
&elen, &offset);
if (!fi) {
if (fibh->sbh != fibh->ebh)
brelse(fibh->ebh);
brelse(fibh->sbh);
brelse(epos.bh);
*err = -EIO;
return NULL;
goto out_err;
}
liu = le16_to_cpu(cfi->lengthOfImpUse);
......@@ -386,7 +382,6 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
if (((sizeof(struct fileIdentDesc) +
liu + lfi + 3) & ~3) == nfidlen) {
brelse(epos.bh);
cfi->descTag.tagSerialNum = cpu_to_le16(1);
cfi->fileVersionNum = cpu_to_le16(1);
cfi->fileCharacteristics = 0;
......@@ -394,10 +389,10 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
cfi->lengthOfImpUse = cpu_to_le16(0);
if (!udf_write_fi(dir, cfi, fi, fibh, NULL,
name))
return fi;
goto out_ok;
else {
*err = -EIO;
return NULL;
goto out_err;
}
}
}
......@@ -427,7 +422,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
fibh->sbh = fibh->ebh =
udf_expand_dir_adinicb(dir, &block, err);
if (!fibh->sbh)
return NULL;
goto out_err;
epos.block = dinfo->i_location;
epos.offset = udf_file_entry_alloc_offset(dir);
/* Load extent udf_expand_dir_adinicb() has created */
......@@ -468,11 +463,8 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
dir->i_sb->s_blocksize_bits);
fibh->ebh = udf_bread(dir,
f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
if (!fibh->ebh) {
brelse(epos.bh);
brelse(fibh->sbh);
return NULL;
}
if (!fibh->ebh)
goto out_err;
if (!fibh->soffset) {
if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
......@@ -503,20 +495,25 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
cfi->lengthFileIdent = namelen;
cfi->lengthOfImpUse = cpu_to_le16(0);
if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) {
brelse(epos.bh);
dir->i_size += nfidlen;
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
dinfo->i_lenAlloc += nfidlen;
mark_inode_dirty(dir);
return fi;
goto out_ok;
} else {
brelse(epos.bh);
if (fibh->sbh != fibh->ebh)
brelse(fibh->ebh);
brelse(fibh->sbh);
*err = -EIO;
return NULL;
goto out_err;
}
out_err:
fi = NULL;
if (fibh->sbh != fibh->ebh)
brelse(fibh->ebh);
brelse(fibh->sbh);
out_ok:
brelse(epos.bh);
kfree(name);
return fi;
}
static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
......@@ -871,7 +868,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
char *ea;
int err;
int block;
char name[UDF_NAME_LEN];
char *name = NULL;
int namelen;
struct buffer_head *bh;
struct udf_inode_info *iinfo;
......@@ -881,6 +878,12 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
if (!inode)
goto out;
name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
if (!name) {
err = -ENOMEM;
goto out_no_entry;
}
iinfo = UDF_I(inode);
inode->i_mode = S_IFLNK | S_IRWXUGO;
inode->i_data.a_ops = &udf_symlink_aops;
......@@ -1020,6 +1023,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
err = 0;
out:
kfree(name);
unlock_kernel();
return err;
......
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