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