119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * mkjournal.c --- make a journal for a filesystem 319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright (C) 2000 Theodore Ts'o. 53984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %Begin-Header% 78558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * This file may be redistributed under the terms of the GNU Library 88558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * General Public License, version 2. 919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %End-Header% 1019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdio.h> 1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <string.h> 1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_UNISTD_H 1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <unistd.h> 1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_ERRNO_H 1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <errno.h> 1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <fcntl.h> 2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <time.h> 2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_SYS_STAT_H 2319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/stat.h> 2419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 2519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_SYS_TYPES_H 2619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/types.h> 2719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_SYS_IOCTL_H 2919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/ioctl.h> 3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_NETINET_IN_H 3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <netinet/in.h> 3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 3419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 3519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2_fs.h" 3619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "e2p/e2p.h" 3719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2fs.h" 3819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "jfs_user.h" 3919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 4019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 4119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function automatically sets up the journal superblock and 4219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * returns it as an allocated block. 4319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 4419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_create_journal_superblock(ext2_filsys fs, 4519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project __u32 size, int flags, 4619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char **ret_jsb) 4719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 4819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 4919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project journal_superblock_t *jsb; 5019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 5119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (size < 1024) 5219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return EXT2_ET_JOURNAL_TOO_SMALL; 5319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 5419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((retval = ext2fs_get_mem(fs->blocksize, &jsb))) 5519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 5619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 5719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memset (jsb, 0, fs->blocksize); 5819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 5919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER); 6019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (flags & EXT2_MKJOURNAL_V1_SUPER) 6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V1); 6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project else 6319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2); 6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project jsb->s_blocksize = htonl(fs->blocksize); 6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project jsb->s_maxlen = htonl(size); 6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project jsb->s_nr_users = htonl(1); 6719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project jsb->s_first = htonl(1); 6819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project jsb->s_sequence = htonl(1); 6919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memcpy(jsb->s_uuid, fs->super->s_uuid, sizeof(fs->super->s_uuid)); 7019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 7119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * If we're creating an external journal device, we need to 7219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * adjust these fields. 7319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 7419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->super->s_feature_incompat & 7519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { 7619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project jsb->s_nr_users = 0; 7719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->blocksize == 1024) 7819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project jsb->s_first = htonl(3); 7919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project else 8019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project jsb->s_first = htonl(2); 8119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 8219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 8319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *ret_jsb = (char *) jsb; 8419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function writes a journal using POSIX routines. It is used 8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * for creating external journals and creating journals on live 9019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * filesystems. 9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic errcode_t write_journal_file(ext2_filsys fs, char *filename, 9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t size, int flags) 9419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *buf = 0; 9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int fd, ret_size; 9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t i; 9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf))) 10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* Open the device or journal file */ 10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((fd = open(filename, O_WRONLY)) < 0) { 10519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = errno; 10619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* Write the superblock out */ 11019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = EXT2_ET_SHORT_WRITE; 11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ret_size = write(fd, buf, fs->blocksize); 11219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ret_size < 0) { 11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = errno; 11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 11519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 11619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ret_size != (int) fs->blocksize) 11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 11819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memset(buf, 0, fs->blocksize); 11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project for (i = 1; i < size; i++) { 12119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ret_size = write(fd, buf, fs->blocksize); 12219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ret_size < 0) { 12319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = errno; 12419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 12519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 12619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ret_size != (int) fs->blocksize) 12719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 12819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 12919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project close(fd); 13019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 13119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = 0; 13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrout: 13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free_mem(&buf); 13419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 13619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 13719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 1383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Convenience function which zeros out _num_ blocks starting at 1393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * _blk_. In case of an error, the details of the error is returned 1403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * via _ret_blk_ and _ret_count_ if they are non-NULL pointers. 1413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Returns 0 on success, and an error code on an error. 1423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 1433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * As a special case, if the first argument is NULL, then it will 1443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * attempt to free the static zeroizing buffer. (This is to keep 1453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * programs that check for memory leaks happy.) 1463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 1473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define STRIDE_LENGTH 8 1483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidterrcode_t ext2fs_zero_blocks(ext2_filsys fs, blk_t blk, int num, 1493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt blk_t *ret_blk, int *ret_count) 1503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{ 1513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int j, count; 1523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt static char *buf; 1533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt errcode_t retval; 1543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* If fs is null, clean up the static buffer and return */ 1563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!fs) { 1573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (buf) { 1583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt free(buf); 1593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt buf = 0; 1603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 1613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return 0; 1623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 1633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* Allocate the zeroizing buffer if necessary */ 1643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!buf) { 1653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt buf = malloc(fs->blocksize * STRIDE_LENGTH); 1663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!buf) 1673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return ENOMEM; 1683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt memset(buf, 0, fs->blocksize * STRIDE_LENGTH); 1693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 1703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* OK, do the write loop */ 1713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt j=0; 1723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt while (j < num) { 1733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (blk % STRIDE_LENGTH) { 1743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt count = STRIDE_LENGTH - (blk % STRIDE_LENGTH); 1753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (count > (num - j)) 1763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt count = num - j; 1773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } else { 1783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt count = num - j; 1793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (count > STRIDE_LENGTH) 1803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt count = STRIDE_LENGTH; 1813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 1823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = io_channel_write_blk(fs->io, blk, count, buf); 1833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval) { 1843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (ret_count) 1853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *ret_count = count; 1863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (ret_blk) 1873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *ret_blk = blk; 1883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 1893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 1903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt j += count; blk += count; 1913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 1923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return 0; 1933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt} 1943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/* 19619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Helper function for creating the journal using direct I/O routines 19719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 19819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstruct mkjournal_struct { 19919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int num_blocks; 20019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int newblocks; 2013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt blk_t goal; 2023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt blk_t blk_to_zero; 2033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt int zero_count; 20419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *buf; 20519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t err; 20619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}; 20719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 20819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int mkjournal_proc(ext2_filsys fs, 20919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t *blocknr, 21019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2_blkcnt_t blockcnt, 21119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t ref_block EXT2FS_ATTR((unused)), 21219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int ref_offset EXT2FS_ATTR((unused)), 21319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project void *priv_data) 21419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 21519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct mkjournal_struct *es = (struct mkjournal_struct *) priv_data; 21619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t new_blk; 21719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 2183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 21919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (*blocknr) { 2203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt es->goal = *blocknr; 22119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 22219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 2233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = ext2fs_new_block(fs, es->goal, 0, &new_blk); 22419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 22519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es->err = retval; 22619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return BLOCK_ABORT; 22719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 2283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (blockcnt >= 0) 22919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es->num_blocks--; 23019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 23119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es->newblocks++; 2323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = 0; 2333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (blockcnt <= 0) 2343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = io_channel_write_blk(fs->io, new_blk, 1, es->buf); 2353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt else { 2363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (es->zero_count) { 2373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if ((es->blk_to_zero + es->zero_count == new_blk) && 2383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (es->zero_count < 1024)) 2393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt es->zero_count++; 2403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt else { 2413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = ext2fs_zero_blocks(fs, 2423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt es->blk_to_zero, 2433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt es->zero_count, 2443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 0, 0); 2453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt es->zero_count = 0; 2463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 2473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 2483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (es->zero_count == 0) { 2493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt es->blk_to_zero = new_blk; 2503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt es->zero_count = 1; 2513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 2523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 25319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 25419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (blockcnt == 0) 25519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memset(es->buf, 0, fs->blocksize); 25619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 25719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 25819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es->err = retval; 25919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return BLOCK_ABORT; 26019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 2613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *blocknr = es->goal = new_blk; 26219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_block_alloc_stats(fs, new_blk, +1); 26319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 26419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (es->num_blocks == 0) 26519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return (BLOCK_CHANGED | BLOCK_ABORT); 26619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project else 26719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return BLOCK_CHANGED; 2683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 26919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 27019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 27119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 27219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function creates a journal using direct I/O routines. 27319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 27419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino, 27519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t size, int flags) 27619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 27719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *buf; 2783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt dgrp_t group, start, end, i, log_flex; 27919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 28019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode inode; 28119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct mkjournal_struct es; 28219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 28319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf))) 28419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 2853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 28619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((retval = ext2fs_read_bitmaps(fs))) 28719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 28819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 28919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) 29019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 29119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 29219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (inode.i_blocks > 0) 29319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return EEXIST; 29419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 29519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es.num_blocks = size; 29619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es.newblocks = 0; 29719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es.buf = buf; 29819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es.err = 0; 2993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt es.zero_count = 0; 3003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) { 3023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt inode.i_flags |= EXT4_EXTENTS_FL; 3033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if ((retval = ext2fs_write_inode(fs, journal_ino, &inode))) 3043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return retval; 3053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 3063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* 3083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * Set the initial goal block to be roughly at the middle of 3093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * the filesystem. Pick a group that has the largest number 3103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * of free blocks. 3113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */ 3123984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt group = ext2fs_group_of_blk(fs, (fs->super->s_blocks_count - 3133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fs->super->s_first_data_block) / 2); 3143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt log_flex = 1 << fs->super->s_log_groups_per_flex; 3153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fs->super->s_log_groups_per_flex && (group > log_flex)) { 3163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt group = group & ~(log_flex - 1); 3173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt while ((group < fs->group_desc_count) && 3183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fs->group_desc[group].bg_free_blocks_count == 0) 3193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt group++; 3203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (group == fs->group_desc_count) 3213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt group = 0; 3223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt start = group; 3233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } else 3243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt start = (group > 0) ? group-1 : group; 3253984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt end = ((group+1) < fs->group_desc_count) ? group+1 : group; 3263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt group = start; 3273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt for (i=start+1; i <= end; i++) 3283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fs->group_desc[i].bg_free_blocks_count > 3293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fs->group_desc[group].bg_free_blocks_count) 3303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt group = i; 3313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 3323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt es.goal = (fs->super->s_blocks_per_group * group) + 3333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fs->super->s_first_data_block; 33419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 33519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_block_iterate2(fs, journal_ino, BLOCK_FLAG_APPEND, 33619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 0, mkjournal_proc, &es); 33719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (es.err) { 33819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = es.err; 33919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 34019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 3413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (es.zero_count) { 3423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = ext2fs_zero_blocks(fs, es.blk_to_zero, 3433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt es.zero_count, 0, 0); 3443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval) 3453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt goto errout; 3463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 34719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 34819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) 34919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 35019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 35119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_size += fs->blocksize * size; 3523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_iblk_add_blocks(fs, &inode, es.newblocks); 35319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_mtime = inode.i_ctime = fs->now ? fs->now : time(0); 35419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_links_count = 1; 35519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_mode = LINUX_S_IFREG | 0600; 35619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 3573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if ((retval = ext2fs_write_new_inode(fs, journal_ino, &inode))) 35819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 35919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = 0; 36019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 36119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4); 36219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_jnl_blocks[16] = inode.i_size; 36319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; 36419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_mark_super_dirty(fs); 36519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 36619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrout: 36719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free_mem(&buf); 36819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 36919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 37019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 37119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 37219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Find a reasonable journal file size (in blocks) given the number of blocks 37319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * in the filesystem. For very small filesystems, it is not reasonable to 37419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * have a journal that fills more than half of the filesystem. 37519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 37619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectint ext2fs_default_journal_size(__u64 blocks) 37719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 37819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (blocks < 2048) 37919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return -1; 38019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (blocks < 32768) 38119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return (1024); 38219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (blocks < 256*1024) 38319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return (4096); 38419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (blocks < 512*1024) 38519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return (8192); 38619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (blocks < 1024*1024) 38719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return (16384); 38819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 32768; 38919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 39019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 39119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 39219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function adds a journal device to a filesystem 39319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 39419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev) 39519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 39619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct stat st; 39719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 39819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char buf[1024]; 39919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project journal_superblock_t *jsb; 40019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int start; 40119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project __u32 i, nr_users; 40219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 40319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* Make sure the device exists and is a block device */ 40419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (stat(journal_dev->device_name, &st) < 0) 40519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return errno; 4063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 40719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!S_ISBLK(st.st_mode)) 40819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return EXT2_ET_JOURNAL_NOT_BLOCK; /* Must be a block device */ 40919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 41019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* Get the journal superblock */ 41119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project start = 1; 41219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (journal_dev->blocksize == 1024) 41319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project start++; 41419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((retval = io_channel_read_blk(journal_dev->io, start, -1024, buf))) 41519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 41619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 41719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project jsb = (journal_superblock_t *) buf; 41819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) || 41919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) 42019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return EXT2_ET_NO_JOURNAL_SB; 42119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 42219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ntohl(jsb->s_blocksize) != (unsigned long) fs->blocksize) 42319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return EXT2_ET_UNEXPECTED_BLOCK_SIZE; 42419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 42519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* Check and see if this filesystem has already been added */ 42619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project nr_users = ntohl(jsb->s_nr_users); 42719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project for (i=0; i < nr_users; i++) { 42819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (memcmp(fs->super->s_uuid, 42919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project &jsb->s_users[i*16], 16) == 0) 43019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project break; 43119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 43219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (i >= nr_users) { 43319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memcpy(&jsb->s_users[nr_users*16], 43419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_uuid, 16); 43519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project jsb->s_nr_users = htonl(nr_users+1); 43619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 43719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 43819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* Writeback the journal superblock */ 43919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((retval = io_channel_write_blk(journal_dev->io, start, -1024, buf))) 44019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 4413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 44219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_journal_inum = 0; 44319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_journal_dev = st.st_rdev; 44419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memcpy(fs->super->s_journal_uuid, jsb->s_uuid, 44519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project sizeof(fs->super->s_journal_uuid)); 44619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; 44719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_mark_super_dirty(fs); 44819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 44919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 45019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 45119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 45219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function adds a journal inode to a filesystem, using either 45319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * POSIX routines if the filesystem is mounted, or using direct I/O 45419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * functions if it is not. 45519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 45619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, int flags) 45719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 45819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 45919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_ino_t journal_ino; 46019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct stat st; 46119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char jfile[1024]; 46219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int mount_flags, f; 46319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int fd = -1; 46419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 46519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((retval = ext2fs_check_mount_point(fs->device_name, &mount_flags, 46619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project jfile, sizeof(jfile)-10))) 46719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 46819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 46919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (mount_flags & EXT2_MF_MOUNTED) { 47019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project strcat(jfile, "/.journal"); 47119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 47219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 4733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * If .../.journal already exists, make sure any 47419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * immutable or append-only flags are cleared. 47519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 47619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP) 47719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (void) chflags (jfile, 0); 47819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#else 47919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_EXT2_IOCTLS 48019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fd = open(jfile, O_RDONLY); 48119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fd >= 0) { 48219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project f = 0; 48319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ioctl(fd, EXT2_IOC_SETFLAGS, &f); 48419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project close(fd); 48519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 48619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 48719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 48819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 48919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* Create the journal file */ 49019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0) 49119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return errno; 49219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 49319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((retval = write_journal_file(fs, jfile, size, flags))) 49419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 4953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 49619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* Get inode number of the journal file */ 4973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (fstat(fd, &st) < 0) { 4983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = errno; 49919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 5003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 50119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 50219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP) 50319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = fchflags (fd, UF_NODUMP|UF_IMMUTABLE); 50419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#else 50519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_EXT2_IOCTLS 5063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (ioctl(fd, EXT2_IOC_GETFLAGS, &f) < 0) { 5073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = errno; 5083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt goto errout; 5093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 5103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt f |= EXT2_NODUMP_FL | EXT2_IMMUTABLE_FL; 51119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f); 51219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 51319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 5143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (retval) { 5153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = errno; 51619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 5173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 5183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 5193984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (close(fd) < 0) { 5203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = errno; 5213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fd = -1; 5223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt goto errout; 5233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 52419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project journal_ino = st.st_ino; 52519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } else { 52619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((mount_flags & EXT2_MF_BUSY) && 52719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project !(fs->flags & EXT2_FLAG_EXCLUSIVE)) { 52819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = EBUSY; 52919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 53019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 53119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project journal_ino = EXT2_JOURNAL_INO; 53219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((retval = write_journal_inode(fs, journal_ino, 53319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project size, flags))) 53419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 53519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 5363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 53719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_journal_inum = journal_ino; 53819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_journal_dev = 0; 53919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memset(fs->super->s_journal_uuid, 0, 54019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project sizeof(fs->super->s_journal_uuid)); 54119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; 54219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 54319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_mark_super_dirty(fs); 54419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 54519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrout: 54619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fd > 0) 54719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project close(fd); 54819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 54919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 55019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 55119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef DEBUG 55219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectmain(int argc, char **argv) 55319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 55419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 55519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *device_name; 55619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_filsys fs; 55719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 55819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (argc < 2) { 55919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fprintf(stderr, "Usage: %s filesystem\n", argv[0]); 56019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project exit(1); 56119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 56219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project device_name = argv[1]; 5633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 56419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0, 56519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project unix_io_manager, &fs); 56619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 56719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(argv[0], retval, "while opening %s", device_name); 56819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project exit(1); 56919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 57019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 57119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_add_journal_inode(fs, 1024); 57219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 57319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project com_err(argv[0], retval, "while adding journal to %s", 57419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project device_name); 57519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project exit(1); 57619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 57719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_flush(fs); 57819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 57919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project printf("Warning, had trouble writing out superblocks.\n"); 58019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 58119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_close(fs); 58219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project exit(0); 5833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 58419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 58519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 586