2 * Copyright (c) 2005 Silicon Graphics, Inc.
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.
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.
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
20 #include <xfs/command.h>
21 #include <xfs/input.h>
23 #include <xfs/parent.h>
24 #include <xfs/handle.h>
29 #define PARENTBUF_SZ 16384
30 #define BSTATBUF_SZ 4096
32 static cmdinfo_t parent_cmd
;
33 static int verbose_flag
;
34 static int err_status
;
35 static uint64_t inodes_checked
;
38 * check out a parent entry to see if the values seem valid
41 check_parent_entry(xfs_bstat_t
*bstatp
, parent_t
*parent
, char *mntpt
)
44 char fullpath
[PATH_MAX
];
48 sprintf(fullpath
, _("%s%s"), mntpt
, parent
->p_name
);
50 sts
= lstat(fullpath
, &statbuf
);
53 _("inode-path for inode: %llu is incorrect - path non-existent\n"),
57 _("path \"%s\" does not stat for inode: %llu; err = %s\n"),
65 if (verbose_flag
> 1) {
66 printf(_("path \"%s\" found\n"), fullpath
);
70 if (statbuf
.st_ino
!= bstatp
->bs_ino
) {
72 _("inode-path for inode: %llu is incorrect - wrong inode#\n"),
76 _("ino mismatch for path \"%s\" %llu vs %llu\n"),
83 } else if (verbose_flag
> 1) {
84 printf(_("inode number match: %llu\n"), statbuf
.st_ino
);
88 str
= strrchr(fullpath
, '/');
90 sts
= stat(fullpath
, &statbuf
);
93 _("parent path \"%s\" does not stat: %s\n"),
99 if (parent
->p_ino
!= statbuf
.st_ino
) {
101 _("inode-path for inode: %llu is incorrect - wrong parent inode#\n"),
105 _("ino mismatch for path \"%s\" %llu vs %llu\n"),
113 if (verbose_flag
> 1) {
114 printf(_("parent ino match for %llu\n"), parent
->p_ino
);
121 check_parents(parent_t
*parentbuf
, jdm_fshandle_t
*fshandlep
, xfs_bstat_t
*statp
, char *mntpt
)
126 parent_cursor_t cursor
;
128 memset(&cursor
, 0, sizeof(cursor
));
130 error
= jdm_getparentpaths(fshandlep
,
139 fprintf(stderr
, _("getparentpaths failed for ino %llu: %s\n"),
147 /* no links for inode - something wrong here */
148 fprintf(stderr
, _("inode-path for inode: %llu is missing\n"), statp
->bs_ino
);
154 for (i
= 0; i
< count
; i
++) {
155 check_parent_entry(statp
, entryp
, mntpt
);
156 entryp
= (parent_t
*) (((char*)entryp
) + entryp
->p_reclen
);
163 do_bulkstat(parent_t
*parentbuf
, xfs_bstat_t
*bstatbuf
,
164 char *mntpt
, int fsfd
, jdm_fshandle_t
*fshandlep
)
171 xfs_fsop_bulkreq_t bulkreq
;
174 if ((error
= stat(mntpt
, &mntstat
))) {
175 fprintf(stderr
, _("can't stat mount point \"%s\": %s\n"),
176 mntpt
, strerror(error
));
180 bulkreq
.lastip
= &lastino
;
181 bulkreq
.icount
= BSTATBUF_SZ
;
182 bulkreq
.ubuffer
= (void *)bstatbuf
;
183 bulkreq
.ocount
= &buflenout
;
185 while (xfsctl(mntpt
, fsfd
, XFS_IOC_FSBULKSTAT
, &bulkreq
) == 0) {
186 if (*(bulkreq
.ocount
) == 0) {
189 for (p
= bstatbuf
, endp
= bstatbuf
+ *bulkreq
.ocount
; p
< endp
; p
++) {
191 /* inode being modified, get synced data with iget */
192 if ( (!p
->bs_nlink
|| !p
->bs_mode
) && p
->bs_ino
!= 0 ) {
194 if (xfsctl(mntpt
, fsfd
, XFS_IOC_FSBULKSTAT_SINGLE
, &bulkreq
) < 0) {
196 _("failed to get bulkstat information for inode %llu\n"),
200 if (!p
->bs_nlink
|| !p
->bs_mode
|| !p
->bs_ino
) {
202 _("failed to get valid bulkstat information for inode %llu\n"),
209 if (p
->bs_ino
== mntstat
.st_ino
) {
213 if (verbose_flag
> 1) {
214 printf(_("checking inode %llu\n"), p
->bs_ino
);
217 /* print dotted progress */
218 if ((inodes_checked
% 100) == 0 && verbose_flag
== 1) {
219 printf("."); fflush(stdout
);
223 check_parents(parentbuf
, fshandlep
, p
, mntpt
);
228 fprintf(stderr
, _("syssgi bulkstat failed: %s\n"), strerror(errno
));
239 jdm_fshandle_t
*fshandlep
;
241 xfs_bstat_t
*bstatbuf
;
250 fs_table_initialise();
252 fs
= fs_table_lookup(file
->name
, FS_MOUNT_POINT
);
254 fprintf(stderr
, _("file argument, \"%s\", is not in a mounted XFS filesystem\n"),
261 fshandlep
= jdm_getfshandle(mntpt
);
262 if (fshandlep
== 0) {
263 fprintf(stderr
, _("unable to open \"%s\" for jdm: %s\n"),
269 /* allocate buffers */
270 bstatbuf
= (xfs_bstat_t
*)calloc(BSTATBUF_SZ
, sizeof(xfs_bstat_t
));
271 parentbuf
= (parent_t
*)malloc(PARENTBUF_SZ
);
272 if (!bstatbuf
|| !parentbuf
) {
273 fprintf(stderr
, _("unable to allocate buffers: %s\n"),
278 if (do_bulkstat(parentbuf
, bstatbuf
, mntpt
, fsfd
, fshandlep
) != 0)
282 fprintf(stderr
, _("num errors: %d\n"), err_status
);
284 printf(_("succeeded checking %llu inodes\n"), inodes_checked
);
292 print_parent_entry(parent_t
*parent
)
294 printf(_("p_ino = %llu\n"), parent
->p_ino
);
295 printf(_("p_gen = %u\n"), parent
->p_gen
);
296 printf(_("p_reclen = %u\n"), parent
->p_reclen
);
297 printf(_("p_name = \"%s\"\n"),parent
->p_name
);
301 parent_list(int fullpath
)
309 parent_cursor_t cursor
;
311 char *path
= file
->name
;
313 parentbuf
= (parent_t
*)malloc(PARENTBUF_SZ
);
315 fprintf(stderr
, _("%s: unable to allocate parent buffer: %s\n"),
316 progname
, strerror(errno
));
320 /* XXXX for linux libhandle version - to set libhandle fsfd cache */
325 if (path_to_fshandle(path
, &fshandle
, &fshlen
) != 0) {
326 fprintf(stderr
, _("%s: failed path_to_fshandle \"%s\": %s\n"),
327 progname
, path
, strerror(errno
));
332 if (path_to_handle(path
, &handlep
, &handlen
) != 0) {
333 fprintf(stderr
, _("%s: path_to_handle failed for \"%s\"\n"), progname
, path
);
337 memset(&cursor
, 0, sizeof(cursor
));
340 error
= getparentpaths_by_handle(handlep
,
348 error
= getparents_by_handle(handlep
,
358 fprintf(stderr
, _("%s: getparentpaths failed for \"%s\": %s\n"),
359 progname
, path
, strerror(errno
));
364 /* no links for inode - something wrong here */
365 fprintf(stderr
, _("%s: inode-path is missing\n"), progname
);
370 for (i
= 0; i
< count
; i
++) {
371 print_parent_entry(entryp
);
372 entryp
= (parent_t
*) (((char*)entryp
) + entryp
->p_reclen
);
384 parent_f(int argc
, char **argv
)
387 int listpath_flag
= 0;
392 while ((c
= getopt(argc
, argv
, "cpv")) != EOF
) {
404 return command_usage(&parent_cmd
);
408 if (!check_flag
&& !listpath_flag
) /* default case */
409 exitcode
= parent_list(listpath_flag
);
412 exitcode
= parent_list(listpath_flag
);
414 exitcode
= parent_check();
425 " list the current file's parents and their filenames\n"
427 " -c -- check the current file's file system for parent consistency\n"
428 " -p -- list the current file's parents and their full paths\n"
429 " -v -- verbose mode\n"
436 parent_cmd
.name
= _("parent");
437 parent_cmd
.cfunc
= parent_f
;
438 parent_cmd
.argmin
= 0;
439 parent_cmd
.argmax
= -1;
440 parent_cmd
.args
= _("[-cpv]");
441 parent_cmd
.flags
= CMD_NOMAP_OK
;
442 parent_cmd
.oneline
= _("print or check parent inodes");
443 parent_cmd
.help
= parent_help
;
446 add_command(&parent_cmd
);