]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - io/parent.c
Fix alignment issue back porting to IRIX.
[thirdparty/xfsprogs-dev.git] / io / parent.c
CommitLineData
258b00ea 1/*
74043ab2 2 * Copyright (c) 2005-2006 Silicon Graphics, Inc.
258b00ea
TS
3 * All Rights Reserved.
4 *
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.
8 *
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.
13 *
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
17 */
18
19#include <xfs/xfs.h>
20#include <xfs/command.h>
21#include <xfs/input.h>
22#include <xfs/path.h>
23#include <xfs/parent.h>
24#include <xfs/handle.h>
25#include <xfs/jdm.h>
26#include "init.h"
27#include "io.h"
28
29#define PARENTBUF_SZ 16384
74043ab2 30#define BSTATBUF_SZ 16384
258b00ea
TS
31
32static cmdinfo_t parent_cmd;
33static int verbose_flag;
34static int err_status;
74043ab2
TS
35static __u64 inodes_checked;
36static char *mntpt;
258b00ea
TS
37
38/*
39 * check out a parent entry to see if the values seem valid
40 */
41static void
74043ab2 42check_parent_entry(xfs_bstat_t *bstatp, parent_t *parent)
258b00ea
TS
43{
44 int sts;
45 char fullpath[PATH_MAX];
46 struct stat statbuf;
47 char *str;
48
49 sprintf(fullpath, _("%s%s"), mntpt, parent->p_name);
50
51 sts = lstat(fullpath, &statbuf);
52 if (sts != 0) {
53 fprintf(stderr,
74043ab2
TS
54 _("inode-path for inode: %llu is incorrect - path \"%s\" non-existent\n"),
55 bstatp->bs_ino, fullpath);
258b00ea
TS
56 if (verbose_flag) {
57 fprintf(stderr,
58 _("path \"%s\" does not stat for inode: %llu; err = %s\n"),
59 fullpath,
60 bstatp->bs_ino,
61 strerror(errno));
62 }
63 err_status++;
64 return;
65 } else {
66 if (verbose_flag > 1) {
67 printf(_("path \"%s\" found\n"), fullpath);
68 }
69 }
70
71 if (statbuf.st_ino != bstatp->bs_ino) {
72 fprintf(stderr,
73 _("inode-path for inode: %llu is incorrect - wrong inode#\n"),
74 bstatp->bs_ino);
75 if (verbose_flag) {
76 fprintf(stderr,
77 _("ino mismatch for path \"%s\" %llu vs %llu\n"),
78 fullpath,
79 statbuf.st_ino,
80 bstatp->bs_ino);
81 }
82 err_status++;
83 return;
84 } else if (verbose_flag > 1) {
85 printf(_("inode number match: %llu\n"), statbuf.st_ino);
86 }
87
88 /* get parent path */
89 str = strrchr(fullpath, '/');
90 *str = '\0';
91 sts = stat(fullpath, &statbuf);
92 if (sts != 0) {
93 fprintf(stderr,
94 _("parent path \"%s\" does not stat: %s\n"),
95 fullpath,
96 strerror(errno));
97 err_status++;
98 return;
99 } else {
100 if (parent->p_ino != statbuf.st_ino) {
101 fprintf(stderr,
102 _("inode-path for inode: %llu is incorrect - wrong parent inode#\n"),
103 bstatp->bs_ino);
104 if (verbose_flag) {
105 fprintf(stderr,
106 _("ino mismatch for path \"%s\" %llu vs %llu\n"),
107 fullpath,
108 parent->p_ino,
109 statbuf.st_ino);
110 }
111 err_status++;
112 return;
113 } else {
114 if (verbose_flag > 1) {
115 printf(_("parent ino match for %llu\n"), parent->p_ino);
116 }
117 }
118 }
119}
120
121static void
74043ab2
TS
122check_parents(parent_t *parentbuf, size_t *parentbuf_size,
123 jdm_fshandle_t *fshandlep, xfs_bstat_t *statp)
258b00ea
TS
124{
125 int error, i;
74043ab2 126 __u32 count;
258b00ea 127 parent_t *entryp;
258b00ea 128
258b00ea 129 do {
74043ab2
TS
130 error = jdm_parentpaths(fshandlep, statp, parentbuf, *parentbuf_size, &count);
131
132 if (error == ERANGE) {
133 *parentbuf_size *= 2;
134 parentbuf = (parent_t *)realloc(parentbuf, *parentbuf_size);
135 } else if (error) {
136 fprintf(stderr, _("parentpaths failed for ino %llu: %s\n"),
258b00ea 137 statp->bs_ino,
8577b2c9 138 strerror(errno));
258b00ea
TS
139 err_status++;
140 break;
141 }
74043ab2
TS
142 } while (error == ERANGE);
143
258b00ea 144
74043ab2
TS
145 if (count == 0) {
146 /* no links for inode - something wrong here */
147 fprintf(stderr, _("inode-path for inode: %llu is missing\n"), statp->bs_ino);
148 err_status++;
149 }
258b00ea 150
74043ab2
TS
151 entryp = parentbuf;
152 for (i = 0; i < count; i++) {
153 check_parent_entry(statp, entryp);
154 entryp = (parent_t*) (((char*)entryp) + entryp->p_reclen);
155 }
258b00ea
TS
156}
157
158static int
74043ab2
TS
159do_bulkstat(parent_t *parentbuf, size_t *parentbuf_size, xfs_bstat_t *bstatbuf,
160 int fsfd, jdm_fshandle_t *fshandlep)
258b00ea 161{
d026b19e
NS
162 __s32 buflenout;
163 __u64 lastino = 0;
258b00ea
TS
164 xfs_bstat_t *p;
165 xfs_bstat_t *endp;
166 xfs_fsop_bulkreq_t bulkreq;
167 struct stat mntstat;
168
a504bf72 169 if (stat(mntpt, &mntstat)) {
258b00ea 170 fprintf(stderr, _("can't stat mount point \"%s\": %s\n"),
8577b2c9 171 mntpt, strerror(errno));
258b00ea
TS
172 return 1;
173 }
174
175 bulkreq.lastip = &lastino;
176 bulkreq.icount = BSTATBUF_SZ;
177 bulkreq.ubuffer = (void *)bstatbuf;
178 bulkreq.ocount = &buflenout;
179
180 while (xfsctl(mntpt, fsfd, XFS_IOC_FSBULKSTAT, &bulkreq) == 0) {
181 if (*(bulkreq.ocount) == 0) {
182 return 0;
183 }
184 for (p = bstatbuf, endp = bstatbuf + *bulkreq.ocount; p < endp; p++) {
185
186 /* inode being modified, get synced data with iget */
187 if ( (!p->bs_nlink || !p->bs_mode) && p->bs_ino != 0 ) {
188
189 if (xfsctl(mntpt, fsfd, XFS_IOC_FSBULKSTAT_SINGLE, &bulkreq) < 0) {
190 fprintf(stderr,
191 _("failed to get bulkstat information for inode %llu\n"),
192 p->bs_ino );
193 continue;
194 }
195 if (!p->bs_nlink || !p->bs_mode || !p->bs_ino) {
196 fprintf(stderr,
197 _("failed to get valid bulkstat information for inode %llu\n"),
198 p->bs_ino );
199 continue;
200 }
201 }
202
203 /* skip root */
204 if (p->bs_ino == mntstat.st_ino) {
205 continue;
206 }
207
208 if (verbose_flag > 1) {
209 printf(_("checking inode %llu\n"), p->bs_ino);
210 }
211
212 /* print dotted progress */
213 if ((inodes_checked % 100) == 0 && verbose_flag == 1) {
214 printf("."); fflush(stdout);
215 }
216 inodes_checked++;
217
74043ab2 218 check_parents(parentbuf, parentbuf_size, fshandlep, p);
258b00ea
TS
219 }
220
221 }/*while*/
222
223 fprintf(stderr, _("syssgi bulkstat failed: %s\n"), strerror(errno));
224 return 1;
225}
226
227static int
228parent_check(void)
229{
258b00ea
TS
230 int fsfd;
231 jdm_fshandle_t *fshandlep;
232 parent_t *parentbuf;
74043ab2 233 size_t parentbuf_size = PARENTBUF_SZ;
258b00ea
TS
234 xfs_bstat_t *bstatbuf;
235
236 err_status = 0;
237 inodes_checked = 0;
238
239 sync();
240
258b00ea
TS
241 fsfd = file->fd;
242
243 fshandlep = jdm_getfshandle(mntpt);
244 if (fshandlep == 0) {
245 fprintf(stderr, _("unable to open \"%s\" for jdm: %s\n"),
246 mntpt,
247 strerror(errno));
248 return 1;
249 }
250
251 /* allocate buffers */
252 bstatbuf = (xfs_bstat_t *)calloc(BSTATBUF_SZ, sizeof(xfs_bstat_t));
74043ab2 253 parentbuf = (parent_t *)malloc(parentbuf_size);
258b00ea
TS
254 if (!bstatbuf || !parentbuf) {
255 fprintf(stderr, _("unable to allocate buffers: %s\n"),
256 strerror(errno));
257 return 1;
258 }
259
74043ab2 260 if (do_bulkstat(parentbuf, &parentbuf_size, bstatbuf, fsfd, fshandlep) != 0)
258b00ea
TS
261 err_status++;
262
263 if (err_status > 0)
264 fprintf(stderr, _("num errors: %d\n"), err_status);
265 else
266 printf(_("succeeded checking %llu inodes\n"), inodes_checked);
267
268 free(bstatbuf);
269 free(parentbuf);
270 return err_status;
271}
272
273static void
74043ab2 274print_parent_entry(parent_t *parent, int fullpath)
258b00ea
TS
275{
276 printf(_("p_ino = %llu\n"), parent->p_ino);
277 printf(_("p_gen = %u\n"), parent->p_gen);
278 printf(_("p_reclen = %u\n"), parent->p_reclen);
74043ab2
TS
279 if (fullpath)
280 printf(_("p_name = \"%s%s\"\n"), mntpt, parent->p_name);
281 else
282 printf(_("p_name = \"%s\"\n"), parent->p_name);
258b00ea
TS
283}
284
285static int
286parent_list(int fullpath)
287{
288 void *handlep;
289 size_t handlen;
290 int error, i;
291 int retval = 1;
74043ab2 292 __u32 count;
258b00ea 293 parent_t *entryp;
74043ab2 294 parent_t *parentbuf = NULL;
258b00ea 295 char *path = file->name;
74043ab2 296 int pb_size = PARENTBUF_SZ;
258b00ea
TS
297
298 /* XXXX for linux libhandle version - to set libhandle fsfd cache */
299 {
300 void *fshandle;
301 size_t fshlen;
302
74043ab2 303 if (path_to_fshandle(mntpt, &fshandle, &fshlen) != 0) {
258b00ea
TS
304 fprintf(stderr, _("%s: failed path_to_fshandle \"%s\": %s\n"),
305 progname, path, strerror(errno));
306 goto error;
307 }
308 }
309
310 if (path_to_handle(path, &handlep, &handlen) != 0) {
311 fprintf(stderr, _("%s: path_to_handle failed for \"%s\"\n"), progname, path);
312 goto error;
313 }
314
258b00ea 315 do {
74043ab2
TS
316 parentbuf = (parent_t *)realloc(parentbuf, pb_size);
317 if (!parentbuf) {
318 fprintf(stderr, _("%s: unable to allocate parent buffer: %s\n"),
319 progname, strerror(errno));
320 return 1;
321 }
322
258b00ea 323 if (fullpath) {
74043ab2 324 error = parentpaths_by_handle(handlep,
258b00ea
TS
325 handlen,
326 parentbuf,
74043ab2
TS
327 pb_size,
328 &count);
258b00ea 329 } else {
74043ab2 330 error = parents_by_handle(handlep,
258b00ea
TS
331 handlen,
332 parentbuf,
74043ab2
TS
333 pb_size,
334 &count);
258b00ea 335 }
74043ab2
TS
336 if (error == ERANGE) {
337 pb_size *= 2;
338 } else if (error) {
339 fprintf(stderr, _("%s: %s call failed for \"%s\": %s\n"),
340 progname, fullpath ? "parentpaths" : "parents",
341 path, strerror(errno));
258b00ea
TS
342 goto error;
343 }
74043ab2 344 } while (error == ERANGE);
258b00ea 345
74043ab2
TS
346 if (count == 0) {
347 /* no links for inode - something wrong here */
348 fprintf(stderr, _("%s: inode-path is missing\n"), progname);
349 goto error;
350 }
258b00ea 351
74043ab2
TS
352 entryp = parentbuf;
353 for (i = 0; i < count; i++) {
354 print_parent_entry(entryp, fullpath);
355 entryp = (parent_t*) (((char*)entryp) + entryp->p_reclen);
356 }
258b00ea
TS
357
358 retval = 0;
359error:
360 free(parentbuf);
361 return retval;
362}
363
364int
365parent_f(int argc, char **argv)
366{
367 int c;
368 int listpath_flag = 0;
369 int check_flag = 0;
74043ab2
TS
370 fs_path_t *fs;
371 static int tab_init;
372
373 if (!tab_init) {
374 tab_init = 1;
375 fs_table_initialise();
376 }
377 fs = fs_table_lookup(file->name, FS_MOUNT_POINT);
378 if (!fs) {
379 fprintf(stderr, _("file argument, \"%s\", is not in a mounted XFS filesystem\n"),
380 file->name);
381 return 1;
382 }
383 mntpt = fs->fs_dir;
258b00ea
TS
384
385 verbose_flag = 0;
386
387 while ((c = getopt(argc, argv, "cpv")) != EOF) {
388 switch (c) {
389 case 'c':
390 check_flag = 1;
391 break;
392 case 'p':
393 listpath_flag = 1;
394 break;
395 case 'v':
396 verbose_flag++;
397 break;
398 default:
399 return command_usage(&parent_cmd);
400 }
401 }
402
403 if (!check_flag && !listpath_flag) /* default case */
404 exitcode = parent_list(listpath_flag);
405 else {
406 if (listpath_flag)
407 exitcode = parent_list(listpath_flag);
408 if (check_flag)
409 exitcode = parent_check();
410 }
411
412 return 0;
413}
414
415static void
416parent_help(void)
417{
418 printf(_(
419"\n"
420" list the current file's parents and their filenames\n"
421"\n"
422" -c -- check the current file's file system for parent consistency\n"
423" -p -- list the current file's parents and their full paths\n"
424" -v -- verbose mode\n"
425"\n"));
426}
427
428void
429parent_init(void)
430{
431 parent_cmd.name = _("parent");
432 parent_cmd.cfunc = parent_f;
433 parent_cmd.argmin = 0;
434 parent_cmd.argmax = -1;
435 parent_cmd.args = _("[-cpv]");
436 parent_cmd.flags = CMD_NOMAP_OK;
437 parent_cmd.oneline = _("print or check parent inodes");
438 parent_cmd.help = parent_help;
439
440 if (expert)
441 add_command(&parent_cmd);
442}