Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
fs
ubifs
master.c
Go to the documentation of this file.
1
/*
2
* This file is part of UBIFS.
3
*
4
* Copyright (C) 2006-2008 Nokia Corporation.
5
*
6
* This program is free software; you can redistribute it and/or modify it
7
* under the terms of the GNU General Public License version 2 as published by
8
* the Free Software Foundation.
9
*
10
* This program is distributed in the hope that it will be useful, but WITHOUT
11
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13
* more details.
14
*
15
* You should have received a copy of the GNU General Public License along with
16
* this program; if not, write to the Free Software Foundation, Inc., 51
17
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
*
19
* Authors: Artem Bityutskiy (Битюцкий Артём)
20
* Adrian Hunter
21
*/
22
23
/* This file implements reading and writing the master node */
24
25
#include "
ubifs.h
"
26
36
static
int
scan_for_master(
struct
ubifs_info
*
c
)
37
{
38
struct
ubifs_scan_leb
*sleb;
39
struct
ubifs_scan_node
*snod;
40
int
lnum,
offs
= 0, nodes_cnt;
41
42
lnum =
UBIFS_MST_LNUM
;
43
44
sleb =
ubifs_scan
(c, lnum, 0, c->
sbuf
, 1);
45
if
(IS_ERR(sleb))
46
return
PTR_ERR(sleb);
47
nodes_cnt = sleb->
nodes_cnt
;
48
if
(nodes_cnt > 0) {
49
snod =
list_entry
(sleb->
nodes
.prev,
struct
ubifs_scan_node
,
50
list
);
51
if
(snod->
type
!=
UBIFS_MST_NODE
)
52
goto
out_dump;
53
memcpy
(c->
mst_node
, snod->
node
, snod->
len
);
54
offs = snod->
offs
;
55
}
56
ubifs_scan_destroy
(sleb);
57
58
lnum += 1;
59
60
sleb =
ubifs_scan
(c, lnum, 0, c->
sbuf
, 1);
61
if
(IS_ERR(sleb))
62
return
PTR_ERR(sleb);
63
if
(sleb->
nodes_cnt
!= nodes_cnt)
64
goto
out
;
65
if
(!sleb->
nodes_cnt
)
66
goto
out
;
67
snod =
list_entry
(sleb->
nodes
.prev,
struct
ubifs_scan_node
,
list
);
68
if
(snod->
type
!=
UBIFS_MST_NODE
)
69
goto
out_dump;
70
if
(snod->
offs
!= offs)
71
goto
out
;
72
if
(
memcmp
((
void
*)c->
mst_node
+
UBIFS_CH_SZ
,
73
(
void
*)snod->
node
+
UBIFS_CH_SZ
,
74
UBIFS_MST_NODE_SZ
-
UBIFS_CH_SZ
))
75
goto
out
;
76
c->
mst_offs
=
offs
;
77
ubifs_scan_destroy
(sleb);
78
return
0;
79
80
out
:
81
ubifs_scan_destroy
(sleb);
82
return
-
EUCLEAN
;
83
84
out_dump:
85
ubifs_err
(
"unexpected node type %d master LEB %d:%d"
,
86
snod->
type
, lnum, snod->
offs
);
87
ubifs_scan_destroy
(sleb);
88
return
-
EINVAL
;
89
}
90
98
static
int
validate_master(
const
struct
ubifs_info
*c)
99
{
100
long
long
main_sz;
101
int
err
;
102
103
if
(c->
max_sqnum
>=
SQNUM_WATERMARK
) {
104
err = 1;
105
goto
out
;
106
}
107
108
if
(c->
cmt_no
>= c->
max_sqnum
) {
109
err = 2;
110
goto
out
;
111
}
112
113
if
(c->
highest_inum
>=
INUM_WATERMARK
) {
114
err = 3;
115
goto
out
;
116
}
117
118
if
(c->
lhead_lnum
<
UBIFS_LOG_LNUM
||
119
c->
lhead_lnum
>=
UBIFS_LOG_LNUM
+ c->
log_lebs
||
120
c->
lhead_offs
< 0 || c->
lhead_offs
>= c->
leb_size
||
121
c->
lhead_offs
& (c->
min_io_size
- 1)) {
122
err = 4;
123
goto
out
;
124
}
125
126
if
(c->
zroot
.lnum >= c->
leb_cnt
|| c->
zroot
.lnum < c->
main_first
||
127
c->
zroot
.offs >= c->
leb_size
|| c->
zroot
.offs & 7) {
128
err = 5;
129
goto
out
;
130
}
131
132
if
(c->
zroot
.len < c->
ranges
[
UBIFS_IDX_NODE
].min_len ||
133
c->
zroot
.len > c->
ranges
[
UBIFS_IDX_NODE
].max_len) {
134
err = 6;
135
goto
out
;
136
}
137
138
if
(c->
gc_lnum
>= c->
leb_cnt
|| c->
gc_lnum
< c->
main_first
) {
139
err = 7;
140
goto
out
;
141
}
142
143
if
(c->
ihead_lnum
>= c->
leb_cnt
|| c->
ihead_lnum
< c->
main_first
||
144
c->
ihead_offs
% c->
min_io_size
|| c->
ihead_offs
< 0 ||
145
c->
ihead_offs
> c->
leb_size
|| c->
ihead_offs
& 7) {
146
err = 8;
147
goto
out
;
148
}
149
150
main_sz = (
long
long
)c->
main_lebs
* c->
leb_size
;
151
if
(c->
bi
.old_idx_sz & 7 || c->
bi
.old_idx_sz >= main_sz) {
152
err = 9;
153
goto
out
;
154
}
155
156
if
(c->
lpt_lnum
< c->
lpt_first
|| c->
lpt_lnum
> c->
lpt_last
||
157
c->
lpt_offs
< 0 || c->
lpt_offs
+ c->
nnode_sz
> c->
leb_size
) {
158
err = 10;
159
goto
out
;
160
}
161
162
if
(c->
nhead_lnum
< c->
lpt_first
|| c->
nhead_lnum
> c->
lpt_last
||
163
c->
nhead_offs
< 0 || c->
nhead_offs
% c->
min_io_size
||
164
c->
nhead_offs
> c->
leb_size
) {
165
err = 11;
166
goto
out
;
167
}
168
169
if
(c->
ltab_lnum
< c->
lpt_first
|| c->
ltab_lnum
> c->
lpt_last
||
170
c->
ltab_offs
< 0 ||
171
c->
ltab_offs
+ c->
ltab_sz
> c->
leb_size
) {
172
err = 12;
173
goto
out
;
174
}
175
176
if
(c->
big_lpt
&& (c->
lsave_lnum
< c->
lpt_first
||
177
c->
lsave_lnum
> c->
lpt_last
|| c->
lsave_offs
< 0 ||
178
c->
lsave_offs
+ c->
lsave_sz
> c->
leb_size
)) {
179
err = 13;
180
goto
out
;
181
}
182
183
if
(c->
lscan_lnum
< c->
main_first
|| c->
lscan_lnum
>= c->
leb_cnt
) {
184
err = 14;
185
goto
out
;
186
}
187
188
if
(c->
lst
.empty_lebs < 0 || c->
lst
.empty_lebs > c->
main_lebs
- 2) {
189
err = 15;
190
goto
out
;
191
}
192
193
if
(c->
lst
.idx_lebs < 0 || c->
lst
.idx_lebs > c->
main_lebs
- 1) {
194
err = 16;
195
goto
out
;
196
}
197
198
if
(c->
lst
.total_free < 0 || c->
lst
.total_free > main_sz ||
199
c->
lst
.total_free & 7) {
200
err = 17;
201
goto
out
;
202
}
203
204
if
(c->
lst
.total_dirty < 0 || (c->
lst
.total_dirty & 7)) {
205
err = 18;
206
goto
out
;
207
}
208
209
if
(c->
lst
.total_used < 0 || (c->
lst
.total_used & 7)) {
210
err = 19;
211
goto
out
;
212
}
213
214
if
(c->
lst
.total_free + c->
lst
.total_dirty +
215
c->
lst
.total_used > main_sz) {
216
err = 20;
217
goto
out
;
218
}
219
220
if
(c->
lst
.total_dead + c->
lst
.total_dark +
221
c->
lst
.total_used + c->
bi
.old_idx_sz > main_sz) {
222
err = 21;
223
goto
out
;
224
}
225
226
if
(c->
lst
.total_dead < 0 ||
227
c->
lst
.total_dead > c->
lst
.total_free + c->
lst
.total_dirty ||
228
c->
lst
.total_dead & 7) {
229
err = 22;
230
goto
out
;
231
}
232
233
if
(c->
lst
.total_dark < 0 ||
234
c->
lst
.total_dark > c->
lst
.total_free + c->
lst
.total_dirty ||
235
c->
lst
.total_dark & 7) {
236
err = 23;
237
goto
out
;
238
}
239
240
return
0;
241
242
out
:
243
ubifs_err
(
"bad master node at offset %d error %d"
, c->
mst_offs
, err);
244
ubifs_dump_node
(c, c->
mst_node
);
245
return
-
EINVAL
;
246
}
247
256
int
ubifs_read_master
(
struct
ubifs_info
*c)
257
{
258
int
err
, old_leb_cnt;
259
260
c->
mst_node
= kzalloc(c->
mst_node_alsz
,
GFP_KERNEL
);
261
if
(!c->
mst_node
)
262
return
-
ENOMEM
;
263
264
err = scan_for_master(c);
265
if
(err) {
266
if
(err == -
EUCLEAN
)
267
err =
ubifs_recover_master_node
(c);
268
if
(err)
269
/*
270
* Note, we do not free 'c->mst_node' here because the
271
* unmount routine will take care of this.
272
*/
273
return
err
;
274
}
275
276
/* Make sure that the recovery flag is clear */
277
c->
mst_node
->flags &=
cpu_to_le32
(~
UBIFS_MST_RCVRY
);
278
279
c->
max_sqnum
=
le64_to_cpu
(c->
mst_node
->ch.sqnum);
280
c->
highest_inum
=
le64_to_cpu
(c->
mst_node
->highest_inum);
281
c->
cmt_no
=
le64_to_cpu
(c->
mst_node
->cmt_no);
282
c->
zroot
.lnum =
le32_to_cpu
(c->
mst_node
->root_lnum);
283
c->
zroot
.offs =
le32_to_cpu
(c->
mst_node
->root_offs);
284
c->
zroot
.len =
le32_to_cpu
(c->
mst_node
->root_len);
285
c->
lhead_lnum
=
le32_to_cpu
(c->
mst_node
->log_lnum);
286
c->
gc_lnum
=
le32_to_cpu
(c->
mst_node
->gc_lnum);
287
c->
ihead_lnum
=
le32_to_cpu
(c->
mst_node
->ihead_lnum);
288
c->
ihead_offs
=
le32_to_cpu
(c->
mst_node
->ihead_offs);
289
c->
bi
.old_idx_sz =
le64_to_cpu
(c->
mst_node
->index_size);
290
c->
lpt_lnum
=
le32_to_cpu
(c->
mst_node
->lpt_lnum);
291
c->
lpt_offs
=
le32_to_cpu
(c->
mst_node
->lpt_offs);
292
c->
nhead_lnum
=
le32_to_cpu
(c->
mst_node
->nhead_lnum);
293
c->
nhead_offs
=
le32_to_cpu
(c->
mst_node
->nhead_offs);
294
c->
ltab_lnum
=
le32_to_cpu
(c->
mst_node
->ltab_lnum);
295
c->
ltab_offs
=
le32_to_cpu
(c->
mst_node
->ltab_offs);
296
c->
lsave_lnum
=
le32_to_cpu
(c->
mst_node
->lsave_lnum);
297
c->
lsave_offs
=
le32_to_cpu
(c->
mst_node
->lsave_offs);
298
c->
lscan_lnum
=
le32_to_cpu
(c->
mst_node
->lscan_lnum);
299
c->
lst
.empty_lebs =
le32_to_cpu
(c->
mst_node
->empty_lebs);
300
c->
lst
.idx_lebs =
le32_to_cpu
(c->
mst_node
->idx_lebs);
301
old_leb_cnt =
le32_to_cpu
(c->
mst_node
->leb_cnt);
302
c->
lst
.total_free =
le64_to_cpu
(c->
mst_node
->total_free);
303
c->
lst
.total_dirty =
le64_to_cpu
(c->
mst_node
->total_dirty);
304
c->
lst
.total_used =
le64_to_cpu
(c->
mst_node
->total_used);
305
c->
lst
.total_dead =
le64_to_cpu
(c->
mst_node
->total_dead);
306
c->
lst
.total_dark =
le64_to_cpu
(c->
mst_node
->total_dark);
307
308
c->
calc_idx_sz
= c->
bi
.old_idx_sz;
309
310
if
(c->
mst_node
->flags &
cpu_to_le32
(
UBIFS_MST_NO_ORPHS
))
311
c->
no_orphs
= 1;
312
313
if
(old_leb_cnt != c->
leb_cnt
) {
314
/* The file system has been resized */
315
int
growth = c->
leb_cnt
- old_leb_cnt;
316
317
if
(c->
leb_cnt
< old_leb_cnt ||
318
c->
leb_cnt
<
UBIFS_MIN_LEB_CNT
) {
319
ubifs_err
(
"bad leb_cnt on master node"
);
320
ubifs_dump_node
(c, c->
mst_node
);
321
return
-
EINVAL
;
322
}
323
324
dbg_mnt
(
"Auto resizing (master) from %d LEBs to %d LEBs"
,
325
old_leb_cnt, c->
leb_cnt
);
326
c->
lst
.empty_lebs += growth;
327
c->
lst
.total_free += growth * (
long
long
)c->
leb_size
;
328
c->
lst
.total_dark += growth * (
long
long
)c->
dark_wm
;
329
330
/*
331
* Reflect changes back onto the master node. N.B. the master
332
* node gets written immediately whenever mounting (or
333
* remounting) in read-write mode, so we do not need to write it
334
* here.
335
*/
336
c->
mst_node
->leb_cnt =
cpu_to_le32
(c->
leb_cnt
);
337
c->
mst_node
->empty_lebs =
cpu_to_le32
(c->
lst
.empty_lebs);
338
c->
mst_node
->total_free =
cpu_to_le64
(c->
lst
.total_free);
339
c->
mst_node
->total_dark =
cpu_to_le64
(c->
lst
.total_dark);
340
}
341
342
err = validate_master(c);
343
if
(err)
344
return
err
;
345
346
err =
dbg_old_index_check_init
(c, &c->
zroot
);
347
348
return
err
;
349
}
350
360
int
ubifs_write_master
(
struct
ubifs_info
*c)
361
{
362
int
err
, lnum,
offs
,
len
;
363
364
ubifs_assert
(!c->
ro_media
&& !c->
ro_mount
);
365
if
(c->
ro_error
)
366
return
-
EROFS
;
367
368
lnum =
UBIFS_MST_LNUM
;
369
offs = c->
mst_offs
+ c->
mst_node_alsz
;
370
len =
UBIFS_MST_NODE_SZ
;
371
372
if
(offs +
UBIFS_MST_NODE_SZ
> c->
leb_size
) {
373
err =
ubifs_leb_unmap
(c, lnum);
374
if
(err)
375
return
err
;
376
offs = 0;
377
}
378
379
c->
mst_offs
=
offs
;
380
c->
mst_node
->highest_inum =
cpu_to_le64
(c->
highest_inum
);
381
382
err =
ubifs_write_node
(c, c->
mst_node
, len, lnum, offs);
383
if
(err)
384
return
err
;
385
386
lnum += 1;
387
388
if
(offs == 0) {
389
err =
ubifs_leb_unmap
(c, lnum);
390
if
(err)
391
return
err
;
392
}
393
err =
ubifs_write_node
(c, c->
mst_node
, len, lnum, offs);
394
395
return
err
;
396
}
Generated on Thu Jan 10 2013 14:50:07 for Linux Kernel by
1.8.2