Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 24 Aug 2005 05:05:49 GMT
From:      soc-polytopes <soc-polytopes@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 82487 for review
Message-ID:  <200508240505.j7O55nim010300@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=82487

Change 82487 by soc-polytopes@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;
 }
 
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200508240505.j7O55nim010300>