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