xref: /openbmc/linux/fs/gfs2/util.c (revision 96de2506)
1 /*
2  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3  * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
4  *
5  * This copyrighted material is made available to anyone wishing to use,
6  * modify, copy, or redistribute it subject to the terms and conditions
7  * of the GNU General Public License version 2.
8  */
9 
10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11 
12 #include <linux/spinlock.h>
13 #include <linux/completion.h>
14 #include <linux/buffer_head.h>
15 #include <linux/crc32.h>
16 #include <linux/gfs2_ondisk.h>
17 #include <linux/uaccess.h>
18 
19 #include "gfs2.h"
20 #include "incore.h"
21 #include "glock.h"
22 #include "util.h"
23 
24 struct kmem_cache *gfs2_glock_cachep __read_mostly;
25 struct kmem_cache *gfs2_glock_aspace_cachep __read_mostly;
26 struct kmem_cache *gfs2_inode_cachep __read_mostly;
27 struct kmem_cache *gfs2_bufdata_cachep __read_mostly;
28 struct kmem_cache *gfs2_rgrpd_cachep __read_mostly;
29 struct kmem_cache *gfs2_quotad_cachep __read_mostly;
30 struct kmem_cache *gfs2_qadata_cachep __read_mostly;
31 mempool_t *gfs2_page_pool __read_mostly;
32 
33 void gfs2_assert_i(struct gfs2_sbd *sdp)
34 {
35 	fs_emerg(sdp, "fatal assertion failed\n");
36 }
37 
38 int gfs2_lm_withdraw(struct gfs2_sbd *sdp, const char *fmt, ...)
39 {
40 	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
41 	const struct lm_lockops *lm = ls->ls_ops;
42 	va_list args;
43 	struct va_format vaf;
44 
45 	if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW &&
46 	    test_and_set_bit(SDF_SHUTDOWN, &sdp->sd_flags))
47 		return 0;
48 
49 	if (fmt) {
50 		va_start(args, fmt);
51 
52 		vaf.fmt = fmt;
53 		vaf.va = &args;
54 
55 		fs_err(sdp, "%pV", &vaf);
56 
57 		va_end(args);
58 	}
59 
60 	if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW) {
61 		fs_err(sdp, "about to withdraw this file system\n");
62 		BUG_ON(sdp->sd_args.ar_debug);
63 
64 		kobject_uevent(&sdp->sd_kobj, KOBJ_OFFLINE);
65 
66 		if (!strcmp(sdp->sd_lockstruct.ls_ops->lm_proto_name, "lock_dlm"))
67 			wait_for_completion(&sdp->sd_wdack);
68 
69 		if (lm->lm_unmount) {
70 			fs_err(sdp, "telling LM to unmount\n");
71 			lm->lm_unmount(sdp);
72 		}
73 		set_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags);
74 		fs_err(sdp, "withdrawn\n");
75 		dump_stack();
76 	}
77 
78 	if (sdp->sd_args.ar_errors == GFS2_ERRORS_PANIC)
79 		panic("GFS2: fsid=%s: panic requested\n", sdp->sd_fsname);
80 
81 	return -1;
82 }
83 
84 /**
85  * gfs2_assert_withdraw_i - Cause the machine to withdraw if @assertion is false
86  * Returns: -1 if this call withdrew the machine,
87  *          -2 if it was already withdrawn
88  */
89 
90 int gfs2_assert_withdraw_i(struct gfs2_sbd *sdp, char *assertion,
91 			   const char *function, char *file, unsigned int line)
92 {
93 	int me;
94 	me = gfs2_lm_withdraw(sdp,
95 			      "fatal: assertion \"%s\" failed\n"
96 			      "   function = %s, file = %s, line = %u\n",
97 			      assertion, function, file, line);
98 	dump_stack();
99 	return (me) ? -1 : -2;
100 }
101 
102 /**
103  * gfs2_assert_warn_i - Print a message to the console if @assertion is false
104  * Returns: -1 if we printed something
105  *          -2 if we didn't
106  */
107 
108 int gfs2_assert_warn_i(struct gfs2_sbd *sdp, char *assertion,
109 		       const char *function, char *file, unsigned int line)
110 {
111 	if (time_before(jiffies,
112 			sdp->sd_last_warning +
113 			gfs2_tune_get(sdp, gt_complain_secs) * HZ))
114 		return -2;
115 
116 	if (sdp->sd_args.ar_errors == GFS2_ERRORS_WITHDRAW)
117 		fs_warn(sdp, "warning: assertion \"%s\" failed at function = %s, file = %s, line = %u\n",
118 			assertion, function, file, line);
119 
120 	if (sdp->sd_args.ar_debug)
121 		BUG();
122 	else
123 		dump_stack();
124 
125 	if (sdp->sd_args.ar_errors == GFS2_ERRORS_PANIC)
126 		panic("GFS2: fsid=%s: warning: assertion \"%s\" failed\n"
127 		      "GFS2: fsid=%s:   function = %s, file = %s, line = %u\n",
128 		      sdp->sd_fsname, assertion,
129 		      sdp->sd_fsname, function, file, line);
130 
131 	sdp->sd_last_warning = jiffies;
132 
133 	return -1;
134 }
135 
136 /**
137  * gfs2_consist_i - Flag a filesystem consistency error and withdraw
138  * Returns: -1 if this call withdrew the machine,
139  *          0 if it was already withdrawn
140  */
141 
142 int gfs2_consist_i(struct gfs2_sbd *sdp, int cluster_wide, const char *function,
143 		   char *file, unsigned int line)
144 {
145 	int rv;
146 	rv = gfs2_lm_withdraw(sdp,
147 			      "fatal: filesystem consistency error - function = %s, file = %s, line = %u\n",
148 			      function, file, line);
149 	return rv;
150 }
151 
152 /**
153  * gfs2_consist_inode_i - Flag an inode consistency error and withdraw
154  * Returns: -1 if this call withdrew the machine,
155  *          0 if it was already withdrawn
156  */
157 
158 int gfs2_consist_inode_i(struct gfs2_inode *ip, int cluster_wide,
159 			 const char *function, char *file, unsigned int line)
160 {
161 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
162 	int rv;
163 	rv = gfs2_lm_withdraw(sdp,
164 			      "fatal: filesystem consistency error\n"
165 			      "  inode = %llu %llu\n"
166 			      "  function = %s, file = %s, line = %u\n",
167 			      (unsigned long long)ip->i_no_formal_ino,
168 			      (unsigned long long)ip->i_no_addr,
169 			      function, file, line);
170 	return rv;
171 }
172 
173 /**
174  * gfs2_consist_rgrpd_i - Flag a RG consistency error and withdraw
175  * Returns: -1 if this call withdrew the machine,
176  *          0 if it was already withdrawn
177  */
178 
179 int gfs2_consist_rgrpd_i(struct gfs2_rgrpd *rgd, int cluster_wide,
180 			 const char *function, char *file, unsigned int line)
181 {
182 	struct gfs2_sbd *sdp = rgd->rd_sbd;
183 	int rv;
184 	rv = gfs2_lm_withdraw(sdp,
185 			      "fatal: filesystem consistency error\n"
186 			      "  RG = %llu\n"
187 			      "  function = %s, file = %s, line = %u\n",
188 			      (unsigned long long)rgd->rd_addr,
189 			      function, file, line);
190 	return rv;
191 }
192 
193 /**
194  * gfs2_meta_check_ii - Flag a magic number consistency error and withdraw
195  * Returns: -1 if this call withdrew the machine,
196  *          -2 if it was already withdrawn
197  */
198 
199 int gfs2_meta_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
200 		       const char *type, const char *function, char *file,
201 		       unsigned int line)
202 {
203 	int me;
204 	me = gfs2_lm_withdraw(sdp,
205 			      "fatal: invalid metadata block\n"
206 			      "  bh = %llu (%s)\n"
207 			      "  function = %s, file = %s, line = %u\n",
208 			      (unsigned long long)bh->b_blocknr, type,
209 			      function, file, line);
210 	return (me) ? -1 : -2;
211 }
212 
213 /**
214  * gfs2_metatype_check_ii - Flag a metadata type consistency error and withdraw
215  * Returns: -1 if this call withdrew the machine,
216  *          -2 if it was already withdrawn
217  */
218 
219 int gfs2_metatype_check_ii(struct gfs2_sbd *sdp, struct buffer_head *bh,
220 			   u16 type, u16 t, const char *function,
221 			   char *file, unsigned int line)
222 {
223 	int me;
224 	me = gfs2_lm_withdraw(sdp,
225 			      "fatal: invalid metadata block\n"
226 			      "  bh = %llu (type: exp=%u, found=%u)\n"
227 			      "  function = %s, file = %s, line = %u\n",
228 			      (unsigned long long)bh->b_blocknr, type, t,
229 			      function, file, line);
230 	return (me) ? -1 : -2;
231 }
232 
233 /**
234  * gfs2_io_error_i - Flag an I/O error and withdraw
235  * Returns: -1 if this call withdrew the machine,
236  *          0 if it was already withdrawn
237  */
238 
239 int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function, char *file,
240 		    unsigned int line)
241 {
242 	int rv;
243 	rv = gfs2_lm_withdraw(sdp,
244 			      "fatal: I/O error\n"
245 			      "  function = %s, file = %s, line = %u\n",
246 			      function, file, line);
247 	return rv;
248 }
249 
250 /**
251  * gfs2_io_error_bh_i - Flag a buffer I/O error
252  * @withdraw: withdraw the filesystem
253  */
254 
255 void gfs2_io_error_bh_i(struct gfs2_sbd *sdp, struct buffer_head *bh,
256 			const char *function, char *file, unsigned int line,
257 			bool withdraw)
258 {
259 	fs_err(sdp,
260 	       "fatal: I/O error\n"
261 	       "  block = %llu\n"
262 	       "  function = %s, file = %s, line = %u\n",
263 	       (unsigned long long)bh->b_blocknr,
264 	       function, file, line);
265 	if (withdraw)
266 		gfs2_lm_withdraw(sdp, NULL);
267 }
268 
269