Coverage Report

Created: 2024-09-08 06:27

/src/e2fsprogs/lib/ext2fs/mkjournal.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * mkjournal.c --- make a journal for a filesystem
3
 *
4
 * Copyright (C) 2000 Theodore Ts'o.
5
 *
6
 * %Begin-Header%
7
 * This file may be redistributed under the terms of the GNU Library
8
 * General Public License, version 2.
9
 * %End-Header%
10
 */
11
12
#include "config.h"
13
#include <stdio.h>
14
#include <string.h>
15
#include <assert.h>
16
#if HAVE_UNISTD_H
17
#include <unistd.h>
18
#endif
19
#if HAVE_ERRNO_H
20
#include <errno.h>
21
#endif
22
#include <fcntl.h>
23
#if HAVE_SYS_STAT_H
24
#include <sys/stat.h>
25
#endif
26
#if HAVE_SYS_TYPES_H
27
#include <sys/types.h>
28
#endif
29
#if HAVE_SYS_IOCTL_H
30
#include <sys/ioctl.h>
31
#endif
32
#if HAVE_NETINET_IN_H
33
#include <netinet/in.h>
34
#endif
35
36
#include "ext2_fs.h"
37
#include "e2p/e2p.h"
38
#include "ext2fsP.h"
39
40
#include "kernel-jbd.h"
41
42
/*
43
 * This function automatically sets up the journal superblock and
44
 * returns it as an allocated block.
45
 */
46
errcode_t ext2fs_create_journal_superblock2(ext2_filsys fs,
47
             struct ext2fs_journal_params *jparams,
48
             int flags, char **ret_jsb)
49
0
{
50
0
  errcode_t   retval;
51
0
  journal_superblock_t  *jsb;
52
53
0
  if (jparams->num_journal_blocks < JBD2_MIN_JOURNAL_BLOCKS)
54
0
    return EXT2_ET_JOURNAL_TOO_SMALL;
55
56
0
  if ((retval = ext2fs_get_mem(fs->blocksize, &jsb)))
57
0
    return retval;
58
59
0
  memset (jsb, 0, fs->blocksize);
60
61
0
  jsb->s_header.h_magic = htonl(JBD2_MAGIC_NUMBER);
62
0
  if (flags & EXT2_MKJOURNAL_V1_SUPER)
63
0
    jsb->s_header.h_blocktype = htonl(JBD2_SUPERBLOCK_V1);
64
0
  else
65
0
    jsb->s_header.h_blocktype = htonl(JBD2_SUPERBLOCK_V2);
66
0
  jsb->s_blocksize = htonl(fs->blocksize);
67
0
  jsb->s_maxlen = htonl(jparams->num_journal_blocks + jparams->num_fc_blocks);
68
0
  jsb->s_nr_users = htonl(1);
69
0
  jsb->s_first = htonl(1);
70
0
  jsb->s_sequence = htonl(1);
71
0
  jsb->s_num_fc_blks = htonl(jparams->num_fc_blocks);
72
0
  memcpy(jsb->s_uuid, fs->super->s_uuid, sizeof(fs->super->s_uuid));
73
  /*
74
   * If we're creating an external journal device, we need to
75
   * adjust these fields.
76
   */
77
0
  if (ext2fs_has_feature_journal_dev(fs->super)) {
78
0
    jsb->s_nr_users = 0;
79
0
    jsb->s_first = htonl(ext2fs_journal_sb_start(fs->blocksize) + 1);
80
0
  }
81
82
0
  *ret_jsb = (char *) jsb;
83
0
  return 0;
84
0
}
85
86
errcode_t ext2fs_create_journal_superblock(ext2_filsys fs, __u32 num_blocks,
87
          int flags, char **ret_sb)
88
0
{
89
0
  struct ext2fs_journal_params jparams;
90
91
0
  jparams.num_journal_blocks = num_blocks;
92
0
  jparams.num_fc_blocks = 0;
93
94
0
  return ext2fs_create_journal_superblock2(fs, &jparams, flags, ret_sb);
95
0
}
96
97
/*
98
 * This function writes a journal using POSIX routines.  It is used
99
 * for creating external journals and creating journals on live
100
 * filesystems.
101
 */
102
static errcode_t write_journal_file(ext2_filsys fs, char *filename,
103
            struct ext2fs_journal_params *jparams,
104
            int flags)
105
0
{
106
0
  errcode_t retval;
107
0
  char    *buf = 0;
108
0
  int   fd, ret_size;
109
0
  blk_t   i;
110
111
0
  if ((retval = ext2fs_create_journal_superblock2(fs, jparams, flags,
112
0
                   &buf)))
113
0
    return retval;
114
115
  /* Open the device or journal file */
116
0
  if ((fd = open(filename, O_WRONLY)) < 0) {
117
0
    retval = errno;
118
0
    goto errfree;
119
0
  }
120
121
  /* Write the superblock out */
122
0
  retval = EXT2_ET_SHORT_WRITE;
123
0
  ret_size = write(fd, buf, fs->blocksize);
124
0
  if (ret_size < 0) {
125
0
    retval = errno;
126
0
    goto errout;
127
0
  }
128
0
  if (ret_size != (int) fs->blocksize)
129
0
    goto errout;
130
0
  memset(buf, 0, fs->blocksize);
131
132
0
  if (flags & EXT2_MKJOURNAL_LAZYINIT)
133
0
    goto success;
134
135
0
  for (i = 1; i < jparams->num_journal_blocks + jparams->num_fc_blocks; i++) {
136
0
    ret_size = write(fd, buf, fs->blocksize);
137
0
    if (ret_size < 0) {
138
0
      retval = errno;
139
0
      goto errout;
140
0
    }
141
0
    if (ret_size != (int) fs->blocksize)
142
0
      goto errout;
143
0
  }
144
145
0
success:
146
0
  retval = 0;
147
0
errout:
148
0
  close(fd);
149
0
errfree:
150
0
  ext2fs_free_mem(&buf);
151
0
  return retval;
152
0
}
153
154
/*
155
 * Convenience function which zeros out _num_ blocks starting at
156
 * _blk_.  In case of an error, the details of the error is returned
157
 * via _ret_blk_ and _ret_count_ if they are non-NULL pointers.
158
 * Returns 0 on success, and an error code on an error.
159
 *
160
 * As a special case, if the first argument is NULL, then it will
161
 * attempt to free the static zeroizing buffer.  (This is to keep
162
 * programs that check for memory leaks happy.)
163
 */
164
0
#define MAX_STRIDE_LENGTH (4194304 / (int) fs->blocksize)
165
errcode_t ext2fs_zero_blocks2(ext2_filsys fs, blk64_t blk, int num,
166
            blk64_t *ret_blk, int *ret_count)
167
1.46k
{
168
1.46k
  int   j, count;
169
1.46k
  static void *buf;
170
1.46k
  static int  stride_length;
171
1.46k
  errcode_t retval;
172
173
  /* If fs is null, clean up the static buffer and return */
174
1.46k
  if (!fs) {
175
1.46k
    if (buf) {
176
0
      free(buf);
177
0
      buf = 0;
178
0
      stride_length = 0;
179
0
    }
180
1.46k
    return 0;
181
1.46k
  }
182
183
  /* Deal with zeroing less than 1 block */
184
0
  if (num <= 0)
185
0
    return 0;
186
187
  /* Try a zero out command, if supported */
188
0
  retval = io_channel_zeroout(fs->io, blk, num);
189
0
  if (retval == 0)
190
0
    return 0;
191
192
  /* Allocate the zeroizing buffer if necessary */
193
0
  if (num > stride_length && stride_length < MAX_STRIDE_LENGTH) {
194
0
    void *p;
195
0
    int new_stride = num;
196
197
0
    if (new_stride > MAX_STRIDE_LENGTH)
198
0
      new_stride = MAX_STRIDE_LENGTH;
199
0
    p = realloc(buf, fs->blocksize * new_stride);
200
0
    if (!p)
201
0
      return EXT2_ET_NO_MEMORY;
202
0
    buf = p;
203
0
    stride_length = new_stride;
204
0
    memset(buf, 0, fs->blocksize * stride_length);
205
0
  }
206
  /* OK, do the write loop */
207
0
  j=0;
208
0
  while (j < num) {
209
0
    if (blk % stride_length) {
210
0
      count = stride_length - (blk % stride_length);
211
0
      if (count > (num - j))
212
0
        count = num - j;
213
0
    } else {
214
0
      count = num - j;
215
0
      if (count > stride_length)
216
0
        count = stride_length;
217
0
    }
218
0
    retval = io_channel_write_blk64(fs->io, blk, count, buf);
219
0
    if (retval) {
220
0
      if (ret_count)
221
0
        *ret_count = count;
222
0
      if (ret_blk)
223
0
        *ret_blk = blk;
224
0
      return retval;
225
0
    }
226
0
    j += count; blk += count;
227
0
  }
228
0
  return 0;
229
0
}
230
231
errcode_t ext2fs_zero_blocks(ext2_filsys fs, blk_t blk, int num,
232
           blk_t *ret_blk, int *ret_count)
233
0
{
234
0
  blk64_t ret_blk2;
235
0
  errcode_t retval;
236
237
0
  retval = ext2fs_zero_blocks2(fs, blk, num, &ret_blk2, ret_count);
238
0
  if (retval)
239
0
    *ret_blk = (blk_t) ret_blk2;
240
0
  return retval;
241
0
}
242
243
/*
244
 * Calculate the initial goal block to be roughly at the middle of the
245
 * filesystem.  Pick a group that has the largest number of free
246
 * blocks.
247
 */
248
static blk64_t get_midpoint_journal_block(ext2_filsys fs)
249
0
{
250
0
  dgrp_t  group, start, end, i, log_flex;
251
252
0
  group = ext2fs_group_of_blk2(fs, (ext2fs_blocks_count(fs->super) -
253
0
           fs->super->s_first_data_block) / 2);
254
0
  log_flex = 1U << fs->super->s_log_groups_per_flex;
255
0
  if (fs->super->s_log_groups_per_flex && (group > log_flex)) {
256
0
    group = group & ~(log_flex - 1);
257
0
    while ((group < fs->group_desc_count) &&
258
0
           ext2fs_bg_free_blocks_count(fs, group) == 0)
259
0
      group++;
260
0
    if (group == fs->group_desc_count)
261
0
      group = 0;
262
0
    start = group;
263
0
  } else
264
0
    start = (group > 0) ? group-1 : group;
265
0
  end = ((group+1) < fs->group_desc_count) ? group+1 : group;
266
0
  group = start;
267
0
  for (i = start + 1; i <= end; i++)
268
0
    if (ext2fs_bg_free_blocks_count(fs, i) >
269
0
        ext2fs_bg_free_blocks_count(fs, group))
270
0
      group = i;
271
0
  return ext2fs_group_first_block2(fs, group);
272
0
}
273
274
/*
275
 * This function creates a journal using direct I/O routines.
276
 */
277
static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
278
             struct ext2fs_journal_params *jparams,
279
             blk64_t goal, int flags)
280
0
{
281
0
  char      *buf;
282
0
  errcode_t   retval;
283
0
  struct ext2_inode inode;
284
0
  unsigned long long  inode_size;
285
0
  int     falloc_flags = EXT2_FALLOCATE_FORCE_INIT;
286
0
  blk64_t     zblk;
287
0
  time_t      now;
288
289
0
  if ((retval = ext2fs_create_journal_superblock2(fs, jparams, flags,
290
0
                   &buf)))
291
0
    return retval;
292
293
0
  if ((retval = ext2fs_read_bitmaps(fs)))
294
0
    goto out2;
295
296
0
  if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
297
0
    goto out2;
298
299
0
  if (inode.i_blocks > 0) {
300
0
    retval = EEXIST;
301
0
    goto out2;
302
0
  }
303
304
0
  if (goal == ~0ULL)
305
0
    goal = get_midpoint_journal_block(fs);
306
307
0
  if (ext2fs_has_feature_extents(fs->super))
308
0
    inode.i_flags |= EXT4_EXTENTS_FL;
309
310
0
  if (!(flags & EXT2_MKJOURNAL_LAZYINIT))
311
0
    falloc_flags |= EXT2_FALLOCATE_ZERO_BLOCKS;
312
313
0
  inode_size = (unsigned long long)fs->blocksize *
314
0
      (jparams->num_journal_blocks + jparams->num_fc_blocks);
315
0
  now = ext2fsP_get_time(fs);
316
0
  ext2fs_inode_xtime_set(&inode, i_mtime, now);
317
0
  ext2fs_inode_xtime_set(&inode, i_ctime, now);
318
0
  inode.i_links_count = 1;
319
0
  inode.i_mode = LINUX_S_IFREG | 0600;
320
0
  retval = ext2fs_inode_size_set(fs, &inode, inode_size);
321
0
  if (retval)
322
0
    goto out2;
323
324
0
  retval = ext2fs_fallocate(fs, falloc_flags, journal_ino,
325
0
          &inode, goal, 0,
326
0
          jparams->num_journal_blocks + jparams->num_fc_blocks);
327
0
  if (retval)
328
0
    goto out2;
329
330
0
  if ((retval = ext2fs_write_new_inode(fs, journal_ino, &inode)))
331
0
    goto out2;
332
333
0
  retval = ext2fs_bmap2(fs, journal_ino, &inode, NULL, 0, 0, NULL, &zblk);
334
0
  if (retval)
335
0
    goto out2;
336
337
0
  retval = io_channel_write_blk64(fs->io, zblk, 1, buf);
338
0
  if (retval)
339
0
    goto out2;
340
341
0
  memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4);
342
0
  fs->super->s_jnl_blocks[15] = inode.i_size_high;
343
0
  fs->super->s_jnl_blocks[16] = inode.i_size;
344
0
  fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
345
0
  ext2fs_mark_super_dirty(fs);
346
347
0
out2:
348
0
  ext2fs_free_mem(&buf);
349
0
  return retval;
350
0
}
351
352
/*
353
 * Find a reasonable journal file size (in blocks) given the number of blocks
354
 * in the filesystem.  For very small filesystems, it is not reasonable to
355
 * have a journal that fills more than half of the filesystem.
356
 *
357
 * n.b. comments assume 4k blocks
358
 */
359
int ext2fs_default_journal_size(__u64 num_blocks)
360
0
{
361
0
  if (num_blocks < 2048)
362
0
    return -1;
363
0
  if (num_blocks < 32768)   /* 128 MB */
364
0
    return (1024);     /* 4 MB */
365
0
  if (num_blocks < 256*1024) /* 1 GB */
366
0
    return (4096);     /* 16 MB */
367
0
  if (num_blocks < 512*1024) /* 2 GB */
368
0
    return (8192);     /* 32 MB */
369
0
  if (num_blocks < 4096*1024) /* 16 GB */
370
0
    return (16384);     /* 64 MB */
371
0
  if (num_blocks < 8192*1024) /* 32 GB */
372
0
    return (32768);     /* 128 MB */
373
0
  if (num_blocks < 16384*1024) /* 64 GB */
374
0
    return (65536);     /* 256 MB */
375
0
  if (num_blocks < 32768*1024) /* 128 GB */
376
0
    return (131072);   /* 512 MB */
377
0
  return 262144;       /* 1 GB */
378
0
}
379
380
errcode_t ext2fs_get_journal_params(struct ext2fs_journal_params *params,
381
    ext2_filsys fs)
382
0
{
383
0
  blk_t total_blks;
384
0
  int ret;
385
386
0
  memset(params, 0, sizeof(*params));
387
0
  if (ext2fs_has_feature_journal_dev(fs->super)) {
388
0
    total_blks = ext2fs_blocks_count(fs->super);
389
0
    if (total_blks < JBD2_MIN_JOURNAL_BLOCKS)
390
0
      return EXT2_ET_JOURNAL_TOO_SMALL;
391
392
0
    if (!ext2fs_has_feature_fast_commit(fs->super)) {
393
0
      params->num_journal_blocks = total_blks;
394
0
      params->num_fc_blocks = 0;
395
0
      return 0;
396
0
    }
397
0
    params->num_journal_blocks = ext2fs_blocks_count(fs->super) *
398
0
        EXT2_JOURNAL_TO_FC_BLKS_RATIO /
399
0
        (EXT2_JOURNAL_TO_FC_BLKS_RATIO + 1);
400
0
    if (JBD2_MIN_JOURNAL_BLOCKS > params->num_journal_blocks)
401
0
      params->num_journal_blocks = JBD2_MIN_JOURNAL_BLOCKS;
402
0
    params->num_fc_blocks = total_blks - params->num_journal_blocks;
403
0
    return 0;
404
0
  }
405
406
0
  ret = ext2fs_default_journal_size(ext2fs_blocks_count(fs->super));
407
0
  if (ret < 0)
408
0
    return EXT2_ET_JOURNAL_TOO_SMALL;
409
410
0
  params->num_journal_blocks = ret;
411
0
  if (ext2fs_has_feature_fast_commit(fs->super))
412
0
    params->num_fc_blocks = params->num_journal_blocks /
413
0
      EXT2_JOURNAL_TO_FC_BLKS_RATIO;
414
0
  return 0;
415
0
}
416
417
int ext2fs_journal_sb_start(int blocksize)
418
0
{
419
0
  if (blocksize == EXT2_MIN_BLOCK_SIZE)
420
0
    return 2;
421
0
  return 1;
422
0
}
423
424
/*
425
 * This function adds a journal device to a filesystem
426
 */
427
errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
428
0
{
429
0
  struct stat st;
430
0
  errcode_t retval;
431
0
  char    buf[SUPERBLOCK_SIZE];
432
0
  journal_superblock_t  *jsb;
433
0
  int   start;
434
0
  __u32   i, nr_users;
435
436
  /* Make sure the device exists and is a block device */
437
0
  if (stat(journal_dev->device_name, &st) < 0)
438
0
    return errno;
439
440
0
  if (!S_ISBLK(st.st_mode))
441
0
    return EXT2_ET_JOURNAL_NOT_BLOCK; /* Must be a block device */
442
443
  /* Get the journal superblock */
444
0
  start = ext2fs_journal_sb_start(journal_dev->blocksize);
445
0
  if ((retval = io_channel_read_blk64(journal_dev->io, start,
446
0
              -SUPERBLOCK_SIZE,
447
0
              buf)))
448
0
    return retval;
449
450
0
  jsb = (journal_superblock_t *) buf;
451
0
  if ((jsb->s_header.h_magic != (unsigned) ntohl(JBD2_MAGIC_NUMBER)) ||
452
0
      (jsb->s_header.h_blocktype != (unsigned) ntohl(JBD2_SUPERBLOCK_V2)))
453
0
    return EXT2_ET_NO_JOURNAL_SB;
454
455
0
  if (ntohl(jsb->s_blocksize) != (unsigned long) fs->blocksize)
456
0
    return EXT2_ET_UNEXPECTED_BLOCK_SIZE;
457
458
  /* Check and see if this filesystem has already been added */
459
0
  nr_users = ntohl(jsb->s_nr_users);
460
0
  if (nr_users > JBD2_USERS_MAX)
461
0
    return EXT2_ET_CORRUPT_JOURNAL_SB;
462
0
  for (i=0; i < nr_users; i++) {
463
0
    if (memcmp(fs->super->s_uuid,
464
0
         &jsb->s_users[i*16], 16) == 0)
465
0
      break;
466
0
  }
467
0
  if (i >= nr_users) {
468
0
    memcpy(&jsb->s_users[nr_users*16],
469
0
           fs->super->s_uuid, 16);
470
0
    jsb->s_nr_users = htonl(nr_users+1);
471
0
  }
472
473
  /* Writeback the journal superblock */
474
0
  if ((retval = io_channel_write_blk64(journal_dev->io, start,
475
0
              -SUPERBLOCK_SIZE, buf)))
476
0
    return retval;
477
478
0
  fs->super->s_journal_inum = 0;
479
0
  fs->super->s_journal_dev = st.st_rdev;
480
0
  memcpy(fs->super->s_journal_uuid, jsb->s_uuid,
481
0
         sizeof(fs->super->s_journal_uuid));
482
0
  memset(fs->super->s_jnl_blocks, 0, sizeof(fs->super->s_jnl_blocks));
483
0
  ext2fs_set_feature_journal(fs->super);
484
0
  ext2fs_mark_super_dirty(fs);
485
0
  return 0;
486
0
}
487
488
/*
489
 * This function adds a journal inode to a filesystem, using either
490
 * POSIX routines if the filesystem is mounted, or using direct I/O
491
 * functions if it is not.
492
 */
493
errcode_t ext2fs_add_journal_inode3(ext2_filsys fs, struct ext2fs_journal_params *jparams,
494
            blk64_t goal, int flags)
495
0
{
496
0
  errcode_t   retval;
497
0
  ext2_ino_t    journal_ino;
498
0
  struct stat   st;
499
0
  char      jfile[1024];
500
0
  int     mount_flags;
501
0
  int     fd = -1;
502
503
0
  if (flags & EXT2_MKJOURNAL_NO_MNT_CHECK)
504
0
    mount_flags = 0;
505
0
  else if ((retval = ext2fs_check_mount_point(fs->device_name,
506
0
                &mount_flags,
507
0
                jfile, sizeof(jfile)-10)))
508
0
    return retval;
509
510
0
  if (mount_flags & EXT2_MF_MOUNTED) {
511
0
#if HAVE_EXT2_IOCTLS
512
0
    int f = 0;
513
0
#endif
514
0
    strcat(jfile, "/.journal");
515
516
    /*
517
     * If .../.journal already exists, make sure any
518
     * immutable or append-only flags are cleared.
519
     */
520
#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP)
521
    (void) chflags (jfile, 0);
522
#else
523
0
#if HAVE_EXT2_IOCTLS
524
0
    fd = open(jfile, O_RDONLY);
525
0
    if (fd >= 0) {
526
0
      retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f);
527
0
      close(fd);
528
0
      if (retval)
529
0
        return errno;
530
0
    }
531
0
#endif
532
0
#endif
533
534
    /* Create the journal file */
535
0
    if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0)
536
0
      return errno;
537
538
    /* Note that we can't do lazy journal initialization for mounted
539
     * filesystems, since the zero writing is also allocating the
540
     * journal blocks.  We could use fallocate, but not all kernels
541
     * support that, and creating a journal on a mounted ext2
542
     * filesystems is extremely rare these days...  Ignore it. */
543
0
    flags &= ~EXT2_MKJOURNAL_LAZYINIT;
544
545
0
    if ((retval = write_journal_file(fs, jfile, jparams, flags)))
546
0
      goto errout;
547
548
    /* Get inode number of the journal file */
549
0
    if (fstat(fd, &st) < 0) {
550
0
      retval = errno;
551
0
      goto errout;
552
0
    }
553
554
#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP)
555
    retval = fchflags (fd, UF_NODUMP|UF_IMMUTABLE);
556
#else
557
0
#if HAVE_EXT2_IOCTLS
558
0
    if (ioctl(fd, EXT2_IOC_GETFLAGS, &f) < 0) {
559
0
      retval = errno;
560
0
      goto errout;
561
0
    }
562
0
    f |= EXT2_NODUMP_FL | EXT2_IMMUTABLE_FL;
563
0
    retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f);
564
0
#endif
565
0
#endif
566
0
    if (retval) {
567
0
      retval = errno;
568
0
      goto errout;
569
0
    }
570
571
0
    if (close(fd) < 0) {
572
0
      retval = errno;
573
0
      fd = -1;
574
0
      goto errout;
575
0
    }
576
0
    journal_ino = st.st_ino;
577
0
    memset(fs->super->s_jnl_blocks, 0,
578
0
           sizeof(fs->super->s_jnl_blocks));
579
0
  } else {
580
0
    if ((mount_flags & EXT2_MF_BUSY) &&
581
0
        !(fs->flags & EXT2_FLAG_EXCLUSIVE)) {
582
0
      retval = EBUSY;
583
0
      goto errout;
584
0
    }
585
0
    journal_ino = EXT2_JOURNAL_INO;
586
0
    if ((retval = write_journal_inode(fs, journal_ino,
587
0
              jparams, goal, flags)))
588
0
      return retval;
589
0
  }
590
591
0
  fs->super->s_journal_inum = journal_ino;
592
0
  fs->super->s_journal_dev = 0;
593
0
  memset(fs->super->s_journal_uuid, 0,
594
0
         sizeof(fs->super->s_journal_uuid));
595
0
  ext2fs_set_feature_journal(fs->super);
596
597
0
  ext2fs_mark_super_dirty(fs);
598
0
  return 0;
599
0
errout:
600
0
  if (fd >= 0)
601
0
    close(fd);
602
0
  return retval;
603
0
}
604
605
errcode_t ext2fs_add_journal_inode2(ext2_filsys fs, blk_t num_blocks,
606
            blk64_t goal, int flags)
607
0
{
608
0
  struct ext2fs_journal_params jparams;
609
610
0
  jparams.num_journal_blocks = num_blocks;
611
0
  jparams.num_fc_blocks = 0;
612
613
0
  return ext2fs_add_journal_inode3(fs, &jparams, goal, flags);
614
0
}
615
616
errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t num_blocks, int flags)
617
0
{
618
0
  return ext2fs_add_journal_inode2(fs, num_blocks, ~0ULL, flags);
619
0
}
620
621
622
#ifdef DEBUG
623
main(int argc, char **argv)
624
{
625
  errcode_t retval;
626
  char    *device_name;
627
  ext2_filsys fs;
628
629
  if (argc < 2) {
630
    fprintf(stderr, "Usage: %s filesystem\n", argv[0]);
631
    exit(1);
632
  }
633
  device_name = argv[1];
634
635
  retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0,
636
            unix_io_manager, &fs);
637
  if (retval) {
638
    com_err(argv[0], retval, "while opening %s", device_name);
639
    exit(1);
640
  }
641
642
  retval = ext2fs_add_journal_inode(fs, JBD2_MIN_JOURNAL_BLOCKS, 0);
643
  if (retval) {
644
    com_err(argv[0], retval, "while adding journal to %s",
645
      device_name);
646
    exit(1);
647
  }
648
  retval = ext2fs_flush(fs);
649
  if (retval) {
650
    printf("Warning, had trouble writing out superblocks.\n");
651
  }
652
  ext2fs_close_free(&fs);
653
  exit(0);
654
655
}
656
#endif