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
28 #define PARENTBUF_SZ 16384
29 #define BSTATBUF_SZ 16384
31 static cmdinfo_t parent_cmd
;
32 static int verbose_flag
;
33 static int err_status
;
34 static __u64 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
)
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 \"%s\" non-existent\n"),
54 (unsigned long long) bstatp
->bs_ino
, fullpath
);
57 _("path \"%s\" does not stat for inode: %llu; err = %s\n"),
59 (unsigned long long) bstatp
->bs_ino
,
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"),
73 (unsigned long long) bstatp
->bs_ino
);
76 _("ino mismatch for path \"%s\" %llu vs %llu\n"),
78 (unsigned long long)statbuf
.st_ino
,
79 (unsigned long long)bstatp
->bs_ino
);
83 } else if (verbose_flag
> 1) {
84 printf(_("inode number match: %llu\n"),
85 (unsigned long long)statbuf
.st_ino
);
89 str
= strrchr(fullpath
, '/');
91 sts
= stat(fullpath
, &statbuf
);
94 _("parent path \"%s\" does not stat: %s\n"),
100 if (parent
->p_ino
!= statbuf
.st_ino
) {
102 _("inode-path for inode: %llu is incorrect - wrong parent inode#\n"),
103 (unsigned long long) bstatp
->bs_ino
);
106 _("ino mismatch for path \"%s\" %llu vs %llu\n"),
108 (unsigned long long)parent
->p_ino
,
109 (unsigned long long)statbuf
.st_ino
);
114 if (verbose_flag
> 1) {
115 printf(_("parent ino match for %llu\n"),
116 (unsigned long long) 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"),
138 (unsigned long long) statp
->bs_ino
,
143 } while (error
== ERANGE
);
147 /* no links for inode - something wrong here */
148 fprintf(stderr
, _("inode-path for inode: %llu is missing\n"),
149 (unsigned long long) statp
->bs_ino
);
154 for (i
= 0; i
< count
; i
++) {
155 check_parent_entry(statp
, entryp
);
156 entryp
= (parent_t
*) (((char*)entryp
) + entryp
->p_reclen
);
161 do_bulkstat(parent_t
*parentbuf
, size_t *parentbuf_size
, xfs_bstat_t
*bstatbuf
,
162 int fsfd
, jdm_fshandle_t
*fshandlep
)
168 xfs_fsop_bulkreq_t bulkreq
;
171 if (stat(mntpt
, &mntstat
)) {
172 fprintf(stderr
, _("can't stat mount point \"%s\": %s\n"),
173 mntpt
, strerror(errno
));
177 bulkreq
.lastip
= &lastino
;
178 bulkreq
.icount
= BSTATBUF_SZ
;
179 bulkreq
.ubuffer
= (void *)bstatbuf
;
180 bulkreq
.ocount
= &buflenout
;
182 while (xfsctl(mntpt
, fsfd
, XFS_IOC_FSBULKSTAT
, &bulkreq
) == 0) {
183 if (*(bulkreq
.ocount
) == 0) {
186 for (p
= bstatbuf
, endp
= bstatbuf
+ *bulkreq
.ocount
; p
< endp
; p
++) {
188 /* inode being modified, get synced data with iget */
189 if ( (!p
->bs_nlink
|| !p
->bs_mode
) && p
->bs_ino
!= 0 ) {
191 if (xfsctl(mntpt
, fsfd
, XFS_IOC_FSBULKSTAT_SINGLE
, &bulkreq
) < 0) {
193 _("failed to get bulkstat information for inode %llu\n"),
194 (unsigned long long) p
->bs_ino
);
197 if (!p
->bs_nlink
|| !p
->bs_mode
|| !p
->bs_ino
) {
199 _("failed to get valid bulkstat information for inode %llu\n"),
200 (unsigned long long) p
->bs_ino
);
206 if (p
->bs_ino
== mntstat
.st_ino
) {
210 if (verbose_flag
> 1) {
211 printf(_("checking inode %llu\n"),
212 (unsigned long long) p
->bs_ino
);
215 /* print dotted progress */
216 if ((inodes_checked
% 100) == 0 && verbose_flag
== 1) {
217 printf("."); fflush(stdout
);
221 check_parents(parentbuf
, parentbuf_size
, fshandlep
, p
);
226 fprintf(stderr
, _("syssgi bulkstat failed: %s\n"), strerror(errno
));
234 jdm_fshandle_t
*fshandlep
;
236 size_t parentbuf_size
= PARENTBUF_SZ
;
237 xfs_bstat_t
*bstatbuf
;
246 fshandlep
= jdm_getfshandle(mntpt
);
247 if (fshandlep
== NULL
) {
248 fprintf(stderr
, _("unable to open \"%s\" for jdm: %s\n"),
254 /* allocate buffers */
255 bstatbuf
= (xfs_bstat_t
*)calloc(BSTATBUF_SZ
, sizeof(xfs_bstat_t
));
256 parentbuf
= (parent_t
*)malloc(parentbuf_size
);
257 if (!bstatbuf
|| !parentbuf
) {
258 fprintf(stderr
, _("unable to allocate buffers: %s\n"),
264 if (do_bulkstat(parentbuf
, &parentbuf_size
, bstatbuf
, fsfd
, fshandlep
) != 0)
268 fprintf(stderr
, _("num errors: %d\n"), err_status
);
270 printf(_("succeeded checking %llu inodes\n"),
271 (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
)
295 void *handlep
= NULL
;
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
));
315 free_handle(fshandle
, fshlen
);
318 if (path_to_handle(path
, &handlep
, &handlen
) != 0) {
319 fprintf(stderr
, _("%s: path_to_handle failed for \"%s\"\n"), progname
, path
);
324 parentbuf
= (parent_t
*)realloc(parentbuf
, pb_size
);
326 fprintf(stderr
, _("%s: unable to allocate parent buffer: %s\n"),
327 progname
, strerror(errno
));
332 error
= parentpaths_by_handle(handlep
,
338 error
= parents_by_handle(handlep
,
344 if (error
== ERANGE
) {
347 fprintf(stderr
, _("%s: %s call failed for \"%s\": %s\n"),
348 progname
, fullpath
? "parentpaths" : "parents",
349 path
, strerror(errno
));
352 } while (error
== ERANGE
);
355 /* no links for inode - something wrong here */
356 fprintf(stderr
, _("%s: inode-path is missing\n"), progname
);
361 for (i
= 0; i
< count
; i
++) {
362 print_parent_entry(entryp
, fullpath
);
363 entryp
= (parent_t
*) (((char*)entryp
) + entryp
->p_reclen
);
374 parent_f(int argc
, char **argv
)
377 int listpath_flag
= 0;
384 fs_table_initialise(0, NULL
, 0, NULL
);
386 fs
= fs_table_lookup(file
->name
, FS_MOUNT_POINT
);
388 fprintf(stderr
, _("file argument, \"%s\", is not in a mounted XFS filesystem\n"),
396 while ((c
= getopt(argc
, argv
, "cpv")) != EOF
) {
408 return command_usage(&parent_cmd
);
412 if (!check_flag
&& !listpath_flag
) /* default case */
413 exitcode
= parent_list(listpath_flag
);
416 exitcode
= parent_list(listpath_flag
);
418 exitcode
= parent_check();
429 " list the current file's parents and their filenames\n"
431 " -c -- check the current file's file system for parent consistency\n"
432 " -p -- list the current file's parents and their full paths\n"
433 " -v -- verbose mode\n"
440 parent_cmd
.name
= "parent";
441 parent_cmd
.cfunc
= parent_f
;
442 parent_cmd
.argmin
= 0;
443 parent_cmd
.argmax
= -1;
444 parent_cmd
.args
= _("[-cpv]");
445 parent_cmd
.flags
= CMD_NOMAP_OK
;
446 parent_cmd
.oneline
= _("print or check parent inodes");
447 parent_cmd
.help
= parent_help
;
450 add_command(&parent_cmd
);