1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * Copyright (C) International Business Machines Corp., 2000-2004 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 5*1da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 6*1da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 7*1da177e4SLinus Torvalds * (at your option) any later version. 8*1da177e4SLinus Torvalds * 9*1da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, 10*1da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 11*1da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12*1da177e4SLinus Torvalds * the GNU General Public License for more details. 13*1da177e4SLinus Torvalds * 14*1da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 15*1da177e4SLinus Torvalds * along with this program; if not, write to the Free Software 16*1da177e4SLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17*1da177e4SLinus Torvalds */ 18*1da177e4SLinus Torvalds 19*1da177e4SLinus Torvalds /* 20*1da177e4SLinus Torvalds * jfs_umount.c 21*1da177e4SLinus Torvalds * 22*1da177e4SLinus Torvalds * note: file system in transition to aggregate/fileset: 23*1da177e4SLinus Torvalds * (ref. jfs_mount.c) 24*1da177e4SLinus Torvalds * 25*1da177e4SLinus Torvalds * file system unmount is interpreted as mount of the single/only 26*1da177e4SLinus Torvalds * fileset in the aggregate and, if unmount of the last fileset, 27*1da177e4SLinus Torvalds * as unmount of the aggerate; 28*1da177e4SLinus Torvalds */ 29*1da177e4SLinus Torvalds 30*1da177e4SLinus Torvalds #include <linux/fs.h> 31*1da177e4SLinus Torvalds #include "jfs_incore.h" 32*1da177e4SLinus Torvalds #include "jfs_filsys.h" 33*1da177e4SLinus Torvalds #include "jfs_superblock.h" 34*1da177e4SLinus Torvalds #include "jfs_dmap.h" 35*1da177e4SLinus Torvalds #include "jfs_imap.h" 36*1da177e4SLinus Torvalds #include "jfs_metapage.h" 37*1da177e4SLinus Torvalds #include "jfs_debug.h" 38*1da177e4SLinus Torvalds 39*1da177e4SLinus Torvalds /* 40*1da177e4SLinus Torvalds * NAME: jfs_umount(vfsp, flags, crp) 41*1da177e4SLinus Torvalds * 42*1da177e4SLinus Torvalds * FUNCTION: vfs_umount() 43*1da177e4SLinus Torvalds * 44*1da177e4SLinus Torvalds * PARAMETERS: vfsp - virtual file system pointer 45*1da177e4SLinus Torvalds * flags - unmount for shutdown 46*1da177e4SLinus Torvalds * crp - credential 47*1da177e4SLinus Torvalds * 48*1da177e4SLinus Torvalds * RETURN : EBUSY - device has open files 49*1da177e4SLinus Torvalds */ 50*1da177e4SLinus Torvalds int jfs_umount(struct super_block *sb) 51*1da177e4SLinus Torvalds { 52*1da177e4SLinus Torvalds struct address_space *bdev_mapping = sb->s_bdev->bd_inode->i_mapping; 53*1da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(sb); 54*1da177e4SLinus Torvalds struct inode *ipbmap = sbi->ipbmap; 55*1da177e4SLinus Torvalds struct inode *ipimap = sbi->ipimap; 56*1da177e4SLinus Torvalds struct inode *ipaimap = sbi->ipaimap; 57*1da177e4SLinus Torvalds struct inode *ipaimap2 = sbi->ipaimap2; 58*1da177e4SLinus Torvalds struct jfs_log *log; 59*1da177e4SLinus Torvalds int rc = 0; 60*1da177e4SLinus Torvalds 61*1da177e4SLinus Torvalds jfs_info("UnMount JFS: sb:0x%p", sb); 62*1da177e4SLinus Torvalds 63*1da177e4SLinus Torvalds /* 64*1da177e4SLinus Torvalds * update superblock and close log 65*1da177e4SLinus Torvalds * 66*1da177e4SLinus Torvalds * if mounted read-write and log based recovery was enabled 67*1da177e4SLinus Torvalds */ 68*1da177e4SLinus Torvalds if ((log = sbi->log)) 69*1da177e4SLinus Torvalds /* 70*1da177e4SLinus Torvalds * Wait for outstanding transactions to be written to log: 71*1da177e4SLinus Torvalds */ 72*1da177e4SLinus Torvalds jfs_flush_journal(log, 2); 73*1da177e4SLinus Torvalds 74*1da177e4SLinus Torvalds /* 75*1da177e4SLinus Torvalds * close fileset inode allocation map (aka fileset inode) 76*1da177e4SLinus Torvalds */ 77*1da177e4SLinus Torvalds diUnmount(ipimap, 0); 78*1da177e4SLinus Torvalds 79*1da177e4SLinus Torvalds diFreeSpecial(ipimap); 80*1da177e4SLinus Torvalds sbi->ipimap = NULL; 81*1da177e4SLinus Torvalds 82*1da177e4SLinus Torvalds /* 83*1da177e4SLinus Torvalds * close secondary aggregate inode allocation map 84*1da177e4SLinus Torvalds */ 85*1da177e4SLinus Torvalds ipaimap2 = sbi->ipaimap2; 86*1da177e4SLinus Torvalds if (ipaimap2) { 87*1da177e4SLinus Torvalds diUnmount(ipaimap2, 0); 88*1da177e4SLinus Torvalds diFreeSpecial(ipaimap2); 89*1da177e4SLinus Torvalds sbi->ipaimap2 = NULL; 90*1da177e4SLinus Torvalds } 91*1da177e4SLinus Torvalds 92*1da177e4SLinus Torvalds /* 93*1da177e4SLinus Torvalds * close aggregate inode allocation map 94*1da177e4SLinus Torvalds */ 95*1da177e4SLinus Torvalds ipaimap = sbi->ipaimap; 96*1da177e4SLinus Torvalds diUnmount(ipaimap, 0); 97*1da177e4SLinus Torvalds diFreeSpecial(ipaimap); 98*1da177e4SLinus Torvalds sbi->ipaimap = NULL; 99*1da177e4SLinus Torvalds 100*1da177e4SLinus Torvalds /* 101*1da177e4SLinus Torvalds * close aggregate block allocation map 102*1da177e4SLinus Torvalds */ 103*1da177e4SLinus Torvalds dbUnmount(ipbmap, 0); 104*1da177e4SLinus Torvalds 105*1da177e4SLinus Torvalds diFreeSpecial(ipbmap); 106*1da177e4SLinus Torvalds sbi->ipimap = NULL; 107*1da177e4SLinus Torvalds 108*1da177e4SLinus Torvalds /* 109*1da177e4SLinus Torvalds * Make sure all metadata makes it to disk before we mark 110*1da177e4SLinus Torvalds * the superblock as clean 111*1da177e4SLinus Torvalds */ 112*1da177e4SLinus Torvalds filemap_fdatawrite(bdev_mapping); 113*1da177e4SLinus Torvalds filemap_fdatawait(bdev_mapping); 114*1da177e4SLinus Torvalds 115*1da177e4SLinus Torvalds /* 116*1da177e4SLinus Torvalds * ensure all file system file pages are propagated to their 117*1da177e4SLinus Torvalds * home blocks on disk (and their in-memory buffer pages are 118*1da177e4SLinus Torvalds * invalidated) BEFORE updating file system superblock state 119*1da177e4SLinus Torvalds * (to signify file system is unmounted cleanly, and thus in 120*1da177e4SLinus Torvalds * consistent state) and log superblock active file system 121*1da177e4SLinus Torvalds * list (to signify skip logredo()). 122*1da177e4SLinus Torvalds */ 123*1da177e4SLinus Torvalds if (log) { /* log = NULL if read-only mount */ 124*1da177e4SLinus Torvalds updateSuper(sb, FM_CLEAN); 125*1da177e4SLinus Torvalds 126*1da177e4SLinus Torvalds /* Restore default gfp_mask for bdev */ 127*1da177e4SLinus Torvalds mapping_set_gfp_mask(bdev_mapping, GFP_USER); 128*1da177e4SLinus Torvalds 129*1da177e4SLinus Torvalds /* 130*1da177e4SLinus Torvalds * close log: 131*1da177e4SLinus Torvalds * 132*1da177e4SLinus Torvalds * remove file system from log active file system list. 133*1da177e4SLinus Torvalds */ 134*1da177e4SLinus Torvalds rc = lmLogClose(sb); 135*1da177e4SLinus Torvalds } 136*1da177e4SLinus Torvalds jfs_info("UnMount JFS Complete: rc = %d", rc); 137*1da177e4SLinus Torvalds return rc; 138*1da177e4SLinus Torvalds } 139*1da177e4SLinus Torvalds 140*1da177e4SLinus Torvalds 141*1da177e4SLinus Torvalds int jfs_umount_rw(struct super_block *sb) 142*1da177e4SLinus Torvalds { 143*1da177e4SLinus Torvalds struct address_space *bdev_mapping = sb->s_bdev->bd_inode->i_mapping; 144*1da177e4SLinus Torvalds struct jfs_sb_info *sbi = JFS_SBI(sb); 145*1da177e4SLinus Torvalds struct jfs_log *log = sbi->log; 146*1da177e4SLinus Torvalds 147*1da177e4SLinus Torvalds if (!log) 148*1da177e4SLinus Torvalds return 0; 149*1da177e4SLinus Torvalds 150*1da177e4SLinus Torvalds /* 151*1da177e4SLinus Torvalds * close log: 152*1da177e4SLinus Torvalds * 153*1da177e4SLinus Torvalds * remove file system from log active file system list. 154*1da177e4SLinus Torvalds */ 155*1da177e4SLinus Torvalds jfs_flush_journal(log, 2); 156*1da177e4SLinus Torvalds 157*1da177e4SLinus Torvalds /* 158*1da177e4SLinus Torvalds * Make sure all metadata makes it to disk 159*1da177e4SLinus Torvalds */ 160*1da177e4SLinus Torvalds dbSync(sbi->ipbmap); 161*1da177e4SLinus Torvalds diSync(sbi->ipimap); 162*1da177e4SLinus Torvalds 163*1da177e4SLinus Torvalds /* 164*1da177e4SLinus Torvalds * Note that we have to do this even if sync_blockdev() will 165*1da177e4SLinus Torvalds * do exactly the same a few instructions later: We can't 166*1da177e4SLinus Torvalds * mark the superblock clean before everything is flushed to 167*1da177e4SLinus Torvalds * disk. 168*1da177e4SLinus Torvalds */ 169*1da177e4SLinus Torvalds filemap_fdatawrite(bdev_mapping); 170*1da177e4SLinus Torvalds filemap_fdatawait(bdev_mapping); 171*1da177e4SLinus Torvalds 172*1da177e4SLinus Torvalds updateSuper(sb, FM_CLEAN); 173*1da177e4SLinus Torvalds 174*1da177e4SLinus Torvalds /* Restore default gfp_mask for bdev */ 175*1da177e4SLinus Torvalds mapping_set_gfp_mask(bdev_mapping, GFP_USER); 176*1da177e4SLinus Torvalds 177*1da177e4SLinus Torvalds return lmLogClose(sb); 178*1da177e4SLinus Torvalds } 179