/* $NetBSD$ */ /*- * Copyright (c) 2006 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Matt Fleming * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Called at file system mount time. * This function decides whether to replay the journal. */ int ffs_journal_mount(struct mount *mp) { struct ufsmount *ump = VFSTOUFS(mp); struct fs *fs = ump->um_fs; struct vnode *vp; struct ffs_journal_sblock *sblock; struct ffs_journal_entry *dtrans; struct lwp *l = curlwp; int error, i; if (mp->mnt_flag & MNT_RDONLY) { /* * If the file system is going to be mount read-only * we need to replay the journal in memory only, but * this is not currently supported. */ return (EPERM); } else { /* * Read all the entries in the journal area and see if * any were not completed. If some journal entries were * not completed then replay the journal. */ if ((error = VFS_VGET(mp, fs->fs_ijournal, &vp))) return (error); /* * Read the superblock at the beginning of the journal * file. If all transactions completed before this filesystem * was unmounted then the flags will be FFS_JOURNAL_CLEAN. * If there are no transactions in the log, normal operation * commences. Otherwise, check each of the transactions in * the log. If the transaction is valid (i.e. it finished) * then replay it. Invalid transactions are skipped. */ sblock = (struct ffs_journal_sblock *)&vp->v_data; if (!(sblock->flags & FFS_JOURNAL_CLEAN)) { dtrans = malloc(sizeof(struct ffs_journal_entry), M_UFSMNT, M_WAITOK); /* end points immediately after last transaction */ while (sblock->begin < sblock->end-1) { dtrans = (struct ffs_journal_entry *)sblock + sblock->begin; for (i=0; i < dtrans->nblks; i++) { if (ffs_journal_replay(dtrans, i)) return 1; } sblock->begin += (MAXBLOCKS + dtrans->nblks); } sblock->flags = FFS_JOURNAL_CLEAN; ffs_sync(mp, 0, l->l_cred, l); } VOP_UNLOCK(vp, LK_EXCLUSIVE); vrele(vp); } return 0; } int ffs_journal_unmount(struct mount *mp, struct fs *fs) { struct vnode *vp; int error; if ((error = ffs_vget(mp, fs->fs_ijournal, &vp))) return (error); /* HOLDRELE(vp); */ VOP_UNLOCK(vp, LK_EXCLUSIVE); vrele(vp); return 0; } /* * This function 'rolls' the journal area forward, moving the currently * active area through the journal. Because the journal is implemented * as a circular buffer we need to take care of wrapping around the * journal. * * XXX Not too sure how to implement this */ void ffs_roll_journal(struct ffs_journal_sblock *sb) { } /* * ffs_replay() is responsible for searching through the log area * and finding valid transactions that have not been completed. A transaction * is 'finished' when all modifications to metadata have been made in memory * and the transaction has been written to the log area. A transaction * is 'complete' when the transaction in the log area has been flushed * to disk. */ int ffs_journal_replay(struct ffs_journal_entry *entry, int blk) { return 0; } /* These functions make up a transaction. */ int ffs_begin_trans(void) { return 0; } int ffs_finish_trans(void) { return 0; } /* * Write a journal entry into the journal. This functions must be called * anytime that a transaction modifies a metadata block, otherwise the * filesystem will be in an inconsitent state. * * The blocks that are written to the journal area are locked in the cache. */ int ffs_journal_write_blocks(void) { return 0; }