Commit e65af39e authored by Dave Kleikamp's avatar Dave Kleikamp

Add support for external JFS journal

Submitted by Christoph Hellwig & Dave Kleikamp
parent db468b69
...@@ -123,7 +123,7 @@ struct jfs_sb_info { ...@@ -123,7 +123,7 @@ struct jfs_sb_info {
short nbperpage; /* 2: blocks per page */ short nbperpage; /* 2: blocks per page */
short l2nbperpage; /* 2: log2 blocks per page */ short l2nbperpage; /* 2: log2 blocks per page */
short l2niperblk; /* 2: log2 inodes per page */ short l2niperblk; /* 2: log2 inodes per page */
short reserved; /* 2: log2 inodes per page */ kdev_t logdev; /* 2: external log device */
pxd_t logpxd; /* 8: pxd describing log */ pxd_t logpxd; /* 8: pxd describing log */
pxd_t ait2; /* 8: pxd describing AIT copy */ pxd_t ait2; /* 8: pxd describing AIT copy */
/* Formerly in ipimap */ /* Formerly in ipimap */
......
...@@ -159,7 +159,6 @@ do { \ ...@@ -159,7 +159,6 @@ do { \
/* /*
* external references * external references
*/ */
extern void vPut(struct inode *ip);
extern void txLazyUnlock(tblock_t * tblk); extern void txLazyUnlock(tblock_t * tblk);
extern int jfs_thread_stopped(void); extern int jfs_thread_stopped(void);
extern struct task_struct *jfsIOtask; extern struct task_struct *jfsIOtask;
...@@ -172,6 +171,7 @@ static int lmWriteRecord(log_t * log, tblock_t * tblk, lrd_t * lrd, ...@@ -172,6 +171,7 @@ static int lmWriteRecord(log_t * log, tblock_t * tblk, lrd_t * lrd,
tlock_t * tlck); tlock_t * tlck);
static int lmNextPage(log_t * log); static int lmNextPage(log_t * log);
static int lmLogFileSystem(log_t * log, kdev_t fsdev, int activate);
static int lmLogInit(log_t * log); static int lmLogInit(log_t * log);
static int lmLogShutdown(log_t * log); static int lmLogShutdown(log_t * log);
...@@ -1057,46 +1057,36 @@ int lmLogSync(log_t * log, int nosyncwait) ...@@ -1057,46 +1057,36 @@ int lmLogSync(log_t * log, int nosyncwait)
int lmLogOpen(struct super_block *sb, log_t ** logptr) int lmLogOpen(struct super_block *sb, log_t ** logptr)
{ {
int rc; int rc;
kdev_t logdev; /* dev_t of log device */ struct block_device *bdev;
log_t *log; log_t *log;
logdev = sb->s_dev; if (!(log = kmalloc(sizeof(log_t), GFP_KERNEL)))
return ENOMEM;
memset(log, 0, sizeof(log_t));
#ifdef _STILL_TO_PORT if (!(JFS_SBI(sb)->mntflag & JFS_INLINELOG))
/*
* open the inode representing the log device (aka log inode)
*/
if (logdev != fsdev)
goto externalLog; goto externalLog;
#endif /* _STILL_TO_PORT */
/* /*
* in-line log in host file system * in-line log in host file system
* *
* file system to log have 1-to-1 relationship; * file system to log have 1-to-1 relationship;
*/ */
// inlineLog:
*logptr = log = kmalloc(sizeof(log_t), GFP_KERNEL);
if (log == 0)
return ENOMEM;
memset(log, 0, sizeof(log_t));
log->sb = sb; /* This should be a list */ log->sb = sb; /* This should be a list */
log->flag = JFS_INLINELOG; log->flag = JFS_INLINELOG;
log->dev = logdev; log->dev = sb->s_dev;
log->base = addressPXD(&JFS_SBI(sb)->logpxd); log->base = addressPXD(&JFS_SBI(sb)->logpxd);
log->size = lengthPXD(&JFS_SBI(sb)->logpxd) >> log->size = lengthPXD(&JFS_SBI(sb)->logpxd) >>
(L2LOGPSIZE - sb->s_blocksize_bits); (L2LOGPSIZE - sb->s_blocksize_bits);
log->l2bsize = sb->s_blocksize_bits; log->l2bsize = sb->s_blocksize_bits;
ASSERT(L2LOGPSIZE >= sb->s_blocksize_bits); ASSERT(L2LOGPSIZE >= sb->s_blocksize_bits);
/* /*
* initialize log. * initialize log.
*/ */
if ((rc = lmLogInit(log))) if ((rc = lmLogInit(log)))
goto errout10; goto errout10;
#ifdef _STILL_TO_PORT
goto out; goto out;
/* /*
...@@ -1105,103 +1095,47 @@ int lmLogOpen(struct super_block *sb, log_t ** logptr) ...@@ -1105,103 +1095,47 @@ int lmLogOpen(struct super_block *sb, log_t ** logptr)
* file systems to log may have n-to-1 relationship; * file systems to log may have n-to-1 relationship;
*/ */
externalLog: externalLog:
/* if (!(bdev = bdget(kdev_t_to_nr(JFS_SBI(sb)->logdev)))) {
* open log inode rc = ENODEV;
* goto errout10;
* log inode is reserved inode of (dev_t = log device,
* fileset number = 0, i_number = 0), which acquire
* one i_count for each open by file system.
*
* hand craft dummy vfs to force iget() the special case of
* an in-memory inode allocation without on-disk inode
*/
memset(&dummyvfs, 0, sizeof(struct vfs));
dummyvfs.filesetvfs.vfs_data = NULL;
dummyvfs.dummyvfs.dev = logdev;
dummyvfs.dummyvfs.ipmnt = NULL;
ICACHE_LOCK();
rc = iget((struct vfs *) &dummyvfs, 0, (inode_t **) & log, 0);
ICACHE_UNLOCK();
if (rc)
return rc;
log->flag = 0;
log->dev = logdev;
log->base = 0;
log->size = 0;
/*
* serialize open/close between multiple file systems
* bound with the log;
*/
ip = (inode_t *) log;
IWRITE_LOCK(ip);
/*
* subsequent open: add file system to log active file system list
*/
#ifdef _JFS_OS2
if (log->strat2p)
#endif /* _JFS_OS2 */
{
if (rc = lmLogFileSystem(log, fsdev, 1))
goto errout10;
IWRITE_UNLOCK(ip);
*iplog = ip;
jFYI(1, ("lmLogOpen: exit(0)\n"));
return 0;
} }
/* decouple log inode from dummy vfs */ if ((rc = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_FS))) {
vPut(ip); rc = -rc;
goto errout10;
/* }
* first open:
*/
#ifdef _JFS_OS2
/*
* establish access to the single/shared (already open) log device
*/
logdevfp = (void *) logStrat2;
log->strat2p = logStrat2;
log->strat3p = logStrat3;
log->l2pbsize = 9; /* todo: when OS/2 have multiple external log */
#endif /* _JFS_OS2 */
log->sb = sb; /* This should be a list */
log->dev = JFS_SBI(sb)->logdev;
log->bdev = bdev;
/* /*
* initialize log: * initialize log:
*/ */
if (rc = lmLogInit(log)) if ((rc = lmLogInit(log)))
goto errout20; goto errout20;
/* /*
* add file system to log active file system list * add file system to log active file system list
*/ */
if (rc = lmLogFileSystem(log, fsdev, 1)) if ((rc = lmLogFileSystem(log, sb->s_dev, 1)))
goto errout30; goto errout30;
/*
* insert log device into log device list
*/
out: out:
#endif /* _STILL_TO_PORT */
jFYI(1, ("lmLogOpen: exit(0)\n")); jFYI(1, ("lmLogOpen: exit(0)\n"));
*logptr = log;
return 0; return 0;
/* /*
* unwind on error * unwind on error
*/ */
#ifdef _STILL_TO_PORT
errout30: /* unwind lbmLogInit() */ errout30: /* unwind lbmLogInit() */
lbmLogShutdown(log); lbmLogShutdown(log);
errout20: /* close external log device */ errout20: /* close external log device */
blkdev_put(bdev, BDEV_FS);
#endif /* _STILL_TO_PORT */ errout10: /* free log descriptor */
errout10: /* free log inode */
kfree(log); kfree(log);
jFYI(1, ("lmLogOpen: exit(%d)\n", rc)); jFYI(1, ("lmLogOpen: exit(%d)\n", rc));
...@@ -1253,6 +1187,10 @@ static int lmLogInit(log_t * log) ...@@ -1253,6 +1187,10 @@ static int lmLogInit(log_t * log)
/* /*
* validate log superblock * validate log superblock
*/ */
if (!(log->flag & JFS_INLINELOG))
log->l2bsize = 12; /* XXX kludge alert XXX */
if ((rc = lbmRead(log, 1, &bpsuper))) if ((rc = lbmRead(log, 1, &bpsuper)))
goto errout10; goto errout10;
...@@ -1282,6 +1220,7 @@ static int lmLogInit(log_t * log) ...@@ -1282,6 +1220,7 @@ static int lmLogInit(log_t * log)
log, (unsigned long long) log->base, log->size)); log, (unsigned long long) log->base, log->size));
} else { } else {
log->size = le32_to_cpu(logsuper->size); log->size = le32_to_cpu(logsuper->size);
log->l2bsize = le32_to_cpu(logsuper->l2bsize);
jFYI(0, jFYI(0,
("lmLogInit: external log:0x%p base:0x%Lx size:0x%x\n", ("lmLogInit: external log:0x%p base:0x%Lx size:0x%x\n",
log, (unsigned long long) log->base, log->size)); log, (unsigned long long) log->base, log->size));
...@@ -1376,6 +1315,7 @@ static int lmLogInit(log_t * log) ...@@ -1376,6 +1315,7 @@ static int lmLogInit(log_t * log)
logsuper->state = cpu_to_le32(LOGMOUNT); logsuper->state = cpu_to_le32(LOGMOUNT);
log->serial = le32_to_cpu(logsuper->serial) + 1; log->serial = le32_to_cpu(logsuper->serial) + 1;
logsuper->serial = cpu_to_le32(log->serial); logsuper->serial = cpu_to_le32(log->serial);
logsuper->device = cpu_to_le32(kdev_t_to_nr(log->dev));
lbmDirectWrite(log, bpsuper, lbmWRITE | lbmRELEASE | lbmSYNC); lbmDirectWrite(log, bpsuper, lbmWRITE | lbmRELEASE | lbmSYNC);
if ((rc = lbmIOWait(bpsuper, lbmFREE))) if ((rc = lbmIOWait(bpsuper, lbmFREE)))
goto errout30; goto errout30;
...@@ -1419,47 +1359,24 @@ int lmLogClose(struct super_block *sb, log_t * log) ...@@ -1419,47 +1359,24 @@ int lmLogClose(struct super_block *sb, log_t * log)
jFYI(1, ("lmLogClose: log:0x%p\n", log)); jFYI(1, ("lmLogClose: log:0x%p\n", log));
if (!(log->flag & JFS_INLINELOG))
goto externalLog;
/* /*
* in-line log in host file system * in-line log in host file system
*/ */
// inlineLog: rc = lmLogShutdown(log);
#ifdef _STILL_TO_PORT goto out;
if (log->flag & JFS_INLINELOG) {
rc = lmLogShutdown(log);
goto out1;
}
/* /*
* external log as separate logical volume * external log as separate logical volume
*/ */
externalLog: externalLog:
lmLogFileSystem(log, sb->s_dev, 0);
/* serialize open/close between multiple file systems
* associated with the log
*/
IWRITE_LOCK(iplog);
/*
* remove file system from log active file system list
*/
rc = lmLogFileSystem(log, fsdev, 0);
if (iplog->i_count > 1)
goto out2;
/*
* last close: shut down log
*/
rc = ((rc1 = lmLogShutdown(log)) && rc == 0) ? rc1 : rc;
out1:
#else /* _STILL_TO_PORT */
rc = lmLogShutdown(log); rc = lmLogShutdown(log);
#endif /* _STILL_TO_PORT */ blkdev_put(log->bdev, BDEV_FS);
// out2:
out:
jFYI(0, ("lmLogClose: exit(%d)\n", rc)); jFYI(0, ("lmLogClose: exit(%d)\n", rc));
return rc; return rc;
} }
...@@ -1561,7 +1478,6 @@ static int lmLogShutdown(log_t * log) ...@@ -1561,7 +1478,6 @@ static int lmLogShutdown(log_t * log)
} }
#ifdef _STILL_TO_PORT
/* /*
* NAME: lmLogFileSystem() * NAME: lmLogFileSystem()
* *
...@@ -1569,7 +1485,7 @@ static int lmLogShutdown(log_t * log) ...@@ -1569,7 +1485,7 @@ static int lmLogShutdown(log_t * log)
* file system into/from log active file system list. * file system into/from log active file system list.
* *
* PARAMETE: log - pointer to logs inode. * PARAMETE: log - pointer to logs inode.
* fsdev - dev_t of filesystem. * fsdev - kdev_t of filesystem.
* serial - pointer to returned log serial number * serial - pointer to returned log serial number
* activate - insert/remove device from active list. * activate - insert/remove device from active list.
* *
...@@ -1578,10 +1494,11 @@ static int lmLogShutdown(log_t * log) ...@@ -1578,10 +1494,11 @@ static int lmLogShutdown(log_t * log)
* *
* serialization: IWRITE_LOCK(log inode) held on entry/exit * serialization: IWRITE_LOCK(log inode) held on entry/exit
*/ */
static int lmLogFileSystem(log_t * log, dev_t fsdev, int activate) static int lmLogFileSystem(log_t * log, kdev_t fsdev, int activate)
{ {
int rc = 0; int rc = 0;
int bit, word; int i;
u32 dev_le = cpu_to_le32(kdev_t_to_nr(fsdev));
logsuper_t *logsuper; logsuper_t *logsuper;
lbuf_t *bpsuper; lbuf_t *bpsuper;
...@@ -1592,15 +1509,25 @@ static int lmLogFileSystem(log_t * log, dev_t fsdev, int activate) ...@@ -1592,15 +1509,25 @@ static int lmLogFileSystem(log_t * log, dev_t fsdev, int activate)
return rc; return rc;
logsuper = (logsuper_t *) bpsuper->l_ldata; logsuper = (logsuper_t *) bpsuper->l_ldata;
bit = minor(fsdev); if (activate) {
word = bit / 32; for (i = 0; i < MAX_ACTIVE; i++)
bit -= 32 * word; if (logsuper->active[i] == 0) {
if (activate) logsuper->active[i] = dev_le;
logsuper->active[word] |= break;
cpu_to_le32((LEFTMOSTONE >> bit)); }
else if (i == MAX_ACTIVE) {
logsuper->active[word] &= jERROR(1,("Too many file systems sharing journal!\n"));
cpu_to_le32((~(LEFTMOSTONE >> bit))); lbmFree(bpsuper);
return EMFILE; /* Is there a better rc? */
}
} else {
for (i = 0; i < MAX_ACTIVE; i++)
if (logsuper->active[i] == dev_le) {
logsuper->active[i] = 0;
break;
}
assert(i < MAX_ACTIVE);
}
/* /*
* synchronous write log superblock: * synchronous write log superblock:
...@@ -1618,7 +1545,6 @@ static int lmLogFileSystem(log_t * log, dev_t fsdev, int activate) ...@@ -1618,7 +1545,6 @@ static int lmLogFileSystem(log_t * log, dev_t fsdev, int activate)
return rc; return rc;
} }
#endif /* _STILL_TO_PORT */
/* /*
......
...@@ -60,6 +60,8 @@ ...@@ -60,6 +60,8 @@
#define LOGMAGIC 0x87654321 #define LOGMAGIC 0x87654321
#define LOGVERSION 1 #define LOGVERSION 1
#define MAX_ACTIVE 512 /* Max active file systems sharing log */
typedef struct { typedef struct {
u32 magic; /* 4: log lv identifier */ u32 magic; /* 4: log lv identifier */
s32 version; /* 4: version number */ s32 version; /* 4: version number */
...@@ -72,8 +74,8 @@ typedef struct { ...@@ -72,8 +74,8 @@ typedef struct {
u32 state; /* 4: state - see below */ u32 state; /* 4: state - see below */
s32 end; /* 4: addr of last log record set by logredo */ s32 end; /* 4: addr of last log record set by logredo */
u32 active[8]; /* 32: active file systems bit vector */ u32 device; /* 4: save device in case location changes */
s32 rsrvd[LOGPSIZE / 4 - 17]; u32 active[MAX_ACTIVE]; /* 2048: active file systems list */
} logsuper_t; } logsuper_t;
/* log flag: commit option (see jfs_filsys.h) */ /* log flag: commit option (see jfs_filsys.h) */
...@@ -200,7 +202,7 @@ typedef struct lrd { ...@@ -200,7 +202,7 @@ typedef struct lrd {
s32 backchain; /* 4: ptr to prev record of same transaction */ s32 backchain; /* 4: ptr to prev record of same transaction */
u16 type; /* 2: record type */ u16 type; /* 2: record type */
s16 length; /* 2: length of data in record (in byte) */ s16 length; /* 2: length of data in record (in byte) */
s32 aggregate; /* 4: file system lv/aggregate */ u32 aggregate; /* 4: file system lv/aggregate */
/* (16) */ /* (16) */
/* /*
...@@ -367,7 +369,7 @@ typedef struct jfs_log { ...@@ -367,7 +369,7 @@ typedef struct jfs_log {
* the log between fs's * the log between fs's
*/ */
kdev_t dev; /* 4: log lv number */ kdev_t dev; /* 4: log lv number */
struct file *devfp; /* 4: log device file */ struct block_device *bdev; /* 4: log lv pointer */
s32 serial; /* 4: log mount serial number */ s32 serial; /* 4: log mount serial number */
s64 base; /* @8: log extent address (inline log ) */ s64 base; /* @8: log extent address (inline log ) */
......
...@@ -283,24 +283,6 @@ int jfs_mount_rw(struct super_block *sb, int remount) ...@@ -283,24 +283,6 @@ int jfs_mount_rw(struct super_block *sb, int remount)
return rc; return rc;
} }
} }
#ifdef _STILL_TO_PORT
/*
* get log device associated with the fs being mounted;
*/
if (ipmnt->i_mntflag & JFS_INLINELOG) {
vfsp->vfs_logVPB = vfsp->vfs_hVPB;
vfsp->vfs_logvpfs = vfsp->vfs_vpfsi;
} else if (vfsp->vfs_logvpfs == NULL) {
/*
* XXX: there's only one external log per system;
*/
jERROR(1, ("jfs_mount: Mount Failure! No Log Device.\n"));
goto errout30;
}
logdev = vfsp->vfs_logvpfs->vpi_unit;
ipmnt->i_logdev = logdev;
#endif /* _STILL_TO_PORT */
/* /*
* open/initialize log * open/initialize log
...@@ -360,7 +342,7 @@ static int chkSuper(struct super_block *sb) ...@@ -360,7 +342,7 @@ static int chkSuper(struct super_block *sb)
*/ */
/* validate fs signature */ /* validate fs signature */
if (strncmp(j_sb->s_magic, JFS_MAGIC, 4) || if (strncmp(j_sb->s_magic, JFS_MAGIC, 4) ||
j_sb->s_version != cpu_to_le32(JFS_VERSION)) { j_sb->s_version > cpu_to_le32(JFS_VERSION)) {
//rc = EFORMAT; //rc = EFORMAT;
rc = EINVAL; rc = EINVAL;
goto out; goto out;
...@@ -398,10 +380,6 @@ static int chkSuper(struct super_block *sb) ...@@ -398,10 +380,6 @@ static int chkSuper(struct super_block *sb)
j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT); j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT);
} }
/* in release 1, the flag MUST reflect inline log, and group commit */
if ((j_sb->s_flag & cpu_to_le32(JFS_INLINELOG)) !=
cpu_to_le32(JFS_INLINELOG))
j_sb->s_flag |= cpu_to_le32(JFS_INLINELOG);
if ((j_sb->s_flag & cpu_to_le32(JFS_GROUPCOMMIT)) != if ((j_sb->s_flag & cpu_to_le32(JFS_GROUPCOMMIT)) !=
cpu_to_le32(JFS_GROUPCOMMIT)) cpu_to_le32(JFS_GROUPCOMMIT))
j_sb->s_flag |= cpu_to_le32(JFS_GROUPCOMMIT); j_sb->s_flag |= cpu_to_le32(JFS_GROUPCOMMIT);
...@@ -437,6 +415,8 @@ static int chkSuper(struct super_block *sb) ...@@ -437,6 +415,8 @@ static int chkSuper(struct super_block *sb)
sbi->l2niperblk = sbi->l2bsize - L2DISIZE; sbi->l2niperblk = sbi->l2bsize - L2DISIZE;
if (sbi->mntflag & JFS_INLINELOG) if (sbi->mntflag & JFS_INLINELOG)
sbi->logpxd = j_sb->s_logpxd; sbi->logpxd = j_sb->s_logpxd;
else
sbi->logdev = to_kdev_t(le32_to_cpu(j_sb->s_logdev));
sbi->ait2 = j_sb->s_ait2; sbi->ait2 = j_sb->s_ait2;
out: out:
...@@ -476,6 +456,10 @@ int updateSuper(struct super_block *sb, uint state) ...@@ -476,6 +456,10 @@ int updateSuper(struct super_block *sb, uint state)
j_sb->s_logdev = j_sb->s_logdev =
cpu_to_le32(kdev_t_to_nr(JFS_SBI(sb)->log->dev)); cpu_to_le32(kdev_t_to_nr(JFS_SBI(sb)->log->dev));
j_sb->s_logserial = cpu_to_le32(JFS_SBI(sb)->log->serial); j_sb->s_logserial = cpu_to_le32(JFS_SBI(sb)->log->serial);
/* record our own device number in case the location
* changes after a reboot
*/
j_sb->s_device = cpu_to_le32(kdev_t_to_nr(sb->s_dev));
} else if (state == FM_CLEAN) { } else if (state == FM_CLEAN) {
/* /*
* If this volume is shared with OS/2, OS/2 will need to * If this volume is shared with OS/2, OS/2 will need to
......
...@@ -25,9 +25,9 @@ ...@@ -25,9 +25,9 @@
/* /*
* make the magic number something a human could read * make the magic number something a human could read
*/ */
#define JFS_MAGIC "JFS1" /* Magic word: Version 1 */ #define JFS_MAGIC "JFS1" /* Magic word */
#define JFS_VERSION 1 /* Version number: Version 1 */ #define JFS_VERSION 2 /* Version number: Version 2 */
#define LV_NAME_SIZE 11 /* MUST BE 11 for OS/2 boot sector */ #define LV_NAME_SIZE 11 /* MUST BE 11 for OS/2 boot sector */
...@@ -103,38 +103,10 @@ struct jfs_superblock { ...@@ -103,38 +103,10 @@ struct jfs_superblock {
pxd_t s_xlogpxd; /* 8: extendfs logpxd */ pxd_t s_xlogpxd; /* 8: extendfs logpxd */
/* - 128 byte boundary - */ /* - 128 byte boundary - */
/* u32 s_device; /* Store device in case location changes
* DFS VFS support (preliminary) * between reboots
*/
char s_attach; /* 1: VFS: flag: set when aggregate is attached
*/ */
u8 rsrvd4[7]; /* 7: reserved - set to 0 */
u64 totalUsable; /* 8: VFS: total of 1K blocks which are
* available to "normal" (non-root) users.
*/
u64 minFree; /* 8: VFS: # of 1K blocks held in reserve for
* exclusive use of root. This value can be 0,
* and if it is then totalUsable will be equal
* to # of blocks in aggregate. I believe this
* means that minFree + totalUsable = # blocks.
* In that case, we don't need to store both
* totalUsable and minFree since we can compute
* one from the other. I would guess minFree
* would be the one we should store, and
* totalUsable would be the one we should
* compute. (Just a guess...)
*/
u64 realFree; /* 8: VFS: # of free 1K blocks can be used by
* "normal" users. It may be this is something
* we should compute when asked for instead of
* storing in the superblock. I don't know how
* often this information is needed.
*/
/*
* graffiti area
*/
}; };
extern int readSuper(struct super_block *, struct metapage **); extern int readSuper(struct super_block *, struct metapage **);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment