PERFORCE change 82487 for review
soc-polytopes
soc-polytopes at FreeBSD.org
Wed Aug 24 05:05:50 GMT 2005
http://perforce.freebsd.org/chv.cgi?CH=82487
Change 82487 by soc-polytopes at polytopes_kafka on 2005/08/24 05:05:11
Another checkpoint. Working on revamping the code that manages
how we know when a transaction is complete and when to unpin
our orig. buffers.
Affected files ...
.. //depot/projects/soc2005/ufsj/src/sys/ufs/ufs/journal.h#3 edit
.. //depot/projects/soc2005/ufsj/src/sys/ufs/ufs/ufs_journal.c#3 edit
Differences ...
==== //depot/projects/soc2005/ufsj/src/sys/ufs/ufs/journal.h#3 (text+ko) ====
@@ -61,6 +61,13 @@
#define UFSJ_MAX_SIZE 62
/*
+ * If the disk's free space drops below this level, it is critically full.
+ * This value is in Mega(?)bytes?
+ */
+
+#define UFSJ_CRITICAL_FREE_SPACE 10
+
+/*
* A journal entry header. It contains the sector information of each of
* the block in the entry, along with the size and index of the entry.
* It's size is a multiple of the disk sector size, usually 512 bytes.
==== //depot/projects/soc2005/ufsj/src/sys/ufs/ufs/ufs_journal.c#3 (text+ko) ====
@@ -73,7 +73,12 @@
static int ufsj_replay(struct ufs_journal *journal);
static void tbuf_done(struct buf *arg);
static void ufsbuf_done(struct buf *arg) __unused;
-static int ufsj_critical_full(void);
+static int ufsj_critical_full(struct fs *fs);
+
+#define UFSJ_ALLOCATE_HEADER(aa, bb) UFS_BALLOC((aa), 0, sizeof(struct ufsj_header), FSCRED, 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))
/* To be called when the FS is mounted */
int
@@ -251,34 +256,34 @@
KASSERT(u_mnt != NULL, ("ufsj_start_transaction: mountpoint is NULL."));
KASSERT(handle != NULL, ("ufsj_start_transaction: handle is NULL."));
+ /* Malloc new handle and header, do this now so that we can block before
+ acquiring jmtx. */
+ /* When do we free these? */
+ h = malloc(sizeof(struct ufsj_transaction), M_UFSMNT, M_WAITOK|M_ZERO);
+ hdr = malloc(sizeof(struct ufsj_header), M_UFSMNT, M_WAITOK|M_ZERO);
+
+ /* Grab the Journal from ufsmount */
+ jnl = u_mnt->um_journal;
+ /* Lock the journal */
+ mtx_lock(&jnl->jmtx);
+
fs = u_mnt->um_fs;
- jnl = u_mnt->um_journal;
vp = jnl->jvp;
- if (ufsj_critical_full()){
+ if (ufsj_critical_full(fs)){
ufsj_flush(jnl);
}
/* Allocate a block for the transaction header */
- /* Think that this is not the correct function */
- /* Does anyone know what the second arg to balloc should be? */
- /* NOCRED, FSCRED? We do not want the cred of the invoker */
- /* Do we need flags? (I think probably) */
-
- error = UFS_BALLOC(vp, 0, sizeof(struct ufsj_header),
- FSCRED, 0, &bp);
+ error = UFSJ_ALLOCATE_HEADER(vp, bp);
if (error){
- /* Do Cleanup */
+ /* Did not allocate a buf */
goto end;
}
- /* Malloc new handle and header */
- h = malloc(sizeof(struct ufsj_transaction), M_UFSMNT, M_WAITOK|M_ZERO);
- hdr = malloc(sizeof(struct ufsj_header), M_UFSMNT, M_WAITOK|M_ZERO);
-
-
+ /* Synch access to jnl? YES */
hdr->j_gen = jnl->gen;
hdr->j_count = 0;
hdr->j_type |= type;
@@ -286,6 +291,9 @@
h->gen = jnl->gen;
h->data = bp;
h->journal = jnl;
+
+ /* Done with journal */
+ mtx_unlock(&jnl->jmtx);
bp->b_data = (void *)hdr;
@@ -324,8 +332,6 @@
panic("ufsj: Filled transaction");
}
- /* Pin the bp */
-
error = UFS_BALLOC(handle->journal->jvp, 0, sizeof(*(bp->b_data)),
FSCRED, bp->b_flags, &bpc);
if (error){
@@ -337,18 +343,20 @@
bpc->b_data = bp->b_data;
header->j_count++;
- /* How do we set the lba to bpc? */
-/* header->sectors[header->j_count] = (daddr_t)bpc; */
+
+ header->sectors[header->j_count] = bpc->b_lblkno;
+ bp->b_iodone = ufsbuf_done;
+ bpc->b_iodone = tbuf_done;
+
+ /* Pin the buffer */
+ /* TODO */
+ /* Write the block */
+ bdwrite(bp);
- bp->b_iodone = tbuf_done;
+ return 0;
end:
+ brelse(bpc);
return error;
-
- /* Adjust the bufdone pointer in the bp to call us so we know when to
- * retire the transaction.
- */
-
- return (0);
}
/*
@@ -360,40 +368,77 @@
ufsj_end_transaction(ufsj_thandle_t handle)
{
-#if 0
- printf("Ended transaction: %p\n", (void *)handle);
-#endif
+ struct buf *bp; /* Footer */
+ struct fs *fs;
+ struct vnode *vp;
+ struct ufs_journal *jnl;
+ int error;
+
+ KASSERT(handle != NULL, ("ufsj_end_transaction: handle is NULL."));
+
+
+ /* Grab the Jouranl from our handle */
+ jnl = handle->journal;
+
+
+ /* Lock the journal */
+ mtx_lock(&jnl->jmtx);
+
+ fs = jnl->ump->um_fs;
+ vp = jnl->jvp;
+
/* Allocate a footer block */
+ error = UFSJ_ALLOCATE_HEADER(vp, bp);
+ if (error)
+ goto end;
/* 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);
- /* Allocate a generate number. */
-
/* Write the header, footer, and data blocks */
/* Update the journal superblock with the index and the generation */
+ jnl->gen++;
+ jnl->tail = bp->b_lblkno;
+ /* Write the Journal */
+
+ /* Done with the journal, set it free */
+ mtx_unlock(&jnl->jmtx);
+
return (0);
+ end:
+
+ /* We're still holding the journal lock (verify this) and let it go */
+ if (mtx_owned(&jnl->jmtx))
+ mtx_unlock(&jnl->jmtx);
+
+ /* We got the buffer, don't forget to let it go */
+ brelse(bp);
+ return error;
}
/* bufdone callback for transaction buffers. */
static void
-tbuf_done(struct buf *arg)
+tbuf_done(struct buf *bp)
{
/* Is the transaction fully written to disk? If so then unpin the
* buffers.
*/
+ /* We can also free the header */
}
/* bufdone callback for the real buffers. */
static void
-ufsbuf_done(struct buf *arg)
+ufsbuf_done(struct buf *bp)
{
/* Are all of the real buffers on disk? If so then update the
* journalling superblock to so show that the transaction is retired.
*/
+ /* We can also free the transaction handle */
}
static void
@@ -405,14 +450,24 @@
static int
ufsj_replay(struct ufs_journal *journal)
{
+ /* Read in the journal file from the jnl superblock */
+ /* Crufty 2-Pass (not really) algorithm */
+ /* 1. build up list of transactions.
+ 2. Order the transactions
+ 3. write the blocks to disk
+ */
return (0);
}
static int
-ufsj_critical_full(void)
+ufsj_critical_full(struct fs *fs)
{
- /* XXX */
- return 0;
+ /* Is MINFREE a good value, or is it even correct? */
+ int free_space = freespace(fs, MINFREE);
+ if (free_space < UFSJ_MEGS_TO_FRAGS(fs, UFSJ_CRITICAL_FREE_SPACE))
+ return 1;
+ else
+ return 0;
}
More information about the p4-projects
mailing list