1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2005-2006 Silicon Graphics, Inc.
16 #define PARENTBUF_SZ 16384
17 #define BSTATBUF_SZ 16384
19 static cmdinfo_t parent_cmd
;
20 static int verbose_flag
;
21 static int err_status
;
22 static __u64 inodes_checked
;
26 * check out a parent entry to see if the values seem valid
29 check_parent_entry(xfs_bstat_t
*bstatp
, parent_t
*parent
)
32 char fullpath
[PATH_MAX
];
36 sprintf(fullpath
, _("%s%s"), mntpt
, parent
->p_name
);
38 sts
= lstat(fullpath
, &statbuf
);
41 _("inode-path for inode: %llu is incorrect - path \"%s\" non-existent\n"),
42 (unsigned long long) bstatp
->bs_ino
, fullpath
);
45 _("path \"%s\" does not stat for inode: %llu; err = %s\n"),
47 (unsigned long long) bstatp
->bs_ino
,
53 if (verbose_flag
> 1) {
54 printf(_("path \"%s\" found\n"), fullpath
);
58 if (statbuf
.st_ino
!= bstatp
->bs_ino
) {
60 _("inode-path for inode: %llu is incorrect - wrong inode#\n"),
61 (unsigned long long) bstatp
->bs_ino
);
64 _("ino mismatch for path \"%s\" %llu vs %llu\n"),
66 (unsigned long long)statbuf
.st_ino
,
67 (unsigned long long)bstatp
->bs_ino
);
71 } else if (verbose_flag
> 1) {
72 printf(_("inode number match: %llu\n"),
73 (unsigned long long)statbuf
.st_ino
);
77 str
= strrchr(fullpath
, '/');
79 sts
= stat(fullpath
, &statbuf
);
82 _("parent path \"%s\" does not stat: %s\n"),
88 if (parent
->p_ino
!= statbuf
.st_ino
) {
90 _("inode-path for inode: %llu is incorrect - wrong parent inode#\n"),
91 (unsigned long long) bstatp
->bs_ino
);
94 _("ino mismatch for path \"%s\" %llu vs %llu\n"),
96 (unsigned long long)parent
->p_ino
,
97 (unsigned long long)statbuf
.st_ino
);
102 if (verbose_flag
> 1) {
103 printf(_("parent ino match for %llu\n"),
104 (unsigned long long) parent
->p_ino
);
111 check_parents(parent_t
*parentbuf
, size_t *parentbuf_size
,
112 jdm_fshandle_t
*fshandlep
, xfs_bstat_t
*statp
)
119 error
= jdm_parentpaths(fshandlep
, statp
, parentbuf
, *parentbuf_size
, &count
);
121 if (error
== ERANGE
) {
122 *parentbuf_size
*= 2;
123 parentbuf
= (parent_t
*)realloc(parentbuf
, *parentbuf_size
);
125 fprintf(stderr
, _("parentpaths failed for ino %llu: %s\n"),
126 (unsigned long long) statp
->bs_ino
,
131 } while (error
== ERANGE
);
135 /* no links for inode - something wrong here */
136 fprintf(stderr
, _("inode-path for inode: %llu is missing\n"),
137 (unsigned long long) statp
->bs_ino
);
142 for (i
= 0; i
< count
; i
++) {
143 check_parent_entry(statp
, entryp
);
144 entryp
= (parent_t
*) (((char*)entryp
) + entryp
->p_reclen
);
149 do_bulkstat(parent_t
*parentbuf
, size_t *parentbuf_size
, xfs_bstat_t
*bstatbuf
,
150 int fsfd
, jdm_fshandle_t
*fshandlep
)
156 xfs_fsop_bulkreq_t bulkreq
;
159 if (stat(mntpt
, &mntstat
)) {
160 fprintf(stderr
, _("can't stat mount point \"%s\": %s\n"),
161 mntpt
, strerror(errno
));
165 bulkreq
.lastip
= &lastino
;
166 bulkreq
.icount
= BSTATBUF_SZ
;
167 bulkreq
.ubuffer
= (void *)bstatbuf
;
168 bulkreq
.ocount
= &buflenout
;
170 while (xfsctl(mntpt
, fsfd
, XFS_IOC_FSBULKSTAT
, &bulkreq
) == 0) {
171 if (*(bulkreq
.ocount
) == 0) {
174 for (p
= bstatbuf
, endp
= bstatbuf
+ *bulkreq
.ocount
; p
< endp
; p
++) {
176 /* inode being modified, get synced data with iget */
177 if ( (!p
->bs_nlink
|| !p
->bs_mode
) && p
->bs_ino
!= 0 ) {
179 if (xfsctl(mntpt
, fsfd
, XFS_IOC_FSBULKSTAT_SINGLE
, &bulkreq
) < 0) {
181 _("failed to get bulkstat information for inode %llu\n"),
182 (unsigned long long) p
->bs_ino
);
185 if (!p
->bs_nlink
|| !p
->bs_mode
|| !p
->bs_ino
) {
187 _("failed to get valid bulkstat information for inode %llu\n"),
188 (unsigned long long) p
->bs_ino
);
194 if (p
->bs_ino
== mntstat
.st_ino
) {
198 if (verbose_flag
> 1) {
199 printf(_("checking inode %llu\n"),
200 (unsigned long long) p
->bs_ino
);
203 /* print dotted progress */
204 if ((inodes_checked
% 100) == 0 && verbose_flag
== 1) {
205 printf("."); fflush(stdout
);
209 check_parents(parentbuf
, parentbuf_size
, fshandlep
, p
);
214 fprintf(stderr
, _("syssgi bulkstat failed: %s\n"), strerror(errno
));
222 jdm_fshandle_t
*fshandlep
;
224 size_t parentbuf_size
= PARENTBUF_SZ
;
225 xfs_bstat_t
*bstatbuf
;
234 fshandlep
= jdm_getfshandle(mntpt
);
235 if (fshandlep
== NULL
) {
236 fprintf(stderr
, _("unable to open \"%s\" for jdm: %s\n"),
242 /* allocate buffers */
243 bstatbuf
= (xfs_bstat_t
*)calloc(BSTATBUF_SZ
, sizeof(xfs_bstat_t
));
244 parentbuf
= (parent_t
*)malloc(parentbuf_size
);
245 if (!bstatbuf
|| !parentbuf
) {
246 fprintf(stderr
, _("unable to allocate buffers: %s\n"),
252 if (do_bulkstat(parentbuf
, &parentbuf_size
, bstatbuf
, fsfd
, fshandlep
) != 0)
256 fprintf(stderr
, _("num errors: %d\n"), err_status
);
258 printf(_("succeeded checking %llu inodes\n"),
259 (unsigned long long) inodes_checked
);
269 print_parent_entry(parent_t
*parent
, int fullpath
)
271 printf(_("p_ino = %llu\n"), (unsigned long long) parent
->p_ino
);
272 printf(_("p_gen = %u\n"), parent
->p_gen
);
273 printf(_("p_reclen = %u\n"), parent
->p_reclen
);
275 printf(_("p_name = \"%s%s\"\n"), mntpt
, parent
->p_name
);
277 printf(_("p_name = \"%s\"\n"), parent
->p_name
);
281 parent_list(int fullpath
)
283 void *handlep
= NULL
;
289 parent_t
*parentbuf
= NULL
;
290 char *path
= file
->name
;
291 int pb_size
= PARENTBUF_SZ
;
293 /* XXXX for linux libhandle version - to set libhandle fsfd cache */
298 if (path_to_fshandle(mntpt
, &fshandle
, &fshlen
) != 0) {
299 fprintf(stderr
, _("%s: failed path_to_fshandle \"%s\": %s\n"),
300 progname
, path
, strerror(errno
));
303 free_handle(fshandle
, fshlen
);
306 if (path_to_handle(path
, &handlep
, &handlen
) != 0) {
307 fprintf(stderr
, _("%s: path_to_handle failed for \"%s\"\n"), progname
, path
);
312 parentbuf
= (parent_t
*)realloc(parentbuf
, pb_size
);
314 fprintf(stderr
, _("%s: unable to allocate parent buffer: %s\n"),
315 progname
, strerror(errno
));
320 error
= parentpaths_by_handle(handlep
,
326 error
= parents_by_handle(handlep
,
332 if (error
== ERANGE
) {
335 fprintf(stderr
, _("%s: %s call failed for \"%s\": %s\n"),
336 progname
, fullpath
? "parentpaths" : "parents",
337 path
, strerror(errno
));
340 } while (error
== ERANGE
);
343 /* no links for inode - something wrong here */
344 fprintf(stderr
, _("%s: inode-path is missing\n"), progname
);
349 for (i
= 0; i
< count
; i
++) {
350 print_parent_entry(entryp
, fullpath
);
351 entryp
= (parent_t
*) (((char*)entryp
) + entryp
->p_reclen
);
362 parent_f(int argc
, char **argv
)
365 int listpath_flag
= 0;
372 fs_table_initialise(0, NULL
, 0, NULL
);
374 fs
= fs_table_lookup(file
->name
, FS_MOUNT_POINT
);
376 fprintf(stderr
, _("file argument, \"%s\", is not in a mounted XFS filesystem\n"),
384 while ((c
= getopt(argc
, argv
, "cpv")) != EOF
) {
396 return command_usage(&parent_cmd
);
400 if (!check_flag
&& !listpath_flag
) /* default case */
401 exitcode
= parent_list(listpath_flag
);
404 exitcode
= parent_list(listpath_flag
);
406 exitcode
= parent_check();
417 " list the current file's parents and their filenames\n"
419 " -c -- check the current file's file system for parent consistency\n"
420 " -p -- list the current file's parents and their full paths\n"
421 " -v -- verbose mode\n"
428 parent_cmd
.name
= "parent";
429 parent_cmd
.cfunc
= parent_f
;
430 parent_cmd
.argmin
= 0;
431 parent_cmd
.argmax
= -1;
432 parent_cmd
.args
= _("[-cpv]");
433 parent_cmd
.flags
= CMD_NOMAP_OK
;
434 parent_cmd
.oneline
= _("print or check parent inodes");
435 parent_cmd
.help
= parent_help
;
438 add_command(&parent_cmd
);