* UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB'
@ 2012-07-16 18:22 Brent Taylor
2012-08-13 13:41 ` Brent Taylor
` (2 more replies)
0 siblings, 3 replies; 14+ messages in thread
From: Brent Taylor @ 2012-07-16 18:22 UTC (permalink / raw)
To: linux-mtd
[-- Attachment #1.1: Type: text/plain, Size: 67566 bytes --]
I'm developing on custom hardware using an at91sam9g45 processor with 64 MB
of RAM and 64 MB of NOR flash running Linux 3.0.13.
I'm doing some power-cycle testing and after several hours, UBIFS failed to
mount the root partition and printed the message "grab_empty_leb: could not
find an empty LEB". The system boots and starts a script that will power
cycle the board anytime between 10 and 20 seconds after the script has
started. Just before a power cycle occurs, syslog and our main process are
the only processes that could be writing to disk.
I then checked http://git.infradead.org/users/dedekind/ubifs-v3.0.git to
see if there was a patch and couldn't find anything describing my exact
problem. I generated a patch from commit
02f8c6aee8df3cdc935e9bdd4f2d020306035dbe to
a0c2d5050bd191e53a761381027c8e5ab8e25336 (see attached ubifs.3.0.diff) and
rebuilt the kernel. If there was a patch for my issue, I was expecting the
root partition to be recovered but it wasn't. I'm currently running the
same test with the patched kernel. Below is the information from the
patched kernel.
If there is any more information I need to provide, please let me know.
Any help would be appreciated,
Bud
[linux-16][~> uname -a
Linux linux 3.0.13 #20 Mon Jul 16 11:16:58 CDT 2012 armv5tejl GNU/Linux
[linux-16][~> mtdinfo -a
Count of MTD devices: 5
Present MTD devices: mtd0, mtd1, mtd2, mtd3, mtd4
Sysfs interface supported: yes
mtd0
Name: boot
Type: nor
Eraseblock size: 131072 bytes, 128.0 KiB
Amount of eraseblocks: 1 (131072 bytes, 128.0 KiB)
Minimum input/output unit size: 1 byte
Sub-page size: 1 byte
Character device major/minor: 90:0
Bad blocks are allowed: false
Device is writable: false
mtd1
Name: uboot
Type: nor
Eraseblock size: 131072 bytes, 128.0 KiB
Amount of eraseblocks: 1 (131072 bytes, 128.0 KiB)
Minimum input/output unit size: 1 byte
Sub-page size: 1 byte
Character device major/minor: 90:2
Bad blocks are allowed: false
Device is writable: false
mtd2
Name: env
Type: nor
Eraseblock size: 131072 bytes, 128.0 KiB
Amount of eraseblocks: 1 (131072 bytes, 128.0 KiB)
Minimum input/output unit size: 1 byte
Sub-page size: 1 byte
Character device major/minor: 90:4
Bad blocks are allowed: false
Device is writable: true
mtd3
Name: kernel
Type: nor
Eraseblock size: 131072 bytes, 128.0 KiB
Amount of eraseblocks: 16 (2097152 bytes, 2.0 MiB)
Minimum input/output unit size: 1 byte
Sub-page size: 1 byte
Character device major/minor: 90:6
Bad blocks are allowed: false
Device is writable: false
mtd4
Name: root-fs
Type: nor
Eraseblock size: 131072 bytes, 128.0 KiB
Amount of eraseblocks: 493 (64618496 bytes, 61.6 MiB)
Minimum input/output unit size: 1 byte
Sub-page size: 1 byte
Character device major/minor: 90:8
Bad blocks are allowed: false
Device is writable: true
[linux-16][~> ubinfo -a /dev/ubi0
ubi0
Volumes count: 1
Logical eraseblock size: 130944 bytes, 127.9 KiB
Total amount of logical eraseblocks: 493 (64555392 bytes, 61.6 MiB)
Amount of available logical eraseblocks: 0 (0 bytes)
Maximum count of volumes 128
Count of bad physical eraseblocks: 0
Count of reserved physical eraseblocks: 0
Current maximum erase counter value: 154
Minimum input/output unit size: 1 byte
Character device major/minor: 253:0
Present volumes: 0
Volume ID: 0 (on ubi0)
Type: dynamic
Alignment: 1
Size: 489 LEBs (64031616 bytes, 61.1 MiB)
State: OK
Name: ubirootfs
Character device major/minor: 253:1
[linux-16][~> mount -t ubifs ubi0:ubirootfs /opt/root/
UBIFS: recovery needed
UBIFS error (pid 958): grab_empty_leb: could not find an empty LEB
(pid 958) start dumping LEB properties
(pid 958) Lprops statistics: empty_lebs 2, idx_lebs 28
taken_empty_lebs 2, total_free 1193080, total_dirty 19318832
total_used 41441632, total_dark 1291912, total_dead 56
LEB 10 free 24 dirty 4064 used 126856 free + dirty
4088 dark 4088 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 11 free 8 dirty 640 used 130296 free + dirty
648 dark 648 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 12 free 40 dirty 960 used 129944 free + dirty
1000 dark 1000 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 13 free 0 dirty 1600 used 129344 free + dirty
1600 dark 1600 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 14 free 104 dirty 1272 used 129568 free + dirty
1376 dark 1376 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 15 free 104 dirty 1920 used 128920 free + dirty
2024 dark 2024 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 16 free 152 dirty 1120 used 129672 free + dirty
1272 dark 1272 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 17 free 112 dirty 1120 used 129712 free + dirty
1232 dark 1232 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 18 free 48 dirty 1120 used 129776 free + dirty
1168 dark 1168 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 19 free 104 dirty 1120 used 129720 free + dirty
1224 dark 1224 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 20 free 56 dirty 1280 used 129608 free + dirty
1336 dark 1336 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 21 free 56 dirty 1120 used 129768 free + dirty
1176 dark 1176 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 22 free 128 dirty 640 used 130176 free + dirty
768 dark 768 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 23 free 120 dirty 480 used 130344 free + dirty
600 dark 600 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 24 free 64 dirty 1600 used 129280 free + dirty
1664 dark 1664 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 25 free 24 dirty 1440 used 129480 free + dirty
1464 dark 1464 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 26 free 8 dirty 640 used 130296 free + dirty
648 dark 648 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 27 free 40 dirty 1760 used 129144 free + dirty
1800 dark 1800 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 28 free 64 dirty 1120 used 129760 free + dirty
1184 dark 1184 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 29 free 32 dirty 160 used 130752 free + dirty
192 dark 192 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 30 free 72 dirty 1328 used 129544 free + dirty
1400 dark 1400 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 31 free 48 dirty 2272 used 128624 free + dirty
2320 dark 2320 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 32 free 56 dirty 1280 used 129608 free + dirty
1336 dark 1336 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 33 free 48 dirty 800 used 130096 free + dirty
848 dark 848 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 34 free 128 dirty 1440 used 129376 free + dirty
1568 dark 1568 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 35 free 64 dirty 960 used 129920 free + dirty
1024 dark 1024 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 36 free 104 dirty 160 used 130680 free + dirty
264 dark 264 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 37 free 40 dirty 640 used 130264 free + dirty
680 dark 680 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 38 free 72 dirty 2112 used 128760 free + dirty
2184 dark 2184 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 39 free 104 dirty 25328 used 105512 free + dirty
25432 dark 4256 dead 0 nodes fit 5 flags 0x1 (dirty)
LEB 40 free 72 dirty 96464 used 34408 free + dirty
96536 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 41 free 104 dirty 104832 used 26008 free + dirty
104936 dark 4256 dead 0 nodes fit 24 flags 0x1 (dirty)
LEB 42 free 72 dirty 111616 used 19256 free + dirty
111688 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)
LEB 43 free 88 dirty 83008 used 47848 free + dirty
83096 dark 4256 dead 0 nodes fit 19 flags 0x1 (dirty)
LEB 44 free 48 dirty 53944 used 76952 free + dirty
53992 dark 4256 dead 0 nodes fit 12 flags 0x1 (dirty)
LEB 45 free 128 dirty 88752 used 42064 free + dirty
88880 dark 4256 dead 0 nodes fit 20 flags 0x1 (dirty)
LEB 46 free 136 dirty 111976 used 18832 free + dirty
112112 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)
LEB 47 free 16 dirty 89176 used 41752 free + dirty
89192 dark 4256 dead 0 nodes fit 20 flags 0x1 (dirty)
LEB 48 free 24 dirty 96616 used 34304 free + dirty
96640 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 49 free 48 dirty 88320 used 42576 free + dirty
88368 dark 4256 dead 0 nodes fit 20 flags 0x1 (dirty)
LEB 50 free 88 dirty 1120 used 129736 free + dirty
1208 dark 1208 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 51 free 152 dirty 84456 used 46336 free + dirty
84608 dark 4256 dead 0 nodes fit 19 flags 0x1 (dirty)
LEB 52 free 24 dirty 1736 used 129184 free + dirty
1760 dark 1760 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 53 free 32 dirty 107272 used 23640 free + dirty
107304 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 54 free 72 dirty 8696 used 122176 free + dirty
8768 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 55 free 144 dirty 92152 used 38648 free + dirty
92296 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)
LEB 56 free 120 dirty 86160 used 44664 free + dirty
86280 dark 4256 dead 0 nodes fit 20 flags 0x1 (dirty)
LEB 57 free 56 dirty 97728 used 33160 free + dirty
97784 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 58 free 16 dirty 50696 used 80232 free + dirty
50712 dark 4256 dead 0 nodes fit 11 flags 0x1 (dirty)
LEB 59 free 0 dirty 97448 used 33496 free + dirty
97448 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 60 free 80 dirty 83216 used 47648 free + dirty
83296 dark 4256 dead 0 nodes fit 19 flags 0x1 (dirty)
LEB 61 free 64 dirty 43384 used 87496 free + dirty
43448 dark 4256 dead 0 nodes fit 10 flags 0x1 (dirty)
LEB 62 free 40 dirty 2568 used 128336 free + dirty
2608 dark 2608 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 63 free 64 dirty 3632 used 127248 free + dirty
3696 dark 3696 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 64 free 0 dirty 9528 used 121416 free + dirty
9528 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 65 free 152 dirty 696 used 130096 free + dirty
848 dark 848 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 66 free 48 dirty 57392 used 73504 free + dirty
57440 dark 4256 dead 0 nodes fit 13 flags 0x1 (dirty)
LEB 67 free 64 dirty 90192 used 40688 free + dirty
90256 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)
LEB 68 free 72 dirty 111312 used 19560 free + dirty
111384 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)
LEB 69 free 0 dirty 85128 used 45816 free + dirty
85128 dark 4256 dead 0 nodes fit 20 flags 0x1 (dirty)
LEB 70 free 96 dirty 97600 used 33248 free + dirty
97696 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 71 free 16 dirty 91408 used 39520 free + dirty
91424 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)
LEB 72 free 48 dirty 103064 used 27832 free + dirty
103112 dark 4256 dead 0 nodes fit 24 flags 0x1 (dirty)
LEB 73 free 112 dirty 98704 used 32128 free + dirty
98816 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 74 free 8 dirty 1712 used 129224 free + dirty
1720 dark 1720 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 75 free 144 dirty 1656 used 129144 free + dirty
1800 dark 1800 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 76 free 80 dirty 76656 used 54208 free + dirty
76736 dark 4256 dead 0 nodes fit 18 flags 0x1 (dirty)
LEB 77 free 128 dirty 61016 used 69800 free + dirty
61144 dark 4256 dead 0 nodes fit 14 flags 0x1 (dirty)
LEB 78 free 40 dirty 48576 used 82328 free + dirty
48616 dark 4256 dead 0 nodes fit 11 flags 0x1 (dirty)
LEB 79 free 88 dirty 9592 used 121264 free + dirty
9680 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 80 free 40 dirty 54184 used 76720 free + dirty
54224 dark 4256 dead 0 nodes fit 12 flags 0x1 (dirty)
LEB 81 free 32 dirty 8592 used 122320 free + dirty
8624 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 82 free 8 dirty 1112 used 129824 free + dirty
1120 dark 1120 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 83 free 24 dirty 104352 used 26568 free + dirty
104376 dark 4256 dead 0 nodes fit 24 flags 0x1 (dirty)
LEB 84 free 56 dirty 9680 used 121208 free + dirty
9736 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 85 free 32 dirty 1112 used 129800 free + dirty
1144 dark 1144 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 86 free 72 dirty 88976 used 41896 free + dirty
89048 dark 4256 dead 0 nodes fit 20 flags 0x1 (dirty)
LEB 87 free 0 dirty 90504 used 40440 free + dirty
90504 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)
LEB 88 free 128 dirty 82728 used 48088 free + dirty
82856 dark 4256 dead 0 nodes fit 19 flags 0x1 (dirty)
LEB 89 free 64 dirty 104640 used 26240 free + dirty
104704 dark 4256 dead 0 nodes fit 24 flags 0x1 (dirty)
LEB 90 free 88 dirty 68744 used 62112 free + dirty
68832 dark 4256 dead 0 nodes fit 16 flags 0x1 (dirty)
LEB 91 free 152 dirty 1528 used 129264 free + dirty
1680 dark 1680 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 92 free 448 dirty 124120 used 6376 free + dirty
124568 dark 4256 dead 0 nodes fit 29 flags 0x10 (taken, bud of jhead
2 (data))
LEB 93 free 72 dirty 480 used 130392 free + dirty
552 dark 552 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 94 free 64 dirty 108216 used 22664 free + dirty
108280 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 95 free 72 dirty 105400 used 25472 free + dirty
105472 dark 4256 dead 0 nodes fit 24 flags 0x1 (dirty)
LEB 96 free 72 dirty 112456 used 18416 free + dirty
112528 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)
LEB 97 free 16 dirty 99960 used 30968 free + dirty
99976 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 98 free 24 dirty 58792 used 72128 free + dirty
58816 dark 4256 dead 0 nodes fit 13 flags 0x1 (dirty)
LEB 99 free 0 dirty 92688 used 38256 free + dirty
92688 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)
LEB 100 free 88728 dirty 20312 used 21904 free + dirty
109040 flags 0x22 (dirty index)
LEB 101 free 7152 dirty 107016 used 16776 free + dirty
114168 flags 0x22 (dirty index)
LEB 102 free 40 dirty 100824 used 30080 free + dirty
100864 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 103 free 128 dirty 98464 used 32352 free + dirty
98592 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 104 free 72 dirty 112808 used 18064 free + dirty
112880 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)
LEB 105 free 0 dirty 85704 used 45240 free + dirty
85704 dark 4256 dead 0 nodes fit 20 flags 0x1 (dirty)
LEB 106 free 48 dirty 1488 used 129408 free + dirty
1536 dark 1536 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 107 free 88 dirty 320 used 130536 free + dirty
408 dark 408 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 108 free 48 dirty 960 used 129936 free + dirty
1008 dark 1008 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 109 free 8880 dirty 106784 used 15280 free + dirty
115664 flags 0x22 (dirty index)
LEB 110 free 128 dirty 94504 used 36312 free + dirty
94632 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 111 free 64 dirty 9728 used 121152 free + dirty
9792 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 112 free 40 dirty 1672 used 129232 free + dirty
1712 dark 1712 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 113 free 88 dirty 2400 used 128456 free + dirty
2488 dark 2488 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 114 free 152 dirty 15152 used 115640 free + dirty
15304 dark 4256 dead 0 nodes fit 3 flags 0x1 (dirty)
LEB 115 free 40 dirty 64424 used 66480 free + dirty
64464 dark 4256 dead 0 nodes fit 15 flags 0x1 (dirty)
LEB 116 free 32 dirty 1904 used 129008 free + dirty
1936 dark 1936 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 117 free 80 dirty 2184 used 128680 free + dirty
2264 dark 2264 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 118 free 144 dirty 82784 used 48016 free + dirty
82928 dark 4256 dead 0 nodes fit 19 flags 0x1 (dirty)
LEB 119 free 80 dirty 101648 used 29216 free + dirty
101728 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 120 free 136 dirty 99720 used 31088 free + dirty
99856 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 121 free 72 dirty 94688 used 36184 free + dirty
94760 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 122 free 104 dirty 1920 used 128920 free + dirty
2024 dark 2024 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 123 free 144 dirty 1440 used 129360 free + dirty
1584 dark 1584 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 124 free 96 dirty 81088 used 49760 free + dirty
81184 dark 4256 dead 0 nodes fit 19 flags 0x1 (dirty)
LEB 125 free 16 dirty 78320 used 52608 free + dirty
78336 flags 0x22 (dirty index)
LEB 126 free 120 dirty 89976 used 40848 free + dirty
90096 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)
LEB 127 free 8 dirty 72 used 130864 free + dirty
80 dark 80 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 128 free 8 dirty 1120 used 129816 free + dirty
1128 dark 1128 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 129 free 88 dirty 2560 used 128296 free + dirty
2648 dark 2648 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 130 free 144 dirty 1120 used 129680 free + dirty
1264 dark 1264 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 131 free 104 dirty 1600 used 129240 free + dirty
1704 dark 1704 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 132 free 40 dirty 1120 used 129784 free + dirty
1160 dark 1160 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 133 free 32 dirty 1192 used 129720 free + dirty
1224 dark 1224 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 134 free 88 dirty 2216 used 128640 free + dirty
2304 dark 2304 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 135 free 120 dirty 1760 used 129064 free + dirty
1880 dark 1880 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 136 free 88 dirty 160 used 130696 free + dirty
248 dark 248 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 137 free 8 dirty 160 used 130776 free + dirty
168 dark 168 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 138 free 144 dirty 800 used 130000 free + dirty
944 dark 944 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 139 free 56 dirty 2080 used 128808 free + dirty
2136 dark 2136 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 140 free 40 dirty 2392 used 128512 free + dirty
2432 dark 2432 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 141 free 40 dirty 800 used 130104 free + dirty
840 dark 840 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 142 free 24 dirty 320 used 130600 free + dirty
344 dark 344 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 143 free 48 dirty 1600 used 129296 free + dirty
1648 dark 1648 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 144 free 32 dirty 2400 used 128512 free + dirty
2432 dark 2432 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 145 free 104 dirty 1440 used 129400 free + dirty
1544 dark 1544 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 146 free 96 dirty 640 used 130208 free + dirty
736 dark 736 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 147 free 104 dirty 1120 used 129720 free + dirty
1224 dark 1224 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 148 free 48 dirty 0 used 130896 free + dirty
48 dark 0 dead 48 nodes fit 0 flags 0x3 (free)
LEB 149 free 24 dirty 320 used 130600 free + dirty
344 dark 344 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 150 free 128 dirty 2360 used 128456 free + dirty
2488 dark 2488 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 151 free 72 dirty 1896 used 128976 free + dirty
1968 dark 1968 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 152 free 40 dirty 320 used 130584 free + dirty
360 dark 360 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 153 free 48 dirty 480 used 130416 free + dirty
528 dark 528 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 154 free 112 dirty 160 used 130672 free + dirty
272 dark 272 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 155 free 8 dirty 2584 used 128352 free + dirty
2592 dark 2592 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 156 free 88 dirty 1280 used 129576 free + dirty
1368 dark 1368 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 157 free 0 dirty 1344 used 129600 free + dirty
1344 dark 1344 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 158 free 72 dirty 2624 used 128248 free + dirty
2696 dark 2696 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 159 free 104 dirty 1600 used 129240 free + dirty
1704 dark 1704 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 160 free 24 dirty 1120 used 129800 free + dirty
1144 dark 1144 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 161 free 96 dirty 1760 used 129088 free + dirty
1856 dark 1856 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 162 free 48 dirty 480 used 130416 free + dirty
528 dark 528 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 163 free 88 dirty 464 used 130392 free + dirty
552 dark 552 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 164 free 48 dirty 3696 used 127200 free + dirty
3744 dark 3744 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 165 free 48 dirty 13688 used 117208 free + dirty
13736 dark 4256 dead 0 nodes fit 3 flags 0x1 (dirty)
LEB 166 free 72 dirty 21328 used 109544 free + dirty
21400 dark 4256 dead 0 nodes fit 5 flags 0x1 (dirty)
LEB 167 free 128 dirty 28752 used 102064 free + dirty
28880 dark 4256 dead 0 nodes fit 6 flags 0x1 (dirty)
LEB 168 free 144 dirty 97760 used 33040 free + dirty
97904 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 169 free 192 dirty 71616 used 59136 free + dirty
71808 flags 0x22 (dirty index)
LEB 170 free 1352 dirty 60440 used 69152 free + dirty
61792 flags 0x22 (dirty index)
LEB 171 free 144 dirty 1656 used 129144 free + dirty
1800 dark 1800 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 172 free 104 dirty 23568 used 107272 free + dirty
23672 dark 4256 dead 0 nodes fit 5 flags 0x1 (dirty)
LEB 173 free 112 dirty 20336 used 110496 free + dirty
20448 dark 4256 dead 0 nodes fit 4 flags 0x1 (dirty)
LEB 174 free 72 dirty 27808 used 103064 free + dirty
27880 dark 4256 dead 0 nodes fit 6 flags 0x1 (dirty)
LEB 175 free 120 dirty 30488 used 100336 free + dirty
30608 dark 4256 dead 0 nodes fit 7 flags 0x1 (dirty)
LEB 176 free 64 dirty 160 used 130720 free + dirty
224 dark 224 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 177 free 120 dirty 23416 used 107408 free + dirty
23536 dark 4256 dead 0 nodes fit 5 flags 0x1 (dirty)
LEB 178 free 48 dirty 55992 used 74904 free + dirty
56040 dark 4256 dead 0 nodes fit 13 flags 0x1 (dirty)
LEB 179 free 88 dirty 1904 used 128952 free + dirty
1992 dark 1992 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 180 free 96 dirty 9712 used 121136 free + dirty
9808 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 181 free 72 dirty 320 used 130552 free + dirty
392 dark 392 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 182 free 128 dirty 23920 used 106896 free + dirty
24048 dark 4256 dead 0 nodes fit 5 flags 0x1 (dirty)
LEB 183 free 80 dirty 800 used 130064 free + dirty
880 dark 880 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 184 free 32 dirty 320 used 130592 free + dirty
352 dark 352 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 185 free 8 dirty 2400 used 128536 free + dirty
2408 dark 2408 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 186 free 8 dirty 64 used 130872 free + dirty
72 dark 72 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 187 free 0 dirty 960 used 129984 free + dirty
960 dark 960 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 188 free 152 dirty 480 used 130312 free + dirty
632 dark 632 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 189 free 48 dirty 640 used 130256 free + dirty
688 dark 688 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 190 free 56 dirty 93312 used 37576 free + dirty
93368 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)
LEB 191 free 104 dirty 1920 used 128920 free + dirty
2024 dark 2024 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 192 free 0 dirty 160 used 130784 free + dirty
160 dark 160 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 193 free 0 dirty 800 used 130144 free + dirty
800 dark 800 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 194 free 24 dirty 128 used 130792 free + dirty
152 dark 152 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 195 free 40 dirty 15816 used 115088 free + dirty
15856 dark 4256 dead 0 nodes fit 3 flags 0x1 (dirty)
LEB 196 free 32 dirty 39160 used 91752 free + dirty
39192 dark 4256 dead 0 nodes fit 9 flags 0x1 (dirty)
LEB 197 free 40 dirty 36632 used 94272 free + dirty
36672 dark 4256 dead 0 nodes fit 8 flags 0x1 (dirty)
LEB 198 free 16 dirty 62008 used 68920 free + dirty
62024 dark 4256 dead 0 nodes fit 14 flags 0x1 (dirty)
LEB 199 free 40 dirty 1600 used 129304 free + dirty
1640 dark 1640 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 200 free 56 dirty 160 used 130728 free + dirty
216 dark 216 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 201 free 8 dirty 108008 used 22928 free + dirty
108016 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 202 free 16 dirty 64 used 130864 free + dirty
80 dark 80 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 203 free 71648 dirty 31168 used 28128 free + dirty
102816 flags 0x22 (dirty index)
LEB 204 free 24 dirty 66320 used 64600 free + dirty
66344 dark 4256 dead 0 nodes fit 15 flags 0x1 (dirty)
LEB 205 free 8 dirty 1760 used 129176 free + dirty
1768 dark 1768 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 206 free 1048 dirty 125856 used 4040 free + dirty
126904 dark 4256 dead 0 nodes fit 29 flags 0x10 (taken, bud of jhead
2 (data))
LEB 207 free 80 dirty 1480 used 129384 free + dirty
1560 dark 1560 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 208 free 104 dirty 9272 used 121568 free + dirty
9376 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 209 free 56 dirty 76344 used 54544 free + dirty
76400 dark 4256 dead 0 nodes fit 17 flags 0x1 (dirty)
LEB 210 free 40 dirty 85824 used 45080 free + dirty
85864 dark 4256 dead 0 nodes fit 20 flags 0x1 (dirty)
LEB 211 free 80 dirty 984 used 129880 free + dirty
1064 dark 1064 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 212 free 16 dirty 49080 used 81848 free + dirty
49096 dark 4256 dead 0 nodes fit 11 flags 0x1 (dirty)
LEB 213 free 48 dirty 93840 used 37056 free + dirty
93888 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 214 free 24 dirty 104256 used 26664 free + dirty
104280 dark 4256 dead 0 nodes fit 24 flags 0x1 (dirty)
LEB 215 free 112 dirty 111328 used 19504 free + dirty
111440 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)
LEB 216 free 32 dirty 108456 used 22456 free + dirty
108488 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 217 free 144 dirty 100152 used 30648 free + dirty
100296 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 218 free 32 dirty 108136 used 22776 free + dirty
108168 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 219 free 264 dirty 56600 used 74080 free + dirty
56864 flags 0x22 (dirty index)
LEB 220 free 40 dirty 89960 used 40944 free + dirty
90000 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)
LEB 221 free 56 dirty 23272 used 107616 free + dirty
23328 dark 4256 dead 0 nodes fit 5 flags 0x1 (dirty)
LEB 222 free 144 dirty 480 used 130320 free + dirty
624 dark 624 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 223 free 96 dirty 1120 used 129728 free + dirty
1216 dark 1216 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 224 free 80 dirty 640 used 130224 free + dirty
720 dark 720 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 225 free 96 dirty 2560 used 128288 free + dirty
2656 dark 2656 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 226 free 64 dirty 1120 used 129760 free + dirty
1184 dark 1184 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 227 free 24 dirty 92784 used 38136 free + dirty
92808 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)
LEB 228 free 0 dirty 18472 used 112472 free + dirty
18472 dark 4256 dead 0 nodes fit 4 flags 0x1 (dirty)
LEB 229 free 0 dirty 1760 used 129184 free + dirty
1760 dark 1760 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 230 free 40 dirty 640 used 130264 free + dirty
680 dark 680 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 231 free 24 dirty 1280 used 129640 free + dirty
1304 dark 1304 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 232 free 40 dirty 640 used 130264 free + dirty
680 dark 680 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 233 free 0 dirty 1280 used 129664 free + dirty
1280 dark 1280 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 234 free 0 dirty 80 used 130864 free + dirty
80 dark 80 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 235 free 64 dirty 320 used 130560 free + dirty
384 dark 384 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 236 free 56 dirty 320 used 130568 free + dirty
376 dark 376 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 237 free 0 dirty 0 used 130944 free + dirty
0 dark 0 dead 0 nodes fit 0 flags 0x10 (taken, jhead 0(GC))
LEB 238 free 16 dirty 960 used 129968 free + dirty
976 dark 976 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 239 free 48 dirty 100736 used 30160 free + dirty
100784 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 240 free 88 dirty 110216 used 20640 free + dirty
110304 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 241 free 8 dirty 960 used 129976 free + dirty
968 dark 968 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 242 free 24 dirty 20632 used 110288 free + dirty
20656 dark 4256 dead 0 nodes fit 4 flags 0x1 (dirty)
LEB 243 free 0 dirty 2720 used 128224 free + dirty
2720 dark 2720 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 244 free 144 dirty 640 used 130160 free + dirty
784 dark 784 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 245 free 1400 dirty 110912 used 18632 free + dirty
112312 flags 0x22 (dirty index)
LEB 246 free 0 dirty 640 used 130304 free + dirty
640 dark 640 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 247 free 32 dirty 640 used 130272 free + dirty
672 dark 672 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 248 free 112 dirty 1760 used 129072 free + dirty
1872 dark 1872 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 249 free 96 dirty 3360 used 127488 free + dirty
3456 dark 3456 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 250 free 0 dirty 1280 used 129664 free + dirty
1280 dark 1280 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 251 free 48 dirty 54736 used 76160 free + dirty
54784 dark 4256 dead 0 nodes fit 12 flags 0x1 (dirty)
LEB 252 free 88 dirty 47472 used 83384 free + dirty
47560 dark 4256 dead 0 nodes fit 11 flags 0x1 (dirty)
LEB 253 free 0 dirty 78304 used 52640 free + dirty
78304 dark 4256 dead 0 nodes fit 18 flags 0x1 (dirty)
LEB 254 free 48 dirty 109800 used 21096 free + dirty
109848 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 255 free 120 dirty 19704 used 111120 free + dirty
19824 dark 4256 dead 0 nodes fit 4 flags 0x1 (dirty)
LEB 256 free 136 dirty 98760 used 32048 free + dirty
98896 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 257 free 136 dirty 80736 used 50072 free + dirty
80872 dark 4256 dead 0 nodes fit 19 flags 0x1 (dirty)
LEB 258 free 40 dirty 480 used 130424 free + dirty
520 dark 520 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 259 free 48 dirty 109424 used 21472 free + dirty
109472 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 260 free 88 dirty 2080 used 128776 free + dirty
2168 dark 2168 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 261 free 104 dirty 480 used 130360 free + dirty
584 dark 584 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 262 free 240 dirty 125416 used 5288 free + dirty
125656 dark 4256 dead 0 nodes fit 29 flags 0x1 (dirty)
LEB 263 free 16 dirty 640 used 130288 free + dirty
656 dark 656 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 264 free 64 dirty 2240 used 128640 free + dirty
2304 dark 2304 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 265 free 0 dirty 24520 used 106424 free + dirty
24520 dark 4256 dead 0 nodes fit 5 flags 0x1 (dirty)
LEB 266 free 128 dirty 160 used 130656 free + dirty
288 dark 288 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 267 free 104 dirty 124248 used 6592 free + dirty
124352 dark 4256 dead 0 nodes fit 29 flags 0x1 (dirty)
LEB 268 free 88 dirty 160 used 130696 free + dirty
248 dark 248 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 269 free 72 dirty 160 used 130712 free + dirty
232 dark 232 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 270 free 120 dirty 960 used 129864 free + dirty
1080 dark 1080 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 271 free 88 dirty 103400 used 27456 free + dirty
103488 dark 4256 dead 0 nodes fit 24 flags 0x1 (dirty)
LEB 272 free 96 dirty 112344 used 18504 free + dirty
112440 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)
LEB 273 free 88 dirty 2080 used 128776 free + dirty
2168 dark 2168 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 274 free 112 dirty 75144 used 55688 free + dirty
75256 dark 4256 dead 0 nodes fit 17 flags 0x1 (dirty)
LEB 275 free 88 dirty 93264 used 37592 free + dirty
93352 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)
LEB 276 free 56 dirty 99160 used 31728 free + dirty
99216 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 277 free 64 dirty 57136 used 73744 free + dirty
57200 dark 4256 dead 0 nodes fit 13 flags 0x1 (dirty)
LEB 278 free 80 dirty 8472 used 122392 free + dirty
8552 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 279 free 80 dirty 2080 used 128784 free + dirty
2160 dark 2160 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 280 free 0 dirty 8576 used 122368 free + dirty
8576 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 281 free 128 dirty 81352 used 49464 free + dirty
81480 dark 4256 dead 0 nodes fit 19 flags 0x1 (dirty)
LEB 282 free 56 dirty 1920 used 128968 free + dirty
1976 dark 1976 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 283 free 0 dirty 1920 used 129024 free + dirty
1920 dark 1920 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 284 free 16 dirty 2080 used 128848 free + dirty
2096 dark 2096 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 285 free 64 dirty 320 used 130560 free + dirty
384 dark 384 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 286 free 72 dirty 109792 used 21080 free + dirty
109864 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 287 free 0 dirty 98144 used 32800 free + dirty
98144 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 288 free 16576 dirty 89760 used 24608 free + dirty
106336 flags 0x22 (dirty index)
LEB 289 free 144 dirty 11304 used 119496 free + dirty
11448 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 290 free 104 dirty 58744 used 72096 free + dirty
58848 dark 4256 dead 0 nodes fit 13 flags 0x1 (dirty)
LEB 291 free 144 dirty 64856 used 65944 free + dirty
65000 dark 4256 dead 0 nodes fit 15 flags 0x1 (dirty)
LEB 292 free 88 dirty 320 used 130536 free + dirty
408 dark 408 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 293 free 4952 dirty 124872 used 1120 free + dirty
129824 dark 4256 dead 0 nodes fit 30 flags 0x10 (taken, jhead 1
(base))
LEB 294 free 32 dirty 1440 used 129472 free + dirty
1472 dark 1472 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 295 free 128 dirty 960 used 129856 free + dirty
1088 dark 1088 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 296 free 8 dirty 1920 used 129016 free + dirty
1928 dark 1928 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 297 free 128 dirty 800 used 130016 free + dirty
928 dark 928 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 298 free 136 dirty 1120 used 129688 free + dirty
1256 dark 1256 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 299 free 16 dirty 1440 used 129488 free + dirty
1456 dark 1456 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 300 free 32 dirty 103952 used 26960 free + dirty
103984 flags 0x22 (dirty index)
LEB 301 free 40 dirty 96 used 130808 free + dirty
136 dark 136 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 302 free 80 dirty 800 used 130064 free + dirty
880 dark 880 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 303 free 152 dirty 1120 used 129672 free + dirty
1272 dark 1272 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 304 free 0 dirty 480 used 130464 free + dirty
480 dark 480 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 305 free 96 dirty 2080 used 128768 free + dirty
2176 dark 2176 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 306 free 64 dirty 1440 used 129440 free + dirty
1504 dark 1504 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 307 free 16 dirty 1920 used 129008 free + dirty
1936 dark 1936 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 308 free 16 dirty 1920 used 129008 free + dirty
1936 dark 1936 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 309 free 8 dirty 1440 used 129496 free + dirty
1448 dark 1448 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 310 free 136 dirty 1760 used 129048 free + dirty
1896 dark 1896 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 311 free 24 dirty 7496 used 123424 free + dirty
7520 dark 4256 dead 0 nodes fit 1 flags 0x1 (dirty)
LEB 312 free 680 dirty 125816 used 4448 free + dirty
126496 dark 4256 dead 0 nodes fit 29 flags 0x10 (taken, bud of jhead
2 (data))
LEB 313 free 0 dirty 15928 used 115016 free + dirty
15928 dark 4256 dead 0 nodes fit 3 flags 0x1 (dirty)
LEB 314 free 24 dirty 42344 used 88576 free + dirty
42368 dark 4256 dead 0 nodes fit 9 flags 0x1 (dirty)
LEB 315 free 96 dirty 99848 used 31000 free + dirty
99944 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 316 free 48 dirty 95152 used 35744 free + dirty
95200 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 317 free 8 dirty 0 used 130936 free + dirty
8 dark 0 dead 8 nodes fit 0 flags 0x3 (free)
LEB 318 free 72 dirty 8088 used 122784 free + dirty
8160 dark 4256 dead 0 nodes fit 1 flags 0x1 (dirty)
LEB 319 free 40 dirty 1440 used 129464 free + dirty
1480 dark 1480 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 320 free 120 dirty 960 used 129864 free + dirty
1080 dark 1080 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 321 free 32 dirty 480 used 130432 free + dirty
512 dark 512 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 322 free 40 dirty 1600 used 129304 free + dirty
1640 dark 1640 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 323 free 56 dirty 108416 used 22472 free + dirty
108472 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 324 free 96 dirty 960 used 129888 free + dirty
1056 dark 1056 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 325 free 0 dirty 2720 used 128224 free + dirty
2720 dark 2720 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 326 free 56 dirty 9344 used 121544 free + dirty
9400 dark 4256 dead 0 nodes fit 2 flags 0x0 (not categorized)
LEB 327 free 8 dirty 1904 used 129032 free + dirty
1912 dark 1912 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 328 free 96 dirty 8376 used 122472 free + dirty
8472 dark 4256 dead 0 nodes fit 1 flags 0x1 (dirty)
LEB 329 free 66160 dirty 41304 used 23480 free + dirty
107464 flags 0x22 (dirty index)
LEB 330 free 0 dirty 109496 used 21448 free + dirty
109496 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 331 free 0 dirty 89744 used 41200 free + dirty
89744 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)
LEB 332 free 128 dirty 111744 used 19072 free + dirty
111872 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)
LEB 333 free 56 dirty 105848 used 25040 free + dirty
105904 dark 4256 dead 0 nodes fit 24 flags 0x1 (dirty)
LEB 334 free 80 dirty 110080 used 20784 free + dirty
110160 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 335 free 112 dirty 52312 used 78520 free + dirty
52424 dark 4256 dead 0 nodes fit 12 flags 0x1 (dirty)
LEB 336 free 40 dirty 99824 used 31080 free + dirty
99864 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 337 free 128 dirty 111152 used 19664 free + dirty
111280 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)
LEB 338 free 24 dirty 74768 used 56152 free + dirty
74792 dark 4256 dead 0 nodes fit 17 flags 0x1 (dirty)
LEB 339 free 128 dirty 87632 used 43184 free + dirty
87760 dark 4256 dead 0 nodes fit 20 flags 0x1 (dirty)
LEB 340 free 32 dirty 93392 used 37520 free + dirty
93424 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)
LEB 341 free 56 dirty 93800 used 37088 free + dirty
93856 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 342 free 0 dirty 86024 used 44920 free + dirty
86024 dark 4256 dead 0 nodes fit 20 flags 0x1 (dirty)
LEB 343 free 31880 dirty 81056 used 18008 free + dirty
112936 flags 0x22 (dirty index)
LEB 344 free 0 dirty 130944 used 0 free + dirty
130944 dark 4256 dead 0 nodes fit 30 flags 0x5 (freeable)
LEB 345 free 40176 dirty 62576 used 28192 free + dirty
102752 flags 0x22 (dirty index)
LEB 346 free 96 dirty 108880 used 21968 free + dirty
108976 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 347 free 144 dirty 48248 used 82552 free + dirty
48392 dark 4256 dead 0 nodes fit 11 flags 0x1 (dirty)
LEB 348 free 40 dirty 99680 used 31224 free + dirty
99720 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 349 free 120 dirty 104912 used 25912 free + dirty
105032 dark 4256 dead 0 nodes fit 24 flags 0x1 (dirty)
LEB 350 free 136 dirty 2400 used 128408 free + dirty
2536 dark 2536 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 351 free 96 dirty 8152 used 122696 free + dirty
8248 dark 4256 dead 0 nodes fit 1 flags 0x1 (dirty)
LEB 352 free 96 dirty 31248 used 99600 free + dirty
31344 dark 4256 dead 0 nodes fit 7 flags 0x1 (dirty)
LEB 353 free 8 dirty 1440 used 129496 free + dirty
1448 dark 1448 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 354 free 120 dirty 1112 used 129712 free + dirty
1232 dark 1232 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 355 free 56 dirty 25824 used 105064 free + dirty
25880 dark 4256 dead 0 nodes fit 6 flags 0x1 (dirty)
LEB 356 free 112 dirty 1840 used 128992 free + dirty
1952 dark 1952 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 357 free 48 dirty 97264 used 33632 free + dirty
97312 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 358 free 8 dirty 6736 used 124200 free + dirty
6744 dark 4256 dead 0 nodes fit 1 flags 0x1 (dirty)
LEB 359 free 72 dirty 104552 used 26320 free + dirty
104624 dark 4256 dead 0 nodes fit 24 flags 0x1 (dirty)
LEB 360 free 136 dirty 3008 used 127800 free + dirty
3144 dark 3144 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 361 free 48 dirty 106704 used 24192 free + dirty
106752 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 362 free 40 dirty 95136 used 35768 free + dirty
95176 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 363 free 128 dirty 9264 used 121552 free + dirty
9392 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 364 free 96 dirty 320 used 130528 free + dirty
416 dark 416 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 365 free 48 dirty 94408 used 36488 free + dirty
94456 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 366 free 72 dirty 1288 used 129584 free + dirty
1360 dark 1360 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 367 free 8 dirty 8808 used 122128 free + dirty
8816 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 368 free 56 dirty 2368 used 128520 free + dirty
2424 dark 2424 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 369 free 32 dirty 41872 used 89040 free + dirty
41904 dark 4256 dead 0 nodes fit 9 flags 0x1 (dirty)
LEB 370 free 136 dirty 26984 used 103824 free + dirty
27120 dark 4256 dead 0 nodes fit 6 flags 0x0 (not categorized)
LEB 371 free 152 dirty 1864 used 128928 free + dirty
2016 dark 2016 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 372 free 24 dirty 1576 used 129344 free + dirty
1600 dark 1600 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 373 free 16 dirty 2368 used 128560 free + dirty
2384 dark 2384 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 374 free 128 dirty 98464 used 32352 free + dirty
98592 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 375 free 24 dirty 1480 used 129440 free + dirty
1504 dark 1504 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 376 free 16 dirty 1328 used 129600 free + dirty
1344 dark 1344 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 377 free 96 dirty 2376 used 128472 free + dirty
2472 dark 2472 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 378 free 8 dirty 1760 used 129176 free + dirty
1768 dark 1768 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 379 free 80 dirty 112208 used 18656 free + dirty
112288 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)
LEB 380 free 144 dirty 99024 used 31776 free + dirty
99168 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 381 free 40 dirty 81256 used 49648 free + dirty
81296 dark 4256 dead 0 nodes fit 19 flags 0x1 (dirty)
LEB 382 free 96 dirty 1072 used 129776 free + dirty
1168 dark 1168 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 383 free 96 dirty 2344 used 128504 free + dirty
2440 dark 2440 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 384 free 16 dirty 760 used 130168 free + dirty
776 dark 776 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 385 free 56 dirty 2672 used 128216 free + dirty
2728 dark 2728 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 386 free 40 dirty 95928 used 34976 free + dirty
95968 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 387 free 8 dirty 99496 used 31440 free + dirty
99504 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 388 free 72 dirty 110648 used 20224 free + dirty
110720 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)
LEB 389 free 152 dirty 99536 used 31256 free + dirty
99688 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 390 free 5888 dirty 104784 used 20272 free + dirty
110672 flags 0x22 (dirty index)
LEB 391 free 152 dirty 71184 used 59608 free + dirty
71336 dark 4256 dead 0 nodes fit 16 flags 0x1 (dirty)
LEB 392 free 16 dirty 2240 used 128688 free + dirty
2256 dark 2256 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 393 free 112 dirty 2232 used 128600 free + dirty
2344 dark 2344 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 394 free 40 dirty 1088 used 129816 free + dirty
1128 dark 1128 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 395 free 8 dirty 84400 used 46536 free + dirty
84408 dark 4256 dead 0 nodes fit 19 flags 0x1 (dirty)
LEB 396 free 136 dirty 93696 used 37112 free + dirty
93832 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 397 free 48 dirty 110888 used 20008 free + dirty
110936 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)
LEB 398 free 58064 dirty 54072 used 18808 free + dirty
112136 flags 0x22 (dirty index)
LEB 399 free 120 dirty 84936 used 45888 free + dirty
85056 dark 4256 dead 0 nodes fit 19 flags 0x1 (dirty)
LEB 400 free 77168 dirty 37248 used 16528 free + dirty
114416 flags 0x22 (dirty index)
LEB 401 free 96 dirty 92512 used 38336 free + dirty
92608 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)
LEB 402 free 136 dirty 9360 used 121448 free + dirty
9496 dark 4256 dead 0 nodes fit 2 flags 0x0 (not categorized)
LEB 403 free 144 dirty 480 used 130320 free + dirty
624 dark 624 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 404 free 27096 dirty 74360 used 29488 free + dirty
101456 flags 0x22 (dirty index)
LEB 405 free 0 dirty 63200 used 67744 free + dirty
63200 dark 4256 dead 0 nodes fit 14 flags 0x1 (dirty)
LEB 406 free 64 dirty 2672 used 128208 free + dirty
2736 dark 2736 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 407 free 88 dirty 109440 used 21416 free + dirty
109528 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 408 free 96 dirty 110248 used 20600 free + dirty
110344 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 409 free 88 dirty 3912 used 126944 free + dirty
4000 dark 4000 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 410 free 16 dirty 1768 used 129160 free + dirty
1784 dark 1784 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 411 free 88 dirty 5312 used 125544 free + dirty
5400 dark 4256 dead 0 nodes fit 1 flags 0x1 (dirty)
LEB 412 free 130944 dirty 0 used 0 free + dirty
130944 dark 4256 dead 0 nodes fit 30 flags 0x10 (taken, bud of jhead
2 (data))
LEB 413 free 112 dirty 9480 used 121352 free + dirty
9592 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 414 free 0 dirty 101064 used 29880 free + dirty
101064 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 415 free 48 dirty 98656 used 32240 free + dirty
98704 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty
LEB 416 free 48 dirty 86224 used 44672 free + dirty
86272 dark 4256 dead 0 nodes fit 20 flags 0x1 (dirty)
LEB 417 free 48 dirty 16552 used 114344 free + dirty
16600 dark 4256 dead 0 nodes fit 3 flags 0x1 (dirty)
LEB 418 free 128 dirty 76176 used 54640 free + dirty
76304 dark 4256 dead 0 nodes fit 17 flags 0x1 (dirty)
LEB 419 free 82224 dirty 30024 used 18696 free + dirty
112248 flags 0x22 (dirty index)
LEB 420 free 38112 dirty 70008 used 22824 free + dirty
108120 flags 0x22 (dirty index)
LEB 421 free 42104 dirty 66416 used 22424 free + dirty
108520 flags 0x22 (dirty index)
LEB 422 free 15768 dirty 98416 used 16760 free + dirty
114184 flags 0x22 (dirty index)
LEB 423 free 112 dirty 2504 used 128328 free + dirty
2616 dark 2616 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 424 free 56 dirty 3184 used 127704 free + dirty
3240 dark 3240 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 425 free 8 dirty 61376 used 69560 free + dirty
61384 dark 4256 dead 0 nodes fit 14 flags 0x1 (dirty)
LEB 426 free 8 dirty 880 used 130056 free + dirty
888 dark 888 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 427 free 24 dirty 1848 used 129072 free + dirty
1872 dark 1872 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 428 free 0 dirty 888 used 130056 free + dirty
888 dark 888 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 429 free 48 dirty 640 used 130256 free + dirty
688 dark 688 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 430 free 16 dirty 1432 used 129496 free + dirty
1448 dark 1448 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 431 free 8 dirty 64 used 130872 free + dirty
72 dark 72 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 432 free 56 dirty 1984 used 128904 free + dirty
2040 dark 2040 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 433 free 32 dirty 2992 used 127920 free + dirty
3024 dark 3024 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 434 free 96 dirty 107624 used 23224 free + dirty
107720 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 435 free 80 dirty 18656 used 112208 free + dirty
18736 dark 4256 dead 0 nodes fit 4 flags 0x1 (dirty)
LEB 436 free 48 dirty 96312 used 34584 free + dirty
96360 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 437 free 88 dirty 111288 used 19568 free + dirty
111376 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)
LEB 438 free 104 dirty 1824 used 129016 free + dirty
1928 dark 1928 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 439 free 0 dirty 1376 used 129568 free + dirty
1376 dark 1376 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 440 free 40 dirty 94600 used 36304 free + dirty
94640 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 441 free 144 dirty 112056 used 18744 free + dirty
112200 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)
LEB 442 free 72 dirty 107008 used 23864 free + dirty
107080 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 443 free 120 dirty 98544 used 32280 free + dirty
98664 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 444 free 8 dirty 91832 used 39104 free + dirty
91840 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)
LEB 445 free 104 dirty 96344 used 34496 free + dirty
96448 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 446 free 152 dirty 91600 used 39192 free + dirty
91752 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)
LEB 447 free 8 dirty 9008 used 121928 free + dirty
9016 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 448 free 120 dirty 1440 used 129384 free + dirty
1560 dark 1560 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 449 free 144 dirty 7480 used 123320 free + dirty
7624 dark 4256 dead 0 nodes fit 1 flags 0x1 (dirty)
LEB 450 free 88 dirty 7352 used 123504 free + dirty
7440 dark 4256 dead 0 nodes fit 1 flags 0x0 (not categorized)
LEB 451 free 80 dirty 58008 used 72856 free + dirty
58088 dark 4256 dead 0 nodes fit 13 flags 0x1 (dirty)
LEB 452 free 9040 dirty 95656 used 26248 free + dirty
104696 flags 0x22 (dirty index)
LEB 453 free 8152 dirty 113096 used 9696 free + dirty
121248 flags 0x30 (index, taken)
LEB 454 free 40 dirty 99984 used 30920 free + dirty
100024 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 455 free 56 dirty 7832 used 123056 free + dirty
7888 dark 4256 dead 0 nodes fit 1 flags 0x1 (dirty)
LEB 456 free 64 dirty 111448 used 19432 free + dirty
111512 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)
LEB 457 free 40 dirty 95480 used 35424 free + dirty
95520 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)
LEB 458 free 60056 dirty 53472 used 17416 free + dirty
113528 flags 0x22 (dirty index)
LEB 459 free 16 dirty 100136 used 30792 free + dirty
100152 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 460 free 0 dirty 320 used 130624 free + dirty
320 dark 320 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 461 free 104 dirty 109608 used 21232 free + dirty
109712 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 462 free 64 dirty 114528 used 16352 free + dirty
114592 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)
LEB 463 free 152 dirty 109624 used 21168 free + dirty
109776 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 464 free 112 dirty 99080 used 31752 free + dirty
99192 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 465 free 72 dirty 99264 used 31608 free + dirty
99336 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)
LEB 466 free 48 dirty 480 used 130416 free + dirty
528 dark 528 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 467 free 152 dirty 2560 used 128232 free + dirty
2712 dark 2712 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 468 free 55128 dirty 47592 used 28224 free + dirty
102720 flags 0x22 (dirty index)
LEB 469 free 130944 dirty 0 used 0 free + dirty
130944 dark 4256 dead 0 nodes fit 30 flags 0x10 (taken, jhead 2(data))
LEB 470 free 40 dirty 1968 used 128936 free + dirty
2008 dark 2008 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 471 free 144 dirty 960 used 129840 free + dirty
1104 dark 1104 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 472 free 32 dirty 9000 used 121912 free + dirty
9032 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 473 free 144 dirty 9048 used 121752 free + dirty
9192 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 474 free 0 dirty 126600 used 4344 free + dirty
126600 dark 4256 dead 0 nodes fit 29 flags 0x1 (dirty)
LEB 475 free 152 dirty 63856 used 66936 free + dirty
64008 dark 4256 dead 0 nodes fit 15 flags 0x1 (dirty)
LEB 476 free 144 dirty 1760 used 129040 free + dirty
1904 dark 1904 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 477 free 88 dirty 2008 used 128848 free + dirty
2096 dark 2096 dead 0 nodes fit 0 flags 0x0 (not categorized)
LEB 478 free 13448 dirty 99712 used 17784 free + dirty
113160 flags 0x22 (dirty index)
LEB 479 free 104 dirty 9152 used 121688 free + dirty
9256 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)
LEB 480 free 0 dirty 1152 used 129792 free + dirty
1152 dark 1152 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 481 free 0 dirty 2664 used 128280 free + dirty
2664 dark 2664 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 482 free 112 dirty 125704 used 5128 free + dirty
125816 dark 4256 dead 0 nodes fit 29 flags 0x1 (dirty)
LEB 483 free 80 dirty 8288 used 122576 free + dirty
8368 dark 4256 dead 0 nodes fit 1 flags 0x0 (not categorized)
LEB 484 free 168 dirty 125736 used 5040 free + dirty
125904 dark 4256 dead 0 nodes fit 29 flags 0x1 (dirty)
LEB 485 free 48 dirty 2696 used 128200 free + dirty
2744 dark 2744 dead 0 nodes fit 0 flags 0x1 (dirty)
LEB 486 free 96 dirty 107016 used 23832 free + dirty
107112 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 487 free 56 dirty 110128 used 20760 free + dirty
110184 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)
LEB 488 free 67464 dirty 36960 used 26520 free + dirty
104424 flags 0x22 (dirty index)
(pid 958) finish dumping LEB properties
(pid 958) Budgeting info: data budget sum 0, total budget sum 0
budg_data_growth 0, budg_dd_growth 0, budg_idx_growth 0
min_idx_lebs 19, old_idx_sz 774952, uncommitted_idx 9024
page_budget 4144, inode_budget 160, dent_budget 312
nospace 0, nospace_rp 0
dark_wm 4256, dead_wm 56, max_idx_node_sz 192
freeable_cnt 1, calc_idx_sz 768632, idx_gc_cnt 0
dirty_pg_cnt 0, dirty_zn_cnt 47, clean_zn_cnt 0
gc_lnum -1, ihead_lnum 453
jhead 0 (GC) LEB 237
jhead 1 (base) LEB 293
jhead 2 (data) LEB 469
bud LEB 92
bud LEB 206
bud LEB 237
bud LEB 293
bud LEB 312
bud LEB 412
bud LEB 469
commit state 0
Budgeting predictions:
available: 16938560, outstanding 0, free 16002679
mount: No space left on device
[-- Attachment #1.2: Type: text/html, Size: 128653 bytes --]
[-- Attachment #2: ubifs.3.0.diff --]
[-- Type: application/octet-stream, Size: 435366 bytes --]
diff -uN -uNr linux-3.0/Documentation/filesystems/ubifs.txt linux-3.0.x.ubifs.latest/Documentation/filesystems/ubifs.txt
--- linux-3.0/Documentation/filesystems/ubifs.txt 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/Documentation/filesystems/ubifs.txt 2012-06-28 11:26:15.000000000 -0500
@@ -111,34 +111,6 @@
to UBI and mount volume "rootfs":
ubi.mtd=0 root=ubi0:rootfs rootfstype=ubifs
-
-Module Parameters for Debugging
-===============================
-
-When UBIFS has been compiled with debugging enabled, there are 2 module
-parameters that are available to control aspects of testing and debugging.
-
-debug_chks Selects extra checks that UBIFS can do while running:
-
- Check Flag value
-
- General checks 1
- Check Tree Node Cache (TNC) 2
- Check indexing tree size 4
- Check orphan area 8
- Check old indexing tree 16
- Check LEB properties (lprops) 32
- Check leaf nodes and inodes 64
-
-debug_tsts Selects a mode of testing, as follows:
-
- Test mode Flag value
-
- Failure mode for recovery testing 4
-
-For example, set debug_chks to 3 to enable general and TNC checks.
-
-
References
==========
diff -uN -uNr linux-3.0/drivers/mtd/ubi/Kconfig linux-3.0.x.ubifs.latest/drivers/mtd/ubi/Kconfig
--- linux-3.0/drivers/mtd/ubi/Kconfig 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/Kconfig 2012-06-28 11:26:15.000000000 -0500
@@ -52,12 +52,4 @@
work on top of UBI. Do not enable this unless you use legacy
software.
-config MTD_UBI_DEBUG
- bool "UBI debugging"
- depends on SYSFS
- select DEBUG_FS
- select KALLSYMS
- help
- This option enables UBI debugging.
-
endif # MTD_UBI
diff -uN -uNr linux-3.0/drivers/mtd/ubi/Makefile linux-3.0.x.ubifs.latest/drivers/mtd/ubi/Makefile
--- linux-3.0/drivers/mtd/ubi/Makefile 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/Makefile 2012-06-28 11:26:15.000000000 -0500
@@ -1,7 +1,6 @@
obj-$(CONFIG_MTD_UBI) += ubi.o
-ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o scan.o
-ubi-y += misc.o
+ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o attach.o
+ubi-y += misc.o debug.o
-ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o
obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o
diff -uN -uNr linux-3.0/drivers/mtd/ubi/attach.c linux-3.0.x.ubifs.latest/drivers/mtd/ubi/attach.c
--- linux-3.0/drivers/mtd/ubi/attach.c 1969-12-31 18:00:00.000000000 -0600
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/attach.c 2012-06-28 11:26:15.000000000 -0500
@@ -0,0 +1,1631 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Artem Bityutskiy (Битюцкий Артём)
+ */
+
+/*
+ * UBI attaching sub-system.
+ *
+ * This sub-system is responsible for attaching MTD devices and it also
+ * implements flash media scanning.
+ *
+ * The attaching information is represented by a &struct ubi_attach_info'
+ * object. Information about volumes is represented by &struct ubi_ainf_volume
+ * objects which are kept in volume RB-tree with root at the @volumes field.
+ * The RB-tree is indexed by the volume ID.
+ *
+ * Logical eraseblocks are represented by &struct ubi_ainf_peb objects. These
+ * objects are kept in per-volume RB-trees with the root at the corresponding
+ * &struct ubi_ainf_volume object. To put it differently, we keep an RB-tree of
+ * per-volume objects and each of these objects is the root of RB-tree of
+ * per-LEB objects.
+ *
+ * Corrupted physical eraseblocks are put to the @corr list, free physical
+ * eraseblocks are put to the @free list and the physical eraseblock to be
+ * erased are put to the @erase list.
+ *
+ * About corruptions
+ * ~~~~~~~~~~~~~~~~~
+ *
+ * UBI protects EC and VID headers with CRC-32 checksums, so it can detect
+ * whether the headers are corrupted or not. Sometimes UBI also protects the
+ * data with CRC-32, e.g., when it executes the atomic LEB change operation, or
+ * when it moves the contents of a PEB for wear-leveling purposes.
+ *
+ * UBI tries to distinguish between 2 types of corruptions.
+ *
+ * 1. Corruptions caused by power cuts. These are expected corruptions and UBI
+ * tries to handle them gracefully, without printing too many warnings and
+ * error messages. The idea is that we do not lose important data in these
+ * cases - we may lose only the data which were being written to the media just
+ * before the power cut happened, and the upper layers (e.g., UBIFS) are
+ * supposed to handle such data losses (e.g., by using the FS journal).
+ *
+ * When UBI detects a corruption (CRC-32 mismatch) in a PEB, and it looks like
+ * the reason is a power cut, UBI puts this PEB to the @erase list, and all
+ * PEBs in the @erase list are scheduled for erasure later.
+ *
+ * 2. Unexpected corruptions which are not caused by power cuts. During
+ * attaching, such PEBs are put to the @corr list and UBI preserves them.
+ * Obviously, this lessens the amount of available PEBs, and if at some point
+ * UBI runs out of free PEBs, it switches to R/O mode. UBI also loudly informs
+ * about such PEBs every time the MTD device is attached.
+ *
+ * However, it is difficult to reliably distinguish between these types of
+ * corruptions and UBI's strategy is as follows (in case of attaching by
+ * scanning). UBI assumes corruption type 2 if the VID header is corrupted and
+ * the data area does not contain all 0xFFs, and there were no bit-flips or
+ * integrity errors (e.g., ECC errors in case of NAND) while reading the data
+ * area. Otherwise UBI assumes corruption type 1. So the decision criteria
+ * are as follows.
+ * o If the data area contains only 0xFFs, there are no data, and it is safe
+ * to just erase this PEB - this is corruption type 1.
+ * o If the data area has bit-flips or data integrity errors (ECC errors on
+ * NAND), it is probably a PEB which was being erased when power cut
+ * happened, so this is corruption type 1. However, this is just a guess,
+ * which might be wrong.
+ * o Otherwise this it corruption type 2.
+ */
+
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/crc32.h>
+#include <linux/math64.h>
+#include <linux/random.h>
+#include "ubi.h"
+
+static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai);
+
+/* Temporary variables used during scanning */
+static struct ubi_ec_hdr *ech;
+static struct ubi_vid_hdr *vidh;
+
+/**
+ * add_to_list - add physical eraseblock to a list.
+ * @ai: attaching information
+ * @pnum: physical eraseblock number to add
+ * @vol_id: the last used volume id for the PEB
+ * @lnum: the last used LEB number for the PEB
+ * @ec: erase counter of the physical eraseblock
+ * @to_head: if not zero, add to the head of the list
+ * @list: the list to add to
+ *
+ * This function allocates a 'struct ubi_ainf_peb' object for physical
+ * eraseblock @pnum and adds it to the "free", "erase", or "alien" lists.
+ * It stores the @lnum and @vol_id alongside, which can both be
+ * %UBI_UNKNOWN if they are not available, not readable, or not assigned.
+ * If @to_head is not zero, PEB will be added to the head of the list, which
+ * basically means it will be processed first later. E.g., we add corrupted
+ * PEBs (corrupted due to power cuts) to the head of the erase list to make
+ * sure we erase them first and get rid of corruptions ASAP. This function
+ * returns zero in case of success and a negative error code in case of
+ * failure.
+ */
+static int add_to_list(struct ubi_attach_info *ai, int pnum, int vol_id,
+ int lnum, int ec, int to_head, struct list_head *list)
+{
+ struct ubi_ainf_peb *aeb;
+
+ if (list == &ai->free) {
+ dbg_bld("add to free: PEB %d, EC %d", pnum, ec);
+ } else if (list == &ai->erase) {
+ dbg_bld("add to erase: PEB %d, EC %d", pnum, ec);
+ } else if (list == &ai->alien) {
+ dbg_bld("add to alien: PEB %d, EC %d", pnum, ec);
+ ai->alien_peb_count += 1;
+ } else
+ BUG();
+
+ aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL);
+ if (!aeb)
+ return -ENOMEM;
+
+ aeb->pnum = pnum;
+ aeb->vol_id = vol_id;
+ aeb->lnum = lnum;
+ aeb->ec = ec;
+ if (to_head)
+ list_add(&aeb->u.list, list);
+ else
+ list_add_tail(&aeb->u.list, list);
+ return 0;
+}
+
+/**
+ * add_corrupted - add a corrupted physical eraseblock.
+ * @ai: attaching information
+ * @pnum: physical eraseblock number to add
+ * @ec: erase counter of the physical eraseblock
+ *
+ * This function allocates a 'struct ubi_ainf_peb' object for a corrupted
+ * physical eraseblock @pnum and adds it to the 'corr' list. The corruption
+ * was presumably not caused by a power cut. Returns zero in case of success
+ * and a negative error code in case of failure.
+ */
+static int add_corrupted(struct ubi_attach_info *ai, int pnum, int ec)
+{
+ struct ubi_ainf_peb *aeb;
+
+ dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
+
+ aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL);
+ if (!aeb)
+ return -ENOMEM;
+
+ ai->corr_peb_count += 1;
+ aeb->pnum = pnum;
+ aeb->ec = ec;
+ list_add(&aeb->u.list, &ai->corr);
+ return 0;
+}
+
+/**
+ * validate_vid_hdr - check volume identifier header.
+ * @vid_hdr: the volume identifier header to check
+ * @av: information about the volume this logical eraseblock belongs to
+ * @pnum: physical eraseblock number the VID header came from
+ *
+ * This function checks that data stored in @vid_hdr is consistent. Returns
+ * non-zero if an inconsistency was found and zero if not.
+ *
+ * Note, UBI does sanity check of everything it reads from the flash media.
+ * Most of the checks are done in the I/O sub-system. Here we check that the
+ * information in the VID header is consistent to the information in other VID
+ * headers of the same volume.
+ */
+static int validate_vid_hdr(const struct ubi_vid_hdr *vid_hdr,
+ const struct ubi_ainf_volume *av, int pnum)
+{
+ int vol_type = vid_hdr->vol_type;
+ int vol_id = be32_to_cpu(vid_hdr->vol_id);
+ int used_ebs = be32_to_cpu(vid_hdr->used_ebs);
+ int data_pad = be32_to_cpu(vid_hdr->data_pad);
+
+ if (av->leb_count != 0) {
+ int av_vol_type;
+
+ /*
+ * This is not the first logical eraseblock belonging to this
+ * volume. Ensure that the data in its VID header is consistent
+ * to the data in previous logical eraseblock headers.
+ */
+
+ if (vol_id != av->vol_id) {
+ ubi_err("inconsistent vol_id");
+ goto bad;
+ }
+
+ if (av->vol_type == UBI_STATIC_VOLUME)
+ av_vol_type = UBI_VID_STATIC;
+ else
+ av_vol_type = UBI_VID_DYNAMIC;
+
+ if (vol_type != av_vol_type) {
+ ubi_err("inconsistent vol_type");
+ goto bad;
+ }
+
+ if (used_ebs != av->used_ebs) {
+ ubi_err("inconsistent used_ebs");
+ goto bad;
+ }
+
+ if (data_pad != av->data_pad) {
+ ubi_err("inconsistent data_pad");
+ goto bad;
+ }
+ }
+
+ return 0;
+
+bad:
+ ubi_err("inconsistent VID header at PEB %d", pnum);
+ ubi_dump_vid_hdr(vid_hdr);
+ ubi_dump_av(av);
+ return -EINVAL;
+}
+
+/**
+ * add_volume - add volume to the attaching information.
+ * @ai: attaching information
+ * @vol_id: ID of the volume to add
+ * @pnum: physical eraseblock number
+ * @vid_hdr: volume identifier header
+ *
+ * If the volume corresponding to the @vid_hdr logical eraseblock is already
+ * present in the attaching information, this function does nothing. Otherwise
+ * it adds corresponding volume to the attaching information. Returns a pointer
+ * to the allocated "av" object in case of success and a negative error code in
+ * case of failure.
+ */
+static struct ubi_ainf_volume *add_volume(struct ubi_attach_info *ai,
+ int vol_id, int pnum,
+ const struct ubi_vid_hdr *vid_hdr)
+{
+ struct ubi_ainf_volume *av;
+ struct rb_node **p = &ai->volumes.rb_node, *parent = NULL;
+
+ ubi_assert(vol_id == be32_to_cpu(vid_hdr->vol_id));
+
+ /* Walk the volume RB-tree to look if this volume is already present */
+ while (*p) {
+ parent = *p;
+ av = rb_entry(parent, struct ubi_ainf_volume, rb);
+
+ if (vol_id == av->vol_id)
+ return av;
+
+ if (vol_id > av->vol_id)
+ p = &(*p)->rb_left;
+ else
+ p = &(*p)->rb_right;
+ }
+
+ /* The volume is absent - add it */
+ av = kmalloc(sizeof(struct ubi_ainf_volume), GFP_KERNEL);
+ if (!av)
+ return ERR_PTR(-ENOMEM);
+
+ av->highest_lnum = av->leb_count = 0;
+ av->vol_id = vol_id;
+ av->root = RB_ROOT;
+ av->used_ebs = be32_to_cpu(vid_hdr->used_ebs);
+ av->data_pad = be32_to_cpu(vid_hdr->data_pad);
+ av->compat = vid_hdr->compat;
+ av->vol_type = vid_hdr->vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME
+ : UBI_STATIC_VOLUME;
+ if (vol_id > ai->highest_vol_id)
+ ai->highest_vol_id = vol_id;
+
+ rb_link_node(&av->rb, parent, p);
+ rb_insert_color(&av->rb, &ai->volumes);
+ ai->vols_found += 1;
+ dbg_bld("added volume %d", vol_id);
+ return av;
+}
+
+/**
+ * compare_lebs - find out which logical eraseblock is newer.
+ * @ubi: UBI device description object
+ * @aeb: first logical eraseblock to compare
+ * @pnum: physical eraseblock number of the second logical eraseblock to
+ * compare
+ * @vid_hdr: volume identifier header of the second logical eraseblock
+ *
+ * This function compares 2 copies of a LEB and informs which one is newer. In
+ * case of success this function returns a positive value, in case of failure, a
+ * negative error code is returned. The success return codes use the following
+ * bits:
+ * o bit 0 is cleared: the first PEB (described by @aeb) is newer than the
+ * second PEB (described by @pnum and @vid_hdr);
+ * o bit 0 is set: the second PEB is newer;
+ * o bit 1 is cleared: no bit-flips were detected in the newer LEB;
+ * o bit 1 is set: bit-flips were detected in the newer LEB;
+ * o bit 2 is cleared: the older LEB is not corrupted;
+ * o bit 2 is set: the older LEB is corrupted.
+ */
+static int compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb,
+ int pnum, const struct ubi_vid_hdr *vid_hdr)
+{
+ void *buf;
+ int len, err, second_is_newer, bitflips = 0, corrupted = 0;
+ uint32_t data_crc, crc;
+ struct ubi_vid_hdr *vh = NULL;
+ unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum);
+
+ if (sqnum2 == aeb->sqnum) {
+ /*
+ * This must be a really ancient UBI image which has been
+ * created before sequence numbers support has been added. At
+ * that times we used 32-bit LEB versions stored in logical
+ * eraseblocks. That was before UBI got into mainline. We do not
+ * support these images anymore. Well, those images still work,
+ * but only if no unclean reboots happened.
+ */
+ ubi_err("unsupported on-flash UBI format\n");
+ return -EINVAL;
+ }
+
+ /* Obviously the LEB with lower sequence counter is older */
+ second_is_newer = (sqnum2 > aeb->sqnum);
+
+ /*
+ * Now we know which copy is newer. If the copy flag of the PEB with
+ * newer version is not set, then we just return, otherwise we have to
+ * check data CRC. For the second PEB we already have the VID header,
+ * for the first one - we'll need to re-read it from flash.
+ *
+ * Note: this may be optimized so that we wouldn't read twice.
+ */
+
+ if (second_is_newer) {
+ if (!vid_hdr->copy_flag) {
+ /* It is not a copy, so it is newer */
+ dbg_bld("second PEB %d is newer, copy_flag is unset",
+ pnum);
+ return 1;
+ }
+ } else {
+ if (!aeb->copy_flag) {
+ /* It is not a copy, so it is newer */
+ dbg_bld("first PEB %d is newer, copy_flag is unset",
+ pnum);
+ return bitflips << 1;
+ }
+
+ vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
+ if (!vh)
+ return -ENOMEM;
+
+ pnum = aeb->pnum;
+ err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
+ if (err) {
+ if (err == UBI_IO_BITFLIPS)
+ bitflips = 1;
+ else {
+ ubi_err("VID of PEB %d header is bad, but it "
+ "was OK earlier, err %d", pnum, err);
+ if (err > 0)
+ err = -EIO;
+
+ goto out_free_vidh;
+ }
+ }
+
+ vid_hdr = vh;
+ }
+
+ /* Read the data of the copy and check the CRC */
+
+ len = be32_to_cpu(vid_hdr->data_size);
+ buf = vmalloc(len);
+ if (!buf) {
+ err = -ENOMEM;
+ goto out_free_vidh;
+ }
+
+ err = ubi_io_read_data(ubi, buf, pnum, 0, len);
+ if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG)
+ goto out_free_buf;
+
+ data_crc = be32_to_cpu(vid_hdr->data_crc);
+ crc = crc32(UBI_CRC32_INIT, buf, len);
+ if (crc != data_crc) {
+ dbg_bld("PEB %d CRC error: calculated %#08x, must be %#08x",
+ pnum, crc, data_crc);
+ corrupted = 1;
+ bitflips = 0;
+ second_is_newer = !second_is_newer;
+ } else {
+ dbg_bld("PEB %d CRC is OK", pnum);
+ bitflips = !!err;
+ }
+
+ vfree(buf);
+ ubi_free_vid_hdr(ubi, vh);
+
+ if (second_is_newer)
+ dbg_bld("second PEB %d is newer, copy_flag is set", pnum);
+ else
+ dbg_bld("first PEB %d is newer, copy_flag is set", pnum);
+
+ return second_is_newer | (bitflips << 1) | (corrupted << 2);
+
+out_free_buf:
+ vfree(buf);
+out_free_vidh:
+ ubi_free_vid_hdr(ubi, vh);
+ return err;
+}
+
+/**
+ * ubi_add_to_av - add used physical eraseblock to the attaching information.
+ * @ubi: UBI device description object
+ * @ai: attaching information
+ * @pnum: the physical eraseblock number
+ * @ec: erase counter
+ * @vid_hdr: the volume identifier header
+ * @bitflips: if bit-flips were detected when this physical eraseblock was read
+ *
+ * This function adds information about a used physical eraseblock to the
+ * 'used' tree of the corresponding volume. The function is rather complex
+ * because it has to handle cases when this is not the first physical
+ * eraseblock belonging to the same logical eraseblock, and the newer one has
+ * to be picked, while the older one has to be dropped. This function returns
+ * zero in case of success and a negative error code in case of failure.
+ */
+int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum,
+ int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips)
+{
+ int err, vol_id, lnum;
+ unsigned long long sqnum;
+ struct ubi_ainf_volume *av;
+ struct ubi_ainf_peb *aeb;
+ struct rb_node **p, *parent = NULL;
+
+ vol_id = be32_to_cpu(vid_hdr->vol_id);
+ lnum = be32_to_cpu(vid_hdr->lnum);
+ sqnum = be64_to_cpu(vid_hdr->sqnum);
+
+ dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, bitflips %d",
+ pnum, vol_id, lnum, ec, sqnum, bitflips);
+
+ av = add_volume(ai, vol_id, pnum, vid_hdr);
+ if (IS_ERR(av))
+ return PTR_ERR(av);
+
+ if (ai->max_sqnum < sqnum)
+ ai->max_sqnum = sqnum;
+
+ /*
+ * Walk the RB-tree of logical eraseblocks of volume @vol_id to look
+ * if this is the first instance of this logical eraseblock or not.
+ */
+ p = &av->root.rb_node;
+ while (*p) {
+ int cmp_res;
+
+ parent = *p;
+ aeb = rb_entry(parent, struct ubi_ainf_peb, u.rb);
+ if (lnum != aeb->lnum) {
+ if (lnum < aeb->lnum)
+ p = &(*p)->rb_left;
+ else
+ p = &(*p)->rb_right;
+ continue;
+ }
+
+ /*
+ * There is already a physical eraseblock describing the same
+ * logical eraseblock present.
+ */
+
+ dbg_bld("this LEB already exists: PEB %d, sqnum %llu, EC %d",
+ aeb->pnum, aeb->sqnum, aeb->ec);
+
+ /*
+ * Make sure that the logical eraseblocks have different
+ * sequence numbers. Otherwise the image is bad.
+ *
+ * However, if the sequence number is zero, we assume it must
+ * be an ancient UBI image from the era when UBI did not have
+ * sequence numbers. We still can attach these images, unless
+ * there is a need to distinguish between old and new
+ * eraseblocks, in which case we'll refuse the image in
+ * 'compare_lebs()'. In other words, we attach old clean
+ * images, but refuse attaching old images with duplicated
+ * logical eraseblocks because there was an unclean reboot.
+ */
+ if (aeb->sqnum == sqnum && sqnum != 0) {
+ ubi_err("two LEBs with same sequence number %llu",
+ sqnum);
+ ubi_dump_aeb(aeb, 0);
+ ubi_dump_vid_hdr(vid_hdr);
+ return -EINVAL;
+ }
+
+ /*
+ * Now we have to drop the older one and preserve the newer
+ * one.
+ */
+ cmp_res = compare_lebs(ubi, aeb, pnum, vid_hdr);
+ if (cmp_res < 0)
+ return cmp_res;
+
+ if (cmp_res & 1) {
+ /*
+ * This logical eraseblock is newer than the one
+ * found earlier.
+ */
+ err = validate_vid_hdr(vid_hdr, av, pnum);
+ if (err)
+ return err;
+
+ err = add_to_list(ai, aeb->pnum, aeb->vol_id,
+ aeb->lnum, aeb->ec, cmp_res & 4,
+ &ai->erase);
+ if (err)
+ return err;
+
+ aeb->ec = ec;
+ aeb->pnum = pnum;
+ aeb->vol_id = vol_id;
+ aeb->lnum = lnum;
+ aeb->scrub = ((cmp_res & 2) || bitflips);
+ aeb->copy_flag = vid_hdr->copy_flag;
+ aeb->sqnum = sqnum;
+
+ if (av->highest_lnum == lnum)
+ av->last_data_size =
+ be32_to_cpu(vid_hdr->data_size);
+
+ return 0;
+ } else {
+ /*
+ * This logical eraseblock is older than the one found
+ * previously.
+ */
+ return add_to_list(ai, pnum, vol_id, lnum, ec,
+ cmp_res & 4, &ai->erase);
+ }
+ }
+
+ /*
+ * We've met this logical eraseblock for the first time, add it to the
+ * attaching information.
+ */
+
+ err = validate_vid_hdr(vid_hdr, av, pnum);
+ if (err)
+ return err;
+
+ aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL);
+ if (!aeb)
+ return -ENOMEM;
+
+ aeb->ec = ec;
+ aeb->pnum = pnum;
+ aeb->vol_id = vol_id;
+ aeb->lnum = lnum;
+ aeb->scrub = bitflips;
+ aeb->copy_flag = vid_hdr->copy_flag;
+ aeb->sqnum = sqnum;
+
+ if (av->highest_lnum <= lnum) {
+ av->highest_lnum = lnum;
+ av->last_data_size = be32_to_cpu(vid_hdr->data_size);
+ }
+
+ av->leb_count += 1;
+ rb_link_node(&aeb->u.rb, parent, p);
+ rb_insert_color(&aeb->u.rb, &av->root);
+ return 0;
+}
+
+/**
+ * ubi_find_av - find volume in the attaching information.
+ * @ai: attaching information
+ * @vol_id: the requested volume ID
+ *
+ * This function returns a pointer to the volume description or %NULL if there
+ * are no data about this volume in the attaching information.
+ */
+struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai,
+ int vol_id)
+{
+ struct ubi_ainf_volume *av;
+ struct rb_node *p = ai->volumes.rb_node;
+
+ while (p) {
+ av = rb_entry(p, struct ubi_ainf_volume, rb);
+
+ if (vol_id == av->vol_id)
+ return av;
+
+ if (vol_id > av->vol_id)
+ p = p->rb_left;
+ else
+ p = p->rb_right;
+ }
+
+ return NULL;
+}
+
+/**
+ * ubi_remove_av - delete attaching information about a volume.
+ * @ai: attaching information
+ * @av: the volume attaching information to delete
+ */
+void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av)
+{
+ struct rb_node *rb;
+ struct ubi_ainf_peb *aeb;
+
+ dbg_bld("remove attaching information about volume %d", av->vol_id);
+
+ while ((rb = rb_first(&av->root))) {
+ aeb = rb_entry(rb, struct ubi_ainf_peb, u.rb);
+ rb_erase(&aeb->u.rb, &av->root);
+ list_add_tail(&aeb->u.list, &ai->erase);
+ }
+
+ rb_erase(&av->rb, &ai->volumes);
+ kfree(av);
+ ai->vols_found -= 1;
+}
+
+/**
+ * early_erase_peb - erase a physical eraseblock.
+ * @ubi: UBI device description object
+ * @ai: attaching information
+ * @pnum: physical eraseblock number to erase;
+ * @ec: erase counter value to write (%UBI_UNKNOWN if it is unknown)
+ *
+ * This function erases physical eraseblock 'pnum', and writes the erase
+ * counter header to it. This function should only be used on UBI device
+ * initialization stages, when the EBA sub-system had not been yet initialized.
+ * This function returns zero in case of success and a negative error code in
+ * case of failure.
+ */
+static int early_erase_peb(struct ubi_device *ubi,
+ const struct ubi_attach_info *ai, int pnum, int ec)
+{
+ int err;
+ struct ubi_ec_hdr *ec_hdr;
+
+ if ((long long)ec >= UBI_MAX_ERASECOUNTER) {
+ /*
+ * Erase counter overflow. Upgrade UBI and use 64-bit
+ * erase counters internally.
+ */
+ ubi_err("erase counter overflow at PEB %d, EC %d", pnum, ec);
+ return -EINVAL;
+ }
+
+ ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
+ if (!ec_hdr)
+ return -ENOMEM;
+
+ ec_hdr->ec = cpu_to_be64(ec);
+
+ err = ubi_io_sync_erase(ubi, pnum, 0);
+ if (err < 0)
+ goto out_free;
+
+ err = ubi_io_write_ec_hdr(ubi, pnum, ec_hdr);
+
+out_free:
+ kfree(ec_hdr);
+ return err;
+}
+
+/**
+ * ubi_early_get_peb - get a free physical eraseblock.
+ * @ubi: UBI device description object
+ * @ai: attaching information
+ *
+ * This function returns a free physical eraseblock. It is supposed to be
+ * called on the UBI initialization stages when the wear-leveling sub-system is
+ * not initialized yet. This function picks a physical eraseblocks from one of
+ * the lists, writes the EC header if it is needed, and removes it from the
+ * list.
+ *
+ * This function returns a pointer to the "aeb" of the found free PEB in case
+ * of success and an error code in case of failure.
+ */
+struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi,
+ struct ubi_attach_info *ai)
+{
+ int err = 0;
+ struct ubi_ainf_peb *aeb, *tmp_aeb;
+
+ if (!list_empty(&ai->free)) {
+ aeb = list_entry(ai->free.next, struct ubi_ainf_peb, u.list);
+ list_del(&aeb->u.list);
+ dbg_bld("return free PEB %d, EC %d", aeb->pnum, aeb->ec);
+ return aeb;
+ }
+
+ /*
+ * We try to erase the first physical eraseblock from the erase list
+ * and pick it if we succeed, or try to erase the next one if not. And
+ * so forth. We don't want to take care about bad eraseblocks here -
+ * they'll be handled later.
+ */
+ list_for_each_entry_safe(aeb, tmp_aeb, &ai->erase, u.list) {
+ if (aeb->ec == UBI_UNKNOWN)
+ aeb->ec = ai->mean_ec;
+
+ err = early_erase_peb(ubi, ai, aeb->pnum, aeb->ec+1);
+ if (err)
+ continue;
+
+ aeb->ec += 1;
+ list_del(&aeb->u.list);
+ dbg_bld("return PEB %d, EC %d", aeb->pnum, aeb->ec);
+ return aeb;
+ }
+
+ ubi_err("no free eraseblocks");
+ return ERR_PTR(-ENOSPC);
+}
+
+/**
+ * check_corruption - check the data area of PEB.
+ * @ubi: UBI device description object
+ * @vid_hrd: the (corrupted) VID header of this PEB
+ * @pnum: the physical eraseblock number to check
+ *
+ * This is a helper function which is used to distinguish between VID header
+ * corruptions caused by power cuts and other reasons. If the PEB contains only
+ * 0xFF bytes in the data area, the VID header is most probably corrupted
+ * because of a power cut (%0 is returned in this case). Otherwise, it was
+ * probably corrupted for some other reasons (%1 is returned in this case). A
+ * negative error code is returned if a read error occurred.
+ *
+ * If the corruption reason was a power cut, UBI can safely erase this PEB.
+ * Otherwise, it should preserve it to avoid possibly destroying important
+ * information.
+ */
+static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
+ int pnum)
+{
+ int err;
+
+ mutex_lock(&ubi->buf_mutex);
+ memset(ubi->peb_buf, 0x00, ubi->leb_size);
+
+ err = ubi_io_read(ubi, ubi->peb_buf, pnum, ubi->leb_start,
+ ubi->leb_size);
+ if (err == UBI_IO_BITFLIPS || err == -EBADMSG) {
+ /*
+ * Bit-flips or integrity errors while reading the data area.
+ * It is difficult to say for sure what type of corruption is
+ * this, but presumably a power cut happened while this PEB was
+ * erased, so it became unstable and corrupted, and should be
+ * erased.
+ */
+ err = 0;
+ goto out_unlock;
+ }
+
+ if (err)
+ goto out_unlock;
+
+ if (ubi_check_pattern(ubi->peb_buf, 0xFF, ubi->leb_size))
+ goto out_unlock;
+
+ ubi_err("PEB %d contains corrupted VID header, and the data does not "
+ "contain all 0xFF, this may be a non-UBI PEB or a severe VID "
+ "header corruption which requires manual inspection", pnum);
+ ubi_dump_vid_hdr(vid_hdr);
+ dbg_msg("hexdump of PEB %d offset %d, length %d",
+ pnum, ubi->leb_start, ubi->leb_size);
+ ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+ ubi->peb_buf, ubi->leb_size, 1);
+ err = 1;
+
+out_unlock:
+ mutex_unlock(&ubi->buf_mutex);
+ return err;
+}
+
+/**
+ * scan_peb - scan and process UBI headers of a PEB.
+ * @ubi: UBI device description object
+ * @ai: attaching information
+ * @pnum: the physical eraseblock number
+ *
+ * This function reads UBI headers of PEB @pnum, checks them, and adds
+ * information about this PEB to the corresponding list or RB-tree in the
+ * "attaching info" structure. Returns zero if the physical eraseblock was
+ * successfully handled and a negative error code in case of failure.
+ */
+static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
+ int pnum)
+{
+ long long uninitialized_var(ec);
+ int err, bitflips = 0, vol_id, ec_err = 0;
+
+ dbg_bld("scan PEB %d", pnum);
+
+ /* Skip bad physical eraseblocks */
+ err = ubi_io_is_bad(ubi, pnum);
+ if (err < 0)
+ return err;
+ else if (err) {
+ ai->bad_peb_count += 1;
+ return 0;
+ }
+
+ err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
+ if (err < 0)
+ return err;
+ switch (err) {
+ case 0:
+ break;
+ case UBI_IO_BITFLIPS:
+ bitflips = 1;
+ break;
+ case UBI_IO_FF:
+ ai->empty_peb_count += 1;
+ return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN,
+ UBI_UNKNOWN, 0, &ai->erase);
+ case UBI_IO_FF_BITFLIPS:
+ ai->empty_peb_count += 1;
+ return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN,
+ UBI_UNKNOWN, 1, &ai->erase);
+ case UBI_IO_BAD_HDR_EBADMSG:
+ case UBI_IO_BAD_HDR:
+ /*
+ * We have to also look at the VID header, possibly it is not
+ * corrupted. Set %bitflips flag in order to make this PEB be
+ * moved and EC be re-created.
+ */
+ ec_err = err;
+ ec = UBI_UNKNOWN;
+ bitflips = 1;
+ break;
+ default:
+ ubi_err("'ubi_io_read_ec_hdr()' returned unknown code %d", err);
+ return -EINVAL;
+ }
+
+ if (!ec_err) {
+ int image_seq;
+
+ /* Make sure UBI version is OK */
+ if (ech->version != UBI_VERSION) {
+ ubi_err("this UBI version is %d, image version is %d",
+ UBI_VERSION, (int)ech->version);
+ return -EINVAL;
+ }
+
+ ec = be64_to_cpu(ech->ec);
+ if (ec > UBI_MAX_ERASECOUNTER) {
+ /*
+ * Erase counter overflow. The EC headers have 64 bits
+ * reserved, but we anyway make use of only 31 bit
+ * values, as this seems to be enough for any existing
+ * flash. Upgrade UBI and use 64-bit erase counters
+ * internally.
+ */
+ ubi_err("erase counter overflow, max is %d",
+ UBI_MAX_ERASECOUNTER);
+ ubi_dump_ec_hdr(ech);
+ return -EINVAL;
+ }
+
+ /*
+ * Make sure that all PEBs have the same image sequence number.
+ * This allows us to detect situations when users flash UBI
+ * images incorrectly, so that the flash has the new UBI image
+ * and leftovers from the old one. This feature was added
+ * relatively recently, and the sequence number was always
+ * zero, because old UBI implementations always set it to zero.
+ * For this reasons, we do not panic if some PEBs have zero
+ * sequence number, while other PEBs have non-zero sequence
+ * number.
+ */
+ image_seq = be32_to_cpu(ech->image_seq);
+ if (!ubi->image_seq && image_seq)
+ ubi->image_seq = image_seq;
+ if (ubi->image_seq && image_seq &&
+ ubi->image_seq != image_seq) {
+ ubi_err("bad image sequence number %d in PEB %d, "
+ "expected %d", image_seq, pnum, ubi->image_seq);
+ ubi_dump_ec_hdr(ech);
+ return -EINVAL;
+ }
+ }
+
+ /* OK, we've done with the EC header, let's look at the VID header */
+
+ err = ubi_io_read_vid_hdr(ubi, pnum, vidh, 0);
+ if (err < 0)
+ return err;
+ switch (err) {
+ case 0:
+ break;
+ case UBI_IO_BITFLIPS:
+ bitflips = 1;
+ break;
+ case UBI_IO_BAD_HDR_EBADMSG:
+ if (ec_err == UBI_IO_BAD_HDR_EBADMSG)
+ /*
+ * Both EC and VID headers are corrupted and were read
+ * with data integrity error, probably this is a bad
+ * PEB, bit it is not marked as bad yet. This may also
+ * be a result of power cut during erasure.
+ */
+ ai->maybe_bad_peb_count += 1;
+ case UBI_IO_BAD_HDR:
+ if (ec_err)
+ /*
+ * Both headers are corrupted. There is a possibility
+ * that this a valid UBI PEB which has corresponding
+ * LEB, but the headers are corrupted. However, it is
+ * impossible to distinguish it from a PEB which just
+ * contains garbage because of a power cut during erase
+ * operation. So we just schedule this PEB for erasure.
+ *
+ * Besides, in case of NOR flash, we deliberately
+ * corrupt both headers because NOR flash erasure is
+ * slow and can start from the end.
+ */
+ err = 0;
+ else
+ /*
+ * The EC was OK, but the VID header is corrupted. We
+ * have to check what is in the data area.
+ */
+ err = check_corruption(ubi, vidh, pnum);
+
+ if (err < 0)
+ return err;
+ else if (!err)
+ /* This corruption is caused by a power cut */
+ err = add_to_list(ai, pnum, UBI_UNKNOWN,
+ UBI_UNKNOWN, ec, 1, &ai->erase);
+ else
+ /* This is an unexpected corruption */
+ err = add_corrupted(ai, pnum, ec);
+ if (err)
+ return err;
+ goto adjust_mean_ec;
+ case UBI_IO_FF_BITFLIPS:
+ err = add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN,
+ ec, 1, &ai->erase);
+ if (err)
+ return err;
+ goto adjust_mean_ec;
+ case UBI_IO_FF:
+ if (ec_err)
+ err = add_to_list(ai, pnum, UBI_UNKNOWN,
+ UBI_UNKNOWN, ec, 1, &ai->erase);
+ else
+ err = add_to_list(ai, pnum, UBI_UNKNOWN,
+ UBI_UNKNOWN, ec, 0, &ai->free);
+ if (err)
+ return err;
+ goto adjust_mean_ec;
+ default:
+ ubi_err("'ubi_io_read_vid_hdr()' returned unknown code %d",
+ err);
+ return -EINVAL;
+ }
+
+ vol_id = be32_to_cpu(vidh->vol_id);
+ if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOLUME_ID) {
+ int lnum = be32_to_cpu(vidh->lnum);
+
+ /* Unsupported internal volume */
+ switch (vidh->compat) {
+ case UBI_COMPAT_DELETE:
+ ubi_msg("\"delete\" compatible internal volume %d:%d"
+ " found, will remove it", vol_id, lnum);
+ err = add_to_list(ai, pnum, vol_id, lnum,
+ ec, 1, &ai->erase);
+ if (err)
+ return err;
+ return 0;
+
+ case UBI_COMPAT_RO:
+ ubi_msg("read-only compatible internal volume %d:%d"
+ " found, switch to read-only mode",
+ vol_id, lnum);
+ ubi->ro_mode = 1;
+ break;
+
+ case UBI_COMPAT_PRESERVE:
+ ubi_msg("\"preserve\" compatible internal volume %d:%d"
+ " found", vol_id, lnum);
+ err = add_to_list(ai, pnum, vol_id, lnum,
+ ec, 0, &ai->alien);
+ if (err)
+ return err;
+ return 0;
+
+ case UBI_COMPAT_REJECT:
+ ubi_err("incompatible internal volume %d:%d found",
+ vol_id, lnum);
+ return -EINVAL;
+ }
+ }
+
+ if (ec_err)
+ ubi_warn("valid VID header but corrupted EC header at PEB %d",
+ pnum);
+ err = ubi_add_to_av(ubi, ai, pnum, ec, vidh, bitflips);
+ if (err)
+ return err;
+
+adjust_mean_ec:
+ if (!ec_err) {
+ ai->ec_sum += ec;
+ ai->ec_count += 1;
+ if (ec > ai->max_ec)
+ ai->max_ec = ec;
+ if (ec < ai->min_ec)
+ ai->min_ec = ec;
+ }
+
+ return 0;
+}
+
+/**
+ * late_analysis - analyze the overall situation with PEB.
+ * @ubi: UBI device description object
+ * @ai: attaching information
+ *
+ * This is a helper function which takes a look what PEBs we have after we
+ * gather information about all of them ("ai" is compete). It decides whether
+ * the flash is empty and should be formatted of whether there are too many
+ * corrupted PEBs and we should not attach this MTD device. Returns zero if we
+ * should proceed with attaching the MTD device, and %-EINVAL if we should not.
+ */
+static int late_analysis(struct ubi_device *ubi, struct ubi_attach_info *ai)
+{
+ struct ubi_ainf_peb *aeb;
+ int max_corr, peb_count;
+
+ peb_count = ubi->peb_count - ai->bad_peb_count - ai->alien_peb_count;
+ max_corr = peb_count / 20 ?: 8;
+
+ /*
+ * Few corrupted PEBs is not a problem and may be just a result of
+ * unclean reboots. However, many of them may indicate some problems
+ * with the flash HW or driver.
+ */
+ if (ai->corr_peb_count) {
+ ubi_err("%d PEBs are corrupted and preserved",
+ ai->corr_peb_count);
+ printk(KERN_ERR "Corrupted PEBs are:");
+ list_for_each_entry(aeb, &ai->corr, u.list)
+ printk(KERN_CONT " %d", aeb->pnum);
+ printk(KERN_CONT "\n");
+
+ /*
+ * If too many PEBs are corrupted, we refuse attaching,
+ * otherwise, only print a warning.
+ */
+ if (ai->corr_peb_count >= max_corr) {
+ ubi_err("too many corrupted PEBs, refusing");
+ return -EINVAL;
+ }
+ }
+
+ if (ai->empty_peb_count + ai->maybe_bad_peb_count == peb_count) {
+ /*
+ * All PEBs are empty, or almost all - a couple PEBs look like
+ * they may be bad PEBs which were not marked as bad yet.
+ *
+ * This piece of code basically tries to distinguish between
+ * the following situations:
+ *
+ * 1. Flash is empty, but there are few bad PEBs, which are not
+ * marked as bad so far, and which were read with error. We
+ * want to go ahead and format this flash. While formatting,
+ * the faulty PEBs will probably be marked as bad.
+ *
+ * 2. Flash contains non-UBI data and we do not want to format
+ * it and destroy possibly important information.
+ */
+ if (ai->maybe_bad_peb_count <= 2) {
+ ai->is_empty = 1;
+ ubi_msg("empty MTD device detected");
+ get_random_bytes(&ubi->image_seq,
+ sizeof(ubi->image_seq));
+ } else {
+ ubi_err("MTD device is not UBI-formatted and possibly "
+ "contains non-UBI data - refusing it");
+ return -EINVAL;
+ }
+
+ }
+
+ return 0;
+}
+
+/**
+ * scan_all - scan entire MTD device.
+ * @ubi: UBI device description object
+ *
+ * This function does full scanning of an MTD device and returns complete
+ * information about it in form of a "struct ubi_attach_info" object. In case
+ * of failure, an error code is returned.
+ */
+static struct ubi_attach_info *scan_all(struct ubi_device *ubi)
+{
+ int err, pnum;
+ struct rb_node *rb1, *rb2;
+ struct ubi_ainf_volume *av;
+ struct ubi_ainf_peb *aeb;
+ struct ubi_attach_info *ai;
+
+ ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
+ if (!ai)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_LIST_HEAD(&ai->corr);
+ INIT_LIST_HEAD(&ai->free);
+ INIT_LIST_HEAD(&ai->erase);
+ INIT_LIST_HEAD(&ai->alien);
+ ai->volumes = RB_ROOT;
+
+ err = -ENOMEM;
+ ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache",
+ sizeof(struct ubi_ainf_peb),
+ 0, 0, NULL);
+ if (!ai->aeb_slab_cache)
+ goto out_ai;
+
+ ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
+ if (!ech)
+ goto out_ai;
+
+ vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
+ if (!vidh)
+ goto out_ech;
+
+ for (pnum = 0; pnum < ubi->peb_count; pnum++) {
+ cond_resched();
+
+ dbg_gen("process PEB %d", pnum);
+ err = scan_peb(ubi, ai, pnum);
+ if (err < 0)
+ goto out_vidh;
+ }
+
+ dbg_msg("scanning is finished");
+
+ /* Calculate mean erase counter */
+ if (ai->ec_count)
+ ai->mean_ec = div_u64(ai->ec_sum, ai->ec_count);
+
+ err = late_analysis(ubi, ai);
+ if (err)
+ goto out_vidh;
+
+ /*
+ * In case of unknown erase counter we use the mean erase counter
+ * value.
+ */
+ ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) {
+ ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb)
+ if (aeb->ec == UBI_UNKNOWN)
+ aeb->ec = ai->mean_ec;
+ }
+
+ list_for_each_entry(aeb, &ai->free, u.list) {
+ if (aeb->ec == UBI_UNKNOWN)
+ aeb->ec = ai->mean_ec;
+ }
+
+ list_for_each_entry(aeb, &ai->corr, u.list)
+ if (aeb->ec == UBI_UNKNOWN)
+ aeb->ec = ai->mean_ec;
+
+ list_for_each_entry(aeb, &ai->erase, u.list)
+ if (aeb->ec == UBI_UNKNOWN)
+ aeb->ec = ai->mean_ec;
+
+ err = self_check_ai(ubi, ai);
+ if (err)
+ goto out_vidh;
+
+ ubi_free_vid_hdr(ubi, vidh);
+ kfree(ech);
+
+ return ai;
+
+out_vidh:
+ ubi_free_vid_hdr(ubi, vidh);
+out_ech:
+ kfree(ech);
+out_ai:
+ ubi_destroy_ai(ai);
+ return ERR_PTR(err);
+}
+
+/**
+ * ubi_attach - attach an MTD device.
+ * @ubi: UBI device descriptor
+ *
+ * This function returns zero in case of success and a negative error code in
+ * case of failure.
+ */
+int ubi_attach(struct ubi_device *ubi)
+{
+ int err;
+ struct ubi_attach_info *ai;
+
+ ai = scan_all(ubi);
+ if (IS_ERR(ai))
+ return PTR_ERR(ai);
+
+ ubi->bad_peb_count = ai->bad_peb_count;
+ ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;
+ ubi->corr_peb_count = ai->corr_peb_count;
+ ubi->max_ec = ai->max_ec;
+ ubi->mean_ec = ai->mean_ec;
+ ubi_msg("max. sequence number: %llu", ai->max_sqnum);
+
+ err = ubi_read_volume_table(ubi, ai);
+ if (err)
+ goto out_ai;
+
+ err = ubi_wl_init(ubi, ai);
+ if (err)
+ goto out_vtbl;
+
+ err = ubi_eba_init(ubi, ai);
+ if (err)
+ goto out_wl;
+
+ ubi_destroy_ai(ai);
+ return 0;
+
+out_wl:
+ ubi_wl_close(ubi);
+out_vtbl:
+ ubi_free_internal_volumes(ubi);
+ vfree(ubi->vtbl);
+out_ai:
+ ubi_destroy_ai(ai);
+ return err;
+}
+
+/**
+ * destroy_av - free volume attaching information.
+ * @av: volume attaching information
+ * @ai: attaching information
+ *
+ * This function destroys the volume attaching information.
+ */
+static void destroy_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av)
+{
+ struct ubi_ainf_peb *aeb;
+ struct rb_node *this = av->root.rb_node;
+
+ while (this) {
+ if (this->rb_left)
+ this = this->rb_left;
+ else if (this->rb_right)
+ this = this->rb_right;
+ else {
+ aeb = rb_entry(this, struct ubi_ainf_peb, u.rb);
+ this = rb_parent(this);
+ if (this) {
+ if (this->rb_left == &aeb->u.rb)
+ this->rb_left = NULL;
+ else
+ this->rb_right = NULL;
+ }
+
+ kmem_cache_free(ai->aeb_slab_cache, aeb);
+ }
+ }
+ kfree(av);
+}
+
+/**
+ * ubi_destroy_ai - destroy attaching information.
+ * @ai: attaching information
+ */
+void ubi_destroy_ai(struct ubi_attach_info *ai)
+{
+ struct ubi_ainf_peb *aeb, *aeb_tmp;
+ struct ubi_ainf_volume *av;
+ struct rb_node *rb;
+
+ list_for_each_entry_safe(aeb, aeb_tmp, &ai->alien, u.list) {
+ list_del(&aeb->u.list);
+ kmem_cache_free(ai->aeb_slab_cache, aeb);
+ }
+ list_for_each_entry_safe(aeb, aeb_tmp, &ai->erase, u.list) {
+ list_del(&aeb->u.list);
+ kmem_cache_free(ai->aeb_slab_cache, aeb);
+ }
+ list_for_each_entry_safe(aeb, aeb_tmp, &ai->corr, u.list) {
+ list_del(&aeb->u.list);
+ kmem_cache_free(ai->aeb_slab_cache, aeb);
+ }
+ list_for_each_entry_safe(aeb, aeb_tmp, &ai->free, u.list) {
+ list_del(&aeb->u.list);
+ kmem_cache_free(ai->aeb_slab_cache, aeb);
+ }
+
+ /* Destroy the volume RB-tree */
+ rb = ai->volumes.rb_node;
+ while (rb) {
+ if (rb->rb_left)
+ rb = rb->rb_left;
+ else if (rb->rb_right)
+ rb = rb->rb_right;
+ else {
+ av = rb_entry(rb, struct ubi_ainf_volume, rb);
+
+ rb = rb_parent(rb);
+ if (rb) {
+ if (rb->rb_left == &av->rb)
+ rb->rb_left = NULL;
+ else
+ rb->rb_right = NULL;
+ }
+
+ destroy_av(ai, av);
+ }
+ }
+
+ if (ai->aeb_slab_cache)
+ kmem_cache_destroy(ai->aeb_slab_cache);
+
+ kfree(ai);
+}
+
+/**
+ * self_check_ai - check the attaching information.
+ * @ubi: UBI device description object
+ * @ai: attaching information
+ *
+ * This function returns zero if the attaching information is all right, and a
+ * negative error code if not or if an error occurred.
+ */
+static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai)
+{
+ int pnum, err, vols_found = 0;
+ struct rb_node *rb1, *rb2;
+ struct ubi_ainf_volume *av;
+ struct ubi_ainf_peb *aeb, *last_aeb;
+ uint8_t *buf;
+
+ if (!ubi->dbg->chk_gen)
+ return 0;
+
+ /*
+ * At first, check that attaching information is OK.
+ */
+ ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) {
+ int leb_count = 0;
+
+ cond_resched();
+
+ vols_found += 1;
+
+ if (ai->is_empty) {
+ ubi_err("bad is_empty flag");
+ goto bad_av;
+ }
+
+ if (av->vol_id < 0 || av->highest_lnum < 0 ||
+ av->leb_count < 0 || av->vol_type < 0 || av->used_ebs < 0 ||
+ av->data_pad < 0 || av->last_data_size < 0) {
+ ubi_err("negative values");
+ goto bad_av;
+ }
+
+ if (av->vol_id >= UBI_MAX_VOLUMES &&
+ av->vol_id < UBI_INTERNAL_VOL_START) {
+ ubi_err("bad vol_id");
+ goto bad_av;
+ }
+
+ if (av->vol_id > ai->highest_vol_id) {
+ ubi_err("highest_vol_id is %d, but vol_id %d is there",
+ ai->highest_vol_id, av->vol_id);
+ goto out;
+ }
+
+ if (av->vol_type != UBI_DYNAMIC_VOLUME &&
+ av->vol_type != UBI_STATIC_VOLUME) {
+ ubi_err("bad vol_type");
+ goto bad_av;
+ }
+
+ if (av->data_pad > ubi->leb_size / 2) {
+ ubi_err("bad data_pad");
+ goto bad_av;
+ }
+
+ last_aeb = NULL;
+ ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) {
+ cond_resched();
+
+ last_aeb = aeb;
+ leb_count += 1;
+
+ if (aeb->pnum < 0 || aeb->ec < 0) {
+ ubi_err("negative values");
+ goto bad_aeb;
+ }
+
+ if (aeb->ec < ai->min_ec) {
+ ubi_err("bad ai->min_ec (%d), %d found",
+ ai->min_ec, aeb->ec);
+ goto bad_aeb;
+ }
+
+ if (aeb->ec > ai->max_ec) {
+ ubi_err("bad ai->max_ec (%d), %d found",
+ ai->max_ec, aeb->ec);
+ goto bad_aeb;
+ }
+
+ if (aeb->pnum >= ubi->peb_count) {
+ ubi_err("too high PEB number %d, total PEBs %d",
+ aeb->pnum, ubi->peb_count);
+ goto bad_aeb;
+ }
+
+ if (av->vol_type == UBI_STATIC_VOLUME) {
+ if (aeb->lnum >= av->used_ebs) {
+ ubi_err("bad lnum or used_ebs");
+ goto bad_aeb;
+ }
+ } else {
+ if (av->used_ebs != 0) {
+ ubi_err("non-zero used_ebs");
+ goto bad_aeb;
+ }
+ }
+
+ if (aeb->lnum > av->highest_lnum) {
+ ubi_err("incorrect highest_lnum or lnum");
+ goto bad_aeb;
+ }
+ }
+
+ if (av->leb_count != leb_count) {
+ ubi_err("bad leb_count, %d objects in the tree",
+ leb_count);
+ goto bad_av;
+ }
+
+ if (!last_aeb)
+ continue;
+
+ aeb = last_aeb;
+
+ if (aeb->lnum != av->highest_lnum) {
+ ubi_err("bad highest_lnum");
+ goto bad_aeb;
+ }
+ }
+
+ if (vols_found != ai->vols_found) {
+ ubi_err("bad ai->vols_found %d, should be %d",
+ ai->vols_found, vols_found);
+ goto out;
+ }
+
+ /* Check that attaching information is correct */
+ ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) {
+ last_aeb = NULL;
+ ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) {
+ int vol_type;
+
+ cond_resched();
+
+ last_aeb = aeb;
+
+ err = ubi_io_read_vid_hdr(ubi, aeb->pnum, vidh, 1);
+ if (err && err != UBI_IO_BITFLIPS) {
+ ubi_err("VID header is not OK (%d)", err);
+ if (err > 0)
+ err = -EIO;
+ return err;
+ }
+
+ vol_type = vidh->vol_type == UBI_VID_DYNAMIC ?
+ UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME;
+ if (av->vol_type != vol_type) {
+ ubi_err("bad vol_type");
+ goto bad_vid_hdr;
+ }
+
+ if (aeb->sqnum != be64_to_cpu(vidh->sqnum)) {
+ ubi_err("bad sqnum %llu", aeb->sqnum);
+ goto bad_vid_hdr;
+ }
+
+ if (av->vol_id != be32_to_cpu(vidh->vol_id)) {
+ ubi_err("bad vol_id %d", av->vol_id);
+ goto bad_vid_hdr;
+ }
+
+ if (av->compat != vidh->compat) {
+ ubi_err("bad compat %d", vidh->compat);
+ goto bad_vid_hdr;
+ }
+
+ if (aeb->lnum != be32_to_cpu(vidh->lnum)) {
+ ubi_err("bad lnum %d", aeb->lnum);
+ goto bad_vid_hdr;
+ }
+
+ if (av->used_ebs != be32_to_cpu(vidh->used_ebs)) {
+ ubi_err("bad used_ebs %d", av->used_ebs);
+ goto bad_vid_hdr;
+ }
+
+ if (av->data_pad != be32_to_cpu(vidh->data_pad)) {
+ ubi_err("bad data_pad %d", av->data_pad);
+ goto bad_vid_hdr;
+ }
+ }
+
+ if (!last_aeb)
+ continue;
+
+ if (av->highest_lnum != be32_to_cpu(vidh->lnum)) {
+ ubi_err("bad highest_lnum %d", av->highest_lnum);
+ goto bad_vid_hdr;
+ }
+
+ if (av->last_data_size != be32_to_cpu(vidh->data_size)) {
+ ubi_err("bad last_data_size %d", av->last_data_size);
+ goto bad_vid_hdr;
+ }
+ }
+
+ /*
+ * Make sure that all the physical eraseblocks are in one of the lists
+ * or trees.
+ */
+ buf = kzalloc(ubi->peb_count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ for (pnum = 0; pnum < ubi->peb_count; pnum++) {
+ err = ubi_io_is_bad(ubi, pnum);
+ if (err < 0) {
+ kfree(buf);
+ return err;
+ } else if (err)
+ buf[pnum] = 1;
+ }
+
+ ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb)
+ ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb)
+ buf[aeb->pnum] = 1;
+
+ list_for_each_entry(aeb, &ai->free, u.list)
+ buf[aeb->pnum] = 1;
+
+ list_for_each_entry(aeb, &ai->corr, u.list)
+ buf[aeb->pnum] = 1;
+
+ list_for_each_entry(aeb, &ai->erase, u.list)
+ buf[aeb->pnum] = 1;
+
+ list_for_each_entry(aeb, &ai->alien, u.list)
+ buf[aeb->pnum] = 1;
+
+ err = 0;
+ for (pnum = 0; pnum < ubi->peb_count; pnum++)
+ if (!buf[pnum]) {
+ ubi_err("PEB %d is not referred", pnum);
+ err = 1;
+ }
+
+ kfree(buf);
+ if (err)
+ goto out;
+ return 0;
+
+bad_aeb:
+ ubi_err("bad attaching information about LEB %d", aeb->lnum);
+ ubi_dump_aeb(aeb, 0);
+ ubi_dump_av(av);
+ goto out;
+
+bad_av:
+ ubi_err("bad attaching information about volume %d", av->vol_id);
+ ubi_dump_av(av);
+ goto out;
+
+bad_vid_hdr:
+ ubi_err("bad attaching information about volume %d", av->vol_id);
+ ubi_dump_av(av);
+ ubi_dump_vid_hdr(vidh);
+
+out:
+ dump_stack();
+ return -EINVAL;
+}
diff -uN -uNr linux-3.0/drivers/mtd/ubi/build.c linux-3.0.x.ubifs.latest/drivers/mtd/ubi/build.c
--- linux-3.0/drivers/mtd/ubi/build.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/build.c 2012-06-28 11:26:15.000000000 -0500
@@ -27,10 +27,6 @@
* module load parameters or the kernel boot parameters. If MTD devices were
* specified, UBI does not attach any MTD device, but it is possible to do
* later using the "UBI control device".
- *
- * At the moment we only attach UBI devices by scanning, which will become a
- * bottleneck when flashes reach certain large size. Then one may improve UBI
- * and add other methods, although it does not seem to be easy to do.
*/
#include <linux/err.h>
@@ -554,10 +550,10 @@
}
/**
- * free_internal_volumes - free internal volumes.
+ * ubi_free_internal_volumes - free internal volumes.
* @ubi: UBI device description object
*/
-static void free_internal_volumes(struct ubi_device *ubi)
+void ubi_free_internal_volumes(struct ubi_device *ubi)
{
int i;
@@ -569,59 +565,6 @@
}
/**
- * attach_by_scanning - attach an MTD device using scanning method.
- * @ubi: UBI device descriptor
- *
- * This function returns zero in case of success and a negative error code in
- * case of failure.
- *
- * Note, currently this is the only method to attach UBI devices. Hopefully in
- * the future we'll have more scalable attaching methods and avoid full media
- * scanning. But even in this case scanning will be needed as a fall-back
- * attaching method if there are some on-flash table corruptions.
- */
-static int attach_by_scanning(struct ubi_device *ubi)
-{
- int err;
- struct ubi_scan_info *si;
-
- si = ubi_scan(ubi);
- if (IS_ERR(si))
- return PTR_ERR(si);
-
- ubi->bad_peb_count = si->bad_peb_count;
- ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;
- ubi->corr_peb_count = si->corr_peb_count;
- ubi->max_ec = si->max_ec;
- ubi->mean_ec = si->mean_ec;
- ubi_msg("max. sequence number: %llu", si->max_sqnum);
-
- err = ubi_read_volume_table(ubi, si);
- if (err)
- goto out_si;
-
- err = ubi_wl_init_scan(ubi, si);
- if (err)
- goto out_vtbl;
-
- err = ubi_eba_init_scan(ubi, si);
- if (err)
- goto out_wl;
-
- ubi_scan_destroy_si(si);
- return 0;
-
-out_wl:
- ubi_wl_close(ubi);
-out_vtbl:
- free_internal_volumes(ubi);
- vfree(ubi->vtbl);
-out_si:
- ubi_scan_destroy_si(si);
- return err;
-}
-
-/**
* io_init - initialize I/O sub-system for a given UBI device.
* @ubi: UBI device description object
*
@@ -790,11 +733,11 @@
ubi_msg("data offset: %d", ubi->leb_start);
/*
- * Note, ideally, we have to initialize ubi->bad_peb_count here. But
+ * Note, ideally, we have to initialize @ubi->bad_peb_count here. But
* unfortunately, MTD does not provide this information. We should loop
* over all physical eraseblocks and invoke mtd->block_is_bad() for
- * each physical eraseblock. So, we skip ubi->bad_peb_count
- * uninitialized and initialize it after scanning.
+ * each physical eraseblock. So, we leave @ubi->bad_peb_count
+ * uninitialized so far.
*/
return 0;
@@ -805,7 +748,7 @@
* @ubi: UBI device description object
* @vol_id: ID of the volume to re-size
*
- * This function re-sizes the volume marked by the @UBI_VTBL_AUTORESIZE_FLG in
+ * This function re-sizes the volume marked by the %UBI_VTBL_AUTORESIZE_FLG in
* the volume table to the largest possible size. See comments in ubi-header.h
* for more description of the flag. Returns zero in case of success and a
* negative error code in case of failure.
@@ -881,7 +824,7 @@
for (i = 0; i < UBI_MAX_DEVICES; i++) {
ubi = ubi_devices[i];
if (ubi && mtd->index == ubi->mtd->index) {
- dbg_err("mtd%d is already attached to ubi%d",
+ ubi_err("mtd%d is already attached to ubi%d",
mtd->index, i);
return -EEXIST;
}
@@ -907,7 +850,7 @@
if (!ubi_devices[ubi_num])
break;
if (ubi_num == UBI_MAX_DEVICES) {
- dbg_err("only %d UBI devices may be created",
+ ubi_err("only %d UBI devices may be created",
UBI_MAX_DEVICES);
return -ENFILE;
}
@@ -917,7 +860,7 @@
/* Make sure ubi_num is not busy */
if (ubi_devices[ubi_num]) {
- dbg_err("ubi%d already exists", ubi_num);
+ ubi_err("ubi%d already exists", ubi_num);
return -EEXIST;
}
}
@@ -937,7 +880,7 @@
spin_lock_init(&ubi->volumes_lock);
ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
- dbg_msg("sizeof(struct ubi_scan_leb) %zu", sizeof(struct ubi_scan_leb));
+ dbg_msg("sizeof(struct ubi_ainf_peb) %zu", sizeof(struct ubi_ainf_peb));
dbg_msg("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry));
err = io_init(ubi);
@@ -945,18 +888,18 @@
goto out_free;
err = -ENOMEM;
- ubi->peb_buf1 = vmalloc(ubi->peb_size);
- if (!ubi->peb_buf1)
+ ubi->peb_buf = vmalloc(ubi->peb_size);
+ if (!ubi->peb_buf)
goto out_free;
- ubi->peb_buf2 = vmalloc(ubi->peb_size);
- if (!ubi->peb_buf2)
+ err = ubi_debugging_init_dev(ubi);
+ if (err)
goto out_free;
- err = attach_by_scanning(ubi);
+ err = ubi_attach(ubi);
if (err) {
- dbg_err("failed to attach by scanning, error %d", err);
- goto out_free;
+ ubi_err("failed to attach mtd%d, error %d", mtd->index, err);
+ goto out_debugging;
}
if (ubi->autoresize_vol_id != -1) {
@@ -969,12 +912,16 @@
if (err)
goto out_detach;
+ err = ubi_debugfs_init_dev(ubi);
+ if (err)
+ goto out_uif;
+
ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
if (IS_ERR(ubi->bgt_thread)) {
err = PTR_ERR(ubi->bgt_thread);
ubi_err("cannot spawn \"%s\", error %d", ubi->bgt_name,
err);
- goto out_uif;
+ goto out_debugfs;
}
ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num);
@@ -1008,15 +955,20 @@
ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
return ubi_num;
+out_debugfs:
+ ubi_debugfs_exit_dev(ubi);
out_uif:
+ get_device(&ubi->dev);
+ ubi_assert(ref);
uif_close(ubi);
out_detach:
ubi_wl_close(ubi);
- free_internal_volumes(ubi);
+ ubi_free_internal_volumes(ubi);
vfree(ubi->vtbl);
+out_debugging:
+ ubi_debugging_exit_dev(ubi);
out_free:
- vfree(ubi->peb_buf1);
- vfree(ubi->peb_buf2);
+ vfree(ubi->peb_buf);
if (ref)
put_device(&ubi->dev);
else
@@ -1080,13 +1032,14 @@
*/
get_device(&ubi->dev);
+ ubi_debugfs_exit_dev(ubi);
uif_close(ubi);
ubi_wl_close(ubi);
- free_internal_volumes(ubi);
+ ubi_free_internal_volumes(ubi);
vfree(ubi->vtbl);
put_mtd_device(ubi->mtd);
- vfree(ubi->peb_buf1);
- vfree(ubi->peb_buf2);
+ ubi_debugging_exit_dev(ubi);
+ vfree(ubi->peb_buf);
ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num);
put_device(&ubi->dev);
return 0;
@@ -1199,6 +1152,11 @@
if (!ubi_wl_entry_slab)
goto out_dev_unreg;
+ err = ubi_debugfs_init();
+ if (err)
+ goto out_slab;
+
+
/* Attach MTD devices */
for (i = 0; i < mtd_devs; i++) {
struct mtd_dev_param *p = &mtd_dev_param[i];
@@ -1247,6 +1205,8 @@
ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1);
mutex_unlock(&ubi_devices_mutex);
}
+ ubi_debugfs_exit();
+out_slab:
kmem_cache_destroy(ubi_wl_entry_slab);
out_dev_unreg:
misc_deregister(&ubi_ctrl_cdev);
@@ -1270,6 +1230,7 @@
ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1);
mutex_unlock(&ubi_devices_mutex);
}
+ ubi_debugfs_exit();
kmem_cache_destroy(ubi_wl_entry_slab);
misc_deregister(&ubi_ctrl_cdev);
class_remove_file(ubi_class, &ubi_version);
diff -uN -uNr linux-3.0/drivers/mtd/ubi/cdev.c linux-3.0.x.ubifs.latest/drivers/mtd/ubi/cdev.c
--- linux-3.0/drivers/mtd/ubi/cdev.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/cdev.c 2012-06-28 11:26:15.000000000 -0500
@@ -63,7 +63,7 @@
users = vol->readers + vol->writers + vol->exclusive;
ubi_assert(users > 0);
if (users > 1) {
- dbg_err("%d users for volume %d", users, vol->vol_id);
+ ubi_err("%d users for volume %d", users, vol->vol_id);
err = -EBUSY;
} else {
vol->readers = vol->writers = 0;
@@ -159,7 +159,7 @@
if (vol->updating) {
/* Update is in progress, seeking is prohibited */
- dbg_err("updating");
+ ubi_err("updating");
return -EBUSY;
}
@@ -178,7 +178,7 @@
}
if (new_offset < 0 || new_offset > vol->used_bytes) {
- dbg_err("bad seek %lld", new_offset);
+ ubi_err("bad seek %lld", new_offset);
return -EINVAL;
}
@@ -212,11 +212,11 @@
count, *offp, vol->vol_id);
if (vol->updating) {
- dbg_err("updating");
+ ubi_err("updating");
return -EBUSY;
}
if (vol->upd_marker) {
- dbg_err("damaged volume, update marker is set");
+ ubi_err("damaged volume, update marker is set");
return -EBADF;
}
if (*offp == vol->used_bytes || count == 0)
@@ -296,7 +296,7 @@
lnum = div_u64_rem(*offp, vol->usable_leb_size, &off);
if (off & (ubi->min_io_size - 1)) {
- dbg_err("unaligned position");
+ ubi_err("unaligned position");
return -EINVAL;
}
@@ -305,7 +305,7 @@
/* We can write only in fractions of the minimum I/O unit */
if (count & (ubi->min_io_size - 1)) {
- dbg_err("unaligned write length");
+ ubi_err("unaligned write length");
return -EINVAL;
}
@@ -330,8 +330,7 @@
break;
}
- err = ubi_eba_write_leb(ubi, vol, lnum, tbuf, off, len,
- UBI_UNKNOWN);
+ err = ubi_eba_write_leb(ubi, vol, lnum, tbuf, off, len);
if (err)
break;
@@ -473,9 +472,6 @@
if (req.lnum < 0 || req.lnum >= vol->reserved_pebs ||
req.bytes < 0 || req.lnum >= vol->usable_leb_size)
break;
- if (req.dtype != UBI_LONGTERM && req.dtype != UBI_SHORTTERM &&
- req.dtype != UBI_UNKNOWN)
- break;
err = get_exclusive(desc);
if (err < 0)
@@ -514,7 +510,7 @@
if (err)
break;
- err = ubi_wl_flush(ubi);
+ err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
break;
}
@@ -528,7 +524,7 @@
err = -EFAULT;
break;
}
- err = ubi_leb_map(desc, req.lnum, req.dtype);
+ err = ubi_leb_map(desc, req.lnum);
break;
}
@@ -628,6 +624,9 @@
if (req->alignment != 1 && n)
goto bad;
+ if (!req->name[0] || !req->name_len)
+ goto bad;
+
if (req->name_len > UBI_VOL_NAME_MAX) {
err = -ENAMETOOLONG;
goto bad;
@@ -640,8 +639,8 @@
return 0;
bad:
- dbg_err("bad volume creation request");
- ubi_dbg_dump_mkvol_req(req);
+ ubi_err("bad volume creation request");
+ ubi_dump_mkvol_req(req);
return err;
}
@@ -706,12 +705,12 @@
for (i = 0; i < req->count - 1; i++) {
for (n = i + 1; n < req->count; n++) {
if (req->ents[i].vol_id == req->ents[n].vol_id) {
- dbg_err("duplicated volume id %d",
+ ubi_err("duplicated volume id %d",
req->ents[i].vol_id);
return -EINVAL;
}
if (!strcmp(req->ents[i].name, req->ents[n].name)) {
- dbg_err("duplicated volume name \"%s\"",
+ ubi_err("duplicated volume name \"%s\"",
req->ents[i].name);
return -EINVAL;
}
@@ -734,7 +733,7 @@
re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE);
if (IS_ERR(re->desc)) {
err = PTR_ERR(re->desc);
- dbg_err("cannot open volume %d, error %d", vol_id, err);
+ ubi_err("cannot open volume %d, error %d", vol_id, err);
kfree(re);
goto out_free;
}
@@ -793,7 +792,7 @@
continue;
/* The volume exists but busy, or an error occurred */
- dbg_err("cannot open volume \"%s\", error %d",
+ ubi_err("cannot open volume \"%s\", error %d",
re->new_name, err);
goto out_free;
}
diff -uN -uNr linux-3.0/drivers/mtd/ubi/debug.c linux-3.0.x.ubifs.latest/drivers/mtd/ubi/debug.c
--- linux-3.0/drivers/mtd/ubi/debug.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/debug.c 2012-06-28 11:26:15.000000000 -0500
@@ -18,32 +18,49 @@
* Author: Artem Bityutskiy (Битюцкий Артём)
*/
-/*
- * Here we keep all the UBI debugging stuff which should normally be disabled
- * and compiled-out, but it is extremely helpful when hunting bugs or doing big
- * changes.
- */
-
-#ifdef CONFIG_MTD_UBI_DEBUG
-
#include "ubi.h"
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
#include <linux/module.h>
-#include <linux/moduleparam.h>
-unsigned int ubi_chk_flags;
-unsigned int ubi_tst_flags;
-module_param_named(debug_chks, ubi_chk_flags, uint, S_IRUGO | S_IWUSR);
-module_param_named(debug_tsts, ubi_chk_flags, uint, S_IRUGO | S_IWUSR);
+/**
+ * ubi_dump_flash - dump a region of flash.
+ * @ubi: UBI device description object
+ * @pnum: the physical eraseblock number to dump
+ * @offset: the starting offset within the physical eraseblock to dump
+ * @len: the length of the region to dump
+ */
+void ubi_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len)
+{
+ int err;
+ size_t read;
+ void *buf;
+ loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
-MODULE_PARM_DESC(debug_chks, "Debug check flags");
-MODULE_PARM_DESC(debug_tsts, "Debug special test flags");
+ buf = vmalloc(len);
+ if (!buf)
+ return;
+ err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
+ if (err && err != -EUCLEAN) {
+ ubi_err("error %d while reading %d bytes from PEB %d:%d, "
+ "read %zd bytes", err, len, pnum, offset, read);
+ goto out;
+ }
+
+ ubi_msg("dumping %d bytes of data from PEB %d, offset %d",
+ len, pnum, offset);
+ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
+out:
+ vfree(buf);
+ return;
+}
/**
- * ubi_dbg_dump_ec_hdr - dump an erase counter header.
+ * ubi_dump_ec_hdr - dump an erase counter header.
* @ec_hdr: the erase counter header to dump
*/
-void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
+void ubi_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
{
printk(KERN_DEBUG "Erase counter header dump:\n");
printk(KERN_DEBUG "\tmagic %#08x\n",
@@ -65,10 +82,10 @@
}
/**
- * ubi_dbg_dump_vid_hdr - dump a volume identifier header.
+ * ubi_dump_vid_hdr - dump a volume identifier header.
* @vid_hdr: the volume identifier header to dump
*/
-void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
+void ubi_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
{
printk(KERN_DEBUG "Volume identifier header dump:\n");
printk(KERN_DEBUG "\tmagic %08x\n", be32_to_cpu(vid_hdr->magic));
@@ -90,10 +107,10 @@
}
/**
- * ubi_dbg_dump_vol_info- dump volume information.
+ * ubi_dump_vol_info - dump volume information.
* @vol: UBI volume description object
*/
-void ubi_dbg_dump_vol_info(const struct ubi_volume *vol)
+void ubi_dump_vol_info(const struct ubi_volume *vol)
{
printk(KERN_DEBUG "Volume information dump:\n");
printk(KERN_DEBUG "\tvol_id %d\n", vol->vol_id);
@@ -120,11 +137,11 @@
}
/**
- * ubi_dbg_dump_vtbl_record - dump a &struct ubi_vtbl_record object.
+ * ubi_dump_vtbl_record - dump a &struct ubi_vtbl_record object.
* @r: the object to dump
* @idx: volume table index
*/
-void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
+void ubi_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx)
{
int name_len = be16_to_cpu(r->name_len);
@@ -154,44 +171,44 @@
}
/**
- * ubi_dbg_dump_sv - dump a &struct ubi_scan_volume object.
- * @sv: the object to dump
+ * ubi_dump_av - dump a &struct ubi_ainf_volume object.
+ * @av: the object to dump
*/
-void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv)
+void ubi_dump_av(const struct ubi_ainf_volume *av)
{
- printk(KERN_DEBUG "Volume scanning information dump:\n");
- printk(KERN_DEBUG "\tvol_id %d\n", sv->vol_id);
- printk(KERN_DEBUG "\thighest_lnum %d\n", sv->highest_lnum);
- printk(KERN_DEBUG "\tleb_count %d\n", sv->leb_count);
- printk(KERN_DEBUG "\tcompat %d\n", sv->compat);
- printk(KERN_DEBUG "\tvol_type %d\n", sv->vol_type);
- printk(KERN_DEBUG "\tused_ebs %d\n", sv->used_ebs);
- printk(KERN_DEBUG "\tlast_data_size %d\n", sv->last_data_size);
- printk(KERN_DEBUG "\tdata_pad %d\n", sv->data_pad);
+ printk(KERN_DEBUG "Volume attaching information dump:\n");
+ printk(KERN_DEBUG "\tvol_id %d\n", av->vol_id);
+ printk(KERN_DEBUG "\thighest_lnum %d\n", av->highest_lnum);
+ printk(KERN_DEBUG "\tleb_count %d\n", av->leb_count);
+ printk(KERN_DEBUG "\tcompat %d\n", av->compat);
+ printk(KERN_DEBUG "\tvol_type %d\n", av->vol_type);
+ printk(KERN_DEBUG "\tused_ebs %d\n", av->used_ebs);
+ printk(KERN_DEBUG "\tlast_data_size %d\n", av->last_data_size);
+ printk(KERN_DEBUG "\tdata_pad %d\n", av->data_pad);
}
/**
- * ubi_dbg_dump_seb - dump a &struct ubi_scan_leb object.
- * @seb: the object to dump
+ * ubi_dump_aeb - dump a &struct ubi_ainf_peb object.
+ * @aeb: the object to dump
* @type: object type: 0 - not corrupted, 1 - corrupted
*/
-void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type)
+void ubi_dump_aeb(const struct ubi_ainf_peb *aeb, int type)
{
- printk(KERN_DEBUG "eraseblock scanning information dump:\n");
- printk(KERN_DEBUG "\tec %d\n", seb->ec);
- printk(KERN_DEBUG "\tpnum %d\n", seb->pnum);
+ printk(KERN_DEBUG "eraseblock attaching information dump:\n");
+ printk(KERN_DEBUG "\tec %d\n", aeb->ec);
+ printk(KERN_DEBUG "\tpnum %d\n", aeb->pnum);
if (type == 0) {
- printk(KERN_DEBUG "\tlnum %d\n", seb->lnum);
- printk(KERN_DEBUG "\tscrub %d\n", seb->scrub);
- printk(KERN_DEBUG "\tsqnum %llu\n", seb->sqnum);
+ printk(KERN_DEBUG "\tlnum %d\n", aeb->lnum);
+ printk(KERN_DEBUG "\tscrub %d\n", aeb->scrub);
+ printk(KERN_DEBUG "\tsqnum %llu\n", aeb->sqnum);
}
}
/**
- * ubi_dbg_dump_mkvol_req - dump a &struct ubi_mkvol_req object.
+ * ubi_dump_mkvol_req - dump a &struct ubi_mkvol_req object.
* @req: the object to dump
*/
-void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req)
+void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req)
{
char nm[17];
@@ -208,35 +225,268 @@
}
/**
- * ubi_dbg_dump_flash - dump a region of flash.
+ * ubi_debugging_init_dev - initialize debugging for an UBI device.
* @ubi: UBI device description object
- * @pnum: the physical eraseblock number to dump
- * @offset: the starting offset within the physical eraseblock to dump
- * @len: the length of the region to dump
+ *
+ * This function initializes debugging-related data for UBI device @ubi.
+ * Returns zero in case of success and a negative error code in case of
+ * failure.
*/
-void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len)
+int ubi_debugging_init_dev(struct ubi_device *ubi)
{
- int err;
- size_t read;
- void *buf;
- loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
+ ubi->dbg = kzalloc(sizeof(struct ubi_debug_info), GFP_KERNEL);
+ if (!ubi->dbg)
+ return -ENOMEM;
- buf = vmalloc(len);
- if (!buf)
- return;
- err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
- if (err && err != -EUCLEAN) {
- ubi_err("error %d while reading %d bytes from PEB %d:%d, "
- "read %zd bytes", err, len, pnum, offset, read);
+ return 0;
+}
+
+/**
+ * ubi_debugging_exit_dev - free debugging data for an UBI device.
+ * @ubi: UBI device description object
+ */
+void ubi_debugging_exit_dev(struct ubi_device *ubi)
+{
+ kfree(ubi->dbg);
+}
+
+/*
+ * Root directory for UBI stuff in debugfs. Contains sub-directories which
+ * contain the stuff specific to particular UBI devices.
+ */
+static struct dentry *dfs_rootdir;
+
+/**
+ * ubi_debugfs_init - create UBI debugfs directory.
+ *
+ * Create UBI debugfs directory. Returns zero in case of success and a negative
+ * error code in case of failure.
+ */
+int ubi_debugfs_init(void)
+{
+#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEBUG_FS_MODULE)
+ dfs_rootdir = debugfs_create_dir("ubi", NULL);
+ if (IS_ERR_OR_NULL(dfs_rootdir)) {
+ int err = dfs_rootdir ? -ENODEV : PTR_ERR(dfs_rootdir);
+
+ ubi_err("cannot create \"ubi\" debugfs directory, error %d\n",
+ err);
+ return err;
+ }
+#endif
+
+ return 0;
+}
+
+/**
+ * ubi_debugfs_exit - remove UBI debugfs directory.
+ */
+void ubi_debugfs_exit(void)
+{
+#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEBUG_FS_MODULE)
+ debugfs_remove(dfs_rootdir);
+#endif
+}
+
+/* Read an UBI debugfs file */
+static ssize_t dfs_file_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long ubi_num = (unsigned long)file->private_data;
+ struct dentry *dent = file->f_path.dentry;
+ struct ubi_device *ubi;
+ struct ubi_debug_info *d;
+ char buf[3];
+ int val;
+
+ ubi = ubi_get_device(ubi_num);
+ if (!ubi)
+ return -ENODEV;
+ d = ubi->dbg;
+
+ if (dent == d->dfs_chk_gen)
+ val = d->chk_gen;
+ else if (dent == d->dfs_chk_io)
+ val = d->chk_io;
+ else if (dent == d->dfs_disable_bgt)
+ val = d->disable_bgt;
+ else if (dent == d->dfs_emulate_bitflips)
+ val = d->emulate_bitflips;
+ else if (dent == d->dfs_emulate_io_failures)
+ val = d->emulate_io_failures;
+ else {
+ count = -EINVAL;
goto out;
}
- dbg_msg("dumping %d bytes of data from PEB %d, offset %d",
- len, pnum, offset);
- print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
+ if (val)
+ buf[0] = '1';
+ else
+ buf[0] = '0';
+ buf[1] = '\n';
+ buf[2] = 0x00;
+
+ count = simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+
out:
- vfree(buf);
- return;
+ ubi_put_device(ubi);
+ return count;
}
-#endif /* CONFIG_MTD_UBI_DEBUG */
+/* Write an UBI debugfs file */
+static ssize_t dfs_file_write(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long ubi_num = (unsigned long)file->private_data;
+ struct dentry *dent = file->f_path.dentry;
+ struct ubi_device *ubi;
+ struct ubi_debug_info *d;
+ size_t buf_size;
+ char buf[8];
+ int val;
+
+ ubi = ubi_get_device(ubi_num);
+ if (!ubi)
+ return -ENODEV;
+ d = ubi->dbg;
+
+ buf_size = min_t(size_t, count, (sizeof(buf) - 1));
+ if (copy_from_user(buf, user_buf, buf_size)) {
+ count = -EFAULT;
+ goto out;
+ }
+
+ if (buf[0] == '1')
+ val = 1;
+ else if (buf[0] == '0')
+ val = 0;
+ else {
+ count = -EINVAL;
+ goto out;
+ }
+
+ if (dent == d->dfs_chk_gen)
+ d->chk_gen = val;
+ else if (dent == d->dfs_chk_io)
+ d->chk_io = val;
+ else if (dent == d->dfs_disable_bgt)
+ d->disable_bgt = val;
+ else if (dent == d->dfs_emulate_bitflips)
+ d->emulate_bitflips = val;
+ else if (dent == d->dfs_emulate_io_failures)
+ d->emulate_io_failures = val;
+ else
+ count = -EINVAL;
+
+out:
+ ubi_put_device(ubi);
+ return count;
+}
+
+static int default_open(struct inode *inode, struct file *file)
+{
+ if (inode->i_private)
+ file->private_data = inode->i_private;
+
+ return 0;
+}
+
+/* File operations for all UBI debugfs files */
+static const struct file_operations dfs_fops = {
+ .read = dfs_file_read,
+ .write = dfs_file_write,
+ .open = default_open,
+ .llseek = no_llseek,
+ .owner = THIS_MODULE,
+};
+
+/**
+ * ubi_debugfs_init_dev - initialize debugfs for an UBI device.
+ * @ubi: UBI device description object
+ *
+ * This function creates all debugfs files for UBI device @ubi. Returns zero in
+ * case of success and a negative error code in case of failure.
+ */
+int ubi_debugfs_init_dev(struct ubi_device *ubi)
+{
+ int err, n;
+ unsigned long ubi_num = ubi->ubi_num;
+ const char *fname;
+ struct dentry *dent;
+ struct ubi_debug_info *d = ubi->dbg;
+
+#if !defined(CONFIG_DEBUG_FS) && !defined(CONFIG_DEBUG_FS_MODULE)
+ return 0;
+#endif
+
+ n = snprintf(d->dfs_dir_name, UBI_DFS_DIR_LEN + 1, UBI_DFS_DIR_NAME,
+ ubi->ubi_num);
+ if (n == UBI_DFS_DIR_LEN) {
+ /* The array size is too small */
+ fname = UBI_DFS_DIR_NAME;
+ dent = ERR_PTR(-EINVAL);
+ goto out;
+ }
+
+ fname = d->dfs_dir_name;
+ dent = debugfs_create_dir(fname, dfs_rootdir);
+ if (IS_ERR_OR_NULL(dent))
+ goto out;
+ d->dfs_dir = dent;
+
+ fname = "chk_gen";
+ dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_chk_gen = dent;
+
+ fname = "chk_io";
+ dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_chk_io = dent;
+
+ fname = "tst_disable_bgt";
+ dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_disable_bgt = dent;
+
+ fname = "tst_emulate_bitflips";
+ dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_emulate_bitflips = dent;
+
+ fname = "tst_emulate_io_failures";
+ dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, (void *)ubi_num,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_emulate_io_failures = dent;
+
+ return 0;
+
+out_remove:
+ debugfs_remove_recursive(d->dfs_dir);
+out:
+ err = dent ? PTR_ERR(dent) : -ENODEV;
+ ubi_err("cannot create \"%s\" debugfs file or directory, error %d\n",
+ fname, err);
+ return err;
+}
+
+/**
+ * dbg_debug_exit_dev - free all debugfs files corresponding to device @ubi
+ * @ubi: UBI device description object
+ */
+void ubi_debugfs_exit_dev(struct ubi_device *ubi)
+{
+#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEBUG_FS_MODULE)
+ debugfs_remove_recursive(ubi->dbg->dfs_dir);
+#endif
+}
diff -uN -uNr linux-3.0/drivers/mtd/ubi/debug.h linux-3.0.x.ubifs.latest/drivers/mtd/ubi/debug.h
--- linux-3.0/drivers/mtd/ubi/debug.h 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/debug.h 2012-06-28 11:26:15.000000000 -0500
@@ -21,29 +21,20 @@
#ifndef __UBI_DEBUG_H__
#define __UBI_DEBUG_H__
-struct ubi_ec_hdr;
-struct ubi_vid_hdr;
-struct ubi_volume;
-struct ubi_vtbl_record;
-struct ubi_scan_volume;
-struct ubi_scan_leb;
-struct ubi_mkvol_req;
+void ubi_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
+void ubi_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr);
+void ubi_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr);
-#ifdef CONFIG_MTD_UBI_DEBUG
#include <linux/random.h>
#define ubi_assert(expr) do { \
if (unlikely(!(expr))) { \
printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \
__func__, __LINE__, current->pid); \
- ubi_dbg_dump_stack(); \
+ dump_stack(); \
} \
} while (0)
-#define dbg_err(fmt, ...) ubi_err(fmt, ##__VA_ARGS__)
-
-#define ubi_dbg_dump_stack() dump_stack()
-
#define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a) \
print_hex_dump(l, ps, pt, r, g, b, len, a)
@@ -51,7 +42,10 @@
pr_debug("UBI DBG " type ": " fmt "\n", ##__VA_ARGS__)
/* Just a debugging messages not related to any specific UBI subsystem */
-#define dbg_msg(fmt, ...) ubi_dbg_msg("msg", fmt, ##__VA_ARGS__)
+#define dbg_msg(fmt, ...) \
+ printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \
+ current->pid, __func__, ##__VA_ARGS__)
+
/* General debugging messages */
#define dbg_gen(fmt, ...) ubi_dbg_msg("gen", fmt, ##__VA_ARGS__)
/* Messages from the eraseblock association sub-system */
@@ -63,155 +57,109 @@
/* Initialization and build messages */
#define dbg_bld(fmt, ...) ubi_dbg_msg("bld", fmt, ##__VA_ARGS__)
-void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr);
-void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr);
-void ubi_dbg_dump_vol_info(const struct ubi_volume *vol);
-void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx);
-void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv);
-void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type);
-void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
-void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
-
-extern unsigned int ubi_chk_flags;
+void ubi_dump_vol_info(const struct ubi_volume *vol);
+void ubi_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx);
+void ubi_dump_av(const struct ubi_ainf_volume *av);
+void ubi_dump_aeb(const struct ubi_ainf_peb *aeb, int type);
+void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req);
+int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset,
+ int len);
+int ubi_debugging_init_dev(struct ubi_device *ubi);
+void ubi_debugging_exit_dev(struct ubi_device *ubi);
+int ubi_debugfs_init(void);
+void ubi_debugfs_exit(void);
+int ubi_debugfs_init_dev(struct ubi_device *ubi);
+void ubi_debugfs_exit_dev(struct ubi_device *ubi);
/*
- * Debugging check flags.
- *
- * UBI_CHK_GEN: general checks
- * UBI_CHK_IO: check writes and erases
+ * The UBI debugfs directory name pattern and maximum name length (3 for "ubi"
+ * + 2 for the number plus 1 for the trailing zero byte.
*/
-enum {
- UBI_CHK_GEN = 0x1,
- UBI_CHK_IO = 0x2,
-};
+#define UBI_DFS_DIR_NAME "ubi%d"
+#define UBI_DFS_DIR_LEN (3 + 2 + 1)
-int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len);
-int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
- int offset, int len);
-
-extern unsigned int ubi_tst_flags;
-
-/*
- * Special testing flags.
+/**
+ * struct ubi_debug_info - debugging information for an UBI device.
*
- * UBIFS_TST_DISABLE_BGT: disable the background thread
- * UBI_TST_EMULATE_BITFLIPS: emulate bit-flips
- * UBI_TST_EMULATE_WRITE_FAILURES: emulate write failures
- * UBI_TST_EMULATE_ERASE_FAILURES: emulate erase failures
- */
-enum {
- UBI_TST_DISABLE_BGT = 0x1,
- UBI_TST_EMULATE_BITFLIPS = 0x2,
- UBI_TST_EMULATE_WRITE_FAILURES = 0x4,
- UBI_TST_EMULATE_ERASE_FAILURES = 0x8,
+ * @chk_gen: if UBI general extra checks are enabled
+ * @chk_io: if UBI I/O extra checks are enabled
+ * @disable_bgt: disable the background task for testing purposes
+ * @emulate_bitflips: emulate bit-flips for testing purposes
+ * @emulate_io_failures: emulate write/erase failures for testing purposes
+ * @dfs_dir_name: name of debugfs directory containing files of this UBI device
+ * @dfs_dir: direntry object of the UBI device debugfs directory
+ * @dfs_chk_gen: debugfs knob to enable UBI general extra checks
+ * @dfs_chk_io: debugfs knob to enable UBI I/O extra checks
+ * @dfs_disable_bgt: debugfs knob to disable the background task
+ * @dfs_emulate_bitflips: debugfs knob to emulate bit-flips
+ * @dfs_emulate_io_failures: debugfs knob to emulate write/erase failures
+ */
+struct ubi_debug_info {
+ unsigned int chk_gen:1;
+ unsigned int chk_io:1;
+ unsigned int disable_bgt:1;
+ unsigned int emulate_bitflips:1;
+ unsigned int emulate_io_failures:1;
+ char dfs_dir_name[UBI_DFS_DIR_LEN + 1];
+ struct dentry *dfs_dir;
+ struct dentry *dfs_chk_gen;
+ struct dentry *dfs_chk_io;
+ struct dentry *dfs_disable_bgt;
+ struct dentry *dfs_emulate_bitflips;
+ struct dentry *dfs_emulate_io_failures;
};
/**
* ubi_dbg_is_bgt_disabled - if the background thread is disabled.
+ * @ubi: UBI device description object
*
* Returns non-zero if the UBI background thread is disabled for testing
* purposes.
*/
-static inline int ubi_dbg_is_bgt_disabled(void)
+static inline int ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi)
{
- return ubi_tst_flags & UBI_TST_DISABLE_BGT;
+ return ubi->dbg->disable_bgt;
}
/**
* ubi_dbg_is_bitflip - if it is time to emulate a bit-flip.
+ * @ubi: UBI device description object
*
* Returns non-zero if a bit-flip should be emulated, otherwise returns zero.
*/
-static inline int ubi_dbg_is_bitflip(void)
+static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi)
{
- if (ubi_tst_flags & UBI_TST_EMULATE_BITFLIPS)
+ if (ubi->dbg->emulate_bitflips)
return !(random32() % 200);
return 0;
}
/**
* ubi_dbg_is_write_failure - if it is time to emulate a write failure.
+ * @ubi: UBI device description object
*
* Returns non-zero if a write failure should be emulated, otherwise returns
* zero.
*/
-static inline int ubi_dbg_is_write_failure(void)
+static inline int ubi_dbg_is_write_failure(const struct ubi_device *ubi)
{
- if (ubi_tst_flags & UBI_TST_EMULATE_WRITE_FAILURES)
+ if (ubi->dbg->emulate_io_failures)
return !(random32() % 500);
return 0;
}
/**
* ubi_dbg_is_erase_failure - if its time to emulate an erase failure.
+ * @ubi: UBI device description object
*
* Returns non-zero if an erase failure should be emulated, otherwise returns
* zero.
*/
-static inline int ubi_dbg_is_erase_failure(void)
+static inline int ubi_dbg_is_erase_failure(const struct ubi_device *ubi)
{
- if (ubi_tst_flags & UBI_TST_EMULATE_ERASE_FAILURES)
+ if (ubi->dbg->emulate_io_failures)
return !(random32() % 400);
return 0;
}
-#else
-
-/* Use "if (0)" to make compiler check arguments even if debugging is off */
-#define ubi_assert(expr) do { \
- if (0) { \
- printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \
- __func__, __LINE__, current->pid); \
- } \
-} while (0)
-
-#define dbg_err(fmt, ...) do { \
- if (0) \
- ubi_err(fmt, ##__VA_ARGS__); \
-} while (0)
-
-#define ubi_dbg_msg(fmt, ...) do { \
- if (0) \
- pr_debug(fmt "\n", ##__VA_ARGS__); \
-} while (0)
-
-#define dbg_msg(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_gen(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_eba(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_wl(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_io(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_bld(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__)
-
-static inline void ubi_dbg_dump_stack(void) { return; }
-static inline void
-ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) { return; }
-static inline void
-ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr) { return; }
-static inline void
-ubi_dbg_dump_vol_info(const struct ubi_volume *vol) { return; }
-static inline void
-ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx) { return; }
-static inline void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv) { return; }
-static inline void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb,
- int type) { return; }
-static inline void
-ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req) { return; }
-static inline void ubi_dbg_dump_flash(struct ubi_device *ubi,
- int pnum, int offset, int len) { return; }
-static inline void
-ubi_dbg_print_hex_dump(const char *l, const char *ps, int pt, int r,
- int g, const void *b, size_t len, bool a) { return; }
-
-static inline int ubi_dbg_is_bgt_disabled(void) { return 0; }
-static inline int ubi_dbg_is_bitflip(void) { return 0; }
-static inline int ubi_dbg_is_write_failure(void) { return 0; }
-static inline int ubi_dbg_is_erase_failure(void) { return 0; }
-static inline int ubi_dbg_check_all_ff(struct ubi_device *ubi,
- int pnum, int offset,
- int len) { return 0; }
-static inline int ubi_dbg_check_write(struct ubi_device *ubi,
- const void *buf, int pnum,
- int offset, int len) { return 0; }
-
-#endif /* !CONFIG_MTD_UBI_DEBUG */
#endif /* !__UBI_DEBUG_H__ */
diff -uN -uNr linux-3.0/drivers/mtd/ubi/eba.c linux-3.0.x.ubifs.latest/drivers/mtd/ubi/eba.c
--- linux-3.0/drivers/mtd/ubi/eba.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/eba.c 2012-06-28 11:26:15.000000000 -0500
@@ -341,7 +341,7 @@
dbg_eba("erase LEB %d:%d, PEB %d", vol_id, lnum, pnum);
vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED;
- err = ubi_wl_put_peb(ubi, pnum, 0);
+ err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 0);
out_unlock:
leb_write_unlock(ubi, vol_id, lnum);
@@ -507,7 +507,7 @@
return -ENOMEM;
retry:
- new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN);
+ new_pnum = ubi_wl_get_peb(ubi);
if (new_pnum < 0) {
ubi_free_vid_hdr(ubi, vid_hdr);
return new_pnum;
@@ -529,18 +529,18 @@
data_size = offset + len;
mutex_lock(&ubi->buf_mutex);
- memset(ubi->peb_buf1 + offset, 0xFF, len);
+ memset(ubi->peb_buf + offset, 0xFF, len);
/* Read everything before the area where the write failure happened */
if (offset > 0) {
- err = ubi_io_read_data(ubi, ubi->peb_buf1, pnum, 0, offset);
+ err = ubi_io_read_data(ubi, ubi->peb_buf, pnum, 0, offset);
if (err && err != UBI_IO_BITFLIPS)
goto out_unlock;
}
- memcpy(ubi->peb_buf1 + offset, buf, len);
+ memcpy(ubi->peb_buf + offset, buf, len);
- err = ubi_io_write_data(ubi, ubi->peb_buf1, new_pnum, 0, data_size);
+ err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size);
if (err) {
mutex_unlock(&ubi->buf_mutex);
goto write_error;
@@ -550,7 +550,7 @@
ubi_free_vid_hdr(ubi, vid_hdr);
vol->eba_tbl[lnum] = new_pnum;
- ubi_wl_put_peb(ubi, pnum, 1);
+ ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
ubi_msg("data was successfully recovered");
return 0;
@@ -558,7 +558,7 @@
out_unlock:
mutex_unlock(&ubi->buf_mutex);
out_put:
- ubi_wl_put_peb(ubi, new_pnum, 1);
+ ubi_wl_put_peb(ubi, vol_id, lnum, new_pnum, 1);
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
@@ -568,7 +568,7 @@
* get another one.
*/
ubi_warn("failed to write to PEB %d", new_pnum);
- ubi_wl_put_peb(ubi, new_pnum, 1);
+ ubi_wl_put_peb(ubi, vol_id, lnum, new_pnum, 1);
if (++tries > UBI_IO_RETRIES) {
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
@@ -585,7 +585,6 @@
* @buf: the data to write
* @offset: offset within the logical eraseblock where to write
* @len: how many bytes to write
- * @dtype: data type
*
* This function writes data to logical eraseblock @lnum of a dynamic volume
* @vol. Returns zero in case of success and a negative error code in case
@@ -593,7 +592,7 @@
* written to the flash media, but may be some garbage.
*/
int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
- const void *buf, int offset, int len, int dtype)
+ const void *buf, int offset, int len)
{
int err, pnum, tries = 0, vol_id = vol->vol_id;
struct ubi_vid_hdr *vid_hdr;
@@ -641,7 +640,7 @@
vid_hdr->data_pad = cpu_to_be32(vol->data_pad);
retry:
- pnum = ubi_wl_get_peb(ubi, dtype);
+ pnum = ubi_wl_get_peb(ubi);
if (pnum < 0) {
ubi_free_vid_hdr(ubi, vid_hdr);
leb_write_unlock(ubi, vol_id, lnum);
@@ -687,7 +686,7 @@
* eraseblock, so just put it and request a new one. We assume that if
* this physical eraseblock went bad, the erase code will handle that.
*/
- err = ubi_wl_put_peb(ubi, pnum, 1);
+ err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
if (err || ++tries > UBI_IO_RETRIES) {
ubi_ro_mode(ubi);
leb_write_unlock(ubi, vol_id, lnum);
@@ -707,7 +706,6 @@
* @lnum: logical eraseblock number
* @buf: data to write
* @len: how many bytes to write
- * @dtype: data type
* @used_ebs: how many logical eraseblocks will this volume contain
*
* This function writes data to logical eraseblock @lnum of static volume
@@ -724,8 +722,7 @@
* code in case of failure.
*/
int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
- int lnum, const void *buf, int len, int dtype,
- int used_ebs)
+ int lnum, const void *buf, int len, int used_ebs)
{
int err, pnum, tries = 0, data_size = len, vol_id = vol->vol_id;
struct ubi_vid_hdr *vid_hdr;
@@ -763,7 +760,7 @@
vid_hdr->data_crc = cpu_to_be32(crc);
retry:
- pnum = ubi_wl_get_peb(ubi, dtype);
+ pnum = ubi_wl_get_peb(ubi);
if (pnum < 0) {
ubi_free_vid_hdr(ubi, vid_hdr);
leb_write_unlock(ubi, vol_id, lnum);
@@ -807,7 +804,7 @@
return err;
}
- err = ubi_wl_put_peb(ubi, pnum, 1);
+ err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
if (err || ++tries > UBI_IO_RETRIES) {
ubi_ro_mode(ubi);
leb_write_unlock(ubi, vol_id, lnum);
@@ -827,7 +824,6 @@
* @lnum: logical eraseblock number
* @buf: data to write
* @len: how many bytes to write
- * @dtype: data type
*
* This function changes the contents of a logical eraseblock atomically. @buf
* has to contain new logical eraseblock data, and @len - the length of the
@@ -839,7 +835,7 @@
* LEB change may be done at a time. This is ensured by @ubi->alc_mutex.
*/
int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
- int lnum, const void *buf, int len, int dtype)
+ int lnum, const void *buf, int len)
{
int err, pnum, tries = 0, vol_id = vol->vol_id;
struct ubi_vid_hdr *vid_hdr;
@@ -856,7 +852,7 @@
err = ubi_eba_unmap_leb(ubi, vol, lnum);
if (err)
return err;
- return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0, dtype);
+ return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0);
}
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
@@ -881,7 +877,7 @@
vid_hdr->data_crc = cpu_to_be32(crc);
retry:
- pnum = ubi_wl_get_peb(ubi, dtype);
+ pnum = ubi_wl_get_peb(ubi);
if (pnum < 0) {
err = pnum;
goto out_leb_unlock;
@@ -905,7 +901,7 @@
}
if (vol->eba_tbl[lnum] >= 0) {
- err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 0);
+ err = ubi_wl_put_peb(ubi, vol_id, lnum, vol->eba_tbl[lnum], 0);
if (err)
goto out_leb_unlock;
}
@@ -930,7 +926,7 @@
goto out_leb_unlock;
}
- err = ubi_wl_put_peb(ubi, pnum, 1);
+ err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
if (err || ++tries > UBI_IO_RETRIES) {
ubi_ro_mode(ubi);
goto out_leb_unlock;
@@ -979,7 +975,7 @@
* physical eraseblock @to. The @vid_hdr buffer may be changed by this
* function. Returns:
* o %0 in case of success;
- * o %MOVE_CANCEL_RACE, %MOVE_TARGET_WR_ERR, %MOVE_CANCEL_BITFLIPS, etc;
+ * o %MOVE_CANCEL_RACE, %MOVE_TARGET_WR_ERR, %MOVE_TARGET_BITFLIPS, etc;
* o a negative error code in case of failure.
*/
int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
@@ -1028,12 +1024,14 @@
* 'ubi_wl_put_peb()' function on the @ubi->move_mutex. In turn, we are
* holding @ubi->move_mutex and go sleep on the LEB lock. So, if the
* LEB is already locked, we just do not move it and return
- * %MOVE_CANCEL_RACE, which means that UBI will re-try, but later.
+ * %MOVE_RETRY. Note, we do not return %MOVE_CANCEL_RACE here because
+ * we do not know the reasons of the contention - it may be just a
+ * normal I/O on this LEB, so we want to re-try.
*/
err = leb_write_trylock(ubi, vol_id, lnum);
if (err) {
dbg_wl("contention on LEB %d:%d, cancel", vol_id, lnum);
- return MOVE_CANCEL_RACE;
+ return MOVE_RETRY;
}
/*
@@ -1051,13 +1049,13 @@
/*
* OK, now the LEB is locked and we can safely start moving it. Since
- * this function utilizes the @ubi->peb_buf1 buffer which is shared
+ * this function utilizes the @ubi->peb_buf buffer which is shared
* with some other functions - we lock the buffer by taking the
* @ubi->buf_mutex.
*/
mutex_lock(&ubi->buf_mutex);
dbg_wl("read %d bytes of data", aldata_size);
- err = ubi_io_read_data(ubi, ubi->peb_buf1, from, 0, aldata_size);
+ err = ubi_io_read_data(ubi, ubi->peb_buf, from, 0, aldata_size);
if (err && err != UBI_IO_BITFLIPS) {
ubi_warn("error %d while reading data from PEB %d",
err, from);
@@ -1077,10 +1075,10 @@
*/
if (vid_hdr->vol_type == UBI_VID_DYNAMIC)
aldata_size = data_size =
- ubi_calc_data_len(ubi, ubi->peb_buf1, data_size);
+ ubi_calc_data_len(ubi, ubi->peb_buf, data_size);
cond_resched();
- crc = crc32(UBI_CRC32_INIT, ubi->peb_buf1, data_size);
+ crc = crc32(UBI_CRC32_INIT, ubi->peb_buf, data_size);
cond_resched();
/*
@@ -1114,12 +1112,12 @@
if (is_error_sane(err))
err = MOVE_TARGET_RD_ERR;
} else
- err = MOVE_CANCEL_BITFLIPS;
+ err = MOVE_TARGET_BITFLIPS;
goto out_unlock_buf;
}
if (data_size > 0) {
- err = ubi_io_write_data(ubi, ubi->peb_buf1, to, 0, aldata_size);
+ err = ubi_io_write_data(ubi, ubi->peb_buf, to, 0, aldata_size);
if (err) {
if (err == -EIO)
err = MOVE_TARGET_WR_ERR;
@@ -1132,8 +1130,8 @@
* We've written the data and are going to read it back to make
* sure it was written correctly.
*/
-
- err = ubi_io_read_data(ubi, ubi->peb_buf2, to, 0, aldata_size);
+ memset(ubi->peb_buf, 0xFF, aldata_size);
+ err = ubi_io_read_data(ubi, ubi->peb_buf, to, 0, aldata_size);
if (err) {
if (err != UBI_IO_BITFLIPS) {
ubi_warn("error %d while reading data back "
@@ -1141,13 +1139,13 @@
if (is_error_sane(err))
err = MOVE_TARGET_RD_ERR;
} else
- err = MOVE_CANCEL_BITFLIPS;
+ err = MOVE_TARGET_BITFLIPS;
goto out_unlock_buf;
}
cond_resched();
- if (memcmp(ubi->peb_buf1, ubi->peb_buf2, aldata_size)) {
+ if (crc != crc32(UBI_CRC32_INIT, ubi->peb_buf, data_size)) {
ubi_warn("read data back from PEB %d and it is "
"different", to);
err = -EINVAL;
@@ -1169,7 +1167,7 @@
* print_rsvd_warning - warn about not having enough reserved PEBs.
* @ubi: UBI device description object
*
- * This is a helper function for 'ubi_eba_init_scan()' which is called when UBI
+ * This is a helper function for 'ubi_eba_init()' which is called when UBI
* cannot reserve enough PEBs for bad block handling. This function makes a
* decision whether we have to print a warning or not. The algorithm is as
* follows:
@@ -1184,13 +1182,13 @@
* reported by real users.
*/
static void print_rsvd_warning(struct ubi_device *ubi,
- struct ubi_scan_info *si)
+ struct ubi_attach_info *ai)
{
/*
* The 1 << 18 (256KiB) number is picked randomly, just a reasonably
* large number to distinguish between newly flashed and used images.
*/
- if (si->max_sqnum > (1 << 18)) {
+ if (ai->max_sqnum > (1 << 18)) {
int min = ubi->beb_rsvd_level / 10;
if (!min)
@@ -1207,19 +1205,19 @@
}
/**
- * ubi_eba_init_scan - initialize the EBA sub-system using scanning information.
+ * ubi_eba_init - initialize the EBA sub-system using attaching information.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
*
* This function returns zero in case of success and a negative error code in
* case of failure.
*/
-int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
+int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
{
int i, j, err, num_volumes;
- struct ubi_scan_volume *sv;
+ struct ubi_ainf_volume *av;
struct ubi_volume *vol;
- struct ubi_scan_leb *seb;
+ struct ubi_ainf_peb *aeb;
struct rb_node *rb;
dbg_eba("initialize EBA sub-system");
@@ -1228,7 +1226,7 @@
mutex_init(&ubi->alc_mutex);
ubi->ltree = RB_ROOT;
- ubi->global_sqnum = si->max_sqnum + 1;
+ ubi->global_sqnum = ai->max_sqnum + 1;
num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT;
for (i = 0; i < num_volumes; i++) {
@@ -1248,18 +1246,18 @@
for (j = 0; j < vol->reserved_pebs; j++)
vol->eba_tbl[j] = UBI_LEB_UNMAPPED;
- sv = ubi_scan_find_sv(si, idx2vol_id(ubi, i));
- if (!sv)
+ av = ubi_find_av(ai, idx2vol_id(ubi, i));
+ if (!av)
continue;
- ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) {
- if (seb->lnum >= vol->reserved_pebs)
+ ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb) {
+ if (aeb->lnum >= vol->reserved_pebs)
/*
* This may happen in case of an unclean reboot
* during re-size.
*/
- ubi_scan_move_to_list(sv, seb, &si->erase);
- vol->eba_tbl[seb->lnum] = seb->pnum;
+ ubi_move_aeb_to_list(av, aeb, &ai->erase);
+ vol->eba_tbl[aeb->lnum] = aeb->pnum;
}
}
@@ -1281,7 +1279,7 @@
if (ubi->avail_pebs < ubi->beb_rsvd_level) {
/* No enough free physical eraseblocks */
ubi->beb_rsvd_pebs = ubi->avail_pebs;
- print_rsvd_warning(ubi, si);
+ print_rsvd_warning(ubi, ai);
} else
ubi->beb_rsvd_pebs = ubi->beb_rsvd_level;
diff -uN -uNr linux-3.0/drivers/mtd/ubi/gluebi.c linux-3.0.x.ubifs.latest/drivers/mtd/ubi/gluebi.c
--- linux-3.0/drivers/mtd/ubi/gluebi.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/gluebi.c 2012-06-28 11:26:15.000000000 -0500
@@ -238,7 +238,7 @@
if (to_write > total_written)
to_write = total_written;
- err = ubi_write(gluebi->desc, lnum, buf, offs, to_write);
+ err = ubi_leb_write(gluebi->desc, lnum, buf, offs, to_write);
if (err)
break;
diff -uN -uNr linux-3.0/drivers/mtd/ubi/io.c linux-3.0.x.ubifs.latest/drivers/mtd/ubi/io.c
--- linux-3.0/drivers/mtd/ubi/io.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/io.c 2012-06-28 11:26:15.000000000 -0500
@@ -91,21 +91,15 @@
#include <linux/slab.h>
#include "ubi.h"
-#ifdef CONFIG_MTD_UBI_DEBUG
-static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum);
-static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum);
-static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
- const struct ubi_ec_hdr *ec_hdr);
-static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum);
-static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
- const struct ubi_vid_hdr *vid_hdr);
-#else
-#define paranoid_check_not_bad(ubi, pnum) 0
-#define paranoid_check_peb_ec_hdr(ubi, pnum) 0
-#define paranoid_check_ec_hdr(ubi, pnum, ec_hdr) 0
-#define paranoid_check_peb_vid_hdr(ubi, pnum) 0
-#define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0
-#endif
+static int self_check_not_bad(const struct ubi_device *ubi, int pnum);
+static int self_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum);
+static int self_check_ec_hdr(const struct ubi_device *ubi, int pnum,
+ const struct ubi_ec_hdr *ec_hdr);
+static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum);
+static int self_check_vid_hdr(const struct ubi_device *ubi, int pnum,
+ const struct ubi_vid_hdr *vid_hdr);
+static int self_check_write(struct ubi_device *ubi, const void *buf, int pnum,
+ int offset, int len);
/**
* ubi_io_read - read data from a physical eraseblock.
@@ -142,7 +136,7 @@
ubi_assert(offset >= 0 && offset + len <= ubi->peb_size);
ubi_assert(len > 0);
- err = paranoid_check_not_bad(ubi, pnum);
+ err = self_check_not_bad(ubi, pnum);
if (err)
return err;
@@ -189,16 +183,16 @@
}
if (retries++ < UBI_IO_RETRIES) {
- dbg_io("error %d%s while reading %d bytes from PEB "
- "%d:%d, read only %zd bytes, retry",
- err, errstr, len, pnum, offset, read);
+ ubi_warn("error %d%s while reading %d bytes from PEB "
+ "%d:%d, read only %zd bytes, retry",
+ err, errstr, len, pnum, offset, read);
yield();
goto retry;
}
ubi_err("error %d%s while reading %d bytes from PEB %d:%d, "
"read %zd bytes", err, errstr, len, pnum, offset, read);
- ubi_dbg_dump_stack();
+ dump_stack();
/*
* The driver should never return -EBADMSG if it failed to read
@@ -212,7 +206,7 @@
} else {
ubi_assert(len == read);
- if (ubi_dbg_is_bitflip()) {
+ if (ubi_dbg_is_bitflip(ubi)) {
dbg_gen("bit-flip (emulated)");
err = UBI_IO_BITFLIPS;
}
@@ -257,14 +251,12 @@
return -EROFS;
}
- /* The below has to be compiled out if paranoid checks are disabled */
-
- err = paranoid_check_not_bad(ubi, pnum);
+ err = self_check_not_bad(ubi, pnum);
if (err)
return err;
/* The area we are writing to has to contain all 0xFF bytes */
- err = ubi_dbg_check_all_ff(ubi, pnum, offset, len);
+ err = ubi_self_check_all_ff(ubi, pnum, offset, len);
if (err)
return err;
@@ -273,18 +265,18 @@
* We write to the data area of the physical eraseblock. Make
* sure it has valid EC and VID headers.
*/
- err = paranoid_check_peb_ec_hdr(ubi, pnum);
+ err = self_check_peb_ec_hdr(ubi, pnum);
if (err)
return err;
- err = paranoid_check_peb_vid_hdr(ubi, pnum);
+ err = self_check_peb_vid_hdr(ubi, pnum);
if (err)
return err;
}
- if (ubi_dbg_is_write_failure()) {
- dbg_err("cannot write %d bytes to PEB %d:%d "
+ if (ubi_dbg_is_write_failure(ubi)) {
+ ubi_err("cannot write %d bytes to PEB %d:%d "
"(emulated)", len, pnum, offset);
- ubi_dbg_dump_stack();
+ dump_stack();
return -EIO;
}
@@ -293,13 +285,13 @@
if (err) {
ubi_err("error %d while writing %d bytes to PEB %d:%d, written "
"%zd bytes", err, len, pnum, offset, written);
- ubi_dbg_dump_stack();
- ubi_dbg_dump_flash(ubi, pnum, offset, len);
+ dump_stack();
+ ubi_dump_flash(ubi, pnum, offset, len);
} else
ubi_assert(written == len);
if (!err) {
- err = ubi_dbg_check_write(ubi, buf, pnum, offset, len);
+ err = self_check_write(ubi, buf, pnum, offset, len);
if (err)
return err;
@@ -310,7 +302,7 @@
offset += len;
len = ubi->peb_size - offset;
if (len)
- err = ubi_dbg_check_all_ff(ubi, pnum, offset, len);
+ err = ubi_self_check_all_ff(ubi, pnum, offset, len);
}
return err;
@@ -364,13 +356,13 @@
err = ubi->mtd->erase(ubi->mtd, &ei);
if (err) {
if (retries++ < UBI_IO_RETRIES) {
- dbg_io("error %d while erasing PEB %d, retry",
- err, pnum);
+ ubi_warn("error %d while erasing PEB %d, retry",
+ err, pnum);
yield();
goto retry;
}
ubi_err("cannot erase PEB %d, error %d", pnum, err);
- ubi_dbg_dump_stack();
+ dump_stack();
return err;
}
@@ -383,21 +375,21 @@
if (ei.state == MTD_ERASE_FAILED) {
if (retries++ < UBI_IO_RETRIES) {
- dbg_io("error while erasing PEB %d, retry", pnum);
+ ubi_warn("error while erasing PEB %d, retry", pnum);
yield();
goto retry;
}
ubi_err("cannot erase PEB %d", pnum);
- ubi_dbg_dump_stack();
+ dump_stack();
return -EIO;
}
- err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size);
+ err = ubi_self_check_all_ff(ubi, pnum, 0, ubi->peb_size);
if (err)
return err;
- if (ubi_dbg_is_erase_failure()) {
- dbg_err("cannot erase PEB %d (emulated)", pnum);
+ if (ubi_dbg_is_erase_failure(ubi)) {
+ ubi_err("cannot erase PEB %d (emulated)", pnum);
return -EIO;
}
@@ -431,11 +423,11 @@
goto out;
/* Make sure the PEB contains only 0xFF bytes */
- err = ubi_io_read(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size);
+ err = ubi_io_read(ubi, ubi->peb_buf, pnum, 0, ubi->peb_size);
if (err)
goto out;
- err = ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size);
+ err = ubi_check_pattern(ubi->peb_buf, 0xFF, ubi->peb_size);
if (err == 0) {
ubi_err("erased PEB %d, but a non-0xFF byte found",
pnum);
@@ -444,17 +436,17 @@
}
/* Write a pattern and check it */
- memset(ubi->peb_buf1, patterns[i], ubi->peb_size);
- err = ubi_io_write(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size);
+ memset(ubi->peb_buf, patterns[i], ubi->peb_size);
+ err = ubi_io_write(ubi, ubi->peb_buf, pnum, 0, ubi->peb_size);
if (err)
goto out;
- memset(ubi->peb_buf1, ~patterns[i], ubi->peb_size);
- err = ubi_io_read(ubi, ubi->peb_buf1, pnum, 0, ubi->peb_size);
+ memset(ubi->peb_buf, ~patterns[i], ubi->peb_size);
+ err = ubi_io_read(ubi, ubi->peb_buf, pnum, 0, ubi->peb_size);
if (err)
goto out;
- err = ubi_check_pattern(ubi->peb_buf1, patterns[i],
+ err = ubi_check_pattern(ubi->peb_buf, patterns[i],
ubi->peb_size);
if (err == 0) {
ubi_err("pattern %x checking failed for PEB %d",
@@ -521,8 +513,7 @@
* It is important to first invalidate the EC header, and then the VID
* header. Otherwise a power cut may lead to valid EC header and
* invalid VID header, in which case UBI will treat this PEB as
- * corrupted and will try to preserve it, and print scary warnings (see
- * the header comment in scan.c for more information).
+ * corrupted and will try to preserve it, and print scary warnings.
*/
addr = (loff_t)pnum * ubi->peb_size;
err = ubi->mtd->write(ubi->mtd, addr, 4, &written, (void *)&data);
@@ -564,7 +555,7 @@
*/
ubi_err("cannot invalidate PEB %d, write returned %d read returned %d",
pnum, err, err1);
- ubi_dbg_dump_flash(ubi, pnum, 0, ubi->peb_size);
+ ubi_dump_flash(ubi, pnum, 0, ubi->peb_size);
return -EIO;
}
@@ -590,7 +581,7 @@
ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
- err = paranoid_check_not_bad(ubi, pnum);
+ err = self_check_not_bad(ubi, pnum);
if (err != 0)
return err;
@@ -722,8 +713,8 @@
bad:
ubi_err("bad EC header");
- ubi_dbg_dump_ec_hdr(ec_hdr);
- ubi_dbg_dump_stack();
+ ubi_dump_ec_hdr(ec_hdr);
+ dump_stack();
return 1;
}
@@ -804,7 +795,7 @@
if (verbose) {
ubi_warn("bad magic number at PEB %d: %08x instead of "
"%08x", pnum, magic, UBI_EC_HDR_MAGIC);
- ubi_dbg_dump_ec_hdr(ec_hdr);
+ ubi_dump_ec_hdr(ec_hdr);
}
dbg_bld("bad magic number at PEB %d: %08x instead of "
"%08x", pnum, magic, UBI_EC_HDR_MAGIC);
@@ -818,7 +809,7 @@
if (verbose) {
ubi_warn("bad EC header CRC at PEB %d, calculated "
"%#08x, read %#08x", pnum, crc, hdr_crc);
- ubi_dbg_dump_ec_hdr(ec_hdr);
+ ubi_dump_ec_hdr(ec_hdr);
}
dbg_bld("bad EC header CRC at PEB %d, calculated "
"%#08x, read %#08x", pnum, crc, hdr_crc);
@@ -875,7 +866,7 @@
crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
ec_hdr->hdr_crc = cpu_to_be32(crc);
- err = paranoid_check_ec_hdr(ubi, pnum, ec_hdr);
+ err = self_check_ec_hdr(ubi, pnum, ec_hdr);
if (err)
return err;
@@ -906,40 +897,40 @@
int usable_leb_size = ubi->leb_size - data_pad;
if (copy_flag != 0 && copy_flag != 1) {
- dbg_err("bad copy_flag");
+ ubi_err("bad copy_flag");
goto bad;
}
if (vol_id < 0 || lnum < 0 || data_size < 0 || used_ebs < 0 ||
data_pad < 0) {
- dbg_err("negative values");
+ ubi_err("negative values");
goto bad;
}
if (vol_id >= UBI_MAX_VOLUMES && vol_id < UBI_INTERNAL_VOL_START) {
- dbg_err("bad vol_id");
+ ubi_err("bad vol_id");
goto bad;
}
if (vol_id < UBI_INTERNAL_VOL_START && compat != 0) {
- dbg_err("bad compat");
+ ubi_err("bad compat");
goto bad;
}
if (vol_id >= UBI_INTERNAL_VOL_START && compat != UBI_COMPAT_DELETE &&
compat != UBI_COMPAT_RO && compat != UBI_COMPAT_PRESERVE &&
compat != UBI_COMPAT_REJECT) {
- dbg_err("bad compat");
+ ubi_err("bad compat");
goto bad;
}
if (vol_type != UBI_VID_DYNAMIC && vol_type != UBI_VID_STATIC) {
- dbg_err("bad vol_type");
+ ubi_err("bad vol_type");
goto bad;
}
if (data_pad >= ubi->leb_size / 2) {
- dbg_err("bad data_pad");
+ ubi_err("bad data_pad");
goto bad;
}
@@ -951,45 +942,45 @@
* mapped logical eraseblocks.
*/
if (used_ebs == 0) {
- dbg_err("zero used_ebs");
+ ubi_err("zero used_ebs");
goto bad;
}
if (data_size == 0) {
- dbg_err("zero data_size");
+ ubi_err("zero data_size");
goto bad;
}
if (lnum < used_ebs - 1) {
if (data_size != usable_leb_size) {
- dbg_err("bad data_size");
+ ubi_err("bad data_size");
goto bad;
}
} else if (lnum == used_ebs - 1) {
if (data_size == 0) {
- dbg_err("bad data_size at last LEB");
+ ubi_err("bad data_size at last LEB");
goto bad;
}
} else {
- dbg_err("too high lnum");
+ ubi_err("too high lnum");
goto bad;
}
} else {
if (copy_flag == 0) {
if (data_crc != 0) {
- dbg_err("non-zero data CRC");
+ ubi_err("non-zero data CRC");
goto bad;
}
if (data_size != 0) {
- dbg_err("non-zero data_size");
+ ubi_err("non-zero data_size");
goto bad;
}
} else {
if (data_size == 0) {
- dbg_err("zero data_size of copy");
+ ubi_err("zero data_size of copy");
goto bad;
}
}
if (used_ebs != 0) {
- dbg_err("bad used_ebs");
+ ubi_err("bad used_ebs");
goto bad;
}
}
@@ -998,8 +989,8 @@
bad:
ubi_err("bad VID header");
- ubi_dbg_dump_vid_hdr(vid_hdr);
- ubi_dbg_dump_stack();
+ ubi_dump_vid_hdr(vid_hdr);
+ dump_stack();
return 1;
}
@@ -1055,7 +1046,7 @@
if (verbose) {
ubi_warn("bad magic number at PEB %d: %08x instead of "
"%08x", pnum, magic, UBI_VID_HDR_MAGIC);
- ubi_dbg_dump_vid_hdr(vid_hdr);
+ ubi_dump_vid_hdr(vid_hdr);
}
dbg_bld("bad magic number at PEB %d: %08x instead of "
"%08x", pnum, magic, UBI_VID_HDR_MAGIC);
@@ -1069,7 +1060,7 @@
if (verbose) {
ubi_warn("bad CRC at PEB %d, calculated %#08x, "
"read %#08x", pnum, crc, hdr_crc);
- ubi_dbg_dump_vid_hdr(vid_hdr);
+ ubi_dump_vid_hdr(vid_hdr);
}
dbg_bld("bad CRC at PEB %d, calculated %#08x, "
"read %#08x", pnum, crc, hdr_crc);
@@ -1113,7 +1104,7 @@
dbg_io("write VID header to PEB %d", pnum);
ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
- err = paranoid_check_peb_ec_hdr(ubi, pnum);
+ err = self_check_peb_ec_hdr(ubi, pnum);
if (err)
return err;
@@ -1122,7 +1113,7 @@
crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC);
vid_hdr->hdr_crc = cpu_to_be32(crc);
- err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr);
+ err = self_check_vid_hdr(ubi, pnum, vid_hdr);
if (err)
return err;
@@ -1132,34 +1123,32 @@
return err;
}
-#ifdef CONFIG_MTD_UBI_DEBUG
-
/**
- * paranoid_check_not_bad - ensure that a physical eraseblock is not bad.
+ * self_check_not_bad - ensure that a physical eraseblock is not bad.
* @ubi: UBI device description object
* @pnum: physical eraseblock number to check
*
* This function returns zero if the physical eraseblock is good, %-EINVAL if
* it is bad and a negative error code if an error occurred.
*/
-static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
+static int self_check_not_bad(const struct ubi_device *ubi, int pnum)
{
int err;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
err = ubi_io_is_bad(ubi, pnum);
if (!err)
return err;
- ubi_err("paranoid check failed for PEB %d", pnum);
- ubi_dbg_dump_stack();
+ ubi_err("self-check failed for PEB %d", pnum);
+ dump_stack();
return err > 0 ? -EINVAL : err;
}
/**
- * paranoid_check_ec_hdr - check if an erase counter header is all right.
+ * self_check_ec_hdr - check if an erase counter header is all right.
* @ubi: UBI device description object
* @pnum: physical eraseblock number the erase counter header belongs to
* @ec_hdr: the erase counter header to check
@@ -1167,13 +1156,13 @@
* This function returns zero if the erase counter header contains valid
* values, and %-EINVAL if not.
*/
-static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
- const struct ubi_ec_hdr *ec_hdr)
+static int self_check_ec_hdr(const struct ubi_device *ubi, int pnum,
+ const struct ubi_ec_hdr *ec_hdr)
{
int err;
uint32_t magic;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
magic = be32_to_cpu(ec_hdr->magic);
@@ -1185,33 +1174,33 @@
err = validate_ec_hdr(ubi, ec_hdr);
if (err) {
- ubi_err("paranoid check failed for PEB %d", pnum);
+ ubi_err("self-check failed for PEB %d", pnum);
goto fail;
}
return 0;
fail:
- ubi_dbg_dump_ec_hdr(ec_hdr);
- ubi_dbg_dump_stack();
+ ubi_dump_ec_hdr(ec_hdr);
+ dump_stack();
return -EINVAL;
}
/**
- * paranoid_check_peb_ec_hdr - check erase counter header.
+ * self_check_peb_ec_hdr - check erase counter header.
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to check
*
* This function returns zero if the erase counter header is all right and and
* a negative error code if not or if an error occurred.
*/
-static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
+static int self_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
{
int err;
uint32_t crc, hdr_crc;
struct ubi_ec_hdr *ec_hdr;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
@@ -1226,14 +1215,14 @@
hdr_crc = be32_to_cpu(ec_hdr->hdr_crc);
if (hdr_crc != crc) {
ubi_err("bad CRC, calculated %#08x, read %#08x", crc, hdr_crc);
- ubi_err("paranoid check failed for PEB %d", pnum);
- ubi_dbg_dump_ec_hdr(ec_hdr);
- ubi_dbg_dump_stack();
+ ubi_err("self-check failed for PEB %d", pnum);
+ ubi_dump_ec_hdr(ec_hdr);
+ dump_stack();
err = -EINVAL;
goto exit;
}
- err = paranoid_check_ec_hdr(ubi, pnum, ec_hdr);
+ err = self_check_ec_hdr(ubi, pnum, ec_hdr);
exit:
kfree(ec_hdr);
@@ -1241,7 +1230,7 @@
}
/**
- * paranoid_check_vid_hdr - check that a volume identifier header is all right.
+ * self_check_vid_hdr - check that a volume identifier header is all right.
* @ubi: UBI device description object
* @pnum: physical eraseblock number the volume identifier header belongs to
* @vid_hdr: the volume identifier header to check
@@ -1249,13 +1238,13 @@
* This function returns zero if the volume identifier header is all right, and
* %-EINVAL if not.
*/
-static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
- const struct ubi_vid_hdr *vid_hdr)
+static int self_check_vid_hdr(const struct ubi_device *ubi, int pnum,
+ const struct ubi_vid_hdr *vid_hdr)
{
int err;
uint32_t magic;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
magic = be32_to_cpu(vid_hdr->magic);
@@ -1267,36 +1256,36 @@
err = validate_vid_hdr(ubi, vid_hdr);
if (err) {
- ubi_err("paranoid check failed for PEB %d", pnum);
+ ubi_err("self-check failed for PEB %d", pnum);
goto fail;
}
return err;
fail:
- ubi_err("paranoid check failed for PEB %d", pnum);
- ubi_dbg_dump_vid_hdr(vid_hdr);
- ubi_dbg_dump_stack();
+ ubi_err("self-check failed for PEB %d", pnum);
+ ubi_dump_vid_hdr(vid_hdr);
+ dump_stack();
return -EINVAL;
}
/**
- * paranoid_check_peb_vid_hdr - check volume identifier header.
+ * self_check_peb_vid_hdr - check volume identifier header.
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to check
*
* This function returns zero if the volume identifier header is all right,
* and a negative error code if not or if an error occurred.
*/
-static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
+static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
{
int err;
uint32_t crc, hdr_crc;
struct ubi_vid_hdr *vid_hdr;
void *p;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
@@ -1314,14 +1303,14 @@
if (hdr_crc != crc) {
ubi_err("bad VID header CRC at PEB %d, calculated %#08x, "
"read %#08x", pnum, crc, hdr_crc);
- ubi_err("paranoid check failed for PEB %d", pnum);
- ubi_dbg_dump_vid_hdr(vid_hdr);
- ubi_dbg_dump_stack();
+ ubi_err("self-check failed for PEB %d", pnum);
+ ubi_dump_vid_hdr(vid_hdr);
+ dump_stack();
err = -EINVAL;
goto exit;
}
- err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr);
+ err = self_check_vid_hdr(ubi, pnum, vid_hdr);
exit:
ubi_free_vid_hdr(ubi, vid_hdr);
@@ -1329,7 +1318,7 @@
}
/**
- * ubi_dbg_check_write - make sure write succeeded.
+ * self_check_write - make sure write succeeded.
* @ubi: UBI device description object
* @buf: buffer with data which were written
* @pnum: physical eraseblock number the data were written to
@@ -1340,15 +1329,15 @@
* the original data buffer - the data have to match. Returns zero if the data
* match and a negative error code if not or in case of failure.
*/
-int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
- int offset, int len)
+static int self_check_write(struct ubi_device *ubi, const void *buf, int pnum,
+ int offset, int len)
{
int err, i;
size_t read;
void *buf1;
loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
buf1 = __vmalloc(len, GFP_NOFS, PAGE_KERNEL);
@@ -1369,7 +1358,7 @@
if (c == c1)
continue;
- ubi_err("paranoid check failed for PEB %d:%d, len %d",
+ ubi_err("self-check failed for PEB %d:%d, len %d",
pnum, offset, len);
ubi_msg("data differ at position %d", i);
dump_len = max_t(int, 128, len - i);
@@ -1381,7 +1370,7 @@
i, i + dump_len);
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
buf1 + i, dump_len, 1);
- ubi_dbg_dump_stack();
+ dump_stack();
err = -EINVAL;
goto out_free;
}
@@ -1395,7 +1384,7 @@
}
/**
- * ubi_dbg_check_all_ff - check that a region of flash is empty.
+ * ubi_self_check_all_ff - check that a region of flash is empty.
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to check
* @offset: the starting offset within the physical eraseblock to check
@@ -1405,14 +1394,14 @@
* @offset of the physical eraseblock @pnum, and a negative error code if not
* or if an error occurred.
*/
-int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
+int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
{
size_t read;
int err;
void *buf;
loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
- if (!(ubi_chk_flags & UBI_CHK_IO))
+ if (!ubi->dbg->chk_io)
return 0;
buf = __vmalloc(len, GFP_NOFS, PAGE_KERNEL);
@@ -1439,14 +1428,12 @@
return 0;
fail:
- ubi_err("paranoid check failed for PEB %d", pnum);
+ ubi_err("self-check failed for PEB %d", pnum);
ubi_msg("hex dump of the %d-%d region", offset, offset + len);
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
err = -EINVAL;
error:
- ubi_dbg_dump_stack();
+ dump_stack();
vfree(buf);
return err;
}
-
-#endif /* CONFIG_MTD_UBI_DEBUG */
diff -uN -uNr linux-3.0/drivers/mtd/ubi/kapi.c linux-3.0.x.ubifs.latest/drivers/mtd/ubi/kapi.c
--- linux-3.0/drivers/mtd/ubi/kapi.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/kapi.c 2012-06-28 11:26:15.000000000 -0500
@@ -221,7 +221,7 @@
kfree(desc);
out_put_ubi:
ubi_put_device(ubi);
- dbg_err("cannot open device %d, volume %d, error %d",
+ ubi_err("cannot open device %d, volume %d, error %d",
ubi_num, vol_id, err);
return ERR_PTR(err);
}
@@ -426,11 +426,9 @@
* @buf: data to write
* @offset: offset within the logical eraseblock where to write
* @len: how many bytes to write
- * @dtype: expected data type
*
* This function writes @len bytes of data from @buf to offset @offset of
- * logical eraseblock @lnum. The @dtype argument describes expected lifetime of
- * the data.
+ * logical eraseblock @lnum.
*
* This function takes care of physical eraseblock write failures. If write to
* the physical eraseblock write operation fails, the logical eraseblock is
@@ -447,7 +445,7 @@
* returns immediately with %-EBADF code.
*/
int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
- int offset, int len, int dtype)
+ int offset, int len)
{
struct ubi_volume *vol = desc->vol;
struct ubi_device *ubi = vol->ubi;
@@ -466,17 +464,13 @@
offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1))
return -EINVAL;
- if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
- dtype != UBI_UNKNOWN)
- return -EINVAL;
-
if (vol->upd_marker)
return -EBADF;
if (len == 0)
return 0;
- return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len, dtype);
+ return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len);
}
EXPORT_SYMBOL_GPL(ubi_leb_write);
@@ -486,7 +480,6 @@
* @lnum: logical eraseblock number to change
* @buf: data to write
* @len: how many bytes to write
- * @dtype: expected data type
*
* This function changes the contents of a logical eraseblock atomically. @buf
* has to contain new logical eraseblock data, and @len - the length of the
@@ -497,7 +490,7 @@
* code in case of failure.
*/
int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
- int len, int dtype)
+ int len)
{
struct ubi_volume *vol = desc->vol;
struct ubi_device *ubi = vol->ubi;
@@ -515,17 +508,13 @@
len > vol->usable_leb_size || len & (ubi->min_io_size - 1))
return -EINVAL;
- if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
- dtype != UBI_UNKNOWN)
- return -EINVAL;
-
if (vol->upd_marker)
return -EBADF;
if (len == 0)
return 0;
- return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len, dtype);
+ return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len);
}
EXPORT_SYMBOL_GPL(ubi_leb_change);
@@ -562,7 +551,7 @@
if (err)
return err;
- return ubi_wl_flush(ubi);
+ return ubi_wl_flush(ubi, vol->vol_id, lnum);
}
EXPORT_SYMBOL_GPL(ubi_leb_erase);
@@ -626,7 +615,6 @@
* ubi_leb_map - map logical eraseblock to a physical eraseblock.
* @desc: volume descriptor
* @lnum: logical eraseblock number
- * @dtype: expected data type
*
* This function maps an un-mapped logical eraseblock @lnum to a physical
* eraseblock. This means, that after a successful invocation of this
@@ -639,7 +627,7 @@
* eraseblock is already mapped, and other negative error codes in case of
* other failures.
*/
-int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
+int ubi_leb_map(struct ubi_volume_desc *desc, int lnum)
{
struct ubi_volume *vol = desc->vol;
struct ubi_device *ubi = vol->ubi;
@@ -652,17 +640,13 @@
if (lnum < 0 || lnum >= vol->reserved_pebs)
return -EINVAL;
- if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM &&
- dtype != UBI_UNKNOWN)
- return -EINVAL;
-
if (vol->upd_marker)
return -EBADF;
if (vol->eba_tbl[lnum] >= 0)
return -EBADMSG;
- return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0, dtype);
+ return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0);
}
EXPORT_SYMBOL_GPL(ubi_leb_map);
@@ -722,6 +706,33 @@
}
EXPORT_SYMBOL_GPL(ubi_sync);
+/**
+ * ubi_flush - flush UBI work queue.
+ * @ubi_num: UBI device to flush work queue
+ * @vol_id: volume id to flush for
+ * @lnum: logical eraseblock number to flush for
+ *
+ * This function executes all pending works for a particular volume id / logical
+ * eraseblock number pair. If either value is set to %UBI_ALL, then it acts as
+ * a wildcard for all of the corresponding volume numbers or logical
+ * eraseblock numbers. It returns zero in case of success and a negative error
+ * code in case of failure.
+ */
+int ubi_flush(int ubi_num, int vol_id, int lnum)
+{
+ struct ubi_device *ubi;
+ int err = 0;
+
+ ubi = ubi_get_device(ubi_num);
+ if (!ubi)
+ return -ENODEV;
+
+ err = ubi_wl_flush(ubi, vol_id, lnum);
+ ubi_put_device(ubi);
+ return err;
+}
+EXPORT_SYMBOL_GPL(ubi_flush);
+
BLOCKING_NOTIFIER_HEAD(ubi_notifiers);
/**
diff -uN -uNr linux-3.0/drivers/mtd/ubi/scan.c linux-3.0.x.ubifs.latest/drivers/mtd/ubi/scan.c
--- linux-3.0/drivers/mtd/ubi/scan.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/scan.c 1969-12-31 18:00:00.000000000 -0600
@@ -1,1605 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Author: Artem Bityutskiy (Битюцкий Артём)
- */
-
-/*
- * UBI scanning sub-system.
- *
- * This sub-system is responsible for scanning the flash media, checking UBI
- * headers and providing complete information about the UBI flash image.
- *
- * The scanning information is represented by a &struct ubi_scan_info' object.
- * Information about found volumes is represented by &struct ubi_scan_volume
- * objects which are kept in volume RB-tree with root at the @volumes field.
- * The RB-tree is indexed by the volume ID.
- *
- * Scanned logical eraseblocks are represented by &struct ubi_scan_leb objects.
- * These objects are kept in per-volume RB-trees with the root at the
- * corresponding &struct ubi_scan_volume object. To put it differently, we keep
- * an RB-tree of per-volume objects and each of these objects is the root of
- * RB-tree of per-eraseblock objects.
- *
- * Corrupted physical eraseblocks are put to the @corr list, free physical
- * eraseblocks are put to the @free list and the physical eraseblock to be
- * erased are put to the @erase list.
- *
- * About corruptions
- * ~~~~~~~~~~~~~~~~~
- *
- * UBI protects EC and VID headers with CRC-32 checksums, so it can detect
- * whether the headers are corrupted or not. Sometimes UBI also protects the
- * data with CRC-32, e.g., when it executes the atomic LEB change operation, or
- * when it moves the contents of a PEB for wear-leveling purposes.
- *
- * UBI tries to distinguish between 2 types of corruptions.
- *
- * 1. Corruptions caused by power cuts. These are expected corruptions and UBI
- * tries to handle them gracefully, without printing too many warnings and
- * error messages. The idea is that we do not lose important data in these case
- * - we may lose only the data which was being written to the media just before
- * the power cut happened, and the upper layers (e.g., UBIFS) are supposed to
- * handle such data losses (e.g., by using the FS journal).
- *
- * When UBI detects a corruption (CRC-32 mismatch) in a PEB, and it looks like
- * the reason is a power cut, UBI puts this PEB to the @erase list, and all
- * PEBs in the @erase list are scheduled for erasure later.
- *
- * 2. Unexpected corruptions which are not caused by power cuts. During
- * scanning, such PEBs are put to the @corr list and UBI preserves them.
- * Obviously, this lessens the amount of available PEBs, and if at some point
- * UBI runs out of free PEBs, it switches to R/O mode. UBI also loudly informs
- * about such PEBs every time the MTD device is attached.
- *
- * However, it is difficult to reliably distinguish between these types of
- * corruptions and UBI's strategy is as follows. UBI assumes corruption type 2
- * if the VID header is corrupted and the data area does not contain all 0xFFs,
- * and there were no bit-flips or integrity errors while reading the data area.
- * Otherwise UBI assumes corruption type 1. So the decision criteria are as
- * follows.
- * o If the data area contains only 0xFFs, there is no data, and it is safe
- * to just erase this PEB - this is corruption type 1.
- * o If the data area has bit-flips or data integrity errors (ECC errors on
- * NAND), it is probably a PEB which was being erased when power cut
- * happened, so this is corruption type 1. However, this is just a guess,
- * which might be wrong.
- * o Otherwise this it corruption type 2.
- */
-
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/crc32.h>
-#include <linux/math64.h>
-#include <linux/random.h>
-#include "ubi.h"
-
-#ifdef CONFIG_MTD_UBI_DEBUG
-static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si);
-#else
-#define paranoid_check_si(ubi, si) 0
-#endif
-
-/* Temporary variables used during scanning */
-static struct ubi_ec_hdr *ech;
-static struct ubi_vid_hdr *vidh;
-
-/**
- * add_to_list - add physical eraseblock to a list.
- * @si: scanning information
- * @pnum: physical eraseblock number to add
- * @ec: erase counter of the physical eraseblock
- * @to_head: if not zero, add to the head of the list
- * @list: the list to add to
- *
- * This function adds physical eraseblock @pnum to free, erase, or alien lists.
- * If @to_head is not zero, PEB will be added to the head of the list, which
- * basically means it will be processed first later. E.g., we add corrupted
- * PEBs (corrupted due to power cuts) to the head of the erase list to make
- * sure we erase them first and get rid of corruptions ASAP. This function
- * returns zero in case of success and a negative error code in case of
- * failure.
- */
-static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head,
- struct list_head *list)
-{
- struct ubi_scan_leb *seb;
-
- if (list == &si->free) {
- dbg_bld("add to free: PEB %d, EC %d", pnum, ec);
- } else if (list == &si->erase) {
- dbg_bld("add to erase: PEB %d, EC %d", pnum, ec);
- } else if (list == &si->alien) {
- dbg_bld("add to alien: PEB %d, EC %d", pnum, ec);
- si->alien_peb_count += 1;
- } else
- BUG();
-
- seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
- if (!seb)
- return -ENOMEM;
-
- seb->pnum = pnum;
- seb->ec = ec;
- if (to_head)
- list_add(&seb->u.list, list);
- else
- list_add_tail(&seb->u.list, list);
- return 0;
-}
-
-/**
- * add_corrupted - add a corrupted physical eraseblock.
- * @si: scanning information
- * @pnum: physical eraseblock number to add
- * @ec: erase counter of the physical eraseblock
- *
- * This function adds corrupted physical eraseblock @pnum to the 'corr' list.
- * The corruption was presumably not caused by a power cut. Returns zero in
- * case of success and a negative error code in case of failure.
- */
-static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec)
-{
- struct ubi_scan_leb *seb;
-
- dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
-
- seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
- if (!seb)
- return -ENOMEM;
-
- si->corr_peb_count += 1;
- seb->pnum = pnum;
- seb->ec = ec;
- list_add(&seb->u.list, &si->corr);
- return 0;
-}
-
-/**
- * validate_vid_hdr - check volume identifier header.
- * @vid_hdr: the volume identifier header to check
- * @sv: information about the volume this logical eraseblock belongs to
- * @pnum: physical eraseblock number the VID header came from
- *
- * This function checks that data stored in @vid_hdr is consistent. Returns
- * non-zero if an inconsistency was found and zero if not.
- *
- * Note, UBI does sanity check of everything it reads from the flash media.
- * Most of the checks are done in the I/O sub-system. Here we check that the
- * information in the VID header is consistent to the information in other VID
- * headers of the same volume.
- */
-static int validate_vid_hdr(const struct ubi_vid_hdr *vid_hdr,
- const struct ubi_scan_volume *sv, int pnum)
-{
- int vol_type = vid_hdr->vol_type;
- int vol_id = be32_to_cpu(vid_hdr->vol_id);
- int used_ebs = be32_to_cpu(vid_hdr->used_ebs);
- int data_pad = be32_to_cpu(vid_hdr->data_pad);
-
- if (sv->leb_count != 0) {
- int sv_vol_type;
-
- /*
- * This is not the first logical eraseblock belonging to this
- * volume. Ensure that the data in its VID header is consistent
- * to the data in previous logical eraseblock headers.
- */
-
- if (vol_id != sv->vol_id) {
- dbg_err("inconsistent vol_id");
- goto bad;
- }
-
- if (sv->vol_type == UBI_STATIC_VOLUME)
- sv_vol_type = UBI_VID_STATIC;
- else
- sv_vol_type = UBI_VID_DYNAMIC;
-
- if (vol_type != sv_vol_type) {
- dbg_err("inconsistent vol_type");
- goto bad;
- }
-
- if (used_ebs != sv->used_ebs) {
- dbg_err("inconsistent used_ebs");
- goto bad;
- }
-
- if (data_pad != sv->data_pad) {
- dbg_err("inconsistent data_pad");
- goto bad;
- }
- }
-
- return 0;
-
-bad:
- ubi_err("inconsistent VID header at PEB %d", pnum);
- ubi_dbg_dump_vid_hdr(vid_hdr);
- ubi_dbg_dump_sv(sv);
- return -EINVAL;
-}
-
-/**
- * add_volume - add volume to the scanning information.
- * @si: scanning information
- * @vol_id: ID of the volume to add
- * @pnum: physical eraseblock number
- * @vid_hdr: volume identifier header
- *
- * If the volume corresponding to the @vid_hdr logical eraseblock is already
- * present in the scanning information, this function does nothing. Otherwise
- * it adds corresponding volume to the scanning information. Returns a pointer
- * to the scanning volume object in case of success and a negative error code
- * in case of failure.
- */
-static struct ubi_scan_volume *add_volume(struct ubi_scan_info *si, int vol_id,
- int pnum,
- const struct ubi_vid_hdr *vid_hdr)
-{
- struct ubi_scan_volume *sv;
- struct rb_node **p = &si->volumes.rb_node, *parent = NULL;
-
- ubi_assert(vol_id == be32_to_cpu(vid_hdr->vol_id));
-
- /* Walk the volume RB-tree to look if this volume is already present */
- while (*p) {
- parent = *p;
- sv = rb_entry(parent, struct ubi_scan_volume, rb);
-
- if (vol_id == sv->vol_id)
- return sv;
-
- if (vol_id > sv->vol_id)
- p = &(*p)->rb_left;
- else
- p = &(*p)->rb_right;
- }
-
- /* The volume is absent - add it */
- sv = kmalloc(sizeof(struct ubi_scan_volume), GFP_KERNEL);
- if (!sv)
- return ERR_PTR(-ENOMEM);
-
- sv->highest_lnum = sv->leb_count = 0;
- sv->vol_id = vol_id;
- sv->root = RB_ROOT;
- sv->used_ebs = be32_to_cpu(vid_hdr->used_ebs);
- sv->data_pad = be32_to_cpu(vid_hdr->data_pad);
- sv->compat = vid_hdr->compat;
- sv->vol_type = vid_hdr->vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME
- : UBI_STATIC_VOLUME;
- if (vol_id > si->highest_vol_id)
- si->highest_vol_id = vol_id;
-
- rb_link_node(&sv->rb, parent, p);
- rb_insert_color(&sv->rb, &si->volumes);
- si->vols_found += 1;
- dbg_bld("added volume %d", vol_id);
- return sv;
-}
-
-/**
- * compare_lebs - find out which logical eraseblock is newer.
- * @ubi: UBI device description object
- * @seb: first logical eraseblock to compare
- * @pnum: physical eraseblock number of the second logical eraseblock to
- * compare
- * @vid_hdr: volume identifier header of the second logical eraseblock
- *
- * This function compares 2 copies of a LEB and informs which one is newer. In
- * case of success this function returns a positive value, in case of failure, a
- * negative error code is returned. The success return codes use the following
- * bits:
- * o bit 0 is cleared: the first PEB (described by @seb) is newer than the
- * second PEB (described by @pnum and @vid_hdr);
- * o bit 0 is set: the second PEB is newer;
- * o bit 1 is cleared: no bit-flips were detected in the newer LEB;
- * o bit 1 is set: bit-flips were detected in the newer LEB;
- * o bit 2 is cleared: the older LEB is not corrupted;
- * o bit 2 is set: the older LEB is corrupted.
- */
-static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
- int pnum, const struct ubi_vid_hdr *vid_hdr)
-{
- void *buf;
- int len, err, second_is_newer, bitflips = 0, corrupted = 0;
- uint32_t data_crc, crc;
- struct ubi_vid_hdr *vh = NULL;
- unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum);
-
- if (sqnum2 == seb->sqnum) {
- /*
- * This must be a really ancient UBI image which has been
- * created before sequence numbers support has been added. At
- * that times we used 32-bit LEB versions stored in logical
- * eraseblocks. That was before UBI got into mainline. We do not
- * support these images anymore. Well, those images still work,
- * but only if no unclean reboots happened.
- */
- ubi_err("unsupported on-flash UBI format\n");
- return -EINVAL;
- }
-
- /* Obviously the LEB with lower sequence counter is older */
- second_is_newer = !!(sqnum2 > seb->sqnum);
-
- /*
- * Now we know which copy is newer. If the copy flag of the PEB with
- * newer version is not set, then we just return, otherwise we have to
- * check data CRC. For the second PEB we already have the VID header,
- * for the first one - we'll need to re-read it from flash.
- *
- * Note: this may be optimized so that we wouldn't read twice.
- */
-
- if (second_is_newer) {
- if (!vid_hdr->copy_flag) {
- /* It is not a copy, so it is newer */
- dbg_bld("second PEB %d is newer, copy_flag is unset",
- pnum);
- return 1;
- }
- } else {
- if (!seb->copy_flag) {
- /* It is not a copy, so it is newer */
- dbg_bld("first PEB %d is newer, copy_flag is unset",
- pnum);
- return bitflips << 1;
- }
-
- vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
- if (!vh)
- return -ENOMEM;
-
- pnum = seb->pnum;
- err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
- if (err) {
- if (err == UBI_IO_BITFLIPS)
- bitflips = 1;
- else {
- dbg_err("VID of PEB %d header is bad, but it "
- "was OK earlier, err %d", pnum, err);
- if (err > 0)
- err = -EIO;
-
- goto out_free_vidh;
- }
- }
-
- vid_hdr = vh;
- }
-
- /* Read the data of the copy and check the CRC */
-
- len = be32_to_cpu(vid_hdr->data_size);
- buf = vmalloc(len);
- if (!buf) {
- err = -ENOMEM;
- goto out_free_vidh;
- }
-
- err = ubi_io_read_data(ubi, buf, pnum, 0, len);
- if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG)
- goto out_free_buf;
-
- data_crc = be32_to_cpu(vid_hdr->data_crc);
- crc = crc32(UBI_CRC32_INIT, buf, len);
- if (crc != data_crc) {
- dbg_bld("PEB %d CRC error: calculated %#08x, must be %#08x",
- pnum, crc, data_crc);
- corrupted = 1;
- bitflips = 0;
- second_is_newer = !second_is_newer;
- } else {
- dbg_bld("PEB %d CRC is OK", pnum);
- bitflips = !!err;
- }
-
- vfree(buf);
- ubi_free_vid_hdr(ubi, vh);
-
- if (second_is_newer)
- dbg_bld("second PEB %d is newer, copy_flag is set", pnum);
- else
- dbg_bld("first PEB %d is newer, copy_flag is set", pnum);
-
- return second_is_newer | (bitflips << 1) | (corrupted << 2);
-
-out_free_buf:
- vfree(buf);
-out_free_vidh:
- ubi_free_vid_hdr(ubi, vh);
- return err;
-}
-
-/**
- * ubi_scan_add_used - add physical eraseblock to the scanning information.
- * @ubi: UBI device description object
- * @si: scanning information
- * @pnum: the physical eraseblock number
- * @ec: erase counter
- * @vid_hdr: the volume identifier header
- * @bitflips: if bit-flips were detected when this physical eraseblock was read
- *
- * This function adds information about a used physical eraseblock to the
- * 'used' tree of the corresponding volume. The function is rather complex
- * because it has to handle cases when this is not the first physical
- * eraseblock belonging to the same logical eraseblock, and the newer one has
- * to be picked, while the older one has to be dropped. This function returns
- * zero in case of success and a negative error code in case of failure.
- */
-int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
- int pnum, int ec, const struct ubi_vid_hdr *vid_hdr,
- int bitflips)
-{
- int err, vol_id, lnum;
- unsigned long long sqnum;
- struct ubi_scan_volume *sv;
- struct ubi_scan_leb *seb;
- struct rb_node **p, *parent = NULL;
-
- vol_id = be32_to_cpu(vid_hdr->vol_id);
- lnum = be32_to_cpu(vid_hdr->lnum);
- sqnum = be64_to_cpu(vid_hdr->sqnum);
-
- dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, bitflips %d",
- pnum, vol_id, lnum, ec, sqnum, bitflips);
-
- sv = add_volume(si, vol_id, pnum, vid_hdr);
- if (IS_ERR(sv))
- return PTR_ERR(sv);
-
- if (si->max_sqnum < sqnum)
- si->max_sqnum = sqnum;
-
- /*
- * Walk the RB-tree of logical eraseblocks of volume @vol_id to look
- * if this is the first instance of this logical eraseblock or not.
- */
- p = &sv->root.rb_node;
- while (*p) {
- int cmp_res;
-
- parent = *p;
- seb = rb_entry(parent, struct ubi_scan_leb, u.rb);
- if (lnum != seb->lnum) {
- if (lnum < seb->lnum)
- p = &(*p)->rb_left;
- else
- p = &(*p)->rb_right;
- continue;
- }
-
- /*
- * There is already a physical eraseblock describing the same
- * logical eraseblock present.
- */
-
- dbg_bld("this LEB already exists: PEB %d, sqnum %llu, "
- "EC %d", seb->pnum, seb->sqnum, seb->ec);
-
- /*
- * Make sure that the logical eraseblocks have different
- * sequence numbers. Otherwise the image is bad.
- *
- * However, if the sequence number is zero, we assume it must
- * be an ancient UBI image from the era when UBI did not have
- * sequence numbers. We still can attach these images, unless
- * there is a need to distinguish between old and new
- * eraseblocks, in which case we'll refuse the image in
- * 'compare_lebs()'. In other words, we attach old clean
- * images, but refuse attaching old images with duplicated
- * logical eraseblocks because there was an unclean reboot.
- */
- if (seb->sqnum == sqnum && sqnum != 0) {
- ubi_err("two LEBs with same sequence number %llu",
- sqnum);
- ubi_dbg_dump_seb(seb, 0);
- ubi_dbg_dump_vid_hdr(vid_hdr);
- return -EINVAL;
- }
-
- /*
- * Now we have to drop the older one and preserve the newer
- * one.
- */
- cmp_res = compare_lebs(ubi, seb, pnum, vid_hdr);
- if (cmp_res < 0)
- return cmp_res;
-
- if (cmp_res & 1) {
- /*
- * This logical eraseblock is newer than the one
- * found earlier.
- */
- err = validate_vid_hdr(vid_hdr, sv, pnum);
- if (err)
- return err;
-
- err = add_to_list(si, seb->pnum, seb->ec, cmp_res & 4,
- &si->erase);
- if (err)
- return err;
-
- seb->ec = ec;
- seb->pnum = pnum;
- seb->scrub = ((cmp_res & 2) || bitflips);
- seb->copy_flag = vid_hdr->copy_flag;
- seb->sqnum = sqnum;
-
- if (sv->highest_lnum == lnum)
- sv->last_data_size =
- be32_to_cpu(vid_hdr->data_size);
-
- return 0;
- } else {
- /*
- * This logical eraseblock is older than the one found
- * previously.
- */
- return add_to_list(si, pnum, ec, cmp_res & 4,
- &si->erase);
- }
- }
-
- /*
- * We've met this logical eraseblock for the first time, add it to the
- * scanning information.
- */
-
- err = validate_vid_hdr(vid_hdr, sv, pnum);
- if (err)
- return err;
-
- seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
- if (!seb)
- return -ENOMEM;
-
- seb->ec = ec;
- seb->pnum = pnum;
- seb->lnum = lnum;
- seb->scrub = bitflips;
- seb->copy_flag = vid_hdr->copy_flag;
- seb->sqnum = sqnum;
-
- if (sv->highest_lnum <= lnum) {
- sv->highest_lnum = lnum;
- sv->last_data_size = be32_to_cpu(vid_hdr->data_size);
- }
-
- sv->leb_count += 1;
- rb_link_node(&seb->u.rb, parent, p);
- rb_insert_color(&seb->u.rb, &sv->root);
- return 0;
-}
-
-/**
- * ubi_scan_find_sv - find volume in the scanning information.
- * @si: scanning information
- * @vol_id: the requested volume ID
- *
- * This function returns a pointer to the volume description or %NULL if there
- * are no data about this volume in the scanning information.
- */
-struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si,
- int vol_id)
-{
- struct ubi_scan_volume *sv;
- struct rb_node *p = si->volumes.rb_node;
-
- while (p) {
- sv = rb_entry(p, struct ubi_scan_volume, rb);
-
- if (vol_id == sv->vol_id)
- return sv;
-
- if (vol_id > sv->vol_id)
- p = p->rb_left;
- else
- p = p->rb_right;
- }
-
- return NULL;
-}
-
-/**
- * ubi_scan_find_seb - find LEB in the volume scanning information.
- * @sv: a pointer to the volume scanning information
- * @lnum: the requested logical eraseblock
- *
- * This function returns a pointer to the scanning logical eraseblock or %NULL
- * if there are no data about it in the scanning volume information.
- */
-struct ubi_scan_leb *ubi_scan_find_seb(const struct ubi_scan_volume *sv,
- int lnum)
-{
- struct ubi_scan_leb *seb;
- struct rb_node *p = sv->root.rb_node;
-
- while (p) {
- seb = rb_entry(p, struct ubi_scan_leb, u.rb);
-
- if (lnum == seb->lnum)
- return seb;
-
- if (lnum > seb->lnum)
- p = p->rb_left;
- else
- p = p->rb_right;
- }
-
- return NULL;
-}
-
-/**
- * ubi_scan_rm_volume - delete scanning information about a volume.
- * @si: scanning information
- * @sv: the volume scanning information to delete
- */
-void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv)
-{
- struct rb_node *rb;
- struct ubi_scan_leb *seb;
-
- dbg_bld("remove scanning information about volume %d", sv->vol_id);
-
- while ((rb = rb_first(&sv->root))) {
- seb = rb_entry(rb, struct ubi_scan_leb, u.rb);
- rb_erase(&seb->u.rb, &sv->root);
- list_add_tail(&seb->u.list, &si->erase);
- }
-
- rb_erase(&sv->rb, &si->volumes);
- kfree(sv);
- si->vols_found -= 1;
-}
-
-/**
- * ubi_scan_erase_peb - erase a physical eraseblock.
- * @ubi: UBI device description object
- * @si: scanning information
- * @pnum: physical eraseblock number to erase;
- * @ec: erase counter value to write (%UBI_SCAN_UNKNOWN_EC if it is unknown)
- *
- * This function erases physical eraseblock 'pnum', and writes the erase
- * counter header to it. This function should only be used on UBI device
- * initialization stages, when the EBA sub-system had not been yet initialized.
- * This function returns zero in case of success and a negative error code in
- * case of failure.
- */
-int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si,
- int pnum, int ec)
-{
- int err;
- struct ubi_ec_hdr *ec_hdr;
-
- if ((long long)ec >= UBI_MAX_ERASECOUNTER) {
- /*
- * Erase counter overflow. Upgrade UBI and use 64-bit
- * erase counters internally.
- */
- ubi_err("erase counter overflow at PEB %d, EC %d", pnum, ec);
- return -EINVAL;
- }
-
- ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
- if (!ec_hdr)
- return -ENOMEM;
-
- ec_hdr->ec = cpu_to_be64(ec);
-
- err = ubi_io_sync_erase(ubi, pnum, 0);
- if (err < 0)
- goto out_free;
-
- err = ubi_io_write_ec_hdr(ubi, pnum, ec_hdr);
-
-out_free:
- kfree(ec_hdr);
- return err;
-}
-
-/**
- * ubi_scan_get_free_peb - get a free physical eraseblock.
- * @ubi: UBI device description object
- * @si: scanning information
- *
- * This function returns a free physical eraseblock. It is supposed to be
- * called on the UBI initialization stages when the wear-leveling sub-system is
- * not initialized yet. This function picks a physical eraseblocks from one of
- * the lists, writes the EC header if it is needed, and removes it from the
- * list.
- *
- * This function returns scanning physical eraseblock information in case of
- * success and an error code in case of failure.
- */
-struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
- struct ubi_scan_info *si)
-{
- int err = 0;
- struct ubi_scan_leb *seb, *tmp_seb;
-
- if (!list_empty(&si->free)) {
- seb = list_entry(si->free.next, struct ubi_scan_leb, u.list);
- list_del(&seb->u.list);
- dbg_bld("return free PEB %d, EC %d", seb->pnum, seb->ec);
- return seb;
- }
-
- /*
- * We try to erase the first physical eraseblock from the erase list
- * and pick it if we succeed, or try to erase the next one if not. And
- * so forth. We don't want to take care about bad eraseblocks here -
- * they'll be handled later.
- */
- list_for_each_entry_safe(seb, tmp_seb, &si->erase, u.list) {
- if (seb->ec == UBI_SCAN_UNKNOWN_EC)
- seb->ec = si->mean_ec;
-
- err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1);
- if (err)
- continue;
-
- seb->ec += 1;
- list_del(&seb->u.list);
- dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec);
- return seb;
- }
-
- ubi_err("no free eraseblocks");
- return ERR_PTR(-ENOSPC);
-}
-
-/**
- * check_corruption - check the data area of PEB.
- * @ubi: UBI device description object
- * @vid_hrd: the (corrupted) VID header of this PEB
- * @pnum: the physical eraseblock number to check
- *
- * This is a helper function which is used to distinguish between VID header
- * corruptions caused by power cuts and other reasons. If the PEB contains only
- * 0xFF bytes in the data area, the VID header is most probably corrupted
- * because of a power cut (%0 is returned in this case). Otherwise, it was
- * probably corrupted for some other reasons (%1 is returned in this case). A
- * negative error code is returned if a read error occurred.
- *
- * If the corruption reason was a power cut, UBI can safely erase this PEB.
- * Otherwise, it should preserve it to avoid possibly destroying important
- * information.
- */
-static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
- int pnum)
-{
- int err;
-
- mutex_lock(&ubi->buf_mutex);
- memset(ubi->peb_buf1, 0x00, ubi->leb_size);
-
- err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start,
- ubi->leb_size);
- if (err == UBI_IO_BITFLIPS || err == -EBADMSG) {
- /*
- * Bit-flips or integrity errors while reading the data area.
- * It is difficult to say for sure what type of corruption is
- * this, but presumably a power cut happened while this PEB was
- * erased, so it became unstable and corrupted, and should be
- * erased.
- */
- err = 0;
- goto out_unlock;
- }
-
- if (err)
- goto out_unlock;
-
- if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size))
- goto out_unlock;
-
- ubi_err("PEB %d contains corrupted VID header, and the data does not "
- "contain all 0xFF, this may be a non-UBI PEB or a severe VID "
- "header corruption which requires manual inspection", pnum);
- ubi_dbg_dump_vid_hdr(vid_hdr);
- dbg_msg("hexdump of PEB %d offset %d, length %d",
- pnum, ubi->leb_start, ubi->leb_size);
- ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
- ubi->peb_buf1, ubi->leb_size, 1);
- err = 1;
-
-out_unlock:
- mutex_unlock(&ubi->buf_mutex);
- return err;
-}
-
-/**
- * process_eb - read, check UBI headers, and add them to scanning information.
- * @ubi: UBI device description object
- * @si: scanning information
- * @pnum: the physical eraseblock number
- *
- * This function returns a zero if the physical eraseblock was successfully
- * handled and a negative error code in case of failure.
- */
-static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
- int pnum)
-{
- long long uninitialized_var(ec);
- int err, bitflips = 0, vol_id, ec_err = 0;
-
- dbg_bld("scan PEB %d", pnum);
-
- /* Skip bad physical eraseblocks */
- err = ubi_io_is_bad(ubi, pnum);
- if (err < 0)
- return err;
- else if (err) {
- /*
- * FIXME: this is actually duty of the I/O sub-system to
- * initialize this, but MTD does not provide enough
- * information.
- */
- si->bad_peb_count += 1;
- return 0;
- }
-
- err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
- if (err < 0)
- return err;
- switch (err) {
- case 0:
- break;
- case UBI_IO_BITFLIPS:
- bitflips = 1;
- break;
- case UBI_IO_FF:
- si->empty_peb_count += 1;
- return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 0,
- &si->erase);
- case UBI_IO_FF_BITFLIPS:
- si->empty_peb_count += 1;
- return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 1,
- &si->erase);
- case UBI_IO_BAD_HDR_EBADMSG:
- case UBI_IO_BAD_HDR:
- /*
- * We have to also look at the VID header, possibly it is not
- * corrupted. Set %bitflips flag in order to make this PEB be
- * moved and EC be re-created.
- */
- ec_err = err;
- ec = UBI_SCAN_UNKNOWN_EC;
- bitflips = 1;
- break;
- default:
- ubi_err("'ubi_io_read_ec_hdr()' returned unknown code %d", err);
- return -EINVAL;
- }
-
- if (!ec_err) {
- int image_seq;
-
- /* Make sure UBI version is OK */
- if (ech->version != UBI_VERSION) {
- ubi_err("this UBI version is %d, image version is %d",
- UBI_VERSION, (int)ech->version);
- return -EINVAL;
- }
-
- ec = be64_to_cpu(ech->ec);
- if (ec > UBI_MAX_ERASECOUNTER) {
- /*
- * Erase counter overflow. The EC headers have 64 bits
- * reserved, but we anyway make use of only 31 bit
- * values, as this seems to be enough for any existing
- * flash. Upgrade UBI and use 64-bit erase counters
- * internally.
- */
- ubi_err("erase counter overflow, max is %d",
- UBI_MAX_ERASECOUNTER);
- ubi_dbg_dump_ec_hdr(ech);
- return -EINVAL;
- }
-
- /*
- * Make sure that all PEBs have the same image sequence number.
- * This allows us to detect situations when users flash UBI
- * images incorrectly, so that the flash has the new UBI image
- * and leftovers from the old one. This feature was added
- * relatively recently, and the sequence number was always
- * zero, because old UBI implementations always set it to zero.
- * For this reasons, we do not panic if some PEBs have zero
- * sequence number, while other PEBs have non-zero sequence
- * number.
- */
- image_seq = be32_to_cpu(ech->image_seq);
- if (!ubi->image_seq && image_seq)
- ubi->image_seq = image_seq;
- if (ubi->image_seq && image_seq &&
- ubi->image_seq != image_seq) {
- ubi_err("bad image sequence number %d in PEB %d, "
- "expected %d", image_seq, pnum, ubi->image_seq);
- ubi_dbg_dump_ec_hdr(ech);
- return -EINVAL;
- }
- }
-
- /* OK, we've done with the EC header, let's look at the VID header */
-
- err = ubi_io_read_vid_hdr(ubi, pnum, vidh, 0);
- if (err < 0)
- return err;
- switch (err) {
- case 0:
- break;
- case UBI_IO_BITFLIPS:
- bitflips = 1;
- break;
- case UBI_IO_BAD_HDR_EBADMSG:
- if (ec_err == UBI_IO_BAD_HDR_EBADMSG)
- /*
- * Both EC and VID headers are corrupted and were read
- * with data integrity error, probably this is a bad
- * PEB, bit it is not marked as bad yet. This may also
- * be a result of power cut during erasure.
- */
- si->maybe_bad_peb_count += 1;
- case UBI_IO_BAD_HDR:
- if (ec_err)
- /*
- * Both headers are corrupted. There is a possibility
- * that this a valid UBI PEB which has corresponding
- * LEB, but the headers are corrupted. However, it is
- * impossible to distinguish it from a PEB which just
- * contains garbage because of a power cut during erase
- * operation. So we just schedule this PEB for erasure.
- *
- * Besides, in case of NOR flash, we deliberately
- * corrupt both headers because NOR flash erasure is
- * slow and can start from the end.
- */
- err = 0;
- else
- /*
- * The EC was OK, but the VID header is corrupted. We
- * have to check what is in the data area.
- */
- err = check_corruption(ubi, vidh, pnum);
-
- if (err < 0)
- return err;
- else if (!err)
- /* This corruption is caused by a power cut */
- err = add_to_list(si, pnum, ec, 1, &si->erase);
- else
- /* This is an unexpected corruption */
- err = add_corrupted(si, pnum, ec);
- if (err)
- return err;
- goto adjust_mean_ec;
- case UBI_IO_FF_BITFLIPS:
- err = add_to_list(si, pnum, ec, 1, &si->erase);
- if (err)
- return err;
- goto adjust_mean_ec;
- case UBI_IO_FF:
- if (ec_err)
- err = add_to_list(si, pnum, ec, 1, &si->erase);
- else
- err = add_to_list(si, pnum, ec, 0, &si->free);
- if (err)
- return err;
- goto adjust_mean_ec;
- default:
- ubi_err("'ubi_io_read_vid_hdr()' returned unknown code %d",
- err);
- return -EINVAL;
- }
-
- vol_id = be32_to_cpu(vidh->vol_id);
- if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOLUME_ID) {
- int lnum = be32_to_cpu(vidh->lnum);
-
- /* Unsupported internal volume */
- switch (vidh->compat) {
- case UBI_COMPAT_DELETE:
- ubi_msg("\"delete\" compatible internal volume %d:%d"
- " found, will remove it", vol_id, lnum);
- err = add_to_list(si, pnum, ec, 1, &si->erase);
- if (err)
- return err;
- return 0;
-
- case UBI_COMPAT_RO:
- ubi_msg("read-only compatible internal volume %d:%d"
- " found, switch to read-only mode",
- vol_id, lnum);
- ubi->ro_mode = 1;
- break;
-
- case UBI_COMPAT_PRESERVE:
- ubi_msg("\"preserve\" compatible internal volume %d:%d"
- " found", vol_id, lnum);
- err = add_to_list(si, pnum, ec, 0, &si->alien);
- if (err)
- return err;
- return 0;
-
- case UBI_COMPAT_REJECT:
- ubi_err("incompatible internal volume %d:%d found",
- vol_id, lnum);
- return -EINVAL;
- }
- }
-
- if (ec_err)
- ubi_warn("valid VID header but corrupted EC header at PEB %d",
- pnum);
- err = ubi_scan_add_used(ubi, si, pnum, ec, vidh, bitflips);
- if (err)
- return err;
-
-adjust_mean_ec:
- if (!ec_err) {
- si->ec_sum += ec;
- si->ec_count += 1;
- if (ec > si->max_ec)
- si->max_ec = ec;
- if (ec < si->min_ec)
- si->min_ec = ec;
- }
-
- return 0;
-}
-
-/**
- * check_what_we_have - check what PEB were found by scanning.
- * @ubi: UBI device description object
- * @si: scanning information
- *
- * This is a helper function which takes a look what PEBs were found by
- * scanning, and decides whether the flash is empty and should be formatted and
- * whether there are too many corrupted PEBs and we should not attach this
- * MTD device. Returns zero if we should proceed with attaching the MTD device,
- * and %-EINVAL if we should not.
- */
-static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si)
-{
- struct ubi_scan_leb *seb;
- int max_corr, peb_count;
-
- peb_count = ubi->peb_count - si->bad_peb_count - si->alien_peb_count;
- max_corr = peb_count / 20 ?: 8;
-
- /*
- * Few corrupted PEBs is not a problem and may be just a result of
- * unclean reboots. However, many of them may indicate some problems
- * with the flash HW or driver.
- */
- if (si->corr_peb_count) {
- ubi_err("%d PEBs are corrupted and preserved",
- si->corr_peb_count);
- printk(KERN_ERR "Corrupted PEBs are:");
- list_for_each_entry(seb, &si->corr, u.list)
- printk(KERN_CONT " %d", seb->pnum);
- printk(KERN_CONT "\n");
-
- /*
- * If too many PEBs are corrupted, we refuse attaching,
- * otherwise, only print a warning.
- */
- if (si->corr_peb_count >= max_corr) {
- ubi_err("too many corrupted PEBs, refusing");
- return -EINVAL;
- }
- }
-
- if (si->empty_peb_count + si->maybe_bad_peb_count == peb_count) {
- /*
- * All PEBs are empty, or almost all - a couple PEBs look like
- * they may be bad PEBs which were not marked as bad yet.
- *
- * This piece of code basically tries to distinguish between
- * the following situations:
- *
- * 1. Flash is empty, but there are few bad PEBs, which are not
- * marked as bad so far, and which were read with error. We
- * want to go ahead and format this flash. While formatting,
- * the faulty PEBs will probably be marked as bad.
- *
- * 2. Flash contains non-UBI data and we do not want to format
- * it and destroy possibly important information.
- */
- if (si->maybe_bad_peb_count <= 2) {
- si->is_empty = 1;
- ubi_msg("empty MTD device detected");
- get_random_bytes(&ubi->image_seq,
- sizeof(ubi->image_seq));
- } else {
- ubi_err("MTD device is not UBI-formatted and possibly "
- "contains non-UBI data - refusing it");
- return -EINVAL;
- }
-
- }
-
- return 0;
-}
-
-/**
- * ubi_scan - scan an MTD device.
- * @ubi: UBI device description object
- *
- * This function does full scanning of an MTD device and returns complete
- * information about it. In case of failure, an error code is returned.
- */
-struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
-{
- int err, pnum;
- struct rb_node *rb1, *rb2;
- struct ubi_scan_volume *sv;
- struct ubi_scan_leb *seb;
- struct ubi_scan_info *si;
-
- si = kzalloc(sizeof(struct ubi_scan_info), GFP_KERNEL);
- if (!si)
- return ERR_PTR(-ENOMEM);
-
- INIT_LIST_HEAD(&si->corr);
- INIT_LIST_HEAD(&si->free);
- INIT_LIST_HEAD(&si->erase);
- INIT_LIST_HEAD(&si->alien);
- si->volumes = RB_ROOT;
-
- err = -ENOMEM;
- si->scan_leb_slab = kmem_cache_create("ubi_scan_leb_slab",
- sizeof(struct ubi_scan_leb),
- 0, 0, NULL);
- if (!si->scan_leb_slab)
- goto out_si;
-
- ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
- if (!ech)
- goto out_slab;
-
- vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
- if (!vidh)
- goto out_ech;
-
- for (pnum = 0; pnum < ubi->peb_count; pnum++) {
- cond_resched();
-
- dbg_gen("process PEB %d", pnum);
- err = process_eb(ubi, si, pnum);
- if (err < 0)
- goto out_vidh;
- }
-
- dbg_msg("scanning is finished");
-
- /* Calculate mean erase counter */
- if (si->ec_count)
- si->mean_ec = div_u64(si->ec_sum, si->ec_count);
-
- err = check_what_we_have(ubi, si);
- if (err)
- goto out_vidh;
-
- /*
- * In case of unknown erase counter we use the mean erase counter
- * value.
- */
- ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
- ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb)
- if (seb->ec == UBI_SCAN_UNKNOWN_EC)
- seb->ec = si->mean_ec;
- }
-
- list_for_each_entry(seb, &si->free, u.list) {
- if (seb->ec == UBI_SCAN_UNKNOWN_EC)
- seb->ec = si->mean_ec;
- }
-
- list_for_each_entry(seb, &si->corr, u.list)
- if (seb->ec == UBI_SCAN_UNKNOWN_EC)
- seb->ec = si->mean_ec;
-
- list_for_each_entry(seb, &si->erase, u.list)
- if (seb->ec == UBI_SCAN_UNKNOWN_EC)
- seb->ec = si->mean_ec;
-
- err = paranoid_check_si(ubi, si);
- if (err)
- goto out_vidh;
-
- ubi_free_vid_hdr(ubi, vidh);
- kfree(ech);
-
- return si;
-
-out_vidh:
- ubi_free_vid_hdr(ubi, vidh);
-out_ech:
- kfree(ech);
-out_slab:
- kmem_cache_destroy(si->scan_leb_slab);
-out_si:
- ubi_scan_destroy_si(si);
- return ERR_PTR(err);
-}
-
-/**
- * destroy_sv - free the scanning volume information
- * @sv: scanning volume information
- * @si: scanning information
- *
- * This function destroys the volume RB-tree (@sv->root) and the scanning
- * volume information.
- */
-static void destroy_sv(struct ubi_scan_info *si, struct ubi_scan_volume *sv)
-{
- struct ubi_scan_leb *seb;
- struct rb_node *this = sv->root.rb_node;
-
- while (this) {
- if (this->rb_left)
- this = this->rb_left;
- else if (this->rb_right)
- this = this->rb_right;
- else {
- seb = rb_entry(this, struct ubi_scan_leb, u.rb);
- this = rb_parent(this);
- if (this) {
- if (this->rb_left == &seb->u.rb)
- this->rb_left = NULL;
- else
- this->rb_right = NULL;
- }
-
- kmem_cache_free(si->scan_leb_slab, seb);
- }
- }
- kfree(sv);
-}
-
-/**
- * ubi_scan_destroy_si - destroy scanning information.
- * @si: scanning information
- */
-void ubi_scan_destroy_si(struct ubi_scan_info *si)
-{
- struct ubi_scan_leb *seb, *seb_tmp;
- struct ubi_scan_volume *sv;
- struct rb_node *rb;
-
- list_for_each_entry_safe(seb, seb_tmp, &si->alien, u.list) {
- list_del(&seb->u.list);
- kmem_cache_free(si->scan_leb_slab, seb);
- }
- list_for_each_entry_safe(seb, seb_tmp, &si->erase, u.list) {
- list_del(&seb->u.list);
- kmem_cache_free(si->scan_leb_slab, seb);
- }
- list_for_each_entry_safe(seb, seb_tmp, &si->corr, u.list) {
- list_del(&seb->u.list);
- kmem_cache_free(si->scan_leb_slab, seb);
- }
- list_for_each_entry_safe(seb, seb_tmp, &si->free, u.list) {
- list_del(&seb->u.list);
- kmem_cache_free(si->scan_leb_slab, seb);
- }
-
- /* Destroy the volume RB-tree */
- rb = si->volumes.rb_node;
- while (rb) {
- if (rb->rb_left)
- rb = rb->rb_left;
- else if (rb->rb_right)
- rb = rb->rb_right;
- else {
- sv = rb_entry(rb, struct ubi_scan_volume, rb);
-
- rb = rb_parent(rb);
- if (rb) {
- if (rb->rb_left == &sv->rb)
- rb->rb_left = NULL;
- else
- rb->rb_right = NULL;
- }
-
- destroy_sv(si, sv);
- }
- }
-
- kmem_cache_destroy(si->scan_leb_slab);
- kfree(si);
-}
-
-#ifdef CONFIG_MTD_UBI_DEBUG
-
-/**
- * paranoid_check_si - check the scanning information.
- * @ubi: UBI device description object
- * @si: scanning information
- *
- * This function returns zero if the scanning information is all right, and a
- * negative error code if not or if an error occurred.
- */
-static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
-{
- int pnum, err, vols_found = 0;
- struct rb_node *rb1, *rb2;
- struct ubi_scan_volume *sv;
- struct ubi_scan_leb *seb, *last_seb;
- uint8_t *buf;
-
- if (!(ubi_chk_flags & UBI_CHK_GEN))
- return 0;
-
- /*
- * At first, check that scanning information is OK.
- */
- ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
- int leb_count = 0;
-
- cond_resched();
-
- vols_found += 1;
-
- if (si->is_empty) {
- ubi_err("bad is_empty flag");
- goto bad_sv;
- }
-
- if (sv->vol_id < 0 || sv->highest_lnum < 0 ||
- sv->leb_count < 0 || sv->vol_type < 0 || sv->used_ebs < 0 ||
- sv->data_pad < 0 || sv->last_data_size < 0) {
- ubi_err("negative values");
- goto bad_sv;
- }
-
- if (sv->vol_id >= UBI_MAX_VOLUMES &&
- sv->vol_id < UBI_INTERNAL_VOL_START) {
- ubi_err("bad vol_id");
- goto bad_sv;
- }
-
- if (sv->vol_id > si->highest_vol_id) {
- ubi_err("highest_vol_id is %d, but vol_id %d is there",
- si->highest_vol_id, sv->vol_id);
- goto out;
- }
-
- if (sv->vol_type != UBI_DYNAMIC_VOLUME &&
- sv->vol_type != UBI_STATIC_VOLUME) {
- ubi_err("bad vol_type");
- goto bad_sv;
- }
-
- if (sv->data_pad > ubi->leb_size / 2) {
- ubi_err("bad data_pad");
- goto bad_sv;
- }
-
- last_seb = NULL;
- ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) {
- cond_resched();
-
- last_seb = seb;
- leb_count += 1;
-
- if (seb->pnum < 0 || seb->ec < 0) {
- ubi_err("negative values");
- goto bad_seb;
- }
-
- if (seb->ec < si->min_ec) {
- ubi_err("bad si->min_ec (%d), %d found",
- si->min_ec, seb->ec);
- goto bad_seb;
- }
-
- if (seb->ec > si->max_ec) {
- ubi_err("bad si->max_ec (%d), %d found",
- si->max_ec, seb->ec);
- goto bad_seb;
- }
-
- if (seb->pnum >= ubi->peb_count) {
- ubi_err("too high PEB number %d, total PEBs %d",
- seb->pnum, ubi->peb_count);
- goto bad_seb;
- }
-
- if (sv->vol_type == UBI_STATIC_VOLUME) {
- if (seb->lnum >= sv->used_ebs) {
- ubi_err("bad lnum or used_ebs");
- goto bad_seb;
- }
- } else {
- if (sv->used_ebs != 0) {
- ubi_err("non-zero used_ebs");
- goto bad_seb;
- }
- }
-
- if (seb->lnum > sv->highest_lnum) {
- ubi_err("incorrect highest_lnum or lnum");
- goto bad_seb;
- }
- }
-
- if (sv->leb_count != leb_count) {
- ubi_err("bad leb_count, %d objects in the tree",
- leb_count);
- goto bad_sv;
- }
-
- if (!last_seb)
- continue;
-
- seb = last_seb;
-
- if (seb->lnum != sv->highest_lnum) {
- ubi_err("bad highest_lnum");
- goto bad_seb;
- }
- }
-
- if (vols_found != si->vols_found) {
- ubi_err("bad si->vols_found %d, should be %d",
- si->vols_found, vols_found);
- goto out;
- }
-
- /* Check that scanning information is correct */
- ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
- last_seb = NULL;
- ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) {
- int vol_type;
-
- cond_resched();
-
- last_seb = seb;
-
- err = ubi_io_read_vid_hdr(ubi, seb->pnum, vidh, 1);
- if (err && err != UBI_IO_BITFLIPS) {
- ubi_err("VID header is not OK (%d)", err);
- if (err > 0)
- err = -EIO;
- return err;
- }
-
- vol_type = vidh->vol_type == UBI_VID_DYNAMIC ?
- UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME;
- if (sv->vol_type != vol_type) {
- ubi_err("bad vol_type");
- goto bad_vid_hdr;
- }
-
- if (seb->sqnum != be64_to_cpu(vidh->sqnum)) {
- ubi_err("bad sqnum %llu", seb->sqnum);
- goto bad_vid_hdr;
- }
-
- if (sv->vol_id != be32_to_cpu(vidh->vol_id)) {
- ubi_err("bad vol_id %d", sv->vol_id);
- goto bad_vid_hdr;
- }
-
- if (sv->compat != vidh->compat) {
- ubi_err("bad compat %d", vidh->compat);
- goto bad_vid_hdr;
- }
-
- if (seb->lnum != be32_to_cpu(vidh->lnum)) {
- ubi_err("bad lnum %d", seb->lnum);
- goto bad_vid_hdr;
- }
-
- if (sv->used_ebs != be32_to_cpu(vidh->used_ebs)) {
- ubi_err("bad used_ebs %d", sv->used_ebs);
- goto bad_vid_hdr;
- }
-
- if (sv->data_pad != be32_to_cpu(vidh->data_pad)) {
- ubi_err("bad data_pad %d", sv->data_pad);
- goto bad_vid_hdr;
- }
- }
-
- if (!last_seb)
- continue;
-
- if (sv->highest_lnum != be32_to_cpu(vidh->lnum)) {
- ubi_err("bad highest_lnum %d", sv->highest_lnum);
- goto bad_vid_hdr;
- }
-
- if (sv->last_data_size != be32_to_cpu(vidh->data_size)) {
- ubi_err("bad last_data_size %d", sv->last_data_size);
- goto bad_vid_hdr;
- }
- }
-
- /*
- * Make sure that all the physical eraseblocks are in one of the lists
- * or trees.
- */
- buf = kzalloc(ubi->peb_count, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- for (pnum = 0; pnum < ubi->peb_count; pnum++) {
- err = ubi_io_is_bad(ubi, pnum);
- if (err < 0) {
- kfree(buf);
- return err;
- } else if (err)
- buf[pnum] = 1;
- }
-
- ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb)
- ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb)
- buf[seb->pnum] = 1;
-
- list_for_each_entry(seb, &si->free, u.list)
- buf[seb->pnum] = 1;
-
- list_for_each_entry(seb, &si->corr, u.list)
- buf[seb->pnum] = 1;
-
- list_for_each_entry(seb, &si->erase, u.list)
- buf[seb->pnum] = 1;
-
- list_for_each_entry(seb, &si->alien, u.list)
- buf[seb->pnum] = 1;
-
- err = 0;
- for (pnum = 0; pnum < ubi->peb_count; pnum++)
- if (!buf[pnum]) {
- ubi_err("PEB %d is not referred", pnum);
- err = 1;
- }
-
- kfree(buf);
- if (err)
- goto out;
- return 0;
-
-bad_seb:
- ubi_err("bad scanning information about LEB %d", seb->lnum);
- ubi_dbg_dump_seb(seb, 0);
- ubi_dbg_dump_sv(sv);
- goto out;
-
-bad_sv:
- ubi_err("bad scanning information about volume %d", sv->vol_id);
- ubi_dbg_dump_sv(sv);
- goto out;
-
-bad_vid_hdr:
- ubi_err("bad scanning information about volume %d", sv->vol_id);
- ubi_dbg_dump_sv(sv);
- ubi_dbg_dump_vid_hdr(vidh);
-
-out:
- ubi_dbg_dump_stack();
- return -EINVAL;
-}
-
-#endif /* CONFIG_MTD_UBI_DEBUG */
diff -uN -uNr linux-3.0/drivers/mtd/ubi/scan.h linux-3.0.x.ubifs.latest/drivers/mtd/ubi/scan.h
--- linux-3.0/drivers/mtd/ubi/scan.h 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/scan.h 1969-12-31 18:00:00.000000000 -0600
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Author: Artem Bityutskiy (Битюцкий Артём)
- */
-
-#ifndef __UBI_SCAN_H__
-#define __UBI_SCAN_H__
-
-/* The erase counter value for this physical eraseblock is unknown */
-#define UBI_SCAN_UNKNOWN_EC (-1)
-
-/**
- * struct ubi_scan_leb - scanning information about a physical eraseblock.
- * @ec: erase counter (%UBI_SCAN_UNKNOWN_EC if it is unknown)
- * @pnum: physical eraseblock number
- * @lnum: logical eraseblock number
- * @scrub: if this physical eraseblock needs scrubbing
- * @copy_flag: this LEB is a copy (@copy_flag is set in VID header of this LEB)
- * @sqnum: sequence number
- * @u: unions RB-tree or @list links
- * @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects
- * @u.list: link in one of the eraseblock lists
- *
- * One object of this type is allocated for each physical eraseblock during
- * scanning.
- */
-struct ubi_scan_leb {
- int ec;
- int pnum;
- int lnum;
- unsigned int scrub:1;
- unsigned int copy_flag:1;
- unsigned long long sqnum;
- union {
- struct rb_node rb;
- struct list_head list;
- } u;
-};
-
-/**
- * struct ubi_scan_volume - scanning information about a volume.
- * @vol_id: volume ID
- * @highest_lnum: highest logical eraseblock number in this volume
- * @leb_count: number of logical eraseblocks in this volume
- * @vol_type: volume type
- * @used_ebs: number of used logical eraseblocks in this volume (only for
- * static volumes)
- * @last_data_size: amount of data in the last logical eraseblock of this
- * volume (always equivalent to the usable logical eraseblock
- * size in case of dynamic volumes)
- * @data_pad: how many bytes at the end of logical eraseblocks of this volume
- * are not used (due to volume alignment)
- * @compat: compatibility flags of this volume
- * @rb: link in the volume RB-tree
- * @root: root of the RB-tree containing all the eraseblock belonging to this
- * volume (&struct ubi_scan_leb objects)
- *
- * One object of this type is allocated for each volume during scanning.
- */
-struct ubi_scan_volume {
- int vol_id;
- int highest_lnum;
- int leb_count;
- int vol_type;
- int used_ebs;
- int last_data_size;
- int data_pad;
- int compat;
- struct rb_node rb;
- struct rb_root root;
-};
-
-/**
- * struct ubi_scan_info - UBI scanning information.
- * @volumes: root of the volume RB-tree
- * @corr: list of corrupted physical eraseblocks
- * @free: list of free physical eraseblocks
- * @erase: list of physical eraseblocks which have to be erased
- * @alien: list of physical eraseblocks which should not be used by UBI (e.g.,
- * those belonging to "preserve"-compatible internal volumes)
- * @corr_peb_count: count of PEBs in the @corr list
- * @empty_peb_count: count of PEBs which are presumably empty (contain only
- * 0xFF bytes)
- * @alien_peb_count: count of PEBs in the @alien list
- * @bad_peb_count: count of bad physical eraseblocks
- * @maybe_bad_peb_count: count of bad physical eraseblocks which are not marked
- * as bad yet, but which look like bad
- * @vols_found: number of volumes found during scanning
- * @highest_vol_id: highest volume ID
- * @is_empty: flag indicating whether the MTD device is empty or not
- * @min_ec: lowest erase counter value
- * @max_ec: highest erase counter value
- * @max_sqnum: highest sequence number value
- * @mean_ec: mean erase counter value
- * @ec_sum: a temporary variable used when calculating @mean_ec
- * @ec_count: a temporary variable used when calculating @mean_ec
- * @scan_leb_slab: slab cache for &struct ubi_scan_leb objects
- *
- * This data structure contains the result of scanning and may be used by other
- * UBI sub-systems to build final UBI data structures, further error-recovery
- * and so on.
- */
-struct ubi_scan_info {
- struct rb_root volumes;
- struct list_head corr;
- struct list_head free;
- struct list_head erase;
- struct list_head alien;
- int corr_peb_count;
- int empty_peb_count;
- int alien_peb_count;
- int bad_peb_count;
- int maybe_bad_peb_count;
- int vols_found;
- int highest_vol_id;
- int is_empty;
- int min_ec;
- int max_ec;
- unsigned long long max_sqnum;
- int mean_ec;
- uint64_t ec_sum;
- int ec_count;
- struct kmem_cache *scan_leb_slab;
-};
-
-struct ubi_device;
-struct ubi_vid_hdr;
-
-/*
- * ubi_scan_move_to_list - move a PEB from the volume tree to a list.
- *
- * @sv: volume scanning information
- * @seb: scanning eraseblock information
- * @list: the list to move to
- */
-static inline void ubi_scan_move_to_list(struct ubi_scan_volume *sv,
- struct ubi_scan_leb *seb,
- struct list_head *list)
-{
- rb_erase(&seb->u.rb, &sv->root);
- list_add_tail(&seb->u.list, list);
-}
-
-int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
- int pnum, int ec, const struct ubi_vid_hdr *vid_hdr,
- int bitflips);
-struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si,
- int vol_id);
-struct ubi_scan_leb *ubi_scan_find_seb(const struct ubi_scan_volume *sv,
- int lnum);
-void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv);
-struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
- struct ubi_scan_info *si);
-int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si,
- int pnum, int ec);
-struct ubi_scan_info *ubi_scan(struct ubi_device *ubi);
-void ubi_scan_destroy_si(struct ubi_scan_info *si);
-
-#endif /* !__UBI_SCAN_H__ */
diff -uN -uNr linux-3.0/drivers/mtd/ubi/ubi-media.h linux-3.0.x.ubifs.latest/drivers/mtd/ubi/ubi-media.h
--- linux-3.0/drivers/mtd/ubi/ubi-media.h 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/ubi-media.h 2012-06-28 11:26:15.000000000 -0500
@@ -149,10 +149,10 @@
* The @image_seq field is used to validate a UBI image that has been prepared
* for a UBI device. The @image_seq value can be any value, but it must be the
* same on all eraseblocks. UBI will ensure that all new erase counter headers
- * also contain this value, and will check the value when scanning at start-up.
+ * also contain this value, and will check the value when attaching the flash.
* One way to make use of @image_seq is to increase its value by one every time
* an image is flashed over an existing image, then, if the flashing does not
- * complete, UBI will detect the error when scanning.
+ * complete, UBI will detect the error when attaching the media.
*/
struct ubi_ec_hdr {
__be32 magic;
@@ -298,8 +298,8 @@
#define UBI_INT_VOL_COUNT 1
/*
- * Starting ID of internal volumes. There is reserved room for 4096 internal
- * volumes.
+ * Starting ID of internal volumes: 0x7fffefff.
+ * There is reserved room for 4096 internal volumes.
*/
#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
diff -uN -uNr linux-3.0/drivers/mtd/ubi/ubi.h linux-3.0.x.ubifs.latest/drivers/mtd/ubi/ubi.h
--- linux-3.0/drivers/mtd/ubi/ubi.h 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/ubi.h 2012-06-28 11:26:15.000000000 -0500
@@ -43,8 +43,6 @@
#include <asm/pgtable.h>
#include "ubi-media.h"
-#include "scan.h"
-#include "debug.h"
/* Maximum number of supported UBI devices */
#define UBI_MAX_DEVICES 32
@@ -67,7 +65,10 @@
/* Background thread name pattern */
#define UBI_BGT_NAME_PATTERN "ubi_bgt%dd"
-/* This marker in the EBA table means that the LEB is um-mapped */
+/*
+ * This marker in the EBA table means that the LEB is um-mapped.
+ * NOTE! It has to have the same value as %UBI_ALL.
+ */
#define UBI_LEB_UNMAPPED -1
/*
@@ -83,6 +84,9 @@
*/
#define UBI_PROT_QUEUE_LEN 10
+/* The volume ID/LEB number/erase counter is unknown */
+#define UBI_UNKNOWN -1
+
/*
* Error codes returned by the I/O sub-system.
*
@@ -119,15 +123,17 @@
* PEB
* MOVE_TARGET_WR_ERR: canceled because there was a write error to the target
* PEB
- * MOVE_CANCEL_BITFLIPS: canceled because a bit-flip was detected in the
+ * MOVE_TARGET_BITFLIPS: canceled because a bit-flip was detected in the
* target PEB
+ * MOVE_RETRY: retry scrubbing the PEB
*/
enum {
MOVE_CANCEL_RACE = 1,
MOVE_SOURCE_RD_ERR,
MOVE_TARGET_RD_ERR,
MOVE_TARGET_WR_ERR,
- MOVE_CANCEL_BITFLIPS,
+ MOVE_TARGET_BITFLIPS,
+ MOVE_RETRY,
};
/**
@@ -221,8 +227,6 @@
* @upd_ebs: how many eraseblocks are expected to be updated
* @ch_lnum: LEB number which is being changing by the atomic LEB change
* operation
- * @ch_dtype: data persistency type which is being changing by the atomic LEB
- * change operation
* @upd_bytes: how many bytes are expected to be received for volume update or
* atomic LEB change
* @upd_received: how many bytes were already received for volume update or
@@ -269,7 +273,6 @@
int upd_ebs;
int ch_lnum;
- int ch_dtype;
long long upd_bytes;
long long upd_received;
void *upd_buf;
@@ -386,10 +389,11 @@
* time (MTD write buffer size)
* @mtd: MTD device descriptor
*
- * @peb_buf1: a buffer of PEB size used for different purposes
- * @peb_buf2: another buffer of PEB size used for different purposes
- * @buf_mutex: protects @peb_buf1 and @peb_buf2
+ * @peb_buf: a buffer of PEB size used for different purposes
+ * @buf_mutex: protects @peb_buf
* @ckvol_mutex: serializes static volume checking when opening
+ *
+ * @dbg: debugging information for this UBI device
*/
struct ubi_device {
struct cdev cdev;
@@ -468,12 +472,133 @@
int max_write_size;
struct mtd_info *mtd;
- void *peb_buf1;
- void *peb_buf2;
+ void *peb_buf;
struct mutex buf_mutex;
struct mutex ckvol_mutex;
+
+ struct ubi_debug_info *dbg;
+};
+
+/**
+ * struct ubi_ainf_peb - attach information about a physical eraseblock.
+ * @ec: erase counter (%UBI_UNKNOWN if it is unknown)
+ * @pnum: physical eraseblock number
+ * @vol_id: ID of the volume this LEB belongs to
+ * @lnum: logical eraseblock number
+ * @scrub: if this physical eraseblock needs scrubbing
+ * @copy_flag: this LEB is a copy (@copy_flag is set in VID header of this LEB)
+ * @sqnum: sequence number
+ * @u: unions RB-tree or @list links
+ * @u.rb: link in the per-volume RB-tree of &struct ubi_ainf_peb objects
+ * @u.list: link in one of the eraseblock lists
+ *
+ * One object of this type is allocated for each physical eraseblock when
+ * attaching an MTD device. Note, if this PEB does not belong to any LEB /
+ * volume, the @vol_id and @lnum fields are initialized to %UBI_UNKNOWN.
+ */
+struct ubi_ainf_peb {
+ int ec;
+ int pnum;
+ int vol_id;
+ int lnum;
+ unsigned int scrub:1;
+ unsigned int copy_flag:1;
+ unsigned long long sqnum;
+ union {
+ struct rb_node rb;
+ struct list_head list;
+ } u;
+};
+
+/**
+ * struct ubi_ainf_volume - attaching information about a volume.
+ * @vol_id: volume ID
+ * @highest_lnum: highest logical eraseblock number in this volume
+ * @leb_count: number of logical eraseblocks in this volume
+ * @vol_type: volume type
+ * @used_ebs: number of used logical eraseblocks in this volume (only for
+ * static volumes)
+ * @last_data_size: amount of data in the last logical eraseblock of this
+ * volume (always equivalent to the usable logical eraseblock
+ * size in case of dynamic volumes)
+ * @data_pad: how many bytes at the end of logical eraseblocks of this volume
+ * are not used (due to volume alignment)
+ * @compat: compatibility flags of this volume
+ * @rb: link in the volume RB-tree
+ * @root: root of the RB-tree containing all the eraseblock belonging to this
+ * volume (&struct ubi_ainf_peb objects)
+ *
+ * One object of this type is allocated for each volume when attaching an MTD
+ * device.
+ */
+struct ubi_ainf_volume {
+ int vol_id;
+ int highest_lnum;
+ int leb_count;
+ int vol_type;
+ int used_ebs;
+ int last_data_size;
+ int data_pad;
+ int compat;
+ struct rb_node rb;
+ struct rb_root root;
};
+/**
+ * struct ubi_attach_info - MTD device attaching information.
+ * @volumes: root of the volume RB-tree
+ * @corr: list of corrupted physical eraseblocks
+ * @free: list of free physical eraseblocks
+ * @erase: list of physical eraseblocks which have to be erased
+ * @alien: list of physical eraseblocks which should not be used by UBI (e.g.,
+ * those belonging to "preserve"-compatible internal volumes)
+ * @corr_peb_count: count of PEBs in the @corr list
+ * @empty_peb_count: count of PEBs which are presumably empty (contain only
+ * 0xFF bytes)
+ * @alien_peb_count: count of PEBs in the @alien list
+ * @bad_peb_count: count of bad physical eraseblocks
+ * @maybe_bad_peb_count: count of bad physical eraseblocks which are not marked
+ * as bad yet, but which look like bad
+ * @vols_found: number of volumes found
+ * @highest_vol_id: highest volume ID
+ * @is_empty: flag indicating whether the MTD device is empty or not
+ * @min_ec: lowest erase counter value
+ * @max_ec: highest erase counter value
+ * @max_sqnum: highest sequence number value
+ * @mean_ec: mean erase counter value
+ * @ec_sum: a temporary variable used when calculating @mean_ec
+ * @ec_count: a temporary variable used when calculating @mean_ec
+ * @aeb_slab_cache: slab cache for &struct ubi_ainf_peb objects
+ *
+ * This data structure contains the result of attaching an MTD device and may
+ * be used by other UBI sub-systems to build final UBI data structures, further
+ * error-recovery and so on.
+ */
+struct ubi_attach_info {
+ struct rb_root volumes;
+ struct list_head corr;
+ struct list_head free;
+ struct list_head erase;
+ struct list_head alien;
+ int corr_peb_count;
+ int empty_peb_count;
+ int alien_peb_count;
+ int bad_peb_count;
+ int maybe_bad_peb_count;
+ int vols_found;
+ int highest_vol_id;
+ int is_empty;
+ int min_ec;
+ int max_ec;
+ unsigned long long max_sqnum;
+ int mean_ec;
+ uint64_t ec_sum;
+ int ec_count;
+ struct kmem_cache *aeb_slab_cache;
+};
+
+#include "debug.h"
+
extern struct kmem_cache *ubi_wl_entry_slab;
extern const struct file_operations ubi_ctrl_cdev_operations;
extern const struct file_operations ubi_cdev_operations;
@@ -482,12 +607,23 @@
extern struct mutex ubi_devices_mutex;
extern struct blocking_notifier_head ubi_notifiers;
+/* scan.c */
+int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum,
+ int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips);
+struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai,
+ int vol_id);
+void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av);
+struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi,
+ struct ubi_attach_info *ai);
+int ubi_attach(struct ubi_device *ubi);
+void ubi_destroy_ai(struct ubi_attach_info *ai);
+
/* vtbl.c */
int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
struct ubi_vtbl_record *vtbl_rec);
int ubi_vtbl_rename_volumes(struct ubi_device *ubi,
struct list_head *rename_list);
-int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si);
+int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai);
/* vmt.c */
int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req);
@@ -520,22 +656,22 @@
int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
void *buf, int offset, int len, int check);
int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
- const void *buf, int offset, int len, int dtype);
+ const void *buf, int offset, int len);
int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol,
- int lnum, const void *buf, int len, int dtype,
- int used_ebs);
+ int lnum, const void *buf, int len, int used_ebs);
int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
- int lnum, const void *buf, int len, int dtype);
+ int lnum, const void *buf, int len);
int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
struct ubi_vid_hdr *vid_hdr);
-int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si);
+int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai);
/* wl.c */
-int ubi_wl_get_peb(struct ubi_device *ubi, int dtype);
-int ubi_wl_put_peb(struct ubi_device *ubi, int pnum, int torture);
-int ubi_wl_flush(struct ubi_device *ubi);
+int ubi_wl_get_peb(struct ubi_device *ubi);
+int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum,
+ int pnum, int torture);
+int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum);
int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum);
-int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si);
+int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai);
void ubi_wl_close(struct ubi_device *ubi);
int ubi_thread(void *u);
@@ -568,6 +704,7 @@
int ubi_notify_all(struct ubi_device *ubi, int ntype,
struct notifier_block *nb);
int ubi_enumerate_volumes(struct notifier_block *nb);
+void ubi_free_internal_volumes(struct ubi_device *ubi);
/* kapi.c */
void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di);
@@ -588,6 +725,21 @@
rb = rb_next(rb), \
pos = (rb ? container_of(rb, typeof(*pos), member) : NULL))
+/*
+ * ubi_move_aeb_to_list - move a PEB from the volume tree to a list.
+ *
+ * @av: volume attaching information
+ * @aeb: attaching eraseblock information
+ * @list: the list to move to
+ */
+static inline void ubi_move_aeb_to_list(struct ubi_ainf_volume *av,
+ struct ubi_ainf_peb *aeb,
+ struct list_head *list)
+{
+ rb_erase(&aeb->u.rb, &av->root);
+ list_add_tail(&aeb->u.list, list);
+}
+
/**
* ubi_zalloc_vid_hdr - allocate a volume identifier header object.
* @ubi: UBI device description object
@@ -662,6 +814,7 @@
if (!ubi->ro_mode) {
ubi->ro_mode = 1;
ubi_warn("switch to read-only mode");
+ dump_stack();
}
}
diff -uN -uNr linux-3.0/drivers/mtd/ubi/upd.c linux-3.0.x.ubifs.latest/drivers/mtd/ubi/upd.c
--- linux-3.0/drivers/mtd/ubi/upd.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/upd.c 2012-06-28 11:26:15.000000000 -0500
@@ -147,7 +147,7 @@
}
if (bytes == 0) {
- err = ubi_wl_flush(ubi);
+ err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
if (err)
return err;
@@ -186,14 +186,12 @@
dbg_gen("start changing LEB %d:%d, %u bytes",
vol->vol_id, req->lnum, req->bytes);
if (req->bytes == 0)
- return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0,
- req->dtype);
+ return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0);
vol->upd_bytes = req->bytes;
vol->upd_received = 0;
vol->changing_leb = 1;
vol->ch_lnum = req->lnum;
- vol->ch_dtype = req->dtype;
vol->upd_buf = vmalloc(req->bytes);
if (!vol->upd_buf)
@@ -246,8 +244,7 @@
return 0;
}
- err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len,
- UBI_UNKNOWN);
+ err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len);
} else {
/*
* When writing static volume, and this is the last logical
@@ -259,8 +256,7 @@
* contain zeros, not random trash.
*/
memset(buf + len, 0, vol->usable_leb_size - len);
- err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len,
- UBI_UNKNOWN, used_ebs);
+ err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len, used_ebs);
}
return err;
@@ -365,7 +361,7 @@
ubi_assert(vol->upd_received <= vol->upd_bytes);
if (vol->upd_received == vol->upd_bytes) {
- err = ubi_wl_flush(ubi);
+ err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
if (err)
return err;
/* The update is finished, clear the update marker */
@@ -421,7 +417,7 @@
len - vol->upd_bytes);
len = ubi_calc_data_len(ubi, vol->upd_buf, len);
err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum,
- vol->upd_buf, len, UBI_UNKNOWN);
+ vol->upd_buf, len);
if (err)
return err;
}
diff -uN -uNr linux-3.0/drivers/mtd/ubi/vmt.c linux-3.0.x.ubifs.latest/drivers/mtd/ubi/vmt.c
--- linux-3.0/drivers/mtd/ubi/vmt.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/vmt.c 2012-06-28 11:26:15.000000000 -0500
@@ -28,11 +28,7 @@
#include <linux/slab.h>
#include "ubi.h"
-#ifdef CONFIG_MTD_UBI_DEBUG
-static int paranoid_check_volumes(struct ubi_device *ubi);
-#else
-#define paranoid_check_volumes(ubi) 0
-#endif
+static int self_check_volumes(struct ubi_device *ubi);
static ssize_t vol_attribute_show(struct device *dev,
struct device_attribute *attr, char *buf);
@@ -226,7 +222,7 @@
}
if (vol_id == UBI_VOL_NUM_AUTO) {
- dbg_err("out of volume IDs");
+ ubi_err("out of volume IDs");
err = -ENFILE;
goto out_unlock;
}
@@ -240,7 +236,7 @@
/* Ensure that this volume does not exist */
err = -EEXIST;
if (ubi->volumes[vol_id]) {
- dbg_err("volume %d already exists", vol_id);
+ ubi_err("volume %d already exists", vol_id);
goto out_unlock;
}
@@ -249,7 +245,7 @@
if (ubi->volumes[i] &&
ubi->volumes[i]->name_len == req->name_len &&
!strcmp(ubi->volumes[i]->name, req->name)) {
- dbg_err("volume \"%s\" exists (ID %d)", req->name, i);
+ ubi_err("volume \"%s\" exists (ID %d)", req->name, i);
goto out_unlock;
}
@@ -260,9 +256,9 @@
/* Reserve physical eraseblocks */
if (vol->reserved_pebs > ubi->avail_pebs) {
- dbg_err("not enough PEBs, only %d available", ubi->avail_pebs);
+ ubi_err("not enough PEBs, only %d available", ubi->avail_pebs);
if (ubi->corr_peb_count)
- dbg_err("%d PEBs are corrupted and not used",
+ ubi_err("%d PEBs are corrupted and not used",
ubi->corr_peb_count);
err = -ENOSPC;
goto out_unlock;
@@ -283,7 +279,7 @@
* Finish all pending erases because there may be some LEBs belonging
* to the same volume ID.
*/
- err = ubi_wl_flush(ubi);
+ err = ubi_wl_flush(ubi, vol_id, UBI_ALL);
if (err)
goto out_acc;
@@ -359,8 +355,7 @@
spin_unlock(&ubi->volumes_lock);
ubi_volume_notify(ubi, vol, UBI_VOLUME_ADDED);
- if (paranoid_check_volumes(ubi))
- dbg_err("check failed while creating volume %d", vol_id);
+ self_check_volumes(ubi);
return err;
out_sysfs:
@@ -460,8 +455,8 @@
spin_unlock(&ubi->volumes_lock);
ubi_volume_notify(ubi, vol, UBI_VOLUME_REMOVED);
- if (!no_vtbl && paranoid_check_volumes(ubi))
- dbg_err("check failed while removing volume %d", vol_id);
+ if (!no_vtbl)
+ self_check_volumes(ubi);
return err;
@@ -499,7 +494,7 @@
if (vol->vol_type == UBI_STATIC_VOLUME &&
reserved_pebs < vol->used_ebs) {
- dbg_err("too small size %d, %d LEBs contain data",
+ ubi_err("too small size %d, %d LEBs contain data",
reserved_pebs, vol->used_ebs);
return -EINVAL;
}
@@ -528,10 +523,10 @@
if (pebs > 0) {
spin_lock(&ubi->volumes_lock);
if (pebs > ubi->avail_pebs) {
- dbg_err("not enough PEBs: requested %d, available %d",
+ ubi_err("not enough PEBs: requested %d, available %d",
pebs, ubi->avail_pebs);
if (ubi->corr_peb_count)
- dbg_err("%d PEBs are corrupted and not used",
+ ubi_err("%d PEBs are corrupted and not used",
ubi->corr_peb_count);
spin_unlock(&ubi->volumes_lock);
err = -ENOSPC;
@@ -587,8 +582,7 @@
}
ubi_volume_notify(ubi, vol, UBI_VOLUME_RESIZED);
- if (paranoid_check_volumes(ubi))
- dbg_err("check failed while re-sizing volume %d", vol_id);
+ self_check_volumes(ubi);
return err;
out_acc:
@@ -637,8 +631,8 @@
}
}
- if (!err && paranoid_check_volumes(ubi))
- ;
+ if (!err)
+ self_check_volumes(ubi);
return err;
}
@@ -685,8 +679,7 @@
return err;
}
- if (paranoid_check_volumes(ubi))
- dbg_err("check failed while adding volume %d", vol_id);
+ self_check_volumes(ubi);
return err;
out_cdev:
@@ -711,16 +704,14 @@
volume_sysfs_close(vol);
}
-#ifdef CONFIG_MTD_UBI_DEBUG
-
/**
- * paranoid_check_volume - check volume information.
+ * self_check_volume - check volume information.
* @ubi: UBI device description object
* @vol_id: volume ID
*
* Returns zero if volume is all right and a a negative error code if not.
*/
-static int paranoid_check_volume(struct ubi_device *ubi, int vol_id)
+static int self_check_volume(struct ubi_device *ubi, int vol_id)
{
int idx = vol_id2idx(ubi, vol_id);
int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker;
@@ -770,7 +761,7 @@
}
if (vol->upd_marker && vol->corrupted) {
- dbg_err("update marker and corrupted simultaneously");
+ ubi_err("update marker and corrupted simultaneously");
goto fail;
}
@@ -852,34 +843,33 @@
return 0;
fail:
- ubi_err("paranoid check failed for volume %d", vol_id);
+ ubi_err("self-check failed for volume %d", vol_id);
if (vol)
- ubi_dbg_dump_vol_info(vol);
- ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id);
+ ubi_dump_vol_info(vol);
+ ubi_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id);
dump_stack();
spin_unlock(&ubi->volumes_lock);
return -EINVAL;
}
/**
- * paranoid_check_volumes - check information about all volumes.
+ * self_check_volumes - check information about all volumes.
* @ubi: UBI device description object
*
* Returns zero if volumes are all right and a a negative error code if not.
*/
-static int paranoid_check_volumes(struct ubi_device *ubi)
+static int self_check_volumes(struct ubi_device *ubi)
{
int i, err = 0;
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return 0;
for (i = 0; i < ubi->vtbl_slots; i++) {
- err = paranoid_check_volume(ubi, i);
+ err = self_check_volume(ubi, i);
if (err)
break;
}
return err;
}
-#endif
diff -uN -uNr linux-3.0/drivers/mtd/ubi/vtbl.c linux-3.0.x.ubifs.latest/drivers/mtd/ubi/vtbl.c
--- linux-3.0/drivers/mtd/ubi/vtbl.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/vtbl.c 2012-06-28 11:26:15.000000000 -0500
@@ -37,16 +37,15 @@
* LEB 1. This scheme guarantees recoverability from unclean reboots.
*
* In this UBI implementation the on-flash volume table does not contain any
- * information about how many data static volumes contain. This information may
- * be found from the scanning data.
+ * information about how much data static volumes contain.
*
* But it would still be beneficial to store this information in the volume
* table. For example, suppose we have a static volume X, and all its physical
* eraseblocks became bad for some reasons. Suppose we are attaching the
- * corresponding MTD device, the scanning has found no logical eraseblocks
+ * corresponding MTD device, for some reason we find no logical eraseblocks
* corresponding to the volume X. According to the volume table volume X does
* exist. So we don't know whether it is just empty or all its physical
- * eraseblocks went bad. So we cannot alarm the user about this corruption.
+ * eraseblocks went bad. So we cannot alarm the user properly.
*
* The volume table also stores so-called "update marker", which is used for
* volume updates. Before updating the volume, the update marker is set, and
@@ -62,11 +61,7 @@
#include <asm/div64.h>
#include "ubi.h"
-#ifdef CONFIG_MTD_UBI_DEBUG
-static void paranoid_vtbl_check(const struct ubi_device *ubi);
-#else
-#define paranoid_vtbl_check(ubi)
-#endif
+static void self_vtbl_check(const struct ubi_device *ubi);
/* Empty volume table record */
static struct ubi_vtbl_record empty_vtbl_record;
@@ -106,12 +101,12 @@
return err;
err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
- ubi->vtbl_size, UBI_LONGTERM);
+ ubi->vtbl_size);
if (err)
return err;
}
- paranoid_vtbl_check(ubi);
+ self_vtbl_check(ubi);
return 0;
}
@@ -158,7 +153,7 @@
return err;
err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0,
- ubi->vtbl_size, UBI_LONGTERM);
+ ubi->vtbl_size);
if (err)
return err;
}
@@ -197,7 +192,7 @@
if (be32_to_cpu(vtbl[i].crc) != crc) {
ubi_err("bad CRC at record %u: %#08x, not %#08x",
i, crc, be32_to_cpu(vtbl[i].crc));
- ubi_dbg_dump_vtbl_record(&vtbl[i], i);
+ ubi_dump_vtbl_record(&vtbl[i], i);
return 1;
}
@@ -229,7 +224,7 @@
n = ubi->leb_size % alignment;
if (data_pad != n) {
- dbg_err("bad data_pad, has to be %d", n);
+ ubi_err("bad data_pad, has to be %d", n);
err = 6;
goto bad;
}
@@ -245,7 +240,7 @@
}
if (reserved_pebs > ubi->good_peb_count) {
- dbg_err("too large reserved_pebs %d, good PEBs %d",
+ ubi_err("too large reserved_pebs %d, good PEBs %d",
reserved_pebs, ubi->good_peb_count);
err = 9;
goto bad;
@@ -277,8 +272,8 @@
!strncmp(vtbl[i].name, vtbl[n].name, len1)) {
ubi_err("volumes %d and %d have the same name"
" \"%s\"", i, n, vtbl[i].name);
- ubi_dbg_dump_vtbl_record(&vtbl[i], i);
- ubi_dbg_dump_vtbl_record(&vtbl[n], n);
+ ubi_dump_vtbl_record(&vtbl[i], i);
+ ubi_dump_vtbl_record(&vtbl[n], n);
return -EINVAL;
}
}
@@ -288,27 +283,26 @@
bad:
ubi_err("volume table check failed: record %d, error %d", i, err);
- ubi_dbg_dump_vtbl_record(&vtbl[i], i);
+ ubi_dump_vtbl_record(&vtbl[i], i);
return -EINVAL;
}
/**
* create_vtbl - create a copy of volume table.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
* @copy: number of the volume table copy
* @vtbl: contents of the volume table
*
* This function returns zero in case of success and a negative error code in
* case of failure.
*/
-static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
+static int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai,
int copy, void *vtbl)
{
int err, tries = 0;
- static struct ubi_vid_hdr *vid_hdr;
- struct ubi_scan_volume *sv;
- struct ubi_scan_leb *new_seb, *old_seb = NULL;
+ struct ubi_vid_hdr *vid_hdr;
+ struct ubi_ainf_peb *new_aeb;
ubi_msg("create volume table (copy #%d)", copy + 1);
@@ -316,47 +310,37 @@
if (!vid_hdr)
return -ENOMEM;
- /*
- * Check if there is a logical eraseblock which would have to contain
- * this volume table copy was found during scanning. It has to be wiped
- * out.
- */
- sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOLUME_ID);
- if (sv)
- old_seb = ubi_scan_find_seb(sv, copy);
-
retry:
- new_seb = ubi_scan_get_free_peb(ubi, si);
- if (IS_ERR(new_seb)) {
- err = PTR_ERR(new_seb);
+ new_aeb = ubi_early_get_peb(ubi, ai);
+ if (IS_ERR(new_aeb)) {
+ err = PTR_ERR(new_aeb);
goto out_free;
}
- vid_hdr->vol_type = UBI_VID_DYNAMIC;
+ vid_hdr->vol_type = UBI_LAYOUT_VOLUME_TYPE;
vid_hdr->vol_id = cpu_to_be32(UBI_LAYOUT_VOLUME_ID);
vid_hdr->compat = UBI_LAYOUT_VOLUME_COMPAT;
vid_hdr->data_size = vid_hdr->used_ebs =
vid_hdr->data_pad = cpu_to_be32(0);
vid_hdr->lnum = cpu_to_be32(copy);
- vid_hdr->sqnum = cpu_to_be64(++si->max_sqnum);
+ vid_hdr->sqnum = cpu_to_be64(++ai->max_sqnum);
/* The EC header is already there, write the VID header */
- err = ubi_io_write_vid_hdr(ubi, new_seb->pnum, vid_hdr);
+ err = ubi_io_write_vid_hdr(ubi, new_aeb->pnum, vid_hdr);
if (err)
goto write_error;
/* Write the layout volume contents */
- err = ubi_io_write_data(ubi, vtbl, new_seb->pnum, 0, ubi->vtbl_size);
+ err = ubi_io_write_data(ubi, vtbl, new_aeb->pnum, 0, ubi->vtbl_size);
if (err)
goto write_error;
/*
- * And add it to the scanning information. Don't delete the old
- * @old_seb as it will be deleted and freed in 'ubi_scan_add_used()'.
+ * And add it to the attaching information. Don't delete the old version
+ * of this LEB as it will be deleted and freed in 'ubi_add_to_av()'.
*/
- err = ubi_scan_add_used(ubi, si, new_seb->pnum, new_seb->ec,
- vid_hdr, 0);
- kfree(new_seb);
+ err = ubi_add_to_av(ubi, ai, new_aeb->pnum, new_aeb->ec, vid_hdr, 0);
+ kfree(new_aeb);
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
@@ -366,10 +350,10 @@
* Probably this physical eraseblock went bad, try to pick
* another one.
*/
- list_add(&new_seb->u.list, &si->erase);
+ list_add(&new_aeb->u.list, &ai->erase);
goto retry;
}
- kfree(new_seb);
+ kfree(new_aeb);
out_free:
ubi_free_vid_hdr(ubi, vid_hdr);
return err;
@@ -379,20 +363,20 @@
/**
* process_lvol - process the layout volume.
* @ubi: UBI device description object
- * @si: scanning information
- * @sv: layout volume scanning information
+ * @ai: attaching information
+ * @av: layout volume attaching information
*
* This function is responsible for reading the layout volume, ensuring it is
* not corrupted, and recovering from corruptions if needed. Returns volume
* table in case of success and a negative error code in case of failure.
*/
static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
- struct ubi_scan_info *si,
- struct ubi_scan_volume *sv)
+ struct ubi_attach_info *ai,
+ struct ubi_ainf_volume *av)
{
int err;
struct rb_node *rb;
- struct ubi_scan_leb *seb;
+ struct ubi_ainf_peb *aeb;
struct ubi_vtbl_record *leb[UBI_LAYOUT_VOLUME_EBS] = { NULL, NULL };
int leb_corrupted[UBI_LAYOUT_VOLUME_EBS] = {1, 1};
@@ -424,14 +408,14 @@
dbg_gen("check layout volume");
/* Read both LEB 0 and LEB 1 into memory */
- ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) {
- leb[seb->lnum] = vzalloc(ubi->vtbl_size);
- if (!leb[seb->lnum]) {
+ ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb) {
+ leb[aeb->lnum] = vzalloc(ubi->vtbl_size);
+ if (!leb[aeb->lnum]) {
err = -ENOMEM;
goto out_free;
}
- err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0,
+ err = ubi_io_read_data(ubi, leb[aeb->lnum], aeb->pnum, 0,
ubi->vtbl_size);
if (err == UBI_IO_BITFLIPS || err == -EBADMSG)
/*
@@ -439,12 +423,12 @@
* uncorrectable ECC error, but we have our own CRC and
* the data will be checked later. If the data is OK,
* the PEB will be scrubbed (because we set
- * seb->scrub). If the data is not OK, the contents of
+ * aeb->scrub). If the data is not OK, the contents of
* the PEB will be recovered from the second copy, and
- * seb->scrub will be cleared in
- * 'ubi_scan_add_used()'.
+ * aeb->scrub will be cleared in
+ * 'ubi_add_to_av()'.
*/
- seb->scrub = 1;
+ aeb->scrub = 1;
else if (err)
goto out_free;
}
@@ -463,7 +447,7 @@
ubi->vtbl_size);
if (leb_corrupted[1]) {
ubi_warn("volume table copy #2 is corrupted");
- err = create_vtbl(ubi, si, 1, leb[0]);
+ err = create_vtbl(ubi, ai, 1, leb[0]);
if (err)
goto out_free;
ubi_msg("volume table was restored");
@@ -486,7 +470,7 @@
}
ubi_warn("volume table copy #1 is corrupted");
- err = create_vtbl(ubi, si, 0, leb[1]);
+ err = create_vtbl(ubi, ai, 0, leb[1]);
if (err)
goto out_free;
ubi_msg("volume table was restored");
@@ -504,13 +488,13 @@
/**
* create_empty_lvol - create empty layout volume.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
*
* This function returns volume table contents in case of success and a
* negative error code in case of failure.
*/
static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi,
- struct ubi_scan_info *si)
+ struct ubi_attach_info *ai)
{
int i;
struct ubi_vtbl_record *vtbl;
@@ -525,7 +509,7 @@
for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
int err;
- err = create_vtbl(ubi, si, i, vtbl);
+ err = create_vtbl(ubi, ai, i, vtbl);
if (err) {
vfree(vtbl);
return ERR_PTR(err);
@@ -538,18 +522,19 @@
/**
* init_volumes - initialize volume information for existing volumes.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: scanning information
* @vtbl: volume table
*
* This function allocates volume description objects for existing volumes.
* Returns zero in case of success and a negative error code in case of
* failure.
*/
-static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
+static int init_volumes(struct ubi_device *ubi,
+ const struct ubi_attach_info *ai,
const struct ubi_vtbl_record *vtbl)
{
int i, reserved_pebs = 0;
- struct ubi_scan_volume *sv;
+ struct ubi_ainf_volume *av;
struct ubi_volume *vol;
for (i = 0; i < ubi->vtbl_slots; i++) {
@@ -605,8 +590,8 @@
}
/* Static volumes only */
- sv = ubi_scan_find_sv(si, i);
- if (!sv) {
+ av = ubi_find_av(ai, i);
+ if (!av) {
/*
* No eraseblocks belonging to this volume found. We
* don't actually know whether this static volume is
@@ -618,22 +603,22 @@
continue;
}
- if (sv->leb_count != sv->used_ebs) {
+ if (av->leb_count != av->used_ebs) {
/*
* We found a static volume which misses several
* eraseblocks. Treat it as corrupted.
*/
ubi_warn("static volume %d misses %d LEBs - corrupted",
- sv->vol_id, sv->used_ebs - sv->leb_count);
+ av->vol_id, av->used_ebs - av->leb_count);
vol->corrupted = 1;
continue;
}
- vol->used_ebs = sv->used_ebs;
+ vol->used_ebs = av->used_ebs;
vol->used_bytes =
(long long)(vol->used_ebs - 1) * vol->usable_leb_size;
- vol->used_bytes += sv->last_data_size;
- vol->last_eb_bytes = sv->last_data_size;
+ vol->used_bytes += av->last_data_size;
+ vol->last_eb_bytes = av->last_data_size;
}
/* And add the layout volume */
@@ -642,7 +627,7 @@
return -ENOMEM;
vol->reserved_pebs = UBI_LAYOUT_VOLUME_EBS;
- vol->alignment = 1;
+ vol->alignment = UBI_LAYOUT_VOLUME_ALIGN;
vol->vol_type = UBI_DYNAMIC_VOLUME;
vol->name_len = sizeof(UBI_LAYOUT_VOLUME_NAME) - 1;
memcpy(vol->name, UBI_LAYOUT_VOLUME_NAME, vol->name_len + 1);
@@ -674,105 +659,104 @@
}
/**
- * check_sv - check volume scanning information.
+ * check_av - check volume attaching information.
* @vol: UBI volume description object
- * @sv: volume scanning information
+ * @av: volume attaching information
*
- * This function returns zero if the volume scanning information is consistent
+ * This function returns zero if the volume attaching information is consistent
* to the data read from the volume tabla, and %-EINVAL if not.
*/
-static int check_sv(const struct ubi_volume *vol,
- const struct ubi_scan_volume *sv)
+static int check_av(const struct ubi_volume *vol,
+ const struct ubi_ainf_volume *av)
{
int err;
- if (sv->highest_lnum >= vol->reserved_pebs) {
+ if (av->highest_lnum >= vol->reserved_pebs) {
err = 1;
goto bad;
}
- if (sv->leb_count > vol->reserved_pebs) {
+ if (av->leb_count > vol->reserved_pebs) {
err = 2;
goto bad;
}
- if (sv->vol_type != vol->vol_type) {
+ if (av->vol_type != vol->vol_type) {
err = 3;
goto bad;
}
- if (sv->used_ebs > vol->reserved_pebs) {
+ if (av->used_ebs > vol->reserved_pebs) {
err = 4;
goto bad;
}
- if (sv->data_pad != vol->data_pad) {
+ if (av->data_pad != vol->data_pad) {
err = 5;
goto bad;
}
return 0;
bad:
- ubi_err("bad scanning information, error %d", err);
- ubi_dbg_dump_sv(sv);
- ubi_dbg_dump_vol_info(vol);
+ ubi_err("bad attaching information, error %d", err);
+ ubi_dump_av(av);
+ ubi_dump_vol_info(vol);
return -EINVAL;
}
/**
- * check_scanning_info - check that scanning information.
+ * check_attaching_info - check that attaching information.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
*
* Even though we protect on-flash data by CRC checksums, we still don't trust
- * the media. This function ensures that scanning information is consistent to
- * the information read from the volume table. Returns zero if the scanning
+ * the media. This function ensures that attaching information is consistent to
+ * the information read from the volume table. Returns zero if the attaching
* information is OK and %-EINVAL if it is not.
*/
-static int check_scanning_info(const struct ubi_device *ubi,
- struct ubi_scan_info *si)
+static int check_attaching_info(const struct ubi_device *ubi,
+ struct ubi_attach_info *ai)
{
int err, i;
- struct ubi_scan_volume *sv;
+ struct ubi_ainf_volume *av;
struct ubi_volume *vol;
- if (si->vols_found > UBI_INT_VOL_COUNT + ubi->vtbl_slots) {
- ubi_err("scanning found %d volumes, maximum is %d + %d",
- si->vols_found, UBI_INT_VOL_COUNT, ubi->vtbl_slots);
+ if (ai->vols_found > UBI_INT_VOL_COUNT + ubi->vtbl_slots) {
+ ubi_err("found %d volumes while attaching, maximum is %d + %d",
+ ai->vols_found, UBI_INT_VOL_COUNT, ubi->vtbl_slots);
return -EINVAL;
}
- if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT &&
- si->highest_vol_id < UBI_INTERNAL_VOL_START) {
- ubi_err("too large volume ID %d found by scanning",
- si->highest_vol_id);
+ if (ai->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT &&
+ ai->highest_vol_id < UBI_INTERNAL_VOL_START) {
+ ubi_err("too large volume ID %d found", ai->highest_vol_id);
return -EINVAL;
}
for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
cond_resched();
- sv = ubi_scan_find_sv(si, i);
+ av = ubi_find_av(ai, i);
vol = ubi->volumes[i];
if (!vol) {
- if (sv)
- ubi_scan_rm_volume(si, sv);
+ if (av)
+ ubi_remove_av(ai, av);
continue;
}
if (vol->reserved_pebs == 0) {
ubi_assert(i < ubi->vtbl_slots);
- if (!sv)
+ if (!av)
continue;
/*
- * During scanning we found a volume which does not
+ * During attaching we found a volume which does not
* exist according to the information in the volume
* table. This must have happened due to an unclean
* reboot while the volume was being removed. Discard
* these eraseblocks.
*/
- ubi_msg("finish volume %d removal", sv->vol_id);
- ubi_scan_rm_volume(si, sv);
- } else if (sv) {
- err = check_sv(vol, sv);
+ ubi_msg("finish volume %d removal", av->vol_id);
+ ubi_remove_av(ai, av);
+ } else if (av) {
+ err = check_av(vol, av);
if (err)
return err;
}
@@ -784,16 +768,16 @@
/**
* ubi_read_volume_table - read the volume table.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
*
* This function reads volume table, checks it, recover from errors if needed,
* or creates it if needed. Returns zero in case of success and a negative
* error code in case of failure.
*/
-int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
+int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai)
{
int i, err;
- struct ubi_scan_volume *sv;
+ struct ubi_ainf_volume *av;
empty_vtbl_record.crc = cpu_to_be32(0xf116c36b);
@@ -808,8 +792,8 @@
ubi->vtbl_size = ubi->vtbl_slots * UBI_VTBL_RECORD_SIZE;
ubi->vtbl_size = ALIGN(ubi->vtbl_size, ubi->min_io_size);
- sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOLUME_ID);
- if (!sv) {
+ av = ubi_find_av(ai, UBI_LAYOUT_VOLUME_ID);
+ if (!av) {
/*
* No logical eraseblocks belonging to the layout volume were
* found. This could mean that the flash is just empty. In
@@ -818,8 +802,8 @@
* But if flash is not empty this must be a corruption or the
* MTD device just contains garbage.
*/
- if (si->is_empty) {
- ubi->vtbl = create_empty_lvol(ubi, si);
+ if (ai->is_empty) {
+ ubi->vtbl = create_empty_lvol(ubi, ai);
if (IS_ERR(ubi->vtbl))
return PTR_ERR(ubi->vtbl);
} else {
@@ -827,14 +811,14 @@
return -EINVAL;
}
} else {
- if (sv->leb_count > UBI_LAYOUT_VOLUME_EBS) {
+ if (av->leb_count > UBI_LAYOUT_VOLUME_EBS) {
/* This must not happen with proper UBI images */
- dbg_err("too many LEBs (%d) in layout volume",
- sv->leb_count);
+ ubi_err("too many LEBs (%d) in layout volume",
+ av->leb_count);
return -EINVAL;
}
- ubi->vtbl = process_lvol(ubi, si, sv);
+ ubi->vtbl = process_lvol(ubi, ai, av);
if (IS_ERR(ubi->vtbl))
return PTR_ERR(ubi->vtbl);
}
@@ -845,15 +829,15 @@
* The layout volume is OK, initialize the corresponding in-RAM data
* structures.
*/
- err = init_volumes(ubi, si, ubi->vtbl);
+ err = init_volumes(ubi, ai, ubi->vtbl);
if (err)
goto out_free;
/*
- * Make sure that the scanning information is consistent to the
+ * Make sure that the attaching information is consistent to the
* information stored in the volume table.
*/
- err = check_scanning_info(ubi, si);
+ err = check_attaching_info(ubi, ai);
if (err)
goto out_free;
@@ -868,21 +852,17 @@
return err;
}
-#ifdef CONFIG_MTD_UBI_DEBUG
-
/**
- * paranoid_vtbl_check - check volume table.
+ * self_vtbl_check - check volume table.
* @ubi: UBI device description object
*/
-static void paranoid_vtbl_check(const struct ubi_device *ubi)
+static void self_vtbl_check(const struct ubi_device *ubi)
{
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return;
if (vtbl_check(ubi, ubi->vtbl)) {
- ubi_err("paranoid check failed");
+ ubi_err("self-check failed");
BUG();
}
}
-
-#endif /* CONFIG_MTD_UBI_DEBUG */
diff -uN -uNr linux-3.0/drivers/mtd/ubi/wl.c linux-3.0.x.ubifs.latest/drivers/mtd/ubi/wl.c
--- linux-3.0/drivers/mtd/ubi/wl.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/drivers/mtd/ubi/wl.c 2012-06-28 11:26:15.000000000 -0500
@@ -1,4 +1,5 @@
/*
+ * @ubi: UBI device description object
* Copyright (c) International Business Machines Corp., 2006
*
* This program is free software; you can redistribute it and/or modify
@@ -40,12 +41,6 @@
* physical eraseblocks with low erase counter to free physical eraseblocks
* with high erase counter.
*
- * The 'ubi_wl_get_peb()' function accepts data type hints which help to pick
- * an "optimal" physical eraseblock. For example, when it is known that the
- * physical eraseblock will be "put" soon because it contains short-term data,
- * the WL sub-system may pick a free physical eraseblock with low erase
- * counter, and so forth.
- *
* If the WL sub-system fails to erase a physical eraseblock, it marks it as
* bad.
*
@@ -69,8 +64,7 @@
* to the user; instead, we first want to let users fill them up with data;
*
* o there is a chance that the user will put the physical eraseblock very
- * soon, so it makes sense not to move it for some time, but wait; this is
- * especially important in case of "short term" physical eraseblocks.
+ * soon, so it makes sense not to move it for some time, but wait.
*
* Physical eraseblocks stay protected only for limited time. But the "time" is
* measured in erase cycles in this case. This is implemented with help of the
@@ -146,6 +140,8 @@
* @list: a link in the list of pending works
* @func: worker function
* @e: physical eraseblock to erase
+ * @vol_id: the volume ID on which this erasure is being performed
+ * @lnum: the logical eraseblock number
* @torture: if the physical eraseblock has to be tortured
*
* The @func pointer points to the worker function. If the @cancel argument is
@@ -158,19 +154,16 @@
int (*func)(struct ubi_device *ubi, struct ubi_work *wrk, int cancel);
/* The below fields are only relevant to erasure works */
struct ubi_wl_entry *e;
+ int vol_id;
+ int lnum;
int torture;
};
-#ifdef CONFIG_MTD_UBI_DEBUG
-static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec);
-static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
- struct rb_root *root);
-static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e);
-#else
-#define paranoid_check_ec(ubi, pnum, ec) 0
-#define paranoid_check_in_wl_tree(e, root)
-#define paranoid_check_in_pq(ubi, e) 0
-#endif
+static int self_check_ec(struct ubi_device *ubi, int pnum, int ec);
+static int self_check_in_wl_tree(const struct ubi_device *ubi,
+ struct ubi_wl_entry *e, struct rb_root *root);
+static int self_check_in_pq(const struct ubi_device *ubi,
+ struct ubi_wl_entry *e);
/**
* wl_tree_add - add a wear-leveling entry to a WL RB-tree.
@@ -347,18 +340,19 @@
/**
* find_wl_entry - find wear-leveling entry closest to certain erase counter.
* @root: the RB-tree where to look for
- * @max: highest possible erase counter
+ * @diff: maximum possible difference from the smallest erase counter
*
* This function looks for a wear leveling entry with erase counter closest to
- * @max and less than @max.
+ * min + @diff, where min is the smallest erase counter.
*/
-static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int max)
+static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int diff)
{
struct rb_node *p;
struct ubi_wl_entry *e;
+ int max;
e = rb_entry(rb_first(root), struct ubi_wl_entry, u.rb);
- max += e->ec;
+ max = e->ec + diff;
p = root->rb_node;
while (p) {
@@ -379,19 +373,15 @@
/**
* ubi_wl_get_peb - get a physical eraseblock.
* @ubi: UBI device description object
- * @dtype: type of data which will be stored in this physical eraseblock
*
* This function returns a physical eraseblock in case of success and a
* negative error code in case of failure. Might sleep.
*/
-int ubi_wl_get_peb(struct ubi_device *ubi, int dtype)
+int ubi_wl_get_peb(struct ubi_device *ubi)
{
- int err, medium_ec;
+ int err;
struct ubi_wl_entry *e, *first, *last;
- ubi_assert(dtype == UBI_LONGTERM || dtype == UBI_SHORTTERM ||
- dtype == UBI_UNKNOWN);
-
retry:
spin_lock(&ubi->wl_lock);
if (!ubi->free.rb_node) {
@@ -409,47 +399,15 @@
goto retry;
}
- switch (dtype) {
- case UBI_LONGTERM:
- /*
- * For long term data we pick a physical eraseblock with high
- * erase counter. But the highest erase counter we can pick is
- * bounded by the the lowest erase counter plus
- * %WL_FREE_MAX_DIFF.
- */
- e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
- break;
- case UBI_UNKNOWN:
- /*
- * For unknown data we pick a physical eraseblock with medium
- * erase counter. But we by no means can pick a physical
- * eraseblock with erase counter greater or equivalent than the
- * lowest erase counter plus %WL_FREE_MAX_DIFF.
- */
- first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry,
- u.rb);
- last = rb_entry(rb_last(&ubi->free), struct ubi_wl_entry, u.rb);
-
- if (last->ec - first->ec < WL_FREE_MAX_DIFF)
- e = rb_entry(ubi->free.rb_node,
- struct ubi_wl_entry, u.rb);
- else {
- medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2;
- e = find_wl_entry(&ubi->free, medium_ec);
- }
- break;
- case UBI_SHORTTERM:
- /*
- * For short term data we pick a physical eraseblock with the
- * lowest erase counter as we expect it will be erased soon.
- */
- e = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, u.rb);
- break;
- default:
- BUG();
- }
+ first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, u.rb);
+ last = rb_entry(rb_last(&ubi->free), struct ubi_wl_entry, u.rb);
- paranoid_check_in_wl_tree(e, &ubi->free);
+ if (last->ec - first->ec < WL_FREE_MAX_DIFF)
+ e = rb_entry(ubi->free.rb_node, struct ubi_wl_entry, u.rb);
+ else
+ e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF/2);
+
+ self_check_in_wl_tree(ubi, e, &ubi->free);
/*
* Move the physical eraseblock to the protection queue where it will
@@ -460,8 +418,8 @@
prot_queue_add(ubi, e);
spin_unlock(&ubi->wl_lock);
- err = ubi_dbg_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset,
- ubi->peb_size - ubi->vid_hdr_aloffset);
+ err = ubi_self_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset,
+ ubi->peb_size - ubi->vid_hdr_aloffset);
if (err) {
ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum);
return err;
@@ -486,7 +444,7 @@
if (!e)
return -ENODEV;
- if (paranoid_check_in_pq(ubi, e))
+ if (self_check_in_pq(ubi, e))
return -ENODEV;
list_del(&e->u.list);
@@ -512,7 +470,7 @@
dbg_wl("erase PEB %d, old EC %llu", e->pnum, ec);
- err = paranoid_check_ec(ubi, e->pnum, e->ec);
+ err = self_check_ec(ubi, e->pnum, e->ec);
if (err)
return -EINVAL;
@@ -613,7 +571,7 @@
list_add_tail(&wrk->list, &ubi->works);
ubi_assert(ubi->works_count >= 0);
ubi->works_count += 1;
- if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled())
+ if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled(ubi))
wake_up_process(ubi->bgt_thread);
spin_unlock(&ubi->wl_lock);
}
@@ -625,13 +583,15 @@
* schedule_erase - schedule an erase work.
* @ubi: UBI device description object
* @e: the WL entry of the physical eraseblock to erase
+ * @vol_id: the volume ID that last used this PEB
+ * @lnum: the last used logical eraseblock number for the PEB
* @torture: if the physical eraseblock has to be tortured
*
* This function returns zero in case of success and a %-ENOMEM in case of
* failure.
*/
static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
- int torture)
+ int vol_id, int lnum, int torture)
{
struct ubi_work *wl_wrk;
@@ -644,6 +604,8 @@
wl_wrk->func = &erase_worker;
wl_wrk->e = e;
+ wl_wrk->vol_id = vol_id;
+ wl_wrk->lnum = lnum;
wl_wrk->torture = torture;
schedule_ubi_work(ubi, wl_wrk);
@@ -712,7 +674,7 @@
e1->ec, e2->ec);
goto out_cancel;
}
- paranoid_check_in_wl_tree(e1, &ubi->used);
+ self_check_in_wl_tree(ubi, e1, &ubi->used);
rb_erase(&e1->u.rb, &ubi->used);
dbg_wl("move PEB %d EC %d to PEB %d EC %d",
e1->pnum, e1->ec, e2->pnum, e2->ec);
@@ -721,12 +683,12 @@
scrubbing = 1;
e1 = rb_entry(rb_first(&ubi->scrub), struct ubi_wl_entry, u.rb);
e2 = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF);
- paranoid_check_in_wl_tree(e1, &ubi->scrub);
+ self_check_in_wl_tree(ubi, e1, &ubi->scrub);
rb_erase(&e1->u.rb, &ubi->scrub);
dbg_wl("scrub PEB %d to PEB %d", e1->pnum, e2->pnum);
}
- paranoid_check_in_wl_tree(e2, &ubi->free);
+ self_check_in_wl_tree(ubi, e2, &ubi->free);
rb_erase(&e2->u.rb, &ubi->free);
ubi->move_from = e1;
ubi->move_to = e2;
@@ -792,8 +754,11 @@
protect = 1;
goto out_not_moved;
}
-
- if (err == MOVE_CANCEL_BITFLIPS || err == MOVE_TARGET_WR_ERR ||
+ if (err == MOVE_RETRY) {
+ scrubbing = 1;
+ goto out_not_moved;
+ }
+ if (err == MOVE_TARGET_BITFLIPS || err == MOVE_TARGET_WR_ERR ||
err == MOVE_TARGET_RD_ERR) {
/*
* Target PEB had bit-flips or write error - torture it.
@@ -841,7 +806,7 @@
ubi->move_to_put = ubi->wl_scheduled = 0;
spin_unlock(&ubi->wl_lock);
- err = schedule_erase(ubi, e1, 0);
+ err = schedule_erase(ubi, e1, vol_id, lnum, 0);
if (err) {
kmem_cache_free(ubi_wl_entry_slab, e1);
if (e2)
@@ -856,7 +821,7 @@
*/
dbg_wl("PEB %d (LEB %d:%d) was put meanwhile, erase",
e2->pnum, vol_id, lnum);
- err = schedule_erase(ubi, e2, 0);
+ err = schedule_erase(ubi, e2, vol_id, lnum, 0);
if (err) {
kmem_cache_free(ubi_wl_entry_slab, e2);
goto out_ro;
@@ -895,7 +860,7 @@
spin_unlock(&ubi->wl_lock);
ubi_free_vid_hdr(ubi, vid_hdr);
- err = schedule_erase(ubi, e2, torture);
+ err = schedule_erase(ubi, e2, vol_id, lnum, torture);
if (err) {
kmem_cache_free(ubi_wl_entry_slab, e2);
goto out_ro;
@@ -1014,6 +979,8 @@
{
struct ubi_wl_entry *e = wl_wrk->e;
int pnum = e->pnum, err, need;
+ int vol_id = wl_wrk->vol_id;
+ int lnum = wl_wrk->lnum;
if (cancel) {
dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec);
@@ -1022,7 +989,8 @@
return 0;
}
- dbg_wl("erase PEB %d EC %d", pnum, e->ec);
+ dbg_wl("erase PEB %d EC %d LEB %d:%d",
+ pnum, e->ec, wl_wrk->vol_id, wl_wrk->lnum);
err = sync_erase(ubi, e, wl_wrk->torture);
if (!err) {
@@ -1046,27 +1014,28 @@
ubi_err("failed to erase PEB %d, error %d", pnum, err);
kfree(wl_wrk);
- kmem_cache_free(ubi_wl_entry_slab, e);
if (err == -EINTR || err == -ENOMEM || err == -EAGAIN ||
err == -EBUSY) {
int err1;
/* Re-schedule the LEB for erasure */
- err1 = schedule_erase(ubi, e, 0);
+ err1 = schedule_erase(ubi, e, vol_id, lnum, 0);
if (err1) {
err = err1;
goto out_ro;
}
return err;
- } else if (err != -EIO) {
+ }
+
+ kmem_cache_free(ubi_wl_entry_slab, e);
+ if (err != -EIO)
/*
* If this is not %-EIO, we have no idea what to do. Scheduling
* this physical eraseblock for erasure again would cause
* errors again and again. Well, lets switch to R/O mode.
*/
goto out_ro;
- }
/* It is %-EIO, the PEB went bad */
@@ -1119,6 +1088,8 @@
/**
* ubi_wl_put_peb - return a PEB to the wear-leveling sub-system.
* @ubi: UBI device description object
+ * @vol_id: the volume ID that last used this PEB
+ * @lnum: the last used logical eraseblock number for the PEB
* @pnum: physical eraseblock to return
* @torture: if this physical eraseblock has to be tortured
*
@@ -1127,7 +1098,8 @@
* occurred to this @pnum and it has to be tested. This function returns zero
* in case of success, and a negative error code in case of failure.
*/
-int ubi_wl_put_peb(struct ubi_device *ubi, int pnum, int torture)
+int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum,
+ int pnum, int torture)
{
int err;
struct ubi_wl_entry *e;
@@ -1169,13 +1141,13 @@
return 0;
} else {
if (in_wl_tree(e, &ubi->used)) {
- paranoid_check_in_wl_tree(e, &ubi->used);
+ self_check_in_wl_tree(ubi, e, &ubi->used);
rb_erase(&e->u.rb, &ubi->used);
} else if (in_wl_tree(e, &ubi->scrub)) {
- paranoid_check_in_wl_tree(e, &ubi->scrub);
+ self_check_in_wl_tree(ubi, e, &ubi->scrub);
rb_erase(&e->u.rb, &ubi->scrub);
} else if (in_wl_tree(e, &ubi->erroneous)) {
- paranoid_check_in_wl_tree(e, &ubi->erroneous);
+ self_check_in_wl_tree(ubi, e, &ubi->erroneous);
rb_erase(&e->u.rb, &ubi->erroneous);
ubi->erroneous_peb_count -= 1;
ubi_assert(ubi->erroneous_peb_count >= 0);
@@ -1193,7 +1165,7 @@
}
spin_unlock(&ubi->wl_lock);
- err = schedule_erase(ubi, e, torture);
+ err = schedule_erase(ubi, e, vol_id, lnum, torture);
if (err) {
spin_lock(&ubi->wl_lock);
wl_tree_add(e, &ubi->used);
@@ -1242,7 +1214,7 @@
}
if (in_wl_tree(e, &ubi->used)) {
- paranoid_check_in_wl_tree(e, &ubi->used);
+ self_check_in_wl_tree(ubi, e, &ubi->used);
rb_erase(&e->u.rb, &ubi->used);
} else {
int err;
@@ -1269,23 +1241,54 @@
/**
* ubi_wl_flush - flush all pending works.
* @ubi: UBI device description object
+ * @vol_id: the volume id to flush for
+ * @lnum: the logical eraseblock number to flush for
*
- * This function returns zero in case of success and a negative error code in
- * case of failure.
+ * This function executes all pending works for a particular volume id /
+ * logical eraseblock number pair. If either value is set to %UBI_ALL, then it
+ * acts as a wildcard for all of the corresponding volume numbers or logical
+ * eraseblock numbers. It returns zero in case of success and a negative error
+ * code in case of failure.
*/
-int ubi_wl_flush(struct ubi_device *ubi)
+int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum)
{
- int err;
+ int err = 0;
+ int found = 1;
/*
* Erase while the pending works queue is not empty, but not more than
* the number of currently pending works.
*/
- dbg_wl("flush (%d pending works)", ubi->works_count);
- while (ubi->works_count) {
- err = do_work(ubi);
- if (err)
- return err;
+ dbg_wl("flush pending work for LEB %d:%d (%d pending works)",
+ vol_id, lnum, ubi->works_count);
+
+ while (found) {
+ struct ubi_work *wrk;
+ found = 0;
+
+ down_read(&ubi->work_sem);
+ spin_lock(&ubi->wl_lock);
+ list_for_each_entry(wrk, &ubi->works, list) {
+ if ((vol_id == UBI_ALL || wrk->vol_id == vol_id) &&
+ (lnum == UBI_ALL || wrk->lnum == lnum)) {
+ list_del(&wrk->list);
+ ubi->works_count -= 1;
+ ubi_assert(ubi->works_count >= 0);
+ spin_unlock(&ubi->wl_lock);
+
+ err = wrk->func(ubi, wrk, 0);
+ if (err) {
+ up_read(&ubi->work_sem);
+ return err;
+ }
+
+ spin_lock(&ubi->wl_lock);
+ found = 1;
+ break;
+ }
+ }
+ spin_unlock(&ubi->wl_lock);
+ up_read(&ubi->work_sem);
}
/*
@@ -1295,18 +1298,7 @@
down_write(&ubi->work_sem);
up_write(&ubi->work_sem);
- /*
- * And in case last was the WL worker and it canceled the LEB
- * movement, flush again.
- */
- while (ubi->works_count) {
- dbg_wl("flush more (%d pending works)", ubi->works_count);
- err = do_work(ubi);
- if (err)
- return err;
- }
-
- return 0;
+ return err;
}
/**
@@ -1364,7 +1356,7 @@
spin_lock(&ubi->wl_lock);
if (list_empty(&ubi->works) || ubi->ro_mode ||
- !ubi->thread_enabled || ubi_dbg_is_bgt_disabled()) {
+ !ubi->thread_enabled || ubi_dbg_is_bgt_disabled(ubi)) {
set_current_state(TASK_INTERRUPTIBLE);
spin_unlock(&ubi->wl_lock);
schedule();
@@ -1415,26 +1407,26 @@
}
/**
- * ubi_wl_init_scan - initialize the WL sub-system using scanning information.
+ * ubi_wl_init - initialize the WL sub-system using attaching information.
* @ubi: UBI device description object
- * @si: scanning information
+ * @ai: attaching information
*
* This function returns zero in case of success, and a negative error code in
* case of failure.
*/
-int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
+int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
{
int err, i;
struct rb_node *rb1, *rb2;
- struct ubi_scan_volume *sv;
- struct ubi_scan_leb *seb, *tmp;
+ struct ubi_ainf_volume *av;
+ struct ubi_ainf_peb *aeb, *tmp;
struct ubi_wl_entry *e;
ubi->used = ubi->erroneous = ubi->free = ubi->scrub = RB_ROOT;
spin_lock_init(&ubi->wl_lock);
mutex_init(&ubi->move_mutex);
init_rwsem(&ubi->work_sem);
- ubi->max_ec = si->max_ec;
+ ubi->max_ec = ai->max_ec;
INIT_LIST_HEAD(&ubi->works);
sprintf(ubi->bgt_name, UBI_BGT_NAME_PATTERN, ubi->ubi_num);
@@ -1448,48 +1440,48 @@
INIT_LIST_HEAD(&ubi->pq[i]);
ubi->pq_head = 0;
- list_for_each_entry_safe(seb, tmp, &si->erase, u.list) {
+ list_for_each_entry_safe(aeb, tmp, &ai->erase, u.list) {
cond_resched();
e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
if (!e)
goto out_free;
- e->pnum = seb->pnum;
- e->ec = seb->ec;
+ e->pnum = aeb->pnum;
+ e->ec = aeb->ec;
ubi->lookuptbl[e->pnum] = e;
- if (schedule_erase(ubi, e, 0)) {
+ if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0)) {
kmem_cache_free(ubi_wl_entry_slab, e);
goto out_free;
}
}
- list_for_each_entry(seb, &si->free, u.list) {
+ list_for_each_entry(aeb, &ai->free, u.list) {
cond_resched();
e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
if (!e)
goto out_free;
- e->pnum = seb->pnum;
- e->ec = seb->ec;
+ e->pnum = aeb->pnum;
+ e->ec = aeb->ec;
ubi_assert(e->ec >= 0);
wl_tree_add(e, &ubi->free);
ubi->lookuptbl[e->pnum] = e;
}
- ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
- ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) {
+ ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) {
+ ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) {
cond_resched();
e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
if (!e)
goto out_free;
- e->pnum = seb->pnum;
- e->ec = seb->ec;
+ e->pnum = aeb->pnum;
+ e->ec = aeb->ec;
ubi->lookuptbl[e->pnum] = e;
- if (!seb->scrub) {
+ if (!aeb->scrub) {
dbg_wl("add PEB %d EC %d to the used tree",
e->pnum, e->ec);
wl_tree_add(e, &ubi->used);
@@ -1561,10 +1553,8 @@
kfree(ubi->lookuptbl);
}
-#ifdef CONFIG_MTD_UBI_DEBUG
-
/**
- * paranoid_check_ec - make sure that the erase counter of a PEB is correct.
+ * self_check_ec - make sure that the erase counter of a PEB is correct.
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to check
* @ec: the erase counter to check
@@ -1573,13 +1563,13 @@
* is equivalent to @ec, and a negative error code if not or if an error
* occurred.
*/
-static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec)
+static int self_check_ec(struct ubi_device *ubi, int pnum, int ec)
{
int err;
long long read_ec;
struct ubi_ec_hdr *ec_hdr;
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return 0;
ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
@@ -1595,9 +1585,9 @@
read_ec = be64_to_cpu(ec_hdr->ec);
if (ec != read_ec) {
- ubi_err("paranoid check failed for PEB %d", pnum);
+ ubi_err("self-check failed for PEB %d", pnum);
ubi_err("read EC is %lld, should be %d", read_ec, ec);
- ubi_dbg_dump_stack();
+ dump_stack();
err = 1;
} else
err = 0;
@@ -1608,42 +1598,44 @@
}
/**
- * paranoid_check_in_wl_tree - check that wear-leveling entry is in WL RB-tree.
+ * self_check_in_wl_tree - check that wear-leveling entry is in WL RB-tree.
+ * @ubi: UBI device description object
* @e: the wear-leveling entry to check
* @root: the root of the tree
*
* This function returns zero if @e is in the @root RB-tree and %-EINVAL if it
* is not.
*/
-static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
- struct rb_root *root)
+static int self_check_in_wl_tree(const struct ubi_device *ubi,
+ struct ubi_wl_entry *e, struct rb_root *root)
{
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return 0;
if (in_wl_tree(e, root))
return 0;
- ubi_err("paranoid check failed for PEB %d, EC %d, RB-tree %p ",
+ ubi_err("self-check failed for PEB %d, EC %d, RB-tree %p ",
e->pnum, e->ec, root);
- ubi_dbg_dump_stack();
+ dump_stack();
return -EINVAL;
}
/**
- * paranoid_check_in_pq - check if wear-leveling entry is in the protection
+ * self_check_in_pq - check if wear-leveling entry is in the protection
* queue.
* @ubi: UBI device description object
* @e: the wear-leveling entry to check
*
* This function returns zero if @e is in @ubi->pq and %-EINVAL if it is not.
*/
-static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e)
+static int self_check_in_pq(const struct ubi_device *ubi,
+ struct ubi_wl_entry *e)
{
struct ubi_wl_entry *p;
int i;
- if (!(ubi_chk_flags & UBI_CHK_GEN))
+ if (!ubi->dbg->chk_gen)
return 0;
for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i)
@@ -1651,10 +1643,8 @@
if (p == e)
return 0;
- ubi_err("paranoid check failed for PEB %d, EC %d, Protect queue",
+ ubi_err("self-check failed for PEB %d, EC %d, Protect queue",
e->pnum, e->ec);
- ubi_dbg_dump_stack();
+ dump_stack();
return -EINVAL;
}
-
-#endif /* CONFIG_MTD_UBI_DEBUG */
diff -uN -uNr linux-3.0/fs/ubifs/Kconfig linux-3.0.x.ubifs.latest/fs/ubifs/Kconfig
--- linux-3.0/fs/ubifs/Kconfig 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/Kconfig 2012-06-28 11:26:15.000000000 -0500
@@ -11,12 +11,6 @@
help
UBIFS is a file system for flash devices which works on top of UBI.
-config UBIFS_FS_XATTR
- bool "Extended attributes support"
- depends on UBIFS_FS
- help
- This option enables support of extended attributes.
-
config UBIFS_FS_ADVANCED_COMPR
bool "Advanced compression options"
depends on UBIFS_FS
@@ -41,20 +35,3 @@
default y
help
Zlib compresses better than LZO but it is slower. Say 'Y' if unsure.
-
-# Debugging-related stuff
-config UBIFS_FS_DEBUG
- bool "Enable debugging support"
- depends on UBIFS_FS
- select DEBUG_FS
- select KALLSYMS
- help
- This option enables UBIFS debugging support. It makes sure various
- assertions, self-checks, debugging messages and test modes are compiled
- in (this all is compiled out otherwise). Assertions are light-weight
- and this option also enables them. Self-checks, debugging messages and
- test modes are switched off by default. Thus, it is safe and actually
- recommended to have debugging support enabled, and it should not slow
- down UBIFS. You can then further enable / disable individual debugging
- features using UBIFS module parameters and the corresponding sysfs
- interfaces.
diff -uN -uNr linux-3.0/fs/ubifs/Makefile linux-3.0.x.ubifs.latest/fs/ubifs/Makefile
--- linux-3.0/fs/ubifs/Makefile 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/Makefile 2012-06-28 11:26:15.000000000 -0500
@@ -3,7 +3,4 @@
ubifs-y += shrinker.o journal.o file.o dir.o super.o sb.o io.o
ubifs-y += tnc.o master.o scan.o replay.o log.o commit.o gc.o orphan.o
ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o
-ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o
-
-ubifs-$(CONFIG_UBIFS_FS_DEBUG) += debug.o
-ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o
+ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o xattr.o debug.o
diff -uN -uNr linux-3.0/fs/ubifs/commit.c linux-3.0.x.ubifs.latest/fs/ubifs/commit.c
--- linux-3.0/fs/ubifs/commit.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/commit.c 2012-06-28 11:26:15.000000000 -0500
@@ -78,7 +78,7 @@
* If the root TNC node is dirty, we definitely have something to
* commit.
*/
- if (c->zroot.znode && test_bit(DIRTY_ZNODE, &c->zroot.znode->flags))
+ if (c->zroot.znode && ubifs_zn_dirty(c->zroot.znode))
return 0;
/*
@@ -418,7 +418,7 @@
spin_lock(&c->cs_lock);
if (c->cmt_state == COMMIT_BROKEN) {
- err = -EINVAL;
+ err = -EROFS;
goto out;
}
@@ -444,7 +444,7 @@
* re-check it.
*/
if (c->cmt_state == COMMIT_BROKEN) {
- err = -EINVAL;
+ err = -EROFS;
goto out_cmt_unlock;
}
@@ -496,7 +496,9 @@
return ret;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
+/*
+ * Everything below is related to debugging.
+ */
/**
* struct idx_node - hold index nodes during index tree traversal.
@@ -576,7 +578,7 @@
struct idx_node *i;
size_t sz;
- if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX))
+ if (!dbg_is_chk_index(c))
return 0;
INIT_LIST_HEAD(&list);
@@ -714,14 +716,14 @@
return 0;
out_dump:
- dbg_err("dumping index node (iip=%d)", i->iip);
- dbg_dump_node(c, idx);
+ ubifs_err("dumping index node (iip=%d)", i->iip);
+ ubifs_dump_node(c, idx);
list_del(&i->list);
kfree(i);
if (!list_empty(&list)) {
i = list_entry(list.prev, struct idx_node, list);
- dbg_err("dumping parent index node");
- dbg_dump_node(c, &i->idx);
+ ubifs_err("dumping parent index node");
+ ubifs_dump_node(c, &i->idx);
}
out_free:
while (!list_empty(&list)) {
@@ -734,5 +736,3 @@
err = -EINVAL;
return err;
}
-
-#endif /* CONFIG_UBIFS_FS_DEBUG */
diff -uN -uNr linux-3.0/fs/ubifs/debug.c linux-3.0.x.ubifs.latest/fs/ubifs/debug.c
--- linux-3.0/fs/ubifs/debug.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/debug.c 2012-06-28 11:26:15.000000000 -0500
@@ -27,29 +27,14 @@
* various local functions of those subsystems.
*/
-#define UBIFS_DBG_PRESERVE_UBI
-
-#include "ubifs.h"
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/debugfs.h>
#include <linux/math64.h>
+#include <linux/uaccess.h>
+#include <linux/random.h>
+#include "ubifs.h"
-#ifdef CONFIG_UBIFS_FS_DEBUG
-
-DEFINE_SPINLOCK(dbg_lock);
-
-static char dbg_key_buf0[128];
-static char dbg_key_buf1[128];
-
-unsigned int ubifs_chk_flags;
-unsigned int ubifs_tst_flags;
-
-module_param_named(debug_chks, ubifs_chk_flags, uint, S_IRUGO | S_IWUSR);
-module_param_named(debug_tsts, ubifs_tst_flags, uint, S_IRUGO | S_IWUSR);
-
-MODULE_PARM_DESC(debug_chks, "Debug check flags");
-MODULE_PARM_DESC(debug_tsts, "Debug special test flags");
+static DEFINE_SPINLOCK(dbg_lock);
static const char *get_key_fmt(int fmt)
{
@@ -91,8 +76,30 @@
}
}
-static void sprintf_key(const struct ubifs_info *c, const union ubifs_key *key,
- char *buffer)
+static const char *get_dent_type(int type)
+{
+ switch (type) {
+ case UBIFS_ITYPE_REG:
+ return "file";
+ case UBIFS_ITYPE_DIR:
+ return "dir";
+ case UBIFS_ITYPE_LNK:
+ return "symlink";
+ case UBIFS_ITYPE_BLK:
+ return "blkdev";
+ case UBIFS_ITYPE_CHR:
+ return "char dev";
+ case UBIFS_ITYPE_FIFO:
+ return "fifo";
+ case UBIFS_ITYPE_SOCK:
+ return "socket";
+ default:
+ return "unknown/invalid type";
+ }
+}
+
+const char *dbg_snprintf_key(const struct ubifs_info *c,
+ const union ubifs_key *key, char *buffer, int len)
{
char *p = buffer;
int type = key_type(c, key);
@@ -100,45 +107,34 @@
if (c->key_fmt == UBIFS_SIMPLE_KEY_FMT) {
switch (type) {
case UBIFS_INO_KEY:
- sprintf(p, "(%lu, %s)", (unsigned long)key_inum(c, key),
- get_key_type(type));
+ len -= snprintf(p, len, "(%lu, %s)",
+ (unsigned long)key_inum(c, key),
+ get_key_type(type));
break;
case UBIFS_DENT_KEY:
case UBIFS_XENT_KEY:
- sprintf(p, "(%lu, %s, %#08x)",
- (unsigned long)key_inum(c, key),
- get_key_type(type), key_hash(c, key));
+ len -= snprintf(p, len, "(%lu, %s, %#08x)",
+ (unsigned long)key_inum(c, key),
+ get_key_type(type), key_hash(c, key));
break;
case UBIFS_DATA_KEY:
- sprintf(p, "(%lu, %s, %u)",
- (unsigned long)key_inum(c, key),
- get_key_type(type), key_block(c, key));
+ len -= snprintf(p, len, "(%lu, %s, %u)",
+ (unsigned long)key_inum(c, key),
+ get_key_type(type), key_block(c, key));
break;
case UBIFS_TRUN_KEY:
- sprintf(p, "(%lu, %s)",
- (unsigned long)key_inum(c, key),
- get_key_type(type));
+ len -= snprintf(p, len, "(%lu, %s)",
+ (unsigned long)key_inum(c, key),
+ get_key_type(type));
break;
default:
- sprintf(p, "(bad key type: %#08x, %#08x)",
- key->u32[0], key->u32[1]);
+ len -= snprintf(p, len, "(bad key type: %#08x, %#08x)",
+ key->u32[0], key->u32[1]);
}
} else
- sprintf(p, "bad key format %d", c->key_fmt);
-}
-
-const char *dbg_key_str0(const struct ubifs_info *c, const union ubifs_key *key)
-{
- /* dbg_lock must be held */
- sprintf_key(c, key, dbg_key_buf0);
- return dbg_key_buf0;
-}
-
-const char *dbg_key_str1(const struct ubifs_info *c, const union ubifs_key *key)
-{
- /* dbg_lock must be held */
- sprintf_key(c, key, dbg_key_buf1);
- return dbg_key_buf1;
+ len -= snprintf(p, len, "bad key format %d", c->key_fmt);
+ ubifs_assert(len > 0);
+ return p;
}
const char *dbg_ntype(int type)
@@ -223,68 +219,99 @@
static void dump_ch(const struct ubifs_ch *ch)
{
- printk(KERN_DEBUG "\tmagic %#x\n", le32_to_cpu(ch->magic));
- printk(KERN_DEBUG "\tcrc %#x\n", le32_to_cpu(ch->crc));
- printk(KERN_DEBUG "\tnode_type %d (%s)\n", ch->node_type,
+ printk(KERN_ERR "\tmagic %#x\n", le32_to_cpu(ch->magic));
+ printk(KERN_ERR "\tcrc %#x\n", le32_to_cpu(ch->crc));
+ printk(KERN_ERR "\tnode_type %d (%s)\n", ch->node_type,
dbg_ntype(ch->node_type));
- printk(KERN_DEBUG "\tgroup_type %d (%s)\n", ch->group_type,
+ printk(KERN_ERR "\tgroup_type %d (%s)\n", ch->group_type,
dbg_gtype(ch->group_type));
- printk(KERN_DEBUG "\tsqnum %llu\n",
+ printk(KERN_ERR "\tsqnum %llu\n",
(unsigned long long)le64_to_cpu(ch->sqnum));
- printk(KERN_DEBUG "\tlen %u\n", le32_to_cpu(ch->len));
+ printk(KERN_ERR "\tlen %u\n", le32_to_cpu(ch->len));
}
-void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode)
+void ubifs_dump_inode(struct ubifs_info *c, const struct inode *inode)
{
const struct ubifs_inode *ui = ubifs_inode(inode);
+ struct qstr nm = { .name = NULL };
+ union ubifs_key key;
+ struct ubifs_dent_node *dent, *pdent = NULL;
+ int count = 2;
- printk(KERN_DEBUG "Dump in-memory inode:");
- printk(KERN_DEBUG "\tinode %lu\n", inode->i_ino);
- printk(KERN_DEBUG "\tsize %llu\n",
+ printk(KERN_ERR "Dump in-memory inode:");
+ printk(KERN_ERR "\tinode %lu\n", inode->i_ino);
+ printk(KERN_ERR "\tsize %llu\n",
(unsigned long long)i_size_read(inode));
- printk(KERN_DEBUG "\tnlink %u\n", inode->i_nlink);
- printk(KERN_DEBUG "\tuid %u\n", (unsigned int)inode->i_uid);
- printk(KERN_DEBUG "\tgid %u\n", (unsigned int)inode->i_gid);
- printk(KERN_DEBUG "\tatime %u.%u\n",
+ printk(KERN_ERR "\tnlink %u\n", inode->i_nlink);
+ printk(KERN_ERR "\tuid %u\n", (unsigned int)inode->i_uid);
+ printk(KERN_ERR "\tgid %u\n", (unsigned int)inode->i_gid);
+ printk(KERN_ERR "\tatime %u.%u\n",
(unsigned int)inode->i_atime.tv_sec,
(unsigned int)inode->i_atime.tv_nsec);
- printk(KERN_DEBUG "\tmtime %u.%u\n",
+ printk(KERN_ERR "\tmtime %u.%u\n",
(unsigned int)inode->i_mtime.tv_sec,
(unsigned int)inode->i_mtime.tv_nsec);
- printk(KERN_DEBUG "\tctime %u.%u\n",
+ printk(KERN_ERR "\tctime %u.%u\n",
(unsigned int)inode->i_ctime.tv_sec,
(unsigned int)inode->i_ctime.tv_nsec);
- printk(KERN_DEBUG "\tcreat_sqnum %llu\n", ui->creat_sqnum);
- printk(KERN_DEBUG "\txattr_size %u\n", ui->xattr_size);
- printk(KERN_DEBUG "\txattr_cnt %u\n", ui->xattr_cnt);
- printk(KERN_DEBUG "\txattr_names %u\n", ui->xattr_names);
- printk(KERN_DEBUG "\tdirty %u\n", ui->dirty);
- printk(KERN_DEBUG "\txattr %u\n", ui->xattr);
- printk(KERN_DEBUG "\tbulk_read %u\n", ui->xattr);
- printk(KERN_DEBUG "\tsynced_i_size %llu\n",
+ printk(KERN_ERR "\tcreat_sqnum %llu\n", ui->creat_sqnum);
+ printk(KERN_ERR "\txattr_size %u\n", ui->xattr_size);
+ printk(KERN_ERR "\txattr_cnt %u\n", ui->xattr_cnt);
+ printk(KERN_ERR "\txattr_names %u\n", ui->xattr_names);
+ printk(KERN_ERR "\tdirty %u\n", ui->dirty);
+ printk(KERN_ERR "\txattr %u\n", ui->xattr);
+ printk(KERN_ERR "\tbulk_read %u\n", ui->xattr);
+ printk(KERN_ERR "\tsynced_i_size %llu\n",
(unsigned long long)ui->synced_i_size);
- printk(KERN_DEBUG "\tui_size %llu\n",
+ printk(KERN_ERR "\tui_size %llu\n",
(unsigned long long)ui->ui_size);
- printk(KERN_DEBUG "\tflags %d\n", ui->flags);
- printk(KERN_DEBUG "\tcompr_type %d\n", ui->compr_type);
- printk(KERN_DEBUG "\tlast_page_read %lu\n", ui->last_page_read);
- printk(KERN_DEBUG "\tread_in_a_row %lu\n", ui->read_in_a_row);
- printk(KERN_DEBUG "\tdata_len %d\n", ui->data_len);
+ printk(KERN_ERR "\tflags %d\n", ui->flags);
+ printk(KERN_ERR "\tcompr_type %d\n", ui->compr_type);
+ printk(KERN_ERR "\tlast_page_read %lu\n", ui->last_page_read);
+ printk(KERN_ERR "\tread_in_a_row %lu\n", ui->read_in_a_row);
+ printk(KERN_ERR "\tdata_len %d\n", ui->data_len);
+
+ if (!S_ISDIR(inode->i_mode))
+ return;
+
+ printk(KERN_ERR "List of directory entries:\n");
+ ubifs_assert(!mutex_is_locked(&c->tnc_mutex));
+
+ lowest_dent_key(c, &key, inode->i_ino);
+ while (1) {
+ dent = ubifs_tnc_next_ent(c, &key, &nm);
+ if (IS_ERR(dent)) {
+ if (PTR_ERR(dent) != -ENOENT)
+ printk(KERN_ERR "error %ld\n", PTR_ERR(dent));
+ break;
+ }
+
+ printk(KERN_ERR "\t%d: %s (%s)\n",
+ count++, dent->name, get_dent_type(dent->type));
+
+ nm.name = dent->name;
+ nm.len = le16_to_cpu(dent->nlen);
+ kfree(pdent);
+ pdent = dent;
+ key_read(c, &dent->key, &key);
+ }
+ kfree(pdent);
}
-void dbg_dump_node(const struct ubifs_info *c, const void *node)
+void ubifs_dump_node(const struct ubifs_info *c, const void *node)
{
int i, n;
union ubifs_key key;
const struct ubifs_ch *ch = node;
+ char key_buf[DBG_KEY_BUF_LEN];
- if (dbg_failure_mode)
+ if (dbg_is_tst_rcvry(c))
return;
/* If the magic is incorrect, just hexdump the first bytes */
if (le32_to_cpu(ch->magic) != UBIFS_NODE_MAGIC) {
- printk(KERN_DEBUG "Not a node, first %zu bytes:", UBIFS_CH_SZ);
- print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+ printk(KERN_ERR "Not a node, first %zu bytes:", UBIFS_CH_SZ);
+ print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 32, 1,
(void *)node, UBIFS_CH_SZ, 1);
return;
}
@@ -297,7 +324,7 @@
{
const struct ubifs_pad_node *pad = node;
- printk(KERN_DEBUG "\tpad_len %u\n",
+ printk(KERN_ERR "\tpad_len %u\n",
le32_to_cpu(pad->pad_len));
break;
}
@@ -306,50 +333,50 @@
const struct ubifs_sb_node *sup = node;
unsigned int sup_flags = le32_to_cpu(sup->flags);
- printk(KERN_DEBUG "\tkey_hash %d (%s)\n",
+ printk(KERN_ERR "\tkey_hash %d (%s)\n",
(int)sup->key_hash, get_key_hash(sup->key_hash));
- printk(KERN_DEBUG "\tkey_fmt %d (%s)\n",
+ printk(KERN_ERR "\tkey_fmt %d (%s)\n",
(int)sup->key_fmt, get_key_fmt(sup->key_fmt));
- printk(KERN_DEBUG "\tflags %#x\n", sup_flags);
- printk(KERN_DEBUG "\t big_lpt %u\n",
+ printk(KERN_ERR "\tflags %#x\n", sup_flags);
+ printk(KERN_ERR "\t big_lpt %u\n",
!!(sup_flags & UBIFS_FLG_BIGLPT));
- printk(KERN_DEBUG "\t space_fixup %u\n",
+ printk(KERN_ERR "\t space_fixup %u\n",
!!(sup_flags & UBIFS_FLG_SPACE_FIXUP));
- printk(KERN_DEBUG "\tmin_io_size %u\n",
+ printk(KERN_ERR "\tmin_io_size %u\n",
le32_to_cpu(sup->min_io_size));
- printk(KERN_DEBUG "\tleb_size %u\n",
+ printk(KERN_ERR "\tleb_size %u\n",
le32_to_cpu(sup->leb_size));
- printk(KERN_DEBUG "\tleb_cnt %u\n",
+ printk(KERN_ERR "\tleb_cnt %u\n",
le32_to_cpu(sup->leb_cnt));
- printk(KERN_DEBUG "\tmax_leb_cnt %u\n",
+ printk(KERN_ERR "\tmax_leb_cnt %u\n",
le32_to_cpu(sup->max_leb_cnt));
- printk(KERN_DEBUG "\tmax_bud_bytes %llu\n",
+ printk(KERN_ERR "\tmax_bud_bytes %llu\n",
(unsigned long long)le64_to_cpu(sup->max_bud_bytes));
- printk(KERN_DEBUG "\tlog_lebs %u\n",
+ printk(KERN_ERR "\tlog_lebs %u\n",
le32_to_cpu(sup->log_lebs));
- printk(KERN_DEBUG "\tlpt_lebs %u\n",
+ printk(KERN_ERR "\tlpt_lebs %u\n",
le32_to_cpu(sup->lpt_lebs));
- printk(KERN_DEBUG "\torph_lebs %u\n",
+ printk(KERN_ERR "\torph_lebs %u\n",
le32_to_cpu(sup->orph_lebs));
- printk(KERN_DEBUG "\tjhead_cnt %u\n",
+ printk(KERN_ERR "\tjhead_cnt %u\n",
le32_to_cpu(sup->jhead_cnt));
- printk(KERN_DEBUG "\tfanout %u\n",
+ printk(KERN_ERR "\tfanout %u\n",
le32_to_cpu(sup->fanout));
- printk(KERN_DEBUG "\tlsave_cnt %u\n",
+ printk(KERN_ERR "\tlsave_cnt %u\n",
le32_to_cpu(sup->lsave_cnt));
- printk(KERN_DEBUG "\tdefault_compr %u\n",
+ printk(KERN_ERR "\tdefault_compr %u\n",
(int)le16_to_cpu(sup->default_compr));
- printk(KERN_DEBUG "\trp_size %llu\n",
+ printk(KERN_ERR "\trp_size %llu\n",
(unsigned long long)le64_to_cpu(sup->rp_size));
- printk(KERN_DEBUG "\trp_uid %u\n",
+ printk(KERN_ERR "\trp_uid %u\n",
le32_to_cpu(sup->rp_uid));
- printk(KERN_DEBUG "\trp_gid %u\n",
+ printk(KERN_ERR "\trp_gid %u\n",
le32_to_cpu(sup->rp_gid));
- printk(KERN_DEBUG "\tfmt_version %u\n",
+ printk(KERN_ERR "\tfmt_version %u\n",
le32_to_cpu(sup->fmt_version));
- printk(KERN_DEBUG "\ttime_gran %u\n",
+ printk(KERN_ERR "\ttime_gran %u\n",
le32_to_cpu(sup->time_gran));
- printk(KERN_DEBUG "\tUUID %pUB\n",
+ printk(KERN_ERR "\tUUID %pUB\n",
sup->uuid);
break;
}
@@ -357,61 +384,61 @@
{
const struct ubifs_mst_node *mst = node;
- printk(KERN_DEBUG "\thighest_inum %llu\n",
+ printk(KERN_ERR "\thighest_inum %llu\n",
(unsigned long long)le64_to_cpu(mst->highest_inum));
- printk(KERN_DEBUG "\tcommit number %llu\n",
+ printk(KERN_ERR "\tcommit number %llu\n",
(unsigned long long)le64_to_cpu(mst->cmt_no));
- printk(KERN_DEBUG "\tflags %#x\n",
+ printk(KERN_ERR "\tflags %#x\n",
le32_to_cpu(mst->flags));
- printk(KERN_DEBUG "\tlog_lnum %u\n",
+ printk(KERN_ERR "\tlog_lnum %u\n",
le32_to_cpu(mst->log_lnum));
- printk(KERN_DEBUG "\troot_lnum %u\n",
+ printk(KERN_ERR "\troot_lnum %u\n",
le32_to_cpu(mst->root_lnum));
- printk(KERN_DEBUG "\troot_offs %u\n",
+ printk(KERN_ERR "\troot_offs %u\n",
le32_to_cpu(mst->root_offs));
- printk(KERN_DEBUG "\troot_len %u\n",
+ printk(KERN_ERR "\troot_len %u\n",
le32_to_cpu(mst->root_len));
- printk(KERN_DEBUG "\tgc_lnum %u\n",
+ printk(KERN_ERR "\tgc_lnum %u\n",
le32_to_cpu(mst->gc_lnum));
- printk(KERN_DEBUG "\tihead_lnum %u\n",
+ printk(KERN_ERR "\tihead_lnum %u\n",
le32_to_cpu(mst->ihead_lnum));
- printk(KERN_DEBUG "\tihead_offs %u\n",
+ printk(KERN_ERR "\tihead_offs %u\n",
le32_to_cpu(mst->ihead_offs));
- printk(KERN_DEBUG "\tindex_size %llu\n",
+ printk(KERN_ERR "\tindex_size %llu\n",
(unsigned long long)le64_to_cpu(mst->index_size));
- printk(KERN_DEBUG "\tlpt_lnum %u\n",
+ printk(KERN_ERR "\tlpt_lnum %u\n",
le32_to_cpu(mst->lpt_lnum));
- printk(KERN_DEBUG "\tlpt_offs %u\n",
+ printk(KERN_ERR "\tlpt_offs %u\n",
le32_to_cpu(mst->lpt_offs));
- printk(KERN_DEBUG "\tnhead_lnum %u\n",
+ printk(KERN_ERR "\tnhead_lnum %u\n",
le32_to_cpu(mst->nhead_lnum));
- printk(KERN_DEBUG "\tnhead_offs %u\n",
+ printk(KERN_ERR "\tnhead_offs %u\n",
le32_to_cpu(mst->nhead_offs));
- printk(KERN_DEBUG "\tltab_lnum %u\n",
+ printk(KERN_ERR "\tltab_lnum %u\n",
le32_to_cpu(mst->ltab_lnum));
- printk(KERN_DEBUG "\tltab_offs %u\n",
+ printk(KERN_ERR "\tltab_offs %u\n",
le32_to_cpu(mst->ltab_offs));
- printk(KERN_DEBUG "\tlsave_lnum %u\n",
+ printk(KERN_ERR "\tlsave_lnum %u\n",
le32_to_cpu(mst->lsave_lnum));
- printk(KERN_DEBUG "\tlsave_offs %u\n",
+ printk(KERN_ERR "\tlsave_offs %u\n",
le32_to_cpu(mst->lsave_offs));
- printk(KERN_DEBUG "\tlscan_lnum %u\n",
+ printk(KERN_ERR "\tlscan_lnum %u\n",
le32_to_cpu(mst->lscan_lnum));
- printk(KERN_DEBUG "\tleb_cnt %u\n",
+ printk(KERN_ERR "\tleb_cnt %u\n",
le32_to_cpu(mst->leb_cnt));
- printk(KERN_DEBUG "\tempty_lebs %u\n",
+ printk(KERN_ERR "\tempty_lebs %u\n",
le32_to_cpu(mst->empty_lebs));
- printk(KERN_DEBUG "\tidx_lebs %u\n",
+ printk(KERN_ERR "\tidx_lebs %u\n",
le32_to_cpu(mst->idx_lebs));
- printk(KERN_DEBUG "\ttotal_free %llu\n",
+ printk(KERN_ERR "\ttotal_free %llu\n",
(unsigned long long)le64_to_cpu(mst->total_free));
- printk(KERN_DEBUG "\ttotal_dirty %llu\n",
+ printk(KERN_ERR "\ttotal_dirty %llu\n",
(unsigned long long)le64_to_cpu(mst->total_dirty));
- printk(KERN_DEBUG "\ttotal_used %llu\n",
+ printk(KERN_ERR "\ttotal_used %llu\n",
(unsigned long long)le64_to_cpu(mst->total_used));
- printk(KERN_DEBUG "\ttotal_dead %llu\n",
+ printk(KERN_ERR "\ttotal_dead %llu\n",
(unsigned long long)le64_to_cpu(mst->total_dead));
- printk(KERN_DEBUG "\ttotal_dark %llu\n",
+ printk(KERN_ERR "\ttotal_dark %llu\n",
(unsigned long long)le64_to_cpu(mst->total_dark));
break;
}
@@ -419,11 +446,11 @@
{
const struct ubifs_ref_node *ref = node;
- printk(KERN_DEBUG "\tlnum %u\n",
+ printk(KERN_ERR "\tlnum %u\n",
le32_to_cpu(ref->lnum));
- printk(KERN_DEBUG "\toffs %u\n",
+ printk(KERN_ERR "\toffs %u\n",
le32_to_cpu(ref->offs));
- printk(KERN_DEBUG "\tjhead %u\n",
+ printk(KERN_ERR "\tjhead %u\n",
le32_to_cpu(ref->jhead));
break;
}
@@ -432,39 +459,40 @@
const struct ubifs_ino_node *ino = node;
key_read(c, &ino->key, &key);
- printk(KERN_DEBUG "\tkey %s\n", DBGKEY(&key));
- printk(KERN_DEBUG "\tcreat_sqnum %llu\n",
+ printk(KERN_ERR "\tkey %s\n",
+ dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
+ printk(KERN_ERR "\tcreat_sqnum %llu\n",
(unsigned long long)le64_to_cpu(ino->creat_sqnum));
- printk(KERN_DEBUG "\tsize %llu\n",
+ printk(KERN_ERR "\tsize %llu\n",
(unsigned long long)le64_to_cpu(ino->size));
- printk(KERN_DEBUG "\tnlink %u\n",
+ printk(KERN_ERR "\tnlink %u\n",
le32_to_cpu(ino->nlink));
- printk(KERN_DEBUG "\tatime %lld.%u\n",
+ printk(KERN_ERR "\tatime %lld.%u\n",
(long long)le64_to_cpu(ino->atime_sec),
le32_to_cpu(ino->atime_nsec));
- printk(KERN_DEBUG "\tmtime %lld.%u\n",
+ printk(KERN_ERR "\tmtime %lld.%u\n",
(long long)le64_to_cpu(ino->mtime_sec),
le32_to_cpu(ino->mtime_nsec));
- printk(KERN_DEBUG "\tctime %lld.%u\n",
+ printk(KERN_ERR "\tctime %lld.%u\n",
(long long)le64_to_cpu(ino->ctime_sec),
le32_to_cpu(ino->ctime_nsec));
- printk(KERN_DEBUG "\tuid %u\n",
+ printk(KERN_ERR "\tuid %u\n",
le32_to_cpu(ino->uid));
- printk(KERN_DEBUG "\tgid %u\n",
+ printk(KERN_ERR "\tgid %u\n",
le32_to_cpu(ino->gid));
- printk(KERN_DEBUG "\tmode %u\n",
+ printk(KERN_ERR "\tmode %u\n",
le32_to_cpu(ino->mode));
- printk(KERN_DEBUG "\tflags %#x\n",
+ printk(KERN_ERR "\tflags %#x\n",
le32_to_cpu(ino->flags));
- printk(KERN_DEBUG "\txattr_cnt %u\n",
+ printk(KERN_ERR "\txattr_cnt %u\n",
le32_to_cpu(ino->xattr_cnt));
- printk(KERN_DEBUG "\txattr_size %u\n",
+ printk(KERN_ERR "\txattr_size %u\n",
le32_to_cpu(ino->xattr_size));
- printk(KERN_DEBUG "\txattr_names %u\n",
+ printk(KERN_ERR "\txattr_names %u\n",
le32_to_cpu(ino->xattr_names));
- printk(KERN_DEBUG "\tcompr_type %#x\n",
+ printk(KERN_ERR "\tcompr_type %#x\n",
(int)le16_to_cpu(ino->compr_type));
- printk(KERN_DEBUG "\tdata len %u\n",
+ printk(KERN_ERR "\tdata len %u\n",
le32_to_cpu(ino->data_len));
break;
}
@@ -475,15 +503,16 @@
int nlen = le16_to_cpu(dent->nlen);
key_read(c, &dent->key, &key);
- printk(KERN_DEBUG "\tkey %s\n", DBGKEY(&key));
- printk(KERN_DEBUG "\tinum %llu\n",
+ printk(KERN_ERR "\tkey %s\n",
+ dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
+ printk(KERN_ERR "\tinum %llu\n",
(unsigned long long)le64_to_cpu(dent->inum));
- printk(KERN_DEBUG "\ttype %d\n", (int)dent->type);
- printk(KERN_DEBUG "\tnlen %d\n", nlen);
- printk(KERN_DEBUG "\tname ");
+ printk(KERN_ERR "\ttype %d\n", (int)dent->type);
+ printk(KERN_ERR "\tnlen %d\n", nlen);
+ printk(KERN_ERR "\tname ");
if (nlen > UBIFS_MAX_NLEN)
- printk(KERN_DEBUG "(bad name length, not printing, "
+ printk(KERN_ERR "(bad name length, not printing, "
"bad or corrupted node)");
else {
for (i = 0; i < nlen && dent->name[i]; i++)
@@ -499,15 +528,16 @@
int dlen = le32_to_cpu(ch->len) - UBIFS_DATA_NODE_SZ;
key_read(c, &dn->key, &key);
- printk(KERN_DEBUG "\tkey %s\n", DBGKEY(&key));
- printk(KERN_DEBUG "\tsize %u\n",
+ printk(KERN_ERR "\tkey %s\n",
+ dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
+ printk(KERN_ERR "\tsize %u\n",
le32_to_cpu(dn->size));
- printk(KERN_DEBUG "\tcompr_typ %d\n",
+ printk(KERN_ERR "\tcompr_typ %d\n",
(int)le16_to_cpu(dn->compr_type));
- printk(KERN_DEBUG "\tdata size %d\n",
+ printk(KERN_ERR "\tdata size %d\n",
dlen);
- printk(KERN_DEBUG "\tdata:\n");
- print_hex_dump(KERN_DEBUG, "\t", DUMP_PREFIX_OFFSET, 32, 1,
+ printk(KERN_ERR "\tdata:\n");
+ print_hex_dump(KERN_ERR, "\t", DUMP_PREFIX_OFFSET, 32, 1,
(void *)&dn->data, dlen, 0);
break;
}
@@ -515,11 +545,11 @@
{
const struct ubifs_trun_node *trun = node;
- printk(KERN_DEBUG "\tinum %u\n",
+ printk(KERN_ERR "\tinum %u\n",
le32_to_cpu(trun->inum));
- printk(KERN_DEBUG "\told_size %llu\n",
+ printk(KERN_ERR "\told_size %llu\n",
(unsigned long long)le64_to_cpu(trun->old_size));
- printk(KERN_DEBUG "\tnew_size %llu\n",
+ printk(KERN_ERR "\tnew_size %llu\n",
(unsigned long long)le64_to_cpu(trun->new_size));
break;
}
@@ -528,19 +558,21 @@
const struct ubifs_idx_node *idx = node;
n = le16_to_cpu(idx->child_cnt);
- printk(KERN_DEBUG "\tchild_cnt %d\n", n);
- printk(KERN_DEBUG "\tlevel %d\n",
+ printk(KERN_ERR "\tchild_cnt %d\n", n);
+ printk(KERN_ERR "\tlevel %d\n",
(int)le16_to_cpu(idx->level));
- printk(KERN_DEBUG "\tBranches:\n");
+ printk(KERN_ERR "\tBranches:\n");
for (i = 0; i < n && i < c->fanout - 1; i++) {
const struct ubifs_branch *br;
br = ubifs_idx_branch(c, idx, i);
key_read(c, &br->key, &key);
- printk(KERN_DEBUG "\t%d: LEB %d:%d len %d key %s\n",
+ printk(KERN_ERR "\t%d: LEB %d:%d len %d key %s\n",
i, le32_to_cpu(br->lnum), le32_to_cpu(br->offs),
- le32_to_cpu(br->len), DBGKEY(&key));
+ le32_to_cpu(br->len),
+ dbg_snprintf_key(c, &key, key_buf,
+ DBG_KEY_BUF_LEN));
}
break;
}
@@ -550,57 +582,57 @@
{
const struct ubifs_orph_node *orph = node;
- printk(KERN_DEBUG "\tcommit number %llu\n",
+ printk(KERN_ERR "\tcommit number %llu\n",
(unsigned long long)
le64_to_cpu(orph->cmt_no) & LLONG_MAX);
- printk(KERN_DEBUG "\tlast node flag %llu\n",
+ printk(KERN_ERR "\tlast node flag %llu\n",
(unsigned long long)(le64_to_cpu(orph->cmt_no)) >> 63);
n = (le32_to_cpu(ch->len) - UBIFS_ORPH_NODE_SZ) >> 3;
- printk(KERN_DEBUG "\t%d orphan inode numbers:\n", n);
+ printk(KERN_ERR "\t%d orphan inode numbers:\n", n);
for (i = 0; i < n; i++)
- printk(KERN_DEBUG "\t ino %llu\n",
+ printk(KERN_ERR "\t ino %llu\n",
(unsigned long long)le64_to_cpu(orph->inos[i]));
break;
}
default:
- printk(KERN_DEBUG "node type %d was not recognized\n",
+ printk(KERN_ERR "node type %d was not recognized\n",
(int)ch->node_type);
}
spin_unlock(&dbg_lock);
}
-void dbg_dump_budget_req(const struct ubifs_budget_req *req)
+void ubifs_dump_budget_req(const struct ubifs_budget_req *req)
{
spin_lock(&dbg_lock);
- printk(KERN_DEBUG "Budgeting request: new_ino %d, dirtied_ino %d\n",
+ printk(KERN_ERR "Budgeting request: new_ino %d, dirtied_ino %d\n",
req->new_ino, req->dirtied_ino);
- printk(KERN_DEBUG "\tnew_ino_d %d, dirtied_ino_d %d\n",
+ printk(KERN_ERR "\tnew_ino_d %d, dirtied_ino_d %d\n",
req->new_ino_d, req->dirtied_ino_d);
- printk(KERN_DEBUG "\tnew_page %d, dirtied_page %d\n",
+ printk(KERN_ERR "\tnew_page %d, dirtied_page %d\n",
req->new_page, req->dirtied_page);
- printk(KERN_DEBUG "\tnew_dent %d, mod_dent %d\n",
+ printk(KERN_ERR "\tnew_dent %d, mod_dent %d\n",
req->new_dent, req->mod_dent);
- printk(KERN_DEBUG "\tidx_growth %d\n", req->idx_growth);
- printk(KERN_DEBUG "\tdata_growth %d dd_growth %d\n",
+ printk(KERN_ERR "\tidx_growth %d\n", req->idx_growth);
+ printk(KERN_ERR "\tdata_growth %d dd_growth %d\n",
req->data_growth, req->dd_growth);
spin_unlock(&dbg_lock);
}
-void dbg_dump_lstats(const struct ubifs_lp_stats *lst)
+void ubifs_dump_lstats(const struct ubifs_lp_stats *lst)
{
spin_lock(&dbg_lock);
- printk(KERN_DEBUG "(pid %d) Lprops statistics: empty_lebs %d, "
+ printk(KERN_ERR "(pid %d) Lprops statistics: empty_lebs %d, "
"idx_lebs %d\n", current->pid, lst->empty_lebs, lst->idx_lebs);
- printk(KERN_DEBUG "\ttaken_empty_lebs %d, total_free %lld, "
+ printk(KERN_ERR "\ttaken_empty_lebs %d, total_free %lld, "
"total_dirty %lld\n", lst->taken_empty_lebs, lst->total_free,
lst->total_dirty);
- printk(KERN_DEBUG "\ttotal_used %lld, total_dark %lld, "
+ printk(KERN_ERR "\ttotal_used %lld, total_dark %lld, "
"total_dead %lld\n", lst->total_used, lst->total_dark,
lst->total_dead);
spin_unlock(&dbg_lock);
}
-void dbg_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi)
+void ubifs_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi)
{
int i;
struct rb_node *rb;
@@ -610,21 +642,21 @@
spin_lock(&c->space_lock);
spin_lock(&dbg_lock);
- printk(KERN_DEBUG "(pid %d) Budgeting info: data budget sum %lld, "
+ printk(KERN_ERR "(pid %d) Budgeting info: data budget sum %lld, "
"total budget sum %lld\n", current->pid,
bi->data_growth + bi->dd_growth,
bi->data_growth + bi->dd_growth + bi->idx_growth);
- printk(KERN_DEBUG "\tbudg_data_growth %lld, budg_dd_growth %lld, "
+ printk(KERN_ERR "\tbudg_data_growth %lld, budg_dd_growth %lld, "
"budg_idx_growth %lld\n", bi->data_growth, bi->dd_growth,
bi->idx_growth);
- printk(KERN_DEBUG "\tmin_idx_lebs %d, old_idx_sz %llu, "
+ printk(KERN_ERR "\tmin_idx_lebs %d, old_idx_sz %llu, "
"uncommitted_idx %lld\n", bi->min_idx_lebs, bi->old_idx_sz,
bi->uncommitted_idx);
- printk(KERN_DEBUG "\tpage_budget %d, inode_budget %d, dent_budget %d\n",
+ printk(KERN_ERR "\tpage_budget %d, inode_budget %d, dent_budget %d\n",
bi->page_budget, bi->inode_budget, bi->dent_budget);
- printk(KERN_DEBUG "\tnospace %u, nospace_rp %u\n",
+ printk(KERN_ERR "\tnospace %u, nospace_rp %u\n",
bi->nospace, bi->nospace_rp);
- printk(KERN_DEBUG "\tdark_wm %d, dead_wm %d, max_idx_node_sz %d\n",
+ printk(KERN_ERR "\tdark_wm %d, dead_wm %d, max_idx_node_sz %d\n",
c->dark_wm, c->dead_wm, c->max_idx_node_sz);
if (bi != &c->bi)
@@ -635,45 +667,45 @@
*/
goto out_unlock;
- printk(KERN_DEBUG "\tfreeable_cnt %d, calc_idx_sz %lld, idx_gc_cnt %d\n",
+ printk(KERN_ERR "\tfreeable_cnt %d, calc_idx_sz %lld, idx_gc_cnt %d\n",
c->freeable_cnt, c->calc_idx_sz, c->idx_gc_cnt);
- printk(KERN_DEBUG "\tdirty_pg_cnt %ld, dirty_zn_cnt %ld, "
+ printk(KERN_ERR "\tdirty_pg_cnt %ld, dirty_zn_cnt %ld, "
"clean_zn_cnt %ld\n", atomic_long_read(&c->dirty_pg_cnt),
atomic_long_read(&c->dirty_zn_cnt),
atomic_long_read(&c->clean_zn_cnt));
- printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n",
+ printk(KERN_ERR "\tgc_lnum %d, ihead_lnum %d\n",
c->gc_lnum, c->ihead_lnum);
/* If we are in R/O mode, journal heads do not exist */
if (c->jheads)
for (i = 0; i < c->jhead_cnt; i++)
- printk(KERN_DEBUG "\tjhead %s\t LEB %d\n",
+ printk(KERN_ERR "\tjhead %s\t LEB %d\n",
dbg_jhead(c->jheads[i].wbuf.jhead),
c->jheads[i].wbuf.lnum);
for (rb = rb_first(&c->buds); rb; rb = rb_next(rb)) {
bud = rb_entry(rb, struct ubifs_bud, rb);
- printk(KERN_DEBUG "\tbud LEB %d\n", bud->lnum);
+ printk(KERN_ERR "\tbud LEB %d\n", bud->lnum);
}
list_for_each_entry(bud, &c->old_buds, list)
- printk(KERN_DEBUG "\told bud LEB %d\n", bud->lnum);
+ printk(KERN_ERR "\told bud LEB %d\n", bud->lnum);
list_for_each_entry(idx_gc, &c->idx_gc, list)
- printk(KERN_DEBUG "\tGC'ed idx LEB %d unmap %d\n",
+ printk(KERN_ERR "\tGC'ed idx LEB %d unmap %d\n",
idx_gc->lnum, idx_gc->unmap);
- printk(KERN_DEBUG "\tcommit state %d\n", c->cmt_state);
+ printk(KERN_ERR "\tcommit state %d\n", c->cmt_state);
/* Print budgeting predictions */
available = ubifs_calc_available(c, c->bi.min_idx_lebs);
outstanding = c->bi.data_growth + c->bi.dd_growth;
free = ubifs_get_free_space_nolock(c);
- printk(KERN_DEBUG "Budgeting predictions:\n");
- printk(KERN_DEBUG "\tavailable: %lld, outstanding %lld, free %lld\n",
+ printk(KERN_ERR "Budgeting predictions:\n");
+ printk(KERN_ERR "\tavailable: %lld, outstanding %lld, free %lld\n",
available, outstanding, free);
out_unlock:
spin_unlock(&dbg_lock);
spin_unlock(&c->space_lock);
}
-void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp)
+void ubifs_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp)
{
int i, spc, dark = 0, dead = 0;
struct rb_node *rb;
@@ -686,11 +718,11 @@
dark = ubifs_calc_dark(c, spc);
if (lp->flags & LPROPS_INDEX)
- printk(KERN_DEBUG "LEB %-7d free %-8d dirty %-8d used %-8d "
+ printk(KERN_ERR "LEB %-7d free %-8d dirty %-8d used %-8d "
"free + dirty %-8d flags %#x (", lp->lnum, lp->free,
lp->dirty, c->leb_size - spc, spc, lp->flags);
else
- printk(KERN_DEBUG "LEB %-7d free %-8d dirty %-8d used %-8d "
+ printk(KERN_ERR "LEB %-7d free %-8d dirty %-8d used %-8d "
"free + dirty %-8d dark %-4d dead %-4d nodes fit %-3d "
"flags %#-4x (", lp->lnum, lp->free, lp->dirty,
c->leb_size - spc, spc, dark, dead,
@@ -767,77 +799,93 @@
printk(KERN_CONT ")\n");
}
-void dbg_dump_lprops(struct ubifs_info *c)
+void ubifs_dump_lprops(struct ubifs_info *c)
{
int lnum, err;
struct ubifs_lprops lp;
struct ubifs_lp_stats lst;
- printk(KERN_DEBUG "(pid %d) start dumping LEB properties\n",
+ printk(KERN_ERR "(pid %d) start dumping LEB properties\n",
current->pid);
ubifs_get_lp_stats(c, &lst);
- dbg_dump_lstats(&lst);
+ ubifs_dump_lstats(&lst);
for (lnum = c->main_first; lnum < c->leb_cnt; lnum++) {
err = ubifs_read_one_lp(c, lnum, &lp);
if (err)
ubifs_err("cannot read lprops for LEB %d", lnum);
- dbg_dump_lprop(c, &lp);
+ ubifs_dump_lprop(c, &lp);
}
- printk(KERN_DEBUG "(pid %d) finish dumping LEB properties\n",
+ printk(KERN_ERR "(pid %d) finish dumping LEB properties\n",
current->pid);
}
-void dbg_dump_lpt_info(struct ubifs_info *c)
+void ubifs_dump_lpt_info(struct ubifs_info *c)
{
int i;
spin_lock(&dbg_lock);
- printk(KERN_DEBUG "(pid %d) dumping LPT information\n", current->pid);
- printk(KERN_DEBUG "\tlpt_sz: %lld\n", c->lpt_sz);
- printk(KERN_DEBUG "\tpnode_sz: %d\n", c->pnode_sz);
- printk(KERN_DEBUG "\tnnode_sz: %d\n", c->nnode_sz);
- printk(KERN_DEBUG "\tltab_sz: %d\n", c->ltab_sz);
- printk(KERN_DEBUG "\tlsave_sz: %d\n", c->lsave_sz);
- printk(KERN_DEBUG "\tbig_lpt: %d\n", c->big_lpt);
- printk(KERN_DEBUG "\tlpt_hght: %d\n", c->lpt_hght);
- printk(KERN_DEBUG "\tpnode_cnt: %d\n", c->pnode_cnt);
- printk(KERN_DEBUG "\tnnode_cnt: %d\n", c->nnode_cnt);
- printk(KERN_DEBUG "\tdirty_pn_cnt: %d\n", c->dirty_pn_cnt);
- printk(KERN_DEBUG "\tdirty_nn_cnt: %d\n", c->dirty_nn_cnt);
- printk(KERN_DEBUG "\tlsave_cnt: %d\n", c->lsave_cnt);
- printk(KERN_DEBUG "\tspace_bits: %d\n", c->space_bits);
- printk(KERN_DEBUG "\tlpt_lnum_bits: %d\n", c->lpt_lnum_bits);
- printk(KERN_DEBUG "\tlpt_offs_bits: %d\n", c->lpt_offs_bits);
- printk(KERN_DEBUG "\tlpt_spc_bits: %d\n", c->lpt_spc_bits);
- printk(KERN_DEBUG "\tpcnt_bits: %d\n", c->pcnt_bits);
- printk(KERN_DEBUG "\tlnum_bits: %d\n", c->lnum_bits);
- printk(KERN_DEBUG "\tLPT root is at %d:%d\n", c->lpt_lnum, c->lpt_offs);
- printk(KERN_DEBUG "\tLPT head is at %d:%d\n",
+ printk(KERN_ERR "(pid %d) dumping LPT information\n", current->pid);
+ printk(KERN_ERR "\tlpt_sz: %lld\n", c->lpt_sz);
+ printk(KERN_ERR "\tpnode_sz: %d\n", c->pnode_sz);
+ printk(KERN_ERR "\tnnode_sz: %d\n", c->nnode_sz);
+ printk(KERN_ERR "\tltab_sz: %d\n", c->ltab_sz);
+ printk(KERN_ERR "\tlsave_sz: %d\n", c->lsave_sz);
+ printk(KERN_ERR "\tbig_lpt: %d\n", c->big_lpt);
+ printk(KERN_ERR "\tlpt_hght: %d\n", c->lpt_hght);
+ printk(KERN_ERR "\tpnode_cnt: %d\n", c->pnode_cnt);
+ printk(KERN_ERR "\tnnode_cnt: %d\n", c->nnode_cnt);
+ printk(KERN_ERR "\tdirty_pn_cnt: %d\n", c->dirty_pn_cnt);
+ printk(KERN_ERR "\tdirty_nn_cnt: %d\n", c->dirty_nn_cnt);
+ printk(KERN_ERR "\tlsave_cnt: %d\n", c->lsave_cnt);
+ printk(KERN_ERR "\tspace_bits: %d\n", c->space_bits);
+ printk(KERN_ERR "\tlpt_lnum_bits: %d\n", c->lpt_lnum_bits);
+ printk(KERN_ERR "\tlpt_offs_bits: %d\n", c->lpt_offs_bits);
+ printk(KERN_ERR "\tlpt_spc_bits: %d\n", c->lpt_spc_bits);
+ printk(KERN_ERR "\tpcnt_bits: %d\n", c->pcnt_bits);
+ printk(KERN_ERR "\tlnum_bits: %d\n", c->lnum_bits);
+ printk(KERN_ERR "\tLPT root is at %d:%d\n", c->lpt_lnum, c->lpt_offs);
+ printk(KERN_ERR "\tLPT head is at %d:%d\n",
c->nhead_lnum, c->nhead_offs);
- printk(KERN_DEBUG "\tLPT ltab is at %d:%d\n",
+ printk(KERN_ERR "\tLPT ltab is at %d:%d\n",
c->ltab_lnum, c->ltab_offs);
if (c->big_lpt)
- printk(KERN_DEBUG "\tLPT lsave is at %d:%d\n",
+ printk(KERN_ERR "\tLPT lsave is at %d:%d\n",
c->lsave_lnum, c->lsave_offs);
for (i = 0; i < c->lpt_lebs; i++)
- printk(KERN_DEBUG "\tLPT LEB %d free %d dirty %d tgc %d "
+ printk(KERN_ERR "\tLPT LEB %d free %d dirty %d tgc %d "
"cmt %d\n", i + c->lpt_first, c->ltab[i].free,
c->ltab[i].dirty, c->ltab[i].tgc, c->ltab[i].cmt);
spin_unlock(&dbg_lock);
}
-void dbg_dump_leb(const struct ubifs_info *c, int lnum)
+void ubifs_dump_sleb(const struct ubifs_info *c,
+ const struct ubifs_scan_leb *sleb, int offs)
+{
+ struct ubifs_scan_node *snod;
+
+ printk(KERN_ERR "(pid %d) start dumping scanned data from LEB %d:%d\n",
+ current->pid, sleb->lnum, offs);
+
+ list_for_each_entry(snod, &sleb->nodes, list) {
+ cond_resched();
+ printk(KERN_ERR "Dumping node at LEB %d:%d len %d\n", sleb->lnum,
+ snod->offs, snod->len);
+ ubifs_dump_node(c, snod->node);
+ }
+}
+
+void ubifs_dump_leb(const struct ubifs_info *c, int lnum)
{
struct ubifs_scan_leb *sleb;
struct ubifs_scan_node *snod;
void *buf;
- if (dbg_failure_mode)
+ if (dbg_is_tst_rcvry(c))
return;
- printk(KERN_DEBUG "(pid %d) start dumping LEB %d\n",
+ printk(KERN_ERR "(pid %d) start dumping LEB %d\n",
current->pid, lnum);
buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
@@ -852,17 +900,17 @@
goto out;
}
- printk(KERN_DEBUG "LEB %d has %d nodes ending at %d\n", lnum,
+ printk(KERN_ERR "LEB %d has %d nodes ending at %d\n", lnum,
sleb->nodes_cnt, sleb->endpt);
list_for_each_entry(snod, &sleb->nodes, list) {
cond_resched();
- printk(KERN_DEBUG "Dumping node at LEB %d:%d len %d\n", lnum,
+ printk(KERN_ERR "Dumping node at LEB %d:%d len %d\n", lnum,
snod->offs, snod->len);
- dbg_dump_node(c, snod->node);
+ ubifs_dump_node(c, snod->node);
}
- printk(KERN_DEBUG "(pid %d) finish dumping LEB %d\n",
+ printk(KERN_ERR "(pid %d) finish dumping LEB %d\n",
current->pid, lnum);
ubifs_scan_destroy(sleb);
@@ -871,11 +919,12 @@
return;
}
-void dbg_dump_znode(const struct ubifs_info *c,
- const struct ubifs_znode *znode)
+void ubifs_dump_znode(const struct ubifs_info *c,
+ const struct ubifs_znode *znode)
{
int n;
const struct ubifs_zbranch *zbr;
+ char key_buf[DBG_KEY_BUF_LEN];
spin_lock(&dbg_lock);
if (znode->parent)
@@ -883,7 +932,7 @@
else
zbr = &c->zroot;
- printk(KERN_DEBUG "znode %p, LEB %d:%d len %d parent %p iip %d level %d"
+ printk(KERN_ERR "znode %p, LEB %d:%d len %d parent %p iip %d level %d"
" child_cnt %d flags %lx\n", znode, zbr->lnum, zbr->offs,
zbr->len, znode->parent, znode->iip, znode->level,
znode->child_cnt, znode->flags);
@@ -893,93 +942,97 @@
return;
}
- printk(KERN_DEBUG "zbranches:\n");
+ printk(KERN_ERR "zbranches:\n");
for (n = 0; n < znode->child_cnt; n++) {
zbr = &znode->zbranch[n];
if (znode->level > 0)
- printk(KERN_DEBUG "\t%d: znode %p LEB %d:%d len %d key "
+ printk(KERN_ERR "\t%d: znode %p LEB %d:%d len %d key "
"%s\n", n, zbr->znode, zbr->lnum,
zbr->offs, zbr->len,
- DBGKEY(&zbr->key));
+ dbg_snprintf_key(c, &zbr->key,
+ key_buf,
+ DBG_KEY_BUF_LEN));
else
- printk(KERN_DEBUG "\t%d: LNC %p LEB %d:%d len %d key "
+ printk(KERN_ERR "\t%d: LNC %p LEB %d:%d len %d key "
"%s\n", n, zbr->znode, zbr->lnum,
zbr->offs, zbr->len,
- DBGKEY(&zbr->key));
+ dbg_snprintf_key(c, &zbr->key,
+ key_buf,
+ DBG_KEY_BUF_LEN));
}
spin_unlock(&dbg_lock);
}
-void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat)
+void ubifs_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat)
{
int i;
- printk(KERN_DEBUG "(pid %d) start dumping heap cat %d (%d elements)\n",
+ printk(KERN_ERR "(pid %d) start dumping heap cat %d (%d elements)\n",
current->pid, cat, heap->cnt);
for (i = 0; i < heap->cnt; i++) {
struct ubifs_lprops *lprops = heap->arr[i];
- printk(KERN_DEBUG "\t%d. LEB %d hpos %d free %d dirty %d "
+ printk(KERN_ERR "\t%d. LEB %d hpos %d free %d dirty %d "
"flags %d\n", i, lprops->lnum, lprops->hpos,
lprops->free, lprops->dirty, lprops->flags);
}
- printk(KERN_DEBUG "(pid %d) finish dumping heap\n", current->pid);
+ printk(KERN_ERR "(pid %d) finish dumping heap\n", current->pid);
}
-void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
- struct ubifs_nnode *parent, int iip)
+void ubifs_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
+ struct ubifs_nnode *parent, int iip)
{
int i;
- printk(KERN_DEBUG "(pid %d) dumping pnode:\n", current->pid);
- printk(KERN_DEBUG "\taddress %zx parent %zx cnext %zx\n",
+ printk(KERN_ERR "(pid %d) dumping pnode:\n", current->pid);
+ printk(KERN_ERR "\taddress %zx parent %zx cnext %zx\n",
(size_t)pnode, (size_t)parent, (size_t)pnode->cnext);
- printk(KERN_DEBUG "\tflags %lu iip %d level %d num %d\n",
+ printk(KERN_ERR "\tflags %lu iip %d level %d num %d\n",
pnode->flags, iip, pnode->level, pnode->num);
for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
struct ubifs_lprops *lp = &pnode->lprops[i];
- printk(KERN_DEBUG "\t%d: free %d dirty %d flags %d lnum %d\n",
+ printk(KERN_ERR "\t%d: free %d dirty %d flags %d lnum %d\n",
i, lp->free, lp->dirty, lp->flags, lp->lnum);
}
}
-void dbg_dump_tnc(struct ubifs_info *c)
+void ubifs_dump_tnc(struct ubifs_info *c)
{
struct ubifs_znode *znode;
int level;
- printk(KERN_DEBUG "\n");
- printk(KERN_DEBUG "(pid %d) start dumping TNC tree\n", current->pid);
+ printk(KERN_ERR "\n");
+ printk(KERN_ERR "(pid %d) start dumping TNC tree\n", current->pid);
znode = ubifs_tnc_levelorder_next(c->zroot.znode, NULL);
level = znode->level;
- printk(KERN_DEBUG "== Level %d ==\n", level);
+ printk(KERN_ERR "== Level %d ==\n", level);
while (znode) {
if (level != znode->level) {
level = znode->level;
- printk(KERN_DEBUG "== Level %d ==\n", level);
+ printk(KERN_ERR "== Level %d ==\n", level);
}
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
znode = ubifs_tnc_levelorder_next(c->zroot.znode, znode);
}
- printk(KERN_DEBUG "(pid %d) finish dumping TNC tree\n", current->pid);
+ printk(KERN_ERR "(pid %d) finish dumping TNC tree\n", current->pid);
}
static int dump_znode(struct ubifs_info *c, struct ubifs_znode *znode,
void *priv)
{
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
return 0;
}
/**
- * dbg_dump_index - dump the on-flash index.
+ * ubifs_dump_index - dump the on-flash index.
* @c: UBIFS file-system description object
*
- * This function dumps whole UBIFS indexing B-tree, unlike 'dbg_dump_tnc()'
+ * This function dumps whole UBIFS indexing B-tree, unlike 'ubifs_dump_tnc()'
* which dumps only in-memory znodes and does not read znodes which from flash.
*/
-void dbg_dump_index(struct ubifs_info *c)
+void ubifs_dump_index(struct ubifs_info *c)
{
dbg_walk_index(c, NULL, dump_znode, NULL);
}
@@ -1065,21 +1118,22 @@
out:
ubifs_msg("saved lprops statistics dump");
- dbg_dump_lstats(&d->saved_lst);
+ ubifs_dump_lstats(&d->saved_lst);
ubifs_msg("saved budgeting info dump");
- dbg_dump_budg(c, &d->saved_bi);
+ ubifs_dump_budg(c, &d->saved_bi);
ubifs_msg("saved idx_gc_cnt %d", d->saved_idx_gc_cnt);
ubifs_msg("current lprops statistics dump");
ubifs_get_lp_stats(c, &lst);
- dbg_dump_lstats(&lst);
+ ubifs_dump_lstats(&lst);
ubifs_msg("current budgeting info dump");
- dbg_dump_budg(c, &c->bi);
+ ubifs_dump_budg(c, &c->bi);
dump_stack();
return -EINVAL;
}
/**
* dbg_check_synced_i_size - check synchronized inode size.
+ * @c: UBIFS file-system description object
* @inode: inode to check
*
* If inode is clean, synchronized inode size has to be equivalent to current
@@ -1087,12 +1141,12 @@
* has to be locked). Returns %0 if synchronized inode size if correct, and
* %-EINVAL if not.
*/
-int dbg_check_synced_i_size(struct inode *inode)
+int dbg_check_synced_i_size(const struct ubifs_info *c, struct inode *inode)
{
int err = 0;
struct ubifs_inode *ui = ubifs_inode(inode);
- if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+ if (!dbg_is_chk_gen(c))
return 0;
if (!S_ISREG(inode->i_mode))
return 0;
@@ -1104,7 +1158,7 @@
"is clean", ui->ui_size, ui->synced_i_size);
ubifs_err("i_ino %lu, i_mode %#x, i_size %lld", inode->i_ino,
inode->i_mode, i_size_read(inode));
- dbg_dump_stack();
+ dump_stack();
err = -EINVAL;
}
spin_unlock(&ui->ui_lock);
@@ -1125,7 +1179,7 @@
* Note, it is good idea to make sure the @dir->i_mutex is locked before
* calling this function.
*/
-int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir)
+int dbg_check_dir(struct ubifs_info *c, const struct inode *dir)
{
unsigned int nlink = 2;
union ubifs_key key;
@@ -1133,7 +1187,7 @@
struct qstr nm = { .name = NULL };
loff_t size = UBIFS_INO_NODE_SZ;
- if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+ if (!dbg_is_chk_gen(c))
return 0;
if (!S_ISDIR(dir->i_mode))
@@ -1167,12 +1221,14 @@
"but calculated size is %llu", dir->i_ino,
(unsigned long long)i_size_read(dir),
(unsigned long long)size);
+ ubifs_dump_inode(c, dir);
dump_stack();
return -EINVAL;
}
if (dir->i_nlink != nlink) {
ubifs_err("directory inode %lu has nlink %u, but calculated "
"nlink is %u", dir->i_ino, dir->i_nlink, nlink);
+ ubifs_dump_inode(c, dir);
dump_stack();
return -EINVAL;
}
@@ -1199,6 +1255,7 @@
int err, nlen1, nlen2, cmp;
struct ubifs_dent_node *dent1, *dent2;
union ubifs_key key;
+ char key_buf[DBG_KEY_BUF_LEN];
ubifs_assert(!keys_cmp(c, &zbr1->key, &zbr2->key));
dent1 = kmalloc(UBIFS_MAX_DENT_NODE_SZ, GFP_NOFS);
@@ -1228,21 +1285,25 @@
err = 1;
key_read(c, &dent1->key, &key);
if (keys_cmp(c, &zbr1->key, &key)) {
- dbg_err("1st entry at %d:%d has key %s", zbr1->lnum,
- zbr1->offs, DBGKEY(&key));
- dbg_err("but it should have key %s according to tnc",
- DBGKEY(&zbr1->key));
- dbg_dump_node(c, dent1);
+ ubifs_err("1st entry at %d:%d has key %s", zbr1->lnum,
+ zbr1->offs, dbg_snprintf_key(c, &key, key_buf,
+ DBG_KEY_BUF_LEN));
+ ubifs_err("but it should have key %s according to tnc",
+ dbg_snprintf_key(c, &zbr1->key, key_buf,
+ DBG_KEY_BUF_LEN));
+ ubifs_dump_node(c, dent1);
goto out_free;
}
key_read(c, &dent2->key, &key);
if (keys_cmp(c, &zbr2->key, &key)) {
- dbg_err("2nd entry at %d:%d has key %s", zbr1->lnum,
- zbr1->offs, DBGKEY(&key));
- dbg_err("but it should have key %s according to tnc",
- DBGKEY(&zbr2->key));
- dbg_dump_node(c, dent2);
+ ubifs_err("2nd entry at %d:%d has key %s", zbr1->lnum,
+ zbr1->offs, dbg_snprintf_key(c, &key, key_buf,
+ DBG_KEY_BUF_LEN));
+ ubifs_err("but it should have key %s according to tnc",
+ dbg_snprintf_key(c, &zbr2->key, key_buf,
+ DBG_KEY_BUF_LEN));
+ ubifs_dump_node(c, dent2);
goto out_free;
}
@@ -1255,15 +1316,15 @@
goto out_free;
}
if (cmp == 0 && nlen1 == nlen2)
- dbg_err("2 xent/dent nodes with the same name");
+ ubifs_err("2 xent/dent nodes with the same name");
else
- dbg_err("bad order of colliding key %s",
- DBGKEY(&key));
+ ubifs_err("bad order of colliding key %s",
+ dbg_snprintf_key(c, &key, key_buf, DBG_KEY_BUF_LEN));
ubifs_msg("first node at %d:%d\n", zbr1->lnum, zbr1->offs);
- dbg_dump_node(c, dent1);
+ ubifs_dump_node(c, dent1);
ubifs_msg("second node at %d:%d\n", zbr2->lnum, zbr2->offs);
- dbg_dump_node(c, dent2);
+ ubifs_dump_node(c, dent2);
out_free:
kfree(dent2);
@@ -1466,10 +1527,10 @@
out:
ubifs_err("failed, error %d", err);
ubifs_msg("dump of the znode");
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
if (zp) {
ubifs_msg("dump of the parent znode");
- dbg_dump_znode(c, zp);
+ ubifs_dump_znode(c, zp);
}
dump_stack();
return -EINVAL;
@@ -1489,7 +1550,7 @@
long clean_cnt = 0, dirty_cnt = 0;
int err, last;
- if (!(ubifs_chk_flags & UBIFS_CHK_TNC))
+ if (!dbg_is_chk_index(c))
return 0;
ubifs_assert(mutex_is_locked(&c->tnc_mutex));
@@ -1536,9 +1597,9 @@
return err;
if (err) {
ubifs_msg("first znode");
- dbg_dump_znode(c, prev);
+ ubifs_dump_znode(c, prev);
ubifs_msg("second znode");
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
return -EINVAL;
}
}
@@ -1627,7 +1688,7 @@
if (err) {
ubifs_err("znode checking function returned "
"error %d", err);
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
goto out_dump;
}
}
@@ -1695,7 +1756,7 @@
else
zbr = &c->zroot;
ubifs_msg("dump of znode at LEB %d:%d", zbr->lnum, zbr->offs);
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
out_unlock:
mutex_unlock(&c->tnc_mutex);
return err;
@@ -1736,7 +1797,7 @@
int err;
long long calc = 0;
- if (!(ubifs_chk_flags & UBIFS_CHK_IDX_SZ))
+ if (!dbg_is_chk_index(c))
return 0;
err = dbg_walk_index(c, NULL, add_size, &calc);
@@ -2131,7 +2192,7 @@
out_dump:
ubifs_msg("dump of node at LEB %d:%d", zbr->lnum, zbr->offs);
- dbg_dump_node(c, node);
+ ubifs_dump_node(c, node);
out_free:
kfree(node);
return err;
@@ -2289,7 +2350,7 @@
ubifs_msg("dump of the inode %lu sitting in LEB %d:%d",
(unsigned long)fscki->inum, zbr->lnum, zbr->offs);
- dbg_dump_node(c, ino);
+ ubifs_dump_node(c, ino);
kfree(ino);
return -EINVAL;
}
@@ -2312,7 +2373,7 @@
int err;
struct fsck_data fsckd;
- if (!(ubifs_chk_flags & UBIFS_CHK_FS))
+ if (!dbg_is_chk_fs(c))
return 0;
fsckd.inodes = RB_ROOT;
@@ -2347,7 +2408,7 @@
struct list_head *cur;
struct ubifs_scan_node *sa, *sb;
- if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+ if (!dbg_is_chk_gen(c))
return 0;
for (cur = head->next; cur->next != head; cur = cur->next) {
@@ -2360,12 +2421,12 @@
if (sa->type != UBIFS_DATA_NODE) {
ubifs_err("bad node type %d", sa->type);
- dbg_dump_node(c, sa->node);
+ ubifs_dump_node(c, sa->node);
return -EINVAL;
}
if (sb->type != UBIFS_DATA_NODE) {
ubifs_err("bad node type %d", sb->type);
- dbg_dump_node(c, sb->node);
+ ubifs_dump_node(c, sb->node);
return -EINVAL;
}
@@ -2396,8 +2457,8 @@
return 0;
error_dump:
- dbg_dump_node(c, sa->node);
- dbg_dump_node(c, sb->node);
+ ubifs_dump_node(c, sa->node);
+ ubifs_dump_node(c, sb->node);
return -EINVAL;
}
@@ -2414,7 +2475,7 @@
struct list_head *cur;
struct ubifs_scan_node *sa, *sb;
- if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+ if (!dbg_is_chk_gen(c))
return 0;
for (cur = head->next; cur->next != head; cur = cur->next) {
@@ -2428,13 +2489,13 @@
if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
sa->type != UBIFS_XENT_NODE) {
ubifs_err("bad node type %d", sa->type);
- dbg_dump_node(c, sa->node);
+ ubifs_dump_node(c, sa->node);
return -EINVAL;
}
if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
sa->type != UBIFS_XENT_NODE) {
ubifs_err("bad node type %d", sb->type);
- dbg_dump_node(c, sb->node);
+ ubifs_dump_node(c, sb->node);
return -EINVAL;
}
@@ -2484,221 +2545,148 @@
error_dump:
ubifs_msg("dumping first node");
- dbg_dump_node(c, sa->node);
+ ubifs_dump_node(c, sa->node);
ubifs_msg("dumping second node");
- dbg_dump_node(c, sb->node);
+ ubifs_dump_node(c, sb->node);
return -EINVAL;
return 0;
}
-int dbg_force_in_the_gaps(void)
-{
- if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
- return 0;
-
- return !(random32() & 7);
-}
-
-/* Failure mode for recovery testing */
-
-#define chance(n, d) (simple_rand() <= (n) * 32768LL / (d))
-
-struct failure_mode_info {
- struct list_head list;
- struct ubifs_info *c;
-};
-
-static LIST_HEAD(fmi_list);
-static DEFINE_SPINLOCK(fmi_lock);
-
-static unsigned int next;
-
-static int simple_rand(void)
+static inline int chance(unsigned int n, unsigned int out_of)
{
- if (next == 0)
- next = current->pid;
- next = next * 1103515245 + 12345;
- return (next >> 16) & 32767;
-}
+ return !!((random32() % out_of) + 1 <= n);
-static void failure_mode_init(struct ubifs_info *c)
-{
- struct failure_mode_info *fmi;
-
- fmi = kmalloc(sizeof(struct failure_mode_info), GFP_NOFS);
- if (!fmi) {
- ubifs_err("Failed to register failure mode - no memory");
- return;
- }
- fmi->c = c;
- spin_lock(&fmi_lock);
- list_add_tail(&fmi->list, &fmi_list);
- spin_unlock(&fmi_lock);
}
-static void failure_mode_exit(struct ubifs_info *c)
+static int power_cut_emulated(struct ubifs_info *c, int lnum, int write)
{
- struct failure_mode_info *fmi, *tmp;
-
- spin_lock(&fmi_lock);
- list_for_each_entry_safe(fmi, tmp, &fmi_list, list)
- if (fmi->c == c) {
- list_del(&fmi->list);
- kfree(fmi);
- }
- spin_unlock(&fmi_lock);
-}
-
-static struct ubifs_info *dbg_find_info(struct ubi_volume_desc *desc)
-{
- struct failure_mode_info *fmi;
-
- spin_lock(&fmi_lock);
- list_for_each_entry(fmi, &fmi_list, list)
- if (fmi->c->ubi == desc) {
- struct ubifs_info *c = fmi->c;
-
- spin_unlock(&fmi_lock);
- return c;
- }
- spin_unlock(&fmi_lock);
- return NULL;
-}
-
-static int in_failure_mode(struct ubi_volume_desc *desc)
-{
- struct ubifs_info *c = dbg_find_info(desc);
-
- if (c && dbg_failure_mode)
- return c->dbg->failure_mode;
- return 0;
-}
+ struct ubifs_debug_info *d = c->dbg;
-static int do_fail(struct ubi_volume_desc *desc, int lnum, int write)
-{
- struct ubifs_info *c = dbg_find_info(desc);
- struct ubifs_debug_info *d;
+ ubifs_assert(dbg_is_tst_rcvry(c));
- if (!c || !dbg_failure_mode)
- return 0;
- d = c->dbg;
- if (d->failure_mode)
- return 1;
- if (!d->fail_cnt) {
- /* First call - decide delay to failure */
+ if (!d->pc_cnt) {
+ /* First call - decide delay to the power cut */
if (chance(1, 2)) {
- unsigned int delay = 1 << (simple_rand() >> 11);
+ unsigned long delay;
if (chance(1, 2)) {
- d->fail_delay = 1;
- d->fail_timeout = jiffies +
- msecs_to_jiffies(delay);
- dbg_rcvry("failing after %ums", delay);
+ d->pc_delay = 1;
+ /* Fail withing 1 minute */
+ delay = random32() % 60000;
+ d->pc_timeout = jiffies;
+ d->pc_timeout += msecs_to_jiffies(delay);
+ ubifs_warn("failing after %lums", delay);
} else {
- d->fail_delay = 2;
- d->fail_cnt_max = delay;
- dbg_rcvry("failing after %u calls", delay);
+ d->pc_delay = 2;
+ delay = random32() % 10000;
+ /* Fail within 10000 operations */
+ d->pc_cnt_max = delay;
+ ubifs_warn("failing after %lu calls", delay);
}
}
- d->fail_cnt += 1;
+
+ d->pc_cnt += 1;
}
+
/* Determine if failure delay has expired */
- if (d->fail_delay == 1) {
- if (time_before(jiffies, d->fail_timeout))
+ if (d->pc_delay == 1 && time_before(jiffies, d->pc_timeout))
return 0;
- } else if (d->fail_delay == 2)
- if (d->fail_cnt++ < d->fail_cnt_max)
+ if (d->pc_delay == 2 && d->pc_cnt++ < d->pc_cnt_max)
return 0;
+
if (lnum == UBIFS_SB_LNUM) {
- if (write) {
- if (chance(1, 2))
- return 0;
- } else if (chance(19, 20))
+ if (write && chance(1, 2))
return 0;
- dbg_rcvry("failing in super block LEB %d", lnum);
+ if (chance(19, 20))
+ return 0;
+ ubifs_warn("failing in super block LEB %d", lnum);
} else if (lnum == UBIFS_MST_LNUM || lnum == UBIFS_MST_LNUM + 1) {
if (chance(19, 20))
return 0;
- dbg_rcvry("failing in master LEB %d", lnum);
+ ubifs_warn("failing in master LEB %d", lnum);
} else if (lnum >= UBIFS_LOG_LNUM && lnum <= c->log_last) {
- if (write) {
- if (chance(99, 100))
- return 0;
- } else if (chance(399, 400))
+ if (write && chance(99, 100))
+ return 0;
+ if (chance(399, 400))
return 0;
- dbg_rcvry("failing in log LEB %d", lnum);
+ ubifs_warn("failing in log LEB %d", lnum);
} else if (lnum >= c->lpt_first && lnum <= c->lpt_last) {
- if (write) {
- if (chance(7, 8))
- return 0;
- } else if (chance(19, 20))
+ if (write && chance(7, 8))
+ return 0;
+ if (chance(19, 20))
return 0;
- dbg_rcvry("failing in LPT LEB %d", lnum);
+ ubifs_warn("failing in LPT LEB %d", lnum);
} else if (lnum >= c->orph_first && lnum <= c->orph_last) {
- if (write) {
- if (chance(1, 2))
- return 0;
- } else if (chance(9, 10))
+ if (write && chance(1, 2))
return 0;
- dbg_rcvry("failing in orphan LEB %d", lnum);
+ if (chance(9, 10))
+ return 0;
+ ubifs_warn("failing in orphan LEB %d", lnum);
} else if (lnum == c->ihead_lnum) {
if (chance(99, 100))
return 0;
- dbg_rcvry("failing in index head LEB %d", lnum);
+ ubifs_warn("failing in index head LEB %d", lnum);
} else if (c->jheads && lnum == c->jheads[GCHD].wbuf.lnum) {
if (chance(9, 10))
return 0;
- dbg_rcvry("failing in GC head LEB %d", lnum);
+ ubifs_warn("failing in GC head LEB %d", lnum);
} else if (write && !RB_EMPTY_ROOT(&c->buds) &&
!ubifs_search_bud(c, lnum)) {
if (chance(19, 20))
return 0;
- dbg_rcvry("failing in non-bud LEB %d", lnum);
+ ubifs_warn("failing in non-bud LEB %d", lnum);
} else if (c->cmt_state == COMMIT_RUNNING_BACKGROUND ||
c->cmt_state == COMMIT_RUNNING_REQUIRED) {
if (chance(999, 1000))
return 0;
- dbg_rcvry("failing in bud LEB %d commit running", lnum);
+ ubifs_warn("failing in bud LEB %d commit running", lnum);
} else {
if (chance(9999, 10000))
return 0;
- dbg_rcvry("failing in bud LEB %d commit not running", lnum);
+ ubifs_warn("failing in bud LEB %d commit not running", lnum);
}
- ubifs_err("*** SETTING FAILURE MODE ON (LEB %d) ***", lnum);
- d->failure_mode = 1;
+
+ d->pc_happened = 1;
+ ubifs_warn("========== Power cut emulated ==========");
dump_stack();
return 1;
}
-static void cut_data(const void *buf, int len)
+static void cut_data(const void *buf, unsigned int len)
{
- int flen, i;
+ unsigned int from, to, i, ffs = chance(1, 2);
unsigned char *p = (void *)buf;
- flen = (len * (long long)simple_rand()) >> 15;
- for (i = flen; i < len; i++)
- p[i] = 0xff;
-}
+ from = random32() % (len + 1);
+ if (chance(1, 2))
+ to = random32() % (len - from + 1);
+ else
+ to = len;
-int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
- int len, int check)
-{
- if (in_failure_mode(desc))
- return -EROFS;
- return ubi_leb_read(desc, lnum, buf, offset, len, check);
+ if (from < to)
+ ubifs_warn("filled bytes %u-%u with %s", from, to - 1,
+ ffs ? "0xFFs" : "random data");
+
+ if (ffs)
+ for (i = from; i < to; i++)
+ p[i] = 0xFF;
+ else
+ for (i = from; i < to; i++)
+ p[i] = random32() % 0x100;
}
-int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
- int offset, int len, int dtype)
+int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf,
+ int offs, int len)
{
int err, failing;
- if (in_failure_mode(desc))
+ if (c->dbg->pc_happened)
return -EROFS;
- failing = do_fail(desc, lnum, 1);
+
+ failing = power_cut_emulated(c, lnum, 1);
if (failing)
cut_data(buf, len);
- err = ubi_leb_write(desc, lnum, buf, offset, len, dtype);
+ err = ubi_leb_write(c->ubi, lnum, buf, offs, len);
if (err)
return err;
if (failing)
@@ -2706,162 +2694,207 @@
return 0;
}
-int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
- int len, int dtype)
+int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf,
+ int len)
{
int err;
- if (do_fail(desc, lnum, 1))
+ if (c->dbg->pc_happened)
+ return -EROFS;
+ if (power_cut_emulated(c, lnum, 1))
return -EROFS;
- err = ubi_leb_change(desc, lnum, buf, len, dtype);
+ err = ubi_leb_change(c->ubi, lnum, buf, len);
if (err)
return err;
- if (do_fail(desc, lnum, 1))
+ if (power_cut_emulated(c, lnum, 1))
return -EROFS;
return 0;
}
-int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum)
+int dbg_leb_unmap(struct ubifs_info *c, int lnum)
{
int err;
- if (do_fail(desc, lnum, 0))
+ if (c->dbg->pc_happened)
return -EROFS;
- err = ubi_leb_erase(desc, lnum);
+ if (power_cut_emulated(c, lnum, 0))
+ return -EROFS;
+ err = ubi_leb_unmap(c->ubi, lnum);
if (err)
return err;
- if (do_fail(desc, lnum, 0))
+ if (power_cut_emulated(c, lnum, 0))
return -EROFS;
return 0;
}
-int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum)
+int dbg_leb_map(struct ubifs_info *c, int lnum)
{
int err;
- if (do_fail(desc, lnum, 0))
+ if (c->dbg->pc_happened)
+ return -EROFS;
+ if (power_cut_emulated(c, lnum, 0))
return -EROFS;
- err = ubi_leb_unmap(desc, lnum);
+ err = ubi_leb_map(c->ubi, lnum);
if (err)
return err;
- if (do_fail(desc, lnum, 0))
+ if (power_cut_emulated(c, lnum, 0))
return -EROFS;
return 0;
}
-int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum)
-{
- if (in_failure_mode(desc))
- return -EROFS;
- return ubi_is_mapped(desc, lnum);
-}
+/*
+ * Root directory for UBIFS stuff in debugfs. Contains sub-directories which
+ * contain the stuff specific to particular file-system mounts.
+ */
+static struct dentry *dfs_rootdir;
-int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
+static int dfs_file_open(struct inode *inode, struct file *file)
{
- int err;
-
- if (do_fail(desc, lnum, 0))
- return -EROFS;
- err = ubi_leb_map(desc, lnum, dtype);
- if (err)
- return err;
- if (do_fail(desc, lnum, 0))
- return -EROFS;
- return 0;
+ file->private_data = inode->i_private;
+ return nonseekable_open(inode, file);
}
/**
- * ubifs_debugging_init - initialize UBIFS debugging.
- * @c: UBIFS file-system description object
- *
- * This function initializes debugging-related data for the file system.
- * Returns zero in case of success and a negative error code in case of
+ * provide_user_output - provide output to the user reading a debugfs file.
+ * @val: boolean value for the answer
+ * @u: the buffer to store the answer at
+ * @count: size of the buffer
+ * @ppos: position in the @u output buffer
+ *
+ * This is a simple helper function which stores @val boolean value in the user
+ * buffer when the user reads one of UBIFS debugfs files. Returns amount of
+ * bytes written to @u in case of success and a negative error code in case of
* failure.
*/
-int ubifs_debugging_init(struct ubifs_info *c)
+static int provide_user_output(int val, char __user *u, size_t count,
+ loff_t *ppos)
{
- c->dbg = kzalloc(sizeof(struct ubifs_debug_info), GFP_KERNEL);
- if (!c->dbg)
- return -ENOMEM;
+ char buf[3];
- failure_mode_init(c);
- return 0;
+ if (val)
+ buf[0] = '1';
+ else
+ buf[0] = '0';
+ buf[1] = '\n';
+ buf[2] = 0x00;
+
+ return simple_read_from_buffer(u, count, ppos, buf, 2);
}
-/**
- * ubifs_debugging_exit - free debugging data.
- * @c: UBIFS file-system description object
- */
-void ubifs_debugging_exit(struct ubifs_info *c)
+static ssize_t dfs_file_read(struct file *file, char __user *u, size_t count,
+ loff_t *ppos)
{
- failure_mode_exit(c);
- kfree(c->dbg);
-}
+ struct dentry *dent = file->f_path.dentry;
+ struct ubifs_info *c = file->private_data;
+ struct ubifs_debug_info *d = c->dbg;
+ int val;
-/*
- * Root directory for UBIFS stuff in debugfs. Contains sub-directories which
- * contain the stuff specific to particular file-system mounts.
- */
-static struct dentry *dfs_rootdir;
+ if (dent == d->dfs_chk_gen)
+ val = d->chk_gen;
+ else if (dent == d->dfs_chk_index)
+ val = d->chk_index;
+ else if (dent == d->dfs_chk_orph)
+ val = d->chk_orph;
+ else if (dent == d->dfs_chk_lprops)
+ val = d->chk_lprops;
+ else if (dent == d->dfs_chk_fs)
+ val = d->chk_fs;
+ else if (dent == d->dfs_tst_rcvry)
+ val = d->tst_rcvry;
+ else
+ return -EINVAL;
+
+ return provide_user_output(val, u, count, ppos);
+}
/**
- * dbg_debugfs_init - initialize debugfs file-system.
+ * interpret_user_input - interpret user debugfs file input.
+ * @u: user-provided buffer with the input
+ * @count: buffer size
*
- * UBIFS uses debugfs file-system to expose various debugging knobs to
- * user-space. This function creates "ubifs" directory in the debugfs
- * file-system. Returns zero in case of success and a negative error code in
- * case of failure.
+ * This is a helper function which interpret user input to a boolean UBIFS
+ * debugfs file. Returns %0 or %1 in case of success and a negative error code
+ * in case of failure.
*/
-int dbg_debugfs_init(void)
+static int interpret_user_input(const char __user *u, size_t count)
{
- dfs_rootdir = debugfs_create_dir("ubifs", NULL);
- if (IS_ERR(dfs_rootdir)) {
- int err = PTR_ERR(dfs_rootdir);
- ubifs_err("cannot create \"ubifs\" debugfs directory, "
- "error %d\n", err);
- return err;
- }
+ size_t buf_size;
+ char buf[8];
- return 0;
-}
+ buf_size = min_t(size_t, count, (sizeof(buf) - 1));
+ if (copy_from_user(buf, u, buf_size))
+ return -EFAULT;
-/**
- * dbg_debugfs_exit - remove the "ubifs" directory from debugfs file-system.
- */
-void dbg_debugfs_exit(void)
-{
- debugfs_remove(dfs_rootdir);
-}
+ if (buf[0] == '1')
+ return 1;
+ else if (buf[0] == '0')
+ return 0;
-static int open_debugfs_file(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return nonseekable_open(inode, file);
+ return -EINVAL;
}
-static ssize_t write_debugfs_file(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
+static ssize_t dfs_file_write(struct file *file, const char __user *u,
+ size_t count, loff_t *ppos)
{
struct ubifs_info *c = file->private_data;
struct ubifs_debug_info *d = c->dbg;
+ struct dentry *dent = file->f_path.dentry;
+ int val;
- if (file->f_path.dentry == d->dfs_dump_lprops)
- dbg_dump_lprops(c);
- else if (file->f_path.dentry == d->dfs_dump_budg)
- dbg_dump_budg(c, &c->bi);
- else if (file->f_path.dentry == d->dfs_dump_tnc) {
+ /*
+ * TODO: this is racy - the file-system might have already been
+ * unmounted and we'd oops in this case. The plan is to fix it with
+ * help of 'iterate_supers_type()' which we should have in v3.0: when
+ * a debugfs opened, we rember FS's UUID in file->private_data. Then
+ * whenever we access the FS via a debugfs file, we iterate all UBIFS
+ * superblocks and fine the one with the same UUID, and take the
+ * locking right.
+ *
+ * The other way to go suggested by Al Viro is to create a separate
+ * 'ubifs-debug' file-system instead.
+ */
+ if (file->f_path.dentry == d->dfs_dump_lprops) {
+ ubifs_dump_lprops(c);
+ return count;
+ }
+ if (file->f_path.dentry == d->dfs_dump_budg) {
+ ubifs_dump_budg(c, &c->bi);
+ return count;
+ }
+ if (file->f_path.dentry == d->dfs_dump_tnc) {
mutex_lock(&c->tnc_mutex);
- dbg_dump_tnc(c);
+ ubifs_dump_tnc(c);
mutex_unlock(&c->tnc_mutex);
- } else
+ return count;
+ }
+
+ val = interpret_user_input(u, count);
+ if (val < 0)
+ return val;
+
+ if (dent == d->dfs_chk_gen)
+ d->chk_gen = val;
+ else if (dent == d->dfs_chk_index)
+ d->chk_index = val;
+ else if (dent == d->dfs_chk_orph)
+ d->chk_orph = val;
+ else if (dent == d->dfs_chk_lprops)
+ d->chk_lprops = val;
+ else if (dent == d->dfs_chk_fs)
+ d->chk_fs = val;
+ else if (dent == d->dfs_tst_rcvry)
+ d->tst_rcvry = val;
+ else
return -EINVAL;
return count;
}
static const struct file_operations dfs_fops = {
- .open = open_debugfs_file,
- .write = write_debugfs_file,
+ .open = dfs_file_open,
+ .read = dfs_file_read,
+ .write = dfs_file_write,
.owner = THIS_MODULE,
.llseek = no_llseek,
};
@@ -2880,12 +2913,24 @@
*/
int dbg_debugfs_init_fs(struct ubifs_info *c)
{
- int err;
+ int err, n;
const char *fname;
struct dentry *dent;
struct ubifs_debug_info *d = c->dbg;
- sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
+#if !defined(CONFIG_DEBUG_FS) && !defined(CONFIG_DEBUG_FS_MODULE)
+ return 0;
+#endif
+
+ n = snprintf(d->dfs_dir_name, UBIFS_DFS_DIR_LEN + 1, UBIFS_DFS_DIR_NAME,
+ c->vi.ubi_num, c->vi.vol_id);
+ if (n == UBIFS_DFS_DIR_LEN) {
+ /* The array size is too small */
+ fname = UBIFS_DFS_DIR_NAME;
+ dent = ERR_PTR(-EINVAL);
+ goto out;
+ }
+
fname = d->dfs_dir_name;
dent = debugfs_create_dir(fname, dfs_rootdir);
if (IS_ERR_OR_NULL(dent))
@@ -2910,13 +2955,55 @@
goto out_remove;
d->dfs_dump_tnc = dent;
+ fname = "chk_general";
+ dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_chk_gen = dent;
+
+ fname = "chk_index";
+ dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_chk_index = dent;
+
+ fname = "chk_orphans";
+ dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_chk_orph = dent;
+
+ fname = "chk_lprops";
+ dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_chk_lprops = dent;
+
+ fname = "chk_fs";
+ dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_chk_fs = dent;
+
+ fname = "tst_recovery";
+ dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+ &dfs_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ d->dfs_tst_rcvry = dent;
+
return 0;
out_remove:
debugfs_remove_recursive(d->dfs_dir);
out:
err = dent ? PTR_ERR(dent) : -ENODEV;
- ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
+ ubifs_err("cannot create \"%s\" debugfs file or directory, error %d\n",
fname, err);
return err;
}
@@ -2927,7 +3014,188 @@
*/
void dbg_debugfs_exit_fs(struct ubifs_info *c)
{
+#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEBUG_FS_MODULE)
debugfs_remove_recursive(c->dbg->dfs_dir);
+#endif
+}
+
+struct ubifs_global_debug_info ubifs_dbg;
+
+static struct dentry *dfs_chk_gen;
+static struct dentry *dfs_chk_index;
+static struct dentry *dfs_chk_orph;
+static struct dentry *dfs_chk_lprops;
+static struct dentry *dfs_chk_fs;
+static struct dentry *dfs_tst_rcvry;
+
+static ssize_t dfs_global_file_read(struct file *file, char __user *u,
+ size_t count, loff_t *ppos)
+{
+ struct dentry *dent = file->f_path.dentry;
+ int val;
+
+ if (dent == dfs_chk_gen)
+ val = ubifs_dbg.chk_gen;
+ else if (dent == dfs_chk_index)
+ val = ubifs_dbg.chk_index;
+ else if (dent == dfs_chk_orph)
+ val = ubifs_dbg.chk_orph;
+ else if (dent == dfs_chk_lprops)
+ val = ubifs_dbg.chk_lprops;
+ else if (dent == dfs_chk_fs)
+ val = ubifs_dbg.chk_fs;
+ else if (dent == dfs_tst_rcvry)
+ val = ubifs_dbg.tst_rcvry;
+ else
+ return -EINVAL;
+
+ return provide_user_output(val, u, count, ppos);
}
-#endif /* CONFIG_UBIFS_FS_DEBUG */
+static ssize_t dfs_global_file_write(struct file *file, const char __user *u,
+ size_t count, loff_t *ppos)
+{
+ struct dentry *dent = file->f_path.dentry;
+ int val;
+
+ val = interpret_user_input(u, count);
+ if (val < 0)
+ return val;
+
+ if (dent == dfs_chk_gen)
+ ubifs_dbg.chk_gen = val;
+ else if (dent == dfs_chk_index)
+ ubifs_dbg.chk_index = val;
+ else if (dent == dfs_chk_orph)
+ ubifs_dbg.chk_orph = val;
+ else if (dent == dfs_chk_lprops)
+ ubifs_dbg.chk_lprops = val;
+ else if (dent == dfs_chk_fs)
+ ubifs_dbg.chk_fs = val;
+ else if (dent == dfs_tst_rcvry)
+ ubifs_dbg.tst_rcvry = val;
+ else
+ return -EINVAL;
+
+ return count;
+}
+
+static const struct file_operations dfs_global_fops = {
+ .read = dfs_global_file_read,
+ .write = dfs_global_file_write,
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+};
+
+/**
+ * dbg_debugfs_init - initialize debugfs file-system.
+ *
+ * UBIFS uses debugfs file-system to expose various debugging knobs to
+ * user-space. This function creates "ubifs" directory in the debugfs
+ * file-system. Returns zero in case of success and a negative error code in
+ * case of failure.
+ */
+int dbg_debugfs_init(void)
+{
+ int err;
+ const char *fname;
+ struct dentry *dent;
+
+#if !defined(CONFIG_DEBUG_FS) && !defined(CONFIG_DEBUG_FS_MODULE)
+ return 0;
+#endif
+
+ fname = "ubifs";
+ dent = debugfs_create_dir(fname, NULL);
+ if (IS_ERR_OR_NULL(dent))
+ goto out;
+ dfs_rootdir = dent;
+
+ fname = "chk_general";
+ dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+ &dfs_global_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ dfs_chk_gen = dent;
+
+ fname = "chk_index";
+ dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+ &dfs_global_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ dfs_chk_index = dent;
+
+ fname = "chk_orphans";
+ dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+ &dfs_global_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ dfs_chk_orph = dent;
+
+ fname = "chk_lprops";
+ dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+ &dfs_global_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ dfs_chk_lprops = dent;
+
+ fname = "chk_fs";
+ dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+ &dfs_global_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ dfs_chk_fs = dent;
+
+ fname = "tst_recovery";
+ dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+ &dfs_global_fops);
+ if (IS_ERR_OR_NULL(dent))
+ goto out_remove;
+ dfs_tst_rcvry = dent;
+
+ return 0;
+
+out_remove:
+ debugfs_remove_recursive(dfs_rootdir);
+out:
+ err = dent ? PTR_ERR(dent) : -ENODEV;
+ ubifs_err("cannot create \"%s\" debugfs file or directory, error %d\n",
+ fname, err);
+ return err;
+}
+
+/**
+ * dbg_debugfs_exit - remove the "ubifs" directory from debugfs file-system.
+ */
+void dbg_debugfs_exit(void)
+{
+#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEBUG_FS_MODULE)
+ debugfs_remove_recursive(dfs_rootdir);
+#endif
+}
+
+/**
+ * ubifs_debugging_init - initialize UBIFS debugging.
+ * @c: UBIFS file-system description object
+ *
+ * This function initializes debugging-related data for the file system.
+ * Returns zero in case of success and a negative error code in case of
+ * failure.
+ */
+int ubifs_debugging_init(struct ubifs_info *c)
+{
+ c->dbg = kzalloc(sizeof(struct ubifs_debug_info), GFP_KERNEL);
+ if (!c->dbg)
+ return -ENOMEM;
+
+ return 0;
+}
+
+/**
+ * ubifs_debugging_exit - free debugging data.
+ * @c: UBIFS file-system description object
+ */
+void ubifs_debugging_exit(struct ubifs_info *c)
+{
+ kfree(c->dbg);
+}
diff -uN -uNr linux-3.0/fs/ubifs/debug.h linux-3.0.x.ubifs.latest/fs/ubifs/debug.h
--- linux-3.0/fs/ubifs/debug.h 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/debug.h 2012-06-28 11:26:15.000000000 -0500
@@ -29,20 +29,25 @@
typedef int (*dbg_znode_callback)(struct ubifs_info *c,
struct ubifs_znode *znode, void *priv);
-#ifdef CONFIG_UBIFS_FS_DEBUG
-
-#include <linux/random.h>
+/*
+ * The UBIFS debugfs directory name pattern and maximum name length (3 for "ubi"
+ * + 1 for "_" and plus 2x2 for 2 UBI numbers and 1 for the trailing zero byte.
+ */
+#define UBIFS_DFS_DIR_NAME "ubi%d_%d"
+#define UBIFS_DFS_DIR_LEN (3 + 1 + 2*2 + 1)
/**
* ubifs_debug_info - per-FS debugging information.
* @old_zroot: old index root - used by 'dbg_check_old_index()'
* @old_zroot_level: old index root level - used by 'dbg_check_old_index()'
* @old_zroot_sqnum: old index root sqnum - used by 'dbg_check_old_index()'
- * @failure_mode: failure mode for recovery testing
- * @fail_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls
- * @fail_timeout: time in jiffies when delay of failure mode expires
- * @fail_cnt: current number of calls to failure mode I/O functions
- * @fail_cnt_max: number of calls by which to delay failure mode
+ *
+ * @pc_happened: non-zero if an emulated power cut happened
+ * @pc_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls
+ * @pc_timeout: time in jiffies when delay of failure mode expires
+ * @pc_cnt: current number of calls to failure mode I/O functions
+ * @pc_cnt_max: number of calls by which to delay failure mode
+ *
* @chk_lpt_sz: used by LPT tree size checker
* @chk_lpt_sz2: used by LPT tree size checker
* @chk_lpt_wastage: used by LPT tree size checker
@@ -56,21 +61,36 @@
* @saved_free: saved amount of free space
* @saved_idx_gc_cnt: saved value of @c->idx_gc_cnt
*
+ * @chk_gen: if general extra checks are enabled
+ * @chk_index: if index xtra checks are enabled
+ * @chk_orph: if orphans extra checks are enabled
+ * @chk_lprops: if lprops extra checks are enabled
+ * @chk_fs: if UBIFS contents extra checks are enabled
+ * @tst_rcvry: if UBIFS recovery testing mode enabled
+ *
* @dfs_dir_name: name of debugfs directory containing this file-system's files
* @dfs_dir: direntry object of the file-system debugfs directory
* @dfs_dump_lprops: "dump lprops" debugfs knob
* @dfs_dump_budg: "dump budgeting information" debugfs knob
* @dfs_dump_tnc: "dump TNC" debugfs knob
+ * @dfs_chk_gen: debugfs knob to enable UBIFS general extra checks
+ * @dfs_chk_index: debugfs knob to enable UBIFS index extra checks
+ * @dfs_chk_orph: debugfs knob to enable UBIFS orphans extra checks
+ * @dfs_chk_lprops: debugfs knob to enable UBIFS LEP properties extra checks
+ * @dfs_chk_fs: debugfs knob to enable UBIFS contents extra checks
+ * @dfs_tst_rcvry: debugfs knob to enable UBIFS recovery testing
*/
struct ubifs_debug_info {
struct ubifs_zbranch old_zroot;
int old_zroot_level;
unsigned long long old_zroot_sqnum;
- int failure_mode;
- int fail_delay;
- unsigned long fail_timeout;
- unsigned int fail_cnt;
- unsigned int fail_cnt_max;
+
+ int pc_happened;
+ int pc_delay;
+ unsigned long pc_timeout;
+ unsigned int pc_cnt;
+ unsigned int pc_cnt_max;
+
long long chk_lpt_sz;
long long chk_lpt_sz2;
long long chk_lpt_wastage;
@@ -84,18 +104,50 @@
long long saved_free;
int saved_idx_gc_cnt;
- char dfs_dir_name[100];
+ unsigned int chk_gen:1;
+ unsigned int chk_index:1;
+ unsigned int chk_orph:1;
+ unsigned int chk_lprops:1;
+ unsigned int chk_fs:1;
+ unsigned int tst_rcvry:1;
+
+ char dfs_dir_name[UBIFS_DFS_DIR_LEN + 1];
struct dentry *dfs_dir;
struct dentry *dfs_dump_lprops;
struct dentry *dfs_dump_budg;
struct dentry *dfs_dump_tnc;
+ struct dentry *dfs_chk_gen;
+ struct dentry *dfs_chk_index;
+ struct dentry *dfs_chk_orph;
+ struct dentry *dfs_chk_lprops;
+ struct dentry *dfs_chk_fs;
+ struct dentry *dfs_tst_rcvry;
+};
+
+/**
+ * ubifs_global_debug_info - global (not per-FS) UBIFS debugging information.
+ *
+ * @chk_gen: if general extra checks are enabled
+ * @chk_index: if index xtra checks are enabled
+ * @chk_orph: if orphans extra checks are enabled
+ * @chk_lprops: if lprops extra checks are enabled
+ * @chk_fs: if UBIFS contents extra checks are enabled
+ * @tst_rcvry: if UBIFS recovery testing mode enabled
+ */
+struct ubifs_global_debug_info {
+ unsigned int chk_gen:1;
+ unsigned int chk_index:1;
+ unsigned int chk_orph:1;
+ unsigned int chk_lprops:1;
+ unsigned int chk_fs:1;
+ unsigned int tst_rcvry:1;
};
#define ubifs_assert(expr) do { \
if (unlikely(!(expr))) { \
printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \
__func__, __LINE__, current->pid); \
- dbg_dump_stack(); \
+ dump_stack(); \
} \
} while (0)
@@ -107,46 +159,39 @@
} \
} while (0)
-#define dbg_dump_stack() dump_stack()
+#define ubifs_dbg_msg(type, fmt, ...) \
+ pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__)
-#define dbg_err(fmt, ...) do { \
- spin_lock(&dbg_lock); \
- ubifs_err(fmt, ##__VA_ARGS__); \
- spin_unlock(&dbg_lock); \
-} while (0)
-
-const char *dbg_key_str0(const struct ubifs_info *c,
- const union ubifs_key *key);
-const char *dbg_key_str1(const struct ubifs_info *c,
- const union ubifs_key *key);
-
-/*
- * DBGKEY macros require @dbg_lock to be held, which it is in the dbg message
- * macros.
- */
-#define DBGKEY(key) dbg_key_str0(c, (key))
-#define DBGKEY1(key) dbg_key_str1(c, (key))
-
-#define ubifs_dbg_msg(type, fmt, ...) do { \
- spin_lock(&dbg_lock); \
- pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__); \
- spin_unlock(&dbg_lock); \
+#define DBG_KEY_BUF_LEN 32
+#define ubifs_dbg_msg_key(type, key, fmt, ...) do { \
+ char __tmp_key_buf[DBG_KEY_BUF_LEN]; \
+ pr_debug("UBIFS DBG " type ": " fmt "%s\n", ##__VA_ARGS__, \
+ dbg_snprintf_key(c, key, __tmp_key_buf, DBG_KEY_BUF_LEN)); \
} while (0)
/* Just a debugging messages not related to any specific UBIFS subsystem */
-#define dbg_msg(fmt, ...) ubifs_dbg_msg("msg", fmt, ##__VA_ARGS__)
+#define dbg_msg(fmt, ...) \
+ printk(KERN_DEBUG "UBIFS DBG (pid %d): %s: " fmt "\n", current->pid, \
+ __func__, ##__VA_ARGS__)
+
/* General messages */
#define dbg_gen(fmt, ...) ubifs_dbg_msg("gen", fmt, ##__VA_ARGS__)
/* Additional journal messages */
#define dbg_jnl(fmt, ...) ubifs_dbg_msg("jnl", fmt, ##__VA_ARGS__)
+#define dbg_jnlk(key, fmt, ...) \
+ ubifs_dbg_msg_key("jnl", key, fmt, ##__VA_ARGS__)
/* Additional TNC messages */
#define dbg_tnc(fmt, ...) ubifs_dbg_msg("tnc", fmt, ##__VA_ARGS__)
+#define dbg_tnck(key, fmt, ...) \
+ ubifs_dbg_msg_key("tnc", key, fmt, ##__VA_ARGS__)
/* Additional lprops messages */
#define dbg_lp(fmt, ...) ubifs_dbg_msg("lp", fmt, ##__VA_ARGS__)
/* Additional LEB find messages */
#define dbg_find(fmt, ...) ubifs_dbg_msg("find", fmt, ##__VA_ARGS__)
/* Additional mount messages */
#define dbg_mnt(fmt, ...) ubifs_dbg_msg("mnt", fmt, ##__VA_ARGS__)
+#define dbg_mntk(key, fmt, ...) \
+ ubifs_dbg_msg_key("mnt", key, fmt, ##__VA_ARGS__)
/* Additional I/O messages */
#define dbg_io(fmt, ...) ubifs_dbg_msg("io", fmt, ##__VA_ARGS__)
/* Additional commit messages */
@@ -162,41 +207,36 @@
/* Additional recovery messages */
#define dbg_rcvry(fmt, ...) ubifs_dbg_msg("rcvry", fmt, ##__VA_ARGS__)
-/*
- * Debugging check flags.
- *
- * UBIFS_CHK_GEN: general checks
- * UBIFS_CHK_TNC: check TNC
- * UBIFS_CHK_IDX_SZ: check index size
- * UBIFS_CHK_ORPH: check orphans
- * UBIFS_CHK_OLD_IDX: check the old index
- * UBIFS_CHK_LPROPS: check lprops
- * UBIFS_CHK_FS: check the file-system
- */
-enum {
- UBIFS_CHK_GEN = 0x1,
- UBIFS_CHK_TNC = 0x2,
- UBIFS_CHK_IDX_SZ = 0x4,
- UBIFS_CHK_ORPH = 0x8,
- UBIFS_CHK_OLD_IDX = 0x10,
- UBIFS_CHK_LPROPS = 0x20,
- UBIFS_CHK_FS = 0x40,
-};
+extern struct ubifs_global_debug_info ubifs_dbg;
-/*
- * Special testing flags.
- *
- * UBIFS_TST_RCVRY: failure mode for recovery testing
- */
-enum {
- UBIFS_TST_RCVRY = 0x4,
-};
-
-extern spinlock_t dbg_lock;
-
-extern unsigned int ubifs_msg_flags;
-extern unsigned int ubifs_chk_flags;
-extern unsigned int ubifs_tst_flags;
+static inline int dbg_is_chk_gen(const struct ubifs_info *c)
+{
+ return !!(ubifs_dbg.chk_gen || c->dbg->chk_gen);
+}
+static inline int dbg_is_chk_index(const struct ubifs_info *c)
+{
+ return !!(ubifs_dbg.chk_index || c->dbg->chk_index);
+}
+static inline int dbg_is_chk_orph(const struct ubifs_info *c)
+{
+ return !!(ubifs_dbg.chk_orph || c->dbg->chk_orph);
+}
+static inline int dbg_is_chk_lprops(const struct ubifs_info *c)
+{
+ return !!(ubifs_dbg.chk_lprops || c->dbg->chk_lprops);
+}
+static inline int dbg_is_chk_fs(const struct ubifs_info *c)
+{
+ return !!(ubifs_dbg.chk_fs || c->dbg->chk_fs);
+}
+static inline int dbg_is_tst_rcvry(const struct ubifs_info *c)
+{
+ return !!(ubifs_dbg.tst_rcvry || c->dbg->tst_rcvry);
+}
+static inline int dbg_is_power_cut(const struct ubifs_info *c)
+{
+ return !!c->dbg->pc_happened;
+}
int ubifs_debugging_init(struct ubifs_info *c);
void ubifs_debugging_exit(struct ubifs_info *c);
@@ -207,25 +247,29 @@
const char *dbg_jhead(int jhead);
const char *dbg_get_key_dump(const struct ubifs_info *c,
const union ubifs_key *key);
-void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode);
-void dbg_dump_node(const struct ubifs_info *c, const void *node);
-void dbg_dump_lpt_node(const struct ubifs_info *c, void *node, int lnum,
- int offs);
-void dbg_dump_budget_req(const struct ubifs_budget_req *req);
-void dbg_dump_lstats(const struct ubifs_lp_stats *lst);
-void dbg_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi);
-void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp);
-void dbg_dump_lprops(struct ubifs_info *c);
-void dbg_dump_lpt_info(struct ubifs_info *c);
-void dbg_dump_leb(const struct ubifs_info *c, int lnum);
-void dbg_dump_znode(const struct ubifs_info *c,
- const struct ubifs_znode *znode);
-void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat);
-void dbg_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
- struct ubifs_nnode *parent, int iip);
-void dbg_dump_tnc(struct ubifs_info *c);
-void dbg_dump_index(struct ubifs_info *c);
-void dbg_dump_lpt_lebs(const struct ubifs_info *c);
+const char *dbg_snprintf_key(const struct ubifs_info *c,
+ const union ubifs_key *key, char *buffer, int len);
+void ubifs_dump_inode(struct ubifs_info *c, const struct inode *inode);
+void ubifs_dump_node(const struct ubifs_info *c, const void *node);
+void ubifs_dump_budget_req(const struct ubifs_budget_req *req);
+void ubifs_dump_lstats(const struct ubifs_lp_stats *lst);
+void ubifs_dump_budg(struct ubifs_info *c, const struct ubifs_budg_info *bi);
+void ubifs_dump_lprop(const struct ubifs_info *c,
+ const struct ubifs_lprops *lp);
+void ubifs_dump_lprops(struct ubifs_info *c);
+void ubifs_dump_lpt_info(struct ubifs_info *c);
+void ubifs_dump_leb(const struct ubifs_info *c, int lnum);
+void ubifs_dump_sleb(const struct ubifs_info *c,
+ const struct ubifs_scan_leb *sleb, int offs);
+void ubifs_dump_znode(const struct ubifs_info *c,
+ const struct ubifs_znode *znode);
+void ubifs_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap,
+ int cat);
+void ubifs_dump_pnode(struct ubifs_info *c, struct ubifs_pnode *pnode,
+ struct ubifs_nnode *parent, int iip);
+void ubifs_dump_tnc(struct ubifs_info *c);
+void ubifs_dump_index(struct ubifs_info *c);
+void ubifs_dump_lpt_lebs(const struct ubifs_info *c);
int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb,
dbg_znode_callback znode_cb, void *priv);
@@ -240,8 +284,8 @@
int dbg_check_ltab(struct ubifs_info *c);
int dbg_chk_lpt_free_spc(struct ubifs_info *c);
int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len);
-int dbg_check_synced_i_size(struct inode *inode);
-int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir);
+int dbg_check_synced_i_size(const struct ubifs_info *c, struct inode *inode);
+int dbg_check_dir(struct ubifs_info *c, const struct inode *dir);
int dbg_check_tnc(struct ubifs_info *c, int extra);
int dbg_check_idx_size(struct ubifs_info *c, long long idx_size);
int dbg_check_filesystem(struct ubifs_info *c);
@@ -254,54 +298,11 @@
int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head);
int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head);
-/* Force the use of in-the-gaps method for testing */
-static inline int dbg_force_in_the_gaps_enabled(void)
-{
- return ubifs_chk_flags & UBIFS_CHK_GEN;
-}
-int dbg_force_in_the_gaps(void);
-
-/* Failure mode for recovery testing */
-#define dbg_failure_mode (ubifs_tst_flags & UBIFS_TST_RCVRY)
-
-#ifndef UBIFS_DBG_PRESERVE_UBI
-#define ubi_leb_read dbg_leb_read
-#define ubi_leb_write dbg_leb_write
-#define ubi_leb_change dbg_leb_change
-#define ubi_leb_erase dbg_leb_erase
-#define ubi_leb_unmap dbg_leb_unmap
-#define ubi_is_mapped dbg_is_mapped
-#define ubi_leb_map dbg_leb_map
-#endif
-
-int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
- int len, int check);
-int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
- int offset, int len, int dtype);
-int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
- int len, int dtype);
-int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum);
-int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum);
-int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum);
-int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype);
-
-static inline int dbg_read(struct ubi_volume_desc *desc, int lnum, char *buf,
- int offset, int len)
-{
- return dbg_leb_read(desc, lnum, buf, offset, len, 0);
-}
-
-static inline int dbg_write(struct ubi_volume_desc *desc, int lnum,
- const void *buf, int offset, int len)
-{
- return dbg_leb_write(desc, lnum, buf, offset, len, UBI_UNKNOWN);
-}
-
-static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
- const void *buf, int len)
-{
- return dbg_leb_change(desc, lnum, buf, len, UBI_UNKNOWN);
-}
+int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
+ int len);
+int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len);
+int dbg_leb_unmap(struct ubifs_info *c, int lnum);
+int dbg_leb_map(struct ubifs_info *c, int lnum);
/* Debugfs-related stuff */
int dbg_debugfs_init(void);
@@ -309,136 +310,4 @@
int dbg_debugfs_init_fs(struct ubifs_info *c);
void dbg_debugfs_exit_fs(struct ubifs_info *c);
-#else /* !CONFIG_UBIFS_FS_DEBUG */
-
-/* Use "if (0)" to make compiler check arguments even if debugging is off */
-#define ubifs_assert(expr) do { \
- if (0 && (expr)) \
- printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \
- __func__, __LINE__, current->pid); \
-} while (0)
-
-#define dbg_err(fmt, ...) do { \
- if (0) \
- ubifs_err(fmt, ##__VA_ARGS__); \
-} while (0)
-
-#define ubifs_dbg_msg(fmt, ...) do { \
- if (0) \
- pr_debug(fmt "\n", ##__VA_ARGS__); \
-} while (0)
-
-#define dbg_dump_stack()
-#define ubifs_assert_cmt_locked(c)
-
-#define dbg_msg(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_gen(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_jnl(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_tnc(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_lp(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_find(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_mnt(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_io(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_cmt(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_budg(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_log(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_gc(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_scan(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-#define dbg_rcvry(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
-
-#define DBGKEY(key) ((char *)(key))
-#define DBGKEY1(key) ((char *)(key))
-
-static inline int ubifs_debugging_init(struct ubifs_info *c) { return 0; }
-static inline void ubifs_debugging_exit(struct ubifs_info *c) { return; }
-static inline const char *dbg_ntype(int type) { return ""; }
-static inline const char *dbg_cstate(int cmt_state) { return ""; }
-static inline const char *dbg_jhead(int jhead) { return ""; }
-static inline const char *
-dbg_get_key_dump(const struct ubifs_info *c,
- const union ubifs_key *key) { return ""; }
-static inline void dbg_dump_inode(const struct ubifs_info *c,
- const struct inode *inode) { return; }
-static inline void dbg_dump_node(const struct ubifs_info *c,
- const void *node) { return; }
-static inline void dbg_dump_lpt_node(const struct ubifs_info *c,
- void *node, int lnum,
- int offs) { return; }
-static inline void
-dbg_dump_budget_req(const struct ubifs_budget_req *req) { return; }
-static inline void
-dbg_dump_lstats(const struct ubifs_lp_stats *lst) { return; }
-static inline void
-dbg_dump_budg(struct ubifs_info *c,
- const struct ubifs_budg_info *bi) { return; }
-static inline void dbg_dump_lprop(const struct ubifs_info *c,
- const struct ubifs_lprops *lp) { return; }
-static inline void dbg_dump_lprops(struct ubifs_info *c) { return; }
-static inline void dbg_dump_lpt_info(struct ubifs_info *c) { return; }
-static inline void dbg_dump_leb(const struct ubifs_info *c,
- int lnum) { return; }
-static inline void
-dbg_dump_znode(const struct ubifs_info *c,
- const struct ubifs_znode *znode) { return; }
-static inline void dbg_dump_heap(struct ubifs_info *c,
- struct ubifs_lpt_heap *heap,
- int cat) { return; }
-static inline void dbg_dump_pnode(struct ubifs_info *c,
- struct ubifs_pnode *pnode,
- struct ubifs_nnode *parent,
- int iip) { return; }
-static inline void dbg_dump_tnc(struct ubifs_info *c) { return; }
-static inline void dbg_dump_index(struct ubifs_info *c) { return; }
-static inline void dbg_dump_lpt_lebs(const struct ubifs_info *c) { return; }
-
-static inline int dbg_walk_index(struct ubifs_info *c,
- dbg_leaf_callback leaf_cb,
- dbg_znode_callback znode_cb,
- void *priv) { return 0; }
-static inline void dbg_save_space_info(struct ubifs_info *c) { return; }
-static inline int dbg_check_space_info(struct ubifs_info *c) { return 0; }
-static inline int dbg_check_lprops(struct ubifs_info *c) { return 0; }
-static inline int
-dbg_old_index_check_init(struct ubifs_info *c,
- struct ubifs_zbranch *zroot) { return 0; }
-static inline int
-dbg_check_old_index(struct ubifs_info *c,
- struct ubifs_zbranch *zroot) { return 0; }
-static inline int dbg_check_cats(struct ubifs_info *c) { return 0; }
-static inline int dbg_check_ltab(struct ubifs_info *c) { return 0; }
-static inline int dbg_chk_lpt_free_spc(struct ubifs_info *c) { return 0; }
-static inline int dbg_chk_lpt_sz(struct ubifs_info *c,
- int action, int len) { return 0; }
-static inline int dbg_check_synced_i_size(struct inode *inode) { return 0; }
-static inline int dbg_check_dir_size(struct ubifs_info *c,
- const struct inode *dir) { return 0; }
-static inline int dbg_check_tnc(struct ubifs_info *c, int extra) { return 0; }
-static inline int dbg_check_idx_size(struct ubifs_info *c,
- long long idx_size) { return 0; }
-static inline int dbg_check_filesystem(struct ubifs_info *c) { return 0; }
-static inline void dbg_check_heap(struct ubifs_info *c,
- struct ubifs_lpt_heap *heap,
- int cat, int add_pos) { return; }
-static inline int dbg_check_lpt_nodes(struct ubifs_info *c,
- struct ubifs_cnode *cnode, int row, int col) { return 0; }
-static inline int dbg_check_inode_size(struct ubifs_info *c,
- const struct inode *inode,
- loff_t size) { return 0; }
-static inline int
-dbg_check_data_nodes_order(struct ubifs_info *c,
- struct list_head *head) { return 0; }
-static inline int
-dbg_check_nondata_nodes_order(struct ubifs_info *c,
- struct list_head *head) { return 0; }
-
-static inline int dbg_force_in_the_gaps(void) { return 0; }
-#define dbg_force_in_the_gaps_enabled() 0
-#define dbg_failure_mode 0
-
-static inline int dbg_debugfs_init(void) { return 0; }
-static inline void dbg_debugfs_exit(void) { return; }
-static inline int dbg_debugfs_init_fs(struct ubifs_info *c) { return 0; }
-static inline int dbg_debugfs_exit_fs(struct ubifs_info *c) { return 0; }
-
-#endif /* !CONFIG_UBIFS_FS_DEBUG */
#endif /* !__UBIFS_DEBUG_H__ */
diff -uN -uNr linux-3.0/fs/ubifs/dir.c linux-3.0.x.ubifs.latest/fs/ubifs/dir.c
--- linux-3.0/fs/ubifs/dir.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/dir.c 2012-06-28 11:26:15.000000000 -0500
@@ -102,7 +102,7 @@
* UBIFS has to fully control "clean <-> dirty" transitions of inodes
* to make budgeting work.
*/
- inode->i_flags |= (S_NOCMTIME);
+ inode->i_flags |= S_NOCMTIME;
inode_init_owner(inode, dir, mode);
inode->i_mtime = inode->i_atime = inode->i_ctime =
@@ -170,11 +170,11 @@
return inode;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
-
-static int dbg_check_name(struct ubifs_dent_node *dent, struct qstr *nm)
+static int dbg_check_name(const struct ubifs_info *c,
+ const struct ubifs_dent_node *dent,
+ const struct qstr *nm)
{
- if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+ if (!dbg_is_chk_gen(c))
return 0;
if (le16_to_cpu(dent->nlen) != nm->len)
return -EINVAL;
@@ -183,12 +183,6 @@
return 0;
}
-#else
-
-#define dbg_check_name(dent, nm) 0
-
-#endif
-
static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
struct nameidata *nd)
{
@@ -219,7 +213,7 @@
goto out;
}
- if (dbg_check_name(dent, &dentry->d_name)) {
+ if (dbg_check_name(c, dent, &dentry->d_name)) {
err = -EINVAL;
goto out;
}
@@ -522,7 +516,7 @@
ubifs_assert(mutex_is_locked(&dir->i_mutex));
ubifs_assert(mutex_is_locked(&inode->i_mutex));
- err = dbg_check_synced_i_size(inode);
+ err = dbg_check_synced_i_size(c, inode);
if (err)
return err;
@@ -577,7 +571,7 @@
inode->i_nlink, dir->i_ino);
ubifs_assert(mutex_is_locked(&dir->i_mutex));
ubifs_assert(mutex_is_locked(&inode->i_mutex));
- err = dbg_check_synced_i_size(inode);
+ err = dbg_check_synced_i_size(c, inode);
if (err)
return err;
@@ -1185,12 +1179,10 @@
.rename = ubifs_rename,
.setattr = ubifs_setattr,
.getattr = ubifs_getattr,
-#ifdef CONFIG_UBIFS_FS_XATTR
.setxattr = ubifs_setxattr,
.getxattr = ubifs_getxattr,
.listxattr = ubifs_listxattr,
.removexattr = ubifs_removexattr,
-#endif
};
const struct file_operations ubifs_dir_operations = {
diff -uN -uNr linux-3.0/fs/ubifs/file.c linux-3.0.x.ubifs.latest/fs/ubifs/file.c
--- linux-3.0/fs/ubifs/file.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/file.c 2012-06-28 11:26:15.000000000 -0500
@@ -97,7 +97,7 @@
dump:
ubifs_err("bad data node (block %u, inode %lu)",
block, inode->i_ino);
- dbg_dump_node(c, dn);
+ ubifs_dump_node(c, dn);
return -EINVAL;
}
@@ -1263,7 +1263,7 @@
if (err)
return err;
- err = dbg_check_synced_i_size(inode);
+ err = dbg_check_synced_i_size(c, inode);
if (err)
return err;
@@ -1561,12 +1561,10 @@
const struct inode_operations ubifs_file_inode_operations = {
.setattr = ubifs_setattr,
.getattr = ubifs_getattr,
-#ifdef CONFIG_UBIFS_FS_XATTR
.setxattr = ubifs_setxattr,
.getxattr = ubifs_getxattr,
.listxattr = ubifs_listxattr,
.removexattr = ubifs_removexattr,
-#endif
};
const struct inode_operations ubifs_symlink_inode_operations = {
diff -uN -uNr linux-3.0/fs/ubifs/find.c linux-3.0.x.ubifs.latest/fs/ubifs/find.c
--- linux-3.0/fs/ubifs/find.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/find.c 2012-06-28 11:26:15.000000000 -0500
@@ -939,8 +939,8 @@
}
dbg_find("LEB %d, dirty %d and free %d flags %#x", lp->lnum, lp->dirty,
lp->free, lp->flags);
- ubifs_assert(lp->flags | LPROPS_TAKEN);
- ubifs_assert(lp->flags | LPROPS_INDEX);
+ ubifs_assert(lp->flags & LPROPS_TAKEN);
+ ubifs_assert(lp->flags & LPROPS_INDEX);
return lnum;
}
diff -uN -uNr linux-3.0/fs/ubifs/gc.c linux-3.0.x.ubifs.latest/fs/ubifs/gc.c
--- linux-3.0/fs/ubifs/gc.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/gc.c 2012-06-28 11:26:15.000000000 -0500
@@ -109,7 +109,7 @@
return err;
c->gc_lnum = -1;
- err = ubifs_wbuf_seek_nolock(wbuf, gc_lnum, 0, UBI_LONGTERM);
+ err = ubifs_wbuf_seek_nolock(wbuf, gc_lnum, 0);
return err;
}
diff -uN -uNr linux-3.0/fs/ubifs/io.c linux-3.0.x.ubifs.latest/fs/ubifs/io.c
--- linux-3.0/fs/ubifs/io.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/io.c 2012-06-28 11:26:15.000000000 -0500
@@ -86,10 +86,126 @@
c->no_chk_data_crc = 0;
c->vfs_sb->s_flags |= MS_RDONLY;
ubifs_warn("switched to read-only mode, error %d", err);
- dbg_dump_stack();
+ dump_stack();
}
}
+/*
+ * Below are simple wrappers over UBI I/O functions which include some
+ * additional checks and UBIFS debugging stuff. See corresponding UBI function
+ * for more information.
+ */
+
+int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
+ int len, int even_ebadmsg)
+{
+ int err;
+
+ err = ubi_read(c->ubi, lnum, buf, offs, len);
+ /*
+ * In case of %-EBADMSG print the error message only if the
+ * @even_ebadmsg is true.
+ */
+ if (err && (err != -EBADMSG || even_ebadmsg)) {
+ ubifs_err("reading %d bytes from LEB %d:%d failed, error %d",
+ len, lnum, offs, err);
+ dump_stack();
+ }
+ return err;
+}
+
+int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
+ int len)
+{
+ int err;
+
+ ubifs_assert(!c->ro_media && !c->ro_mount);
+ if (c->ro_error)
+ return -EROFS;
+ if (!dbg_is_tst_rcvry(c))
+ err = ubi_leb_write(c->ubi, lnum, buf, offs, len);
+ else
+ err = dbg_leb_write(c, lnum, buf, offs, len);
+ if (err) {
+ ubifs_err("writing %d bytes to LEB %d:%d failed, error %d",
+ len, lnum, offs, err);
+ ubifs_ro_mode(c, err);
+ dump_stack();
+ }
+ return err;
+}
+
+int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len)
+{
+ int err;
+
+ ubifs_assert(!c->ro_media && !c->ro_mount);
+ if (c->ro_error)
+ return -EROFS;
+ if (!dbg_is_tst_rcvry(c))
+ err = ubi_leb_change(c->ubi, lnum, buf, len);
+ else
+ err = dbg_leb_change(c, lnum, buf, len);
+ if (err) {
+ ubifs_err("changing %d bytes in LEB %d failed, error %d",
+ len, lnum, err);
+ ubifs_ro_mode(c, err);
+ dump_stack();
+ }
+ return err;
+}
+
+int ubifs_leb_unmap(struct ubifs_info *c, int lnum)
+{
+ int err;
+
+ ubifs_assert(!c->ro_media && !c->ro_mount);
+ if (c->ro_error)
+ return -EROFS;
+ if (!dbg_is_tst_rcvry(c))
+ err = ubi_leb_unmap(c->ubi, lnum);
+ else
+ err = dbg_leb_unmap(c, lnum);
+ if (err) {
+ ubifs_err("unmap LEB %d failed, error %d", lnum, err);
+ ubifs_ro_mode(c, err);
+ dump_stack();
+ }
+ return err;
+}
+
+int ubifs_leb_map(struct ubifs_info *c, int lnum)
+{
+ int err;
+
+ ubifs_assert(!c->ro_media && !c->ro_mount);
+ if (c->ro_error)
+ return -EROFS;
+ if (!dbg_is_tst_rcvry(c))
+ err = ubi_leb_map(c->ubi, lnum);
+ else
+ err = dbg_leb_map(c, lnum);
+ if (err) {
+ ubifs_err("mapping LEB %d failed, error %d", lnum, err);
+ ubifs_ro_mode(c, err);
+ dump_stack();
+ }
+ return err;
+}
+
+int ubifs_is_mapped(const struct ubifs_info *c, int lnum)
+{
+ int err;
+
+ err = ubi_is_mapped(c->ubi, lnum);
+ if (err < 0) {
+ ubifs_err("ubi_is_mapped failed for LEB %d, error %d",
+ lnum, err);
+ dump_stack();
+ }
+ return err;
+}
+
/**
* ubifs_check_node - check node.
* @c: UBIFS file-system description object
@@ -177,8 +293,8 @@
out:
if (!quiet) {
ubifs_err("bad node at LEB %d:%d", lnum, offs);
- dbg_dump_node(c, buf);
- dbg_dump_stack();
+ ubifs_dump_node(c, buf);
+ dump_stack();
}
return err;
}
@@ -406,14 +522,9 @@
dirt = sync_len - wbuf->used;
if (dirt)
ubifs_pad(c, wbuf->buf + wbuf->used, dirt);
- err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
- sync_len, wbuf->dtype);
- if (err) {
- ubifs_err("cannot write %d bytes to LEB %d:%d",
- sync_len, wbuf->lnum, wbuf->offs);
- dbg_dump_stack();
+ err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs, sync_len);
+ if (err)
return err;
- }
spin_lock(&wbuf->lock);
wbuf->offs += sync_len;
@@ -449,14 +560,12 @@
* @wbuf: write-buffer
* @lnum: logical eraseblock number to seek to
* @offs: logical eraseblock offset to seek to
- * @dtype: data type
*
* This function targets the write-buffer to logical eraseblock @lnum:@offs.
* The write-buffer has to be empty. Returns zero in case of success and a
* negative error code in case of failure.
*/
-int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
- int dtype)
+int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs)
{
const struct ubifs_info *c = wbuf->c;
@@ -479,7 +588,6 @@
wbuf->avail = wbuf->size;
wbuf->used = 0;
spin_unlock(&wbuf->lock);
- wbuf->dtype = dtype;
return 0;
}
@@ -605,9 +713,8 @@
if (aligned_len == wbuf->avail) {
dbg_io("flush jhead %s wbuf to LEB %d:%d",
dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
- err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf,
- wbuf->offs, wbuf->size,
- wbuf->dtype);
+ err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf,
+ wbuf->offs, wbuf->size);
if (err)
goto out;
@@ -642,8 +749,8 @@
dbg_io("flush jhead %s wbuf to LEB %d:%d",
dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail);
- err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
- wbuf->size, wbuf->dtype);
+ err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs,
+ wbuf->size);
if (err)
goto out;
@@ -661,8 +768,8 @@
*/
dbg_io("write %d bytes to LEB %d:%d",
wbuf->size, wbuf->lnum, wbuf->offs);
- err = ubi_leb_write(c->ubi, wbuf->lnum, buf, wbuf->offs,
- wbuf->size, wbuf->dtype);
+ err = ubifs_leb_write(c, wbuf->lnum, buf, wbuf->offs,
+ wbuf->size);
if (err)
goto out;
@@ -683,8 +790,8 @@
n <<= c->max_write_shift;
dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum,
wbuf->offs);
- err = ubi_leb_write(c->ubi, wbuf->lnum, buf + written,
- wbuf->offs, n, wbuf->dtype);
+ err = ubifs_leb_write(c, wbuf->lnum, buf + written,
+ wbuf->offs, n);
if (err)
goto out;
wbuf->offs += n;
@@ -728,9 +835,9 @@
out:
ubifs_err("cannot write %d bytes to LEB %d:%d, error %d",
len, wbuf->lnum, wbuf->offs, err);
- dbg_dump_node(c, buf);
- dbg_dump_stack();
- dbg_dump_leb(c, wbuf->lnum);
+ ubifs_dump_node(c, buf);
+ dump_stack();
+ ubifs_dump_leb(c, wbuf->lnum);
return err;
}
@@ -741,7 +848,6 @@
* @len: node length
* @lnum: logical eraseblock number
* @offs: offset within the logical eraseblock
- * @dtype: node life-time hint (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)
*
* This function automatically fills node magic number, assigns sequence
* number, and calculates node CRC checksum. The length of the @buf buffer has
@@ -750,7 +856,7 @@
* success and a negative error code in case of failure.
*/
int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
- int offs, int dtype)
+ int offs)
{
int err, buf_len = ALIGN(len, c->min_io_size);
@@ -766,13 +872,9 @@
return -EROFS;
ubifs_prepare_node(c, buf, len, 1);
- err = ubi_leb_write(c->ubi, lnum, buf, offs, buf_len, dtype);
- if (err) {
- ubifs_err("cannot write %d bytes to LEB %d:%d, error %d",
- buf_len, lnum, offs, err);
- dbg_dump_node(c, buf);
- dbg_dump_stack();
- }
+ err = ubifs_leb_write(c, lnum, buf, offs, buf_len);
+ if (err)
+ ubifs_dump_node(c, buf);
return err;
}
@@ -824,13 +926,9 @@
if (rlen > 0) {
/* Read everything that goes before write-buffer */
- err = ubi_read(c->ubi, lnum, buf, offs, rlen);
- if (err && err != -EBADMSG) {
- ubifs_err("failed to read node %d from LEB %d:%d, "
- "error %d", type, lnum, offs, err);
- dbg_dump_stack();
+ err = ubifs_leb_read(c, lnum, buf, offs, rlen, 0);
+ if (err && err != -EBADMSG)
return err;
- }
}
if (type != ch->node_type) {
@@ -855,8 +953,8 @@
out:
ubifs_err("bad node at LEB %d:%d", lnum, offs);
- dbg_dump_node(c, buf);
- dbg_dump_stack();
+ ubifs_dump_node(c, buf);
+ dump_stack();
return -EINVAL;
}
@@ -885,12 +983,9 @@
ubifs_assert(!(offs & 7) && offs < c->leb_size);
ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
- err = ubi_read(c->ubi, lnum, buf, offs, len);
- if (err && err != -EBADMSG) {
- ubifs_err("cannot read node %d from LEB %d:%d, error %d",
- type, lnum, offs, err);
+ err = ubifs_leb_read(c, lnum, buf, offs, len, 0);
+ if (err && err != -EBADMSG)
return err;
- }
if (type != ch->node_type) {
ubifs_err("bad node type (%d but expected %d)",
@@ -915,8 +1010,8 @@
out:
ubifs_err("bad node at LEB %d:%d, LEB mapping status %d", lnum, offs,
ubi_is_mapped(c->ubi, lnum));
- dbg_dump_node(c, buf);
- dbg_dump_stack();
+ ubifs_dump_node(c, buf);
+ dump_stack();
return -EINVAL;
}
@@ -954,7 +1049,6 @@
*/
size = c->max_write_size - (c->leb_start % c->max_write_size);
wbuf->avail = wbuf->size = size;
- wbuf->dtype = UBI_UNKNOWN;
wbuf->sync_callback = NULL;
mutex_init(&wbuf->io_mutex);
spin_lock_init(&wbuf->lock);
diff -uN -uNr linux-3.0/fs/ubifs/journal.c linux-3.0.x.ubifs.latest/fs/ubifs/journal.c
--- linux-3.0/fs/ubifs/journal.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/journal.c 2012-06-28 11:26:15.000000000 -0500
@@ -214,7 +214,7 @@
err = ubifs_add_bud_to_log(c, jhead, lnum, offs);
if (err)
goto out_return;
- err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs, wbuf->dtype);
+ err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs);
if (err)
goto out_unlock;
@@ -385,9 +385,9 @@
if (err == -ENOSPC) {
/* This are some budgeting problems, print useful information */
down_write(&c->commit_sem);
- dbg_dump_stack();
- dbg_dump_budg(c, &c->bi);
- dbg_dump_lprops(c);
+ dump_stack();
+ ubifs_dump_budg(c, &c->bi);
+ ubifs_dump_lprops(c);
cmt_retries = dbg_check_lprops(c);
up_write(&c->commit_sem);
}
@@ -697,9 +697,8 @@
int dlen = COMPRESSED_DATA_NODE_BUF_SZ, allocated = 1;
struct ubifs_inode *ui = ubifs_inode(inode);
- dbg_jnl("ino %lu, blk %u, len %d, key %s",
- (unsigned long)key_inum(c, key), key_block(c, key), len,
- DBGKEY(key));
+ dbg_jnlk(key, "ino %lu, blk %u, len %d, key ",
+ (unsigned long)key_inum(c, key), key_block(c, key), len);
ubifs_assert(len <= UBIFS_BLOCK_SIZE);
data = kmalloc(dlen, GFP_NOFS | __GFP_NOWARN);
@@ -1177,7 +1176,7 @@
dn = (void *)trun + UBIFS_TRUN_NODE_SZ;
blk = new_size >> UBIFS_BLOCK_SHIFT;
data_key_init(c, &key, inum, blk);
- dbg_jnl("last block key %s", DBGKEY(&key));
+ dbg_jnlk(&key, "last block key ");
err = ubifs_tnc_lookup(c, &key, dn);
if (err == -ENOENT)
dlen = 0; /* Not found (so it is a hole) */
@@ -1268,7 +1267,6 @@
return err;
}
-#ifdef CONFIG_UBIFS_FS_XATTR
/**
* ubifs_jnl_delete_xattr - delete an extended attribute.
@@ -1463,4 +1461,3 @@
return err;
}
-#endif /* CONFIG_UBIFS_FS_XATTR */
diff -uN -uNr linux-3.0/fs/ubifs/log.c linux-3.0.x.ubifs.latest/fs/ubifs/log.c
--- linux-3.0/fs/ubifs/log.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/log.c 2012-06-28 11:26:15.000000000 -0500
@@ -29,11 +29,7 @@
#include "ubifs.h"
-#ifdef CONFIG_UBIFS_FS_DEBUG
static int dbg_check_bud_bytes(struct ubifs_info *c);
-#else
-#define dbg_check_bud_bytes(c) 0
-#endif
/**
* ubifs_search_bud - search bud LEB.
@@ -262,7 +258,7 @@
* an unclean reboot, because the target LEB might have been
* unmapped, but not yet physically erased.
*/
- err = ubi_leb_map(c->ubi, bud->lnum, UBI_SHORTTERM);
+ err = ubifs_leb_map(c, bud->lnum);
if (err)
goto out_unlock;
}
@@ -270,7 +266,7 @@
dbg_log("write ref LEB %d:%d",
c->lhead_lnum, c->lhead_offs);
err = ubifs_write_node(c, ref, UBIFS_REF_NODE_SZ, c->lhead_lnum,
- c->lhead_offs, UBI_SHORTTERM);
+ c->lhead_offs);
if (err)
goto out_unlock;
@@ -283,8 +279,6 @@
return 0;
out_unlock:
- if (err != -EAGAIN)
- ubifs_ro_mode(c, err);
mutex_unlock(&c->log_mutex);
kfree(ref);
kfree(bud);
@@ -424,7 +418,7 @@
len = ALIGN(len, c->min_io_size);
dbg_log("writing commit start at LEB %d:0, len %d", c->lhead_lnum, len);
- err = ubifs_leb_write(c, c->lhead_lnum, cs, 0, len, UBI_SHORTTERM);
+ err = ubifs_leb_write(c, c->lhead_lnum, cs, 0, len);
if (err)
goto out;
@@ -625,7 +619,7 @@
int sz = ALIGN(*offs, c->min_io_size), err;
ubifs_pad(c, buf + *offs, sz - *offs);
- err = ubifs_leb_change(c, *lnum, buf, sz, UBI_SHORTTERM);
+ err = ubifs_leb_change(c, *lnum, buf, sz);
if (err)
return err;
*lnum = ubifs_next_log_lnum(c, *lnum);
@@ -704,7 +698,7 @@
int sz = ALIGN(offs, c->min_io_size);
ubifs_pad(c, buf + offs, sz - offs);
- err = ubifs_leb_change(c, write_lnum, buf, sz, UBI_SHORTTERM);
+ err = ubifs_leb_change(c, write_lnum, buf, sz);
if (err)
goto out_free;
offs = ALIGN(offs, c->min_io_size);
@@ -736,8 +730,6 @@
return err;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
-
/**
* dbg_check_bud_bytes - make sure bud bytes calculation are all right.
* @c: UBIFS file-system description object
@@ -752,7 +744,7 @@
struct ubifs_bud *bud;
long long bud_bytes = 0;
- if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+ if (!dbg_is_chk_gen(c))
return 0;
spin_lock(&c->buds_lock);
@@ -769,5 +761,3 @@
return err;
}
-
-#endif /* CONFIG_UBIFS_FS_DEBUG */
diff -uN -uNr linux-3.0/fs/ubifs/lprops.c linux-3.0.x.ubifs.latest/fs/ubifs/lprops.c
--- linux-3.0/fs/ubifs/lprops.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/lprops.c 2012-06-28 11:26:15.000000000 -0500
@@ -447,7 +447,7 @@
int new_cat = ubifs_categorize_lprops(c, lprops);
if (old_cat == new_cat) {
- struct ubifs_lpt_heap *heap = &c->lpt_heap[new_cat - 1];
+ struct ubifs_lpt_heap *heap;
/* lprops on a heap now must be moved up or down */
if (new_cat < 1 || new_cat > LPROPS_HEAP_CNT)
@@ -504,7 +504,7 @@
pnode = (struct ubifs_pnode *)container_of(lprops - pos,
struct ubifs_pnode,
lprops[0]);
- return !test_bit(COW_ZNODE, &pnode->flags) &&
+ return !test_bit(COW_CNODE, &pnode->flags) &&
test_bit(DIRTY_CNODE, &pnode->flags);
}
@@ -846,7 +846,9 @@
return lprops;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
+/*
+ * Everything below is related to debugging.
+ */
/**
* dbg_check_cats - check category heaps and lists.
@@ -860,7 +862,7 @@
struct list_head *pos;
int i, cat;
- if (!(ubifs_chk_flags & (UBIFS_CHK_GEN | UBIFS_CHK_LPROPS)))
+ if (!dbg_is_chk_gen(c) && !dbg_is_chk_lprops(c))
return 0;
list_for_each_entry(lprops, &c->empty_list, list) {
@@ -958,7 +960,7 @@
{
int i = 0, j, err = 0;
- if (!(ubifs_chk_flags & (UBIFS_CHK_GEN | UBIFS_CHK_LPROPS)))
+ if (!dbg_is_chk_gen(c) && !dbg_is_chk_lprops(c))
return;
for (i = 0; i < heap->cnt; i++) {
@@ -1001,8 +1003,8 @@
out:
if (err) {
dbg_msg("failed cat %d hpos %d err %d", cat, i, err);
- dbg_dump_stack();
- dbg_dump_heap(c, heap, cat);
+ dump_stack();
+ ubifs_dump_heap(c, heap, cat);
}
}
@@ -1109,8 +1111,8 @@
if (IS_ERR(sleb)) {
ret = PTR_ERR(sleb);
if (ret == -EUCLEAN) {
- dbg_dump_lprops(c);
- dbg_dump_budg(c, &c->bi);
+ ubifs_dump_lprops(c);
+ ubifs_dump_budg(c, &c->bi);
}
goto out;
}
@@ -1237,7 +1239,7 @@
ubifs_err("bad accounting of LEB %d: free %d, dirty %d flags %#x, "
"should be free %d, dirty %d",
lnum, lp->free, lp->dirty, lp->flags, free, dirty);
- dbg_dump_leb(c, lnum);
+ ubifs_dump_leb(c, lnum);
out_destroy:
ubifs_scan_destroy(sleb);
ret = -EINVAL;
@@ -1262,7 +1264,7 @@
int i, err;
struct ubifs_lp_stats lst;
- if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+ if (!dbg_is_chk_lprops(c))
return 0;
/*
@@ -1315,5 +1317,3 @@
out:
return err;
}
-
-#endif /* CONFIG_UBIFS_FS_DEBUG */
diff -uN -uNr linux-3.0/fs/ubifs/lpt.c linux-3.0.x.ubifs.latest/fs/ubifs/lpt.c
--- linux-3.0/fs/ubifs/lpt.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/lpt.c 2012-06-28 11:26:15.000000000 -0500
@@ -701,8 +701,7 @@
alen = ALIGN(len, c->min_io_size);
set_ltab(c, lnum, c->leb_size - alen, alen - len);
memset(p, 0xff, alen - len);
- err = ubi_leb_change(c->ubi, lnum++, buf, alen,
- UBI_SHORTTERM);
+ err = ubifs_leb_change(c, lnum++, buf, alen);
if (err)
goto out;
p = buf;
@@ -732,8 +731,7 @@
set_ltab(c, lnum, c->leb_size - alen,
alen - len);
memset(p, 0xff, alen - len);
- err = ubi_leb_change(c->ubi, lnum++, buf, alen,
- UBI_SHORTTERM);
+ err = ubifs_leb_change(c, lnum++, buf, alen);
if (err)
goto out;
p = buf;
@@ -780,8 +778,7 @@
alen = ALIGN(len, c->min_io_size);
set_ltab(c, lnum, c->leb_size - alen, alen - len);
memset(p, 0xff, alen - len);
- err = ubi_leb_change(c->ubi, lnum++, buf, alen,
- UBI_SHORTTERM);
+ err = ubifs_leb_change(c, lnum++, buf, alen);
if (err)
goto out;
p = buf;
@@ -806,7 +803,7 @@
alen = ALIGN(len, c->min_io_size);
set_ltab(c, lnum, c->leb_size - alen, alen - len);
memset(p, 0xff, alen - len);
- err = ubi_leb_change(c->ubi, lnum++, buf, alen, UBI_SHORTTERM);
+ err = ubifs_leb_change(c, lnum++, buf, alen);
if (err)
goto out;
p = buf;
@@ -826,7 +823,7 @@
/* Write remaining buffer */
memset(p, 0xff, alen - len);
- err = ubi_leb_change(c->ubi, lnum, buf, alen, UBI_SHORTTERM);
+ err = ubifs_leb_change(c, lnum, buf, alen);
if (err)
goto out;
@@ -926,7 +923,7 @@
if (crc != calc_crc) {
ubifs_err("invalid crc in LPT node: crc %hx calc %hx", crc,
calc_crc);
- dbg_dump_stack();
+ dump_stack();
return -EINVAL;
}
return 0;
@@ -949,7 +946,7 @@
if (node_type != type) {
ubifs_err("invalid type (%d) in LPT node type %d", node_type,
type);
- dbg_dump_stack();
+ dump_stack();
return -EINVAL;
}
return 0;
@@ -1222,7 +1219,7 @@
if (c->big_lpt)
nnode->num = calc_nnode_num_from_parent(c, parent, iip);
} else {
- err = ubi_read(c->ubi, lnum, buf, offs, c->nnode_sz);
+ err = ubifs_leb_read(c, lnum, buf, offs, c->nnode_sz, 1);
if (err)
goto out;
err = ubifs_unpack_nnode(c, buf, nnode);
@@ -1247,6 +1244,7 @@
out:
ubifs_err("error %d reading nnode at %d:%d", err, lnum, offs);
+ dump_stack();
kfree(nnode);
return err;
}
@@ -1290,7 +1288,7 @@
lprops->flags = ubifs_categorize_lprops(c, lprops);
}
} else {
- err = ubi_read(c->ubi, lnum, buf, offs, c->pnode_sz);
+ err = ubifs_leb_read(c, lnum, buf, offs, c->pnode_sz, 1);
if (err)
goto out;
err = unpack_pnode(c, buf, pnode);
@@ -1311,7 +1309,8 @@
out:
ubifs_err("error %d reading pnode at %d:%d", err, lnum, offs);
- dbg_dump_pnode(c, pnode, parent, iip);
+ ubifs_dump_pnode(c, pnode, parent, iip);
+ dump_stack();
dbg_msg("calc num: %d", calc_pnode_num_from_parent(c, parent, iip));
kfree(pnode);
return err;
@@ -1331,7 +1330,7 @@
buf = vmalloc(c->ltab_sz);
if (!buf)
return -ENOMEM;
- err = ubi_read(c->ubi, c->ltab_lnum, buf, c->ltab_offs, c->ltab_sz);
+ err = ubifs_leb_read(c, c->ltab_lnum, buf, c->ltab_offs, c->ltab_sz, 1);
if (err)
goto out;
err = unpack_ltab(c, buf);
@@ -1354,7 +1353,8 @@
buf = vmalloc(c->lsave_sz);
if (!buf)
return -ENOMEM;
- err = ubi_read(c->ubi, c->lsave_lnum, buf, c->lsave_offs, c->lsave_sz);
+ err = ubifs_leb_read(c, c->lsave_lnum, buf, c->lsave_offs,
+ c->lsave_sz, 1);
if (err)
goto out;
err = unpack_lsave(c, buf);
@@ -1737,16 +1737,20 @@
if (rd) {
err = lpt_init_rd(c);
if (err)
- return err;
+ goto out_err;
}
if (wr) {
err = lpt_init_wr(c);
if (err)
- return err;
+ goto out_err;
}
return 0;
+
+out_err:
+ ubifs_lpt_free(c, 0);
+ return err;
}
/**
@@ -1814,8 +1818,8 @@
if (c->big_lpt)
nnode->num = calc_nnode_num_from_parent(c, parent, iip);
} else {
- err = ubi_read(c->ubi, branch->lnum, buf, branch->offs,
- c->nnode_sz);
+ err = ubifs_leb_read(c, branch->lnum, buf, branch->offs,
+ c->nnode_sz, 1);
if (err)
return ERR_PTR(err);
err = ubifs_unpack_nnode(c, buf, nnode);
@@ -1883,8 +1887,8 @@
ubifs_assert(branch->lnum >= c->lpt_first &&
branch->lnum <= c->lpt_last);
ubifs_assert(branch->offs >= 0 && branch->offs < c->leb_size);
- err = ubi_read(c->ubi, branch->lnum, buf, branch->offs,
- c->pnode_sz);
+ err = ubifs_leb_read(c, branch->lnum, buf, branch->offs,
+ c->pnode_sz, 1);
if (err)
return ERR_PTR(err);
err = unpack_pnode(c, buf, pnode);
@@ -1983,12 +1987,11 @@
if (path[h].in_tree)
continue;
- nnode = kmalloc(sz, GFP_NOFS);
+ nnode = kmemdup(&path[h].nnode, sz, GFP_NOFS);
if (!nnode) {
err = -ENOMEM;
goto out;
}
- memcpy(nnode, &path[h].nnode, sz);
parent = nnode->parent;
parent->nbranch[nnode->iip].nnode = nnode;
path[h].ptr.nnode = nnode;
@@ -2001,12 +2004,11 @@
const size_t sz = sizeof(struct ubifs_pnode);
struct ubifs_nnode *parent;
- pnode = kmalloc(sz, GFP_NOFS);
+ pnode = kmemdup(&path[h].pnode, sz, GFP_NOFS);
if (!pnode) {
err = -ENOMEM;
goto out;
}
- memcpy(pnode, &path[h].pnode, sz);
parent = pnode->parent;
parent->nbranch[pnode->iip].pnode = pnode;
path[h].ptr.pnode = pnode;
@@ -2079,8 +2081,6 @@
return err;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
-
/**
* dbg_chk_pnode - check a pnode.
* @c: the UBIFS file-system description object
@@ -2095,8 +2095,8 @@
int i;
if (pnode->num != col) {
- dbg_err("pnode num %d expected %d parent num %d iip %d",
- pnode->num, col, pnode->parent->num, pnode->iip);
+ ubifs_err("pnode num %d expected %d parent num %d iip %d",
+ pnode->num, col, pnode->parent->num, pnode->iip);
return -EINVAL;
}
for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
@@ -2110,14 +2110,14 @@
if (lnum >= c->leb_cnt)
continue;
if (lprops->lnum != lnum) {
- dbg_err("bad LEB number %d expected %d",
- lprops->lnum, lnum);
+ ubifs_err("bad LEB number %d expected %d",
+ lprops->lnum, lnum);
return -EINVAL;
}
if (lprops->flags & LPROPS_TAKEN) {
if (cat != LPROPS_UNCAT) {
- dbg_err("LEB %d taken but not uncat %d",
- lprops->lnum, cat);
+ ubifs_err("LEB %d taken but not uncat %d",
+ lprops->lnum, cat);
return -EINVAL;
}
continue;
@@ -2129,8 +2129,8 @@
case LPROPS_FRDI_IDX:
break;
default:
- dbg_err("LEB %d index but cat %d",
- lprops->lnum, cat);
+ ubifs_err("LEB %d index but cat %d",
+ lprops->lnum, cat);
return -EINVAL;
}
} else {
@@ -2142,8 +2142,8 @@
case LPROPS_FREEABLE:
break;
default:
- dbg_err("LEB %d not index but cat %d",
- lprops->lnum, cat);
+ ubifs_err("LEB %d not index but cat %d",
+ lprops->lnum, cat);
return -EINVAL;
}
}
@@ -2183,24 +2183,24 @@
break;
}
if (!found) {
- dbg_err("LEB %d cat %d not found in cat heap/list",
- lprops->lnum, cat);
+ ubifs_err("LEB %d cat %d not found in cat heap/list",
+ lprops->lnum, cat);
return -EINVAL;
}
switch (cat) {
case LPROPS_EMPTY:
if (lprops->free != c->leb_size) {
- dbg_err("LEB %d cat %d free %d dirty %d",
- lprops->lnum, cat, lprops->free,
- lprops->dirty);
+ ubifs_err("LEB %d cat %d free %d dirty %d",
+ lprops->lnum, cat, lprops->free,
+ lprops->dirty);
return -EINVAL;
}
case LPROPS_FREEABLE:
case LPROPS_FRDI_IDX:
if (lprops->free + lprops->dirty != c->leb_size) {
- dbg_err("LEB %d cat %d free %d dirty %d",
- lprops->lnum, cat, lprops->free,
- lprops->dirty);
+ ubifs_err("LEB %d cat %d free %d dirty %d",
+ lprops->lnum, cat, lprops->free,
+ lprops->dirty);
return -EINVAL;
}
}
@@ -2224,7 +2224,7 @@
struct ubifs_cnode *cn;
int num, iip = 0, err;
- if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+ if (!dbg_is_chk_lprops(c))
return 0;
while (cnode) {
@@ -2234,9 +2234,10 @@
/* cnode is a nnode */
num = calc_nnode_num(row, col);
if (cnode->num != num) {
- dbg_err("nnode num %d expected %d "
- "parent num %d iip %d", cnode->num, num,
- (nnode ? nnode->num : 0), cnode->iip);
+ ubifs_err("nnode num %d expected %d "
+ "parent num %d iip %d",
+ cnode->num, num,
+ (nnode ? nnode->num : 0), cnode->iip);
return -EINVAL;
}
nn = (struct ubifs_nnode *)cnode;
@@ -2273,5 +2274,3 @@
}
return 0;
}
-
-#endif /* CONFIG_UBIFS_FS_DEBUG */
diff -uN -uNr linux-3.0/fs/ubifs/lpt_commit.c linux-3.0.x.ubifs.latest/fs/ubifs/lpt_commit.c
--- linux-3.0/fs/ubifs/lpt_commit.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/lpt_commit.c 2012-06-28 11:26:15.000000000 -0500
@@ -27,13 +27,10 @@
#include <linux/crc16.h>
#include <linux/slab.h>
+#include <linux/random.h>
#include "ubifs.h"
-#ifdef CONFIG_UBIFS_FS_DEBUG
static int dbg_populate_lsave(struct ubifs_info *c);
-#else
-#define dbg_populate_lsave(c) 0
-#endif
/**
* first_dirty_cnode - find first dirty cnode.
@@ -116,8 +113,8 @@
return 0;
cnt += 1;
while (1) {
- ubifs_assert(!test_bit(COW_ZNODE, &cnode->flags));
- __set_bit(COW_ZNODE, &cnode->flags);
+ ubifs_assert(!test_bit(COW_CNODE, &cnode->flags));
+ __set_bit(COW_CNODE, &cnode->flags);
cnext = next_dirty_cnode(cnode);
if (!cnext) {
cnode->cnext = c->lpt_cnext;
@@ -323,11 +320,10 @@
return 0;
no_space:
- ubifs_err("LPT out of space");
- dbg_err("LPT out of space at LEB %d:%d needing %d, done_ltab %d, "
- "done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
- dbg_dump_lpt_info(c);
- dbg_dump_lpt_lebs(c);
+ ubifs_err("LPT out of space at LEB %d:%d needing %d, done_ltab %d, "
+ "done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
+ ubifs_dump_lpt_info(c);
+ ubifs_dump_lpt_lebs(c);
dump_stack();
return err;
}
@@ -420,7 +416,7 @@
alen = ALIGN(wlen, c->min_io_size);
memset(buf + offs, 0xff, alen - wlen);
err = ubifs_leb_write(c, lnum, buf + from, from,
- alen, UBI_SHORTTERM);
+ alen);
if (err)
return err;
}
@@ -465,7 +461,7 @@
*/
clear_bit(DIRTY_CNODE, &cnode->flags);
smp_mb__before_clear_bit();
- clear_bit(COW_ZNODE, &cnode->flags);
+ clear_bit(COW_CNODE, &cnode->flags);
smp_mb__after_clear_bit();
offs += len;
dbg_chk_lpt_sz(c, 1, len);
@@ -478,8 +474,7 @@
wlen = offs - from;
alen = ALIGN(wlen, c->min_io_size);
memset(buf + offs, 0xff, alen - wlen);
- err = ubifs_leb_write(c, lnum, buf + from, from, alen,
- UBI_SHORTTERM);
+ err = ubifs_leb_write(c, lnum, buf + from, from, alen);
if (err)
return err;
dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
@@ -505,8 +500,7 @@
wlen = offs - from;
alen = ALIGN(wlen, c->min_io_size);
memset(buf + offs, 0xff, alen - wlen);
- err = ubifs_leb_write(c, lnum, buf + from, from, alen,
- UBI_SHORTTERM);
+ err = ubifs_leb_write(c, lnum, buf + from, from, alen);
if (err)
return err;
dbg_chk_lpt_sz(c, 2, c->leb_size - offs);
@@ -530,7 +524,7 @@
wlen = offs - from;
alen = ALIGN(wlen, c->min_io_size);
memset(buf + offs, 0xff, alen - wlen);
- err = ubifs_leb_write(c, lnum, buf + from, from, alen, UBI_SHORTTERM);
+ err = ubifs_leb_write(c, lnum, buf + from, from, alen);
if (err)
return err;
@@ -551,11 +545,10 @@
return 0;
no_space:
- ubifs_err("LPT out of space mismatch");
- dbg_err("LPT out of space mismatch at LEB %d:%d needing %d, done_ltab "
- "%d, done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
- dbg_dump_lpt_info(c);
- dbg_dump_lpt_lebs(c);
+ ubifs_err("LPT out of space mismatch at LEB %d:%d needing %d, done_ltab "
+ "%d, done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
+ ubifs_dump_lpt_info(c);
+ ubifs_dump_lpt_lebs(c);
dump_stack();
return err;
}
@@ -1160,11 +1153,11 @@
void *buf = c->lpt_buf;
dbg_lp("LEB %d", lnum);
- err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
- if (err) {
- ubifs_err("cannot read LEB %d, error %d", lnum, err);
+
+ err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
+ if (err)
return err;
- }
+
while (1) {
if (!is_a_node(c, buf, len)) {
int pad_len;
@@ -1496,7 +1489,9 @@
kfree(c->lpt_nod_buf);
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
+/*
+ * Everything below is related to debugging.
+ */
/**
* dbg_is_all_ff - determine if a buffer contains only 0xFF bytes.
@@ -1640,7 +1635,7 @@
int ret;
void *buf, *p;
- if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+ if (!dbg_is_chk_lprops(c))
return 0;
buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
@@ -1650,11 +1645,11 @@
}
dbg_lp("LEB %d", lnum);
- err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
- if (err) {
- dbg_msg("ubi_read failed, LEB %d, error %d", lnum, err);
+
+ err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
+ if (err)
goto out;
- }
+
while (1) {
if (!is_a_node(c, p, len)) {
int i, pad_len;
@@ -1711,7 +1706,7 @@
{
int lnum, err, i, cnt;
- if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+ if (!dbg_is_chk_lprops(c))
return 0;
/* Bring the entire tree into memory */
@@ -1734,7 +1729,7 @@
for (lnum = c->lpt_first; lnum <= c->lpt_last; lnum++) {
err = dbg_check_ltab_lnum(c, lnum);
if (err) {
- dbg_err("failed at LEB %d", lnum);
+ ubifs_err("failed at LEB %d", lnum);
return err;
}
}
@@ -1754,7 +1749,7 @@
long long free = 0;
int i;
- if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+ if (!dbg_is_chk_lprops(c))
return 0;
for (i = 0; i < c->lpt_lebs; i++) {
@@ -1766,10 +1761,10 @@
free += c->leb_size;
}
if (free < c->lpt_sz) {
- dbg_err("LPT space error: free %lld lpt_sz %lld",
- free, c->lpt_sz);
- dbg_dump_lpt_info(c);
- dbg_dump_lpt_lebs(c);
+ ubifs_err("LPT space error: free %lld lpt_sz %lld",
+ free, c->lpt_sz);
+ ubifs_dump_lpt_info(c);
+ ubifs_dump_lpt_lebs(c);
dump_stack();
return -EINVAL;
}
@@ -1796,7 +1791,7 @@
long long chk_lpt_sz, lpt_sz;
int err = 0;
- if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+ if (!dbg_is_chk_lprops(c))
return 0;
switch (action) {
@@ -1806,13 +1801,13 @@
d->chk_lpt_lebs = 0;
d->chk_lpt_wastage = 0;
if (c->dirty_pn_cnt > c->pnode_cnt) {
- dbg_err("dirty pnodes %d exceed max %d",
- c->dirty_pn_cnt, c->pnode_cnt);
+ ubifs_err("dirty pnodes %d exceed max %d",
+ c->dirty_pn_cnt, c->pnode_cnt);
err = -EINVAL;
}
if (c->dirty_nn_cnt > c->nnode_cnt) {
- dbg_err("dirty nnodes %d exceed max %d",
- c->dirty_nn_cnt, c->nnode_cnt);
+ ubifs_err("dirty nnodes %d exceed max %d",
+ c->dirty_nn_cnt, c->nnode_cnt);
err = -EINVAL;
}
return err;
@@ -1829,23 +1824,23 @@
chk_lpt_sz *= d->chk_lpt_lebs;
chk_lpt_sz += len - c->nhead_offs;
if (d->chk_lpt_sz != chk_lpt_sz) {
- dbg_err("LPT wrote %lld but space used was %lld",
- d->chk_lpt_sz, chk_lpt_sz);
+ ubifs_err("LPT wrote %lld but space used was %lld",
+ d->chk_lpt_sz, chk_lpt_sz);
err = -EINVAL;
}
if (d->chk_lpt_sz > c->lpt_sz) {
- dbg_err("LPT wrote %lld but lpt_sz is %lld",
- d->chk_lpt_sz, c->lpt_sz);
+ ubifs_err("LPT wrote %lld but lpt_sz is %lld",
+ d->chk_lpt_sz, c->lpt_sz);
err = -EINVAL;
}
if (d->chk_lpt_sz2 && d->chk_lpt_sz != d->chk_lpt_sz2) {
- dbg_err("LPT layout size %lld but wrote %lld",
- d->chk_lpt_sz, d->chk_lpt_sz2);
+ ubifs_err("LPT layout size %lld but wrote %lld",
+ d->chk_lpt_sz, d->chk_lpt_sz2);
err = -EINVAL;
}
if (d->chk_lpt_sz2 && d->new_nhead_offs != len) {
- dbg_err("LPT new nhead offs: expected %d was %d",
- d->new_nhead_offs, len);
+ ubifs_err("LPT new nhead offs: expected %d was %d",
+ d->new_nhead_offs, len);
err = -EINVAL;
}
lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
@@ -1854,13 +1849,13 @@
if (c->big_lpt)
lpt_sz += c->lsave_sz;
if (d->chk_lpt_sz - d->chk_lpt_wastage > lpt_sz) {
- dbg_err("LPT chk_lpt_sz %lld + waste %lld exceeds %lld",
- d->chk_lpt_sz, d->chk_lpt_wastage, lpt_sz);
+ ubifs_err("LPT chk_lpt_sz %lld + waste %lld exceeds %lld",
+ d->chk_lpt_sz, d->chk_lpt_wastage, lpt_sz);
err = -EINVAL;
}
if (err) {
- dbg_dump_lpt_info(c);
- dbg_dump_lpt_lebs(c);
+ ubifs_dump_lpt_info(c);
+ ubifs_dump_lpt_lebs(c);
dump_stack();
}
d->chk_lpt_sz2 = d->chk_lpt_sz;
@@ -1879,7 +1874,7 @@
}
/**
- * dbg_dump_lpt_leb - dump an LPT LEB.
+ * ubifs_dump_lpt_leb - dump an LPT LEB.
* @c: UBIFS file-system description object
* @lnum: LEB number to dump
*
@@ -1901,11 +1896,10 @@
return;
}
- err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
- if (err) {
- ubifs_err("cannot read LEB %d, error %d", lnum, err);
+ err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
+ if (err)
goto out;
- }
+
while (1) {
offs = c->leb_size - len;
if (!is_a_node(c, p, len)) {
@@ -1986,13 +1980,13 @@
}
/**
- * dbg_dump_lpt_lebs - dump LPT lebs.
+ * ubifs_dump_lpt_lebs - dump LPT lebs.
* @c: UBIFS file-system description object
*
* This function dumps all LPT LEBs. The caller has to make sure the LPT is
* locked.
*/
-void dbg_dump_lpt_lebs(const struct ubifs_info *c)
+void ubifs_dump_lpt_lebs(const struct ubifs_info *c)
{
int i;
@@ -2019,7 +2013,7 @@
struct ubifs_lpt_heap *heap;
int i;
- if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+ if (!dbg_is_chk_gen(c))
return 0;
if (random32() & 3)
return 0;
@@ -2046,5 +2040,3 @@
return 1;
}
-
-#endif /* CONFIG_UBIFS_FS_DEBUG */
diff -uN -uNr linux-3.0/fs/ubifs/master.c linux-3.0.x.ubifs.latest/fs/ubifs/master.c
--- linux-3.0/fs/ubifs/master.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/master.c 2012-06-28 11:26:15.000000000 -0500
@@ -241,7 +241,7 @@
out:
ubifs_err("bad master node at offset %d error %d", c->mst_offs, err);
- dbg_dump_node(c, c->mst_node);
+ ubifs_dump_node(c, c->mst_node);
return -EINVAL;
}
@@ -317,7 +317,7 @@
if (c->leb_cnt < old_leb_cnt ||
c->leb_cnt < UBIFS_MIN_LEB_CNT) {
ubifs_err("bad leb_cnt on master node");
- dbg_dump_node(c, c->mst_node);
+ ubifs_dump_node(c, c->mst_node);
return -EINVAL;
}
@@ -379,7 +379,7 @@
c->mst_offs = offs;
c->mst_node->highest_inum = cpu_to_le64(c->highest_inum);
- err = ubifs_write_node(c, c->mst_node, len, lnum, offs, UBI_SHORTTERM);
+ err = ubifs_write_node(c, c->mst_node, len, lnum, offs);
if (err)
return err;
@@ -390,7 +390,7 @@
if (err)
return err;
}
- err = ubifs_write_node(c, c->mst_node, len, lnum, offs, UBI_SHORTTERM);
+ err = ubifs_write_node(c, c->mst_node, len, lnum, offs);
return err;
}
diff -uN -uNr linux-3.0/fs/ubifs/misc.h linux-3.0.x.ubifs.latest/fs/ubifs/misc.h
--- linux-3.0/fs/ubifs/misc.h 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/misc.h 2012-06-28 11:26:15.000000000 -0500
@@ -39,6 +39,29 @@
}
/**
+ * ubifs_zn_obsolete - check if znode is obsolete.
+ * @znode: znode to check
+ *
+ * This helper function returns %1 if @znode is obsolete and %0 otherwise.
+ */
+static inline int ubifs_zn_obsolete(const struct ubifs_znode *znode)
+{
+ return !!test_bit(OBSOLETE_ZNODE, &znode->flags);
+}
+
+/**
+ * ubifs_zn_cow - check if znode has to be copied on write.
+ * @znode: znode to check
+ *
+ * This helper function returns %1 if @znode is has COW flag set and %0
+ * otherwise.
+ */
+static inline int ubifs_zn_cow(const struct ubifs_znode *znode)
+{
+ return !!test_bit(COW_ZNODE, &znode->flags);
+}
+
+/**
* ubifs_wake_up_bgt - wake up background thread.
* @c: UBIFS file-system description object
*/
@@ -122,86 +145,6 @@
}
/**
- * ubifs_leb_unmap - unmap an LEB.
- * @c: UBIFS file-system description object
- * @lnum: LEB number to unmap
- *
- * This function returns %0 on success and a negative error code on failure.
- */
-static inline int ubifs_leb_unmap(const struct ubifs_info *c, int lnum)
-{
- int err;
-
- ubifs_assert(!c->ro_media && !c->ro_mount);
- if (c->ro_error)
- return -EROFS;
- err = ubi_leb_unmap(c->ubi, lnum);
- if (err) {
- ubifs_err("unmap LEB %d failed, error %d", lnum, err);
- return err;
- }
-
- return 0;
-}
-
-/**
- * ubifs_leb_write - write to a LEB.
- * @c: UBIFS file-system description object
- * @lnum: LEB number to write
- * @buf: buffer to write from
- * @offs: offset within LEB to write to
- * @len: length to write
- * @dtype: data type
- *
- * This function returns %0 on success and a negative error code on failure.
- */
-static inline int ubifs_leb_write(const struct ubifs_info *c, int lnum,
- const void *buf, int offs, int len, int dtype)
-{
- int err;
-
- ubifs_assert(!c->ro_media && !c->ro_mount);
- if (c->ro_error)
- return -EROFS;
- err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
- if (err) {
- ubifs_err("writing %d bytes at %d:%d, error %d",
- len, lnum, offs, err);
- return err;
- }
-
- return 0;
-}
-
-/**
- * ubifs_leb_change - atomic LEB change.
- * @c: UBIFS file-system description object
- * @lnum: LEB number to write
- * @buf: buffer to write from
- * @len: length to write
- * @dtype: data type
- *
- * This function returns %0 on success and a negative error code on failure.
- */
-static inline int ubifs_leb_change(const struct ubifs_info *c, int lnum,
- const void *buf, int len, int dtype)
-{
- int err;
-
- ubifs_assert(!c->ro_media && !c->ro_mount);
- if (c->ro_error)
- return -EROFS;
- err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
- if (err) {
- ubifs_err("changing %d bytes in LEB %d, error %d",
- len, lnum, err);
- return err;
- }
-
- return 0;
-}
-
-/**
* ubifs_encode_dev - encode device node IDs.
* @dev: UBIFS device node information
* @rdev: device IDs to encode
diff -uN -uNr linux-3.0/fs/ubifs/orphan.c linux-3.0.x.ubifs.latest/fs/ubifs/orphan.c
--- linux-3.0/fs/ubifs/orphan.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/orphan.c 2012-06-28 11:26:15.000000000 -0500
@@ -52,11 +52,7 @@
* than the maximum number of orphans allowed.
*/
-#ifdef CONFIG_UBIFS_FS_DEBUG
static int dbg_check_orphans(struct ubifs_info *c);
-#else
-#define dbg_check_orphans(c) 0
-#endif
/**
* ubifs_add_orphan - add an orphan.
@@ -92,7 +88,7 @@
else if (inum > o->inum)
p = &(*p)->rb_right;
else {
- dbg_err("orphaned twice");
+ ubifs_err("orphaned twice");
spin_unlock(&c->orphan_lock);
kfree(orphan);
return 0;
@@ -158,8 +154,8 @@
}
}
spin_unlock(&c->orphan_lock);
- dbg_err("missing orphan ino %lu", (unsigned long)inum);
- dbg_dump_stack();
+ ubifs_err("missing orphan ino %lu", (unsigned long)inum);
+ dump_stack();
}
/**
@@ -248,8 +244,7 @@
ubifs_assert(c->ohead_offs == 0);
ubifs_prepare_node(c, c->orph_buf, len, 1);
len = ALIGN(len, c->min_io_size);
- err = ubifs_leb_change(c, c->ohead_lnum, c->orph_buf, len,
- UBI_SHORTTERM);
+ err = ubifs_leb_change(c, c->ohead_lnum, c->orph_buf, len);
} else {
if (c->ohead_offs == 0) {
/* Ensure LEB has been unmapped */
@@ -258,7 +253,7 @@
return err;
}
err = ubifs_write_node(c, c->orph_buf, len, c->ohead_lnum,
- c->ohead_offs, UBI_SHORTTERM);
+ c->ohead_offs);
}
return err;
}
@@ -569,7 +564,7 @@
if (snod->type != UBIFS_ORPH_NODE) {
ubifs_err("invalid node type %d in orphan area at "
"%d:%d", snod->type, sleb->lnum, snod->offs);
- dbg_dump_node(c, snod->node);
+ ubifs_dump_node(c, snod->node);
return -EINVAL;
}
@@ -597,7 +592,7 @@
ubifs_err("out of order commit number %llu in "
"orphan node at %d:%d",
cmt_no, sleb->lnum, snod->offs);
- dbg_dump_node(c, snod->node);
+ ubifs_dump_node(c, snod->node);
return -EINVAL;
}
dbg_rcvry("out of date LEB %d", sleb->lnum);
@@ -725,7 +720,9 @@
return err;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
+/*
+ * Everything below is related to debugging.
+ */
struct check_orphan {
struct rb_node rb;
@@ -929,7 +926,7 @@
struct check_info ci;
int err;
- if (!(ubifs_chk_flags & UBIFS_CHK_ORPH))
+ if (!dbg_is_chk_orph(c))
return 0;
ci.last_ino = 0;
@@ -968,5 +965,3 @@
kfree(ci.node);
return err;
}
-
-#endif /* CONFIG_UBIFS_FS_DEBUG */
diff -uN -uNr linux-3.0/fs/ubifs/recovery.c linux-3.0.x.ubifs.latest/fs/ubifs/recovery.c
--- linux-3.0/fs/ubifs/recovery.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/recovery.c 2012-06-28 11:26:15.000000000 -0500
@@ -117,7 +117,7 @@
if (!sbuf)
return -ENOMEM;
- err = ubi_read(c->ubi, lnum, sbuf, 0, c->leb_size);
+ err = ubifs_leb_read(c, lnum, sbuf, 0, c->leb_size, 0);
if (err && err != -EBADMSG)
goto out_free;
@@ -213,10 +213,10 @@
mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY);
ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1);
- err = ubi_leb_change(c->ubi, lnum, mst, sz, UBI_SHORTTERM);
+ err = ubifs_leb_change(c, lnum, mst, sz);
if (err)
goto out;
- err = ubi_leb_change(c->ubi, lnum + 1, mst, sz, UBI_SHORTTERM);
+ err = ubifs_leb_change(c, lnum + 1, mst, sz);
if (err)
goto out;
out:
@@ -274,7 +274,8 @@
if (cor1)
goto out_err;
mst = mst1;
- } else if (offs1 == 0 && offs2 + sz >= c->leb_size) {
+ } else if (offs1 == 0 &&
+ c->leb_size - offs2 - sz < sz) {
/* 1st LEB was unmapped and written, 2nd not */
if (cor1)
goto out_err;
@@ -361,12 +362,12 @@
out_free:
ubifs_err("failed to recover master node");
if (mst1) {
- dbg_err("dumping first master node");
- dbg_dump_node(c, mst1);
+ ubifs_err("dumping first master node");
+ ubifs_dump_node(c, mst1);
}
if (mst2) {
- dbg_err("dumping second master node");
- dbg_dump_node(c, mst2);
+ ubifs_err("dumping second master node");
+ ubifs_dump_node(c, mst2);
}
vfree(buf2);
vfree(buf1);
@@ -539,8 +540,8 @@
int len = ALIGN(endpt, c->min_io_size);
if (start) {
- err = ubi_read(c->ubi, lnum, sleb->buf, 0,
- start);
+ err = ubifs_leb_read(c, lnum, sleb->buf, 0,
+ start, 1);
if (err)
return err;
}
@@ -554,8 +555,7 @@
ubifs_pad(c, buf, pad_len);
}
}
- err = ubi_leb_change(c->ubi, lnum, sleb->buf, len,
- UBI_UNKNOWN);
+ err = ubifs_leb_change(c, lnum, sleb->buf, len);
if (err)
return err;
}
@@ -678,10 +678,11 @@
ret == SCANNED_GARBAGE ||
ret == SCANNED_A_BAD_PAD_NODE ||
ret == SCANNED_A_CORRUPT_NODE) {
- dbg_rcvry("found corruption - %d", ret);
+ dbg_rcvry("found corruption (%d) at %d:%d",
+ ret, lnum, offs);
break;
} else {
- dbg_err("unexpected return value %d", ret);
+ ubifs_err("unexpected return value %d", ret);
err = -EINVAL;
goto error;
}
@@ -787,7 +788,7 @@
corrupted_rescan:
/* Re-scan the corrupted data with verbose messages */
- dbg_err("corruptio %d", ret);
+ ubifs_err("corruptio %d", ret);
ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
corrupted:
ubifs_scanned_corruption(c, lnum, offs, buf);
@@ -819,22 +820,23 @@
return -ENOMEM;
if (c->leb_size - offs < UBIFS_CS_NODE_SZ)
goto out_err;
- err = ubi_read(c->ubi, lnum, (void *)cs_node, offs, UBIFS_CS_NODE_SZ);
+ err = ubifs_leb_read(c, lnum, (void *)cs_node, offs,
+ UBIFS_CS_NODE_SZ, 0);
if (err && err != -EBADMSG)
goto out_free;
ret = ubifs_scan_a_node(c, cs_node, UBIFS_CS_NODE_SZ, lnum, offs, 0);
if (ret != SCANNED_A_NODE) {
- dbg_err("Not a valid node");
+ ubifs_err("Not a valid node");
goto out_err;
}
if (cs_node->ch.node_type != UBIFS_CS_NODE) {
- dbg_err("Node a CS node, type is %d", cs_node->ch.node_type);
+ ubifs_err("Node a CS node, type is %d", cs_node->ch.node_type);
goto out_err;
}
if (le64_to_cpu(cs_node->cmt_no) != c->cmt_no) {
- dbg_err("CS node cmt_no %llu != current cmt_no %llu",
- (unsigned long long)le64_to_cpu(cs_node->cmt_no),
- c->cmt_no);
+ ubifs_err("CS node cmt_no %llu != current cmt_no %llu",
+ (unsigned long long)le64_to_cpu(cs_node->cmt_no),
+ c->cmt_no);
goto out_err;
}
*cs_sqnum = le64_to_cpu(cs_node->ch.sqnum);
@@ -919,8 +921,7 @@
*
* This function returns %0 on success and a negative error code on failure.
*/
-static int recover_head(const struct ubifs_info *c, int lnum, int offs,
- void *sbuf)
+static int recover_head(struct ubifs_info *c, int lnum, int offs, void *sbuf)
{
int len = c->max_write_size, err;
@@ -931,15 +932,15 @@
return 0;
/* Read at the head location and check it is empty flash */
- err = ubi_read(c->ubi, lnum, sbuf, offs, len);
+ err = ubifs_leb_read(c, lnum, sbuf, offs, len, 1);
if (err || !is_empty(sbuf, len)) {
dbg_rcvry("cleaning head at %d:%d", lnum, offs);
if (offs == 0)
return ubifs_leb_unmap(c, lnum);
- err = ubi_read(c->ubi, lnum, sbuf, 0, offs);
+ err = ubifs_leb_read(c, lnum, sbuf, 0, offs, 1);
if (err)
return err;
- return ubi_leb_change(c->ubi, lnum, sbuf, offs, UBI_UNKNOWN);
+ return ubifs_leb_change(c, lnum, sbuf, offs);
}
return 0;
@@ -962,7 +963,7 @@
*
* This function returns %0 on success and a negative error code on failure.
*/
-int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf)
+int ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf)
{
int err;
@@ -982,7 +983,7 @@
}
/**
- * clean_an_unclean_leb - read and write a LEB to remove corruption.
+ * clean_an_unclean_leb - read and write a LEB to remove corruption.
* @c: UBIFS file-system description object
* @ucleb: unclean LEB information
* @sbuf: LEB-sized buffer to use
@@ -993,7 +994,7 @@
*
* This function returns %0 on success and a negative error code on failure.
*/
-static int clean_an_unclean_leb(const struct ubifs_info *c,
+static int clean_an_unclean_leb(struct ubifs_info *c,
struct ubifs_unclean_leb *ucleb, void *sbuf)
{
int err, lnum = ucleb->lnum, offs = 0, len = ucleb->endpt, quiet = 1;
@@ -1009,7 +1010,7 @@
return 0;
}
- err = ubi_read(c->ubi, lnum, buf, offs, len);
+ err = ubifs_leb_read(c, lnum, buf, offs, len, 0);
if (err && err != -EBADMSG)
return err;
@@ -1069,7 +1070,7 @@
}
/* Write back the LEB atomically */
- err = ubi_leb_change(c->ubi, lnum, sbuf, len, UBI_UNKNOWN);
+ err = ubifs_leb_change(c, lnum, sbuf, len);
if (err)
return err;
@@ -1089,7 +1090,7 @@
*
* This function returns %0 on success and a negative error code on failure.
*/
-int ubifs_clean_lebs(const struct ubifs_info *c, void *sbuf)
+int ubifs_clean_lebs(struct ubifs_info *c, void *sbuf)
{
dbg_rcvry("recovery");
while (!list_empty(&c->unclean_leb_list)) {
@@ -1136,9 +1137,9 @@
*/
lnum = ubifs_find_free_leb_for_idx(c);
if (lnum < 0) {
- dbg_err("could not find an empty LEB");
- dbg_dump_lprops(c);
- dbg_dump_budg(c, &c->bi);
+ ubifs_err("could not find an empty LEB");
+ ubifs_dump_lprops(c);
+ ubifs_dump_budg(c, &c->bi);
return lnum;
}
@@ -1216,7 +1217,7 @@
}
mutex_unlock(&wbuf->io_mutex);
if (err < 0) {
- dbg_err("GC failed, error %d", err);
+ ubifs_err("GC failed, error %d", err);
if (err == -EAGAIN)
err = -EINVAL;
return err;
@@ -1454,7 +1455,7 @@
if (i_size >= e->d_size)
return 0;
/* Read the LEB */
- err = ubi_read(c->ubi, lnum, c->sbuf, 0, c->leb_size);
+ err = ubifs_leb_read(c, lnum, c->sbuf, 0, c->leb_size, 1);
if (err)
goto out;
/* Change the size field and recalculate the CRC */
@@ -1470,7 +1471,7 @@
len -= 1;
len = ALIGN(len + 1, c->min_io_size);
/* Atomically write the fixed LEB back again */
- err = ubi_leb_change(c->ubi, lnum, c->sbuf, len, UBI_UNKNOWN);
+ err = ubifs_leb_change(c, lnum, c->sbuf, len);
if (err)
goto out;
dbg_rcvry("inode %lu at %d:%d size %lld -> %lld",
diff -uN -uNr linux-3.0/fs/ubifs/replay.c linux-3.0.x.ubifs.latest/fs/ubifs/replay.c
--- linux-3.0/fs/ubifs/replay.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/replay.c 2012-06-28 11:26:15.000000000 -0500
@@ -154,8 +154,7 @@
/* Make sure the journal head points to the latest bud */
err = ubifs_wbuf_seek_nolock(&c->jheads[b->bud->jhead].wbuf,
- b->bud->lnum, c->leb_size - b->free,
- UBI_SHORTTERM);
+ b->bud->lnum, c->leb_size - b->free);
out:
ubifs_release_lprops(c);
@@ -221,8 +220,8 @@
{
int err;
- dbg_mnt("LEB %d:%d len %d deletion %d sqnum %llu %s", r->lnum,
- r->offs, r->len, r->deletion, r->sqnum, DBGKEY(&r->key));
+ dbg_mntk(&r->key, "LEB %d:%d len %d deletion %d sqnum %llu key ",
+ r->lnum, r->offs, r->len, r->deletion, r->sqnum);
/* Set c->replay_sqnum to help deal with dangling branches. */
c->replay_sqnum = r->sqnum;
@@ -361,7 +360,7 @@
{
struct replay_entry *r;
- dbg_mnt("add LEB %d:%d, key %s", lnum, offs, DBGKEY(key));
+ dbg_mntk(key, "add LEB %d:%d, key ", lnum, offs);
if (key_inum(c, key) >= c->highest_inum)
c->highest_inum = key_inum(c, key);
@@ -409,7 +408,7 @@
struct replay_entry *r;
char *nbuf;
- dbg_mnt("add LEB %d:%d, key %s", lnum, offs, DBGKEY(key));
+ dbg_mntk(key, "add LEB %d:%d, key ", lnum, offs);
if (key_inum(c, key) >= c->highest_inum)
c->highest_inum = key_inum(c, key);
@@ -523,8 +522,7 @@
if (!list_is_last(&next->list, &jh->buds_list))
return 0;
- err = ubi_read(c->ubi, next->lnum, (char *)&data,
- next->start, 4);
+ err = ubifs_leb_read(c, next->lnum, (char *)&data, next->start, 4, 1);
if (err)
return 0;
@@ -687,7 +685,7 @@
out_dump:
ubifs_err("bad node is at LEB %d:%d", lnum, snod->offs);
- dbg_dump_node(c, snod->node);
+ ubifs_dump_node(c, snod->node);
ubifs_scan_destroy(sleb);
return -EINVAL;
}
@@ -862,16 +860,16 @@
* numbers.
*/
if (snod->type != UBIFS_CS_NODE) {
- dbg_err("first log node at LEB %d:%d is not CS node",
- lnum, offs);
+ ubifs_err("first log node at LEB %d:%d is not CS node",
+ lnum, offs);
goto out_dump;
}
if (le64_to_cpu(node->cmt_no) != c->cmt_no) {
- dbg_err("first CS node at LEB %d:%d has wrong "
- "commit number %llu expected %llu",
- lnum, offs,
- (unsigned long long)le64_to_cpu(node->cmt_no),
- c->cmt_no);
+ ubifs_err("first CS node at LEB %d:%d has wrong "
+ "commit number %llu expected %llu",
+ lnum, offs,
+ (unsigned long long)le64_to_cpu(node->cmt_no),
+ c->cmt_no);
goto out_dump;
}
@@ -893,7 +891,7 @@
/* Make sure the first node sits at offset zero of the LEB */
if (snod->offs != 0) {
- dbg_err("first node is not at zero offset");
+ ubifs_err("first node is not at zero offset");
goto out_dump;
}
@@ -906,8 +904,8 @@
}
if (snod->sqnum < c->cs_sqnum) {
- dbg_err("bad sqnum %llu, commit sqnum %llu",
- snod->sqnum, c->cs_sqnum);
+ ubifs_err("bad sqnum %llu, commit sqnum %llu",
+ snod->sqnum, c->cs_sqnum);
goto out_dump;
}
@@ -959,7 +957,7 @@
out_dump:
ubifs_err("log error detected while replaying the log at LEB %d:%d",
lnum, offs + snod->offs);
- dbg_dump_node(c, snod->node);
+ ubifs_dump_node(c, snod->node);
ubifs_scan_destroy(sleb);
return -EINVAL;
}
diff -uN -uNr linux-3.0/fs/ubifs/sb.c linux-3.0.x.ubifs.latest/fs/ubifs/sb.c
--- linux-3.0/fs/ubifs/sb.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/sb.c 2012-06-28 11:26:15.000000000 -0500
@@ -130,7 +130,6 @@
* orphan node.
*/
orph_lebs = UBIFS_MIN_ORPH_LEBS;
-#ifdef CONFIG_UBIFS_FS_DEBUG
if (c->leb_cnt - min_leb_cnt > 1)
/*
* For debugging purposes it is better to have at least 2
@@ -138,7 +137,6 @@
* consolidations and would be stressed more.
*/
orph_lebs += 1;
-#endif
main_lebs = c->leb_cnt - UBIFS_SB_LEBS - UBIFS_MST_LEBS - log_lebs;
main_lebs -= orph_lebs;
@@ -196,7 +194,7 @@
sup->rp_size = cpu_to_le64(tmp64);
sup->ro_compat_version = cpu_to_le32(UBIFS_RO_COMPAT_VERSION);
- err = ubifs_write_node(c, sup, UBIFS_SB_NODE_SZ, 0, 0, UBI_LONGTERM);
+ err = ubifs_write_node(c, sup, UBIFS_SB_NODE_SZ, 0, 0);
kfree(sup);
if (err)
return err;
@@ -247,19 +245,18 @@
mst->total_dirty = cpu_to_le64(tmp64);
/* The indexing LEB does not contribute to dark space */
- tmp64 = (c->main_lebs - 1) * c->dark_wm;
+ tmp64 = ((long long)(c->main_lebs - 1) * c->dark_wm);
mst->total_dark = cpu_to_le64(tmp64);
mst->total_used = cpu_to_le64(UBIFS_INO_NODE_SZ);
- err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM, 0,
- UBI_UNKNOWN);
+ err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM, 0);
if (err) {
kfree(mst);
return err;
}
- err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM + 1, 0,
- UBI_UNKNOWN);
+ err = ubifs_write_node(c, mst, UBIFS_MST_NODE_SZ, UBIFS_MST_LNUM + 1,
+ 0);
kfree(mst);
if (err)
return err;
@@ -282,8 +279,7 @@
key_write_idx(c, &key, &br->key);
br->lnum = cpu_to_le32(main_first + DEFAULT_DATA_LEB);
br->len = cpu_to_le32(UBIFS_INO_NODE_SZ);
- err = ubifs_write_node(c, idx, tmp, main_first + DEFAULT_IDX_LEB, 0,
- UBI_UNKNOWN);
+ err = ubifs_write_node(c, idx, tmp, main_first + DEFAULT_IDX_LEB, 0);
kfree(idx);
if (err)
return err;
@@ -315,8 +311,7 @@
ino->flags = cpu_to_le32(UBIFS_COMPR_FL);
err = ubifs_write_node(c, ino, UBIFS_INO_NODE_SZ,
- main_first + DEFAULT_DATA_LEB, 0,
- UBI_UNKNOWN);
+ main_first + DEFAULT_DATA_LEB, 0);
kfree(ino);
if (err)
return err;
@@ -335,8 +330,7 @@
return -ENOMEM;
cs->ch.node_type = UBIFS_CS_NODE;
- err = ubifs_write_node(c, cs, UBIFS_CS_NODE_SZ, UBIFS_LOG_LNUM,
- 0, UBI_UNKNOWN);
+ err = ubifs_write_node(c, cs, UBIFS_CS_NODE_SZ, UBIFS_LOG_LNUM, 0);
kfree(cs);
ubifs_msg("default file-system created");
@@ -410,13 +404,23 @@
}
if (c->main_lebs < UBIFS_MIN_MAIN_LEBS) {
- err = 7;
+ ubifs_err("too few main LEBs count %d, must be at least %d",
+ c->main_lebs, UBIFS_MIN_MAIN_LEBS);
goto failed;
}
- if (c->max_bud_bytes < (long long)c->leb_size * UBIFS_MIN_BUD_LEBS ||
- c->max_bud_bytes > (long long)c->leb_size * c->main_lebs) {
- err = 8;
+ max_bytes = (long long)c->leb_size * UBIFS_MIN_BUD_LEBS;
+ if (c->max_bud_bytes < max_bytes) {
+ ubifs_err("too small journal (%lld bytes), must be at least "
+ "%lld bytes", c->max_bud_bytes, max_bytes);
+ goto failed;
+ }
+
+ max_bytes = (long long)c->leb_size * c->main_lebs;
+ if (c->max_bud_bytes > max_bytes) {
+ ubifs_err("too large journal size (%lld bytes), only %lld bytes"
+ "available in the main area",
+ c->max_bud_bytes, max_bytes);
goto failed;
}
@@ -450,7 +454,6 @@
goto failed;
}
- max_bytes = c->main_lebs * (long long)c->leb_size;
if (c->rp_size < 0 || max_bytes < c->rp_size) {
err = 14;
goto failed;
@@ -466,7 +469,7 @@
failed:
ubifs_err("bad superblock, error %d", err);
- dbg_dump_node(c, sup);
+ ubifs_dump_node(c, sup);
return -EINVAL;
}
@@ -509,7 +512,7 @@
int len = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size);
ubifs_prepare_node(c, sup, UBIFS_SB_NODE_SZ, 1);
- return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len, UBI_LONGTERM);
+ return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len);
}
/**
@@ -674,15 +677,15 @@
if (len == 0) {
dbg_mnt("unmap empty LEB %d", lnum);
- return ubi_leb_unmap(c->ubi, lnum);
+ return ubifs_leb_unmap(c, lnum);
}
dbg_mnt("fixup LEB %d, data len %d", lnum, len);
- err = ubi_read(c->ubi, lnum, c->sbuf, 0, len);
+ err = ubifs_leb_read(c, lnum, c->sbuf, 0, len, 1);
if (err)
return err;
- return ubi_leb_change(c->ubi, lnum, c->sbuf, len, UBI_UNKNOWN);
+ return ubifs_leb_change(c, lnum, c->sbuf, len);
}
/**
diff -uN -uNr linux-3.0/fs/ubifs/scan.c linux-3.0.x.ubifs.latest/fs/ubifs/scan.c
--- linux-3.0/fs/ubifs/scan.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/scan.c 2012-06-28 11:26:15.000000000 -0500
@@ -101,7 +101,7 @@
if (!quiet) {
ubifs_err("bad pad node at LEB %d:%d",
lnum, offs);
- dbg_dump_node(c, pad);
+ ubifs_dump_node(c, pad);
}
return SCANNED_A_BAD_PAD_NODE;
}
@@ -109,8 +109,8 @@
/* Make the node pads to 8-byte boundary */
if ((node_len + pad_len) & 7) {
if (!quiet)
- dbg_err("bad padding length %d - %d",
- offs, offs + node_len + pad_len);
+ ubifs_err("bad padding length %d - %d",
+ offs, offs + node_len + pad_len);
return SCANNED_A_BAD_PAD_NODE;
}
@@ -148,7 +148,7 @@
INIT_LIST_HEAD(&sleb->nodes);
sleb->buf = sbuf;
- err = ubi_read(c->ubi, lnum, sbuf + offs, offs, c->leb_size - offs);
+ err = ubifs_leb_read(c, lnum, sbuf + offs, offs, c->leb_size - offs, 0);
if (err && err != -EBADMSG) {
ubifs_err("cannot read %d bytes from LEB %d:%d,"
" error %d", c->leb_size - offs, lnum, offs, err);
@@ -240,12 +240,12 @@
int len;
ubifs_err("corruption at LEB %d:%d", lnum, offs);
- if (dbg_failure_mode)
+ if (dbg_is_tst_rcvry(c))
return;
len = c->leb_size - offs;
if (len > 8192)
len = 8192;
- dbg_err("first %d bytes from LEB %d:%d", len, lnum, offs);
+ ubifs_err("first %d bytes from LEB %d:%d", len, lnum, offs);
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1);
}
@@ -300,16 +300,16 @@
switch (ret) {
case SCANNED_GARBAGE:
- dbg_err("garbage");
+ ubifs_err("garbage");
goto corrupted;
case SCANNED_A_NODE:
break;
case SCANNED_A_CORRUPT_NODE:
case SCANNED_A_BAD_PAD_NODE:
- dbg_err("bad node");
+ ubifs_err("bad node");
goto corrupted;
default:
- dbg_err("unknown");
+ ubifs_err("unknown");
err = -EINVAL;
goto error;
}
diff -uN -uNr linux-3.0/fs/ubifs/super.c linux-3.0.x.ubifs.latest/fs/ubifs/super.c
--- linux-3.0/fs/ubifs/super.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/super.c 2012-06-28 11:26:15.000000000 -0500
@@ -85,7 +85,7 @@
if (ui->data_len < 0 || ui->data_len > UBIFS_MAX_INO_DATA)
return 4;
- if (ui->xattr && (inode->i_mode & S_IFMT) != S_IFREG)
+ if (ui->xattr && !S_ISREG(inode->i_mode))
return 5;
if (!ubifs_compr_present(ui->compr_type)) {
@@ -94,7 +94,7 @@
ubifs_compr_name(ui->compr_type));
}
- err = dbg_check_dir_size(c, inode);
+ err = dbg_check_dir(c, inode);
return err;
}
@@ -246,8 +246,8 @@
out_invalid:
ubifs_err("inode %lu validation failed, error %d", inode->i_ino, err);
- dbg_dump_node(c, ino);
- dbg_dump_inode(c, inode);
+ ubifs_dump_node(c, ino);
+ ubifs_dump_inode(c, inode);
err = -EINVAL;
out_ino:
kfree(ino);
@@ -669,8 +669,8 @@
tmp = UBIFS_CS_NODE_SZ + UBIFS_REF_NODE_SZ * c->jhead_cnt;
tmp = ALIGN(tmp, c->min_io_size);
if (tmp > c->leb_size) {
- dbg_err("too small LEB size %d, at least %d needed",
- c->leb_size, tmp);
+ ubifs_err("too small LEB size %d, at least %d needed",
+ c->leb_size, tmp);
return -EINVAL;
}
@@ -684,8 +684,8 @@
tmp /= c->leb_size;
tmp += 1;
if (c->log_lebs < tmp) {
- dbg_err("too small log %d LEBs, required min. %d LEBs",
- c->log_lebs, tmp);
+ ubifs_err("too small log %d LEBs, required min. %d LEBs",
+ c->log_lebs, tmp);
return -EINVAL;
}
@@ -814,13 +814,10 @@
c->jheads[i].grouped = 1;
}
- c->jheads[BASEHD].wbuf.dtype = UBI_SHORTTERM;
/*
- * Garbage Collector head likely contains long-term data and
- * does not need to be synchronized by timer. Also GC head nodes are
- * not grouped.
+ * Garbage Collector head does not need to be synchronized by timer.
+ * Also GC head nodes are not grouped.
*/
- c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM;
c->jheads[GCHD].wbuf.no_timer = 1;
c->jheads[GCHD].grouped = 0;
@@ -864,7 +861,7 @@
orph = list_entry(c->orph_list.next, struct ubifs_orphan, list);
list_del(&orph->list);
kfree(orph);
- dbg_err("orphan list not empty at unmount");
+ ubifs_err("orphan list not empty at unmount");
}
vfree(c->orph_buf);
@@ -914,7 +911,7 @@
c->empty = 1;
for (lnum = 0; lnum < c->leb_cnt; lnum++) {
- err = ubi_is_mapped(c->ubi, lnum);
+ err = ubifs_is_mapped(c, lnum);
if (unlikely(err < 0))
return err;
if (err == 1) {
@@ -1148,8 +1145,8 @@
ubifs_assert(c->dark_wm > 0);
if (c->lst.total_free + c->lst.total_dirty < c->dark_wm) {
ubifs_err("insufficient free space to mount in R/W mode");
- dbg_dump_budg(c, &c->bi);
- dbg_dump_lprops(c);
+ ubifs_dump_budg(c, &c->bi);
+ ubifs_dump_lprops(c);
return -ENOSPC;
}
return 0;
@@ -1302,7 +1299,7 @@
if (!c->ro_mount && c->space_fixup) {
err = ubifs_fixup_free_space(c);
if (err)
- goto out_master;
+ goto out_lpt;
}
if (!c->ro_mount) {
@@ -2129,8 +2126,8 @@
*/
ubi = open_ubi(name, UBI_READONLY);
if (IS_ERR(ubi)) {
- dbg_err("cannot open \"%s\", error %d",
- name, (int)PTR_ERR(ubi));
+ ubifs_err("cannot open \"%s\", error %d",
+ name, (int)PTR_ERR(ubi));
return ERR_CAST(ubi);
}
diff -uN -uNr linux-3.0/fs/ubifs/tnc.c linux-3.0.x.ubifs.latest/fs/ubifs/tnc.c
--- linux-3.0/fs/ubifs/tnc.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/tnc.c 2012-06-28 11:26:15.000000000 -0500
@@ -223,7 +223,7 @@
__set_bit(DIRTY_ZNODE, &zn->flags);
__clear_bit(COW_ZNODE, &zn->flags);
- ubifs_assert(!test_bit(OBSOLETE_ZNODE, &znode->flags));
+ ubifs_assert(!ubifs_zn_obsolete(znode));
__set_bit(OBSOLETE_ZNODE, &znode->flags);
if (znode->level != 0) {
@@ -271,7 +271,7 @@
struct ubifs_znode *zn;
int err;
- if (!test_bit(COW_ZNODE, &znode->flags)) {
+ if (!ubifs_zn_cow(znode)) {
/* znode is not being committed */
if (!test_and_set_bit(DIRTY_ZNODE, &znode->flags)) {
atomic_long_inc(&c->dirty_zn_cnt);
@@ -339,17 +339,16 @@
err = ubifs_validate_entry(c, dent);
if (err) {
- dbg_dump_stack();
- dbg_dump_node(c, dent);
+ dump_stack();
+ ubifs_dump_node(c, dent);
return err;
}
- lnc_node = kmalloc(zbr->len, GFP_NOFS);
+ lnc_node = kmemdup(node, zbr->len, GFP_NOFS);
if (!lnc_node)
/* We don't have to have the cache, so no error */
return 0;
- memcpy(lnc_node, node, zbr->len);
zbr->leaf = lnc_node;
return 0;
}
@@ -373,8 +372,8 @@
err = ubifs_validate_entry(c, node);
if (err) {
- dbg_dump_stack();
- dbg_dump_node(c, node);
+ dump_stack();
+ ubifs_dump_node(c, node);
return err;
}
@@ -462,7 +461,7 @@
dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len);
- err = ubi_read(c->ubi, lnum, buf, offs, len);
+ err = ubifs_leb_read(c, lnum, buf, offs, len, 1);
if (err) {
ubifs_err("cannot read node type %d from LEB %d:%d, error %d",
type, lnum, offs, err);
@@ -506,7 +505,7 @@
{
int ret;
- dbg_tnc("LEB %d:%d, key %s", zbr->lnum, zbr->offs, DBGKEY(key));
+ dbg_tnck(key, "LEB %d:%d, key ", zbr->lnum, zbr->offs);
ret = try_read_node(c, node, key_type(c, key), zbr->len, zbr->lnum,
zbr->offs);
@@ -520,8 +519,8 @@
ret = 0;
}
if (ret == 0 && c->replaying)
- dbg_mnt("dangling branch LEB %d:%d len %d, key %s",
- zbr->lnum, zbr->offs, zbr->len, DBGKEY(key));
+ dbg_mntk(key, "dangling branch LEB %d:%d len %d, key ",
+ zbr->lnum, zbr->offs, zbr->len);
return ret;
}
@@ -996,9 +995,9 @@
if (adding || !o_znode)
return 0;
- dbg_mnt("dangling match LEB %d:%d len %d %s",
+ dbg_mntk(key, "dangling match LEB %d:%d len %d key ",
o_znode->zbranch[o_n].lnum, o_znode->zbranch[o_n].offs,
- o_znode->zbranch[o_n].len, DBGKEY(key));
+ o_znode->zbranch[o_n].len);
*zn = o_znode;
*n = o_n;
return 1;
@@ -1180,7 +1179,7 @@
struct ubifs_znode *znode;
unsigned long time = get_seconds();
- dbg_tnc("search key %s", DBGKEY(key));
+ dbg_tnck(key, "search key ");
ubifs_assert(key_type(c, key) < UBIFS_INVALID_KEY);
znode = c->zroot.znode;
@@ -1316,7 +1315,7 @@
struct ubifs_znode *znode;
unsigned long time = get_seconds();
- dbg_tnc("search and dirty key %s", DBGKEY(key));
+ dbg_tnck(key, "search and dirty key ");
znode = c->zroot.znode;
if (unlikely(!znode)) {
@@ -1666,7 +1665,7 @@
if (!overlap) {
/* We may safely unlock the write-buffer and read the data */
spin_unlock(&wbuf->lock);
- return ubi_read(c->ubi, lnum, buf, offs, len);
+ return ubifs_leb_read(c, lnum, buf, offs, len, 0);
}
/* Don't read under wbuf */
@@ -1680,7 +1679,7 @@
if (rlen > 0)
/* Read everything that goes before write-buffer */
- return ubi_read(c->ubi, lnum, buf, offs, rlen);
+ return ubifs_leb_read(c, lnum, buf, offs, rlen, 0);
return 0;
}
@@ -1723,8 +1722,8 @@
if (!keys_eq(c, &zbr->key, &key1)) {
ubifs_err("bad key in node at LEB %d:%d",
zbr->lnum, zbr->offs);
- dbg_tnc("looked for key %s found node's key %s",
- DBGKEY(&zbr->key), DBGKEY1(&key1));
+ dbg_tnck(&zbr->key, "looked for key ");
+ dbg_tnck(&key1, "found node's key ");
goto out_err;
}
@@ -1734,8 +1733,8 @@
err = -EINVAL;
out:
ubifs_err("bad node at LEB %d:%d", zbr->lnum, zbr->offs);
- dbg_dump_node(c, buf);
- dbg_dump_stack();
+ ubifs_dump_node(c, buf);
+ dump_stack();
return err;
}
@@ -1767,7 +1766,7 @@
if (wbuf)
err = read_wbuf(wbuf, bu->buf, len, lnum, offs);
else
- err = ubi_read(c->ubi, lnum, bu->buf, offs, len);
+ err = ubifs_leb_read(c, lnum, bu->buf, offs, len, 0);
/* Check for a race with GC */
if (maybe_leb_gced(c, lnum, bu->gc_seq))
@@ -1776,8 +1775,8 @@
if (err && err != -EBADMSG) {
ubifs_err("failed to read from LEB %d:%d, error %d",
lnum, offs, err);
- dbg_dump_stack();
- dbg_tnc("key %s", DBGKEY(&bu->key));
+ dump_stack();
+ dbg_tnck(&bu->key, "key ");
return err;
}
@@ -1812,7 +1811,7 @@
int found, n, err;
struct ubifs_znode *znode;
- dbg_tnc("name '%.*s' key %s", nm->len, nm->name, DBGKEY(key));
+ dbg_tnck(key, "name '%.*s' key ", nm->len, nm->name);
mutex_lock(&c->tnc_mutex);
found = ubifs_lookup_level0(c, key, &znode, &n);
if (!found) {
@@ -1986,8 +1985,7 @@
zp = znode->parent;
if (znode->child_cnt < c->fanout) {
ubifs_assert(n != c->fanout);
- dbg_tnc("inserted at %d level %d, key %s", n, znode->level,
- DBGKEY(key));
+ dbg_tnck(key, "inserted at %d level %d, key ", n, znode->level);
insert_zbranch(znode, zbr, n);
@@ -2002,7 +2000,7 @@
* Unfortunately, @znode does not have more empty slots and we have to
* split it.
*/
- dbg_tnc("splitting level %d, key %s", znode->level, DBGKEY(key));
+ dbg_tnck(key, "splitting level %d, key ", znode->level);
if (znode->alt)
/*
@@ -2096,7 +2094,7 @@
}
/* Insert new key and branch */
- dbg_tnc("inserting at %d level %d, key %s", n, zn->level, DBGKEY(key));
+ dbg_tnck(key, "inserting at %d level %d, key ", n, zn->level);
insert_zbranch(zi, zbr, n);
@@ -2172,7 +2170,7 @@
struct ubifs_znode *znode;
mutex_lock(&c->tnc_mutex);
- dbg_tnc("%d:%d, len %d, key %s", lnum, offs, len, DBGKEY(key));
+ dbg_tnck(key, "%d:%d, len %d, key ", lnum, offs, len);
found = lookup_level0_dirty(c, key, &znode, &n);
if (!found) {
struct ubifs_zbranch zbr;
@@ -2221,8 +2219,8 @@
struct ubifs_znode *znode;
mutex_lock(&c->tnc_mutex);
- dbg_tnc("old LEB %d:%d, new LEB %d:%d, len %d, key %s", old_lnum,
- old_offs, lnum, offs, len, DBGKEY(key));
+ dbg_tnck(key, "old LEB %d:%d, new LEB %d:%d, len %d, key ", old_lnum,
+ old_offs, lnum, offs, len);
found = lookup_level0_dirty(c, key, &znode, &n);
if (found < 0) {
err = found;
@@ -2304,8 +2302,8 @@
struct ubifs_znode *znode;
mutex_lock(&c->tnc_mutex);
- dbg_tnc("LEB %d:%d, name '%.*s', key %s", lnum, offs, nm->len, nm->name,
- DBGKEY(key));
+ dbg_tnck(key, "LEB %d:%d, name '%.*s', key ",
+ lnum, offs, nm->len, nm->name);
found = lookup_level0_dirty(c, key, &znode, &n);
if (found < 0) {
err = found;
@@ -2398,14 +2396,14 @@
/* Delete without merge for now */
ubifs_assert(znode->level == 0);
ubifs_assert(n >= 0 && n < c->fanout);
- dbg_tnc("deleting %s", DBGKEY(&znode->zbranch[n].key));
+ dbg_tnck(&znode->zbranch[n].key, "deleting key ");
zbr = &znode->zbranch[n];
lnc_free(zbr);
err = ubifs_add_dirt(c, zbr->lnum, zbr->len);
if (err) {
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
return err;
}
@@ -2423,7 +2421,7 @@
*/
do {
- ubifs_assert(!test_bit(OBSOLETE_ZNODE, &znode->flags));
+ ubifs_assert(!ubifs_zn_obsolete(znode));
ubifs_assert(ubifs_zn_dirty(znode));
zp = znode->parent;
@@ -2479,9 +2477,8 @@
c->zroot.offs = zbr->offs;
c->zroot.len = zbr->len;
c->zroot.znode = znode;
- ubifs_assert(!test_bit(OBSOLETE_ZNODE,
- &zp->flags));
- ubifs_assert(test_bit(DIRTY_ZNODE, &zp->flags));
+ ubifs_assert(!ubifs_zn_obsolete(zp));
+ ubifs_assert(ubifs_zn_dirty(zp));
atomic_long_dec(&c->dirty_zn_cnt);
if (zp->cnext) {
@@ -2509,7 +2506,7 @@
struct ubifs_znode *znode;
mutex_lock(&c->tnc_mutex);
- dbg_tnc("key %s", DBGKEY(key));
+ dbg_tnck(key, "key ");
found = lookup_level0_dirty(c, key, &znode, &n);
if (found < 0) {
err = found;
@@ -2540,7 +2537,7 @@
struct ubifs_znode *znode;
mutex_lock(&c->tnc_mutex);
- dbg_tnc("%.*s, key %s", nm->len, nm->name, DBGKEY(key));
+ dbg_tnck(key, "%.*s, key ", nm->len, nm->name);
err = lookup_level0_dirty(c, key, &znode, &n);
if (err < 0)
goto out_unlock;
@@ -2652,10 +2649,10 @@
err = ubifs_add_dirt(c, znode->zbranch[i].lnum,
znode->zbranch[i].len);
if (err) {
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
goto out_unlock;
}
- dbg_tnc("removing %s", DBGKEY(key));
+ dbg_tnck(key, "removing key ");
}
if (k) {
for (i = n + 1 + k; i < znode->child_cnt; i++)
@@ -2775,7 +2772,7 @@
struct ubifs_zbranch *zbr;
union ubifs_key *dkey;
- dbg_tnc("%s %s", nm->name ? (char *)nm->name : "(lowest)", DBGKEY(key));
+ dbg_tnck(key, "%s ", nm->name ? (char *)nm->name : "(lowest)");
ubifs_assert(is_hash_key(c, key));
mutex_lock(&c->tnc_mutex);
@@ -2865,7 +2862,7 @@
struct ubifs_znode *znode = cnext;
cnext = cnext->cnext;
- if (test_bit(OBSOLETE_ZNODE, &znode->flags))
+ if (ubifs_zn_obsolete(znode))
kfree(znode);
} while (cnext && cnext != c->cnext);
}
@@ -3278,8 +3275,6 @@
return err;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
-
/**
* dbg_check_inode_size - check if inode size is correct.
* @c: UBIFS file-system description object
@@ -3301,7 +3296,7 @@
if (!S_ISREG(inode->i_mode))
return 0;
- if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+ if (!dbg_is_chk_gen(c))
return 0;
block = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
@@ -3334,16 +3329,15 @@
out_dump:
block = key_block(c, key);
- ubifs_err("inode %lu has size %lld, but there are data at offset %lld "
- "(data key %s)", (unsigned long)inode->i_ino, size,
- ((loff_t)block) << UBIFS_BLOCK_SHIFT, DBGKEY(key));
- dbg_dump_inode(c, inode);
- dbg_dump_stack();
- err = -EINVAL;
+ ubifs_err("inode %lu has size %lld, but there are data at offset %lld",
+ (unsigned long)inode->i_ino, size,
+ ((loff_t)block) << UBIFS_BLOCK_SHIFT);
+ mutex_unlock(&c->tnc_mutex);
+ ubifs_dump_inode(c, inode);
+ dump_stack();
+ return -EINVAL;
out_unlock:
mutex_unlock(&c->tnc_mutex);
return err;
}
-
-#endif /* CONFIG_UBIFS_FS_DEBUG */
diff -uN -uNr linux-3.0/fs/ubifs/tnc_commit.c linux-3.0.x.ubifs.latest/fs/ubifs/tnc_commit.c
--- linux-3.0/fs/ubifs/tnc_commit.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/tnc_commit.c 2012-06-28 11:26:15.000000000 -0500
@@ -22,6 +22,7 @@
/* This file implements TNC functions for committing */
+#include <linux/random.h>
#include "ubifs.h"
/**
@@ -53,18 +54,16 @@
br->len = cpu_to_le32(zbr->len);
if (!zbr->lnum || !zbr->len) {
ubifs_err("bad ref in znode");
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
if (zbr->znode)
- dbg_dump_znode(c, zbr->znode);
+ ubifs_dump_znode(c, zbr->znode);
}
}
ubifs_prepare_node(c, idx, len, 0);
-#ifdef CONFIG_UBIFS_FS_DEBUG
znode->lnum = lnum;
znode->offs = offs;
znode->len = len;
-#endif
err = insert_old_idx_znode(c, znode);
@@ -87,8 +86,12 @@
atomic_long_dec(&c->dirty_zn_cnt);
ubifs_assert(ubifs_zn_dirty(znode));
- ubifs_assert(test_bit(COW_ZNODE, &znode->flags));
+ ubifs_assert(ubifs_zn_cow(znode));
+ /*
+ * Note, unlike 'write_index()' we do not add memory barriers here
+ * because this function is called with @c->tnc_mutex locked.
+ */
__clear_bit(DIRTY_ZNODE, &znode->flags);
__clear_bit(COW_ZNODE, &znode->flags);
@@ -317,8 +320,7 @@
0, 0, 0);
if (err)
return err;
- err = ubifs_leb_change(c, lnum, c->ileb_buf, c->ileb_len,
- UBI_SHORTTERM);
+ err = ubifs_leb_change(c, lnum, c->ileb_buf, c->ileb_len);
if (err)
return err;
dbg_gc("LEB %d wrote %d index nodes", lnum, tot_written);
@@ -377,14 +379,14 @@
c->gap_lebs = NULL;
return err;
}
- if (dbg_force_in_the_gaps_enabled()) {
+ if (!dbg_is_chk_index(c)) {
/*
* Do not print scary warnings if the debugging
* option which forces in-the-gaps is enabled.
*/
ubifs_warn("out of space");
- dbg_dump_budg(c, &c->bi);
- dbg_dump_lprops(c);
+ ubifs_dump_budg(c, &c->bi);
+ ubifs_dump_lprops(c);
}
/* Try to commit anyway */
err = 0;
@@ -451,11 +453,9 @@
offs = buf_offs + used;
-#ifdef CONFIG_UBIFS_FS_DEBUG
znode->lnum = lnum;
znode->offs = offs;
znode->len = len;
-#endif
/* Update the parent */
zp = znode->parent;
@@ -491,25 +491,6 @@
else
next_len = ubifs_idx_node_sz(c, cnext->child_cnt);
- if (c->min_io_size == 1) {
- buf_offs += ALIGN(len, 8);
- if (next_len) {
- if (buf_offs + next_len <= c->leb_size)
- continue;
- err = ubifs_update_one_lp(c, lnum, 0,
- c->leb_size - buf_offs, 0, 0);
- if (err)
- return err;
- lnum = -1;
- continue;
- }
- err = ubifs_update_one_lp(c, lnum,
- c->leb_size - buf_offs, 0, 0, 0);
- if (err)
- return err;
- break;
- }
-
/* Update buffer positions */
wlen = used + len;
used += ALIGN(len, 8);
@@ -550,10 +531,8 @@
break;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
c->dbg->new_ihead_lnum = lnum;
c->dbg->new_ihead_offs = buf_offs;
-#endif
return 0;
}
@@ -658,7 +637,7 @@
}
cnt += 1;
while (1) {
- ubifs_assert(!test_bit(COW_ZNODE, &znode->flags));
+ ubifs_assert(!ubifs_zn_cow(znode));
__set_bit(COW_ZNODE, &znode->flags);
znode->alt = 0;
cnext = find_next_dirty(znode);
@@ -704,7 +683,7 @@
c->ilebs[c->ileb_cnt++] = lnum;
dbg_cmt("LEB %d", lnum);
}
- if (dbg_force_in_the_gaps())
+ if (dbg_is_chk_index(c) && !(random32() & 7))
return -ENOSPC;
return 0;
}
@@ -830,7 +809,7 @@
struct ubifs_idx_node *idx;
struct ubifs_znode *znode, *cnext;
int i, lnum, offs, len, next_len, buf_len, buf_offs, used;
- int avail, wlen, err, lnum_pos = 0;
+ int avail, wlen, err, lnum_pos = 0, blen, nxt_offs;
cnext = c->enext;
if (!cnext)
@@ -878,9 +857,9 @@
br->len = cpu_to_le32(zbr->len);
if (!zbr->lnum || !zbr->len) {
ubifs_err("bad ref in znode");
- dbg_dump_znode(c, znode);
+ ubifs_dump_znode(c, znode);
if (zbr->znode)
- dbg_dump_znode(c, zbr->znode);
+ ubifs_dump_znode(c, zbr->znode);
}
}
len = ubifs_idx_node_sz(c, znode->child_cnt);
@@ -895,19 +874,17 @@
}
offs = buf_offs + used;
-#ifdef CONFIG_UBIFS_FS_DEBUG
if (lnum != znode->lnum || offs != znode->offs ||
len != znode->len) {
ubifs_err("inconsistent znode posn");
return -EINVAL;
}
-#endif
/* Grab some stuff from znode while we still can */
cnext = znode->cnext;
ubifs_assert(ubifs_zn_dirty(znode));
- ubifs_assert(test_bit(COW_ZNODE, &znode->flags));
+ ubifs_assert(ubifs_zn_cow(znode));
/*
* It is important that other threads should see %DIRTY_ZNODE
@@ -922,6 +899,28 @@
clear_bit(COW_ZNODE, &znode->flags);
smp_mb__after_clear_bit();
+ /*
+ * We have marked the znode as clean but have not updated the
+ * @c->clean_zn_cnt counter. If this znode becomes dirty again
+ * before 'free_obsolete_znodes()' is called, then
+ * @c->clean_zn_cnt will be decremented before it gets
+ * incremented (resulting in 2 decrements for the same znode).
+ * This means that @c->clean_zn_cnt may become negative for a
+ * while.
+ *
+ * Q: why we cannot increment @c->clean_zn_cnt?
+ * A: because we do not have the @c->tnc_mutex locked, and the
+ * following code would be racy and buggy:
+ *
+ * if (!ubifs_zn_obsolete(znode)) {
+ * atomic_long_inc(&c->clean_zn_cnt);
+ * atomic_long_inc(&ubifs_clean_zn_cnt);
+ * }
+ *
+ * Thus, we just delay the @c->clean_zn_cnt update until we
+ * have the mutex locked.
+ */
+
/* Do not access znode from this point on */
/* Update buffer positions */
@@ -938,76 +937,46 @@
else
next_len = ubifs_idx_node_sz(c, cnext->child_cnt);
- if (c->min_io_size == 1) {
- /*
- * Write the prepared index node immediately if there is
- * no minimum IO size
- */
- err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs,
- wlen, UBI_SHORTTERM);
- if (err)
- return err;
- buf_offs += ALIGN(wlen, 8);
- if (next_len) {
- used = 0;
- avail = buf_len;
- if (buf_offs + next_len > c->leb_size) {
- err = ubifs_update_one_lp(c, lnum,
- LPROPS_NC, 0, 0, LPROPS_TAKEN);
- if (err)
- return err;
- lnum = -1;
- }
+ nxt_offs = buf_offs + used + next_len;
+ if (next_len && nxt_offs <= c->leb_size) {
+ if (avail > 0)
continue;
- }
+ else
+ blen = buf_len;
} else {
- int blen, nxt_offs = buf_offs + used + next_len;
+ wlen = ALIGN(wlen, 8);
+ blen = ALIGN(wlen, c->min_io_size);
+ ubifs_pad(c, c->cbuf + wlen, blen - wlen);
+ }
- if (next_len && nxt_offs <= c->leb_size) {
- if (avail > 0)
- continue;
- else
- blen = buf_len;
- } else {
- wlen = ALIGN(wlen, 8);
- blen = ALIGN(wlen, c->min_io_size);
- ubifs_pad(c, c->cbuf + wlen, blen - wlen);
- }
- /*
- * The buffer is full or there are no more znodes
- * to do
- */
- err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs,
- blen, UBI_SHORTTERM);
- if (err)
- return err;
- buf_offs += blen;
- if (next_len) {
- if (nxt_offs > c->leb_size) {
- err = ubifs_update_one_lp(c, lnum,
- LPROPS_NC, 0, 0, LPROPS_TAKEN);
- if (err)
- return err;
- lnum = -1;
- }
- used -= blen;
- if (used < 0)
- used = 0;
- avail = buf_len - used;
- memmove(c->cbuf, c->cbuf + blen, used);
- continue;
+ /* The buffer is full or there are no more znodes to do */
+ err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs, blen);
+ if (err)
+ return err;
+ buf_offs += blen;
+ if (next_len) {
+ if (nxt_offs > c->leb_size) {
+ err = ubifs_update_one_lp(c, lnum, LPROPS_NC, 0,
+ 0, LPROPS_TAKEN);
+ if (err)
+ return err;
+ lnum = -1;
}
+ used -= blen;
+ if (used < 0)
+ used = 0;
+ avail = buf_len - used;
+ memmove(c->cbuf, c->cbuf + blen, used);
+ continue;
}
break;
}
-#ifdef CONFIG_UBIFS_FS_DEBUG
if (lnum != c->dbg->new_ihead_lnum ||
buf_offs != c->dbg->new_ihead_offs) {
ubifs_err("inconsistent ihead");
return -EINVAL;
}
-#endif
c->ihead_lnum = lnum;
c->ihead_offs = buf_offs;
@@ -1029,7 +998,7 @@
do {
znode = cnext;
cnext = znode->cnext;
- if (test_bit(OBSOLETE_ZNODE, &znode->flags))
+ if (ubifs_zn_obsolete(znode))
kfree(znode);
else {
znode->cnext = NULL;
diff -uN -uNr linux-3.0/fs/ubifs/tnc_misc.c linux-3.0.x.ubifs.latest/fs/ubifs/tnc_misc.c
--- linux-3.0/fs/ubifs/tnc_misc.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/tnc_misc.c 2012-06-28 11:26:15.000000000 -0500
@@ -293,10 +293,10 @@
lnum, offs, znode->level, znode->child_cnt);
if (znode->child_cnt > c->fanout || znode->level > UBIFS_MAX_LEVELS) {
- dbg_err("current fanout %d, branch count %d",
- c->fanout, znode->child_cnt);
- dbg_err("max levels %d, znode level %d",
- UBIFS_MAX_LEVELS, znode->level);
+ ubifs_err("current fanout %d, branch count %d",
+ c->fanout, znode->child_cnt);
+ ubifs_err("max levels %d, znode level %d",
+ UBIFS_MAX_LEVELS, znode->level);
err = 1;
goto out_dump;
}
@@ -316,7 +316,7 @@
if (zbr->lnum < c->main_first ||
zbr->lnum >= c->leb_cnt || zbr->offs < 0 ||
zbr->offs + zbr->len > c->leb_size || zbr->offs & 7) {
- dbg_err("bad branch %d", i);
+ ubifs_err("bad branch %d", i);
err = 2;
goto out_dump;
}
@@ -328,8 +328,8 @@
case UBIFS_XENT_KEY:
break;
default:
- dbg_msg("bad key type at slot %d: %s", i,
- DBGKEY(&zbr->key));
+ dbg_msg("bad key type at slot %d: %d",
+ i, key_type(c, &zbr->key));
err = 3;
goto out_dump;
}
@@ -340,19 +340,19 @@
type = key_type(c, &zbr->key);
if (c->ranges[type].max_len == 0) {
if (zbr->len != c->ranges[type].len) {
- dbg_err("bad target node (type %d) length (%d)",
- type, zbr->len);
- dbg_err("have to be %d", c->ranges[type].len);
+ ubifs_err("bad target node (type %d) length (%d)",
+ type, zbr->len);
+ ubifs_err("have to be %d", c->ranges[type].len);
err = 4;
goto out_dump;
}
} else if (zbr->len < c->ranges[type].min_len ||
zbr->len > c->ranges[type].max_len) {
- dbg_err("bad target node (type %d) length (%d)",
- type, zbr->len);
- dbg_err("have to be in range of %d-%d",
- c->ranges[type].min_len,
- c->ranges[type].max_len);
+ ubifs_err("bad target node (type %d) length (%d)",
+ type, zbr->len);
+ ubifs_err("have to be in range of %d-%d",
+ c->ranges[type].min_len,
+ c->ranges[type].max_len);
err = 5;
goto out_dump;
}
@@ -370,13 +370,13 @@
cmp = keys_cmp(c, key1, key2);
if (cmp > 0) {
- dbg_err("bad key order (keys %d and %d)", i, i + 1);
+ ubifs_err("bad key order (keys %d and %d)", i, i + 1);
err = 6;
goto out_dump;
} else if (cmp == 0 && !is_hash_key(c, key1)) {
/* These can only be keys with colliding hash */
- dbg_err("keys %d and %d are not hashed but equivalent",
- i, i + 1);
+ ubifs_err("keys %d and %d are not hashed but equivalent",
+ i, i + 1);
err = 7;
goto out_dump;
}
@@ -387,7 +387,7 @@
out_dump:
ubifs_err("bad indexing node at LEB %d:%d, error %d", lnum, offs, err);
- dbg_dump_node(c, idx);
+ ubifs_dump_node(c, idx);
kfree(idx);
return -EINVAL;
}
@@ -475,7 +475,7 @@
zbr->offs);
if (err) {
- dbg_tnc("key %s", DBGKEY(key));
+ dbg_tnck(key, "key ");
return err;
}
@@ -484,9 +484,9 @@
if (!keys_eq(c, key, &key1)) {
ubifs_err("bad key in node at LEB %d:%d",
zbr->lnum, zbr->offs);
- dbg_tnc("looked for key %s found node's key %s",
- DBGKEY(key), DBGKEY1(&key1));
- dbg_dump_node(c, node);
+ dbg_tnck(key, "looked for key ");
+ dbg_tnck(&key1, "but found node's key ");
+ ubifs_dump_node(c, node);
return -EINVAL;
}
diff -uN -uNr linux-3.0/fs/ubifs/ubifs.h linux-3.0.x.ubifs.latest/fs/ubifs/ubifs.h
--- linux-3.0/fs/ubifs/ubifs.h 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/ubifs.h 2012-06-28 11:26:15.000000000 -0500
@@ -84,9 +84,6 @@
#define INUM_WARN_WATERMARK 0xFFF00000
#define INUM_WATERMARK 0xFFFFFF00
-/* Largest key size supported in this implementation */
-#define CUR_MAX_KEY_LEN UBIFS_SK_LEN
-
/* Maximum number of entries in each LPT (LEB category) heap */
#define LPT_HEAP_SZ 256
@@ -230,14 +227,14 @@
* LPT cnode flag bits.
*
* DIRTY_CNODE: cnode is dirty
- * COW_CNODE: cnode is being committed and must be copied before writing
* OBSOLETE_CNODE: cnode is being committed and has been copied (or deleted),
- * so it can (and must) be freed when the commit is finished
+ * so it can (and must) be freed when the commit is finished
+ * COW_CNODE: cnode is being committed and must be copied before writing
*/
enum {
DIRTY_CNODE = 0,
- COW_CNODE = 1,
- OBSOLETE_CNODE = 2,
+ OBSOLETE_CNODE = 1,
+ COW_CNODE = 2,
};
/*
@@ -277,10 +274,10 @@
/* The below union makes it easier to deal with keys */
union ubifs_key {
- uint8_t u8[CUR_MAX_KEY_LEN];
- uint32_t u32[CUR_MAX_KEY_LEN/4];
- uint64_t u64[CUR_MAX_KEY_LEN/8];
- __le32 j32[CUR_MAX_KEY_LEN/4];
+ uint8_t u8[UBIFS_SK_LEN];
+ uint32_t u32[UBIFS_SK_LEN/4];
+ uint64_t u64[UBIFS_SK_LEN/8];
+ __le32 j32[UBIFS_SK_LEN/4];
};
/**
@@ -653,8 +650,6 @@
* @avail: number of bytes available in the write-buffer
* @used: number of used bytes in the write-buffer
* @size: write-buffer size (in [@c->min_io_size, @c->max_write_size] range)
- * @dtype: type of data stored in this LEB (%UBI_LONGTERM, %UBI_SHORTTERM,
- * %UBI_UNKNOWN)
* @jhead: journal head the mutex belongs to (note, needed only to shut lockdep
* up by 'mutex_lock_nested()).
* @sync_callback: write-buffer synchronization callback
@@ -688,7 +683,6 @@
int avail;
int used;
int size;
- int dtype;
int jhead;
int (*sync_callback)(struct ubifs_info *c, int lnum, int free, int pad);
struct mutex io_mutex;
@@ -765,6 +759,9 @@
* @offs: offset of the corresponding indexing node
* @len: length of the corresponding indexing node
* @zbranch: array of znode branches (@c->fanout elements)
+ *
+ * Note! The @lnum, @offs, and @len fields are not really needed - we have them
+ * only for internal consistency check. They could be removed to save some RAM.
*/
struct ubifs_znode {
struct ubifs_znode *parent;
@@ -775,9 +772,9 @@
int child_cnt;
int iip;
int alt;
-#ifdef CONFIG_UBIFS_FS_DEBUG
- int lnum, offs, len;
-#endif
+ int lnum;
+ int offs;
+ int len;
struct ubifs_zbranch zbranch[];
};
@@ -1447,9 +1444,7 @@
struct rb_root size_tree;
struct ubifs_mount_opts mount_opts;
-#ifdef CONFIG_UBIFS_FS_DEBUG
struct ubifs_debug_info *dbg;
-#endif
};
extern struct list_head ubifs_infos;
@@ -1468,16 +1463,23 @@
/* io.c */
void ubifs_ro_mode(struct ubifs_info *c, int err);
+int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
+ int len, int even_ebadmsg);
+int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
+ int len);
+int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len);
+int ubifs_leb_unmap(struct ubifs_info *c, int lnum);
+int ubifs_leb_map(struct ubifs_info *c, int lnum);
+int ubifs_is_mapped(const struct ubifs_info *c, int lnum);
int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len);
-int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
- int dtype);
+int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs);
int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf);
int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
int lnum, int offs);
int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
int lnum, int offs);
int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum,
- int offs, int dtype);
+ int offs);
int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
int offs, int quiet, int must_chk_crc);
void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad);
@@ -1747,8 +1749,8 @@
int offs, void *sbuf, int jhead);
struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
int offs, void *sbuf);
-int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf);
-int ubifs_clean_lebs(const struct ubifs_info *c, void *sbuf);
+int ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf);
+int ubifs_clean_lebs(struct ubifs_info *c, void *sbuf);
int ubifs_rcvry_gc_commit(struct ubifs_info *c);
int ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key,
int deletion, loff_t new_size);
diff -uN -uNr linux-3.0/fs/ubifs/xattr.c linux-3.0.x.ubifs.latest/fs/ubifs/xattr.c
--- linux-3.0/fs/ubifs/xattr.c 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/fs/ubifs/xattr.c 2012-06-28 11:26:15.000000000 -0500
@@ -138,12 +138,11 @@
ui = ubifs_inode(inode);
ui->xattr = 1;
ui->flags |= UBIFS_XATTR_FL;
- ui->data = kmalloc(size, GFP_NOFS);
+ ui->data = kmemdup(value, size, GFP_NOFS);
if (!ui->data) {
err = -ENOMEM;
goto out_free;
}
- memcpy(ui->data, value, size);
inode->i_size = ui->ui_size = size;
ui->data_len = size;
@@ -204,12 +203,11 @@
return err;
kfree(ui->data);
- ui->data = kmalloc(size, GFP_NOFS);
+ ui->data = kmemdup(value, size, GFP_NOFS);
if (!ui->data) {
err = -ENOMEM;
goto out_free;
}
- memcpy(ui->data, value, size);
inode->i_size = ui->ui_size = size;
ui->data_len = size;
@@ -401,8 +399,8 @@
if (buf) {
/* If @buf is %NULL we are supposed to return the length */
if (ui->data_len > size) {
- dbg_err("buffer size %zd, xattr len %d",
- size, ui->data_len);
+ ubifs_err("buffer size %zd, xattr len %d",
+ size, ui->data_len);
err = -ERANGE;
goto out_iput;
}
diff -uN -uNr linux-3.0/include/linux/mtd/ubi.h linux-3.0.x.ubifs.latest/include/linux/mtd/ubi.h
--- linux-3.0/include/linux/mtd/ubi.h 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/include/linux/mtd/ubi.h 2012-06-28 11:26:15.000000000 -0500
@@ -25,6 +25,9 @@
#include <linux/types.h>
#include <mtd/ubi-user.h>
+/* All voumes/LEBs */
+#define UBI_ALL -1
+
/*
* enum ubi_open_mode - UBI volume open mode constants.
*
@@ -155,12 +158,14 @@
};
/*
- * enum - volume notification types.
- * @UBI_VOLUME_ADDED: volume has been added
- * @UBI_VOLUME_REMOVED: start volume volume
- * @UBI_VOLUME_RESIZED: volume size has been re-sized
- * @UBI_VOLUME_RENAMED: volume name has been re-named
- * @UBI_VOLUME_UPDATED: volume name has been updated
+ * Volume notification types.
+ * @UBI_VOLUME_ADDED: a volume has been added (an UBI device was attached or a
+ * volume was created)
+ * @UBI_VOLUME_REMOVED: a volume has been removed (an UBI device was detached
+ * or a volume was removed)
+ * @UBI_VOLUME_RESIZED: a volume has been re-sized
+ * @UBI_VOLUME_RENAMED: a volume has been re-named
+ * @UBI_VOLUME_UPDATED: data has been written to a volume
*
* These constants define which type of event has happened when a volume
* notification function is invoked.
@@ -206,14 +211,15 @@
int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
int len, int check);
int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
- int offset, int len, int dtype);
+ int offset, int len);
int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
- int len, int dtype);
+ int len);
int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum);
int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum);
-int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype);
+int ubi_leb_map(struct ubi_volume_desc *desc, int lnum);
int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum);
int ubi_sync(int ubi_num);
+int ubi_flush(int ubi_num, int vol_id, int lnum);
/*
* This function is the same as the 'ubi_leb_read()' function, but it does not
@@ -224,25 +230,4 @@
{
return ubi_leb_read(desc, lnum, buf, offset, len, 0);
}
-
-/*
- * This function is the same as the 'ubi_leb_write()' functions, but it does
- * not have the data type argument.
- */
-static inline int ubi_write(struct ubi_volume_desc *desc, int lnum,
- const void *buf, int offset, int len)
-{
- return ubi_leb_write(desc, lnum, buf, offset, len, UBI_UNKNOWN);
-}
-
-/*
- * This function is the same as the 'ubi_leb_change()' functions, but it does
- * not have the data type argument.
- */
-static inline int ubi_change(struct ubi_volume_desc *desc, int lnum,
- const void *buf, int len)
-{
- return ubi_leb_change(desc, lnum, buf, len, UBI_UNKNOWN);
-}
-
#endif /* !__LINUX_UBI_H__ */
diff -uN -uNr linux-3.0/include/mtd/ubi-user.h linux-3.0.x.ubifs.latest/include/mtd/ubi-user.h
--- linux-3.0/include/mtd/ubi-user.h 2011-07-21 21:17:23.000000000 -0500
+++ linux-3.0.x.ubifs.latest/include/mtd/ubi-user.h 2012-06-28 11:26:15.000000000 -0500
@@ -196,23 +196,6 @@
#define UBI_MAX_RNVOL 32
/*
- * UBI data type hint constants.
- *
- * UBI_LONGTERM: long-term data
- * UBI_SHORTTERM: short-term data
- * UBI_UNKNOWN: data persistence is unknown
- *
- * These constants are used when data is written to UBI volumes in order to
- * help the UBI wear-leveling unit to find more appropriate physical
- * eraseblocks.
- */
-enum {
- UBI_LONGTERM = 1,
- UBI_SHORTTERM = 2,
- UBI_UNKNOWN = 3,
-};
-
-/*
* UBI volume type constants.
*
* @UBI_DYNAMIC_VOLUME: dynamic volume
@@ -375,25 +358,34 @@
* requests.
* @lnum: logical eraseblock number to change
* @bytes: how many bytes will be written to the logical eraseblock
- * @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)
+ * @dtype: pass "3" for better compatibility with old kernels
* @padding: reserved for future, not used, has to be zeroed
+ *
+ * The @dtype field used to inform UBI about what kind of data will be written
+ * to the LEB: long term (value 1), short term (value 2), unknown (value 3).
+ * UBI tried to pick a PEB with lower erase counter for short term data and a
+ * PEB with higher erase counter for long term data. But this was not really
+ * used because users usually do not know this and could easily mislead UBI. We
+ * removed this feature in May 2012. UBI currently just ignores the @dtype
+ * field. But for better compatibility with older kernels it is recommended to
+ * set @dtype to 3 (unknown).
*/
struct ubi_leb_change_req {
__s32 lnum;
__s32 bytes;
- __s8 dtype;
+ __s8 dtype; /* obsolete, do not use! */
__s8 padding[7];
} __packed;
/**
* struct ubi_map_req - a data structure used in map LEB requests.
+ * @dtype: pass "3" for better compatibility with old kernels
* @lnum: logical eraseblock number to unmap
- * @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)
* @padding: reserved for future, not used, has to be zeroed
*/
struct ubi_map_req {
__s32 lnum;
- __s8 dtype;
+ __s8 dtype; /* obsolete, do not use! */
__s8 padding[3];
} __packed;
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB'
2012-07-16 18:22 UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB' Brent Taylor
@ 2012-08-13 13:41 ` Brent Taylor
2012-08-17 12:57 ` Artem Bityutskiy
2012-08-17 12:50 ` Artem Bityutskiy
2012-08-31 11:44 ` Artem Bityutskiy
2 siblings, 1 reply; 14+ messages in thread
From: Brent Taylor @ 2012-08-13 13:41 UTC (permalink / raw)
To: linux-mtd
Brent Taylor <motobud <at> gmail.com> writes:
>
>
> I'm developing on custom hardware using an at91sam9g45 processor with 64 MB of
RAM and 64 MB of NOR flash running Linux 3.0.13.I'm doing some power-cycle
testing and after several hours, UBIFS failed to mount the root partition and
printed the message "grab_empty_leb: could not find an empty LEB". The system
boots and starts a script that will power cycle the board anytime between 10 and
20 seconds after the script has started. Just before a power cycle occurs,
syslog and our main process are the only processes that could be writing to
disk. I then checked http://git.infradead.org/users/dedekind/ubifs-v3.0.git to
see if there was a patch and couldn't find anything describing my exact
problem. I generated a patch from commit
02f8c6aee8df3cdc935e9bdd4f2d020306035dbe to
a0c2d5050bd191e53a761381027c8e5ab8e25336 (see attached ubifs.3.0.diff) and
rebuilt the kernel. If there was a patch for my issue, I was expecting the root
partition to be recovered but it wasn't. I'm currently running the same test
with the patched kernel. Below is the information from the patched kernel.If
there is any more information I need to provide, please let me know.
> Any help would be appreciated,
> Bud[linux-16][~> uname -aLinux linux 3.0.13 #20 Mon Jul 16 11:16:58 CDT 2012
armv5tejl GNU/Linux[linux-16][~> mtdinfo -aCount of MTD devices:
5Present MTD devices: mtd0, mtd1, mtd2, mtd3, mtd4Sysfs interface
supported: yesmtd0Name:
bootType: norEraseblock size: 131072
bytes, 128.0 KiBAmount of eraseblocks: 1 (131072 bytes, 128.0
KiB)Minimum input/output unit size: 1 byteSub-page size: 1
byteCharacter device major/minor: 90:0Bad blocks are allowed:
falseDevice is writable: falsemtd1Name:
ubootType: norEraseblock size: 131072
bytes, 128.0 KiBAmount of eraseblocks: 1 (131072 bytes, 128.0
KiB)Minimum input/output unit size: 1 byteSub-page size: 1
byteCharacter device major/minor: 90:2Bad blocks are allowed:
falseDevice is writable: falsemtd2Name:
envType: norEraseblock size: 131072
bytes, 128.0 KiBAmount of eraseblocks: 1 (131072 bytes, 128.0
KiB)Minimum input/output unit size: 1 byteSub-page size: 1
byteCharacter device major/minor: 90:4Bad blocks are allowed:
falseDevice is writable: truemtd3Name:
kernelType: norEraseblock size: 131072
bytes, 128.0 KiBAmount of eraseblocks: 16 (2097152 bytes, 2.0
MiB)Minimum input/output unit size: 1 byteSub-page size: 1
byteCharacter device major/minor: 90:6Bad blocks are allowed:
falseDevice is writable: falsemtd4Name:
root-fsType: norEraseblock size: 131072
bytes, 128.0 KiBAmount of eraseblocks: 493 (64618496 bytes, 61.6
MiB)Minimum input/output unit size: 1 byteSub-page size: 1
byteCharacter device major/minor: 90:8Bad blocks are allowed:
falseDevice is writable: true[linux-16][~> ubinfo -a
/dev/ubi0ubi0Volumes count: 1Logical eraseblock
size: 130944 bytes, 127.9 KiBTotal amount of logical
eraseblocks: 493 (64555392 bytes, 61.6 MiB)Amount of available logical
eraseblocks: 0 (0 bytes)Maximum count of volumes 128Count of bad
physical eraseblocks: 0Count of reserved physical eraseblocks: 0Current
maximum erase counter value: 154Minimum input/output unit size: 1
byteCharacter device major/minor: 253:0Present
volumes: 0Volume ID: 0 (on ubi0)Type:
dynamicAlignment: 1Size: 489 LEBs (64031616 bytes, 61.1
MiB)State: OKName: ubirootfsCharacter device major/minor:
253:1[linux-16][~> mount -t ubifs ubi0:ubirootfs /opt/root/UBIFS: recovery
neededUBIFS error (pid 958): grab_empty_leb: could not find an empty LEB(pid
958) start dumping LEB properties(pid 958) Lprops statistics: empty_lebs 2,
idx_lebs 28 taken_empty_lebs 2, total_free 1193080, total_dirty
19318832 total_used 41441632, total_dark 1291912, total_dead 56LEB
10 free 24 dirty 4064 used 126856 free + dirty 4088 dark
4088 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 11 free 8 dirty
640 used 130296 free + dirty 648 dark 648 dead 0 nodes fit 0
flags 0x1 (dirty)LEB 12 free 40 dirty 960 used 129944 free +
dirty 1000 dark 1000 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 13
free 0 dirty 1600 used 129344 free + dirty 1600 dark 1600 dead
0 nodes fit 0 flags 0x1 (dirty)LEB 14 free 104 dirty 1272
used 129568 free + dirty 1376 dark 1376 dead 0 nodes fit 0 flags 0x1
(dirty)LEB> 15 free 104 dirty 1920 used 128920 free + dirty
2024 dark 2024 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 16 free
152 dirty 1120 used 129672 free + dirty 1272 dark 1272 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 17 free 112 dirty 1120 used
129712 free + dirty 1232 dark 1232 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 18 free 48 dirty 1120 used 129776 free + dirty
1168 dark 1168 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 19 free
104 dirty 1120 used 129720 free + dirty 1224 dark 1224 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 20 free 56 dirty 1280 used
129608 free + dirty 1336 dark 1336 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 21 free 56 dirty 1120 used 129768 free + dirty
1176 dark 1176 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 22 free
128 dirty 640 used 130176 free + dirty 768 dark 768 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 23 free 120 dirty 480 used
130344 free + dirty 600 dark 600 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 24 free 64 dirty 1600 used 129280 free + dirty
1664 dark 1664 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 25 free
24 dirty 1440 used 129480 free + dirty 1464 dark 1464 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 26 free 8 dirty 640 used
130296 free + dirty 648 dark 648 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 27 free 40 dirty 1760 used 129144 free + dirty
1800 dark 1800 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 28 free
64 dirty 1120 used 129760 free + dirty 1184 dark 1184 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 29 free 32 dirty 160 used
130752 free + dirty 192 dark 192 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 30 free 72 dirty 1328 used 129544 free + dirty
1400 dark 1400 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 31 free
48 dirty 2272 used 128624 free + dirty 2320 dark 2320 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 32 free 56 dirty 1280 used
129608 free + dirty 1336 dark 1336 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 33 free 48 dirty 800 used 130096 free + dirty
848 dark 848 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 34 free
128 dirty 1440 used 129376 free + dirty 1568 dark 1568 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 35 free 64 dirty 960 used
129920 free + dirty 1024 dark 1024 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 36 free 104 dirty 160 used 130680 free + dirty
264 dark 264 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 37 free
40 dirty 640 used 130264 free + dirty 680 dark 680 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 38 free 72 dirty 2112 used
128760 free + dirty 2184 dark 2184 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 39 free 104 dirty 25328 used 105512 free + dirty
25432 dark 4256 dead 0 nodes fit 5 flags 0x1 (dirty)LEB 40 free
72 dirty 96464 used 34408 free + dirty 96536 dark 4256 dead 0
nodes fit 22 flags 0x1 (dirty)LEB 41 free 104 dirty 104832 used
26008 free + dirty 104936 dark 4256 dead 0 nodes fit 24 flags 0x1
(dirty)LEB 42 free 72 dirty 111616 used 19256 free + dirty
111688 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)LEB 43 free
88 dirty 83008 used 47848 free + dirty 83096 dark 4256 dead 0
nodes fit 19 flags 0x1 (dirty)LEB 44 free 48 dirty 53944 used
76952 free + dirty 53992 dark 4256 dead 0 nodes fit 12 flags 0x1
(dirty)LEB 45 free 128 dirty 88752 used 42064 free + dirty
88880 dark 4256 dead 0 nodes fit 20 flags 0x1 (dirty)LEB 46 free
136 dirty 111976 used 18832 free + dirty 112112 dark 4256 dead 0
nodes fit 26 flags 0x1 (dirty)LEB 47 free 16 dirty 89176 used
41752 free + dirty 89192 dark 4256 dead 0 nodes fit 20 flags 0x1
(dirty)LEB 48 free 24 dirty 96616 used 34304 free + dirty
96640 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)LEB 49 free
48 dirty 88320 used 42576 free + dirty 88368 dark 4256 dead 0
nodes fit 20 flags 0x1 (dirty)LEB 50 free 88 dirty 1120 used
129736 free + dirty 1208 dark 1208 dead 0 nodes fit 0 flags 0x1&>
nbsp; (dirty)LEB 51 free 152 dirty 84456 used 46336 free + dirty
84608 dark 4256 dead 0 nodes fit 19 flags 0x1 (dirty)LEB 52 free
24 dirty 1736 used 129184 free + dirty 1760 dark 1760 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 53 free 32 dirty 107272 used
23640 free + dirty 107304 dark 4256 dead 0 nodes fit 25 flags 0x1
(dirty)LEB 54 free 72 dirty 8696 used 122176 free + dirty
8768 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)LEB 55 free
144 dirty 92152 used 38648 free + dirty 92296 dark 4256 dead 0
nodes fit 21 flags 0x1 (dirty)LEB 56 free 120 dirty 86160 used
44664 free + dirty 86280 dark 4256 dead 0 nodes fit 20 flags 0x1
(dirty)LEB 57 free 56 dirty 97728 used 33160 free + dirty
97784 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)LEB 58 free
16 dirty 50696 used 80232 free + dirty 50712 dark 4256 dead 0
nodes fit 11 flags 0x1 (dirty)LEB 59 free 0 dirty 97448 used
33496 free + dirty 97448 dark 4256 dead 0 nodes fit 22 flags 0x1
(dirty)LEB 60 free 80 dirty 83216 used 47648 free + dirty
83296 dark 4256 dead 0 nodes fit 19 flags 0x1 (dirty)LEB 61 free
64 dirty 43384 used 87496 free + dirty 43448 dark 4256 dead 0
nodes fit 10 flags 0x1 (dirty)LEB 62 free 40 dirty 2568 used
128336 free + dirty 2608 dark 2608 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 63 free 64 dirty 3632 used 127248 free + dirty
3696 dark 3696 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 64 free
0 dirty 9528 used 121416 free + dirty 9528 dark 4256 dead 0
nodes fit 2 flags 0x1 (dirty)LEB 65 free 152 dirty 696 used
130096 free + dirty 848 dark 848 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 66 free 48 dirty 57392 used 73504 free + dirty
57440 dark 4256 dead 0 nodes fit 13 flags 0x1 (dirty)LEB 67 free
64 dirty 90192 used 40688 free + dirty 90256 dark 4256 dead 0
nodes fit 21 flags 0x1 (dirty)LEB 68 free 72 dirty 111312 used
19560 free + dirty 111384 dark 4256 dead 0 nodes fit 26 flags 0x1
(dirty)LEB 69 free 0 dirty 85128 used 45816 free + dirty
85128 dark 4256 dead 0 nodes fit 20 flags 0x1 (dirty)LEB 70 free
96 dirty 97600 used 33248 free + dirty 97696 dark 4256 dead 0
nodes fit 22 flags 0x1 (dirty)LEB 71 free 16 dirty 91408 used
39520 free + dirty 91424 dark 4256 dead 0 nodes fit 21 flags 0x1
(dirty)LEB 72 free 48 dirty 103064 used 27832 free + dirty
103112 dark 4256 dead 0 nodes fit 24 flags 0x1 (dirty)LEB 73 free
112 dirty 98704 used 32128 free + dirty 98816 dark 4256 dead 0
nodes fit 23 flags 0x1 (dirty)LEB 74 free 8 dirty 1712 used
129224 free + dirty 1720 dark 1720 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 75 free 144 dirty 1656 used 129144 free + dirty
1800 dark 1800 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 76 free
80 dirty 76656 used 54208 free + dirty 76736 dark 4256 dead 0
nodes fit 18 flags 0x1 (dirty)LEB 77 free 128 dirty 61016 used
69800 free + dirty 61144 dark 4256 dead 0 nodes fit 14 flags 0x1
(dirty)LEB 78 free 40 dirty 48576 used 82328 free + dirty
48616 dark 4256 dead 0 nodes fit 11 flags 0x1 (dirty)LEB 79 free
88 dirty 9592 used 121264 free + dirty 9680 dark 4256 dead 0
nodes fit 2 flags 0x1 (dirty)LEB 80 free 40 dirty 54184 used
76720 free + dirty 54224 dark 4256 dead 0 nodes fit 12 flags 0x1
(dirty)LEB 81 free 32 dirty 8592 used 122320 free + dirty
8624 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)LEB 82 free
8 dirty 1112 used 129824 free + dirty 1120 dark 1120 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 83 free 24 dirty 104352 used
26568 free + dirty 104376 dark 4256 dead 0 nodes fit 24 flags 0x1
(dirty)LEB 84 free 56 dirty 9680 used 121208 free + dirty
9736 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)LEB 85 free
32 dirty 1112 used 129800 free + dirty 1144 dark 1144 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 86 free 72 dirty 88976 used
41896 free + dirty 89048 dark 4256 dead 0 nodes fit 20 flags 0x1
(dirty)LEB 87 free 0 dirty 90504 u> sed 40440 free + dirty
90504 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)LEB 88 free
128 dirty 82728 used 48088 free + dirty 82856 dark 4256 dead 0
nodes fit 19 flags 0x1 (dirty)LEB 89 free 64 dirty 104640 used
26240 free + dirty 104704 dark 4256 dead 0 nodes fit 24 flags 0x1
(dirty)LEB 90 free 88 dirty 68744 used 62112 free + dirty
68832 dark 4256 dead 0 nodes fit 16 flags 0x1 (dirty)LEB 91 free
152 dirty 1528 used 129264 free + dirty 1680 dark 1680 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 92 free 448 dirty 124120 used
6376 free + dirty 124568 dark 4256 dead 0 nodes fit 29 flags 0x10
(taken, bud of jhead 2 (data))LEB 93 free 72 dirty 480 used
130392 free + dirty 552 dark 552 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 94 free 64 dirty 108216 used 22664 free + dirty
108280 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)LEB 95 free
72 dirty 105400 used 25472 free + dirty 105472 dark 4256 dead 0
nodes fit 24 flags 0x1 (dirty)LEB 96 free 72 dirty 112456 used
18416 free + dirty 112528 dark 4256 dead 0 nodes fit 26 flags 0x1
(dirty)LEB 97 free 16 dirty 99960 used 30968 free + dirty
99976 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)LEB 98 free
24 dirty 58792 used 72128 free + dirty 58816 dark 4256 dead 0
nodes fit 13 flags 0x1 (dirty)LEB 99 free 0 dirty 92688 used
38256 free + dirty 92688 dark 4256 dead 0 nodes fit 21 flags 0x1
(dirty)LEB 100 free 88728 dirty 20312 used 21904 free + dirty
109040 flags 0x22 (dirty index)LEB 101 free 7152 dirty 107016 used
16776 free + dirty 114168 flags 0x22 (dirty index)LEB 102 free 40
dirty 100824 used 30080 free + dirty 100864 dark 4256 dead 0 nodes fit
23 flags 0x1 (dirty)LEB 103 free 128 dirty 98464 used 32352
free + dirty 98592 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)LEB
104 free 72 dirty 112808 used 18064 free + dirty 112880 dark
4256 dead 0 nodes fit 26 flags 0x1 (dirty)LEB 105 free 0 dirty
85704 used 45240 free + dirty 85704 dark 4256 dead 0 nodes fit 20
flags 0x1 (dirty)LEB 106 free 48 dirty 1488 used 129408 free +
dirty 1536 dark 1536 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 107
free 88 dirty 320 used 130536 free + dirty 408 dark 408 dead
0 nodes fit 0 flags 0x1 (dirty)LEB 108 free 48 dirty 960
used 129936 free + dirty 1008 dark 1008 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 109 free 8880 dirty 106784 used 15280 free + dirty
115664 flags 0x22 (dirty index)LEB 110 free 128 dirty 94504 used
36312 free + dirty 94632 dark 4256 dead 0 nodes fit 22 flags 0x1
(dirty)LEB 111 free 64 dirty 9728 used 121152 free + dirty
9792 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)LEB 112 free
40 dirty 1672 used 129232 free + dirty 1712 dark 1712 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 113 free 88 dirty 2400 used
128456 free + dirty 2488 dark 2488 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 114 free 152 dirty 15152 used 115640 free + dirty
15304 dark 4256 dead 0 nodes fit 3 flags 0x1 (dirty)LEB 115 free
40 dirty 64424 used 66480 free + dirty 64464 dark 4256 dead 0
nodes fit 15 flags 0x1 (dirty)LEB 116 free 32 dirty 1904 used
129008 free + dirty 1936 dark 1936 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 117 free 80 dirty 2184 used 128680 free + dirty
2264 dark 2264 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 118 free
144 dirty 82784 used 48016 free + dirty 82928 dark 4256 dead 0
nodes fit 19 flags 0x1 (dirty)LEB 119 free 80 dirty 101648 used
29216 free + dirty 101728 dark 4256 dead 0 nodes fit 23 flags 0x1
(dirty)LEB 120 free 136 dirty 99720 used 31088 free + dirty
99856 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)LEB 121 free
72 dirty 94688 used 36184 free + dirty 94760 dark 4256 dead 0
nodes fit 22 flags 0x1 (dirty)LEB 122 free 104 dirty 1920 used
128920 free + dirty 2024 dark 2024 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 123 free 144 dirty 1440 used 129360 free + dirty
1584 dark 1584 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 124 free
96 dirty 81088 used 49760 free + dirty 81184 dark 4256 dead 0
nodes fit 19 flags 0x1 (dirty)LEB 125 free 16 dirty 78320 > ; used
52608 free + dirty 78336 flags 0x22 (dirty index)LEB 126 free 120
dirty 89976 used 40848 free + dirty 90096 dark 4256 dead 0 nodes fit
21 flags 0x1 (dirty)LEB 127 free 8 dirty 72 used 130864
free + dirty 80 dark 80 dead 0 nodes fit 0 flags 0x1 (dirty)LEB
128 free 8 dirty 1120 used 129816 free + dirty 1128 dark
1128 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 129 free 88 dirty
2560 used 128296 free + dirty 2648 dark 2648 dead 0 nodes fit 0
flags 0x1 (dirty)LEB 130 free 144 dirty 1120 used 129680 free +
dirty 1264 dark 1264 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 131
free 104 dirty 1600 used 129240 free + dirty 1704 dark 1704 dead
0 nodes fit 0 flags 0x1 (dirty)LEB 132 free 40 dirty 1120
used 129784 free + dirty 1160 dark 1160 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 133 free 32 dirty 1192 used 129720 free + dirty
1224 dark 1224 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 134 free
88 dirty 2216 used 128640 free + dirty 2304 dark 2304 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 135 free 120 dirty 1760 used
129064 free + dirty 1880 dark 1880 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 136 free 88 dirty 160 used 130696 free + dirty
248 dark 248 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 137 free
8 dirty 160 used 130776 free + dirty 168 dark 168 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 138 free 144 dirty 800 used
130000 free + dirty 944 dark 944 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 139 free 56 dirty 2080 used 128808 free + dirty
2136 dark 2136 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 140 free
40 dirty 2392 used 128512 free + dirty 2432 dark 2432 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 141 free 40 dirty 800 used
130104 free + dirty 840 dark 840 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 142 free 24 dirty 320 used 130600 free + dirty
344 dark 344 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 143 free
48 dirty 1600 used 129296 free + dirty 1648 dark 1648 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 144 free 32 dirty 2400 used
128512 free + dirty 2432 dark 2432 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 145 free 104 dirty 1440 used 129400 free + dirty
1544 dark 1544 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 146 free
96 dirty 640 used 130208 free + dirty 736 dark 736 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 147 free 104 dirty 1120 used
129720 free + dirty 1224 dark 1224 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 148 free 48 dirty 0 used 130896 free + dirty
48 dark 0 dead 48 nodes fit 0 flags 0x3 (free)LEB 149 free
24 dirty 320 used 130600 free + dirty 344 dark 344 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 150 free 128 dirty 2360 used
128456 free + dirty 2488 dark 2488 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 151 free 72 dirty 1896 used 128976 free + dirty
1968 dark 1968 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 152 free
40 dirty 320 used 130584 free + dirty 360 dark 360 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 153 free 48 dirty 480 used
130416 free + dirty 528 dark 528 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 154 free 112 dirty 160 used 130672 free + dirty
272 dark 272 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 155 free
8 dirty 2584 used 128352 free + dirty 2592 dark 2592 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 156 free 88 dirty 1280 used
129576 free + dirty 1368 dark 1368 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 157 free 0 dirty 1344 used 129600 free + dirty
1344 dark 1344 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 158 free
72 dirty 2624 used 128248 free + dirty 2696 dark 2696 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 159 free 104 dirty 1600 used
129240 free + dirty 1704 dark 1704 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 160 free 24 dirty 1120 used 129800 free + dirty
1144 dark 1144 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 161 free
96 > ; dirty 1760 used 129088 free + dirty 1856 dark 1856 dead
0 nodes fit 0 flags 0x1 (dirty)LEB 162 free 48 dirty 480
used 130416 free + dirty 528 dark 528 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 163 free 88 dirty 464 used 130392 free + dirty
552 dark 552 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 164 free
48 dirty 3696 used 127200 free + dirty 3744 dark 3744 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 165 free 48 dirty 13688 used
117208 free + dirty 13736 dark 4256 dead 0 nodes fit 3 flags 0x1
(dirty)LEB 166 free 72 dirty 21328 used 109544 free + dirty
21400 dark 4256 dead 0 nodes fit 5 flags 0x1 (dirty)LEB 167 free
128 dirty 28752 used 102064 free + dirty 28880 dark 4256 dead 0
nodes fit 6 flags 0x1 (dirty)LEB 168 free 144 dirty 97760 used
33040 free + dirty 97904 dark 4256 dead 0 nodes fit 23 flags 0x1
(dirty)LEB 169 free 192 dirty 71616 used 59136 free + dirty
71808 flags 0x22 (dirty index)LEB 170 free 1352 dirty 60440 used
69152 free + dirty 61792 flags 0x22 (dirty index)LEB 171 free 144
dirty 1656 used 129144 free + dirty 1800 dark 1800 dead 0 nodes fit
0 flags 0x1 (dirty)LEB 172 free 104 dirty 23568 used 107272
free + dirty 23672 dark 4256 dead 0 nodes fit 5 flags 0x1 (dirty)LEB
173 free 112 dirty 20336 used 110496 free + dirty 20448 dark
4256 dead 0 nodes fit 4 flags 0x1 (dirty)LEB 174 free 72 dirty
27808 used 103064 free + dirty 27880 dark 4256 dead 0 nodes fit 6
flags 0x1 (dirty)LEB 175 free 120 dirty 30488 used 100336 free +
dirty 30608 dark 4256 dead 0 nodes fit 7 flags 0x1 (dirty)LEB 176
free 64 dirty 160 used 130720 free + dirty 224 dark 224 dead
0 nodes fit 0 flags 0x1 (dirty)LEB 177 free 120 dirty 23416
used 107408 free + dirty 23536 dark 4256 dead 0 nodes fit 5 flags 0x1
(dirty)LEB 178 free 48 dirty 55992 used 74904 free + dirty
56040 dark 4256 dead 0 nodes fit 13 flags 0x1 (dirty)LEB 179 free
88 dirty 1904 used 128952 free + dirty 1992 dark 1992 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 180 free 96 dirty 9712 used
121136 free + dirty 9808 dark 4256 dead 0 nodes fit 2 flags 0x1
(dirty)LEB 181 free 72 dirty 320 used 130552 free + dirty
392 dark 392 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 182 free
128 dirty 23920 used 106896 free + dirty 24048 dark 4256 dead 0
nodes fit 5 flags 0x1 (dirty)LEB 183 free 80 dirty 800 used
130064 free + dirty 880 dark 880 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 184 free 32 dirty 320 used 130592 free + dirty
352 dark 352 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 185 free
8 dirty 2400 used 128536 free + dirty 2408 dark 2408 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 186 free 8 dirty 64 used
130872 free + dirty 72 dark 72 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 187 free 0 dirty 960 used 129984 free + dirty
960 dark 960 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 188 free
152 dirty 480 used 130312 free + dirty 632 dark 632 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 189 free 48 dirty 640 used
130256 free + dirty 688 dark 688 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 190 free 56 dirty 93312 used 37576 free + dirty
93368 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)LEB 191 free
104 dirty 1920 used 128920 free + dirty 2024 dark 2024 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 192 free 0 dirty 160 used
130784 free + dirty 160 dark 160 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 193 free 0 dirty 800 used 130144 free + dirty
800 dark 800 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 194 free
24 dirty 128 used 130792 free + dirty 152 dark 152 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 195 free 40 dirty 15816 used
115088 free + dirty 15856 dark 4256 dead 0 nodes fit 3 flags 0x1
(dirty)LEB 196 free 32 dirty 39160 used 91752 free + dirty
39192 dark 4256 dead 0 nodes fit 9 flags 0x1 (dirty)LEB 197 free
40 dirty 36632 used 94272 free + dirty 36672 dark 4256 dead
0 &nb> sp; nodes fit 8 flags 0x1 (dirty)LEB 198 free 16 dirty
62008 used 68920 free + dirty 62024 dark 4256 dead 0 nodes fit 14
flags 0x1 (dirty)LEB 199 free 40 dirty 1600 used 129304 free +
dirty 1640 dark 1640 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 200
free 56 dirty 160 used 130728 free + dirty 216 dark 216 dead
0 nodes fit 0 flags 0x1 (dirty)LEB 201 free 8 dirty 108008
used 22928 free + dirty 108016 dark 4256 dead 0 nodes fit 25 flags 0x1
(dirty)LEB 202 free 16 dirty 64 used 130864 free + dirty
80 dark 80 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 203 free
71648 dirty 31168 used 28128 free + dirty 102816 flags 0x22 (dirty
index)LEB 204 free 24 dirty 66320 used 64600 free + dirty
66344 dark 4256 dead 0 nodes fit 15 flags 0x1 (dirty)LEB 205 free
8 dirty 1760 used 129176 free + dirty 1768 dark 1768 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 206 free 1048 dirty 125856 used
4040 free + dirty 126904 dark 4256 dead 0 nodes fit 29 flags 0x10
(taken, bud of jhead 2 (data))LEB 207 free 80 dirty 1480 used
129384 free + dirty 1560 dark 1560 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 208 free 104 dirty 9272 used 121568 free + dirty
9376 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)LEB 209 free
56 dirty 76344 used 54544 free + dirty 76400 dark 4256 dead 0
nodes fit 17 flags 0x1 (dirty)LEB 210 free 40 dirty 85824 used
45080 free + dirty 85864 dark 4256 dead 0 nodes fit 20 flags 0x1
(dirty)LEB 211 free 80 dirty 984 used 129880 free + dirty
1064 dark 1064 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 212 free
16 dirty 49080 used 81848 free + dirty 49096 dark 4256 dead 0
nodes fit 11 flags 0x1 (dirty)LEB 213 free 48 dirty 93840 used
37056 free + dirty 93888 dark 4256 dead 0 nodes fit 22 flags 0x1
(dirty)LEB 214 free 24 dirty 104256 used 26664 free + dirty
104280 dark 4256 dead 0 nodes fit 24 flags 0x1 (dirty)LEB 215 free
112 dirty 111328 used 19504 free + dirty 111440 dark 4256 dead 0
nodes fit 26 flags 0x1 (dirty)LEB 216 free 32 dirty 108456 used
22456 free + dirty 108488 dark 4256 dead 0 nodes fit 25 flags 0x1
(dirty)LEB 217 free 144 dirty 100152 used 30648 free + dirty
100296 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)LEB 218 free
32 dirty 108136 used 22776 free + dirty 108168 dark 4256 dead 0
nodes fit 25 flags 0x1 (dirty)LEB 219 free 264 dirty 56600 used
74080 free + dirty 56864 flags 0x22 (dirty index)LEB 220 free 40
dirty 89960 used 40944 free + dirty 90000 dark 4256 dead 0 nodes fit
21 flags 0x1 (dirty)LEB 221 free 56 dirty 23272 used 107616
free + dirty 23328 dark 4256 dead 0 nodes fit 5 flags 0x1 (dirty)LEB
222 free 144 dirty 480 used 130320 free + dirty 624 dark
624 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 223 free 96 dirty
1120 used 129728 free + dirty 1216 dark 1216 dead 0 nodes fit 0
flags 0x1 (dirty)LEB 224 free 80 dirty 640 used 130224 free +
dirty 720 dark 720 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 225
free 96 dirty 2560 used 128288 free + dirty 2656 dark 2656 dead
0 nodes fit 0 flags 0x1 (dirty)LEB 226 free 64 dirty 1120
used 129760 free + dirty 1184 dark 1184 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 227 free 24 dirty 92784 used 38136 free + dirty
92808 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)LEB 228 free
0 dirty 18472 used 112472 free + dirty 18472 dark 4256 dead 0
nodes fit 4 flags 0x1 (dirty)LEB 229 free 0 dirty 1760 used
129184 free + dirty 1760 dark 1760 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 230 free 40 dirty 640 used 130264 free + dirty
680 dark 680 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 231 free
24 dirty 1280 used 129640 free + dirty 1304 dark 1304 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 232 free 40 dirty 640 used
130264 free + dirty 680 dark 680 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 233 free 0 dirty 1280 used 129664 free + dirty
1280 dark 1280 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 234 free
0 dirty 80 used 130864 free + dirty 80 dark 80 dead 0
node> s fit 0 flags 0x1 (dirty)LEB 235 free 64 dirty 320 used
130560 free + dirty 384 dark 384 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 236 free 56 dirty 320 used 130568 free + dirty
376 dark 376 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 237 free
0 dirty 0 used 130944 free + dirty 0 dark 0 dead 0
nodes fit 0 flags 0x10 (taken, jhead 0(GC))LEB 238 free 16 dirty
960 used 129968 free + dirty 976 dark 976 dead 0 nodes fit 0
flags 0x1 (dirty)LEB 239 free 48 dirty 100736 used 30160 free +
dirty 100784 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)LEB 240
free 88 dirty 110216 used 20640 free + dirty 110304 dark 4256 dead
0 nodes fit 25 flags 0x1 (dirty)LEB 241 free 8 dirty 960
used 129976 free + dirty 968 dark 968 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 242 free 24 dirty 20632 used 110288 free + dirty
20656 dark 4256 dead 0 nodes fit 4 flags 0x1 (dirty)LEB 243 free
0 dirty 2720 used 128224 free + dirty 2720 dark 2720 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 244 free 144 dirty 640 used
130160 free + dirty 784 dark 784 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 245 free 1400 dirty 110912 used 18632 free + dirty
112312 flags 0x22 (dirty index)LEB 246 free 0 dirty 640 used
130304 free + dirty 640 dark 640 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 247 free 32 dirty 640 used 130272 free + dirty
672 dark 672 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 248 free
112 dirty 1760 used 129072 free + dirty 1872 dark 1872 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 249 free 96 dirty 3360 used
127488 free + dirty 3456 dark 3456 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 250 free 0 dirty 1280 used 129664 free + dirty
1280 dark 1280 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 251 free
48 dirty 54736 used 76160 free + dirty 54784 dark 4256 dead 0
nodes fit 12 flags 0x1 (dirty)LEB 252 free 88 dirty 47472 used
83384 free + dirty 47560 dark 4256 dead 0 nodes fit 11 flags 0x1
(dirty)LEB 253 free 0 dirty 78304 used 52640 free + dirty
78304 dark 4256 dead 0 nodes fit 18 flags 0x1 (dirty)LEB 254 free
48 dirty 109800 used 21096 free + dirty 109848 dark 4256 dead 0
nodes fit 25 flags 0x1 (dirty)LEB 255 free 120 dirty 19704 used
111120 free + dirty 19824 dark 4256 dead 0 nodes fit 4 flags 0x1
(dirty)LEB 256 free 136 dirty 98760 used 32048 free + dirty
98896 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)LEB 257 free
136 dirty 80736 used 50072 free + dirty 80872 dark 4256 dead 0
nodes fit 19 flags 0x1 (dirty)LEB 258 free 40 dirty 480 used
130424 free + dirty 520 dark 520 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 259 free 48 dirty 109424 used 21472 free + dirty
109472 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)LEB 260 free
88 dirty 2080 used 128776 free + dirty 2168 dark 2168 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 261 free 104 dirty 480 used
130360 free + dirty 584 dark 584 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 262 free 240 dirty 125416 used 5288 free + dirty
125656 dark 4256 dead 0 nodes fit 29 flags 0x1 (dirty)LEB 263 free
16 dirty 640 used 130288 free + dirty 656 dark 656 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 264 free 64 dirty 2240 used
128640 free + dirty 2304 dark 2304 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 265 free 0 dirty 24520 used 106424 free + dirty
24520 dark 4256 dead 0 nodes fit 5 flags 0x1 (dirty)LEB 266 free
128 dirty 160 used 130656 free + dirty 288 dark 288 dead 0
nodes fit 0 flags 0x0 (not categorized)LEB 267 free 104 dirty
124248 used 6592 free + dirty 124352 dark 4256 dead 0 nodes fit 29
flags 0x1 (dirty)LEB 268 free 88 dirty 160 used 130696 free +
dirty 248 dark 248 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB
269 free 72 dirty 160 used 130712 free + dirty 232 dark
232 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB 270 free
120 dirty 960 used 129864 free + dirty 1080 dark 1080 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 271> free 88 dirty 103400 used
27456 free + dirty 103488 dark 4256 dead 0 nodes fit 24 flags 0x1
(dirty)LEB 272 free 96 dirty 112344 used 18504 free + dirty
112440 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)LEB 273 free
88 dirty 2080 used 128776 free + dirty 2168 dark 2168 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 274 free 112 dirty 75144 used
55688 free + dirty 75256 dark 4256 dead 0 nodes fit 17 flags 0x1
(dirty)LEB 275 free 88 dirty 93264 used 37592 free + dirty
93352 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)LEB 276 free
56 dirty 99160 used 31728 free + dirty 99216 dark 4256 dead 0
nodes fit 23 flags 0x1 (dirty)LEB 277 free 64 dirty 57136 used
73744 free + dirty 57200 dark 4256 dead 0 nodes fit 13 flags 0x1
(dirty)LEB 278 free 80 dirty 8472 used 122392 free + dirty
8552 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)LEB 279 free
80 dirty 2080 used 128784 free + dirty 2160 dark 2160 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 280 free 0 dirty 8576 used
122368 free + dirty 8576 dark 4256 dead 0 nodes fit 2 flags 0x1
(dirty)LEB 281 free 128 dirty 81352 used 49464 free + dirty
81480 dark 4256 dead 0 nodes fit 19 flags 0x1 (dirty)LEB 282 free
56 dirty 1920 used 128968 free + dirty 1976 dark 1976 dead 0
nodes fit 0 flags 0x0 (not categorized)LEB 283 free 0 dirty
1920 used 129024 free + dirty 1920 dark 1920 dead 0 nodes fit 0
flags 0x1 (dirty)LEB 284 free 16 dirty 2080 used 128848 free +
dirty 2096 dark 2096 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB
285 free 64 dirty 320 used 130560 free + dirty 384 dark
384 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB 286 free
72 dirty 109792 used 21080 free + dirty 109864 dark 4256 dead 0
nodes fit 25 flags 0x1 (dirty)LEB 287 free 0 dirty 98144 used
32800 free + dirty 98144 dark 4256 dead 0 nodes fit 23 flags 0x1
(dirty)LEB 288 free 16576 dirty 89760 used 24608 free + dirty
106336 flags 0x22 (dirty index)LEB 289 free 144 dirty 11304 used
119496 free + dirty 11448 dark 4256 dead 0 nodes fit 2 flags 0x1
(dirty)LEB 290 free 104 dirty 58744 used 72096 free + dirty
58848 dark 4256 dead 0 nodes fit 13 flags 0x1 (dirty)LEB 291 free
144 dirty 64856 used 65944 free + dirty 65000 dark 4256 dead 0
nodes fit 15 flags 0x1 (dirty)LEB 292 free 88 dirty 320 used
130536 free + dirty 408 dark 408 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 293 free 4952 dirty 124872 used 1120 free + dirty
129824 dark 4256 dead 0 nodes fit 30 flags 0x10 (taken, jhead 1 (base))LEB
294 free 32 dirty 1440 used 129472 free + dirty 1472 dark
1472 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB 295 free
128 dirty 960 used 129856 free + dirty 1088 dark 1088 dead 0
nodes fit 0 flags 0x0 (not categorized)LEB 296 free 8 dirty
1920 used 129016 free + dirty 1928 dark 1928 dead 0 nodes fit 0
flags 0x0 (not categorized)LEB 297 free 128 dirty 800 used
130016 free + dirty 928 dark 928 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 298 free 136 dirty 1120 used 129688 free + dirty
1256 dark 1256 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB
299 free 16 dirty 1440 used 129488 free + dirty 1456 dark
1456 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB 300 free
32 dirty 103952 used 26960 free + dirty 103984 flags 0x22 (dirty
index)LEB 301 free 40 dirty 96 used 130808 free + dirty
136 dark 136 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB
302 free 80 dirty 800 used 130064 free + dirty 880 dark
880 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB 303 free
152 dirty 1120 used 129672 free + dirty 1272 dark 1272 dead 0
nodes fit 0 flags 0x0 (not categorized)LEB 304 free 0 dirty
480 used 130464 free + dirty 480 dark 480 dead 0 nodes fit 0
flags 0x0 (not categorized)LEB 305 free 96 dirty 2080 used
128768 free + dirty 2176 dark 2176 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 306 free 64 dirty 1440 used 129440 free + dirty
1504 dark 1504 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB
307 free 16 dirty 1920 used 129008 free + dirty 1936 da> rk
1936 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 308 free 16 dirty
1920 used 129008 free + dirty 1936 dark 1936 dead 0 nodes fit 0
flags 0x1 (dirty)LEB 309 free 8 dirty 1440 used 129496 free +
dirty 1448 dark 1448 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 310
free 136 dirty 1760 used 129048 free + dirty 1896 dark 1896 dead
0 nodes fit 0 flags 0x1 (dirty)LEB 311 free 24 dirty 7496
used 123424 free + dirty 7520 dark 4256 dead 0 nodes fit 1 flags 0x1
(dirty)LEB 312 free 680 dirty 125816 used 4448 free + dirty
126496 dark 4256 dead 0 nodes fit 29 flags 0x10 (taken, bud of jhead 2
(data))LEB 313 free 0 dirty 15928 used 115016 free + dirty
15928 dark 4256 dead 0 nodes fit 3 flags 0x1 (dirty)LEB 314 free
24 dirty 42344 used 88576 free + dirty 42368 dark 4256 dead 0
nodes fit 9 flags 0x1 (dirty)LEB 315 free 96 dirty 99848 used
31000 free + dirty 99944 dark 4256 dead 0 nodes fit 23 flags 0x1
(dirty)LEB 316 free 48 dirty 95152 used 35744 free + dirty
95200 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)LEB 317 free
8 dirty 0 used 130936 free + dirty 8 dark 0 dead 8
nodes fit 0 flags 0x3 (free)LEB 318 free 72 dirty 8088 used
122784 free + dirty 8160 dark 4256 dead 0 nodes fit 1 flags 0x1
(dirty)LEB 319 free 40 dirty 1440 used 129464 free + dirty
1480 dark 1480 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB
320 free 120 dirty 960 used 129864 free + dirty 1080 dark
1080 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 321 free 32 dirty
480 used 130432 free + dirty 512 dark 512 dead 0 nodes fit 0
flags 0x1 (dirty)LEB 322 free 40 dirty 1600 used 129304 free +
dirty 1640 dark 1640 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 323
free 56 dirty 108416 used 22472 free + dirty 108472 dark 4256 dead
0 nodes fit 25 flags 0x1 (dirty)LEB 324 free 96 dirty 960
used 129888 free + dirty 1056 dark 1056 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 325 free 0 dirty 2720 used 128224 free + dirty
2720 dark 2720 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 326 free
56 dirty 9344 used 121544 free + dirty 9400 dark 4256 dead 0
nodes fit 2 flags 0x0 (not categorized)LEB 327 free 8 dirty
1904 used 129032 free + dirty 1912 dark 1912 dead 0 nodes fit 0
flags 0x0 (not categorized)LEB 328 free 96 dirty 8376 used
122472 free + dirty 8472 dark 4256 dead 0 nodes fit 1 flags 0x1
(dirty)LEB 329 free 66160 dirty 41304 used 23480 free + dirty
107464 flags 0x22 (dirty index)LEB 330 free 0 dirty 109496 used
21448 free + dirty 109496 dark 4256 dead 0 nodes fit 25 flags 0x1
(dirty)LEB 331 free 0 dirty 89744 used 41200 free + dirty
89744 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)LEB 332 free
128 dirty 111744 used 19072 free + dirty 111872 dark 4256 dead 0
nodes fit 26 flags 0x1 (dirty)LEB 333 free 56 dirty 105848 used
25040 free + dirty 105904 dark 4256 dead 0 nodes fit 24 flags 0x1
(dirty)LEB 334 free 80 dirty 110080 used 20784 free + dirty
110160 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)LEB 335 free
112 dirty 52312 used 78520 free + dirty 52424 dark 4256 dead 0
nodes fit 12 flags 0x1 (dirty)LEB 336 free 40 dirty 99824 used
31080 free + dirty 99864 dark 4256 dead 0 nodes fit 23 flags 0x1
(dirty)LEB 337 free 128 dirty 111152 used 19664 free + dirty
111280 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)LEB 338 free
24 dirty 74768 used 56152 free + dirty 74792 dark 4256 dead 0
nodes fit 17 flags 0x1 (dirty)LEB 339 free 128 dirty 87632 used
43184 free + dirty 87760 dark 4256 dead 0 nodes fit 20 flags 0x1
(dirty)LEB 340 free 32 dirty 93392 used 37520 free + dirty
93424 dark 4256 dead 0 nodes fit 21 flags 0x1 (dirty)LEB 341 free
56 dirty 93800 used 37088 free + dirty 93856 dark 4256 dead 0
nodes fit 22 flags 0x1 (dirty)LEB 342 free 0 dirty 86024 used
44920 free + dirty 86024 dark 4256 dead 0 nodes fit 20 flags 0x1
(dirty)LEB 343 free 31880 dirty 81056 used 18008 free + dirty
112936 flags 0x22 (dirty index)LEB 344 free 0 dirty 130944 used
0 free + dirty 130944 dark 4256 dead 0 nodes fit 30 flags 0x5 (f>
reeable)LEB 345 free 40176 dirty 62576 used 28192 free + dirty
102752 flags 0x22 (dirty index)LEB 346 free 96 dirty 108880 used
21968 free + dirty 108976 dark 4256 dead 0 nodes fit 25 flags 0x1
(dirty)LEB 347 free 144 dirty 48248 used 82552 free + dirty
48392 dark 4256 dead 0 nodes fit 11 flags 0x1 (dirty)LEB 348 free
40 dirty 99680 used 31224 free + dirty 99720 dark 4256 dead 0
nodes fit 23 flags 0x1 (dirty)LEB 349 free 120 dirty 104912 used
25912 free + dirty 105032 dark 4256 dead 0 nodes fit 24 flags 0x1
(dirty)LEB 350 free 136 dirty 2400 used 128408 free + dirty
2536 dark 2536 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 351 free
96 dirty 8152 used 122696 free + dirty 8248 dark 4256 dead 0
nodes fit 1 flags 0x1 (dirty)LEB 352 free 96 dirty 31248 used
99600 free + dirty 31344 dark 4256 dead 0 nodes fit 7 flags 0x1
(dirty)LEB 353 free 8 dirty 1440 used 129496 free + dirty
1448 dark 1448 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 354 free
120 dirty 1112 used 129712 free + dirty 1232 dark 1232 dead 0
nodes fit 0 flags 0x0 (not categorized)LEB 355 free 56 dirty
25824 used 105064 free + dirty 25880 dark 4256 dead 0 nodes fit 6
flags 0x1 (dirty)LEB 356 free 112 dirty 1840 used 128992 free +
dirty 1952 dark 1952 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB
357 free 48 dirty 97264 used 33632 free + dirty 97312 dark
4256 dead 0 nodes fit 22 flags 0x1 (dirty)LEB 358 free 8 dirty
6736 used 124200 free + dirty 6744 dark 4256 dead 0 nodes fit 1
flags 0x1 (dirty)LEB 359 free 72 dirty 104552 used 26320 free +
dirty 104624 dark 4256 dead 0 nodes fit 24 flags 0x1 (dirty)LEB 360
free 136 dirty 3008 used 127800 free + dirty 3144 dark 3144 dead
0 nodes fit 0 flags 0x0 (not categorized)LEB 361 free 48 dirty
106704 used 24192 free + dirty 106752 dark 4256 dead 0 nodes fit 25
flags 0x1 (dirty)LEB 362 free 40 dirty 95136 used 35768 free +
dirty 95176 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)LEB 363
free 128 dirty 9264 used 121552 free + dirty 9392 dark 4256 dead
0 nodes fit 2 flags 0x1 (dirty)LEB 364 free 96 dirty 320
used 130528 free + dirty 416 dark 416 dead 0 nodes fit 0 flags 0x0
(not categorized)LEB 365 free 48 dirty 94408 used 36488 free +
dirty 94456 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)LEB 366
free 72 dirty 1288 used 129584 free + dirty 1360 dark 1360 dead
0 nodes fit 0 flags 0x0 (not categorized)LEB 367 free 8 dirty
8808 used 122128 free + dirty 8816 dark 4256 dead 0 nodes fit 2
flags 0x1 (dirty)LEB 368 free 56 dirty 2368 used 128520 free +
dirty 2424 dark 2424 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 369
free 32 dirty 41872 used 89040 free + dirty 41904 dark 4256 dead
0 nodes fit 9 flags 0x1 (dirty)LEB 370 free 136 dirty 26984
used 103824 free + dirty 27120 dark 4256 dead 0 nodes fit 6 flags 0x0
(not categorized)LEB 371 free 152 dirty 1864 used 128928 free +
dirty 2016 dark 2016 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB
372 free 24 dirty 1576 used 129344 free + dirty 1600 dark
1600 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 373 free 16 dirty
2368 used 128560 free + dirty 2384 dark 2384 dead 0 nodes fit 0
flags 0x1 (dirty)LEB 374 free 128 dirty 98464 used 32352 free +
dirty 98592 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)LEB 375
free 24 dirty 1480 used 129440 free + dirty 1504 dark 1504 dead
0 nodes fit 0 flags 0x0 (not categorized)LEB 376 free 16 dirty
1328 used 129600 free + dirty 1344 dark 1344 dead 0 nodes fit 0
flags 0x0 (not categorized)LEB 377 free 96 dirty 2376 used
128472 free + dirty 2472 dark 2472 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 378 free 8 dirty 1760 used 129176 free + dirty
1768 dark 1768 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB
379 free 80 dirty 112208 used 18656 free + dirty 112288 dark
4256 dead 0 nodes fit 26 flags 0x1 (dirty)LEB 380 free 144 dirty
99024 used 31776 free + dirty 99168 dark 4256 dead 0 nodes fit 23
flags 0x1 (dirty)LEB 381 free 40 dirty 81256 used 49648 free +
dirty 81296 dark 4256 dead 0 nodes fit 19 flags 0x1 > ; (dirty)LEB
382 free 96 dirty 1072 used 129776 free + dirty 1168 dark
1168 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB 383 free
96 dirty 2344 used 128504 free + dirty 2440 dark 2440 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 384 free 16 dirty 760 used
130168 free + dirty 776 dark 776 dead 0 nodes fit 0 flags 0x0 (not
categorized)LEB 385 free 56 dirty 2672 used 128216 free + dirty
2728 dark 2728 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 386 free
40 dirty 95928 used 34976 free + dirty 95968 dark 4256 dead 0
nodes fit 22 flags 0x1 (dirty)LEB 387 free 8 dirty 99496 used
31440 free + dirty 99504 dark 4256 dead 0 nodes fit 23 flags 0x1
(dirty)LEB 388 free 72 dirty 110648 used 20224 free + dirty
110720 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)LEB 389 free
152 dirty 99536 used 31256 free + dirty 99688 dark 4256 dead 0
nodes fit 23 flags 0x1 (dirty)LEB 390 free 5888 dirty 104784 used
20272 free + dirty 110672 flags 0x22 (dirty index)LEB 391 free 152
dirty 71184 used 59608 free + dirty 71336 dark 4256 dead 0 nodes fit
16 flags 0x1 (dirty)LEB 392 free 16 dirty 2240 used 128688
free + dirty 2256 dark 2256 dead 0 nodes fit 0 flags 0x0 (not
categorized)LEB 393 free 112 dirty 2232 used 128600 free + dirty
2344 dark 2344 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 394 free
40 dirty 1088 used 129816 free + dirty 1128 dark 1128 dead 0
nodes fit 0 flags 0x0 (not categorized)LEB 395 free 8 dirty
84400 used 46536 free + dirty 84408 dark 4256 dead 0 nodes fit 19
flags 0x1 (dirty)LEB 396 free 136 dirty 93696 used 37112 free +
dirty 93832 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)LEB 397
free 48 dirty 110888 used 20008 free + dirty 110936 dark 4256 dead
0 nodes fit 26 flags 0x1 (dirty)LEB 398 free 58064 dirty 54072
used 18808 free + dirty 112136 flags 0x22 (dirty index)LEB 399 free
120 dirty 84936 used 45888 free + dirty 85056 dark 4256 dead 0
nodes fit 19 flags 0x1 (dirty)LEB 400 free 77168 dirty 37248 used
16528 free + dirty 114416 flags 0x22 (dirty index)LEB 401 free 96
dirty 92512 used 38336 free + dirty 92608 dark 4256 dead 0 nodes fit
21 flags 0x1 (dirty)LEB 402 free 136 dirty 9360 used 121448
free + dirty 9496 dark 4256 dead 0 nodes fit 2 flags 0x0 (not
categorized)LEB 403 free 144 dirty 480 used 130320 free + dirty
624 dark 624 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB
404 free 27096 dirty 74360 used 29488 free + dirty 101456 flags
0x22 (dirty index)LEB 405 free 0 dirty 63200 used 67744 free +
dirty 63200 dark 4256 dead 0 nodes fit 14 flags 0x1 (dirty)LEB 406
free 64 dirty 2672 used 128208 free + dirty 2736 dark 2736 dead
0 nodes fit 0 flags 0x0 (not categorized)LEB 407 free 88 dirty
109440 used 21416 free + dirty 109528 dark 4256 dead 0 nodes fit 25
flags 0x1 (dirty)LEB 408 free 96 dirty 110248 used 20600 free +
dirty 110344 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)LEB 409
free 88 dirty 3912 used 126944 free + dirty 4000 dark 4000 dead
0 nodes fit 0 flags 0x1 (dirty)LEB 410 free 16 dirty 1768
used 129160 free + dirty 1784 dark 1784 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 411 free 88 dirty 5312 used 125544 free + dirty
5400 dark 4256 dead 0 nodes fit 1 flags 0x1 (dirty)LEB 412 free
130944 dirty 0 used 0 free + dirty 130944 dark 4256 dead 0
nodes fit 30 flags 0x10 (taken, bud of jhead 2 (data))LEB 413 free 112
dirty 9480 used 121352 free + dirty 9592 dark 4256 dead 0 nodes fit
2 flags 0x1 (dirty)LEB 414 free 0 dirty 101064 used 29880
free + dirty 101064 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)LEB
415 free 48 dirty 98656 used 32240 free + dirty 98704 dark
4256 dead 0 nodes fit 23 flags 0x1 (dirtyLEB 416 free 48 dirty
86224 used 44672 free + dirty 86272 dark 4256 dead 0 nodes fit 20
flags 0x1 (dirty)LEB 417 free 48 dirty 16552 used 114344 free +
dirty 16600 dark 4256 dead 0 nodes fit 3 flags 0x1 (dirty)LEB 418
free 128 dirty 76176 used 54640 free + dirty 76304 dark 4256 dead
0 nodes fit 17 flags 0x1 (dirty)LEB 419 free 82224 dirty 30024
used 18696 free + dirty 112248 flags 0x22 (dirty index)LEB 420 > free
38112 dirty 70008 used 22824 free + dirty 108120 flags 0x22 (dirty
index)LEB 421 free 42104 dirty 66416 used 22424 free + dirty
108520 flags 0x22 (dirty index)LEB 422 free 15768 dirty 98416 used
16760 free + dirty 114184 flags 0x22 (dirty index)LEB 423 free 112
dirty 2504 used 128328 free + dirty 2616 dark 2616 dead 0 nodes fit
0 flags 0x1 (dirty)LEB 424 free 56 dirty 3184 used 127704
free + dirty 3240 dark 3240 dead 0 nodes fit 0 flags 0x1 (dirty)LEB
425 free 8 dirty 61376 used 69560 free + dirty 61384 dark
4256 dead 0 nodes fit 14 flags 0x1 (dirty)LEB 426 free 8 dirty
880 used 130056 free + dirty 888 dark 888 dead 0 nodes fit 0
flags 0x0 (not categorized)LEB 427 free 24 dirty 1848 used
129072 free + dirty 1872 dark 1872 dead 0 nodes fit 0 flags 0x0 (not
categorized)LEB 428 free 0 dirty 888 used 130056 free + dirty
888 dark 888 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB
429 free 48 dirty 640 used 130256 free + dirty 688 dark
688 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB 430 free
16 dirty 1432 used 129496 free + dirty 1448 dark 1448 dead 0
nodes fit 0 flags 0x0 (not categorized)LEB 431 free 8 dirty
64 used 130872 free + dirty 72 dark 72 dead 0 nodes fit 0
flags 0x0 (not categorized)LEB 432 free 56 dirty 1984 used
128904 free + dirty 2040 dark 2040 dead 0 nodes fit 0 flags 0x0 (not
categorized)LEB 433 free 32 dirty 2992 used 127920 free + dirty
3024 dark 3024 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 434 free
96 dirty 107624 used 23224 free + dirty 107720 dark 4256 dead 0
nodes fit 25 flags 0x1 (dirty)LEB 435 free 80 dirty 18656 used
112208 free + dirty 18736 dark 4256 dead 0 nodes fit 4 flags 0x1
(dirty)LEB 436 free 48 dirty 96312 used 34584 free + dirty
96360 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)LEB 437 free
88 dirty 111288 used 19568 free + dirty 111376 dark 4256 dead 0
nodes fit 26 flags 0x1 (dirty)LEB 438 free 104 dirty 1824 used
129016 free + dirty 1928 dark 1928 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 439 free 0 dirty 1376 used 129568 free + dirty
1376 dark 1376 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 440 free
40 dirty 94600 used 36304 free + dirty 94640 dark 4256 dead 0
nodes fit 22 flags 0x1 (dirty)LEB 441 free 144 dirty 112056 used
18744 free + dirty 112200 dark 4256 dead 0 nodes fit 26 flags 0x1
(dirty)LEB 442 free 72 dirty 107008 used 23864 free + dirty
107080 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)LEB 443 free
120 dirty 98544 used 32280 free + dirty 98664 dark 4256 dead 0
nodes fit 23 flags 0x1 (dirty)LEB 444 free 8 dirty 91832 used
39104 free + dirty 91840 dark 4256 dead 0 nodes fit 21 flags 0x1
(dirty)LEB 445 free 104 dirty 96344 used 34496 free + dirty
96448 dark 4256 dead 0 nodes fit 22 flags 0x1 (dirty)LEB 446 free
152 dirty 91600 used 39192 free + dirty 91752 dark 4256 dead 0
nodes fit 21 flags 0x1 (dirty)LEB 447 free 8 dirty 9008 used
121928 free + dirty 9016 dark 4256 dead 0 nodes fit 2 flags 0x1
(dirty)LEB 448 free 120 dirty 1440 used 129384 free + dirty
1560 dark 1560 dead 0 nodes fit 0 flags 0x0 (not categorized)LEB
449 free 144 dirty 7480 used 123320 free + dirty 7624 dark
4256 dead 0 nodes fit 1 flags 0x1 (dirty)LEB 450 free 88 dirty
7352 used 123504 free + dirty 7440 dark 4256 dead 0 nodes fit 1
flags 0x0 (not categorized)LEB 451 free 80 dirty 58008 used
72856 free + dirty 58088 dark 4256 dead 0 nodes fit 13 flags 0x1
(dirty)LEB 452 free 9040 dirty 95656 used 26248 free + dirty
104696 flags 0x22 (dirty index)LEB 453 free 8152 dirty 113096 used
9696 free + dirty 121248 flags 0x30 (index, taken)LEB 454 free
40 dirty 99984 used 30920 free + dirty 100024 dark 4256 dead 0
nodes fit 23 flags 0x1 (dirty)LEB 455 free 56 dirty 7832 used
123056 free + dirty 7888 dark 4256 dead 0 nodes fit 1 flags 0x1
(dirty)LEB 456 free 64 dirty 111448 used 19432 free + dirty
111512 dark 4256 dead 0 nodes fit 26 flags 0x1 (dirty)LEB 457 free
40 dirty 95480 used 35424 free + dirty 95520 dark 4256 dead 0
nodes fit 22 flags 0x1 (dirty)L> EB 458 free 60056 dirty 53472 used
17416 free + dirty 113528 flags 0x22 (dirty index)LEB 459 free 16
dirty 100136 used 30792 free + dirty 100152 dark 4256 dead 0 nodes fit
23 flags 0x1 (dirty)LEB 460 free 0 dirty 320 used 130624
free + dirty 320 dark 320 dead 0 nodes fit 0 flags 0x0 (not
categorized)LEB 461 free 104 dirty 109608 used 21232 free + dirty
109712 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)LEB 462 free
64 dirty 114528 used 16352 free + dirty 114592 dark 4256 dead 0
nodes fit 26 flags 0x1 (dirty)LEB 463 free 152 dirty 109624 used
21168 free + dirty 109776 dark 4256 dead 0 nodes fit 25 flags 0x1
(dirty)LEB 464 free 112 dirty 99080 used 31752 free + dirty
99192 dark 4256 dead 0 nodes fit 23 flags 0x1 (dirty)LEB 465 free
72 dirty 99264 used 31608 free + dirty 99336 dark 4256 dead 0
nodes fit 23 flags 0x1 (dirty)LEB 466 free 48 dirty 480 used
130416 free + dirty 528 dark 528 dead 0 nodes fit 0 flags 0x0 (not
categorized)LEB 467 free 152 dirty 2560 used 128232 free + dirty
2712 dark 2712 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 468 free
55128 dirty 47592 used 28224 free + dirty 102720 flags 0x22 (dirty
index)LEB 469 free 130944 dirty 0 used 0 free + dirty
130944 dark 4256 dead 0 nodes fit 30 flags 0x10 (taken, jhead 2(data))LEB
470 free 40 dirty 1968 used 128936 free + dirty 2008 dark
2008 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 471 free 144 dirty
960 used 129840 free + dirty 1104 dark 1104 dead 0 nodes fit 0
flags 0x0 (not categorized)LEB 472 free 32 dirty 9000 used
121912 free + dirty 9032 dark 4256 dead 0 nodes fit 2 flags 0x1
(dirty)LEB 473 free 144 dirty 9048 used 121752 free + dirty
9192 dark 4256 dead 0 nodes fit 2 flags 0x1 (dirty)LEB 474 free
0 dirty 126600 used 4344 free + dirty 126600 dark 4256 dead 0
nodes fit 29 flags 0x1 (dirty)LEB 475 free 152 dirty 63856 used
66936 free + dirty 64008 dark 4256 dead 0 nodes fit 15 flags 0x1
(dirty)LEB 476 free 144 dirty 1760 used 129040 free + dirty
1904 dark 1904 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 477 free
88 dirty 2008 used 128848 free + dirty 2096 dark 2096 dead 0
nodes fit 0 flags 0x0 (not categorized)LEB 478 free 13448 dirty
99712 used 17784 free + dirty 113160 flags 0x22 (dirty index)LEB 479
free 104 dirty 9152 used 121688 free + dirty 9256 dark 4256 dead
0 nodes fit 2 flags 0x1 (dirty)LEB 480 free 0 dirty 1152
used 129792 free + dirty 1152 dark 1152 dead 0 nodes fit 0 flags 0x1
(dirty)LEB 481 free 0 dirty 2664 used 128280 free + dirty
2664 dark 2664 dead 0 nodes fit 0 flags 0x1 (dirty)LEB 482 free
112 dirty 125704 used 5128 free + dirty 125816 dark 4256 dead 0
nodes fit 29 flags 0x1 (dirty)LEB 483 free 80 dirty 8288 used
122576 free + dirty 8368 dark 4256 dead 0 nodes fit 1 flags 0x0 (not
categorized)LEB 484 free 168 dirty 125736 used 5040 free + dirty
125904 dark 4256 dead 0 nodes fit 29 flags 0x1 (dirty)LEB 485 free
48 dirty 2696 used 128200 free + dirty 2744 dark 2744 dead 0
nodes fit 0 flags 0x1 (dirty)LEB 486 free 96 dirty 107016 used
23832 free + dirty 107112 dark 4256 dead 0 nodes fit 25 flags 0x1
(dirty)LEB 487 free 56 dirty 110128 used 20760 free + dirty
110184 dark 4256 dead 0 nodes fit 25 flags 0x1 (dirty)LEB 488 free
67464 dirty 36960 used 26520 free + dirty 104424 flags 0x22 (dirty
index)(pid 958) finish dumping LEB properties(pid 958) Budgeting info: data
budget sum 0, total budget sum 0 budg_data_growth 0, budg_dd_growth 0,
budg_idx_growth 0 min_idx_lebs 19, old_idx_sz 774952, uncommitted_idx
9024 page_budget 4144, inode_budget 160, dent_budget 312 nospace
0, nospace_rp 0 dark_wm 4256, dead_wm 56, max_idx_node_sz 192
freeable_cnt 1, calc_idx_sz 768632, idx_gc_cnt 0 dirty_pg_cnt 0,
dirty_zn_cnt 47, clean_zn_cnt 0 gc_lnum -1, ihead_lnum 453 jhead 0
(GC) LEB 237 jhead 1 (base) LEB 293 jhead 2 (data) LEB
469 bud LEB 92 bud LEB 206 bud LEB 237 bud LEB
293 bud LEB 312 bud LEB 412 bud LEB 469 commit state
0Budgeting predictions: &> nbsp; available: 16938560, outstanding 0, free
16002679mount: No space left on device
>
> Attachment (ubifs.3.0.diff): application/octet-stream, 425 KiB
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>
I've been running with the patched kernel for about a month now and I've seen
this issue once since then. Does anyone have any other ideas on how I can
better track this down. I've taken precautions to test if the external data
partitions mounted properly, if not, then they are reformatted and initialized.
I will have a problem if the issue occurs in the root filesystem.
Thanks,
Bud
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB'
2012-07-16 18:22 UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB' Brent Taylor
2012-08-13 13:41 ` Brent Taylor
@ 2012-08-17 12:50 ` Artem Bityutskiy
2012-08-31 11:44 ` Artem Bityutskiy
2 siblings, 0 replies; 14+ messages in thread
From: Artem Bityutskiy @ 2012-08-17 12:50 UTC (permalink / raw)
To: Brent Taylor; +Cc: linux-mtd
[-- Attachment #1: Type: text/plain, Size: 1392 bytes --]
On Mon, 2012-07-16 at 13:22 -0500, Brent Taylor wrote:
> I'm developing on custom hardware using an at91sam9g45 processor with
> 64 MB of RAM and 64 MB of NOR flash running Linux 3.0.13.
>
> I'm doing some power-cycle testing and after several hours, UBIFS
> failed to mount the root partition and printed the message
> "grab_empty_leb: could not find an empty LEB". The system boots and
> starts a script that will power cycle the board anytime between 10 and
> 20 seconds after the script has started. Just before a power cycle
> occurs, syslog and our main process are the only processes that could
> be writing to disk.
>
> I then checked http://git.infradead.org/users/dedekind/ubifs-v3.0.git
> to see if there was a patch and couldn't find anything describing my
> exact problem. I generated a patch from commit
> 02f8c6aee8df3cdc935e9bdd4f2d020306035dbe to
> a0c2d5050bd191e53a761381027c8e5ab8e25336 (see attached ubifs.3.0.diff)
> and rebuilt the kernel. If there was a patch for my issue, I was
> expecting the root partition to be recovered but it wasn't. I'm
> currently running the same test with the patched kernel. Below is the
> information from the patched kernel.
>
> If there is any more information I need to provide, please let me
> know.
>
Do you have a possibility to share the broken image?
--
Best Regards,
Artem Bityutskiy
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB'
2012-08-13 13:41 ` Brent Taylor
@ 2012-08-17 12:57 ` Artem Bityutskiy
2012-08-24 15:59 ` Brent Taylor
0 siblings, 1 reply; 14+ messages in thread
From: Artem Bityutskiy @ 2012-08-17 12:57 UTC (permalink / raw)
To: Brent Taylor; +Cc: linux-mtd
[-- Attachment #1: Type: text/plain, Size: 521 bytes --]
On Mon, 2012-08-13 at 13:41 +0000, Brent Taylor wrote:
> I've been running with the patched kernel for about a month now and I've seen
> this issue once since then. Does anyone have any other ideas on how I can
> better track this down. I've taken precautions to test if the external data
> partitions mounted properly, if not, then they are reformatted and initialized.
> I will have a problem if the issue occurs in the root filesystem.
What kind of test do you run?
--
Best Regards,
Artem Bityutskiy
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB'
2012-08-17 12:57 ` Artem Bityutskiy
@ 2012-08-24 15:59 ` Brent Taylor
2012-08-24 16:13 ` Artem Bityutskiy
0 siblings, 1 reply; 14+ messages in thread
From: Brent Taylor @ 2012-08-24 15:59 UTC (permalink / raw)
To: dedekind1; +Cc: linux-mtd
On Fri, Aug 17, 2012 at 7:57 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
>
> On Mon, 2012-08-13 at 13:41 +0000, Brent Taylor wrote:
> > I've been running with the patched kernel for about a month now and I've seen
> > this issue once since then. Does anyone have any other ideas on how I can
> > better track this down. I've taken precautions to test if the external data
> > partitions mounted properly, if not, then they are reformatted and initialized.
> > I will have a problem if the issue occurs in the root filesystem.
>
> What kind of test do you run?
>
> --
> Best Regards,
> Artem Bityutskiy
Artem,
Thanks for taking the time to look at this.
I'm not sure if I can share the image just yet. What all would you
need? vmlinuz, uImage, the config file?.
I've changed my test setup slightly since my initial post. My test
setup now includes a Linux PC that is connected to an ethernet
controlled power switch
(http://www.controlanything.com/Relay/Relay/ethernet_relay_controllers)
that is powering my hardware. I have a script that runs that sends a
command to the power switch to cut power, sleep for 2 seconds, then
re-apply power. It then waits anywhere between 0 and 45 seconds
before cutting power again.
I've upgraded to linux-3.5.1 and I haven't started to run the test
again, but will pretty soon.
-- Bud
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB'
2012-08-24 15:59 ` Brent Taylor
@ 2012-08-24 16:13 ` Artem Bityutskiy
0 siblings, 0 replies; 14+ messages in thread
From: Artem Bityutskiy @ 2012-08-24 16:13 UTC (permalink / raw)
To: Brent Taylor; +Cc: linux-mtd
[-- Attachment #1: Type: text/plain, Size: 1189 bytes --]
On Fri, 2012-08-24 at 10:59 -0500, Brent Taylor wrote:
> On Fri, Aug 17, 2012 at 7:57 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> >
> > On Mon, 2012-08-13 at 13:41 +0000, Brent Taylor wrote:
> > > I've been running with the patched kernel for about a month now and I've seen
> > > this issue once since then. Does anyone have any other ideas on how I can
> > > better track this down. I've taken precautions to test if the external data
> > > partitions mounted properly, if not, then they are reformatted and initialized.
> > > I will have a problem if the issue occurs in the root filesystem.
> >
> > What kind of test do you run?
> >
> > --
> > Best Regards,
> > Artem Bityutskiy
>
>
> Artem,
> Thanks for taking the time to look at this.
>
> I'm not sure if I can share the image just yet. What all would you
> need? vmlinuz, uImage, the config file?.
No. dd if=/dev/mtd4 of=image
and share the image. I could try to put it to mtdram and mount the
volume, and take a closer look at the error.
But I think I saw these errors before when testing, they were so rare,
and I did not have time to dig.
--
Best Regards,
Artem Bityutskiy
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB'
2012-07-16 18:22 UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB' Brent Taylor
2012-08-13 13:41 ` Brent Taylor
2012-08-17 12:50 ` Artem Bityutskiy
@ 2012-08-31 11:44 ` Artem Bityutskiy
[not found] ` <CAP+RiCBRopbShAGf_fWCvK2R=uPPR1j4Pz12JfJxdEMUjwofNw@mail.gmail.com>
2 siblings, 1 reply; 14+ messages in thread
From: Artem Bityutskiy @ 2012-08-31 11:44 UTC (permalink / raw)
To: Brent Taylor; +Cc: linux-mtd
[-- Attachment #1: Type: text/plain, Size: 1105 bytes --]
On Mon, 2012-07-16 at 13:22 -0500, Brent Taylor wrote:
> I'm developing on custom hardware using an at91sam9g45 processor with
> 64 MB of RAM and 64 MB of NOR flash running Linux 3.0.13.
>
> I'm doing some power-cycle testing and after several hours, UBIFS
> failed to mount the root partition and printed the message
> "grab_empty_leb: could not find an empty LEB". The system boots and
> starts a script that will power cycle the board anytime between 10 and
> 20 seconds after the script has started. Just before a power cycle
> occurs, syslog and our main process are the only processes that could
> be writing to disk.
>
I was trying to do power cut emulation testing with mtdram, and I see
there are some issues which do not seem to exist on NAND. But they are
different to yours. I remember I saw these -ENOSPC issues in the past,
but they were very difficult to reproduce.
I will try to investigate why power-cut emulation testing fails on
mtdram, but I have limited amount of time and I do not know when I'll be
able to do this.
--
Best Regards,
Artem Bityutskiy
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB'
[not found] ` <CAP+RiCBRopbShAGf_fWCvK2R=uPPR1j4Pz12JfJxdEMUjwofNw@mail.gmail.com>
@ 2012-09-17 13:34 ` Brent Taylor
2012-09-23 15:48 ` Brent Taylor
` (2 more replies)
0 siblings, 3 replies; 14+ messages in thread
From: Brent Taylor @ 2012-09-17 13:34 UTC (permalink / raw)
To: dedekind1; +Cc: linux-mtd
On Fri, Aug 31, 2012 at 8:23 AM, Brent Taylor <motobud@gmail.com> wrote:
>
> I'm currently running the test again, and will know the results on wed, sept 5. If I do see a failure, I can send you an image, the problem is that the image will be either 256MB, 1GB, or 15GB depending on which partition fails. Will either of the larger sizes be an issue for you? What would be the best way to get the image to you?
>
> Thanks for your time.
> Bud
>
> On Aug 31, 2012 7:39 AM, "Artem Bityutskiy" <dedekind1@gmail.com> wrote:
>>
>> On Mon, 2012-07-16 at 13:22 -0500, Brent Taylor wrote:
>> > I'm developing on custom hardware using an at91sam9g45 processor with
>> > 64 MB of RAM and 64 MB of NOR flash running Linux 3.0.13.
>> >
>> > I'm doing some power-cycle testing and after several hours, UBIFS
>> > failed to mount the root partition and printed the message
>> > "grab_empty_leb: could not find an empty LEB". The system boots and
>> > starts a script that will power cycle the board anytime between 10 and
>> > 20 seconds after the script has started. Just before a power cycle
>> > occurs, syslog and our main process are the only processes that could
>> > be writing to disk.
>> >
>> I was trying to do power cut emulation testing with mtdram, and I see
>> there are some issues which do not seem to exist on NAND. But they are
>> different to yours. I remember I saw these -ENOSPC issues in the past,
>> but they were very difficult to reproduce.
>>
>> I will try to investigate why power-cut emulation testing fails on
>> mtdram, but I have limited amount of time and I do not know when I'll be
>> able to do this.
>>
>> --
>> Best Regards,
>> Artem Bityutskiy
Artem,
I was finally able to capture the issue again with linux version
3.5.1, and I now have a 64MB mtd image for you to look at. The issue
occurred in the root filesystem this time. Let me know what's the
best way to get this image to you. The image was retrieved from a NOR
flash chip instead of a NAND flash chip, but I've seen the error on
both which leads me to believe it's not a flash driver issue and it's
something in the UBIFS subsystem. If there is more data you need from
me to help track this down, just let me know.
Thanks for your time,
Bud
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB'
2012-09-17 13:34 ` Brent Taylor
@ 2012-09-23 15:48 ` Brent Taylor
2012-09-23 16:03 ` Artem Bityutskiy
2012-10-09 13:30 ` Artem Bityutskiy
2012-10-04 15:05 ` Artem Bityutskiy
2012-10-09 12:00 ` Artem Bityutskiy
2 siblings, 2 replies; 14+ messages in thread
From: Brent Taylor @ 2012-09-23 15:48 UTC (permalink / raw)
To: dedekind1; +Cc: linux-mtd
On Mon, Sep 17, 2012 at 8:34 AM, Brent Taylor <motobud@gmail.com> wrote:
> On Fri, Aug 31, 2012 at 8:23 AM, Brent Taylor <motobud@gmail.com> wrote:
>>
>> I'm currently running the test again, and will know the results on wed, sept 5. If I do see a failure, I can send you an image, the problem is that the image will be either 256MB, 1GB, or 15GB depending on which partition fails. Will either of the larger sizes be an issue for you? What would be the best way to get the image to you?
>>
>> Thanks for your time.
>> Bud
>>
>> On Aug 31, 2012 7:39 AM, "Artem Bityutskiy" <dedekind1@gmail.com> wrote:
>>>
>>> On Mon, 2012-07-16 at 13:22 -0500, Brent Taylor wrote:
>>> > I'm developing on custom hardware using an at91sam9g45 processor with
>>> > 64 MB of RAM and 64 MB of NOR flash running Linux 3.0.13.
>>> >
>>> > I'm doing some power-cycle testing and after several hours, UBIFS
>>> > failed to mount the root partition and printed the message
>>> > "grab_empty_leb: could not find an empty LEB". The system boots and
>>> > starts a script that will power cycle the board anytime between 10 and
>>> > 20 seconds after the script has started. Just before a power cycle
>>> > occurs, syslog and our main process are the only processes that could
>>> > be writing to disk.
>>> >
>>> I was trying to do power cut emulation testing with mtdram, and I see
>>> there are some issues which do not seem to exist on NAND. But they are
>>> different to yours. I remember I saw these -ENOSPC issues in the past,
>>> but they were very difficult to reproduce.
>>>
>>> I will try to investigate why power-cut emulation testing fails on
>>> mtdram, but I have limited amount of time and I do not know when I'll be
>>> able to do this.
>>>
>>> --
>>> Best Regards,
>>> Artem Bityutskiy
>
>
> Artem,
> I was finally able to capture the issue again with linux version
> 3.5.1, and I now have a 64MB mtd image for you to look at. The issue
> occurred in the root filesystem this time. Let me know what's the
> best way to get this image to you. The image was retrieved from a NOR
> flash chip instead of a NAND flash chip, but I've seen the error on
> both which leads me to believe it's not a flash driver issue and it's
> something in the UBIFS subsystem. If there is more data you need from
> me to help track this down, just let me know.
>
> Thanks for your time,
> Bud
Ping, I just didn't want to get lost in the e-mail shuffle.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB'
2012-09-23 15:48 ` Brent Taylor
@ 2012-09-23 16:03 ` Artem Bityutskiy
2012-10-09 13:30 ` Artem Bityutskiy
1 sibling, 0 replies; 14+ messages in thread
From: Artem Bityutskiy @ 2012-09-23 16:03 UTC (permalink / raw)
To: Brent Taylor; +Cc: linux-mtd
[-- Attachment #1: Type: text/plain, Size: 245 bytes --]
On Sun, 2012-09-23 at 10:48 -0500, Brent Taylor wrote:
>
> Ping, I just didn't want to get lost in the e-mail shuffle.
I simply do not have enough time. But at some point I should come to
this.
>
--
Best Regards,
Artem Bityutskiy
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB'
2012-09-17 13:34 ` Brent Taylor
2012-09-23 15:48 ` Brent Taylor
@ 2012-10-04 15:05 ` Artem Bityutskiy
2012-10-09 12:00 ` Artem Bityutskiy
2 siblings, 0 replies; 14+ messages in thread
From: Artem Bityutskiy @ 2012-10-04 15:05 UTC (permalink / raw)
To: Brent Taylor; +Cc: linux-mtd
[-- Attachment #1: Type: text/plain, Size: 838 bytes --]
On Mon, 2012-09-17 at 08:34 -0500, Brent Taylor wrote:
> Artem,
> I was finally able to capture the issue again with linux version
> 3.5.1, and I now have a 64MB mtd image for you to look at. The issue
> occurred in the root filesystem this time. Let me know what's the
> best way to get this image to you. The image was retrieved from a NOR
> flash chip instead of a NAND flash chip, but I've seen the error on
> both which leads me to believe it's not a flash driver issue and it's
> something in the UBIFS subsystem. If there is more data you need from
> me to help track this down, just let me know.
Well, I do not have any service where you can upload it to. If it
compresses well, may be e-mail would work. Otherwise you'd need to give
me an URL where to download from.
--
Best Regards,
Artem Bityutskiy
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB'
2012-09-17 13:34 ` Brent Taylor
2012-09-23 15:48 ` Brent Taylor
2012-10-04 15:05 ` Artem Bityutskiy
@ 2012-10-09 12:00 ` Artem Bityutskiy
2 siblings, 0 replies; 14+ messages in thread
From: Artem Bityutskiy @ 2012-10-09 12:00 UTC (permalink / raw)
To: Brent Taylor; +Cc: linux-mtd
[-- Attachment #1: Type: text/plain, Size: 1169 bytes --]
On Mon, 2012-09-17 at 08:34 -0500, Brent Taylor wrote:
> Artem,
> I was finally able to capture the issue again with linux version
> 3.5.1, and I now have a 64MB mtd image for you to look at. The issue
> occurred in the root filesystem this time. Let me know what's the
> best way to get this image to you. The image was retrieved from a NOR
> flash chip instead of a NAND flash chip, but I've seen the error on
> both which leads me to believe it's not a flash driver issue and it's
> something in the UBIFS subsystem. If there is more data you need from
> me to help track this down, just let me know.
I've took a look. So far I do not understand what is going on. There
seems to be some bug in UBIFS. I'll try to dig deeper.
But what I've noticed that if you do this:
echo 1 > /sys/kernel/debug/ubifs/chk_lprops
before mounting UBIFS, then it mounts fine. If this issue is a blocker
for you, you may use this as a workaround.
Note, this enables lprops checks in UBIFS which slow it down. So you can
use this trick only to mount, and then you can write 0 to that file to
disable the checks.
--
Best Regards,
Artem Bityutskiy
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB'
2012-09-23 15:48 ` Brent Taylor
2012-09-23 16:03 ` Artem Bityutskiy
@ 2012-10-09 13:30 ` Artem Bityutskiy
[not found] ` <CAP+RiCBCe-KUu+dd5NTizMoJU4gd+r5o=VmBa4CauP704uSmbQ@mail.gmail.com>
1 sibling, 1 reply; 14+ messages in thread
From: Artem Bityutskiy @ 2012-10-09 13:30 UTC (permalink / raw)
To: Brent Taylor; +Cc: linux-mtd
[-- Attachment #1.1: Type: text/plain, Size: 2293 bytes --]
On Sun, 2012-09-23 at 10:48 -0500, Brent Taylor wrote:
> Ping, I just didn't want to get lost in the e-mail shuffle.
OK, Brent, here is the fix. I am sorry for so long delay. I simply
do not have enough time for my UBIFS hobby. And thank you for sending
me the image. The fix is attached.
From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Date: Tue, 9 Oct 2012 16:20:15 +0300
Subject: [PATCH] UBIFS: fix mounting problems after power cuts
This is a bugfix for a problem with the following symptoms:
1. A power cut happens
2. After reboot, we try to mount UBIFS
3. Mount fails with "No space left on device" error message
UBIFS complains like this:
UBIFS error (pid 28225): grab_empty_leb: could not find an empty LEB
The root cause of this problem is that when we mount, not all LEBs are
categorized. Only those which were read are. However, the
'ubifs_find_free_leb_for_idx()' function assumes that all LEBs were
categorized and 'c->freeable_cnt' is valid, which is a false assumption.
This patch fixes the problem by teaching 'ubifs_find_free_leb_for_idx()'
to always fall back to LPT scanning if no freeable LEBs were found.
This problem was reported by several people in the past, but Brent Taylor
was able to reproduce it and send me a flash image which cannot be mounted,
which made it easy to hunt the bug. Kudos to Brent.
Reported-by: Brent Taylor <motobud@gmail.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Cc: stable@vger.kernel.org
---
fs/ubifs/find.c | 10 ++++------
1 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c
index 28ec13a..959386b 100644
--- a/fs/ubifs/find.c
+++ b/fs/ubifs/find.c
@@ -682,12 +682,10 @@ int ubifs_find_free_leb_for_idx(struct ubifs_info *c)
lprops = ubifs_fast_find_freeable(c);
if (!lprops) {
ubifs_assert(c->freeable_cnt == 0);
- if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
- lprops = scan_for_leb_for_idx(c);
- if (IS_ERR(lprops)) {
- err = PTR_ERR(lprops);
- goto out;
- }
+ lprops = scan_for_leb_for_idx(c);
+ if (IS_ERR(lprops)) {
+ err = PTR_ERR(lprops);
+ goto out;
}
}
}
--
1.7.7.6
--
Best Regards,
Artem Bityutskiy
[-- Attachment #1.2: 0001-UBIFS-fix-mounting-problems-after-power-cuts.patch --]
[-- Type: text/x-patch, Size: 2024 bytes --]
From e8d6b0e4615ba38b0d3dd6246517b346c91e6a8d Mon Sep 17 00:00:00 2001
From: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Date: Tue, 9 Oct 2012 16:20:15 +0300
Subject: [PATCH] UBIFS: fix mounting problems after power cuts
This is a bugfix for a problem with the following symptoms:
1. A power cut happens
2. After reboot, we try to mount UBIFS
3. Mount fails with "No space left on device" error message
UBIFS complains like this:
UBIFS error (pid 28225): grab_empty_leb: could not find an empty LEB
The root cause of this problem is that when we mount, not all LEBs are
categorized. Only those which were read are. However, the
'ubifs_find_free_leb_for_idx()' function assumes that all LEBs were
categorized and 'c->freeable_cnt' is valid, which is a false assumption.
This patch fixes the problem by teaching 'ubifs_find_free_leb_for_idx()'
to always fall back to LPT scanning if no freeable LEBs were found.
This problem was reported by several people in the past, but Brent Taylor
was able to reproduce it and send me a flash image which cannot be mounted,
which made it easy to hunt the bug. Kudos to Brent.
Reported-by: Brent Taylor <motobud@gmail.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Cc: stable@vger.kernel.org
---
fs/ubifs/find.c | 10 ++++------
1 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c
index 28ec13a..959386b 100644
--- a/fs/ubifs/find.c
+++ b/fs/ubifs/find.c
@@ -682,12 +682,10 @@ int ubifs_find_free_leb_for_idx(struct ubifs_info *c)
lprops = ubifs_fast_find_freeable(c);
if (!lprops) {
ubifs_assert(c->freeable_cnt == 0);
- if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
- lprops = scan_for_leb_for_idx(c);
- if (IS_ERR(lprops)) {
- err = PTR_ERR(lprops);
- goto out;
- }
+ lprops = scan_for_leb_for_idx(c);
+ if (IS_ERR(lprops)) {
+ err = PTR_ERR(lprops);
+ goto out;
}
}
}
--
1.7.7.6
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB'
[not found] ` <CAP+RiCBCe-KUu+dd5NTizMoJU4gd+r5o=VmBa4CauP704uSmbQ@mail.gmail.com>
@ 2012-10-09 17:25 ` Artem Bityutskiy
0 siblings, 0 replies; 14+ messages in thread
From: Artem Bityutskiy @ 2012-10-09 17:25 UTC (permalink / raw)
To: Brent Taylor; +Cc: linux-mtd
[-- Attachment #1: Type: text/plain, Size: 522 bytes --]
On Tue, 2012-10-09 at 12:11 -0500, Brent Taylor wrote:
> Artem,
> Thanks so much for your time to track down this bug. I've tested
> your patch and it does mount the filesystem that it would fail on
> before. I'm glad I could help. I want to thank you for all your work
> in the UBI and UBIFS subsystems and all your contributions to the
> Linux kernel.
Thanks!
I will send a better version of the patch later, and give it some more
test. I will keep you in CC.
--
Best Regards,
Artem Bityutskiy
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2012-10-09 17:25 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-16 18:22 UBIFS Recovery Issue: 'grab_empty_leb: could not find an empty LEB' Brent Taylor
2012-08-13 13:41 ` Brent Taylor
2012-08-17 12:57 ` Artem Bityutskiy
2012-08-24 15:59 ` Brent Taylor
2012-08-24 16:13 ` Artem Bityutskiy
2012-08-17 12:50 ` Artem Bityutskiy
2012-08-31 11:44 ` Artem Bityutskiy
[not found] ` <CAP+RiCBRopbShAGf_fWCvK2R=uPPR1j4Pz12JfJxdEMUjwofNw@mail.gmail.com>
2012-09-17 13:34 ` Brent Taylor
2012-09-23 15:48 ` Brent Taylor
2012-09-23 16:03 ` Artem Bityutskiy
2012-10-09 13:30 ` Artem Bityutskiy
[not found] ` <CAP+RiCBCe-KUu+dd5NTizMoJU4gd+r5o=VmBa4CauP704uSmbQ@mail.gmail.com>
2012-10-09 17:25 ` Artem Bityutskiy
2012-10-04 15:05 ` Artem Bityutskiy
2012-10-09 12:00 ` Artem Bityutskiy
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.