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