Whamcloud - gitweb
ChangeLog, ext2_err.et.in, ext2fs.h, initialize.c, mkjournal.c, openfs.c:
authorTheodore Ts'o <tytso@mit.edu>
Tue, 16 Jan 2001 06:56:14 +0000 (06:56 +0000)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 16 Jan 2001 06:56:14 +0000 (06:56 +0000)
  initialize.c (ext2fs_initialize): Add support for initializing the
   ext2 superblock for external journal devices.  This basically means we
   don't bother to allocate any block group descriptors.
  openfs.c (ext2fs_open): Only open external journal devices if the new
   flag EXT2_FLAG_JOURNAL_DEV_OK is passed to ext2fs_open.  When opening
   such devices, don't try to read the block group descriptors, since
   they're not there.
  ext2_err.et.in (EXT2_NO_JOURNAL_SB): Add new error code
  mkjournal.c: Export a new function,
   ext2fs_create_journal_superblock(), which allocates and returns a
   buffer containing a journal superblock.  This is needed by mke2fs to
   create an external journal.  Rewrote ext2fs_add_journal_device() so
   that it no longer creates the external journal, but rather adds a
   filesystem to an existing external journal.  It handles all of the
   UUID manipulation.
  ext2fs.h: List the EXT3_FEATURE_JOURNAL_DEV as a flag supported by the
   library.  Define the EXT2_FLAG_JOURNAL_DEV_OK.  Changed function
   prototype for ext2fs_add_journal_device().

lib/ext2fs/ChangeLog
lib/ext2fs/ext2_err.et.in
lib/ext2fs/ext2fs.h
lib/ext2fs/initialize.c
lib/ext2fs/mkjournal.c
lib/ext2fs/openfs.c

index 54ef029..0a0c498 100644 (file)
@@ -1,3 +1,30 @@
+2001-01-15  Theodore Ts'o  <tytso@valinux.com>
+
+       * initialize.c (ext2fs_initialize): Add support for initializing
+               the ext2 superblock for external journal devices.  This
+               basically means we don't bother to allocate any block
+               group descriptors.
+
+       * openfs.c (ext2fs_open): Only open external journal devices if
+               the new flag EXT2_FLAG_JOURNAL_DEV_OK is passed to
+               ext2fs_open.  When opening such devices, don't try to read
+               the block group descriptors, since they're not there.
+
+       * ext2_err.et.in (EXT2_NO_JOURNAL_SB): Add new error code 
+       
+       * mkjournal.c: Export a new function,
+               ext2fs_create_journal_superblock(), which allocates and
+               returns a buffer containing a journal superblock.  This is
+               needed by mke2fs to create an external journal.  Rewrote
+               ext2fs_add_journal_device() so that it no longer creates
+               the external journal, but rather adds a filesystem to an
+               existing external journal.  It handles all of the UUID
+               manipulation.
+
+       * ext2fs.h: List the EXT3_FEATURE_JOURNAL_DEV as a flag supported
+               by the library.  Define the EXT2_FLAG_JOURNAL_DEV_OK.
+               Changed function prototype for ext2fs_add_journal_device().
+               
 2001-01-14  Theodore Ts'o  <tytso@valinux.com>
 
        * closefs.c (ext2fs_flush): Don't write out anything beyond the
index bc79a47..24bce49 100644 (file)
@@ -260,5 +260,8 @@ ec  EXT2_ET_FILE_TOO_BIG,
 ec     EXT2_JOURNAL_NOT_BLOCK,
        "Supplied journal device not a block device"
 
+ec     EXT2_NO_JOURNAL_SB,
+       "Journal superblock not found"
+
        end
 
index 3b5d2e6..74bcb5d 100644 (file)
@@ -159,7 +159,7 @@ typedef struct ext2_file *ext2_file_t;
 #define EXT2_SEEK_END  2
 
 /*
- * Flags for the ext2_filsys structure
+ * Flags for the ext2_filsys structure and for ext2fs_open()
  */
 #define EXT2_FLAG_RW                   0x01
 #define EXT2_FLAG_CHANGED              0x02
@@ -173,6 +173,7 @@ typedef struct ext2_file *ext2_file_t;
 #define EXT2_FLAG_MASTER_SB_ONLY       0x200
 #define EXT2_FLAG_FORCE                        0x400
 #define EXT2_FLAG_SUPER_ONLY           0x800
+#define EXT2_FLAG_JOURNAL_DEV_OK       0x1000
 
 /*
  * Special flag in the ext2 inode i_flag field that means that this is
@@ -412,9 +413,11 @@ typedef struct ext2_icount *ext2_icount_t;
 #endif
 #define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
                                         EXT2_FEATURE_INCOMPAT_COMPRESSION|\
+                                        EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
                                         EXT3_FEATURE_INCOMPAT_RECOVER)
 #else
 #define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
+                                        EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\
                                         EXT3_FEATURE_INCOMPAT_RECOVER)
 #endif
 #define EXT2_LIB_FEATURE_RO_COMPAT_SUPP        (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
@@ -717,8 +720,11 @@ extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum
                              const char *name);
 
 /* mkjournal.c */
-extern errcode_t ext2fs_add_journal_device(ext2_filsys fs, char *device,
-                                          blk_t size, int flags);
+extern errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
+                                                 __u32 size, int flags,
+                                                 char  **ret_jsb);
+extern errcode_t ext2fs_add_journal_device(ext2_filsys fs,
+                                          ext2_filsys journal_dev);
 extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size,
                                          int flags);
 
index 9fe76a4..6251339 100644 (file)
@@ -144,6 +144,18 @@ errcode_t ext2fs_initialize(const char *name, int flags,
                goto cleanup;
        }
 
+       /*
+        * If we're creating an external journal device, we don't need
+        * to bother with the rest.
+        */
+       if (super->s_feature_incompat &
+           EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+               fs->group_desc_count = 0;
+               ext2fs_mark_super_dirty(fs);
+               *ret_fs = fs;
+               return 0;
+       }
+
 retry:
        fs->group_desc_count = (super->s_blocks_count -
                                super->s_first_data_block +
index e8ab683..73b4b02 100644 (file)
 #include "ext2fs.h"
 #include "jfs_user.h"
 
-static void init_journal_superblock(journal_superblock_t *jsb,
-                                   __u32 blocksize, __u32 size, int flags)
+/*
+ * This function automatically sets up the journal superblock and
+ * returns it as an allocated block.
+ */
+errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
+                                          __u32 size, int flags,
+                                          char  **ret_jsb)
 {
-       memset (jsb, 0, sizeof(*jsb));
+       errcode_t               retval;
+       journal_superblock_t    *jsb;
+       
+       if ((retval = ext2fs_get_mem(fs->blocksize, (void **) &jsb)))
+               return retval;
+
+       memset (jsb, 0, fs->blocksize);
 
        jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
        if (flags & EXT2_MKJOURNAL_V1_SUPER)
                jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V1);
        else
                jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
-       jsb->s_blocksize = htonl(blocksize);
+       jsb->s_blocksize = htonl(fs->blocksize);
        jsb->s_maxlen = htonl(size);
        jsb->s_first = htonl(1);
        jsb->s_sequence = htonl(1);
+       memcpy(jsb->s_uuid, fs->super->s_uuid, sizeof(fs->super->s_uuid));
+       jsb->s_nr_users = 1;
+       /*
+        * Now for the special settings if we're creating an external
+        * journal device
+        */
+       if (fs->super->s_feature_incompat &
+           EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+               jsb->s_nr_users = 0;
+               jsb->s_first = htonl(fs->super->s_first_data_block+2);
+       }
+
+       *ret_jsb = (char *) jsb;
+       return 0;
 }
 
 /*
@@ -60,34 +85,27 @@ static void init_journal_superblock(journal_superblock_t *jsb,
  * for creating external journals and creating journals on live
  * filesystems.
  */
-static errcode_t write_journal_file(ext2_filsys fs, char *device,
+static errcode_t write_journal_file(ext2_filsys fs, char *filename,
                                    blk_t size, int flags)
 {
        errcode_t       retval;
        char            *buf = 0;
-       journal_superblock_t    jsb;
        int             i, fd, ret_size;
 
-       init_journal_superblock(&jsb, fs->blocksize, size, flags);
-
-       /* Create a block buffer */
-       buf = malloc(fs->blocksize);
-       if (!buf)
-               return ENOMEM;
+       if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf)))
+               return retval;
 
-       /* Open the device */
-       if ((fd = open(device, O_WRONLY)) < 0) {
+       /* Open the device or journal file */
+       if ((fd = open(filename, O_WRONLY)) < 0) {
                retval = errno;
                goto errout;
        }
 
        /* Write the superblock out */
-       memset(buf, 0, fs->blocksize);
-       memcpy(buf, &jsb, sizeof(jsb));
        retval = EXT2_ET_SHORT_WRITE;
        ret_size = write(fd, buf, fs->blocksize);
        if (ret_size < 0) {
-               errno = retval;
+               retval = errno;
                goto errout;
        }
        if (ret_size != fs->blocksize)
@@ -107,7 +125,7 @@ static errcode_t write_journal_file(ext2_filsys fs, char *device,
 
        retval = 0;
 errout:
-       free(buf);
+       ext2fs_free_mem((void **) &buf);
        return retval;
 }
 
@@ -177,14 +195,14 @@ static int mkjournal_proc(ext2_filsys             fs,
 static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
                                     blk_t size, int flags)
 {
-       journal_superblock_t    jsb;
+       char                    *buf;
        errcode_t               retval;
        struct ext2_inode       inode;
        struct mkjournal_struct es;
-       char                    *buf;
-
-       init_journal_superblock(&jsb, fs->blocksize, size, flags);
 
+       if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf)))
+               return retval;
+       
        if ((retval = ext2fs_read_bitmaps(fs)))
                return retval;
 
@@ -194,14 +212,6 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
        if (inode.i_blocks > 0)
                return EEXIST;
 
-       /* Create the block buffer */
-       buf = malloc(fs->blocksize);
-       if (!buf)
-               return ENOMEM;
-
-       memset(buf, 0, fs->blocksize);
-       memcpy(buf, &jsb, sizeof(jsb));
-
        es.num_blocks = size;
        es.newblocks = 0;
        es.buf = buf;
@@ -209,12 +219,13 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
 
        retval = ext2fs_block_iterate2(fs, journal_ino, BLOCK_FLAG_APPEND,
                                       0, mkjournal_proc, &es);
-       free(buf);
-       if (es.err)
-               return es.err;
+       if (es.err) {
+               retval = es.err;
+               goto errout;
+       }
 
        if ((retval = ext2fs_read_inode(fs, journal_ino, &inode)))
-               return retval;
+               goto errout;
 
        inode.i_size += fs->blocksize * size;
        inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
@@ -223,44 +234,65 @@ static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino,
        inode.i_mode = LINUX_S_IFREG | 0600;
 
        if ((retval = ext2fs_write_inode(fs, journal_ino, &inode)))
-               return retval;
+               goto errout;
+       retval = 0;
 
-       return 0;
+errout:
+       ext2fs_free_mem((void **) &buf);
+       return retval;
 }
 
 /*
  * This function adds a journal device to a filesystem
  */
-errcode_t ext2fs_add_journal_device(ext2_filsys fs, char *device,
-                                   blk_t size, int flags)
+errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev)
 {
        struct stat     st;
        errcode_t       retval;
-       blk_t           dev_size;
+       char            buf[1024];
+       journal_superblock_t    *jsb;
+       int             i;
+       __u32           nr_users;
 
        /* Make sure the device exists and is a block device */
-       if (stat(device, &st) < 0)
+       if (stat(fs->device_name, &st) < 0)
                return errno;
+       
        if (!S_ISBLK(st.st_mode))
                return EXT2_JOURNAL_NOT_BLOCK;  /* Must be a block device */
 
-       /* Get the size of the device */
-       if ((retval = ext2fs_get_device_size(device, fs->blocksize,
-                                            &dev_size)))
+       /* Get the journal superblock */
+       if ((retval = io_channel_read_blk(journal_dev->io, 1, -1024, buf)))
                return retval;
 
-       if (!size)
-               size = dev_size; /* Default to the size of the device */
-       else if (size > dev_size)
-               return EINVAL;  /* Requested size bigger than device */
+       jsb = (journal_superblock_t *) buf;
+       if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
+           (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2)))
+               return EXT2_NO_JOURNAL_SB;
+
+       if (ntohl(jsb->s_blocksize) != fs->blocksize)
+               return EXT2_ET_UNEXPECTED_BLOCK_SIZE;
 
-       retval = write_journal_file(fs, device, size, flags);
-       if (retval)
+       /* Check and see if this filesystem has already been added */
+       nr_users = ntohl(jsb->s_nr_users);
+       for (i=0; i < nr_users; i++) {
+               if (memcmp(fs->super->s_uuid,
+                          &jsb->s_users[i*16], 16) == 0)
+                       break;
+       }
+       if (i >= nr_users) {
+               memcpy(&jsb->s_users[nr_users*16],
+                      fs->super->s_uuid, 16);
+               jsb->s_nr_users = htonl(nr_users+1);
+       }
+
+       /* Writeback the journal superblock */
+       if ((retval = io_channel_write_blk(journal_dev->io, 1, -1024, buf)))
                return retval;
        
        fs->super->s_journal_inum = 0;
        fs->super->s_journal_dev = st.st_rdev;
-       memset(fs->super->s_journal_uuid, 0,
+       memcpy(fs->super->s_journal_uuid, jsb->s_uuid,
               sizeof(fs->super->s_journal_uuid));
        fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
        ext2fs_mark_super_dirty(fs);
index 1b1430d..3b9531a 100644 (file)
@@ -138,6 +138,12 @@ errcode_t ext2fs_open(const char *name, int flags, int superblock,
                        retval = EXT2_ET_RO_UNSUPP_FEATURE;
                        goto cleanup;
                }
+               if (!(flags & EXT2_FLAG_JOURNAL_DEV_OK) &&
+                   (fs->super->s_feature_incompat &
+                    EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
+                       retval = EXT2_ET_UNSUPP_FEATURE;
+                       goto cleanup;
+               }
        }
        
        fs->blocksize = EXT2_BLOCK_SIZE(fs->super);
@@ -160,6 +166,17 @@ errcode_t ext2fs_open(const char *name, int flags, int superblock,
         * Set the blocksize to the filesystem's blocksize.
         */
        io_channel_set_blksize(fs->io, fs->blocksize);
+
+       /*
+        * If this is an external journal device, don't try to read
+        * the group descriptors, because they're not there.
+        */
+       if (fs->super->s_feature_incompat &
+           EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+               fs->group_desc_count = 0;
+               *ret_fs = fs;
+               return 0;
+       }
        
        /*
         * Read group descriptors