| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 6 | *   the Free Software Foundation; either version 2 of the License, or | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7 | *   (at your option) any later version. | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 8 | * | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 15 | *   along with this program;  if not, write to the Free Software | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | * | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 24 | * file system mount is interpreted as the mount of aggregate, | 
|  | 25 | * if not already mounted, and mount of the single/only fileset in | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 26 | * the aggregate; | 
|  | 27 | * | 
|  | 28 | * a file system/aggregate is represented by an internal inode | 
|  | 29 | * (aka mount inode) initialized with aggregate superblock; | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 30 | * each vfs represents a fileset, and points to its "fileset inode | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 31 | * allocation map inode" (aka fileset inode): | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 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 | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | * | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 44 | *   aggregate | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | { | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 83 | int rc = 0;		/* Return code */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | /* | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 91 | * read/validate superblock | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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) { | 
| Paul Bolle | 426d310 | 2010-08-07 12:30:03 +0200 | [diff] [blame] | 100 | jfs_err("jfs_mount: Failed to read AGGREGATE_I"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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); | 
| Joe Perches | 09aaa74 | 2007-11-13 22:16:08 -0600 | [diff] [blame] | 150 | if (!ipaimap2) { | 
| Paul Bolle | 426d310 | 2010-08-07 12:30:03 +0200 | [diff] [blame] | 151 | jfs_err("jfs_mount: Failed to read AGGREGATE_I"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | /* | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 172 | *	mount (the only/single) fileset | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | /* | 
| Dave Kleikamp | f720e3b | 2007-06-06 15:28:35 -0500 | [diff] [blame] | 198 | *	unwind on error | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | { | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 241 | struct jfs_sb_info *sbi = JFS_SBI(sb); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 288 | return rc; | 
|  | 289 | } | 
|  | 290 |  | 
|  | 291 | /* | 
|  | 292 | *	chkSuper() | 
|  | 293 | * | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 294 | * validate the superblock of the file system to be mounted and | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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->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 | */ | 
|  | 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; | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 429 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | * | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 489 | * note: MOUNT record is at aggregate level, not at fileset level, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 490 | * since log records of previous mounts of a fileset | 
| Dave Kleikamp | 63f83c9 | 2006-10-02 09:55:27 -0500 | [diff] [blame] | 491 | * (e.g., AFTER record of extent allocation) have to be processed | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | } |