2 * Copyright (c) 2005-2006 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 16384
32 static cmdinfo_t parent_cmd
;
33 static int verbose_flag
;
34 static int err_status
;
35 static __u64 inodes_checked
;
39 * check out a parent entry to see if the values seem valid
42 check_parent_entry(xfs_bstat_t
*bstatp
, parent_t
*parent
)
45 char fullpath
[PATH_MAX
];
49 sprintf(fullpath
, _("%s%s"), mntpt
, parent
->p_name
);
51 sts
= lstat(fullpath
, &statbuf
);
54 _("inode-path for inode: %llu is incorrect - path \"%s\" non-existent\n"),
55 bstatp
->bs_ino
, fullpath
);
58 _("path \"%s\" does not stat for inode: %llu; err = %s\n"),
66 if (verbose_flag
> 1) {
67 printf(_("path \"%s\" found\n"), fullpath
);
71 if (statbuf
.st_ino
!= bstatp
->bs_ino
) {
73 _("inode-path for inode: %llu is incorrect - wrong inode#\n"),
77 _("ino mismatch for path \"%s\" %llu vs %llu\n"),
79 (unsigned long long)statbuf
.st_ino
,
80 (unsigned long long)bstatp
->bs_ino
);
84 } else if (verbose_flag
> 1) {
85 printf(_("inode number match: %llu\n"),
86 (unsigned long long)statbuf
.st_ino
);
90 str
= strrchr(fullpath
, '/');
92 sts
= stat(fullpath
, &statbuf
);
95 _("parent path \"%s\" does not stat: %s\n"),
101 if (parent
->p_ino
!= statbuf
.st_ino
) {
103 _("inode-path for inode: %llu is incorrect - wrong parent inode#\n"),
107 _("ino mismatch for path \"%s\" %llu vs %llu\n"),
109 (unsigned long long)parent
->p_ino
,
110 (unsigned long long)statbuf
.st_ino
);
115 if (verbose_flag
> 1) {
116 printf(_("parent ino match for %llu\n"), parent
->p_ino
);
123 check_parents(parent_t
*parentbuf
, size_t *parentbuf_size
,
124 jdm_fshandle_t
*fshandlep
, xfs_bstat_t
*statp
)
131 error
= jdm_parentpaths(fshandlep
, statp
, parentbuf
, *parentbuf_size
, &count
);
133 if (error
== ERANGE
) {
134 *parentbuf_size
*= 2;
135 parentbuf
= (parent_t
*)realloc(parentbuf
, *parentbuf_size
);
137 fprintf(stderr
, _("parentpaths failed for ino %llu: %s\n"),
143 } while (error
== ERANGE
);
147 /* no links for inode - something wrong here */
148 fprintf(stderr
, _("inode-path for inode: %llu is missing\n"), statp
->bs_ino
);
153 for (i
= 0; i
< count
; i
++) {
154 check_parent_entry(statp
, entryp
);
155 entryp
= (parent_t
*) (((char*)entryp
) + entryp
->p_reclen
);
160 do_bulkstat(parent_t
*parentbuf
, size_t *parentbuf_size
, xfs_bstat_t
*bstatbuf
,
161 int fsfd
, jdm_fshandle_t
*fshandlep
)
167 xfs_fsop_bulkreq_t bulkreq
;
170 if (stat(mntpt
, &mntstat
)) {
171 fprintf(stderr
, _("can't stat mount point \"%s\": %s\n"),
172 mntpt
, strerror(errno
));
176 bulkreq
.lastip
= &lastino
;
177 bulkreq
.icount
= BSTATBUF_SZ
;
178 bulkreq
.ubuffer
= (void *)bstatbuf
;
179 bulkreq
.ocount
= &buflenout
;
181 while (xfsctl(mntpt
, fsfd
, XFS_IOC_FSBULKSTAT
, &bulkreq
) == 0) {
182 if (*(bulkreq
.ocount
) == 0) {
185 for (p
= bstatbuf
, endp
= bstatbuf
+ *bulkreq
.ocount
; p
< endp
; p
++) {
187 /* inode being modified, get synced data with iget */
188 if ( (!p
->bs_nlink
|| !p
->bs_mode
) && p
->bs_ino
!= 0 ) {
190 if (xfsctl(mntpt
, fsfd
, XFS_IOC_FSBULKSTAT_SINGLE
, &bulkreq
) < 0) {
192 _("failed to get bulkstat information for inode %llu\n"),
196 if (!p
->bs_nlink
|| !p
->bs_mode
|| !p
->bs_ino
) {
198 _("failed to get valid bulkstat information for inode %llu\n"),
205 if (p
->bs_ino
== mntstat
.st_ino
) {
209 if (verbose_flag
> 1) {
210 printf(_("checking inode %llu\n"), p
->bs_ino
);
213 /* print dotted progress */
214 if ((inodes_checked
% 100) == 0 && verbose_flag
== 1) {
215 printf("."); fflush(stdout
);
219 check_parents(parentbuf
, parentbuf_size
, fshandlep
, p
);
224 fprintf(stderr
, _("syssgi bulkstat failed: %s\n"), strerror(errno
));
232 jdm_fshandle_t
*fshandlep
;
234 size_t parentbuf_size
= PARENTBUF_SZ
;
235 xfs_bstat_t
*bstatbuf
;
244 fshandlep
= jdm_getfshandle(mntpt
);
245 if (fshandlep
== NULL
) {
246 fprintf(stderr
, _("unable to open \"%s\" for jdm: %s\n"),
252 /* allocate buffers */
253 bstatbuf
= (xfs_bstat_t
*)calloc(BSTATBUF_SZ
, sizeof(xfs_bstat_t
));
254 parentbuf
= (parent_t
*)malloc(parentbuf_size
);
255 if (!bstatbuf
|| !parentbuf
) {
256 fprintf(stderr
, _("unable to allocate buffers: %s\n"),
261 if (do_bulkstat(parentbuf
, &parentbuf_size
, bstatbuf
, fsfd
, fshandlep
) != 0)
265 fprintf(stderr
, _("num errors: %d\n"), err_status
);
267 printf(_("succeeded checking %llu inodes\n"), inodes_checked
);
275 print_parent_entry(parent_t
*parent
, int fullpath
)
277 printf(_("p_ino = %llu\n"), parent
->p_ino
);
278 printf(_("p_gen = %u\n"), parent
->p_gen
);
279 printf(_("p_reclen = %u\n"), parent
->p_reclen
);
281 printf(_("p_name = \"%s%s\"\n"), mntpt
, parent
->p_name
);
283 printf(_("p_name = \"%s\"\n"), parent
->p_name
);
287 parent_list(int fullpath
)
295 parent_t
*parentbuf
= NULL
;
296 char *path
= file
->name
;
297 int pb_size
= PARENTBUF_SZ
;
299 /* XXXX for linux libhandle version - to set libhandle fsfd cache */
304 if (path_to_fshandle(mntpt
, &fshandle
, &fshlen
) != 0) {
305 fprintf(stderr
, _("%s: failed path_to_fshandle \"%s\": %s\n"),
306 progname
, path
, strerror(errno
));
311 if (path_to_handle(path
, &handlep
, &handlen
) != 0) {
312 fprintf(stderr
, _("%s: path_to_handle failed for \"%s\"\n"), progname
, path
);
317 parentbuf
= (parent_t
*)realloc(parentbuf
, pb_size
);
319 fprintf(stderr
, _("%s: unable to allocate parent buffer: %s\n"),
320 progname
, strerror(errno
));
325 error
= parentpaths_by_handle(handlep
,
331 error
= parents_by_handle(handlep
,
337 if (error
== ERANGE
) {
340 fprintf(stderr
, _("%s: %s call failed for \"%s\": %s\n"),
341 progname
, fullpath
? "parentpaths" : "parents",
342 path
, strerror(errno
));
345 } while (error
== ERANGE
);
348 /* no links for inode - something wrong here */
349 fprintf(stderr
, _("%s: inode-path is missing\n"), progname
);
354 for (i
= 0; i
< count
; i
++) {
355 print_parent_entry(entryp
, fullpath
);
356 entryp
= (parent_t
*) (((char*)entryp
) + entryp
->p_reclen
);
366 parent_f(int argc
, char **argv
)
369 int listpath_flag
= 0;
376 fs_table_initialise();
378 fs
= fs_table_lookup(file
->name
, FS_MOUNT_POINT
);
380 fprintf(stderr
, _("file argument, \"%s\", is not in a mounted XFS filesystem\n"),
388 while ((c
= getopt(argc
, argv
, "cpv")) != EOF
) {
400 return command_usage(&parent_cmd
);
404 if (!check_flag
&& !listpath_flag
) /* default case */
405 exitcode
= parent_list(listpath_flag
);
408 exitcode
= parent_list(listpath_flag
);
410 exitcode
= parent_check();
421 " list the current file's parents and their filenames\n"
423 " -c -- check the current file's file system for parent consistency\n"
424 " -p -- list the current file's parents and their full paths\n"
425 " -v -- verbose mode\n"
432 parent_cmd
.name
= "parent";
433 parent_cmd
.cfunc
= parent_f
;
434 parent_cmd
.argmin
= 0;
435 parent_cmd
.argmax
= -1;
436 parent_cmd
.args
= _("[-cpv]");
437 parent_cmd
.flags
= CMD_NOMAP_OK
;
438 parent_cmd
.oneline
= _("print or check parent inodes");
439 parent_cmd
.help
= parent_help
;
442 add_command(&parent_cmd
);