Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1012

kernel-2.6.18-238.el5.src.rpm

From: Eric Sandeen <sandeen@redhat.com>
Date: Thu, 21 Aug 2008 15:44:23 -0500
Subject: [fs] ext4: backport to rhel5.3 interfaces
Message-id: 48ADD3A7.5000403@redhat.com
O-Subject: [RHEL5.3 Patch 4/6] ext4: backport to rhel5.3 interfaces
Bugzilla: 458718

[Bug 458718] FEAT: RHEL 5.3 ext4 tech preview

Many backporting patches rolled up, to accomodate the RHEL5 interfaces.

missing_headers
generic_file_aio_write_fixup
no_READ_META
no_PageChecked
fix_f_path
ra_has_index
invalidate_bdev
no-print_hex_dump
kmem_cache_create-args
no-WARN_ON-ret
un-constify
no_iov_shorten
no-vm-ops-fault
no-write_begin_end
iget_failed
export_operations
void_percpu_counter_init
percpu_counter_sum_positive
no-nameidta-path
bi_end_io
mb_cache_entry_alloc_args
no_mnt_want_write
no_quota_on_remount
proc_create_data
enable_falloc
HAVE_FALLOCATE
no-nr_cpu_ids
no_trylock_page
no_spin_needbreak
ext4-own-zero-page

Again, please see fine-grained patches at
http://people.redhat.com/esandeen/ext4/ext4-patchset-for-rhel5.3.tar.bz2
if desired.

With this, ext4 compiles & runs.

diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index ac568da..d158d13 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -1624,7 +1624,7 @@ ext4_fsblk_t ext4_has_free_blocks(struct ext4_sb_info *sbi,
 #ifdef CONFIG_SMP
 	if (free_blocks - root_blocks < FBC_BATCH)
 		free_blocks =
-			percpu_counter_sum_positive(&sbi->s_freeblocks_counter);
+			percpu_counter_sum(&sbi->s_freeblocks_counter);
 #endif
 	if (free_blocks <= root_blocks)
 		/* we don't have free space */
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index f830a6c..cc3b4ed 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -100,7 +100,7 @@ static int ext4_readdir(struct file * filp,
 	struct ext4_dir_entry_2 *de;
 	struct super_block *sb;
 	int err;
-	struct inode *inode = filp->f_path.dentry->d_inode;
+	struct inode *inode = filp->f_dentry->d_inode;
 	int ret = 0;
 
 	sb = inode->i_sb;
@@ -118,7 +118,7 @@ static int ext4_readdir(struct file * filp,
 		 * We don't set the inode dirty flag since it's not
 		 * critical that it get flushed back to the disk.
 		 */
-		EXT4_I(filp->f_path.dentry->d_inode)->i_flags &= ~EXT4_INDEX_FL;
+		EXT4_I(filp->f_dentry->d_inode)->i_flags &= ~EXT4_INDEX_FL;
 	}
 	stored = 0;
 	offset = filp->f_pos & (sb->s_blocksize - 1);
@@ -131,14 +131,12 @@ static int ext4_readdir(struct file * filp,
 		map_bh.b_state = 0;
 		err = ext4_get_blocks_wrap(NULL, inode, blk, 1, &map_bh, 0, 0);
 		if (err > 0) {
-			pgoff_t index = map_bh.b_blocknr >>
-					(PAGE_CACHE_SHIFT - inode->i_blkbits);
-			if (!ra_has_index(&filp->f_ra, index))
-				page_cache_sync_readahead(
-					sb->s_bdev->bd_inode->i_mapping,
-					&filp->f_ra, filp,
-					index, 1);
-			filp->f_ra.prev_pos = (loff_t)index << PAGE_CACHE_SHIFT;
+			page_cache_readahead(sb->s_bdev->bd_inode->i_mapping,
+				&filp->f_ra,
+				filp,
+				map_bh.b_blocknr >>
+					(PAGE_CACHE_SHIFT - inode->i_blkbits),
+				1);
 			bh = ext4_bread(NULL, inode, blk, 0, &err);
 		}
 
@@ -392,7 +390,7 @@ static int call_filldir(struct file * filp, void * dirent,
 {
 	struct dir_private_info *info = filp->private_data;
 	loff_t	curr_pos;
-	struct inode *inode = filp->f_path.dentry->d_inode;
+	struct inode *inode = filp->f_dentry->d_inode;
 	struct super_block * sb;
 	int error;
 
@@ -422,7 +420,7 @@ static int ext4_dx_readdir(struct file * filp,
 			 void * dirent, filldir_t filldir)
 {
 	struct dir_private_info *info = filp->private_data;
-	struct inode *inode = filp->f_path.dentry->d_inode;
+	struct inode *inode = filp->f_dentry->d_inode;
 	struct fname *fname;
 	int	ret;
 
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 0eb68db..728cbf1 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -18,9 +18,10 @@
 
 #include <linux/types.h>
 #include <linux/blkdev.h>
-#include <linux/magic.h>
 #include "ext4_i.h"
 
+#define EXT4_SUPER_MAGIC	0xEF53
+
 /*
  * The fourth extended filesystem constants/structures
  */
@@ -1093,6 +1094,7 @@ extern int ext4_group_extend(struct super_block *sb,
 				ext4_fsblk_t n_blocks_count);
 
 /* super.c */
+extern struct page *ext4_zero_page;
 extern void ext4_error (struct super_block *, const char *, const char *, ...)
 	__attribute__ ((format (printf, 3, 4)));
 extern void __ext4_std_error (struct super_block *, const char *, int);
@@ -1209,16 +1211,16 @@ do {								\
 extern const struct file_operations ext4_dir_operations;
 
 /* file.c */
-extern const struct inode_operations ext4_file_inode_operations;
-extern const struct file_operations ext4_file_operations;
+extern struct inode_operations ext4_file_inode_operations;
+extern struct file_operations ext4_file_operations;
 
 /* namei.c */
-extern const struct inode_operations ext4_dir_inode_operations;
-extern const struct inode_operations ext4_special_inode_operations;
+extern struct inode_operations ext4_dir_inode_operations;
+extern struct inode_operations ext4_special_inode_operations;
 
 /* symlink.c */
-extern const struct inode_operations ext4_symlink_inode_operations;
-extern const struct inode_operations ext4_fast_symlink_inode_operations;
+extern struct inode_operations ext4_symlink_inode_operations;
+extern struct inode_operations ext4_fast_symlink_inode_operations;
 
 /* extents.c */
 extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index f3cddb1..8616977 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -38,7 +38,9 @@
 #include <linux/quotaops.h>
 #include <linux/string.h>
 #include <linux/slab.h>
+#ifdef HAVE_FALLOCATE
 #include <linux/falloc.h>
+#endif
 #include <asm/uaccess.h>
 #include "ext4_jbd2.h"
 #include "ext4_extents.h"
@@ -2048,7 +2050,8 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start)
 				err = -EIO;
 				break;
 			}
-			if (WARN_ON(i + 1 > depth)) {
+			WARN_ON(i + 1 > depth);
+			if (i + 1 > depth) {
 				err = -EIO;
 				break;
 			}
@@ -2151,9 +2154,11 @@ void ext4_ext_release(struct super_block *sb)
 #endif
 }
 
-static void bi_complete(struct bio *bio, int error)
+#ifdef HAVE_FALLOCATE
+static int bi_complete(struct bio *bio, unsigned int bytes, int error)
 {
 	complete((struct completion *)bio->bi_private);
+	return 0;
 }
 
 /* FIXME!! we need to try to merge to left or right after zero-out  */
@@ -2191,7 +2196,7 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex)
 		done = 0;
 		offset = 0;
 		while (done < len) {
-			ret = bio_add_page(bio, ZERO_PAGE(0),
+			ret = bio_add_page(bio, ext4_zero_page,
 							blocksize, offset);
 			if (ret != blocksize) {
 				/*
@@ -2518,6 +2523,7 @@ fix_extent_len:
 	ext4_ext_dirty(handle, inode, path + depth);
 	return err;
 }
+#endif
 
 /*
  * Block allocation/map/preallocation routine for extents based files
@@ -2624,6 +2630,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
 							EXT4_EXT_CACHE_EXTENT);
 				goto out;
 			}
+#ifdef HAVE_FALLOCATE
 			if (create == EXT4_CREATE_UNINITIALIZED_EXT)
 				goto out;
 			if (!create) {
@@ -2649,6 +2656,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
 			} else
 				allocated = ret;
 			goto outnew;
+#endif
 		}
 	}
 
@@ -2834,6 +2842,7 @@ out_stop:
 	ext4_journal_stop(handle);
 }
 
+#ifdef HAVE_FALLOCATE
 static void ext4_falloc_update_inode(struct inode *inode,
 				int mode, loff_t new_size, int update_ctime)
 {
@@ -2943,3 +2952,4 @@ retry:
 	mutex_unlock(&inode->i_mutex);
 	return ret > 0 ? ret2 : ret;
 }
+#endif
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index b9510ba..72d932d 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -48,11 +48,11 @@ static int ext4_release_file (struct inode * inode, struct file * filp)
 }
 
 static ssize_t
-ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
-		unsigned long nr_segs, loff_t pos)
+ext4_file_write(struct kiocb *iocb, const char __user *buf,
+		size_t count, loff_t pos)
 {
 	struct file *file = iocb->ki_filp;
-	struct inode *inode = file->f_path.dentry->d_inode;
+	struct inode *inode = file->f_dentry->d_inode;
 	ssize_t ret;
 	int err;
 
@@ -63,18 +63,15 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov,
 
 	if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) {
 		struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
-		size_t length = iov_length(iov, nr_segs);
 
 		if (pos > sbi->s_bitmap_maxbytes)
 			return -EFBIG;
 
-		if (pos + length > sbi->s_bitmap_maxbytes) {
-			nr_segs = iov_shorten((struct iovec *)iov, nr_segs,
-					      sbi->s_bitmap_maxbytes - pos);
-		}
+		if (pos + count > sbi->s_bitmap_maxbytes)
+			count = sbi->s_bitmap_maxbytes - pos;
 	}
 
-	ret = generic_file_aio_write(iocb, iov, nr_segs, pos);
+	ret = generic_file_aio_write(iocb, buf, count, pos);
 	/*
 	 * Skip flushing if there was an error, or if nothing was written.
 	 */
@@ -124,7 +121,8 @@ force_commit:
 }
 
 static struct vm_operations_struct ext4_file_vm_ops = {
-	.fault		= filemap_fault,
+	.nopage		= filemap_nopage,
+	.populate	= filemap_populate,
 	.page_mkwrite   = ext4_page_mkwrite,
 };
 
@@ -136,11 +134,10 @@ static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
 		return -ENOEXEC;
 	file_accessed(file);
 	vma->vm_ops = &ext4_file_vm_ops;
-	vma->vm_flags |= VM_CAN_NONLINEAR;
 	return 0;
 }
 
-const struct file_operations ext4_file_operations = {
+struct file_operations ext4_file_operations = {
 	.llseek		= generic_file_llseek,
 	.read		= do_sync_read,
 	.write		= do_sync_write,
@@ -158,7 +155,7 @@ const struct file_operations ext4_file_operations = {
 	.splice_write	= generic_file_splice_write,
 };
 
-const struct inode_operations ext4_file_inode_operations = {
+struct inode_operations ext4_file_inode_operations = {
 	.truncate	= ext4_truncate,
 	.setattr	= ext4_setattr,
 #ifdef CONFIG_EXT4DEV_FS_XATTR
@@ -168,6 +165,8 @@ const struct inode_operations ext4_file_inode_operations = {
 	.removexattr	= generic_removexattr,
 #endif
 	.permission	= ext4_permission,
+#ifdef HAVE_FALLOCATE
 	.fallocate	= ext4_fallocate,
+#endif
 };
 
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 8bc09ce..a0cac14 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1167,7 +1167,7 @@ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode,
 		return bh;
 	if (buffer_uptodate(bh))
 		return bh;
-	ll_rw_block(READ_META, 1, &bh);
+	ll_rw_block(READ, 1, &bh);
 	wait_on_buffer(bh);
 	if (buffer_uptodate(bh))
 		return bh;
@@ -1241,50 +1241,34 @@ static int do_journal_get_write_access(handle_t *handle,
 	return ext4_journal_get_write_access(handle, bh);
 }
 
-static int ext4_write_begin(struct file *file, struct address_space *mapping,
-				loff_t pos, unsigned len, unsigned flags,
-				struct page **pagep, void **fsdata)
+static int ext4_prepare_write(struct file *file, struct page *page,
+			      unsigned from, unsigned to)
 {
- 	struct inode *inode = mapping->host;
+	struct inode *inode = page->mapping->host;
 	int ret, needed_blocks = ext4_writepage_trans_blocks(inode);
 	handle_t *handle;
 	int retries = 0;
- 	struct page *page;
- 	pgoff_t index;
- 	unsigned from, to;
-
- 	index = pos >> PAGE_CACHE_SHIFT;
- 	from = pos & (PAGE_CACHE_SIZE - 1);
- 	to = from + len;
 
 retry:
- 	page = __grab_cache_page(mapping, index);
- 	if (!page)
- 		return -ENOMEM;
- 	*pagep = page;
-
-  	handle = ext4_journal_start(inode, needed_blocks);
-  	if (IS_ERR(handle)) {
- 		unlock_page(page);
- 		page_cache_release(page);
-  		ret = PTR_ERR(handle);
-  		goto out;
+	handle = ext4_journal_start(inode, needed_blocks);
+	if (IS_ERR(handle)) {
+		ret = PTR_ERR(handle);
+		goto out;
 	}
+	if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
+		ret = nobh_prepare_write(page, from, to, ext4_get_block);
+	else
+		ret = block_prepare_write(page, from, to, ext4_get_block);
+	if (ret)
+		goto prepare_write_failed;
 
-	ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
-							ext4_get_block);
-
-	if (!ret && ext4_should_journal_data(inode)) {
+	if (ext4_should_journal_data(inode)) {
 		ret = walk_page_buffers(handle, page_buffers(page),
 				from, to, NULL, do_journal_get_write_access);
 	}
-
-	if (ret) {
+prepare_write_failed:
+	if (ret)
 		ext4_journal_stop(handle);
- 		unlock_page(page);
- 		page_cache_release(page);
-	}
-
 	if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
 		goto retry;
 out:
@@ -1300,8 +1284,8 @@ int ext4_journal_dirty_data(handle_t *handle, struct buffer_head *bh)
 	return err;
 }
 
-/* For write_end() in data=journal mode */
-static int write_end_fn(handle_t *handle, struct buffer_head *bh)
+/* For commit_write() in data=journal mode */
+static int commit_write_fn(handle_t *handle, struct buffer_head *bh)
 {
 	if (!buffer_mapped(bh) || buffer_freed(bh))
 		return 0;
@@ -1310,42 +1294,17 @@ static int write_end_fn(handle_t *handle, struct buffer_head *bh)
 }
 
 /*
- * Generic write_end handler for ordered and writeback ext4 journal modes.
- * We can't use generic_write_end, because that unlocks the page and we need to
- * unlock the page after ext4_journal_stop, but ext4_journal_stop must run
- * after block_write_end.
- */
-static int ext4_generic_write_end(struct file *file,
-				struct address_space *mapping,
-				loff_t pos, unsigned len, unsigned copied,
-				struct page *page, void *fsdata)
-{
-	struct inode *inode = file->f_mapping->host;
-
-	copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
-
-	if (pos+copied > inode->i_size) {
-		i_size_write(inode, pos+copied);
-		mark_inode_dirty(inode);
-	}
-
-	return copied;
-}
-
-/*
  * We need to pick up the new inode size which generic_commit_write gave us
  * `file' can be NULL - eg, when called from page_symlink().
  *
  * ext4 never places buffers on inode->i_mapping->private_list.  metadata
  * buffers are managed internally.
  */
-static int ext4_ordered_write_end(struct file *file,
-				struct address_space *mapping,
-				loff_t pos, unsigned len, unsigned copied,
-				struct page *page, void *fsdata)
+static int ext4_ordered_commit_write(struct file *file, struct page *page,
+			unsigned from, unsigned to)
 {
 	handle_t *handle = ext4_journal_current_handle();
-	struct inode *inode = file->f_mapping->host;
+	struct inode *inode = page->mapping->host;
 	int ret = 0, ret2;
 
 	ret = walk_page_buffers(handle, page_buffers(page),
@@ -1353,85 +1312,66 @@ static int ext4_ordered_write_end(struct file *file,
 
 	if (ret == 0) {
 		/*
-		 * generic_write_end() will run mark_inode_dirty() if i_size
+		 * generic_commit_write() will run mark_inode_dirty() if i_size
 		 * changes.  So let's piggyback the i_disksize mark_inode_dirty
 		 * into that.
 		 */
 		loff_t new_i_size;
 
-		new_i_size = pos + copied;
+		new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
 		if (new_i_size > EXT4_I(inode)->i_disksize)
 			EXT4_I(inode)->i_disksize = new_i_size;
-		ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
-							page, fsdata);
-		copied = ret2;
-		if (ret2 < 0)
-			ret = ret2;
+		ret = generic_commit_write(file, page, from, to);
 	}
 	ret2 = ext4_journal_stop(handle);
 	if (!ret)
 		ret = ret2;
-	unlock_page(page);
-	page_cache_release(page);
-
-	return ret ? ret : copied;
+	return ret;
 }
 
-static int ext4_writeback_write_end(struct file *file,
-				struct address_space *mapping,
-				loff_t pos, unsigned len, unsigned copied,
-				struct page *page, void *fsdata)
+static int ext4_writeback_commit_write(struct file *file, struct page *page,
+				unsigned from, unsigned to)
 {
 	handle_t *handle = ext4_journal_current_handle();
-	struct inode *inode = file->f_mapping->host;
+	struct inode *inode = page->mapping->host;
 	int ret = 0, ret2;
 	loff_t new_i_size;
 
-	new_i_size = pos + copied;
+	new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
 	if (new_i_size > EXT4_I(inode)->i_disksize)
 		EXT4_I(inode)->i_disksize = new_i_size;
 
-	ret2 = ext4_generic_write_end(file, mapping, pos, len, copied,
-							page, fsdata);
-	copied = ret2;
-	if (ret2 < 0)
-		ret = ret2;
+	if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode))
+		ret = nobh_commit_write(file, page, from, to);
+	else
+		ret = generic_commit_write(file, page, from, to);
 
 	ret2 = ext4_journal_stop(handle);
 	if (!ret)
 		ret = ret2;
-	unlock_page(page);
-	page_cache_release(page);
 
-	return ret ? ret : copied;
+	return ret;
 }
 
-static int ext4_journalled_write_end(struct file *file,
-				struct address_space *mapping,
-				loff_t pos, unsigned len, unsigned copied,
-				struct page *page, void *fsdata)
+static int ext4_journalled_commit_write(struct file *file,
+			struct page *page, unsigned from, unsigned to)
 {
 	handle_t *handle = ext4_journal_current_handle();
-	struct inode *inode = mapping->host;
+	struct inode *inode = page->mapping->host;
 	int ret = 0, ret2;
 	int partial = 0;
-	unsigned from, to;
-
-	from = pos & (PAGE_CACHE_SIZE - 1);
-	to = from + len;
-
-	if (copied < len) {
-		if (!PageUptodate(page))
-			copied = 0;
-		page_zero_new_buffers(page, from+copied, to);
-	}
+	loff_t pos;
+	/*
+	 * Here we duplicate the generic_commit_write() functionality
+	 */
+	pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
 
 	ret = walk_page_buffers(handle, page_buffers(page), from,
-				to, &partial, write_end_fn);
+				to, &partial, commit_write_fn);
 	if (!partial)
 		SetPageUptodate(page);
-	if (pos+copied > inode->i_size)
-		i_size_write(inode, pos+copied);
+	if (pos > inode->i_size)
+		i_size_write(inode, pos);
 	EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
 	if (inode->i_size > EXT4_I(inode)->i_disksize) {
 		EXT4_I(inode)->i_disksize = inode->i_size;
@@ -1439,14 +1379,10 @@ static int ext4_journalled_write_end(struct file *file,
 		if (!ret)
 			ret = ret2;
 	}
-
 	ret2 = ext4_journal_stop(handle);
 	if (!ret)
 		ret = ret2;
-	unlock_page(page);
-	page_cache_release(page);
-
-	return ret ? ret : copied;
+	return ret;
 }
 
 /*
@@ -1688,12 +1624,12 @@ static int ext4_journalled_writepage(struct page *page,
 		goto no_write;
 	}
 
-	if (!page_has_buffers(page) || PageChecked(page)) {
+	if (!page_has_buffers(page) || PageFsMisc(page)) {
 		/*
 		 * It's mmapped pagecache.  Add buffers and journal it.  There
 		 * doesn't seem much point in redirtying the page here.
 		 */
-		ClearPageChecked(page);
+		ClearPageFsMisc(page);
 		ret = block_prepare_write(page, 0, PAGE_CACHE_SIZE,
 					ext4_get_block);
 		if (ret != 0) {
@@ -1704,7 +1640,7 @@ static int ext4_journalled_writepage(struct page *page,
 			PAGE_CACHE_SIZE, NULL, do_journal_get_write_access);
 
 		err = walk_page_buffers(handle, page_buffers(page), 0,
-				PAGE_CACHE_SIZE, NULL, write_end_fn);
+				PAGE_CACHE_SIZE, NULL, commit_write_fn);
 		if (ret == 0)
 			ret = err;
 		EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
@@ -1750,7 +1686,7 @@ static void ext4_invalidatepage(struct page *page, unsigned long offset)
 	 * If it's a full truncate we just forget about the pending dirtying
 	 */
 	if (offset == 0)
-		ClearPageChecked(page);
+		ClearPageFsMisc(page);
 
 	jbd2_journal_invalidatepage(journal, page, offset);
 }
@@ -1759,7 +1695,7 @@ static int ext4_releasepage(struct page *page, gfp_t wait)
 {
 	journal_t *journal = EXT4_JOURNAL(page->mapping->host);
 
-	WARN_ON(PageChecked(page));
+	WARN_ON(PageFsMisc(page));
 	if (!page_has_buffers(page))
 		return 0;
 	return jbd2_journal_try_to_free_buffers(journal, page, wait);
@@ -1863,7 +1799,7 @@ out:
  */
 static int ext4_journalled_set_page_dirty(struct page *page)
 {
-	SetPageChecked(page);
+	SetPageFsMisc(page);
 	return __set_page_dirty_nobuffers(page);
 }
 
@@ -1872,8 +1808,8 @@ static const struct address_space_operations ext4_ordered_aops = {
 	.readpages	= ext4_readpages,
 	.writepage	= ext4_ordered_writepage,
 	.sync_page	= block_sync_page,
-	.write_begin	= ext4_write_begin,
-	.write_end	= ext4_ordered_write_end,
+	.prepare_write	= ext4_prepare_write,
+	.commit_write	= ext4_ordered_commit_write,
 	.bmap		= ext4_bmap,
 	.invalidatepage	= ext4_invalidatepage,
 	.releasepage	= ext4_releasepage,
@@ -1886,8 +1822,8 @@ static const struct address_space_operations ext4_writeback_aops = {
 	.readpages	= ext4_readpages,
 	.writepage	= ext4_writeback_writepage,
 	.sync_page	= block_sync_page,
-	.write_begin	= ext4_write_begin,
-	.write_end	= ext4_writeback_write_end,
+	.prepare_write	= ext4_prepare_write,
+	.commit_write	= ext4_writeback_commit_write,
 	.bmap		= ext4_bmap,
 	.invalidatepage	= ext4_invalidatepage,
 	.releasepage	= ext4_releasepage,
@@ -1900,8 +1836,8 @@ static const struct address_space_operations ext4_journalled_aops = {
 	.readpages	= ext4_readpages,
 	.writepage	= ext4_journalled_writepage,
 	.sync_page	= block_sync_page,
-	.write_begin	= ext4_write_begin,
-	.write_end	= ext4_journalled_write_end,
+	.prepare_write	= ext4_prepare_write,
+	.commit_write	= ext4_journalled_commit_write,
 	.set_page_dirty	= ext4_journalled_set_page_dirty,
 	.bmap		= ext4_bmap,
 	.invalidatepage	= ext4_invalidatepage,
@@ -2725,7 +2661,7 @@ make_io:
 		 */
 		get_bh(bh);
 		bh->b_end_io = end_buffer_read_sync;
-		submit_bh(READ_META, bh);
+		submit_bh(READ, bh);
 		wait_on_buffer(bh);
 		if (!buffer_uptodate(bh)) {
 			ext4_error(inode->i_sb, "ext4_get_inode_loc",
@@ -2947,7 +2883,9 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
 	return inode;
 
 bad_inode:
-	iget_failed(inode);
+	make_bad_inode(inode);
+	unlock_new_inode(inode);
+	iput(inode);
 	return ERR_PTR(ret);
 }
 
@@ -3675,9 +3613,11 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page)
 	unsigned long len;
 	int ret = -EINVAL;
 	struct file *file = vma->vm_file;
-	struct inode *inode = file->f_path.dentry->d_inode;
+	struct inode *inode = file->f_dentry->d_inode;
 	struct address_space *mapping = inode->i_mapping;
 
+	lock_page(page);
+
 	/*
 	 * Get i_alloc_sem to stop truncates messing with the inode. We cannot
 	 * get i_mutex because we are already holding mmap_sem.
@@ -3705,22 +3645,21 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page)
 			goto out_unlock;
 	}
 	/*
-	 * OK, we need to fill the hole... Do write_begin write_end
+	 * OK, we need to fill the hole... Do prepare_write commit_write
 	 * to do block allocation/reservation.We are not holding
-	 * inode.i__mutex here. That allow * parallel write_begin,
-	 * write_end call. lock_page prevent this from happening
+	 * inode.i__mutex here. That allow * parallel prepare_write,
+	 * commit_write call. lock_page prevent this from happening
 	 * on the same page though
 	 */
-	ret = mapping->a_ops->write_begin(file, mapping, page_offset(page),
-			len, AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
+	ret = mapping->a_ops->prepare_write(file, page, 0, len);
 	if (ret < 0)
 		goto out_unlock;
-	ret = mapping->a_ops->write_end(file, mapping, page_offset(page),
-			len, len, page, NULL);
+	ret = mapping->a_ops->commit_write(file, page, 0, len);
 	if (ret < 0)
 		goto out_unlock;
 	ret = 0;
 out_unlock:
 	up_read(&inode->i_alloc_sem);
+	unlock_page(page);
 	return ret;
 }
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 7a6c2f1..426fd0e 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -13,7 +13,6 @@
 #include <linux/time.h>
 #include <linux/compat.h>
 #include <linux/smp_lock.h>
-#include <linux/mount.h>
 #include <asm/uaccess.h>
 #include "ext4_jbd2.h"
 #include "ext4.h"
@@ -39,25 +38,24 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		unsigned int oldflags;
 		unsigned int jflag;
 
+		if (IS_RDONLY(inode))
+			return -EROFS;
+
 		if (!is_owner_or_cap(inode))
 			return -EACCES;
 
 		if (get_user(flags, (int __user *) arg))
 			return -EFAULT;
 
-		err = mnt_want_write(filp->f_path.mnt);
-		if (err)
-			return err;
-
 		if (!S_ISDIR(inode->i_mode))
 			flags &= ~EXT4_DIRSYNC_FL;
 
-		err = -EPERM;
 		mutex_lock(&inode->i_mutex);
 		/* Is it quota file? Do not allow user to mess with it */
-		if (IS_NOQUOTA(inode))
-			goto flags_out;
-
+		if (IS_NOQUOTA(inode)) {
+			mutex_unlock(&inode->i_mutex);
+			return -EPERM;
+		}
 		oldflags = ei->i_flags;
 
 		/* The JOURNAL_DATA flag is modifiable only by root */
@@ -70,8 +68,10 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		 * This test looks nicer. Thanks to Pauline Middelink
 		 */
 		if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
-			if (!capable(CAP_LINUX_IMMUTABLE))
-				goto flags_out;
+			if (!capable(CAP_LINUX_IMMUTABLE)) {
+				mutex_unlock(&inode->i_mutex);
+				return -EPERM;
+			}
 		}
 
 		/*
@@ -79,14 +79,17 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		 * the relevant capability.
 		 */
 		if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
-			if (!capable(CAP_SYS_RESOURCE))
-				goto flags_out;
+			if (!capable(CAP_SYS_RESOURCE)) {
+				mutex_unlock(&inode->i_mutex);
+				return -EPERM;
+			}
 		}
 
+
 		handle = ext4_journal_start(inode, 1);
 		if (IS_ERR(handle)) {
-			err = PTR_ERR(handle);
-			goto flags_out;
+			mutex_unlock(&inode->i_mutex);
+			return PTR_ERR(handle);
 		}
 		if (IS_SYNC(inode))
 			handle->h_sync = 1;
@@ -104,14 +107,14 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		err = ext4_mark_iloc_dirty(handle, inode, &iloc);
 flags_err:
 		ext4_journal_stop(handle);
-		if (err)
-			goto flags_out;
+		if (err) {
+			mutex_unlock(&inode->i_mutex);
+			return err;
+		}
 
 		if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL))
 			err = ext4_change_inode_journal_flag(inode, jflag);
-flags_out:
 		mutex_unlock(&inode->i_mutex);
-		mnt_drop_write(filp->f_path.mnt);
 		return err;
 	}
 	case EXT4_IOC_GETVERSION:
@@ -126,20 +129,14 @@ flags_out:
 
 		if (!is_owner_or_cap(inode))
 			return -EPERM;
-
-		err = mnt_want_write(filp->f_path.mnt);
-		if (err)
-			return err;
-		if (get_user(generation, (int __user *) arg)) {
-			err = -EFAULT;
-			goto setversion_out;
-		}
+		if (IS_RDONLY(inode))
+			return -EROFS;
+		if (get_user(generation, (int __user *) arg))
+			return -EFAULT;
 
 		handle = ext4_journal_start(inode, 1);
-		if (IS_ERR(handle)) {
-			err = PTR_ERR(handle);
-			goto setversion_out;
-		}
+		if (IS_ERR(handle))
+			return PTR_ERR(handle);
 		err = ext4_reserve_inode_write(handle, inode, &iloc);
 		if (err == 0) {
 			inode->i_ctime = ext4_current_time(inode);
@@ -147,8 +144,6 @@ flags_out:
 			err = ext4_mark_iloc_dirty(handle, inode, &iloc);
 		}
 		ext4_journal_stop(handle);
-setversion_out:
-		mnt_drop_write(filp->f_path.mnt);
 		return err;
 	}
 #ifdef CONFIG_JBD2_DEBUG
@@ -184,21 +179,19 @@ setversion_out:
 		}
 		return -ENOTTY;
 	case EXT4_IOC_SETRSVSZ: {
-		int err;
 
 		if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
 			return -ENOTTY;
 
+		if (IS_RDONLY(inode))
+			return -EROFS;
+
 		if (!is_owner_or_cap(inode))
 			return -EACCES;
 
 		if (get_user(rsv_window_size, (int __user *)arg))
 			return -EFAULT;
 
-		err = mnt_want_write(filp->f_path.mnt);
-		if (err)
-			return err;
-
 		if (rsv_window_size > EXT4_MAX_RESERVE_BLOCKS)
 			rsv_window_size = EXT4_MAX_RESERVE_BLOCKS;
 
@@ -215,7 +208,6 @@ setversion_out:
 			rsv->rsv_goal_size = rsv_window_size;
 		}
 		up_write(&ei->i_data_sem);
-		mnt_drop_write(filp->f_path.mnt);
 		return 0;
 	}
 	case EXT4_IOC_GROUP_EXTEND: {
@@ -226,18 +218,16 @@ setversion_out:
 		if (!capable(CAP_SYS_RESOURCE))
 			return -EPERM;
 
+		if (IS_RDONLY(inode))
+			return -EROFS;
+
 		if (get_user(n_blocks_count, (__u32 __user *)arg))
 			return -EFAULT;
 
-		err = mnt_want_write(filp->f_path.mnt);
-		if (err)
-			return err;
-
 		err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count);
 		jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
 		jbd2_journal_flush(EXT4_SB(sb)->s_journal);
 		jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
-		mnt_drop_write(filp->f_path.mnt);
 
 		return err;
 	}
@@ -249,19 +239,17 @@ setversion_out:
 		if (!capable(CAP_SYS_RESOURCE))
 			return -EPERM;
 
+		if (IS_RDONLY(inode))
+			return -EROFS;
+
 		if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg,
 				sizeof(input)))
 			return -EFAULT;
 
-		err = mnt_want_write(filp->f_path.mnt);
-		if (err)
-			return err;
-
 		err = ext4_group_add(sb, &input);
 		jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
 		jbd2_journal_flush(EXT4_SB(sb)->s_journal);
 		jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
-		mnt_drop_write(filp->f_path.mnt);
 
 		return err;
 	}
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 31f98f3..7000510 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -2181,10 +2181,17 @@ static void ext4_mb_history_init(struct super_block *sb)
 	int i;
 
 	if (sbi->s_mb_proc != NULL) {
-		proc_create_data("mb_history", S_IRUGO, sbi->s_mb_proc,
-				 &ext4_mb_seq_history_fops, sb);
-		proc_create_data("mb_groups", S_IRUGO, sbi->s_mb_proc,
-				 &ext4_mb_seq_groups_fops, sb);
+		struct proc_dir_entry *p;
+		p = create_proc_entry("mb_history", S_IRUGO, sbi->s_mb_proc);
+		if (p) {
+			p->proc_fops = &ext4_mb_seq_history_fops;
+			p->data = sb;
+		}
+		p = create_proc_entry("mb_groups", S_IRUGO, sbi->s_mb_proc);
+		if (p) {
+			p->proc_fops = &ext4_mb_seq_groups_fops;
+			p->data = sb;
+		}
 	}
 
 	sbi->s_mb_history_max = 1000;
@@ -2540,7 +2547,7 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
 	sbi->s_mb_history_filter = EXT4_MB_HISTORY_DEFAULT;
 	sbi->s_mb_group_prealloc = MB_DEFAULT_GROUP_PREALLOC;
 
-	i = sizeof(struct ext4_locality_group) * nr_cpu_ids;
+	i = sizeof(struct ext4_locality_group) * num_possible_cpus();
 	sbi->s_locality_groups = kmalloc(i, GFP_KERNEL);
 	if (sbi->s_locality_groups == NULL) {
 		clear_opt(sbi->s_mount_opt, MBALLOC);
@@ -2548,7 +2555,7 @@ int ext4_mb_init(struct super_block *sb, int needs_recovery)
 		kfree(sbi->s_mb_maxs);
 		return -ENOMEM;
 	}
-	for (i = 0; i < nr_cpu_ids; i++) {
+	for (i = 0; i < num_possible_cpus(); i++) {
 		struct ext4_locality_group *lg;
 		lg = &sbi->s_locality_groups[i];
 		mutex_init(&lg->lg_mutex);
@@ -2740,7 +2747,7 @@ static int ext4_mb_##name##_proc_open(struct inode *inode, struct file *file)\
 static ssize_t ext4_mb_##name##_proc_write(struct file *file,	\
 		const char __user *buf, size_t cnt, loff_t *ppos)	\
 {								\
-	struct ext4_sb_info *sbi = PDE(file->f_path.dentry->d_inode)->data;\
+	struct ext4_sb_info *sbi = PDE(file->f_dentry->d_inode)->data;\
 	char str[32];						\
 	long value;						\
 	if (cnt >= sizeof(str))					\
@@ -2772,8 +2779,11 @@ MB_PROC_FOPS(group_prealloc);
 
 #define	MB_PROC_HANDLER(name, var)					\
 do {									\
-	proc = proc_create_data(name, mode, sbi->s_mb_proc,		\
-				&ext4_mb_##var##_proc_fops, sbi);	\
+	proc  = create_proc_entry(name, mode, sbi->s_mb_proc);		\
+	if (proc) {							\
+		proc->proc_fops = &ext4_mb_##var##_proc_fops;		\
+		proc->data = sb;					\
+	}								\
 	if (proc == NULL) {						\
 		printk(KERN_ERR "EXT4-fs: can't to create %s\n", name);	\
 		goto err_out;						\
@@ -2842,14 +2852,14 @@ int __init init_ext4_mballoc(void)
 	ext4_pspace_cachep =
 		kmem_cache_create("ext4_prealloc_space",
 				     sizeof(struct ext4_prealloc_space),
-				     0, SLAB_RECLAIM_ACCOUNT, NULL);
+				     0, SLAB_RECLAIM_ACCOUNT, NULL, NULL);
 	if (ext4_pspace_cachep == NULL)
 		return -ENOMEM;
 
 	ext4_ac_cachep =
 		kmem_cache_create("ext4_alloc_context",
 				     sizeof(struct ext4_allocation_context),
-				     0, SLAB_RECLAIM_ACCOUNT, NULL);
+				     0, SLAB_RECLAIM_ACCOUNT, NULL, NULL);
 	if (ext4_ac_cachep == NULL) {
 		kmem_cache_destroy(ext4_pspace_cachep);
 		return -ENOMEM;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 387ad98..f3fe06b 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -637,7 +637,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
 
 	dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash,
 		       start_minor_hash));
-	dir = dir_file->f_path.dentry->d_inode;
+	dir = dir_file->f_dentry->d_inode;
 	if (!(EXT4_I(dir)->i_flags & EXT4_INDEX_FL)) {
 		hinfo.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version;
 		hinfo.seed = EXT4_SB(dir->i_sb)->s_hash_seed;
@@ -648,7 +648,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
 	}
 	hinfo.hash = start_hash;
 	hinfo.minor_hash = 0;
-	frame = dx_probe(NULL, dir_file->f_path.dentry->d_inode, &hinfo, frames, &err);
+	frame = dx_probe(NULL, dir_file->f_dentry->d_inode, &hinfo, frames, &err);
 	if (!frame)
 		return err;
 
@@ -912,7 +912,7 @@ restart:
 				bh = ext4_getblk(NULL, dir, b++, 0, &err);
 				bh_use[ra_max] = bh;
 				if (bh)
-					ll_rw_block(READ_META, 1, &bh);
+					ll_rw_block(READ, 1, &bh);
 			}
 		}
 		if ((bh = bh_use[ra_ptr++]) == NULL)
@@ -2443,7 +2443,7 @@ end_rename:
 /*
  * directories can handle most operations...
  */
-const struct inode_operations ext4_dir_inode_operations = {
+struct inode_operations ext4_dir_inode_operations = {
 	.create		= ext4_create,
 	.lookup		= ext4_lookup,
 	.link		= ext4_link,
@@ -2463,7 +2463,7 @@ const struct inode_operations ext4_dir_inode_operations = {
 	.permission	= ext4_permission,
 };
 
-const struct inode_operations ext4_special_inode_operations = {
+struct inode_operations ext4_special_inode_operations = {
 	.setattr	= ext4_setattr,
 #ifdef CONFIG_EXT4DEV_FS_XATTR
 	.setxattr	= generic_setxattr,
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 2f76c1d..0f80083 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -27,7 +27,6 @@
 #include <linux/parser.h>
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
-#include <linux/exportfs.h>
 #include <linux/vfs.h>
 #include <linux/random.h>
 #include <linux/mount.h>
@@ -64,6 +63,7 @@ static void ext4_unlockfs(struct super_block *sb);
 static void ext4_write_super(struct super_block *sb);
 static void ext4_write_super_lockfs(struct super_block *sb);
 
+struct page *ext4_zero_page;
 
 ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
 			       struct ext4_group_desc *bg)
@@ -534,7 +534,7 @@ static void ext4_put_super(struct super_block *sb)
 		dump_orphan_list(sb, sbi);
 	J_ASSERT(list_empty(&sbi->s_orphan));
 
-	invalidate_bdev(sb->s_bdev);
+	invalidate_bdev(sb->s_bdev, 0);
 	if (sbi->journal_bdev && sbi->journal_bdev != sb->s_bdev) {
 		/*
 		 * Invalidate the journal device's buffers.  We don't want them
@@ -542,7 +542,7 @@ static void ext4_put_super(struct super_block *sb)
 		 * hotswapped, and it breaks the `ro-after' testing code.
 		 */
 		sync_blockdev(sbi->journal_bdev);
-		invalidate_bdev(sbi->journal_bdev);
+		invalidate_bdev(sbi->journal_bdev, 0);
 		ext4_blkdev_remove(sbi);
 	}
 	sb->s_fs_info = NULL;
@@ -580,15 +580,12 @@ static void ext4_destroy_inode(struct inode *inode)
 	if (!list_empty(&(EXT4_I(inode)->i_orphan))) {
 		printk("EXT4 Inode %p: orphan list check failed!\n",
 			EXT4_I(inode));
-		print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4,
-				EXT4_I(inode), sizeof(struct ext4_inode_info),
-				true);
 		dump_stack();
 	}
 	kmem_cache_free(ext4_inode_cachep, EXT4_I(inode));
 }
 
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
 {
 	struct ext4_inode_info *ei = (struct ext4_inode_info *) foo;
 
@@ -606,7 +603,7 @@ static int init_inodecache(void)
 					     sizeof(struct ext4_inode_info),
 					     0, (SLAB_RECLAIM_ACCOUNT|
 						SLAB_MEM_SPREAD),
-					     init_once);
+					     init_once, NULL);
 	if (ext4_inode_cachep == NULL)
 		return -ENOMEM;
 	return 0;
@@ -767,10 +764,14 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs)
 }
 
 
-static struct inode *ext4_nfs_get_inode(struct super_block *sb,
-		u64 ino, u32 generation)
+static struct dentry *ext4_get_dentry(struct super_block *sb, void *vobjp)
 {
+	__u32 *objp = vobjp;
+	unsigned long ino = objp[0];
+	__u32 generation = objp[1];
 	struct inode *inode;
+	struct dentry *result;
+
 
 	if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO)
 		return ERR_PTR(-ESTALE);
@@ -792,22 +793,15 @@ static struct inode *ext4_nfs_get_inode(struct super_block *sb,
 		iput(inode);
 		return ERR_PTR(-ESTALE);
 	}
-
-	return inode;
-}
-
-static struct dentry *ext4_fh_to_dentry(struct super_block *sb, struct fid *fid,
-		int fh_len, int fh_type)
-{
-	return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
-				    ext4_nfs_get_inode);
-}
-
-static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid,
-		int fh_len, int fh_type)
-{
-	return generic_fh_to_parent(sb, fid, fh_len, fh_type,
-				    ext4_nfs_get_inode);
+	/* now to find a dentry.
+	 * If possible, get a well-connected one
+	 */
+	result = d_alloc_anon(inode);
+	if (!result) {
+		iput(inode);
+		return ERR_PTR(-ENOMEM);
+	}
+	return result;
 }
 
 #ifdef CONFIG_QUOTA
@@ -821,8 +815,7 @@ static int ext4_acquire_dquot(struct dquot *dquot);
 static int ext4_release_dquot(struct dquot *dquot);
 static int ext4_mark_dquot_dirty(struct dquot *dquot);
 static int ext4_write_info(struct super_block *sb, int type);
-static int ext4_quota_on(struct super_block *sb, int type, int format_id,
-				char *path, int remount);
+static int ext4_quota_on(struct super_block *sb, int type, int format_id, char *path);
 static int ext4_quota_on_mount(struct super_block *sb, int type);
 static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
 			       size_t len, loff_t off);
@@ -855,7 +848,7 @@ static struct quotactl_ops ext4_qctl_operations = {
 };
 #endif
 
-static const struct super_operations ext4_sops = {
+static struct super_operations ext4_sops = {
 	.alloc_inode	= ext4_alloc_inode,
 	.destroy_inode	= ext4_destroy_inode,
 	.write_inode	= ext4_write_inode,
@@ -876,10 +869,9 @@ static const struct super_operations ext4_sops = {
 #endif
 };
 
-static const struct export_operations ext4_export_ops = {
-	.fh_to_dentry = ext4_fh_to_dentry,
-	.fh_to_parent = ext4_fh_to_parent,
+static struct export_operations ext4_export_ops = {
 	.get_parent = ext4_get_parent,
+	.get_dentry = ext4_get_dentry,
 };
 
 enum {
@@ -988,7 +980,7 @@ static int parse_options(char *options, struct super_block *sb,
 	int data_opt = 0;
 	int option;
 #ifdef CONFIG_QUOTA
-	int qtype, qfmt;
+	int qtype;
 	char *qname;
 #endif
 	ext4_fsblk_t last_block;
@@ -1172,9 +1164,7 @@ static int parse_options(char *options, struct super_block *sb,
 		case Opt_grpjquota:
 			qtype = GRPQUOTA;
 set_qf_name:
-			if ((sb_any_quota_enabled(sb) ||
-			     sb_any_quota_suspended(sb)) &&
-			    !sbi->s_qf_names[qtype]) {
+			if (sb_any_quota_enabled(sb)) {
 				printk(KERN_ERR
 					"EXT4-fs: Cannot change journaled "
 					"quota options when quota turned on.\n");
@@ -1212,9 +1202,7 @@ set_qf_name:
 		case Opt_offgrpjquota:
 			qtype = GRPQUOTA;
 clear_qf_name:
-			if ((sb_any_quota_enabled(sb) ||
-			     sb_any_quota_suspended(sb)) &&
-			    sbi->s_qf_names[qtype]) {
+			if (sb_any_quota_enabled(sb)) {
 				printk(KERN_ERR "EXT4-fs: Cannot change "
 					"journaled quota options when "
 					"quota turned on.\n");
@@ -1227,20 +1215,10 @@ clear_qf_name:
 			sbi->s_qf_names[qtype] = NULL;
 			break;
 		case Opt_jqfmt_vfsold:
-			qfmt = QFMT_VFS_OLD;
-			goto set_qf_format;
+			sbi->s_jquota_fmt = QFMT_VFS_OLD;
+			break;
 		case Opt_jqfmt_vfsv0:
-			qfmt = QFMT_VFS_V0;
-set_qf_format:
-			if ((sb_any_quota_enabled(sb) ||
-			     sb_any_quota_suspended(sb)) &&
-			    sbi->s_jquota_fmt != qfmt) {
-				printk(KERN_ERR "EXT4-fs: Cannot change "
-					"journaled quota options when "
-					"quota turned on.\n");
-				return 0;
-			}
-			sbi->s_jquota_fmt = qfmt;
+			sbi->s_jquota_fmt = QFMT_VFS_V0;
 			break;
 		case Opt_quota:
 		case Opt_usrquota:
@@ -1724,7 +1702,7 @@ static void ext4_orphan_cleanup(struct super_block *sb,
 	/* Turn quotas off */
 	for (i = 0; i < MAXQUOTAS; i++) {
 		if (sb_dqopt(sb)->files[i])
-			vfs_quota_off(sb, i, 0);
+			vfs_quota_off(sb, i);
 	}
 #endif
 	sb->s_flags = s_flags; /* Restore MS_RDONLY status */
@@ -1902,7 +1880,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	int needs_recovery;
 	__le32 features;
 	__u64 blocks_count;
-	int err;
 
 	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi)
@@ -2221,20 +2198,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	get_random_bytes(&sbi->s_next_generation, sizeof(u32));
 	spin_lock_init(&sbi->s_next_gen_lock);
 
-	err = percpu_counter_init(&sbi->s_freeblocks_counter,
+	percpu_counter_init(&sbi->s_freeblocks_counter,
 			ext4_count_free_blocks(sb));
-	if (!err) {
-		err = percpu_counter_init(&sbi->s_freeinodes_counter,
+	percpu_counter_init(&sbi->s_freeinodes_counter,
 				ext4_count_free_inodes(sb));
-	}
-	if (!err) {
-		err = percpu_counter_init(&sbi->s_dirs_counter,
+	percpu_counter_init(&sbi->s_dirs_counter,
 				ext4_count_dirs(sb));
-	}
-	if (err) {
-		printk(KERN_ERR "EXT4-fs: insufficient memory\n");
-		goto failed_mount3;
-	}
 
 	/* per fileystem reservation list head & lock */
 	spin_lock_init(&sbi->s_rsv_window_lock);
@@ -3129,13 +3098,14 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
 	buf->f_type = EXT4_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
 	buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
-	buf->f_bfree = percpu_counter_sum_positive(&sbi->s_freeblocks_counter);
+	/* percpu_counter_sum already _positive in RHEL5 */
+	buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
 	ext4_free_blocks_count_set(es, buf->f_bfree);
 	buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
 	if (buf->f_bfree < ext4_r_blocks_count(es))
 		buf->f_bavail = 0;
 	buf->f_files = le32_to_cpu(es->s_inodes_count);
-	buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter);
+	buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
 	es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
 	buf->f_namelen = EXT4_NAME_LEN;
 	fsid = le64_to_cpup((void *)es->s_uuid) ^
@@ -3295,30 +3265,27 @@ static int ext4_quota_on_mount(struct super_block *sb, int type)
  * Standard function to be called on quota_on
  */
 static int ext4_quota_on(struct super_block *sb, int type, int format_id,
-			 char *path, int remount)
+			 char *path)
 {
 	int err;
 	struct nameidata nd;
 
 	if (!test_opt(sb, QUOTA))
 		return -EINVAL;
-	/* When remounting, no checks are needed and in fact, path is NULL */
-	if (remount)
-		return vfs_quota_on(sb, type, format_id, path, remount);
 
 	err = path_lookup(path, LOOKUP_FOLLOW, &nd);
 	if (err)
 		return err;
 
 	/* Quotafile not on the same filesystem? */
-	if (nd.path.mnt->mnt_sb != sb) {
-		path_put(&nd.path);
+	if (nd.mnt->mnt_sb != sb) {
+		path_release(&nd);
 		return -EXDEV;
 	}
 	/* Journaling quota? */
 	if (EXT4_SB(sb)->s_qf_names[type]) {
 		/* Quotafile not in fs root? */
-		if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode)
+		if (nd.dentry->d_parent->d_inode != sb->s_root->d_inode)
 			printk(KERN_WARNING
 				"EXT4-fs: Quota file not on filesystem root. "
 				"Journaled quota will not work.\n");
@@ -3328,7 +3295,7 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
 	 * When we journal data on quota file, we have to flush journal to see
 	 * all updates to the file when we bypass pagecache...
 	 */
-	if (ext4_should_journal_data(nd.path.dentry->d_inode)) {
+	if (ext4_should_journal_data(nd.dentry->d_inode)) {
 		/*
 		 * We don't need to lock updates but journal_flush() could
 		 * otherwise be livelocked...
@@ -3338,8 +3305,8 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
 		jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
 	}
 
-	path_put(&nd.path);
-	return vfs_quota_on(sb, type, format_id, path, remount);
+	path_release(&nd);
+	return vfs_quota_on(sb, type, format_id, path);
 }
 
 /* Read data from quotafile - avoid pagecache and such because we cannot afford
@@ -3464,17 +3431,27 @@ static struct file_system_type ext4dev_fs_type = {
 	.name		= "ext4dev",
 	.get_sb		= ext4_get_sb,
 	.kill_sb	= kill_block_super,
+#ifdef HAVE_FALLOCATE
+	.fs_flags	= FS_REQUIRES_DEV|FS_HAS_FALLOCATE,
+#else
 	.fs_flags	= FS_REQUIRES_DEV,
+#endif
 };
 
 static int __init init_ext4_fs(void)
 {
 	int err;
+	void *p;
+
+	ext4_zero_page = alloc_page(GFP_USER);
+	if (!ext4_zero_page)
+		return -ENOMEM;
+	p = kmap(ext4_zero_page);
+	memset(p, 0, PAGE_SIZE);
 
 	err = init_ext4_mballoc();
 	if (err)
-		return err;
-
+		goto out3;
 	err = init_ext4_xattr();
 	if (err)
 		goto out2;
@@ -3491,6 +3468,8 @@ out1:
 	exit_ext4_xattr();
 out2:
 	exit_ext4_mballoc();
+out3:
+	__free_page(ext4_zero_page);
 	return err;
 }
 
@@ -3500,6 +3479,7 @@ static void __exit exit_ext4_fs(void)
 	destroy_inodecache();
 	exit_ext4_xattr();
 	exit_ext4_mballoc();
+	__free_page(ext4_zero_page);
 }
 
 MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
index e917864..a8c25ad 100644
--- a/fs/ext4/symlink.c
+++ b/fs/ext4/symlink.c
@@ -30,7 +30,7 @@ static void * ext4_follow_link(struct dentry *dentry, struct nameidata *nd)
 	return NULL;
 }
 
-const struct inode_operations ext4_symlink_inode_operations = {
+struct inode_operations ext4_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= page_follow_link_light,
 	.put_link	= page_put_link,
@@ -42,7 +42,7 @@ const struct inode_operations ext4_symlink_inode_operations = {
 #endif
 };
 
-const struct inode_operations ext4_fast_symlink_inode_operations = {
+struct inode_operations ext4_fast_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= ext4_follow_link,
 #ifdef CONFIG_EXT4DEV_FS_XATTR
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 8954208..0034670 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -1389,7 +1389,7 @@ ext4_xattr_cache_insert(struct buffer_head *bh)
 	struct mb_cache_entry *ce;
 	int error;
 
-	ce = mb_cache_entry_alloc(ext4_xattr_cache, GFP_NOFS);
+	ce = mb_cache_entry_alloc(ext4_xattr_cache);
 	if (!ce) {
 		ea_bdebug(bh, "out of memory");
 		return;
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
index 6914598..3f18958 100644
--- a/fs/jbd2/checkpoint.c
+++ b/fs/jbd2/checkpoint.c
@@ -353,8 +353,7 @@ restart:
 			}
 			retry = __process_buffer(journal, jh, bhs, &batch_count,
 						 transaction);
-			if (!retry && (need_resched() ||
-				spin_needbreak(&journal->j_list_lock))) {
+			if (!retry && lock_need_resched(&journal->j_list_lock)) {
 				spin_unlock(&journal->j_list_lock);
 				retry = 1;
 				break;
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index b706b7d..04ee96f 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -65,7 +65,7 @@ static void release_buffer_page(struct buffer_head *bh)
 		goto nope;
 
 	/* OK, it's a truncated page */
-	if (!trylock_page(page))
+	if (TestSetPageLocked(page))
 		goto nope;
 
 	page_cache_get(page);
@@ -360,7 +360,7 @@ write_out_data:
 			put_bh(bh);
 		}
 
-		if (need_resched() || spin_needbreak(&journal->j_list_lock)) {
+		if (lock_need_resched(&journal->j_list_lock)) {
 			spin_unlock(&journal->j_list_lock);
 			goto write_out_data;
 		}
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index e52a41d..1bd9060 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -30,7 +30,6 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/mm.h>
-#include <linux/freezer.h>
 #include <linux/pagemap.h>
 #include <linux/kthread.h>
 #include <linux/poison.h>
@@ -903,10 +902,19 @@ static void jbd2_stats_proc_init(journal_t *journal)
 	bdevname(journal->j_dev, name);
 	journal->j_proc_entry = proc_mkdir(name, proc_jbd2_stats);
 	if (journal->j_proc_entry) {
-		proc_create_data("history", S_IRUGO, journal->j_proc_entry,
-				 &jbd2_seq_history_fops, journal);
-		proc_create_data("info", S_IRUGO, journal->j_proc_entry,
-				 &jbd2_seq_info_fops, journal);
+		struct proc_dir_entry *p;
+		p = create_proc_entry("history", S_IRUGO,
+				journal->j_proc_entry);
+		if (p) {
+			p->proc_fops = &jbd2_seq_history_fops;
+			p->data = journal;
+			p = create_proc_entry("info", S_IRUGO,
+						journal->j_proc_entry);
+			if (p) {
+				p->proc_fops = &jbd2_seq_info_fops;
+				p->data = journal;
+			}
+		}
 	}
 }
 
@@ -1964,8 +1972,9 @@ static int journal_init_jbd2_journal_head_cache(void)
 	jbd2_journal_head_cache = kmem_cache_create("jbd2_journal_head",
 				sizeof(struct journal_head),
 				0,		/* offset */
-				SLAB_TEMPORARY,	/* flags */
-				NULL);		/* ctor */
+				0,		/* flags */
+				NULL,		/* ctor */
+				NULL);		/* dtor */
 	retval = 0;
 	if (!jbd2_journal_head_cache) {
 		retval = -ENOMEM;
@@ -2261,8 +2270,9 @@ static int __init journal_init_handle_cache(void)
 	jbd2_handle_cache = kmem_cache_create("jbd2_journal_handle",
 				sizeof(handle_t),
 				0,		/* offset */
-				SLAB_TEMPORARY,	/* flags */
-				NULL);		/* ctor */
+				0,		/* flags */
+				NULL,		/* ctor */
+				NULL);		/* dtor */
 	if (jbd2_handle_cache == NULL) {
 		printk(KERN_EMERG "JBD: failed to create handle cache\n");
 		return -ENOMEM;
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
index 257ff26..4adcb09 100644
--- a/fs/jbd2/revoke.c
+++ b/fs/jbd2/revoke.c
@@ -187,14 +187,14 @@ int __init jbd2_journal_init_revoke_caches(void)
 	jbd2_revoke_record_cache = kmem_cache_create("jbd2_revoke_record",
 					   sizeof(struct jbd2_revoke_record_s),
 					   0,
-					   SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY,
-					   NULL);
+					   SLAB_HWCACHE_ALIGN,
+					   NULL, NULL);
 	if (!jbd2_revoke_record_cache)
 		goto record_cache_failure;
 
 	jbd2_revoke_table_cache = kmem_cache_create("jbd2_revoke_table",
 					   sizeof(struct jbd2_revoke_table_s),
-					   0, SLAB_TEMPORARY, NULL);
+					   0, 0, NULL, NULL);
 	if (!jbd2_revoke_table_cache)
 		goto table_cache_failure;
 	return 0;