From owner-p4-projects@FreeBSD.ORG Thu Sep 1 04:06:13 2005 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 59FAB16A421; Thu, 1 Sep 2005 04:06:13 +0000 (GMT) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 0F86616A41F for ; Thu, 1 Sep 2005 04:06:13 +0000 (GMT) (envelope-from soc-polytopes@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id BC64843D45 for ; Thu, 1 Sep 2005 04:06:12 +0000 (GMT) (envelope-from soc-polytopes@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id j8146CY3066704 for ; Thu, 1 Sep 2005 04:06:12 GMT (envelope-from soc-polytopes@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id j8146CG1066701 for perforce@freebsd.org; Thu, 1 Sep 2005 04:06:12 GMT (envelope-from soc-polytopes@freebsd.org) Date: Thu, 1 Sep 2005 04:06:12 GMT Message-Id: <200509010406.j8146CG1066701@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to soc-polytopes@freebsd.org using -f From: soc-polytopes To: Perforce Change Reviews Cc: Subject: PERFORCE change 82954 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 01 Sep 2005 04:06:14 -0000 http://perforce.freebsd.org/chv.cgi?CH=82954 Change 82954 by soc-polytopes@polytopes_kafka on 2005/09/01 04:05:23 Checkpoint. Affected files ... .. //depot/projects/soc2005/ufsj/src/sys/ufs/ufs/journal.h#6 edit .. //depot/projects/soc2005/ufsj/src/sys/ufs/ufs/ufs_journal.c#6 edit Differences ... ==== //depot/projects/soc2005/ufsj/src/sys/ufs/ufs/journal.h#6 (text+ko) ==== @@ -115,7 +115,8 @@ struct ufs_journal *journal; int pinned_buf_count; LIST_HEAD(buffer_list, ufsj_buffer_pair) b_list; - void *data; + void *header; + void *footer; } *ufsj_thandle_t; struct ufsj_buffer_pair{ @@ -125,6 +126,8 @@ }; MALLOC_DECLARE(M_UFSJ_HEADER); +MALLOC_DECLARE(M_UFSJ_TRANSACTION_LIST); +MALLOC_DECLARE(M_UFSJ_BUF_PAIR); extern int ufsj_start(struct vnode *devvp, struct mount *mp, struct fs *fs, struct thread *td); ==== //depot/projects/soc2005/ufsj/src/sys/ufs/ufs/ufs_journal.c#6 (text+ko) ==== @@ -53,6 +53,9 @@ * 6. What do we do with these pink elephants called QUOTA and SOFTUPDATES? =-) */ +/* BUGS: 1. Race condition with writing the footer. */ + + struct ufs_journal { uint64_t gen; off_t start; @@ -85,12 +88,14 @@ static void ufsj_register_block(ufsj_thandle_t transaction, struct buf *wait_buf, struct buf *pinned_buf); -#define UFSJ_ALLOCATE_HEADER(aa, bb) UFS_BALLOC((aa), 0, sizeof(struct ufsj_header), FSCRED, 0, &(bb)) +#define UFSJ_ALLOCATE_HEADER(aa, bb) UFS_BALLOC((aa), 0, sizeof(struct ufsj_header), curthread->td_ucred, 0, &(bb)) /* UFSJ_CRITICAL_FREE_SPACE is in Megs, but freespace returns frags */ #define UFSJ_MEGS_TO_FRAGS(fs, megs) (1024*1024*(fs)->fs_fsize*(megs)) MALLOC_DEFINE(M_UFSJ_HEADER, "journalheader", "A UFS Journal header."); +MALLOC_DEFINE(M_UFSJ_TRANSACTION_LIST, "transactionlist", "A list of UFS journal transactions."); +MALLOC_DEFINE(M_UFSJ_BUF_PAIR, "bufpair", "A pair of bufs, one pinned and the other a wait condition."); /* To be called when the FS is mounted */ int @@ -186,6 +191,8 @@ printf(" jsb->j_flags=%b\n", jsb->j_flags, "\10\2ENABLED\1DIRTY\n"); error = 1; /* XXX Does this really warrant an error? */ + /* Yes, tthis can imply that we have a null jsb, + which gives lovely writes to 0x0 */ goto out; } @@ -251,7 +258,7 @@ struct vnode *jvp; int error, jflags; - td = curthread; /* XXX */ + td = curthread; /* Curthread gives us the correct creds (I think) */ ump = VFSTOUFS(mp); journal = ump->um_journal; jflags = 0; @@ -311,7 +318,7 @@ struct ufs_journal *jnl; ufsj_thandle_t transaction; struct ufsj_header *hdr; - int error = 0; + int error = 0, journal_is_locked = 0; KASSERT(u_mnt != NULL, ("ufsj_start_transaction: mountpoint is NULL.")); KASSERT(handle != NULL, ("ufsj_start_transaction: handle is NULL.")); @@ -342,9 +349,23 @@ ufsj_flush(jnl); } + printf("ufsj_start_transaction: Acquiring lock on %p\n", vp); + if (vn_lock(vp, LK_EXCLUSIVE|LK_NOWAIT, curthread)){ + printf("ufsj_start_transaction: Couldn't lock vnode, giving up\n"); + error = 1; + goto end; + } + journal_is_locked = 1; + + ASSERT_VOP_LOCKED(vp, "ufsj_start_transaction"); + + printf("ufsj_start_transaction: Trying to allocate header.\n"); /* Allocate a block for the transaction header */ error = UFSJ_ALLOCATE_HEADER(vp, bp); + journal_is_locked = 0; + VOP_UNLOCK(vp, 0, curthread); + if (error){ /* Did not allocate a buf */ goto end; @@ -356,7 +377,7 @@ hdr->j_type |= type; transaction->gen = jnl->gen; - transaction->data = bp; + transaction->header = bp; transaction->journal = jnl; /* Done with journal */ @@ -371,6 +392,9 @@ *handle = transaction; end: + if (journal_is_locked) + VOP_UNLOCK(vp, 0, curthread); + return (error); } @@ -386,15 +410,17 @@ struct buf *bpc; struct ufsj_header *header; - int error; + int error = 0, journal_is_locked = 0; KASSERT(handle != NULL, ("ufsj_write_blocks: NULL transaction")); KASSERT(bp != NULL, ("ufsj_write_blocks: NULL buffer")); - header = handle->data; + header = handle->header; - if (!(bp->b_flags & BA_METAONLY)) + /* It seems that there is no BA_METAONLY, oops! + if (!(bp->b_flags & BA_METAONLY)) panic("ufsj: Got non-metadata block(0x%X)", (unsigned int)bp); + */ if (header->j_count > UFSJ_MAX_SIZE){ panic("ufsj: Went past the end of the journal, count: %d", (int)header->j_count); @@ -403,11 +429,23 @@ panic("ufsj: Filled transaction"); } - error = UFS_BALLOC(handle->journal->jvp, 0, sizeof(*(bp->b_data)), - FSCRED, bp->b_flags, &bpc); + + printf("ufsj_write_blocks: Acquiring lock on %p\n", handle->journal->jvp); + if (vn_lock(handle->journal->jvp, LK_EXCLUSIVE|LK_CANRECURSE|LK_NOWAIT, curthread)){ + printf("ufsj_write_blocks: Couldn't lock vnode, giving up\n"); + error = 1; + goto end; + } + journal_is_locked = 1; + ASSERT_VOP_LOCKED(handle->journal->jvp, "ufsj_write_blocks"); + + error = UFS_BALLOC(handle->journal->jvp, 1, sizeof(*(bp->b_data)), + curthread->td_ucred, bp->b_flags, &bpc); + journal_is_locked = 0; + VOP_UNLOCK(handle->journal->jvp, 0, curthread); if (error){ + /* XXX: Does anymore cleanup need done? */ goto end; - /* XXX */ } /* Just copy the pointer, don't copy the data */ @@ -416,7 +454,7 @@ header->j_count++; /* Record where the orig. block lives */ - header->sectors[header->j_count] = bp->b_lblkno; + header->sectors[header->j_count] = bpc->b_lblkno; bp->b_iodone = ufsbuf_done; bpc->b_iodone = tbuf_done; @@ -430,6 +468,8 @@ return 0; end: + if (journal_is_locked) + VOP_UNLOCK(handle->journal->jvp, 0, curthread); brelse(bpc); return error; } @@ -447,7 +487,8 @@ struct fs *fs; struct vnode *vp; struct ufs_journal *jnl; - int error; + struct ufsj_buffer_pair *pair; + int error = 0, journal_is_locked = 0; KASSERT(handle != NULL, ("ufsj_end_transaction: handle is NULL.")); @@ -462,17 +503,33 @@ fs = jnl->ump->um_fs; vp = jnl->jvp; + printf("ufsj_end_transaction: Acquiring lock on %p\n", vp); + if (vn_lock(vp, LK_EXCLUSIVE|LK_NOWAIT, curthread)){ + printf("ufsj_end_transaction: Couldn't lock vnode, giving up\n"); + error = 1; + goto end; + } + journal_is_locked = 1; + ASSERT_VOP_LOCKED(vp, "ufsj_end_transaction"); + /* Allocate a footer block */ error = UFSJ_ALLOCATE_HEADER(vp, bp); if (error) goto end; + handle->footer = bp; + /* Allocate space in the journal. Is the journal full? If so then * synchronously flush the blocks for the oldest transactions */ if (ufsj_critical_full(fs)) ufsj_flush(jnl); /* Write the header, footer, and data blocks */ + bdwrite(handle->header); + LIST_FOREACH(pair, &(handle->b_list), next){ + bdwrite(pair->wait_buf); + } + bdwrite(bp); /* Update the journal superblock with the index and the generation */ jnl->gen++; @@ -526,7 +583,7 @@ LIST_FOREACH_SAFE(lp, &(jnl->t_list), next, lp_tmp){ ufsj_thandle_t handle = lp->t; - struct ufsj_header *hdr = handle->data; + struct ufsj_header *hdr = handle->header; int i; for (i = 0; i < hdr->j_count; i++){ if (bp->b_lblkno == hdr->sectors[i]){ @@ -608,7 +665,21 @@ static void ufsj_flush(struct ufs_journal *journal) { - return; + struct ufsj_transaction_list *lp; + struct ufsj_buffer_pair *pair; + + LIST_FOREACH(lp, &(journal->t_list), next){ + ufsj_thandle_t handle = lp->t; + bawrite(handle->header); + LIST_FOREACH(pair, &(handle->b_list), next){ + bawrite(pair->wait_buf); +#ifdef BAW_HAS_INCLUDED_THE_XFS_PINNING_CODE + bunpin(pair->pinned_buf); +#endif + bawrite(pair->pinned_buf); + } + bawrite(handle->footer); + } } static int @@ -643,14 +714,14 @@ KASSERT(transaction != NULL, ("ufsj_register_transaction: mountpoint is NULL.")); - /* Allocate entry -- FIXME: malloc type */ - entry = malloc(sizeof(struct ufsj_transaction_list), M_UFSMNT, M_WAITOK|M_ZERO); + /* Allocate Entry */ + entry = malloc(sizeof(struct ufsj_transaction_list), M_UFSJ_TRANSACTION_LIST, M_WAITOK|M_ZERO); if (entry == NULL){ panic("ufsj_register_transaction: We were unable to allocate a new entry."); } - hdr = (struct ufsj_header *)transaction->data; + hdr = (struct ufsj_header *)transaction->header; jnl = transaction->journal; /* Lock the journal */ @@ -669,7 +740,7 @@ { struct ufsj_buffer_pair *pair; - pair = malloc(sizeof(struct ufsj_buffer_pair), M_UFSMNT, M_WAITOK|M_ZERO); + pair = malloc(sizeof(struct ufsj_buffer_pair), M_UFSJ_BUF_PAIR, M_WAITOK|M_ZERO); if (pair == NULL){ panic("ufsj_register_block: Unable to allocate list entry.");