mkjournal.c revision 9f8046fc6dfc13eee2f5c363214e60b533872cac
1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch/*
2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * mkjournal.c --- make a journal for a filesystem
3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *
4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Copyright (C) 2000 Theodore Ts'o.
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * %Begin-Header%
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * This file may be redistributed under the terms of the GNU Public
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * License.
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * %End-Header%
103240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch */
113240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <stdio.h>
13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include <string.h>
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if HAVE_UNISTD_H
153240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include <unistd.h>
163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif
173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#if HAVE_ERRNO_H
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <errno.h>
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fcntl.h>
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <time.h>
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if HAVE_SYS_STAT_H
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <sys/stat.h>
24bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#endif
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if HAVE_SYS_TYPES_H
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <sys/types.h>
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if HAVE_NETINET_IN_H
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <netinet/in.h>
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ext2_fs.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "e2p/e2p.h"
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ext2fs.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "jfs_user.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/*
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * This function automatically sets up the journal superblock and
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * returns it as an allocated block.
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)					   __u32 size, int flags,
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)					   char  **ret_jsb)
4458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles){
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	errcode_t		retval;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	journal_superblock_t	*jsb;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (size < 1024)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return EXT2_ET_JOURNAL_TOO_SMALL;
50ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if ((retval = ext2fs_get_mem(fs->blocksize, (void **) &jsb)))
523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)		return retval;
533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
54effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	memset (jsb, 0, fs->blocksize);
5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	if (flags & EXT2_MKJOURNAL_V1_SUPER)
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V1);
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	else
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	jsb->s_blocksize = htonl(fs->blocksize);
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	jsb->s_maxlen = htonl(size);
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	jsb->s_nr_users = htonl(1);
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	jsb->s_first = htonl(1);
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	jsb->s_sequence = htonl(1);
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	memcpy(jsb->s_uuid, fs->super->s_uuid, sizeof(fs->super->s_uuid));
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	/*
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 * If we're creating an external journal device, we need to
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 * adjust these fields.
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	 */
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	if (fs->super->s_feature_incompat &
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		jsb->s_nr_users = 0;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	*ret_jsb = (char *) jsb;
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	return 0;
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/*
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * This function writes a journal using POSIX routines.  It is used
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * for creating external journals and creating journals on live
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * filesystems.
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) */
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)static errcode_t write_journal_file(ext2_filsys fs, char *filename,
8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)				    blk_t size, int flags)
8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles){
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	errcode_t	retval;
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	char		*buf = 0;
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	int		i, fd, ret_size;
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf)))
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		return retval;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	/* Open the device or journal file */
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	if ((fd = open(filename, O_WRONLY)) < 0) {
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		retval = errno;
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		goto errout;
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	}
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	/* Write the superblock out */
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	retval = EXT2_ET_SHORT_WRITE;
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	ret_size = write(fd, buf, fs->blocksize);
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	if (ret_size < 0) {
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		retval = errno;
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		goto errout;
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	}
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	if (ret_size != fs->blocksize)
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)		goto errout;
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	memset(buf, 0, fs->blocksize);
110bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
111bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch	for (i = 1; i < size; i++) {
112bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch		ret_size = write(fd, buf, fs->blocksize);
113bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch		if (ret_size < 0) {
1143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)			retval = errno;
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			goto errout;
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		}
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		if (ret_size != fs->blocksize)
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			goto errout;
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	close(fd);
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	retval = 0;
12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)errout:
12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	ext2fs_free_mem((void **) &buf);
12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)	return retval;
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/*
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Helper function for creating the journal using direct I/O routines
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct mkjournal_struct {
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	int		num_blocks;
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	int		newblocks;
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	char		*buf;
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	errcode_t	err;
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static int mkjournal_proc(ext2_filsys		fs,
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			   blk_t		*blocknr,
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			   e2_blkcnt_t		blockcnt,
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			   blk_t		ref_block,
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			   int			ref_offset,
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			   void			*priv_data)
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles){
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	struct mkjournal_struct *es = (struct mkjournal_struct *) priv_data;
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	blk_t	new_blk;
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	static blk_t	last_blk = 0;
148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	errcode_t	retval;
149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	int		group;
150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	if (*blocknr) {
152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch		last_blk = *blocknr;
153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch		return 0;
154effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	}
155effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	retval = ext2fs_new_block(fs, last_blk, 0, &new_blk);
156effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	if (retval) {
1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		es->err = retval;
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		return BLOCK_ABORT;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (blockcnt > 0)
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		es->num_blocks--;
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	es->newblocks++;
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	retval = io_channel_write_blk(fs->io, new_blk, 1, es->buf);
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (blockcnt == 0)
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		memset(es->buf, 0, fs->blocksize);
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	if (retval) {
1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		es->err = retval;
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		return BLOCK_ABORT;
1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	}
1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	*blocknr = new_blk;
1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	ext2fs_mark_block_bitmap(fs->block_map, new_blk);
1757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	ext2fs_mark_bb_dirty(fs);
1767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	group = ext2fs_group_of_blk(fs, new_blk);
1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	fs->group_desc[group].bg_free_blocks_count--;
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	fs->super->s_free_blocks_count--;
1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	ext2fs_mark_super_dirty(fs);
1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	if (es->num_blocks == 0)
1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		return (BLOCK_CHANGED | BLOCK_ABORT);
1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	else
1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		return BLOCK_CHANGED;
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)/*
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * This function creates a journal using direct I/O routines.
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */
1917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstatic errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				     blk_t size, int flags)
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles){
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	char			*buf;
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	errcode_t		retval;
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	struct ext2_inode	inode;
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	struct mkjournal_struct	es;
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)	if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf)))
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		return retval;
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if ((retval = ext2fs_read_bitmaps(fs)))
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return retval;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return retval;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)	if (inode.i_blocks > 0)
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		return EEXIST;
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
21168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)	es.num_blocks = size;
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	es.newblocks = 0;
21368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)	es.buf = buf;
21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)	es.err = 0;
21568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)	retval = ext2fs_block_iterate2(fs, journal_ino, BLOCK_FLAG_APPEND,
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				       0, mkjournal_proc, &es);
21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)	if (es.err) {
21968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)		retval = es.err;
22068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)		goto errout;
22168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)	}
22268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
22368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)	if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
22468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)		goto errout;
22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
22668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 	inode.i_size += fs->blocksize * size;
22768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)	inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
22868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)	inode.i_mtime = inode.i_ctime = time(0);
22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)	inode.i_links_count = 1;
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)	inode.i_mode = LINUX_S_IFREG | 0600;
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if ((retval = ext2fs_write_inode(fs, journal_ino, &inode)))
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		goto errout;
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	retval = 0;
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)errout:
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	ext2fs_free_mem((void **) &buf);
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	return retval;
239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/*
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * This function adds a journal device to a filesystem
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	struct stat	st;
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	errcode_t	retval;
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	char		buf[1024];
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	journal_superblock_t	*jsb;
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	int		i;
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	__u32		nr_users;
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	/* Make sure the device exists and is a block device */
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (stat(journal_dev->device_name, &st) < 0)
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return errno;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	if (!S_ISBLK(st.st_mode))
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		return EXT2_ET_JOURNAL_NOT_BLOCK; /* Must be a block device */
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	/* Get the journal superblock */
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if ((retval = io_channel_read_blk(journal_dev->io, 1, -1024, buf)))
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		return retval;
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	jsb = (journal_superblock_t *) buf;
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	    (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2)))
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return EXT2_ET_NO_JOURNAL_SB;
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (ntohl(jsb->s_blocksize) != fs->blocksize)
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		return EXT2_ET_UNEXPECTED_BLOCK_SIZE;
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	/* Check and see if this filesystem has already been added */
2737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	nr_users = ntohl(jsb->s_nr_users);
2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	for (i=0; i < nr_users; i++) {
2757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		if (memcmp(fs->super->s_uuid,
2767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			   &jsb->s_users[i*16], 16) == 0)
2777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch			break;
2787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	}
2797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	if (i >= nr_users) {
2807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		memcpy(&jsb->s_users[nr_users*16],
281effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch		       fs->super->s_uuid, 16);
282effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch		jsb->s_nr_users = htonl(nr_users+1);
283effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	}
284effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
285effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	/* Writeback the journal superblock */
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if ((retval = io_channel_write_blk(journal_dev->io, 1, -1024, buf)))
2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		return retval;
2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	fs->super->s_journal_inum = 0;
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	fs->super->s_journal_dev = st.st_rdev;
2917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	memcpy(fs->super->s_journal_uuid, jsb->s_uuid,
2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	       sizeof(fs->super->s_journal_uuid));
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	ext2fs_mark_super_dirty(fs);
2957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch	return 0;
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/*
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * This function adds a journal inode to a filesystem, using either
3007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * POSIX routines if the filesystem is mounted, or using direct I/O
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * functions if it is not.
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, int flags)
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	errcode_t		retval;
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	ext2_ino_t		journal_ino;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	struct stat		st;
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	char			jfile[1024];
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	int			fd, mount_flags;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if ((retval = ext2fs_check_mount_point(fs->device_name, &mount_flags,
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)					       jfile, sizeof(jfile)-10)))
313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		return retval;
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	if (mount_flags & EXT2_MF_MOUNTED) {
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		strcat(jfile, "/.journal");
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		/* Create the journal file */
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0)
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			return errno;
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		close(fd);
322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if ((retval = write_journal_file(fs, jfile, size, flags)))
324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			return retval;
325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		/* Get inode number of the journal file */
327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (stat(jfile, &st) < 0)
328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			return errno;
329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if ((retval = fsetflags(jfile,
331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch					EXT2_NODUMP_FL | EXT2_IMMUTABLE_FL)))
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			return retval;
333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		journal_ino = st.st_ino;
335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	} else {
336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		journal_ino = EXT2_JOURNAL_INO;
337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if ((retval = write_journal_inode(fs, journal_ino,
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)						  size, flags)))
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			return retval;
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
3417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	fs->super->s_journal_inum = journal_ino;
343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	fs->super->s_journal_dev = 0;
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	memset(fs->super->s_journal_uuid, 0,
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	       sizeof(fs->super->s_journal_uuid));
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	ext2fs_mark_super_dirty(fs);
349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	return 0;
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#ifdef DEBUG
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)main(int argc, char **argv)
354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	errcode_t	retval;
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	char		*device_name;
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	ext2_filsys 	fs;
3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	if (argc < 2) {
3607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch		fprintf(stderr, "Usage: %s filesystem\n", argv[0]);
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		exit(1);
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	}
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	device_name = argv[1];
364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0,
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)			      unix_io_manager, &fs);
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (retval) {
368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		com_err(argv[0], retval, "while opening %s", device_name);
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		exit(1);
370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	retval = ext2fs_add_journal_inode(fs, 1024);
373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (retval) {
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		com_err(argv[0], retval, "while adding journal to %s",
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			device_name);
376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)		exit(1);
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	}
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	retval = ext2fs_flush(fs);
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	if (retval) {
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		printf("Warning, had trouble writing out superblocks.\n");
381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	}
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	ext2fs_close(fs);
383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)	exit(0);
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)