xref: /openbmc/linux/fs/gfs2/util.c (revision ecc23d0a422a3118fcf6e4f0a46e17a6c2047b02)
17336d0e6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2b3b94faaSDavid Teigland /*
3b3b94faaSDavid Teigland  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
43a8a9a10SSteven Whitehouse  * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
5b3b94faaSDavid Teigland  */
6b3b94faaSDavid Teigland 
7d77d1b58SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8d77d1b58SJoe Perches 
9b3b94faaSDavid Teigland #include <linux/spinlock.h>
10b3b94faaSDavid Teigland #include <linux/completion.h>
11b3b94faaSDavid Teigland #include <linux/buffer_head.h>
12f66af88eSAndreas Gruenbacher #include <linux/kthread.h>
13b3b94faaSDavid Teigland #include <linux/crc32.h>
145c676f6dSSteven Whitehouse #include <linux/gfs2_ondisk.h>
15601ef0d5SBob Peterson #include <linux/delay.h>
167c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
17b3b94faaSDavid Teigland 
18b3b94faaSDavid Teigland #include "gfs2.h"
195c676f6dSSteven Whitehouse #include "incore.h"
20b3b94faaSDavid Teigland #include "glock.h"
21601ef0d5SBob Peterson #include "glops.h"
22601ef0d5SBob Peterson #include "log.h"
230d91061aSBob Peterson #include "lops.h"
240d91061aSBob Peterson #include "recovery.h"
2572244b6bSBob Peterson #include "rgrp.h"
260d91061aSBob Peterson #include "super.h"
275c676f6dSSteven Whitehouse #include "util.h"
28b3b94faaSDavid Teigland 
29e18b890bSChristoph Lameter struct kmem_cache *gfs2_glock_cachep __read_mostly;
30009d8518SSteven Whitehouse struct kmem_cache *gfs2_glock_aspace_cachep __read_mostly;
31e18b890bSChristoph Lameter struct kmem_cache *gfs2_inode_cachep __read_mostly;
32e18b890bSChristoph Lameter struct kmem_cache *gfs2_bufdata_cachep __read_mostly;
336bdd9be6SBob Peterson struct kmem_cache *gfs2_rgrpd_cachep __read_mostly;
3437b2c837SSteven Whitehouse struct kmem_cache *gfs2_quotad_cachep __read_mostly;
35b54e9a0bSBob Peterson struct kmem_cache *gfs2_qadata_cachep __read_mostly;
36b839dadaSBob Peterson struct kmem_cache *gfs2_trans_cachep __read_mostly;
37e8c92ed7SSteven Whitehouse mempool_t *gfs2_page_pool __read_mostly;
38b3b94faaSDavid Teigland 
gfs2_assert_i(struct gfs2_sbd * sdp)39b3b94faaSDavid Teigland void gfs2_assert_i(struct gfs2_sbd *sdp)
40b3b94faaSDavid Teigland {
418382e26bSJoe Perches 	fs_emerg(sdp, "fatal assertion failed\n");
42b3b94faaSDavid Teigland }
43b3b94faaSDavid Teigland 
440d91061aSBob Peterson /**
450d91061aSBob Peterson  * check_journal_clean - Make sure a journal is clean for a spectator mount
460d91061aSBob Peterson  * @sdp: The GFS2 superblock
470d91061aSBob Peterson  * @jd: The journal descriptor
48c551f66cSLee Jones  * @verbose: Show more prints in the log
490d91061aSBob Peterson  *
500d91061aSBob Peterson  * Returns: 0 if the journal is clean or locked, else an error
510d91061aSBob Peterson  */
check_journal_clean(struct gfs2_sbd * sdp,struct gfs2_jdesc * jd,bool verbose)527d9f9249SBob Peterson int check_journal_clean(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
537d9f9249SBob Peterson 			bool verbose)
540d91061aSBob Peterson {
550d91061aSBob Peterson 	int error;
560d91061aSBob Peterson 	struct gfs2_holder j_gh;
570d91061aSBob Peterson 	struct gfs2_log_header_host head;
580d91061aSBob Peterson 	struct gfs2_inode *ip;
590d91061aSBob Peterson 
600d91061aSBob Peterson 	ip = GFS2_I(jd->jd_inode);
610d91061aSBob Peterson 	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_NOEXP |
620d91061aSBob Peterson 				   GL_EXACT | GL_NOCACHE, &j_gh);
630d91061aSBob Peterson 	if (error) {
647d9f9249SBob Peterson 		if (verbose)
657d9f9249SBob Peterson 			fs_err(sdp, "Error %d locking journal for spectator "
667d9f9249SBob Peterson 			       "mount.\n", error);
670d91061aSBob Peterson 		return -EPERM;
680d91061aSBob Peterson 	}
690d91061aSBob Peterson 	error = gfs2_jdesc_check(jd);
700d91061aSBob Peterson 	if (error) {
717d9f9249SBob Peterson 		if (verbose)
727d9f9249SBob Peterson 			fs_err(sdp, "Error checking journal for spectator "
737d9f9249SBob Peterson 			       "mount.\n");
740d91061aSBob Peterson 		goto out_unlock;
750d91061aSBob Peterson 	}
760d91061aSBob Peterson 	error = gfs2_find_jhead(jd, &head, false);
770d91061aSBob Peterson 	if (error) {
787d9f9249SBob Peterson 		if (verbose)
797d9f9249SBob Peterson 			fs_err(sdp, "Error parsing journal for spectator "
807d9f9249SBob Peterson 			       "mount.\n");
810d91061aSBob Peterson 		goto out_unlock;
820d91061aSBob Peterson 	}
830d91061aSBob Peterson 	if (!(head.lh_flags & GFS2_LOG_HEAD_UNMOUNT)) {
840d91061aSBob Peterson 		error = -EPERM;
857d9f9249SBob Peterson 		if (verbose)
867d9f9249SBob Peterson 			fs_err(sdp, "jid=%u: Journal is dirty, so the first "
877d9f9249SBob Peterson 			       "mounter must not be a spectator.\n",
887d9f9249SBob Peterson 			       jd->jd_jid);
890d91061aSBob Peterson 	}
900d91061aSBob Peterson 
910d91061aSBob Peterson out_unlock:
920d91061aSBob Peterson 	gfs2_glock_dq_uninit(&j_gh);
930d91061aSBob Peterson 	return error;
940d91061aSBob Peterson }
950d91061aSBob Peterson 
96c77b52c0SBob Peterson /**
97e392edd5SAndreas Gruenbacher  * gfs2_freeze_lock_shared - hold the freeze glock
98c77b52c0SBob Peterson  * @sdp: the superblock
99c77b52c0SBob Peterson  */
gfs2_freeze_lock_shared(struct gfs2_sbd * sdp)1006c7410f4SAndreas Gruenbacher int gfs2_freeze_lock_shared(struct gfs2_sbd *sdp)
101c77b52c0SBob Peterson {
102d9612c66SAndreas Gruenbacher 	int flags = LM_FLAG_NOEXP | GL_EXACT;
103c77b52c0SBob Peterson 	int error;
104c77b52c0SBob Peterson 
105d9612c66SAndreas Gruenbacher 	error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, flags,
1066c7410f4SAndreas Gruenbacher 				   &sdp->sd_freeze_gh);
107d9612c66SAndreas Gruenbacher 	if (error && error != GLR_TRYFAILED)
108af1abe11SAndreas Gruenbacher 		fs_err(sdp, "can't lock the freeze glock: %d\n", error);
109c77b52c0SBob Peterson 	return error;
110c77b52c0SBob Peterson }
111c77b52c0SBob Peterson 
gfs2_freeze_unlock(struct gfs2_holder * freeze_gh)112c77b52c0SBob Peterson void gfs2_freeze_unlock(struct gfs2_holder *freeze_gh)
113c77b52c0SBob Peterson {
114c77b52c0SBob Peterson 	if (gfs2_holder_initialized(freeze_gh))
115c77b52c0SBob Peterson 		gfs2_glock_dq_uninit(freeze_gh);
116c77b52c0SBob Peterson }
117c77b52c0SBob Peterson 
signal_our_withdraw(struct gfs2_sbd * sdp)118601ef0d5SBob Peterson static void signal_our_withdraw(struct gfs2_sbd *sdp)
119601ef0d5SBob Peterson {
120f5f02fdeSBob Peterson 	struct gfs2_glock *live_gl = sdp->sd_live_gh.gh_gl;
121d5bf630fSBob Peterson 	struct inode *inode;
122d5bf630fSBob Peterson 	struct gfs2_inode *ip;
123d5bf630fSBob Peterson 	struct gfs2_glock *i_gl;
124d5bf630fSBob Peterson 	u64 no_formal_ino;
125601ef0d5SBob Peterson 	int ret = 0;
126601ef0d5SBob Peterson 	int tries;
127601ef0d5SBob Peterson 
128d5bf630fSBob Peterson 	if (test_bit(SDF_NORECOVERY, &sdp->sd_flags) || !sdp->sd_jdesc)
129601ef0d5SBob Peterson 		return;
130601ef0d5SBob Peterson 
131f5456b5dSBob Peterson 	gfs2_ail_drain(sdp); /* frees all transactions */
132d5bf630fSBob Peterson 	inode = sdp->sd_jdesc->jd_inode;
133d5bf630fSBob Peterson 	ip = GFS2_I(inode);
134d5bf630fSBob Peterson 	i_gl = ip->i_gl;
135d5bf630fSBob Peterson 	no_formal_ino = ip->i_no_formal_ino;
136d5bf630fSBob Peterson 
137601ef0d5SBob Peterson 	/* Prevent any glock dq until withdraw recovery is complete */
138601ef0d5SBob Peterson 	set_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags);
139601ef0d5SBob Peterson 	/*
140601ef0d5SBob Peterson 	 * Don't tell dlm we're bailing until we have no more buffers in the
141601ef0d5SBob Peterson 	 * wind. If journal had an IO error, the log code should just purge
142601ef0d5SBob Peterson 	 * the outstanding buffers rather than submitting new IO. Making the
143601ef0d5SBob Peterson 	 * file system read-only will flush the journal, etc.
144601ef0d5SBob Peterson 	 *
145601ef0d5SBob Peterson 	 * During a normal unmount, gfs2_make_fs_ro calls gfs2_log_shutdown
146601ef0d5SBob Peterson 	 * which clears SDF_JOURNAL_LIVE. In a withdraw, we must not write
147601ef0d5SBob Peterson 	 * any UNMOUNT log header, so we can't call gfs2_log_shutdown, and
148601ef0d5SBob Peterson 	 * therefore we need to clear SDF_JOURNAL_LIVE manually.
149601ef0d5SBob Peterson 	 */
150601ef0d5SBob Peterson 	clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
15196b1454fSBob Peterson 	if (!sb_rdonly(sdp->sd_vfs)) {
152b77b4a48SAndreas Gruenbacher 		bool locked = mutex_trylock(&sdp->sd_freeze_mutex);
15396b1454fSBob Peterson 
154fe4f7940SAndreas Gruenbacher 		wake_up(&sdp->sd_logd_waitq);
155fe4f7940SAndreas Gruenbacher 		wake_up(&sdp->sd_quota_wait);
156f66af88eSAndreas Gruenbacher 
157f66af88eSAndreas Gruenbacher 		wait_event_timeout(sdp->sd_log_waitq,
158f66af88eSAndreas Gruenbacher 				   gfs2_log_is_empty(sdp),
159f66af88eSAndreas Gruenbacher 				   HZ * 5);
160f66af88eSAndreas Gruenbacher 
161f66af88eSAndreas Gruenbacher 		sdp->sd_vfs->s_flags |= SB_RDONLY;
162b77b4a48SAndreas Gruenbacher 
163b77b4a48SAndreas Gruenbacher 		if (locked)
164b77b4a48SAndreas Gruenbacher 			mutex_unlock(&sdp->sd_freeze_mutex);
165b77b4a48SAndreas Gruenbacher 
166053640a7SBob Peterson 		/*
167053640a7SBob Peterson 		 * Dequeue any pending non-system glock holders that can no
168053640a7SBob Peterson 		 * longer be granted because the file system is withdrawn.
169053640a7SBob Peterson 		 */
170053640a7SBob Peterson 		gfs2_gl_dq_holders(sdp);
17196b1454fSBob Peterson 	}
172601ef0d5SBob Peterson 
17353af80ceSBob Peterson 	if (sdp->sd_lockstruct.ls_ops->lm_lock == NULL) { /* lock_nolock */
17453af80ceSBob Peterson 		if (!ret)
17553af80ceSBob Peterson 			ret = -EIO;
17653af80ceSBob Peterson 		clear_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags);
17753af80ceSBob Peterson 		goto skip_recovery;
17853af80ceSBob Peterson 	}
179601ef0d5SBob Peterson 	/*
180601ef0d5SBob Peterson 	 * Drop the glock for our journal so another node can recover it.
181601ef0d5SBob Peterson 	 */
182601ef0d5SBob Peterson 	if (gfs2_holder_initialized(&sdp->sd_journal_gh)) {
183601ef0d5SBob Peterson 		gfs2_glock_dq_wait(&sdp->sd_journal_gh);
184601ef0d5SBob Peterson 		gfs2_holder_uninit(&sdp->sd_journal_gh);
185601ef0d5SBob Peterson 	}
186601ef0d5SBob Peterson 	sdp->sd_jinode_gh.gh_flags |= GL_NOCACHE;
187601ef0d5SBob Peterson 	gfs2_glock_dq(&sdp->sd_jinode_gh);
188b77b4a48SAndreas Gruenbacher 	gfs2_thaw_freeze_initiator(sdp->sd_vfs);
189b77b4a48SAndreas Gruenbacher 	wait_on_bit(&i_gl->gl_flags, GLF_DEMOTE, TASK_UNINTERRUPTIBLE);
190601ef0d5SBob Peterson 
191601ef0d5SBob Peterson 	/*
192601ef0d5SBob Peterson 	 * holder_uninit to force glock_put, to force dlm to let go
193601ef0d5SBob Peterson 	 */
194601ef0d5SBob Peterson 	gfs2_holder_uninit(&sdp->sd_jinode_gh);
195601ef0d5SBob Peterson 
196601ef0d5SBob Peterson 	/*
197601ef0d5SBob Peterson 	 * Note: We need to be careful here:
198601ef0d5SBob Peterson 	 * Our iput of jd_inode will evict it. The evict will dequeue its
199601ef0d5SBob Peterson 	 * glock, but the glock dq will wait for the withdraw unless we have
200601ef0d5SBob Peterson 	 * exception code in glock_dq.
201601ef0d5SBob Peterson 	 */
202601ef0d5SBob Peterson 	iput(inode);
20304133b60SBob Peterson 	sdp->sd_jdesc->jd_inode = NULL;
204601ef0d5SBob Peterson 	/*
205601ef0d5SBob Peterson 	 * Wait until the journal inode's glock is freed. This allows try locks
206601ef0d5SBob Peterson 	 * on other nodes to be successful, otherwise we remain the owner of
207601ef0d5SBob Peterson 	 * the glock as far as dlm is concerned.
208601ef0d5SBob Peterson 	 */
209f5f02fdeSBob Peterson 	if (i_gl->gl_ops->go_free) {
210f5f02fdeSBob Peterson 		set_bit(GLF_FREEING, &i_gl->gl_flags);
211f5f02fdeSBob Peterson 		wait_on_bit(&i_gl->gl_flags, GLF_FREEING, TASK_UNINTERRUPTIBLE);
212601ef0d5SBob Peterson 	}
213601ef0d5SBob Peterson 
214601ef0d5SBob Peterson 	/*
215601ef0d5SBob Peterson 	 * Dequeue the "live" glock, but keep a reference so it's never freed.
216601ef0d5SBob Peterson 	 */
217f5f02fdeSBob Peterson 	gfs2_glock_hold(live_gl);
218601ef0d5SBob Peterson 	gfs2_glock_dq_wait(&sdp->sd_live_gh);
219601ef0d5SBob Peterson 	/*
220601ef0d5SBob Peterson 	 * We enqueue the "live" glock in EX so that all other nodes
221601ef0d5SBob Peterson 	 * get a demote request and act on it. We don't really want the
222601ef0d5SBob Peterson 	 * lock in EX, so we send a "try" lock with 1CB to produce a callback.
223601ef0d5SBob Peterson 	 */
224601ef0d5SBob Peterson 	fs_warn(sdp, "Requesting recovery of jid %d.\n",
225601ef0d5SBob Peterson 		sdp->sd_lockstruct.ls_jid);
226ebdc416cSAndreas Gruenbacher 	gfs2_holder_reinit(LM_ST_EXCLUSIVE,
227ebdc416cSAndreas Gruenbacher 			   LM_FLAG_TRY_1CB | LM_FLAG_NOEXP | GL_NOPID,
228601ef0d5SBob Peterson 			   &sdp->sd_live_gh);
229601ef0d5SBob Peterson 	msleep(GL_GLOCK_MAX_HOLD);
230601ef0d5SBob Peterson 	/*
231601ef0d5SBob Peterson 	 * This will likely fail in a cluster, but succeed standalone:
232601ef0d5SBob Peterson 	 */
233601ef0d5SBob Peterson 	ret = gfs2_glock_nq(&sdp->sd_live_gh);
234601ef0d5SBob Peterson 
235601ef0d5SBob Peterson 	/*
236601ef0d5SBob Peterson 	 * If we actually got the "live" lock in EX mode, there are no other
237601ef0d5SBob Peterson 	 * nodes available to replay our journal. So we try to replay it
238601ef0d5SBob Peterson 	 * ourselves. We hold the "live" glock to prevent other mounters
239601ef0d5SBob Peterson 	 * during recovery, then just dequeue it and reacquire it in our
240601ef0d5SBob Peterson 	 * normal SH mode. Just in case the problem that caused us to
241601ef0d5SBob Peterson 	 * withdraw prevents us from recovering our journal (e.g. io errors
242601ef0d5SBob Peterson 	 * and such) we still check if the journal is clean before proceeding
243601ef0d5SBob Peterson 	 * but we may wait forever until another mounter does the recovery.
244601ef0d5SBob Peterson 	 */
245601ef0d5SBob Peterson 	if (ret == 0) {
246601ef0d5SBob Peterson 		fs_warn(sdp, "No other mounters found. Trying to recover our "
247601ef0d5SBob Peterson 			"own journal jid %d.\n", sdp->sd_lockstruct.ls_jid);
248601ef0d5SBob Peterson 		if (gfs2_recover_journal(sdp->sd_jdesc, 1))
249601ef0d5SBob Peterson 			fs_warn(sdp, "Unable to recover our journal jid %d.\n",
250601ef0d5SBob Peterson 				sdp->sd_lockstruct.ls_jid);
251601ef0d5SBob Peterson 		gfs2_glock_dq_wait(&sdp->sd_live_gh);
252ebdc416cSAndreas Gruenbacher 		gfs2_holder_reinit(LM_ST_SHARED,
253ebdc416cSAndreas Gruenbacher 				   LM_FLAG_NOEXP | GL_EXACT | GL_NOPID,
254601ef0d5SBob Peterson 				   &sdp->sd_live_gh);
255601ef0d5SBob Peterson 		gfs2_glock_nq(&sdp->sd_live_gh);
256601ef0d5SBob Peterson 	}
257601ef0d5SBob Peterson 
258*67696fefSAndreas Gruenbacher 	gfs2_glock_put(live_gl); /* drop extra reference we acquired */
259601ef0d5SBob Peterson 	clear_bit(SDF_WITHDRAW_RECOVERY, &sdp->sd_flags);
260601ef0d5SBob Peterson 
261601ef0d5SBob Peterson 	/*
262601ef0d5SBob Peterson 	 * At this point our journal is evicted, so we need to get a new inode
263601ef0d5SBob Peterson 	 * for it. Once done, we need to call gfs2_find_jhead which
264601ef0d5SBob Peterson 	 * calls gfs2_map_journal_extents to map it for us again.
265601ef0d5SBob Peterson 	 *
266601ef0d5SBob Peterson 	 * Note that we don't really want it to look up a FREE block. The
267601ef0d5SBob Peterson 	 * GFS2_BLKST_FREE simply overrides a block check in gfs2_inode_lookup
268601ef0d5SBob Peterson 	 * which would otherwise fail because it requires grabbing an rgrp
269601ef0d5SBob Peterson 	 * glock, which would fail with -EIO because we're withdrawing.
270601ef0d5SBob Peterson 	 */
271601ef0d5SBob Peterson 	inode = gfs2_inode_lookup(sdp->sd_vfs, DT_UNKNOWN,
272601ef0d5SBob Peterson 				  sdp->sd_jdesc->jd_no_addr, no_formal_ino,
273601ef0d5SBob Peterson 				  GFS2_BLKST_FREE);
274601ef0d5SBob Peterson 	if (IS_ERR(inode)) {
275601ef0d5SBob Peterson 		fs_warn(sdp, "Reprocessing of jid %d failed with %ld.\n",
276601ef0d5SBob Peterson 			sdp->sd_lockstruct.ls_jid, PTR_ERR(inode));
277601ef0d5SBob Peterson 		goto skip_recovery;
278601ef0d5SBob Peterson 	}
279601ef0d5SBob Peterson 	sdp->sd_jdesc->jd_inode = inode;
2801b8550b5SBob Peterson 	d_mark_dontcache(inode);
281601ef0d5SBob Peterson 
282601ef0d5SBob Peterson 	/*
283601ef0d5SBob Peterson 	 * Now wait until recovery is complete.
284601ef0d5SBob Peterson 	 */
285601ef0d5SBob Peterson 	for (tries = 0; tries < 10; tries++) {
2867d9f9249SBob Peterson 		ret = check_journal_clean(sdp, sdp->sd_jdesc, false);
287601ef0d5SBob Peterson 		if (!ret)
288601ef0d5SBob Peterson 			break;
289601ef0d5SBob Peterson 		msleep(HZ);
290601ef0d5SBob Peterson 		fs_warn(sdp, "Waiting for journal recovery jid %d.\n",
291601ef0d5SBob Peterson 			sdp->sd_lockstruct.ls_jid);
292601ef0d5SBob Peterson 	}
293601ef0d5SBob Peterson skip_recovery:
294601ef0d5SBob Peterson 	if (!ret)
295601ef0d5SBob Peterson 		fs_warn(sdp, "Journal recovery complete for jid %d.\n",
296601ef0d5SBob Peterson 			sdp->sd_lockstruct.ls_jid);
297601ef0d5SBob Peterson 	else
2987392fbb0SBob Peterson 		fs_warn(sdp, "Journal recovery skipped for jid %d until next "
299601ef0d5SBob Peterson 			"mount.\n", sdp->sd_lockstruct.ls_jid);
300601ef0d5SBob Peterson 	fs_warn(sdp, "Glock dequeues delayed: %lu\n", sdp->sd_glock_dqs_held);
301601ef0d5SBob Peterson 	sdp->sd_glock_dqs_held = 0;
302601ef0d5SBob Peterson 	wake_up_bit(&sdp->sd_flags, SDF_WITHDRAW_RECOVERY);
303601ef0d5SBob Peterson }
304601ef0d5SBob Peterson 
gfs2_lm(struct gfs2_sbd * sdp,const char * fmt,...)305badb55ecSAndreas Gruenbacher void gfs2_lm(struct gfs2_sbd *sdp, const char *fmt, ...)
306badb55ecSAndreas Gruenbacher {
307badb55ecSAndreas Gruenbacher 	struct va_format vaf;
308badb55ecSAndreas Gruenbacher 	va_list args;
309badb55ecSAndreas Gruenbacher 
310badb55ecSAndreas Gruenbacher 	if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW &&
311badb55ecSAndreas Gruenbacher 	    test_bit(SDF_WITHDRAWN, &sdp->sd_flags))
312badb55ecSAndreas Gruenbacher 		return;
313badb55ecSAndreas Gruenbacher 
314badb55ecSAndreas Gruenbacher 	va_start(args, fmt);
315badb55ecSAndreas Gruenbacher 	vaf.fmt = fmt;
316badb55ecSAndreas Gruenbacher 	vaf.va = &args;
317badb55ecSAndreas Gruenbacher 	fs_err(sdp, "%pV", &vaf);
318badb55ecSAndreas Gruenbacher 	va_end(args);
319badb55ecSAndreas Gruenbacher }
320badb55ecSAndreas Gruenbacher 
gfs2_withdraw(struct gfs2_sbd * sdp)321badb55ecSAndreas Gruenbacher int gfs2_withdraw(struct gfs2_sbd *sdp)
322da755fdbSSteven Whitehouse {
323f057f6cdSSteven Whitehouse 	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
324f057f6cdSSteven Whitehouse 	const struct lm_lockops *lm = ls->ls_ops;
325da755fdbSSteven Whitehouse 
326e3da6be3SAndreas Gruenbacher 	if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW) {
327e3da6be3SAndreas Gruenbacher 		unsigned long old = READ_ONCE(sdp->sd_flags), new;
328601ef0d5SBob Peterson 
329e3da6be3SAndreas Gruenbacher 		do {
330e3da6be3SAndreas Gruenbacher 			if (old & BIT(SDF_WITHDRAWN)) {
331e3da6be3SAndreas Gruenbacher 				wait_on_bit(&sdp->sd_flags,
332e3da6be3SAndreas Gruenbacher 					    SDF_WITHDRAW_IN_PROG,
333601ef0d5SBob Peterson 					    TASK_UNINTERRUPTIBLE);
334601ef0d5SBob Peterson 				return -1;
335601ef0d5SBob Peterson 			}
336e3da6be3SAndreas Gruenbacher 			new = old | BIT(SDF_WITHDRAWN) | BIT(SDF_WITHDRAW_IN_PROG);
337e3da6be3SAndreas Gruenbacher 		} while (unlikely(!try_cmpxchg(&sdp->sd_flags, &old, new)));
338601ef0d5SBob Peterson 
339da755fdbSSteven Whitehouse 		fs_err(sdp, "about to withdraw this file system\n");
340da755fdbSSteven Whitehouse 		BUG_ON(sdp->sd_args.ar_debug);
341da755fdbSSteven Whitehouse 
342601ef0d5SBob Peterson 		signal_our_withdraw(sdp);
343601ef0d5SBob Peterson 
344f057f6cdSSteven Whitehouse 		kobject_uevent(&sdp->sd_kobj, KOBJ_OFFLINE);
345f057f6cdSSteven Whitehouse 
346fd95e81cSSteven Whitehouse 		if (!strcmp(sdp->sd_lockstruct.ls_ops->lm_proto_name, "lock_dlm"))
347fd95e81cSSteven Whitehouse 			wait_for_completion(&sdp->sd_wdack);
348fd95e81cSSteven Whitehouse 
349f057f6cdSSteven Whitehouse 		if (lm->lm_unmount) {
350f057f6cdSSteven Whitehouse 			fs_err(sdp, "telling LM to unmount\n");
351f057f6cdSSteven Whitehouse 			lm->lm_unmount(sdp);
352f057f6cdSSteven Whitehouse 		}
353601ef0d5SBob Peterson 		fs_err(sdp, "File system withdrawn\n");
354da755fdbSSteven Whitehouse 		dump_stack();
355601ef0d5SBob Peterson 		clear_bit(SDF_WITHDRAW_IN_PROG, &sdp->sd_flags);
356601ef0d5SBob Peterson 		smp_mb__after_atomic();
357601ef0d5SBob Peterson 		wake_up_bit(&sdp->sd_flags, SDF_WITHDRAW_IN_PROG);
358d34843d0SBob Peterson 	}
359d34843d0SBob Peterson 
360d34843d0SBob Peterson 	if (sdp->sd_args.ar_errors == GFS2_ERRORS_PANIC)
361d77d1b58SJoe Perches 		panic("GFS2: fsid=%s: panic requested\n", sdp->sd_fsname);
362da755fdbSSteven Whitehouse 
363da755fdbSSteven Whitehouse 	return -1;
364da755fdbSSteven Whitehouse }
365da755fdbSSteven Whitehouse 
366c551f66cSLee Jones /*
367b3b94faaSDavid Teigland  * gfs2_assert_withdraw_i - Cause the machine to withdraw if @assertion is false
368b3b94faaSDavid Teigland  */
369b3b94faaSDavid Teigland 
gfs2_assert_withdraw_i(struct gfs2_sbd * sdp,char * assertion,const char * function,char * file,unsigned int line,bool delayed)3708e28ef1fSAndreas Gruenbacher void gfs2_assert_withdraw_i(struct gfs2_sbd *sdp, char *assertion,
371ca399c96SBob Peterson 			    const char *function, char *file, unsigned int line,
372ca399c96SBob Peterson 			    bool delayed)
373b3b94faaSDavid Teigland {
374d6b412c5SAndreas Gruenbacher 	if (gfs2_withdrawing_or_withdrawn(sdp))
375ca399c96SBob Peterson 		return;
376ca399c96SBob Peterson 
377ca399c96SBob Peterson 	fs_err(sdp,
378cb94eb06SJoe Perches 	       "fatal: assertion \"%s\" failed\n"
379cb94eb06SJoe Perches 	       "   function = %s, file = %s, line = %u\n",
380cb94eb06SJoe Perches 	       assertion, function, file, line);
381ca399c96SBob Peterson 
382ca399c96SBob Peterson 	/*
383ca399c96SBob Peterson 	 * If errors=panic was specified on mount, it won't help to delay the
384ca399c96SBob Peterson 	 * withdraw.
385ca399c96SBob Peterson 	 */
386ca399c96SBob Peterson 	if (sdp->sd_args.ar_errors == GFS2_ERRORS_PANIC)
387ca399c96SBob Peterson 		delayed = false;
388ca399c96SBob Peterson 
389ca399c96SBob Peterson 	if (delayed)
390ca399c96SBob Peterson 		gfs2_withdraw_delayed(sdp);
391ca399c96SBob Peterson 	else
3928e28ef1fSAndreas Gruenbacher 		gfs2_withdraw(sdp);
39318ec7d5cSSteven Whitehouse 	dump_stack();
394b3b94faaSDavid Teigland }
395b3b94faaSDavid Teigland 
396c551f66cSLee Jones /*
397b3b94faaSDavid Teigland  * gfs2_assert_warn_i - Print a message to the console if @assertion is false
398b3b94faaSDavid Teigland  */
399b3b94faaSDavid Teigland 
gfs2_assert_warn_i(struct gfs2_sbd * sdp,char * assertion,const char * function,char * file,unsigned int line)4008e28ef1fSAndreas Gruenbacher void gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion,
401b3b94faaSDavid Teigland 			const char *function, char *file, unsigned int line)
402b3b94faaSDavid Teigland {
403b3b94faaSDavid Teigland 	if (time_before(jiffies,
404b3b94faaSDavid Teigland 			sdp->sd_last_warning +
405b3b94faaSDavid Teigland 			gfs2_tune_get(sdp, gt_complain_secs) * HZ))
4068e28ef1fSAndreas Gruenbacher 		return;
407b3b94faaSDavid Teigland 
408d34843d0SBob Peterson 	if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW)
4098382e26bSJoe Perches 		fs_warn(sdp, "warning: assertion \"%s\" failed at function = %s, file = %s, line = %u\n",
4108382e26bSJoe Perches 			assertion, function, file, line);
411b3b94faaSDavid Teigland 
412b3b94faaSDavid Teigland 	if (sdp->sd_args.ar_debug)
413b3b94faaSDavid Teigland 		BUG();
41418ec7d5cSSteven Whitehouse 	else
41518ec7d5cSSteven Whitehouse 		dump_stack();
416b3b94faaSDavid Teigland 
417d34843d0SBob Peterson 	if (sdp->sd_args.ar_errors == GFS2_ERRORS_PANIC)
418d34843d0SBob Peterson 		panic("GFS2: fsid=%s: warning: assertion \"%s\" failed\n"
419d34843d0SBob Peterson 		      "GFS2: fsid=%s:   function = %s, file = %s, line = %u\n",
420d34843d0SBob Peterson 		      sdp->sd_fsname, assertion,
421d34843d0SBob Peterson 		      sdp->sd_fsname, function, file, line);
422d34843d0SBob Peterson 
423b3b94faaSDavid Teigland 	sdp->sd_last_warning = jiffies;
424b3b94faaSDavid Teigland }
425b3b94faaSDavid Teigland 
426c551f66cSLee Jones /*
427b3b94faaSDavid Teigland  * gfs2_consist_i - Flag a filesystem consistency error and withdraw
428b3b94faaSDavid Teigland  */
429b3b94faaSDavid Teigland 
gfs2_consist_i(struct gfs2_sbd * sdp,const char * function,char * file,unsigned int line)430a5ca2f1cSAndreas Gruenbacher void gfs2_consist_i(struct gfs2_sbd *sdp, const char *function,
431b3b94faaSDavid Teigland 		    char *file, unsigned int line)
432b3b94faaSDavid Teigland {
433badb55ecSAndreas Gruenbacher 	gfs2_lm(sdp,
434cb94eb06SJoe Perches 		"fatal: filesystem consistency error - function = %s, file = %s, line = %u\n",
435cb94eb06SJoe Perches 		function, file, line);
436a5ca2f1cSAndreas Gruenbacher 	gfs2_withdraw(sdp);
437b3b94faaSDavid Teigland }
438b3b94faaSDavid Teigland 
439c551f66cSLee Jones /*
440b3b94faaSDavid Teigland  * gfs2_consist_inode_i - Flag an inode consistency error and withdraw
441b3b94faaSDavid Teigland  */
442b3b94faaSDavid Teigland 
gfs2_consist_inode_i(struct gfs2_inode * ip,const char * function,char * file,unsigned int line)443a5ca2f1cSAndreas Gruenbacher void gfs2_consist_inode_i(struct gfs2_inode *ip,
444b3b94faaSDavid Teigland 			  const char *function, char *file, unsigned int line)
445b3b94faaSDavid Teigland {
446feaa7bbaSSteven Whitehouse 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
447badb55ecSAndreas Gruenbacher 
448badb55ecSAndreas Gruenbacher 	gfs2_lm(sdp,
449cb94eb06SJoe Perches 		"fatal: filesystem consistency error\n"
450cb94eb06SJoe Perches 		"  inode = %llu %llu\n"
451cb94eb06SJoe Perches 		"  function = %s, file = %s, line = %u\n",
452cb94eb06SJoe Perches 		(unsigned long long)ip->i_no_formal_ino,
453dbb7cae2SSteven Whitehouse 		(unsigned long long)ip->i_no_addr,
454cb94eb06SJoe Perches 		function, file, line);
455a739765cSBob Peterson 	gfs2_dump_glock(NULL, ip->i_gl, 1);
456a5ca2f1cSAndreas Gruenbacher 	gfs2_withdraw(sdp);
457b3b94faaSDavid Teigland }
458b3b94faaSDavid Teigland 
459c551f66cSLee Jones /*
460b3b94faaSDavid Teigland  * gfs2_consist_rgrpd_i - Flag a RG consistency error and withdraw
461b3b94faaSDavid Teigland  */
462b3b94faaSDavid Teigland 
gfs2_consist_rgrpd_i(struct gfs2_rgrpd * rgd,const char * function,char * file,unsigned int line)463a5ca2f1cSAndreas Gruenbacher void gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd,
464b3b94faaSDavid Teigland 			  const char *function, char *file, unsigned int line)
465b3b94faaSDavid Teigland {
466b3b94faaSDavid Teigland 	struct gfs2_sbd *sdp = rgd->rd_sbd;
46798fb0574SBob Peterson 	char fs_id_buf[sizeof(sdp->sd_fsname) + 7];
46872244b6bSBob Peterson 
4693792ce97SBob Peterson 	sprintf(fs_id_buf, "fsid=%s: ", sdp->sd_fsname);
4700e539ca1SAndrew Price 	gfs2_rgrp_dump(NULL, rgd, fs_id_buf);
471badb55ecSAndreas Gruenbacher 	gfs2_lm(sdp,
472cb94eb06SJoe Perches 		"fatal: filesystem consistency error\n"
473cb94eb06SJoe Perches 		"  RG = %llu\n"
474cb94eb06SJoe Perches 		"  function = %s, file = %s, line = %u\n",
475cb94eb06SJoe Perches 		(unsigned long long)rgd->rd_addr,
476cb94eb06SJoe Perches 		function, file, line);
477a739765cSBob Peterson 	gfs2_dump_glock(NULL, rgd->rd_gl, 1);
478a5ca2f1cSAndreas Gruenbacher 	gfs2_withdraw(sdp);
479b3b94faaSDavid Teigland }
480b3b94faaSDavid Teigland 
481c551f66cSLee Jones /*
482b3b94faaSDavid Teigland  * gfs2_meta_check_ii - Flag a magic number consistency error and withdraw
483b3b94faaSDavid Teigland  * Returns: -1 if this call withdrew the machine,
484b3b94faaSDavid Teigland  *          -2 if it was already withdrawn
485b3b94faaSDavid Teigland  */
486b3b94faaSDavid Teigland 
gfs2_meta_check_ii(struct gfs2_sbd * sdp,struct buffer_head * bh,const char * type,const char * function,char * file,unsigned int line)487b3b94faaSDavid Teigland int gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
488b3b94faaSDavid Teigland 		       const char *type, const char *function, char *file,
489b3b94faaSDavid Teigland 		       unsigned int line)
490b3b94faaSDavid Teigland {
491b3b94faaSDavid Teigland 	int me;
492badb55ecSAndreas Gruenbacher 
493badb55ecSAndreas Gruenbacher 	gfs2_lm(sdp,
494cb94eb06SJoe Perches 		"fatal: invalid metadata block\n"
495cb94eb06SJoe Perches 		"  bh = %llu (%s)\n"
496cb94eb06SJoe Perches 		"  function = %s, file = %s, line = %u\n",
497cb94eb06SJoe Perches 		(unsigned long long)bh->b_blocknr, type,
498cb94eb06SJoe Perches 		function, file, line);
499badb55ecSAndreas Gruenbacher 	me = gfs2_withdraw(sdp);
500b3b94faaSDavid Teigland 	return (me) ? -1 : -2;
501b3b94faaSDavid Teigland }
502b3b94faaSDavid Teigland 
503c551f66cSLee Jones /*
504b3b94faaSDavid Teigland  * gfs2_metatype_check_ii - Flag a metadata type consistency error and withdraw
505b3b94faaSDavid Teigland  * Returns: -1 if this call withdrew the machine,
506b3b94faaSDavid Teigland  *          -2 if it was already withdrawn
507b3b94faaSDavid Teigland  */
508b3b94faaSDavid Teigland 
gfs2_metatype_check_ii(struct gfs2_sbd * sdp,struct buffer_head * bh,u16 type,u16 t,const char * function,char * file,unsigned int line)509b3b94faaSDavid Teigland int gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
510cd915493SSteven Whitehouse 			   u16 type, u16 t, const char *function,
511b3b94faaSDavid Teigland 			   char *file, unsigned int line)
512b3b94faaSDavid Teigland {
513b3b94faaSDavid Teigland 	int me;
514badb55ecSAndreas Gruenbacher 
515badb55ecSAndreas Gruenbacher 	gfs2_lm(sdp,
516cb94eb06SJoe Perches 		"fatal: invalid metadata block\n"
517cb94eb06SJoe Perches 		"  bh = %llu (type: exp=%u, found=%u)\n"
518cb94eb06SJoe Perches 		"  function = %s, file = %s, line = %u\n",
519cb94eb06SJoe Perches 		(unsigned long long)bh->b_blocknr, type, t,
520cb94eb06SJoe Perches 		function, file, line);
521badb55ecSAndreas Gruenbacher 	me = gfs2_withdraw(sdp);
522b3b94faaSDavid Teigland 	return (me) ? -1 : -2;
523b3b94faaSDavid Teigland }
524b3b94faaSDavid Teigland 
525c551f66cSLee Jones /*
526b3b94faaSDavid Teigland  * gfs2_io_error_i - Flag an I/O error and withdraw
527b3b94faaSDavid Teigland  * Returns: -1 if this call withdrew the machine,
528b3b94faaSDavid Teigland  *          0 if it was already withdrawn
529b3b94faaSDavid Teigland  */
530b3b94faaSDavid Teigland 
gfs2_io_error_i(struct gfs2_sbd * sdp,const char * function,char * file,unsigned int line)531b3b94faaSDavid Teigland int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function, char *file,
532b3b94faaSDavid Teigland 		    unsigned int line)
533b3b94faaSDavid Teigland {
534badb55ecSAndreas Gruenbacher 	gfs2_lm(sdp,
535cb94eb06SJoe Perches 		"fatal: I/O error\n"
536cb94eb06SJoe Perches 		"  function = %s, file = %s, line = %u\n",
537cb94eb06SJoe Perches 		function, file, line);
538badb55ecSAndreas Gruenbacher 	return gfs2_withdraw(sdp);
539b3b94faaSDavid Teigland }
540b3b94faaSDavid Teigland 
541c551f66cSLee Jones /*
5429e1a9ecdSAndreas Gruenbacher  * gfs2_io_error_bh_i - Flag a buffer I/O error
5439e1a9ecdSAndreas Gruenbacher  * @withdraw: withdraw the filesystem
544b3b94faaSDavid Teigland  */
545b3b94faaSDavid Teigland 
gfs2_io_error_bh_i(struct gfs2_sbd * sdp,struct buffer_head * bh,const char * function,char * file,unsigned int line,bool withdraw)5469e1a9ecdSAndreas Gruenbacher void gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh,
5479e1a9ecdSAndreas Gruenbacher 			const char *function, char *file, unsigned int line,
5489e1a9ecdSAndreas Gruenbacher 			bool withdraw)
549b3b94faaSDavid Teigland {
550d6b412c5SAndreas Gruenbacher 	if (gfs2_withdrawing_or_withdrawn(sdp))
55169511080SBob Peterson 		return;
55269511080SBob Peterson 
55369511080SBob Peterson 	fs_err(sdp, "fatal: I/O error\n"
554cb94eb06SJoe Perches 	       "  block = %llu\n"
555cb94eb06SJoe Perches 	       "  function = %s, file = %s, line = %u\n",
55669511080SBob Peterson 	       (unsigned long long)bh->b_blocknr, function, file, line);
5579e1a9ecdSAndreas Gruenbacher 	if (withdraw)
558badb55ecSAndreas Gruenbacher 		gfs2_withdraw(sdp);
559b3b94faaSDavid Teigland }
560b3b94faaSDavid Teigland 
561