11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (C) International Business Machines Corp., 2000-2004 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 51da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 61da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 71da177e4SLinus Torvalds * (at your option) any later version. 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, 101da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 111da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 121da177e4SLinus Torvalds * the GNU General Public License for more details. 131da177e4SLinus Torvalds * 141da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 151da177e4SLinus Torvalds * along with this program; if not, write to the Free Software 161da177e4SLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 171da177e4SLinus Torvalds */ 181da177e4SLinus Torvalds 191da177e4SLinus Torvalds /* 201da177e4SLinus Torvalds * Module: jfs_mount.c 211da177e4SLinus Torvalds * 221da177e4SLinus Torvalds * note: file system in transition to aggregate/fileset: 231da177e4SLinus Torvalds * 241da177e4SLinus Torvalds * file system mount is interpreted as the mount of aggregate, 251da177e4SLinus Torvalds * if not already mounted, and mount of the single/only fileset in 261da177e4SLinus Torvalds * the aggregate; 271da177e4SLinus Torvalds * 281da177e4SLinus Torvalds * a file system/aggregate is represented by an internal inode 291da177e4SLinus Torvalds * (aka mount inode) initialized with aggregate superblock; 301da177e4SLinus Torvalds * each vfs represents a fileset, and points to its "fileset inode 311da177e4SLinus Torvalds * allocation map inode" (aka fileset inode): 321da177e4SLinus Torvalds * (an aggregate itself is structured recursively as a filset: 331da177e4SLinus Torvalds * an internal vfs is constructed and points to its "fileset inode 341da177e4SLinus Torvalds * allocation map inode" (aka aggregate inode) where each inode 351da177e4SLinus Torvalds * represents a fileset inode) so that inode number is mapped to 361da177e4SLinus Torvalds * on-disk inode in uniform way at both aggregate and fileset level; 371da177e4SLinus Torvalds * 381da177e4SLinus Torvalds * each vnode/inode of a fileset is linked to its vfs (to facilitate 391da177e4SLinus Torvalds * per fileset inode operations, e.g., unmount of a fileset, etc.); 401da177e4SLinus Torvalds * each inode points to the mount inode (to facilitate access to 411da177e4SLinus Torvalds * per aggregate information, e.g., block size, etc.) as well as 421da177e4SLinus Torvalds * its file set inode. 431da177e4SLinus Torvalds * 441da177e4SLinus Torvalds * aggregate 451da177e4SLinus Torvalds * ipmnt 461da177e4SLinus Torvalds * mntvfs -> fileset ipimap+ -> aggregate ipbmap -> aggregate ipaimap; 471da177e4SLinus Torvalds * fileset vfs -> vp(1) <-> ... <-> vp(n) <->vproot; 481da177e4SLinus Torvalds */ 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds #include <linux/fs.h> 511da177e4SLinus Torvalds #include <linux/buffer_head.h> 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds #include "jfs_incore.h" 541da177e4SLinus Torvalds #include "jfs_filsys.h" 551da177e4SLinus Torvalds #include "jfs_superblock.h" 561da177e4SLinus Torvalds #include "jfs_dmap.h" 571da177e4SLinus Torvalds #include "jfs_imap.h" 581da177e4SLinus Torvalds #include "jfs_metapage.h" 591da177e4SLinus Torvalds #include "jfs_debug.h" 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds 621da177e4SLinus Torvalds /* 631da177e4SLinus Torvalds * forward references 641da177e4SLinus Torvalds */ 651da177e4SLinus Torvalds static int chkSuper(struct super_block *); 661da177e4SLinus Torvalds static int logMOUNT(struct super_block *sb); 671da177e4SLinus Torvalds 681da177e4SLinus Torvalds /* 691da177e4SLinus Torvalds * NAME: jfs_mount(sb) 701da177e4SLinus Torvalds * 711da177e4SLinus Torvalds * FUNCTION: vfs_mount() 721da177e4SLinus Torvalds * 731da177e4SLinus Torvalds * PARAMETER: sb - super block 741da177e4SLinus Torvalds * 751da177e4SLinus Torvalds * RETURN: -EBUSY - device already mounted or open for write 761da177e4SLinus Torvalds * -EBUSY - cvrdvp already mounted; 771da177e4SLinus Torvalds * -EBUSY - mount table full 781da177e4SLinus Torvalds * -ENOTDIR- cvrdvp not directory on a device mount 791da177e4SLinus Torvalds * -ENXIO - device open failure 801da177e4SLinus Torvalds */ 811da177e4SLinus Torvalds int jfs_mount(struct super_block *sb) 821da177e4SLinus Torvalds { 831da177e4SLinus Torvalds int rc = 0; /* Return code */ 841da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(sb); 851da177e4SLinus Torvalds struct inode *ipaimap = NULL; 861da177e4SLinus Torvalds struct inode *ipaimap2 = NULL; 871da177e4SLinus Torvalds struct inode *ipimap = NULL; 881da177e4SLinus Torvalds struct inode *ipbmap = NULL; 891da177e4SLinus Torvalds 901da177e4SLinus Torvalds /* 911da177e4SLinus Torvalds * read/validate superblock 921da177e4SLinus Torvalds * (initialize mount inode from the superblock) 931da177e4SLinus Torvalds */ 941da177e4SLinus Torvalds if ((rc = chkSuper(sb))) { 951da177e4SLinus Torvalds goto errout20; 961da177e4SLinus Torvalds } 971da177e4SLinus Torvalds 981da177e4SLinus Torvalds ipaimap = diReadSpecial(sb, AGGREGATE_I, 0); 991da177e4SLinus Torvalds if (ipaimap == NULL) { 1001da177e4SLinus Torvalds jfs_err("jfs_mount: Faild to read AGGREGATE_I"); 1011da177e4SLinus Torvalds rc = -EIO; 1021da177e4SLinus Torvalds goto errout20; 1031da177e4SLinus Torvalds } 1041da177e4SLinus Torvalds sbi->ipaimap = ipaimap; 1051da177e4SLinus Torvalds 1061da177e4SLinus Torvalds jfs_info("jfs_mount: ipaimap:0x%p", ipaimap); 1071da177e4SLinus Torvalds 1081da177e4SLinus Torvalds /* 1091da177e4SLinus Torvalds * initialize aggregate inode allocation map 1101da177e4SLinus Torvalds */ 1111da177e4SLinus Torvalds if ((rc = diMount(ipaimap))) { 1121da177e4SLinus Torvalds jfs_err("jfs_mount: diMount(ipaimap) failed w/rc = %d", rc); 1131da177e4SLinus Torvalds goto errout21; 1141da177e4SLinus Torvalds } 1151da177e4SLinus Torvalds 1161da177e4SLinus Torvalds /* 1171da177e4SLinus Torvalds * open aggregate block allocation map 1181da177e4SLinus Torvalds */ 1191da177e4SLinus Torvalds ipbmap = diReadSpecial(sb, BMAP_I, 0); 1201da177e4SLinus Torvalds if (ipbmap == NULL) { 1211da177e4SLinus Torvalds rc = -EIO; 1221da177e4SLinus Torvalds goto errout22; 1231da177e4SLinus Torvalds } 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds jfs_info("jfs_mount: ipbmap:0x%p", ipbmap); 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds sbi->ipbmap = ipbmap; 1281da177e4SLinus Torvalds 1291da177e4SLinus Torvalds /* 1301da177e4SLinus Torvalds * initialize aggregate block allocation map 1311da177e4SLinus Torvalds */ 1321da177e4SLinus Torvalds if ((rc = dbMount(ipbmap))) { 1331da177e4SLinus Torvalds jfs_err("jfs_mount: dbMount failed w/rc = %d", rc); 1341da177e4SLinus Torvalds goto errout22; 1351da177e4SLinus Torvalds } 1361da177e4SLinus Torvalds 1371da177e4SLinus Torvalds /* 1381da177e4SLinus Torvalds * open the secondary aggregate inode allocation map 1391da177e4SLinus Torvalds * 1401da177e4SLinus Torvalds * This is a duplicate of the aggregate inode allocation map. 1411da177e4SLinus Torvalds * 1421da177e4SLinus Torvalds * hand craft a vfs in the same fashion as we did to read ipaimap. 1431da177e4SLinus Torvalds * By adding INOSPEREXT (32) to the inode number, we are telling 1441da177e4SLinus Torvalds * diReadSpecial that we are reading from the secondary aggregate 1451da177e4SLinus Torvalds * inode table. This also creates a unique entry in the inode hash 1461da177e4SLinus Torvalds * table. 1471da177e4SLinus Torvalds */ 1481da177e4SLinus Torvalds if ((sbi->mntflag & JFS_BAD_SAIT) == 0) { 1491da177e4SLinus Torvalds ipaimap2 = diReadSpecial(sb, AGGREGATE_I, 1); 150*09aaa749SJoe Perches if (!ipaimap2) { 1511da177e4SLinus Torvalds jfs_err("jfs_mount: Faild to read AGGREGATE_I"); 1521da177e4SLinus Torvalds rc = -EIO; 1531da177e4SLinus Torvalds goto errout35; 1541da177e4SLinus Torvalds } 1551da177e4SLinus Torvalds sbi->ipaimap2 = ipaimap2; 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds jfs_info("jfs_mount: ipaimap2:0x%p", ipaimap2); 1581da177e4SLinus Torvalds 1591da177e4SLinus Torvalds /* 1601da177e4SLinus Torvalds * initialize secondary aggregate inode allocation map 1611da177e4SLinus Torvalds */ 1621da177e4SLinus Torvalds if ((rc = diMount(ipaimap2))) { 1631da177e4SLinus Torvalds jfs_err("jfs_mount: diMount(ipaimap2) failed, rc = %d", 1641da177e4SLinus Torvalds rc); 1651da177e4SLinus Torvalds goto errout35; 1661da177e4SLinus Torvalds } 1671da177e4SLinus Torvalds } else 1681da177e4SLinus Torvalds /* Secondary aggregate inode table is not valid */ 1691da177e4SLinus Torvalds sbi->ipaimap2 = NULL; 1701da177e4SLinus Torvalds 1711da177e4SLinus Torvalds /* 1721da177e4SLinus Torvalds * mount (the only/single) fileset 1731da177e4SLinus Torvalds */ 1741da177e4SLinus Torvalds /* 1751da177e4SLinus Torvalds * open fileset inode allocation map (aka fileset inode) 1761da177e4SLinus Torvalds */ 1771da177e4SLinus Torvalds ipimap = diReadSpecial(sb, FILESYSTEM_I, 0); 1781da177e4SLinus Torvalds if (ipimap == NULL) { 1791da177e4SLinus Torvalds jfs_err("jfs_mount: Failed to read FILESYSTEM_I"); 1801da177e4SLinus Torvalds /* open fileset secondary inode allocation map */ 1811da177e4SLinus Torvalds rc = -EIO; 1821da177e4SLinus Torvalds goto errout40; 1831da177e4SLinus Torvalds } 1841da177e4SLinus Torvalds jfs_info("jfs_mount: ipimap:0x%p", ipimap); 1851da177e4SLinus Torvalds 1861da177e4SLinus Torvalds /* map further access of per fileset inodes by the fileset inode */ 1871da177e4SLinus Torvalds sbi->ipimap = ipimap; 1881da177e4SLinus Torvalds 1891da177e4SLinus Torvalds /* initialize fileset inode allocation map */ 1901da177e4SLinus Torvalds if ((rc = diMount(ipimap))) { 1911da177e4SLinus Torvalds jfs_err("jfs_mount: diMount failed w/rc = %d", rc); 1921da177e4SLinus Torvalds goto errout41; 1931da177e4SLinus Torvalds } 1941da177e4SLinus Torvalds 1951da177e4SLinus Torvalds goto out; 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds /* 1981da177e4SLinus Torvalds * unwind on error 1991da177e4SLinus Torvalds */ 2001da177e4SLinus Torvalds errout41: /* close fileset inode allocation map inode */ 2011da177e4SLinus Torvalds diFreeSpecial(ipimap); 2021da177e4SLinus Torvalds 2031da177e4SLinus Torvalds errout40: /* fileset closed */ 2041da177e4SLinus Torvalds 2051da177e4SLinus Torvalds /* close secondary aggregate inode allocation map */ 2061da177e4SLinus Torvalds if (ipaimap2) { 2071da177e4SLinus Torvalds diUnmount(ipaimap2, 1); 2081da177e4SLinus Torvalds diFreeSpecial(ipaimap2); 2091da177e4SLinus Torvalds } 2101da177e4SLinus Torvalds 2111da177e4SLinus Torvalds errout35: 2121da177e4SLinus Torvalds 2131da177e4SLinus Torvalds /* close aggregate block allocation map */ 2141da177e4SLinus Torvalds dbUnmount(ipbmap, 1); 2151da177e4SLinus Torvalds diFreeSpecial(ipbmap); 2161da177e4SLinus Torvalds 2171da177e4SLinus Torvalds errout22: /* close aggregate inode allocation map */ 2181da177e4SLinus Torvalds 2191da177e4SLinus Torvalds diUnmount(ipaimap, 1); 2201da177e4SLinus Torvalds 2211da177e4SLinus Torvalds errout21: /* close aggregate inodes */ 2221da177e4SLinus Torvalds diFreeSpecial(ipaimap); 2231da177e4SLinus Torvalds errout20: /* aggregate closed */ 2241da177e4SLinus Torvalds 2251da177e4SLinus Torvalds out: 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds if (rc) 2281da177e4SLinus Torvalds jfs_err("Mount JFS Failure: %d", rc); 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds return rc; 2311da177e4SLinus Torvalds } 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds /* 2341da177e4SLinus Torvalds * NAME: jfs_mount_rw(sb, remount) 2351da177e4SLinus Torvalds * 2361da177e4SLinus Torvalds * FUNCTION: Completes read-write mount, or remounts read-only volume 2371da177e4SLinus Torvalds * as read-write 2381da177e4SLinus Torvalds */ 2391da177e4SLinus Torvalds int jfs_mount_rw(struct super_block *sb, int remount) 2401da177e4SLinus Torvalds { 2411da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(sb); 2421da177e4SLinus Torvalds int rc; 2431da177e4SLinus Torvalds 2441da177e4SLinus Torvalds /* 2451da177e4SLinus Torvalds * If we are re-mounting a previously read-only volume, we want to 2461da177e4SLinus Torvalds * re-read the inode and block maps, since fsck.jfs may have updated 2471da177e4SLinus Torvalds * them. 2481da177e4SLinus Torvalds */ 2491da177e4SLinus Torvalds if (remount) { 2501da177e4SLinus Torvalds if (chkSuper(sb) || (sbi->state != FM_CLEAN)) 2511da177e4SLinus Torvalds return -EINVAL; 2521da177e4SLinus Torvalds 2531da177e4SLinus Torvalds truncate_inode_pages(sbi->ipimap->i_mapping, 0); 2541da177e4SLinus Torvalds truncate_inode_pages(sbi->ipbmap->i_mapping, 0); 2551da177e4SLinus Torvalds diUnmount(sbi->ipimap, 1); 2561da177e4SLinus Torvalds if ((rc = diMount(sbi->ipimap))) { 2571da177e4SLinus Torvalds jfs_err("jfs_mount_rw: diMount failed!"); 2581da177e4SLinus Torvalds return rc; 2591da177e4SLinus Torvalds } 2601da177e4SLinus Torvalds 2611da177e4SLinus Torvalds dbUnmount(sbi->ipbmap, 1); 2621da177e4SLinus Torvalds if ((rc = dbMount(sbi->ipbmap))) { 2631da177e4SLinus Torvalds jfs_err("jfs_mount_rw: dbMount failed!"); 2641da177e4SLinus Torvalds return rc; 2651da177e4SLinus Torvalds } 2661da177e4SLinus Torvalds } 2671da177e4SLinus Torvalds 2681da177e4SLinus Torvalds /* 2691da177e4SLinus Torvalds * open/initialize log 2701da177e4SLinus Torvalds */ 2711da177e4SLinus Torvalds if ((rc = lmLogOpen(sb))) 2721da177e4SLinus Torvalds return rc; 2731da177e4SLinus Torvalds 2741da177e4SLinus Torvalds /* 2751da177e4SLinus Torvalds * update file system superblock; 2761da177e4SLinus Torvalds */ 2771da177e4SLinus Torvalds if ((rc = updateSuper(sb, FM_MOUNT))) { 2781da177e4SLinus Torvalds jfs_err("jfs_mount: updateSuper failed w/rc = %d", rc); 2791da177e4SLinus Torvalds lmLogClose(sb); 2801da177e4SLinus Torvalds return rc; 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds 2831da177e4SLinus Torvalds /* 2841da177e4SLinus Torvalds * write MOUNT log record of the file system 2851da177e4SLinus Torvalds */ 2861da177e4SLinus Torvalds logMOUNT(sb); 2871da177e4SLinus Torvalds 2881da177e4SLinus Torvalds return rc; 2891da177e4SLinus Torvalds } 2901da177e4SLinus Torvalds 2911da177e4SLinus Torvalds /* 2921da177e4SLinus Torvalds * chkSuper() 2931da177e4SLinus Torvalds * 2941da177e4SLinus Torvalds * validate the superblock of the file system to be mounted and 2951da177e4SLinus Torvalds * get the file system parameters. 2961da177e4SLinus Torvalds * 2971da177e4SLinus Torvalds * returns 2981da177e4SLinus Torvalds * 0 with fragsize set if check successful 2991da177e4SLinus Torvalds * error code if not successful 3001da177e4SLinus Torvalds */ 3011da177e4SLinus Torvalds static int chkSuper(struct super_block *sb) 3021da177e4SLinus Torvalds { 3031da177e4SLinus Torvalds int rc = 0; 3041da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(sb); 3051da177e4SLinus Torvalds struct jfs_superblock *j_sb; 3061da177e4SLinus Torvalds struct buffer_head *bh; 3071da177e4SLinus Torvalds int AIM_bytesize, AIT_bytesize; 3081da177e4SLinus Torvalds int expected_AIM_bytesize, expected_AIT_bytesize; 3091da177e4SLinus Torvalds s64 AIM_byte_addr, AIT_byte_addr, fsckwsp_addr; 3101da177e4SLinus Torvalds s64 byte_addr_diff0, byte_addr_diff1; 3111da177e4SLinus Torvalds s32 bsize; 3121da177e4SLinus Torvalds 3131da177e4SLinus Torvalds if ((rc = readSuper(sb, &bh))) 3141da177e4SLinus Torvalds return rc; 3151da177e4SLinus Torvalds j_sb = (struct jfs_superblock *)bh->b_data; 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds /* 3181da177e4SLinus Torvalds * validate superblock 3191da177e4SLinus Torvalds */ 3201da177e4SLinus Torvalds /* validate fs signature */ 3211da177e4SLinus Torvalds if (strncmp(j_sb->s_magic, JFS_MAGIC, 4) || 3221da177e4SLinus Torvalds le32_to_cpu(j_sb->s_version) > JFS_VERSION) { 3231da177e4SLinus Torvalds rc = -EINVAL; 3241da177e4SLinus Torvalds goto out; 3251da177e4SLinus Torvalds } 3261da177e4SLinus Torvalds 3271da177e4SLinus Torvalds bsize = le32_to_cpu(j_sb->s_bsize); 3281da177e4SLinus Torvalds #ifdef _JFS_4K 3291da177e4SLinus Torvalds if (bsize != PSIZE) { 3301da177e4SLinus Torvalds jfs_err("Currently only 4K block size supported!"); 3311da177e4SLinus Torvalds rc = -EINVAL; 3321da177e4SLinus Torvalds goto out; 3331da177e4SLinus Torvalds } 3341da177e4SLinus Torvalds #endif /* _JFS_4K */ 3351da177e4SLinus Torvalds 3361da177e4SLinus Torvalds jfs_info("superblock: flag:0x%08x state:0x%08x size:0x%Lx", 3371da177e4SLinus Torvalds le32_to_cpu(j_sb->s_flag), le32_to_cpu(j_sb->s_state), 3381da177e4SLinus Torvalds (unsigned long long) le64_to_cpu(j_sb->s_size)); 3391da177e4SLinus Torvalds 3401da177e4SLinus Torvalds /* validate the descriptors for Secondary AIM and AIT */ 3411da177e4SLinus Torvalds if ((j_sb->s_flag & cpu_to_le32(JFS_BAD_SAIT)) != 3421da177e4SLinus Torvalds cpu_to_le32(JFS_BAD_SAIT)) { 3431da177e4SLinus Torvalds expected_AIM_bytesize = 2 * PSIZE; 3441da177e4SLinus Torvalds AIM_bytesize = lengthPXD(&(j_sb->s_aim2)) * bsize; 3451da177e4SLinus Torvalds expected_AIT_bytesize = 4 * PSIZE; 3461da177e4SLinus Torvalds AIT_bytesize = lengthPXD(&(j_sb->s_ait2)) * bsize; 3471da177e4SLinus Torvalds AIM_byte_addr = addressPXD(&(j_sb->s_aim2)) * bsize; 3481da177e4SLinus Torvalds AIT_byte_addr = addressPXD(&(j_sb->s_ait2)) * bsize; 3491da177e4SLinus Torvalds byte_addr_diff0 = AIT_byte_addr - AIM_byte_addr; 3501da177e4SLinus Torvalds fsckwsp_addr = addressPXD(&(j_sb->s_fsckpxd)) * bsize; 3511da177e4SLinus Torvalds byte_addr_diff1 = fsckwsp_addr - AIT_byte_addr; 3521da177e4SLinus Torvalds if ((AIM_bytesize != expected_AIM_bytesize) || 3531da177e4SLinus Torvalds (AIT_bytesize != expected_AIT_bytesize) || 3541da177e4SLinus Torvalds (byte_addr_diff0 != AIM_bytesize) || 3551da177e4SLinus Torvalds (byte_addr_diff1 <= AIT_bytesize)) 3561da177e4SLinus Torvalds j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT); 3571da177e4SLinus Torvalds } 3581da177e4SLinus Torvalds 3591da177e4SLinus Torvalds if ((j_sb->s_flag & cpu_to_le32(JFS_GROUPCOMMIT)) != 3601da177e4SLinus Torvalds cpu_to_le32(JFS_GROUPCOMMIT)) 3611da177e4SLinus Torvalds j_sb->s_flag |= cpu_to_le32(JFS_GROUPCOMMIT); 3621da177e4SLinus Torvalds 3631da177e4SLinus Torvalds /* validate fs state */ 3641da177e4SLinus Torvalds if (j_sb->s_state != cpu_to_le32(FM_CLEAN) && 3651da177e4SLinus Torvalds !(sb->s_flags & MS_RDONLY)) { 3661da177e4SLinus Torvalds jfs_err("jfs_mount: Mount Failure: File System Dirty."); 3671da177e4SLinus Torvalds rc = -EINVAL; 3681da177e4SLinus Torvalds goto out; 3691da177e4SLinus Torvalds } 3701da177e4SLinus Torvalds 3711da177e4SLinus Torvalds sbi->state = le32_to_cpu(j_sb->s_state); 3721da177e4SLinus Torvalds sbi->mntflag = le32_to_cpu(j_sb->s_flag); 3731da177e4SLinus Torvalds 3741da177e4SLinus Torvalds /* 3751da177e4SLinus Torvalds * JFS always does I/O by 4K pages. Don't tell the buffer cache 3761da177e4SLinus Torvalds * that we use anything else (leave s_blocksize alone). 3771da177e4SLinus Torvalds */ 3781da177e4SLinus Torvalds sbi->bsize = bsize; 3791da177e4SLinus Torvalds sbi->l2bsize = le16_to_cpu(j_sb->s_l2bsize); 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds /* 3821da177e4SLinus Torvalds * For now, ignore s_pbsize, l2bfactor. All I/O going through buffer 3831da177e4SLinus Torvalds * cache. 3841da177e4SLinus Torvalds */ 3851da177e4SLinus Torvalds sbi->nbperpage = PSIZE >> sbi->l2bsize; 3861da177e4SLinus Torvalds sbi->l2nbperpage = L2PSIZE - sbi->l2bsize; 3871da177e4SLinus Torvalds sbi->l2niperblk = sbi->l2bsize - L2DISIZE; 3881da177e4SLinus Torvalds if (sbi->mntflag & JFS_INLINELOG) 3891da177e4SLinus Torvalds sbi->logpxd = j_sb->s_logpxd; 3901da177e4SLinus Torvalds else { 3911da177e4SLinus Torvalds sbi->logdev = new_decode_dev(le32_to_cpu(j_sb->s_logdev)); 3921da177e4SLinus Torvalds memcpy(sbi->uuid, j_sb->s_uuid, sizeof(sbi->uuid)); 3931da177e4SLinus Torvalds memcpy(sbi->loguuid, j_sb->s_loguuid, sizeof(sbi->uuid)); 3941da177e4SLinus Torvalds } 3951da177e4SLinus Torvalds sbi->fsckpxd = j_sb->s_fsckpxd; 3961da177e4SLinus Torvalds sbi->ait2 = j_sb->s_ait2; 3971da177e4SLinus Torvalds 3981da177e4SLinus Torvalds out: 3991da177e4SLinus Torvalds brelse(bh); 4001da177e4SLinus Torvalds return rc; 4011da177e4SLinus Torvalds } 4021da177e4SLinus Torvalds 4031da177e4SLinus Torvalds 4041da177e4SLinus Torvalds /* 4051da177e4SLinus Torvalds * updateSuper() 4061da177e4SLinus Torvalds * 4071da177e4SLinus Torvalds * update synchronously superblock if it is mounted read-write. 4081da177e4SLinus Torvalds */ 4091da177e4SLinus Torvalds int updateSuper(struct super_block *sb, uint state) 4101da177e4SLinus Torvalds { 4111da177e4SLinus Torvalds struct jfs_superblock *j_sb; 4121da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(sb); 4131da177e4SLinus Torvalds struct buffer_head *bh; 4141da177e4SLinus Torvalds int rc; 4151da177e4SLinus Torvalds 4161da177e4SLinus Torvalds if (sbi->flag & JFS_NOINTEGRITY) { 4171da177e4SLinus Torvalds if (state == FM_DIRTY) { 4181da177e4SLinus Torvalds sbi->p_state = state; 4191da177e4SLinus Torvalds return 0; 4201da177e4SLinus Torvalds } else if (state == FM_MOUNT) { 4211da177e4SLinus Torvalds sbi->p_state = sbi->state; 4221da177e4SLinus Torvalds state = FM_DIRTY; 4231da177e4SLinus Torvalds } else if (state == FM_CLEAN) { 4241da177e4SLinus Torvalds state = sbi->p_state; 4251da177e4SLinus Torvalds } else 4261da177e4SLinus Torvalds jfs_err("updateSuper: bad state"); 4271da177e4SLinus Torvalds } else if (sbi->state == FM_DIRTY) 4281da177e4SLinus Torvalds return 0; 4291da177e4SLinus Torvalds 4301da177e4SLinus Torvalds if ((rc = readSuper(sb, &bh))) 4311da177e4SLinus Torvalds return rc; 4321da177e4SLinus Torvalds 4331da177e4SLinus Torvalds j_sb = (struct jfs_superblock *)bh->b_data; 4341da177e4SLinus Torvalds 4351da177e4SLinus Torvalds j_sb->s_state = cpu_to_le32(state); 4361da177e4SLinus Torvalds sbi->state = state; 4371da177e4SLinus Torvalds 4381da177e4SLinus Torvalds if (state == FM_MOUNT) { 4391da177e4SLinus Torvalds /* record log's dev_t and mount serial number */ 4401da177e4SLinus Torvalds j_sb->s_logdev = cpu_to_le32(new_encode_dev(sbi->log->bdev->bd_dev)); 4411da177e4SLinus Torvalds j_sb->s_logserial = cpu_to_le32(sbi->log->serial); 4421da177e4SLinus Torvalds } else if (state == FM_CLEAN) { 4431da177e4SLinus Torvalds /* 4441da177e4SLinus Torvalds * If this volume is shared with OS/2, OS/2 will need to 4451da177e4SLinus Torvalds * recalculate DASD usage, since we don't deal with it. 4461da177e4SLinus Torvalds */ 4471da177e4SLinus Torvalds if (j_sb->s_flag & cpu_to_le32(JFS_DASD_ENABLED)) 4481da177e4SLinus Torvalds j_sb->s_flag |= cpu_to_le32(JFS_DASD_PRIME); 4491da177e4SLinus Torvalds } 4501da177e4SLinus Torvalds 4511da177e4SLinus Torvalds mark_buffer_dirty(bh); 4521da177e4SLinus Torvalds sync_dirty_buffer(bh); 4531da177e4SLinus Torvalds brelse(bh); 4541da177e4SLinus Torvalds 4551da177e4SLinus Torvalds return 0; 4561da177e4SLinus Torvalds } 4571da177e4SLinus Torvalds 4581da177e4SLinus Torvalds 4591da177e4SLinus Torvalds /* 4601da177e4SLinus Torvalds * readSuper() 4611da177e4SLinus Torvalds * 4621da177e4SLinus Torvalds * read superblock by raw sector address 4631da177e4SLinus Torvalds */ 4641da177e4SLinus Torvalds int readSuper(struct super_block *sb, struct buffer_head **bpp) 4651da177e4SLinus Torvalds { 4661da177e4SLinus Torvalds /* read in primary superblock */ 4671da177e4SLinus Torvalds *bpp = sb_bread(sb, SUPER1_OFF >> sb->s_blocksize_bits); 4681da177e4SLinus Torvalds if (*bpp) 4691da177e4SLinus Torvalds return 0; 4701da177e4SLinus Torvalds 4711da177e4SLinus Torvalds /* read in secondary/replicated superblock */ 4721da177e4SLinus Torvalds *bpp = sb_bread(sb, SUPER2_OFF >> sb->s_blocksize_bits); 4731da177e4SLinus Torvalds if (*bpp) 4741da177e4SLinus Torvalds return 0; 4751da177e4SLinus Torvalds 4761da177e4SLinus Torvalds return -EIO; 4771da177e4SLinus Torvalds } 4781da177e4SLinus Torvalds 4791da177e4SLinus Torvalds 4801da177e4SLinus Torvalds /* 4811da177e4SLinus Torvalds * logMOUNT() 4821da177e4SLinus Torvalds * 4831da177e4SLinus Torvalds * function: write a MOUNT log record for file system. 4841da177e4SLinus Torvalds * 4851da177e4SLinus Torvalds * MOUNT record keeps logredo() from processing log records 4861da177e4SLinus Torvalds * for this file system past this point in log. 4871da177e4SLinus Torvalds * it is harmless if mount fails. 4881da177e4SLinus Torvalds * 4891da177e4SLinus Torvalds * note: MOUNT record is at aggregate level, not at fileset level, 4901da177e4SLinus Torvalds * since log records of previous mounts of a fileset 4911da177e4SLinus Torvalds * (e.g., AFTER record of extent allocation) have to be processed 4921da177e4SLinus Torvalds * to update block allocation map at aggregate level. 4931da177e4SLinus Torvalds */ 4941da177e4SLinus Torvalds static int logMOUNT(struct super_block *sb) 4951da177e4SLinus Torvalds { 4961da177e4SLinus Torvalds struct jfs_log *log = JFS_SBI(sb)->log; 4971da177e4SLinus Torvalds struct lrd lrd; 4981da177e4SLinus Torvalds 4991da177e4SLinus Torvalds lrd.logtid = 0; 5001da177e4SLinus Torvalds lrd.backchain = 0; 5011da177e4SLinus Torvalds lrd.type = cpu_to_le16(LOG_MOUNT); 5021da177e4SLinus Torvalds lrd.length = 0; 5031da177e4SLinus Torvalds lrd.aggregate = cpu_to_le32(new_encode_dev(sb->s_bdev->bd_dev)); 5041da177e4SLinus Torvalds lmLog(log, NULL, &lrd, NULL); 5051da177e4SLinus Torvalds 5061da177e4SLinus Torvalds return 0; 5071da177e4SLinus Torvalds } 508