Date: Thu, 1 Sep 2005 07:00:42 GMT From: soc-polytopes <soc-polytopes@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 82957 for review Message-ID: <200509010700.j8170gp8081836@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=82957 Change 82957 by soc-polytopes@polytopes_kafka on 2005/09/01 07:00:06 For Scott, still have a locking issue in write_blocks Affected files ... .. //depot/projects/soc2005/ufsj/src/sbin/newfs/mkfs.c#3 edit .. //depot/projects/soc2005/ufsj/src/sbin/tunefs/tunefs.c#4 edit .. //depot/projects/soc2005/ufsj/src/sys/ufs/ufs/journal.h#7 edit .. //depot/projects/soc2005/ufsj/src/sys/ufs/ufs/ufs_journal.c#7 edit Differences ... ==== //depot/projects/soc2005/ufsj/src/sbin/newfs/mkfs.c#3 (text+ko) ==== @@ -1087,7 +1087,7 @@ create_journal_file(void) { /* Find the journal inode, and create the file there */ -/* This is only in here now - +/* This is only in here now as a stub */ + return 0; } ==== //depot/projects/soc2005/ufsj/src/sbin/tunefs/tunefs.c#4 (text+ko) ==== @@ -297,9 +297,11 @@ } if (jflag) { name = "journalling"; - if (jvalue == 0) + if (jvalue == 0) { sblock.fs_flags &= ~FS_JOURNAL; - else { + } else if (sblock.fs_flags & FS_DOSOFTDEP) { + warnx("Soft updates is already enabled, cannot journal."); + } else { sblock.fs_flags |= FS_JOURNAL; sblock.fs_journal_inode = jvalue; } @@ -346,6 +348,9 @@ else if (sblock.fs_clean == 0) { warnx("%s cannot be enabled until fsck is run", name); + } else if (sblock.fs_flags & FS_JOURNAL) { + warnx("%s cannot be enabled while journaling is enabled", + name); } else { sblock.fs_flags |= FS_DOSOFTDEP; warnx("%s set", name); ==== //depot/projects/soc2005/ufsj/src/sys/ufs/ufs/journal.h#7 (text+ko) ==== @@ -25,6 +25,11 @@ */ /* + Special thanks to Google for choosing this project as part of + the Google Summer of Code. +*/ + +/* * UFS Journal structures and definitions */ ==== //depot/projects/soc2005/ufsj/src/sys/ufs/ufs/ufs_journal.c#7 (text+ko) ==== @@ -53,7 +53,11 @@ * 6. What do we do with these pink elephants called QUOTA and SOFTUPDATES? =-) */ -/* BUGS: 1. Race condition with writing the footer. */ +/* + BUGS: 1. Race condition with writing the footer. + 2. Until the buffer pinning is patched in, out of order writes + 3. Data integrity is not yet ensured. +*/ struct ufs_journal { @@ -88,7 +92,7 @@ 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), curthread->td_ucred, 0, &(bb)) +#define UFSJ_ALLOCATE_HEADER(vp, offset, bp) UFS_BALLOC((vp), (offset), sizeof(struct ufsj_header), curthread->td_ucred, 0, &(bp)) /* UFSJ_CRITICAL_FREE_SPACE is in Megs, but freespace returns frags */ #define UFSJ_MEGS_TO_FRAGS(fs, megs) (1024*1024*(fs)->fs_fsize*(megs)) @@ -97,6 +101,31 @@ 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."); + +/* A handy macro to avoid duplicating the jsb sync code */ +#define SYNC_JOURNAL(jvp, jbp, journal, error, routine_name) \ +do { \ + struct ufsj_superblock *jsb; \ + /* Write the Journal */ \ + printf("%s: reading jsb\n", (routine_name)); \ + if (((error) = bread((jvp), (journal)->jsb_off, JSBLOCKSIZE, \ + NOCRED, &(jbp))) == 0) { \ + jsb = (struct ufsj_superblock *) (jbp)->b_data; \ + jsb->j_gen = (journal)->gen; \ + jsb->j_head = (journal)->head; \ + jsb->j_tail = (journal)->tail; \ + printf("%s: writing jsb\n", (routine_name)); \ + if (((error) = bwrite((jbp))) != 0) \ + printf("Error %d writing journal superblock!\n", (error)); \ + } else { \ + printf("%s: read of sb failed\n", (routine_name)); \ + brelse((jbp)); \ + } \ +} while(0) + + + + /* To be called when the FS is mounted */ int ufsj_start(struct vnode *devvp, struct mount *mp, struct fs *fs, struct thread *td) @@ -207,7 +236,7 @@ journal->bsize = fs->fs_bsize; journal->fs = fs; - printf("Setting ump->um_journal to 0x%p\n", (void *)journal); + printf("Setting ump->um_journal to %p\n", (void *)journal); ump->um_journal = journal; flags = jsb->j_flags; @@ -318,29 +347,31 @@ struct ufs_journal *jnl; ufsj_thandle_t transaction; struct ufsj_header *hdr; + uma_zone_t zone; 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.")); /* Grab the Journal from ufsmount */ jnl = u_mnt->um_journal; + zone = jnl->tzone; - /* Lock the journal */ - mtx_lock(&jnl->jmtx); - /* Malloc new handle and header, do this now so that we can block before acquiring jmtx. */ /* This is NOT good, we don't want to sleep with the lock */ - /* What is the malloc type of a header? */ - hdr = malloc(sizeof(struct ufsj_header), M_UFSJ_HEADER, M_NOWAIT|M_ZERO); - transaction = uma_zalloc(jnl->tzone, M_NOWAIT|M_ZERO); + hdr = malloc(sizeof(struct ufsj_header), M_UFSJ_HEADER, M_WAITOK|M_ZERO); + transaction = uma_zalloc(jnl->tzone, M_WAITOK|M_ZERO); - /* We need to spin until we get a memory lock, since we hold the journal lock! */ + /* Don't need to spin, but could have failures */ if (!hdr){ - panic("FUCK!"); + panic("ufsj_start_transaction: Unable to allocate header."); } else if (!transaction){ - panic("FUCK AND FUCK AGAIN!"); + panic("ufsj_start_transaction: Unable to allocate transaction."); } + + /* Lock the journal */ + mtx_lock(&jnl->jmtx); + fs = u_mnt->um_fs; vp = jnl->jvp; @@ -355,13 +386,17 @@ 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); + error = UFSJ_ALLOCATE_HEADER(vp, jnl->next, bp); + + /* Point to the next blkno */ + jnl->next++; journal_is_locked = 0; VOP_UNLOCK(vp, 0, curthread); @@ -391,6 +426,7 @@ *handle = transaction; + printf("ufsj_start_transaction: Transaction created successfully\n"); end: if (journal_is_locked) VOP_UNLOCK(vp, 0, curthread); @@ -410,6 +446,7 @@ struct buf *bpc; struct ufsj_header *header; + struct ufs_journal *jnl; int error = 0, journal_is_locked = 0; KASSERT(handle != NULL, ("ufsj_write_blocks: NULL transaction")); @@ -430,6 +467,8 @@ } + jnl = handle->journal; + mtx_lock(&jnl->jmtx); 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"); @@ -439,27 +478,33 @@ journal_is_locked = 1; ASSERT_VOP_LOCKED(handle->journal->jvp, "ufsj_write_blocks"); - error = UFS_BALLOC(handle->journal->jvp, 1, sizeof(*(bp->b_data)), + printf("ufsj_write_blocks: Trying to get buffer copy, lblk: %ld sz: %ld\n", + (long)jnl->next, (long)jnl->fs->fs_bsize); + error = UFS_BALLOC(handle->journal->jvp, jnl->next, jnl->fs->fs_bsize, 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; } + jnl->next++; + mtx_unlock(&jnl->jmtx); /* Just copy the pointer, don't copy the data */ bpc->b_data = bp->b_data; header->j_count++; - /* Record where the orig. block lives */ header->sectors[header->j_count] = bpc->b_lblkno; bp->b_iodone = ufsbuf_done; bpc->b_iodone = tbuf_done; /* Pin the buffer */ - /* TODO */ +#ifdef BAW_HAS_INCLUDED_THE_XFS_PINNING_CODE + bpin(bp); +#endif /* Write the block */ bdwrite(bp); @@ -468,6 +513,8 @@ return 0; end: + if (mtx_owned(&jnl->jmtx)) + mtx_unlock(&jnl->jmtx); if (journal_is_locked) VOP_UNLOCK(handle->journal->jvp, 0, curthread); brelse(bpc); @@ -488,6 +535,7 @@ struct vnode *vp; struct ufs_journal *jnl; struct ufsj_buffer_pair *pair; + struct buf *jbp; int error = 0, journal_is_locked = 0; KASSERT(handle != NULL, ("ufsj_end_transaction: handle is NULL.")); @@ -513,10 +561,11 @@ ASSERT_VOP_LOCKED(vp, "ufsj_end_transaction"); /* Allocate a footer block */ - error = UFSJ_ALLOCATE_HEADER(vp, bp); + error = UFSJ_ALLOCATE_HEADER(vp, jnl->next, bp); if (error) goto end; + jnl->next++; handle->footer = bp; /* Allocate space in the journal. Is the journal full? If so then @@ -535,7 +584,7 @@ jnl->gen++; jnl->tail = bp->b_lblkno; - /* Write the Journal */ + SYNC_JOURNAL(jnl->jvp, jbp, jnl, error, "ufsj_end_transaction"); /* Done with the journal, set it free */ mtx_unlock(&jnl->jmtx); @@ -605,7 +654,9 @@ } if (journal_updated){ - /* sync jsb and jnl */ + struct buf *jbp; + int error = 0; + SYNC_JOURNAL(jnl->jvp, jbp, jnl, error, "ufsbuf_done"); } mtx_unlock(&jnl->jmtx); @@ -667,18 +718,20 @@ { struct ufsj_transaction_list *lp; struct ufsj_buffer_pair *pair; + int error = 0; LIST_FOREACH(lp, &(journal->t_list), next){ ufsj_thandle_t handle = lp->t; - bawrite(handle->header); + /* FIXME: How do we handle errors */ + error = bwrite(handle->header); LIST_FOREACH(pair, &(handle->b_list), next){ - bawrite(pair->wait_buf); + error = bwrite(pair->wait_buf); #ifdef BAW_HAS_INCLUDED_THE_XFS_PINNING_CODE bunpin(pair->pinned_buf); #endif - bawrite(pair->pinned_buf); + error = bwrite(pair->pinned_buf); } - bawrite(handle->footer); + error = bwrite(handle->footer); } } @@ -691,6 +744,13 @@ 2. Order the transactions 3. write the blocks to disk */ + /* Read jnl->head */ + /* while (cur_blk != jnl->tail) + getblk cur_blk + write_blk to real location + cur_blk = header->*mumble* + */ + return (0); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200509010700.j8170gp8081836>