diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-10 11:55:46 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-10 11:55:46 -0400 |
| commit | d53b47c08d8fda1892f47393de8eeab4e34b3188 (patch) | |
| tree | 717911fc55a24ad186b62890843e6125fe5907a1 | |
| parent | a3c54931199565930d6d84f4c3456f6440aefd41 (diff) | |
| parent | 380347e9ca76828ee9bac63cfc338ca99cdee4f3 (diff) | |
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
| -rw-r--r-- | drivers/mtd/ubi/block.c | 4 | ||||
| -rw-r--r-- | drivers/mtd/ubi/cdev.c | 2 | ||||
| -rw-r--r-- | drivers/mtd/ubi/fastmap.c | 4 | ||||
| -rw-r--r-- | fs/ubifs/budget.c | 1 | ||||
| -rw-r--r-- | fs/ubifs/debug.c | 4 | ||||
| -rw-r--r-- | fs/ubifs/file.c | 6 | ||||
| -rw-r--r-- | fs/ubifs/io.c | 18 | ||||
| -rw-r--r-- | fs/ubifs/shrinker.c | 1 | ||||
| -rw-r--r-- | fs/ubifs/super.c | 5 | ||||
| -rw-r--r-- | fs/ubifs/tnc.c | 5 | ||||
| -rw-r--r-- | fs/ubifs/ubifs.h | 11 |
11 files changed, 41 insertions, 20 deletions
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c index 20a667c95da4..8457df7ec5af 100644 --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c | |||
| @@ -432,8 +432,10 @@ int ubiblock_create(struct ubi_volume_info *vi) | |||
| 432 | * Rembember workqueues are cheap, they're not threads. | 432 | * Rembember workqueues are cheap, they're not threads. |
| 433 | */ | 433 | */ |
| 434 | dev->wq = alloc_workqueue("%s", 0, 0, gd->disk_name); | 434 | dev->wq = alloc_workqueue("%s", 0, 0, gd->disk_name); |
| 435 | if (!dev->wq) | 435 | if (!dev->wq) { |
| 436 | ret = -ENOMEM; | ||
| 436 | goto out_free_queue; | 437 | goto out_free_queue; |
| 438 | } | ||
| 437 | INIT_WORK(&dev->work, ubiblock_do_work); | 439 | INIT_WORK(&dev->work, ubiblock_do_work); |
| 438 | 440 | ||
| 439 | mutex_lock(&devices_mutex); | 441 | mutex_lock(&devices_mutex); |
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index f54562a5998e..7646220ca6e2 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c | |||
| @@ -731,7 +731,7 @@ static int rename_volumes(struct ubi_device *ubi, | |||
| 731 | goto out_free; | 731 | goto out_free; |
| 732 | } | 732 | } |
| 733 | 733 | ||
| 734 | re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE); | 734 | re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_READWRITE); |
| 735 | if (IS_ERR(re->desc)) { | 735 | if (IS_ERR(re->desc)) { |
| 736 | err = PTR_ERR(re->desc); | 736 | err = PTR_ERR(re->desc); |
| 737 | ubi_err("cannot open volume %d, error %d", vol_id, err); | 737 | ubi_err("cannot open volume %d, error %d", vol_id, err); |
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index c5dad652614d..b04e7d059888 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c | |||
| @@ -125,9 +125,9 @@ static struct ubi_ainf_volume *add_vol(struct ubi_attach_info *ai, int vol_id, | |||
| 125 | parent = *p; | 125 | parent = *p; |
| 126 | av = rb_entry(parent, struct ubi_ainf_volume, rb); | 126 | av = rb_entry(parent, struct ubi_ainf_volume, rb); |
| 127 | 127 | ||
| 128 | if (vol_id > av->vol_id) | 128 | if (vol_id < av->vol_id) |
| 129 | p = &(*p)->rb_left; | 129 | p = &(*p)->rb_left; |
| 130 | else if (vol_id > av->vol_id) | 130 | else |
| 131 | p = &(*p)->rb_right; | 131 | p = &(*p)->rb_right; |
| 132 | } | 132 | } |
| 133 | 133 | ||
diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index e8e01d74dc05..eb997e9c4ab0 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c | |||
| @@ -437,7 +437,6 @@ static int calc_dd_growth(const struct ubifs_info *c, | |||
| 437 | */ | 437 | */ |
| 438 | int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req) | 438 | int ubifs_budget_space(struct ubifs_info *c, struct ubifs_budget_req *req) |
| 439 | { | 439 | { |
| 440 | int uninitialized_var(cmt_retries), uninitialized_var(wb_retries); | ||
| 441 | int err, idx_growth, data_growth, dd_growth, retried = 0; | 440 | int err, idx_growth, data_growth, dd_growth, retried = 0; |
| 442 | 441 | ||
| 443 | ubifs_assert(req->new_page <= 1); | 442 | ubifs_assert(req->new_page <= 1); |
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 5157b866a853..177b0152fef4 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c | |||
| @@ -745,8 +745,10 @@ void ubifs_dump_lprops(struct ubifs_info *c) | |||
| 745 | 745 | ||
| 746 | for (lnum = c->main_first; lnum < c->leb_cnt; lnum++) { | 746 | for (lnum = c->main_first; lnum < c->leb_cnt; lnum++) { |
| 747 | err = ubifs_read_one_lp(c, lnum, &lp); | 747 | err = ubifs_read_one_lp(c, lnum, &lp); |
| 748 | if (err) | 748 | if (err) { |
| 749 | ubifs_err("cannot read lprops for LEB %d", lnum); | 749 | ubifs_err("cannot read lprops for LEB %d", lnum); |
| 750 | continue; | ||
| 751 | } | ||
| 750 | 752 | ||
| 751 | ubifs_dump_lprop(c, &lp); | 753 | ubifs_dump_lprop(c, &lp); |
| 752 | } | 754 | } |
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 4f34dbae823d..0ab7f7dfb98b 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c | |||
| @@ -903,8 +903,9 @@ static int do_writepage(struct page *page, int len) | |||
| 903 | struct ubifs_info *c = inode->i_sb->s_fs_info; | 903 | struct ubifs_info *c = inode->i_sb->s_fs_info; |
| 904 | 904 | ||
| 905 | #ifdef UBIFS_DEBUG | 905 | #ifdef UBIFS_DEBUG |
| 906 | struct ubifs_inode *ui = ubifs_inode(inode); | ||
| 906 | spin_lock(&ui->ui_lock); | 907 | spin_lock(&ui->ui_lock); |
| 907 | ubifs_assert(page->index <= ui->synced_i_size << PAGE_CACHE_SIZE); | 908 | ubifs_assert(page->index <= ui->synced_i_size >> PAGE_CACHE_SHIFT); |
| 908 | spin_unlock(&ui->ui_lock); | 909 | spin_unlock(&ui->ui_lock); |
| 909 | #endif | 910 | #endif |
| 910 | 911 | ||
| @@ -1525,8 +1526,7 @@ static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, | |||
| 1525 | } | 1526 | } |
| 1526 | 1527 | ||
| 1527 | wait_for_stable_page(page); | 1528 | wait_for_stable_page(page); |
| 1528 | unlock_page(page); | 1529 | return VM_FAULT_LOCKED; |
| 1529 | return 0; | ||
| 1530 | 1530 | ||
| 1531 | out_unlock: | 1531 | out_unlock: |
| 1532 | unlock_page(page); | 1532 | unlock_page(page); |
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index e18b9889a51b..2290d5866725 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c | |||
| @@ -988,30 +988,32 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len, | |||
| 988 | return err; | 988 | return err; |
| 989 | 989 | ||
| 990 | if (type != ch->node_type) { | 990 | if (type != ch->node_type) { |
| 991 | ubifs_err("bad node type (%d but expected %d)", | 991 | ubifs_errc(c, "bad node type (%d but expected %d)", |
| 992 | ch->node_type, type); | 992 | ch->node_type, type); |
| 993 | goto out; | 993 | goto out; |
| 994 | } | 994 | } |
| 995 | 995 | ||
| 996 | err = ubifs_check_node(c, buf, lnum, offs, 0, 0); | 996 | err = ubifs_check_node(c, buf, lnum, offs, 0, 0); |
| 997 | if (err) { | 997 | if (err) { |
| 998 | ubifs_err("expected node type %d", type); | 998 | ubifs_errc(c, "expected node type %d", type); |
| 999 | return err; | 999 | return err; |
| 1000 | } | 1000 | } |
| 1001 | 1001 | ||
| 1002 | l = le32_to_cpu(ch->len); | 1002 | l = le32_to_cpu(ch->len); |
| 1003 | if (l != len) { | 1003 | if (l != len) { |
| 1004 | ubifs_err("bad node length %d, expected %d", l, len); | 1004 | ubifs_errc(c, "bad node length %d, expected %d", l, len); |
| 1005 | goto out; | 1005 | goto out; |
| 1006 | } | 1006 | } |
| 1007 | 1007 | ||
| 1008 | return 0; | 1008 | return 0; |
| 1009 | 1009 | ||
| 1010 | out: | 1010 | out: |
| 1011 | ubifs_err("bad node at LEB %d:%d, LEB mapping status %d", lnum, offs, | 1011 | ubifs_errc(c, "bad node at LEB %d:%d, LEB mapping status %d", lnum, |
| 1012 | ubi_is_mapped(c->ubi, lnum)); | 1012 | offs, ubi_is_mapped(c->ubi, lnum)); |
| 1013 | ubifs_dump_node(c, buf); | 1013 | if (!c->probing) { |
| 1014 | dump_stack(); | 1014 | ubifs_dump_node(c, buf); |
| 1015 | dump_stack(); | ||
| 1016 | } | ||
| 1015 | return -EINVAL; | 1017 | return -EINVAL; |
| 1016 | } | 1018 | } |
| 1017 | 1019 | ||
diff --git a/fs/ubifs/shrinker.c b/fs/ubifs/shrinker.c index f35135e28e96..9a9fb94a41c6 100644 --- a/fs/ubifs/shrinker.c +++ b/fs/ubifs/shrinker.c | |||
| @@ -128,7 +128,6 @@ static int shrink_tnc(struct ubifs_info *c, int nr, int age, int *contention) | |||
| 128 | freed = ubifs_destroy_tnc_subtree(znode); | 128 | freed = ubifs_destroy_tnc_subtree(znode); |
| 129 | atomic_long_sub(freed, &ubifs_clean_zn_cnt); | 129 | atomic_long_sub(freed, &ubifs_clean_zn_cnt); |
| 130 | atomic_long_sub(freed, &c->clean_zn_cnt); | 130 | atomic_long_sub(freed, &c->clean_zn_cnt); |
| 131 | ubifs_assert(atomic_long_read(&c->clean_zn_cnt) >= 0); | ||
| 132 | total_freed += freed; | 131 | total_freed += freed; |
| 133 | znode = zprev; | 132 | znode = zprev; |
| 134 | } | 133 | } |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index a81c7b556896..3904c8574ef9 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
| @@ -1149,6 +1149,9 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1149 | size_t sz; | 1149 | size_t sz; |
| 1150 | 1150 | ||
| 1151 | c->ro_mount = !!(c->vfs_sb->s_flags & MS_RDONLY); | 1151 | c->ro_mount = !!(c->vfs_sb->s_flags & MS_RDONLY); |
| 1152 | /* Suppress error messages while probing if MS_SILENT is set */ | ||
| 1153 | c->probing = !!(c->vfs_sb->s_flags & MS_SILENT); | ||
| 1154 | |||
| 1152 | err = init_constants_early(c); | 1155 | err = init_constants_early(c); |
| 1153 | if (err) | 1156 | if (err) |
| 1154 | return err; | 1157 | return err; |
| @@ -1214,6 +1217,8 @@ static int mount_ubifs(struct ubifs_info *c) | |||
| 1214 | if (err) | 1217 | if (err) |
| 1215 | goto out_free; | 1218 | goto out_free; |
| 1216 | 1219 | ||
| 1220 | c->probing = 0; | ||
| 1221 | |||
| 1217 | /* | 1222 | /* |
| 1218 | * Make sure the compressor which is set as default in the superblock | 1223 | * Make sure the compressor which is set as default in the superblock |
| 1219 | * or overridden by mount options is actually compiled in. | 1224 | * or overridden by mount options is actually compiled in. |
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index 9083bc7ed4ae..8a40cf9c02d7 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c | |||
| @@ -2859,10 +2859,11 @@ void ubifs_tnc_close(struct ubifs_info *c) | |||
| 2859 | { | 2859 | { |
| 2860 | tnc_destroy_cnext(c); | 2860 | tnc_destroy_cnext(c); |
| 2861 | if (c->zroot.znode) { | 2861 | if (c->zroot.znode) { |
| 2862 | long n; | 2862 | long n, freed; |
| 2863 | 2863 | ||
| 2864 | ubifs_destroy_tnc_subtree(c->zroot.znode); | ||
| 2865 | n = atomic_long_read(&c->clean_zn_cnt); | 2864 | n = atomic_long_read(&c->clean_zn_cnt); |
| 2865 | freed = ubifs_destroy_tnc_subtree(c->zroot.znode); | ||
| 2866 | ubifs_assert(freed == n); | ||
| 2866 | atomic_long_sub(n, &ubifs_clean_zn_cnt); | 2867 | atomic_long_sub(n, &ubifs_clean_zn_cnt); |
| 2867 | } | 2868 | } |
| 2868 | kfree(c->gap_lebs); | 2869 | kfree(c->gap_lebs); |
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index e8c8cfe1435c..c1f71fe17cc0 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h | |||
| @@ -51,6 +51,15 @@ | |||
| 51 | #define ubifs_warn(fmt, ...) \ | 51 | #define ubifs_warn(fmt, ...) \ |
| 52 | pr_warn("UBIFS warning (pid %d): %s: " fmt "\n", \ | 52 | pr_warn("UBIFS warning (pid %d): %s: " fmt "\n", \ |
| 53 | current->pid, __func__, ##__VA_ARGS__) | 53 | current->pid, __func__, ##__VA_ARGS__) |
| 54 | /* | ||
| 55 | * A variant of 'ubifs_err()' which takes the UBIFS file-sytem description | ||
| 56 | * object as an argument. | ||
| 57 | */ | ||
| 58 | #define ubifs_errc(c, fmt, ...) \ | ||
| 59 | do { \ | ||
| 60 | if (!(c)->probing) \ | ||
| 61 | ubifs_err(fmt, ##__VA_ARGS__); \ | ||
| 62 | } while (0) | ||
| 54 | 63 | ||
| 55 | /* UBIFS file system VFS magic number */ | 64 | /* UBIFS file system VFS magic number */ |
| 56 | #define UBIFS_SUPER_MAGIC 0x24051905 | 65 | #define UBIFS_SUPER_MAGIC 0x24051905 |
| @@ -1209,6 +1218,7 @@ struct ubifs_debug_info; | |||
| 1209 | * @need_recovery: %1 if the file-system needs recovery | 1218 | * @need_recovery: %1 if the file-system needs recovery |
| 1210 | * @replaying: %1 during journal replay | 1219 | * @replaying: %1 during journal replay |
| 1211 | * @mounting: %1 while mounting | 1220 | * @mounting: %1 while mounting |
| 1221 | * @probing: %1 while attempting to mount if MS_SILENT mount flag is set | ||
| 1212 | * @remounting_rw: %1 while re-mounting from R/O mode to R/W mode | 1222 | * @remounting_rw: %1 while re-mounting from R/O mode to R/W mode |
| 1213 | * @replay_list: temporary list used during journal replay | 1223 | * @replay_list: temporary list used during journal replay |
| 1214 | * @replay_buds: list of buds to replay | 1224 | * @replay_buds: list of buds to replay |
| @@ -1441,6 +1451,7 @@ struct ubifs_info { | |||
| 1441 | unsigned int replaying:1; | 1451 | unsigned int replaying:1; |
| 1442 | unsigned int mounting:1; | 1452 | unsigned int mounting:1; |
| 1443 | unsigned int remounting_rw:1; | 1453 | unsigned int remounting_rw:1; |
| 1454 | unsigned int probing:1; | ||
| 1444 | struct list_head replay_list; | 1455 | struct list_head replay_list; |
| 1445 | struct list_head replay_buds; | 1456 | struct list_head replay_buds; |
| 1446 | unsigned long long cs_sqnum; | 1457 | unsigned long long cs_sqnum; |
