~ubuntu-branches/ubuntu/edgy/xfsprogs/edgy

« back to all changes in this revision

Viewing changes to io/parent.c

  • Committer: Bazaar Package Importer
  • Author(s): Nathan Scott
  • Date: 2005-11-16 16:32:35 UTC
  • Revision ID: james.westby@ubuntu.com-20051116163235-synnef6xjj18ny42
Tags: 2.7.7-1
* New upstream release.
* Add support for (optional) ATTR2 format extension (closes: #336350)
* Allow gcc -pedantic option for C++ <xfs.h> users (closes: #249429)
* Fix segv in xfs_db frag command (closes: #338207)

Show diffs side-by-side

added added

removed removed

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