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