]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - io/parent.c
mkfs: fix typo in output
[thirdparty/xfsprogs-dev.git] / io / parent.c
CommitLineData
258b00ea 1/*
74043ab2 2 * Copyright (c) 2005-2006 Silicon Graphics, Inc.
258b00ea
TS
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 <xfs/xfs.h>
20#include <xfs/command.h>
21#include <xfs/input.h>
22#include <xfs/path.h>
23#include <xfs/parent.h>
24#include <xfs/handle.h>
25#include <xfs/jdm.h>
26#include "init.h"
27#include "io.h"
28
29#define PARENTBUF_SZ 16384
74043ab2 30#define BSTATBUF_SZ 16384
258b00ea
TS
31
32static cmdinfo_t parent_cmd;
33static int verbose_flag;
34static int err_status;
74043ab2
TS
35static __u64 inodes_checked;
36static char *mntpt;
258b00ea
TS
37
38/*
39 * check out a parent entry to see if the values seem valid
40 */
41static void
74043ab2 42check_parent_entry(xfs_bstat_t *bstatp, parent_t *parent)
258b00ea
TS
43{
44 int sts;
45 char fullpath[PATH_MAX];
46 struct stat statbuf;
47 char *str;
48
49 sprintf(fullpath, _("%s%s"), mntpt, parent->p_name);
50
51 sts = lstat(fullpath, &statbuf);
52 if (sts != 0) {
53 fprintf(stderr,
74043ab2 54 _("inode-path for inode: %llu is incorrect - path \"%s\" non-existent\n"),
f934f4a5 55 (unsigned long long) bstatp->bs_ino, fullpath);
258b00ea
TS
56 if (verbose_flag) {
57 fprintf(stderr,
58 _("path \"%s\" does not stat for inode: %llu; err = %s\n"),
59 fullpath,
f934f4a5 60 (unsigned long long) bstatp->bs_ino,
258b00ea
TS
61 strerror(errno));
62 }
63 err_status++;
64 return;
65 } else {
66 if (verbose_flag > 1) {
67 printf(_("path \"%s\" found\n"), fullpath);
68 }
69 }
70
71 if (statbuf.st_ino != bstatp->bs_ino) {
72 fprintf(stderr,
73 _("inode-path for inode: %llu is incorrect - wrong inode#\n"),
f934f4a5 74 (unsigned long long) bstatp->bs_ino);
258b00ea
TS
75 if (verbose_flag) {
76 fprintf(stderr,
77 _("ino mismatch for path \"%s\" %llu vs %llu\n"),
78 fullpath,
5acc4dfe
NS
79 (unsigned long long)statbuf.st_ino,
80 (unsigned long long)bstatp->bs_ino);
258b00ea
TS
81 }
82 err_status++;
83 return;
84 } else if (verbose_flag > 1) {
5acc4dfe
NS
85 printf(_("inode number match: %llu\n"),
86 (unsigned long long)statbuf.st_ino);
258b00ea
TS
87 }
88
89 /* get parent path */
90 str = strrchr(fullpath, '/');
91 *str = '\0';
92 sts = stat(fullpath, &statbuf);
93 if (sts != 0) {
94 fprintf(stderr,
95 _("parent path \"%s\" does not stat: %s\n"),
96 fullpath,
97 strerror(errno));
98 err_status++;
99 return;
100 } else {
101 if (parent->p_ino != statbuf.st_ino) {
102 fprintf(stderr,
103 _("inode-path for inode: %llu is incorrect - wrong parent inode#\n"),
f934f4a5 104 (unsigned long long) bstatp->bs_ino);
258b00ea
TS
105 if (verbose_flag) {
106 fprintf(stderr,
107 _("ino mismatch for path \"%s\" %llu vs %llu\n"),
108 fullpath,
5acc4dfe
NS
109 (unsigned long long)parent->p_ino,
110 (unsigned long long)statbuf.st_ino);
258b00ea
TS
111 }
112 err_status++;
113 return;
114 } else {
115 if (verbose_flag > 1) {
f934f4a5
AE
116 printf(_("parent ino match for %llu\n"),
117 (unsigned long long) parent->p_ino);
258b00ea
TS
118 }
119 }
120 }
121}
122
123static void
74043ab2
TS
124check_parents(parent_t *parentbuf, size_t *parentbuf_size,
125 jdm_fshandle_t *fshandlep, xfs_bstat_t *statp)
258b00ea
TS
126{
127 int error, i;
74043ab2 128 __u32 count;
258b00ea 129 parent_t *entryp;
258b00ea 130
258b00ea 131 do {
74043ab2
TS
132 error = jdm_parentpaths(fshandlep, statp, parentbuf, *parentbuf_size, &count);
133
134 if (error == ERANGE) {
135 *parentbuf_size *= 2;
136 parentbuf = (parent_t *)realloc(parentbuf, *parentbuf_size);
137 } else if (error) {
138 fprintf(stderr, _("parentpaths failed for ino %llu: %s\n"),
f934f4a5 139 (unsigned long long) statp->bs_ino,
8577b2c9 140 strerror(errno));
258b00ea
TS
141 err_status++;
142 break;
143 }
74043ab2
TS
144 } while (error == ERANGE);
145
258b00ea 146
74043ab2
TS
147 if (count == 0) {
148 /* no links for inode - something wrong here */
f934f4a5
AE
149 fprintf(stderr, _("inode-path for inode: %llu is missing\n"),
150 (unsigned long long) statp->bs_ino);
74043ab2
TS
151 err_status++;
152 }
258b00ea 153
74043ab2
TS
154 entryp = parentbuf;
155 for (i = 0; i < count; i++) {
156 check_parent_entry(statp, entryp);
157 entryp = (parent_t*) (((char*)entryp) + entryp->p_reclen);
158 }
258b00ea
TS
159}
160
161static int
74043ab2
TS
162do_bulkstat(parent_t *parentbuf, size_t *parentbuf_size, xfs_bstat_t *bstatbuf,
163 int fsfd, jdm_fshandle_t *fshandlep)
258b00ea 164{
d026b19e
NS
165 __s32 buflenout;
166 __u64 lastino = 0;
258b00ea
TS
167 xfs_bstat_t *p;
168 xfs_bstat_t *endp;
169 xfs_fsop_bulkreq_t bulkreq;
170 struct stat mntstat;
171
a504bf72 172 if (stat(mntpt, &mntstat)) {
258b00ea 173 fprintf(stderr, _("can't stat mount point \"%s\": %s\n"),
8577b2c9 174 mntpt, strerror(errno));
258b00ea
TS
175 return 1;
176 }
177
178 bulkreq.lastip = &lastino;
179 bulkreq.icount = BSTATBUF_SZ;
180 bulkreq.ubuffer = (void *)bstatbuf;
181 bulkreq.ocount = &buflenout;
182
183 while (xfsctl(mntpt, fsfd, XFS_IOC_FSBULKSTAT, &bulkreq) == 0) {
184 if (*(bulkreq.ocount) == 0) {
185 return 0;
186 }
187 for (p = bstatbuf, endp = bstatbuf + *bulkreq.ocount; p < endp; p++) {
188
189 /* inode being modified, get synced data with iget */
190 if ( (!p->bs_nlink || !p->bs_mode) && p->bs_ino != 0 ) {
191
192 if (xfsctl(mntpt, fsfd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq) < 0) {
193 fprintf(stderr,
194 _("failed to get bulkstat information for inode %llu\n"),
f934f4a5 195 (unsigned long long) p->bs_ino);
258b00ea
TS
196 continue;
197 }
198 if (!p->bs_nlink || !p->bs_mode || !p->bs_ino) {
199 fprintf(stderr,
200 _("failed to get valid bulkstat information for inode %llu\n"),
f934f4a5 201 (unsigned long long) p->bs_ino);
258b00ea
TS
202 continue;
203 }
204 }
205
206 /* skip root */
207 if (p->bs_ino == mntstat.st_ino) {
208 continue;
209 }
210
211 if (verbose_flag > 1) {
f934f4a5
AE
212 printf(_("checking inode %llu\n"),
213 (unsigned long long) p->bs_ino);
258b00ea
TS
214 }
215
216 /* print dotted progress */
217 if ((inodes_checked % 100) == 0 && verbose_flag == 1) {
218 printf("."); fflush(stdout);
219 }
220 inodes_checked++;
221
74043ab2 222 check_parents(parentbuf, parentbuf_size, fshandlep, p);
258b00ea
TS
223 }
224
225 }/*while*/
226
227 fprintf(stderr, _("syssgi bulkstat failed: %s\n"), strerror(errno));
228 return 1;
229}
230
231static int
232parent_check(void)
233{
258b00ea
TS
234 int fsfd;
235 jdm_fshandle_t *fshandlep;
236 parent_t *parentbuf;
74043ab2 237 size_t parentbuf_size = PARENTBUF_SZ;
258b00ea
TS
238 xfs_bstat_t *bstatbuf;
239
240 err_status = 0;
241 inodes_checked = 0;
242
243 sync();
244
258b00ea
TS
245 fsfd = file->fd;
246
247 fshandlep = jdm_getfshandle(mntpt);
5e656dbb 248 if (fshandlep == NULL) {
258b00ea
TS
249 fprintf(stderr, _("unable to open \"%s\" for jdm: %s\n"),
250 mntpt,
251 strerror(errno));
252 return 1;
253 }
254
255 /* allocate buffers */
256 bstatbuf = (xfs_bstat_t *)calloc(BSTATBUF_SZ, sizeof(xfs_bstat_t));
74043ab2 257 parentbuf = (parent_t *)malloc(parentbuf_size);
258b00ea
TS
258 if (!bstatbuf || !parentbuf) {
259 fprintf(stderr, _("unable to allocate buffers: %s\n"),
260 strerror(errno));
355ac015
ES
261 free(bstatbuf);
262 free(parentbuf);
258b00ea
TS
263 return 1;
264 }
265
74043ab2 266 if (do_bulkstat(parentbuf, &parentbuf_size, bstatbuf, fsfd, fshandlep) != 0)
258b00ea
TS
267 err_status++;
268
269 if (err_status > 0)
270 fprintf(stderr, _("num errors: %d\n"), err_status);
271 else
f934f4a5
AE
272 printf(_("succeeded checking %llu inodes\n"),
273 (unsigned long long) inodes_checked);
258b00ea
TS
274
275 free(bstatbuf);
276 free(parentbuf);
277 return err_status;
278}
279
280static void
74043ab2 281print_parent_entry(parent_t *parent, int fullpath)
258b00ea 282{
f934f4a5 283 printf(_("p_ino = %llu\n"), (unsigned long long) parent->p_ino);
258b00ea
TS
284 printf(_("p_gen = %u\n"), parent->p_gen);
285 printf(_("p_reclen = %u\n"), parent->p_reclen);
74043ab2
TS
286 if (fullpath)
287 printf(_("p_name = \"%s%s\"\n"), mntpt, parent->p_name);
288 else
289 printf(_("p_name = \"%s\"\n"), parent->p_name);
258b00ea
TS
290}
291
292static int
293parent_list(int fullpath)
294{
295 void *handlep;
296 size_t handlen;
297 int error, i;
298 int retval = 1;
74043ab2 299 __u32 count;
258b00ea 300 parent_t *entryp;
74043ab2 301 parent_t *parentbuf = NULL;
258b00ea 302 char *path = file->name;
74043ab2 303 int pb_size = PARENTBUF_SZ;
258b00ea
TS
304
305 /* XXXX for linux libhandle version - to set libhandle fsfd cache */
306 {
307 void *fshandle;
308 size_t fshlen;
309
74043ab2 310 if (path_to_fshandle(mntpt, &fshandle, &fshlen) != 0) {
258b00ea
TS
311 fprintf(stderr, _("%s: failed path_to_fshandle \"%s\": %s\n"),
312 progname, path, strerror(errno));
313 goto error;
314 }
315 }
316
317 if (path_to_handle(path, &handlep, &handlen) != 0) {
318 fprintf(stderr, _("%s: path_to_handle failed for \"%s\"\n"), progname, path);
319 goto error;
320 }
321
258b00ea 322 do {
74043ab2
TS
323 parentbuf = (parent_t *)realloc(parentbuf, pb_size);
324 if (!parentbuf) {
325 fprintf(stderr, _("%s: unable to allocate parent buffer: %s\n"),
326 progname, strerror(errno));
327 return 1;
328 }
329
258b00ea 330 if (fullpath) {
74043ab2 331 error = parentpaths_by_handle(handlep,
258b00ea
TS
332 handlen,
333 parentbuf,
74043ab2
TS
334 pb_size,
335 &count);
258b00ea 336 } else {
74043ab2 337 error = parents_by_handle(handlep,
258b00ea
TS
338 handlen,
339 parentbuf,
74043ab2
TS
340 pb_size,
341 &count);
258b00ea 342 }
74043ab2
TS
343 if (error == ERANGE) {
344 pb_size *= 2;
345 } else if (error) {
346 fprintf(stderr, _("%s: %s call failed for \"%s\": %s\n"),
347 progname, fullpath ? "parentpaths" : "parents",
348 path, strerror(errno));
258b00ea
TS
349 goto error;
350 }
74043ab2 351 } while (error == ERANGE);
258b00ea 352
74043ab2
TS
353 if (count == 0) {
354 /* no links for inode - something wrong here */
355 fprintf(stderr, _("%s: inode-path is missing\n"), progname);
356 goto error;
357 }
258b00ea 358
74043ab2
TS
359 entryp = parentbuf;
360 for (i = 0; i < count; i++) {
361 print_parent_entry(entryp, fullpath);
362 entryp = (parent_t*) (((char*)entryp) + entryp->p_reclen);
363 }
258b00ea
TS
364
365 retval = 0;
366error:
367 free(parentbuf);
368 return retval;
369}
370
371int
372parent_f(int argc, char **argv)
373{
374 int c;
375 int listpath_flag = 0;
376 int check_flag = 0;
74043ab2
TS
377 fs_path_t *fs;
378 static int tab_init;
379
380 if (!tab_init) {
381 tab_init = 1;
0900efe4 382 fs_table_initialise(0, NULL, 0, NULL);
74043ab2
TS
383 }
384 fs = fs_table_lookup(file->name, FS_MOUNT_POINT);
385 if (!fs) {
386 fprintf(stderr, _("file argument, \"%s\", is not in a mounted XFS filesystem\n"),
387 file->name);
388 return 1;
389 }
390 mntpt = fs->fs_dir;
258b00ea
TS
391
392 verbose_flag = 0;
393
394 while ((c = getopt(argc, argv, "cpv")) != EOF) {
395 switch (c) {
396 case 'c':
397 check_flag = 1;
398 break;
399 case 'p':
400 listpath_flag = 1;
401 break;
402 case 'v':
403 verbose_flag++;
404 break;
405 default:
406 return command_usage(&parent_cmd);
407 }
408 }
409
410 if (!check_flag && !listpath_flag) /* default case */
411 exitcode = parent_list(listpath_flag);
412 else {
413 if (listpath_flag)
414 exitcode = parent_list(listpath_flag);
415 if (check_flag)
416 exitcode = parent_check();
417 }
418
419 return 0;
420}
421
422static void
423parent_help(void)
424{
425 printf(_(
426"\n"
427" list the current file's parents and their filenames\n"
428"\n"
429" -c -- check the current file's file system for parent consistency\n"
430" -p -- list the current file's parents and their full paths\n"
431" -v -- verbose mode\n"
432"\n"));
433}
434
435void
436parent_init(void)
437{
ad765595 438 parent_cmd.name = "parent";
258b00ea
TS
439 parent_cmd.cfunc = parent_f;
440 parent_cmd.argmin = 0;
441 parent_cmd.argmax = -1;
442 parent_cmd.args = _("[-cpv]");
443 parent_cmd.flags = CMD_NOMAP_OK;
444 parent_cmd.oneline = _("print or check parent inodes");
445 parent_cmd.help = parent_help;
446
447 if (expert)
448 add_command(&parent_cmd);
449}