xref: /openbmc/linux/fs/jfs/jfs_umount.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
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