Commit e84bcd61 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'upstream-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs

Pull UBI/UBIFS updates from Miquel Raynal:
 "This pull request contains mostly fixes for UBI and UBIFS:

  UBI:
   - Fixes for memory leaks in error paths
   - Fix for an logic error in a fastmap selfcheck

  UBIFS:
   - Fix for FS_IOC_SETFLAGS related to fscrypt flag
   - Support for FS_ENCRYPT_FL
   - Fix for a dead lock in bulk-read mode"

Sent on behalf of Richard Weinberger who is traveling.

* tag 'upstream-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs:
  ubi: Fix an error pointer dereference in error handling code
  ubifs: Fix memory leak from c->sup_node
  ubifs: Fix ino_t format warnings in orphan_delete()
  ubifs: Fix deadlock in concurrent bulk-read and writepage
  ubifs: Fix wrong memory allocation
  ubi: Free the normal volumes in error paths of ubi_attach_mtd_dev()
  ubi: Check the presence of volume before call ubi_fastmap_destroy_checkmap()
  ubifs: Add support for FS_ENCRYPT_FL
  ubifs: Fix FS_IOC_SETFLAGS unexpectedly clearing encrypt flag
  ubi: wl: Remove set but not used variable 'prev_e'
  ubi: fastmap: Fix inverted logic in seen selfcheck
parents 6e135bae 5d3805af
...@@ -1640,7 +1640,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan) ...@@ -1640,7 +1640,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
out_wl: out_wl:
ubi_wl_close(ubi); ubi_wl_close(ubi);
out_vtbl: out_vtbl:
ubi_free_internal_volumes(ubi); ubi_free_all_volumes(ubi);
vfree(ubi->vtbl); vfree(ubi->vtbl);
out_ai: out_ai:
destroy_ai(ai); destroy_ai(ai);
......
...@@ -503,21 +503,42 @@ static void uif_close(struct ubi_device *ubi) ...@@ -503,21 +503,42 @@ static void uif_close(struct ubi_device *ubi)
} }
/** /**
* ubi_free_internal_volumes - free internal volumes. * ubi_free_volumes_from - free volumes from specific index.
* @ubi: UBI device description object * @ubi: UBI device description object
* @from: the start index used for volume free.
*/ */
void ubi_free_internal_volumes(struct ubi_device *ubi) static void ubi_free_volumes_from(struct ubi_device *ubi, int from)
{ {
int i; int i;
for (i = ubi->vtbl_slots; for (i = from; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { if (!ubi->volumes[i])
continue;
ubi_eba_replace_table(ubi->volumes[i], NULL); ubi_eba_replace_table(ubi->volumes[i], NULL);
ubi_fastmap_destroy_checkmap(ubi->volumes[i]); ubi_fastmap_destroy_checkmap(ubi->volumes[i]);
kfree(ubi->volumes[i]); kfree(ubi->volumes[i]);
ubi->volumes[i] = NULL;
} }
} }
/**
* ubi_free_all_volumes - free all volumes.
* @ubi: UBI device description object
*/
void ubi_free_all_volumes(struct ubi_device *ubi)
{
ubi_free_volumes_from(ubi, 0);
}
/**
* ubi_free_internal_volumes - free internal volumes.
* @ubi: UBI device description object
*/
void ubi_free_internal_volumes(struct ubi_device *ubi)
{
ubi_free_volumes_from(ubi, ubi->vtbl_slots);
}
static int get_bad_peb_limit(const struct ubi_device *ubi, int max_beb_per1024) static int get_bad_peb_limit(const struct ubi_device *ubi, int max_beb_per1024)
{ {
int limit, device_pebs; int limit, device_pebs;
...@@ -1013,7 +1034,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, ...@@ -1013,7 +1034,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
out_detach: out_detach:
ubi_devices[ubi_num] = NULL; ubi_devices[ubi_num] = NULL;
ubi_wl_close(ubi); ubi_wl_close(ubi);
ubi_free_internal_volumes(ubi); ubi_free_all_volumes(ubi);
vfree(ubi->vtbl); vfree(ubi->vtbl);
out_free: out_free:
vfree(ubi->peb_buf); vfree(ubi->peb_buf);
......
...@@ -64,7 +64,7 @@ static int self_check_seen(struct ubi_device *ubi, unsigned long *seen) ...@@ -64,7 +64,7 @@ static int self_check_seen(struct ubi_device *ubi, unsigned long *seen)
return 0; return 0;
for (pnum = 0; pnum < ubi->peb_count; pnum++) { for (pnum = 0; pnum < ubi->peb_count; pnum++) {
if (test_bit(pnum, seen) && ubi->lookuptbl[pnum]) { if (!test_bit(pnum, seen) && ubi->lookuptbl[pnum]) {
ubi_err(ubi, "self-check failed for PEB %d, fastmap didn't see it", pnum); ubi_err(ubi, "self-check failed for PEB %d, fastmap didn't see it", pnum);
ret = -EINVAL; ret = -EINVAL;
} }
...@@ -1137,7 +1137,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ...@@ -1137,7 +1137,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
struct rb_node *tmp_rb; struct rb_node *tmp_rb;
int ret, i, j, free_peb_count, used_peb_count, vol_count; int ret, i, j, free_peb_count, used_peb_count, vol_count;
int scrub_peb_count, erase_peb_count; int scrub_peb_count, erase_peb_count;
unsigned long *seen_pebs = NULL; unsigned long *seen_pebs;
fm_raw = ubi->fm_buf; fm_raw = ubi->fm_buf;
memset(ubi->fm_buf, 0, ubi->fm_size); memset(ubi->fm_buf, 0, ubi->fm_size);
...@@ -1151,7 +1151,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ...@@ -1151,7 +1151,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
dvbuf = new_fm_vbuf(ubi, UBI_FM_DATA_VOLUME_ID); dvbuf = new_fm_vbuf(ubi, UBI_FM_DATA_VOLUME_ID);
if (!dvbuf) { if (!dvbuf) {
ret = -ENOMEM; ret = -ENOMEM;
goto out_kfree; goto out_free_avbuf;
} }
avhdr = ubi_get_vid_hdr(avbuf); avhdr = ubi_get_vid_hdr(avbuf);
...@@ -1160,7 +1160,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ...@@ -1160,7 +1160,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
seen_pebs = init_seen(ubi); seen_pebs = init_seen(ubi);
if (IS_ERR(seen_pebs)) { if (IS_ERR(seen_pebs)) {
ret = PTR_ERR(seen_pebs); ret = PTR_ERR(seen_pebs);
goto out_kfree; goto out_free_dvbuf;
} }
spin_lock(&ubi->volumes_lock); spin_lock(&ubi->volumes_lock);
...@@ -1328,7 +1328,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ...@@ -1328,7 +1328,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
ret = ubi_io_write_vid_hdr(ubi, new_fm->e[0]->pnum, avbuf); ret = ubi_io_write_vid_hdr(ubi, new_fm->e[0]->pnum, avbuf);
if (ret) { if (ret) {
ubi_err(ubi, "unable to write vid_hdr to fastmap SB!"); ubi_err(ubi, "unable to write vid_hdr to fastmap SB!");
goto out_kfree; goto out_free_seen;
} }
for (i = 0; i < new_fm->used_blocks; i++) { for (i = 0; i < new_fm->used_blocks; i++) {
...@@ -1350,7 +1350,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ...@@ -1350,7 +1350,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
if (ret) { if (ret) {
ubi_err(ubi, "unable to write vid_hdr to PEB %i!", ubi_err(ubi, "unable to write vid_hdr to PEB %i!",
new_fm->e[i]->pnum); new_fm->e[i]->pnum);
goto out_kfree; goto out_free_seen;
} }
} }
...@@ -1360,7 +1360,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ...@@ -1360,7 +1360,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
if (ret) { if (ret) {
ubi_err(ubi, "unable to write fastmap to PEB %i!", ubi_err(ubi, "unable to write fastmap to PEB %i!",
new_fm->e[i]->pnum); new_fm->e[i]->pnum);
goto out_kfree; goto out_free_seen;
} }
} }
...@@ -1370,10 +1370,13 @@ static int ubi_write_fastmap(struct ubi_device *ubi, ...@@ -1370,10 +1370,13 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
ret = self_check_seen(ubi, seen_pebs); ret = self_check_seen(ubi, seen_pebs);
dbg_bld("fastmap written!"); dbg_bld("fastmap written!");
out_kfree: out_free_seen:
ubi_free_vid_buf(avbuf);
ubi_free_vid_buf(dvbuf);
free_seen(seen_pebs); free_seen(seen_pebs);
out_free_dvbuf:
ubi_free_vid_buf(dvbuf);
out_free_avbuf:
ubi_free_vid_buf(avbuf);
out: out:
return ret; return ret;
} }
......
...@@ -950,6 +950,7 @@ int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -950,6 +950,7 @@ int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol,
int ubi_notify_all(struct ubi_device *ubi, int ntype, int ubi_notify_all(struct ubi_device *ubi, int ntype,
struct notifier_block *nb); struct notifier_block *nb);
int ubi_enumerate_volumes(struct notifier_block *nb); int ubi_enumerate_volumes(struct notifier_block *nb);
void ubi_free_all_volumes(struct ubi_device *ubi);
void ubi_free_internal_volumes(struct ubi_device *ubi); void ubi_free_internal_volumes(struct ubi_device *ubi);
/* kapi.c */ /* kapi.c */
......
...@@ -782,7 +782,7 @@ static int check_attaching_info(const struct ubi_device *ubi, ...@@ -782,7 +782,7 @@ static int check_attaching_info(const struct ubi_device *ubi,
*/ */
int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai) int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai)
{ {
int i, err; int err;
struct ubi_ainf_volume *av; struct ubi_ainf_volume *av;
empty_vtbl_record.crc = cpu_to_be32(0xf116c36b); empty_vtbl_record.crc = cpu_to_be32(0xf116c36b);
...@@ -851,11 +851,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai) ...@@ -851,11 +851,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai)
out_free: out_free:
vfree(ubi->vtbl); vfree(ubi->vtbl);
for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { ubi_free_all_volumes(ubi);
ubi_fastmap_destroy_checkmap(ubi->volumes[i]);
kfree(ubi->volumes[i]);
ubi->volumes[i] = NULL;
}
return err; return err;
} }
......
...@@ -319,7 +319,7 @@ static struct ubi_wl_entry *find_wl_entry(struct ubi_device *ubi, ...@@ -319,7 +319,7 @@ static struct ubi_wl_entry *find_wl_entry(struct ubi_device *ubi,
struct rb_root *root, int diff) struct rb_root *root, int diff)
{ {
struct rb_node *p; struct rb_node *p;
struct ubi_wl_entry *e, *prev_e = NULL; struct ubi_wl_entry *e;
int max; int max;
e = rb_entry(rb_first(root), struct ubi_wl_entry, u.rb); e = rb_entry(rb_first(root), struct ubi_wl_entry, u.rb);
...@@ -334,7 +334,6 @@ static struct ubi_wl_entry *find_wl_entry(struct ubi_device *ubi, ...@@ -334,7 +334,6 @@ static struct ubi_wl_entry *find_wl_entry(struct ubi_device *ubi,
p = p->rb_left; p = p->rb_left;
else { else {
p = p->rb_right; p = p->rb_right;
prev_e = e;
e = e1; e = e1;
} }
} }
......
...@@ -786,7 +786,9 @@ static int ubifs_do_bulk_read(struct ubifs_info *c, struct bu_info *bu, ...@@ -786,7 +786,9 @@ static int ubifs_do_bulk_read(struct ubifs_info *c, struct bu_info *bu,
if (page_offset > end_index) if (page_offset > end_index)
break; break;
page = find_or_create_page(mapping, page_offset, ra_gfp_mask); page = pagecache_get_page(mapping, page_offset,
FGP_LOCK|FGP_ACCESSED|FGP_CREAT|FGP_NOWAIT,
ra_gfp_mask);
if (!page) if (!page)
break; break;
if (!PageUptodate(page)) if (!PageUptodate(page))
......
...@@ -17,10 +17,14 @@ ...@@ -17,10 +17,14 @@
#include "ubifs.h" #include "ubifs.h"
/* Need to be kept consistent with checked flags in ioctl2ubifs() */ /* Need to be kept consistent with checked flags in ioctl2ubifs() */
#define UBIFS_SUPPORTED_IOCTL_FLAGS \ #define UBIFS_SETTABLE_IOCTL_FLAGS \
(FS_COMPR_FL | FS_SYNC_FL | FS_APPEND_FL | \ (FS_COMPR_FL | FS_SYNC_FL | FS_APPEND_FL | \
FS_IMMUTABLE_FL | FS_DIRSYNC_FL) FS_IMMUTABLE_FL | FS_DIRSYNC_FL)
/* Need to be kept consistent with checked flags in ubifs2ioctl() */
#define UBIFS_GETTABLE_IOCTL_FLAGS \
(UBIFS_SETTABLE_IOCTL_FLAGS | FS_ENCRYPT_FL)
/** /**
* ubifs_set_inode_flags - set VFS inode flags. * ubifs_set_inode_flags - set VFS inode flags.
* @inode: VFS inode to set flags for * @inode: VFS inode to set flags for
...@@ -91,6 +95,8 @@ static int ubifs2ioctl(int ubifs_flags) ...@@ -91,6 +95,8 @@ static int ubifs2ioctl(int ubifs_flags)
ioctl_flags |= FS_IMMUTABLE_FL; ioctl_flags |= FS_IMMUTABLE_FL;
if (ubifs_flags & UBIFS_DIRSYNC_FL) if (ubifs_flags & UBIFS_DIRSYNC_FL)
ioctl_flags |= FS_DIRSYNC_FL; ioctl_flags |= FS_DIRSYNC_FL;
if (ubifs_flags & UBIFS_CRYPT_FL)
ioctl_flags |= FS_ENCRYPT_FL;
return ioctl_flags; return ioctl_flags;
} }
...@@ -113,7 +119,8 @@ static int setflags(struct inode *inode, int flags) ...@@ -113,7 +119,8 @@ static int setflags(struct inode *inode, int flags)
if (err) if (err)
goto out_unlock; goto out_unlock;
ui->flags = ioctl2ubifs(flags); ui->flags &= ~ioctl2ubifs(UBIFS_SETTABLE_IOCTL_FLAGS);
ui->flags |= ioctl2ubifs(flags);
ubifs_set_inode_flags(inode); ubifs_set_inode_flags(inode);
inode->i_ctime = current_time(inode); inode->i_ctime = current_time(inode);
release = ui->dirty; release = ui->dirty;
...@@ -155,8 +162,9 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -155,8 +162,9 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (get_user(flags, (int __user *) arg)) if (get_user(flags, (int __user *) arg))
return -EFAULT; return -EFAULT;
if (flags & ~UBIFS_SUPPORTED_IOCTL_FLAGS) if (flags & ~UBIFS_GETTABLE_IOCTL_FLAGS)
return -EOPNOTSUPP; return -EOPNOTSUPP;
flags &= UBIFS_SETTABLE_IOCTL_FLAGS;
if (!S_ISDIR(inode->i_mode)) if (!S_ISDIR(inode->i_mode))
flags &= ~FS_DIRSYNC_FL; flags &= ~FS_DIRSYNC_FL;
......
...@@ -129,7 +129,7 @@ static void __orphan_drop(struct ubifs_info *c, struct ubifs_orphan *o) ...@@ -129,7 +129,7 @@ static void __orphan_drop(struct ubifs_info *c, struct ubifs_orphan *o)
static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph) static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph)
{ {
if (orph->del) { if (orph->del) {
dbg_gen("deleted twice ino %lu", orph->inum); dbg_gen("deleted twice ino %lu", (unsigned long)orph->inum);
return; return;
} }
...@@ -137,7 +137,7 @@ static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph) ...@@ -137,7 +137,7 @@ static void orphan_delete(struct ubifs_info *c, struct ubifs_orphan *orph)
orph->del = 1; orph->del = 1;
orph->dnext = c->orph_dnext; orph->dnext = c->orph_dnext;
c->orph_dnext = orph; c->orph_dnext = orph;
dbg_gen("delete later ino %lu", orph->inum); dbg_gen("delete later ino %lu", (unsigned long)orph->inum);
return; return;
} }
......
...@@ -161,7 +161,7 @@ static int create_default_filesystem(struct ubifs_info *c) ...@@ -161,7 +161,7 @@ static int create_default_filesystem(struct ubifs_info *c)
sup = kzalloc(ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size), GFP_KERNEL); sup = kzalloc(ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size), GFP_KERNEL);
mst = kzalloc(c->mst_node_alsz, GFP_KERNEL); mst = kzalloc(c->mst_node_alsz, GFP_KERNEL);
idx_node_size = ubifs_idx_node_sz(c, 1); idx_node_size = ubifs_idx_node_sz(c, 1);
idx = kzalloc(ALIGN(tmp, c->min_io_size), GFP_KERNEL); idx = kzalloc(ALIGN(idx_node_size, c->min_io_size), GFP_KERNEL);
ino = kzalloc(ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size), GFP_KERNEL); ino = kzalloc(ALIGN(UBIFS_INO_NODE_SZ, c->min_io_size), GFP_KERNEL);
cs = kzalloc(ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size), GFP_KERNEL); cs = kzalloc(ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size), GFP_KERNEL);
......
...@@ -1599,6 +1599,7 @@ static int mount_ubifs(struct ubifs_info *c) ...@@ -1599,6 +1599,7 @@ static int mount_ubifs(struct ubifs_info *c)
vfree(c->ileb_buf); vfree(c->ileb_buf);
vfree(c->sbuf); vfree(c->sbuf);
kfree(c->bottom_up_buf); kfree(c->bottom_up_buf);
kfree(c->sup_node);
ubifs_debugging_exit(c); ubifs_debugging_exit(c);
return err; return err;
} }
...@@ -1641,6 +1642,7 @@ static void ubifs_umount(struct ubifs_info *c) ...@@ -1641,6 +1642,7 @@ static void ubifs_umount(struct ubifs_info *c)
vfree(c->ileb_buf); vfree(c->ileb_buf);
vfree(c->sbuf); vfree(c->sbuf);
kfree(c->bottom_up_buf); kfree(c->bottom_up_buf);
kfree(c->sup_node);
ubifs_debugging_exit(c); ubifs_debugging_exit(c);
} }
......
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