Skip to content

Commit

Permalink
patch standalone_next3_module.patch
Browse files Browse the repository at this point in the history
  • Loading branch information
Amir Goldstein committed Jul 13, 2010
1 parent d7b662e commit 479fcab
Show file tree
Hide file tree
Showing 17 changed files with 261 additions and 281 deletions.
128 changes: 0 additions & 128 deletions fs/buffer.c
Expand Up @@ -16,8 +16,6 @@
* Added 32k buffer block sizes - these are required older ARM systems. - RMK
*
* async buffer flushing, 1999 Andrea Arcangeli <andrea@suse.de>
*
* Tracked buffer read for Next3, Amir Goldstein <amir73il@users.sf.net>, 2008
*/

#include <linux/kernel.h>
Expand Down Expand Up @@ -296,123 +294,6 @@ static void free_more_memory(void)
}
}

#ifdef CONFIG_NEXT3_FS_SNAPSHOT_RACE_READ
/*
* Tracked read functions.
* When reading through a next3 snapshot file hole to a block device block,
* all writes to this block need to wait for completion of the async read.
* next3_snapshot_readpage() always calls block_read_full_page() to attach
* a buffer head to the page and be aware of tracked reads.
* next3_snapshot_get_block() calls start_buffer_tracked_read() to mark both
* snapshot page buffer and block device page buffer.
* next3_snapshot_get_block() calls cancel_buffer_tracked_read() if snapshot
* doesn't need to read through to the block device.
* block_read_full_page() calls submit_buffer_tracked_read() to submit a
* tracked async read.
* end_buffer_async_read() calls end_buffer_tracked_read() to complete the
* tracked read operation.
* The only lock needed in all these functions is PageLock on the snapshot page,
* which is guarantied in readpage() and verified in block_read_full_page().
* The block device page buffer doesn't need any lock because the operations
* {get|put}_bh_tracked_reader() are atomic.
*/

/*
* start buffer tracked read
* called from inside get_block()
* get tracked reader ref count on buffer cache entry
* and set buffer tracked read flag
*/
int start_buffer_tracked_read(struct buffer_head *bh)
{
struct buffer_head *bdev_bh;

BUG_ON(buffer_tracked_read(bh));
BUG_ON(!buffer_mapped(bh));

/* grab the buffer cache entry */
bdev_bh = __getblk(bh->b_bdev, bh->b_blocknr, bh->b_size);
if (!bdev_bh)
return -EIO;

BUG_ON(bdev_bh == bh);
set_buffer_tracked_read(bh);
get_bh_tracked_reader(bdev_bh);
put_bh(bdev_bh);
return 0;
}
EXPORT_SYMBOL_GPL(start_buffer_tracked_read);

/*
* cancel buffer tracked read
* called for tracked read that was started but was not submitted
* put tracked reader ref count on buffer cache entry
* and clear buffer tracked read flag
*/
void cancel_buffer_tracked_read(struct buffer_head *bh)
{
struct buffer_head *bdev_bh;

BUG_ON(!buffer_tracked_read(bh));
BUG_ON(!buffer_mapped(bh));

/* try to grab the buffer cache entry */
bdev_bh = __find_get_block(bh->b_bdev, bh->b_blocknr, bh->b_size);
BUG_ON(!bdev_bh || bdev_bh == bh);
clear_buffer_tracked_read(bh);
clear_buffer_mapped(bh);
put_bh_tracked_reader(bdev_bh);
put_bh(bdev_bh);
}
EXPORT_SYMBOL_GPL(cancel_buffer_tracked_read);

/*
* submit buffer tracked read
* save a reference to buffer cache entry and submit I/O
*/
static int submit_buffer_tracked_read(struct buffer_head *bh)
{
struct buffer_head *bdev_bh;
BUG_ON(!buffer_tracked_read(bh));
BUG_ON(!buffer_mapped(bh));
/* tracked read doesn't work with multiple buffers per page */
BUG_ON(bh->b_this_page != bh);

/*
* Try to grab the buffer cache entry before submitting async read
* because we cannot call blocking function __find_get_block()
* in interrupt context inside end_buffer_tracked_read().
*/
bdev_bh = __find_get_block(bh->b_bdev, bh->b_blocknr, bh->b_size);
BUG_ON(!bdev_bh || bdev_bh == bh);
/* override page buffers list with reference to buffer cache entry */
bh->b_this_page = bdev_bh;
submit_bh(READ, bh);
return 0;
}

/*
* end buffer tracked read
* complete submitted tracked read
*/
static void end_buffer_tracked_read(struct buffer_head *bh)
{
struct buffer_head *bdev_bh = bh->b_this_page;

BUG_ON(!buffer_tracked_read(bh));
BUG_ON(!bdev_bh || bdev_bh == bh);
bh->b_this_page = bh;
/*
* clear the buffer mapping to make sure
* that get_block() will always be called
*/
clear_buffer_mapped(bh);
clear_buffer_tracked_read(bh);
put_bh_tracked_reader(bdev_bh);
put_bh(bdev_bh);
}

#endif
/*
* I/O completion handler for block_read_full_page() - pages
* which come unlocked at the end of I/O.
Expand All @@ -427,11 +308,6 @@ static void end_buffer_async_read(struct buffer_head *bh, int uptodate)

BUG_ON(!buffer_async_read(bh));

#ifdef CONFIG_NEXT3_FS_SNAPSHOT_RACE_READ
if (buffer_tracked_read(bh))
end_buffer_tracked_read(bh);

#endif
page = bh->b_page;
if (uptodate) {
set_buffer_uptodate(bh);
Expand Down Expand Up @@ -2335,10 +2211,6 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
*/
for (i = 0; i < nr; i++) {
bh = arr[i];
#ifdef CONFIG_NEXT3_FS_SNAPSHOT_RACE_READ
if (buffer_tracked_read(bh))
return submit_buffer_tracked_read(bh);
#endif
if (buffer_uptodate(bh))
end_buffer_async_read(bh, 1);
else
Expand Down
5 changes: 5 additions & 0 deletions fs/jbd/journal.c
Expand Up @@ -1903,6 +1903,11 @@ void journal_put_journal_head(struct journal_head *jh)
u8 journal_enable_debug __read_mostly;
EXPORT_SYMBOL(journal_enable_debug);

#ifdef CONFIG_NEXT3_FS_SNAPSHOT_JOURNAL_TRACE
const u8 journal_handle_size = sizeof(handle_t);
EXPORT_SYMBOL(journal_handle_size);

#endif
static struct dentry *jbd_debugfs_dir;
static struct dentry *jbd_debug;

Expand Down
4 changes: 2 additions & 2 deletions fs/next3/Kconfig
@@ -1,6 +1,6 @@
config NEXT3_FS
tristate "Next3 journalling file system support"
select JBD
depends on JBD
help
This is the journalling version of the Second extended file system
(often called next3), the de facto standard Linux file system
Expand Down Expand Up @@ -65,7 +65,7 @@ config NEXT3_FS_XATTR
config NEXT3_FS_POSIX_ACL
bool "Next3 POSIX Access Control Lists"
depends on NEXT3_FS_XATTR
select FS_POSIX_ACL
depends on FS_POSIX_ACL
help
Posix Access Control Lists (ACLs) support permissions for users and
groups beyond the owner/group/world scheme.
Expand Down
9 changes: 8 additions & 1 deletion fs/next3/Makefile
Expand Up @@ -2,11 +2,18 @@
# Makefile for the linux next3-filesystem routines.
#

# default configuration for standalone module
CONFIG_NEXT3_FS?=m
CONFIG_NEXT3_FS_XATTR?=y
CONFIG_NEXT3_FS_POSIX_ACL?=$(CONFIG_FS_POSIX_ACL)
CONFIG_NEXT3_FS_SECURITY?=y
CONFIG_NEXT3_FS_DEBUG?=y

obj-$(CONFIG_NEXT3_FS) += next3.o

next3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
ioctl.o namei.o super.o symlink.o hash.o resize.o next3_jbd.o
next3-y += snapshot.o snapshot_ctl.o
next3-y += snapshot.o snapshot_ctl.o buffer.o

next3-$(CONFIG_NEXT3_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
next3-$(CONFIG_NEXT3_FS_POSIX_ACL) += acl.o
Expand Down
2 changes: 1 addition & 1 deletion fs/next3/balloc.c
Expand Up @@ -1703,7 +1703,7 @@ static int next3_has_free_blocks(struct next3_sb_info *sbi)
* snapshot reserved blocks for COWing to active snapshot
*/
if (free_blocks < snapshot_r_blocks + 1 &&
!handle->h_cowing) {
!IS_COWING(handle)) {
return 0;
}
/*
Expand Down
8 changes: 4 additions & 4 deletions fs/next3/inode.c
Expand Up @@ -1488,9 +1488,9 @@ int next3_get_blocks_handle(handle_t *handle, struct inode *inode,
* operation, because snapshot file has read-only aops and because
* truncate/unlink of snapshot file is not permitted.
*/
BUG_ON(next3_snapshot_is_active(inode) && !handle->h_cowing);
BUG_ON(!next3_snapshot_is_active(inode) && handle->h_cowing);
mutex_lock_nested(&ei->truncate_mutex, handle->h_cowing);
BUG_ON(next3_snapshot_is_active(inode) && !IS_COWING(handle));
BUG_ON(!next3_snapshot_is_active(inode) && IS_COWING(handle));
mutex_lock_nested(&ei->truncate_mutex, IS_COWING(handle));
#else
mutex_lock(&ei->truncate_mutex);
#endif
Expand Down Expand Up @@ -2601,7 +2601,7 @@ static int next3_snapshot_get_block(struct inode *inode, sector_t iblock,
static int next3_snapshot_readpage(struct file *file, struct page *page)
{
/* do read I/O with buffer heads to enable tracked reads */
return block_read_full_page(page, next3_snapshot_get_block);
return next3_read_full_page(page, next3_snapshot_get_block);
}

#endif
Expand Down
13 changes: 13 additions & 0 deletions fs/next3/next3.h
Expand Up @@ -25,6 +25,19 @@
#ifdef CONFIG_NEXT3_FS_SNAPSHOT
#ifndef NEXT3_SUPER_MAGIC
#define NEXT3_SUPER_MAGIC EXT3_SUPER_MAGIC
/* if the kernel was not patched, next3 is compiled as standalone module */
#define CONFIG_NEXT3_FS_STANDALONE
#endif

#ifdef CONFIG_NEXT3_FS_STANDALONE
/* configuration options for standalone module */
#define CONFIG_NEXT3_DEFAULTS_TO_ORDERED
#define CONFIG_NEXT3_FS_XATTR
#define CONFIG_NEXT3_FS_SECURITY
#define CONFIG_NEXT3_FS_DEBUG
#endif
#if defined(CONFIG_NEXT3_FS_STANDALONE) && defined(CONFIG_FS_POSIX_ACL)
#define CONFIG_NEXT3_FS_POSIX_ACL
#endif

#endif
Expand Down
26 changes: 13 additions & 13 deletions fs/next3/next3_jbd.c
Expand Up @@ -95,20 +95,20 @@ int __next3_journal_dirty_metadata(const char *where,
if (err)
return err;

if (!handle->h_cowing) {
if (!IS_COWING(handle)) {
struct journal_head *jh = bh2jh(bh);
jbd_lock_bh_state(bh);
if (jh->b_modified && !jh->b_user_modified) {
if (jh->b_modified == 1) {
/*
* buffer_credits was decremented when buffer was
* modified for the first time in the current
* transaction, which may have been during a COW
* operation. We decrement user_credits and mark
* b_user_modified, on the first time that the buffer
* b_modified = 2, on the first time that the buffer
* is modified not during a COW operation (!h_cowing).
*/
jh->b_user_modified = 1;
handle->h_user_credits--;
jh->b_modified = 2;
((next3_handle_t *)handle)->h_user_credits--;
}
jbd_unlock_bh_state(bh);
}
Expand All @@ -125,7 +125,7 @@ int __next3_journal_release_buffer(const char *where, handle_t *handle,
{
int err = 0;

if (handle->h_cowing)
if (IS_COWING(handle))
goto out;

/*
Expand All @@ -142,7 +142,7 @@ int __next3_journal_release_buffer(const char *where, handle_t *handle,
snapshot_debug(1, "%s: warning: couldn't extend transaction "
"from %s (credits=%d/%d)\n", __func__,
where, handle->h_buffer_credits,
handle->h_user_credits);
((next3_handle_t *)handle)->h_user_credits);
err = 0;
}
next3_journal_trace(SNAP_WARN, where, handle, -1);
Expand All @@ -154,9 +154,9 @@ int __next3_journal_release_buffer(const char *where, handle_t *handle,
#endif
#ifdef CONFIG_NEXT3_FS_SNAPSHOT_JOURNAL_TRACE
#ifdef CONFIG_JBD_DEBUG
static void next3_journal_cow_stats(int n, handle_t *handle)
static void next3_journal_cow_stats(int n, next3_handle_t *handle)
{
if (!journal_enable_debug)
if (!trace_cow_enabled())
return;
snapshot_debug(n, "COW stats: moved/copied=%d/%d, "
"mapped/bitmap/cached=%d/%d/%d, "
Expand All @@ -171,14 +171,14 @@ static void next3_journal_cow_stats(int n, handle_t *handle)

#ifdef CONFIG_NEXT3_FS_DEBUG
void __next3_journal_trace(int n, const char *fn, const char *caller,
handle_t *handle, int nblocks)
next3_handle_t *handle, int nblocks)
{
struct super_block *sb = handle->h_transaction->t_journal->j_private;
struct inode *active_snapshot = next3_snapshot_has_active(sb);
int upper = NEXT3_SNAPSHOT_START_TRANS_BLOCKS(handle->h_base_credits);
int lower = NEXT3_SNAPSHOT_TRANS_BLOCKS(handle->h_user_credits);
int final = (nblocks == 0 && handle->h_ref == 1 &&
!handle->h_cowing);
!IS_COWING(handle));

switch (snapshot_enable_debug) {
case SNAP_INFO:
Expand All @@ -192,7 +192,7 @@ void __next3_journal_trace(int n, const char *fn, const char *caller,
* valid if there is an active snapshot and not during COW
*/
if (handle->h_buffer_credits < lower &&
active_snapshot && !handle->h_cowing)
active_snapshot && !IS_COWING(handle))
break;
case SNAP_ERR:
/* trace if user credits are too low */
Expand All @@ -208,7 +208,7 @@ void __next3_journal_trace(int n, const char *fn, const char *caller,
break;
}

snapshot_debug_l(n, handle->h_cowing, "%s(%d): credits=%d, limit=%d/%d,"
snapshot_debug_l(n, IS_COWING(handle), "%s(%d): credits=%d, limit=%d/%d,"
" user=%d/%d, ref=%d, caller=%s\n", fn, nblocks,
handle->h_buffer_credits, lower, upper,
handle->h_user_credits, handle->h_base_credits,
Expand Down

0 comments on commit 479fcab

Please sign in to comment.