Commit bb0d9672 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] reiserfs: data=ordered support

From: Chris Mason <mason@suse.com>

reiserfs data=ordered support.
parent 7c563ced
...@@ -1583,6 +1583,7 @@ int try_to_release_page(struct page *page, int gfp_mask) ...@@ -1583,6 +1583,7 @@ int try_to_release_page(struct page *page, int gfp_mask)
return mapping->a_ops->releasepage(page, gfp_mask); return mapping->a_ops->releasepage(page, gfp_mask);
return try_to_free_buffers(page); return try_to_free_buffers(page);
} }
EXPORT_SYMBOL(try_to_release_page);
/** /**
* block_invalidatepage - invalidate part of all of a buffer-backed page * block_invalidatepage - invalidate part of all of a buffer-backed page
......
This diff is collapsed.
This diff is collapsed.
...@@ -92,6 +92,7 @@ int reiserfs_unpack (struct inode * inode, struct file * filp) ...@@ -92,6 +92,7 @@ int reiserfs_unpack (struct inode * inode, struct file * filp)
int retval = 0; int retval = 0;
int index ; int index ;
struct page *page ; struct page *page ;
struct address_space *mapping ;
unsigned long write_from ; unsigned long write_from ;
unsigned long blocksize = inode->i_sb->s_blocksize ; unsigned long blocksize = inode->i_sb->s_blocksize ;
...@@ -122,17 +123,19 @@ int reiserfs_unpack (struct inode * inode, struct file * filp) ...@@ -122,17 +123,19 @@ int reiserfs_unpack (struct inode * inode, struct file * filp)
** reiserfs_get_block to unpack the tail for us. ** reiserfs_get_block to unpack the tail for us.
*/ */
index = inode->i_size >> PAGE_CACHE_SHIFT ; index = inode->i_size >> PAGE_CACHE_SHIFT ;
page = grab_cache_page(inode->i_mapping, index) ; mapping = inode->i_mapping ;
page = grab_cache_page(mapping, index) ;
retval = -ENOMEM; retval = -ENOMEM;
if (!page) { if (!page) {
goto out ; goto out ;
} }
retval = reiserfs_prepare_write(NULL, page, write_from, blocksize) ; retval = mapping->a_ops->prepare_write(NULL, page, write_from, write_from) ;
if (retval) if (retval)
goto out_unlock ; goto out_unlock ;
/* conversion can change page contents, must flush */ /* conversion can change page contents, must flush */
flush_dcache_page(page) ; flush_dcache_page(page) ;
retval = mapping->a_ops->commit_write(NULL, page, write_from, write_from) ;
REISERFS_I(inode)->i_flags |= i_nopack_mask; REISERFS_I(inode)->i_flags |= i_nopack_mask;
out_unlock: out_unlock:
......
This diff is collapsed.
...@@ -510,6 +510,14 @@ typedef struct { ...@@ -510,6 +510,14 @@ typedef struct {
applied BEFORE setmask */ applied BEFORE setmask */
} opt_desc_t; } opt_desc_t;
/* possible values for -o data= */
static const arg_desc_t logging_mode[] = {
{"ordered", 1<<REISERFS_DATA_ORDERED, (1<<REISERFS_DATA_LOG|1<<REISERFS_DATA_WRITEBACK)},
{"journal", 1<<REISERFS_DATA_LOG, (1<<REISERFS_DATA_ORDERED|1<<REISERFS_DATA_WRITEBACK)},
{"writeback", 1<<REISERFS_DATA_WRITEBACK, (1<<REISERFS_DATA_ORDERED|1<<REISERFS_DATA_LOG)},
{NULL, 0}
};
/* possible values for "-o block-allocator=" and bits which are to be set in /* possible values for "-o block-allocator=" and bits which are to be set in
s_mount_opt of reiserfs specific part of in-core super block */ s_mount_opt of reiserfs specific part of in-core super block */
static const arg_desc_t balloc[] = { static const arg_desc_t balloc[] = {
...@@ -664,6 +672,7 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st ...@@ -664,6 +672,7 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
{"nolog", 0, 0, 0, 0}, /* This is unsupported */ {"nolog", 0, 0, 0, 0}, /* This is unsupported */
{"replayonly", 0, 0, 1<<REPLAYONLY, 0}, {"replayonly", 0, 0, 1<<REPLAYONLY, 0},
{"block-allocator", 'a', balloc, 0, 0}, {"block-allocator", 'a', balloc, 0, 0},
{"data", 'd', logging_mode, 0, 0},
{"resize", 'r', 0, 0, 0}, {"resize", 'r', 0, 0, 0},
{"jdev", 'j', 0, 0, 0}, {"jdev", 'j', 0, 0, 0},
{"nolargeio", 'w', 0, 0, 0}, {"nolargeio", 'w', 0, 0, 0},
...@@ -737,6 +746,33 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st ...@@ -737,6 +746,33 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
return 1; return 1;
} }
static void switch_data_mode(struct super_block *s, unsigned long mode) {
REISERFS_SB(s)->s_mount_opt &= ~((1 << REISERFS_DATA_LOG) |
(1 << REISERFS_DATA_ORDERED) |
(1 << REISERFS_DATA_WRITEBACK));
REISERFS_SB(s)->s_mount_opt |= (1 << mode);
}
static void handle_data_mode(struct super_block *s, unsigned long mount_options)
{
if (mount_options & (1 << REISERFS_DATA_LOG)) {
if (!reiserfs_data_log(s)) {
switch_data_mode(s, REISERFS_DATA_LOG);
printk("reiserfs: switching to journaled data mode\n");
}
} else if (mount_options & (1 << REISERFS_DATA_ORDERED)) {
if (!reiserfs_data_ordered(s)) {
switch_data_mode(s, REISERFS_DATA_ORDERED);
printk("reiserfs: switching to ordered data mode\n");
}
} else if (mount_options & (1 << REISERFS_DATA_WRITEBACK)) {
if (!reiserfs_data_writeback(s)) {
switch_data_mode(s, REISERFS_DATA_WRITEBACK);
printk("reiserfs: switching to writeback data mode\n");
}
}
}
static void handle_attrs( struct super_block *s ) static void handle_attrs( struct super_block *s )
{ {
struct reiserfs_super_block * rs; struct reiserfs_super_block * rs;
...@@ -814,6 +850,7 @@ static int reiserfs_remount (struct super_block * s, int * mount_flags, char * a ...@@ -814,6 +850,7 @@ static int reiserfs_remount (struct super_block * s, int * mount_flags, char * a
if (!(s->s_flags & MS_RDONLY)) if (!(s->s_flags & MS_RDONLY))
return 0; /* We are read-write already */ return 0; /* We are read-write already */
handle_data_mode(s, mount_options);
REISERFS_SB(s)->s_mount_state = sb_umount_state(rs) ; REISERFS_SB(s)->s_mount_state = sb_umount_state(rs) ;
s->s_flags &= ~MS_RDONLY ; /* now it is safe to call journal_begin */ s->s_flags &= ~MS_RDONLY ; /* now it is safe to call journal_begin */
journal_begin(&th, s, 10) ; journal_begin(&th, s, 10) ;
...@@ -1306,6 +1343,21 @@ static int reiserfs_fill_super (struct super_block * s, void * data, int silent) ...@@ -1306,6 +1343,21 @@ static int reiserfs_fill_super (struct super_block * s, void * data, int silent)
SPRINTK(silent, "reiserfs:warning: - it is slow mode for debugging.\n"); SPRINTK(silent, "reiserfs:warning: - it is slow mode for debugging.\n");
#endif #endif
/* make data=ordered the default */
if (!reiserfs_data_log(s) && !reiserfs_data_ordered(s) &&
!reiserfs_data_writeback(s))
{
REISERFS_SB(s)->s_mount_opt |= (1 << REISERFS_DATA_ORDERED);
}
if (reiserfs_data_log(s)) {
printk("reiserfs: using journaled data mode\n");
} else if (reiserfs_data_ordered(s)) {
printk("reiserfs: using ordered data mode\n");
} else {
printk("reiserfs: using writeback data mode\n");
}
// set_device_ro(s->s_dev, 1) ; // set_device_ro(s->s_dev, 1) ;
if( journal_init(s, jdev_name, old_format, commit_max_age) ) { if( journal_init(s, jdev_name, old_format, commit_max_age) ) {
SPRINTK(silent, "sh-2022: reiserfs_fill_super: unable to initialize journal space\n") ; SPRINTK(silent, "sh-2022: reiserfs_fill_super: unable to initialize journal space\n") ;
......
...@@ -1707,6 +1707,15 @@ struct reiserfs_journal_header { ...@@ -1707,6 +1707,15 @@ struct reiserfs_journal_header {
#define journal_getblk(s, block) __getblk(SB_JOURNAL(s)->j_dev_bd, block, s->s_blocksize) #define journal_getblk(s, block) __getblk(SB_JOURNAL(s)->j_dev_bd, block, s->s_blocksize)
#define journal_bread(s, block) __bread(SB_JOURNAL(s)->j_dev_bd, block, s->s_blocksize) #define journal_bread(s, block) __bread(SB_JOURNAL(s)->j_dev_bd, block, s->s_blocksize)
enum reiserfs_bh_state_bits {
BH_JDirty = BH_PrivateStart,
BH_JDirty_wait,
BH_JNew,
BH_JPrepared,
BH_JRestore_dirty,
BH_JTest, // debugging only will go away
};
/* /*
** transaction handle which is passed around for all journal calls ** transaction handle which is passed around for all journal calls
*/ */
...@@ -1726,7 +1735,36 @@ struct reiserfs_transaction_handle { ...@@ -1726,7 +1735,36 @@ struct reiserfs_transaction_handle {
should be displaced from others */ should be displaced from others */
} ; } ;
/* used to keep track of ordered and tail writes, attached to the buffer
* head through b_journal_head.
*/
struct reiserfs_jh {
struct reiserfs_journal_list *jl;
struct buffer_head *bh;
struct list_head list;
};
void reiserfs_free_jh(struct buffer_head *bh);
int reiserfs_add_tail_list(struct inode *inode, struct buffer_head *bh);
int reiserfs_add_ordered_list(struct inode *inode, struct buffer_head *bh);
int journal_mark_dirty(struct reiserfs_transaction_handle *, struct super_block *, struct buffer_head *bh) ; int journal_mark_dirty(struct reiserfs_transaction_handle *, struct super_block *, struct buffer_head *bh) ;
static inline int reiserfs_transaction_running(struct super_block *s) {
struct reiserfs_transaction_handle *th = current->journal_info ;
if (th && th->t_super == s)
return 1 ;
if (th && th->t_super == NULL)
BUG();
return 0 ;
}
int reiserfs_async_progress_wait(struct super_block *s);
struct reiserfs_transaction_handle *
reiserfs_persistent_transaction(struct super_block *, int count);
int reiserfs_end_persistent_transaction(struct reiserfs_transaction_handle *);
int reiserfs_commit_page(struct inode *inode, struct page *page,
unsigned from, unsigned to);
int reiserfs_flush_old_commits(struct super_block *); int reiserfs_flush_old_commits(struct super_block *);
void reiserfs_commit_for_inode(struct inode *) ; void reiserfs_commit_for_inode(struct inode *) ;
void reiserfs_update_inode_transaction(struct inode *) ; void reiserfs_update_inode_transaction(struct inode *) ;
...@@ -1741,7 +1779,6 @@ int journal_release(struct reiserfs_transaction_handle*, struct super_block *) ; ...@@ -1741,7 +1779,6 @@ int journal_release(struct reiserfs_transaction_handle*, struct super_block *) ;
int journal_release_error(struct reiserfs_transaction_handle*, struct super_block *) ; int journal_release_error(struct reiserfs_transaction_handle*, struct super_block *) ;
int journal_end(struct reiserfs_transaction_handle *, struct super_block *, unsigned long) ; int journal_end(struct reiserfs_transaction_handle *, struct super_block *, unsigned long) ;
int journal_end_sync(struct reiserfs_transaction_handle *, struct super_block *, unsigned long) ; int journal_end_sync(struct reiserfs_transaction_handle *, struct super_block *, unsigned long) ;
int journal_mark_dirty_nolog(struct reiserfs_transaction_handle *, struct super_block *, struct buffer_head *bh) ;
int journal_mark_freed(struct reiserfs_transaction_handle *, struct super_block *, b_blocknr_t blocknr) ; int journal_mark_freed(struct reiserfs_transaction_handle *, struct super_block *, b_blocknr_t blocknr) ;
int journal_transaction_should_end(struct reiserfs_transaction_handle *, int) ; int journal_transaction_should_end(struct reiserfs_transaction_handle *, int) ;
int reiserfs_in_journal(struct super_block *p_s_sb, int bmap_nr, int bit_nr, int searchall, b_blocknr_t *next) ; int reiserfs_in_journal(struct super_block *p_s_sb, int bmap_nr, int bit_nr, int searchall, b_blocknr_t *next) ;
...@@ -1749,11 +1786,6 @@ int journal_begin(struct reiserfs_transaction_handle *, struct super_block *p_s_ ...@@ -1749,11 +1786,6 @@ int journal_begin(struct reiserfs_transaction_handle *, struct super_block *p_s_
int buffer_journaled(const struct buffer_head *bh) ; int buffer_journaled(const struct buffer_head *bh) ;
int mark_buffer_journal_new(struct buffer_head *bh) ; int mark_buffer_journal_new(struct buffer_head *bh) ;
int reiserfs_add_page_to_flush_list(struct reiserfs_transaction_handle *,
struct inode *, struct buffer_head *) ;
int reiserfs_remove_page_from_flush_list(struct reiserfs_transaction_handle *,
struct inode *) ;
int reiserfs_allocate_list_bitmaps(struct super_block *s, struct reiserfs_list_bitmap *, int) ; int reiserfs_allocate_list_bitmaps(struct super_block *s, struct reiserfs_list_bitmap *, int) ;
/* why is this kerplunked right here? */ /* why is this kerplunked right here? */
......
...@@ -107,21 +107,6 @@ typedef enum { ...@@ -107,21 +107,6 @@ typedef enum {
#define JOURNAL_HASH_SIZE 8192 #define JOURNAL_HASH_SIZE 8192
#define JOURNAL_NUM_BITMAPS 5 /* number of copies of the bitmaps to have floating. Must be >= 2 */ #define JOURNAL_NUM_BITMAPS 5 /* number of copies of the bitmaps to have floating. Must be >= 2 */
/* these are bh_state bit flag offset numbers, for use in the buffer head */
#define BH_JDirty 16 /* journal data needs to be written before buffer can be marked dirty */
#define BH_JDirty_wait 18 /* commit is done, buffer marked dirty */
#define BH_JNew 19 /* buffer allocated during this transaction, no need to write if freed during this trans too */
/* ugly. metadata blocks must be prepared before they can be logged.
** prepared means unlocked and cleaned. If the block is prepared, but not
** logged for some reason, any bits cleared while preparing it must be
** set again.
*/
#define BH_JPrepared 20 /* block has been prepared for the log */
#define BH_JRestore_dirty 22 /* restore the dirty bit later */
#define BH_JTest 23 /* debugging use only */
/* One of these for every block in every transaction /* One of these for every block in every transaction
** Each one is in two hash tables. First, a hash of the current transaction, and after journal_end, a ** Each one is in two hash tables. First, a hash of the current transaction, and after journal_end, a
** hash of all the in memory transactions. ** hash of all the in memory transactions.
...@@ -178,6 +163,11 @@ struct reiserfs_journal_list { ...@@ -178,6 +163,11 @@ struct reiserfs_journal_list {
/* time ordered list of all transactions we haven't tried to flush yet */ /* time ordered list of all transactions we haven't tried to flush yet */
struct list_head j_working_list; struct list_head j_working_list;
/* list of tail conversion targets in need of flush before commit */
struct list_head j_tail_bh_list;
/* list of data=ordered buffers in need of flush before commit */
struct list_head j_bh_list;
int j_refcount; int j_refcount;
} ; } ;
...@@ -253,7 +243,9 @@ struct reiserfs_journal { ...@@ -253,7 +243,9 @@ struct reiserfs_journal {
unsigned long j_max_trans_size ; unsigned long j_max_trans_size ;
unsigned long j_max_batch_size ; unsigned long j_max_batch_size ;
/* when flushing ordered buffers, throttle new ordered writers */
struct work_struct j_work; struct work_struct j_work;
atomic_t j_async_throttle;
}; };
#define JOURNAL_DESC_MAGIC "ReIsErLB" /* ick. magic string to find desc blocks in the journal */ #define JOURNAL_DESC_MAGIC "ReIsErLB" /* ick. magic string to find desc blocks in the journal */
...@@ -408,11 +400,12 @@ struct reiserfs_sb_info ...@@ -408,11 +400,12 @@ struct reiserfs_sb_info
#define REISERFS_3_5 0 #define REISERFS_3_5 0
#define REISERFS_3_6 1 #define REISERFS_3_6 1
enum reiserfs_mount_options {
/* Mount options */ /* Mount options */
#define REISERFS_LARGETAIL 0 /* large tails will be created in a session */ REISERFS_LARGETAIL, /* large tails will be created in a session */
#define REISERFS_SMALLTAIL 17 /* small (for files less than block size) tails will be created in a session */ REISERFS_SMALLTAIL, /* small (for files less than block size) tails will be created in a session */
#define REPLAYONLY 3 /* replay journal and return 0. Use by fsck */ REPLAYONLY, /* replay journal and return 0. Use by fsck */
#define REISERFS_CONVERT 5 /* -o conv: causes conversion of old REISERFS_CONVERT, /* -o conv: causes conversion of old
format super block to the new format super block to the new
format. If not specified - old format. If not specified - old
partition will be dealt with in a partition will be dealt with in a
...@@ -426,26 +419,29 @@ struct reiserfs_sb_info ...@@ -426,26 +419,29 @@ struct reiserfs_sb_info
** the existing hash on the FS, so if you have a tea hash disk, and mount ** the existing hash on the FS, so if you have a tea hash disk, and mount
** with -o hash=rupasov, the mount will fail. ** with -o hash=rupasov, the mount will fail.
*/ */
#define FORCE_TEA_HASH 6 /* try to force tea hash on mount */ FORCE_TEA_HASH, /* try to force tea hash on mount */
#define FORCE_RUPASOV_HASH 7 /* try to force rupasov hash on mount */ FORCE_RUPASOV_HASH, /* try to force rupasov hash on mount */
#define FORCE_R5_HASH 8 /* try to force rupasov hash on mount */ FORCE_R5_HASH, /* try to force rupasov hash on mount */
#define FORCE_HASH_DETECT 9 /* try to detect hash function on mount */ FORCE_HASH_DETECT, /* try to detect hash function on mount */
REISERFS_DATA_LOG,
REISERFS_DATA_ORDERED,
REISERFS_DATA_WRITEBACK,
/* used for testing experimental features, makes benchmarking new /* used for testing experimental features, makes benchmarking new
features with and without more convenient, should never be used by features with and without more convenient, should never be used by
users in any code shipped to users (ideally) */ users in any code shipped to users (ideally) */
#define REISERFS_NO_BORDER 11 REISERFS_NO_BORDER,
#define REISERFS_NO_UNHASHED_RELOCATION 12 REISERFS_NO_UNHASHED_RELOCATION,
#define REISERFS_HASHED_RELOCATION 13 REISERFS_HASHED_RELOCATION,
REISERFS_ATTRS,
#define REISERFS_ATTRS 15
#define REISERFS_TEST1 11 REISERFS_TEST1,
#define REISERFS_TEST2 12 REISERFS_TEST2,
#define REISERFS_TEST3 13 REISERFS_TEST3,
#define REISERFS_TEST4 14 REISERFS_TEST4,
};
#define reiserfs_r5_hash(s) (REISERFS_SB(s)->s_mount_opt & (1 << FORCE_R5_HASH)) #define reiserfs_r5_hash(s) (REISERFS_SB(s)->s_mount_opt & (1 << FORCE_R5_HASH))
#define reiserfs_rupasov_hash(s) (REISERFS_SB(s)->s_mount_opt & (1 << FORCE_RUPASOV_HASH)) #define reiserfs_rupasov_hash(s) (REISERFS_SB(s)->s_mount_opt & (1 << FORCE_RUPASOV_HASH))
...@@ -459,11 +455,12 @@ struct reiserfs_sb_info ...@@ -459,11 +455,12 @@ struct reiserfs_sb_info
#define have_large_tails(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_LARGETAIL)) #define have_large_tails(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_LARGETAIL))
#define have_small_tails(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_SMALLTAIL)) #define have_small_tails(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_SMALLTAIL))
#define replay_only(s) (REISERFS_SB(s)->s_mount_opt & (1 << REPLAYONLY)) #define replay_only(s) (REISERFS_SB(s)->s_mount_opt & (1 << REPLAYONLY))
#define reiserfs_dont_log(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_NOLOG))
#define reiserfs_attrs(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_ATTRS)) #define reiserfs_attrs(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_ATTRS))
#define old_format_only(s) (REISERFS_SB(s)->s_properties & (1 << REISERFS_3_5)) #define old_format_only(s) (REISERFS_SB(s)->s_properties & (1 << REISERFS_3_5))
#define convert_reiserfs(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_CONVERT)) #define convert_reiserfs(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_CONVERT))
#define reiserfs_data_log(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_LOG))
#define reiserfs_data_ordered(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_ORDERED))
#define reiserfs_data_writeback(s) (REISERFS_SB(s)->s_mount_opt & (1 << REISERFS_DATA_WRITEBACK))
void reiserfs_file_buffer (struct buffer_head * bh, int list); void reiserfs_file_buffer (struct buffer_head * bh, int list);
extern struct file_system_type reiserfs_fs_type; extern struct file_system_type reiserfs_fs_type;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment