162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) International Business Machines Corp., 2000-2004 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci/* 762306a36Sopenharmony_ci * Module: jfs_mount.c 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * note: file system in transition to aggregate/fileset: 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * file system mount is interpreted as the mount of aggregate, 1262306a36Sopenharmony_ci * if not already mounted, and mount of the single/only fileset in 1362306a36Sopenharmony_ci * the aggregate; 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * a file system/aggregate is represented by an internal inode 1662306a36Sopenharmony_ci * (aka mount inode) initialized with aggregate superblock; 1762306a36Sopenharmony_ci * each vfs represents a fileset, and points to its "fileset inode 1862306a36Sopenharmony_ci * allocation map inode" (aka fileset inode): 1962306a36Sopenharmony_ci * (an aggregate itself is structured recursively as a filset: 2062306a36Sopenharmony_ci * an internal vfs is constructed and points to its "fileset inode 2162306a36Sopenharmony_ci * allocation map inode" (aka aggregate inode) where each inode 2262306a36Sopenharmony_ci * represents a fileset inode) so that inode number is mapped to 2362306a36Sopenharmony_ci * on-disk inode in uniform way at both aggregate and fileset level; 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * each vnode/inode of a fileset is linked to its vfs (to facilitate 2662306a36Sopenharmony_ci * per fileset inode operations, e.g., unmount of a fileset, etc.); 2762306a36Sopenharmony_ci * each inode points to the mount inode (to facilitate access to 2862306a36Sopenharmony_ci * per aggregate information, e.g., block size, etc.) as well as 2962306a36Sopenharmony_ci * its file set inode. 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * aggregate 3262306a36Sopenharmony_ci * ipmnt 3362306a36Sopenharmony_ci * mntvfs -> fileset ipimap+ -> aggregate ipbmap -> aggregate ipaimap; 3462306a36Sopenharmony_ci * fileset vfs -> vp(1) <-> ... <-> vp(n) <->vproot; 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#include <linux/fs.h> 3862306a36Sopenharmony_ci#include <linux/buffer_head.h> 3962306a36Sopenharmony_ci#include <linux/blkdev.h> 4062306a36Sopenharmony_ci#include <linux/log2.h> 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#include "jfs_incore.h" 4362306a36Sopenharmony_ci#include "jfs_filsys.h" 4462306a36Sopenharmony_ci#include "jfs_superblock.h" 4562306a36Sopenharmony_ci#include "jfs_dmap.h" 4662306a36Sopenharmony_ci#include "jfs_imap.h" 4762306a36Sopenharmony_ci#include "jfs_metapage.h" 4862306a36Sopenharmony_ci#include "jfs_debug.h" 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/* 5262306a36Sopenharmony_ci * forward references 5362306a36Sopenharmony_ci */ 5462306a36Sopenharmony_cistatic int chkSuper(struct super_block *); 5562306a36Sopenharmony_cistatic int logMOUNT(struct super_block *sb); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* 5862306a36Sopenharmony_ci * NAME: jfs_mount(sb) 5962306a36Sopenharmony_ci * 6062306a36Sopenharmony_ci * FUNCTION: vfs_mount() 6162306a36Sopenharmony_ci * 6262306a36Sopenharmony_ci * PARAMETER: sb - super block 6362306a36Sopenharmony_ci * 6462306a36Sopenharmony_ci * RETURN: -EBUSY - device already mounted or open for write 6562306a36Sopenharmony_ci * -EBUSY - cvrdvp already mounted; 6662306a36Sopenharmony_ci * -EBUSY - mount table full 6762306a36Sopenharmony_ci * -ENOTDIR- cvrdvp not directory on a device mount 6862306a36Sopenharmony_ci * -ENXIO - device open failure 6962306a36Sopenharmony_ci */ 7062306a36Sopenharmony_ciint jfs_mount(struct super_block *sb) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci int rc = 0; /* Return code */ 7362306a36Sopenharmony_ci struct jfs_sb_info *sbi = JFS_SBI(sb); 7462306a36Sopenharmony_ci struct inode *ipaimap = NULL; 7562306a36Sopenharmony_ci struct inode *ipaimap2 = NULL; 7662306a36Sopenharmony_ci struct inode *ipimap = NULL; 7762306a36Sopenharmony_ci struct inode *ipbmap = NULL; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci /* 8062306a36Sopenharmony_ci * read/validate superblock 8162306a36Sopenharmony_ci * (initialize mount inode from the superblock) 8262306a36Sopenharmony_ci */ 8362306a36Sopenharmony_ci if ((rc = chkSuper(sb))) { 8462306a36Sopenharmony_ci goto out; 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci ipaimap = diReadSpecial(sb, AGGREGATE_I, 0); 8862306a36Sopenharmony_ci if (ipaimap == NULL) { 8962306a36Sopenharmony_ci jfs_err("jfs_mount: Failed to read AGGREGATE_I"); 9062306a36Sopenharmony_ci rc = -EIO; 9162306a36Sopenharmony_ci goto out; 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci sbi->ipaimap = ipaimap; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci jfs_info("jfs_mount: ipaimap:0x%p", ipaimap); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci /* 9862306a36Sopenharmony_ci * initialize aggregate inode allocation map 9962306a36Sopenharmony_ci */ 10062306a36Sopenharmony_ci if ((rc = diMount(ipaimap))) { 10162306a36Sopenharmony_ci jfs_err("jfs_mount: diMount(ipaimap) failed w/rc = %d", rc); 10262306a36Sopenharmony_ci goto err_ipaimap; 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci /* 10662306a36Sopenharmony_ci * open aggregate block allocation map 10762306a36Sopenharmony_ci */ 10862306a36Sopenharmony_ci ipbmap = diReadSpecial(sb, BMAP_I, 0); 10962306a36Sopenharmony_ci if (ipbmap == NULL) { 11062306a36Sopenharmony_ci rc = -EIO; 11162306a36Sopenharmony_ci goto err_umount_ipaimap; 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci jfs_info("jfs_mount: ipbmap:0x%p", ipbmap); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci sbi->ipbmap = ipbmap; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci /* 11962306a36Sopenharmony_ci * initialize aggregate block allocation map 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_ci if ((rc = dbMount(ipbmap))) { 12262306a36Sopenharmony_ci jfs_err("jfs_mount: dbMount failed w/rc = %d", rc); 12362306a36Sopenharmony_ci goto err_ipbmap; 12462306a36Sopenharmony_ci } 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci /* 12762306a36Sopenharmony_ci * open the secondary aggregate inode allocation map 12862306a36Sopenharmony_ci * 12962306a36Sopenharmony_ci * This is a duplicate of the aggregate inode allocation map. 13062306a36Sopenharmony_ci * 13162306a36Sopenharmony_ci * hand craft a vfs in the same fashion as we did to read ipaimap. 13262306a36Sopenharmony_ci * By adding INOSPEREXT (32) to the inode number, we are telling 13362306a36Sopenharmony_ci * diReadSpecial that we are reading from the secondary aggregate 13462306a36Sopenharmony_ci * inode table. This also creates a unique entry in the inode hash 13562306a36Sopenharmony_ci * table. 13662306a36Sopenharmony_ci */ 13762306a36Sopenharmony_ci if ((sbi->mntflag & JFS_BAD_SAIT) == 0) { 13862306a36Sopenharmony_ci ipaimap2 = diReadSpecial(sb, AGGREGATE_I, 1); 13962306a36Sopenharmony_ci if (!ipaimap2) { 14062306a36Sopenharmony_ci jfs_err("jfs_mount: Failed to read AGGREGATE_I"); 14162306a36Sopenharmony_ci rc = -EIO; 14262306a36Sopenharmony_ci goto err_umount_ipbmap; 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ci sbi->ipaimap2 = ipaimap2; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci jfs_info("jfs_mount: ipaimap2:0x%p", ipaimap2); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci /* 14962306a36Sopenharmony_ci * initialize secondary aggregate inode allocation map 15062306a36Sopenharmony_ci */ 15162306a36Sopenharmony_ci if ((rc = diMount(ipaimap2))) { 15262306a36Sopenharmony_ci jfs_err("jfs_mount: diMount(ipaimap2) failed, rc = %d", 15362306a36Sopenharmony_ci rc); 15462306a36Sopenharmony_ci goto err_ipaimap2; 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci } else 15762306a36Sopenharmony_ci /* Secondary aggregate inode table is not valid */ 15862306a36Sopenharmony_ci sbi->ipaimap2 = NULL; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci /* 16162306a36Sopenharmony_ci * mount (the only/single) fileset 16262306a36Sopenharmony_ci */ 16362306a36Sopenharmony_ci /* 16462306a36Sopenharmony_ci * open fileset inode allocation map (aka fileset inode) 16562306a36Sopenharmony_ci */ 16662306a36Sopenharmony_ci ipimap = diReadSpecial(sb, FILESYSTEM_I, 0); 16762306a36Sopenharmony_ci if (ipimap == NULL) { 16862306a36Sopenharmony_ci jfs_err("jfs_mount: Failed to read FILESYSTEM_I"); 16962306a36Sopenharmony_ci /* open fileset secondary inode allocation map */ 17062306a36Sopenharmony_ci rc = -EIO; 17162306a36Sopenharmony_ci goto err_umount_ipaimap2; 17262306a36Sopenharmony_ci } 17362306a36Sopenharmony_ci jfs_info("jfs_mount: ipimap:0x%p", ipimap); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci /* initialize fileset inode allocation map */ 17662306a36Sopenharmony_ci if ((rc = diMount(ipimap))) { 17762306a36Sopenharmony_ci jfs_err("jfs_mount: diMount failed w/rc = %d", rc); 17862306a36Sopenharmony_ci goto err_ipimap; 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci /* map further access of per fileset inodes by the fileset inode */ 18262306a36Sopenharmony_ci sbi->ipimap = ipimap; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci return rc; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci /* 18762306a36Sopenharmony_ci * unwind on error 18862306a36Sopenharmony_ci */ 18962306a36Sopenharmony_cierr_ipimap: 19062306a36Sopenharmony_ci /* close fileset inode allocation map inode */ 19162306a36Sopenharmony_ci diFreeSpecial(ipimap); 19262306a36Sopenharmony_cierr_umount_ipaimap2: 19362306a36Sopenharmony_ci /* close secondary aggregate inode allocation map */ 19462306a36Sopenharmony_ci if (ipaimap2) 19562306a36Sopenharmony_ci diUnmount(ipaimap2, 1); 19662306a36Sopenharmony_cierr_ipaimap2: 19762306a36Sopenharmony_ci /* close aggregate inodes */ 19862306a36Sopenharmony_ci if (ipaimap2) 19962306a36Sopenharmony_ci diFreeSpecial(ipaimap2); 20062306a36Sopenharmony_cierr_umount_ipbmap: /* close aggregate block allocation map */ 20162306a36Sopenharmony_ci dbUnmount(ipbmap, 1); 20262306a36Sopenharmony_cierr_ipbmap: /* close aggregate inodes */ 20362306a36Sopenharmony_ci diFreeSpecial(ipbmap); 20462306a36Sopenharmony_cierr_umount_ipaimap: /* close aggregate inode allocation map */ 20562306a36Sopenharmony_ci diUnmount(ipaimap, 1); 20662306a36Sopenharmony_cierr_ipaimap: /* close aggregate inodes */ 20762306a36Sopenharmony_ci diFreeSpecial(ipaimap); 20862306a36Sopenharmony_ciout: 20962306a36Sopenharmony_ci if (rc) 21062306a36Sopenharmony_ci jfs_err("Mount JFS Failure: %d", rc); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci return rc; 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci/* 21662306a36Sopenharmony_ci * NAME: jfs_mount_rw(sb, remount) 21762306a36Sopenharmony_ci * 21862306a36Sopenharmony_ci * FUNCTION: Completes read-write mount, or remounts read-only volume 21962306a36Sopenharmony_ci * as read-write 22062306a36Sopenharmony_ci */ 22162306a36Sopenharmony_ciint jfs_mount_rw(struct super_block *sb, int remount) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci struct jfs_sb_info *sbi = JFS_SBI(sb); 22462306a36Sopenharmony_ci int rc; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci /* 22762306a36Sopenharmony_ci * If we are re-mounting a previously read-only volume, we want to 22862306a36Sopenharmony_ci * re-read the inode and block maps, since fsck.jfs may have updated 22962306a36Sopenharmony_ci * them. 23062306a36Sopenharmony_ci */ 23162306a36Sopenharmony_ci if (remount) { 23262306a36Sopenharmony_ci if (chkSuper(sb) || (sbi->state != FM_CLEAN)) 23362306a36Sopenharmony_ci return -EINVAL; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci truncate_inode_pages(sbi->ipimap->i_mapping, 0); 23662306a36Sopenharmony_ci truncate_inode_pages(sbi->ipbmap->i_mapping, 0); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci IWRITE_LOCK(sbi->ipimap, RDWRLOCK_IMAP); 23962306a36Sopenharmony_ci diUnmount(sbi->ipimap, 1); 24062306a36Sopenharmony_ci if ((rc = diMount(sbi->ipimap))) { 24162306a36Sopenharmony_ci IWRITE_UNLOCK(sbi->ipimap); 24262306a36Sopenharmony_ci jfs_err("jfs_mount_rw: diMount failed!"); 24362306a36Sopenharmony_ci return rc; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci IWRITE_UNLOCK(sbi->ipimap); 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci dbUnmount(sbi->ipbmap, 1); 24862306a36Sopenharmony_ci if ((rc = dbMount(sbi->ipbmap))) { 24962306a36Sopenharmony_ci jfs_err("jfs_mount_rw: dbMount failed!"); 25062306a36Sopenharmony_ci return rc; 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* 25562306a36Sopenharmony_ci * open/initialize log 25662306a36Sopenharmony_ci */ 25762306a36Sopenharmony_ci if ((rc = lmLogOpen(sb))) 25862306a36Sopenharmony_ci return rc; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci /* 26162306a36Sopenharmony_ci * update file system superblock; 26262306a36Sopenharmony_ci */ 26362306a36Sopenharmony_ci if ((rc = updateSuper(sb, FM_MOUNT))) { 26462306a36Sopenharmony_ci jfs_err("jfs_mount: updateSuper failed w/rc = %d", rc); 26562306a36Sopenharmony_ci lmLogClose(sb); 26662306a36Sopenharmony_ci return rc; 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci /* 27062306a36Sopenharmony_ci * write MOUNT log record of the file system 27162306a36Sopenharmony_ci */ 27262306a36Sopenharmony_ci logMOUNT(sb); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci return rc; 27562306a36Sopenharmony_ci} 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci/* 27862306a36Sopenharmony_ci * chkSuper() 27962306a36Sopenharmony_ci * 28062306a36Sopenharmony_ci * validate the superblock of the file system to be mounted and 28162306a36Sopenharmony_ci * get the file system parameters. 28262306a36Sopenharmony_ci * 28362306a36Sopenharmony_ci * returns 28462306a36Sopenharmony_ci * 0 with fragsize set if check successful 28562306a36Sopenharmony_ci * error code if not successful 28662306a36Sopenharmony_ci */ 28762306a36Sopenharmony_cistatic int chkSuper(struct super_block *sb) 28862306a36Sopenharmony_ci{ 28962306a36Sopenharmony_ci int rc = 0; 29062306a36Sopenharmony_ci struct jfs_sb_info *sbi = JFS_SBI(sb); 29162306a36Sopenharmony_ci struct jfs_superblock *j_sb; 29262306a36Sopenharmony_ci struct buffer_head *bh; 29362306a36Sopenharmony_ci int AIM_bytesize, AIT_bytesize; 29462306a36Sopenharmony_ci int expected_AIM_bytesize, expected_AIT_bytesize; 29562306a36Sopenharmony_ci s64 AIM_byte_addr, AIT_byte_addr, fsckwsp_addr; 29662306a36Sopenharmony_ci s64 byte_addr_diff0, byte_addr_diff1; 29762306a36Sopenharmony_ci s32 bsize; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci if ((rc = readSuper(sb, &bh))) 30062306a36Sopenharmony_ci return rc; 30162306a36Sopenharmony_ci j_sb = (struct jfs_superblock *)bh->b_data; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci /* 30462306a36Sopenharmony_ci * validate superblock 30562306a36Sopenharmony_ci */ 30662306a36Sopenharmony_ci /* validate fs signature */ 30762306a36Sopenharmony_ci if (strncmp(j_sb->s_magic, JFS_MAGIC, 4) || 30862306a36Sopenharmony_ci le32_to_cpu(j_sb->s_version) > JFS_VERSION) { 30962306a36Sopenharmony_ci rc = -EINVAL; 31062306a36Sopenharmony_ci goto out; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci bsize = le32_to_cpu(j_sb->s_bsize); 31462306a36Sopenharmony_ci if (bsize != PSIZE) { 31562306a36Sopenharmony_ci jfs_err("Only 4K block size supported!"); 31662306a36Sopenharmony_ci rc = -EINVAL; 31762306a36Sopenharmony_ci goto out; 31862306a36Sopenharmony_ci } 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci jfs_info("superblock: flag:0x%08x state:0x%08x size:0x%Lx", 32162306a36Sopenharmony_ci le32_to_cpu(j_sb->s_flag), le32_to_cpu(j_sb->s_state), 32262306a36Sopenharmony_ci (unsigned long long) le64_to_cpu(j_sb->s_size)); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci /* validate the descriptors for Secondary AIM and AIT */ 32562306a36Sopenharmony_ci if ((j_sb->s_flag & cpu_to_le32(JFS_BAD_SAIT)) != 32662306a36Sopenharmony_ci cpu_to_le32(JFS_BAD_SAIT)) { 32762306a36Sopenharmony_ci expected_AIM_bytesize = 2 * PSIZE; 32862306a36Sopenharmony_ci AIM_bytesize = lengthPXD(&(j_sb->s_aim2)) * bsize; 32962306a36Sopenharmony_ci expected_AIT_bytesize = 4 * PSIZE; 33062306a36Sopenharmony_ci AIT_bytesize = lengthPXD(&(j_sb->s_ait2)) * bsize; 33162306a36Sopenharmony_ci AIM_byte_addr = addressPXD(&(j_sb->s_aim2)) * bsize; 33262306a36Sopenharmony_ci AIT_byte_addr = addressPXD(&(j_sb->s_ait2)) * bsize; 33362306a36Sopenharmony_ci byte_addr_diff0 = AIT_byte_addr - AIM_byte_addr; 33462306a36Sopenharmony_ci fsckwsp_addr = addressPXD(&(j_sb->s_fsckpxd)) * bsize; 33562306a36Sopenharmony_ci byte_addr_diff1 = fsckwsp_addr - AIT_byte_addr; 33662306a36Sopenharmony_ci if ((AIM_bytesize != expected_AIM_bytesize) || 33762306a36Sopenharmony_ci (AIT_bytesize != expected_AIT_bytesize) || 33862306a36Sopenharmony_ci (byte_addr_diff0 != AIM_bytesize) || 33962306a36Sopenharmony_ci (byte_addr_diff1 <= AIT_bytesize)) 34062306a36Sopenharmony_ci j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT); 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci if ((j_sb->s_flag & cpu_to_le32(JFS_GROUPCOMMIT)) != 34462306a36Sopenharmony_ci cpu_to_le32(JFS_GROUPCOMMIT)) 34562306a36Sopenharmony_ci j_sb->s_flag |= cpu_to_le32(JFS_GROUPCOMMIT); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci /* validate fs state */ 34862306a36Sopenharmony_ci if (j_sb->s_state != cpu_to_le32(FM_CLEAN) && 34962306a36Sopenharmony_ci !sb_rdonly(sb)) { 35062306a36Sopenharmony_ci jfs_err("jfs_mount: Mount Failure: File System Dirty."); 35162306a36Sopenharmony_ci rc = -EINVAL; 35262306a36Sopenharmony_ci goto out; 35362306a36Sopenharmony_ci } 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci sbi->state = le32_to_cpu(j_sb->s_state); 35662306a36Sopenharmony_ci sbi->mntflag = le32_to_cpu(j_sb->s_flag); 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci /* 35962306a36Sopenharmony_ci * JFS always does I/O by 4K pages. Don't tell the buffer cache 36062306a36Sopenharmony_ci * that we use anything else (leave s_blocksize alone). 36162306a36Sopenharmony_ci */ 36262306a36Sopenharmony_ci sbi->bsize = bsize; 36362306a36Sopenharmony_ci sbi->l2bsize = le16_to_cpu(j_sb->s_l2bsize); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci /* check some fields for possible corruption */ 36662306a36Sopenharmony_ci if (sbi->l2bsize != ilog2((u32)bsize) || 36762306a36Sopenharmony_ci j_sb->pad != 0 || 36862306a36Sopenharmony_ci le32_to_cpu(j_sb->s_state) > FM_STATE_MAX) { 36962306a36Sopenharmony_ci rc = -EINVAL; 37062306a36Sopenharmony_ci jfs_err("jfs_mount: Mount Failure: superblock is corrupt!"); 37162306a36Sopenharmony_ci goto out; 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci /* 37562306a36Sopenharmony_ci * For now, ignore s_pbsize, l2bfactor. All I/O going through buffer 37662306a36Sopenharmony_ci * cache. 37762306a36Sopenharmony_ci */ 37862306a36Sopenharmony_ci sbi->nbperpage = PSIZE >> sbi->l2bsize; 37962306a36Sopenharmony_ci sbi->l2nbperpage = L2PSIZE - sbi->l2bsize; 38062306a36Sopenharmony_ci sbi->l2niperblk = sbi->l2bsize - L2DISIZE; 38162306a36Sopenharmony_ci if (sbi->mntflag & JFS_INLINELOG) 38262306a36Sopenharmony_ci sbi->logpxd = j_sb->s_logpxd; 38362306a36Sopenharmony_ci else { 38462306a36Sopenharmony_ci sbi->logdev = new_decode_dev(le32_to_cpu(j_sb->s_logdev)); 38562306a36Sopenharmony_ci uuid_copy(&sbi->uuid, &j_sb->s_uuid); 38662306a36Sopenharmony_ci uuid_copy(&sbi->loguuid, &j_sb->s_loguuid); 38762306a36Sopenharmony_ci } 38862306a36Sopenharmony_ci sbi->fsckpxd = j_sb->s_fsckpxd; 38962306a36Sopenharmony_ci sbi->ait2 = j_sb->s_ait2; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci out: 39262306a36Sopenharmony_ci brelse(bh); 39362306a36Sopenharmony_ci return rc; 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci/* 39862306a36Sopenharmony_ci * updateSuper() 39962306a36Sopenharmony_ci * 40062306a36Sopenharmony_ci * update synchronously superblock if it is mounted read-write. 40162306a36Sopenharmony_ci */ 40262306a36Sopenharmony_ciint updateSuper(struct super_block *sb, uint state) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci struct jfs_superblock *j_sb; 40562306a36Sopenharmony_ci struct jfs_sb_info *sbi = JFS_SBI(sb); 40662306a36Sopenharmony_ci struct buffer_head *bh; 40762306a36Sopenharmony_ci int rc; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci if (sbi->flag & JFS_NOINTEGRITY) { 41062306a36Sopenharmony_ci if (state == FM_DIRTY) { 41162306a36Sopenharmony_ci sbi->p_state = state; 41262306a36Sopenharmony_ci return 0; 41362306a36Sopenharmony_ci } else if (state == FM_MOUNT) { 41462306a36Sopenharmony_ci sbi->p_state = sbi->state; 41562306a36Sopenharmony_ci state = FM_DIRTY; 41662306a36Sopenharmony_ci } else if (state == FM_CLEAN) { 41762306a36Sopenharmony_ci state = sbi->p_state; 41862306a36Sopenharmony_ci } else 41962306a36Sopenharmony_ci jfs_err("updateSuper: bad state"); 42062306a36Sopenharmony_ci } else if (sbi->state == FM_DIRTY) 42162306a36Sopenharmony_ci return 0; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci if ((rc = readSuper(sb, &bh))) 42462306a36Sopenharmony_ci return rc; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci j_sb = (struct jfs_superblock *)bh->b_data; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci j_sb->s_state = cpu_to_le32(state); 42962306a36Sopenharmony_ci sbi->state = state; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci if (state == FM_MOUNT) { 43262306a36Sopenharmony_ci /* record log's dev_t and mount serial number */ 43362306a36Sopenharmony_ci j_sb->s_logdev = cpu_to_le32(new_encode_dev(sbi->log->bdev->bd_dev)); 43462306a36Sopenharmony_ci j_sb->s_logserial = cpu_to_le32(sbi->log->serial); 43562306a36Sopenharmony_ci } else if (state == FM_CLEAN) { 43662306a36Sopenharmony_ci /* 43762306a36Sopenharmony_ci * If this volume is shared with OS/2, OS/2 will need to 43862306a36Sopenharmony_ci * recalculate DASD usage, since we don't deal with it. 43962306a36Sopenharmony_ci */ 44062306a36Sopenharmony_ci if (j_sb->s_flag & cpu_to_le32(JFS_DASD_ENABLED)) 44162306a36Sopenharmony_ci j_sb->s_flag |= cpu_to_le32(JFS_DASD_PRIME); 44262306a36Sopenharmony_ci } 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci mark_buffer_dirty(bh); 44562306a36Sopenharmony_ci sync_dirty_buffer(bh); 44662306a36Sopenharmony_ci brelse(bh); 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci return 0; 44962306a36Sopenharmony_ci} 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci/* 45362306a36Sopenharmony_ci * readSuper() 45462306a36Sopenharmony_ci * 45562306a36Sopenharmony_ci * read superblock by raw sector address 45662306a36Sopenharmony_ci */ 45762306a36Sopenharmony_ciint readSuper(struct super_block *sb, struct buffer_head **bpp) 45862306a36Sopenharmony_ci{ 45962306a36Sopenharmony_ci /* read in primary superblock */ 46062306a36Sopenharmony_ci *bpp = sb_bread(sb, SUPER1_OFF >> sb->s_blocksize_bits); 46162306a36Sopenharmony_ci if (*bpp) 46262306a36Sopenharmony_ci return 0; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci /* read in secondary/replicated superblock */ 46562306a36Sopenharmony_ci *bpp = sb_bread(sb, SUPER2_OFF >> sb->s_blocksize_bits); 46662306a36Sopenharmony_ci if (*bpp) 46762306a36Sopenharmony_ci return 0; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci return -EIO; 47062306a36Sopenharmony_ci} 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci/* 47462306a36Sopenharmony_ci * logMOUNT() 47562306a36Sopenharmony_ci * 47662306a36Sopenharmony_ci * function: write a MOUNT log record for file system. 47762306a36Sopenharmony_ci * 47862306a36Sopenharmony_ci * MOUNT record keeps logredo() from processing log records 47962306a36Sopenharmony_ci * for this file system past this point in log. 48062306a36Sopenharmony_ci * it is harmless if mount fails. 48162306a36Sopenharmony_ci * 48262306a36Sopenharmony_ci * note: MOUNT record is at aggregate level, not at fileset level, 48362306a36Sopenharmony_ci * since log records of previous mounts of a fileset 48462306a36Sopenharmony_ci * (e.g., AFTER record of extent allocation) have to be processed 48562306a36Sopenharmony_ci * to update block allocation map at aggregate level. 48662306a36Sopenharmony_ci */ 48762306a36Sopenharmony_cistatic int logMOUNT(struct super_block *sb) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci struct jfs_log *log = JFS_SBI(sb)->log; 49062306a36Sopenharmony_ci struct lrd lrd; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci lrd.logtid = 0; 49362306a36Sopenharmony_ci lrd.backchain = 0; 49462306a36Sopenharmony_ci lrd.type = cpu_to_le16(LOG_MOUNT); 49562306a36Sopenharmony_ci lrd.length = 0; 49662306a36Sopenharmony_ci lrd.aggregate = cpu_to_le32(new_encode_dev(sb->s_bdev->bd_dev)); 49762306a36Sopenharmony_ci lmLog(log, NULL, &lrd, NULL); 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci return 0; 50062306a36Sopenharmony_ci} 501