Commit d53b47c0 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'upstream-3.16-rc1-v2' of git://git.infradead.org/linux-ubifs

Pull UBIFS updates from Artem Bityutskiy:
 "This contains several UBIFS fixes.  One of them fixes a race condition
  between the mmap page fault path and fsync.  Another just removes a
  bogus assertion from the UBIFS memory shrinker.

  UBIFS also started honoring the MS_SILENT mount flag, so now it won't
  print many I/O errors when user-space just tries to probe for the FS.

  Rest of the changes are rather minor UBI/UBIFS fixes, improvements,
  and clean-ups"

* tag 'upstream-3.16-rc1-v2' of git://git.infradead.org/linux-ubifs:
  UBIFS: Add an assertion for clean_zn_cnt
  UBIFS: respect MS_SILENT mount flag
  UBIFS: Remove incorrect assertion in shrink_tnc()
  UBIFS: fix debugging check
  UBIFS: add missing ui pointer in debugging code
  UBI: block: Fix error path on alloc_workqueue failure
  UBIFS: Fix dump messages in ubifs_dump_lprops
  UBI: fix rb_tree node comparison in add_map
  UBIFS: Remove unused variables in ubifs_budget_space
  UBI: weaken the 'exclusive' constraint when opening volumes to rename
  UBIFS: fix an mmap and fsync race condition
parents a3c54931 380347e9
...@@ -432,8 +432,10 @@ int ubiblock_create(struct ubi_volume_info *vi) ...@@ -432,8 +432,10 @@ int ubiblock_create(struct ubi_volume_info *vi)
* Rembember workqueues are cheap, they're not threads. * Rembember workqueues are cheap, they're not threads.
*/ */
dev->wq = alloc_workqueue("%s", 0, 0, gd->disk_name); dev->wq = alloc_workqueue("%s", 0, 0, gd->disk_name);
if (!dev->wq) if (!dev->wq) {
ret = -ENOMEM;
goto out_free_queue; goto out_free_queue;
}
INIT_WORK(&dev->work, ubiblock_do_work); INIT_WORK(&dev->work, ubiblock_do_work);
mutex_lock(&devices_mutex); mutex_lock(&devices_mutex);
......
...@@ -731,7 +731,7 @@ static int rename_volumes(struct ubi_device *ubi, ...@@ -731,7 +731,7 @@ static int rename_volumes(struct ubi_device *ubi,
goto out_free; goto out_free;
} }
re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE); re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_READWRITE);
if (IS_ERR(re->desc)) { if (IS_ERR(re->desc)) {
err = PTR_ERR(re->desc); err = PTR_ERR(re->desc);
ubi_err("cannot open volume %d, error %d", vol_id, err); ubi_err("cannot open volume %d, error %d", vol_id, err);
......
...@@ -125,9 +125,9 @@ static struct ubi_ainf_volume *add_vol(struct ubi_attach_info *ai, int vol_id, ...@@ -125,9 +125,9 @@ static struct ubi_ainf_volume *add_vol(struct ubi_attach_info *ai, int vol_id,
parent = *p; parent = *p;
av = rb_entry(parent, struct ubi_ainf_volume, rb); av = rb_entry(parent, struct ubi_ainf_volume, rb);
if (vol_id > av->vol_id) if (vol_id < av->vol_id)
p = &(*p)->rb_left; p = &(*p)->rb_left;
else if (vol_id > av->vol_id) else
p = &(*p)->rb_right; p = &(*p)->rb_right;
} }
......
...@@ -437,7 +437,6 @@ static int calc_dd_growth(const struct ubifs_info *c, ...@@ -437,7 +437,6 @@ static int calc_dd_growth(const struct ubifs_info *c,
*/ */
int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req) int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req)
{ {
int uninitialized_var(cmt_retries), uninitialized_var(wb_retries);
int err, idx_growth, data_growth, dd_growth, retried = 0; int err, idx_growth, data_growth, dd_growth, retried = 0;
ubifs_assert(req->new_page <= 1); ubifs_assert(req->new_page <= 1);
......
...@@ -745,8 +745,10 @@ void ubifs_dump_lprops(struct ubifs_info *c) ...@@ -745,8 +745,10 @@ void ubifs_dump_lprops(struct ubifs_info *c)
for (lnum = c->main_first; lnum < c->leb_cnt; lnum++) { for (lnum = c->main_first; lnum < c->leb_cnt; lnum++) {
err = ubifs_read_one_lp(c, lnum, &lp); err = ubifs_read_one_lp(c, lnum, &lp);
if (err) if (err) {
ubifs_err("cannot read lprops for LEB %d", lnum); ubifs_err("cannot read lprops for LEB %d", lnum);
continue;
}
ubifs_dump_lprop(c, &lp); ubifs_dump_lprop(c, &lp);
} }
......
...@@ -903,8 +903,9 @@ static int do_writepage(struct page *page, int len) ...@@ -903,8 +903,9 @@ static int do_writepage(struct page *page, int len)
struct ubifs_info *c = inode->i_sb->s_fs_info; struct ubifs_info *c = inode->i_sb->s_fs_info;
#ifdef UBIFS_DEBUG #ifdef UBIFS_DEBUG
struct ubifs_inode *ui = ubifs_inode(inode);
spin_lock(&ui->ui_lock); spin_lock(&ui->ui_lock);
ubifs_assert(page->index <= ui->synced_i_size << PAGE_CACHE_SIZE); ubifs_assert(page->index <= ui->synced_i_size >> PAGE_CACHE_SHIFT);
spin_unlock(&ui->ui_lock); spin_unlock(&ui->ui_lock);
#endif #endif
...@@ -1525,8 +1526,7 @@ static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, ...@@ -1525,8 +1526,7 @@ static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma,
} }
wait_for_stable_page(page); wait_for_stable_page(page);
unlock_page(page); return VM_FAULT_LOCKED;
return 0;
out_unlock: out_unlock:
unlock_page(page); unlock_page(page);
......
...@@ -988,30 +988,32 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len, ...@@ -988,30 +988,32 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
return err; return err;
if (type != ch->node_type) { if (type != ch->node_type) {
ubifs_err("bad node type (%d but expected %d)", ubifs_errc(c, "bad node type (%d but expected %d)",
ch->node_type, type); ch->node_type, type);
goto out; goto out;
} }
err = ubifs_check_node(c, buf, lnum, offs, 0, 0); err = ubifs_check_node(c, buf, lnum, offs, 0, 0);
if (err) { if (err) {
ubifs_err("expected node type %d", type); ubifs_errc(c, "expected node type %d", type);
return err; return err;
} }
l = le32_to_cpu(ch->len); l = le32_to_cpu(ch->len);
if (l != len) { if (l != len) {
ubifs_err("bad node length %d, expected %d", l, len); ubifs_errc(c, "bad node length %d, expected %d", l, len);
goto out; goto out;
} }
return 0; return 0;
out: out:
ubifs_err("bad node at LEB %d:%d, LEB mapping status %d", lnum, offs, ubifs_errc(c, "bad node at LEB %d:%d, LEB mapping status %d", lnum,
ubi_is_mapped(c->ubi, lnum)); offs, ubi_is_mapped(c->ubi, lnum));
ubifs_dump_node(c, buf); if (!c->probing) {
dump_stack(); ubifs_dump_node(c, buf);
dump_stack();
}
return -EINVAL; return -EINVAL;
} }
......
...@@ -128,7 +128,6 @@ static int shrink_tnc(struct ubifs_info *c, int nr, int age, int *contention) ...@@ -128,7 +128,6 @@ static int shrink_tnc(struct ubifs_info *c, int nr, int age, int *contention)
freed = ubifs_destroy_tnc_subtree(znode); freed = ubifs_destroy_tnc_subtree(znode);
atomic_long_sub(freed, &ubifs_clean_zn_cnt); atomic_long_sub(freed, &ubifs_clean_zn_cnt);
atomic_long_sub(freed, &c->clean_zn_cnt); atomic_long_sub(freed, &c->clean_zn_cnt);
ubifs_assert(atomic_long_read(&c->clean_zn_cnt) >= 0);
total_freed += freed; total_freed += freed;
znode = zprev; znode = zprev;
} }
......
...@@ -1149,6 +1149,9 @@ static int mount_ubifs(struct ubifs_info *c) ...@@ -1149,6 +1149,9 @@ static int mount_ubifs(struct ubifs_info *c)
size_t sz; size_t sz;
c->ro_mount = !!(c->vfs_sb->s_flags & MS_RDONLY); c->ro_mount = !!(c->vfs_sb->s_flags & MS_RDONLY);
/* Suppress error messages while probing if MS_SILENT is set */
c->probing = !!(c->vfs_sb->s_flags & MS_SILENT);
err = init_constants_early(c); err = init_constants_early(c);
if (err) if (err)
return err; return err;
...@@ -1214,6 +1217,8 @@ static int mount_ubifs(struct ubifs_info *c) ...@@ -1214,6 +1217,8 @@ static int mount_ubifs(struct ubifs_info *c)
if (err) if (err)
goto out_free; goto out_free;
c->probing = 0;
/* /*
* Make sure the compressor which is set as default in the superblock * Make sure the compressor which is set as default in the superblock
* or overridden by mount options is actually compiled in. * or overridden by mount options is actually compiled in.
......
...@@ -2859,10 +2859,11 @@ void ubifs_tnc_close(struct ubifs_info *c) ...@@ -2859,10 +2859,11 @@ void ubifs_tnc_close(struct ubifs_info *c)
{ {
tnc_destroy_cnext(c); tnc_destroy_cnext(c);
if (c->zroot.znode) { if (c->zroot.znode) {
long n; long n, freed;
ubifs_destroy_tnc_subtree(c->zroot.znode);
n = atomic_long_read(&c->clean_zn_cnt); n = atomic_long_read(&c->clean_zn_cnt);
freed = ubifs_destroy_tnc_subtree(c->zroot.znode);
ubifs_assert(freed == n);
atomic_long_sub(n, &ubifs_clean_zn_cnt); atomic_long_sub(n, &ubifs_clean_zn_cnt);
} }
kfree(c->gap_lebs); kfree(c->gap_lebs);
......
...@@ -51,6 +51,15 @@ ...@@ -51,6 +51,15 @@
#define ubifs_warn(fmt, ...) \ #define ubifs_warn(fmt, ...) \
pr_warn("UBIFS warning (pid %d): %s: " fmt "\n", \ pr_warn("UBIFS warning (pid %d): %s: " fmt "\n", \
current->pid, __func__, ##__VA_ARGS__) current->pid, __func__, ##__VA_ARGS__)
/*
* A variant of 'ubifs_err()' which takes the UBIFS file-sytem description
* object as an argument.
*/
#define ubifs_errc(c, fmt, ...) \
do { \
if (!(c)->probing) \
ubifs_err(fmt, ##__VA_ARGS__); \
} while (0)
/* UBIFS file system VFS magic number */ /* UBIFS file system VFS magic number */
#define UBIFS_SUPER_MAGIC 0x24051905 #define UBIFS_SUPER_MAGIC 0x24051905
...@@ -1209,6 +1218,7 @@ struct ubifs_debug_info; ...@@ -1209,6 +1218,7 @@ struct ubifs_debug_info;
* @need_recovery: %1 if the file-system needs recovery * @need_recovery: %1 if the file-system needs recovery
* @replaying: %1 during journal replay * @replaying: %1 during journal replay
* @mounting: %1 while mounting * @mounting: %1 while mounting
* @probing: %1 while attempting to mount if MS_SILENT mount flag is set
* @remounting_rw: %1 while re-mounting from R/O mode to R/W mode * @remounting_rw: %1 while re-mounting from R/O mode to R/W mode
* @replay_list: temporary list used during journal replay * @replay_list: temporary list used during journal replay
* @replay_buds: list of buds to replay * @replay_buds: list of buds to replay
...@@ -1441,6 +1451,7 @@ struct ubifs_info { ...@@ -1441,6 +1451,7 @@ struct ubifs_info {
unsigned int replaying:1; unsigned int replaying:1;
unsigned int mounting:1; unsigned int mounting:1;
unsigned int remounting_rw:1; unsigned int remounting_rw:1;
unsigned int probing:1;
struct list_head replay_list; struct list_head replay_list;
struct list_head replay_buds; struct list_head replay_buds;
unsigned long long cs_sqnum; unsigned long long cs_sqnum;
......
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