afs/fs/cachefs super.c,1.32,1.33 recycling.c,1.21,1.22
journal.c,1.35,1.36 index.c,1.22,1.23 cachefs-int.h,1.35,1.36
aops.c,1.36,1.37
dwh at infradead.org
dwh at infradead.org
Wed Jun 11 13:59:55 BST 2003
Update of /home/cvs/afs/fs/cachefs
In directory phoenix.infradead.org:/tmp/cvs-serv9041/fs/cachefs
Modified Files:
super.c recycling.c journal.c index.c cachefs-int.h aops.c
Log Message:
fix some data integrity problems
Index: super.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/super.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- super.c 10 Jun 2003 17:49:49 -0000 1.32
+++ super.c 11 Jun 2003 11:59:52 -0000 1.33
@@ -299,6 +299,7 @@
INIT_LIST_HEAD(&super->jnld_link);
init_MUTEX(&super->batch_sem);
+ init_MUTEX(&super->batch_uj_sem);
init_rwsem(&super->batch_ctrl_sem);
spin_lock_init(&super->batch_qlock);
INIT_LIST_HEAD(&super->batch_writeq);
@@ -737,7 +738,7 @@
}
super->dmn_die = 1;
- cachefs_trans_sync(super,1);
+ cachefs_trans_sync(super,CACHEFS_TRANS_SYNC_WAIT_FOR_ACK);
super->dmn_die = 2;
wake_up(&super->dmn_sleepq);
Index: recycling.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/recycling.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- recycling.c 2 Jun 2003 09:17:42 -0000 1.21
+++ recycling.c 11 Jun 2003 11:59:52 -0000 1.22
@@ -340,6 +340,7 @@
{
struct cachefs_ondisc_free_node *node;
struct cachefs_transaction *trans;
+ struct cachefs_block *block;
cachefs_blockix_t *indirect, *jeptr;
struct page *page;
unsigned limit, count, src, dst, max;
@@ -402,12 +403,17 @@
if (indirect[src]) {
jeptr[count] = indirect[src];
count++;
+
+ if (cachefs_block_find(super,jeptr[count],&block) == 0) {
+ clear_bit(CACHEFS_BLOCK_NETFSDATA,&block->flags);
+ cachefs_block_put(block);
+ }
}
src++;
}
- trans->jentry->count = count;
+ trans->jentry->count = count;
ret = cachefs_trans_mark(trans);
if (ret<0) {
@@ -829,7 +835,7 @@
struct cachefs_ondisc_free_node *node;
struct cachefs_transaction *trans;
struct cachefs_vj_entry *vjentry;
- struct cachefs_block *rcyblock = NULL, *upblock = NULL;
+ struct cachefs_block *rcyblock = NULL, *upblock = NULL, *block;
struct page *rcypage = NULL, *uppage = NULL;
int ret;
@@ -863,6 +869,11 @@
cachefs_trans_affects_block(trans,vjentry->vblock,vjentry->ventry,
sizeof(struct cachefs_ondisc_validity_journal));
+
+ if (cachefs_block_find(super,vjentry->bix,&block) == 0) {
+ clear_bit(CACHEFS_BLOCK_NETFSDATA,&block->flags);
+ cachefs_block_put(block);
+ }
if (super->recycle_room==0) {
/* we have to generate a new recycling node */
Index: journal.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/journal.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -r1.35 -r1.36
--- journal.c 10 Jun 2003 17:49:49 -0000 1.35
+++ journal.c 11 Jun 2003 11:59:52 -0000 1.36
@@ -23,7 +23,7 @@
unsigned short batch_end; /* batch mark sector for ujnl_batch */
unsigned short batch_ack; /* batch ACK sector for ujnl_batch */
unsigned short batch_count; /* number of marks in batch */
- unsigned ack_hi; /* highest batch with ACK number */
+ int16_t ack_hi; /* highest batch with ACK number */
};
const char *cachefs_ondisc_ujnl_marks[] = {
@@ -489,6 +489,7 @@
_enter("");
down(&super->batch_sem);
+ down(&super->batch_uj_sem);
spin_lock_irqsave(&super->ujnl_mk_lock,flags);
del_timer_sync(&super->batch_timer);
@@ -525,10 +526,18 @@
BUG_ON(!block->page->private);
if (!test_bit(CACHEFS_BLOCK_WRITEBACK,&block->flags)) {
+ struct list_head *plist;
+
set_bit(CACHEFS_BLOCK_COW ,&block->flags);
set_bit(CACHEFS_BLOCK_WRITEBACK ,&block->flags);
- list_add_tail(&block->batch_link,&super->batch_writeq);
+ plist = &super->batch_writeq;
+ if (test_bit(CACHEFS_BLOCK_NETFSDATA,&block->flags)) {
+ plist = &super->batch_doneq;
+ kdebug("skip meta block %u",block->bix);
+ }
+
+ list_add_tail(&block->batch_link,plist);
block->writeback = block->page;
get_page(block->writeback);
flush_dcache_page(block->writeback);
@@ -773,6 +782,7 @@
bfirst = rb_entry(_n,struct cachefs_block,lookup_node);
if (!test_bit(CACHEFS_BLOCK_WRITEBACK,&bfirst->flags) ||
+ test_bit(CACHEFS_BLOCK_NETFSDATA,&bfirst->flags) ||
test_bit(CACHEFS_BLOCK_UJOURNAL,&bfirst->flags))
goto next_first;
@@ -1187,6 +1197,7 @@
*/
static int cachefs_trans_marker_written(struct bio *bio, unsigned int bytes_done, int error)
{
+ struct cachefs_super *super;
struct cachefs_block *block;
_enter("%p{%u},%u,%d",bio,bio->bi_size,bytes_done,error);
@@ -1198,12 +1209,16 @@
block = bio->bi_private;
- /* mark the block appropriately */
+ /* let critical blocks be reused for netfs data caching */
+ super = block->super;
+ up(&super->batch_uj_sem);
+
if (!test_bit(BIO_UPTODATE,&bio->bi_flags))
set_bit(CACHEFS_BLOCK_ERROR,&block->flags);
page_cache_release(bio->bi_io_vec[0].bv_page);
bio_put(bio);
+
_leave(" = 0");
return 0;
} /* end cachefs_trans_marker_written() */
@@ -1242,16 +1257,16 @@
/*
* synchronise by forcing a batch write to occur and then maybe waiting for it to be ACK'd on disc
*/
-void cachefs_trans_sync(struct cachefs_super *super, int wait)
+void cachefs_trans_sync(struct cachefs_super *super, cachefs_trans_syncwt_t wait)
{
int16_t next_batch;
DECLARE_WAITQUEUE(myself,current);
- kenter("{batch=%hd}",super->ujnl_batch);
+ kenter("{batch=%hd},%d",super->ujnl_batch,wait);
/* if we're not supposed to wait, just induce consideration of a batch write */
- if (!wait) {
+ if (wait == CACHEFS_TRANS_SYNC_NOWAIT) {
set_bit(CACHEFS_SUPER_BATCH_TIMER,&super->flags);
wake_up_all(&super->batch_timer_wq);
kleave("");
@@ -1267,7 +1282,7 @@
}
else {
/* transactions present - must wait till pending batch is written */
- next_batch = super->ujnl_batch + 1;
+ next_batch = super->ujnl_batch + 1;
set_bit(CACHEFS_SUPER_BATCH_TIMER,&super->flags);
wake_up_all(&super->batch_timer_wq);
@@ -1288,8 +1303,14 @@
}
/* now we have to wait for any currently active batch write */
- down(&super->batch_sem);
- up(&super->batch_sem);
+ if (wait==CACHEFS_TRANS_SYNC_WAIT_FOR_MARK) {
+ down(&super->batch_uj_sem);
+ up(&super->batch_uj_sem);
+ }
+ else {
+ down(&super->batch_sem);
+ up(&super->batch_sem);
+ }
kleave("");
} /* end cachefs_trans_sync() */
@@ -1410,13 +1431,14 @@
super->rcm_indirect = jentry->rcm_indirect;
super->rcm_ino = jentry->rcm_ino;
- desc->ack_hi = jentry->batch;
-
- kdebug("UJNL[%u] ACK %u { a=%u[%u] r=%u R=%u:%u:%u[%u-%u]",
- slot,desc->ack_hi,
+ kdebug("UJNL[%u] ACK %u { a=%u[%u] r=%u R=%u:%u:%u[%u-%u] } hi=%u",
+ slot,jentry->batch,
super->alloc_leaf,super->alloc_cur,super->recycle_cur,
super->rcm_ino,super->rcm_indirect,super->rcm_block,
- super->rcm_ptrnext,super->rcm_ptrstop);
+ super->rcm_ptrnext,super->rcm_ptrstop,
+ desc->ack_hi);
+
+ desc->ack_hi = jentry->batch;
}
else {
kdebug("UJNL[%u] ACK %u { hi=%u }",
@@ -1656,6 +1678,8 @@
}
dbgpgalloc(super->alloc_node);
+
+ set_bit(CACHEFS_BLOCK_CRITICAL,&super->alloc_block->flags);
wait_on_page_locked(super->alloc_node);
node = kmap(super->alloc_node);
Index: index.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/index.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- index.c 10 Jun 2003 17:49:49 -0000 1.22
+++ index.c 11 Jun 2003 11:59:52 -0000 1.23
@@ -277,7 +277,8 @@
BUG_ON(newentry==UINT_MAX);
// _debug("syncing");
-// cachefs_trans_sync(iinode->vfs_inode.i_sb->s_fs_info,1);
+// cachefs_trans_sync(iinode->vfs_inode.i_sb->s_fs_info,
+// CACHEFS_TRANS_SYNC_WAIT_FOR_ACK);
_debug("done");
}
/* get the page holding the next free entry */
Index: cachefs-int.h
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/cachefs-int.h,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -r1.35 -r1.36
--- cachefs-int.h 3 Jun 2003 17:45:27 -0000 1.35
+++ cachefs-int.h 11 Jun 2003 11:59:52 -0000 1.36
@@ -71,12 +71,12 @@
struct inode *imisc; /* an inode covering the whole blkdev */
unsigned long flags;
-#define CACHEFS_SUPER_INIT_BLKDEV 0 /* true if initialising blockdev */
-#define CACHEFS_SUPER_BATCH_TIMER 1 /* true if batch timer expired */
-#define CACHEFS_SUPER_DO_RECLAIM 2 /* true if should do reclamation */
-#define CACHEFS_SUPER_RCM_IMM_SCAN 3 /* true if should scan for immediately
+#define CACHEFS_SUPER_INIT_BLKDEV 0 /* T if initialising blockdev */
+#define CACHEFS_SUPER_BATCH_TIMER 1 /* T if batch timer expired */
+#define CACHEFS_SUPER_DO_RECLAIM 2 /* T if should do reclamation */
+#define CACHEFS_SUPER_RCM_IMM_SCAN 3 /* T if should scan for immediately
* reclaimable inodes */
-#define CACHEFS_SUPER_WITHDRAWN 4 /* true if cache has been withdrawn */
+#define CACHEFS_SUPER_WITHDRAWN 4 /* T if cache has been withdrawn */
/* index management */
struct list_head ino_list; /* list of data/index inodes */
@@ -145,6 +145,7 @@
struct list_head ujnl_ackwq; /* marks awaiting on-disc ACK */
struct semaphore batch_sem; /* batching mutex */
+ struct semaphore batch_uj_sem; /* ujnl written sync mutex */
struct rw_semaphore batch_ctrl_sem; /* marking/batching interleave control */
spinlock_t batch_qlock;
struct list_head batch_writeq; /* blocks awaiting writing */
@@ -230,9 +231,10 @@
#define CACHEFS_BLOCK_ERROR 4 /* [bit] block has disc error */
#define CACHEFS_BLOCK_UJOURNAL 5 /* [bit] block holds update journal entries */
#define CACHEFS_BLOCK_CRITICAL 6 /* [bit] block holds critical data that mustn't be
- * zapped until sync'd */
+ * zapped until u-journal sync'd */
#define CACHEFS_BLOCK_WITHDRAWN 7 /* [bit] backing cache withdrawn from service */
-#define CACHEFS_BLOCK_NETFSBUSY 8 /* [bit] netfs is accessing the block */
+#define CACHEFS_BLOCK_NETFSDATA 8 /* [bit] netfs data block (discard metadata) */
+#define CACHEFS_BLOCK_NETFSBUSY 9 /* [bit] netfs is accessing the block */
#define _CACHEFS_BLOCK_ALLOC (1 << CACHEFS_BLOCK_ALLOC)
#define _CACHEFS_BLOCK_COW (1 << CACHEFS_BLOCK_COW)
@@ -595,7 +597,14 @@
extern void cachefs_trans_cancel(struct cachefs_transaction *trans);
extern void cachefs_trans_batch_write(struct cachefs_super *super);
extern void cachefs_trans_batch_timer(unsigned long data);
-extern void cachefs_trans_sync(struct cachefs_super *super, int wait);
+
+typedef enum {
+ CACHEFS_TRANS_SYNC_NOWAIT, /* don't wait - just begin write */
+ CACHEFS_TRANS_SYNC_WAIT_FOR_MARK, /* wait until ujnl BATCH mark is written */
+ CACHEFS_TRANS_SYNC_WAIT_FOR_ACK, /* wait until ujnl ACK mark is written */
+} cachefs_trans_syncwt_t;
+
+extern void cachefs_trans_sync(struct cachefs_super *super, cachefs_trans_syncwt_t wait);
extern int cachefs_ujnl_replay(struct cachefs_super *super);
Index: aops.c
===================================================================
RCS file: /home/cvs/afs/fs/cachefs/aops.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -r1.36 -r1.37
--- aops.c 10 Jun 2003 17:49:49 -0000 1.36
+++ aops.c 11 Jun 2003 11:59:52 -0000 1.37
@@ -39,8 +39,7 @@
#define CACHEFS_BLOCK_WRITTEN 0x00000004
#define CACHEFS_BLOCK_INIT_INDIRECT 0x00000008
#define CACHEFS_BLOCK_INIT_INDEX 0x00000010
-#define CACHEFS_BLOCK_INIT_DATA 0x00000020
-#define CACHEFS_BLOCK_NEED_SYNC 0x00000040
+#define CACHEFS_BLOCK_INIT_NETFSDATA 0x00000020
/* ujournal marks for allocation journalling entries */
enum cachefs_ondisc_ujnl_mark mktype : 8;
@@ -921,7 +920,7 @@
}
/* freshly allocated data blocks must be recorded in the v-journal */
- if (step->flags & CACHEFS_BLOCK_INIT_DATA) {
+ if (step->flags & CACHEFS_BLOCK_INIT_NETFSDATA) {
_debug("init data");
ret = cachefs_vj_alloc(step->transaction,inode);
@@ -1035,7 +1034,8 @@
if (cachefs_trans_mark(step->transaction)<0)
goto error_block;
- if (step->flags & CACHEFS_BLOCK_INIT_DATA) {
+ if (step->flags & CACHEFS_BLOCK_INIT_NETFSDATA) {
+ set_bit(CACHEFS_BLOCK_NETFSDATA,&block->flags);
block->vjentry = step->transaction->vjentry;
block->vjentry->bix = block->bix;
}
@@ -1101,12 +1101,15 @@
cachefs_trans_commit(step->transaction);
step->transaction = NULL;
- /* synchronise after committing (so our allocation will be sync'd before block reuse) */
- if ((step->flags & CACHEFS_BLOCK_NEED_SYNC) &&
+ /* the allocation must be journalled before journalling-independent
+ * writes are permitted to modify a reused metadata block that had
+ * critical data on it
+ */
+ if ((step->flags & CACHEFS_BLOCK_INIT_NETFSDATA) &&
test_bit(CACHEFS_BLOCK_CRITICAL,&block->flags)
) {
- cachefs_trans_sync(super,0);
- // TODO: wait for CRITICAL to be unset
+ cachefs_trans_sync(super,CACHEFS_TRANS_SYNC_WAIT_FOR_MARK);
+ clear_bit(CACHEFS_BLOCK_CRITICAL,&block->flags);
}
cachefs_block_put(block);
@@ -1167,7 +1170,7 @@
path[2].mktype = CACHEFS_ONDISC_UJNL_INDIRECT_ALLOCING;
path[1].mktype = CACHEFS_ONDISC_UJNL_INDIRECT_ALLOCING;
path[0].mktype = CACHEFS_ONDISC_UJNL_DATA_ALLOCING;
- path[0].flags = CACHEFS_BLOCK_INIT_DATA;
+ path[0].flags = CACHEFS_BLOCK_INIT_NETFSDATA;
if (inode->index_esize) {
path[0].mktype = CACHEFS_ONDISC_UJNL_INDEX_EXTENDING;
@@ -1343,6 +1346,9 @@
cachefs_block_put(block);
_leave(" = %d",ret);
return ret;
+ }
+ else if (path[0].flags & CACHEFS_BLOCK_INIT_NETFSDATA) {
+ set_bit(CACHEFS_BLOCK_NETFSDATA,&pageio->mapped_block->flags);
}
/* got the block - set the block offset in the page mapping record */
More information about the linux-afs-cvs
mailing list