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 */ 65 static int chkSuper(struct super_block *); 66 static 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 */ 81 int 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 */ 239 int 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 */ 301 static 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_rdonly(sb)) { 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 uuid_copy(&sbi->uuid, &j_sb->s_uuid); 393 uuid_copy(&sbi->loguuid, &j_sb->s_loguuid); 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 */ 409 int 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 */ 464 int 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 */ 494 static 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