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)
return mapping->a_ops->releasepage(page, gfp_mask);
return try_to_free_buffers(page);
}
EXPORT_SYMBOL(try_to_release_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)
int retval = 0;
int index ;
struct page *page ;
struct address_space *mapping ;
unsigned long write_from ;
unsigned long blocksize = inode->i_sb->s_blocksize ;
......@@ -122,17 +123,19 @@ int reiserfs_unpack (struct inode * inode, struct file * filp)
** reiserfs_get_block to unpack the tail for us.
*/
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;
if (!page) {
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)
goto out_unlock ;
/* conversion can change page contents, must flush */
flush_dcache_page(page) ;
retval = mapping->a_ops->commit_write(NULL, page, write_from, write_from) ;
REISERFS_I(inode)->i_flags |= i_nopack_mask;
out_unlock:
......
This diff is collapsed.
......@@ -510,6 +510,14 @@ typedef struct {
applied BEFORE setmask */
} 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
s_mount_opt of reiserfs specific part of in-core super block */
static const arg_desc_t balloc[] = {
......@@ -664,6 +672,7 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
{"nolog", 0, 0, 0, 0}, /* This is unsupported */
{"replayonly", 0, 0, 1<<REPLAYONLY, 0},
{"block-allocator", 'a', balloc, 0, 0},
{"data", 'd', logging_mode, 0, 0},
{"resize", 'r', 0, 0, 0},
{"jdev", 'j', 0, 0, 0},
{"nolargeio", 'w', 0, 0, 0},
......@@ -737,6 +746,33 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
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 )
{
struct reiserfs_super_block * rs;
......@@ -814,6 +850,7 @@ static int reiserfs_remount (struct super_block * s, int * mount_flags, char * a
if (!(s->s_flags & MS_RDONLY))
return 0; /* We are read-write already */
handle_data_mode(s, mount_options);
REISERFS_SB(s)->s_mount_state = sb_umount_state(rs) ;
s->s_flags &= ~MS_RDONLY ; /* now it is safe to call journal_begin */
journal_begin(&th, s, 10) ;
......@@ -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");
#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) ;
if( journal_init(s, jdev_name, old_format, commit_max_age) ) {
SPRINTK(silent, "sh-2022: reiserfs_fill_super: unable to initialize journal space\n") ;
......
......@@ -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_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
*/
......@@ -1726,7 +1735,36 @@ struct reiserfs_transaction_handle {
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) ;
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 *);
void reiserfs_commit_for_inode(struct inode *) ;
void reiserfs_update_inode_transaction(struct inode *) ;
......@@ -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_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_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_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) ;
......@@ -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 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) ;
/* why is this kerplunked right here? */
......
......@@ -107,21 +107,6 @@ typedef enum {
#define JOURNAL_HASH_SIZE 8192
#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
** 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.
......@@ -178,6 +163,11 @@ struct reiserfs_journal_list {
/* time ordered list of all transactions we haven't tried to flush yet */
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;
} ;
......@@ -253,7 +243,9 @@ struct reiserfs_journal {
unsigned long j_max_trans_size ;
unsigned long j_max_batch_size ;
/* when flushing ordered buffers, throttle new ordered writers */
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 */
......@@ -408,11 +400,12 @@ struct reiserfs_sb_info
#define REISERFS_3_5 0
#define REISERFS_3_6 1
enum reiserfs_mount_options {
/* Mount options */
#define REISERFS_LARGETAIL 0 /* 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 */
#define REPLAYONLY 3 /* replay journal and return 0. Use by fsck */
#define REISERFS_CONVERT 5 /* -o conv: causes conversion of old
REISERFS_LARGETAIL, /* large tails will be created in a session */
REISERFS_SMALLTAIL, /* small (for files less than block size) tails will be created in a session */
REPLAYONLY, /* replay journal and return 0. Use by fsck */
REISERFS_CONVERT, /* -o conv: causes conversion of old
format super block to the new
format. If not specified - old
partition will be dealt with in a
......@@ -426,26 +419,29 @@ struct reiserfs_sb_info
** the existing hash on the FS, so if you have a tea hash disk, and mount
** with -o hash=rupasov, the mount will fail.
*/
#define FORCE_TEA_HASH 6 /* try to force tea hash on mount */
#define FORCE_RUPASOV_HASH 7 /* try to force rupasov hash on mount */
#define FORCE_R5_HASH 8 /* try to force rupasov hash on mount */
#define FORCE_HASH_DETECT 9 /* try to detect hash function on mount */
FORCE_TEA_HASH, /* try to force tea hash on mount */
FORCE_RUPASOV_HASH, /* try to force rupasov hash on mount */
FORCE_R5_HASH, /* try to force rupasov hash 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
features with and without more convenient, should never be used by
users in any code shipped to users (ideally) */
#define REISERFS_NO_BORDER 11
#define REISERFS_NO_UNHASHED_RELOCATION 12
#define REISERFS_HASHED_RELOCATION 13
#define REISERFS_ATTRS 15
REISERFS_NO_BORDER,
REISERFS_NO_UNHASHED_RELOCATION,
REISERFS_HASHED_RELOCATION,
REISERFS_ATTRS,
#define REISERFS_TEST1 11
#define REISERFS_TEST2 12
#define REISERFS_TEST3 13
#define REISERFS_TEST4 14
REISERFS_TEST1,
REISERFS_TEST2,
REISERFS_TEST3,
REISERFS_TEST4,
};
#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))
......@@ -459,11 +455,12 @@ struct reiserfs_sb_info
#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 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 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 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);
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