~wb-munzinger/+junk/ocfs2-tools

« back to all changes in this revision

Viewing changes to debugfs.ocfs2/dump_fs_locks.c

  • Committer: Bazaar Package Importer
  • Author(s): Jeremy Lainé
  • Date: 2009-07-06 07:26:30 UTC
  • mfrom: (1.1.7 upstream) (0.1.5 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090706072630-59335sl51k3rvu74
Tags: 1.4.2-1
* New upstream release (Closes: #535471).
* Drop patch for limits.h, included upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *
6
6
 * Interface with the kernel and dump current fs locking state
7
7
 *
8
 
 * Copyright (C) 2005 Oracle.  All rights reserved.
 
8
 * Copyright (C) 2005, 2008 Oracle.  All rights reserved.
9
9
 *
10
10
 * This program is free software; you can redistribute it and/or
11
11
 * modify it under the terms of the GNU General Public
21
21
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22
22
 * Boston, MA 021110-1307, USA.
23
23
 *
24
 
 *  This code is a port of e2fsprogs/lib/ext2fs/dir_iterate.c
25
 
 *  Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o.
26
24
 */
 
25
 
27
26
#define _XOPEN_SOURCE 600  /* Triggers XOPEN2K in features.h */
28
27
#define _LARGEFILE64_SOURCE
29
28
 
38
37
#include <stdio.h>
39
38
 
40
39
#include "main.h"
41
 
#include "byteorder.h"
 
40
#include "ocfs2/byteorder.h"
42
41
#include "ocfs2_internals.h"
43
42
 
44
43
static char *level_str(int level)
226
225
}
227
226
 
228
227
/* 0 = eof, > 0 = success, < 0 = error */
229
 
static int dump_version_one(FILE *file, FILE *out, int lvbs)
 
228
static int dump_version_two(FILE *file, FILE *out)
 
229
{
 
230
        unsigned long long num_prmode, num_exmode;
 
231
        unsigned int num_prmode_failed, num_exmode_failed;
 
232
        unsigned long long  total_prmode, total_exmode;
 
233
        unsigned int max_prmode, max_exmode, num_refresh;
 
234
        int ret;
 
235
 
 
236
#define NSEC_PER_USEC   1000
 
237
 
 
238
        ret = fscanf(file, "%llu\t"
 
239
                     "%llu\t"
 
240
                     "%u\t"
 
241
                     "%u\t"
 
242
                     "%llu\t"
 
243
                     "%llu\t"
 
244
                     "%u\t"
 
245
                     "%u\t"
 
246
                     "%u",
 
247
                     &num_prmode,
 
248
                     &num_exmode,
 
249
                     &num_prmode_failed,
 
250
                     &num_exmode_failed,
 
251
                     &total_prmode,
 
252
                     &total_exmode,
 
253
                     &max_prmode,
 
254
                     &max_exmode,
 
255
                     &num_refresh);
 
256
        if (ret != 9) {
 
257
                ret = -EINVAL;
 
258
                goto out;
 
259
        }
 
260
 
 
261
        fprintf(out, "PR > Gets: %llu  Fails: %u    Waits (usec) Total: %llu  "
 
262
                "Max: %u\n",
 
263
                num_prmode, num_prmode_failed, total_prmode/NSEC_PER_USEC,
 
264
                max_prmode/NSEC_PER_USEC);
 
265
        fprintf(out, "EX > Gets: %llu  Fails: %u    Waits (usec) Total: %llu  "
 
266
                "Max: %u\n",
 
267
                num_exmode, num_exmode_failed, total_exmode/NSEC_PER_USEC,
 
268
                max_exmode/NSEC_PER_USEC);
 
269
        fprintf(out, "Disk Refreshes: %u\n", num_refresh);
 
270
 
 
271
        ret = 1;
 
272
out:
 
273
        return ret;
 
274
}
 
275
 
 
276
/* 0 = eof, > 0 = success, < 0 = error */
 
277
static int dump_version_one(FILE *file, FILE *out, int lvbs, int only_busy,
 
278
                            struct list_head *locklist, int *skipped,
 
279
                            unsigned int version)
230
280
{
231
281
        char id[OCFS2_LOCK_ID_MAX_LEN + 1];     
232
282
        char lvb[DLM_LVB_LEN];
235
285
        unsigned int action, unlock_action, ro, ex, dummy;
236
286
        const char *format;
237
287
 
 
288
        *skipped = 1;
 
289
 
238
290
        ret = fscanf(file, "%s\t"
239
291
                     "%d\t"
240
292
                     "0x%lx\t"
264
316
                 * include the field delimiting '\t' then fscanf will
265
317
                 * also catch the record delimiting '\n' character,
266
318
                 * which we want to save for the caller to find. */
267
 
                if (i == (DLM_LVB_LEN - 1))
 
319
                if ((i == (DLM_LVB_LEN - 1)) && (version < 2))
268
320
                        format = "0x%x";
269
321
 
270
322
                ret = fscanf(file, format, &dummy);
276
328
                lvb[i] = (char) dummy;
277
329
        }
278
330
 
 
331
        if (!list_empty(locklist)) {
 
332
                if (!del_from_stringlist(id, locklist)) {
 
333
                        ret = 1;
 
334
                        goto out;
 
335
                }
 
336
        }
 
337
 
 
338
        if (only_busy) {
 
339
                if (!(flags & OCFS2_LOCK_BUSY)) {
 
340
                        ret = 1;
 
341
                        goto out;
 
342
                }
 
343
        }
 
344
 
279
345
        fprintf(out, "Lockres: %s  Mode: %s\nFlags:", id, level_str(level));
280
346
        print_flags(flags, out);
281
347
        fprintf(out, "\nRO Holders: %u  EX Holders: %u\n", ro, ex);
289
355
                if (id[0] == 'M')
290
356
                        dump_meta_lvb(lvb, out);
291
357
        }
292
 
        fprintf(out, "\n");
 
358
 
 
359
        *skipped = 0;
293
360
 
294
361
        ret = 1;
295
362
out:
309
376
        return 0;
310
377
}
311
378
 
312
 
#define CURRENT_PROTO 1
 
379
#define CURRENT_PROTO 2
313
380
/* returns 0 on error or end of file */
314
 
static int dump_one_lockres(FILE *file, FILE *out, int lvbs)
 
381
static int dump_one_lockres(FILE *file, FILE *out, int lvbs, int only_busy,
 
382
                            struct list_head *locklist)
315
383
{
316
384
        unsigned int version;
317
385
        int ret;
 
386
        int skipped = 0;
318
387
 
319
388
        ret = fscanf(file, "%x\t", &version);
320
389
        if (ret != 1)
326
395
                return 0;
327
396
        }
328
397
 
329
 
        ret = dump_version_one(file, out, lvbs);
 
398
        ret = dump_version_one(file, out, lvbs, only_busy, locklist, &skipped, version);
330
399
        if (ret <= 0)
331
400
                return 0;
332
401
 
 
402
        if (!skipped) {
 
403
                if (version == CURRENT_PROTO) {
 
404
                        ret = dump_version_two(file, out);
 
405
                        if (ret <= 0)
 
406
                                return 0;
 
407
                }
 
408
 
 
409
                fprintf(out, "\n");
 
410
        }
 
411
 
333
412
        /* Read to the end of the record here. Any new fields tagged
334
413
         * onto the current format will be silently ignored. */
335
414
        ret = !end_line(file);
337
416
        return ret;
338
417
}
339
418
 
340
 
#define DEBUGFS_MAGIC   0x64626720
341
 
static errcode_t try_debugfs_path(const char *path)
342
 
{
343
 
        errcode_t ret;
344
 
        struct stat64 stat_buf;
345
 
        struct statfs64 statfs_buf;
346
 
 
347
 
        ret = stat64(path, &stat_buf);
348
 
        if (ret || !S_ISDIR(stat_buf.st_mode))
349
 
                return O2CB_ET_SERVICE_UNAVAILABLE;
350
 
        ret = statfs64(path, &statfs_buf);
351
 
        if (ret || (statfs_buf.f_type != DEBUGFS_MAGIC))
352
 
                return O2CB_ET_SERVICE_UNAVAILABLE;
353
 
 
354
 
        return 0;
355
 
}
356
 
 
357
 
#define LOCKING_STATE_FORMAT_PATH "%s/ocfs2/%s/locking_state"
358
 
static errcode_t open_locking_state(const char *debugfs_path,
359
 
                                    const char *uuid_str,
360
 
                                    FILE **state_file)
361
 
{
362
 
        errcode_t ret = 0;
363
 
        char path[PATH_MAX];
364
 
 
365
 
        ret = snprintf(path, PATH_MAX - 1, LOCKING_STATE_FORMAT_PATH,
366
 
                       debugfs_path, uuid_str);
367
 
        if ((ret <= 0) || (ret == (PATH_MAX - 1)))
368
 
                return O2CB_ET_INTERNAL_FAILURE;
369
 
 
370
 
        *state_file = fopen(path, "r");
371
 
        if (!*state_file) {
372
 
                switch (errno) {
373
 
                        default:
374
 
                                ret = O2CB_ET_INTERNAL_FAILURE;
375
 
                                break;
376
 
 
377
 
                        case ENOTDIR:
378
 
                        case ENOENT:
379
 
                        case EISDIR:
380
 
                                ret = O2CB_ET_SERVICE_UNAVAILABLE;
381
 
                                break;
382
 
 
383
 
                        case EACCES:
384
 
                        case EPERM:
385
 
                        case EROFS:
386
 
                                ret = O2CB_ET_PERMISSION_DENIED;
387
 
                                break;
388
 
                }
389
 
                goto out;
390
 
        }
391
 
 
392
 
        ret = 0;
393
 
out:
394
 
        return ret;
395
 
}
396
 
 
397
 
#define SYSFS_BASE              "/sys/kernel/"
398
 
#define DEBUGFS_PATH            SYSFS_BASE "debug"
399
 
#define DEBUGFS_ALTERNATE_PATH  "/debug"
400
 
 
401
 
void dump_fs_locks(char *uuid_str, FILE *out, int dump_lvbs)
402
 
{
403
 
        errcode_t ret;
404
 
        int err;
405
 
        const char *debugfs_path = DEBUGFS_PATH;
406
 
        struct stat64 stat_buf;
 
419
void dump_fs_locks(char *uuid_str, FILE *out, char *path, int dump_lvbs,
 
420
                   int only_busy, struct list_head *locklist)
 
421
{
 
422
        errcode_t ret;
 
423
        char debugfs_path[PATH_MAX];
407
424
        FILE *file;
408
 
 
409
 
        err = stat64(SYSFS_BASE, &stat_buf);
410
 
        if (err)
411
 
                debugfs_path = DEBUGFS_ALTERNATE_PATH;
412
 
 
413
 
        ret = try_debugfs_path(debugfs_path);
414
 
        if (ret) {
415
 
                fprintf(stderr, "Could not locate debugfs file system. "
416
 
                        "Perhaps it is not mounted?\n");
417
 
                return;
418
 
        }
419
 
 
420
 
        ret = open_locking_state(debugfs_path, uuid_str, &file);
421
 
        if (ret) {
422
 
                fprintf(stderr, "Could not open debug state for \"%s\".\n"
423
 
                        "Perhaps that OCFS2 file system is not mounted?\n",
424
 
                        uuid_str);
425
 
                return;
426
 
        }
427
 
 
428
 
        while (dump_one_lockres(file, out, dump_lvbs))
429
 
                ;
 
425
        int show_select;
 
426
 
 
427
        if (path == NULL) {
 
428
                ret = get_debugfs_path(debugfs_path, sizeof(debugfs_path));
 
429
                if (ret) {
 
430
                        fprintf(stderr, "Could not locate debugfs file system. "
 
431
                                "Perhaps it is not mounted?\n");
 
432
                        return;
 
433
                }
 
434
 
 
435
                ret = open_debugfs_file(debugfs_path, "ocfs2", uuid_str,
 
436
                                        "locking_state", &file);
 
437
                if (ret) {
 
438
                        fprintf(stderr, "Could not open debug state for "
 
439
                                "\"%s\".\nPerhaps that OCFS2 file system is "
 
440
                                "not mounted?\n", uuid_str);
 
441
                        return;
 
442
                }
 
443
        } else {
 
444
                file = fopen(path, "r");
 
445
                if (!file) {
 
446
                        fprintf(stderr, "Could not open file at \"%s\"\n",
 
447
                                path);
 
448
                        return;
 
449
                }
 
450
        }
 
451
 
 
452
        show_select = !list_empty(locklist);
 
453
 
 
454
        while (dump_one_lockres(file, out, dump_lvbs, only_busy, locklist)) {
 
455
                if (show_select && list_empty(locklist))
 
456
                        break;
 
457
        }
430
458
 
431
459
        fclose(file);
432
460
}