diff -ur linux.old/fs/reiserfs/bitmap.c linux/fs/reiserfs/bitmap.c --- linux.old/fs/reiserfs/bitmap.c Tue Jan 16 02:31:19 2001 +++ linux/fs/reiserfs/bitmap.c Mon Mar 5 13:20:46 2001 @@ -8,6 +8,7 @@ #include #include #include +#include #else @@ -580,6 +577,12 @@ if (p_s_inode->u.reiserfs_i.i_prealloc_count > 0) { p_s_inode->u.reiserfs_i.i_prealloc_count--; *free_blocknrs = p_s_inode->u.reiserfs_i.i_prealloc_block++; + + /* if no more preallocated blocks, remove inode from list */ + if (! p_s_inode->u.reiserfs_i.i_prealloc_count) { + list_del(&p_s_inode->u.reiserfs_i.i_prealloc_list); + } + return ret; } @@ -633,6 +636,11 @@ *free_blocknrs = p_s_inode->u.reiserfs_i.i_prealloc_block; p_s_inode->u.reiserfs_i.i_prealloc_block++; + /* if inode has preallocated blocks, link him to list */ + if (p_s_inode->u.reiserfs_i.i_prealloc_count) { + list_add(&p_s_inode->u.reiserfs_i.i_prealloc_list, + &SB_JOURNAL(th->t_super)->j_prealloc_list); + } /* we did actually manage to get 1 block */ if (ret != CARRY_ON && allocated[0] > 0) { return CARRY_ON ; @@ -664,16 +672,43 @@ // a portion of this function, was derived from minix or ext2's // analog. You should be able to tell which portion by looking at the // ext2 code and comparing. +static void __discard_prealloc (struct reiserfs_transaction_handle * th, + struct inode * inode) +{ + while (inode->u.reiserfs_i.i_prealloc_count > 0) { + reiserfs_free_block(th,inode->u.reiserfs_i.i_prealloc_block); + inode->u.reiserfs_i.i_prealloc_block++; + inode->u.reiserfs_i.i_prealloc_count --; + } + list_del (&(inode->u.reiserfs_i.i_prealloc_list)); +} + void reiserfs_discard_prealloc (struct reiserfs_transaction_handle *th, struct inode * inode) { - if (inode->u.reiserfs_i.i_prealloc_count > 0) { - while (inode->u.reiserfs_i.i_prealloc_count--) { - reiserfs_free_block(th,inode->u.reiserfs_i.i_prealloc_block); - inode->u.reiserfs_i.i_prealloc_block++; - } - } - inode->u.reiserfs_i.i_prealloc_count = 0; +#ifdef CONFIG_REISERFS_CHECK + if (inode->u.reiserfs_i.i_prealloc_count < 0) + reiserfs_warning("zam-4001:" __FUNCTION__ ": inode has negative prealloc blocks count.\n"); +#endif + if (inode->u.reiserfs_i.i_prealloc_count > 0) { + __discard_prealloc(th, inode); + } +} + +void reiserfs_discard_all_prealloc (struct reiserfs_transaction_handle *th) +{ + struct list_head * plist = &SB_JOURNAL(th->t_super)->j_prealloc_list; + struct inode * inode; + + while (!list_empty(plist)) { + inode = list_entry(plist->next, struct inode, u.reiserfs_i.i_prealloc_list); +#ifdef CONFIG_REISERFS_CHECK + if (!inode->u.reiserfs_i.i_prealloc_count) { + reiserfs_warning("zam-4001:" __FUNCTION__ ": inode is in prealloc list but has no preallocated blocks.\n"); + } +#endif + __discard_prealloc(th, inode); + } } #endif diff -ur linux.old/fs/reiserfs/journal.c linux/fs/reiserfs/journal.c --- linux.old/fs/reiserfs/journal.c Tue Jan 16 02:31:19 2001 +++ linux/fs/reiserfs/journal.c Mon Mar 5 13:31:25 2001 @@ -1927,8 +1927,11 @@ free_journal_ram(p_s_sb) ; return 1 ; } - SB_JOURNAL_LIST_INDEX(p_s_sb) = 0 ; /* once the read is done, we can set this where it belongs */ + SB_JOURNAL_LIST_INDEX(p_s_sb) = 0 ; /* once the read is done, we can set this + where it belongs */ + INIT_LIST_HEAD (&SB_JOURNAL(p_s_sb)->j_prealloc_list); + if (reiserfs_dont_log (p_s_sb)) return 0; @@ -2985,6 +2988,11 @@ flush = 1 ; } +#ifdef REISERFS_PREALLOCATE + reiserfs_discard_all_prealloc(th); /* it should not involve new blocks into + * the transaction */ +#endif + rs = SB_DISK_SUPER_BLOCK(p_s_sb) ; /* setup description block */ d_bh = getblk(p_s_sb->s_dev, reiserfs_get_journal_block(p_s_sb) + SB_JOURNAL(p_s_sb)->j_start, p_s_sb->s_blocksize) ; diff -ur linux.old/include/linux/reiserfs_fs.h linux/include/linux/reiserfs_fs.h --- linux.old/include/linux/reiserfs_fs.h Thu Feb 22 20:04:00 2001 +++ linux/include/linux/reiserfs_fs.h Mon Mar 5 13:20:46 2001 @@ -1950,6 +1972,7 @@ void reiserfs_discard_prealloc (struct reiserfs_transaction_handle *th, struct inode * inode); +void reiserfs_discard_all_prealloc (struct reiserfs_transaction_handle *th); #endif /* hashes.c */ diff -ur linux.old/include/linux/reiserfs_fs_i.h linux/include/linux/reiserfs_fs_i.h --- linux.old/include/linux/reiserfs_fs_i.h Mon Jan 15 23:42:32 2001 +++ linux/include/linux/reiserfs_fs_i.h Mon Mar 5 13:20:46 2001 @@ -1,6 +1,8 @@ #ifndef _REISER_FS_I #define _REISER_FS_I +#include + /* these are used to keep track of the pages that need ** flushing before the current transaction can commit */ @@ -52,7 +54,8 @@ //For preallocation int i_prealloc_block; int i_prealloc_count; - + struct list_head i_prealloc_list; /* per-transaction list of inodes which + * have preallocated blocks */ /* I regret that you think the below is a comment you should make.... -Hans */ //nopack-attribute diff -ur linux.old/include/linux/reiserfs_fs_sb.h linux/include/linux/reiserfs_fs_sb.h --- linux.old/include/linux/reiserfs_fs_sb.h Tue Jan 30 10:24:56 2001 +++ linux/include/linux/reiserfs_fs_sb.h Mon Mar 5 13:20:46 2001 @@ -254,6 +259,7 @@ struct reiserfs_journal_cnode *j_hash_table[JOURNAL_HASH_SIZE] ; /* hash table for real buffer heads in current trans */ struct reiserfs_journal_cnode *j_list_hash_table[JOURNAL_HASH_SIZE] ; /* hash table for all the real buffer heads in all the transactions */ + struct list_head j_prealloc_list; /* list of inodes which have preallocated blocks */ }; #define JOURNAL_DESC_MAGIC "ReIsErLB" /* ick. magic string to find desc blocks in the journal */