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