1ae98043fSRyusuke Konishi // SPDX-License-Identifier: GPL-2.0+ 28a9d2191SRyusuke Konishi /* 394ee1d91SRyusuke Konishi * the_nilfs shared structure. 48a9d2191SRyusuke Konishi * 58a9d2191SRyusuke Konishi * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation. 68a9d2191SRyusuke Konishi * 74b420ab4SRyusuke Konishi * Written by Ryusuke Konishi. 88a9d2191SRyusuke Konishi * 98a9d2191SRyusuke Konishi */ 108a9d2191SRyusuke Konishi 118a9d2191SRyusuke Konishi #include <linux/buffer_head.h> 128a9d2191SRyusuke Konishi #include <linux/slab.h> 138a9d2191SRyusuke Konishi #include <linux/blkdev.h> 148a9d2191SRyusuke Konishi #include <linux/backing-dev.h> 159b1fc4e4SRyusuke Konishi #include <linux/random.h> 16*610a2a3dSRyusuke Konishi #include <linux/log2.h> 17e339ad31SRyusuke Konishi #include <linux/crc32.h> 188a9d2191SRyusuke Konishi #include "nilfs.h" 198a9d2191SRyusuke Konishi #include "segment.h" 208a9d2191SRyusuke Konishi #include "alloc.h" 218a9d2191SRyusuke Konishi #include "cpfile.h" 228a9d2191SRyusuke Konishi #include "sufile.h" 238a9d2191SRyusuke Konishi #include "dat.h" 248a9d2191SRyusuke Konishi #include "segbuf.h" 258a9d2191SRyusuke Konishi 2633c8e57cSRyusuke Konishi 276c125160SRyusuke Konishi static int nilfs_valid_sb(struct nilfs_super_block *sbp); 286c125160SRyusuke Konishi 298a9d2191SRyusuke Konishi void nilfs_set_last_segment(struct the_nilfs *nilfs, 308a9d2191SRyusuke Konishi sector_t start_blocknr, u64 seq, __u64 cno) 318a9d2191SRyusuke Konishi { 328a9d2191SRyusuke Konishi spin_lock(&nilfs->ns_last_segment_lock); 338a9d2191SRyusuke Konishi nilfs->ns_last_pseg = start_blocknr; 348a9d2191SRyusuke Konishi nilfs->ns_last_seq = seq; 358a9d2191SRyusuke Konishi nilfs->ns_last_cno = cno; 3632502047SRyusuke Konishi 3732502047SRyusuke Konishi if (!nilfs_sb_dirty(nilfs)) { 3832502047SRyusuke Konishi if (nilfs->ns_prev_seq == nilfs->ns_last_seq) 3932502047SRyusuke Konishi goto stay_cursor; 4032502047SRyusuke Konishi 4132502047SRyusuke Konishi set_nilfs_sb_dirty(nilfs); 4232502047SRyusuke Konishi } 4332502047SRyusuke Konishi nilfs->ns_prev_seq = nilfs->ns_last_seq; 4432502047SRyusuke Konishi 4532502047SRyusuke Konishi stay_cursor: 468a9d2191SRyusuke Konishi spin_unlock(&nilfs->ns_last_segment_lock); 478a9d2191SRyusuke Konishi } 488a9d2191SRyusuke Konishi 498a9d2191SRyusuke Konishi /** 50348fe8daSRyusuke Konishi * alloc_nilfs - allocate a nilfs object 516625689eSRyusuke Konishi * @sb: super block instance 528a9d2191SRyusuke Konishi * 538a9d2191SRyusuke Konishi * Return Value: On success, pointer to the_nilfs is returned. 548a9d2191SRyusuke Konishi * On error, NULL is returned. 558a9d2191SRyusuke Konishi */ 566625689eSRyusuke Konishi struct the_nilfs *alloc_nilfs(struct super_block *sb) 578a9d2191SRyusuke Konishi { 588a9d2191SRyusuke Konishi struct the_nilfs *nilfs; 598a9d2191SRyusuke Konishi 608a9d2191SRyusuke Konishi nilfs = kzalloc(sizeof(*nilfs), GFP_KERNEL); 618a9d2191SRyusuke Konishi if (!nilfs) 628a9d2191SRyusuke Konishi return NULL; 638a9d2191SRyusuke Konishi 646625689eSRyusuke Konishi nilfs->ns_sb = sb; 656625689eSRyusuke Konishi nilfs->ns_bdev = sb->s_bdev; 668a9d2191SRyusuke Konishi atomic_set(&nilfs->ns_ndirtyblks, 0); 678a9d2191SRyusuke Konishi init_rwsem(&nilfs->ns_sem); 68572d8b39SRyusuke Konishi mutex_init(&nilfs->ns_snapshot_mount_mutex); 69693dd321SRyusuke Konishi INIT_LIST_HEAD(&nilfs->ns_dirty_files); 70263d90ceSRyusuke Konishi INIT_LIST_HEAD(&nilfs->ns_gc_inodes); 71693dd321SRyusuke Konishi spin_lock_init(&nilfs->ns_inode_lock); 729b1fc4e4SRyusuke Konishi spin_lock_init(&nilfs->ns_next_gen_lock); 738a9d2191SRyusuke Konishi spin_lock_init(&nilfs->ns_last_segment_lock); 74ba65ae47SRyusuke Konishi nilfs->ns_cptree = RB_ROOT; 75ba65ae47SRyusuke Konishi spin_lock_init(&nilfs->ns_cptree_lock); 768a9d2191SRyusuke Konishi init_rwsem(&nilfs->ns_segctor_sem); 77caa05d49SVyacheslav Dubeyko nilfs->ns_sb_update_freq = NILFS_SB_FREQ; 788a9d2191SRyusuke Konishi 798a9d2191SRyusuke Konishi return nilfs; 808a9d2191SRyusuke Konishi } 818a9d2191SRyusuke Konishi 828a9d2191SRyusuke Konishi /** 83348fe8daSRyusuke Konishi * destroy_nilfs - destroy nilfs object 84348fe8daSRyusuke Konishi * @nilfs: nilfs object to be released 8533c8e57cSRyusuke Konishi */ 86348fe8daSRyusuke Konishi void destroy_nilfs(struct the_nilfs *nilfs) 8733c8e57cSRyusuke Konishi { 888a9d2191SRyusuke Konishi might_sleep(); 898a9d2191SRyusuke Konishi if (nilfs_init(nilfs)) { 90dd70edbdSVyacheslav Dubeyko nilfs_sysfs_delete_device_group(nilfs); 91e339ad31SRyusuke Konishi brelse(nilfs->ns_sbh[0]); 92e339ad31SRyusuke Konishi brelse(nilfs->ns_sbh[1]); 938a9d2191SRyusuke Konishi } 948a9d2191SRyusuke Konishi kfree(nilfs); 958a9d2191SRyusuke Konishi } 968a9d2191SRyusuke Konishi 97f1e89c86SRyusuke Konishi static int nilfs_load_super_root(struct the_nilfs *nilfs, 98f1e89c86SRyusuke Konishi struct super_block *sb, sector_t sr_block) 998a9d2191SRyusuke Konishi { 1008a9d2191SRyusuke Konishi struct buffer_head *bh_sr; 1018a9d2191SRyusuke Konishi struct nilfs_super_root *raw_sr; 102e339ad31SRyusuke Konishi struct nilfs_super_block **sbp = nilfs->ns_sbp; 103f1e89c86SRyusuke Konishi struct nilfs_inode *rawi; 1040c6c44cbSRyusuke Konishi unsigned int dat_entry_size, segment_usage_size, checkpoint_size; 1050c6c44cbSRyusuke Konishi unsigned int inode_size; 1068a9d2191SRyusuke Konishi int err; 1078a9d2191SRyusuke Konishi 1088b94025cSRyusuke Konishi err = nilfs_read_super_root_block(nilfs, sr_block, &bh_sr, 1); 1098a9d2191SRyusuke Konishi if (unlikely(err)) 1108a9d2191SRyusuke Konishi return err; 1118a9d2191SRyusuke Konishi 1128a9d2191SRyusuke Konishi down_read(&nilfs->ns_sem); 113e339ad31SRyusuke Konishi dat_entry_size = le16_to_cpu(sbp[0]->s_dat_entry_size); 114e339ad31SRyusuke Konishi checkpoint_size = le16_to_cpu(sbp[0]->s_checkpoint_size); 115e339ad31SRyusuke Konishi segment_usage_size = le16_to_cpu(sbp[0]->s_segment_usage_size); 1168a9d2191SRyusuke Konishi up_read(&nilfs->ns_sem); 1178a9d2191SRyusuke Konishi 1188a9d2191SRyusuke Konishi inode_size = nilfs->ns_inode_size; 1198a9d2191SRyusuke Konishi 120f1e89c86SRyusuke Konishi rawi = (void *)bh_sr->b_data + NILFS_SR_DAT_OFFSET(inode_size); 121f1e89c86SRyusuke Konishi err = nilfs_dat_read(sb, dat_entry_size, rawi, &nilfs->ns_dat); 122f1e89c86SRyusuke Konishi if (err) 1238a9d2191SRyusuke Konishi goto failed; 1248a9d2191SRyusuke Konishi 125f1e89c86SRyusuke Konishi rawi = (void *)bh_sr->b_data + NILFS_SR_CPFILE_OFFSET(inode_size); 126f1e89c86SRyusuke Konishi err = nilfs_cpfile_read(sb, checkpoint_size, rawi, &nilfs->ns_cpfile); 127f1e89c86SRyusuke Konishi if (err) 1288a9d2191SRyusuke Konishi goto failed_dat; 1298a9d2191SRyusuke Konishi 130f1e89c86SRyusuke Konishi rawi = (void *)bh_sr->b_data + NILFS_SR_SUFILE_OFFSET(inode_size); 131f1e89c86SRyusuke Konishi err = nilfs_sufile_read(sb, segment_usage_size, rawi, 132f1e89c86SRyusuke Konishi &nilfs->ns_sufile); 133f1e89c86SRyusuke Konishi if (err) 1348a9d2191SRyusuke Konishi goto failed_cpfile; 1358a9d2191SRyusuke Konishi 1368a9d2191SRyusuke Konishi raw_sr = (struct nilfs_super_root *)bh_sr->b_data; 1378a9d2191SRyusuke Konishi nilfs->ns_nongc_ctime = le64_to_cpu(raw_sr->sr_nongc_ctime); 1388a9d2191SRyusuke Konishi 1398a9d2191SRyusuke Konishi failed: 1408a9d2191SRyusuke Konishi brelse(bh_sr); 1418a9d2191SRyusuke Konishi return err; 1428a9d2191SRyusuke Konishi 1438a9d2191SRyusuke Konishi failed_cpfile: 144f1e89c86SRyusuke Konishi iput(nilfs->ns_cpfile); 1458a9d2191SRyusuke Konishi 1468a9d2191SRyusuke Konishi failed_dat: 147f1e89c86SRyusuke Konishi iput(nilfs->ns_dat); 1488a9d2191SRyusuke Konishi goto failed; 1498a9d2191SRyusuke Konishi } 1508a9d2191SRyusuke Konishi 1518a9d2191SRyusuke Konishi static void nilfs_init_recovery_info(struct nilfs_recovery_info *ri) 1528a9d2191SRyusuke Konishi { 1538a9d2191SRyusuke Konishi memset(ri, 0, sizeof(*ri)); 1548a9d2191SRyusuke Konishi INIT_LIST_HEAD(&ri->ri_used_segments); 1558a9d2191SRyusuke Konishi } 1568a9d2191SRyusuke Konishi 1578a9d2191SRyusuke Konishi static void nilfs_clear_recovery_info(struct nilfs_recovery_info *ri) 1588a9d2191SRyusuke Konishi { 1598a9d2191SRyusuke Konishi nilfs_dispose_segment_list(&ri->ri_used_segments); 1608a9d2191SRyusuke Konishi } 1618a9d2191SRyusuke Konishi 1628a9d2191SRyusuke Konishi /** 163843d63baSRyusuke Konishi * nilfs_store_log_cursor - load log cursor from a super block 164843d63baSRyusuke Konishi * @nilfs: nilfs object 165843d63baSRyusuke Konishi * @sbp: buffer storing super block to be read 166843d63baSRyusuke Konishi * 167843d63baSRyusuke Konishi * nilfs_store_log_cursor() reads the last position of the log 168843d63baSRyusuke Konishi * containing a super root from a given super block, and initializes 169843d63baSRyusuke Konishi * relevant information on the nilfs object preparatory for log 170843d63baSRyusuke Konishi * scanning and recovery. 171843d63baSRyusuke Konishi */ 172843d63baSRyusuke Konishi static int nilfs_store_log_cursor(struct the_nilfs *nilfs, 173843d63baSRyusuke Konishi struct nilfs_super_block *sbp) 174843d63baSRyusuke Konishi { 175843d63baSRyusuke Konishi int ret = 0; 176843d63baSRyusuke Konishi 177843d63baSRyusuke Konishi nilfs->ns_last_pseg = le64_to_cpu(sbp->s_last_pseg); 178843d63baSRyusuke Konishi nilfs->ns_last_cno = le64_to_cpu(sbp->s_last_cno); 179843d63baSRyusuke Konishi nilfs->ns_last_seq = le64_to_cpu(sbp->s_last_seq); 180843d63baSRyusuke Konishi 18132502047SRyusuke Konishi nilfs->ns_prev_seq = nilfs->ns_last_seq; 182843d63baSRyusuke Konishi nilfs->ns_seg_seq = nilfs->ns_last_seq; 183843d63baSRyusuke Konishi nilfs->ns_segnum = 184843d63baSRyusuke Konishi nilfs_get_segnum_of_block(nilfs, nilfs->ns_last_pseg); 185843d63baSRyusuke Konishi nilfs->ns_cno = nilfs->ns_last_cno + 1; 186843d63baSRyusuke Konishi if (nilfs->ns_segnum >= nilfs->ns_nsegments) { 187a1d0747aSJoe Perches nilfs_err(nilfs->ns_sb, 188feee880fSRyusuke Konishi "pointed segment number is out of range: segnum=%llu, nsegments=%lu", 189feee880fSRyusuke Konishi (unsigned long long)nilfs->ns_segnum, 190feee880fSRyusuke Konishi nilfs->ns_nsegments); 191843d63baSRyusuke Konishi ret = -EINVAL; 192843d63baSRyusuke Konishi } 193843d63baSRyusuke Konishi return ret; 194843d63baSRyusuke Konishi } 195843d63baSRyusuke Konishi 196843d63baSRyusuke Konishi /** 1978a9d2191SRyusuke Konishi * load_nilfs - load and recover the nilfs 1988a9d2191SRyusuke Konishi * @nilfs: the_nilfs structure to be released 199312f79c4SLu Jialin * @sb: super block instance used to recover past segment 2008a9d2191SRyusuke Konishi * 2018a9d2191SRyusuke Konishi * load_nilfs() searches and load the latest super root, 2028a9d2191SRyusuke Konishi * attaches the last segment, and does recovery if needed. 2038a9d2191SRyusuke Konishi * The caller must call this exclusively for simultaneous mounts. 2048a9d2191SRyusuke Konishi */ 205f7545144SRyusuke Konishi int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb) 2068a9d2191SRyusuke Konishi { 2078a9d2191SRyusuke Konishi struct nilfs_recovery_info ri; 208f7545144SRyusuke Konishi unsigned int s_flags = sb->s_flags; 2098a9d2191SRyusuke Konishi int really_read_only = bdev_read_only(nilfs->ns_bdev); 210a057d2c0SRyusuke Konishi int valid_fs = nilfs_valid_fs(nilfs); 211f50a4c81SRyusuke Konishi int err; 2128a9d2191SRyusuke Konishi 213f50a4c81SRyusuke Konishi if (!valid_fs) { 214a1d0747aSJoe Perches nilfs_warn(sb, "mounting unchecked fs"); 2151751e8a6SLinus Torvalds if (s_flags & SB_RDONLY) { 216a1d0747aSJoe Perches nilfs_info(sb, 217feee880fSRyusuke Konishi "recovery required for readonly filesystem"); 218a1d0747aSJoe Perches nilfs_info(sb, 219feee880fSRyusuke Konishi "write access will be enabled during recovery"); 2208a9d2191SRyusuke Konishi } 221f50a4c81SRyusuke Konishi } 222f50a4c81SRyusuke Konishi 223f50a4c81SRyusuke Konishi nilfs_init_recovery_info(&ri); 2248a9d2191SRyusuke Konishi 2258b94025cSRyusuke Konishi err = nilfs_search_super_root(nilfs, &ri); 2268a9d2191SRyusuke Konishi if (unlikely(err)) { 2276c125160SRyusuke Konishi struct nilfs_super_block **sbp = nilfs->ns_sbp; 2286c125160SRyusuke Konishi int blocksize; 2296c125160SRyusuke Konishi 2306c125160SRyusuke Konishi if (err != -EINVAL) 2316c125160SRyusuke Konishi goto scan_error; 2326c125160SRyusuke Konishi 2336c125160SRyusuke Konishi if (!nilfs_valid_sb(sbp[1])) { 234a1d0747aSJoe Perches nilfs_warn(sb, 235feee880fSRyusuke Konishi "unable to fall back to spare super block"); 2366c125160SRyusuke Konishi goto scan_error; 2376c125160SRyusuke Konishi } 238a1d0747aSJoe Perches nilfs_info(sb, "trying rollback from an earlier position"); 2396c125160SRyusuke Konishi 2406c125160SRyusuke Konishi /* 2416c125160SRyusuke Konishi * restore super block with its spare and reconfigure 2426c125160SRyusuke Konishi * relevant states of the nilfs object. 2436c125160SRyusuke Konishi */ 2446c125160SRyusuke Konishi memcpy(sbp[0], sbp[1], nilfs->ns_sbsize); 2456c125160SRyusuke Konishi nilfs->ns_crc_seed = le32_to_cpu(sbp[0]->s_crc_seed); 2466c125160SRyusuke Konishi nilfs->ns_sbwtime = le64_to_cpu(sbp[0]->s_wtime); 2476c125160SRyusuke Konishi 2486c125160SRyusuke Konishi /* verify consistency between two super blocks */ 2496c125160SRyusuke Konishi blocksize = BLOCK_SIZE << le32_to_cpu(sbp[0]->s_log_block_size); 2506c125160SRyusuke Konishi if (blocksize != nilfs->ns_blocksize) { 251a1d0747aSJoe Perches nilfs_warn(sb, 252feee880fSRyusuke Konishi "blocksize differs between two super blocks (%d != %d)", 2536c125160SRyusuke Konishi blocksize, nilfs->ns_blocksize); 2546c125160SRyusuke Konishi goto scan_error; 2556c125160SRyusuke Konishi } 2566c125160SRyusuke Konishi 2576c125160SRyusuke Konishi err = nilfs_store_log_cursor(nilfs, sbp[0]); 2586c125160SRyusuke Konishi if (err) 2596c125160SRyusuke Konishi goto scan_error; 2606c125160SRyusuke Konishi 2616c125160SRyusuke Konishi /* drop clean flag to allow roll-forward and recovery */ 2626c125160SRyusuke Konishi nilfs->ns_mount_state &= ~NILFS_VALID_FS; 2636c125160SRyusuke Konishi valid_fs = 0; 2646c125160SRyusuke Konishi 2656c125160SRyusuke Konishi err = nilfs_search_super_root(nilfs, &ri); 2666c125160SRyusuke Konishi if (err) 2676c125160SRyusuke Konishi goto scan_error; 2688a9d2191SRyusuke Konishi } 2698a9d2191SRyusuke Konishi 270f7545144SRyusuke Konishi err = nilfs_load_super_root(nilfs, sb, ri.ri_super_root); 2718a9d2191SRyusuke Konishi if (unlikely(err)) { 272a1d0747aSJoe Perches nilfs_err(sb, "error %d while loading super root", err); 2738a9d2191SRyusuke Konishi goto failed; 2748a9d2191SRyusuke Konishi } 2758a9d2191SRyusuke Konishi 276f50a4c81SRyusuke Konishi if (valid_fs) 277f50a4c81SRyusuke Konishi goto skip_recovery; 278f50a4c81SRyusuke Konishi 2791751e8a6SLinus Torvalds if (s_flags & SB_RDONLY) { 280c5ca48aaSRyusuke Konishi __u64 features; 281c5ca48aaSRyusuke Konishi 2823b2ce58bSRyusuke Konishi if (nilfs_test_opt(nilfs, NORECOVERY)) { 283a1d0747aSJoe Perches nilfs_info(sb, 284feee880fSRyusuke Konishi "norecovery option specified, skipping roll-forward recovery"); 2850234576dSRyusuke Konishi goto skip_recovery; 2860234576dSRyusuke Konishi } 287c5ca48aaSRyusuke Konishi features = le64_to_cpu(nilfs->ns_sbp[0]->s_feature_compat_ro) & 288c5ca48aaSRyusuke Konishi ~NILFS_FEATURE_COMPAT_RO_SUPP; 289c5ca48aaSRyusuke Konishi if (features) { 290a1d0747aSJoe Perches nilfs_err(sb, 291feee880fSRyusuke Konishi "couldn't proceed with recovery because of unsupported optional features (%llx)", 292c5ca48aaSRyusuke Konishi (unsigned long long)features); 293c5ca48aaSRyusuke Konishi err = -EROFS; 294c5ca48aaSRyusuke Konishi goto failed_unload; 295c5ca48aaSRyusuke Konishi } 296f50a4c81SRyusuke Konishi if (really_read_only) { 297a1d0747aSJoe Perches nilfs_err(sb, 298feee880fSRyusuke Konishi "write access unavailable, cannot proceed"); 299f50a4c81SRyusuke Konishi err = -EROFS; 300f50a4c81SRyusuke Konishi goto failed_unload; 301f50a4c81SRyusuke Konishi } 3021751e8a6SLinus Torvalds sb->s_flags &= ~SB_RDONLY; 3033b2ce58bSRyusuke Konishi } else if (nilfs_test_opt(nilfs, NORECOVERY)) { 304a1d0747aSJoe Perches nilfs_err(sb, 305feee880fSRyusuke Konishi "recovery cancelled because norecovery option was specified for a read/write mount"); 3060234576dSRyusuke Konishi err = -EINVAL; 3070234576dSRyusuke Konishi goto failed_unload; 308f50a4c81SRyusuke Konishi } 309f50a4c81SRyusuke Konishi 310f7545144SRyusuke Konishi err = nilfs_salvage_orphan_logs(nilfs, sb, &ri); 311f50a4c81SRyusuke Konishi if (err) 312f50a4c81SRyusuke Konishi goto failed_unload; 313f50a4c81SRyusuke Konishi 314f50a4c81SRyusuke Konishi down_write(&nilfs->ns_sem); 3157ecaa46cSRyusuke Konishi nilfs->ns_mount_state |= NILFS_VALID_FS; /* set "clean" flag */ 316f7545144SRyusuke Konishi err = nilfs_cleanup_super(sb); 317f50a4c81SRyusuke Konishi up_write(&nilfs->ns_sem); 318f50a4c81SRyusuke Konishi 319f50a4c81SRyusuke Konishi if (err) { 320a1d0747aSJoe Perches nilfs_err(sb, 321feee880fSRyusuke Konishi "error %d updating super block. recovery unfinished.", 322feee880fSRyusuke Konishi err); 323f50a4c81SRyusuke Konishi goto failed_unload; 324f50a4c81SRyusuke Konishi } 325a1d0747aSJoe Perches nilfs_info(sb, "recovery complete"); 326f50a4c81SRyusuke Konishi 327f50a4c81SRyusuke Konishi skip_recovery: 328f50a4c81SRyusuke Konishi nilfs_clear_recovery_info(&ri); 329f7545144SRyusuke Konishi sb->s_flags = s_flags; 330f50a4c81SRyusuke Konishi return 0; 331f50a4c81SRyusuke Konishi 3326c125160SRyusuke Konishi scan_error: 333a1d0747aSJoe Perches nilfs_err(sb, "error %d while searching super root", err); 3346c125160SRyusuke Konishi goto failed; 3356c125160SRyusuke Konishi 336f50a4c81SRyusuke Konishi failed_unload: 337f1e89c86SRyusuke Konishi iput(nilfs->ns_cpfile); 338f1e89c86SRyusuke Konishi iput(nilfs->ns_sufile); 339f1e89c86SRyusuke Konishi iput(nilfs->ns_dat); 3408a9d2191SRyusuke Konishi 3418a9d2191SRyusuke Konishi failed: 3428a9d2191SRyusuke Konishi nilfs_clear_recovery_info(&ri); 343f7545144SRyusuke Konishi sb->s_flags = s_flags; 3448a9d2191SRyusuke Konishi return err; 3458a9d2191SRyusuke Konishi } 3468a9d2191SRyusuke Konishi 3478a9d2191SRyusuke Konishi static unsigned long long nilfs_max_size(unsigned int blkbits) 3488a9d2191SRyusuke Konishi { 3498a9d2191SRyusuke Konishi unsigned int max_bits; 3508a9d2191SRyusuke Konishi unsigned long long res = MAX_LFS_FILESIZE; /* page cache limit */ 3518a9d2191SRyusuke Konishi 3528a9d2191SRyusuke Konishi max_bits = blkbits + NILFS_BMAP_KEY_BIT; /* bmap size limit */ 3538a9d2191SRyusuke Konishi if (max_bits < 64) 3548a9d2191SRyusuke Konishi res = min_t(unsigned long long, res, (1ULL << max_bits) - 1); 3558a9d2191SRyusuke Konishi return res; 3568a9d2191SRyusuke Konishi } 3578a9d2191SRyusuke Konishi 3584e33f9eaSRyusuke Konishi /** 3594e33f9eaSRyusuke Konishi * nilfs_nrsvsegs - calculate the number of reserved segments 3604e33f9eaSRyusuke Konishi * @nilfs: nilfs object 3614e33f9eaSRyusuke Konishi * @nsegs: total number of segments 3624e33f9eaSRyusuke Konishi */ 3634e33f9eaSRyusuke Konishi unsigned long nilfs_nrsvsegs(struct the_nilfs *nilfs, unsigned long nsegs) 3644e33f9eaSRyusuke Konishi { 3654e33f9eaSRyusuke Konishi return max_t(unsigned long, NILFS_MIN_NRSVSEGS, 3664e33f9eaSRyusuke Konishi DIV_ROUND_UP(nsegs * nilfs->ns_r_segments_percentage, 3674e33f9eaSRyusuke Konishi 100)); 3684e33f9eaSRyusuke Konishi } 3694e33f9eaSRyusuke Konishi 3704e33f9eaSRyusuke Konishi void nilfs_set_nsegments(struct the_nilfs *nilfs, unsigned long nsegs) 3714e33f9eaSRyusuke Konishi { 3724e33f9eaSRyusuke Konishi nilfs->ns_nsegments = nsegs; 3734e33f9eaSRyusuke Konishi nilfs->ns_nrsvsegs = nilfs_nrsvsegs(nilfs, nsegs); 3744e33f9eaSRyusuke Konishi } 3754e33f9eaSRyusuke Konishi 376e339ad31SRyusuke Konishi static int nilfs_store_disk_layout(struct the_nilfs *nilfs, 3778a9d2191SRyusuke Konishi struct nilfs_super_block *sbp) 3788a9d2191SRyusuke Konishi { 3799566a7a8SRyusuke Konishi if (le32_to_cpu(sbp->s_rev_level) < NILFS_MIN_SUPP_REV) { 380a1d0747aSJoe Perches nilfs_err(nilfs->ns_sb, 381feee880fSRyusuke Konishi "unsupported revision (superblock rev.=%d.%d, current rev.=%d.%d). Please check the version of mkfs.nilfs(2).", 3828a9d2191SRyusuke Konishi le32_to_cpu(sbp->s_rev_level), 3838a9d2191SRyusuke Konishi le16_to_cpu(sbp->s_minor_rev_level), 3848a9d2191SRyusuke Konishi NILFS_CURRENT_REV, NILFS_MINOR_REV); 3858a9d2191SRyusuke Konishi return -EINVAL; 3868a9d2191SRyusuke Konishi } 387e339ad31SRyusuke Konishi nilfs->ns_sbsize = le16_to_cpu(sbp->s_bytes); 388e339ad31SRyusuke Konishi if (nilfs->ns_sbsize > BLOCK_SIZE) 389e339ad31SRyusuke Konishi return -EINVAL; 390e339ad31SRyusuke Konishi 3918a9d2191SRyusuke Konishi nilfs->ns_inode_size = le16_to_cpu(sbp->s_inode_size); 3920ec060d1SRyusuke Konishi if (nilfs->ns_inode_size > nilfs->ns_blocksize) { 393a1d0747aSJoe Perches nilfs_err(nilfs->ns_sb, "too large inode size: %d bytes", 3940ec060d1SRyusuke Konishi nilfs->ns_inode_size); 3950ec060d1SRyusuke Konishi return -EINVAL; 3960ec060d1SRyusuke Konishi } else if (nilfs->ns_inode_size < NILFS_MIN_INODE_SIZE) { 397a1d0747aSJoe Perches nilfs_err(nilfs->ns_sb, "too small inode size: %d bytes", 3980ec060d1SRyusuke Konishi nilfs->ns_inode_size); 3990ec060d1SRyusuke Konishi return -EINVAL; 4000ec060d1SRyusuke Konishi } 4010ec060d1SRyusuke Konishi 4028a9d2191SRyusuke Konishi nilfs->ns_first_ino = le32_to_cpu(sbp->s_first_ino); 4038a9d2191SRyusuke Konishi 4048a9d2191SRyusuke Konishi nilfs->ns_blocks_per_segment = le32_to_cpu(sbp->s_blocks_per_segment); 4058a9d2191SRyusuke Konishi if (nilfs->ns_blocks_per_segment < NILFS_SEG_MIN_BLOCKS) { 406a1d0747aSJoe Perches nilfs_err(nilfs->ns_sb, "too short segment: %lu blocks", 407feee880fSRyusuke Konishi nilfs->ns_blocks_per_segment); 4088a9d2191SRyusuke Konishi return -EINVAL; 4098a9d2191SRyusuke Konishi } 4108a9d2191SRyusuke Konishi 4118a9d2191SRyusuke Konishi nilfs->ns_first_data_block = le64_to_cpu(sbp->s_first_data_block); 4128a9d2191SRyusuke Konishi nilfs->ns_r_segments_percentage = 4138a9d2191SRyusuke Konishi le32_to_cpu(sbp->s_r_segments_percentage); 4143d777a64SHaogang Chen if (nilfs->ns_r_segments_percentage < 1 || 4153d777a64SHaogang Chen nilfs->ns_r_segments_percentage > 99) { 416a1d0747aSJoe Perches nilfs_err(nilfs->ns_sb, 417feee880fSRyusuke Konishi "invalid reserved segments percentage: %lu", 418feee880fSRyusuke Konishi nilfs->ns_r_segments_percentage); 4193d777a64SHaogang Chen return -EINVAL; 4203d777a64SHaogang Chen } 4213d777a64SHaogang Chen 4224e33f9eaSRyusuke Konishi nilfs_set_nsegments(nilfs, le64_to_cpu(sbp->s_nsegments)); 4238a9d2191SRyusuke Konishi nilfs->ns_crc_seed = le32_to_cpu(sbp->s_crc_seed); 4248a9d2191SRyusuke Konishi return 0; 4258a9d2191SRyusuke Konishi } 4268a9d2191SRyusuke Konishi 427e339ad31SRyusuke Konishi static int nilfs_valid_sb(struct nilfs_super_block *sbp) 428e339ad31SRyusuke Konishi { 429e339ad31SRyusuke Konishi static unsigned char sum[4]; 430e339ad31SRyusuke Konishi const int sumoff = offsetof(struct nilfs_super_block, s_sum); 431e339ad31SRyusuke Konishi size_t bytes; 432e339ad31SRyusuke Konishi u32 crc; 433e339ad31SRyusuke Konishi 434e339ad31SRyusuke Konishi if (!sbp || le16_to_cpu(sbp->s_magic) != NILFS_SUPER_MAGIC) 435e339ad31SRyusuke Konishi return 0; 436e339ad31SRyusuke Konishi bytes = le16_to_cpu(sbp->s_bytes); 43763d2f95dSTorsten Hilbrich if (bytes < sumoff + 4 || bytes > BLOCK_SIZE) 438e339ad31SRyusuke Konishi return 0; 439e339ad31SRyusuke Konishi crc = crc32_le(le32_to_cpu(sbp->s_crc_seed), (unsigned char *)sbp, 440e339ad31SRyusuke Konishi sumoff); 441e339ad31SRyusuke Konishi crc = crc32_le(crc, sum, 4); 442e339ad31SRyusuke Konishi crc = crc32_le(crc, (unsigned char *)sbp + sumoff + 4, 443e339ad31SRyusuke Konishi bytes - sumoff - 4); 444e339ad31SRyusuke Konishi return crc == le32_to_cpu(sbp->s_sum); 445e339ad31SRyusuke Konishi } 446e339ad31SRyusuke Konishi 447*610a2a3dSRyusuke Konishi /** 448*610a2a3dSRyusuke Konishi * nilfs_sb2_bad_offset - check the location of the second superblock 449*610a2a3dSRyusuke Konishi * @sbp: superblock raw data buffer 450*610a2a3dSRyusuke Konishi * @offset: byte offset of second superblock calculated from device size 451*610a2a3dSRyusuke Konishi * 452*610a2a3dSRyusuke Konishi * nilfs_sb2_bad_offset() checks if the position on the second 453*610a2a3dSRyusuke Konishi * superblock is valid or not based on the filesystem parameters 454*610a2a3dSRyusuke Konishi * stored in @sbp. If @offset points to a location within the segment 455*610a2a3dSRyusuke Konishi * area, or if the parameters themselves are not normal, it is 456*610a2a3dSRyusuke Konishi * determined to be invalid. 457*610a2a3dSRyusuke Konishi * 458*610a2a3dSRyusuke Konishi * Return Value: true if invalid, false if valid. 459*610a2a3dSRyusuke Konishi */ 460*610a2a3dSRyusuke Konishi static bool nilfs_sb2_bad_offset(struct nilfs_super_block *sbp, u64 offset) 461e339ad31SRyusuke Konishi { 462*610a2a3dSRyusuke Konishi unsigned int shift_bits = le32_to_cpu(sbp->s_log_block_size); 463*610a2a3dSRyusuke Konishi u32 blocks_per_segment = le32_to_cpu(sbp->s_blocks_per_segment); 464*610a2a3dSRyusuke Konishi u64 nsegments = le64_to_cpu(sbp->s_nsegments); 465*610a2a3dSRyusuke Konishi u64 index; 466*610a2a3dSRyusuke Konishi 467*610a2a3dSRyusuke Konishi if (blocks_per_segment < NILFS_SEG_MIN_BLOCKS || 468*610a2a3dSRyusuke Konishi shift_bits > ilog2(NILFS_MAX_BLOCK_SIZE) - BLOCK_SIZE_BITS) 469*610a2a3dSRyusuke Konishi return true; 470*610a2a3dSRyusuke Konishi 471*610a2a3dSRyusuke Konishi index = offset >> (shift_bits + BLOCK_SIZE_BITS); 472*610a2a3dSRyusuke Konishi do_div(index, blocks_per_segment); 473*610a2a3dSRyusuke Konishi return index < nsegments; 474e339ad31SRyusuke Konishi } 475e339ad31SRyusuke Konishi 476e339ad31SRyusuke Konishi static void nilfs_release_super_block(struct the_nilfs *nilfs) 477e339ad31SRyusuke Konishi { 478e339ad31SRyusuke Konishi int i; 479e339ad31SRyusuke Konishi 480e339ad31SRyusuke Konishi for (i = 0; i < 2; i++) { 481e339ad31SRyusuke Konishi if (nilfs->ns_sbp[i]) { 482e339ad31SRyusuke Konishi brelse(nilfs->ns_sbh[i]); 483e339ad31SRyusuke Konishi nilfs->ns_sbh[i] = NULL; 484e339ad31SRyusuke Konishi nilfs->ns_sbp[i] = NULL; 485e339ad31SRyusuke Konishi } 486e339ad31SRyusuke Konishi } 487e339ad31SRyusuke Konishi } 488e339ad31SRyusuke Konishi 489e339ad31SRyusuke Konishi void nilfs_fall_back_super_block(struct the_nilfs *nilfs) 490e339ad31SRyusuke Konishi { 491e339ad31SRyusuke Konishi brelse(nilfs->ns_sbh[0]); 492e339ad31SRyusuke Konishi nilfs->ns_sbh[0] = nilfs->ns_sbh[1]; 493e339ad31SRyusuke Konishi nilfs->ns_sbp[0] = nilfs->ns_sbp[1]; 494e339ad31SRyusuke Konishi nilfs->ns_sbh[1] = NULL; 495e339ad31SRyusuke Konishi nilfs->ns_sbp[1] = NULL; 496e339ad31SRyusuke Konishi } 497e339ad31SRyusuke Konishi 498e339ad31SRyusuke Konishi void nilfs_swap_super_block(struct the_nilfs *nilfs) 499e339ad31SRyusuke Konishi { 500e339ad31SRyusuke Konishi struct buffer_head *tsbh = nilfs->ns_sbh[0]; 501e339ad31SRyusuke Konishi struct nilfs_super_block *tsbp = nilfs->ns_sbp[0]; 502e339ad31SRyusuke Konishi 503e339ad31SRyusuke Konishi nilfs->ns_sbh[0] = nilfs->ns_sbh[1]; 504e339ad31SRyusuke Konishi nilfs->ns_sbp[0] = nilfs->ns_sbp[1]; 505e339ad31SRyusuke Konishi nilfs->ns_sbh[1] = tsbh; 506e339ad31SRyusuke Konishi nilfs->ns_sbp[1] = tsbp; 507e339ad31SRyusuke Konishi } 508e339ad31SRyusuke Konishi 509e339ad31SRyusuke Konishi static int nilfs_load_super_block(struct the_nilfs *nilfs, 510e339ad31SRyusuke Konishi struct super_block *sb, int blocksize, 511e339ad31SRyusuke Konishi struct nilfs_super_block **sbpp) 512e339ad31SRyusuke Konishi { 513e339ad31SRyusuke Konishi struct nilfs_super_block **sbp = nilfs->ns_sbp; 514e339ad31SRyusuke Konishi struct buffer_head **sbh = nilfs->ns_sbh; 5154fcd6979SChristoph Hellwig u64 sb2off = NILFS_SB2_OFFSET_BYTES(bdev_nr_bytes(nilfs->ns_bdev)); 516e339ad31SRyusuke Konishi int valid[2], swp = 0; 517e339ad31SRyusuke Konishi 518e339ad31SRyusuke Konishi sbp[0] = nilfs_read_super_block(sb, NILFS_SB_OFFSET_BYTES, blocksize, 519e339ad31SRyusuke Konishi &sbh[0]); 520e339ad31SRyusuke Konishi sbp[1] = nilfs_read_super_block(sb, sb2off, blocksize, &sbh[1]); 521e339ad31SRyusuke Konishi 522e339ad31SRyusuke Konishi if (!sbp[0]) { 523e339ad31SRyusuke Konishi if (!sbp[1]) { 524a1d0747aSJoe Perches nilfs_err(sb, "unable to read superblock"); 525e339ad31SRyusuke Konishi return -EIO; 526e339ad31SRyusuke Konishi } 527a1d0747aSJoe Perches nilfs_warn(sb, 528feee880fSRyusuke Konishi "unable to read primary superblock (blocksize = %d)", 529feee880fSRyusuke Konishi blocksize); 5304138ec23SRyusuke Konishi } else if (!sbp[1]) { 531a1d0747aSJoe Perches nilfs_warn(sb, 532feee880fSRyusuke Konishi "unable to read secondary superblock (blocksize = %d)", 533feee880fSRyusuke Konishi blocksize); 5344138ec23SRyusuke Konishi } 535e339ad31SRyusuke Konishi 53625294d8cSRyusuke Konishi /* 53725294d8cSRyusuke Konishi * Compare two super blocks and set 1 in swp if the secondary 53825294d8cSRyusuke Konishi * super block is valid and newer. Otherwise, set 0 in swp. 53925294d8cSRyusuke Konishi */ 540e339ad31SRyusuke Konishi valid[0] = nilfs_valid_sb(sbp[0]); 541e339ad31SRyusuke Konishi valid[1] = nilfs_valid_sb(sbp[1]); 54225294d8cSRyusuke Konishi swp = valid[1] && (!valid[0] || 54325294d8cSRyusuke Konishi le64_to_cpu(sbp[1]->s_last_cno) > 54425294d8cSRyusuke Konishi le64_to_cpu(sbp[0]->s_last_cno)); 545e339ad31SRyusuke Konishi 546e339ad31SRyusuke Konishi if (valid[swp] && nilfs_sb2_bad_offset(sbp[swp], sb2off)) { 547e339ad31SRyusuke Konishi brelse(sbh[1]); 548e339ad31SRyusuke Konishi sbh[1] = NULL; 549e339ad31SRyusuke Konishi sbp[1] = NULL; 550d7178c79SRyusuke Konishi valid[1] = 0; 551e339ad31SRyusuke Konishi swp = 0; 552e339ad31SRyusuke Konishi } 553e339ad31SRyusuke Konishi if (!valid[swp]) { 554e339ad31SRyusuke Konishi nilfs_release_super_block(nilfs); 555a1d0747aSJoe Perches nilfs_err(sb, "couldn't find nilfs on the device"); 556e339ad31SRyusuke Konishi return -EINVAL; 557e339ad31SRyusuke Konishi } 558e339ad31SRyusuke Konishi 559ea1a16f7SRyusuke Konishi if (!valid[!swp]) 560a1d0747aSJoe Perches nilfs_warn(sb, 561feee880fSRyusuke Konishi "broken superblock, retrying with spare superblock (blocksize = %d)", 562feee880fSRyusuke Konishi blocksize); 563ea1a16f7SRyusuke Konishi if (swp) 564e339ad31SRyusuke Konishi nilfs_swap_super_block(nilfs); 565e339ad31SRyusuke Konishi 566b2ac86e1SJiro SEKIBA nilfs->ns_sbwcount = 0; 567b2ac86e1SJiro SEKIBA nilfs->ns_sbwtime = le64_to_cpu(sbp[0]->s_wtime); 568e339ad31SRyusuke Konishi nilfs->ns_prot_seq = le64_to_cpu(sbp[valid[1] & !swp]->s_last_seq); 569e339ad31SRyusuke Konishi *sbpp = sbp[0]; 570e339ad31SRyusuke Konishi return 0; 571e339ad31SRyusuke Konishi } 572e339ad31SRyusuke Konishi 5738a9d2191SRyusuke Konishi /** 5748a9d2191SRyusuke Konishi * init_nilfs - initialize a NILFS instance. 5758a9d2191SRyusuke Konishi * @nilfs: the_nilfs structure 5768a9d2191SRyusuke Konishi * @sb: super block 5778a9d2191SRyusuke Konishi * @data: mount options 5788a9d2191SRyusuke Konishi * 5798a9d2191SRyusuke Konishi * init_nilfs() performs common initialization per block device (e.g. 5808a9d2191SRyusuke Konishi * reading the super block, getting disk layout information, initializing 581f11459adSRyusuke Konishi * shared fields in the_nilfs). 5828a9d2191SRyusuke Konishi * 5838a9d2191SRyusuke Konishi * Return Value: On success, 0 is returned. On error, a negative error 5848a9d2191SRyusuke Konishi * code is returned. 5858a9d2191SRyusuke Konishi */ 586f7545144SRyusuke Konishi int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data) 5878a9d2191SRyusuke Konishi { 5888a9d2191SRyusuke Konishi struct nilfs_super_block *sbp; 5898a9d2191SRyusuke Konishi int blocksize; 590e339ad31SRyusuke Konishi int err; 5918a9d2191SRyusuke Konishi 5928a9d2191SRyusuke Konishi down_write(&nilfs->ns_sem); 5938a9d2191SRyusuke Konishi 59489c0fd01SRyusuke Konishi blocksize = sb_min_blocksize(sb, NILFS_MIN_BLOCK_SIZE); 595e339ad31SRyusuke Konishi if (!blocksize) { 596a1d0747aSJoe Perches nilfs_err(sb, "unable to set blocksize"); 5978a9d2191SRyusuke Konishi err = -EINVAL; 5988a9d2191SRyusuke Konishi goto out; 5998a9d2191SRyusuke Konishi } 600e339ad31SRyusuke Konishi err = nilfs_load_super_block(nilfs, sb, blocksize, &sbp); 601e339ad31SRyusuke Konishi if (err) 602e339ad31SRyusuke Konishi goto out; 603e339ad31SRyusuke Konishi 6048a9d2191SRyusuke Konishi err = nilfs_store_magic_and_option(sb, sbp, data); 6058a9d2191SRyusuke Konishi if (err) 6068a9d2191SRyusuke Konishi goto failed_sbh; 6078a9d2191SRyusuke Konishi 608c5ca48aaSRyusuke Konishi err = nilfs_check_feature_compatibility(sb, sbp); 609c5ca48aaSRyusuke Konishi if (err) 610c5ca48aaSRyusuke Konishi goto failed_sbh; 611c5ca48aaSRyusuke Konishi 6128a9d2191SRyusuke Konishi blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); 61389c0fd01SRyusuke Konishi if (blocksize < NILFS_MIN_BLOCK_SIZE || 61489c0fd01SRyusuke Konishi blocksize > NILFS_MAX_BLOCK_SIZE) { 615a1d0747aSJoe Perches nilfs_err(sb, 616feee880fSRyusuke Konishi "couldn't mount because of unsupported filesystem blocksize %d", 617feee880fSRyusuke Konishi blocksize); 61889c0fd01SRyusuke Konishi err = -EINVAL; 61989c0fd01SRyusuke Konishi goto failed_sbh; 62089c0fd01SRyusuke Konishi } 6218a9d2191SRyusuke Konishi if (sb->s_blocksize != blocksize) { 622e1defc4fSMartin K. Petersen int hw_blocksize = bdev_logical_block_size(sb->s_bdev); 623e339ad31SRyusuke Konishi 624e339ad31SRyusuke Konishi if (blocksize < hw_blocksize) { 625a1d0747aSJoe Perches nilfs_err(sb, 626feee880fSRyusuke Konishi "blocksize %d too small for device (sector-size = %d)", 627e339ad31SRyusuke Konishi blocksize, hw_blocksize); 6288a9d2191SRyusuke Konishi err = -EINVAL; 629e339ad31SRyusuke Konishi goto failed_sbh; 630e339ad31SRyusuke Konishi } 631e339ad31SRyusuke Konishi nilfs_release_super_block(nilfs); 632e339ad31SRyusuke Konishi sb_set_blocksize(sb, blocksize); 633e339ad31SRyusuke Konishi 634e339ad31SRyusuke Konishi err = nilfs_load_super_block(nilfs, sb, blocksize, &sbp); 635e339ad31SRyusuke Konishi if (err) 6368a9d2191SRyusuke Konishi goto out; 637076a378bSRyusuke Konishi /* 638076a378bSRyusuke Konishi * Not to failed_sbh; sbh is released automatically 639076a378bSRyusuke Konishi * when reloading fails. 640076a378bSRyusuke Konishi */ 6418a9d2191SRyusuke Konishi } 6428a9d2191SRyusuke Konishi nilfs->ns_blocksize_bits = sb->s_blocksize_bits; 64392c60ccaSRyusuke Konishi nilfs->ns_blocksize = blocksize; 6448a9d2191SRyusuke Konishi 6459b1fc4e4SRyusuke Konishi get_random_bytes(&nilfs->ns_next_generation, 6469b1fc4e4SRyusuke Konishi sizeof(nilfs->ns_next_generation)); 6479b1fc4e4SRyusuke Konishi 648e339ad31SRyusuke Konishi err = nilfs_store_disk_layout(nilfs, sbp); 6498a9d2191SRyusuke Konishi if (err) 6508a9d2191SRyusuke Konishi goto failed_sbh; 6518a9d2191SRyusuke Konishi 6528a9d2191SRyusuke Konishi sb->s_maxbytes = nilfs_max_size(sb->s_blocksize_bits); 6538a9d2191SRyusuke Konishi 6548a9d2191SRyusuke Konishi nilfs->ns_mount_state = le16_to_cpu(sbp->s_state); 6558a9d2191SRyusuke Konishi 656843d63baSRyusuke Konishi err = nilfs_store_log_cursor(nilfs, sbp); 657843d63baSRyusuke Konishi if (err) 6588a9d2191SRyusuke Konishi goto failed_sbh; 6598a9d2191SRyusuke Konishi 660dd70edbdSVyacheslav Dubeyko err = nilfs_sysfs_create_device_group(sb); 661dd70edbdSVyacheslav Dubeyko if (err) 662dd70edbdSVyacheslav Dubeyko goto failed_sbh; 663dd70edbdSVyacheslav Dubeyko 6648a9d2191SRyusuke Konishi set_nilfs_init(nilfs); 6658a9d2191SRyusuke Konishi err = 0; 6668a9d2191SRyusuke Konishi out: 6678a9d2191SRyusuke Konishi up_write(&nilfs->ns_sem); 6688a9d2191SRyusuke Konishi return err; 6698a9d2191SRyusuke Konishi 6708a9d2191SRyusuke Konishi failed_sbh: 671e339ad31SRyusuke Konishi nilfs_release_super_block(nilfs); 6728a9d2191SRyusuke Konishi goto out; 6738a9d2191SRyusuke Konishi } 6748a9d2191SRyusuke Konishi 675e902ec99SJiro SEKIBA int nilfs_discard_segments(struct the_nilfs *nilfs, __u64 *segnump, 676e902ec99SJiro SEKIBA size_t nsegs) 677e902ec99SJiro SEKIBA { 678e902ec99SJiro SEKIBA sector_t seg_start, seg_end; 679e902ec99SJiro SEKIBA sector_t start = 0, nblocks = 0; 680e902ec99SJiro SEKIBA unsigned int sects_per_block; 681e902ec99SJiro SEKIBA __u64 *sn; 682e902ec99SJiro SEKIBA int ret = 0; 683e902ec99SJiro SEKIBA 684e902ec99SJiro SEKIBA sects_per_block = (1 << nilfs->ns_blocksize_bits) / 685e902ec99SJiro SEKIBA bdev_logical_block_size(nilfs->ns_bdev); 686e902ec99SJiro SEKIBA for (sn = segnump; sn < segnump + nsegs; sn++) { 687e902ec99SJiro SEKIBA nilfs_get_segment_range(nilfs, *sn, &seg_start, &seg_end); 688e902ec99SJiro SEKIBA 689e902ec99SJiro SEKIBA if (!nblocks) { 690e902ec99SJiro SEKIBA start = seg_start; 691e902ec99SJiro SEKIBA nblocks = seg_end - seg_start + 1; 692e902ec99SJiro SEKIBA } else if (start + nblocks == seg_start) { 693e902ec99SJiro SEKIBA nblocks += seg_end - seg_start + 1; 694e902ec99SJiro SEKIBA } else { 695e902ec99SJiro SEKIBA ret = blkdev_issue_discard(nilfs->ns_bdev, 696e902ec99SJiro SEKIBA start * sects_per_block, 697e902ec99SJiro SEKIBA nblocks * sects_per_block, 69844abff2cSChristoph Hellwig GFP_NOFS); 699e902ec99SJiro SEKIBA if (ret < 0) 700e902ec99SJiro SEKIBA return ret; 701e902ec99SJiro SEKIBA nblocks = 0; 702e902ec99SJiro SEKIBA } 703e902ec99SJiro SEKIBA } 704e902ec99SJiro SEKIBA if (nblocks) 705e902ec99SJiro SEKIBA ret = blkdev_issue_discard(nilfs->ns_bdev, 706e902ec99SJiro SEKIBA start * sects_per_block, 707e902ec99SJiro SEKIBA nblocks * sects_per_block, 70844abff2cSChristoph Hellwig GFP_NOFS); 709e902ec99SJiro SEKIBA return ret; 710e902ec99SJiro SEKIBA } 711e902ec99SJiro SEKIBA 7128a9d2191SRyusuke Konishi int nilfs_count_free_blocks(struct the_nilfs *nilfs, sector_t *nblocks) 7138a9d2191SRyusuke Konishi { 7148a9d2191SRyusuke Konishi unsigned long ncleansegs; 7158a9d2191SRyusuke Konishi 716365e215cSRyusuke Konishi down_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); 717ef7d4757SRyusuke Konishi ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile); 718365e215cSRyusuke Konishi up_read(&NILFS_MDT(nilfs->ns_dat)->mi_sem); 7198a9d2191SRyusuke Konishi *nblocks = (sector_t)ncleansegs * nilfs->ns_blocks_per_segment; 720ef7d4757SRyusuke Konishi return 0; 7218a9d2191SRyusuke Konishi } 7228a9d2191SRyusuke Konishi 7238a9d2191SRyusuke Konishi int nilfs_near_disk_full(struct the_nilfs *nilfs) 7248a9d2191SRyusuke Konishi { 7258a9d2191SRyusuke Konishi unsigned long ncleansegs, nincsegs; 7268a9d2191SRyusuke Konishi 727ef7d4757SRyusuke Konishi ncleansegs = nilfs_sufile_get_ncleansegs(nilfs->ns_sufile); 7288a9d2191SRyusuke Konishi nincsegs = atomic_read(&nilfs->ns_ndirtyblks) / 7298a9d2191SRyusuke Konishi nilfs->ns_blocks_per_segment + 1; 730ef7d4757SRyusuke Konishi 731ef7d4757SRyusuke Konishi return ncleansegs <= nilfs->ns_nrsvsegs + nincsegs; 7328a9d2191SRyusuke Konishi } 7338a9d2191SRyusuke Konishi 734ba65ae47SRyusuke Konishi struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno) 7356dd47406SRyusuke Konishi { 736ba65ae47SRyusuke Konishi struct rb_node *n; 737ba65ae47SRyusuke Konishi struct nilfs_root *root; 7386dd47406SRyusuke Konishi 739ba65ae47SRyusuke Konishi spin_lock(&nilfs->ns_cptree_lock); 740ba65ae47SRyusuke Konishi n = nilfs->ns_cptree.rb_node; 741ba65ae47SRyusuke Konishi while (n) { 742ba65ae47SRyusuke Konishi root = rb_entry(n, struct nilfs_root, rb_node); 743ba65ae47SRyusuke Konishi 744ba65ae47SRyusuke Konishi if (cno < root->cno) { 745ba65ae47SRyusuke Konishi n = n->rb_left; 746ba65ae47SRyusuke Konishi } else if (cno > root->cno) { 747ba65ae47SRyusuke Konishi n = n->rb_right; 748ba65ae47SRyusuke Konishi } else { 749d4f0284aSElena Reshetova refcount_inc(&root->count); 750ba65ae47SRyusuke Konishi spin_unlock(&nilfs->ns_cptree_lock); 751ba65ae47SRyusuke Konishi return root; 752ba65ae47SRyusuke Konishi } 753ba65ae47SRyusuke Konishi } 754ba65ae47SRyusuke Konishi spin_unlock(&nilfs->ns_cptree_lock); 755ba65ae47SRyusuke Konishi 756ba65ae47SRyusuke Konishi return NULL; 7576dd47406SRyusuke Konishi } 7586dd47406SRyusuke Konishi 759ba65ae47SRyusuke Konishi struct nilfs_root * 760ba65ae47SRyusuke Konishi nilfs_find_or_create_root(struct the_nilfs *nilfs, __u64 cno) 761ba65ae47SRyusuke Konishi { 762ba65ae47SRyusuke Konishi struct rb_node **p, *parent; 763ba65ae47SRyusuke Konishi struct nilfs_root *root, *new; 764dd70edbdSVyacheslav Dubeyko int err; 765ba65ae47SRyusuke Konishi 766ba65ae47SRyusuke Konishi root = nilfs_lookup_root(nilfs, cno); 767ba65ae47SRyusuke Konishi if (root) 768ba65ae47SRyusuke Konishi return root; 769ba65ae47SRyusuke Konishi 770dd70edbdSVyacheslav Dubeyko new = kzalloc(sizeof(*root), GFP_KERNEL); 771ba65ae47SRyusuke Konishi if (!new) 7726dd47406SRyusuke Konishi return NULL; 7736dd47406SRyusuke Konishi 774ba65ae47SRyusuke Konishi spin_lock(&nilfs->ns_cptree_lock); 775ba65ae47SRyusuke Konishi 776ba65ae47SRyusuke Konishi p = &nilfs->ns_cptree.rb_node; 777ba65ae47SRyusuke Konishi parent = NULL; 778ba65ae47SRyusuke Konishi 779ba65ae47SRyusuke Konishi while (*p) { 780ba65ae47SRyusuke Konishi parent = *p; 781ba65ae47SRyusuke Konishi root = rb_entry(parent, struct nilfs_root, rb_node); 782ba65ae47SRyusuke Konishi 783ba65ae47SRyusuke Konishi if (cno < root->cno) { 784ba65ae47SRyusuke Konishi p = &(*p)->rb_left; 785ba65ae47SRyusuke Konishi } else if (cno > root->cno) { 786ba65ae47SRyusuke Konishi p = &(*p)->rb_right; 787ba65ae47SRyusuke Konishi } else { 788d4f0284aSElena Reshetova refcount_inc(&root->count); 789ba65ae47SRyusuke Konishi spin_unlock(&nilfs->ns_cptree_lock); 790ba65ae47SRyusuke Konishi kfree(new); 791ba65ae47SRyusuke Konishi return root; 792ba65ae47SRyusuke Konishi } 7936dd47406SRyusuke Konishi } 7946dd47406SRyusuke Konishi 795ba65ae47SRyusuke Konishi new->cno = cno; 796ba65ae47SRyusuke Konishi new->ifile = NULL; 797ba65ae47SRyusuke Konishi new->nilfs = nilfs; 798d4f0284aSElena Reshetova refcount_set(&new->count, 1); 799e5f7f848SVyacheslav Dubeyko atomic64_set(&new->inodes_count, 0); 800e5f7f848SVyacheslav Dubeyko atomic64_set(&new->blocks_count, 0); 801ba65ae47SRyusuke Konishi 802ba65ae47SRyusuke Konishi rb_link_node(&new->rb_node, parent, p); 803ba65ae47SRyusuke Konishi rb_insert_color(&new->rb_node, &nilfs->ns_cptree); 804ba65ae47SRyusuke Konishi 805ba65ae47SRyusuke Konishi spin_unlock(&nilfs->ns_cptree_lock); 806ba65ae47SRyusuke Konishi 807dd70edbdSVyacheslav Dubeyko err = nilfs_sysfs_create_snapshot_group(new); 808dd70edbdSVyacheslav Dubeyko if (err) { 809dd70edbdSVyacheslav Dubeyko kfree(new); 810dd70edbdSVyacheslav Dubeyko new = NULL; 811dd70edbdSVyacheslav Dubeyko } 812dd70edbdSVyacheslav Dubeyko 813ba65ae47SRyusuke Konishi return new; 814ba65ae47SRyusuke Konishi } 815ba65ae47SRyusuke Konishi 816ba65ae47SRyusuke Konishi void nilfs_put_root(struct nilfs_root *root) 8178a9d2191SRyusuke Konishi { 818ba65ae47SRyusuke Konishi struct the_nilfs *nilfs = root->nilfs; 8198a9d2191SRyusuke Konishi 82098e2e409SZhen Lei if (refcount_dec_and_lock(&root->count, &nilfs->ns_cptree_lock)) { 821ba65ae47SRyusuke Konishi rb_erase(&root->rb_node, &nilfs->ns_cptree); 822ba65ae47SRyusuke Konishi spin_unlock(&nilfs->ns_cptree_lock); 82398e2e409SZhen Lei 82498e2e409SZhen Lei nilfs_sysfs_delete_snapshot_group(root); 825f1e89c86SRyusuke Konishi iput(root->ifile); 8268a9d2191SRyusuke Konishi 827ba65ae47SRyusuke Konishi kfree(root); 8288a9d2191SRyusuke Konishi } 8298a9d2191SRyusuke Konishi } 830