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: Jan Kara <jack@suse.cz>
This commit is contained in:
Родитель
9bf2c6b834
Коммит
b80697c14d
57
fs/udf/dir.c
57
fs/udf/dir.c
|
@ -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)
|
||||
|
|
128
fs/udf/namei.c
128
fs/udf/namei.c
|
@ -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 @@ add:
|
|||
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 @@ add:
|
|||
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 @@ add:
|
|||
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;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче