hpfs: handle allocation failures in hpfs_add_pos()
pr_err() is nice, but we'd better propagate the error to caller and not proceed to violate the invariants (namely, "every file with f_pos tied to directory block should have its address visible in per-inode array"). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
1d1bb236bc
commit
e82c314755
|
@ -44,7 +44,11 @@ static loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence)
|
|||
else goto fail;
|
||||
if (pos == 12) goto fail;
|
||||
}
|
||||
hpfs_add_pos(i, &filp->f_pos);
|
||||
if (unlikely(hpfs_add_pos(i, &filp->f_pos) < 0)) {
|
||||
hpfs_unlock(s);
|
||||
inode_unlock(i);
|
||||
return -ENOMEM;
|
||||
}
|
||||
ok:
|
||||
filp->f_pos = new_off;
|
||||
hpfs_unlock(s);
|
||||
|
@ -141,8 +145,10 @@ static int hpfs_readdir(struct file *file, struct dir_context *ctx)
|
|||
ctx->pos = 1;
|
||||
}
|
||||
if (ctx->pos == 1) {
|
||||
ret = hpfs_add_pos(inode, &file->f_pos);
|
||||
if (unlikely(ret < 0))
|
||||
goto out;
|
||||
ctx->pos = ((loff_t) hpfs_de_as_down_as_possible(inode->i_sb, hpfs_inode->i_dno) << 4) + 1;
|
||||
hpfs_add_pos(inode, &file->f_pos);
|
||||
file->f_version = inode->i_version;
|
||||
}
|
||||
next_pos = ctx->pos;
|
||||
|
|
|
@ -21,7 +21,7 @@ static loff_t get_pos(struct dnode *d, struct hpfs_dirent *fde)
|
|||
return ((loff_t)le32_to_cpu(d->self) << 4) | (loff_t)1;
|
||||
}
|
||||
|
||||
void hpfs_add_pos(struct inode *inode, loff_t *pos)
|
||||
int hpfs_add_pos(struct inode *inode, loff_t *pos)
|
||||
{
|
||||
struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
|
||||
int i = 0;
|
||||
|
@ -29,11 +29,12 @@ void hpfs_add_pos(struct inode *inode, loff_t *pos)
|
|||
|
||||
if (hpfs_inode->i_rddir_off)
|
||||
for (; hpfs_inode->i_rddir_off[i]; i++)
|
||||
if (hpfs_inode->i_rddir_off[i] == pos) return;
|
||||
if (hpfs_inode->i_rddir_off[i] == pos)
|
||||
return 0;
|
||||
if (!(i&0x0f)) {
|
||||
if (!(ppos = kmalloc((i+0x11) * sizeof(loff_t*), GFP_NOFS))) {
|
||||
pr_err("out of memory for position list\n");
|
||||
return;
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (hpfs_inode->i_rddir_off) {
|
||||
memcpy(ppos, hpfs_inode->i_rddir_off, i * sizeof(loff_t));
|
||||
|
@ -43,6 +44,7 @@ void hpfs_add_pos(struct inode *inode, loff_t *pos)
|
|||
}
|
||||
hpfs_inode->i_rddir_off[i] = pos;
|
||||
hpfs_inode->i_rddir_off[i + 1] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hpfs_del_pos(struct inode *inode, loff_t *pos)
|
||||
|
|
|
@ -242,7 +242,7 @@ extern const struct file_operations hpfs_dir_ops;
|
|||
|
||||
/* dnode.c */
|
||||
|
||||
void hpfs_add_pos(struct inode *, loff_t *);
|
||||
int hpfs_add_pos(struct inode *, loff_t *);
|
||||
void hpfs_del_pos(struct inode *, loff_t *);
|
||||
struct hpfs_dirent *hpfs_add_de(struct super_block *, struct dnode *,
|
||||
const unsigned char *, unsigned, secno);
|
||||
|
|
Loading…
Reference in New Issue