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.

UBIFS: switch self-check knobs to debugfs

UBIFS has many built-in self-check functions which can be enabled using the
debug_chks module parameter or the corresponding sysfs file
(/sys/module/ubifs/parameters/debug_chks). However, this is not flexible enough
because it is not per-filesystem. This patch moves this to debugfs interfaces.

We already have debugfs support, so this patch just adds more debugfs files.
While looking at debugfs support I've noticed that it is racy WRT file-system
unmount, and added a TODO entry for that. This problem has been there for long
time and it is quite standard debugfs PITA. The plan is to fix this later.

This patch is simple, but it is large because it changes many places where we
check if a particular type of checks is enabled or disabled.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>

authored by

Artem Bityutskiy and committed by
Artem Bityutskiy
81e79d38 8d7819b4

+159 -79
-26
Documentation/filesystems/ubifs.txt
··· 111 111 to UBI and mount volume "rootfs": 112 112 ubi.mtd=0 root=ubi0:rootfs rootfstype=ubifs 113 113 114 - 115 - Module Parameters for Debugging 116 - =============================== 117 - 118 - When UBIFS has been compiled with debugging enabled, there are 2 module 119 - parameters that are available to control aspects of testing and debugging. 120 - 121 - debug_chks Selects extra checks that UBIFS can do while running: 122 - 123 - Check Flag value 124 - 125 - General checks 1 126 - Check the index 2 127 - Check orphan area 8 128 - Check LEB properties (lprops) 32 129 - Check leaf nodes and inodes 64 130 - 131 - debug_tsts Selects a mode of testing, as follows: 132 - 133 - Test mode Flag value 134 - 135 - Failure mode for recovery testing 4 136 - 137 - For example, set debug_chks to 3 to enable general and TNC checks. 138 - 139 - 140 114 References 141 115 ========== 142 116
+123 -17
fs/ubifs/debug.c
··· 31 31 32 32 #include "ubifs.h" 33 33 #include <linux/module.h> 34 - #include <linux/moduleparam.h> 35 34 #include <linux/debugfs.h> 36 35 #include <linux/math64.h> 36 + #include <linux/uaccess.h> 37 37 38 38 #ifdef CONFIG_UBIFS_FS_DEBUG 39 39 ··· 41 41 42 42 static char dbg_key_buf0[128]; 43 43 static char dbg_key_buf1[128]; 44 - 45 - unsigned int ubifs_chk_flags; 46 - unsigned int ubifs_tst_flags; 47 - 48 - module_param_named(debug_chks, ubifs_chk_flags, uint, S_IRUGO | S_IWUSR); 49 - module_param_named(debug_tsts, ubifs_tst_flags, uint, S_IRUGO | S_IWUSR); 50 - 51 - MODULE_PARM_DESC(debug_chks, "Debug check flags"); 52 - MODULE_PARM_DESC(debug_tsts, "Debug special test flags"); 53 44 54 45 static const char *get_key_fmt(int fmt) 55 46 { ··· 2877 2886 return nonseekable_open(inode, file); 2878 2887 } 2879 2888 2880 - static ssize_t write_debugfs_file(struct file *file, const char __user *buf, 2881 - size_t count, loff_t *ppos) 2889 + static ssize_t dfs_file_read(struct file *file, char __user *u, size_t count, 2890 + loff_t *ppos) 2891 + { 2892 + struct dentry *dent = file->f_path.dentry; 2893 + struct ubifs_info *c = file->private_data; 2894 + struct ubifs_debug_info *d = c->dbg; 2895 + char buf[3]; 2896 + int val; 2897 + 2898 + if (dent == d->dfs_chk_gen) 2899 + val = d->chk_gen; 2900 + else if (dent == d->dfs_chk_index) 2901 + val = d->chk_index; 2902 + else if (dent == d->dfs_chk_orph) 2903 + val = d->chk_orph; 2904 + else if (dent == d->dfs_chk_lprops) 2905 + val = d->chk_lprops; 2906 + else if (dent == d->dfs_chk_fs) 2907 + val = d->chk_fs; 2908 + else if (dent == d->dfs_tst_rcvry) 2909 + val = d->tst_rcvry; 2910 + else 2911 + return -EINVAL; 2912 + 2913 + if (val) 2914 + buf[0] = '1'; 2915 + else 2916 + buf[0] = '0'; 2917 + buf[1] = '\n'; 2918 + buf[2] = 0x00; 2919 + 2920 + return simple_read_from_buffer(u, count, ppos, buf, 2); 2921 + } 2922 + 2923 + static ssize_t dfs_file_write(struct file *file, const char __user *u, 2924 + size_t count, loff_t *ppos) 2882 2925 { 2883 2926 struct ubifs_info *c = file->private_data; 2884 2927 struct ubifs_debug_info *d = c->dbg; 2928 + struct dentry *dent = file->f_path.dentry; 2929 + size_t buf_size; 2930 + char buf[8]; 2931 + int val; 2885 2932 2886 - if (file->f_path.dentry == d->dfs_dump_lprops) 2933 + /* 2934 + * FIXME: this is racy - the file-system might have already been 2935 + * unmounted and we'd oops in this case. 2936 + */ 2937 + if (file->f_path.dentry == d->dfs_dump_lprops) { 2887 2938 dbg_dump_lprops(c); 2888 - else if (file->f_path.dentry == d->dfs_dump_budg) 2939 + return count; 2940 + } 2941 + if (file->f_path.dentry == d->dfs_dump_budg) { 2889 2942 dbg_dump_budg(c, &c->bi); 2890 - else if (file->f_path.dentry == d->dfs_dump_tnc) { 2943 + return count; 2944 + } 2945 + if (file->f_path.dentry == d->dfs_dump_tnc) { 2891 2946 mutex_lock(&c->tnc_mutex); 2892 2947 dbg_dump_tnc(c); 2893 2948 mutex_unlock(&c->tnc_mutex); 2894 - } else 2949 + return count; 2950 + } 2951 + 2952 + buf_size = min_t(size_t, count, (sizeof(buf) - 1)); 2953 + if (copy_from_user(buf, u, buf_size)) 2954 + return -EFAULT; 2955 + 2956 + if (buf[0] == '1') 2957 + val = 1; 2958 + else if (buf[0] == '0') 2959 + val = 0; 2960 + else 2961 + return -EINVAL; 2962 + 2963 + if (dent == d->dfs_chk_gen) 2964 + d->chk_gen = val; 2965 + else if (dent == d->dfs_chk_index) 2966 + d->chk_index = val; 2967 + else if (dent == d->dfs_chk_orph) 2968 + d->chk_orph = val; 2969 + else if (dent == d->dfs_chk_lprops) 2970 + d->chk_lprops = val; 2971 + else if (dent == d->dfs_chk_fs) 2972 + d->chk_fs = val; 2973 + else if (dent == d->dfs_tst_rcvry) 2974 + d->tst_rcvry = val; 2975 + else 2895 2976 return -EINVAL; 2896 2977 2897 2978 return count; ··· 2971 2908 2972 2909 static const struct file_operations dfs_fops = { 2973 2910 .open = open_debugfs_file, 2974 - .write = write_debugfs_file, 2911 + .read = dfs_file_read, 2912 + .write = dfs_file_write, 2975 2913 .owner = THIS_MODULE, 2976 2914 .llseek = no_llseek, 2977 2915 }; ··· 3028 2964 if (IS_ERR_OR_NULL(dent)) 3029 2965 goto out_remove; 3030 2966 d->dfs_dump_tnc = dent; 2967 + 2968 + fname = "chk_general"; 2969 + dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c, 2970 + &dfs_fops); 2971 + if (IS_ERR_OR_NULL(dent)) 2972 + goto out_remove; 2973 + d->dfs_chk_gen = dent; 2974 + 2975 + fname = "chk_index"; 2976 + dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c, 2977 + &dfs_fops); 2978 + if (IS_ERR_OR_NULL(dent)) 2979 + goto out_remove; 2980 + d->dfs_chk_index = dent; 2981 + 2982 + fname = "chk_orphans"; 2983 + dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c, 2984 + &dfs_fops); 2985 + if (IS_ERR_OR_NULL(dent)) 2986 + goto out_remove; 2987 + d->dfs_chk_orph = dent; 2988 + 2989 + fname = "chk_lprops"; 2990 + dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c, 2991 + &dfs_fops); 2992 + if (IS_ERR_OR_NULL(dent)) 2993 + goto out_remove; 2994 + d->dfs_chk_lprops = dent; 2995 + 2996 + fname = "chk_fs"; 2997 + dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c, 2998 + &dfs_fops); 2999 + if (IS_ERR_OR_NULL(dent)) 3000 + goto out_remove; 3001 + d->dfs_chk_fs = dent; 3002 + 3003 + fname = "tst_recovery"; 3004 + dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c, 3005 + &dfs_fops); 3006 + if (IS_ERR_OR_NULL(dent)) 3007 + goto out_remove; 3008 + d->dfs_tst_rcvry = dent; 3031 3009 3032 3010 return 0; 3033 3011
+36 -36
fs/ubifs/debug.h
··· 43 43 * @old_zroot: old index root - used by 'dbg_check_old_index()' 44 44 * @old_zroot_level: old index root level - used by 'dbg_check_old_index()' 45 45 * @old_zroot_sqnum: old index root sqnum - used by 'dbg_check_old_index()' 46 + * 46 47 * @failure_mode: failure mode for recovery testing 47 48 * @fail_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls 48 49 * @fail_timeout: time in jiffies when delay of failure mode expires 49 50 * @fail_cnt: current number of calls to failure mode I/O functions 50 51 * @fail_cnt_max: number of calls by which to delay failure mode 52 + * 51 53 * @chk_lpt_sz: used by LPT tree size checker 52 54 * @chk_lpt_sz2: used by LPT tree size checker 53 55 * @chk_lpt_wastage: used by LPT tree size checker ··· 63 61 * @saved_free: saved amount of free space 64 62 * @saved_idx_gc_cnt: saved value of @c->idx_gc_cnt 65 63 * 64 + * @chk_gen: if general extra checks are enabled 65 + * @chk_index: if index xtra checks are enabled 66 + * @chk_orph: if orphans extra checks are enabled 67 + * @chk_lprops: if lprops extra checks are enabled 68 + * @chk_fs: if UBIFS contents extra checks are enabled 69 + * @tst_rcvry: if UBIFS recovery testing mode enabled 70 + * 66 71 * @dfs_dir_name: name of debugfs directory containing this file-system's files 67 72 * @dfs_dir: direntry object of the file-system debugfs directory 68 73 * @dfs_dump_lprops: "dump lprops" debugfs knob 69 74 * @dfs_dump_budg: "dump budgeting information" debugfs knob 70 75 * @dfs_dump_tnc: "dump TNC" debugfs knob 76 + * @dfs_chk_gen: debugfs knob to enable UBIFS general extra checks 77 + * @dfs_chk_index: debugfs knob to enable UBIFS index extra checks 78 + * @dfs_chk_orph: debugfs knob to enable UBIFS orphans extra checks 79 + * @dfs_chk_lprops: debugfs knob to enable UBIFS LEP properties extra checks 80 + * @dfs_chk_fs: debugfs knob to enable UBIFS contents extra checks 81 + * @dfs_tst_rcvry: debugfs knob to enable UBIFS recovery testing 71 82 */ 72 83 struct ubifs_debug_info { 73 84 struct ubifs_zbranch old_zroot; 74 85 int old_zroot_level; 75 86 unsigned long long old_zroot_sqnum; 87 + 76 88 int failure_mode; 77 89 int fail_delay; 78 90 unsigned long fail_timeout; 79 91 unsigned int fail_cnt; 80 92 unsigned int fail_cnt_max; 93 + 81 94 long long chk_lpt_sz; 82 95 long long chk_lpt_sz2; 83 96 long long chk_lpt_wastage; ··· 106 89 long long saved_free; 107 90 int saved_idx_gc_cnt; 108 91 92 + unsigned int chk_gen:1; 93 + unsigned int chk_index:1; 94 + unsigned int chk_orph:1; 95 + unsigned int chk_lprops:1; 96 + unsigned int chk_fs:1; 97 + unsigned int tst_rcvry:1; 98 + 109 99 char dfs_dir_name[UBIFS_DFS_DIR_LEN + 1]; 110 100 struct dentry *dfs_dir; 111 101 struct dentry *dfs_dump_lprops; 112 102 struct dentry *dfs_dump_budg; 113 103 struct dentry *dfs_dump_tnc; 104 + struct dentry *dfs_chk_gen; 105 + struct dentry *dfs_chk_index; 106 + struct dentry *dfs_chk_orph; 107 + struct dentry *dfs_chk_lprops; 108 + struct dentry *dfs_chk_fs; 109 + struct dentry *dfs_tst_rcvry; 114 110 }; 115 111 116 112 #define ubifs_assert(expr) do { \ ··· 199 169 200 170 extern spinlock_t dbg_lock; 201 171 202 - /* 203 - * Debugging check flags. 204 - * 205 - * UBIFS_CHK_GEN: general checks 206 - * UBIFS_CHK_INDEX: check the index 207 - * UBIFS_CHK_ORPH: check orphans 208 - * UBIFS_CHK_LPROPS: check lprops 209 - * UBIFS_CHK_FS: check the file-system 210 - */ 211 - enum { 212 - UBIFS_CHK_GEN = 0x1, 213 - UBIFS_CHK_INDEX = 0x2, 214 - UBIFS_CHK_ORPH = 0x8, 215 - UBIFS_CHK_LPROPS = 0x20, 216 - UBIFS_CHK_FS = 0x40, 217 - }; 218 - 219 - /* 220 - * Special testing flags. 221 - * 222 - * UBIFS_TST_RCVRY: failure mode for recovery testing 223 - */ 224 - enum { 225 - UBIFS_TST_RCVRY = 0x4, 226 - }; 227 - 228 - extern unsigned int ubifs_msg_flags; 229 - extern unsigned int ubifs_chk_flags; 230 - extern unsigned int ubifs_tst_flags; 231 - 232 172 static inline int dbg_is_chk_gen(const struct ubifs_info *c) 233 173 { 234 - return !!(ubifs_chk_flags & UBIFS_CHK_GEN); 174 + return c->dbg->chk_gen; 235 175 } 236 176 static inline int dbg_is_chk_index(const struct ubifs_info *c) 237 177 { 238 - return !!(ubifs_chk_flags & UBIFS_CHK_INDEX); 178 + return c->dbg->chk_index; 239 179 } 240 180 static inline int dbg_is_chk_orph(const struct ubifs_info *c) 241 181 { 242 - return !!(ubifs_chk_flags & UBIFS_CHK_ORPH); 182 + return c->dbg->chk_orph; 243 183 } 244 184 static inline int dbg_is_chk_lprops(const struct ubifs_info *c) 245 185 { 246 - return !!(ubifs_chk_flags & UBIFS_CHK_LPROPS); 186 + return c->dbg->chk_lprops; 247 187 } 248 188 static inline int dbg_is_chk_fs(const struct ubifs_info *c) 249 189 { 250 - return !!(ubifs_chk_flags & UBIFS_CHK_FS); 190 + return c->dbg->chk_fs; 251 191 } 252 192 static inline int dbg_is_tst_rcvry(const struct ubifs_info *c) 253 193 { 254 - return !!(ubifs_tst_flags & UBIFS_TST_RCVRY); 194 + return c->dbg->tst_rcvry; 255 195 } 256 196 257 197 int ubifs_debugging_init(struct ubifs_info *c);