1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * Copyright (C) International Business Machines Corp., 2000-2004 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 5*1da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 6*1da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 7*1da177e4SLinus Torvalds * (at your option) any later version. 8*1da177e4SLinus Torvalds * 9*1da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, 10*1da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 11*1da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12*1da177e4SLinus Torvalds * the GNU General Public License for more details. 13*1da177e4SLinus Torvalds * 14*1da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 15*1da177e4SLinus Torvalds * along with this program; if not, write to the Free Software 16*1da177e4SLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17*1da177e4SLinus Torvalds */ 18*1da177e4SLinus Torvalds 19*1da177e4SLinus Torvalds /* 20*1da177e4SLinus Torvalds * Module: jfs_mount.c 21*1da177e4SLinus Torvalds * 22*1da177e4SLinus Torvalds * note: file system in transition to aggregate/fileset: 23*1da177e4SLinus Torvalds * 24*1da177e4SLinus Torvalds * file system mount is interpreted as the mount of aggregate, 25*1da177e4SLinus Torvalds * if not already mounted, and mount of the single/only fileset in 26*1da177e4SLinus Torvalds * the aggregate; 27*1da177e4SLinus Torvalds * 28*1da177e4SLinus Torvalds * a file system/aggregate is represented by an internal inode 29*1da177e4SLinus Torvalds * (aka mount inode) initialized with aggregate superblock; 30*1da177e4SLinus Torvalds * each vfs represents a fileset, and points to its "fileset inode 31*1da177e4SLinus Torvalds * allocation map inode" (aka fileset inode): 32*1da177e4SLinus Torvalds * (an aggregate itself is structured recursively as a filset: 33*1da177e4SLinus Torvalds * an internal vfs is constructed and points to its "fileset inode 34*1da177e4SLinus Torvalds * allocation map inode" (aka aggregate inode) where each inode 35*1da177e4SLinus Torvalds * represents a fileset inode) so that inode number is mapped to 36*1da177e4SLinus Torvalds * on-disk inode in uniform way at both aggregate and fileset level; 37*1da177e4SLinus Torvalds * 38*1da177e4SLinus Torvalds * each vnode/inode of a fileset is linked to its vfs (to facilitate 39*1da177e4SLinus Torvalds * per fileset inode operations, e.g., unmount of a fileset, etc.); 40*1da177e4SLinus Torvalds * each inode points to the mount inode (to facilitate access to 41*1da177e4SLinus Torvalds * per aggregate information, e.g., block size, etc.) as well as 42*1da177e4SLinus Torvalds * its file set inode. 43*1da177e4SLinus Torvalds * 44*1da177e4SLinus Torvalds * aggregate 45*1da177e4SLinus Torvalds * ipmnt 46*1da177e4SLinus Torvalds * mntvfs -> fileset ipimap+ -> aggregate ipbmap -> aggregate ipaimap; 47*1da177e4SLinus Torvalds * fileset vfs -> vp(1) <-> ... <-> vp(n) <->vproot; 48*1da177e4SLinus Torvalds */ 49*1da177e4SLinus Torvalds 50*1da177e4SLinus Torvalds #include <linux/fs.h> 51*1da177e4SLinus Torvalds #include <linux/buffer_head.h> 52*1da177e4SLinus Torvalds 53*1da177e4SLinus Torvalds #include "jfs_incore.h" 54*1da177e4SLinus Torvalds #include "jfs_filsys.h" 55*1da177e4SLinus Torvalds #include "jfs_superblock.h" 56*1da177e4SLinus Torvalds #include "jfs_dmap.h" 57*1da177e4SLinus Torvalds #include "jfs_imap.h" 58*1da177e4SLinus Torvalds #include "jfs_metapage.h" 59*1da177e4SLinus Torvalds #include "jfs_debug.h" 60*1da177e4SLinus Torvalds 61*1da177e4SLinus Torvalds 62*1da177e4SLinus Torvalds /* 63*1da177e4SLinus Torvalds * forward references 64*1da177e4SLinus Torvalds */ 65*1da177e4SLinus Torvalds static int chkSuper(struct super_block *); 66*1da177e4SLinus Torvalds static int logMOUNT(struct super_block *sb); 67*1da177e4SLinus Torvalds 68*1da177e4SLinus Torvalds /* 69*1da177e4SLinus Torvalds * NAME: jfs_mount(sb) 70*1da177e4SLinus Torvalds * 71*1da177e4SLinus Torvalds * FUNCTION: vfs_mount() 72*1da177e4SLinus Torvalds * 73*1da177e4SLinus Torvalds * PARAMETER: sb - super block 74*1da177e4SLinus Torvalds * 75*1da177e4SLinus Torvalds * RETURN: -EBUSY - device already mounted or open for write 76*1da177e4SLinus Torvalds * -EBUSY - cvrdvp already mounted; 77*1da177e4SLinus Torvalds * -EBUSY - mount table full 78*1da177e4SLinus Torvalds * -ENOTDIR- cvrdvp not directory on a device mount 79*1da177e4SLinus Torvalds * -ENXIO - device open failure 80*1da177e4SLinus Torvalds */ 81*1da177e4SLinus Torvalds int jfs_mount(struct super_block *sb) 82*1da177e4SLinus Torvalds { 83*1da177e4SLinus Torvalds int rc = 0; /* Return code */ 84*1da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(sb); 85*1da177e4SLinus Torvalds struct inode *ipaimap = NULL; 86*1da177e4SLinus Torvalds struct inode *ipaimap2 = NULL; 87*1da177e4SLinus Torvalds struct inode *ipimap = NULL; 88*1da177e4SLinus Torvalds struct inode *ipbmap = NULL; 89*1da177e4SLinus Torvalds 90*1da177e4SLinus Torvalds /* 91*1da177e4SLinus Torvalds * read/validate superblock 92*1da177e4SLinus Torvalds * (initialize mount inode from the superblock) 93*1da177e4SLinus Torvalds */ 94*1da177e4SLinus Torvalds if ((rc = chkSuper(sb))) { 95*1da177e4SLinus Torvalds goto errout20; 96*1da177e4SLinus Torvalds } 97*1da177e4SLinus Torvalds 98*1da177e4SLinus Torvalds ipaimap = diReadSpecial(sb, AGGREGATE_I, 0); 99*1da177e4SLinus Torvalds if (ipaimap == NULL) { 100*1da177e4SLinus Torvalds jfs_err("jfs_mount: Faild to read AGGREGATE_I"); 101*1da177e4SLinus Torvalds rc = -EIO; 102*1da177e4SLinus Torvalds goto errout20; 103*1da177e4SLinus Torvalds } 104*1da177e4SLinus Torvalds sbi->ipaimap = ipaimap; 105*1da177e4SLinus Torvalds 106*1da177e4SLinus Torvalds jfs_info("jfs_mount: ipaimap:0x%p", ipaimap); 107*1da177e4SLinus Torvalds 108*1da177e4SLinus Torvalds /* 109*1da177e4SLinus Torvalds * initialize aggregate inode allocation map 110*1da177e4SLinus Torvalds */ 111*1da177e4SLinus Torvalds if ((rc = diMount(ipaimap))) { 112*1da177e4SLinus Torvalds jfs_err("jfs_mount: diMount(ipaimap) failed w/rc = %d", rc); 113*1da177e4SLinus Torvalds goto errout21; 114*1da177e4SLinus Torvalds } 115*1da177e4SLinus Torvalds 116*1da177e4SLinus Torvalds /* 117*1da177e4SLinus Torvalds * open aggregate block allocation map 118*1da177e4SLinus Torvalds */ 119*1da177e4SLinus Torvalds ipbmap = diReadSpecial(sb, BMAP_I, 0); 120*1da177e4SLinus Torvalds if (ipbmap == NULL) { 121*1da177e4SLinus Torvalds rc = -EIO; 122*1da177e4SLinus Torvalds goto errout22; 123*1da177e4SLinus Torvalds } 124*1da177e4SLinus Torvalds 125*1da177e4SLinus Torvalds jfs_info("jfs_mount: ipbmap:0x%p", ipbmap); 126*1da177e4SLinus Torvalds 127*1da177e4SLinus Torvalds sbi->ipbmap = ipbmap; 128*1da177e4SLinus Torvalds 129*1da177e4SLinus Torvalds /* 130*1da177e4SLinus Torvalds * initialize aggregate block allocation map 131*1da177e4SLinus Torvalds */ 132*1da177e4SLinus Torvalds if ((rc = dbMount(ipbmap))) { 133*1da177e4SLinus Torvalds jfs_err("jfs_mount: dbMount failed w/rc = %d", rc); 134*1da177e4SLinus Torvalds goto errout22; 135*1da177e4SLinus Torvalds } 136*1da177e4SLinus Torvalds 137*1da177e4SLinus Torvalds /* 138*1da177e4SLinus Torvalds * open the secondary aggregate inode allocation map 139*1da177e4SLinus Torvalds * 140*1da177e4SLinus Torvalds * This is a duplicate of the aggregate inode allocation map. 141*1da177e4SLinus Torvalds * 142*1da177e4SLinus Torvalds * hand craft a vfs in the same fashion as we did to read ipaimap. 143*1da177e4SLinus Torvalds * By adding INOSPEREXT (32) to the inode number, we are telling 144*1da177e4SLinus Torvalds * diReadSpecial that we are reading from the secondary aggregate 145*1da177e4SLinus Torvalds * inode table. This also creates a unique entry in the inode hash 146*1da177e4SLinus Torvalds * table. 147*1da177e4SLinus Torvalds */ 148*1da177e4SLinus Torvalds if ((sbi->mntflag & JFS_BAD_SAIT) == 0) { 149*1da177e4SLinus Torvalds ipaimap2 = diReadSpecial(sb, AGGREGATE_I, 1); 150*1da177e4SLinus Torvalds if (ipaimap2 == 0) { 151*1da177e4SLinus Torvalds jfs_err("jfs_mount: Faild to read AGGREGATE_I"); 152*1da177e4SLinus Torvalds rc = -EIO; 153*1da177e4SLinus Torvalds goto errout35; 154*1da177e4SLinus Torvalds } 155*1da177e4SLinus Torvalds sbi->ipaimap2 = ipaimap2; 156*1da177e4SLinus Torvalds 157*1da177e4SLinus Torvalds jfs_info("jfs_mount: ipaimap2:0x%p", ipaimap2); 158*1da177e4SLinus Torvalds 159*1da177e4SLinus Torvalds /* 160*1da177e4SLinus Torvalds * initialize secondary aggregate inode allocation map 161*1da177e4SLinus Torvalds */ 162*1da177e4SLinus Torvalds if ((rc = diMount(ipaimap2))) { 163*1da177e4SLinus Torvalds jfs_err("jfs_mount: diMount(ipaimap2) failed, rc = %d", 164*1da177e4SLinus Torvalds rc); 165*1da177e4SLinus Torvalds goto errout35; 166*1da177e4SLinus Torvalds } 167*1da177e4SLinus Torvalds } else 168*1da177e4SLinus Torvalds /* Secondary aggregate inode table is not valid */ 169*1da177e4SLinus Torvalds sbi->ipaimap2 = NULL; 170*1da177e4SLinus Torvalds 171*1da177e4SLinus Torvalds /* 172*1da177e4SLinus Torvalds * mount (the only/single) fileset 173*1da177e4SLinus Torvalds */ 174*1da177e4SLinus Torvalds /* 175*1da177e4SLinus Torvalds * open fileset inode allocation map (aka fileset inode) 176*1da177e4SLinus Torvalds */ 177*1da177e4SLinus Torvalds ipimap = diReadSpecial(sb, FILESYSTEM_I, 0); 178*1da177e4SLinus Torvalds if (ipimap == NULL) { 179*1da177e4SLinus Torvalds jfs_err("jfs_mount: Failed to read FILESYSTEM_I"); 180*1da177e4SLinus Torvalds /* open fileset secondary inode allocation map */ 181*1da177e4SLinus Torvalds rc = -EIO; 182*1da177e4SLinus Torvalds goto errout40; 183*1da177e4SLinus Torvalds } 184*1da177e4SLinus Torvalds jfs_info("jfs_mount: ipimap:0x%p", ipimap); 185*1da177e4SLinus Torvalds 186*1da177e4SLinus Torvalds /* map further access of per fileset inodes by the fileset inode */ 187*1da177e4SLinus Torvalds sbi->ipimap = ipimap; 188*1da177e4SLinus Torvalds 189*1da177e4SLinus Torvalds /* initialize fileset inode allocation map */ 190*1da177e4SLinus Torvalds if ((rc = diMount(ipimap))) { 191*1da177e4SLinus Torvalds jfs_err("jfs_mount: diMount failed w/rc = %d", rc); 192*1da177e4SLinus Torvalds goto errout41; 193*1da177e4SLinus Torvalds } 194*1da177e4SLinus Torvalds 195*1da177e4SLinus Torvalds goto out; 196*1da177e4SLinus Torvalds 197*1da177e4SLinus Torvalds /* 198*1da177e4SLinus Torvalds * unwind on error 199*1da177e4SLinus Torvalds */ 200*1da177e4SLinus Torvalds errout41: /* close fileset inode allocation map inode */ 201*1da177e4SLinus Torvalds diFreeSpecial(ipimap); 202*1da177e4SLinus Torvalds 203*1da177e4SLinus Torvalds errout40: /* fileset closed */ 204*1da177e4SLinus Torvalds 205*1da177e4SLinus Torvalds /* close secondary aggregate inode allocation map */ 206*1da177e4SLinus Torvalds if (ipaimap2) { 207*1da177e4SLinus Torvalds diUnmount(ipaimap2, 1); 208*1da177e4SLinus Torvalds diFreeSpecial(ipaimap2); 209*1da177e4SLinus Torvalds } 210*1da177e4SLinus Torvalds 211*1da177e4SLinus Torvalds errout35: 212*1da177e4SLinus Torvalds 213*1da177e4SLinus Torvalds /* close aggregate block allocation map */ 214*1da177e4SLinus Torvalds dbUnmount(ipbmap, 1); 215*1da177e4SLinus Torvalds diFreeSpecial(ipbmap); 216*1da177e4SLinus Torvalds 217*1da177e4SLinus Torvalds errout22: /* close aggregate inode allocation map */ 218*1da177e4SLinus Torvalds 219*1da177e4SLinus Torvalds diUnmount(ipaimap, 1); 220*1da177e4SLinus Torvalds 221*1da177e4SLinus Torvalds errout21: /* close aggregate inodes */ 222*1da177e4SLinus Torvalds diFreeSpecial(ipaimap); 223*1da177e4SLinus Torvalds errout20: /* aggregate closed */ 224*1da177e4SLinus Torvalds 225*1da177e4SLinus Torvalds out: 226*1da177e4SLinus Torvalds 227*1da177e4SLinus Torvalds if (rc) 228*1da177e4SLinus Torvalds jfs_err("Mount JFS Failure: %d", rc); 229*1da177e4SLinus Torvalds 230*1da177e4SLinus Torvalds return rc; 231*1da177e4SLinus Torvalds } 232*1da177e4SLinus Torvalds 233*1da177e4SLinus Torvalds /* 234*1da177e4SLinus Torvalds * NAME: jfs_mount_rw(sb, remount) 235*1da177e4SLinus Torvalds * 236*1da177e4SLinus Torvalds * FUNCTION: Completes read-write mount, or remounts read-only volume 237*1da177e4SLinus Torvalds * as read-write 238*1da177e4SLinus Torvalds */ 239*1da177e4SLinus Torvalds int jfs_mount_rw(struct super_block *sb, int remount) 240*1da177e4SLinus Torvalds { 241*1da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(sb); 242*1da177e4SLinus Torvalds int rc; 243*1da177e4SLinus Torvalds 244*1da177e4SLinus Torvalds /* 245*1da177e4SLinus Torvalds * If we are re-mounting a previously read-only volume, we want to 246*1da177e4SLinus Torvalds * re-read the inode and block maps, since fsck.jfs may have updated 247*1da177e4SLinus Torvalds * them. 248*1da177e4SLinus Torvalds */ 249*1da177e4SLinus Torvalds if (remount) { 250*1da177e4SLinus Torvalds if (chkSuper(sb) || (sbi->state != FM_CLEAN)) 251*1da177e4SLinus Torvalds return -EINVAL; 252*1da177e4SLinus Torvalds 253*1da177e4SLinus Torvalds truncate_inode_pages(sbi->ipimap->i_mapping, 0); 254*1da177e4SLinus Torvalds truncate_inode_pages(sbi->ipbmap->i_mapping, 0); 255*1da177e4SLinus Torvalds diUnmount(sbi->ipimap, 1); 256*1da177e4SLinus Torvalds if ((rc = diMount(sbi->ipimap))) { 257*1da177e4SLinus Torvalds jfs_err("jfs_mount_rw: diMount failed!"); 258*1da177e4SLinus Torvalds return rc; 259*1da177e4SLinus Torvalds } 260*1da177e4SLinus Torvalds 261*1da177e4SLinus Torvalds dbUnmount(sbi->ipbmap, 1); 262*1da177e4SLinus Torvalds if ((rc = dbMount(sbi->ipbmap))) { 263*1da177e4SLinus Torvalds jfs_err("jfs_mount_rw: dbMount failed!"); 264*1da177e4SLinus Torvalds return rc; 265*1da177e4SLinus Torvalds } 266*1da177e4SLinus Torvalds } 267*1da177e4SLinus Torvalds 268*1da177e4SLinus Torvalds /* 269*1da177e4SLinus Torvalds * open/initialize log 270*1da177e4SLinus Torvalds */ 271*1da177e4SLinus Torvalds if ((rc = lmLogOpen(sb))) 272*1da177e4SLinus Torvalds return rc; 273*1da177e4SLinus Torvalds 274*1da177e4SLinus Torvalds /* 275*1da177e4SLinus Torvalds * update file system superblock; 276*1da177e4SLinus Torvalds */ 277*1da177e4SLinus Torvalds if ((rc = updateSuper(sb, FM_MOUNT))) { 278*1da177e4SLinus Torvalds jfs_err("jfs_mount: updateSuper failed w/rc = %d", rc); 279*1da177e4SLinus Torvalds lmLogClose(sb); 280*1da177e4SLinus Torvalds return rc; 281*1da177e4SLinus Torvalds } 282*1da177e4SLinus Torvalds 283*1da177e4SLinus Torvalds /* 284*1da177e4SLinus Torvalds * write MOUNT log record of the file system 285*1da177e4SLinus Torvalds */ 286*1da177e4SLinus Torvalds logMOUNT(sb); 287*1da177e4SLinus Torvalds 288*1da177e4SLinus Torvalds /* 289*1da177e4SLinus Torvalds * Set page cache allocation policy 290*1da177e4SLinus Torvalds */ 291*1da177e4SLinus Torvalds mapping_set_gfp_mask(sb->s_bdev->bd_inode->i_mapping, GFP_NOFS); 292*1da177e4SLinus Torvalds 293*1da177e4SLinus Torvalds return rc; 294*1da177e4SLinus Torvalds } 295*1da177e4SLinus Torvalds 296*1da177e4SLinus Torvalds /* 297*1da177e4SLinus Torvalds * chkSuper() 298*1da177e4SLinus Torvalds * 299*1da177e4SLinus Torvalds * validate the superblock of the file system to be mounted and 300*1da177e4SLinus Torvalds * get the file system parameters. 301*1da177e4SLinus Torvalds * 302*1da177e4SLinus Torvalds * returns 303*1da177e4SLinus Torvalds * 0 with fragsize set if check successful 304*1da177e4SLinus Torvalds * error code if not successful 305*1da177e4SLinus Torvalds */ 306*1da177e4SLinus Torvalds static int chkSuper(struct super_block *sb) 307*1da177e4SLinus Torvalds { 308*1da177e4SLinus Torvalds int rc = 0; 309*1da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(sb); 310*1da177e4SLinus Torvalds struct jfs_superblock *j_sb; 311*1da177e4SLinus Torvalds struct buffer_head *bh; 312*1da177e4SLinus Torvalds int AIM_bytesize, AIT_bytesize; 313*1da177e4SLinus Torvalds int expected_AIM_bytesize, expected_AIT_bytesize; 314*1da177e4SLinus Torvalds s64 AIM_byte_addr, AIT_byte_addr, fsckwsp_addr; 315*1da177e4SLinus Torvalds s64 byte_addr_diff0, byte_addr_diff1; 316*1da177e4SLinus Torvalds s32 bsize; 317*1da177e4SLinus Torvalds 318*1da177e4SLinus Torvalds if ((rc = readSuper(sb, &bh))) 319*1da177e4SLinus Torvalds return rc; 320*1da177e4SLinus Torvalds j_sb = (struct jfs_superblock *)bh->b_data; 321*1da177e4SLinus Torvalds 322*1da177e4SLinus Torvalds /* 323*1da177e4SLinus Torvalds * validate superblock 324*1da177e4SLinus Torvalds */ 325*1da177e4SLinus Torvalds /* validate fs signature */ 326*1da177e4SLinus Torvalds if (strncmp(j_sb->s_magic, JFS_MAGIC, 4) || 327*1da177e4SLinus Torvalds le32_to_cpu(j_sb->s_version) > JFS_VERSION) { 328*1da177e4SLinus Torvalds rc = -EINVAL; 329*1da177e4SLinus Torvalds goto out; 330*1da177e4SLinus Torvalds } 331*1da177e4SLinus Torvalds 332*1da177e4SLinus Torvalds bsize = le32_to_cpu(j_sb->s_bsize); 333*1da177e4SLinus Torvalds #ifdef _JFS_4K 334*1da177e4SLinus Torvalds if (bsize != PSIZE) { 335*1da177e4SLinus Torvalds jfs_err("Currently only 4K block size supported!"); 336*1da177e4SLinus Torvalds rc = -EINVAL; 337*1da177e4SLinus Torvalds goto out; 338*1da177e4SLinus Torvalds } 339*1da177e4SLinus Torvalds #endif /* _JFS_4K */ 340*1da177e4SLinus Torvalds 341*1da177e4SLinus Torvalds jfs_info("superblock: flag:0x%08x state:0x%08x size:0x%Lx", 342*1da177e4SLinus Torvalds le32_to_cpu(j_sb->s_flag), le32_to_cpu(j_sb->s_state), 343*1da177e4SLinus Torvalds (unsigned long long) le64_to_cpu(j_sb->s_size)); 344*1da177e4SLinus Torvalds 345*1da177e4SLinus Torvalds /* validate the descriptors for Secondary AIM and AIT */ 346*1da177e4SLinus Torvalds if ((j_sb->s_flag & cpu_to_le32(JFS_BAD_SAIT)) != 347*1da177e4SLinus Torvalds cpu_to_le32(JFS_BAD_SAIT)) { 348*1da177e4SLinus Torvalds expected_AIM_bytesize = 2 * PSIZE; 349*1da177e4SLinus Torvalds AIM_bytesize = lengthPXD(&(j_sb->s_aim2)) * bsize; 350*1da177e4SLinus Torvalds expected_AIT_bytesize = 4 * PSIZE; 351*1da177e4SLinus Torvalds AIT_bytesize = lengthPXD(&(j_sb->s_ait2)) * bsize; 352*1da177e4SLinus Torvalds AIM_byte_addr = addressPXD(&(j_sb->s_aim2)) * bsize; 353*1da177e4SLinus Torvalds AIT_byte_addr = addressPXD(&(j_sb->s_ait2)) * bsize; 354*1da177e4SLinus Torvalds byte_addr_diff0 = AIT_byte_addr - AIM_byte_addr; 355*1da177e4SLinus Torvalds fsckwsp_addr = addressPXD(&(j_sb->s_fsckpxd)) * bsize; 356*1da177e4SLinus Torvalds byte_addr_diff1 = fsckwsp_addr - AIT_byte_addr; 357*1da177e4SLinus Torvalds if ((AIM_bytesize != expected_AIM_bytesize) || 358*1da177e4SLinus Torvalds (AIT_bytesize != expected_AIT_bytesize) || 359*1da177e4SLinus Torvalds (byte_addr_diff0 != AIM_bytesize) || 360*1da177e4SLinus Torvalds (byte_addr_diff1 <= AIT_bytesize)) 361*1da177e4SLinus Torvalds j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT); 362*1da177e4SLinus Torvalds } 363*1da177e4SLinus Torvalds 364*1da177e4SLinus Torvalds if ((j_sb->s_flag & cpu_to_le32(JFS_GROUPCOMMIT)) != 365*1da177e4SLinus Torvalds cpu_to_le32(JFS_GROUPCOMMIT)) 366*1da177e4SLinus Torvalds j_sb->s_flag |= cpu_to_le32(JFS_GROUPCOMMIT); 367*1da177e4SLinus Torvalds 368*1da177e4SLinus Torvalds /* validate fs state */ 369*1da177e4SLinus Torvalds if (j_sb->s_state != cpu_to_le32(FM_CLEAN) && 370*1da177e4SLinus Torvalds !(sb->s_flags & MS_RDONLY)) { 371*1da177e4SLinus Torvalds jfs_err("jfs_mount: Mount Failure: File System Dirty."); 372*1da177e4SLinus Torvalds rc = -EINVAL; 373*1da177e4SLinus Torvalds goto out; 374*1da177e4SLinus Torvalds } 375*1da177e4SLinus Torvalds 376*1da177e4SLinus Torvalds sbi->state = le32_to_cpu(j_sb->s_state); 377*1da177e4SLinus Torvalds sbi->mntflag = le32_to_cpu(j_sb->s_flag); 378*1da177e4SLinus Torvalds 379*1da177e4SLinus Torvalds /* 380*1da177e4SLinus Torvalds * JFS always does I/O by 4K pages. Don't tell the buffer cache 381*1da177e4SLinus Torvalds * that we use anything else (leave s_blocksize alone). 382*1da177e4SLinus Torvalds */ 383*1da177e4SLinus Torvalds sbi->bsize = bsize; 384*1da177e4SLinus Torvalds sbi->l2bsize = le16_to_cpu(j_sb->s_l2bsize); 385*1da177e4SLinus Torvalds 386*1da177e4SLinus Torvalds /* 387*1da177e4SLinus Torvalds * For now, ignore s_pbsize, l2bfactor. All I/O going through buffer 388*1da177e4SLinus Torvalds * cache. 389*1da177e4SLinus Torvalds */ 390*1da177e4SLinus Torvalds sbi->nbperpage = PSIZE >> sbi->l2bsize; 391*1da177e4SLinus Torvalds sbi->l2nbperpage = L2PSIZE - sbi->l2bsize; 392*1da177e4SLinus Torvalds sbi->l2niperblk = sbi->l2bsize - L2DISIZE; 393*1da177e4SLinus Torvalds if (sbi->mntflag & JFS_INLINELOG) 394*1da177e4SLinus Torvalds sbi->logpxd = j_sb->s_logpxd; 395*1da177e4SLinus Torvalds else { 396*1da177e4SLinus Torvalds sbi->logdev = new_decode_dev(le32_to_cpu(j_sb->s_logdev)); 397*1da177e4SLinus Torvalds memcpy(sbi->uuid, j_sb->s_uuid, sizeof(sbi->uuid)); 398*1da177e4SLinus Torvalds memcpy(sbi->loguuid, j_sb->s_loguuid, sizeof(sbi->uuid)); 399*1da177e4SLinus Torvalds } 400*1da177e4SLinus Torvalds sbi->fsckpxd = j_sb->s_fsckpxd; 401*1da177e4SLinus Torvalds sbi->ait2 = j_sb->s_ait2; 402*1da177e4SLinus Torvalds 403*1da177e4SLinus Torvalds out: 404*1da177e4SLinus Torvalds brelse(bh); 405*1da177e4SLinus Torvalds return rc; 406*1da177e4SLinus Torvalds } 407*1da177e4SLinus Torvalds 408*1da177e4SLinus Torvalds 409*1da177e4SLinus Torvalds /* 410*1da177e4SLinus Torvalds * updateSuper() 411*1da177e4SLinus Torvalds * 412*1da177e4SLinus Torvalds * update synchronously superblock if it is mounted read-write. 413*1da177e4SLinus Torvalds */ 414*1da177e4SLinus Torvalds int updateSuper(struct super_block *sb, uint state) 415*1da177e4SLinus Torvalds { 416*1da177e4SLinus Torvalds struct jfs_superblock *j_sb; 417*1da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(sb); 418*1da177e4SLinus Torvalds struct buffer_head *bh; 419*1da177e4SLinus Torvalds int rc; 420*1da177e4SLinus Torvalds 421*1da177e4SLinus Torvalds if (sbi->flag & JFS_NOINTEGRITY) { 422*1da177e4SLinus Torvalds if (state == FM_DIRTY) { 423*1da177e4SLinus Torvalds sbi->p_state = state; 424*1da177e4SLinus Torvalds return 0; 425*1da177e4SLinus Torvalds } else if (state == FM_MOUNT) { 426*1da177e4SLinus Torvalds sbi->p_state = sbi->state; 427*1da177e4SLinus Torvalds state = FM_DIRTY; 428*1da177e4SLinus Torvalds } else if (state == FM_CLEAN) { 429*1da177e4SLinus Torvalds state = sbi->p_state; 430*1da177e4SLinus Torvalds } else 431*1da177e4SLinus Torvalds jfs_err("updateSuper: bad state"); 432*1da177e4SLinus Torvalds } else if (sbi->state == FM_DIRTY) 433*1da177e4SLinus Torvalds return 0; 434*1da177e4SLinus Torvalds 435*1da177e4SLinus Torvalds if ((rc = readSuper(sb, &bh))) 436*1da177e4SLinus Torvalds return rc; 437*1da177e4SLinus Torvalds 438*1da177e4SLinus Torvalds j_sb = (struct jfs_superblock *)bh->b_data; 439*1da177e4SLinus Torvalds 440*1da177e4SLinus Torvalds j_sb->s_state = cpu_to_le32(state); 441*1da177e4SLinus Torvalds sbi->state = state; 442*1da177e4SLinus Torvalds 443*1da177e4SLinus Torvalds if (state == FM_MOUNT) { 444*1da177e4SLinus Torvalds /* record log's dev_t and mount serial number */ 445*1da177e4SLinus Torvalds j_sb->s_logdev = cpu_to_le32(new_encode_dev(sbi->log->bdev->bd_dev)); 446*1da177e4SLinus Torvalds j_sb->s_logserial = cpu_to_le32(sbi->log->serial); 447*1da177e4SLinus Torvalds } else if (state == FM_CLEAN) { 448*1da177e4SLinus Torvalds /* 449*1da177e4SLinus Torvalds * If this volume is shared with OS/2, OS/2 will need to 450*1da177e4SLinus Torvalds * recalculate DASD usage, since we don't deal with it. 451*1da177e4SLinus Torvalds */ 452*1da177e4SLinus Torvalds if (j_sb->s_flag & cpu_to_le32(JFS_DASD_ENABLED)) 453*1da177e4SLinus Torvalds j_sb->s_flag |= cpu_to_le32(JFS_DASD_PRIME); 454*1da177e4SLinus Torvalds } 455*1da177e4SLinus Torvalds 456*1da177e4SLinus Torvalds mark_buffer_dirty(bh); 457*1da177e4SLinus Torvalds sync_dirty_buffer(bh); 458*1da177e4SLinus Torvalds brelse(bh); 459*1da177e4SLinus Torvalds 460*1da177e4SLinus Torvalds return 0; 461*1da177e4SLinus Torvalds } 462*1da177e4SLinus Torvalds 463*1da177e4SLinus Torvalds 464*1da177e4SLinus Torvalds /* 465*1da177e4SLinus Torvalds * readSuper() 466*1da177e4SLinus Torvalds * 467*1da177e4SLinus Torvalds * read superblock by raw sector address 468*1da177e4SLinus Torvalds */ 469*1da177e4SLinus Torvalds int readSuper(struct super_block *sb, struct buffer_head **bpp) 470*1da177e4SLinus Torvalds { 471*1da177e4SLinus Torvalds /* read in primary superblock */ 472*1da177e4SLinus Torvalds *bpp = sb_bread(sb, SUPER1_OFF >> sb->s_blocksize_bits); 473*1da177e4SLinus Torvalds if (*bpp) 474*1da177e4SLinus Torvalds return 0; 475*1da177e4SLinus Torvalds 476*1da177e4SLinus Torvalds /* read in secondary/replicated superblock */ 477*1da177e4SLinus Torvalds *bpp = sb_bread(sb, SUPER2_OFF >> sb->s_blocksize_bits); 478*1da177e4SLinus Torvalds if (*bpp) 479*1da177e4SLinus Torvalds return 0; 480*1da177e4SLinus Torvalds 481*1da177e4SLinus Torvalds return -EIO; 482*1da177e4SLinus Torvalds } 483*1da177e4SLinus Torvalds 484*1da177e4SLinus Torvalds 485*1da177e4SLinus Torvalds /* 486*1da177e4SLinus Torvalds * logMOUNT() 487*1da177e4SLinus Torvalds * 488*1da177e4SLinus Torvalds * function: write a MOUNT log record for file system. 489*1da177e4SLinus Torvalds * 490*1da177e4SLinus Torvalds * MOUNT record keeps logredo() from processing log records 491*1da177e4SLinus Torvalds * for this file system past this point in log. 492*1da177e4SLinus Torvalds * it is harmless if mount fails. 493*1da177e4SLinus Torvalds * 494*1da177e4SLinus Torvalds * note: MOUNT record is at aggregate level, not at fileset level, 495*1da177e4SLinus Torvalds * since log records of previous mounts of a fileset 496*1da177e4SLinus Torvalds * (e.g., AFTER record of extent allocation) have to be processed 497*1da177e4SLinus Torvalds * to update block allocation map at aggregate level. 498*1da177e4SLinus Torvalds */ 499*1da177e4SLinus Torvalds static int logMOUNT(struct super_block *sb) 500*1da177e4SLinus Torvalds { 501*1da177e4SLinus Torvalds struct jfs_log *log = JFS_SBI(sb)->log; 502*1da177e4SLinus Torvalds struct lrd lrd; 503*1da177e4SLinus Torvalds 504*1da177e4SLinus Torvalds lrd.logtid = 0; 505*1da177e4SLinus Torvalds lrd.backchain = 0; 506*1da177e4SLinus Torvalds lrd.type = cpu_to_le16(LOG_MOUNT); 507*1da177e4SLinus Torvalds lrd.length = 0; 508*1da177e4SLinus Torvalds lrd.aggregate = cpu_to_le32(new_encode_dev(sb->s_bdev->bd_dev)); 509*1da177e4SLinus Torvalds lmLog(log, NULL, &lrd, NULL); 510*1da177e4SLinus Torvalds 511*1da177e4SLinus Torvalds return 0; 512*1da177e4SLinus Torvalds } 513