Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'for-linus-5.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs

Pull JFFS2, UBI and UBIFS updates from Richard Weinberger:
"JFFS2:
- Fix for a deadlock in jffs2_write_begin()

UBI:
- Fixes in comments

UBIFS:
- Expose error counters in sysfs
- Many bugfixes found by Hulk Robot and others"

* tag 'for-linus-5.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs:
jffs2: GC deadlock reading a page that is used in jffs2_write_begin()
ubifs: read-only if LEB may always be taken in ubifs_garbage_collect
ubifs: fix double return leb in ubifs_garbage_collect
ubifs: fix slab-out-of-bounds in ubifs_change_lp
ubifs: fix snprintf() length check
ubifs: Document sysfs nodes
ubifs: Export filesystem error counters
ubifs: Error path in ubifs_remount_rw() seems to wrongly free write buffers
ubifs: Make use of the helper macro kthread_run()
ubi: Fix a mistake in comment
ubifs: Fix spelling mistakes

+309 -28
+35
Documentation/ABI/testing/sysfs-fs-ubifs
··· 1 + What: /sys/fs/ubifsX_Y/error_magic 2 + Date: October 2021 3 + KernelVersion: 5.16 4 + Contact: linux-mtd@lists.infradead.org 5 + Description: 6 + Exposes magic errors: every node starts with a magic number. 7 + 8 + This counter keeps track of the number of accesses of nodes 9 + with a corrupted magic number. 10 + 11 + The counter is reset to 0 with a remount. 12 + 13 + What: /sys/fs/ubifsX_Y/error_node 14 + Date: October 2021 15 + KernelVersion: 5.16 16 + Contact: linux-mtd@lists.infradead.org 17 + Description: 18 + Exposes node errors. Every node embeds its type. 19 + 20 + This counter keeps track of the number of accesses of nodes 21 + with a corrupted node type. 22 + 23 + The counter is reset to 0 with a remount. 24 + 25 + What: /sys/fs/ubifsX_Y/error_crc 26 + Date: October 2021 27 + KernelVersion: 5.16 28 + Contact: linux-mtd@lists.infradead.org 29 + Description: 30 + Exposes crc errors: every node embeds a crc checksum. 31 + 32 + This counter keeps track of the number of accesses of nodes 33 + with a bad crc checksum. 34 + 35 + The counter is reset to 0 with a remount.
+1
MAINTAINERS
··· 19603 19603 W: http://www.linux-mtd.infradead.org/doc/ubifs.html 19604 19604 T: git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git next 19605 19605 T: git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git fixes 19606 + F: Documentation/ABI/testing/sysfs-fs-ubifs 19606 19607 F: Documentation/filesystems/ubifs-authentication.rst 19607 19608 F: Documentation/filesystems/ubifs.rst 19608 19609 F: fs/ubifs/
+1 -1
drivers/mtd/ubi/debug.c
··· 562 562 } 563 563 564 564 /** 565 - * dbg_debug_exit_dev - free all debugfs files corresponding to device @ubi 565 + * ubi_debugfs_exit_dev - free all debugfs files corresponding to device @ubi 566 566 * @ubi: UBI device description object 567 567 */ 568 568 void ubi_debugfs_exit_dev(struct ubi_device *ubi)
+25 -15
fs/jffs2/file.c
··· 136 136 struct page *pg; 137 137 struct inode *inode = mapping->host; 138 138 struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 139 + struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 139 140 pgoff_t index = pos >> PAGE_SHIFT; 140 141 uint32_t pageofs = index << PAGE_SHIFT; 141 142 int ret = 0; 142 - 143 - pg = grab_cache_page_write_begin(mapping, index, flags); 144 - if (!pg) 145 - return -ENOMEM; 146 - *pagep = pg; 147 143 148 144 jffs2_dbg(1, "%s()\n", __func__); 149 145 150 146 if (pageofs > inode->i_size) { 151 147 /* Make new hole frag from old EOF to new page */ 152 - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 153 148 struct jffs2_raw_inode ri; 154 149 struct jffs2_full_dnode *fn; 155 150 uint32_t alloc_len; ··· 155 160 ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, 156 161 ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); 157 162 if (ret) 158 - goto out_page; 163 + goto out_err; 159 164 160 165 mutex_lock(&f->sem); 161 166 memset(&ri, 0, sizeof(ri)); ··· 185 190 ret = PTR_ERR(fn); 186 191 jffs2_complete_reservation(c); 187 192 mutex_unlock(&f->sem); 188 - goto out_page; 193 + goto out_err; 189 194 } 190 195 ret = jffs2_add_full_dnode_to_inode(c, f, fn); 191 196 if (f->metadata) { ··· 200 205 jffs2_free_full_dnode(fn); 201 206 jffs2_complete_reservation(c); 202 207 mutex_unlock(&f->sem); 203 - goto out_page; 208 + goto out_err; 204 209 } 205 210 jffs2_complete_reservation(c); 206 211 inode->i_size = pageofs; 207 212 mutex_unlock(&f->sem); 208 213 } 214 + 215 + /* 216 + * While getting a page and reading data in, lock c->alloc_sem until 217 + * the page is Uptodate. Otherwise GC task may attempt to read the same 218 + * page in read_cache_page(), which causes a deadlock. 219 + */ 220 + mutex_lock(&c->alloc_sem); 221 + pg = grab_cache_page_write_begin(mapping, index, flags); 222 + if (!pg) { 223 + ret = -ENOMEM; 224 + goto release_sem; 225 + } 226 + *pagep = pg; 209 227 210 228 /* 211 229 * Read in the page if it wasn't already present. Cannot optimize away ··· 229 221 mutex_lock(&f->sem); 230 222 ret = jffs2_do_readpage_nolock(inode, pg); 231 223 mutex_unlock(&f->sem); 232 - if (ret) 233 - goto out_page; 224 + if (ret) { 225 + unlock_page(pg); 226 + put_page(pg); 227 + goto release_sem; 228 + } 234 229 } 235 230 jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags); 236 - return ret; 237 231 238 - out_page: 239 - unlock_page(pg); 240 - put_page(pg); 232 + release_sem: 233 + mutex_unlock(&c->alloc_sem); 234 + out_err: 241 235 return ret; 242 236 } 243 237
+1 -1
fs/ubifs/Makefile
··· 5 5 ubifs-y += tnc.o master.o scan.o replay.o log.o commit.o gc.o orphan.o 6 6 ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o 7 7 ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o debug.o 8 - ubifs-y += misc.o 8 + ubifs-y += misc.o sysfs.o 9 9 ubifs-$(CONFIG_FS_ENCRYPTION) += crypto.o 10 10 ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o 11 11 ubifs-$(CONFIG_UBIFS_FS_AUTHENTICATION) += auth.o
+2 -2
fs/ubifs/dir.c
··· 1207 1207 * @inode1: first inode 1208 1208 * @inode2: second inode 1209 1209 * @inode3: third inode 1210 - * @inode4: fouth inode 1210 + * @inode4: fourth inode 1211 1211 * 1212 1212 * This function is used for 'ubifs_rename()' and @inode1 may be the same as 1213 1213 * @inode2 whereas @inode3 and @inode4 may be %NULL. ··· 1233 1233 * @inode1: first inode 1234 1234 * @inode2: second inode 1235 1235 * @inode3: third inode 1236 - * @inode4: fouth inode 1236 + * @inode4: fourth inode 1237 1237 */ 1238 1238 static void unlock_4_inodes(struct inode *inode1, struct inode *inode2, 1239 1239 struct inode *inode3, struct inode *inode4)
+17 -2
fs/ubifs/gc.c
··· 692 692 for (i = 0; ; i++) { 693 693 int space_before, space_after; 694 694 695 + /* Maybe continue after find and break before find */ 696 + lp.lnum = -1; 697 + 695 698 cond_resched(); 696 699 697 700 /* Give the commit an opportunity to run */ ··· 756 753 * caller instead of the original '-EAGAIN'. 757 754 */ 758 755 err = ubifs_return_leb(c, lp.lnum); 759 - if (err) 756 + if (err) { 760 757 ret = err; 758 + /* 759 + * An LEB may always be "taken", 760 + * so setting ubifs to read-only, 761 + * and then executing sync wbuf will 762 + * return -EROFS and enter the "out" 763 + * error branch. 764 + */ 765 + ubifs_ro_mode(c, ret); 766 + } 767 + /* Maybe double return LEB if goto out */ 768 + lp.lnum = -1; 761 769 break; 762 770 } 763 771 goto out; ··· 857 843 ubifs_wbuf_sync_nolock(wbuf); 858 844 ubifs_ro_mode(c, ret); 859 845 mutex_unlock(&wbuf->io_mutex); 860 - ubifs_return_leb(c, lp.lnum); 846 + if (lp.lnum != -1) 847 + ubifs_return_leb(c, lp.lnum); 861 848 return ret; 862 849 } 863 850
+21
fs/ubifs/io.c
··· 194 194 return err; 195 195 } 196 196 197 + static void record_magic_error(struct ubifs_stats_info *stats) 198 + { 199 + if (stats) 200 + stats->magic_errors++; 201 + } 202 + 203 + static void record_node_error(struct ubifs_stats_info *stats) 204 + { 205 + if (stats) 206 + stats->node_errors++; 207 + } 208 + 209 + static void record_crc_error(struct ubifs_stats_info *stats) 210 + { 211 + if (stats) 212 + stats->crc_errors++; 213 + } 214 + 197 215 /** 198 216 * ubifs_check_node - check node. 199 217 * @c: UBIFS file-system description object ··· 256 238 if (!quiet) 257 239 ubifs_err(c, "bad magic %#08x, expected %#08x", 258 240 magic, UBIFS_NODE_MAGIC); 241 + record_magic_error(c->stats); 259 242 err = -EUCLEAN; 260 243 goto out; 261 244 } ··· 265 246 if (type < 0 || type >= UBIFS_NODE_TYPES_CNT) { 266 247 if (!quiet) 267 248 ubifs_err(c, "bad node type %d", type); 249 + record_node_error(c->stats); 268 250 goto out; 269 251 } 270 252 ··· 290 270 if (!quiet) 291 271 ubifs_err(c, "bad CRC: calculated %#08x, read %#08x", 292 272 crc, node_crc); 273 + record_crc_error(c->stats); 293 274 err = -EUCLEAN; 294 275 goto out; 295 276 }
+1 -1
fs/ubifs/replay.c
··· 106 106 * property values should be @lp->free == @c->leb_size and 107 107 * @lp->dirty == 0, but that is not the case. The reason is that 108 108 * the LEB had been garbage collected before it became the bud, 109 - * and there was not commit inbetween. The garbage collector 109 + * and there was no commit in between. The garbage collector 110 110 * resets the free and dirty space without recording it 111 111 * anywhere except lprops, so if there was no commit then 112 112 * lprops does not have that information.
+17 -6
fs/ubifs/super.c
··· 1264 1264 if (err) 1265 1265 return err; 1266 1266 1267 + err = ubifs_sysfs_register(c); 1268 + if (err) 1269 + goto out_debugging; 1270 + 1267 1271 err = check_volume_empty(c); 1268 1272 if (err) 1269 1273 goto out_free; ··· 1371 1367 sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id); 1372 1368 if (!c->ro_mount) { 1373 1369 /* Create background thread */ 1374 - c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name); 1370 + c->bgt = kthread_run(ubifs_bg_thread, c, "%s", c->bgt_name); 1375 1371 if (IS_ERR(c->bgt)) { 1376 1372 err = PTR_ERR(c->bgt); 1377 1373 c->bgt = NULL; ··· 1379 1375 c->bgt_name, err); 1380 1376 goto out_wbufs; 1381 1377 } 1382 - wake_up_process(c->bgt); 1383 1378 } 1384 1379 1385 1380 err = ubifs_read_master(c); ··· 1644 1641 vfree(c->sbuf); 1645 1642 kfree(c->bottom_up_buf); 1646 1643 kfree(c->sup_node); 1644 + ubifs_sysfs_unregister(c); 1645 + out_debugging: 1647 1646 ubifs_debugging_exit(c); 1648 1647 return err; 1649 1648 } ··· 1689 1684 kfree(c->bottom_up_buf); 1690 1685 kfree(c->sup_node); 1691 1686 ubifs_debugging_exit(c); 1687 + ubifs_sysfs_unregister(c); 1692 1688 } 1693 1689 1694 1690 /** ··· 1786 1780 goto out; 1787 1781 1788 1782 /* Create background thread */ 1789 - c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name); 1783 + c->bgt = kthread_run(ubifs_bg_thread, c, "%s", c->bgt_name); 1790 1784 if (IS_ERR(c->bgt)) { 1791 1785 err = PTR_ERR(c->bgt); 1792 1786 c->bgt = NULL; ··· 1794 1788 c->bgt_name, err); 1795 1789 goto out; 1796 1790 } 1797 - wake_up_process(c->bgt); 1798 1791 1799 1792 c->orph_buf = vmalloc(c->leb_size); 1800 1793 if (!c->orph_buf) { ··· 1858 1853 kthread_stop(c->bgt); 1859 1854 c->bgt = NULL; 1860 1855 } 1861 - free_wbufs(c); 1862 1856 kfree(c->write_reserve_buf); 1863 1857 c->write_reserve_buf = NULL; 1864 1858 vfree(c->ileb_buf); ··· 2440 2436 2441 2437 dbg_debugfs_init(); 2442 2438 2439 + err = ubifs_sysfs_init(); 2440 + if (err) 2441 + goto out_dbg; 2442 + 2443 2443 err = register_filesystem(&ubifs_fs_type); 2444 2444 if (err) { 2445 2445 pr_err("UBIFS error (pid %d): cannot register file system, error %d", 2446 2446 current->pid, err); 2447 - goto out_dbg; 2447 + goto out_sysfs; 2448 2448 } 2449 2449 return 0; 2450 2450 2451 + out_sysfs: 2452 + ubifs_sysfs_exit(); 2451 2453 out_dbg: 2452 2454 dbg_debugfs_exit(); 2453 2455 ubifs_compressors_exit(); ··· 2472 2462 WARN_ON(atomic_long_read(&ubifs_clean_zn_cnt) != 0); 2473 2463 2474 2464 dbg_debugfs_exit(); 2465 + ubifs_sysfs_exit(); 2475 2466 ubifs_compressors_exit(); 2476 2467 unregister_shrinker(&ubifs_shrinker_info); 2477 2468
+153
fs/ubifs/sysfs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * This file is part of UBIFS. 4 + * 5 + * Copyright (C) 2021 Cisco Systems 6 + * 7 + * Author: Stefan Schaeckeler 8 + */ 9 + 10 + 11 + #include <linux/fs.h> 12 + #include "ubifs.h" 13 + 14 + enum attr_id_t { 15 + attr_errors_magic, 16 + attr_errors_node, 17 + attr_errors_crc, 18 + }; 19 + 20 + struct ubifs_attr { 21 + struct attribute attr; 22 + enum attr_id_t attr_id; 23 + }; 24 + 25 + #define UBIFS_ATTR(_name, _mode, _id) \ 26 + static struct ubifs_attr ubifs_attr_##_name = { \ 27 + .attr = {.name = __stringify(_name), .mode = _mode }, \ 28 + .attr_id = attr_##_id, \ 29 + } 30 + 31 + #define UBIFS_ATTR_FUNC(_name, _mode) UBIFS_ATTR(_name, _mode, _name) 32 + 33 + UBIFS_ATTR_FUNC(errors_magic, 0444); 34 + UBIFS_ATTR_FUNC(errors_crc, 0444); 35 + UBIFS_ATTR_FUNC(errors_node, 0444); 36 + 37 + #define ATTR_LIST(name) (&ubifs_attr_##name.attr) 38 + 39 + static struct attribute *ubifs_attrs[] = { 40 + ATTR_LIST(errors_magic), 41 + ATTR_LIST(errors_node), 42 + ATTR_LIST(errors_crc), 43 + NULL, 44 + }; 45 + 46 + static ssize_t ubifs_attr_show(struct kobject *kobj, 47 + struct attribute *attr, char *buf) 48 + { 49 + struct ubifs_info *sbi = container_of(kobj, struct ubifs_info, 50 + kobj); 51 + 52 + struct ubifs_attr *a = container_of(attr, struct ubifs_attr, attr); 53 + 54 + switch (a->attr_id) { 55 + case attr_errors_magic: 56 + return sysfs_emit(buf, "%u\n", sbi->stats->magic_errors); 57 + case attr_errors_node: 58 + return sysfs_emit(buf, "%u\n", sbi->stats->node_errors); 59 + case attr_errors_crc: 60 + return sysfs_emit(buf, "%u\n", sbi->stats->crc_errors); 61 + } 62 + return 0; 63 + }; 64 + 65 + static void ubifs_sb_release(struct kobject *kobj) 66 + { 67 + struct ubifs_info *c = container_of(kobj, struct ubifs_info, kobj); 68 + 69 + complete(&c->kobj_unregister); 70 + } 71 + 72 + static const struct sysfs_ops ubifs_attr_ops = { 73 + .show = ubifs_attr_show, 74 + }; 75 + 76 + static struct kobj_type ubifs_sb_ktype = { 77 + .default_attrs = ubifs_attrs, 78 + .sysfs_ops = &ubifs_attr_ops, 79 + .release = ubifs_sb_release, 80 + }; 81 + 82 + static struct kobj_type ubifs_ktype = { 83 + .sysfs_ops = &ubifs_attr_ops, 84 + }; 85 + 86 + static struct kset ubifs_kset = { 87 + .kobj = {.ktype = &ubifs_ktype}, 88 + }; 89 + 90 + int ubifs_sysfs_register(struct ubifs_info *c) 91 + { 92 + int ret, n; 93 + char dfs_dir_name[UBIFS_DFS_DIR_LEN+1]; 94 + 95 + c->stats = kzalloc(sizeof(struct ubifs_stats_info), GFP_KERNEL); 96 + if (!c->stats) { 97 + ret = -ENOMEM; 98 + goto out_last; 99 + } 100 + n = snprintf(dfs_dir_name, UBIFS_DFS_DIR_LEN + 1, UBIFS_DFS_DIR_NAME, 101 + c->vi.ubi_num, c->vi.vol_id); 102 + 103 + if (n > UBIFS_DFS_DIR_LEN) { 104 + /* The array size is too small */ 105 + ret = -EINVAL; 106 + goto out_free; 107 + } 108 + 109 + c->kobj.kset = &ubifs_kset; 110 + init_completion(&c->kobj_unregister); 111 + 112 + ret = kobject_init_and_add(&c->kobj, &ubifs_sb_ktype, NULL, 113 + "%s", dfs_dir_name); 114 + if (ret) 115 + goto out_put; 116 + 117 + return 0; 118 + 119 + out_put: 120 + kobject_put(&c->kobj); 121 + wait_for_completion(&c->kobj_unregister); 122 + out_free: 123 + kfree(c->stats); 124 + out_last: 125 + ubifs_err(c, "cannot create sysfs entry for ubifs%d_%d, error %d\n", 126 + c->vi.ubi_num, c->vi.vol_id, ret); 127 + return ret; 128 + } 129 + 130 + void ubifs_sysfs_unregister(struct ubifs_info *c) 131 + { 132 + kobject_del(&c->kobj); 133 + kobject_put(&c->kobj); 134 + wait_for_completion(&c->kobj_unregister); 135 + 136 + kfree(c->stats); 137 + } 138 + 139 + int __init ubifs_sysfs_init(void) 140 + { 141 + int ret; 142 + 143 + kobject_set_name(&ubifs_kset.kobj, "ubifs"); 144 + ubifs_kset.kobj.parent = fs_kobj; 145 + ret = kset_register(&ubifs_kset); 146 + 147 + return ret; 148 + } 149 + 150 + void ubifs_sysfs_exit(void) 151 + { 152 + kset_unregister(&ubifs_kset); 153 + }
+35
fs/ubifs/ubifs.h
··· 27 27 #include <linux/security.h> 28 28 #include <linux/xattr.h> 29 29 #include <linux/random.h> 30 + #include <linux/sysfs.h> 31 + #include <linux/completion.h> 30 32 #include <crypto/hash_info.h> 31 33 #include <crypto/hash.h> 32 34 #include <crypto/algapi.h> ··· 156 154 #define UBIFS_HASH_ARR_SZ 0 157 155 #define UBIFS_HMAC_ARR_SZ 0 158 156 #endif 157 + 158 + /* 159 + * The UBIFS sysfs directory name pattern and maximum name length (3 for "ubi" 160 + * + 1 for "_" and plus 2x2 for 2 UBI numbers and 1 for the trailing zero byte. 161 + */ 162 + #define UBIFS_DFS_DIR_NAME "ubi%d_%d" 163 + #define UBIFS_DFS_DIR_LEN (3 + 1 + 2*2 + 1) 159 164 160 165 /* 161 166 * Lockdep classes for UBIFS inode @ui_mutex. ··· 999 990 int dent_budget; 1000 991 }; 1001 992 993 + /** 994 + * ubifs_stats_info - per-FS statistics information. 995 + * @magic_errors: number of bad magic numbers (will be reset with a new mount). 996 + * @node_errors: number of bad nodes (will be reset with a new mount). 997 + * @crc_errors: number of bad crcs (will be reset with a new mount). 998 + */ 999 + struct ubifs_stats_info { 1000 + unsigned int magic_errors; 1001 + unsigned int node_errors; 1002 + unsigned int crc_errors; 1003 + }; 1004 + 1002 1005 struct ubifs_debug_info; 1003 1006 1004 1007 /** ··· 1272 1251 * @mount_opts: UBIFS-specific mount options 1273 1252 * 1274 1253 * @dbg: debugging-related information 1254 + * @stats: statistics exported over sysfs 1255 + * 1256 + * @kobj: kobject for /sys/fs/ubifs/ 1257 + * @kobj_unregister: completion to unregister sysfs kobject 1275 1258 */ 1276 1259 struct ubifs_info { 1277 1260 struct super_block *vfs_sb; ··· 1310 1285 int cmt_state; 1311 1286 spinlock_t cs_lock; 1312 1287 wait_queue_head_t cmt_wq; 1288 + 1289 + struct kobject kobj; 1290 + struct completion kobj_unregister; 1313 1291 1314 1292 unsigned int big_lpt:1; 1315 1293 unsigned int space_fixup:1; ··· 1521 1493 struct ubifs_mount_opts mount_opts; 1522 1494 1523 1495 struct ubifs_debug_info *dbg; 1496 + struct ubifs_stats_info *stats; 1524 1497 }; 1525 1498 1526 1499 extern struct list_head ubifs_infos; ··· 2100 2071 void *out_buf, int *out_len, int *compr_type); 2101 2072 int ubifs_decompress(const struct ubifs_info *c, const void *buf, int len, 2102 2073 void *out, int *out_len, int compr_type); 2074 + 2075 + /* sysfs.c */ 2076 + int ubifs_sysfs_init(void); 2077 + void ubifs_sysfs_exit(void); 2078 + int ubifs_sysfs_register(struct ubifs_info *c); 2079 + void ubifs_sysfs_unregister(struct ubifs_info *c); 2103 2080 2104 2081 #include "debug.h" 2105 2082 #include "misc.h"