Sophie

Sophie

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

kernel-2.6.18-238.el5.src.rpm

From: Josef Bacik <jbacik@redhat.com>
Date: Tue, 10 Feb 2009 13:49:35 -0500
Subject: [mm] make new aops kABI friendly
Message-id: 1234291777-15344-23-git-send-email-jbacik@redhat.com
O-Subject: [PATCH 22/24] [RHEL 5.4] mm: make new aops kABI friendly
Bugzilla: 445433

This patch is not a backport of anything from upstream, and is related to bz
445433.  This patch introduces struct address_space_operations_ext which is used
to hold write_begin and write_end.  If an fs supports the new aops they set
MS_HAS_NEW_AOPS in sb->s_flags and uses the new struct with write_begin and
write_end filled out.

Signed-off-by: Josef Bacik <jbacik@redhat.com>

diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index f61d013..0b481f1 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -770,7 +770,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
 		 */
 		if (!file->f_op->sendfile)
 			goto out_putf;
-		if (aops->prepare_write || aops->write_begin)
+		if (aops->prepare_write || IS_NEWAOPS(inode))
 			lo_flags |= LO_FLAGS_USE_AOPS;
 		if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
 			lo_flags |= LO_FLAGS_READ_ONLY;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 5f5f524..6a2fa23 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -125,6 +125,7 @@ extern int dir_notify_enable;
 #define MS_NO_LEASES	(1<<21)	/* fs does not support leases */
 #define MS_HAS_SETLEASE        (1<<22) /* fs supports setlease fop */
 #define MS_I_VERSION	(1<<23)	/* Update inode I_version field */
+#define MS_HAS_NEW_AOPS	(1<<24) /* fs supports new aops */
 #define MS_ACTIVE	(1<<30)
 #define MS_NOUSER	(1<<31)
 
@@ -189,6 +190,7 @@ extern int dir_notify_enable;
 #define IS_PRIVATE(inode)	((inode)->i_flags & S_PRIVATE)
 #define IS_NO_LEASES(inode)	__IS_FLG(inode, MS_NO_LEASES)
 #define IS_SETLEASE(inode)	__IS_FLG(inode, MS_HAS_SETLEASE)
+#define IS_NEWAOPS(inode)	__IS_FLG(inode, MS_HAS_NEW_AOPS)
 
 /* the read-only stuff doesn't really belong here, but any other place is
    probably as bad and I don't want to create yet another include file. */
@@ -463,13 +465,6 @@ struct address_space_operations {
 	int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
 	int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
 
-	int (*write_begin)(struct file *, struct address_space *mapping,
-				loff_t pos, unsigned len, unsigned flags,
-				struct page **pagep, void **fsdata);
-	int (*write_end)(struct file *, struct address_space *mapping,
-				loff_t pos, unsigned len, unsigned copied,
-				struct page *page, void *fsdata);
-
 	/* Unfortunately this kludge is needed for FIBMAP. Don't use it */
 	sector_t (*bmap)(struct address_space *, sector_t);
 	void (*invalidatepage) (struct page *, unsigned long);
@@ -483,6 +478,18 @@ struct address_space_operations {
 			struct page *, struct page *);
 };
 
+struct address_space_operations_ext {
+	struct address_space_operations orig_aops;
+
+	/* if MS_HAS_NEW_AOPS is set then these are there */
+	int (*write_begin)(struct file *, struct address_space *mapping,
+				loff_t pos, unsigned len, unsigned flags,
+				struct page **pagep, void **fsdata);
+	int (*write_end)(struct file *, struct address_space *mapping,
+				loff_t pos, unsigned len, unsigned copied,
+				struct page *page, void *fsdata);
+};
+
 /*
  * pagecache_write_begin/pagecache_write_end must be used by general code
  * to write into the pagecache.
diff --git a/mm/filemap.c b/mm/filemap.c
index 15282de..3c578e2 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2130,9 +2130,13 @@ int pagecache_write_begin(struct file *file, struct address_space *mapping,
 				struct page **pagep, void **fsdata)
 {
 	const struct address_space_operations *aops = mapping->a_ops;
+	struct inode *inode = mapping->host;
+
+	if (IS_NEWAOPS(inode)) {
+		struct address_space_operations_ext *axops =
+			(struct address_space_operations_ext *)mapping->a_ops;
 
-	if (aops->write_begin) {
-		return aops->write_begin(file, mapping, pos, len, flags,
+		return axops->write_begin(file, mapping, pos, len, flags,
 							pagep, fsdata);
 	} else {
 		int ret;
@@ -2184,11 +2188,14 @@ int pagecache_write_end(struct file *file, struct address_space *mapping,
 				struct page *page, void *fsdata)
 {
 	const struct address_space_operations *aops = mapping->a_ops;
+	struct inode *inode = mapping->host;
 	int ret;
 
-	if (aops->write_end) {
+	if (IS_NEWAOPS(inode)) {
+		struct address_space_operations_ext *axops =
+			(struct address_space_operations_ext *)mapping->a_ops;
 		mark_page_accessed(page);
-		ret = aops->write_end(file, mapping, pos, len, copied,
+		ret = axops->write_end(file, mapping, pos, len, copied,
 							page, fsdata);
 	} else {
 		unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
@@ -2461,7 +2468,8 @@ static ssize_t generic_perform_write(struct file *file,
 				struct iov_iter *i, loff_t pos)
 {
 	struct address_space *mapping = file->f_mapping;
-	const struct address_space_operations *a_ops = mapping->a_ops;
+	const struct address_space_operations_ext *a_ops =
+		(struct address_space_operations_ext *)mapping->a_ops;
 	long status = 0;
 	ssize_t written = 0;
 	unsigned int flags = 0;
@@ -2557,7 +2565,7 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
 	struct iov_iter i;
 
 	iov_iter_init(&i, iov, nr_segs, count, written);
-	if (a_ops->write_begin)
+	if (IS_NEWAOPS(inode))
 		status = generic_perform_write(file, &i, pos);
 	else
 		status = generic_perform_write_2copy(file, &i, pos);