Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *   Copyright (C) International Business Machines Corp., 2000-2004
0004  */
0005 
0006 /*
0007  * Module: jfs_mount.c
0008  *
0009  * note: file system in transition to aggregate/fileset:
0010  *
0011  * file system mount is interpreted as the mount of aggregate,
0012  * if not already mounted, and mount of the single/only fileset in
0013  * the aggregate;
0014  *
0015  * a file system/aggregate is represented by an internal inode
0016  * (aka mount inode) initialized with aggregate superblock;
0017  * each vfs represents a fileset, and points to its "fileset inode
0018  * allocation map inode" (aka fileset inode):
0019  * (an aggregate itself is structured recursively as a filset:
0020  * an internal vfs is constructed and points to its "fileset inode
0021  * allocation map inode" (aka aggregate inode) where each inode
0022  * represents a fileset inode) so that inode number is mapped to
0023  * on-disk inode in uniform way at both aggregate and fileset level;
0024  *
0025  * each vnode/inode of a fileset is linked to its vfs (to facilitate
0026  * per fileset inode operations, e.g., unmount of a fileset, etc.);
0027  * each inode points to the mount inode (to facilitate access to
0028  * per aggregate information, e.g., block size, etc.) as well as
0029  * its file set inode.
0030  *
0031  *   aggregate
0032  *   ipmnt
0033  *   mntvfs -> fileset ipimap+ -> aggregate ipbmap -> aggregate ipaimap;
0034  *             fileset vfs     -> vp(1) <-> ... <-> vp(n) <->vproot;
0035  */
0036 
0037 #include <linux/fs.h>
0038 #include <linux/buffer_head.h>
0039 #include <linux/blkdev.h>
0040 #include <linux/log2.h>
0041 
0042 #include "jfs_incore.h"
0043 #include "jfs_filsys.h"
0044 #include "jfs_superblock.h"
0045 #include "jfs_dmap.h"
0046 #include "jfs_imap.h"
0047 #include "jfs_metapage.h"
0048 #include "jfs_debug.h"
0049 
0050 
0051 /*
0052  * forward references
0053  */
0054 static int chkSuper(struct super_block *);
0055 static int logMOUNT(struct super_block *sb);
0056 
0057 /*
0058  * NAME:    jfs_mount(sb)
0059  *
0060  * FUNCTION:    vfs_mount()
0061  *
0062  * PARAMETER:   sb  - super block
0063  *
0064  * RETURN:  -EBUSY  - device already mounted or open for write
0065  *      -EBUSY  - cvrdvp already mounted;
0066  *      -EBUSY  - mount table full
0067  *      -ENOTDIR- cvrdvp not directory on a device mount
0068  *      -ENXIO  - device open failure
0069  */
0070 int jfs_mount(struct super_block *sb)
0071 {
0072     int rc = 0;     /* Return code */
0073     struct jfs_sb_info *sbi = JFS_SBI(sb);
0074     struct inode *ipaimap = NULL;
0075     struct inode *ipaimap2 = NULL;
0076     struct inode *ipimap = NULL;
0077     struct inode *ipbmap = NULL;
0078 
0079     /*
0080      * read/validate superblock
0081      * (initialize mount inode from the superblock)
0082      */
0083     if ((rc = chkSuper(sb))) {
0084         goto out;
0085     }
0086 
0087     ipaimap = diReadSpecial(sb, AGGREGATE_I, 0);
0088     if (ipaimap == NULL) {
0089         jfs_err("jfs_mount: Failed to read AGGREGATE_I");
0090         rc = -EIO;
0091         goto out;
0092     }
0093     sbi->ipaimap = ipaimap;
0094 
0095     jfs_info("jfs_mount: ipaimap:0x%p", ipaimap);
0096 
0097     /*
0098      * initialize aggregate inode allocation map
0099      */
0100     if ((rc = diMount(ipaimap))) {
0101         jfs_err("jfs_mount: diMount(ipaimap) failed w/rc = %d", rc);
0102         goto err_ipaimap;
0103     }
0104 
0105     /*
0106      * open aggregate block allocation map
0107      */
0108     ipbmap = diReadSpecial(sb, BMAP_I, 0);
0109     if (ipbmap == NULL) {
0110         rc = -EIO;
0111         goto err_umount_ipaimap;
0112     }
0113 
0114     jfs_info("jfs_mount: ipbmap:0x%p", ipbmap);
0115 
0116     sbi->ipbmap = ipbmap;
0117 
0118     /*
0119      * initialize aggregate block allocation map
0120      */
0121     if ((rc = dbMount(ipbmap))) {
0122         jfs_err("jfs_mount: dbMount failed w/rc = %d", rc);
0123         goto err_ipbmap;
0124     }
0125 
0126     /*
0127      * open the secondary aggregate inode allocation map
0128      *
0129      * This is a duplicate of the aggregate inode allocation map.
0130      *
0131      * hand craft a vfs in the same fashion as we did to read ipaimap.
0132      * By adding INOSPEREXT (32) to the inode number, we are telling
0133      * diReadSpecial that we are reading from the secondary aggregate
0134      * inode table.  This also creates a unique entry in the inode hash
0135      * table.
0136      */
0137     if ((sbi->mntflag & JFS_BAD_SAIT) == 0) {
0138         ipaimap2 = diReadSpecial(sb, AGGREGATE_I, 1);
0139         if (!ipaimap2) {
0140             jfs_err("jfs_mount: Failed to read AGGREGATE_I");
0141             rc = -EIO;
0142             goto err_umount_ipbmap;
0143         }
0144         sbi->ipaimap2 = ipaimap2;
0145 
0146         jfs_info("jfs_mount: ipaimap2:0x%p", ipaimap2);
0147 
0148         /*
0149          * initialize secondary aggregate inode allocation map
0150          */
0151         if ((rc = diMount(ipaimap2))) {
0152             jfs_err("jfs_mount: diMount(ipaimap2) failed, rc = %d",
0153                 rc);
0154             goto err_ipaimap2;
0155         }
0156     } else
0157         /* Secondary aggregate inode table is not valid */
0158         sbi->ipaimap2 = NULL;
0159 
0160     /*
0161      *  mount (the only/single) fileset
0162      */
0163     /*
0164      * open fileset inode allocation map (aka fileset inode)
0165      */
0166     ipimap = diReadSpecial(sb, FILESYSTEM_I, 0);
0167     if (ipimap == NULL) {
0168         jfs_err("jfs_mount: Failed to read FILESYSTEM_I");
0169         /* open fileset secondary inode allocation map */
0170         rc = -EIO;
0171         goto err_umount_ipaimap2;
0172     }
0173     jfs_info("jfs_mount: ipimap:0x%p", ipimap);
0174 
0175     /* map further access of per fileset inodes by the fileset inode */
0176     sbi->ipimap = ipimap;
0177 
0178     /* initialize fileset inode allocation map */
0179     if ((rc = diMount(ipimap))) {
0180         jfs_err("jfs_mount: diMount failed w/rc = %d", rc);
0181         goto err_ipimap;
0182     }
0183 
0184     return rc;
0185 
0186     /*
0187      *  unwind on error
0188      */
0189 err_ipimap:
0190     /* close fileset inode allocation map inode */
0191     diFreeSpecial(ipimap);
0192 err_umount_ipaimap2:
0193     /* close secondary aggregate inode allocation map */
0194     if (ipaimap2)
0195         diUnmount(ipaimap2, 1);
0196 err_ipaimap2:
0197     /* close aggregate inodes */
0198     if (ipaimap2)
0199         diFreeSpecial(ipaimap2);
0200 err_umount_ipbmap:  /* close aggregate block allocation map */
0201     dbUnmount(ipbmap, 1);
0202 err_ipbmap:     /* close aggregate inodes */
0203     diFreeSpecial(ipbmap);
0204 err_umount_ipaimap: /* close aggregate inode allocation map */
0205     diUnmount(ipaimap, 1);
0206 err_ipaimap:        /* close aggregate inodes */
0207     diFreeSpecial(ipaimap);
0208 out:
0209     if (rc)
0210         jfs_err("Mount JFS Failure: %d", rc);
0211 
0212     return rc;
0213 }
0214 
0215 /*
0216  * NAME:    jfs_mount_rw(sb, remount)
0217  *
0218  * FUNCTION:    Completes read-write mount, or remounts read-only volume
0219  *      as read-write
0220  */
0221 int jfs_mount_rw(struct super_block *sb, int remount)
0222 {
0223     struct jfs_sb_info *sbi = JFS_SBI(sb);
0224     int rc;
0225 
0226     /*
0227      * If we are re-mounting a previously read-only volume, we want to
0228      * re-read the inode and block maps, since fsck.jfs may have updated
0229      * them.
0230      */
0231     if (remount) {
0232         if (chkSuper(sb) || (sbi->state != FM_CLEAN))
0233             return -EINVAL;
0234 
0235         truncate_inode_pages(sbi->ipimap->i_mapping, 0);
0236         truncate_inode_pages(sbi->ipbmap->i_mapping, 0);
0237         diUnmount(sbi->ipimap, 1);
0238         if ((rc = diMount(sbi->ipimap))) {
0239             jfs_err("jfs_mount_rw: diMount failed!");
0240             return rc;
0241         }
0242 
0243         dbUnmount(sbi->ipbmap, 1);
0244         if ((rc = dbMount(sbi->ipbmap))) {
0245             jfs_err("jfs_mount_rw: dbMount failed!");
0246             return rc;
0247         }
0248     }
0249 
0250     /*
0251      * open/initialize log
0252      */
0253     if ((rc = lmLogOpen(sb)))
0254         return rc;
0255 
0256     /*
0257      * update file system superblock;
0258      */
0259     if ((rc = updateSuper(sb, FM_MOUNT))) {
0260         jfs_err("jfs_mount: updateSuper failed w/rc = %d", rc);
0261         lmLogClose(sb);
0262         return rc;
0263     }
0264 
0265     /*
0266      * write MOUNT log record of the file system
0267      */
0268     logMOUNT(sb);
0269 
0270     return rc;
0271 }
0272 
0273 /*
0274  *  chkSuper()
0275  *
0276  * validate the superblock of the file system to be mounted and
0277  * get the file system parameters.
0278  *
0279  * returns
0280  *  0 with fragsize set if check successful
0281  *  error code if not successful
0282  */
0283 static int chkSuper(struct super_block *sb)
0284 {
0285     int rc = 0;
0286     struct jfs_sb_info *sbi = JFS_SBI(sb);
0287     struct jfs_superblock *j_sb;
0288     struct buffer_head *bh;
0289     int AIM_bytesize, AIT_bytesize;
0290     int expected_AIM_bytesize, expected_AIT_bytesize;
0291     s64 AIM_byte_addr, AIT_byte_addr, fsckwsp_addr;
0292     s64 byte_addr_diff0, byte_addr_diff1;
0293     s32 bsize;
0294 
0295     if ((rc = readSuper(sb, &bh)))
0296         return rc;
0297     j_sb = (struct jfs_superblock *)bh->b_data;
0298 
0299     /*
0300      * validate superblock
0301      */
0302     /* validate fs signature */
0303     if (strncmp(j_sb->s_magic, JFS_MAGIC, 4) ||
0304         le32_to_cpu(j_sb->s_version) > JFS_VERSION) {
0305         rc = -EINVAL;
0306         goto out;
0307     }
0308 
0309     bsize = le32_to_cpu(j_sb->s_bsize);
0310     if (bsize != PSIZE) {
0311         jfs_err("Only 4K block size supported!");
0312         rc = -EINVAL;
0313         goto out;
0314     }
0315 
0316     jfs_info("superblock: flag:0x%08x state:0x%08x size:0x%Lx",
0317          le32_to_cpu(j_sb->s_flag), le32_to_cpu(j_sb->s_state),
0318          (unsigned long long) le64_to_cpu(j_sb->s_size));
0319 
0320     /* validate the descriptors for Secondary AIM and AIT */
0321     if ((j_sb->s_flag & cpu_to_le32(JFS_BAD_SAIT)) !=
0322         cpu_to_le32(JFS_BAD_SAIT)) {
0323         expected_AIM_bytesize = 2 * PSIZE;
0324         AIM_bytesize = lengthPXD(&(j_sb->s_aim2)) * bsize;
0325         expected_AIT_bytesize = 4 * PSIZE;
0326         AIT_bytesize = lengthPXD(&(j_sb->s_ait2)) * bsize;
0327         AIM_byte_addr = addressPXD(&(j_sb->s_aim2)) * bsize;
0328         AIT_byte_addr = addressPXD(&(j_sb->s_ait2)) * bsize;
0329         byte_addr_diff0 = AIT_byte_addr - AIM_byte_addr;
0330         fsckwsp_addr = addressPXD(&(j_sb->s_fsckpxd)) * bsize;
0331         byte_addr_diff1 = fsckwsp_addr - AIT_byte_addr;
0332         if ((AIM_bytesize != expected_AIM_bytesize) ||
0333             (AIT_bytesize != expected_AIT_bytesize) ||
0334             (byte_addr_diff0 != AIM_bytesize) ||
0335             (byte_addr_diff1 <= AIT_bytesize))
0336             j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT);
0337     }
0338 
0339     if ((j_sb->s_flag & cpu_to_le32(JFS_GROUPCOMMIT)) !=
0340         cpu_to_le32(JFS_GROUPCOMMIT))
0341         j_sb->s_flag |= cpu_to_le32(JFS_GROUPCOMMIT);
0342 
0343     /* validate fs state */
0344     if (j_sb->s_state != cpu_to_le32(FM_CLEAN) &&
0345         !sb_rdonly(sb)) {
0346         jfs_err("jfs_mount: Mount Failure: File System Dirty.");
0347         rc = -EINVAL;
0348         goto out;
0349     }
0350 
0351     sbi->state = le32_to_cpu(j_sb->s_state);
0352     sbi->mntflag = le32_to_cpu(j_sb->s_flag);
0353 
0354     /*
0355      * JFS always does I/O by 4K pages.  Don't tell the buffer cache
0356      * that we use anything else (leave s_blocksize alone).
0357      */
0358     sbi->bsize = bsize;
0359     sbi->l2bsize = le16_to_cpu(j_sb->s_l2bsize);
0360 
0361     /* check some fields for possible corruption */
0362     if (sbi->l2bsize != ilog2((u32)bsize) ||
0363         j_sb->pad != 0 ||
0364         le32_to_cpu(j_sb->s_state) > FM_STATE_MAX) {
0365         rc = -EINVAL;
0366         jfs_err("jfs_mount: Mount Failure: superblock is corrupt!");
0367         goto out;
0368     }
0369 
0370     /*
0371      * For now, ignore s_pbsize, l2bfactor.  All I/O going through buffer
0372      * cache.
0373      */
0374     sbi->nbperpage = PSIZE >> sbi->l2bsize;
0375     sbi->l2nbperpage = L2PSIZE - sbi->l2bsize;
0376     sbi->l2niperblk = sbi->l2bsize - L2DISIZE;
0377     if (sbi->mntflag & JFS_INLINELOG)
0378         sbi->logpxd = j_sb->s_logpxd;
0379     else {
0380         sbi->logdev = new_decode_dev(le32_to_cpu(j_sb->s_logdev));
0381         uuid_copy(&sbi->uuid, &j_sb->s_uuid);
0382         uuid_copy(&sbi->loguuid, &j_sb->s_loguuid);
0383     }
0384     sbi->fsckpxd = j_sb->s_fsckpxd;
0385     sbi->ait2 = j_sb->s_ait2;
0386 
0387       out:
0388     brelse(bh);
0389     return rc;
0390 }
0391 
0392 
0393 /*
0394  *  updateSuper()
0395  *
0396  * update synchronously superblock if it is mounted read-write.
0397  */
0398 int updateSuper(struct super_block *sb, uint state)
0399 {
0400     struct jfs_superblock *j_sb;
0401     struct jfs_sb_info *sbi = JFS_SBI(sb);
0402     struct buffer_head *bh;
0403     int rc;
0404 
0405     if (sbi->flag & JFS_NOINTEGRITY) {
0406         if (state == FM_DIRTY) {
0407             sbi->p_state = state;
0408             return 0;
0409         } else if (state == FM_MOUNT) {
0410             sbi->p_state = sbi->state;
0411             state = FM_DIRTY;
0412         } else if (state == FM_CLEAN) {
0413             state = sbi->p_state;
0414         } else
0415             jfs_err("updateSuper: bad state");
0416     } else if (sbi->state == FM_DIRTY)
0417         return 0;
0418 
0419     if ((rc = readSuper(sb, &bh)))
0420         return rc;
0421 
0422     j_sb = (struct jfs_superblock *)bh->b_data;
0423 
0424     j_sb->s_state = cpu_to_le32(state);
0425     sbi->state = state;
0426 
0427     if (state == FM_MOUNT) {
0428         /* record log's dev_t and mount serial number */
0429         j_sb->s_logdev = cpu_to_le32(new_encode_dev(sbi->log->bdev->bd_dev));
0430         j_sb->s_logserial = cpu_to_le32(sbi->log->serial);
0431     } else if (state == FM_CLEAN) {
0432         /*
0433          * If this volume is shared with OS/2, OS/2 will need to
0434          * recalculate DASD usage, since we don't deal with it.
0435          */
0436         if (j_sb->s_flag & cpu_to_le32(JFS_DASD_ENABLED))
0437             j_sb->s_flag |= cpu_to_le32(JFS_DASD_PRIME);
0438     }
0439 
0440     mark_buffer_dirty(bh);
0441     sync_dirty_buffer(bh);
0442     brelse(bh);
0443 
0444     return 0;
0445 }
0446 
0447 
0448 /*
0449  *  readSuper()
0450  *
0451  * read superblock by raw sector address
0452  */
0453 int readSuper(struct super_block *sb, struct buffer_head **bpp)
0454 {
0455     /* read in primary superblock */
0456     *bpp = sb_bread(sb, SUPER1_OFF >> sb->s_blocksize_bits);
0457     if (*bpp)
0458         return 0;
0459 
0460     /* read in secondary/replicated superblock */
0461     *bpp = sb_bread(sb, SUPER2_OFF >> sb->s_blocksize_bits);
0462     if (*bpp)
0463         return 0;
0464 
0465     return -EIO;
0466 }
0467 
0468 
0469 /*
0470  *  logMOUNT()
0471  *
0472  * function: write a MOUNT log record for file system.
0473  *
0474  * MOUNT record keeps logredo() from processing log records
0475  * for this file system past this point in log.
0476  * it is harmless if mount fails.
0477  *
0478  * note: MOUNT record is at aggregate level, not at fileset level,
0479  * since log records of previous mounts of a fileset
0480  * (e.g., AFTER record of extent allocation) have to be processed
0481  * to update block allocation map at aggregate level.
0482  */
0483 static int logMOUNT(struct super_block *sb)
0484 {
0485     struct jfs_log *log = JFS_SBI(sb)->log;
0486     struct lrd lrd;
0487 
0488     lrd.logtid = 0;
0489     lrd.backchain = 0;
0490     lrd.type = cpu_to_le16(LOG_MOUNT);
0491     lrd.length = 0;
0492     lrd.aggregate = cpu_to_le32(new_encode_dev(sb->s_bdev->bd_dev));
0493     lmLog(log, NULL, &lrd, NULL);
0494 
0495     return 0;
0496 }