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