cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

jfs_mount.c (12578B)


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