Skip to content

Commit

Permalink
hpfs: handle allocation failures in hpfs_add_pos()
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
Al Viro committed May 12, 2016
1 parent 1d1bb23 commit e82c314
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 6 deletions.
10 changes: 8 additions & 2 deletions fs/hpfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 5 additions & 3 deletions fs/hpfs/dnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,20 @@ 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;
loff_t **ppos;

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));
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion fs/hpfs/hpfs_fn.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit e82c314

Please sign in to comment.