linux/fs/jfs/jfs_mount.c
<<
>>
Prefs
   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 errout20;
  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 errout20;
  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 errout21;
 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 errout22;
 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 errout22;
 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 errout35;
 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 errout35;
 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 errout40;
 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 errout41;
 182        }
 183
 184        goto out;
 185
 186        /*
 187         *      unwind on error
 188         */
 189      errout41:         /* close fileset inode allocation map inode */
 190        diFreeSpecial(ipimap);
 191
 192      errout40:         /* fileset closed */
 193
 194        /* close secondary aggregate inode allocation map */
 195        if (ipaimap2) {
 196                diUnmount(ipaimap2, 1);
 197                diFreeSpecial(ipaimap2);
 198        }
 199
 200      errout35:
 201
 202        /* close aggregate block allocation map */
 203        dbUnmount(ipbmap, 1);
 204        diFreeSpecial(ipbmap);
 205
 206      errout22:         /* close aggregate inode allocation map */
 207
 208        diUnmount(ipaimap, 1);
 209
 210      errout21:         /* close aggregate inodes */
 211        diFreeSpecial(ipaimap);
 212      errout20:         /* aggregate closed */
 213
 214      out:
 215
 216        if (rc)
 217                jfs_err("Mount JFS Failure: %d", rc);
 218
 219        return rc;
 220}
 221
 222/*
 223 * NAME:        jfs_mount_rw(sb, remount)
 224 *
 225 * FUNCTION:    Completes read-write mount, or remounts read-only volume
 226 *              as read-write
 227 */
 228int jfs_mount_rw(struct super_block *sb, int remount)
 229{
 230        struct jfs_sb_info *sbi = JFS_SBI(sb);
 231        int rc;
 232
 233        /*
 234         * If we are re-mounting a previously read-only volume, we want to
 235         * re-read the inode and block maps, since fsck.jfs may have updated
 236         * them.
 237         */
 238        if (remount) {
 239                if (chkSuper(sb) || (sbi->state != FM_CLEAN))
 240                        return -EINVAL;
 241
 242                truncate_inode_pages(sbi->ipimap->i_mapping, 0);
 243                truncate_inode_pages(sbi->ipbmap->i_mapping, 0);
 244                diUnmount(sbi->ipimap, 1);
 245                if ((rc = diMount(sbi->ipimap))) {
 246                        jfs_err("jfs_mount_rw: diMount failed!");
 247                        return rc;
 248                }
 249
 250                dbUnmount(sbi->ipbmap, 1);
 251                if ((rc = dbMount(sbi->ipbmap))) {
 252                        jfs_err("jfs_mount_rw: dbMount failed!");
 253                        return rc;
 254                }
 255        }
 256
 257        /*
 258         * open/initialize log
 259         */
 260        if ((rc = lmLogOpen(sb)))
 261                return rc;
 262
 263        /*
 264         * update file system superblock;
 265         */
 266        if ((rc = updateSuper(sb, FM_MOUNT))) {
 267                jfs_err("jfs_mount: updateSuper failed w/rc = %d", rc);
 268                lmLogClose(sb);
 269                return rc;
 270        }
 271
 272        /*
 273         * write MOUNT log record of the file system
 274         */
 275        logMOUNT(sb);
 276
 277        return rc;
 278}
 279
 280/*
 281 *      chkSuper()
 282 *
 283 * validate the superblock of the file system to be mounted and
 284 * get the file system parameters.
 285 *
 286 * returns
 287 *      0 with fragsize set if check successful
 288 *      error code if not successful
 289 */
 290static int chkSuper(struct super_block *sb)
 291{
 292        int rc = 0;
 293        struct jfs_sb_info *sbi = JFS_SBI(sb);
 294        struct jfs_superblock *j_sb;
 295        struct buffer_head *bh;
 296        int AIM_bytesize, AIT_bytesize;
 297        int expected_AIM_bytesize, expected_AIT_bytesize;
 298        s64 AIM_byte_addr, AIT_byte_addr, fsckwsp_addr;
 299        s64 byte_addr_diff0, byte_addr_diff1;
 300        s32 bsize;
 301
 302        if ((rc = readSuper(sb, &bh)))
 303                return rc;
 304        j_sb = (struct jfs_superblock *)bh->b_data;
 305
 306        /*
 307         * validate superblock
 308         */
 309        /* validate fs signature */
 310        if (strncmp(j_sb->s_magic, JFS_MAGIC, 4) ||
 311            le32_to_cpu(j_sb->s_version) > JFS_VERSION) {
 312                rc = -EINVAL;
 313                goto out;
 314        }
 315
 316        bsize = le32_to_cpu(j_sb->s_bsize);
 317#ifdef _JFS_4K
 318        if (bsize != PSIZE) {
 319                jfs_err("Currently only 4K block size supported!");
 320                rc = -EINVAL;
 321                goto out;
 322        }
 323#endif                          /* _JFS_4K */
 324
 325        jfs_info("superblock: flag:0x%08x state:0x%08x size:0x%Lx",
 326                 le32_to_cpu(j_sb->s_flag), le32_to_cpu(j_sb->s_state),
 327                 (unsigned long long) le64_to_cpu(j_sb->s_size));
 328
 329        /* validate the descriptors for Secondary AIM and AIT */
 330        if ((j_sb->s_flag & cpu_to_le32(JFS_BAD_SAIT)) !=
 331            cpu_to_le32(JFS_BAD_SAIT)) {
 332                expected_AIM_bytesize = 2 * PSIZE;
 333                AIM_bytesize = lengthPXD(&(j_sb->s_aim2)) * bsize;
 334                expected_AIT_bytesize = 4 * PSIZE;
 335                AIT_bytesize = lengthPXD(&(j_sb->s_ait2)) * bsize;
 336                AIM_byte_addr = addressPXD(&(j_sb->s_aim2)) * bsize;
 337                AIT_byte_addr = addressPXD(&(j_sb->s_ait2)) * bsize;
 338                byte_addr_diff0 = AIT_byte_addr - AIM_byte_addr;
 339                fsckwsp_addr = addressPXD(&(j_sb->s_fsckpxd)) * bsize;
 340                byte_addr_diff1 = fsckwsp_addr - AIT_byte_addr;
 341                if ((AIM_bytesize != expected_AIM_bytesize) ||
 342                    (AIT_bytesize != expected_AIT_bytesize) ||
 343                    (byte_addr_diff0 != AIM_bytesize) ||
 344                    (byte_addr_diff1 <= AIT_bytesize))
 345                        j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT);
 346        }
 347
 348        if ((j_sb->s_flag & cpu_to_le32(JFS_GROUPCOMMIT)) !=
 349            cpu_to_le32(JFS_GROUPCOMMIT))
 350                j_sb->s_flag |= cpu_to_le32(JFS_GROUPCOMMIT);
 351
 352        /* validate fs state */
 353        if (j_sb->s_state != cpu_to_le32(FM_CLEAN) &&
 354            !sb_rdonly(sb)) {
 355                jfs_err("jfs_mount: Mount Failure: File System Dirty.");
 356                rc = -EINVAL;
 357                goto out;
 358        }
 359
 360        sbi->state = le32_to_cpu(j_sb->s_state);
 361        sbi->mntflag = le32_to_cpu(j_sb->s_flag);
 362
 363        /*
 364         * JFS always does I/O by 4K pages.  Don't tell the buffer cache
 365         * that we use anything else (leave s_blocksize alone).
 366         */
 367        sbi->bsize = bsize;
 368        sbi->l2bsize = le16_to_cpu(j_sb->s_l2bsize);
 369
 370        /* check some fields for possible corruption */
 371        if (sbi->l2bsize != ilog2((u32)bsize) ||
 372            j_sb->pad != 0 ||
 373            le32_to_cpu(j_sb->s_state) > FM_STATE_MAX) {
 374                rc = -EINVAL;
 375                jfs_err("jfs_mount: Mount Failure: superblock is corrupt!");
 376                goto out;
 377        }
 378
 379        /*
 380         * For now, ignore s_pbsize, l2bfactor.  All I/O going through buffer
 381         * cache.
 382         */
 383        sbi->nbperpage = PSIZE >> sbi->l2bsize;
 384        sbi->l2nbperpage = L2PSIZE - sbi->l2bsize;
 385        sbi->l2niperblk = sbi->l2bsize - L2DISIZE;
 386        if (sbi->mntflag & JFS_INLINELOG)
 387                sbi->logpxd = j_sb->s_logpxd;
 388        else {
 389                sbi->logdev = new_decode_dev(le32_to_cpu(j_sb->s_logdev));
 390                uuid_copy(&sbi->uuid, &j_sb->s_uuid);
 391                uuid_copy(&sbi->loguuid, &j_sb->s_loguuid);
 392        }
 393        sbi->fsckpxd = j_sb->s_fsckpxd;
 394        sbi->ait2 = j_sb->s_ait2;
 395
 396      out:
 397        brelse(bh);
 398        return rc;
 399}
 400
 401
 402/*
 403 *      updateSuper()
 404 *
 405 * update synchronously superblock if it is mounted read-write.
 406 */
 407int updateSuper(struct super_block *sb, uint state)
 408{
 409        struct jfs_superblock *j_sb;
 410        struct jfs_sb_info *sbi = JFS_SBI(sb);
 411        struct buffer_head *bh;
 412        int rc;
 413
 414        if (sbi->flag & JFS_NOINTEGRITY) {
 415                if (state == FM_DIRTY) {
 416                        sbi->p_state = state;
 417                        return 0;
 418                } else if (state == FM_MOUNT) {
 419                        sbi->p_state = sbi->state;
 420                        state = FM_DIRTY;
 421                } else if (state == FM_CLEAN) {
 422                        state = sbi->p_state;
 423                } else
 424                        jfs_err("updateSuper: bad state");
 425        } else if (sbi->state == FM_DIRTY)
 426                return 0;
 427
 428        if ((rc = readSuper(sb, &bh)))
 429                return rc;
 430
 431        j_sb = (struct jfs_superblock *)bh->b_data;
 432
 433        j_sb->s_state = cpu_to_le32(state);
 434        sbi->state = state;
 435
 436        if (state == FM_MOUNT) {
 437                /* record log's dev_t and mount serial number */
 438                j_sb->s_logdev = cpu_to_le32(new_encode_dev(sbi->log->bdev->bd_dev));
 439                j_sb->s_logserial = cpu_to_le32(sbi->log->serial);
 440        } else if (state == FM_CLEAN) {
 441                /*
 442                 * If this volume is shared with OS/2, OS/2 will need to
 443                 * recalculate DASD usage, since we don't deal with it.
 444                 */
 445                if (j_sb->s_flag & cpu_to_le32(JFS_DASD_ENABLED))
 446                        j_sb->s_flag |= cpu_to_le32(JFS_DASD_PRIME);
 447        }
 448
 449        mark_buffer_dirty(bh);
 450        sync_dirty_buffer(bh);
 451        brelse(bh);
 452
 453        return 0;
 454}
 455
 456
 457/*
 458 *      readSuper()
 459 *
 460 * read superblock by raw sector address
 461 */
 462int readSuper(struct super_block *sb, struct buffer_head **bpp)
 463{
 464        /* read in primary superblock */
 465        *bpp = sb_bread(sb, SUPER1_OFF >> sb->s_blocksize_bits);
 466        if (*bpp)
 467                return 0;
 468
 469        /* read in secondary/replicated superblock */
 470        *bpp = sb_bread(sb, SUPER2_OFF >> sb->s_blocksize_bits);
 471        if (*bpp)
 472                return 0;
 473
 474        return -EIO;
 475}
 476
 477
 478/*
 479 *      logMOUNT()
 480 *
 481 * function: write a MOUNT log record for file system.
 482 *
 483 * MOUNT record keeps logredo() from processing log records
 484 * for this file system past this point in log.
 485 * it is harmless if mount fails.
 486 *
 487 * note: MOUNT record is at aggregate level, not at fileset level,
 488 * since log records of previous mounts of a fileset
 489 * (e.g., AFTER record of extent allocation) have to be processed
 490 * to update block allocation map at aggregate level.
 491 */
 492static int logMOUNT(struct super_block *sb)
 493{
 494        struct jfs_log *log = JFS_SBI(sb)->log;
 495        struct lrd lrd;
 496
 497        lrd.logtid = 0;
 498        lrd.backchain = 0;
 499        lrd.type = cpu_to_le16(LOG_MOUNT);
 500        lrd.length = 0;
 501        lrd.aggregate = cpu_to_le32(new_encode_dev(sb->s_bdev->bd_dev));
 502        lmLog(log, NULL, &lrd, NULL);
 503
 504        return 0;
 505}
 506