Index: sbin/newfs/extern.h =================================================================== RCS file: /cvsroot/src/sbin/newfs/extern.h,v retrieving revision 1.13 diff -u -r1.13 extern.h --- sbin/newfs/extern.h 26 Aug 2006 22:03:47 -0000 1.13 +++ sbin/newfs/extern.h 18 Jan 2007 09:59:52 -0000 @@ -48,6 +48,7 @@ extern int minfree; /* free space threshold */ extern int opt; /* optimization preference (space or time) */ extern int density; /* number of bytes per inode */ +extern int jsize; /* size of journal */ extern int num_inodes; /* number of inodes (overrides density) */ extern int maxcontig; /* max contiguous blocks to allocate */ extern int maxbpg; /* maximum blocks per file in a cyl group */ Index: sbin/newfs/mkfs.c =================================================================== RCS file: /cvsroot/src/sbin/newfs/mkfs.c,v retrieving revision 1.102 diff -u -r1.102 mkfs.c --- sbin/newfs/mkfs.c 16 Oct 2006 03:04:45 -0000 1.102 +++ sbin/newfs/mkfs.c 18 Jan 2007 09:59:53 -0000 @@ -119,6 +119,8 @@ static void setblock(struct fs *, unsigned char *, int); static int ilog2(int); static void zap_old_sblock(int); +static void ffs_alloc_dinode(struct ufs2_dinode *, int, struct fs *); +static void ffs_write_dinode(struct ufs2_dinode *, int, struct fs *, void *); #ifdef MFS static void calc_memfree(void); static void *mkfs_malloc(size_t size); @@ -310,7 +312,11 @@ sblock.fs_old_postblformat = FS_DYNAMICPOSTBLFMT; sblock.fs_old_nrpos = 1; } else { - sblock.fs_magic = FS_UFS2_MAGIC; + if (jsize) + sblock.fs_magic = FS_UFS2J_MAGIC; + else + sblock.fs_magic = FS_UFS2_MAGIC; + sblock.fs_sblockloc = SBLOCK_UFS2; sblock.fs_nindir = sblock.fs_bsize / sizeof(int64_t); sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs2_dinode); @@ -529,9 +535,12 @@ sblock.fs_bsize, sblock.fs_fsize); printf("\tusing %d cylinder groups of %.2fMB, %d blks, " "%d inodes.\n", + sblock.fs_ncg, (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg); + if (jsize) + printf("\tjournal size %dbytes.\n", jsize); #undef B2MBFACTOR } @@ -996,6 +1005,7 @@ fsinit(const struct timeval *tv, mode_t mfsmode, uid_t mfsuid, gid_t mfsgid) { union dinode node; + char *buf2; #ifdef LOSTDIR int i; int dirblksiz = DIRBLKSIZ; @@ -1092,7 +1102,7 @@ node.dp1.di_size)); wtfs(fsbtodb(&sblock, node.dp1.di_db[0]), sblock.fs_fsize, buf); } else { - if (mfs) { + if (mfs) { node.dp2.di_mode = IFDIR | mfsmode; node.dp2.di_uid = mfsuid; node.dp2.di_gid = mfsgid; @@ -1119,6 +1129,58 @@ wtfs(fsbtodb(&sblock, node.dp2.di_db[0]), sblock.fs_fsize, buf); } iput(&node, ROOTINO); + + /* + * XXX only create journal file for UFS2 for now. + */ + if (jsize) { + /* + * create the journal file + */ + memset(&node, 0, sizeof(node)); + node.dp2.di_mode = IFREG | UMASK; + node.dp2.di_uid = geteuid(); + node.dp2.di_gid = getegid(); + node.dp2.di_atime = tv->tv_sec; + node.dp2.di_atimensec = tv->tv_usec * 1000; + node.dp2.di_mtime = tv->tv_sec; + node.dp2.di_mtimensec = tv->tv_usec * 1000; + node.dp2.di_ctime = tv->tv_sec; + node.dp2.di_ctimensec = tv->tv_usec * 1000; + node.dp2.di_birthtime = tv->tv_sec; + node.dp2.di_birthnsec = tv->tv_usec * 1000; + node.dp2.di_nlink = 1; + node.dp2.di_size = jsize; + + buf2 = malloc(sblock.fs_bsize); + memset(buf2, 0, sblock.fs_bsize); + + /* allocate blocks for journal file */ + ffs_alloc_dinode(&node.dp2, + howmany(node.dp2.di_size, sblock.fs_bsize), &sblock); + + /* + journal_sblock = (struct ffs_journal_sblock *)jbuf; + journal_sblock->flags = FFS_JOURNAL_CLEAN; + journal_sblock->begin = 0; + journal_sblock->end = 0; + */ + + /* write changes to filesystem */ + ffs_write_dinode(&node.dp2, + howmany(node.dp2.di_size, sblock.fs_bsize), &sblock, buf2); + + /* XXX which inode do we place this at? Probably wants to be + * as small as possible so that the read is quicker i.e. it's + * at the outter tracks of the disk. + * Also want to replace this magic number with a constant. + */ + iput(&node, JINO); + + /* record the inode number in the superblock. */ + sblock.fs_ijournal = JINO; + } + return (1); } @@ -1497,6 +1559,100 @@ wtfs(sblkoff/sectorsize, sizeof oldfs, &oldfs); } +/* + * This function sets up a dinode entry with 'nblks' blocks allocated + * to it. NB we allocate full blocks (no fragments). + */ +void +ffs_alloc_dinode(struct ufs2_dinode *dip, int nblocks, struct fs *fs) +{ + int i; + int bb, base, factor, lvl; + int32_t ifibc = 0; /* How many indirects blocks */ + + dip->di_blocks = nblocks >> (fs->fs_bshift - fs->fs_fsbtodb + + fs->fs_fsbtodb); + + if (NDADDR < nblocks) { + /* Count up how many indirect blocks we need, recursively */ + /* XXX We are only called with nblocks > 1 for Ifile */ + bb = nblocks - NDADDR; + while (bb > 0) { + bb = howmany(bb, NINDIR(fs)); + ifibc += bb; + --bb; + } + dip->di_blocks += (unsigned int)btodb(fragroundup(fs, dip->di_size)); + } + + /* Assign the block addresses for the ifile */ + for (i = 0; i < MIN(nblocks,NDADDR); i++) { + dip->di_db[i] = alloc(fs->fs_bsize, dip->di_mode); + if (dip->di_db[i] == 0) + err(1, "Could not allocate block\n"); + } + if(nblocks > NDADDR) { + dip->di_ib[0] = alloc(fs->fs_bsize, dip->di_mode); + if (dip->di_ib[0] == 0) + err(1, "Could not allocate block\n"); + bb = howmany(nblocks - NDADDR, NINDIR(fs)) - 1; + factor = NINDIR(fs); + base = -NDADDR - factor; + lvl = 1; + while (bb > 0) { + dip->di_ib[lvl] = alloc(fs->fs_bsize, dip->di_mode); + if (dip->di_ib[lvl] == 0) + err(1, "Could not allocate block\n"); + bb = howmany(bb, NINDIR(fs)); + --bb; + factor *= NINDIR(fs); + base -= factor; + ++lvl; + } + } +} + +/* + * This function writes the data in 'data' to the on-disk inode, 'dip'. + */ +void +ffs_write_dinode(struct ufs2_dinode *dip, int nblocks, struct fs *fs, void *data) +{ + int i; + int bb, base, factor, lvl; + int32_t ifibc = 0; /* How many indirects blocks */ + + if (NDADDR < nblocks) { + /* Count up how many indirect blocks we need, recursively */ + /* XXX We are only called with nblocks > 1 for Ifile */ + bb = nblocks - NDADDR; + while (bb > 0) { + bb = howmany(bb, NINDIR(fs)); + ifibc += bb; + --bb; + } + } + + /* Assign the block addresses for the ifile */ + for (i = 0; i < MIN(nblocks,NDADDR); i++) { + wtfs(fsbtodb(fs, dip->di_db[i]), fs->fs_fsize, data); + } + if(nblocks > NDADDR) { + wtfs(fsbtodb(fs, dip->di_ib[0]), fs->fs_bsize, data); + bb = howmany(nblocks - NDADDR, NINDIR(fs)) - 1; + factor = NINDIR(fs); + base = -NDADDR - factor; + lvl = 1; + while (bb > 0) { + wtfs(fsbtodb(fs, dip->di_ib[lvl]), fs->fs_fsize, data); + bb = howmany(bb, NINDIR(fs)); + --bb; + factor *= NINDIR(fs); + base -= factor; + ++lvl; + } + } +} #ifdef MFS /* Index: sbin/newfs/newfs.8 =================================================================== RCS file: /cvsroot/src/sbin/newfs/newfs.8,v retrieving revision 1.69 diff -u -r1.69 newfs.8 --- sbin/newfs/newfs.8 25 Feb 2006 01:56:41 -0000 1.69 +++ sbin/newfs/newfs.8 18 Jan 2007 09:59:54 -0000 @@ -47,6 +47,7 @@ .Op Fl g Ar avgfilesize .Op Fl h Ar avgfpdir .Op Fl i Ar bytes-per-inode +.Op Fl j Ar journalsize .Op Fl m Ar free-space .Op Fl n Ar inodes .Op Fl O Ar filesystem-format @@ -180,6 +181,9 @@ .It \*[Gt]= 1024 MB 8 KB .El +.It Fl j Ar journalsize +This is the size of the journal. It should be large enough to hold at +least one journal entry. .It Fl m Ar free-space The percentage of space reserved from normal users; the minimum free space threshold. Index: sbin/newfs/newfs.c =================================================================== RCS file: /cvsroot/src/sbin/newfs/newfs.c,v retrieving revision 1.96 diff -u -r1.96 newfs.c --- sbin/newfs/newfs.c 25 Nov 2006 18:18:22 -0000 1.96 +++ sbin/newfs/newfs.c 18 Jan 2007 09:59:54 -0000 @@ -197,6 +197,7 @@ int mfs; /* run as the memory based filesystem */ int Nflag; /* run without writing file system */ +int jsize = 0; /* size of journal */ int Oflag = 1; /* format as an 4.3BSD file system */ int verbosity; /* amount of printf() output */ #define DEFAULT_VERBOSITY 3 /* 4 is traditional behavior */ @@ -264,7 +265,7 @@ opstring = mfs ? "NT:V:a:b:d:e:f:g:h:i:m:n:o:p:s:u:" : - "B:FINO:S:T:V:Za:b:d:e:f:g:h:i:l:m:n:o:r:s:v:"; + "B:FINO:S:T:V:Za:b:d:e:f:g:h:i:j:l:m:n:o:r:s:v:"; while ((ch = getopt(argc, argv, opstring)) != -1) switch (ch) { case 'B': @@ -349,6 +350,10 @@ density = strsuftoi64("bytes per inode", optarg, 1, INT_MAX, NULL); break; + case 'j': + jsize = strsuftoi64("journal size", optarg, 1, + MAXJOURNALSIZE, NULL); + break; case 'm': minfree = strsuftoi64("free space %", optarg, 0, 99, NULL); @@ -804,6 +809,7 @@ { MFS_MOUNT, "-g groupname\tgroup name of mount point" }, { BOTH, "-h avgfpdir\taverage files per directory" }, { BOTH, "-i density\tnumber of bytes per inode" }, + { NEWFS, "-j jsize \tjournal size" }, { BOTH, "-m minfree\tminimum free space %%" }, { BOTH, "-n inodes\tnumber of inodes (overrides -i density)" }, { BOTH, "-o optim\toptimization preference (`space' or `time')" Index: sys/lib/libsa/ufs.c =================================================================== RCS file: /cvsroot/src/sys/lib/libsa/ufs.c,v retrieving revision 1.49 diff -u -r1.49 ufs.c --- sys/lib/libsa/ufs.c 11 May 2006 01:13:44 -0000 1.49 +++ sys/lib/libsa/ufs.c 18 Jan 2007 10:00:17 -0000 @@ -500,7 +500,8 @@ if (fs->fs_sblockloc != sblock_try[i]) /* an alternate superblock - try again */ continue; - if (fs->fs_magic == FS_UFS2_MAGIC) { + if (fs->fs_magic == FS_UFS2_MAGIC || + fs->fs_magic == FS_UFS2J_MAGIC) { return 0; } } Index: sys/ufs/files.ufs =================================================================== RCS file: /cvsroot/src/sys/ufs/files.ufs,v retrieving revision 1.16 diff -u -r1.16 files.ufs --- sys/ufs/files.ufs 13 Nov 2006 16:12:54 -0000 1.16 +++ sys/ufs/files.ufs 18 Jan 2007 10:00:20 -0000 @@ -24,6 +24,7 @@ file ufs/ffs/ffs_balloc.c ffs | mfs | ext2fs file ufs/ffs/ffs_bswap.c (ffs | mfs) & ffs_ei file ufs/ffs/ffs_inode.c ffs | mfs | ext2fs +file ufs/ffs/ffs_journal.c ffs file ufs/ffs/ffs_snapshot.c ffs | mfs | ext2fs file ufs/ffs/ffs_softdep.c ffs & softdep file ufs/ffs/ffs_softdep.stub.c (ffs & !softdep) | Index: sys/ufs/ffs/ffs_alloc.c =================================================================== RCS file: /cvsroot/src/sys/ufs/ffs/ffs_alloc.c,v retrieving revision 1.97 diff -u -r1.97 ffs_alloc.c --- sys/ufs/ffs/ffs_alloc.c 4 Jan 2007 16:55:29 -0000 1.97 +++ sys/ufs/ffs/ffs_alloc.c 18 Jan 2007 10:00:21 -0000 @@ -240,7 +240,7 @@ if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) != 0 && freespace(fs, fs->fs_minfree) <= 0) goto nospace; - if (fs->fs_magic == FS_UFS2_MAGIC) + if (fs->fs_magic == FS_UFS2_MAGIC || fs->fs_magic == FS_UFS2J_MAGIC) bprev = ufs_rw64(ip->i_ffs2_db[lbprev], UFS_FSNEEDSWAP(fs)); else bprev = ufs_rw32(ip->i_ffs1_db[lbprev], UFS_FSNEEDSWAP(fs)); @@ -721,7 +721,7 @@ */ ip->i_gen++; DIP_ASSIGN(ip, gen, ip->i_gen); - if (fs->fs_magic == FS_UFS2_MAGIC) { + if (fs->fs_magic == FS_UFS2_MAGIC || fs->fs_magic == FS_UFS2J_MAGIC) { vfs_timestamp(&ts); ip->i_ffs2_birthtime = ts.tv_sec; ip->i_ffs2_birthnsec = ts.tv_nsec; @@ -1463,7 +1463,7 @@ * Check to see if we need to initialize more inodes. */ initediblk = ufs_rw32(cgp->cg_initediblk, needswap); - if (fs->fs_magic == FS_UFS2_MAGIC && + if ((fs->fs_magic == FS_UFS2_MAGIC || fs->fs_magic == FS_UFS2J_MAGIC) && ipref + INOPB(fs) > initediblk && initediblk < ufs_rw32(cgp->cg_niblk, needswap)) { ibp = getblk(ip->i_devvp, fsbtodb(fs, Index: sys/ufs/ffs/ffs_balloc.c =================================================================== RCS file: /cvsroot/src/sys/ufs/ffs/ffs_balloc.c,v retrieving revision 1.43 diff -u -r1.43 ffs_balloc.c --- sys/ufs/ffs/ffs_balloc.c 14 May 2006 21:32:45 -0000 1.43 +++ sys/ufs/ffs/ffs_balloc.c 18 Jan 2007 10:00:21 -0000 @@ -83,7 +83,8 @@ struct buf **bpp) { - if (VTOI(vp)->i_fs->fs_magic == FS_UFS2_MAGIC) + if (VTOI(vp)->i_fs->fs_magic == FS_UFS2_MAGIC || + VTOI(vp)->i_fs->fs_magic == FS_UFS2J_MAGIC) return ffs_balloc_ufs2(vp, off, size, cred, flags, bpp); else return ffs_balloc_ufs1(vp, off, size, cred, flags, bpp); Index: sys/ufs/ffs/ffs_bswap.c =================================================================== RCS file: /cvsroot/src/sys/ufs/ffs/ffs_bswap.c,v retrieving revision 1.32 diff -u -r1.32 ffs_bswap.c --- sys/ufs/ffs/ffs_bswap.c 11 Dec 2005 12:25:25 -0000 1.32 +++ sys/ufs/ffs/ffs_bswap.c 18 Jan 2007 10:00:21 -0000 @@ -211,7 +211,8 @@ for (i = 0; i < MAXFRAG; i++) n->cg_frsum[i] = bswap32(o->cg_frsum[i]); - if ((fs->fs_magic != FS_UFS2_MAGIC) && + if ((fs->fs_magic != FS_UFS2_MAGIC && + fs->fs_magic != FS_UFS2J_MAGIC) && (fs->fs_old_postblformat == FS_42POSTBLFMT)) { /* old format */ struct ocg *on, *oo; int j; @@ -254,7 +255,8 @@ for (i = 1; i < fs->fs_contigsumsize + 1; i++) n32[i] = bswap32(o32[i]); - if (fs->fs_magic == FS_UFS2_MAGIC) + if (fs->fs_magic == FS_UFS2_MAGIC || + fs->fs_magic == FS_UFS2J_MAGIC) return; n32 = (u_int32_t *)((u_int8_t *)n + btotoff); Index: sys/ufs/ffs/ffs_extern.h =================================================================== RCS file: /cvsroot/src/sys/ufs/ffs/ffs_extern.h,v retrieving revision 1.54 diff -u -r1.54 ffs_extern.h --- sys/ufs/ffs/ffs_extern.h 13 Jul 2006 12:00:26 -0000 1.54 +++ sys/ufs/ffs/ffs_extern.h 18 Jan 2007 10:00:22 -0000 @@ -65,6 +65,10 @@ struct vnode; struct mbuf; struct cg; +struct ffs_log_entry; +struct ffs_transaction; +struct ffs_journal_entry; +struct ffs_journal_sblock; #if defined(_KERNEL) @@ -107,6 +111,15 @@ const struct timespec *, int); int ffs_truncate(struct vnode *, off_t, int, kauth_cred_t, struct lwp *); +/* ffs_journal.c */ +int ffs_journal_unmount(struct mount *, struct fs *); +int ffs_journal_mount(struct mount *); +int ffs_journal_replay(struct ffs_journal_entry *, int); +void ffs_roll_journal(struct ffs_journal_sblock *); +int ffs_begin_trans(void); +int ffs_finish_trans(void); +int ffs_journal_write_blocks(void); + /* ffs_vfsops.c */ void ffs_init(void); void ffs_reinit(void); Index: sys/ufs/ffs/ffs_vfsops.c =================================================================== RCS file: /cvsroot/src/sys/ufs/ffs/ffs_vfsops.c,v retrieving revision 1.192 diff -u -r1.192 ffs_vfsops.c --- sys/ufs/ffs/ffs_vfsops.c 7 Jan 2007 09:33:18 -0000 1.192 +++ sys/ufs/ffs/ffs_vfsops.c 18 Jan 2007 10:00:23 -0000 @@ -501,6 +501,14 @@ return (EINVAL); ump = VFSTOUFS(mp); + + /* + * XXX If journaling is enabled on this filesystem we need + * a better way to reload (we can't simply invalidate the meta-data). + */ + if (ump->um_fs->fs_magic == FS_UFS2J_MAGIC) + return (EOPNOTSUPP); + /* * Step 1: invalidate all cached meta-data. */ @@ -716,6 +724,7 @@ daddr_t sblockloc, fsblockloc; int blks, fstype; int error, i, size, ronly; + int journal = 0; #ifdef FFS_EI int needswap = 0; /* keep gcc happy */ #endif @@ -787,6 +796,18 @@ fstype = UFS2; needswap = 1; #endif + } else if (fs->fs_magic == FS_UFS2J_MAGIC) { + sbsize = fs->fs_sbsize; + fstype = UFS2; + journal = 1; +#ifdef FFS_EI + needswap = 0; + } else if (fs->fs_magic == bswap32(FS_UFS2J_MAGIC)) { + sbsize = bswap32(fs->fs_sbsize); + fstype = UFS2; + journal = 1; + needswap = 1; +#endif } else continue; @@ -1014,6 +1035,15 @@ #endif } #endif /* UFS_EXTATTR */ + + /* + * Execute journal code. + */ + if (journal) { + if (ffs_journal_mount(mp) != 0) + goto out; + } + return (0); out: if (fs) @@ -1169,7 +1199,13 @@ } else ufs_extattr_uepm_destroy(&ump->um_extattr); } + #endif /* UFS_EXTATTR */ + if (fs->fs_magic == FS_UFS2J_MAGIC) { + if ((error = ffs_journal_unmount(mp, fs))) + return (error); + } + if (mp->mnt_flag & MNT_SOFTDEP) { if ((error = softdep_flushfiles(mp, flags, l)) != 0) return (error); @@ -1177,6 +1213,7 @@ if ((error = ffs_flushfiles(mp, flags, l)) != 0) return (error); } + if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) { printf("%s: unmount pending error: blocks %" PRId64 " files %d\n", Index: sys/ufs/ffs/fs.h =================================================================== RCS file: /cvsroot/src/sys/ufs/ffs/fs.h,v retrieving revision 1.46 diff -u -r1.46 fs.h --- sys/ufs/ffs/fs.h 11 Dec 2005 12:25:25 -0000 1.46 +++ sys/ufs/ffs/fs.h 18 Jan 2007 10:00:24 -0000 @@ -356,6 +356,7 @@ int32_t fs_spare5[2]; /* old fs_postbloff */ /* old fs_rotbloff */ int32_t fs_magic; /* magic number */ + int32_t fs_ijournal; /* inode of journal */ }; #define fs_old_postbloff fs_spare5[0] @@ -387,6 +388,7 @@ #define FS_UFS2_MAGIC 0x19540119 /* UFS2 fast file system magic number */ #define FS_UFS1_MAGIC_SWAPPED 0x54190100 #define FS_UFS2_MAGIC_SWAPPED 0x19015419 +#define FS_UFS2J_MAGIC 0x19540120 /* UFS2 with journalling support */ #define FS_OKAY 0x7c269d38 /* superblock checksum */ #define FS_42INODEFMT -1 /* 4.2BSD inode format */ #define FS_44INODEFMT 2 /* 4.4BSD inode format */ @@ -725,4 +727,71 @@ } __attribute__((__packed__)); +/* + * Journaling support for FFS requires two data structures for + * transactions, an in-memory structure and an on-disk structure. + * + * The in-memory data structure is represetned by the 'ffs_transaction' + * structure, and the on-disk data structure is represented by the + * 'ffs_journal_entry' structure. + * + * These data structres have been taken from Dominic Giampaolo's + * "Practical File System Design with The Be File System", I'm not sure + * if they're totally applicable here. + */ + +#define MAXBLOCKS 128 +#define MAXJOURNALSIZE 0x100000 + +/* + * These flags are used in the journal superblock stored inside the log area. + * When all transactions complete, the flags of the superblock should be + * marked FFS_JOURNAL_CLEAN. + */ +#define FFS_JOURNAL_CLEAN 0x0001 /* All transactions have completed. */ +#define FFS_JOURNAL_DIRTY 0x0002 /* Transactions are outstanding. */ + + +/* + * In-memory data structures for a transaction. + * + * XXX We may want to support 'batched transactions'. But this can + * be added later. + */ +struct ffs_transaction { + blkcnt_t nblks; /* num of blocks in trans */ + off_t begin; /* where this transaction starts + * in the log area + */ + off_t endl; /* where we end in the log area */ + int nflushblks; /* num of flushed blocks */ + struct ffs_transaction_entry *te; +}; + +struct ffs_transaction_entry { + daddr_t baddrs[MAXBLOCKS]; /* addr of metadata blocks */ + struct buf *data[MAXBLOCKS]; /* modified metadata blocks */ +}; + +/* On-disk data structures for a transaction */ +struct ffs_journal_entry { + blkcnt_t nblks; /* num of blocks in trans */ + daddr_t addr[MAXBLOCKS]; /* block addresses */ + struct buf *data[MAXBLOCKS]; /* modified blocks */ +}; + +/* + * The log area of the journal (which is simply a file) stores a superblock + * at the beginning. + * + * => begin: marks the beginning of a run of transactions. + * => end: points to one past the end of the transactions in the log. New + * transactions are added to the log area at this address. + */ +struct ffs_journal_sblock { + off_t begin; + off_t end; + int flags; /* See flags below. XXX May be removed*/ +}; + #endif /* !_UFS_FFS_FS_H_ */ Index: sys/ufs/ufs/dinode.h =================================================================== RCS file: /cvsroot/src/sys/ufs/ufs/dinode.h,v retrieving revision 1.19 diff -u -r1.19 dinode.h --- sys/ufs/ufs/dinode.h 11 Dec 2005 12:25:28 -0000 1.19 +++ sys/ufs/ufs/dinode.h 18 Jan 2007 10:00:24 -0000 @@ -64,6 +64,12 @@ */ #define WINO ((ino_t)1) +/* + * XXX This should really be calculated by "newfs(8)" + * This is the default inode number for the journal file. + */ +#define JINO ((ino_t)4) + /* * A dinode contains all the meta-data associated with a UFS file. * This structure defines the on-disk format of a dinode. Since @@ -167,6 +173,7 @@ #define IFLNK 0120000 /* Symbolic link. */ #define IFSOCK 0140000 /* UNIX domain socket. */ #define IFWHT 0160000 /* Whiteout. */ +#define IFJNL 0130000 /* Journal file. */ /* Size of the on-disk inode. */ #define DINODE1_SIZE (sizeof(struct ufs1_dinode)) /* 128 */