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 (unsigned long long) bstatp
->bs_ino
, fullpath
);
58 _("path \"%s\" does not stat for inode: %llu; err = %s\n"),
60 (unsigned long long) bstatp
->bs_ino
,
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"),
74 (unsigned long long) bstatp
->bs_ino
);
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"),
104 (unsigned long long) bstatp
->bs_ino
);
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"),
117 (unsigned long long) parent
->p_ino
);
124 check_parents(parent_t
*parentbuf
, size_t *parentbuf_size
,
125 jdm_fshandle_t
*fshandlep
, xfs_bstat_t
*statp
)
132 error
= jdm_parentpaths(fshandlep
, statp
, parentbuf
, *parentbuf_size
, &count
);
134 if (error
== ERANGE
) {
135 *parentbuf_size
*= 2;
136 parentbuf
= (parent_t
*)realloc(parentbuf
, *parentbuf_size
);
138 fprintf(stderr
, _("parentpaths failed for ino %llu: %s\n"),
139 (unsigned long long) statp
->bs_ino
,
144 } while (error
== ERANGE
);
148 /* no links for inode - something wrong here */
149 fprintf(stderr
, _("inode-path for inode: %llu is missing\n"),
150 (unsigned long long) statp
->bs_ino
);
155 for (i
= 0; i
< count
; i
++) {
156 check_parent_entry(statp
, entryp
);
157 entryp
= (parent_t
*) (((char*)entryp
) + entryp
->p_reclen
);
162 do_bulkstat(parent_t
*parentbuf
, size_t *parentbuf_size
, xfs_bstat_t
*bstatbuf
,
163 int fsfd
, jdm_fshandle_t
*fshandlep
)
169 xfs_fsop_bulkreq_t bulkreq
;
172 if (stat(mntpt
, &mntstat
)) {
173 fprintf(stderr
, _("can't stat mount point \"%s\": %s\n"),
174 mntpt
, strerror(errno
));
178 bulkreq
.lastip
= &lastino
;
179 bulkreq
.icount
= BSTATBUF_SZ
;
180 bulkreq
.ubuffer
= (void *)bstatbuf
;
181 bulkreq
.ocount
= &buflenout
;
183 while (xfsctl(mntpt
, fsfd
, XFS_IOC_FSBULKSTAT
, &bulkreq
) == 0) {
184 if (*(bulkreq
.ocount
) == 0) {
187 for (p
= bstatbuf
, endp
= bstatbuf
+ *bulkreq
.ocount
; p
< endp
; p
++) {
189 /* inode being modified, get synced data with iget */
190 if ( (!p
->bs_nlink
|| !p
->bs_mode
) && p
->bs_ino
!= 0 ) {
192 if (xfsctl(mntpt
, fsfd
, XFS_IOC_FSBULKSTAT_SINGLE
, &bulkreq
) < 0) {
194 _("failed to get bulkstat information for inode %llu\n"),
195 (unsigned long long) p
->bs_ino
);
198 if (!p
->bs_nlink
|| !p
->bs_mode
|| !p
->bs_ino
) {
200 _("failed to get valid bulkstat information for inode %llu\n"),
201 (unsigned long long) p
->bs_ino
);
207 if (p
->bs_ino
== mntstat
.st_ino
) {
211 if (verbose_flag
> 1) {
212 printf(_("checking inode %llu\n"),
213 (unsigned long long) p
->bs_ino
);
216 /* print dotted progress */
217 if ((inodes_checked
% 100) == 0 && verbose_flag
== 1) {
218 printf("."); fflush(stdout
);
222 check_parents(parentbuf
, parentbuf_size
, fshandlep
, p
);
227 fprintf(stderr
, _("syssgi bulkstat failed: %s\n"), strerror(errno
));
235 jdm_fshandle_t
*fshandlep
;
237 size_t parentbuf_size
= PARENTBUF_SZ
;
238 xfs_bstat_t
*bstatbuf
;
247 fshandlep
= jdm_getfshandle(mntpt
);
248 if (fshandlep
== NULL
) {
249 fprintf(stderr
, _("unable to open \"%s\" for jdm: %s\n"),
255 /* allocate buffers */
256 bstatbuf
= (xfs_bstat_t
*)calloc(BSTATBUF_SZ
, sizeof(xfs_bstat_t
));
257 parentbuf
= (parent_t
*)malloc(parentbuf_size
);
258 if (!bstatbuf
|| !parentbuf
) {
259 fprintf(stderr
, _("unable to allocate buffers: %s\n"),
266 if (do_bulkstat(parentbuf
, &parentbuf_size
, bstatbuf
, fsfd
, fshandlep
) != 0)
270 fprintf(stderr
, _("num errors: %d\n"), err_status
);
272 printf(_("succeeded checking %llu inodes\n"),
273 (unsigned long long) inodes_checked
);
281 print_parent_entry(parent_t
*parent
, int fullpath
)
283 printf(_("p_ino = %llu\n"), (unsigned long long) parent
->p_ino
);
284 printf(_("p_gen = %u\n"), parent
->p_gen
);
285 printf(_("p_reclen = %u\n"), parent
->p_reclen
);
287 printf(_("p_name = \"%s%s\"\n"), mntpt
, parent
->p_name
);
289 printf(_("p_name = \"%s\"\n"), parent
->p_name
);
293 parent_list(int fullpath
)
301 parent_t
*parentbuf
= NULL
;
302 char *path
= file
->name
;
303 int pb_size
= PARENTBUF_SZ
;
305 /* XXXX for linux libhandle version - to set libhandle fsfd cache */
310 if (path_to_fshandle(mntpt
, &fshandle
, &fshlen
) != 0) {
311 fprintf(stderr
, _("%s: failed path_to_fshandle \"%s\": %s\n"),
312 progname
, path
, strerror(errno
));
317 if (path_to_handle(path
, &handlep
, &handlen
) != 0) {
318 fprintf(stderr
, _("%s: path_to_handle failed for \"%s\"\n"), progname
, path
);
323 parentbuf
= (parent_t
*)realloc(parentbuf
, pb_size
);
325 fprintf(stderr
, _("%s: unable to allocate parent buffer: %s\n"),
326 progname
, strerror(errno
));
331 error
= parentpaths_by_handle(handlep
,
337 error
= parents_by_handle(handlep
,
343 if (error
== ERANGE
) {
346 fprintf(stderr
, _("%s: %s call failed for \"%s\": %s\n"),
347 progname
, fullpath
? "parentpaths" : "parents",
348 path
, strerror(errno
));
351 } while (error
== ERANGE
);
354 /* no links for inode - something wrong here */
355 fprintf(stderr
, _("%s: inode-path is missing\n"), progname
);
360 for (i
= 0; i
< count
; i
++) {
361 print_parent_entry(entryp
, fullpath
);
362 entryp
= (parent_t
*) (((char*)entryp
) + entryp
->p_reclen
);
372 parent_f(int argc
, char **argv
)
375 int listpath_flag
= 0;
382 fs_table_initialise(0, NULL
, 0, NULL
);
384 fs
= fs_table_lookup(file
->name
, FS_MOUNT_POINT
);
386 fprintf(stderr
, _("file argument, \"%s\", is not in a mounted XFS filesystem\n"),
394 while ((c
= getopt(argc
, argv
, "cpv")) != EOF
) {
406 return command_usage(&parent_cmd
);
410 if (!check_flag
&& !listpath_flag
) /* default case */
411 exitcode
= parent_list(listpath_flag
);
414 exitcode
= parent_list(listpath_flag
);
416 exitcode
= parent_check();
427 " list the current file's parents and their filenames\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"
438 parent_cmd
.name
= "parent";
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
;
448 add_command(&parent_cmd
);