mkjournal.c revision 89a6ebd524891f332aad8ca0281935159ddc1217
1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * mkjournal.c --- make a journal for a filesystem 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Copyright (C) 2000 Theodore Ts'o. 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * %Begin-Header% 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This file may be redistributed under the terms of the GNU Public 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * License. 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * %End-Header% 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h> 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <string.h> 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if HAVE_UNISTD_H 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <unistd.h> 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if HAVE_ERRNO_H 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <errno.h> 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <fcntl.h> 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <time.h> 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if HAVE_SYS_STAT_H 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/stat.h> 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if HAVE_SYS_TYPES_H 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/types.h> 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if HAVE_SYS_IOCTL_H 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/ioctl.h> 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if HAVE_NETINET_IN_H 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <netinet/in.h> 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "ext2_fs.h" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "e2p/e2p.h" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "ext2fs.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "jfs_user.h" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This function automatically sets up the journal superblock and 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * returns it as an allocated block. 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownerrcode_t ext2fs_create_journal_superblock(ext2_filsys fs, 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown __u32 size, int flags, 46436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov char **ret_jsb) 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown errcode_t retval; 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown journal_superblock_t *jsb; 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (size < 1024) 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return EXT2_ET_JOURNAL_TOO_SMALL; 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((retval = ext2fs_get_mem(fs->blocksize, (void **) &jsb))) 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return retval; 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown memset (jsb, 0, fs->blocksize); 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER); 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (flags & EXT2_MKJOURNAL_V1_SUPER) 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V1); 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2); 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jsb->s_blocksize = htonl(fs->blocksize); 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jsb->s_maxlen = htonl(size); 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jsb->s_nr_users = htonl(1); 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jsb->s_first = htonl(1); 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jsb->s_sequence = htonl(1); 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown memcpy(jsb->s_uuid, fs->super->s_uuid, sizeof(fs->super->s_uuid)); 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * If we're creating an external journal device, we need to 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * adjust these fields. 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fs->super->s_feature_incompat & 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jsb->s_nr_users = 0; 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fs->blocksize == 1024) 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jsb->s_first = htonl(3); 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jsb->s_first = htonl(2); 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *ret_jsb = (char *) jsb; 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This function writes a journal using POSIX routines. It is used 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * for creating external journals and creating journals on live 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * filesystems. 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic errcode_t write_journal_file(ext2_filsys fs, char *filename, 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown blk_t size, int flags) 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown errcode_t retval; 96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char *buf = 0; 97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int i, fd, ret_size; 98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf))) 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return retval; 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Open the device or journal file */ 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((fd = open(filename, O_WRONLY)) < 0) { 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown retval = errno; 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto errout; 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Write the superblock out */ 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown retval = EXT2_ET_SHORT_WRITE; 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret_size = write(fd, buf, fs->blocksize); 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret_size < 0) { 112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng retval = errno; 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto errout; 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret_size != fs->blocksize) 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto errout; 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown memset(buf, 0, fs->blocksize); 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 1; i < size; i++) { 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ret_size = write(fd, buf, fs->blocksize); 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret_size < 0) { 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown retval = errno; 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto errout; 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ret_size != fs->blocksize) 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto errout; 127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng close(fd); 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown retval = 0; 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownerrout: 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ext2fs_free_mem((void **) &buf); 133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return retval; 134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* 137436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * Helper function for creating the journal using direct I/O routines 138436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov */ 139436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstruct mkjournal_struct { 140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov int num_blocks; 141436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov int newblocks; 142436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov char *buf; 143436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov errcode_t err; 144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}; 145436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic int mkjournal_proc(ext2_filsys fs, 147436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov blk_t *blocknr, 148436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov e2_blkcnt_t blockcnt, 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown blk_t ref_block, 150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov int ref_offset, 151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov void *priv_data) 152436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{ 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct mkjournal_struct *es = (struct mkjournal_struct *) priv_data; 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown blk_t new_blk; 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static blk_t last_blk = 0; 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown errcode_t retval; 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int group; 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 159436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (*blocknr) { 160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov last_blk = *blocknr; 161436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return 0; 162436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown retval = ext2fs_new_block(fs, last_blk, 0, &new_blk); 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (retval) { 165436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov es->err = retval; 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return BLOCK_ABORT; 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (blockcnt > 0) 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown es->num_blocks--; 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown es->newblocks++; 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown retval = io_channel_write_blk(fs->io, new_blk, 1, es->buf); 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (blockcnt == 0) 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown memset(es->buf, 0, fs->blocksize); 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (retval) { 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown es->err = retval; 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return BLOCK_ABORT; 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *blocknr = new_blk; 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown last_blk = new_blk; 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ext2fs_mark_block_bitmap(fs->block_map, new_blk); 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ext2fs_mark_bb_dirty(fs); 185436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov group = ext2fs_group_of_blk(fs, new_blk); 186436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fs->group_desc[group].bg_free_blocks_count--; 187436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fs->super->s_free_blocks_count--; 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ext2fs_mark_super_dirty(fs); 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 190436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (es->num_blocks == 0) 191436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return (BLOCK_CHANGED | BLOCK_ABORT); 192436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov else 193436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return BLOCK_CHANGED; 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This function creates a journal using direct I/O routines. 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino, 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown blk_t size, int flags) 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char *buf; 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown errcode_t retval; 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct ext2_inode inode; 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct mkjournal_struct es; 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf))) 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return retval; 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((retval = ext2fs_read_bitmaps(fs))) 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return retval; 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return retval; 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (inode.i_blocks > 0) 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return EEXIST; 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown es.num_blocks = size; 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown es.newblocks = 0; 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown es.buf = buf; 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown es.err = 0; 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown retval = ext2fs_block_iterate2(fs, journal_ino, BLOCK_FLAG_APPEND, 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 0, mkjournal_proc, &es); 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (es.err) { 228436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov retval = es.err; 229436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto errout; 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 232436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto errout; 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 235436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov inode.i_size += fs->blocksize * size; 236436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov inode.i_blocks += (fs->blocksize / 512) * es.newblocks; 237436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov inode.i_mtime = inode.i_ctime = time(0); 238436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov inode.i_links_count = 1; 239436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov inode.i_mode = LINUX_S_IFREG | 0600; 240436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((retval = ext2fs_write_inode(fs, journal_ino, &inode))) 242436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov goto errout; 243436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov retval = 0; 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownerrout: 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ext2fs_free_mem((void **) &buf); 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return retval; 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This function adds a journal device to a filesystem 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownerrcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev) 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 255436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov struct stat st; 256436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov errcode_t retval; 257436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov char buf[1024]; 258436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov journal_superblock_t *jsb; 259436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov int i, start; 260436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov __u32 nr_users; 261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Make sure the device exists and is a block device */ 263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (stat(journal_dev->device_name, &st) < 0) 264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return errno; 265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (!S_ISBLK(st.st_mode)) 267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng return EXT2_ET_JOURNAL_NOT_BLOCK; /* Must be a block device */ 268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Get the journal superblock */ 270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng start = 1; 271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (journal_dev->blocksize == 1024) 272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng start++; 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((retval = io_channel_read_blk(journal_dev->io, start, -1024, buf))) 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return retval; 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jsb = (journal_superblock_t *) buf; 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) || 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return EXT2_ET_NO_JOURNAL_SB; 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (ntohl(jsb->s_blocksize) != fs->blocksize) 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return EXT2_ET_UNEXPECTED_BLOCK_SIZE; 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Check and see if this filesystem has already been added */ 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nr_users = ntohl(jsb->s_nr_users); 286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (i=0; i < nr_users; i++) { 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (memcmp(fs->super->s_uuid, 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown &jsb->s_users[i*16], 16) == 0) 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown break; 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (i >= nr_users) { 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown memcpy(&jsb->s_users[nr_users*16], 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fs->super->s_uuid, 16); 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jsb->s_nr_users = htonl(nr_users+1); 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Writeback the journal superblock */ 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((retval = io_channel_write_blk(journal_dev->io, start, -1024, buf))) 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return retval; 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fs->super->s_journal_inum = 0; 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fs->super->s_journal_dev = st.st_rdev; 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown memcpy(fs->super->s_journal_uuid, jsb->s_uuid, 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(fs->super->s_journal_uuid)); 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ext2fs_mark_super_dirty(fs); 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This function adds a journal inode to a filesystem, using either 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * POSIX routines if the filesystem is mounted, or using direct I/O 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * functions if it is not. 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownerrcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, int flags) 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown errcode_t retval; 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ext2_ino_t journal_ino; 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct stat st; 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char jfile[1024]; 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int fd, mount_flags, f; 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((retval = ext2fs_check_mount_point(fs->device_name, &mount_flags, 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jfile, sizeof(jfile)-10))) 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return retval; 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mount_flags & EXT2_MF_MOUNTED) { 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown strcat(jfile, "/.journal"); 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Create the journal file */ 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0) 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return errno; 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((retval = write_journal_file(fs, jfile, size, flags))) 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto errout; 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get inode number of the journal file */ 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (fstat(fd, &st) < 0) 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto errout; 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP) 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown retval = fchflags (fd, UF_NODUMP|UF_IMMUTABLE); 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if HAVE_EXT2_IOCTLS 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown f = EXT2_NODUMP_FL | EXT2_IMMUTABLE_FL;; 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f); 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (retval) 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown goto errout; 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown close(fd); 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown journal_ino = st.st_ino; 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown journal_ino = EXT2_JOURNAL_INO; 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((retval = write_journal_inode(fs, journal_ino, 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown size, flags))) 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return retval; 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fs->super->s_journal_inum = journal_ino; 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fs->super->s_journal_dev = 0; 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown memset(fs->super->s_journal_uuid, 0, 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sizeof(fs->super->s_journal_uuid)); 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ext2fs_mark_super_dirty(fs); 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownerrout: 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown close(fd); 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return retval; 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef DEBUG 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmain(int argc, char **argv) 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown errcode_t retval; 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown char *device_name; 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ext2_filsys fs; 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (argc < 2) { 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown fprintf(stderr, "Usage: %s filesystem\n", argv[0]); 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exit(1); 384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown device_name = argv[1]; 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0, 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown unix_io_manager, &fs); 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (retval) { 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown com_err(argv[0], retval, "while opening %s", device_name); 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exit(1); 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown retval = ext2fs_add_journal_inode(fs, 1024); 395b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (retval) { 396436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov com_err(argv[0], retval, "while adding journal to %s", 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown device_name); 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown exit(1); 399436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 400436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov retval = ext2fs_flush(fs); 401436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (retval) { 402436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov printf("Warning, had trouble writing out superblocks.\n"); 403436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 404436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ext2fs_close(fs); 405436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov exit(0); 406b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 407b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 408b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#endif 409b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov