1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (c) 2000-2006 Silicon Graphics, Inc.
4*4882a593Smuzhiyun * All Rights Reserved.
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include "xfs.h"
8*4882a593Smuzhiyun #include "xfs_shared.h"
9*4882a593Smuzhiyun #include "xfs_format.h"
10*4882a593Smuzhiyun #include "xfs_log_format.h"
11*4882a593Smuzhiyun #include "xfs_trans_resv.h"
12*4882a593Smuzhiyun #include "xfs_sb.h"
13*4882a593Smuzhiyun #include "xfs_mount.h"
14*4882a593Smuzhiyun #include "xfs_inode.h"
15*4882a593Smuzhiyun #include "xfs_btree.h"
16*4882a593Smuzhiyun #include "xfs_bmap.h"
17*4882a593Smuzhiyun #include "xfs_alloc.h"
18*4882a593Smuzhiyun #include "xfs_fsops.h"
19*4882a593Smuzhiyun #include "xfs_trans.h"
20*4882a593Smuzhiyun #include "xfs_buf_item.h"
21*4882a593Smuzhiyun #include "xfs_log.h"
22*4882a593Smuzhiyun #include "xfs_log_priv.h"
23*4882a593Smuzhiyun #include "xfs_dir2.h"
24*4882a593Smuzhiyun #include "xfs_extfree_item.h"
25*4882a593Smuzhiyun #include "xfs_mru_cache.h"
26*4882a593Smuzhiyun #include "xfs_inode_item.h"
27*4882a593Smuzhiyun #include "xfs_icache.h"
28*4882a593Smuzhiyun #include "xfs_trace.h"
29*4882a593Smuzhiyun #include "xfs_icreate_item.h"
30*4882a593Smuzhiyun #include "xfs_filestream.h"
31*4882a593Smuzhiyun #include "xfs_quota.h"
32*4882a593Smuzhiyun #include "xfs_sysfs.h"
33*4882a593Smuzhiyun #include "xfs_ondisk.h"
34*4882a593Smuzhiyun #include "xfs_rmap_item.h"
35*4882a593Smuzhiyun #include "xfs_refcount_item.h"
36*4882a593Smuzhiyun #include "xfs_bmap_item.h"
37*4882a593Smuzhiyun #include "xfs_reflink.h"
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #include <linux/magic.h>
40*4882a593Smuzhiyun #include <linux/fs_context.h>
41*4882a593Smuzhiyun #include <linux/fs_parser.h>
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun static const struct super_operations xfs_super_operations;
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun static struct kset *xfs_kset; /* top-level xfs sysfs dir */
46*4882a593Smuzhiyun #ifdef DEBUG
47*4882a593Smuzhiyun static struct xfs_kobj xfs_dbg_kobj; /* global debug sysfs attrs */
48*4882a593Smuzhiyun #endif
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun enum xfs_dax_mode {
51*4882a593Smuzhiyun XFS_DAX_INODE = 0,
52*4882a593Smuzhiyun XFS_DAX_ALWAYS = 1,
53*4882a593Smuzhiyun XFS_DAX_NEVER = 2,
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun static void
xfs_mount_set_dax_mode(struct xfs_mount * mp,enum xfs_dax_mode mode)57*4882a593Smuzhiyun xfs_mount_set_dax_mode(
58*4882a593Smuzhiyun struct xfs_mount *mp,
59*4882a593Smuzhiyun enum xfs_dax_mode mode)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun switch (mode) {
62*4882a593Smuzhiyun case XFS_DAX_INODE:
63*4882a593Smuzhiyun mp->m_flags &= ~(XFS_MOUNT_DAX_ALWAYS | XFS_MOUNT_DAX_NEVER);
64*4882a593Smuzhiyun break;
65*4882a593Smuzhiyun case XFS_DAX_ALWAYS:
66*4882a593Smuzhiyun mp->m_flags |= XFS_MOUNT_DAX_ALWAYS;
67*4882a593Smuzhiyun mp->m_flags &= ~XFS_MOUNT_DAX_NEVER;
68*4882a593Smuzhiyun break;
69*4882a593Smuzhiyun case XFS_DAX_NEVER:
70*4882a593Smuzhiyun mp->m_flags |= XFS_MOUNT_DAX_NEVER;
71*4882a593Smuzhiyun mp->m_flags &= ~XFS_MOUNT_DAX_ALWAYS;
72*4882a593Smuzhiyun break;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun static const struct constant_table dax_param_enums[] = {
77*4882a593Smuzhiyun {"inode", XFS_DAX_INODE },
78*4882a593Smuzhiyun {"always", XFS_DAX_ALWAYS },
79*4882a593Smuzhiyun {"never", XFS_DAX_NEVER },
80*4882a593Smuzhiyun {}
81*4882a593Smuzhiyun };
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun /*
84*4882a593Smuzhiyun * Table driven mount option parser.
85*4882a593Smuzhiyun */
86*4882a593Smuzhiyun enum {
87*4882a593Smuzhiyun Opt_logbufs, Opt_logbsize, Opt_logdev, Opt_rtdev,
88*4882a593Smuzhiyun Opt_wsync, Opt_noalign, Opt_swalloc, Opt_sunit, Opt_swidth, Opt_nouuid,
89*4882a593Smuzhiyun Opt_grpid, Opt_nogrpid, Opt_bsdgroups, Opt_sysvgroups,
90*4882a593Smuzhiyun Opt_allocsize, Opt_norecovery, Opt_inode64, Opt_inode32, Opt_ikeep,
91*4882a593Smuzhiyun Opt_noikeep, Opt_largeio, Opt_nolargeio, Opt_attr2, Opt_noattr2,
92*4882a593Smuzhiyun Opt_filestreams, Opt_quota, Opt_noquota, Opt_usrquota, Opt_grpquota,
93*4882a593Smuzhiyun Opt_prjquota, Opt_uquota, Opt_gquota, Opt_pquota,
94*4882a593Smuzhiyun Opt_uqnoenforce, Opt_gqnoenforce, Opt_pqnoenforce, Opt_qnoenforce,
95*4882a593Smuzhiyun Opt_discard, Opt_nodiscard, Opt_dax, Opt_dax_enum,
96*4882a593Smuzhiyun };
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun static const struct fs_parameter_spec xfs_fs_parameters[] = {
99*4882a593Smuzhiyun fsparam_u32("logbufs", Opt_logbufs),
100*4882a593Smuzhiyun fsparam_string("logbsize", Opt_logbsize),
101*4882a593Smuzhiyun fsparam_string("logdev", Opt_logdev),
102*4882a593Smuzhiyun fsparam_string("rtdev", Opt_rtdev),
103*4882a593Smuzhiyun fsparam_flag("wsync", Opt_wsync),
104*4882a593Smuzhiyun fsparam_flag("noalign", Opt_noalign),
105*4882a593Smuzhiyun fsparam_flag("swalloc", Opt_swalloc),
106*4882a593Smuzhiyun fsparam_u32("sunit", Opt_sunit),
107*4882a593Smuzhiyun fsparam_u32("swidth", Opt_swidth),
108*4882a593Smuzhiyun fsparam_flag("nouuid", Opt_nouuid),
109*4882a593Smuzhiyun fsparam_flag("grpid", Opt_grpid),
110*4882a593Smuzhiyun fsparam_flag("nogrpid", Opt_nogrpid),
111*4882a593Smuzhiyun fsparam_flag("bsdgroups", Opt_bsdgroups),
112*4882a593Smuzhiyun fsparam_flag("sysvgroups", Opt_sysvgroups),
113*4882a593Smuzhiyun fsparam_string("allocsize", Opt_allocsize),
114*4882a593Smuzhiyun fsparam_flag("norecovery", Opt_norecovery),
115*4882a593Smuzhiyun fsparam_flag("inode64", Opt_inode64),
116*4882a593Smuzhiyun fsparam_flag("inode32", Opt_inode32),
117*4882a593Smuzhiyun fsparam_flag("ikeep", Opt_ikeep),
118*4882a593Smuzhiyun fsparam_flag("noikeep", Opt_noikeep),
119*4882a593Smuzhiyun fsparam_flag("largeio", Opt_largeio),
120*4882a593Smuzhiyun fsparam_flag("nolargeio", Opt_nolargeio),
121*4882a593Smuzhiyun fsparam_flag("attr2", Opt_attr2),
122*4882a593Smuzhiyun fsparam_flag("noattr2", Opt_noattr2),
123*4882a593Smuzhiyun fsparam_flag("filestreams", Opt_filestreams),
124*4882a593Smuzhiyun fsparam_flag("quota", Opt_quota),
125*4882a593Smuzhiyun fsparam_flag("noquota", Opt_noquota),
126*4882a593Smuzhiyun fsparam_flag("usrquota", Opt_usrquota),
127*4882a593Smuzhiyun fsparam_flag("grpquota", Opt_grpquota),
128*4882a593Smuzhiyun fsparam_flag("prjquota", Opt_prjquota),
129*4882a593Smuzhiyun fsparam_flag("uquota", Opt_uquota),
130*4882a593Smuzhiyun fsparam_flag("gquota", Opt_gquota),
131*4882a593Smuzhiyun fsparam_flag("pquota", Opt_pquota),
132*4882a593Smuzhiyun fsparam_flag("uqnoenforce", Opt_uqnoenforce),
133*4882a593Smuzhiyun fsparam_flag("gqnoenforce", Opt_gqnoenforce),
134*4882a593Smuzhiyun fsparam_flag("pqnoenforce", Opt_pqnoenforce),
135*4882a593Smuzhiyun fsparam_flag("qnoenforce", Opt_qnoenforce),
136*4882a593Smuzhiyun fsparam_flag("discard", Opt_discard),
137*4882a593Smuzhiyun fsparam_flag("nodiscard", Opt_nodiscard),
138*4882a593Smuzhiyun fsparam_flag("dax", Opt_dax),
139*4882a593Smuzhiyun fsparam_enum("dax", Opt_dax_enum, dax_param_enums),
140*4882a593Smuzhiyun {}
141*4882a593Smuzhiyun };
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun struct proc_xfs_info {
144*4882a593Smuzhiyun uint64_t flag;
145*4882a593Smuzhiyun char *str;
146*4882a593Smuzhiyun };
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun static int
xfs_fs_show_options(struct seq_file * m,struct dentry * root)149*4882a593Smuzhiyun xfs_fs_show_options(
150*4882a593Smuzhiyun struct seq_file *m,
151*4882a593Smuzhiyun struct dentry *root)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun static struct proc_xfs_info xfs_info_set[] = {
154*4882a593Smuzhiyun /* the few simple ones we can get from the mount struct */
155*4882a593Smuzhiyun { XFS_MOUNT_IKEEP, ",ikeep" },
156*4882a593Smuzhiyun { XFS_MOUNT_WSYNC, ",wsync" },
157*4882a593Smuzhiyun { XFS_MOUNT_NOALIGN, ",noalign" },
158*4882a593Smuzhiyun { XFS_MOUNT_SWALLOC, ",swalloc" },
159*4882a593Smuzhiyun { XFS_MOUNT_NOUUID, ",nouuid" },
160*4882a593Smuzhiyun { XFS_MOUNT_NORECOVERY, ",norecovery" },
161*4882a593Smuzhiyun { XFS_MOUNT_ATTR2, ",attr2" },
162*4882a593Smuzhiyun { XFS_MOUNT_FILESTREAMS, ",filestreams" },
163*4882a593Smuzhiyun { XFS_MOUNT_GRPID, ",grpid" },
164*4882a593Smuzhiyun { XFS_MOUNT_DISCARD, ",discard" },
165*4882a593Smuzhiyun { XFS_MOUNT_LARGEIO, ",largeio" },
166*4882a593Smuzhiyun { XFS_MOUNT_DAX_ALWAYS, ",dax=always" },
167*4882a593Smuzhiyun { XFS_MOUNT_DAX_NEVER, ",dax=never" },
168*4882a593Smuzhiyun { 0, NULL }
169*4882a593Smuzhiyun };
170*4882a593Smuzhiyun struct xfs_mount *mp = XFS_M(root->d_sb);
171*4882a593Smuzhiyun struct proc_xfs_info *xfs_infop;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun for (xfs_infop = xfs_info_set; xfs_infop->flag; xfs_infop++) {
174*4882a593Smuzhiyun if (mp->m_flags & xfs_infop->flag)
175*4882a593Smuzhiyun seq_puts(m, xfs_infop->str);
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun seq_printf(m, ",inode%d",
179*4882a593Smuzhiyun (mp->m_flags & XFS_MOUNT_SMALL_INUMS) ? 32 : 64);
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun if (mp->m_flags & XFS_MOUNT_ALLOCSIZE)
182*4882a593Smuzhiyun seq_printf(m, ",allocsize=%dk",
183*4882a593Smuzhiyun (1 << mp->m_allocsize_log) >> 10);
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun if (mp->m_logbufs > 0)
186*4882a593Smuzhiyun seq_printf(m, ",logbufs=%d", mp->m_logbufs);
187*4882a593Smuzhiyun if (mp->m_logbsize > 0)
188*4882a593Smuzhiyun seq_printf(m, ",logbsize=%dk", mp->m_logbsize >> 10);
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun if (mp->m_logname)
191*4882a593Smuzhiyun seq_show_option(m, "logdev", mp->m_logname);
192*4882a593Smuzhiyun if (mp->m_rtname)
193*4882a593Smuzhiyun seq_show_option(m, "rtdev", mp->m_rtname);
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun if (mp->m_dalign > 0)
196*4882a593Smuzhiyun seq_printf(m, ",sunit=%d",
197*4882a593Smuzhiyun (int)XFS_FSB_TO_BB(mp, mp->m_dalign));
198*4882a593Smuzhiyun if (mp->m_swidth > 0)
199*4882a593Smuzhiyun seq_printf(m, ",swidth=%d",
200*4882a593Smuzhiyun (int)XFS_FSB_TO_BB(mp, mp->m_swidth));
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun if (mp->m_qflags & XFS_UQUOTA_ACCT) {
203*4882a593Smuzhiyun if (mp->m_qflags & XFS_UQUOTA_ENFD)
204*4882a593Smuzhiyun seq_puts(m, ",usrquota");
205*4882a593Smuzhiyun else
206*4882a593Smuzhiyun seq_puts(m, ",uqnoenforce");
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun if (mp->m_qflags & XFS_PQUOTA_ACCT) {
210*4882a593Smuzhiyun if (mp->m_qflags & XFS_PQUOTA_ENFD)
211*4882a593Smuzhiyun seq_puts(m, ",prjquota");
212*4882a593Smuzhiyun else
213*4882a593Smuzhiyun seq_puts(m, ",pqnoenforce");
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun if (mp->m_qflags & XFS_GQUOTA_ACCT) {
216*4882a593Smuzhiyun if (mp->m_qflags & XFS_GQUOTA_ENFD)
217*4882a593Smuzhiyun seq_puts(m, ",grpquota");
218*4882a593Smuzhiyun else
219*4882a593Smuzhiyun seq_puts(m, ",gqnoenforce");
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
223*4882a593Smuzhiyun seq_puts(m, ",noquota");
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun return 0;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun /*
229*4882a593Smuzhiyun * Set parameters for inode allocation heuristics, taking into account
230*4882a593Smuzhiyun * filesystem size and inode32/inode64 mount options; i.e. specifically
231*4882a593Smuzhiyun * whether or not XFS_MOUNT_SMALL_INUMS is set.
232*4882a593Smuzhiyun *
233*4882a593Smuzhiyun * Inode allocation patterns are altered only if inode32 is requested
234*4882a593Smuzhiyun * (XFS_MOUNT_SMALL_INUMS), and the filesystem is sufficiently large.
235*4882a593Smuzhiyun * If altered, XFS_MOUNT_32BITINODES is set as well.
236*4882a593Smuzhiyun *
237*4882a593Smuzhiyun * An agcount independent of that in the mount structure is provided
238*4882a593Smuzhiyun * because in the growfs case, mp->m_sb.sb_agcount is not yet updated
239*4882a593Smuzhiyun * to the potentially higher ag count.
240*4882a593Smuzhiyun *
241*4882a593Smuzhiyun * Returns the maximum AG index which may contain inodes.
242*4882a593Smuzhiyun */
243*4882a593Smuzhiyun xfs_agnumber_t
xfs_set_inode_alloc(struct xfs_mount * mp,xfs_agnumber_t agcount)244*4882a593Smuzhiyun xfs_set_inode_alloc(
245*4882a593Smuzhiyun struct xfs_mount *mp,
246*4882a593Smuzhiyun xfs_agnumber_t agcount)
247*4882a593Smuzhiyun {
248*4882a593Smuzhiyun xfs_agnumber_t index;
249*4882a593Smuzhiyun xfs_agnumber_t maxagi = 0;
250*4882a593Smuzhiyun xfs_sb_t *sbp = &mp->m_sb;
251*4882a593Smuzhiyun xfs_agnumber_t max_metadata;
252*4882a593Smuzhiyun xfs_agino_t agino;
253*4882a593Smuzhiyun xfs_ino_t ino;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun /*
256*4882a593Smuzhiyun * Calculate how much should be reserved for inodes to meet
257*4882a593Smuzhiyun * the max inode percentage. Used only for inode32.
258*4882a593Smuzhiyun */
259*4882a593Smuzhiyun if (M_IGEO(mp)->maxicount) {
260*4882a593Smuzhiyun uint64_t icount;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun icount = sbp->sb_dblocks * sbp->sb_imax_pct;
263*4882a593Smuzhiyun do_div(icount, 100);
264*4882a593Smuzhiyun icount += sbp->sb_agblocks - 1;
265*4882a593Smuzhiyun do_div(icount, sbp->sb_agblocks);
266*4882a593Smuzhiyun max_metadata = icount;
267*4882a593Smuzhiyun } else {
268*4882a593Smuzhiyun max_metadata = agcount;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun /* Get the last possible inode in the filesystem */
272*4882a593Smuzhiyun agino = XFS_AGB_TO_AGINO(mp, sbp->sb_agblocks - 1);
273*4882a593Smuzhiyun ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun /*
276*4882a593Smuzhiyun * If user asked for no more than 32-bit inodes, and the fs is
277*4882a593Smuzhiyun * sufficiently large, set XFS_MOUNT_32BITINODES if we must alter
278*4882a593Smuzhiyun * the allocator to accommodate the request.
279*4882a593Smuzhiyun */
280*4882a593Smuzhiyun if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > XFS_MAXINUMBER_32)
281*4882a593Smuzhiyun mp->m_flags |= XFS_MOUNT_32BITINODES;
282*4882a593Smuzhiyun else
283*4882a593Smuzhiyun mp->m_flags &= ~XFS_MOUNT_32BITINODES;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun for (index = 0; index < agcount; index++) {
286*4882a593Smuzhiyun struct xfs_perag *pag;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun ino = XFS_AGINO_TO_INO(mp, index, agino);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun pag = xfs_perag_get(mp, index);
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun if (mp->m_flags & XFS_MOUNT_32BITINODES) {
293*4882a593Smuzhiyun if (ino > XFS_MAXINUMBER_32) {
294*4882a593Smuzhiyun pag->pagi_inodeok = 0;
295*4882a593Smuzhiyun pag->pagf_metadata = 0;
296*4882a593Smuzhiyun } else {
297*4882a593Smuzhiyun pag->pagi_inodeok = 1;
298*4882a593Smuzhiyun maxagi++;
299*4882a593Smuzhiyun if (index < max_metadata)
300*4882a593Smuzhiyun pag->pagf_metadata = 1;
301*4882a593Smuzhiyun else
302*4882a593Smuzhiyun pag->pagf_metadata = 0;
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun } else {
305*4882a593Smuzhiyun pag->pagi_inodeok = 1;
306*4882a593Smuzhiyun pag->pagf_metadata = 0;
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun xfs_perag_put(pag);
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun return (mp->m_flags & XFS_MOUNT_32BITINODES) ? maxagi : agcount;
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun STATIC int
xfs_blkdev_get(xfs_mount_t * mp,const char * name,struct block_device ** bdevp)316*4882a593Smuzhiyun xfs_blkdev_get(
317*4882a593Smuzhiyun xfs_mount_t *mp,
318*4882a593Smuzhiyun const char *name,
319*4882a593Smuzhiyun struct block_device **bdevp)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun int error = 0;
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun *bdevp = blkdev_get_by_path(name, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
324*4882a593Smuzhiyun mp);
325*4882a593Smuzhiyun if (IS_ERR(*bdevp)) {
326*4882a593Smuzhiyun error = PTR_ERR(*bdevp);
327*4882a593Smuzhiyun xfs_warn(mp, "Invalid device [%s], error=%d", name, error);
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun return error;
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun STATIC void
xfs_blkdev_put(struct block_device * bdev)334*4882a593Smuzhiyun xfs_blkdev_put(
335*4882a593Smuzhiyun struct block_device *bdev)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun if (bdev)
338*4882a593Smuzhiyun blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun void
xfs_blkdev_issue_flush(xfs_buftarg_t * buftarg)342*4882a593Smuzhiyun xfs_blkdev_issue_flush(
343*4882a593Smuzhiyun xfs_buftarg_t *buftarg)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun blkdev_issue_flush(buftarg->bt_bdev, GFP_NOFS);
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun STATIC void
xfs_close_devices(struct xfs_mount * mp)349*4882a593Smuzhiyun xfs_close_devices(
350*4882a593Smuzhiyun struct xfs_mount *mp)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun struct dax_device *dax_ddev = mp->m_ddev_targp->bt_daxdev;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) {
355*4882a593Smuzhiyun struct block_device *logdev = mp->m_logdev_targp->bt_bdev;
356*4882a593Smuzhiyun struct dax_device *dax_logdev = mp->m_logdev_targp->bt_daxdev;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun xfs_free_buftarg(mp->m_logdev_targp);
359*4882a593Smuzhiyun xfs_blkdev_put(logdev);
360*4882a593Smuzhiyun fs_put_dax(dax_logdev);
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun if (mp->m_rtdev_targp) {
363*4882a593Smuzhiyun struct block_device *rtdev = mp->m_rtdev_targp->bt_bdev;
364*4882a593Smuzhiyun struct dax_device *dax_rtdev = mp->m_rtdev_targp->bt_daxdev;
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun xfs_free_buftarg(mp->m_rtdev_targp);
367*4882a593Smuzhiyun xfs_blkdev_put(rtdev);
368*4882a593Smuzhiyun fs_put_dax(dax_rtdev);
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun xfs_free_buftarg(mp->m_ddev_targp);
371*4882a593Smuzhiyun fs_put_dax(dax_ddev);
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun /*
375*4882a593Smuzhiyun * The file system configurations are:
376*4882a593Smuzhiyun * (1) device (partition) with data and internal log
377*4882a593Smuzhiyun * (2) logical volume with data and log subvolumes.
378*4882a593Smuzhiyun * (3) logical volume with data, log, and realtime subvolumes.
379*4882a593Smuzhiyun *
380*4882a593Smuzhiyun * We only have to handle opening the log and realtime volumes here if
381*4882a593Smuzhiyun * they are present. The data subvolume has already been opened by
382*4882a593Smuzhiyun * get_sb_bdev() and is stored in sb->s_bdev.
383*4882a593Smuzhiyun */
384*4882a593Smuzhiyun STATIC int
xfs_open_devices(struct xfs_mount * mp)385*4882a593Smuzhiyun xfs_open_devices(
386*4882a593Smuzhiyun struct xfs_mount *mp)
387*4882a593Smuzhiyun {
388*4882a593Smuzhiyun struct block_device *ddev = mp->m_super->s_bdev;
389*4882a593Smuzhiyun struct dax_device *dax_ddev = fs_dax_get_by_bdev(ddev);
390*4882a593Smuzhiyun struct dax_device *dax_logdev = NULL, *dax_rtdev = NULL;
391*4882a593Smuzhiyun struct block_device *logdev = NULL, *rtdev = NULL;
392*4882a593Smuzhiyun int error;
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun /*
395*4882a593Smuzhiyun * Open real time and log devices - order is important.
396*4882a593Smuzhiyun */
397*4882a593Smuzhiyun if (mp->m_logname) {
398*4882a593Smuzhiyun error = xfs_blkdev_get(mp, mp->m_logname, &logdev);
399*4882a593Smuzhiyun if (error)
400*4882a593Smuzhiyun goto out;
401*4882a593Smuzhiyun dax_logdev = fs_dax_get_by_bdev(logdev);
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun if (mp->m_rtname) {
405*4882a593Smuzhiyun error = xfs_blkdev_get(mp, mp->m_rtname, &rtdev);
406*4882a593Smuzhiyun if (error)
407*4882a593Smuzhiyun goto out_close_logdev;
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun if (rtdev == ddev || rtdev == logdev) {
410*4882a593Smuzhiyun xfs_warn(mp,
411*4882a593Smuzhiyun "Cannot mount filesystem with identical rtdev and ddev/logdev.");
412*4882a593Smuzhiyun error = -EINVAL;
413*4882a593Smuzhiyun goto out_close_rtdev;
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun dax_rtdev = fs_dax_get_by_bdev(rtdev);
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun /*
419*4882a593Smuzhiyun * Setup xfs_mount buffer target pointers
420*4882a593Smuzhiyun */
421*4882a593Smuzhiyun error = -ENOMEM;
422*4882a593Smuzhiyun mp->m_ddev_targp = xfs_alloc_buftarg(mp, ddev, dax_ddev);
423*4882a593Smuzhiyun if (!mp->m_ddev_targp)
424*4882a593Smuzhiyun goto out_close_rtdev;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun if (rtdev) {
427*4882a593Smuzhiyun mp->m_rtdev_targp = xfs_alloc_buftarg(mp, rtdev, dax_rtdev);
428*4882a593Smuzhiyun if (!mp->m_rtdev_targp)
429*4882a593Smuzhiyun goto out_free_ddev_targ;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun if (logdev && logdev != ddev) {
433*4882a593Smuzhiyun mp->m_logdev_targp = xfs_alloc_buftarg(mp, logdev, dax_logdev);
434*4882a593Smuzhiyun if (!mp->m_logdev_targp)
435*4882a593Smuzhiyun goto out_free_rtdev_targ;
436*4882a593Smuzhiyun } else {
437*4882a593Smuzhiyun mp->m_logdev_targp = mp->m_ddev_targp;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun return 0;
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun out_free_rtdev_targ:
443*4882a593Smuzhiyun if (mp->m_rtdev_targp)
444*4882a593Smuzhiyun xfs_free_buftarg(mp->m_rtdev_targp);
445*4882a593Smuzhiyun out_free_ddev_targ:
446*4882a593Smuzhiyun xfs_free_buftarg(mp->m_ddev_targp);
447*4882a593Smuzhiyun out_close_rtdev:
448*4882a593Smuzhiyun xfs_blkdev_put(rtdev);
449*4882a593Smuzhiyun fs_put_dax(dax_rtdev);
450*4882a593Smuzhiyun out_close_logdev:
451*4882a593Smuzhiyun if (logdev && logdev != ddev) {
452*4882a593Smuzhiyun xfs_blkdev_put(logdev);
453*4882a593Smuzhiyun fs_put_dax(dax_logdev);
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun out:
456*4882a593Smuzhiyun fs_put_dax(dax_ddev);
457*4882a593Smuzhiyun return error;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun /*
461*4882a593Smuzhiyun * Setup xfs_mount buffer target pointers based on superblock
462*4882a593Smuzhiyun */
463*4882a593Smuzhiyun STATIC int
xfs_setup_devices(struct xfs_mount * mp)464*4882a593Smuzhiyun xfs_setup_devices(
465*4882a593Smuzhiyun struct xfs_mount *mp)
466*4882a593Smuzhiyun {
467*4882a593Smuzhiyun int error;
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_sectsize);
470*4882a593Smuzhiyun if (error)
471*4882a593Smuzhiyun return error;
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) {
474*4882a593Smuzhiyun unsigned int log_sector_size = BBSIZE;
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun if (xfs_sb_version_hassector(&mp->m_sb))
477*4882a593Smuzhiyun log_sector_size = mp->m_sb.sb_logsectsize;
478*4882a593Smuzhiyun error = xfs_setsize_buftarg(mp->m_logdev_targp,
479*4882a593Smuzhiyun log_sector_size);
480*4882a593Smuzhiyun if (error)
481*4882a593Smuzhiyun return error;
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun if (mp->m_rtdev_targp) {
484*4882a593Smuzhiyun error = xfs_setsize_buftarg(mp->m_rtdev_targp,
485*4882a593Smuzhiyun mp->m_sb.sb_sectsize);
486*4882a593Smuzhiyun if (error)
487*4882a593Smuzhiyun return error;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun return 0;
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun STATIC int
xfs_init_mount_workqueues(struct xfs_mount * mp)494*4882a593Smuzhiyun xfs_init_mount_workqueues(
495*4882a593Smuzhiyun struct xfs_mount *mp)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun mp->m_buf_workqueue = alloc_workqueue("xfs-buf/%s",
498*4882a593Smuzhiyun WQ_MEM_RECLAIM|WQ_FREEZABLE, 1, mp->m_super->s_id);
499*4882a593Smuzhiyun if (!mp->m_buf_workqueue)
500*4882a593Smuzhiyun goto out;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun mp->m_unwritten_workqueue = alloc_workqueue("xfs-conv/%s",
503*4882a593Smuzhiyun WQ_MEM_RECLAIM|WQ_FREEZABLE, 0, mp->m_super->s_id);
504*4882a593Smuzhiyun if (!mp->m_unwritten_workqueue)
505*4882a593Smuzhiyun goto out_destroy_buf;
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun mp->m_cil_workqueue = alloc_workqueue("xfs-cil/%s",
508*4882a593Smuzhiyun WQ_MEM_RECLAIM | WQ_FREEZABLE | WQ_UNBOUND,
509*4882a593Smuzhiyun 0, mp->m_super->s_id);
510*4882a593Smuzhiyun if (!mp->m_cil_workqueue)
511*4882a593Smuzhiyun goto out_destroy_unwritten;
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun mp->m_reclaim_workqueue = alloc_workqueue("xfs-reclaim/%s",
514*4882a593Smuzhiyun WQ_MEM_RECLAIM|WQ_FREEZABLE, 0, mp->m_super->s_id);
515*4882a593Smuzhiyun if (!mp->m_reclaim_workqueue)
516*4882a593Smuzhiyun goto out_destroy_cil;
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun mp->m_eofblocks_workqueue = alloc_workqueue("xfs-eofblocks/%s",
519*4882a593Smuzhiyun WQ_MEM_RECLAIM|WQ_FREEZABLE, 0, mp->m_super->s_id);
520*4882a593Smuzhiyun if (!mp->m_eofblocks_workqueue)
521*4882a593Smuzhiyun goto out_destroy_reclaim;
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun mp->m_sync_workqueue = alloc_workqueue("xfs-sync/%s", WQ_FREEZABLE, 0,
524*4882a593Smuzhiyun mp->m_super->s_id);
525*4882a593Smuzhiyun if (!mp->m_sync_workqueue)
526*4882a593Smuzhiyun goto out_destroy_eofb;
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun return 0;
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun out_destroy_eofb:
531*4882a593Smuzhiyun destroy_workqueue(mp->m_eofblocks_workqueue);
532*4882a593Smuzhiyun out_destroy_reclaim:
533*4882a593Smuzhiyun destroy_workqueue(mp->m_reclaim_workqueue);
534*4882a593Smuzhiyun out_destroy_cil:
535*4882a593Smuzhiyun destroy_workqueue(mp->m_cil_workqueue);
536*4882a593Smuzhiyun out_destroy_unwritten:
537*4882a593Smuzhiyun destroy_workqueue(mp->m_unwritten_workqueue);
538*4882a593Smuzhiyun out_destroy_buf:
539*4882a593Smuzhiyun destroy_workqueue(mp->m_buf_workqueue);
540*4882a593Smuzhiyun out:
541*4882a593Smuzhiyun return -ENOMEM;
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun STATIC void
xfs_destroy_mount_workqueues(struct xfs_mount * mp)545*4882a593Smuzhiyun xfs_destroy_mount_workqueues(
546*4882a593Smuzhiyun struct xfs_mount *mp)
547*4882a593Smuzhiyun {
548*4882a593Smuzhiyun destroy_workqueue(mp->m_sync_workqueue);
549*4882a593Smuzhiyun destroy_workqueue(mp->m_eofblocks_workqueue);
550*4882a593Smuzhiyun destroy_workqueue(mp->m_reclaim_workqueue);
551*4882a593Smuzhiyun destroy_workqueue(mp->m_cil_workqueue);
552*4882a593Smuzhiyun destroy_workqueue(mp->m_unwritten_workqueue);
553*4882a593Smuzhiyun destroy_workqueue(mp->m_buf_workqueue);
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun static void
xfs_flush_inodes_worker(struct work_struct * work)557*4882a593Smuzhiyun xfs_flush_inodes_worker(
558*4882a593Smuzhiyun struct work_struct *work)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun struct xfs_mount *mp = container_of(work, struct xfs_mount,
561*4882a593Smuzhiyun m_flush_inodes_work);
562*4882a593Smuzhiyun struct super_block *sb = mp->m_super;
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun if (down_read_trylock(&sb->s_umount)) {
565*4882a593Smuzhiyun sync_inodes_sb(sb);
566*4882a593Smuzhiyun up_read(&sb->s_umount);
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun /*
571*4882a593Smuzhiyun * Flush all dirty data to disk. Must not be called while holding an XFS_ILOCK
572*4882a593Smuzhiyun * or a page lock. We use sync_inodes_sb() here to ensure we block while waiting
573*4882a593Smuzhiyun * for IO to complete so that we effectively throttle multiple callers to the
574*4882a593Smuzhiyun * rate at which IO is completing.
575*4882a593Smuzhiyun */
576*4882a593Smuzhiyun void
xfs_flush_inodes(struct xfs_mount * mp)577*4882a593Smuzhiyun xfs_flush_inodes(
578*4882a593Smuzhiyun struct xfs_mount *mp)
579*4882a593Smuzhiyun {
580*4882a593Smuzhiyun /*
581*4882a593Smuzhiyun * If flush_work() returns true then that means we waited for a flush
582*4882a593Smuzhiyun * which was already in progress. Don't bother running another scan.
583*4882a593Smuzhiyun */
584*4882a593Smuzhiyun if (flush_work(&mp->m_flush_inodes_work))
585*4882a593Smuzhiyun return;
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun queue_work(mp->m_sync_workqueue, &mp->m_flush_inodes_work);
588*4882a593Smuzhiyun flush_work(&mp->m_flush_inodes_work);
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun /* Catch misguided souls that try to use this interface on XFS */
592*4882a593Smuzhiyun STATIC struct inode *
xfs_fs_alloc_inode(struct super_block * sb)593*4882a593Smuzhiyun xfs_fs_alloc_inode(
594*4882a593Smuzhiyun struct super_block *sb)
595*4882a593Smuzhiyun {
596*4882a593Smuzhiyun BUG();
597*4882a593Smuzhiyun return NULL;
598*4882a593Smuzhiyun }
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun #ifdef DEBUG
601*4882a593Smuzhiyun static void
xfs_check_delalloc(struct xfs_inode * ip,int whichfork)602*4882a593Smuzhiyun xfs_check_delalloc(
603*4882a593Smuzhiyun struct xfs_inode *ip,
604*4882a593Smuzhiyun int whichfork)
605*4882a593Smuzhiyun {
606*4882a593Smuzhiyun struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
607*4882a593Smuzhiyun struct xfs_bmbt_irec got;
608*4882a593Smuzhiyun struct xfs_iext_cursor icur;
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun if (!ifp || !xfs_iext_lookup_extent(ip, ifp, 0, &icur, &got))
611*4882a593Smuzhiyun return;
612*4882a593Smuzhiyun do {
613*4882a593Smuzhiyun if (isnullstartblock(got.br_startblock)) {
614*4882a593Smuzhiyun xfs_warn(ip->i_mount,
615*4882a593Smuzhiyun "ino %llx %s fork has delalloc extent at [0x%llx:0x%llx]",
616*4882a593Smuzhiyun ip->i_ino,
617*4882a593Smuzhiyun whichfork == XFS_DATA_FORK ? "data" : "cow",
618*4882a593Smuzhiyun got.br_startoff, got.br_blockcount);
619*4882a593Smuzhiyun }
620*4882a593Smuzhiyun } while (xfs_iext_next_extent(ifp, &icur, &got));
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun #else
623*4882a593Smuzhiyun #define xfs_check_delalloc(ip, whichfork) do { } while (0)
624*4882a593Smuzhiyun #endif
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun /*
627*4882a593Smuzhiyun * Now that the generic code is guaranteed not to be accessing
628*4882a593Smuzhiyun * the linux inode, we can inactivate and reclaim the inode.
629*4882a593Smuzhiyun */
630*4882a593Smuzhiyun STATIC void
xfs_fs_destroy_inode(struct inode * inode)631*4882a593Smuzhiyun xfs_fs_destroy_inode(
632*4882a593Smuzhiyun struct inode *inode)
633*4882a593Smuzhiyun {
634*4882a593Smuzhiyun struct xfs_inode *ip = XFS_I(inode);
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun trace_xfs_destroy_inode(ip);
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun ASSERT(!rwsem_is_locked(&inode->i_rwsem));
639*4882a593Smuzhiyun XFS_STATS_INC(ip->i_mount, vn_rele);
640*4882a593Smuzhiyun XFS_STATS_INC(ip->i_mount, vn_remove);
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun xfs_inactive(ip);
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun if (!XFS_FORCED_SHUTDOWN(ip->i_mount) && ip->i_delayed_blks) {
645*4882a593Smuzhiyun xfs_check_delalloc(ip, XFS_DATA_FORK);
646*4882a593Smuzhiyun xfs_check_delalloc(ip, XFS_COW_FORK);
647*4882a593Smuzhiyun ASSERT(0);
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun XFS_STATS_INC(ip->i_mount, vn_reclaim);
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun /*
653*4882a593Smuzhiyun * We should never get here with one of the reclaim flags already set.
654*4882a593Smuzhiyun */
655*4882a593Smuzhiyun ASSERT_ALWAYS(!xfs_iflags_test(ip, XFS_IRECLAIMABLE));
656*4882a593Smuzhiyun ASSERT_ALWAYS(!xfs_iflags_test(ip, XFS_IRECLAIM));
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun /*
659*4882a593Smuzhiyun * We always use background reclaim here because even if the inode is
660*4882a593Smuzhiyun * clean, it still may be under IO and hence we have wait for IO
661*4882a593Smuzhiyun * completion to occur before we can reclaim the inode. The background
662*4882a593Smuzhiyun * reclaim path handles this more efficiently than we can here, so
663*4882a593Smuzhiyun * simply let background reclaim tear down all inodes.
664*4882a593Smuzhiyun */
665*4882a593Smuzhiyun xfs_inode_set_reclaim_tag(ip);
666*4882a593Smuzhiyun }
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun static void
xfs_fs_dirty_inode(struct inode * inode,int flag)669*4882a593Smuzhiyun xfs_fs_dirty_inode(
670*4882a593Smuzhiyun struct inode *inode,
671*4882a593Smuzhiyun int flag)
672*4882a593Smuzhiyun {
673*4882a593Smuzhiyun struct xfs_inode *ip = XFS_I(inode);
674*4882a593Smuzhiyun struct xfs_mount *mp = ip->i_mount;
675*4882a593Smuzhiyun struct xfs_trans *tp;
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun if (!(inode->i_sb->s_flags & SB_LAZYTIME))
678*4882a593Smuzhiyun return;
679*4882a593Smuzhiyun if (flag != I_DIRTY_SYNC || !(inode->i_state & I_DIRTY_TIME))
680*4882a593Smuzhiyun return;
681*4882a593Smuzhiyun
682*4882a593Smuzhiyun if (xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, 0, &tp))
683*4882a593Smuzhiyun return;
684*4882a593Smuzhiyun xfs_ilock(ip, XFS_ILOCK_EXCL);
685*4882a593Smuzhiyun xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
686*4882a593Smuzhiyun xfs_trans_log_inode(tp, ip, XFS_ILOG_TIMESTAMP);
687*4882a593Smuzhiyun xfs_trans_commit(tp);
688*4882a593Smuzhiyun }
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun /*
691*4882a593Smuzhiyun * Slab object creation initialisation for the XFS inode.
692*4882a593Smuzhiyun * This covers only the idempotent fields in the XFS inode;
693*4882a593Smuzhiyun * all other fields need to be initialised on allocation
694*4882a593Smuzhiyun * from the slab. This avoids the need to repeatedly initialise
695*4882a593Smuzhiyun * fields in the xfs inode that left in the initialise state
696*4882a593Smuzhiyun * when freeing the inode.
697*4882a593Smuzhiyun */
698*4882a593Smuzhiyun STATIC void
xfs_fs_inode_init_once(void * inode)699*4882a593Smuzhiyun xfs_fs_inode_init_once(
700*4882a593Smuzhiyun void *inode)
701*4882a593Smuzhiyun {
702*4882a593Smuzhiyun struct xfs_inode *ip = inode;
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun memset(ip, 0, sizeof(struct xfs_inode));
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun /* vfs inode */
707*4882a593Smuzhiyun inode_init_once(VFS_I(ip));
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun /* xfs inode */
710*4882a593Smuzhiyun atomic_set(&ip->i_pincount, 0);
711*4882a593Smuzhiyun spin_lock_init(&ip->i_flags_lock);
712*4882a593Smuzhiyun
713*4882a593Smuzhiyun mrlock_init(&ip->i_mmaplock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
714*4882a593Smuzhiyun "xfsino", ip->i_ino);
715*4882a593Smuzhiyun mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
716*4882a593Smuzhiyun "xfsino", ip->i_ino);
717*4882a593Smuzhiyun }
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun /*
720*4882a593Smuzhiyun * We do an unlocked check for XFS_IDONTCACHE here because we are already
721*4882a593Smuzhiyun * serialised against cache hits here via the inode->i_lock and igrab() in
722*4882a593Smuzhiyun * xfs_iget_cache_hit(). Hence a lookup that might clear this flag will not be
723*4882a593Smuzhiyun * racing with us, and it avoids needing to grab a spinlock here for every inode
724*4882a593Smuzhiyun * we drop the final reference on.
725*4882a593Smuzhiyun */
726*4882a593Smuzhiyun STATIC int
xfs_fs_drop_inode(struct inode * inode)727*4882a593Smuzhiyun xfs_fs_drop_inode(
728*4882a593Smuzhiyun struct inode *inode)
729*4882a593Smuzhiyun {
730*4882a593Smuzhiyun struct xfs_inode *ip = XFS_I(inode);
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun /*
733*4882a593Smuzhiyun * If this unlinked inode is in the middle of recovery, don't
734*4882a593Smuzhiyun * drop the inode just yet; log recovery will take care of
735*4882a593Smuzhiyun * that. See the comment for this inode flag.
736*4882a593Smuzhiyun */
737*4882a593Smuzhiyun if (ip->i_flags & XFS_IRECOVERY) {
738*4882a593Smuzhiyun ASSERT(ip->i_mount->m_log->l_flags & XLOG_RECOVERY_NEEDED);
739*4882a593Smuzhiyun return 0;
740*4882a593Smuzhiyun }
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun return generic_drop_inode(inode);
743*4882a593Smuzhiyun }
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun static void
xfs_mount_free(struct xfs_mount * mp)746*4882a593Smuzhiyun xfs_mount_free(
747*4882a593Smuzhiyun struct xfs_mount *mp)
748*4882a593Smuzhiyun {
749*4882a593Smuzhiyun kfree(mp->m_rtname);
750*4882a593Smuzhiyun kfree(mp->m_logname);
751*4882a593Smuzhiyun kmem_free(mp);
752*4882a593Smuzhiyun }
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun STATIC int
xfs_fs_sync_fs(struct super_block * sb,int wait)755*4882a593Smuzhiyun xfs_fs_sync_fs(
756*4882a593Smuzhiyun struct super_block *sb,
757*4882a593Smuzhiyun int wait)
758*4882a593Smuzhiyun {
759*4882a593Smuzhiyun struct xfs_mount *mp = XFS_M(sb);
760*4882a593Smuzhiyun int error;
761*4882a593Smuzhiyun
762*4882a593Smuzhiyun /*
763*4882a593Smuzhiyun * Doing anything during the async pass would be counterproductive.
764*4882a593Smuzhiyun */
765*4882a593Smuzhiyun if (!wait)
766*4882a593Smuzhiyun return 0;
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun error = xfs_log_force(mp, XFS_LOG_SYNC);
769*4882a593Smuzhiyun if (error)
770*4882a593Smuzhiyun return error;
771*4882a593Smuzhiyun
772*4882a593Smuzhiyun if (laptop_mode) {
773*4882a593Smuzhiyun /*
774*4882a593Smuzhiyun * The disk must be active because we're syncing.
775*4882a593Smuzhiyun * We schedule log work now (now that the disk is
776*4882a593Smuzhiyun * active) instead of later (when it might not be).
777*4882a593Smuzhiyun */
778*4882a593Smuzhiyun flush_delayed_work(&mp->m_log->l_work);
779*4882a593Smuzhiyun }
780*4882a593Smuzhiyun
781*4882a593Smuzhiyun return 0;
782*4882a593Smuzhiyun }
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun STATIC int
xfs_fs_statfs(struct dentry * dentry,struct kstatfs * statp)785*4882a593Smuzhiyun xfs_fs_statfs(
786*4882a593Smuzhiyun struct dentry *dentry,
787*4882a593Smuzhiyun struct kstatfs *statp)
788*4882a593Smuzhiyun {
789*4882a593Smuzhiyun struct xfs_mount *mp = XFS_M(dentry->d_sb);
790*4882a593Smuzhiyun xfs_sb_t *sbp = &mp->m_sb;
791*4882a593Smuzhiyun struct xfs_inode *ip = XFS_I(d_inode(dentry));
792*4882a593Smuzhiyun uint64_t fakeinos, id;
793*4882a593Smuzhiyun uint64_t icount;
794*4882a593Smuzhiyun uint64_t ifree;
795*4882a593Smuzhiyun uint64_t fdblocks;
796*4882a593Smuzhiyun xfs_extlen_t lsize;
797*4882a593Smuzhiyun int64_t ffree;
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun statp->f_type = XFS_SUPER_MAGIC;
800*4882a593Smuzhiyun statp->f_namelen = MAXNAMELEN - 1;
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun id = huge_encode_dev(mp->m_ddev_targp->bt_dev);
803*4882a593Smuzhiyun statp->f_fsid = u64_to_fsid(id);
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun icount = percpu_counter_sum(&mp->m_icount);
806*4882a593Smuzhiyun ifree = percpu_counter_sum(&mp->m_ifree);
807*4882a593Smuzhiyun fdblocks = percpu_counter_sum(&mp->m_fdblocks);
808*4882a593Smuzhiyun
809*4882a593Smuzhiyun spin_lock(&mp->m_sb_lock);
810*4882a593Smuzhiyun statp->f_bsize = sbp->sb_blocksize;
811*4882a593Smuzhiyun lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0;
812*4882a593Smuzhiyun statp->f_blocks = sbp->sb_dblocks - lsize;
813*4882a593Smuzhiyun spin_unlock(&mp->m_sb_lock);
814*4882a593Smuzhiyun
815*4882a593Smuzhiyun /* make sure statp->f_bfree does not underflow */
816*4882a593Smuzhiyun statp->f_bfree = max_t(int64_t, fdblocks - mp->m_alloc_set_aside, 0);
817*4882a593Smuzhiyun statp->f_bavail = statp->f_bfree;
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun fakeinos = XFS_FSB_TO_INO(mp, statp->f_bfree);
820*4882a593Smuzhiyun statp->f_files = min(icount + fakeinos, (uint64_t)XFS_MAXINUMBER);
821*4882a593Smuzhiyun if (M_IGEO(mp)->maxicount)
822*4882a593Smuzhiyun statp->f_files = min_t(typeof(statp->f_files),
823*4882a593Smuzhiyun statp->f_files,
824*4882a593Smuzhiyun M_IGEO(mp)->maxicount);
825*4882a593Smuzhiyun
826*4882a593Smuzhiyun /* If sb_icount overshot maxicount, report actual allocation */
827*4882a593Smuzhiyun statp->f_files = max_t(typeof(statp->f_files),
828*4882a593Smuzhiyun statp->f_files,
829*4882a593Smuzhiyun sbp->sb_icount);
830*4882a593Smuzhiyun
831*4882a593Smuzhiyun /* make sure statp->f_ffree does not underflow */
832*4882a593Smuzhiyun ffree = statp->f_files - (icount - ifree);
833*4882a593Smuzhiyun statp->f_ffree = max_t(int64_t, ffree, 0);
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun if ((ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
837*4882a593Smuzhiyun ((mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_PQUOTA_ENFD))) ==
838*4882a593Smuzhiyun (XFS_PQUOTA_ACCT|XFS_PQUOTA_ENFD))
839*4882a593Smuzhiyun xfs_qm_statvfs(ip, statp);
840*4882a593Smuzhiyun
841*4882a593Smuzhiyun if (XFS_IS_REALTIME_MOUNT(mp) &&
842*4882a593Smuzhiyun (ip->i_d.di_flags & (XFS_DIFLAG_RTINHERIT | XFS_DIFLAG_REALTIME))) {
843*4882a593Smuzhiyun statp->f_blocks = sbp->sb_rblocks;
844*4882a593Smuzhiyun statp->f_bavail = statp->f_bfree =
845*4882a593Smuzhiyun sbp->sb_frextents * sbp->sb_rextsize;
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun return 0;
849*4882a593Smuzhiyun }
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun STATIC void
xfs_save_resvblks(struct xfs_mount * mp)852*4882a593Smuzhiyun xfs_save_resvblks(struct xfs_mount *mp)
853*4882a593Smuzhiyun {
854*4882a593Smuzhiyun uint64_t resblks = 0;
855*4882a593Smuzhiyun
856*4882a593Smuzhiyun mp->m_resblks_save = mp->m_resblks;
857*4882a593Smuzhiyun xfs_reserve_blocks(mp, &resblks, NULL);
858*4882a593Smuzhiyun }
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun STATIC void
xfs_restore_resvblks(struct xfs_mount * mp)861*4882a593Smuzhiyun xfs_restore_resvblks(struct xfs_mount *mp)
862*4882a593Smuzhiyun {
863*4882a593Smuzhiyun uint64_t resblks;
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun if (mp->m_resblks_save) {
866*4882a593Smuzhiyun resblks = mp->m_resblks_save;
867*4882a593Smuzhiyun mp->m_resblks_save = 0;
868*4882a593Smuzhiyun } else
869*4882a593Smuzhiyun resblks = xfs_default_resblks(mp);
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun xfs_reserve_blocks(mp, &resblks, NULL);
872*4882a593Smuzhiyun }
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun /*
875*4882a593Smuzhiyun * Trigger writeback of all the dirty metadata in the file system.
876*4882a593Smuzhiyun *
877*4882a593Smuzhiyun * This ensures that the metadata is written to their location on disk rather
878*4882a593Smuzhiyun * than just existing in transactions in the log. This means after a quiesce
879*4882a593Smuzhiyun * there is no log replay required to write the inodes to disk - this is the
880*4882a593Smuzhiyun * primary difference between a sync and a quiesce.
881*4882a593Smuzhiyun *
882*4882a593Smuzhiyun * We cancel log work early here to ensure all transactions the log worker may
883*4882a593Smuzhiyun * run have finished before we clean up and log the superblock and write an
884*4882a593Smuzhiyun * unmount record. The unfreeze process is responsible for restarting the log
885*4882a593Smuzhiyun * worker correctly.
886*4882a593Smuzhiyun */
887*4882a593Smuzhiyun void
xfs_quiesce_attr(struct xfs_mount * mp)888*4882a593Smuzhiyun xfs_quiesce_attr(
889*4882a593Smuzhiyun struct xfs_mount *mp)
890*4882a593Smuzhiyun {
891*4882a593Smuzhiyun int error = 0;
892*4882a593Smuzhiyun
893*4882a593Smuzhiyun cancel_delayed_work_sync(&mp->m_log->l_work);
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun /* force the log to unpin objects from the now complete transactions */
896*4882a593Smuzhiyun xfs_log_force(mp, XFS_LOG_SYNC);
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun
899*4882a593Smuzhiyun /* Push the superblock and write an unmount record */
900*4882a593Smuzhiyun error = xfs_log_sbcount(mp);
901*4882a593Smuzhiyun if (error)
902*4882a593Smuzhiyun xfs_warn(mp, "xfs_attr_quiesce: failed to log sb changes. "
903*4882a593Smuzhiyun "Frozen image may not be consistent.");
904*4882a593Smuzhiyun xfs_log_quiesce(mp);
905*4882a593Smuzhiyun }
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun /*
908*4882a593Smuzhiyun * Second stage of a freeze. The data is already frozen so we only
909*4882a593Smuzhiyun * need to take care of the metadata. Once that's done sync the superblock
910*4882a593Smuzhiyun * to the log to dirty it in case of a crash while frozen. This ensures that we
911*4882a593Smuzhiyun * will recover the unlinked inode lists on the next mount.
912*4882a593Smuzhiyun */
913*4882a593Smuzhiyun STATIC int
xfs_fs_freeze(struct super_block * sb)914*4882a593Smuzhiyun xfs_fs_freeze(
915*4882a593Smuzhiyun struct super_block *sb)
916*4882a593Smuzhiyun {
917*4882a593Smuzhiyun struct xfs_mount *mp = XFS_M(sb);
918*4882a593Smuzhiyun unsigned int flags;
919*4882a593Smuzhiyun int ret;
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun /*
922*4882a593Smuzhiyun * The filesystem is now frozen far enough that memory reclaim
923*4882a593Smuzhiyun * cannot safely operate on the filesystem. Hence we need to
924*4882a593Smuzhiyun * set a GFP_NOFS context here to avoid recursion deadlocks.
925*4882a593Smuzhiyun */
926*4882a593Smuzhiyun flags = memalloc_nofs_save();
927*4882a593Smuzhiyun xfs_stop_block_reaping(mp);
928*4882a593Smuzhiyun xfs_save_resvblks(mp);
929*4882a593Smuzhiyun xfs_quiesce_attr(mp);
930*4882a593Smuzhiyun ret = xfs_sync_sb(mp, true);
931*4882a593Smuzhiyun memalloc_nofs_restore(flags);
932*4882a593Smuzhiyun return ret;
933*4882a593Smuzhiyun }
934*4882a593Smuzhiyun
935*4882a593Smuzhiyun STATIC int
xfs_fs_unfreeze(struct super_block * sb)936*4882a593Smuzhiyun xfs_fs_unfreeze(
937*4882a593Smuzhiyun struct super_block *sb)
938*4882a593Smuzhiyun {
939*4882a593Smuzhiyun struct xfs_mount *mp = XFS_M(sb);
940*4882a593Smuzhiyun
941*4882a593Smuzhiyun xfs_restore_resvblks(mp);
942*4882a593Smuzhiyun xfs_log_work_queue(mp);
943*4882a593Smuzhiyun xfs_start_block_reaping(mp);
944*4882a593Smuzhiyun return 0;
945*4882a593Smuzhiyun }
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun /*
948*4882a593Smuzhiyun * This function fills in xfs_mount_t fields based on mount args.
949*4882a593Smuzhiyun * Note: the superblock _has_ now been read in.
950*4882a593Smuzhiyun */
951*4882a593Smuzhiyun STATIC int
xfs_finish_flags(struct xfs_mount * mp)952*4882a593Smuzhiyun xfs_finish_flags(
953*4882a593Smuzhiyun struct xfs_mount *mp)
954*4882a593Smuzhiyun {
955*4882a593Smuzhiyun int ronly = (mp->m_flags & XFS_MOUNT_RDONLY);
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun /* Fail a mount where the logbuf is smaller than the log stripe */
958*4882a593Smuzhiyun if (xfs_sb_version_haslogv2(&mp->m_sb)) {
959*4882a593Smuzhiyun if (mp->m_logbsize <= 0 &&
960*4882a593Smuzhiyun mp->m_sb.sb_logsunit > XLOG_BIG_RECORD_BSIZE) {
961*4882a593Smuzhiyun mp->m_logbsize = mp->m_sb.sb_logsunit;
962*4882a593Smuzhiyun } else if (mp->m_logbsize > 0 &&
963*4882a593Smuzhiyun mp->m_logbsize < mp->m_sb.sb_logsunit) {
964*4882a593Smuzhiyun xfs_warn(mp,
965*4882a593Smuzhiyun "logbuf size must be greater than or equal to log stripe size");
966*4882a593Smuzhiyun return -EINVAL;
967*4882a593Smuzhiyun }
968*4882a593Smuzhiyun } else {
969*4882a593Smuzhiyun /* Fail a mount if the logbuf is larger than 32K */
970*4882a593Smuzhiyun if (mp->m_logbsize > XLOG_BIG_RECORD_BSIZE) {
971*4882a593Smuzhiyun xfs_warn(mp,
972*4882a593Smuzhiyun "logbuf size for version 1 logs must be 16K or 32K");
973*4882a593Smuzhiyun return -EINVAL;
974*4882a593Smuzhiyun }
975*4882a593Smuzhiyun }
976*4882a593Smuzhiyun
977*4882a593Smuzhiyun /*
978*4882a593Smuzhiyun * V5 filesystems always use attr2 format for attributes.
979*4882a593Smuzhiyun */
980*4882a593Smuzhiyun if (xfs_sb_version_hascrc(&mp->m_sb) &&
981*4882a593Smuzhiyun (mp->m_flags & XFS_MOUNT_NOATTR2)) {
982*4882a593Smuzhiyun xfs_warn(mp, "Cannot mount a V5 filesystem as noattr2. "
983*4882a593Smuzhiyun "attr2 is always enabled for V5 filesystems.");
984*4882a593Smuzhiyun return -EINVAL;
985*4882a593Smuzhiyun }
986*4882a593Smuzhiyun
987*4882a593Smuzhiyun /*
988*4882a593Smuzhiyun * mkfs'ed attr2 will turn on attr2 mount unless explicitly
989*4882a593Smuzhiyun * told by noattr2 to turn it off
990*4882a593Smuzhiyun */
991*4882a593Smuzhiyun if (xfs_sb_version_hasattr2(&mp->m_sb) &&
992*4882a593Smuzhiyun !(mp->m_flags & XFS_MOUNT_NOATTR2))
993*4882a593Smuzhiyun mp->m_flags |= XFS_MOUNT_ATTR2;
994*4882a593Smuzhiyun
995*4882a593Smuzhiyun /*
996*4882a593Smuzhiyun * prohibit r/w mounts of read-only filesystems
997*4882a593Smuzhiyun */
998*4882a593Smuzhiyun if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !ronly) {
999*4882a593Smuzhiyun xfs_warn(mp,
1000*4882a593Smuzhiyun "cannot mount a read-only filesystem as read-write");
1001*4882a593Smuzhiyun return -EROFS;
1002*4882a593Smuzhiyun }
1003*4882a593Smuzhiyun
1004*4882a593Smuzhiyun if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) &&
1005*4882a593Smuzhiyun (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE)) &&
1006*4882a593Smuzhiyun !xfs_sb_version_has_pquotino(&mp->m_sb)) {
1007*4882a593Smuzhiyun xfs_warn(mp,
1008*4882a593Smuzhiyun "Super block does not support project and group quota together");
1009*4882a593Smuzhiyun return -EINVAL;
1010*4882a593Smuzhiyun }
1011*4882a593Smuzhiyun
1012*4882a593Smuzhiyun return 0;
1013*4882a593Smuzhiyun }
1014*4882a593Smuzhiyun
1015*4882a593Smuzhiyun static int
xfs_init_percpu_counters(struct xfs_mount * mp)1016*4882a593Smuzhiyun xfs_init_percpu_counters(
1017*4882a593Smuzhiyun struct xfs_mount *mp)
1018*4882a593Smuzhiyun {
1019*4882a593Smuzhiyun int error;
1020*4882a593Smuzhiyun
1021*4882a593Smuzhiyun error = percpu_counter_init(&mp->m_icount, 0, GFP_KERNEL);
1022*4882a593Smuzhiyun if (error)
1023*4882a593Smuzhiyun return -ENOMEM;
1024*4882a593Smuzhiyun
1025*4882a593Smuzhiyun error = percpu_counter_init(&mp->m_ifree, 0, GFP_KERNEL);
1026*4882a593Smuzhiyun if (error)
1027*4882a593Smuzhiyun goto free_icount;
1028*4882a593Smuzhiyun
1029*4882a593Smuzhiyun error = percpu_counter_init(&mp->m_fdblocks, 0, GFP_KERNEL);
1030*4882a593Smuzhiyun if (error)
1031*4882a593Smuzhiyun goto free_ifree;
1032*4882a593Smuzhiyun
1033*4882a593Smuzhiyun error = percpu_counter_init(&mp->m_delalloc_blks, 0, GFP_KERNEL);
1034*4882a593Smuzhiyun if (error)
1035*4882a593Smuzhiyun goto free_fdblocks;
1036*4882a593Smuzhiyun
1037*4882a593Smuzhiyun return 0;
1038*4882a593Smuzhiyun
1039*4882a593Smuzhiyun free_fdblocks:
1040*4882a593Smuzhiyun percpu_counter_destroy(&mp->m_fdblocks);
1041*4882a593Smuzhiyun free_ifree:
1042*4882a593Smuzhiyun percpu_counter_destroy(&mp->m_ifree);
1043*4882a593Smuzhiyun free_icount:
1044*4882a593Smuzhiyun percpu_counter_destroy(&mp->m_icount);
1045*4882a593Smuzhiyun return -ENOMEM;
1046*4882a593Smuzhiyun }
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun void
xfs_reinit_percpu_counters(struct xfs_mount * mp)1049*4882a593Smuzhiyun xfs_reinit_percpu_counters(
1050*4882a593Smuzhiyun struct xfs_mount *mp)
1051*4882a593Smuzhiyun {
1052*4882a593Smuzhiyun percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount);
1053*4882a593Smuzhiyun percpu_counter_set(&mp->m_ifree, mp->m_sb.sb_ifree);
1054*4882a593Smuzhiyun percpu_counter_set(&mp->m_fdblocks, mp->m_sb.sb_fdblocks);
1055*4882a593Smuzhiyun }
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun static void
xfs_destroy_percpu_counters(struct xfs_mount * mp)1058*4882a593Smuzhiyun xfs_destroy_percpu_counters(
1059*4882a593Smuzhiyun struct xfs_mount *mp)
1060*4882a593Smuzhiyun {
1061*4882a593Smuzhiyun percpu_counter_destroy(&mp->m_icount);
1062*4882a593Smuzhiyun percpu_counter_destroy(&mp->m_ifree);
1063*4882a593Smuzhiyun percpu_counter_destroy(&mp->m_fdblocks);
1064*4882a593Smuzhiyun ASSERT(XFS_FORCED_SHUTDOWN(mp) ||
1065*4882a593Smuzhiyun percpu_counter_sum(&mp->m_delalloc_blks) == 0);
1066*4882a593Smuzhiyun percpu_counter_destroy(&mp->m_delalloc_blks);
1067*4882a593Smuzhiyun }
1068*4882a593Smuzhiyun
1069*4882a593Smuzhiyun static void
xfs_fs_put_super(struct super_block * sb)1070*4882a593Smuzhiyun xfs_fs_put_super(
1071*4882a593Smuzhiyun struct super_block *sb)
1072*4882a593Smuzhiyun {
1073*4882a593Smuzhiyun struct xfs_mount *mp = XFS_M(sb);
1074*4882a593Smuzhiyun
1075*4882a593Smuzhiyun /* if ->fill_super failed, we have no mount to tear down */
1076*4882a593Smuzhiyun if (!sb->s_fs_info)
1077*4882a593Smuzhiyun return;
1078*4882a593Smuzhiyun
1079*4882a593Smuzhiyun xfs_notice(mp, "Unmounting Filesystem");
1080*4882a593Smuzhiyun xfs_filestream_unmount(mp);
1081*4882a593Smuzhiyun xfs_unmountfs(mp);
1082*4882a593Smuzhiyun
1083*4882a593Smuzhiyun xfs_freesb(mp);
1084*4882a593Smuzhiyun free_percpu(mp->m_stats.xs_stats);
1085*4882a593Smuzhiyun xfs_destroy_percpu_counters(mp);
1086*4882a593Smuzhiyun xfs_destroy_mount_workqueues(mp);
1087*4882a593Smuzhiyun xfs_close_devices(mp);
1088*4882a593Smuzhiyun
1089*4882a593Smuzhiyun sb->s_fs_info = NULL;
1090*4882a593Smuzhiyun xfs_mount_free(mp);
1091*4882a593Smuzhiyun }
1092*4882a593Smuzhiyun
1093*4882a593Smuzhiyun static long
xfs_fs_nr_cached_objects(struct super_block * sb,struct shrink_control * sc)1094*4882a593Smuzhiyun xfs_fs_nr_cached_objects(
1095*4882a593Smuzhiyun struct super_block *sb,
1096*4882a593Smuzhiyun struct shrink_control *sc)
1097*4882a593Smuzhiyun {
1098*4882a593Smuzhiyun /* Paranoia: catch incorrect calls during mount setup or teardown */
1099*4882a593Smuzhiyun if (WARN_ON_ONCE(!sb->s_fs_info))
1100*4882a593Smuzhiyun return 0;
1101*4882a593Smuzhiyun return xfs_reclaim_inodes_count(XFS_M(sb));
1102*4882a593Smuzhiyun }
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun static long
xfs_fs_free_cached_objects(struct super_block * sb,struct shrink_control * sc)1105*4882a593Smuzhiyun xfs_fs_free_cached_objects(
1106*4882a593Smuzhiyun struct super_block *sb,
1107*4882a593Smuzhiyun struct shrink_control *sc)
1108*4882a593Smuzhiyun {
1109*4882a593Smuzhiyun return xfs_reclaim_inodes_nr(XFS_M(sb), sc->nr_to_scan);
1110*4882a593Smuzhiyun }
1111*4882a593Smuzhiyun
1112*4882a593Smuzhiyun static const struct super_operations xfs_super_operations = {
1113*4882a593Smuzhiyun .alloc_inode = xfs_fs_alloc_inode,
1114*4882a593Smuzhiyun .destroy_inode = xfs_fs_destroy_inode,
1115*4882a593Smuzhiyun .dirty_inode = xfs_fs_dirty_inode,
1116*4882a593Smuzhiyun .drop_inode = xfs_fs_drop_inode,
1117*4882a593Smuzhiyun .put_super = xfs_fs_put_super,
1118*4882a593Smuzhiyun .sync_fs = xfs_fs_sync_fs,
1119*4882a593Smuzhiyun .freeze_fs = xfs_fs_freeze,
1120*4882a593Smuzhiyun .unfreeze_fs = xfs_fs_unfreeze,
1121*4882a593Smuzhiyun .statfs = xfs_fs_statfs,
1122*4882a593Smuzhiyun .show_options = xfs_fs_show_options,
1123*4882a593Smuzhiyun .nr_cached_objects = xfs_fs_nr_cached_objects,
1124*4882a593Smuzhiyun .free_cached_objects = xfs_fs_free_cached_objects,
1125*4882a593Smuzhiyun };
1126*4882a593Smuzhiyun
1127*4882a593Smuzhiyun static int
suffix_kstrtoint(const char * s,unsigned int base,int * res)1128*4882a593Smuzhiyun suffix_kstrtoint(
1129*4882a593Smuzhiyun const char *s,
1130*4882a593Smuzhiyun unsigned int base,
1131*4882a593Smuzhiyun int *res)
1132*4882a593Smuzhiyun {
1133*4882a593Smuzhiyun int last, shift_left_factor = 0, _res;
1134*4882a593Smuzhiyun char *value;
1135*4882a593Smuzhiyun int ret = 0;
1136*4882a593Smuzhiyun
1137*4882a593Smuzhiyun value = kstrdup(s, GFP_KERNEL);
1138*4882a593Smuzhiyun if (!value)
1139*4882a593Smuzhiyun return -ENOMEM;
1140*4882a593Smuzhiyun
1141*4882a593Smuzhiyun last = strlen(value) - 1;
1142*4882a593Smuzhiyun if (value[last] == 'K' || value[last] == 'k') {
1143*4882a593Smuzhiyun shift_left_factor = 10;
1144*4882a593Smuzhiyun value[last] = '\0';
1145*4882a593Smuzhiyun }
1146*4882a593Smuzhiyun if (value[last] == 'M' || value[last] == 'm') {
1147*4882a593Smuzhiyun shift_left_factor = 20;
1148*4882a593Smuzhiyun value[last] = '\0';
1149*4882a593Smuzhiyun }
1150*4882a593Smuzhiyun if (value[last] == 'G' || value[last] == 'g') {
1151*4882a593Smuzhiyun shift_left_factor = 30;
1152*4882a593Smuzhiyun value[last] = '\0';
1153*4882a593Smuzhiyun }
1154*4882a593Smuzhiyun
1155*4882a593Smuzhiyun if (kstrtoint(value, base, &_res))
1156*4882a593Smuzhiyun ret = -EINVAL;
1157*4882a593Smuzhiyun kfree(value);
1158*4882a593Smuzhiyun *res = _res << shift_left_factor;
1159*4882a593Smuzhiyun return ret;
1160*4882a593Smuzhiyun }
1161*4882a593Smuzhiyun
1162*4882a593Smuzhiyun static inline void
xfs_fs_warn_deprecated(struct fs_context * fc,struct fs_parameter * param,uint64_t flag,bool value)1163*4882a593Smuzhiyun xfs_fs_warn_deprecated(
1164*4882a593Smuzhiyun struct fs_context *fc,
1165*4882a593Smuzhiyun struct fs_parameter *param,
1166*4882a593Smuzhiyun uint64_t flag,
1167*4882a593Smuzhiyun bool value)
1168*4882a593Smuzhiyun {
1169*4882a593Smuzhiyun /* Don't print the warning if reconfiguring and current mount point
1170*4882a593Smuzhiyun * already had the flag set
1171*4882a593Smuzhiyun */
1172*4882a593Smuzhiyun if ((fc->purpose & FS_CONTEXT_FOR_RECONFIGURE) &&
1173*4882a593Smuzhiyun !!(XFS_M(fc->root->d_sb)->m_flags & flag) == value)
1174*4882a593Smuzhiyun return;
1175*4882a593Smuzhiyun xfs_warn(fc->s_fs_info, "%s mount option is deprecated.", param->key);
1176*4882a593Smuzhiyun }
1177*4882a593Smuzhiyun
1178*4882a593Smuzhiyun /*
1179*4882a593Smuzhiyun * Set mount state from a mount option.
1180*4882a593Smuzhiyun *
1181*4882a593Smuzhiyun * NOTE: mp->m_super is NULL here!
1182*4882a593Smuzhiyun */
1183*4882a593Smuzhiyun static int
xfs_fc_parse_param(struct fs_context * fc,struct fs_parameter * param)1184*4882a593Smuzhiyun xfs_fc_parse_param(
1185*4882a593Smuzhiyun struct fs_context *fc,
1186*4882a593Smuzhiyun struct fs_parameter *param)
1187*4882a593Smuzhiyun {
1188*4882a593Smuzhiyun struct xfs_mount *parsing_mp = fc->s_fs_info;
1189*4882a593Smuzhiyun struct fs_parse_result result;
1190*4882a593Smuzhiyun int size = 0;
1191*4882a593Smuzhiyun int opt;
1192*4882a593Smuzhiyun
1193*4882a593Smuzhiyun opt = fs_parse(fc, xfs_fs_parameters, param, &result);
1194*4882a593Smuzhiyun if (opt < 0)
1195*4882a593Smuzhiyun return opt;
1196*4882a593Smuzhiyun
1197*4882a593Smuzhiyun switch (opt) {
1198*4882a593Smuzhiyun case Opt_logbufs:
1199*4882a593Smuzhiyun parsing_mp->m_logbufs = result.uint_32;
1200*4882a593Smuzhiyun return 0;
1201*4882a593Smuzhiyun case Opt_logbsize:
1202*4882a593Smuzhiyun if (suffix_kstrtoint(param->string, 10, &parsing_mp->m_logbsize))
1203*4882a593Smuzhiyun return -EINVAL;
1204*4882a593Smuzhiyun return 0;
1205*4882a593Smuzhiyun case Opt_logdev:
1206*4882a593Smuzhiyun kfree(parsing_mp->m_logname);
1207*4882a593Smuzhiyun parsing_mp->m_logname = kstrdup(param->string, GFP_KERNEL);
1208*4882a593Smuzhiyun if (!parsing_mp->m_logname)
1209*4882a593Smuzhiyun return -ENOMEM;
1210*4882a593Smuzhiyun return 0;
1211*4882a593Smuzhiyun case Opt_rtdev:
1212*4882a593Smuzhiyun kfree(parsing_mp->m_rtname);
1213*4882a593Smuzhiyun parsing_mp->m_rtname = kstrdup(param->string, GFP_KERNEL);
1214*4882a593Smuzhiyun if (!parsing_mp->m_rtname)
1215*4882a593Smuzhiyun return -ENOMEM;
1216*4882a593Smuzhiyun return 0;
1217*4882a593Smuzhiyun case Opt_allocsize:
1218*4882a593Smuzhiyun if (suffix_kstrtoint(param->string, 10, &size))
1219*4882a593Smuzhiyun return -EINVAL;
1220*4882a593Smuzhiyun parsing_mp->m_allocsize_log = ffs(size) - 1;
1221*4882a593Smuzhiyun parsing_mp->m_flags |= XFS_MOUNT_ALLOCSIZE;
1222*4882a593Smuzhiyun return 0;
1223*4882a593Smuzhiyun case Opt_grpid:
1224*4882a593Smuzhiyun case Opt_bsdgroups:
1225*4882a593Smuzhiyun parsing_mp->m_flags |= XFS_MOUNT_GRPID;
1226*4882a593Smuzhiyun return 0;
1227*4882a593Smuzhiyun case Opt_nogrpid:
1228*4882a593Smuzhiyun case Opt_sysvgroups:
1229*4882a593Smuzhiyun parsing_mp->m_flags &= ~XFS_MOUNT_GRPID;
1230*4882a593Smuzhiyun return 0;
1231*4882a593Smuzhiyun case Opt_wsync:
1232*4882a593Smuzhiyun parsing_mp->m_flags |= XFS_MOUNT_WSYNC;
1233*4882a593Smuzhiyun return 0;
1234*4882a593Smuzhiyun case Opt_norecovery:
1235*4882a593Smuzhiyun parsing_mp->m_flags |= XFS_MOUNT_NORECOVERY;
1236*4882a593Smuzhiyun return 0;
1237*4882a593Smuzhiyun case Opt_noalign:
1238*4882a593Smuzhiyun parsing_mp->m_flags |= XFS_MOUNT_NOALIGN;
1239*4882a593Smuzhiyun return 0;
1240*4882a593Smuzhiyun case Opt_swalloc:
1241*4882a593Smuzhiyun parsing_mp->m_flags |= XFS_MOUNT_SWALLOC;
1242*4882a593Smuzhiyun return 0;
1243*4882a593Smuzhiyun case Opt_sunit:
1244*4882a593Smuzhiyun parsing_mp->m_dalign = result.uint_32;
1245*4882a593Smuzhiyun return 0;
1246*4882a593Smuzhiyun case Opt_swidth:
1247*4882a593Smuzhiyun parsing_mp->m_swidth = result.uint_32;
1248*4882a593Smuzhiyun return 0;
1249*4882a593Smuzhiyun case Opt_inode32:
1250*4882a593Smuzhiyun parsing_mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
1251*4882a593Smuzhiyun return 0;
1252*4882a593Smuzhiyun case Opt_inode64:
1253*4882a593Smuzhiyun parsing_mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS;
1254*4882a593Smuzhiyun return 0;
1255*4882a593Smuzhiyun case Opt_nouuid:
1256*4882a593Smuzhiyun parsing_mp->m_flags |= XFS_MOUNT_NOUUID;
1257*4882a593Smuzhiyun return 0;
1258*4882a593Smuzhiyun case Opt_largeio:
1259*4882a593Smuzhiyun parsing_mp->m_flags |= XFS_MOUNT_LARGEIO;
1260*4882a593Smuzhiyun return 0;
1261*4882a593Smuzhiyun case Opt_nolargeio:
1262*4882a593Smuzhiyun parsing_mp->m_flags &= ~XFS_MOUNT_LARGEIO;
1263*4882a593Smuzhiyun return 0;
1264*4882a593Smuzhiyun case Opt_filestreams:
1265*4882a593Smuzhiyun parsing_mp->m_flags |= XFS_MOUNT_FILESTREAMS;
1266*4882a593Smuzhiyun return 0;
1267*4882a593Smuzhiyun case Opt_noquota:
1268*4882a593Smuzhiyun parsing_mp->m_qflags &= ~XFS_ALL_QUOTA_ACCT;
1269*4882a593Smuzhiyun parsing_mp->m_qflags &= ~XFS_ALL_QUOTA_ENFD;
1270*4882a593Smuzhiyun parsing_mp->m_qflags &= ~XFS_ALL_QUOTA_ACTIVE;
1271*4882a593Smuzhiyun return 0;
1272*4882a593Smuzhiyun case Opt_quota:
1273*4882a593Smuzhiyun case Opt_uquota:
1274*4882a593Smuzhiyun case Opt_usrquota:
1275*4882a593Smuzhiyun parsing_mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE |
1276*4882a593Smuzhiyun XFS_UQUOTA_ENFD);
1277*4882a593Smuzhiyun return 0;
1278*4882a593Smuzhiyun case Opt_qnoenforce:
1279*4882a593Smuzhiyun case Opt_uqnoenforce:
1280*4882a593Smuzhiyun parsing_mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE);
1281*4882a593Smuzhiyun parsing_mp->m_qflags &= ~XFS_UQUOTA_ENFD;
1282*4882a593Smuzhiyun return 0;
1283*4882a593Smuzhiyun case Opt_pquota:
1284*4882a593Smuzhiyun case Opt_prjquota:
1285*4882a593Smuzhiyun parsing_mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE |
1286*4882a593Smuzhiyun XFS_PQUOTA_ENFD);
1287*4882a593Smuzhiyun return 0;
1288*4882a593Smuzhiyun case Opt_pqnoenforce:
1289*4882a593Smuzhiyun parsing_mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
1290*4882a593Smuzhiyun parsing_mp->m_qflags &= ~XFS_PQUOTA_ENFD;
1291*4882a593Smuzhiyun return 0;
1292*4882a593Smuzhiyun case Opt_gquota:
1293*4882a593Smuzhiyun case Opt_grpquota:
1294*4882a593Smuzhiyun parsing_mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE |
1295*4882a593Smuzhiyun XFS_GQUOTA_ENFD);
1296*4882a593Smuzhiyun return 0;
1297*4882a593Smuzhiyun case Opt_gqnoenforce:
1298*4882a593Smuzhiyun parsing_mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
1299*4882a593Smuzhiyun parsing_mp->m_qflags &= ~XFS_GQUOTA_ENFD;
1300*4882a593Smuzhiyun return 0;
1301*4882a593Smuzhiyun case Opt_discard:
1302*4882a593Smuzhiyun parsing_mp->m_flags |= XFS_MOUNT_DISCARD;
1303*4882a593Smuzhiyun return 0;
1304*4882a593Smuzhiyun case Opt_nodiscard:
1305*4882a593Smuzhiyun parsing_mp->m_flags &= ~XFS_MOUNT_DISCARD;
1306*4882a593Smuzhiyun return 0;
1307*4882a593Smuzhiyun #ifdef CONFIG_FS_DAX
1308*4882a593Smuzhiyun case Opt_dax:
1309*4882a593Smuzhiyun xfs_mount_set_dax_mode(parsing_mp, XFS_DAX_ALWAYS);
1310*4882a593Smuzhiyun return 0;
1311*4882a593Smuzhiyun case Opt_dax_enum:
1312*4882a593Smuzhiyun xfs_mount_set_dax_mode(parsing_mp, result.uint_32);
1313*4882a593Smuzhiyun return 0;
1314*4882a593Smuzhiyun #endif
1315*4882a593Smuzhiyun /* Following mount options will be removed in September 2025 */
1316*4882a593Smuzhiyun case Opt_ikeep:
1317*4882a593Smuzhiyun xfs_fs_warn_deprecated(fc, param, XFS_MOUNT_IKEEP, true);
1318*4882a593Smuzhiyun parsing_mp->m_flags |= XFS_MOUNT_IKEEP;
1319*4882a593Smuzhiyun return 0;
1320*4882a593Smuzhiyun case Opt_noikeep:
1321*4882a593Smuzhiyun xfs_fs_warn_deprecated(fc, param, XFS_MOUNT_IKEEP, false);
1322*4882a593Smuzhiyun parsing_mp->m_flags &= ~XFS_MOUNT_IKEEP;
1323*4882a593Smuzhiyun return 0;
1324*4882a593Smuzhiyun case Opt_attr2:
1325*4882a593Smuzhiyun xfs_fs_warn_deprecated(fc, param, XFS_MOUNT_ATTR2, true);
1326*4882a593Smuzhiyun parsing_mp->m_flags |= XFS_MOUNT_ATTR2;
1327*4882a593Smuzhiyun return 0;
1328*4882a593Smuzhiyun case Opt_noattr2:
1329*4882a593Smuzhiyun xfs_fs_warn_deprecated(fc, param, XFS_MOUNT_NOATTR2, true);
1330*4882a593Smuzhiyun parsing_mp->m_flags &= ~XFS_MOUNT_ATTR2;
1331*4882a593Smuzhiyun parsing_mp->m_flags |= XFS_MOUNT_NOATTR2;
1332*4882a593Smuzhiyun return 0;
1333*4882a593Smuzhiyun default:
1334*4882a593Smuzhiyun xfs_warn(parsing_mp, "unknown mount option [%s].", param->key);
1335*4882a593Smuzhiyun return -EINVAL;
1336*4882a593Smuzhiyun }
1337*4882a593Smuzhiyun
1338*4882a593Smuzhiyun return 0;
1339*4882a593Smuzhiyun }
1340*4882a593Smuzhiyun
1341*4882a593Smuzhiyun static int
xfs_fc_validate_params(struct xfs_mount * mp)1342*4882a593Smuzhiyun xfs_fc_validate_params(
1343*4882a593Smuzhiyun struct xfs_mount *mp)
1344*4882a593Smuzhiyun {
1345*4882a593Smuzhiyun /*
1346*4882a593Smuzhiyun * no recovery flag requires a read-only mount
1347*4882a593Smuzhiyun */
1348*4882a593Smuzhiyun if ((mp->m_flags & XFS_MOUNT_NORECOVERY) &&
1349*4882a593Smuzhiyun !(mp->m_flags & XFS_MOUNT_RDONLY)) {
1350*4882a593Smuzhiyun xfs_warn(mp, "no-recovery mounts must be read-only.");
1351*4882a593Smuzhiyun return -EINVAL;
1352*4882a593Smuzhiyun }
1353*4882a593Smuzhiyun
1354*4882a593Smuzhiyun if ((mp->m_flags & XFS_MOUNT_NOALIGN) &&
1355*4882a593Smuzhiyun (mp->m_dalign || mp->m_swidth)) {
1356*4882a593Smuzhiyun xfs_warn(mp,
1357*4882a593Smuzhiyun "sunit and swidth options incompatible with the noalign option");
1358*4882a593Smuzhiyun return -EINVAL;
1359*4882a593Smuzhiyun }
1360*4882a593Smuzhiyun
1361*4882a593Smuzhiyun if (!IS_ENABLED(CONFIG_XFS_QUOTA) && mp->m_qflags != 0) {
1362*4882a593Smuzhiyun xfs_warn(mp, "quota support not available in this kernel.");
1363*4882a593Smuzhiyun return -EINVAL;
1364*4882a593Smuzhiyun }
1365*4882a593Smuzhiyun
1366*4882a593Smuzhiyun if ((mp->m_dalign && !mp->m_swidth) ||
1367*4882a593Smuzhiyun (!mp->m_dalign && mp->m_swidth)) {
1368*4882a593Smuzhiyun xfs_warn(mp, "sunit and swidth must be specified together");
1369*4882a593Smuzhiyun return -EINVAL;
1370*4882a593Smuzhiyun }
1371*4882a593Smuzhiyun
1372*4882a593Smuzhiyun if (mp->m_dalign && (mp->m_swidth % mp->m_dalign != 0)) {
1373*4882a593Smuzhiyun xfs_warn(mp,
1374*4882a593Smuzhiyun "stripe width (%d) must be a multiple of the stripe unit (%d)",
1375*4882a593Smuzhiyun mp->m_swidth, mp->m_dalign);
1376*4882a593Smuzhiyun return -EINVAL;
1377*4882a593Smuzhiyun }
1378*4882a593Smuzhiyun
1379*4882a593Smuzhiyun if (mp->m_logbufs != -1 &&
1380*4882a593Smuzhiyun mp->m_logbufs != 0 &&
1381*4882a593Smuzhiyun (mp->m_logbufs < XLOG_MIN_ICLOGS ||
1382*4882a593Smuzhiyun mp->m_logbufs > XLOG_MAX_ICLOGS)) {
1383*4882a593Smuzhiyun xfs_warn(mp, "invalid logbufs value: %d [not %d-%d]",
1384*4882a593Smuzhiyun mp->m_logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS);
1385*4882a593Smuzhiyun return -EINVAL;
1386*4882a593Smuzhiyun }
1387*4882a593Smuzhiyun
1388*4882a593Smuzhiyun if (mp->m_logbsize != -1 &&
1389*4882a593Smuzhiyun mp->m_logbsize != 0 &&
1390*4882a593Smuzhiyun (mp->m_logbsize < XLOG_MIN_RECORD_BSIZE ||
1391*4882a593Smuzhiyun mp->m_logbsize > XLOG_MAX_RECORD_BSIZE ||
1392*4882a593Smuzhiyun !is_power_of_2(mp->m_logbsize))) {
1393*4882a593Smuzhiyun xfs_warn(mp,
1394*4882a593Smuzhiyun "invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]",
1395*4882a593Smuzhiyun mp->m_logbsize);
1396*4882a593Smuzhiyun return -EINVAL;
1397*4882a593Smuzhiyun }
1398*4882a593Smuzhiyun
1399*4882a593Smuzhiyun if ((mp->m_flags & XFS_MOUNT_ALLOCSIZE) &&
1400*4882a593Smuzhiyun (mp->m_allocsize_log > XFS_MAX_IO_LOG ||
1401*4882a593Smuzhiyun mp->m_allocsize_log < XFS_MIN_IO_LOG)) {
1402*4882a593Smuzhiyun xfs_warn(mp, "invalid log iosize: %d [not %d-%d]",
1403*4882a593Smuzhiyun mp->m_allocsize_log, XFS_MIN_IO_LOG, XFS_MAX_IO_LOG);
1404*4882a593Smuzhiyun return -EINVAL;
1405*4882a593Smuzhiyun }
1406*4882a593Smuzhiyun
1407*4882a593Smuzhiyun return 0;
1408*4882a593Smuzhiyun }
1409*4882a593Smuzhiyun
1410*4882a593Smuzhiyun static int
xfs_fc_fill_super(struct super_block * sb,struct fs_context * fc)1411*4882a593Smuzhiyun xfs_fc_fill_super(
1412*4882a593Smuzhiyun struct super_block *sb,
1413*4882a593Smuzhiyun struct fs_context *fc)
1414*4882a593Smuzhiyun {
1415*4882a593Smuzhiyun struct xfs_mount *mp = sb->s_fs_info;
1416*4882a593Smuzhiyun struct inode *root;
1417*4882a593Smuzhiyun int flags = 0, error;
1418*4882a593Smuzhiyun
1419*4882a593Smuzhiyun mp->m_super = sb;
1420*4882a593Smuzhiyun
1421*4882a593Smuzhiyun error = xfs_fc_validate_params(mp);
1422*4882a593Smuzhiyun if (error)
1423*4882a593Smuzhiyun goto out_free_names;
1424*4882a593Smuzhiyun
1425*4882a593Smuzhiyun sb_min_blocksize(sb, BBSIZE);
1426*4882a593Smuzhiyun sb->s_xattr = xfs_xattr_handlers;
1427*4882a593Smuzhiyun sb->s_export_op = &xfs_export_operations;
1428*4882a593Smuzhiyun #ifdef CONFIG_XFS_QUOTA
1429*4882a593Smuzhiyun sb->s_qcop = &xfs_quotactl_operations;
1430*4882a593Smuzhiyun sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP | QTYPE_MASK_PRJ;
1431*4882a593Smuzhiyun #endif
1432*4882a593Smuzhiyun sb->s_op = &xfs_super_operations;
1433*4882a593Smuzhiyun
1434*4882a593Smuzhiyun /*
1435*4882a593Smuzhiyun * Delay mount work if the debug hook is set. This is debug
1436*4882a593Smuzhiyun * instrumention to coordinate simulation of xfs mount failures with
1437*4882a593Smuzhiyun * VFS superblock operations
1438*4882a593Smuzhiyun */
1439*4882a593Smuzhiyun if (xfs_globals.mount_delay) {
1440*4882a593Smuzhiyun xfs_notice(mp, "Delaying mount for %d seconds.",
1441*4882a593Smuzhiyun xfs_globals.mount_delay);
1442*4882a593Smuzhiyun msleep(xfs_globals.mount_delay * 1000);
1443*4882a593Smuzhiyun }
1444*4882a593Smuzhiyun
1445*4882a593Smuzhiyun if (fc->sb_flags & SB_SILENT)
1446*4882a593Smuzhiyun flags |= XFS_MFSI_QUIET;
1447*4882a593Smuzhiyun
1448*4882a593Smuzhiyun error = xfs_open_devices(mp);
1449*4882a593Smuzhiyun if (error)
1450*4882a593Smuzhiyun goto out_free_names;
1451*4882a593Smuzhiyun
1452*4882a593Smuzhiyun error = xfs_init_mount_workqueues(mp);
1453*4882a593Smuzhiyun if (error)
1454*4882a593Smuzhiyun goto out_close_devices;
1455*4882a593Smuzhiyun
1456*4882a593Smuzhiyun error = xfs_init_percpu_counters(mp);
1457*4882a593Smuzhiyun if (error)
1458*4882a593Smuzhiyun goto out_destroy_workqueues;
1459*4882a593Smuzhiyun
1460*4882a593Smuzhiyun /* Allocate stats memory before we do operations that might use it */
1461*4882a593Smuzhiyun mp->m_stats.xs_stats = alloc_percpu(struct xfsstats);
1462*4882a593Smuzhiyun if (!mp->m_stats.xs_stats) {
1463*4882a593Smuzhiyun error = -ENOMEM;
1464*4882a593Smuzhiyun goto out_destroy_counters;
1465*4882a593Smuzhiyun }
1466*4882a593Smuzhiyun
1467*4882a593Smuzhiyun error = xfs_readsb(mp, flags);
1468*4882a593Smuzhiyun if (error)
1469*4882a593Smuzhiyun goto out_free_stats;
1470*4882a593Smuzhiyun
1471*4882a593Smuzhiyun error = xfs_finish_flags(mp);
1472*4882a593Smuzhiyun if (error)
1473*4882a593Smuzhiyun goto out_free_sb;
1474*4882a593Smuzhiyun
1475*4882a593Smuzhiyun error = xfs_setup_devices(mp);
1476*4882a593Smuzhiyun if (error)
1477*4882a593Smuzhiyun goto out_free_sb;
1478*4882a593Smuzhiyun
1479*4882a593Smuzhiyun /* V4 support is undergoing deprecation. */
1480*4882a593Smuzhiyun if (!xfs_sb_version_hascrc(&mp->m_sb)) {
1481*4882a593Smuzhiyun #ifdef CONFIG_XFS_SUPPORT_V4
1482*4882a593Smuzhiyun xfs_warn_once(mp,
1483*4882a593Smuzhiyun "Deprecated V4 format (crc=0) will not be supported after September 2030.");
1484*4882a593Smuzhiyun #else
1485*4882a593Smuzhiyun xfs_warn(mp,
1486*4882a593Smuzhiyun "Deprecated V4 format (crc=0) not supported by kernel.");
1487*4882a593Smuzhiyun error = -EINVAL;
1488*4882a593Smuzhiyun goto out_free_sb;
1489*4882a593Smuzhiyun #endif
1490*4882a593Smuzhiyun }
1491*4882a593Smuzhiyun
1492*4882a593Smuzhiyun /*
1493*4882a593Smuzhiyun * XFS block mappings use 54 bits to store the logical block offset.
1494*4882a593Smuzhiyun * This should suffice to handle the maximum file size that the VFS
1495*4882a593Smuzhiyun * supports (currently 2^63 bytes on 64-bit and ULONG_MAX << PAGE_SHIFT
1496*4882a593Smuzhiyun * bytes on 32-bit), but as XFS and VFS have gotten the s_maxbytes
1497*4882a593Smuzhiyun * calculation wrong on 32-bit kernels in the past, we'll add a WARN_ON
1498*4882a593Smuzhiyun * to check this assertion.
1499*4882a593Smuzhiyun *
1500*4882a593Smuzhiyun * Avoid integer overflow by comparing the maximum bmbt offset to the
1501*4882a593Smuzhiyun * maximum pagecache offset in units of fs blocks.
1502*4882a593Smuzhiyun */
1503*4882a593Smuzhiyun if (XFS_B_TO_FSBT(mp, MAX_LFS_FILESIZE) > XFS_MAX_FILEOFF) {
1504*4882a593Smuzhiyun xfs_warn(mp,
1505*4882a593Smuzhiyun "MAX_LFS_FILESIZE block offset (%llu) exceeds extent map maximum (%llu)!",
1506*4882a593Smuzhiyun XFS_B_TO_FSBT(mp, MAX_LFS_FILESIZE),
1507*4882a593Smuzhiyun XFS_MAX_FILEOFF);
1508*4882a593Smuzhiyun error = -EINVAL;
1509*4882a593Smuzhiyun goto out_free_sb;
1510*4882a593Smuzhiyun }
1511*4882a593Smuzhiyun
1512*4882a593Smuzhiyun error = xfs_filestream_mount(mp);
1513*4882a593Smuzhiyun if (error)
1514*4882a593Smuzhiyun goto out_free_sb;
1515*4882a593Smuzhiyun
1516*4882a593Smuzhiyun /*
1517*4882a593Smuzhiyun * we must configure the block size in the superblock before we run the
1518*4882a593Smuzhiyun * full mount process as the mount process can lookup and cache inodes.
1519*4882a593Smuzhiyun */
1520*4882a593Smuzhiyun sb->s_magic = XFS_SUPER_MAGIC;
1521*4882a593Smuzhiyun sb->s_blocksize = mp->m_sb.sb_blocksize;
1522*4882a593Smuzhiyun sb->s_blocksize_bits = ffs(sb->s_blocksize) - 1;
1523*4882a593Smuzhiyun sb->s_maxbytes = MAX_LFS_FILESIZE;
1524*4882a593Smuzhiyun sb->s_max_links = XFS_MAXLINK;
1525*4882a593Smuzhiyun sb->s_time_gran = 1;
1526*4882a593Smuzhiyun if (xfs_sb_version_hasbigtime(&mp->m_sb)) {
1527*4882a593Smuzhiyun sb->s_time_min = xfs_bigtime_to_unix(XFS_BIGTIME_TIME_MIN);
1528*4882a593Smuzhiyun sb->s_time_max = xfs_bigtime_to_unix(XFS_BIGTIME_TIME_MAX);
1529*4882a593Smuzhiyun } else {
1530*4882a593Smuzhiyun sb->s_time_min = XFS_LEGACY_TIME_MIN;
1531*4882a593Smuzhiyun sb->s_time_max = XFS_LEGACY_TIME_MAX;
1532*4882a593Smuzhiyun }
1533*4882a593Smuzhiyun trace_xfs_inode_timestamp_range(mp, sb->s_time_min, sb->s_time_max);
1534*4882a593Smuzhiyun sb->s_iflags |= SB_I_CGROUPWB;
1535*4882a593Smuzhiyun
1536*4882a593Smuzhiyun set_posix_acl_flag(sb);
1537*4882a593Smuzhiyun
1538*4882a593Smuzhiyun /* version 5 superblocks support inode version counters. */
1539*4882a593Smuzhiyun if (XFS_SB_VERSION_NUM(&mp->m_sb) == XFS_SB_VERSION_5)
1540*4882a593Smuzhiyun sb->s_flags |= SB_I_VERSION;
1541*4882a593Smuzhiyun
1542*4882a593Smuzhiyun if (xfs_sb_version_hasbigtime(&mp->m_sb))
1543*4882a593Smuzhiyun xfs_warn(mp,
1544*4882a593Smuzhiyun "EXPERIMENTAL big timestamp feature in use. Use at your own risk!");
1545*4882a593Smuzhiyun
1546*4882a593Smuzhiyun if (mp->m_flags & XFS_MOUNT_DAX_ALWAYS) {
1547*4882a593Smuzhiyun bool rtdev_is_dax = false, datadev_is_dax;
1548*4882a593Smuzhiyun
1549*4882a593Smuzhiyun xfs_warn(mp,
1550*4882a593Smuzhiyun "DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
1551*4882a593Smuzhiyun
1552*4882a593Smuzhiyun datadev_is_dax = bdev_dax_supported(mp->m_ddev_targp->bt_bdev,
1553*4882a593Smuzhiyun sb->s_blocksize);
1554*4882a593Smuzhiyun if (mp->m_rtdev_targp)
1555*4882a593Smuzhiyun rtdev_is_dax = bdev_dax_supported(
1556*4882a593Smuzhiyun mp->m_rtdev_targp->bt_bdev, sb->s_blocksize);
1557*4882a593Smuzhiyun if (!rtdev_is_dax && !datadev_is_dax) {
1558*4882a593Smuzhiyun xfs_alert(mp,
1559*4882a593Smuzhiyun "DAX unsupported by block device. Turning off DAX.");
1560*4882a593Smuzhiyun xfs_mount_set_dax_mode(mp, XFS_DAX_NEVER);
1561*4882a593Smuzhiyun }
1562*4882a593Smuzhiyun if (xfs_sb_version_hasreflink(&mp->m_sb)) {
1563*4882a593Smuzhiyun xfs_alert(mp,
1564*4882a593Smuzhiyun "DAX and reflink cannot be used together!");
1565*4882a593Smuzhiyun error = -EINVAL;
1566*4882a593Smuzhiyun goto out_filestream_unmount;
1567*4882a593Smuzhiyun }
1568*4882a593Smuzhiyun }
1569*4882a593Smuzhiyun
1570*4882a593Smuzhiyun if (mp->m_flags & XFS_MOUNT_DISCARD) {
1571*4882a593Smuzhiyun struct request_queue *q = bdev_get_queue(sb->s_bdev);
1572*4882a593Smuzhiyun
1573*4882a593Smuzhiyun if (!blk_queue_discard(q)) {
1574*4882a593Smuzhiyun xfs_warn(mp, "mounting with \"discard\" option, but "
1575*4882a593Smuzhiyun "the device does not support discard");
1576*4882a593Smuzhiyun mp->m_flags &= ~XFS_MOUNT_DISCARD;
1577*4882a593Smuzhiyun }
1578*4882a593Smuzhiyun }
1579*4882a593Smuzhiyun
1580*4882a593Smuzhiyun if (xfs_sb_version_hasreflink(&mp->m_sb)) {
1581*4882a593Smuzhiyun if (mp->m_sb.sb_rblocks) {
1582*4882a593Smuzhiyun xfs_alert(mp,
1583*4882a593Smuzhiyun "reflink not compatible with realtime device!");
1584*4882a593Smuzhiyun error = -EINVAL;
1585*4882a593Smuzhiyun goto out_filestream_unmount;
1586*4882a593Smuzhiyun }
1587*4882a593Smuzhiyun
1588*4882a593Smuzhiyun if (xfs_globals.always_cow) {
1589*4882a593Smuzhiyun xfs_info(mp, "using DEBUG-only always_cow mode.");
1590*4882a593Smuzhiyun mp->m_always_cow = true;
1591*4882a593Smuzhiyun }
1592*4882a593Smuzhiyun }
1593*4882a593Smuzhiyun
1594*4882a593Smuzhiyun if (xfs_sb_version_hasrmapbt(&mp->m_sb) && mp->m_sb.sb_rblocks) {
1595*4882a593Smuzhiyun xfs_alert(mp,
1596*4882a593Smuzhiyun "reverse mapping btree not compatible with realtime device!");
1597*4882a593Smuzhiyun error = -EINVAL;
1598*4882a593Smuzhiyun goto out_filestream_unmount;
1599*4882a593Smuzhiyun }
1600*4882a593Smuzhiyun
1601*4882a593Smuzhiyun if (xfs_sb_version_hasinobtcounts(&mp->m_sb))
1602*4882a593Smuzhiyun xfs_warn(mp,
1603*4882a593Smuzhiyun "EXPERIMENTAL inode btree counters feature in use. Use at your own risk!");
1604*4882a593Smuzhiyun
1605*4882a593Smuzhiyun error = xfs_mountfs(mp);
1606*4882a593Smuzhiyun if (error)
1607*4882a593Smuzhiyun goto out_filestream_unmount;
1608*4882a593Smuzhiyun
1609*4882a593Smuzhiyun root = igrab(VFS_I(mp->m_rootip));
1610*4882a593Smuzhiyun if (!root) {
1611*4882a593Smuzhiyun error = -ENOENT;
1612*4882a593Smuzhiyun goto out_unmount;
1613*4882a593Smuzhiyun }
1614*4882a593Smuzhiyun sb->s_root = d_make_root(root);
1615*4882a593Smuzhiyun if (!sb->s_root) {
1616*4882a593Smuzhiyun error = -ENOMEM;
1617*4882a593Smuzhiyun goto out_unmount;
1618*4882a593Smuzhiyun }
1619*4882a593Smuzhiyun
1620*4882a593Smuzhiyun return 0;
1621*4882a593Smuzhiyun
1622*4882a593Smuzhiyun out_filestream_unmount:
1623*4882a593Smuzhiyun xfs_filestream_unmount(mp);
1624*4882a593Smuzhiyun out_free_sb:
1625*4882a593Smuzhiyun xfs_freesb(mp);
1626*4882a593Smuzhiyun out_free_stats:
1627*4882a593Smuzhiyun free_percpu(mp->m_stats.xs_stats);
1628*4882a593Smuzhiyun out_destroy_counters:
1629*4882a593Smuzhiyun xfs_destroy_percpu_counters(mp);
1630*4882a593Smuzhiyun out_destroy_workqueues:
1631*4882a593Smuzhiyun xfs_destroy_mount_workqueues(mp);
1632*4882a593Smuzhiyun out_close_devices:
1633*4882a593Smuzhiyun xfs_close_devices(mp);
1634*4882a593Smuzhiyun out_free_names:
1635*4882a593Smuzhiyun sb->s_fs_info = NULL;
1636*4882a593Smuzhiyun xfs_mount_free(mp);
1637*4882a593Smuzhiyun return error;
1638*4882a593Smuzhiyun
1639*4882a593Smuzhiyun out_unmount:
1640*4882a593Smuzhiyun xfs_filestream_unmount(mp);
1641*4882a593Smuzhiyun xfs_unmountfs(mp);
1642*4882a593Smuzhiyun goto out_free_sb;
1643*4882a593Smuzhiyun }
1644*4882a593Smuzhiyun
1645*4882a593Smuzhiyun static int
xfs_fc_get_tree(struct fs_context * fc)1646*4882a593Smuzhiyun xfs_fc_get_tree(
1647*4882a593Smuzhiyun struct fs_context *fc)
1648*4882a593Smuzhiyun {
1649*4882a593Smuzhiyun return get_tree_bdev(fc, xfs_fc_fill_super);
1650*4882a593Smuzhiyun }
1651*4882a593Smuzhiyun
1652*4882a593Smuzhiyun static int
xfs_remount_rw(struct xfs_mount * mp)1653*4882a593Smuzhiyun xfs_remount_rw(
1654*4882a593Smuzhiyun struct xfs_mount *mp)
1655*4882a593Smuzhiyun {
1656*4882a593Smuzhiyun struct xfs_sb *sbp = &mp->m_sb;
1657*4882a593Smuzhiyun int error;
1658*4882a593Smuzhiyun
1659*4882a593Smuzhiyun if (mp->m_flags & XFS_MOUNT_NORECOVERY) {
1660*4882a593Smuzhiyun xfs_warn(mp,
1661*4882a593Smuzhiyun "ro->rw transition prohibited on norecovery mount");
1662*4882a593Smuzhiyun return -EINVAL;
1663*4882a593Smuzhiyun }
1664*4882a593Smuzhiyun
1665*4882a593Smuzhiyun if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
1666*4882a593Smuzhiyun xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
1667*4882a593Smuzhiyun xfs_warn(mp,
1668*4882a593Smuzhiyun "ro->rw transition prohibited on unknown (0x%x) ro-compat filesystem",
1669*4882a593Smuzhiyun (sbp->sb_features_ro_compat &
1670*4882a593Smuzhiyun XFS_SB_FEAT_RO_COMPAT_UNKNOWN));
1671*4882a593Smuzhiyun return -EINVAL;
1672*4882a593Smuzhiyun }
1673*4882a593Smuzhiyun
1674*4882a593Smuzhiyun mp->m_flags &= ~XFS_MOUNT_RDONLY;
1675*4882a593Smuzhiyun
1676*4882a593Smuzhiyun /*
1677*4882a593Smuzhiyun * If this is the first remount to writeable state we might have some
1678*4882a593Smuzhiyun * superblock changes to update.
1679*4882a593Smuzhiyun */
1680*4882a593Smuzhiyun if (mp->m_update_sb) {
1681*4882a593Smuzhiyun error = xfs_sync_sb(mp, false);
1682*4882a593Smuzhiyun if (error) {
1683*4882a593Smuzhiyun xfs_warn(mp, "failed to write sb changes");
1684*4882a593Smuzhiyun return error;
1685*4882a593Smuzhiyun }
1686*4882a593Smuzhiyun mp->m_update_sb = false;
1687*4882a593Smuzhiyun }
1688*4882a593Smuzhiyun
1689*4882a593Smuzhiyun /*
1690*4882a593Smuzhiyun * Fill out the reserve pool if it is empty. Use the stashed value if
1691*4882a593Smuzhiyun * it is non-zero, otherwise go with the default.
1692*4882a593Smuzhiyun */
1693*4882a593Smuzhiyun xfs_restore_resvblks(mp);
1694*4882a593Smuzhiyun xfs_log_work_queue(mp);
1695*4882a593Smuzhiyun
1696*4882a593Smuzhiyun /* Recover any CoW blocks that never got remapped. */
1697*4882a593Smuzhiyun error = xfs_reflink_recover_cow(mp);
1698*4882a593Smuzhiyun if (error) {
1699*4882a593Smuzhiyun xfs_err(mp,
1700*4882a593Smuzhiyun "Error %d recovering leftover CoW allocations.", error);
1701*4882a593Smuzhiyun xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
1702*4882a593Smuzhiyun return error;
1703*4882a593Smuzhiyun }
1704*4882a593Smuzhiyun xfs_start_block_reaping(mp);
1705*4882a593Smuzhiyun
1706*4882a593Smuzhiyun /* Create the per-AG metadata reservation pool .*/
1707*4882a593Smuzhiyun error = xfs_fs_reserve_ag_blocks(mp);
1708*4882a593Smuzhiyun if (error && error != -ENOSPC)
1709*4882a593Smuzhiyun return error;
1710*4882a593Smuzhiyun
1711*4882a593Smuzhiyun return 0;
1712*4882a593Smuzhiyun }
1713*4882a593Smuzhiyun
1714*4882a593Smuzhiyun static int
xfs_remount_ro(struct xfs_mount * mp)1715*4882a593Smuzhiyun xfs_remount_ro(
1716*4882a593Smuzhiyun struct xfs_mount *mp)
1717*4882a593Smuzhiyun {
1718*4882a593Smuzhiyun struct xfs_eofblocks eofb = {
1719*4882a593Smuzhiyun .eof_flags = XFS_EOF_FLAGS_SYNC,
1720*4882a593Smuzhiyun };
1721*4882a593Smuzhiyun int error;
1722*4882a593Smuzhiyun
1723*4882a593Smuzhiyun /* Flush all the dirty data to disk. */
1724*4882a593Smuzhiyun error = sync_filesystem(mp->m_super);
1725*4882a593Smuzhiyun if (error)
1726*4882a593Smuzhiyun return error;
1727*4882a593Smuzhiyun
1728*4882a593Smuzhiyun /*
1729*4882a593Smuzhiyun * Cancel background eofb scanning so it cannot race with the final
1730*4882a593Smuzhiyun * log force+buftarg wait and deadlock the remount.
1731*4882a593Smuzhiyun */
1732*4882a593Smuzhiyun xfs_stop_block_reaping(mp);
1733*4882a593Smuzhiyun
1734*4882a593Smuzhiyun /*
1735*4882a593Smuzhiyun * Clear out all remaining COW staging extents and speculative post-EOF
1736*4882a593Smuzhiyun * preallocations so that we don't leave inodes requiring inactivation
1737*4882a593Smuzhiyun * cleanups during reclaim on a read-only mount. We must process every
1738*4882a593Smuzhiyun * cached inode, so this requires a synchronous cache scan.
1739*4882a593Smuzhiyun */
1740*4882a593Smuzhiyun error = xfs_icache_free_cowblocks(mp, &eofb);
1741*4882a593Smuzhiyun if (error) {
1742*4882a593Smuzhiyun xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
1743*4882a593Smuzhiyun return error;
1744*4882a593Smuzhiyun }
1745*4882a593Smuzhiyun
1746*4882a593Smuzhiyun /* Free the per-AG metadata reservation pool. */
1747*4882a593Smuzhiyun error = xfs_fs_unreserve_ag_blocks(mp);
1748*4882a593Smuzhiyun if (error) {
1749*4882a593Smuzhiyun xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
1750*4882a593Smuzhiyun return error;
1751*4882a593Smuzhiyun }
1752*4882a593Smuzhiyun
1753*4882a593Smuzhiyun /*
1754*4882a593Smuzhiyun * Before we sync the metadata, we need to free up the reserve block
1755*4882a593Smuzhiyun * pool so that the used block count in the superblock on disk is
1756*4882a593Smuzhiyun * correct at the end of the remount. Stash the current* reserve pool
1757*4882a593Smuzhiyun * size so that if we get remounted rw, we can return it to the same
1758*4882a593Smuzhiyun * size.
1759*4882a593Smuzhiyun */
1760*4882a593Smuzhiyun xfs_save_resvblks(mp);
1761*4882a593Smuzhiyun
1762*4882a593Smuzhiyun xfs_quiesce_attr(mp);
1763*4882a593Smuzhiyun mp->m_flags |= XFS_MOUNT_RDONLY;
1764*4882a593Smuzhiyun
1765*4882a593Smuzhiyun return 0;
1766*4882a593Smuzhiyun }
1767*4882a593Smuzhiyun
1768*4882a593Smuzhiyun /*
1769*4882a593Smuzhiyun * Logically we would return an error here to prevent users from believing
1770*4882a593Smuzhiyun * they might have changed mount options using remount which can't be changed.
1771*4882a593Smuzhiyun *
1772*4882a593Smuzhiyun * But unfortunately mount(8) adds all options from mtab and fstab to the mount
1773*4882a593Smuzhiyun * arguments in some cases so we can't blindly reject options, but have to
1774*4882a593Smuzhiyun * check for each specified option if it actually differs from the currently
1775*4882a593Smuzhiyun * set option and only reject it if that's the case.
1776*4882a593Smuzhiyun *
1777*4882a593Smuzhiyun * Until that is implemented we return success for every remount request, and
1778*4882a593Smuzhiyun * silently ignore all options that we can't actually change.
1779*4882a593Smuzhiyun */
1780*4882a593Smuzhiyun static int
xfs_fc_reconfigure(struct fs_context * fc)1781*4882a593Smuzhiyun xfs_fc_reconfigure(
1782*4882a593Smuzhiyun struct fs_context *fc)
1783*4882a593Smuzhiyun {
1784*4882a593Smuzhiyun struct xfs_mount *mp = XFS_M(fc->root->d_sb);
1785*4882a593Smuzhiyun struct xfs_mount *new_mp = fc->s_fs_info;
1786*4882a593Smuzhiyun xfs_sb_t *sbp = &mp->m_sb;
1787*4882a593Smuzhiyun int flags = fc->sb_flags;
1788*4882a593Smuzhiyun int error;
1789*4882a593Smuzhiyun
1790*4882a593Smuzhiyun /* version 5 superblocks always support version counters. */
1791*4882a593Smuzhiyun if (XFS_SB_VERSION_NUM(&mp->m_sb) == XFS_SB_VERSION_5)
1792*4882a593Smuzhiyun fc->sb_flags |= SB_I_VERSION;
1793*4882a593Smuzhiyun
1794*4882a593Smuzhiyun error = xfs_fc_validate_params(new_mp);
1795*4882a593Smuzhiyun if (error)
1796*4882a593Smuzhiyun return error;
1797*4882a593Smuzhiyun
1798*4882a593Smuzhiyun /* inode32 -> inode64 */
1799*4882a593Smuzhiyun if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) &&
1800*4882a593Smuzhiyun !(new_mp->m_flags & XFS_MOUNT_SMALL_INUMS)) {
1801*4882a593Smuzhiyun mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS;
1802*4882a593Smuzhiyun mp->m_maxagi = xfs_set_inode_alloc(mp, sbp->sb_agcount);
1803*4882a593Smuzhiyun }
1804*4882a593Smuzhiyun
1805*4882a593Smuzhiyun /* inode64 -> inode32 */
1806*4882a593Smuzhiyun if (!(mp->m_flags & XFS_MOUNT_SMALL_INUMS) &&
1807*4882a593Smuzhiyun (new_mp->m_flags & XFS_MOUNT_SMALL_INUMS)) {
1808*4882a593Smuzhiyun mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
1809*4882a593Smuzhiyun mp->m_maxagi = xfs_set_inode_alloc(mp, sbp->sb_agcount);
1810*4882a593Smuzhiyun }
1811*4882a593Smuzhiyun
1812*4882a593Smuzhiyun /* ro -> rw */
1813*4882a593Smuzhiyun if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(flags & SB_RDONLY)) {
1814*4882a593Smuzhiyun error = xfs_remount_rw(mp);
1815*4882a593Smuzhiyun if (error)
1816*4882a593Smuzhiyun return error;
1817*4882a593Smuzhiyun }
1818*4882a593Smuzhiyun
1819*4882a593Smuzhiyun /* rw -> ro */
1820*4882a593Smuzhiyun if (!(mp->m_flags & XFS_MOUNT_RDONLY) && (flags & SB_RDONLY)) {
1821*4882a593Smuzhiyun error = xfs_remount_ro(mp);
1822*4882a593Smuzhiyun if (error)
1823*4882a593Smuzhiyun return error;
1824*4882a593Smuzhiyun }
1825*4882a593Smuzhiyun
1826*4882a593Smuzhiyun return 0;
1827*4882a593Smuzhiyun }
1828*4882a593Smuzhiyun
xfs_fc_free(struct fs_context * fc)1829*4882a593Smuzhiyun static void xfs_fc_free(
1830*4882a593Smuzhiyun struct fs_context *fc)
1831*4882a593Smuzhiyun {
1832*4882a593Smuzhiyun struct xfs_mount *mp = fc->s_fs_info;
1833*4882a593Smuzhiyun
1834*4882a593Smuzhiyun /*
1835*4882a593Smuzhiyun * mp is stored in the fs_context when it is initialized.
1836*4882a593Smuzhiyun * mp is transferred to the superblock on a successful mount,
1837*4882a593Smuzhiyun * but if an error occurs before the transfer we have to free
1838*4882a593Smuzhiyun * it here.
1839*4882a593Smuzhiyun */
1840*4882a593Smuzhiyun if (mp)
1841*4882a593Smuzhiyun xfs_mount_free(mp);
1842*4882a593Smuzhiyun }
1843*4882a593Smuzhiyun
1844*4882a593Smuzhiyun static const struct fs_context_operations xfs_context_ops = {
1845*4882a593Smuzhiyun .parse_param = xfs_fc_parse_param,
1846*4882a593Smuzhiyun .get_tree = xfs_fc_get_tree,
1847*4882a593Smuzhiyun .reconfigure = xfs_fc_reconfigure,
1848*4882a593Smuzhiyun .free = xfs_fc_free,
1849*4882a593Smuzhiyun };
1850*4882a593Smuzhiyun
xfs_init_fs_context(struct fs_context * fc)1851*4882a593Smuzhiyun static int xfs_init_fs_context(
1852*4882a593Smuzhiyun struct fs_context *fc)
1853*4882a593Smuzhiyun {
1854*4882a593Smuzhiyun struct xfs_mount *mp;
1855*4882a593Smuzhiyun
1856*4882a593Smuzhiyun mp = kmem_alloc(sizeof(struct xfs_mount), KM_ZERO);
1857*4882a593Smuzhiyun if (!mp)
1858*4882a593Smuzhiyun return -ENOMEM;
1859*4882a593Smuzhiyun
1860*4882a593Smuzhiyun spin_lock_init(&mp->m_sb_lock);
1861*4882a593Smuzhiyun spin_lock_init(&mp->m_agirotor_lock);
1862*4882a593Smuzhiyun INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC);
1863*4882a593Smuzhiyun spin_lock_init(&mp->m_perag_lock);
1864*4882a593Smuzhiyun mutex_init(&mp->m_growlock);
1865*4882a593Smuzhiyun INIT_WORK(&mp->m_flush_inodes_work, xfs_flush_inodes_worker);
1866*4882a593Smuzhiyun INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);
1867*4882a593Smuzhiyun INIT_DELAYED_WORK(&mp->m_eofblocks_work, xfs_eofblocks_worker);
1868*4882a593Smuzhiyun INIT_DELAYED_WORK(&mp->m_cowblocks_work, xfs_cowblocks_worker);
1869*4882a593Smuzhiyun mp->m_kobj.kobject.kset = xfs_kset;
1870*4882a593Smuzhiyun /*
1871*4882a593Smuzhiyun * We don't create the finobt per-ag space reservation until after log
1872*4882a593Smuzhiyun * recovery, so we must set this to true so that an ifree transaction
1873*4882a593Smuzhiyun * started during log recovery will not depend on space reservations
1874*4882a593Smuzhiyun * for finobt expansion.
1875*4882a593Smuzhiyun */
1876*4882a593Smuzhiyun mp->m_finobt_nores = true;
1877*4882a593Smuzhiyun
1878*4882a593Smuzhiyun /*
1879*4882a593Smuzhiyun * These can be overridden by the mount option parsing.
1880*4882a593Smuzhiyun */
1881*4882a593Smuzhiyun mp->m_logbufs = -1;
1882*4882a593Smuzhiyun mp->m_logbsize = -1;
1883*4882a593Smuzhiyun mp->m_allocsize_log = 16; /* 64k */
1884*4882a593Smuzhiyun
1885*4882a593Smuzhiyun /*
1886*4882a593Smuzhiyun * Copy binary VFS mount flags we are interested in.
1887*4882a593Smuzhiyun */
1888*4882a593Smuzhiyun if (fc->sb_flags & SB_RDONLY)
1889*4882a593Smuzhiyun mp->m_flags |= XFS_MOUNT_RDONLY;
1890*4882a593Smuzhiyun if (fc->sb_flags & SB_DIRSYNC)
1891*4882a593Smuzhiyun mp->m_flags |= XFS_MOUNT_DIRSYNC;
1892*4882a593Smuzhiyun if (fc->sb_flags & SB_SYNCHRONOUS)
1893*4882a593Smuzhiyun mp->m_flags |= XFS_MOUNT_WSYNC;
1894*4882a593Smuzhiyun
1895*4882a593Smuzhiyun fc->s_fs_info = mp;
1896*4882a593Smuzhiyun fc->ops = &xfs_context_ops;
1897*4882a593Smuzhiyun
1898*4882a593Smuzhiyun return 0;
1899*4882a593Smuzhiyun }
1900*4882a593Smuzhiyun
1901*4882a593Smuzhiyun static struct file_system_type xfs_fs_type = {
1902*4882a593Smuzhiyun .owner = THIS_MODULE,
1903*4882a593Smuzhiyun .name = "xfs",
1904*4882a593Smuzhiyun .init_fs_context = xfs_init_fs_context,
1905*4882a593Smuzhiyun .parameters = xfs_fs_parameters,
1906*4882a593Smuzhiyun .kill_sb = kill_block_super,
1907*4882a593Smuzhiyun .fs_flags = FS_REQUIRES_DEV,
1908*4882a593Smuzhiyun };
1909*4882a593Smuzhiyun MODULE_ALIAS_FS("xfs");
1910*4882a593Smuzhiyun
1911*4882a593Smuzhiyun STATIC int __init
xfs_init_zones(void)1912*4882a593Smuzhiyun xfs_init_zones(void)
1913*4882a593Smuzhiyun {
1914*4882a593Smuzhiyun xfs_log_ticket_zone = kmem_cache_create("xfs_log_ticket",
1915*4882a593Smuzhiyun sizeof(struct xlog_ticket),
1916*4882a593Smuzhiyun 0, 0, NULL);
1917*4882a593Smuzhiyun if (!xfs_log_ticket_zone)
1918*4882a593Smuzhiyun goto out;
1919*4882a593Smuzhiyun
1920*4882a593Smuzhiyun xfs_bmap_free_item_zone = kmem_cache_create("xfs_bmap_free_item",
1921*4882a593Smuzhiyun sizeof(struct xfs_extent_free_item),
1922*4882a593Smuzhiyun 0, 0, NULL);
1923*4882a593Smuzhiyun if (!xfs_bmap_free_item_zone)
1924*4882a593Smuzhiyun goto out_destroy_log_ticket_zone;
1925*4882a593Smuzhiyun
1926*4882a593Smuzhiyun xfs_btree_cur_zone = kmem_cache_create("xfs_btree_cur",
1927*4882a593Smuzhiyun sizeof(struct xfs_btree_cur),
1928*4882a593Smuzhiyun 0, 0, NULL);
1929*4882a593Smuzhiyun if (!xfs_btree_cur_zone)
1930*4882a593Smuzhiyun goto out_destroy_bmap_free_item_zone;
1931*4882a593Smuzhiyun
1932*4882a593Smuzhiyun xfs_da_state_zone = kmem_cache_create("xfs_da_state",
1933*4882a593Smuzhiyun sizeof(struct xfs_da_state),
1934*4882a593Smuzhiyun 0, 0, NULL);
1935*4882a593Smuzhiyun if (!xfs_da_state_zone)
1936*4882a593Smuzhiyun goto out_destroy_btree_cur_zone;
1937*4882a593Smuzhiyun
1938*4882a593Smuzhiyun xfs_ifork_zone = kmem_cache_create("xfs_ifork",
1939*4882a593Smuzhiyun sizeof(struct xfs_ifork),
1940*4882a593Smuzhiyun 0, 0, NULL);
1941*4882a593Smuzhiyun if (!xfs_ifork_zone)
1942*4882a593Smuzhiyun goto out_destroy_da_state_zone;
1943*4882a593Smuzhiyun
1944*4882a593Smuzhiyun xfs_trans_zone = kmem_cache_create("xfs_trans",
1945*4882a593Smuzhiyun sizeof(struct xfs_trans),
1946*4882a593Smuzhiyun 0, 0, NULL);
1947*4882a593Smuzhiyun if (!xfs_trans_zone)
1948*4882a593Smuzhiyun goto out_destroy_ifork_zone;
1949*4882a593Smuzhiyun
1950*4882a593Smuzhiyun
1951*4882a593Smuzhiyun /*
1952*4882a593Smuzhiyun * The size of the zone allocated buf log item is the maximum
1953*4882a593Smuzhiyun * size possible under XFS. This wastes a little bit of memory,
1954*4882a593Smuzhiyun * but it is much faster.
1955*4882a593Smuzhiyun */
1956*4882a593Smuzhiyun xfs_buf_item_zone = kmem_cache_create("xfs_buf_item",
1957*4882a593Smuzhiyun sizeof(struct xfs_buf_log_item),
1958*4882a593Smuzhiyun 0, 0, NULL);
1959*4882a593Smuzhiyun if (!xfs_buf_item_zone)
1960*4882a593Smuzhiyun goto out_destroy_trans_zone;
1961*4882a593Smuzhiyun
1962*4882a593Smuzhiyun xfs_efd_zone = kmem_cache_create("xfs_efd_item",
1963*4882a593Smuzhiyun (sizeof(struct xfs_efd_log_item) +
1964*4882a593Smuzhiyun (XFS_EFD_MAX_FAST_EXTENTS - 1) *
1965*4882a593Smuzhiyun sizeof(struct xfs_extent)),
1966*4882a593Smuzhiyun 0, 0, NULL);
1967*4882a593Smuzhiyun if (!xfs_efd_zone)
1968*4882a593Smuzhiyun goto out_destroy_buf_item_zone;
1969*4882a593Smuzhiyun
1970*4882a593Smuzhiyun xfs_efi_zone = kmem_cache_create("xfs_efi_item",
1971*4882a593Smuzhiyun (sizeof(struct xfs_efi_log_item) +
1972*4882a593Smuzhiyun (XFS_EFI_MAX_FAST_EXTENTS - 1) *
1973*4882a593Smuzhiyun sizeof(struct xfs_extent)),
1974*4882a593Smuzhiyun 0, 0, NULL);
1975*4882a593Smuzhiyun if (!xfs_efi_zone)
1976*4882a593Smuzhiyun goto out_destroy_efd_zone;
1977*4882a593Smuzhiyun
1978*4882a593Smuzhiyun xfs_inode_zone = kmem_cache_create("xfs_inode",
1979*4882a593Smuzhiyun sizeof(struct xfs_inode), 0,
1980*4882a593Smuzhiyun (SLAB_HWCACHE_ALIGN |
1981*4882a593Smuzhiyun SLAB_RECLAIM_ACCOUNT |
1982*4882a593Smuzhiyun SLAB_MEM_SPREAD | SLAB_ACCOUNT),
1983*4882a593Smuzhiyun xfs_fs_inode_init_once);
1984*4882a593Smuzhiyun if (!xfs_inode_zone)
1985*4882a593Smuzhiyun goto out_destroy_efi_zone;
1986*4882a593Smuzhiyun
1987*4882a593Smuzhiyun xfs_ili_zone = kmem_cache_create("xfs_ili",
1988*4882a593Smuzhiyun sizeof(struct xfs_inode_log_item), 0,
1989*4882a593Smuzhiyun SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
1990*4882a593Smuzhiyun NULL);
1991*4882a593Smuzhiyun if (!xfs_ili_zone)
1992*4882a593Smuzhiyun goto out_destroy_inode_zone;
1993*4882a593Smuzhiyun
1994*4882a593Smuzhiyun xfs_icreate_zone = kmem_cache_create("xfs_icr",
1995*4882a593Smuzhiyun sizeof(struct xfs_icreate_item),
1996*4882a593Smuzhiyun 0, 0, NULL);
1997*4882a593Smuzhiyun if (!xfs_icreate_zone)
1998*4882a593Smuzhiyun goto out_destroy_ili_zone;
1999*4882a593Smuzhiyun
2000*4882a593Smuzhiyun xfs_rud_zone = kmem_cache_create("xfs_rud_item",
2001*4882a593Smuzhiyun sizeof(struct xfs_rud_log_item),
2002*4882a593Smuzhiyun 0, 0, NULL);
2003*4882a593Smuzhiyun if (!xfs_rud_zone)
2004*4882a593Smuzhiyun goto out_destroy_icreate_zone;
2005*4882a593Smuzhiyun
2006*4882a593Smuzhiyun xfs_rui_zone = kmem_cache_create("xfs_rui_item",
2007*4882a593Smuzhiyun xfs_rui_log_item_sizeof(XFS_RUI_MAX_FAST_EXTENTS),
2008*4882a593Smuzhiyun 0, 0, NULL);
2009*4882a593Smuzhiyun if (!xfs_rui_zone)
2010*4882a593Smuzhiyun goto out_destroy_rud_zone;
2011*4882a593Smuzhiyun
2012*4882a593Smuzhiyun xfs_cud_zone = kmem_cache_create("xfs_cud_item",
2013*4882a593Smuzhiyun sizeof(struct xfs_cud_log_item),
2014*4882a593Smuzhiyun 0, 0, NULL);
2015*4882a593Smuzhiyun if (!xfs_cud_zone)
2016*4882a593Smuzhiyun goto out_destroy_rui_zone;
2017*4882a593Smuzhiyun
2018*4882a593Smuzhiyun xfs_cui_zone = kmem_cache_create("xfs_cui_item",
2019*4882a593Smuzhiyun xfs_cui_log_item_sizeof(XFS_CUI_MAX_FAST_EXTENTS),
2020*4882a593Smuzhiyun 0, 0, NULL);
2021*4882a593Smuzhiyun if (!xfs_cui_zone)
2022*4882a593Smuzhiyun goto out_destroy_cud_zone;
2023*4882a593Smuzhiyun
2024*4882a593Smuzhiyun xfs_bud_zone = kmem_cache_create("xfs_bud_item",
2025*4882a593Smuzhiyun sizeof(struct xfs_bud_log_item),
2026*4882a593Smuzhiyun 0, 0, NULL);
2027*4882a593Smuzhiyun if (!xfs_bud_zone)
2028*4882a593Smuzhiyun goto out_destroy_cui_zone;
2029*4882a593Smuzhiyun
2030*4882a593Smuzhiyun xfs_bui_zone = kmem_cache_create("xfs_bui_item",
2031*4882a593Smuzhiyun xfs_bui_log_item_sizeof(XFS_BUI_MAX_FAST_EXTENTS),
2032*4882a593Smuzhiyun 0, 0, NULL);
2033*4882a593Smuzhiyun if (!xfs_bui_zone)
2034*4882a593Smuzhiyun goto out_destroy_bud_zone;
2035*4882a593Smuzhiyun
2036*4882a593Smuzhiyun return 0;
2037*4882a593Smuzhiyun
2038*4882a593Smuzhiyun out_destroy_bud_zone:
2039*4882a593Smuzhiyun kmem_cache_destroy(xfs_bud_zone);
2040*4882a593Smuzhiyun out_destroy_cui_zone:
2041*4882a593Smuzhiyun kmem_cache_destroy(xfs_cui_zone);
2042*4882a593Smuzhiyun out_destroy_cud_zone:
2043*4882a593Smuzhiyun kmem_cache_destroy(xfs_cud_zone);
2044*4882a593Smuzhiyun out_destroy_rui_zone:
2045*4882a593Smuzhiyun kmem_cache_destroy(xfs_rui_zone);
2046*4882a593Smuzhiyun out_destroy_rud_zone:
2047*4882a593Smuzhiyun kmem_cache_destroy(xfs_rud_zone);
2048*4882a593Smuzhiyun out_destroy_icreate_zone:
2049*4882a593Smuzhiyun kmem_cache_destroy(xfs_icreate_zone);
2050*4882a593Smuzhiyun out_destroy_ili_zone:
2051*4882a593Smuzhiyun kmem_cache_destroy(xfs_ili_zone);
2052*4882a593Smuzhiyun out_destroy_inode_zone:
2053*4882a593Smuzhiyun kmem_cache_destroy(xfs_inode_zone);
2054*4882a593Smuzhiyun out_destroy_efi_zone:
2055*4882a593Smuzhiyun kmem_cache_destroy(xfs_efi_zone);
2056*4882a593Smuzhiyun out_destroy_efd_zone:
2057*4882a593Smuzhiyun kmem_cache_destroy(xfs_efd_zone);
2058*4882a593Smuzhiyun out_destroy_buf_item_zone:
2059*4882a593Smuzhiyun kmem_cache_destroy(xfs_buf_item_zone);
2060*4882a593Smuzhiyun out_destroy_trans_zone:
2061*4882a593Smuzhiyun kmem_cache_destroy(xfs_trans_zone);
2062*4882a593Smuzhiyun out_destroy_ifork_zone:
2063*4882a593Smuzhiyun kmem_cache_destroy(xfs_ifork_zone);
2064*4882a593Smuzhiyun out_destroy_da_state_zone:
2065*4882a593Smuzhiyun kmem_cache_destroy(xfs_da_state_zone);
2066*4882a593Smuzhiyun out_destroy_btree_cur_zone:
2067*4882a593Smuzhiyun kmem_cache_destroy(xfs_btree_cur_zone);
2068*4882a593Smuzhiyun out_destroy_bmap_free_item_zone:
2069*4882a593Smuzhiyun kmem_cache_destroy(xfs_bmap_free_item_zone);
2070*4882a593Smuzhiyun out_destroy_log_ticket_zone:
2071*4882a593Smuzhiyun kmem_cache_destroy(xfs_log_ticket_zone);
2072*4882a593Smuzhiyun out:
2073*4882a593Smuzhiyun return -ENOMEM;
2074*4882a593Smuzhiyun }
2075*4882a593Smuzhiyun
2076*4882a593Smuzhiyun STATIC void
xfs_destroy_zones(void)2077*4882a593Smuzhiyun xfs_destroy_zones(void)
2078*4882a593Smuzhiyun {
2079*4882a593Smuzhiyun /*
2080*4882a593Smuzhiyun * Make sure all delayed rcu free are flushed before we
2081*4882a593Smuzhiyun * destroy caches.
2082*4882a593Smuzhiyun */
2083*4882a593Smuzhiyun rcu_barrier();
2084*4882a593Smuzhiyun kmem_cache_destroy(xfs_bui_zone);
2085*4882a593Smuzhiyun kmem_cache_destroy(xfs_bud_zone);
2086*4882a593Smuzhiyun kmem_cache_destroy(xfs_cui_zone);
2087*4882a593Smuzhiyun kmem_cache_destroy(xfs_cud_zone);
2088*4882a593Smuzhiyun kmem_cache_destroy(xfs_rui_zone);
2089*4882a593Smuzhiyun kmem_cache_destroy(xfs_rud_zone);
2090*4882a593Smuzhiyun kmem_cache_destroy(xfs_icreate_zone);
2091*4882a593Smuzhiyun kmem_cache_destroy(xfs_ili_zone);
2092*4882a593Smuzhiyun kmem_cache_destroy(xfs_inode_zone);
2093*4882a593Smuzhiyun kmem_cache_destroy(xfs_efi_zone);
2094*4882a593Smuzhiyun kmem_cache_destroy(xfs_efd_zone);
2095*4882a593Smuzhiyun kmem_cache_destroy(xfs_buf_item_zone);
2096*4882a593Smuzhiyun kmem_cache_destroy(xfs_trans_zone);
2097*4882a593Smuzhiyun kmem_cache_destroy(xfs_ifork_zone);
2098*4882a593Smuzhiyun kmem_cache_destroy(xfs_da_state_zone);
2099*4882a593Smuzhiyun kmem_cache_destroy(xfs_btree_cur_zone);
2100*4882a593Smuzhiyun kmem_cache_destroy(xfs_bmap_free_item_zone);
2101*4882a593Smuzhiyun kmem_cache_destroy(xfs_log_ticket_zone);
2102*4882a593Smuzhiyun }
2103*4882a593Smuzhiyun
2104*4882a593Smuzhiyun STATIC int __init
xfs_init_workqueues(void)2105*4882a593Smuzhiyun xfs_init_workqueues(void)
2106*4882a593Smuzhiyun {
2107*4882a593Smuzhiyun /*
2108*4882a593Smuzhiyun * The allocation workqueue can be used in memory reclaim situations
2109*4882a593Smuzhiyun * (writepage path), and parallelism is only limited by the number of
2110*4882a593Smuzhiyun * AGs in all the filesystems mounted. Hence use the default large
2111*4882a593Smuzhiyun * max_active value for this workqueue.
2112*4882a593Smuzhiyun */
2113*4882a593Smuzhiyun xfs_alloc_wq = alloc_workqueue("xfsalloc",
2114*4882a593Smuzhiyun WQ_MEM_RECLAIM|WQ_FREEZABLE, 0);
2115*4882a593Smuzhiyun if (!xfs_alloc_wq)
2116*4882a593Smuzhiyun return -ENOMEM;
2117*4882a593Smuzhiyun
2118*4882a593Smuzhiyun xfs_discard_wq = alloc_workqueue("xfsdiscard", WQ_UNBOUND, 0);
2119*4882a593Smuzhiyun if (!xfs_discard_wq)
2120*4882a593Smuzhiyun goto out_free_alloc_wq;
2121*4882a593Smuzhiyun
2122*4882a593Smuzhiyun return 0;
2123*4882a593Smuzhiyun out_free_alloc_wq:
2124*4882a593Smuzhiyun destroy_workqueue(xfs_alloc_wq);
2125*4882a593Smuzhiyun return -ENOMEM;
2126*4882a593Smuzhiyun }
2127*4882a593Smuzhiyun
2128*4882a593Smuzhiyun STATIC void
xfs_destroy_workqueues(void)2129*4882a593Smuzhiyun xfs_destroy_workqueues(void)
2130*4882a593Smuzhiyun {
2131*4882a593Smuzhiyun destroy_workqueue(xfs_discard_wq);
2132*4882a593Smuzhiyun destroy_workqueue(xfs_alloc_wq);
2133*4882a593Smuzhiyun }
2134*4882a593Smuzhiyun
2135*4882a593Smuzhiyun STATIC int __init
init_xfs_fs(void)2136*4882a593Smuzhiyun init_xfs_fs(void)
2137*4882a593Smuzhiyun {
2138*4882a593Smuzhiyun int error;
2139*4882a593Smuzhiyun
2140*4882a593Smuzhiyun xfs_check_ondisk_structs();
2141*4882a593Smuzhiyun
2142*4882a593Smuzhiyun printk(KERN_INFO XFS_VERSION_STRING " with "
2143*4882a593Smuzhiyun XFS_BUILD_OPTIONS " enabled\n");
2144*4882a593Smuzhiyun
2145*4882a593Smuzhiyun xfs_dir_startup();
2146*4882a593Smuzhiyun
2147*4882a593Smuzhiyun error = xfs_init_zones();
2148*4882a593Smuzhiyun if (error)
2149*4882a593Smuzhiyun goto out;
2150*4882a593Smuzhiyun
2151*4882a593Smuzhiyun error = xfs_init_workqueues();
2152*4882a593Smuzhiyun if (error)
2153*4882a593Smuzhiyun goto out_destroy_zones;
2154*4882a593Smuzhiyun
2155*4882a593Smuzhiyun error = xfs_mru_cache_init();
2156*4882a593Smuzhiyun if (error)
2157*4882a593Smuzhiyun goto out_destroy_wq;
2158*4882a593Smuzhiyun
2159*4882a593Smuzhiyun error = xfs_buf_init();
2160*4882a593Smuzhiyun if (error)
2161*4882a593Smuzhiyun goto out_mru_cache_uninit;
2162*4882a593Smuzhiyun
2163*4882a593Smuzhiyun error = xfs_init_procfs();
2164*4882a593Smuzhiyun if (error)
2165*4882a593Smuzhiyun goto out_buf_terminate;
2166*4882a593Smuzhiyun
2167*4882a593Smuzhiyun error = xfs_sysctl_register();
2168*4882a593Smuzhiyun if (error)
2169*4882a593Smuzhiyun goto out_cleanup_procfs;
2170*4882a593Smuzhiyun
2171*4882a593Smuzhiyun xfs_kset = kset_create_and_add("xfs", NULL, fs_kobj);
2172*4882a593Smuzhiyun if (!xfs_kset) {
2173*4882a593Smuzhiyun error = -ENOMEM;
2174*4882a593Smuzhiyun goto out_sysctl_unregister;
2175*4882a593Smuzhiyun }
2176*4882a593Smuzhiyun
2177*4882a593Smuzhiyun xfsstats.xs_kobj.kobject.kset = xfs_kset;
2178*4882a593Smuzhiyun
2179*4882a593Smuzhiyun xfsstats.xs_stats = alloc_percpu(struct xfsstats);
2180*4882a593Smuzhiyun if (!xfsstats.xs_stats) {
2181*4882a593Smuzhiyun error = -ENOMEM;
2182*4882a593Smuzhiyun goto out_kset_unregister;
2183*4882a593Smuzhiyun }
2184*4882a593Smuzhiyun
2185*4882a593Smuzhiyun error = xfs_sysfs_init(&xfsstats.xs_kobj, &xfs_stats_ktype, NULL,
2186*4882a593Smuzhiyun "stats");
2187*4882a593Smuzhiyun if (error)
2188*4882a593Smuzhiyun goto out_free_stats;
2189*4882a593Smuzhiyun
2190*4882a593Smuzhiyun #ifdef DEBUG
2191*4882a593Smuzhiyun xfs_dbg_kobj.kobject.kset = xfs_kset;
2192*4882a593Smuzhiyun error = xfs_sysfs_init(&xfs_dbg_kobj, &xfs_dbg_ktype, NULL, "debug");
2193*4882a593Smuzhiyun if (error)
2194*4882a593Smuzhiyun goto out_remove_stats_kobj;
2195*4882a593Smuzhiyun #endif
2196*4882a593Smuzhiyun
2197*4882a593Smuzhiyun error = xfs_qm_init();
2198*4882a593Smuzhiyun if (error)
2199*4882a593Smuzhiyun goto out_remove_dbg_kobj;
2200*4882a593Smuzhiyun
2201*4882a593Smuzhiyun error = register_filesystem(&xfs_fs_type);
2202*4882a593Smuzhiyun if (error)
2203*4882a593Smuzhiyun goto out_qm_exit;
2204*4882a593Smuzhiyun return 0;
2205*4882a593Smuzhiyun
2206*4882a593Smuzhiyun out_qm_exit:
2207*4882a593Smuzhiyun xfs_qm_exit();
2208*4882a593Smuzhiyun out_remove_dbg_kobj:
2209*4882a593Smuzhiyun #ifdef DEBUG
2210*4882a593Smuzhiyun xfs_sysfs_del(&xfs_dbg_kobj);
2211*4882a593Smuzhiyun out_remove_stats_kobj:
2212*4882a593Smuzhiyun #endif
2213*4882a593Smuzhiyun xfs_sysfs_del(&xfsstats.xs_kobj);
2214*4882a593Smuzhiyun out_free_stats:
2215*4882a593Smuzhiyun free_percpu(xfsstats.xs_stats);
2216*4882a593Smuzhiyun out_kset_unregister:
2217*4882a593Smuzhiyun kset_unregister(xfs_kset);
2218*4882a593Smuzhiyun out_sysctl_unregister:
2219*4882a593Smuzhiyun xfs_sysctl_unregister();
2220*4882a593Smuzhiyun out_cleanup_procfs:
2221*4882a593Smuzhiyun xfs_cleanup_procfs();
2222*4882a593Smuzhiyun out_buf_terminate:
2223*4882a593Smuzhiyun xfs_buf_terminate();
2224*4882a593Smuzhiyun out_mru_cache_uninit:
2225*4882a593Smuzhiyun xfs_mru_cache_uninit();
2226*4882a593Smuzhiyun out_destroy_wq:
2227*4882a593Smuzhiyun xfs_destroy_workqueues();
2228*4882a593Smuzhiyun out_destroy_zones:
2229*4882a593Smuzhiyun xfs_destroy_zones();
2230*4882a593Smuzhiyun out:
2231*4882a593Smuzhiyun return error;
2232*4882a593Smuzhiyun }
2233*4882a593Smuzhiyun
2234*4882a593Smuzhiyun STATIC void __exit
exit_xfs_fs(void)2235*4882a593Smuzhiyun exit_xfs_fs(void)
2236*4882a593Smuzhiyun {
2237*4882a593Smuzhiyun xfs_qm_exit();
2238*4882a593Smuzhiyun unregister_filesystem(&xfs_fs_type);
2239*4882a593Smuzhiyun #ifdef DEBUG
2240*4882a593Smuzhiyun xfs_sysfs_del(&xfs_dbg_kobj);
2241*4882a593Smuzhiyun #endif
2242*4882a593Smuzhiyun xfs_sysfs_del(&xfsstats.xs_kobj);
2243*4882a593Smuzhiyun free_percpu(xfsstats.xs_stats);
2244*4882a593Smuzhiyun kset_unregister(xfs_kset);
2245*4882a593Smuzhiyun xfs_sysctl_unregister();
2246*4882a593Smuzhiyun xfs_cleanup_procfs();
2247*4882a593Smuzhiyun xfs_buf_terminate();
2248*4882a593Smuzhiyun xfs_mru_cache_uninit();
2249*4882a593Smuzhiyun xfs_destroy_workqueues();
2250*4882a593Smuzhiyun xfs_destroy_zones();
2251*4882a593Smuzhiyun xfs_uuid_table_free();
2252*4882a593Smuzhiyun }
2253*4882a593Smuzhiyun
2254*4882a593Smuzhiyun module_init(init_xfs_fs);
2255*4882a593Smuzhiyun module_exit(exit_xfs_fs);
2256*4882a593Smuzhiyun
2257*4882a593Smuzhiyun MODULE_AUTHOR("Silicon Graphics, Inc.");
2258*4882a593Smuzhiyun MODULE_DESCRIPTION(XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled");
2259*4882a593Smuzhiyun MODULE_LICENSE("GPL");
2260*4882a593Smuzhiyun MODULE_IMPORT_NS(ANDROID_GKI_VFS_EXPORT_ONLY);
2261