Blame view
fs/nilfs2/the_nilfs.c
21 KB
8a9d2191e nilfs2: operation... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/* * the_nilfs.c - the_nilfs shared structure. * * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation. * * 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. * |
4b420ab4e nilfs2: clean up ... |
16 |
* Written by Ryusuke Konishi. |
8a9d2191e nilfs2: operation... |
17 18 19 20 21 22 23 |
* */ #include <linux/buffer_head.h> #include <linux/slab.h> #include <linux/blkdev.h> #include <linux/backing-dev.h> |
9b1fc4e49 nilfs2: move next... |
24 |
#include <linux/random.h> |
e339ad31f nilfs2: introduce... |
25 |
#include <linux/crc32.h> |
8a9d2191e nilfs2: operation... |
26 27 28 29 30 31 |
#include "nilfs.h" #include "segment.h" #include "alloc.h" #include "cpfile.h" #include "sufile.h" #include "dat.h" |
8a9d2191e nilfs2: operation... |
32 |
#include "segbuf.h" |
33c8e57c8 nilfs2: get rid o... |
33 |
|
6c1251608 nilfs2: implement... |
34 |
static int nilfs_valid_sb(struct nilfs_super_block *sbp); |
8a9d2191e nilfs2: operation... |
35 36 37 38 39 40 41 |
void nilfs_set_last_segment(struct the_nilfs *nilfs, sector_t start_blocknr, u64 seq, __u64 cno) { spin_lock(&nilfs->ns_last_segment_lock); nilfs->ns_last_pseg = start_blocknr; nilfs->ns_last_seq = seq; nilfs->ns_last_cno = cno; |
325020477 nilfs2: do not up... |
42 43 44 45 46 47 48 49 50 51 |
if (!nilfs_sb_dirty(nilfs)) { if (nilfs->ns_prev_seq == nilfs->ns_last_seq) goto stay_cursor; set_nilfs_sb_dirty(nilfs); } nilfs->ns_prev_seq = nilfs->ns_last_seq; stay_cursor: |
8a9d2191e nilfs2: operation... |
52 53 54 55 |
spin_unlock(&nilfs->ns_last_segment_lock); } /** |
348fe8da1 nilfs2: simplify ... |
56 |
* alloc_nilfs - allocate a nilfs object |
6625689e1 nilfs2: embed a b... |
57 |
* @sb: super block instance |
8a9d2191e nilfs2: operation... |
58 |
* |
8a9d2191e nilfs2: operation... |
59 60 61 |
* Return Value: On success, pointer to the_nilfs is returned. * On error, NULL is returned. */ |
6625689e1 nilfs2: embed a b... |
62 |
struct the_nilfs *alloc_nilfs(struct super_block *sb) |
8a9d2191e nilfs2: operation... |
63 64 65 66 67 68 |
{ struct the_nilfs *nilfs; nilfs = kzalloc(sizeof(*nilfs), GFP_KERNEL); if (!nilfs) return NULL; |
6625689e1 nilfs2: embed a b... |
69 70 |
nilfs->ns_sb = sb; nilfs->ns_bdev = sb->s_bdev; |
8a9d2191e nilfs2: operation... |
71 72 |
atomic_set(&nilfs->ns_ndirtyblks, 0); init_rwsem(&nilfs->ns_sem); |
572d8b394 nilfs2: fix deadl... |
73 |
mutex_init(&nilfs->ns_snapshot_mount_mutex); |
693dd3212 nilfs2: move s_in... |
74 |
INIT_LIST_HEAD(&nilfs->ns_dirty_files); |
263d90cef nilfs2: remove ow... |
75 |
INIT_LIST_HEAD(&nilfs->ns_gc_inodes); |
693dd3212 nilfs2: move s_in... |
76 |
spin_lock_init(&nilfs->ns_inode_lock); |
9b1fc4e49 nilfs2: move next... |
77 |
spin_lock_init(&nilfs->ns_next_gen_lock); |
8a9d2191e nilfs2: operation... |
78 |
spin_lock_init(&nilfs->ns_last_segment_lock); |
ba65ae472 nilfs2: add check... |
79 80 |
nilfs->ns_cptree = RB_ROOT; spin_lock_init(&nilfs->ns_cptree_lock); |
8a9d2191e nilfs2: operation... |
81 |
init_rwsem(&nilfs->ns_segctor_sem); |
caa05d49d nilfs2: add /sys/... |
82 |
nilfs->ns_sb_update_freq = NILFS_SB_FREQ; |
8a9d2191e nilfs2: operation... |
83 84 85 86 87 |
return nilfs; } /** |
348fe8da1 nilfs2: simplify ... |
88 89 |
* destroy_nilfs - destroy nilfs object * @nilfs: nilfs object to be released |
8a9d2191e nilfs2: operation... |
90 |
*/ |
348fe8da1 nilfs2: simplify ... |
91 |
void destroy_nilfs(struct the_nilfs *nilfs) |
8a9d2191e nilfs2: operation... |
92 |
{ |
8a9d2191e nilfs2: operation... |
93 |
might_sleep(); |
8a9d2191e nilfs2: operation... |
94 |
if (nilfs_init(nilfs)) { |
dd70edbde nilfs2: integrate... |
95 |
nilfs_sysfs_delete_device_group(nilfs); |
e339ad31f nilfs2: introduce... |
96 97 |
brelse(nilfs->ns_sbh[0]); brelse(nilfs->ns_sbh[1]); |
8a9d2191e nilfs2: operation... |
98 99 100 |
} kfree(nilfs); } |
f1e89c86f nilfs2: use iget ... |
101 102 |
static int nilfs_load_super_root(struct the_nilfs *nilfs, struct super_block *sb, sector_t sr_block) |
8a9d2191e nilfs2: operation... |
103 104 105 |
{ struct buffer_head *bh_sr; struct nilfs_super_root *raw_sr; |
e339ad31f nilfs2: introduce... |
106 |
struct nilfs_super_block **sbp = nilfs->ns_sbp; |
f1e89c86f nilfs2: use iget ... |
107 |
struct nilfs_inode *rawi; |
0c6c44cb9 nilfs2: avoid bar... |
108 109 |
unsigned int dat_entry_size, segment_usage_size, checkpoint_size; unsigned int inode_size; |
8a9d2191e nilfs2: operation... |
110 |
int err; |
8b94025c0 nilfs2: refactor ... |
111 |
err = nilfs_read_super_root_block(nilfs, sr_block, &bh_sr, 1); |
8a9d2191e nilfs2: operation... |
112 113 114 115 |
if (unlikely(err)) return err; down_read(&nilfs->ns_sem); |
e339ad31f nilfs2: introduce... |
116 117 118 |
dat_entry_size = le16_to_cpu(sbp[0]->s_dat_entry_size); checkpoint_size = le16_to_cpu(sbp[0]->s_checkpoint_size); segment_usage_size = le16_to_cpu(sbp[0]->s_segment_usage_size); |
8a9d2191e nilfs2: operation... |
119 120 121 |
up_read(&nilfs->ns_sem); inode_size = nilfs->ns_inode_size; |
f1e89c86f nilfs2: use iget ... |
122 123 124 |
rawi = (void *)bh_sr->b_data + NILFS_SR_DAT_OFFSET(inode_size); err = nilfs_dat_read(sb, dat_entry_size, rawi, &nilfs->ns_dat); if (err) |
8a9d2191e nilfs2: operation... |
125 |
goto failed; |
f1e89c86f nilfs2: use iget ... |
126 127 128 |
rawi = (void *)bh_sr->b_data + NILFS_SR_CPFILE_OFFSET(inode_size); err = nilfs_cpfile_read(sb, checkpoint_size, rawi, &nilfs->ns_cpfile); if (err) |
8a9d2191e nilfs2: operation... |
129 |
goto failed_dat; |
f1e89c86f nilfs2: use iget ... |
130 131 132 133 |
rawi = (void *)bh_sr->b_data + NILFS_SR_SUFILE_OFFSET(inode_size); err = nilfs_sufile_read(sb, segment_usage_size, rawi, &nilfs->ns_sufile); if (err) |
8a9d2191e nilfs2: operation... |
134 |
goto failed_cpfile; |
8a9d2191e nilfs2: operation... |
135 136 137 138 139 140 |
raw_sr = (struct nilfs_super_root *)bh_sr->b_data; nilfs->ns_nongc_ctime = le64_to_cpu(raw_sr->sr_nongc_ctime); failed: brelse(bh_sr); return err; |
8a9d2191e nilfs2: operation... |
141 |
failed_cpfile: |
f1e89c86f nilfs2: use iget ... |
142 |
iput(nilfs->ns_cpfile); |
8a9d2191e nilfs2: operation... |
143 144 |
failed_dat: |
f1e89c86f nilfs2: use iget ... |
145 |
iput(nilfs->ns_dat); |
8a9d2191e nilfs2: operation... |
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
goto failed; } static void nilfs_init_recovery_info(struct nilfs_recovery_info *ri) { memset(ri, 0, sizeof(*ri)); INIT_LIST_HEAD(&ri->ri_used_segments); } static void nilfs_clear_recovery_info(struct nilfs_recovery_info *ri) { nilfs_dispose_segment_list(&ri->ri_used_segments); } /** |
843d63baa nilfs2: separate ... |
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
* nilfs_store_log_cursor - load log cursor from a super block * @nilfs: nilfs object * @sbp: buffer storing super block to be read * * nilfs_store_log_cursor() reads the last position of the log * containing a super root from a given super block, and initializes * relevant information on the nilfs object preparatory for log * scanning and recovery. */ static int nilfs_store_log_cursor(struct the_nilfs *nilfs, struct nilfs_super_block *sbp) { int ret = 0; nilfs->ns_last_pseg = le64_to_cpu(sbp->s_last_pseg); nilfs->ns_last_cno = le64_to_cpu(sbp->s_last_cno); nilfs->ns_last_seq = le64_to_cpu(sbp->s_last_seq); |
325020477 nilfs2: do not up... |
178 |
nilfs->ns_prev_seq = nilfs->ns_last_seq; |
843d63baa nilfs2: separate ... |
179 180 181 182 183 |
nilfs->ns_seg_seq = nilfs->ns_last_seq; nilfs->ns_segnum = nilfs_get_segnum_of_block(nilfs, nilfs->ns_last_pseg); nilfs->ns_cno = nilfs->ns_last_cno + 1; if (nilfs->ns_segnum >= nilfs->ns_nsegments) { |
feee880fa nilfs2: reduce ba... |
184 185 186 187 |
nilfs_msg(nilfs->ns_sb, KERN_ERR, "pointed segment number is out of range: segnum=%llu, nsegments=%lu", (unsigned long long)nilfs->ns_segnum, nilfs->ns_nsegments); |
843d63baa nilfs2: separate ... |
188 189 190 191 192 193 |
ret = -EINVAL; } return ret; } /** |
8a9d2191e nilfs2: operation... |
194 195 |
* load_nilfs - load and recover the nilfs * @nilfs: the_nilfs structure to be released |
f7545144c nilfs2: use sb in... |
196 |
* @sb: super block isntance used to recover past segment |
8a9d2191e nilfs2: operation... |
197 198 199 200 201 |
* * load_nilfs() searches and load the latest super root, * attaches the last segment, and does recovery if needed. * The caller must call this exclusively for simultaneous mounts. */ |
f7545144c nilfs2: use sb in... |
202 |
int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb) |
8a9d2191e nilfs2: operation... |
203 204 |
{ struct nilfs_recovery_info ri; |
f7545144c nilfs2: use sb in... |
205 |
unsigned int s_flags = sb->s_flags; |
8a9d2191e nilfs2: operation... |
206 |
int really_read_only = bdev_read_only(nilfs->ns_bdev); |
a057d2c01 nilfs2: add helpe... |
207 |
int valid_fs = nilfs_valid_fs(nilfs); |
f50a4c814 nilfs2: move reco... |
208 |
int err; |
8a9d2191e nilfs2: operation... |
209 |
|
f50a4c814 nilfs2: move reco... |
210 |
if (!valid_fs) { |
feee880fa nilfs2: reduce ba... |
211 |
nilfs_msg(sb, KERN_WARNING, "mounting unchecked fs"); |
f50a4c814 nilfs2: move reco... |
212 |
if (s_flags & MS_RDONLY) { |
feee880fa nilfs2: reduce ba... |
213 214 215 216 |
nilfs_msg(sb, KERN_INFO, "recovery required for readonly filesystem"); nilfs_msg(sb, KERN_INFO, "write access will be enabled during recovery"); |
8a9d2191e nilfs2: operation... |
217 |
} |
8a9d2191e nilfs2: operation... |
218 |
} |
f50a4c814 nilfs2: move reco... |
219 |
nilfs_init_recovery_info(&ri); |
8b94025c0 nilfs2: refactor ... |
220 |
err = nilfs_search_super_root(nilfs, &ri); |
8a9d2191e nilfs2: operation... |
221 |
if (unlikely(err)) { |
6c1251608 nilfs2: implement... |
222 223 224 225 226 227 228 |
struct nilfs_super_block **sbp = nilfs->ns_sbp; int blocksize; if (err != -EINVAL) goto scan_error; if (!nilfs_valid_sb(sbp[1])) { |
feee880fa nilfs2: reduce ba... |
229 230 |
nilfs_msg(sb, KERN_WARNING, "unable to fall back to spare super block"); |
6c1251608 nilfs2: implement... |
231 232 |
goto scan_error; } |
feee880fa nilfs2: reduce ba... |
233 234 |
nilfs_msg(sb, KERN_INFO, "trying rollback from an earlier position"); |
6c1251608 nilfs2: implement... |
235 236 237 238 239 240 241 242 243 244 245 246 |
/* * restore super block with its spare and reconfigure * relevant states of the nilfs object. */ memcpy(sbp[0], sbp[1], nilfs->ns_sbsize); nilfs->ns_crc_seed = le32_to_cpu(sbp[0]->s_crc_seed); nilfs->ns_sbwtime = le64_to_cpu(sbp[0]->s_wtime); /* verify consistency between two super blocks */ blocksize = BLOCK_SIZE << le32_to_cpu(sbp[0]->s_log_block_size); if (blocksize != nilfs->ns_blocksize) { |
feee880fa nilfs2: reduce ba... |
247 248 249 |
nilfs_msg(sb, KERN_WARNING, "blocksize differs between two super blocks (%d != %d)", blocksize, nilfs->ns_blocksize); |
6c1251608 nilfs2: implement... |
250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
goto scan_error; } err = nilfs_store_log_cursor(nilfs, sbp[0]); if (err) goto scan_error; /* drop clean flag to allow roll-forward and recovery */ nilfs->ns_mount_state &= ~NILFS_VALID_FS; valid_fs = 0; err = nilfs_search_super_root(nilfs, &ri); if (err) goto scan_error; |
8a9d2191e nilfs2: operation... |
264 |
} |
f7545144c nilfs2: use sb in... |
265 |
err = nilfs_load_super_root(nilfs, sb, ri.ri_super_root); |
8a9d2191e nilfs2: operation... |
266 |
if (unlikely(err)) { |
feee880fa nilfs2: reduce ba... |
267 268 |
nilfs_msg(sb, KERN_ERR, "error %d while loading super root", err); |
8a9d2191e nilfs2: operation... |
269 270 |
goto failed; } |
f50a4c814 nilfs2: move reco... |
271 272 273 274 |
if (valid_fs) goto skip_recovery; if (s_flags & MS_RDONLY) { |
c5ca48aab nilfs2: reject in... |
275 |
__u64 features; |
3b2ce58b0 nilfs2: move moun... |
276 |
if (nilfs_test_opt(nilfs, NORECOVERY)) { |
feee880fa nilfs2: reduce ba... |
277 278 |
nilfs_msg(sb, KERN_INFO, "norecovery option specified, skipping roll-forward recovery"); |
0234576d0 nilfs2: add norec... |
279 280 |
goto skip_recovery; } |
c5ca48aab nilfs2: reject in... |
281 282 283 |
features = le64_to_cpu(nilfs->ns_sbp[0]->s_feature_compat_ro) & ~NILFS_FEATURE_COMPAT_RO_SUPP; if (features) { |
feee880fa nilfs2: reduce ba... |
284 285 286 |
nilfs_msg(sb, KERN_ERR, "couldn't proceed with recovery because of unsupported optional features (%llx)", (unsigned long long)features); |
c5ca48aab nilfs2: reject in... |
287 288 289 |
err = -EROFS; goto failed_unload; } |
f50a4c814 nilfs2: move reco... |
290 |
if (really_read_only) { |
feee880fa nilfs2: reduce ba... |
291 292 |
nilfs_msg(sb, KERN_ERR, "write access unavailable, cannot proceed"); |
f50a4c814 nilfs2: move reco... |
293 294 |
err = -EROFS; goto failed_unload; |
8a9d2191e nilfs2: operation... |
295 |
} |
f7545144c nilfs2: use sb in... |
296 |
sb->s_flags &= ~MS_RDONLY; |
3b2ce58b0 nilfs2: move moun... |
297 |
} else if (nilfs_test_opt(nilfs, NORECOVERY)) { |
feee880fa nilfs2: reduce ba... |
298 299 |
nilfs_msg(sb, KERN_ERR, "recovery cancelled because norecovery option was specified for a read/write mount"); |
0234576d0 nilfs2: add norec... |
300 301 |
err = -EINVAL; goto failed_unload; |
f50a4c814 nilfs2: move reco... |
302 |
} |
f7545144c nilfs2: use sb in... |
303 |
err = nilfs_salvage_orphan_logs(nilfs, sb, &ri); |
f50a4c814 nilfs2: move reco... |
304 305 306 307 |
if (err) goto failed_unload; down_write(&nilfs->ns_sem); |
7ecaa46cf nilfs2: add nilfs... |
308 |
nilfs->ns_mount_state |= NILFS_VALID_FS; /* set "clean" flag */ |
f7545144c nilfs2: use sb in... |
309 |
err = nilfs_cleanup_super(sb); |
f50a4c814 nilfs2: move reco... |
310 311 312 |
up_write(&nilfs->ns_sem); if (err) { |
feee880fa nilfs2: reduce ba... |
313 314 315 |
nilfs_msg(sb, KERN_ERR, "error %d updating super block. recovery unfinished.", err); |
f50a4c814 nilfs2: move reco... |
316 |
goto failed_unload; |
8a9d2191e nilfs2: operation... |
317 |
} |
feee880fa nilfs2: reduce ba... |
318 |
nilfs_msg(sb, KERN_INFO, "recovery complete"); |
8a9d2191e nilfs2: operation... |
319 |
|
f50a4c814 nilfs2: move reco... |
320 |
skip_recovery: |
f50a4c814 nilfs2: move reco... |
321 |
nilfs_clear_recovery_info(&ri); |
f7545144c nilfs2: use sb in... |
322 |
sb->s_flags = s_flags; |
f50a4c814 nilfs2: move reco... |
323 |
return 0; |
6c1251608 nilfs2: implement... |
324 |
scan_error: |
feee880fa nilfs2: reduce ba... |
325 |
nilfs_msg(sb, KERN_ERR, "error %d while searching super root", err); |
6c1251608 nilfs2: implement... |
326 |
goto failed; |
f50a4c814 nilfs2: move reco... |
327 |
failed_unload: |
f1e89c86f nilfs2: use iget ... |
328 329 330 |
iput(nilfs->ns_cpfile); iput(nilfs->ns_sufile); iput(nilfs->ns_dat); |
8a9d2191e nilfs2: operation... |
331 332 333 |
failed: nilfs_clear_recovery_info(&ri); |
f7545144c nilfs2: use sb in... |
334 |
sb->s_flags = s_flags; |
8a9d2191e nilfs2: operation... |
335 336 337 338 339 340 341 342 343 344 345 346 347 |
return err; } static unsigned long long nilfs_max_size(unsigned int blkbits) { unsigned int max_bits; unsigned long long res = MAX_LFS_FILESIZE; /* page cache limit */ max_bits = blkbits + NILFS_BMAP_KEY_BIT; /* bmap size limit */ if (max_bits < 64) res = min_t(unsigned long long, res, (1ULL << max_bits) - 1); return res; } |
4e33f9eab nilfs2: implement... |
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 |
/** * nilfs_nrsvsegs - calculate the number of reserved segments * @nilfs: nilfs object * @nsegs: total number of segments */ unsigned long nilfs_nrsvsegs(struct the_nilfs *nilfs, unsigned long nsegs) { return max_t(unsigned long, NILFS_MIN_NRSVSEGS, DIV_ROUND_UP(nsegs * nilfs->ns_r_segments_percentage, 100)); } void nilfs_set_nsegments(struct the_nilfs *nilfs, unsigned long nsegs) { nilfs->ns_nsegments = nsegs; nilfs->ns_nrsvsegs = nilfs_nrsvsegs(nilfs, nsegs); } |
e339ad31f nilfs2: introduce... |
365 366 |
static int nilfs_store_disk_layout(struct the_nilfs *nilfs, struct nilfs_super_block *sbp) |
8a9d2191e nilfs2: operation... |
367 |
{ |
9566a7a85 nilfs2: accept fu... |
368 |
if (le32_to_cpu(sbp->s_rev_level) < NILFS_MIN_SUPP_REV) { |
feee880fa nilfs2: reduce ba... |
369 370 371 372 373 |
nilfs_msg(nilfs->ns_sb, KERN_ERR, "unsupported revision (superblock rev.=%d.%d, current rev.=%d.%d). Please check the version of mkfs.nilfs(2).", le32_to_cpu(sbp->s_rev_level), le16_to_cpu(sbp->s_minor_rev_level), NILFS_CURRENT_REV, NILFS_MINOR_REV); |
8a9d2191e nilfs2: operation... |
374 375 |
return -EINVAL; } |
e339ad31f nilfs2: introduce... |
376 377 378 |
nilfs->ns_sbsize = le16_to_cpu(sbp->s_bytes); if (nilfs->ns_sbsize > BLOCK_SIZE) return -EINVAL; |
8a9d2191e nilfs2: operation... |
379 |
nilfs->ns_inode_size = le16_to_cpu(sbp->s_inode_size); |
0ec060d18 nilfs2: verify me... |
380 |
if (nilfs->ns_inode_size > nilfs->ns_blocksize) { |
feee880fa nilfs2: reduce ba... |
381 382 383 |
nilfs_msg(nilfs->ns_sb, KERN_ERR, "too large inode size: %d bytes", nilfs->ns_inode_size); |
0ec060d18 nilfs2: verify me... |
384 385 |
return -EINVAL; } else if (nilfs->ns_inode_size < NILFS_MIN_INODE_SIZE) { |
feee880fa nilfs2: reduce ba... |
386 387 388 |
nilfs_msg(nilfs->ns_sb, KERN_ERR, "too small inode size: %d bytes", nilfs->ns_inode_size); |
0ec060d18 nilfs2: verify me... |
389 390 |
return -EINVAL; } |
8a9d2191e nilfs2: operation... |
391 392 393 394 |
nilfs->ns_first_ino = le32_to_cpu(sbp->s_first_ino); nilfs->ns_blocks_per_segment = le32_to_cpu(sbp->s_blocks_per_segment); if (nilfs->ns_blocks_per_segment < NILFS_SEG_MIN_BLOCKS) { |
feee880fa nilfs2: reduce ba... |
395 396 397 |
nilfs_msg(nilfs->ns_sb, KERN_ERR, "too short segment: %lu blocks", nilfs->ns_blocks_per_segment); |
8a9d2191e nilfs2: operation... |
398 399 400 401 |
return -EINVAL; } nilfs->ns_first_data_block = le64_to_cpu(sbp->s_first_data_block); |
8a9d2191e nilfs2: operation... |
402 403 |
nilfs->ns_r_segments_percentage = le32_to_cpu(sbp->s_r_segments_percentage); |
3d777a640 nilfs2: clamp ns_... |
404 405 |
if (nilfs->ns_r_segments_percentage < 1 || nilfs->ns_r_segments_percentage > 99) { |
feee880fa nilfs2: reduce ba... |
406 407 408 |
nilfs_msg(nilfs->ns_sb, KERN_ERR, "invalid reserved segments percentage: %lu", nilfs->ns_r_segments_percentage); |
3d777a640 nilfs2: clamp ns_... |
409 410 |
return -EINVAL; } |
4e33f9eab nilfs2: implement... |
411 |
nilfs_set_nsegments(nilfs, le64_to_cpu(sbp->s_nsegments)); |
8a9d2191e nilfs2: operation... |
412 413 414 |
nilfs->ns_crc_seed = le32_to_cpu(sbp->s_crc_seed); return 0; } |
e339ad31f nilfs2: introduce... |
415 416 417 418 419 420 421 422 423 424 |
static int nilfs_valid_sb(struct nilfs_super_block *sbp) { static unsigned char sum[4]; const int sumoff = offsetof(struct nilfs_super_block, s_sum); size_t bytes; u32 crc; if (!sbp || le16_to_cpu(sbp->s_magic) != NILFS_SUPER_MAGIC) return 0; bytes = le16_to_cpu(sbp->s_bytes); |
63d2f95d6 fs/nilfs2: fix po... |
425 |
if (bytes < sumoff + 4 || bytes > BLOCK_SIZE) |
e339ad31f nilfs2: introduce... |
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 |
return 0; crc = crc32_le(le32_to_cpu(sbp->s_crc_seed), (unsigned char *)sbp, sumoff); crc = crc32_le(crc, sum, 4); crc = crc32_le(crc, (unsigned char *)sbp + sumoff + 4, bytes - sumoff - 4); return crc == le32_to_cpu(sbp->s_sum); } static int nilfs_sb2_bad_offset(struct nilfs_super_block *sbp, u64 offset) { return offset < ((le64_to_cpu(sbp->s_nsegments) * le32_to_cpu(sbp->s_blocks_per_segment)) << (le32_to_cpu(sbp->s_log_block_size) + 10)); } static void nilfs_release_super_block(struct the_nilfs *nilfs) { int i; for (i = 0; i < 2; i++) { if (nilfs->ns_sbp[i]) { brelse(nilfs->ns_sbh[i]); nilfs->ns_sbh[i] = NULL; nilfs->ns_sbp[i] = NULL; } } } void nilfs_fall_back_super_block(struct the_nilfs *nilfs) { brelse(nilfs->ns_sbh[0]); nilfs->ns_sbh[0] = nilfs->ns_sbh[1]; nilfs->ns_sbp[0] = nilfs->ns_sbp[1]; nilfs->ns_sbh[1] = NULL; nilfs->ns_sbp[1] = NULL; } void nilfs_swap_super_block(struct the_nilfs *nilfs) { struct buffer_head *tsbh = nilfs->ns_sbh[0]; struct nilfs_super_block *tsbp = nilfs->ns_sbp[0]; nilfs->ns_sbh[0] = nilfs->ns_sbh[1]; nilfs->ns_sbp[0] = nilfs->ns_sbp[1]; nilfs->ns_sbh[1] = tsbh; nilfs->ns_sbp[1] = tsbp; } static int nilfs_load_super_block(struct the_nilfs *nilfs, struct super_block *sb, int blocksize, struct nilfs_super_block **sbpp) { struct nilfs_super_block **sbp = nilfs->ns_sbp; struct buffer_head **sbh = nilfs->ns_sbh; u64 sb2off = NILFS_SB2_OFFSET_BYTES(nilfs->ns_bdev->bd_inode->i_size); int valid[2], swp = 0; sbp[0] = nilfs_read_super_block(sb, NILFS_SB_OFFSET_BYTES, blocksize, &sbh[0]); sbp[1] = nilfs_read_super_block(sb, sb2off, blocksize, &sbh[1]); if (!sbp[0]) { if (!sbp[1]) { |
feee880fa nilfs2: reduce ba... |
490 |
nilfs_msg(sb, KERN_ERR, "unable to read superblock"); |
e339ad31f nilfs2: introduce... |
491 492 |
return -EIO; } |
feee880fa nilfs2: reduce ba... |
493 494 495 |
nilfs_msg(sb, KERN_WARNING, "unable to read primary superblock (blocksize = %d)", blocksize); |
4138ec238 nilfs2: append bl... |
496 |
} else if (!sbp[1]) { |
feee880fa nilfs2: reduce ba... |
497 498 499 |
nilfs_msg(sb, KERN_WARNING, "unable to read secondary superblock (blocksize = %d)", blocksize); |
4138ec238 nilfs2: append bl... |
500 |
} |
e339ad31f nilfs2: introduce... |
501 |
|
25294d8c3 nilfs2: use check... |
502 503 504 505 |
/* * Compare two super blocks and set 1 in swp if the secondary * super block is valid and newer. Otherwise, set 0 in swp. */ |
e339ad31f nilfs2: introduce... |
506 507 |
valid[0] = nilfs_valid_sb(sbp[0]); valid[1] = nilfs_valid_sb(sbp[1]); |
25294d8c3 nilfs2: use check... |
508 509 510 |
swp = valid[1] && (!valid[0] || le64_to_cpu(sbp[1]->s_last_cno) > le64_to_cpu(sbp[0]->s_last_cno)); |
e339ad31f nilfs2: introduce... |
511 512 513 514 515 |
if (valid[swp] && nilfs_sb2_bad_offset(sbp[swp], sb2off)) { brelse(sbh[1]); sbh[1] = NULL; sbp[1] = NULL; |
d7178c79d nilfs2: fix NULL ... |
516 |
valid[1] = 0; |
e339ad31f nilfs2: introduce... |
517 518 519 520 |
swp = 0; } if (!valid[swp]) { nilfs_release_super_block(nilfs); |
feee880fa nilfs2: reduce ba... |
521 |
nilfs_msg(sb, KERN_ERR, "couldn't find nilfs on the device"); |
e339ad31f nilfs2: introduce... |
522 523 |
return -EINVAL; } |
ea1a16f71 nilfs2: fix false... |
524 |
if (!valid[!swp]) |
feee880fa nilfs2: reduce ba... |
525 526 527 |
nilfs_msg(sb, KERN_WARNING, "broken superblock, retrying with spare superblock (blocksize = %d)", blocksize); |
ea1a16f71 nilfs2: fix false... |
528 |
if (swp) |
e339ad31f nilfs2: introduce... |
529 |
nilfs_swap_super_block(nilfs); |
e339ad31f nilfs2: introduce... |
530 |
|
b2ac86e1a nilfs2: sync supe... |
531 532 |
nilfs->ns_sbwcount = 0; nilfs->ns_sbwtime = le64_to_cpu(sbp[0]->s_wtime); |
e339ad31f nilfs2: introduce... |
533 534 535 536 |
nilfs->ns_prot_seq = le64_to_cpu(sbp[valid[1] & !swp]->s_last_seq); *sbpp = sbp[0]; return 0; } |
8a9d2191e nilfs2: operation... |
537 538 539 |
/** * init_nilfs - initialize a NILFS instance. * @nilfs: the_nilfs structure |
8a9d2191e nilfs2: operation... |
540 541 542 543 544 |
* @sb: super block * @data: mount options * * init_nilfs() performs common initialization per block device (e.g. * reading the super block, getting disk layout information, initializing |
f11459ad7 nilfs2: do not al... |
545 |
* shared fields in the_nilfs). |
8a9d2191e nilfs2: operation... |
546 547 548 549 |
* * Return Value: On success, 0 is returned. On error, a negative error * code is returned. */ |
f7545144c nilfs2: use sb in... |
550 |
int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data) |
8a9d2191e nilfs2: operation... |
551 |
{ |
8a9d2191e nilfs2: operation... |
552 |
struct nilfs_super_block *sbp; |
8a9d2191e nilfs2: operation... |
553 |
int blocksize; |
e339ad31f nilfs2: introduce... |
554 |
int err; |
8a9d2191e nilfs2: operation... |
555 556 |
down_write(&nilfs->ns_sem); |
8a9d2191e nilfs2: operation... |
557 |
|
89c0fd014 nilfs2: reject fi... |
558 |
blocksize = sb_min_blocksize(sb, NILFS_MIN_BLOCK_SIZE); |
e339ad31f nilfs2: introduce... |
559 |
if (!blocksize) { |
feee880fa nilfs2: reduce ba... |
560 |
nilfs_msg(sb, KERN_ERR, "unable to set blocksize"); |
8a9d2191e nilfs2: operation... |
561 562 563 |
err = -EINVAL; goto out; } |
e339ad31f nilfs2: introduce... |
564 565 566 |
err = nilfs_load_super_block(nilfs, sb, blocksize, &sbp); if (err) goto out; |
8a9d2191e nilfs2: operation... |
567 568 569 |
err = nilfs_store_magic_and_option(sb, sbp, data); if (err) goto failed_sbh; |
c5ca48aab nilfs2: reject in... |
570 571 572 |
err = nilfs_check_feature_compatibility(sb, sbp); if (err) goto failed_sbh; |
8a9d2191e nilfs2: operation... |
573 |
blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); |
89c0fd014 nilfs2: reject fi... |
574 575 |
if (blocksize < NILFS_MIN_BLOCK_SIZE || blocksize > NILFS_MAX_BLOCK_SIZE) { |
feee880fa nilfs2: reduce ba... |
576 577 578 |
nilfs_msg(sb, KERN_ERR, "couldn't mount because of unsupported filesystem blocksize %d", blocksize); |
89c0fd014 nilfs2: reject fi... |
579 580 581 |
err = -EINVAL; goto failed_sbh; } |
8a9d2191e nilfs2: operation... |
582 |
if (sb->s_blocksize != blocksize) { |
e1defc4ff block: Do away wi... |
583 |
int hw_blocksize = bdev_logical_block_size(sb->s_bdev); |
e339ad31f nilfs2: introduce... |
584 585 |
if (blocksize < hw_blocksize) { |
feee880fa nilfs2: reduce ba... |
586 587 588 |
nilfs_msg(sb, KERN_ERR, "blocksize %d too small for device (sector-size = %d)", blocksize, hw_blocksize); |
8a9d2191e nilfs2: operation... |
589 |
err = -EINVAL; |
e339ad31f nilfs2: introduce... |
590 591 592 593 594 595 596 |
goto failed_sbh; } nilfs_release_super_block(nilfs); sb_set_blocksize(sb, blocksize); err = nilfs_load_super_block(nilfs, sb, blocksize, &sbp); if (err) |
8a9d2191e nilfs2: operation... |
597 |
goto out; |
076a378ba nilfs2: fix block... |
598 599 600 601 |
/* * Not to failed_sbh; sbh is released automatically * when reloading fails. */ |
8a9d2191e nilfs2: operation... |
602 603 |
} nilfs->ns_blocksize_bits = sb->s_blocksize_bits; |
92c60ccaf nilfs2: add block... |
604 |
nilfs->ns_blocksize = blocksize; |
8a9d2191e nilfs2: operation... |
605 |
|
9b1fc4e49 nilfs2: move next... |
606 607 |
get_random_bytes(&nilfs->ns_next_generation, sizeof(nilfs->ns_next_generation)); |
e339ad31f nilfs2: introduce... |
608 |
err = nilfs_store_disk_layout(nilfs, sbp); |
8a9d2191e nilfs2: operation... |
609 610 611 612 613 614 |
if (err) goto failed_sbh; sb->s_maxbytes = nilfs_max_size(sb->s_blocksize_bits); nilfs->ns_mount_state = le16_to_cpu(sbp->s_state); |
8a9d2191e nilfs2: operation... |
615 |
|
843d63baa nilfs2: separate ... |
616 617 |
err = nilfs_store_log_cursor(nilfs, sbp); if (err) |
8a9d2191e nilfs2: operation... |
618 |
goto failed_sbh; |
8a9d2191e nilfs2: operation... |
619 |
|
dd70edbde nilfs2: integrate... |
620 621 622 |
err = nilfs_sysfs_create_device_group(sb); if (err) goto failed_sbh; |
8a9d2191e nilfs2: operation... |
623 624 625 626 627 628 629 |
set_nilfs_init(nilfs); err = 0; out: up_write(&nilfs->ns_sem); return err; failed_sbh: |
e339ad31f nilfs2: introduce... |
630 |
nilfs_release_super_block(nilfs); |
8a9d2191e nilfs2: operation... |
631 632 |
goto out; } |
e902ec990 nilfs2: issue dis... |
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 |
int nilfs_discard_segments(struct the_nilfs *nilfs, __u64 *segnump, size_t nsegs) { sector_t seg_start, seg_end; sector_t start = 0, nblocks = 0; unsigned int sects_per_block; __u64 *sn; int ret = 0; sects_per_block = (1 << nilfs->ns_blocksize_bits) / bdev_logical_block_size(nilfs->ns_bdev); for (sn = segnump; sn < segnump + nsegs; sn++) { nilfs_get_segment_range(nilfs, *sn, &seg_start, &seg_end); if (!nblocks) { start = seg_start; nblocks = seg_end - seg_start + 1; } else if (start + nblocks == seg_start) { nblocks += seg_end - seg_start + 1; } else { ret = blkdev_issue_discard(nilfs->ns_bdev, start * sects_per_block, nblocks * sects_per_block, |
dd3932edd block: remove BLK... |
656 |
GFP_NOFS, 0); |
e902ec990 nilfs2: issue dis... |
657 658 659 660 661 662 663 664 665 |
if (ret < 0) return ret; nblocks = 0; } } if (nblocks) ret = blkdev_issue_discard(nilfs->ns_bdev, start * sects_per_block, nblocks * sects_per_block, |
dd3932edd block: remove BLK... |
666 |
GFP_NOFS, 0); |
e902ec990 nilfs2: issue dis... |
667 668 |
return ret; } |
8a9d2191e nilfs2: operation... |
669 670 |
int nilfs_count_free_blocks(struct the_nilfs *nilfs, sector_t *nblocks) { |
8a9d2191e nilfs2: operation... |
671 |
unsigned long ncleansegs; |
8a9d2191e nilfs2: operation... |
672 |
|
365e215ce nilfs2: unfold ni... |
673 |
down_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); |
ef7d4757a nilfs2: simplify ... |
674 |
ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile); |
365e215ce nilfs2: unfold ni... |
675 |
up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); |
ef7d4757a nilfs2: simplify ... |
676 677 |
*nblocks = (sector_t)ncleansegs * nilfs->ns_blocks_per_segment; return 0; |
8a9d2191e nilfs2: operation... |
678 |
} |
8a9d2191e nilfs2: operation... |
679 680 |
int nilfs_near_disk_full(struct the_nilfs *nilfs) { |
8a9d2191e nilfs2: operation... |
681 |
unsigned long ncleansegs, nincsegs; |
ef7d4757a nilfs2: simplify ... |
682 683 684 685 686 687 |
ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile); nincsegs = atomic_read(&nilfs->ns_ndirtyblks) / nilfs->ns_blocks_per_segment + 1; return ncleansegs <= nilfs->ns_nrsvsegs + nincsegs; |
8a9d2191e nilfs2: operation... |
688 |
} |
ba65ae472 nilfs2: add check... |
689 |
struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno) |
6dd474066 nilfs2: simplify ... |
690 |
{ |
ba65ae472 nilfs2: add check... |
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 |
struct rb_node *n; struct nilfs_root *root; spin_lock(&nilfs->ns_cptree_lock); n = nilfs->ns_cptree.rb_node; while (n) { root = rb_entry(n, struct nilfs_root, rb_node); if (cno < root->cno) { n = n->rb_left; } else if (cno > root->cno) { n = n->rb_right; } else { atomic_inc(&root->count); spin_unlock(&nilfs->ns_cptree_lock); return root; } |
6dd474066 nilfs2: simplify ... |
708 |
} |
ba65ae472 nilfs2: add check... |
709 |
spin_unlock(&nilfs->ns_cptree_lock); |
6dd474066 nilfs2: simplify ... |
710 |
|
6dd474066 nilfs2: simplify ... |
711 |
return NULL; |
6dd474066 nilfs2: simplify ... |
712 |
} |
ba65ae472 nilfs2: add check... |
713 714 |
struct nilfs_root * nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno) |
8a9d2191e nilfs2: operation... |
715 |
{ |
ba65ae472 nilfs2: add check... |
716 717 |
struct rb_node **p, *parent; struct nilfs_root *root, *new; |
dd70edbde nilfs2: integrate... |
718 |
int err; |
8a9d2191e nilfs2: operation... |
719 |
|
ba65ae472 nilfs2: add check... |
720 721 722 |
root = nilfs_lookup_root(nilfs, cno); if (root) return root; |
8a9d2191e nilfs2: operation... |
723 |
|
dd70edbde nilfs2: integrate... |
724 |
new = kzalloc(sizeof(*root), GFP_KERNEL); |
ba65ae472 nilfs2: add check... |
725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 |
if (!new) return NULL; spin_lock(&nilfs->ns_cptree_lock); p = &nilfs->ns_cptree.rb_node; parent = NULL; while (*p) { parent = *p; root = rb_entry(parent, struct nilfs_root, rb_node); if (cno < root->cno) { p = &(*p)->rb_left; } else if (cno > root->cno) { p = &(*p)->rb_right; } else { atomic_inc(&root->count); spin_unlock(&nilfs->ns_cptree_lock); kfree(new); return root; |
8a9d2191e nilfs2: operation... |
746 747 |
} } |
8a9d2191e nilfs2: operation... |
748 |
|
ba65ae472 nilfs2: add check... |
749 750 751 752 |
new->cno = cno; new->ifile = NULL; new->nilfs = nilfs; atomic_set(&new->count, 1); |
e5f7f8484 ] nilfs2: use ato... |
753 754 |
atomic64_set(&new->inodes_count, 0); atomic64_set(&new->blocks_count, 0); |
ba65ae472 nilfs2: add check... |
755 756 757 758 759 |
rb_link_node(&new->rb_node, parent, p); rb_insert_color(&new->rb_node, &nilfs->ns_cptree); spin_unlock(&nilfs->ns_cptree_lock); |
dd70edbde nilfs2: integrate... |
760 761 762 763 764 |
err = nilfs_sysfs_create_snapshot_group(new); if (err) { kfree(new); new = NULL; } |
ba65ae472 nilfs2: add check... |
765 766 767 768 769 770 771 |
return new; } void nilfs_put_root(struct nilfs_root *root) { if (atomic_dec_and_test(&root->count)) { struct the_nilfs *nilfs = root->nilfs; |
dd70edbde nilfs2: integrate... |
772 |
nilfs_sysfs_delete_snapshot_group(root); |
ba65ae472 nilfs2: add check... |
773 774 775 |
spin_lock(&nilfs->ns_cptree_lock); rb_erase(&root->rb_node, &nilfs->ns_cptree); spin_unlock(&nilfs->ns_cptree_lock); |
72b9918ea nilfs2: deletion ... |
776 |
iput(root->ifile); |
ba65ae472 nilfs2: add check... |
777 778 779 |
kfree(root); } |
8a9d2191e nilfs2: operation... |
780 |
} |