Sophie

Sophie

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

kernel-2.6.18-238.el5.src.rpm

From: Eric Sandeen <sandeen@redhat.com>
Date: Wed, 1 Sep 2010 15:59:34 -0400
Subject: [fs] ext4: add new kernel helpers for RHEL5.6
Message-id: <4C7E7866.1070303@redhat.com>
Patchwork-id: 27987
O-Subject: [PATCH RHEL5.6 1/4] ext4: kernel helpers
Bugzilla: 457153
RH-Acked-by: Edward Shishkin <edward@redhat.com>

For Bug 457153 - ext4 full support in RHEL5

These is support infrastructure for subsequent ext4 changes.

All or part of the following upstream commits:

d5aacad548db1ff547adf35d0a77eb2a8ed4fe14 New helper - simple_fsync()
de9330d13eac1f331e63ab1d18c506365b0151f3 log2.h: Define order_base_2() macro for convenience.
25d9e2d15286281ec834b829a4aaf8969011f1cd truncate: new helpers

and a couple of extra exports I needed to fix up the backport.

KABI NOTE:

Simply including <linux/writeback.h> in fs/libfs.c changed the signatures
of all symbols in that file; I tracked this down to the definition of
struct writeback_control{ ... }; which changes things.  I think the only
change here is the full definition of the structure, which should not
break KABI... so I wrapped it in #ifndef __GENKSYMS__.  KABI expert
eyes are welcomed, but I think this should be fine.

-Eric

Signed-off-by: Jarod Wilson <jarod@redhat.com>

diff --git a/fs/attr.c b/fs/attr.c
index 1fb8e92..af0b2a0 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -61,9 +61,51 @@ fine:
 error:
 	return retval;
 }
-
 EXPORT_SYMBOL(inode_change_ok);
 
+/**
+ * inode_newsize_ok - may this inode be truncated to a given size
+ * @inode:	the inode to be truncated
+ * @offset:	the new size to assign to the inode
+ * @Returns:	0 on success, -ve errno on failure
+ *
+ * inode_newsize_ok will check filesystem limits and ulimits to check that the
+ * new inode size is within limits. inode_newsize_ok will also send SIGXFSZ
+ * when necessary. Caller must not proceed with inode size change if failure is
+ * returned. @inode must be a file (not directory), with appropriate
+ * permissions to allow truncate (inode_newsize_ok does NOT check these
+ * conditions).
+ *
+ * inode_newsize_ok must be called with i_mutex held.
+ */
+int inode_newsize_ok(const struct inode *inode, loff_t offset)
+{
+	if (inode->i_size < offset) {
+		unsigned long limit;
+
+		limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
+		if (limit != RLIM_INFINITY && offset > limit)
+			goto out_sig;
+		if (offset > inode->i_sb->s_maxbytes)
+			goto out_big;
+	} else {
+		/*
+		 * truncation of in-use swapfiles is disallowed - it would
+		 * cause subsequent swapout to scribble on the now-freed
+		 * blocks.
+		 */
+		if (IS_SWAPFILE(inode))
+			return -ETXTBSY;
+	}
+
+	return 0;
+out_sig:
+	send_sig(SIGXFSZ, current, 0);
+out_big:
+	return -EFBIG;
+}
+EXPORT_SYMBOL(inode_newsize_ok);
+
 int inode_setattr(struct inode * inode, struct iattr * attr)
 {
 	unsigned int ia_valid = attr->ia_valid;
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 0b5ebcd..025763e 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -493,6 +493,7 @@ void sync_inodes_sb(struct super_block *sb, int wait)
 	sync_sb_inodes(sb, &wbc);
 	spin_unlock(&inode_lock);
 }
+EXPORT_SYMBOL_GPL(sync_inodes_sb);
 
 /*
  * Rather lame livelock avoidance.
@@ -700,6 +701,7 @@ int writeback_in_progress(struct backing_dev_info *bdi)
 {
 	return test_bit(BDI_pdflush, &bdi->state);
 }
+EXPORT_SYMBOL_GPL(writeback_in_progress);
 
 /**
  * writeback_release: relinquish exclusive writeback access against a device.
diff --git a/fs/libfs.c b/fs/libfs.c
index e09ecbf..0c3239b 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -8,6 +8,10 @@
 #include <linux/mount.h>
 #include <linux/vfs.h>
 #include <linux/mutex.h>
+#ifndef __GENKSYMS__
+#include <linux/writeback.h>
+#endif
+#include <linux/buffer_head.h>
 
 #include <asm/uaccess.h>
 
@@ -657,6 +661,29 @@ out:
 	return ret;
 }
 
+int simple_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_ALL,
+		.nr_to_write = 0, /* metadata-only; caller takes care of data */
+	};
+	struct inode *inode = dentry->d_inode;
+	int err;
+	int ret;
+
+	ret = sync_mapping_buffers(inode->i_mapping);
+	if (!(inode->i_state & I_DIRTY))
+		return ret;
+	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+		return ret;
+
+	err = sync_inode(inode, &wbc);
+	if (ret == 0)
+		ret = err;
+	return ret;
+}
+EXPORT_SYMBOL(simple_fsync);
+
 EXPORT_SYMBOL(dcache_dir_close);
 EXPORT_SYMBOL(dcache_dir_lseek);
 EXPORT_SYMBOL(dcache_dir_open);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index bae2f3d..564027b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2073,6 +2073,8 @@ extern void simple_release_fs(struct vfsmount **mount, int *count);
 
 extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, const void *, size_t);
 
+extern int simple_fsync(struct file *, struct dentry *, int);
+
 #ifdef CONFIG_MIGRATION
 extern int buffer_migrate_page(struct address_space *,
 				struct page *, struct page *);
@@ -2081,6 +2083,7 @@ extern int buffer_migrate_page(struct address_space *,
 #endif
 
 extern int inode_change_ok(struct inode *, struct iattr *);
+extern int inode_newsize_ok(const struct inode *, loff_t offset);
 extern int __must_check inode_setattr(struct inode *, struct iattr *);
 
 extern void file_update_time(struct file *file);
diff --git a/include/linux/log2.h b/include/linux/log2.h
index 99922be..05b34dd 100644
--- a/include/linux/log2.h
+++ b/include/linux/log2.h
@@ -165,4 +165,20 @@ unsigned long __roundup_pow_of_two(unsigned long n)
 	__roundup_pow_of_two(n)			\
  )
 
+/**
+ * order_base_2 - calculate the (rounded up) base 2 order of the argument
+ * @n: parameter
+ *
+ * The first few values calculated by this routine:
+ *  ob2(0) = 0
+ *  ob2(1) = 0
+ *  ob2(2) = 1
+ *  ob2(3) = 2
+ *  ob2(4) = 2
+ *  ob2(5) = 3
+ *  ... and so on.
+ */
+
+#define order_base_2(n) ilog2(roundup_pow_of_two(n))
+
 #endif /* _LINUX_LOG2_H */