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