]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/init.c
xfs: don't rely on extent indices in xfs_bmap_collapse_extents
[thirdparty/xfsprogs-dev.git] / db / init.c
1 /*
2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include "libxfs.h"
20 #include "libxlog.h"
21 #include <signal.h>
22 #include "command.h"
23 #include "init.h"
24 #include "input.h"
25 #include "io.h"
26 #include "init.h"
27 #include "sig.h"
28 #include "output.h"
29 #include "malloc.h"
30 #include "type.h"
31
32 static char **cmdline;
33 static int ncmdline;
34 char *fsdevice;
35 int blkbb;
36 int exitcode;
37 int expert_mode;
38 int force;
39 struct xfs_mount xmount;
40 struct xfs_mount *mp;
41 struct xlog xlog;
42 libxfs_init_t x;
43 xfs_agnumber_t cur_agno = NULLAGNUMBER;
44
45 static void
46 usage(void)
47 {
48 fprintf(stderr, _(
49 "Usage: %s [-ifFrxV] [-p prog] [-l logdev] [-c cmd]... device\n"
50 ), progname);
51 exit(1);
52 }
53
54 void
55 init(
56 int argc,
57 char **argv)
58 {
59 struct xfs_sb *sbp;
60 struct xfs_buf *bp;
61 unsigned int agcount;
62 int c;
63
64 setlocale(LC_ALL, "");
65 bindtextdomain(PACKAGE, LOCALEDIR);
66 textdomain(PACKAGE);
67
68 progname = basename(argv[0]);
69 while ((c = getopt(argc, argv, "c:fFip:rxVl:")) != EOF) {
70 switch (c) {
71 case 'c':
72 cmdline = xrealloc(cmdline, (ncmdline+1)*sizeof(char*));
73 cmdline[ncmdline++] = optarg;
74 break;
75 case 'f':
76 x.disfile = 1;
77 break;
78 case 'F':
79 force = 1;
80 break;
81 case 'i':
82 x.isreadonly = (LIBXFS_ISREADONLY|LIBXFS_ISINACTIVE);
83 break;
84 case 'p':
85 progname = optarg;
86 break;
87 case 'r':
88 x.isreadonly = LIBXFS_ISREADONLY;
89 break;
90 case 'l':
91 x.logname = optarg;
92 break;
93 case 'x':
94 expert_mode = 1;
95 break;
96 case 'V':
97 printf(_("%s version %s\n"), progname, VERSION);
98 exit(0);
99 case '?':
100 usage();
101 /*NOTREACHED*/
102 }
103 }
104 if (optind + 1 != argc) {
105 usage();
106 /*NOTREACHED*/
107 }
108
109 fsdevice = argv[optind];
110 if (!x.disfile)
111 x.volname = fsdevice;
112 else
113 x.dname = fsdevice;
114
115 x.bcache_flags = CACHE_MISCOMPARE_PURGE;
116 if (!libxfs_init(&x)) {
117 fputs(_("\nfatal error -- couldn't initialize XFS library\n"),
118 stderr);
119 exit(1);
120 }
121
122 /*
123 * Read the superblock, but don't validate it - we are a diagnostic
124 * tool and so need to be able to mount busted filesystems.
125 */
126 memset(&xmount, 0, sizeof(struct xfs_mount));
127 libxfs_buftarg_init(&xmount, x.ddev, x.logdev, x.rtdev);
128 bp = libxfs_readbuf(xmount.m_ddev_targp, XFS_SB_DADDR,
129 1 << (XFS_MAX_SECTORSIZE_LOG - BBSHIFT), 0, NULL);
130
131 if (!bp || bp->b_error) {
132 fprintf(stderr, _("%s: %s is invalid (cannot read first 512 "
133 "bytes)\n"), progname, fsdevice);
134 exit(1);
135 }
136
137 /* copy SB from buffer to in-core, converting architecture as we go */
138 libxfs_sb_from_disk(&xmount.m_sb, XFS_BUF_TO_SBP(bp));
139 libxfs_putbuf(bp);
140 libxfs_purgebuf(bp);
141
142 sbp = &xmount.m_sb;
143 if (sbp->sb_magicnum != XFS_SB_MAGIC) {
144 fprintf(stderr, _("%s: %s is not a valid XFS filesystem (unexpected SB magic number 0x%08x)\n"),
145 progname, fsdevice, sbp->sb_magicnum);
146 if (!force) {
147 fprintf(stderr, _("Use -F to force a read attempt.\n"));
148 exit(EXIT_FAILURE);
149 }
150 }
151
152 agcount = sbp->sb_agcount;
153 mp = libxfs_mount(&xmount, sbp, x.ddev, x.logdev, x.rtdev,
154 LIBXFS_MOUNT_DEBUGGER);
155 if (!mp) {
156 fprintf(stderr,
157 _("%s: device %s unusable (not an XFS filesystem?)\n"),
158 progname, fsdevice);
159 exit(1);
160 }
161 mp->m_log = &xlog;
162 blkbb = 1 << mp->m_blkbb_log;
163
164 /* Did we limit a broken agcount in libxfs_mount? */
165 if (sbp->sb_agcount != agcount)
166 exitcode = 1;
167
168 /*
169 * xfs_check needs corrected incore superblock values
170 */
171 if (sbp->sb_rootino != NULLFSINO &&
172 xfs_sb_version_haslazysbcount(&mp->m_sb)) {
173 int error = -libxfs_initialize_perag_data(mp, sbp->sb_agcount);
174 if (error) {
175 fprintf(stderr,
176 _("%s: cannot init perag data (%d). Continuing anyway.\n"),
177 progname, error);
178 }
179 }
180
181 if (xfs_sb_version_hassparseinodes(&mp->m_sb))
182 type_set_tab_spcrc();
183 else if (xfs_sb_version_hascrc(&mp->m_sb))
184 type_set_tab_crc();
185
186 push_cur();
187 init_commands();
188 init_sig();
189 }
190
191 int
192 main(
193 int argc,
194 char **argv)
195 {
196 int c, i, done = 0;
197 char *input;
198 char **v;
199 int start_iocur_sp;
200
201 init(argc, argv);
202 start_iocur_sp = iocur_sp;
203
204 for (i = 0; !done && i < ncmdline; i++) {
205 v = breakline(cmdline[i], &c);
206 if (c)
207 done = command(c, v);
208 xfree(v);
209 }
210 if (cmdline) {
211 xfree(cmdline);
212 goto close_devices;
213 }
214
215 pushfile(stdin);
216 while (!done) {
217 if ((input = fetchline()) == NULL)
218 break;
219 v = breakline(input, &c);
220 if (c)
221 done = command(c, v);
222 doneline(input, v);
223 }
224
225 close_devices:
226 /*
227 * Make sure that we pop the all the buffer contexts we hold so that
228 * they are released before we purge the caches during unmount.
229 */
230 while (iocur_sp > start_iocur_sp)
231 pop_cur();
232 libxfs_umount(mp);
233 if (x.ddev)
234 libxfs_device_close(x.ddev);
235 if (x.logdev && x.logdev != x.ddev)
236 libxfs_device_close(x.logdev);
237 if (x.rtdev)
238 libxfs_device_close(x.rtdev);
239 return exitcode;
240 }