[Pkg-lustre-svn-commit] updated: [897600b] move modifcations from .diff.gz to modified-debian-specific-stuff.patch Signed-off-by: Patrick Winnertz <winnie at debian.org>

Patrick Winnertz winnie at debian.org
Wed Nov 16 12:55:07 UTC 2011


The following commit has been merged in the master branch:
commit 897600b522724e19c60c1e4cb6d0fdc92e1ed33d
Author: Patrick Winnertz <winnie at debian.org>
Date:   Wed Nov 16 12:13:06 2011 +0100

    move modifcations from .diff.gz to modified-debian-specific-stuff.patch
    Signed-off-by: Patrick Winnertz <winnie at debian.org>

diff --git a/debian/patches/modified-debian-specific-stuff.patch b/debian/patches/modified-debian-specific-stuff.patch
new file mode 100644
index 0000000..38c77d5
--- /dev/null
+++ b/debian/patches/modified-debian-specific-stuff.patch
@@ -0,0 +1,4373 @@
+Description: everything which was incorporated into the .diff.gz over time
+ This patch contains every modification which was done directly in .diff.gz
+ over the time. Cleanup is required here in near future.
+ .
+ lustre (1.8.5+dfsg-3) unstable; urgency=low
+ .
+   * [9194f2d] Build ldiskfs kernel module also on plain
+     debian kernel (2.6.32)
+Author: Patrick Winnertz <winnie at debian.org>
+
+---
+The information above should follow the Patch Tagging Guidelines, please
+checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
+are templates for supplementary fields that you might want to add:
+
+Origin: <vendor|upstream|other>, <url of original patch>
+Bug: <url in upstream bugtracker>
+Bug-Debian: http://bugs.debian.org/<bugnumber>
+Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
+Forwarded: <no|not-needed|url proving that it has been forwarded>
+Reviewed-By: <name and email of someone who approved the patch>
+Last-Update: <YYYY-MM-DD>
+
+--- /dev/null
++++ lustre-1.8.5+dfsg/ldiskfs/kernel_patches/series/ldiskfs-2.6.18-debian.series
+@@ -0,0 +1,20 @@
++ext3-wantedi-2.6-rhel4.patch
++iopen-2.6-fc5.patch
++ext3-map_inode_page-2.6.18.patch
++export-ext3-2.6-rhel4.patch
++ext3-include-fixes-2.6-rhel4.patch
++ext3-extents-2.6.18-vanilla.patch
++ext3-mballoc3-core.patch
++ext3-mballoc3-2.6.18.patch
++ext3-nlinks-2.6.9.patch
++ext3-ialloc-2.6.patch
++ext3-remove-cond_resched-calls-2.6.12.patch
++ext3-filterdata-sles10.patch
++ext3-16tb-overflow-fixes.patch
++ext3-uninit-2.6.18.patch
++ext3-nanosecond-2.6.18-vanilla.patch
++ext3-inode-version-2.6.18-vanilla.patch
++ext3-ea-expand-lose-block.patch
++ext3-mmp-2.6.18-vanilla.patch
++ext3-fiemap-2.6.18-vanilla.patch
++ext3-lookup-dotdot-2.6.9.patch
+--- /dev/null
++++ lustre-1.8.5+dfsg/lustre/kernel_patches/series/2.6.27-vanilla.series
+@@ -0,0 +1,15 @@
++lustre_version.patch
++vfs_races-2.6.22-vanilla.patch
++iopen-misc-2.6.22-vanilla.patch
++export-truncate-2.6.18-vanilla.patch 
++export_symbols-2.6.22-vanilla.patch 
++dev_read_only-2.6.27-vanilla.patch 
++export-2.6.27-vanilla.patch 
++export-show_task-2.6.27-vanilla.patch 
++sd_iostats-2.6.27-vanilla.patch
++md-mmp-unplug-dev-2.6.27-vanilla.patch
++quota-Split-off-quota-tree-handling-into-a-separate.patch
++quota-Increase-size-of-variables-for-limits-and-ino.patch
++quota-support-64-bit-quota-format-2.6.27-vanilla.patch
++jbd2-jcberr-2.6-sles11.patch
++jbd2-commit-timer-no-jiffies-rounding.diff
+--- /dev/null
++++ lustre-1.8.5+dfsg/lustre/kernel_patches/series/2.6.26-vanilla.series
+@@ -0,0 +1,2 @@
++lustre_version.patch
++debian-2.6.26.diff 
+--- /dev/null
++++ lustre-1.8.5+dfsg/lustre/kernel_patches/patches/quota-Increase-size-of-variables-for-limits-and-ino.patch
+@@ -0,0 +1,359 @@
++From: Jan Kara <jack at suse.cz>
++References: fate#302681
++Subject: [PATCH 02/28] quota: Increase size of variables for limits and inode usage
++Patch-mainline: 2.6.29?
++
++So far quota was fine with quota block limits and inode limits/numbers in
++a 32-bit type. Now with rapid increase in storage sizes there are coming
++requests to be able to handle quota limits above 4TB / more that 2^32 inodes.
++So bump up sizes of types in mem_dqblk structure to 64-bits to be able to
++handle this. Also update inode allocation / checking functions to use qsize_t
++and make global structure keep quota limits in bytes so that things are
++consistent.
++
++Signed-off-by: Jan Kara <jack at suse.cz>
++---
++ fs/dquot.c               |   50 ++++++++++++++++++++++++++-------------------
++ fs/quota_v1.c            |   25 +++++++++++++++++-----
++ fs/quota_v2.c            |   21 +++++++++++++++---
++ include/linux/quota.h    |   28 +++++++++++--------------
++ include/linux/quotaops.h |    4 +-
++ 5 files changed, 79 insertions(+), 49 deletions(-)
++
++diff --git a/fs/dquot.c b/fs/dquot.c
++index e1dac3e..758bf4a 100644
++--- a/fs/dquot.c
+++++ b/fs/dquot.c
++@@ -833,7 +833,7 @@ static void drop_dquot_ref(struct super_block *sb, int type)
++ 	}
++ }
++ 
++-static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
+++static inline void dquot_incr_inodes(struct dquot *dquot, qsize_t number)
++ {
++ 	dquot->dq_dqb.dqb_curinodes += number;
++ }
++@@ -843,7 +843,7 @@ static inline void dquot_incr_space(struct dquot *dquot, qsize_t number)
++ 	dquot->dq_dqb.dqb_curspace += number;
++ }
++ 
++-static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number)
+++static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
++ {
++ 	if (dquot->dq_dqb.dqb_curinodes > number)
++ 		dquot->dq_dqb.dqb_curinodes -= number;
++@@ -860,7 +860,7 @@ static inline void dquot_decr_space(struct dquot *dquot, qsize_t number)
++ 		dquot->dq_dqb.dqb_curspace -= number;
++ 	else
++ 		dquot->dq_dqb.dqb_curspace = 0;
++-	if (toqb(dquot->dq_dqb.dqb_curspace) <= dquot->dq_dqb.dqb_bsoftlimit)
+++	if (dquot->dq_dqb.dqb_curspace <= dquot->dq_dqb.dqb_bsoftlimit)
++ 		dquot->dq_dqb.dqb_btime = (time_t) 0;
++ 	clear_bit(DQ_BLKS_B, &dquot->dq_flags);
++ }
++@@ -1038,7 +1038,7 @@ static inline char ignore_hardlimit(struct dquot *dquot)
++ }
++ 
++ /* needs dq_data_lock */
++-static int check_idq(struct dquot *dquot, ulong inodes, char *warntype)
+++static int check_idq(struct dquot *dquot, qsize_t inodes, char *warntype)
++ {
++ 	*warntype = QUOTA_NL_NOWARN;
++ 	if (inodes <= 0 || test_bit(DQ_FAKE_B, &dquot->dq_flags))
++@@ -1077,7 +1077,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
++ 		return QUOTA_OK;
++ 
++ 	if (dquot->dq_dqb.dqb_bhardlimit &&
++-	   toqb(dquot->dq_dqb.dqb_curspace + space) > dquot->dq_dqb.dqb_bhardlimit &&
+++	    dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bhardlimit &&
++             !ignore_hardlimit(dquot)) {
++ 		if (!prealloc)
++ 			*warntype = QUOTA_NL_BHARDWARN;
++@@ -1085,7 +1085,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
++ 	}
++ 
++ 	if (dquot->dq_dqb.dqb_bsoftlimit &&
++-	   toqb(dquot->dq_dqb.dqb_curspace + space) > dquot->dq_dqb.dqb_bsoftlimit &&
+++	    dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bsoftlimit &&
++ 	    dquot->dq_dqb.dqb_btime && get_seconds() >= dquot->dq_dqb.dqb_btime &&
++             !ignore_hardlimit(dquot)) {
++ 		if (!prealloc)
++@@ -1094,7 +1094,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
++ 	}
++ 
++ 	if (dquot->dq_dqb.dqb_bsoftlimit &&
++-	   toqb(dquot->dq_dqb.dqb_curspace + space) > dquot->dq_dqb.dqb_bsoftlimit &&
+++	    dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bsoftlimit &&
++ 	    dquot->dq_dqb.dqb_btime == 0) {
++ 		if (!prealloc) {
++ 			*warntype = QUOTA_NL_BSOFTWARN;
++@@ -1111,7 +1111,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
++ 	return QUOTA_OK;
++ }
++ 
++-static int info_idq_free(struct dquot *dquot, ulong inodes)
+++static int info_idq_free(struct dquot *dquot, qsize_t inodes)
++ {
++ 	if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
++ 	    dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit)
++@@ -1128,15 +1128,13 @@ static int info_idq_free(struct dquot *dquot, ulong inodes)
++ static int info_bdq_free(struct dquot *dquot, qsize_t space)
++ {
++ 	if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
++-	    toqb(dquot->dq_dqb.dqb_curspace) <= dquot->dq_dqb.dqb_bsoftlimit)
+++	    dquot->dq_dqb.dqb_curspace <= dquot->dq_dqb.dqb_bsoftlimit)
++ 		return QUOTA_NL_NOWARN;
++ 
++-	if (toqb(dquot->dq_dqb.dqb_curspace - space) <=
++-	    dquot->dq_dqb.dqb_bsoftlimit)
+++	if (dquot->dq_dqb.dqb_curspace - space <= dquot->dq_dqb.dqb_bsoftlimit)
++ 		return QUOTA_NL_BSOFTBELOW;
++-	if (toqb(dquot->dq_dqb.dqb_curspace) >= dquot->dq_dqb.dqb_bhardlimit &&
++-	    toqb(dquot->dq_dqb.dqb_curspace - space) <
++-						dquot->dq_dqb.dqb_bhardlimit)
+++	if (dquot->dq_dqb.dqb_curspace >= dquot->dq_dqb.dqb_bhardlimit &&
+++	    dquot->dq_dqb.dqb_curspace - space < dquot->dq_dqb.dqb_bhardlimit)
++ 		return QUOTA_NL_BHARDBELOW;
++ 	return QUOTA_NL_NOWARN;
++ }
++@@ -1279,7 +1277,7 @@ warn_put_all:
++ /*
++  * This operation can block, but only after everything is updated
++  */
++-int dquot_alloc_inode(const struct inode *inode, unsigned long number)
+++int dquot_alloc_inode(const struct inode *inode, qsize_t number)
++ {
++ 	int cnt, ret = NO_QUOTA;
++ 	char warntype[MAXQUOTAS];
++@@ -1364,7 +1362,7 @@ out_sub:
++ /*
++  * This operation can block, but only after everything is updated
++  */
++-int dquot_free_inode(const struct inode *inode, unsigned long number)
+++int dquot_free_inode(const struct inode *inode, qsize_t number)
++ {
++ 	unsigned int cnt;
++ 	char warntype[MAXQUOTAS];
++@@ -1881,14 +1879,24 @@ int vfs_dq_quota_on_remount(struct super_block *sb)
++ 	return ret;
++ }
++ 
+++static inline qsize_t qbtos(qsize_t blocks)
+++{
+++	return blocks << QIF_DQBLKSIZE_BITS;
+++}
+++
+++static inline qsize_t stoqb(qsize_t space)
+++{
+++	return (space + QIF_DQBLKSIZE - 1) >> QIF_DQBLKSIZE_BITS;
+++}
+++
++ /* Generic routine for getting common part of quota structure */
++ static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di)
++ {
++ 	struct mem_dqblk *dm = &dquot->dq_dqb;
++ 
++ 	spin_lock(&dq_data_lock);
++-	di->dqb_bhardlimit = dm->dqb_bhardlimit;
++-	di->dqb_bsoftlimit = dm->dqb_bsoftlimit;
+++	di->dqb_bhardlimit = stoqb(dm->dqb_bhardlimit);
+++	di->dqb_bsoftlimit = stoqb(dm->dqb_bsoftlimit);
++ 	di->dqb_curspace = dm->dqb_curspace;
++ 	di->dqb_ihardlimit = dm->dqb_ihardlimit;
++ 	di->dqb_isoftlimit = dm->dqb_isoftlimit;
++@@ -1935,8 +1943,8 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
++ 		check_blim = 1;
++ 	}
++ 	if (di->dqb_valid & QIF_BLIMITS) {
++-		dm->dqb_bsoftlimit = di->dqb_bsoftlimit;
++-		dm->dqb_bhardlimit = di->dqb_bhardlimit;
+++		dm->dqb_bsoftlimit = qbtos(di->dqb_bsoftlimit);
+++		dm->dqb_bhardlimit = qbtos(di->dqb_bhardlimit);
++ 		check_blim = 1;
++ 	}
++ 	if (di->dqb_valid & QIF_INODES) {
++@@ -1954,7 +1962,7 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
++ 		dm->dqb_itime = di->dqb_itime;
++ 
++ 	if (check_blim) {
++-		if (!dm->dqb_bsoftlimit || toqb(dm->dqb_curspace) < dm->dqb_bsoftlimit) {
+++		if (!dm->dqb_bsoftlimit || dm->dqb_curspace < dm->dqb_bsoftlimit) {
++ 			dm->dqb_btime = 0;
++ 			clear_bit(DQ_BLKS_B, &dquot->dq_flags);
++ 		}
++diff --git a/fs/quota_v1.c b/fs/quota_v1.c
++index 5ae15b1..3e078ee 100644
++--- a/fs/quota_v1.c
+++++ b/fs/quota_v1.c
++@@ -14,14 +14,27 @@ MODULE_AUTHOR("Jan Kara");
++ MODULE_DESCRIPTION("Old quota format support");
++ MODULE_LICENSE("GPL");
++ 
+++#define QUOTABLOCK_BITS 10
+++#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
+++
+++static inline qsize_t v1_stoqb(qsize_t space)
+++{
+++	return (space + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS;
+++}
+++
+++static inline qsize_t v1_qbtos(qsize_t blocks)
+++{
+++	return blocks << QUOTABLOCK_BITS;
+++}
+++
++ static void v1_disk2mem_dqblk(struct mem_dqblk *m, struct v1_disk_dqblk *d)
++ {
++ 	m->dqb_ihardlimit = d->dqb_ihardlimit;
++ 	m->dqb_isoftlimit = d->dqb_isoftlimit;
++ 	m->dqb_curinodes = d->dqb_curinodes;
++-	m->dqb_bhardlimit = d->dqb_bhardlimit;
++-	m->dqb_bsoftlimit = d->dqb_bsoftlimit;
++-	m->dqb_curspace = ((qsize_t)d->dqb_curblocks) << QUOTABLOCK_BITS;
+++	m->dqb_bhardlimit = v1_qbtos(d->dqb_bhardlimit);
+++	m->dqb_bsoftlimit = v1_qbtos(d->dqb_bsoftlimit);
+++	m->dqb_curspace = v1_qbtos(d->dqb_curblocks);
++ 	m->dqb_itime = d->dqb_itime;
++ 	m->dqb_btime = d->dqb_btime;
++ }
++@@ -31,9 +44,9 @@ static void v1_mem2disk_dqblk(struct v1_disk_dqblk *d, struct mem_dqblk *m)
++ 	d->dqb_ihardlimit = m->dqb_ihardlimit;
++ 	d->dqb_isoftlimit = m->dqb_isoftlimit;
++ 	d->dqb_curinodes = m->dqb_curinodes;
++-	d->dqb_bhardlimit = m->dqb_bhardlimit;
++-	d->dqb_bsoftlimit = m->dqb_bsoftlimit;
++-	d->dqb_curblocks = toqb(m->dqb_curspace);
+++	d->dqb_bhardlimit = v1_stoqb(m->dqb_bhardlimit);
+++	d->dqb_bsoftlimit = v1_stoqb(m->dqb_bsoftlimit);
+++	d->dqb_curblocks = v1_stoqb(m->dqb_curspace);
++ 	d->dqb_itime = m->dqb_itime;
++ 	d->dqb_btime = m->dqb_btime;
++ }
++diff --git a/fs/quota_v2.c b/fs/quota_v2.c
++index b53827d..51c4717 100644
++--- a/fs/quota_v2.c
+++++ b/fs/quota_v2.c
++@@ -26,6 +26,19 @@ typedef char *dqbuf_t;
++ #define GETIDINDEX(id, depth) (((id) >> ((V2_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
++ #define GETENTRIES(buf) ((struct v2_disk_dqblk *)(((char *)buf)+sizeof(struct v2_disk_dqdbheader)))
++ 
+++#define QUOTABLOCK_BITS 10
+++#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
+++
+++static inline qsize_t v2_stoqb(qsize_t space)
+++{
+++	return (space + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS;
+++}
+++
+++static inline qsize_t v2_qbtos(qsize_t blocks)
+++{
+++	return blocks << QUOTABLOCK_BITS;
+++}
+++
++ /* Check whether given file is really vfsv0 quotafile */
++ static int v2_check_quota_file(struct super_block *sb, int type)
++ {
++@@ -104,8 +117,8 @@ static void disk2memdqb(struct mem_dqblk *m, struct v2_disk_dqblk *d)
++ 	m->dqb_isoftlimit = le32_to_cpu(d->dqb_isoftlimit);
++ 	m->dqb_curinodes = le32_to_cpu(d->dqb_curinodes);
++ 	m->dqb_itime = le64_to_cpu(d->dqb_itime);
++-	m->dqb_bhardlimit = le32_to_cpu(d->dqb_bhardlimit);
++-	m->dqb_bsoftlimit = le32_to_cpu(d->dqb_bsoftlimit);
+++	m->dqb_bhardlimit = v2_qbtos(le32_to_cpu(d->dqb_bhardlimit));
+++	m->dqb_bsoftlimit = v2_qbtos(le32_to_cpu(d->dqb_bsoftlimit));
++ 	m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
++ 	m->dqb_btime = le64_to_cpu(d->dqb_btime);
++ }
++@@ -116,8 +129,8 @@ static void mem2diskdqb(struct v2_disk_dqblk *d, struct mem_dqblk *m, qid_t id)
++ 	d->dqb_isoftlimit = cpu_to_le32(m->dqb_isoftlimit);
++ 	d->dqb_curinodes = cpu_to_le32(m->dqb_curinodes);
++ 	d->dqb_itime = cpu_to_le64(m->dqb_itime);
++-	d->dqb_bhardlimit = cpu_to_le32(m->dqb_bhardlimit);
++-	d->dqb_bsoftlimit = cpu_to_le32(m->dqb_bsoftlimit);
+++	d->dqb_bhardlimit = cpu_to_le32(v2_qbtos(m->dqb_bhardlimit));
+++	d->dqb_bsoftlimit = cpu_to_le32(v2_qbtos(m->dqb_bsoftlimit));
++ 	d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
++ 	d->dqb_btime = cpu_to_le64(m->dqb_btime);
++ 	d->dqb_id = cpu_to_le32(id);
++diff --git a/include/linux/quota.h b/include/linux/quota.h
++index eeae7a9..5167786 100644
++--- a/include/linux/quota.h
+++++ b/include/linux/quota.h
++@@ -41,15 +41,6 @@
++ #define __DQUOT_VERSION__	"dquot_6.5.1"
++ #define __DQUOT_NUM_VERSION__	6*10000+5*100+1
++ 
++-/* Size of blocks in which are counted size limits */
++-#define QUOTABLOCK_BITS 10
++-#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
++-
++-/* Conversion routines from and to quota blocks */
++-#define qb2kb(x) ((x) << (QUOTABLOCK_BITS-10))
++-#define kb2qb(x) ((x) >> (QUOTABLOCK_BITS-10))
++-#define toqb(x) (((x) + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS)
++-
++ #define MAXQUOTAS 2
++ #define USRQUOTA  0		/* element used for user quotas */
++ #define GRPQUOTA  1		/* element used for group quotas */
++@@ -82,6 +73,11 @@
++ #define Q_GETQUOTA 0x800007	/* get user quota structure */
++ #define Q_SETQUOTA 0x800008	/* set user quota structure */
++ 
+++/* Size of block in which space limits are passed through the quota
+++ * interface */
+++#define QIF_DQBLKSIZE_BITS 10
+++#define QIF_DQBLKSIZE (1 << QIF_DQBLKSIZE_BITS)
+++
++ /*
++  * Quota structure used for communication with userspace via quotactl
++  * Following flags are used to specify which fields are valid
++@@ -189,12 +185,12 @@ extern spinlock_t dq_data_lock;
++  * Data for one user/group kept in memory
++  */
++ struct mem_dqblk {
++-	__u32 dqb_bhardlimit;	/* absolute limit on disk blks alloc */
++-	__u32 dqb_bsoftlimit;	/* preferred limit on disk blks */
+++	qsize_t dqb_bhardlimit;	/* absolute limit on disk blks alloc */
+++	qsize_t dqb_bsoftlimit;	/* preferred limit on disk blks */
++ 	qsize_t dqb_curspace;	/* current used space */
++-	__u32 dqb_ihardlimit;	/* absolute limit on allocated inodes */
++-	__u32 dqb_isoftlimit;	/* preferred inode limit */
++-	__u32 dqb_curinodes;	/* current # allocated inodes */
+++	qsize_t dqb_ihardlimit;	/* absolute limit on allocated inodes */
+++	qsize_t dqb_isoftlimit;	/* preferred inode limit */
+++	qsize_t dqb_curinodes;	/* current # allocated inodes */
++ 	time_t dqb_btime;	/* time limit for excessive disk use */
++ 	time_t dqb_itime;	/* time limit for excessive inode use */
++ };
++@@ -289,9 +285,9 @@ struct dquot_operations {
++ 	int (*initialize) (struct inode *, int);
++ 	int (*drop) (struct inode *);
++ 	int (*alloc_space) (struct inode *, qsize_t, int);
++-	int (*alloc_inode) (const struct inode *, unsigned long);
+++	int (*alloc_inode) (const struct inode *, qsize_t);
++ 	int (*free_space) (struct inode *, qsize_t);
++-	int (*free_inode) (const struct inode *, unsigned long);
+++	int (*free_inode) (const struct inode *, qsize_t);
++ 	int (*transfer) (struct inode *, struct iattr *);
++ 	int (*write_dquot) (struct dquot *);		/* Ordinary dquot write */
++ 	struct dquot *(*alloc_dquot)(struct super_block *, int);	/* Allocate memory for new dquot (can be NULL if no special entries dquot are needed) */
++diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
++index ca6b9b5..9e7bc4b 100644
++--- a/include/linux/quotaops.h
+++++ b/include/linux/quotaops.h
++@@ -29,10 +29,10 @@ int dquot_initialize(struct inode *inode, int type);
++ int dquot_drop(struct inode *inode);
++ 
++ int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
++-int dquot_alloc_inode(const struct inode *inode, unsigned long number);
+++int dquot_alloc_inode(const struct inode *inode, qsize_t number);
++ 
++ int dquot_free_space(struct inode *inode, qsize_t number);
++-int dquot_free_inode(const struct inode *inode, unsigned long number);
+++int dquot_free_inode(const struct inode *inode, qsize_t number);
++ 
++ int dquot_transfer(struct inode *inode, struct iattr *iattr);
++ int dquot_commit(struct dquot *dquot);
++-- 
++1.5.2.4
++
+--- /dev/null
++++ lustre-1.8.5+dfsg/lustre/kernel_patches/patches/export-2.6.26-vanilla.patch
+@@ -0,0 +1,24 @@
++Index: linux-source-2.6.26/fs/jbd2/journal.c
++===================================================================
++--- linux-source-2.6.26.orig/fs/jbd2/journal.c	2009-10-09 13:49:43.000000000 +0200
+++++ linux-source-2.6.26/fs/jbd2/journal.c	2009-10-09 13:49:50.000000000 +0200
++@@ -460,6 +460,7 @@
++ 	spin_unlock(&journal->j_state_lock);
++ 	return ret;
++ }
+++EXPORT_SYMBOL(jbd2_log_start_commit);
++ 
++ /*
++  * Force and wait upon a commit if the calling process is not within
++Index: linux-source-2.6.26/security/security.c
++===================================================================
++--- linux-source-2.6.26.orig/security/security.c	2009-10-09 13:49:43.000000000 +0200
+++++ linux-source-2.6.26/security/security.c	2009-10-09 13:49:50.000000000 +0200
++@@ -68,6 +68,7 @@
++ 
++ 	return 0;
++ }
+++EXPORT_SYMBOL(security_inode_unlink);
++ 
++ /* Save user chosen LSM */
++ static int __init choose_lsm(char *str)
+--- /dev/null
++++ lustre-1.8.5+dfsg/lustre/kernel_patches/patches/quota-support-64-bit-quota-format-2.6.27-vanilla.patch
+@@ -0,0 +1,282 @@
++From: Jan Kara <jack at suse.cz>
++
++Implement conversion functions for new version (version 1) of quota format
++which supports 64-bit block and inode limits and 64-bit inode usage.  The
++original implementation has been written by Andrew Perepechko.
++
++Signed-off-by: Andrew Perepechko <andrew.perepechko at sun.com>
++Signed-off-by: Jan Kara <jack at suse.cz>
++Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
++---
++
++ fs/quota_v2.c   |  140 ++++++++++++++++++++++++++++++++++++----------
++ fs/quotaio_v2.h |   26 ++++++--
++ 2 files changed, 132 insertions(+), 34 deletions(-)
++
++Index: linux-2.6.27.36/fs/quota_v2.c
++===================================================================
++--- linux-2.6.27.36.orig/fs/quota_v2.c	2009-10-09 17:00:48.000000000 +0200
+++++ linux-2.6.27.36/fs/quota_v2.c	2009-10-09 17:03:35.000000000 +0200
++@@ -23,14 +23,24 @@
++ 
++ #define __QUOTA_V2_PARANOIA
++ 
++-static void v2_mem2diskdqb(void *dp, struct dquot *dquot);
++-static void v2_disk2memdqb(struct dquot *dquot, void *dp);
++-static int v2_is_id(void *dp, struct dquot *dquot);
++-
++-static struct qtree_fmt_operations v2_qtree_ops = {
++-	.mem2disk_dqblk = v2_mem2diskdqb,
++-	.disk2mem_dqblk = v2_disk2memdqb,
++-	.is_id = v2_is_id,
+++static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot);
+++static void v2r0_disk2memdqb(struct dquot *dquot, void *dp);
+++static int v2r0_is_id(void *dp, struct dquot *dquot);
+++
+++static struct qtree_fmt_operations v2r0_qtree_ops = {
+++      .mem2disk_dqblk = v2r0_mem2diskdqb,
+++      .disk2mem_dqblk = v2r0_disk2memdqb,
+++      .is_id = v2r0_is_id,
+++};
+++
+++static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot);
+++static void v2r1_disk2memdqb(struct dquot *dquot, void *dp);
+++static int v2r1_is_id(void *dp, struct dquot *dquot);
+++
+++static struct qtree_fmt_operations v2r1_qtree_ops = {
+++      .mem2disk_dqblk = v2r1_mem2diskdqb,
+++      .disk2mem_dqblk = v2r1_disk2memdqb,
+++      .is_id = v2r1_is_id,
++ };
++ 
++ #define QUOTABLOCK_BITS 10
++@@ -46,8 +56,7 @@
++ 	return blocks << QUOTABLOCK_BITS;
++ }
++ 
++-/* Check whether given file is really vfsv0 quotafile */
++-static int v2_check_quota_file(struct super_block *sb, int type)
+++static int v2_check_quota_file_header(struct super_block *sb, int type)
++ {
++ 	struct v2_disk_dqheader dqhead;
++ 	ssize_t size;
++@@ -58,12 +67,20 @@
++ 	if (size != sizeof(struct v2_disk_dqheader)) {
++ 		printk("quota_v2: failed read expected=%zd got=%zd\n",
++ 			sizeof(struct v2_disk_dqheader), size);
++-		return 0;
+++		return -EIO;
++ 	}
++-	if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
++-	    le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
++-		return 0;
++-	return 1;
+++	if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type])
+++		return -ENOENT;
+++	if (le32_to_cpu(dqhead.dqh_version) > quota_versions[type])
+++		return -EOPNOTSUPP;
+++	return le32_to_cpu(dqhead.dqh_version);
+++}
+++
+++
+++/* Check whether given file is really vfsv0 quotafile */
+++static int v2_check_quota_file(struct super_block *sb, int type)
+++{
+++	return v2_check_quota_file_header(sb, type) >= 0;
++ }
++ 
++ /* Read information header from quota file */
++@@ -72,7 +89,13 @@
++ 	struct v2_disk_dqinfo dinfo;
++ 	struct mem_dqinfo *info = sb_dqinfo(sb, type);
++ 	ssize_t size;
+++	int version = v2_check_quota_file_header(sb, type);
++ 
+++	if (version < 0) {
+++		printk(KERN_WARNING "Cannot identify quota file version on "
+++		       "device %s: %d\n", sb->s_id, version);
+++		return -1;
+++	}
++ 	size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
++ 	       sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
++ 	if (size != sizeof(struct v2_disk_dqinfo)) {
++@@ -81,8 +104,14 @@
++ 		return -1;
++ 	}
++ 	/* limits are stored as unsigned 32-bit data */
++-	info->dqi_maxblimit = 0xffffffff;
++-	info->dqi_maxilimit = 0xffffffff;
+++        if (version == 0) {
+++                /* limits are stored as unsigned 32-bit data */
+++                info->dqi_maxblimit = 0xffffffff;
+++                info->dqi_maxilimit = 0xffffffff;
+++        } else {
+++                info->dqi_maxblimit = 0x7fffffffffffffffULL;
+++                info->dqi_maxilimit = 0x7fffffffffffffffULL;
+++        }
++ 	info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
++ 	info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
++ 	info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
++@@ -94,8 +123,13 @@
++ 	info->u.v2_i.i.dqi_blocksize_bits = V2_DQBLKSIZE_BITS;
++ 	info->u.v2_i.i.dqi_usable_bs = 1 << V2_DQBLKSIZE_BITS;
++ 	info->u.v2_i.i.dqi_qtree_depth = qtree_depth(&info->u.v2_i.i);
++-	info->u.v2_i.i.dqi_entry_size = sizeof(struct v2_disk_dqblk);
++-	info->u.v2_i.i.dqi_ops = &v2_qtree_ops;
+++        if (version == 0) {
+++                qinfo->dqi_entry_size = sizeof(struct v2r0_disk_dqblk);
+++                qinfo->dqi_ops = &v2r0_qtree_ops;
+++        } else {
+++                qinfo->dqi_entry_size = sizeof(struct v2r1_disk_dqblk);
+++                qinfo->dqi_ops = &v2r1_qtree_ops;
+++        }
++ 	return 0;
++ }
++ 
++@@ -125,9 +159,9 @@
++ 	return 0;
++ }
++ 
++-static void v2_disk2memdqb(struct dquot *dquot, void *dp)
+++static void v2r0_disk2memdqb(struct dquot *dquot, void *dp)
++ {
++-	struct v2_disk_dqblk *d = dp, empty;
+++	struct v2r0_disk_dqblk *d = dp, empty;
++ 	struct mem_dqblk *m = &dquot->dq_dqb;
++ 
++ 	m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit);
++@@ -139,15 +173,15 @@
++ 	m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
++ 	m->dqb_btime = le64_to_cpu(d->dqb_btime);
++ 	/* We need to escape back all-zero structure */
++-	memset(&empty, 0, sizeof(struct v2_disk_dqblk));
+++	memset(&empty, 0, sizeof(struct v2r0_disk_dqblk));
++ 	empty.dqb_itime = cpu_to_le64(1);
++-	if (!memcmp(&empty, dp, sizeof(struct v2_disk_dqblk)))
+++	if (!memcmp(&empty, dp, sizeof(struct v2r0_disk_dqblk)))
++ 		m->dqb_itime = 0;
++ }
++ 
++-static void v2_mem2diskdqb(void *dp, struct dquot *dquot)
+++static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot)
++ {
++-	struct v2_disk_dqblk *d = dp;
+++	struct v2r0_disk_dqblk *d = dp;
++ 	struct mem_dqblk *m = &dquot->dq_dqb;
++ 	struct qtree_mem_dqinfo *info =
++ 			&sb_dqinfo(dquot->dq_sb, dquot->dq_type)->u.v2_i.i;
++@@ -165,9 +199,60 @@
++ 		d->dqb_itime = cpu_to_le64(1);
++ }
++ 
++-static int v2_is_id(void *dp, struct dquot *dquot)
+++static int v2r0_is_id(void *dp, struct dquot *dquot)
+++{
+++	struct v2r0_disk_dqblk *d = dp;
+++	struct qtree_mem_dqinfo *info =
+++			sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
+++
+++	if (qtree_entry_unused(info, dp))
+++		return 0;
+++	return le32_to_cpu(d->dqb_id) == dquot->dq_id;
+++}
+++
+++static void v2r1_disk2memdqb(struct dquot *dquot, void *dp)
+++{
+++	struct v2r1_disk_dqblk *d = dp, empty;
+++	struct mem_dqblk *m = &dquot->dq_dqb;
+++
+++	m->dqb_ihardlimit = le64_to_cpu(d->dqb_ihardlimit);
+++	m->dqb_isoftlimit = le64_to_cpu(d->dqb_isoftlimit);
+++	m->dqb_curinodes = le64_to_cpu(d->dqb_curinodes);
+++	m->dqb_itime = le64_to_cpu(d->dqb_itime);
+++	m->dqb_bhardlimit = v2_qbtos(le64_to_cpu(d->dqb_bhardlimit));
+++	m->dqb_bsoftlimit = v2_qbtos(le64_to_cpu(d->dqb_bsoftlimit));
+++	m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
+++	m->dqb_btime = le64_to_cpu(d->dqb_btime);
+++	/* We need to escape back all-zero structure */
+++	memset(&empty, 0, sizeof(struct v2r1_disk_dqblk));
+++	empty.dqb_itime = cpu_to_le64(1);
+++	if (!memcmp(&empty, dp, sizeof(struct v2r1_disk_dqblk)))
+++		m->dqb_itime = 0;
+++}
+++
+++static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot)
+++{
+++	struct v2r1_disk_dqblk *d = dp;
+++	struct mem_dqblk *m = &dquot->dq_dqb;
+++	struct qtree_mem_dqinfo *info =
+++			sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
+++
+++	d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
+++	d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
+++	d->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
+++	d->dqb_itime = cpu_to_le64(m->dqb_itime);
+++	d->dqb_bhardlimit = cpu_to_le64(v2_stoqb(m->dqb_bhardlimit));
+++	d->dqb_bsoftlimit = cpu_to_le64(v2_stoqb(m->dqb_bsoftlimit));
+++	d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
+++	d->dqb_btime = cpu_to_le64(m->dqb_btime);
+++	d->dqb_id = cpu_to_le32(dquot->dq_id);
+++	if (qtree_entry_unused(info, dp))
+++		d->dqb_itime = cpu_to_le64(1);
+++}
+++
+++static int v2r1_is_id(void *dp, struct dquot *dquot)
++ {
++-	struct v2_disk_dqblk *d = dp;
+++	struct v2r1_disk_dqblk *d = dp;
++ 	struct qtree_mem_dqinfo *info =
++ 			&sb_dqinfo(dquot->dq_sb, dquot->dq_type)->u.v2_i.i;
++ 
++Index: linux-2.6.27.36/include/linux/quotaio_v2.h
++===================================================================
++--- linux-2.6.27.36.orig/include/linux/quotaio_v2.h	2009-10-09 17:00:48.000000000 +0200
+++++ linux-2.6.27.36/include/linux/quotaio_v2.h	2009-10-09 17:00:56.000000000 +0200
++@@ -17,8 +17,8 @@
++ }
++ 
++ #define V2_INITQVERSIONS {\
++-	0,		/* USRQUOTA */\
++-	0		/* GRPQUOTA */\
+++	1,		/* USRQUOTA */\
+++	1		/* GRPQUOTA */\
++ }
++ 
++ /* First generic header */
++@@ -28,11 +28,11 @@
++ };
++ 
++ /*
++- * The following structure defines the format of the disk quota file
++- * (as it appears on disk) - the file is a radix tree whose leaves point
++- * to blocks of these structures.
+++ * The following structure defines the format of the disk quota file in version
+++ * 0 - the file is a radix tree whose leaves point to blocks of these
+++ * structures.
++  */
++-struct v2_disk_dqblk {
+++struct v2r0_disk_dqblk {
++ 	__le32 dqb_id;		/* id this quota applies to */
++ 	__le32 dqb_ihardlimit;	/* absolute limit on allocated inodes */
++ 	__le32 dqb_isoftlimit;	/* preferred inode limit */
++@@ -44,6 +44,20 @@
++ 	__le64 dqb_itime;	/* time limit for excessive inode use */
++ };
++ 
+++/* The same structure in quota file version 1 */
+++struct v2r1_disk_dqblk {
+++	__le32 dqb_id;		/* id this quota applies to */
+++	__le32 dqb_padding;	/* padding field */
+++	__le64 dqb_ihardlimit;	/* absolute limit on allocated inodes */
+++	__le64 dqb_isoftlimit;	/* preferred inode limit */
+++	__le64 dqb_curinodes;	/* current # allocated inodes */
+++	__le64 dqb_bhardlimit;	/* absolute limit on disk space */
+++	__le64 dqb_bsoftlimit;	/* preferred limit on disk space */
+++	__le64 dqb_curspace;	/* current space occupied (in bytes) */
+++	__le64 dqb_btime;	/* time limit for excessive disk use */
+++	__le64 dqb_itime;	/* time limit for excessive inode use */
+++};
+++
++ /* Header with type and version specific information */
++ struct v2_disk_dqinfo {
++ 	__le32 dqi_bgrace;	/* Time before block soft limit becomes hard limit */
+--- /dev/null
++++ lustre-1.8.5+dfsg/lustre/kernel_patches/patches/sd_iostats-2.6.26-vanilla.patch
+@@ -0,0 +1,579 @@
++Index: linux-source-2.6.26/drivers/scsi/Kconfig
++===================================================================
++--- linux-source-2.6.26.orig/drivers/scsi/Kconfig	2009-10-09 13:33:25.000000000 +0200
+++++ linux-source-2.6.26/drivers/scsi/Kconfig	2009-10-09 13:39:06.000000000 +0200
++@@ -81,6 +81,14 @@
++ 	  In this case, do not compile the driver for your SCSI host adapter
++ 	  (below) as a module either.
++ 
+++config SD_IOSTATS
+++   bool "Enable SCSI disk I/O stats"
+++   depends on BLK_DEV_SD
+++   default y
+++   ---help---
+++     This enables SCSI disk I/O stats collection.  You must also enable
+++     /proc file system support if you want this feature.
+++
++ config CHR_DEV_ST
++ 	tristate "SCSI tape support"
++ 	depends on SCSI
++Index: linux-source-2.6.26/drivers/scsi/scsi_proc.c
++===================================================================
++--- linux-source-2.6.26.orig/drivers/scsi/scsi_proc.c	2009-10-09 13:33:25.000000000 +0200
+++++ linux-source-2.6.26/drivers/scsi/scsi_proc.c	2009-10-09 13:39:06.000000000 +0200
++@@ -40,7 +40,8 @@
++ /* 4K page size, but our output routines, use some slack for overruns */
++ #define PROC_BLOCK_SIZE (3*1024)
++ 
++-static struct proc_dir_entry *proc_scsi;
+++struct proc_dir_entry *proc_scsi;
+++EXPORT_SYMBOL(proc_scsi);
++ 
++ /* Protect sht->present and sht->proc_dir */
++ static DEFINE_MUTEX(global_host_template_mutex);
++Index: linux-source-2.6.26/drivers/scsi/sd.c
++===================================================================
++--- linux-source-2.6.26.orig/drivers/scsi/sd.c	2009-10-09 13:33:25.000000000 +0200
+++++ linux-source-2.6.26/drivers/scsi/sd.c	2009-10-09 13:39:50.000000000 +0200
++@@ -107,6 +107,24 @@
++  * object after last put) */
++ static DEFINE_MUTEX(sd_ref_mutex);
++ 
+++#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
+++# include <linux/proc_fs.h>
+++# include <linux/seq_file.h>
+++struct proc_dir_entry *sd_iostats_procdir = NULL;
+++char sd_iostats_procdir_name[] = "sd_iostats";
+++static struct file_operations sd_iostats_proc_fops;
+++
+++extern void sd_iostats_init(void);
+++extern void sd_iostats_fini(void);
+++void sd_iostats_start_req(struct scsi_cmnd *SCpnt);
+++void sd_iostats_finish_req(struct scsi_cmnd *SCpnt);
+++#else
+++static inline void sd_iostats_init(void) {}
+++static inline void sd_iostats_fini(void) {}
+++static inline void sd_iostats_start_req(struct scsi_cmnd *SCpnt) {}
+++static inline void sd_iostats_finish_req(struct scsi_cmnd *SCpnt) {}
+++#endif
+++
++ static const char *sd_cache_types[] = {
++ 	"write through", "none", "write back",
++ 	"write back, no read (daft)"
++@@ -578,6 +596,8 @@
++ 
++ 	sdev = sdkp->device;
++ 
+++	sd_iostats_start_req(SCpnt);
+++
++ 	/*
++ 	 * If the device is in error recovery, wait until it is done.
++ 	 * If the device is offline, then disallow any access to it.
++@@ -1023,6 +1043,7 @@
++ 		break;
++ 	}
++  out:
+++ 	sd_iostats_finish_req(SCpnt);
++ 	return good_bytes;
++ }
++ 
++@@ -1712,6 +1733,36 @@
++ 	if (sdp->removable)
++ 		gd->flags |= GENHD_FL_REMOVABLE;
++ 
+++#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
+++	sdkp->stats = kzalloc(sizeof(iostat_stats_t), GFP_KERNEL);
+++	if (!sdkp->stats) {
+++		printk(KERN_WARNING "cannot allocate iostat structure for"
+++				    "%s\n", gd->disk_name);
+++	} else {
+++		do_gettimeofday(&sdkp->stats->iostat_timeval);
+++		sdkp->stats->iostat_queue_stamp = jiffies;
+++		spin_lock_init(&sdkp->stats->iostat_lock);
+++		if (sd_iostats_procdir) {
+++			struct proc_dir_entry *pde;
+++			pde = create_proc_entry(gd->disk_name, S_IRUGO | S_IWUSR,
+++					        sd_iostats_procdir);
+++			if (!pde) {
+++				printk(KERN_WARNING "Can't create /proc/scsi/"
+++						    "%s/%s\n",
+++						    sd_iostats_procdir_name,
+++						    gd->disk_name);
+++				kfree(sdkp->stats);
+++				sdkp->stats = NULL;
+++			} else {
+++				pde->proc_fops = &sd_iostats_proc_fops;
+++				pde->data = gd;
+++			}
+++		} else {
+++			kfree(sdkp->stats);
+++			sdkp->stats = NULL;
+++		}
+++	}
+++#endif
++ 	dev_set_drvdata(dev, sdkp);
++ 	add_disk(gd);
++ 
++@@ -1755,6 +1806,366 @@
++ 	return 0;
++ }
++ 
+++#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
+++static int
+++sd_iostats_seq_show(struct seq_file *seq, void *v)
+++{
+++	struct timeval     now;
+++	struct gendisk *disk = seq->private;
+++	iostat_stats_t    *stats;
+++	unsigned long long read_len;
+++	unsigned long long read_len_tot;
+++	unsigned long      read_num;
+++	unsigned long      read_num_tot;
+++	unsigned long long write_len;
+++	unsigned long long write_len_tot;
+++	unsigned long      write_num;
+++	unsigned long      write_num_tot;
+++	int                i;
+++	int                maxi;
+++
+++	stats = scsi_disk(disk)->stats;
+++	if (stats == NULL) {
+++		printk(KERN_ERR "sd_iostats_seq_show: NULL stats entry\n");
+++		BUG();
+++	}
+++
+++	do_gettimeofday(&now);
+++	now.tv_sec -= stats->iostat_timeval.tv_sec;
+++	now.tv_usec -= stats->iostat_timeval.tv_usec;
+++	if (now.tv_usec < 0) {
+++		now.tv_usec += 1000000;
+++		now.tv_sec--;
+++	}
+++
+++	/* this sampling races with updates */
+++	seq_printf(seq, "index:        %lu   snapshot_time:         %lu.%06lu\n",
+++			(unsigned long) scsi_disk(disk)->index,
+++			now.tv_sec, now.tv_usec);
+++
+++	for (i = IOSTAT_NCOUNTERS - 1; i > 0; i--)
+++		if (stats->iostat_read_histogram[i].iostat_count != 0 ||
+++				stats->iostat_write_histogram[i].iostat_count != 0)
+++			break;
+++	maxi = i;
+++
+++	seq_printf(seq, "%8s %8s %12s %8s %12s\n", "size", 
+++			"reads", "total", "writes", "total");
+++
+++	read_len_tot = write_len_tot = 0;
+++	read_num_tot = write_num_tot = 0;
+++	for (i = 0; i <= maxi; i++) {
+++		read_len = stats->iostat_read_histogram[i].iostat_size;
+++		read_len_tot += read_len;
+++		read_num = stats->iostat_read_histogram[i].iostat_count;
+++		read_num_tot += read_num;
+++
+++		write_len = stats->iostat_write_histogram[i].iostat_size;
+++		write_len_tot += write_len;
+++		write_num = stats->iostat_write_histogram[i].iostat_count;
+++		write_num_tot += write_num;
+++
+++		seq_printf (seq, "%8d %8lu %12llu %8lu %12llu\n", 
+++				512<<i, read_num, read_len, write_num, write_len);
+++	}
+++
+++	seq_printf(seq, "%8s %8lu %12llu %8lu %12llu\n\n", "total",
+++			read_num_tot, read_len_tot, 
+++			write_num_tot, write_len_tot);
+++
+++	seq_printf(seq, "%8s %8s %8s\n", "qdepth", "ticks", "%");
+++	for (i = 0; i < IOSTAT_NCOUNTERS; i++) {
+++		unsigned long long ticks, percent;
+++		ticks = stats->iostat_queue_ticks[i];
+++		if (ticks == 0)
+++			continue;
+++		percent = stats->iostat_queue_ticks[i] * 100;
+++		do_div(percent, stats->iostat_queue_ticks_sum);
+++		seq_printf(seq, "%8d %8llu %8llu\n", i, ticks, percent);
+++	}
+++
+++	if (stats->iostat_reqs != 0) {
+++		unsigned long long aveseek = 0, percent = 0;
+++
+++		if (stats->iostat_seeks) {
+++			aveseek = stats->iostat_seek_sectors;
+++			do_div(aveseek, stats->iostat_seeks);
+++			percent = stats->iostat_seeks * 100;
+++			do_div(percent, stats->iostat_reqs);
+++		}
+++
+++		seq_printf(seq, "\n%llu sectors in %llu reqs: %llu seek(s) over "
+++				"%llu sectors in ave, %llu%% of all reqs\n",
+++				stats->iostat_sectors, stats->iostat_reqs,
+++				stats->iostat_seeks, aveseek, percent);
+++	}
+++
+++	seq_printf(seq, "\n%16s %8s %8s %8s %8s\n", "process time", "reads",
+++			"%%", "writes", "%%");
+++	for (i = 0; i < IOSTAT_NCOUNTERS; i++) {
+++		unsigned long read_percent = 0, write_percent = 0;
+++		if (stats->iostat_wtime[i] == 0 &&
+++				stats->iostat_rtime[i] == 0)
+++			continue;
+++		if (stats->iostat_read_reqs)
+++			read_percent = stats->iostat_rtime[i] * 100 / 
+++				stats->iostat_read_reqs;
+++		if (stats->iostat_write_reqs)
+++			write_percent = stats->iostat_wtime[i] * 100 / 
+++				stats->iostat_write_reqs;
+++		seq_printf(seq, "%16u %8lu %8lu %8lu %8lu\n",
+++				jiffies_to_msecs(((1UL << i) >> 1) << 1),
+++				stats->iostat_rtime[i], read_percent,
+++				stats->iostat_wtime[i], write_percent);
+++	}
+++
+++	seq_printf(seq, "\n%16s %8s %8s %8s %8s\n", "time in queue", "reads",
+++			"%%", "writes", "%%");
+++	for (i = 0; i < IOSTAT_NCOUNTERS; i++) {
+++		unsigned long read_percent = 0, write_percent = 0;
+++		if (stats->iostat_wtime_in_queue[i] == 0 &&
+++				stats->iostat_rtime_in_queue[i] == 0)
+++			continue;
+++		if (stats->iostat_read_reqs)
+++			read_percent = stats->iostat_rtime_in_queue[i] * 100 / 
+++				stats->iostat_read_reqs;
+++		if (stats->iostat_write_reqs)
+++			write_percent = stats->iostat_wtime_in_queue[i] * 100 / 
+++				stats->iostat_write_reqs;
+++		seq_printf(seq, "%16u %8lu %8lu %8lu %8lu\n",
+++				jiffies_to_msecs(((1UL << i) >> 1) << 1),
+++				stats->iostat_rtime_in_queue[i],
+++				read_percent,
+++				stats->iostat_wtime_in_queue[i],
+++				write_percent);
+++	}
+++
+++	return 0;
+++}
+++
+++static void *
+++sd_iostats_seq_start(struct seq_file *p, loff_t *pos)
+++{
+++	return (*pos == 0) ? (void *)1 : NULL;
+++}
+++
+++static void *
+++sd_iostats_seq_next(struct seq_file *p, void *v, loff_t *pos)
+++{
+++	++*pos;
+++	return NULL;
+++}
+++
+++static void
+++sd_iostats_seq_stop(struct seq_file *p, void *v)
+++{
+++}
+++
+++static struct seq_operations sd_iostats_seqops = {
+++	.start = sd_iostats_seq_start,
+++	.stop  = sd_iostats_seq_stop,
+++	.next  = sd_iostats_seq_next,
+++	.show  = sd_iostats_seq_show,
+++};
+++
+++static int
+++sd_iostats_seq_open (struct inode *inode, struct file *file)
+++{
+++	int rc;
+++
+++	rc = seq_open(file, &sd_iostats_seqops);
+++	if (rc != 0)
+++		return rc;
+++
+++	((struct seq_file *)file->private_data)->private = PDE(inode)->data;
+++	return 0;
+++}
+++
+++static ssize_t
+++sd_iostats_seq_write(struct file *file, const char *buffer,
+++		     size_t len, loff_t *off)
+++{
+++	struct seq_file   *seq = file->private_data;
+++	struct gendisk *disk = seq->private;
+++	iostat_stats_t    *stats = scsi_disk(disk)->stats;
+++	unsigned long      flags;
+++	unsigned long      qdepth;
+++
+++
+++	spin_lock_irqsave (&stats->iostat_lock, flags);
+++	qdepth = stats->iostat_queue_depth;
+++	memset (stats, 0, offsetof(iostat_stats_t, iostat_lock));
+++	do_gettimeofday(&stats->iostat_timeval);
+++	stats->iostat_queue_stamp = jiffies;
+++	stats->iostat_queue_depth = qdepth;
+++	spin_unlock_irqrestore (&stats->iostat_lock, flags);
+++
+++	return len;
+++}
+++
+++static struct file_operations sd_iostats_proc_fops = {
+++	.owner   = THIS_MODULE,
+++	.open    = sd_iostats_seq_open,
+++	.read    = seq_read,
+++	.write   = sd_iostats_seq_write,
+++	.llseek  = seq_lseek,
+++	.release = seq_release,
+++};
+++
+++extern struct proc_dir_entry *proc_scsi;
+++
+++void
+++sd_iostats_init(void)
+++{
+++	if (proc_scsi == NULL) {
+++		printk(KERN_WARNING "No access to sd iostats: "
+++			"proc_scsi is NULL\n");
+++		return;
+++	}
+++
+++	sd_iostats_procdir = create_proc_entry(sd_iostats_procdir_name,
+++					       S_IFDIR | S_IRUGO | S_IXUGO,
+++					        proc_scsi);
+++	if (sd_iostats_procdir == NULL) {
+++		printk(KERN_WARNING "No access to sd iostats: "
+++			"can't create /proc/scsi/%s\n", sd_iostats_procdir_name);
+++		return;
+++	}
+++}
+++
+++void sd_iostats_fini(void)
+++{
+++	if (proc_scsi != NULL && sd_iostats_procdir != NULL)
+++		remove_proc_entry(sd_iostats_procdir_name, proc_scsi);
+++
+++	sd_iostats_procdir = NULL;
+++}
+++
+++void sd_iostats_finish_req(struct scsi_cmnd *SCpnt)
+++{
+++	struct request		*rq = SCpnt->request;
+++	iostat_stats_t		*stats;
+++	unsigned long		*tcounter;
+++	int			tbucket;
+++	int			tmp;
+++	unsigned long		irqflags;
+++	unsigned long		i;
+++
+++	stats = scsi_disk(rq->rq_disk)->stats;
+++	if (stats == NULL)
+++		return;
+++
+++	tmp = jiffies - rq->start_time;
+++	for (tbucket = 0; tmp > 1; tbucket++)
+++		tmp >>= 1;
+++	if (tbucket >= IOSTAT_NCOUNTERS)
+++		tbucket = IOSTAT_NCOUNTERS - 1;
+++	//printk("%u ticks in D to %u\n", jiffies - rq->start_time, tbucket);
+++
+++	tcounter = rq_data_dir(rq) == WRITE ?
+++		&stats->iostat_wtime[tbucket] : &stats->iostat_rtime[tbucket];
+++
+++	spin_lock_irqsave(&stats->iostat_lock, irqflags);
+++
+++	/* update delay stats */
+++	(*tcounter)++;
+++
+++	/* update queue depth stats */
+++	i = stats->iostat_queue_depth;
+++	if (i >= IOSTAT_NCOUNTERS)
+++		i = IOSTAT_NCOUNTERS - 1;
+++	stats->iostat_queue_ticks[i] += jiffies - stats->iostat_queue_stamp;
+++	stats->iostat_queue_ticks_sum += jiffies - stats->iostat_queue_stamp;
+++	BUG_ON(stats->iostat_queue_depth == 0);
+++	stats->iostat_queue_depth--;
+++
+++	/* update seek stats. XXX: not sure about nr_sectors */
+++	stats->iostat_sectors += rq->nr_sectors;
+++	stats->iostat_reqs++;
+++	if (rq->sector != stats->iostat_next_sector) {
+++		stats->iostat_seek_sectors +=
+++			rq->sector > stats->iostat_next_sector ?
+++			rq->sector - stats->iostat_next_sector :
+++			stats->iostat_next_sector - rq->sector;
+++		stats->iostat_seeks++;
+++	}
+++	stats->iostat_next_sector = rq->sector + rq->nr_sectors;
+++
+++	stats->iostat_queue_stamp = jiffies;
+++
+++	spin_unlock_irqrestore(&stats->iostat_lock, irqflags);
+++}
+++
+++void sd_iostats_start_req(struct scsi_cmnd *SCpnt)
+++{
+++	struct request		*rq = SCpnt->request;
+++	iostat_stats_t		*stats;
+++	iostat_counter_t	*counter;
+++	int			bucket;
+++	int			tbucket;
+++	int			tmp;
+++	unsigned long		irqflags;
+++	unsigned long		i;
+++	int			nsect;
+++
+++	stats = scsi_disk(rq->rq_disk)->stats;
+++	if (stats == NULL)
+++		return;
+++
+++	nsect = scsi_bufflen(SCpnt) >> 9;
+++	for (bucket = 0, tmp = nsect; tmp > 1; bucket++)
+++		tmp >>= 1;
+++
+++	if (bucket >= IOSTAT_NCOUNTERS) {
+++		printk (KERN_ERR "sd_iostats_bump: nsect %d too big\n", nsect);
+++		BUG();
+++	}
+++
+++	counter = rq_data_dir(rq) == WRITE ?
+++		&stats->iostat_write_histogram[bucket] :
+++		&stats->iostat_read_histogram[bucket];
+++
+++	tmp = jiffies - rq->start_time;
+++	for (tbucket = 0; tmp > 1; tbucket++)
+++		tmp >>= 1;
+++	if (tbucket >= IOSTAT_NCOUNTERS)
+++		tbucket = IOSTAT_NCOUNTERS - 1;
+++	//printk("%u ticks in Q to %u\n", jiffies - rq->start_time, tbucket);
+++
+++	/* an ugly hack to know exact processing time. the right
+++	 * solution is to add one more field to struct request
+++	 * hopefully it will break nothing ... */
+++	rq->start_time = jiffies;
+++
+++	spin_lock_irqsave(&stats->iostat_lock, irqflags);
+++
+++	/* update queue depth stats */
+++	i = stats->iostat_queue_depth;
+++	if (i >= IOSTAT_NCOUNTERS)
+++		i = IOSTAT_NCOUNTERS - 1;
+++	stats->iostat_queue_ticks[i] += jiffies - stats->iostat_queue_stamp;
+++	stats->iostat_queue_ticks_sum += jiffies - stats->iostat_queue_stamp;
+++	stats->iostat_queue_depth++;
+++
+++	/* update delay stats */
+++	if (rq_data_dir(rq) == WRITE) {
+++		stats->iostat_wtime_in_queue[tbucket]++;
+++		stats->iostat_write_reqs++;
+++	} else {
+++		stats->iostat_rtime_in_queue[tbucket]++;
+++		stats->iostat_read_reqs++;
+++	}
+++
+++	/* update size stats */
+++	counter->iostat_size += nsect;
+++	counter->iostat_count++;
+++
+++	stats->iostat_queue_stamp = jiffies;
+++
+++	spin_unlock_irqrestore(&stats->iostat_lock, irqflags);
+++}
+++#endif
+++
++ /**
++  *	scsi_disk_release - Called to free the scsi_disk structure
++  *	@dev: pointer to embedded class device
++@@ -1773,10 +2184,16 @@
++ 	idr_remove(&sd_index_idr, sdkp->index);
++ 	spin_unlock(&sd_index_lock);
++ 
+++#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
+++	if (sdkp->stats) {
+++		remove_proc_entry(disk->disk_name, sd_iostats_procdir);
+++		kfree(sdkp->stats);
+++		sdkp->stats = NULL;
+++	}
+++#endif
++ 	disk->private_data = NULL;
++ 	put_disk(disk);
++ 	put_device(&sdkp->device->sdev_gendev);
++-
++ 	kfree(sdkp);
++ }
++ 
++@@ -1890,6 +2307,8 @@
++ 	if (!majors)
++ 		return -ENODEV;
++ 
+++	sd_iostats_init();
+++
++ 	err = class_register(&sd_disk_class);
++ 	if (err)
++ 		goto err_out;
++@@ -1905,6 +2324,7 @@
++ err_out:
++ 	for (i = 0; i < SD_MAJORS; i++)
++ 		unregister_blkdev(sd_major(i), "sd");
+++	sd_iostats_fini();
++ 	return err;
++ }
++ 
++Index: linux-source-2.6.26/include/scsi/sd.h
++===================================================================
++--- linux-source-2.6.26.orig/include/scsi/sd.h	2009-10-09 13:33:25.000000000 +0200
+++++ linux-source-2.6.26/include/scsi/sd.h	2009-10-09 13:39:06.000000000 +0200
++@@ -31,6 +31,46 @@
++  */
++ #define SD_BUF_SIZE		512
++ 
+++#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
+++typedef struct {
+++	unsigned long long iostat_size;
+++	unsigned long long iostat_count;
+++} iostat_counter_t;
+++
+++#define IOSTAT_NCOUNTERS 16
+++typedef struct {
+++	iostat_counter_t	iostat_read_histogram[IOSTAT_NCOUNTERS];
+++	iostat_counter_t	iostat_write_histogram[IOSTAT_NCOUNTERS];
+++	struct timeval		iostat_timeval;
+++
+++	/* queue depth: how well the pipe is filled up */
+++	unsigned long long	iostat_queue_ticks[IOSTAT_NCOUNTERS];
+++	unsigned long long	iostat_queue_ticks_sum;
+++	unsigned long		iostat_queue_depth;
+++	unsigned long		iostat_queue_stamp;
+++
+++	/* seeks: how linear the traffic is */
+++	unsigned long long	iostat_next_sector;
+++	unsigned long long	iostat_seek_sectors;
+++	unsigned long long	iostat_seeks;
+++	unsigned long long	iostat_sectors;
+++	unsigned long long	iostat_reqs;
+++	unsigned long		iostat_read_reqs;
+++	unsigned long		iostat_write_reqs;
+++
+++	/* process time: how long it takes to process requests */
+++	unsigned long		iostat_rtime[IOSTAT_NCOUNTERS];
+++	unsigned long		iostat_wtime[IOSTAT_NCOUNTERS];
+++
+++	/* queue time: how long process spent in elevator's queue */
+++	unsigned long		iostat_rtime_in_queue[IOSTAT_NCOUNTERS];
+++	unsigned long		iostat_wtime_in_queue[IOSTAT_NCOUNTERS];
+++
+++	/* must be the last field, as it's used to know size to be memset'ed */
+++	spinlock_t		iostat_lock;
+++} ____cacheline_aligned_in_smp iostat_stats_t;
+++#endif
+++
++ struct scsi_disk {
++ 	struct scsi_driver *driver;	/* always &sd_template */
++ 	struct scsi_device *device;
++@@ -45,6 +85,9 @@
++ 	unsigned	WCE : 1;	/* state of disk WCE bit */
++ 	unsigned	RCD : 1;	/* state of disk RCD bit, unused */
++ 	unsigned	DPOFUA : 1;	/* state of disk DPOFUA bit */
+++#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
+++	iostat_stats_t	*stats;		/* scsi disk statistics */
+++#endif
++ };
++ #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
++ 
+--- /dev/null
++++ lustre-1.8.5+dfsg/lustre/kernel_patches/patches/quota-Split-off-quota-tree-handling-into-a-separate.patch
+@@ -0,0 +1,1593 @@
++From: Jan Kara <jack at suse.cz>
++References: fate#302681
++Subject: [PATCH 12/28] quota: Split off quota tree handling into a separate file
++Patch-mainline: 2.6.29?
++
++There is going to be a new version of quota format having 64-bit
++quota limits and a new quota format for OCFS2. They are both
++going to use the same tree structure as VFSv0 quota format. So
++split out tree handling into a separate file and make size of
++leaf blocks, amount of space usable in each block (needed for
++checksumming) and structures contained in them configurable
++so that the code can be shared.
++
++Signed-off-by: Jan Kara <jack at suse.cz>
++---
++ fs/Kconfig                  |    5 
++ fs/Makefile                 |    1 
++ fs/quota_tree.c             |  645 ++++++++++++++++++++++++++++++++++++++++++++
++ fs/quota_tree.h             |   25 +
++ fs/quota_v2.c               |  598 +++-------------------------------------
++ fs/quotaio_v2.h             |   33 --
++ include/linux/dqblk_qtree.h |   56 +++
++ include/linux/dqblk_v2.h    |   19 -
++ 8 files changed, 800 insertions(+), 582 deletions(-)
++ create mode 100644 fs/quota_tree.c
++ create mode 100644 fs/quota_tree.h
++ create mode 100644 include/linux/dqblk_qtree.h
++
++Index: linux-2.6.27.36/fs/Kconfig
++===================================================================
++--- linux-2.6.27.36.orig/fs/Kconfig	2009-10-05 17:19:01.000000000 +0200
+++++ linux-2.6.27.36/fs/Kconfig	2009-10-08 16:32:48.000000000 +0200
++@@ -569,6 +569,10 @@
++ 	  Note that this behavior is currently deprecated and may go away in
++ 	  future. Please use notification via netlink socket instead.
++ 
+++# Generic support for tree structured quota files. Seleted when needed.
+++config QUOTA_TREE
+++	 tristate
+++
++ config QFMT_V1
++ 	tristate "Old quota format support"
++ 	depends on QUOTA
++@@ -580,6 +584,7 @@
++ config QFMT_V2
++ 	tristate "Quota format v2 support"
++ 	depends on QUOTA
+++	select QUOTA_TREE
++ 	help
++ 	  This quota format allows using quotas with 32-bit UIDs/GIDs. If you
++ 	  need this functionality say Y here.
++Index: linux-2.6.27.36/fs/Makefile
++===================================================================
++--- linux-2.6.27.36.orig/fs/Makefile	2009-10-05 17:19:01.000000000 +0200
+++++ linux-2.6.27.36/fs/Makefile	2009-10-08 16:32:48.000000000 +0200
++@@ -53,6 +53,7 @@
++ obj-$(CONFIG_QUOTA)		+= dquot.o
++ obj-$(CONFIG_QFMT_V1)		+= quota_v1.o
++ obj-$(CONFIG_QFMT_V2)		+= quota_v2.o
+++obj-$(CONFIG_QUOTA_TREE)	+= quota_tree.o
++ obj-$(CONFIG_QUOTACTL)		+= quota.o
++ 
++ obj-$(CONFIG_DNOTIFY)		+= dnotify.o
++Index: linux-2.6.27.36/include/linux/quotaio_v2.h
++===================================================================
++--- linux-2.6.27.36.orig/include/linux/quotaio_v2.h	2009-10-05 17:19:01.000000000 +0200
+++++ linux-2.6.27.36/include/linux/quotaio_v2.h	2009-10-08 16:32:48.000000000 +0200
++@@ -21,6 +21,12 @@
++ 	0		/* GRPQUOTA */\
++ }
++ 
+++/* First generic header */
+++struct v2_disk_dqheader {
+++	__le32 dqh_magic;	/* Magic number identifying file */
+++	__le32 dqh_version;	/* File version */
+++};
+++
++ /*
++  * The following structure defines the format of the disk quota file
++  * (as it appears on disk) - the file is a radix tree whose leaves point
++@@ -38,15 +44,6 @@
++ 	__le64 dqb_itime;	/* time limit for excessive inode use */
++ };
++ 
++-/*
++- * Here are header structures as written on disk and their in-memory copies
++- */
++-/* First generic header */
++-struct v2_disk_dqheader {
++-	__le32 dqh_magic;	/* Magic number identifying file */
++-	__le32 dqh_version;	/* File version */
++-};
++-
++ /* Header with type and version specific information */
++ struct v2_disk_dqinfo {
++ 	__le32 dqi_bgrace;	/* Time before block soft limit becomes hard limit */
++@@ -57,23 +54,7 @@
++ 	__le32 dqi_free_entry;	/* Number of block with at least one free entry */
++ };
++ 
++-/*
++- *  Structure of header of block with quota structures. It is padded to 16 bytes so
++- *  there will be space for exactly 21 quota-entries in a block
++- */
++-struct v2_disk_dqdbheader {
++-	__le32 dqdh_next_free;	/* Number of next block with free entry */
++-	__le32 dqdh_prev_free;	/* Number of previous block with free entry */
++-	__le16 dqdh_entries;	/* Number of valid entries in block */
++-	__le16 dqdh_pad1;
++-	__le32 dqdh_pad2;
++-};
++-
++ #define V2_DQINFOOFF	sizeof(struct v2_disk_dqheader)	/* Offset of info header in file */
++-#define V2_DQBLKSIZE_BITS	10
++-#define V2_DQBLKSIZE	(1 << V2_DQBLKSIZE_BITS)	/* Size of block with quota structures */
++-#define V2_DQTREEOFF	1		/* Offset of tree in file in blocks */
++-#define V2_DQTREEDEPTH	4		/* Depth of quota tree */
++-#define V2_DQSTRINBLK	((V2_DQBLKSIZE - sizeof(struct v2_disk_dqdbheader)) / sizeof(struct v2_disk_dqblk))	/* Number of entries in one blocks */
+++#define V2_DQBLKSIZE_BITS 10				/* Size of leaf block in tree */
++ 
++ #endif /* _LINUX_QUOTAIO_V2_H */
++Index: linux-2.6.27.36/fs/quota_tree.c
++===================================================================
++--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++++ linux-2.6.27.36/fs/quota_tree.c	2009-10-08 16:32:48.000000000 +0200
++@@ -0,0 +1,645 @@
+++/*
+++ *	vfsv0 quota IO operations on file
+++ */
+++
+++#include <linux/errno.h>
+++#include <linux/fs.h>
+++#include <linux/mount.h>
+++#include <linux/dqblk_v2.h>
+++#include <linux/kernel.h>
+++#include <linux/init.h>
+++#include <linux/module.h>
+++#include <linux/slab.h>
+++#include <linux/quotaops.h>
+++
+++#include <asm/byteorder.h>
+++
+++#include "quota_tree.h"
+++
+++MODULE_AUTHOR("Jan Kara");
+++MODULE_DESCRIPTION("Quota trie support");
+++MODULE_LICENSE("GPL");
+++
+++#define __QUOTA_QT_PARANOIA
+++
+++typedef char *dqbuf_t;
+++
+++static int get_index(struct qtree_mem_dqinfo *info, qid_t id, int depth)
+++{
+++	unsigned int epb = info->dqi_usable_bs >> 2;
+++
+++	depth = info->dqi_qtree_depth - depth - 1;
+++	while (depth--)
+++		id /= epb;
+++	return id % epb;
+++}
+++
+++/* Number of entries in one blocks */
+++static inline int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info)
+++{
+++	return (info->dqi_usable_bs - sizeof(struct qt_disk_dqdbheader))
+++	       / info->dqi_entry_size;
+++}
+++
+++static dqbuf_t getdqbuf(size_t size)
+++{
+++	dqbuf_t buf = kmalloc(size, GFP_NOFS);
+++	if (!buf)
+++		printk(KERN_WARNING "VFS: Not enough memory for quota buffers.\n");
+++	return buf;
+++}
+++
+++static inline void freedqbuf(dqbuf_t buf)
+++{
+++	kfree(buf);
+++}
+++
+++static inline ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, dqbuf_t buf)
+++{
+++	struct super_block *sb = info->dqi_sb;
+++
+++	memset(buf, 0, info->dqi_usable_bs);
+++	return sb->s_op->quota_read(sb, info->dqi_type, (char *)buf,
+++	       info->dqi_usable_bs, blk << info->dqi_blocksize_bits);
+++}
+++
+++static inline ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, dqbuf_t buf)
+++{
+++	struct super_block *sb = info->dqi_sb;
+++
+++	return sb->s_op->quota_write(sb, info->dqi_type, (char *)buf,
+++	       info->dqi_usable_bs, blk << info->dqi_blocksize_bits);
+++}
+++
+++/* Remove empty block from list and return it */
+++static int get_free_dqblk(struct qtree_mem_dqinfo *info)
+++{
+++	dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
+++	struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
+++	int ret, blk;
+++
+++	if (!buf)
+++		return -ENOMEM;
+++	if (info->dqi_free_blk) {
+++		blk = info->dqi_free_blk;
+++		ret = read_blk(info, blk, buf);
+++		if (ret < 0)
+++			goto out_buf;
+++		info->dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
+++	}
+++	else {
+++		memset(buf, 0, info->dqi_usable_bs);
+++		/* Assure block allocation... */
+++		ret = write_blk(info, info->dqi_blocks, buf);
+++		if (ret < 0)
+++			goto out_buf;
+++		blk = info->dqi_blocks++;
+++	}
+++	mark_info_dirty(info->dqi_sb, info->dqi_type);
+++	ret = blk;
+++out_buf:
+++	freedqbuf(buf);
+++	return ret;
+++}
+++
+++/* Insert empty block to the list */
+++static int put_free_dqblk(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk)
+++{
+++	struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
+++	int err;
+++
+++	dh->dqdh_next_free = cpu_to_le32(info->dqi_free_blk);
+++	dh->dqdh_prev_free = cpu_to_le32(0);
+++	dh->dqdh_entries = cpu_to_le16(0);
+++	err = write_blk(info, blk, buf);
+++	if (err < 0)
+++		return err;
+++	info->dqi_free_blk = blk;
+++	mark_info_dirty(info->dqi_sb, info->dqi_type);
+++	return 0;
+++}
+++
+++/* Remove given block from the list of blocks with free entries */
+++static int remove_free_dqentry(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk)
+++{
+++	dqbuf_t tmpbuf = getdqbuf(info->dqi_usable_bs);
+++	struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
+++	uint nextblk = le32_to_cpu(dh->dqdh_next_free);
+++	uint prevblk = le32_to_cpu(dh->dqdh_prev_free);
+++	int err;
+++
+++	if (!tmpbuf)
+++		return -ENOMEM;
+++	if (nextblk) {
+++		err = read_blk(info, nextblk, tmpbuf);
+++		if (err < 0)
+++			goto out_buf;
+++		((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
+++							dh->dqdh_prev_free;
+++		err = write_blk(info, nextblk, tmpbuf);
+++		if (err < 0)
+++			goto out_buf;
+++	}
+++	if (prevblk) {
+++		err = read_blk(info, prevblk, tmpbuf);
+++		if (err < 0)
+++			goto out_buf;
+++		((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_next_free =
+++							dh->dqdh_next_free;
+++		err = write_blk(info, prevblk, tmpbuf);
+++		if (err < 0)
+++			goto out_buf;
+++	} else {
+++		info->dqi_free_entry = nextblk;
+++		mark_info_dirty(info->dqi_sb, info->dqi_type);
+++	}
+++	freedqbuf(tmpbuf);
+++	dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
+++	/* No matter whether write succeeds block is out of list */
+++	if (write_blk(info, blk, buf) < 0)
+++		printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk);
+++	return 0;
+++out_buf:
+++	freedqbuf(tmpbuf);
+++	return err;
+++}
+++
+++/* Insert given block to the beginning of list with free entries */
+++static int insert_free_dqentry(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk)
+++{
+++	dqbuf_t tmpbuf = getdqbuf(info->dqi_usable_bs);
+++	struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
+++	int err;
+++
+++	if (!tmpbuf)
+++		return -ENOMEM;
+++	dh->dqdh_next_free = cpu_to_le32(info->dqi_free_entry);
+++	dh->dqdh_prev_free = cpu_to_le32(0);
+++	err = write_blk(info, blk, buf);
+++	if (err < 0)
+++		goto out_buf;
+++	if (info->dqi_free_entry) {
+++		err = read_blk(info, info->dqi_free_entry, tmpbuf);
+++		if (err < 0)
+++			goto out_buf;
+++		((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
+++							cpu_to_le32(blk);
+++		err = write_blk(info, info->dqi_free_entry, tmpbuf);
+++		if (err < 0)
+++			goto out_buf;
+++	}
+++	freedqbuf(tmpbuf);
+++	info->dqi_free_entry = blk;
+++	mark_info_dirty(info->dqi_sb, info->dqi_type);
+++	return 0;
+++out_buf:
+++	freedqbuf(tmpbuf);
+++	return err;
+++}
+++
+++/* Is the entry in the block free? */
+++int qtree_entry_unused(struct qtree_mem_dqinfo *info, char *disk)
+++{
+++	int i;
+++
+++	for (i = 0; i < info->dqi_entry_size; i++)
+++		if (disk[i])
+++			return 0;
+++	return 1;
+++}
+++EXPORT_SYMBOL(qtree_entry_unused);
+++
+++/* Find space for dquot */
+++static uint find_free_dqentry(struct qtree_mem_dqinfo *info,
+++			      struct dquot *dquot, int *err)
+++{
+++	uint blk, i;
+++	struct qt_disk_dqdbheader *dh;
+++	dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
+++	char *ddquot;
+++
+++	*err = 0;
+++	if (!buf) {
+++		*err = -ENOMEM;
+++		return 0;
+++	}
+++	dh = (struct qt_disk_dqdbheader *)buf;
+++	if (info->dqi_free_entry) {
+++		blk = info->dqi_free_entry;
+++		*err = read_blk(info, blk, buf);
+++		if (*err < 0)
+++			goto out_buf;
+++	} else {
+++		blk = get_free_dqblk(info);
+++		if ((int)blk < 0) {
+++			*err = blk;
+++			freedqbuf(buf);
+++			return 0;
+++		}
+++		memset(buf, 0, info->dqi_usable_bs);
+++		/* This is enough as block is already zeroed and entry list is empty... */
+++		info->dqi_free_entry = blk;
+++		mark_info_dirty(dquot->dq_sb, dquot->dq_type);
+++	}
+++	/* Block will be full? */
+++	if (le16_to_cpu(dh->dqdh_entries) + 1 >= qtree_dqstr_in_blk(info)) {
+++		*err = remove_free_dqentry(info, buf, blk);
+++		if (*err < 0) {
+++			printk(KERN_ERR "VFS: find_free_dqentry(): Can't "
+++			       "remove block (%u) from entry free list.\n",
+++			       blk);
+++			goto out_buf;
+++		}
+++	}
+++	le16_add_cpu(&dh->dqdh_entries, 1);
+++	/* Find free structure in block */
+++	for (i = 0, ddquot = ((char *)buf) + sizeof(struct qt_disk_dqdbheader);
+++	     i < qtree_dqstr_in_blk(info) && !qtree_entry_unused(info, ddquot);
+++	     i++, ddquot += info->dqi_entry_size);
+++#ifdef __QUOTA_QT_PARANOIA
+++	if (i == qtree_dqstr_in_blk(info)) {
+++		printk(KERN_ERR "VFS: find_free_dqentry(): Data block full "
+++				"but it shouldn't.\n");
+++		*err = -EIO;
+++		goto out_buf;
+++	}
+++#endif
+++	*err = write_blk(info, blk, buf);
+++	if (*err < 0) {
+++		printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota "
+++				"data block %u.\n", blk);
+++		goto out_buf;
+++	}
+++	dquot->dq_off = (blk << info->dqi_blocksize_bits) +
+++			sizeof(struct qt_disk_dqdbheader) +
+++			i * info->dqi_entry_size;
+++	freedqbuf(buf);
+++	return blk;
+++out_buf:
+++	freedqbuf(buf);
+++	return 0;
+++}
+++
+++/* Insert reference to structure into the trie */
+++static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
+++			  uint *treeblk, int depth)
+++{
+++	dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
+++	int ret = 0, newson = 0, newact = 0;
+++	__le32 *ref;
+++	uint newblk;
+++
+++	if (!buf)
+++		return -ENOMEM;
+++	if (!*treeblk) {
+++		ret = get_free_dqblk(info);
+++		if (ret < 0)
+++			goto out_buf;
+++		*treeblk = ret;
+++		memset(buf, 0, info->dqi_usable_bs);
+++		newact = 1;
+++	} else {
+++		ret = read_blk(info, *treeblk, buf);
+++		if (ret < 0) {
+++			printk(KERN_ERR "VFS: Can't read tree quota block "
+++					"%u.\n", *treeblk);
+++			goto out_buf;
+++		}
+++	}
+++	ref = (__le32 *)buf;
+++	newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]);
+++	if (!newblk)
+++		newson = 1;
+++	if (depth == info->dqi_qtree_depth - 1) {
+++#ifdef __QUOTA_QT_PARANOIA
+++		if (newblk) {
+++			printk(KERN_ERR "VFS: Inserting already present quota "
+++					"entry (block %u).\n",
+++			       le32_to_cpu(ref[get_index(info,
+++						dquot->dq_id, depth)]));
+++			ret = -EIO;
+++			goto out_buf;
+++		}
+++#endif
+++		newblk = find_free_dqentry(info, dquot, &ret);
+++	} else {
+++		ret = do_insert_tree(info, dquot, &newblk, depth+1);
+++	}
+++	if (newson && ret >= 0) {
+++		ref[get_index(info, dquot->dq_id, depth)] =
+++							cpu_to_le32(newblk);
+++		ret = write_blk(info, *treeblk, buf);
+++	} else if (newact && ret < 0) {
+++		put_free_dqblk(info, buf, *treeblk);
+++	}
+++out_buf:
+++	freedqbuf(buf);
+++	return ret;
+++}
+++
+++/* Wrapper for inserting quota structure into tree */
+++static inline int dq_insert_tree(struct qtree_mem_dqinfo *info,
+++				 struct dquot *dquot)
+++{
+++	int tmp = QT_TREEOFF;
+++	return do_insert_tree(info, dquot, &tmp, 0);
+++}
+++
+++/*
+++ *	We don't have to be afraid of deadlocks as we never have quotas on quota files...
+++ */
+++int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
+++{
+++	int type = dquot->dq_type;
+++	struct super_block *sb = dquot->dq_sb;
+++	ssize_t ret;
+++	dqbuf_t ddquot = getdqbuf(info->dqi_entry_size);
+++
+++	if (!ddquot)
+++		return -ENOMEM;
+++
+++	/* dq_off is guarded by dqio_mutex */
+++	if (!dquot->dq_off) {
+++		ret = dq_insert_tree(info, dquot);
+++		if (ret < 0) {
+++			printk(KERN_ERR "VFS: Error %zd occurred while "
+++					"creating quota.\n", ret);
+++			freedqbuf(ddquot);
+++			return ret;
+++		}
+++	}
+++	spin_lock(&dq_data_lock);
+++	info->dqi_ops->mem2disk_dqblk(ddquot, dquot);
+++	spin_unlock(&dq_data_lock);
+++	ret = sb->s_op->quota_write(sb, type, (char *)ddquot,
+++					info->dqi_entry_size, dquot->dq_off);
+++	if (ret != info->dqi_entry_size) {
+++		printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
+++		       sb->s_id);
+++		if (ret >= 0)
+++			ret = -ENOSPC;
+++	} else {
+++		ret = 0;
+++	}
+++	dqstats.writes++;
+++	freedqbuf(ddquot);
+++
+++	return ret;
+++}
+++EXPORT_SYMBOL(qtree_write_dquot);
+++
+++/* Free dquot entry in data block */
+++static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot,
+++			uint blk)
+++{
+++	struct qt_disk_dqdbheader *dh;
+++	dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
+++	int ret = 0;
+++
+++	if (!buf)
+++		return -ENOMEM;
+++	if (dquot->dq_off >> info->dqi_blocksize_bits != blk) {
+++		printk(KERN_ERR "VFS: Quota structure has offset to other "
+++		  "block (%u) than it should (%u).\n", blk,
+++		  (uint)(dquot->dq_off >> info->dqi_blocksize_bits));
+++		goto out_buf;
+++	}
+++	ret = read_blk(info, blk, buf);
+++	if (ret < 0) {
+++		printk(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
+++		goto out_buf;
+++	}
+++	dh = (struct qt_disk_dqdbheader *)buf;
+++	le16_add_cpu(&dh->dqdh_entries, -1);
+++	if (!le16_to_cpu(dh->dqdh_entries)) {	/* Block got free? */
+++		ret = remove_free_dqentry(info, buf, blk);
+++		if (ret >= 0)
+++			ret = put_free_dqblk(info, buf, blk);
+++		if (ret < 0) {
+++			printk(KERN_ERR "VFS: Can't move quota data block (%u) "
+++			  "to free list.\n", blk);
+++			goto out_buf;
+++		}
+++	} else {
+++		memset(buf +
+++		       (dquot->dq_off & ((1 << info->dqi_blocksize_bits) - 1)),
+++		       0, info->dqi_entry_size);
+++		if (le16_to_cpu(dh->dqdh_entries) ==
+++		    qtree_dqstr_in_blk(info) - 1) {
+++			/* Insert will write block itself */
+++			ret = insert_free_dqentry(info, buf, blk);
+++			if (ret < 0) {
+++				printk(KERN_ERR "VFS: Can't insert quota data "
+++				       "block (%u) to free entry list.\n", blk);
+++				goto out_buf;
+++			}
+++		} else {
+++			ret = write_blk(info, blk, buf);
+++			if (ret < 0) {
+++				printk(KERN_ERR "VFS: Can't write quota data "
+++				  "block %u\n", blk);
+++				goto out_buf;
+++			}
+++		}
+++	}
+++	dquot->dq_off = 0;	/* Quota is now unattached */
+++out_buf:
+++	freedqbuf(buf);
+++	return ret;
+++}
+++
+++/* Remove reference to dquot from tree */
+++static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
+++		       uint *blk, int depth)
+++{
+++	dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
+++	int ret = 0;
+++	uint newblk;
+++	__le32 *ref = (__le32 *)buf;
+++
+++	if (!buf)
+++		return -ENOMEM;
+++	ret = read_blk(info, *blk, buf);
+++	if (ret < 0) {
+++		printk(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
+++		goto out_buf;
+++	}
+++	newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]);
+++	if (depth == info->dqi_qtree_depth - 1) {
+++		ret = free_dqentry(info, dquot, newblk);
+++		newblk = 0;
+++	} else {
+++		ret = remove_tree(info, dquot, &newblk, depth+1);
+++	}
+++	if (ret >= 0 && !newblk) {
+++		int i;
+++		ref[get_index(info, dquot->dq_id, depth)] = cpu_to_le32(0);
+++		/* Block got empty? */
+++		for (i = 0;
+++		     i < (info->dqi_usable_bs >> 2) && !ref[i];
+++		     i++);
+++		/* Don't put the root block into the free block list */
+++		if (i == (info->dqi_usable_bs >> 2)
+++		    && *blk != QT_TREEOFF) {
+++			put_free_dqblk(info, buf, *blk);
+++			*blk = 0;
+++		} else {
+++			ret = write_blk(info, *blk, buf);
+++			if (ret < 0)
+++				printk(KERN_ERR "VFS: Can't write quota tree "
+++				  "block %u.\n", *blk);
+++		}
+++	}
+++out_buf:
+++	freedqbuf(buf);
+++	return ret;
+++}
+++
+++/* Delete dquot from tree */
+++int qtree_delete_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
+++{
+++	uint tmp = QT_TREEOFF;
+++
+++	if (!dquot->dq_off)	/* Even not allocated? */
+++		return 0;
+++	return remove_tree(info, dquot, &tmp, 0);
+++}
+++EXPORT_SYMBOL(qtree_delete_dquot);
+++
+++/* Find entry in block */
+++static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info,
+++				 struct dquot *dquot, uint blk)
+++{
+++	dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
+++	loff_t ret = 0;
+++	int i;
+++	char *ddquot;
+++
+++	if (!buf)
+++		return -ENOMEM;
+++	ret = read_blk(info, blk, buf);
+++	if (ret < 0) {
+++		printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
+++		goto out_buf;
+++	}
+++	for (i = 0, ddquot = ((char *)buf) + sizeof(struct qt_disk_dqdbheader);
+++	     i < qtree_dqstr_in_blk(info) && !info->dqi_ops->is_id(ddquot, dquot);
+++	     i++, ddquot += info->dqi_entry_size);
+++	if (i == qtree_dqstr_in_blk(info)) {
+++		printk(KERN_ERR "VFS: Quota for id %u referenced "
+++		  "but not present.\n", dquot->dq_id);
+++		ret = -EIO;
+++		goto out_buf;
+++	} else {
+++		ret = (blk << info->dqi_blocksize_bits) + sizeof(struct
+++		  qt_disk_dqdbheader) + i * info->dqi_entry_size;
+++	}
+++out_buf:
+++	freedqbuf(buf);
+++	return ret;
+++}
+++
+++/* Find entry for given id in the tree */
+++static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info,
+++				struct dquot *dquot, uint blk, int depth)
+++{
+++	dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
+++	loff_t ret = 0;
+++	__le32 *ref = (__le32 *)buf;
+++
+++	if (!buf)
+++		return -ENOMEM;
+++	ret = read_blk(info, blk, buf);
+++	if (ret < 0) {
+++		printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
+++		goto out_buf;
+++	}
+++	ret = 0;
+++	blk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]);
+++	if (!blk)	/* No reference? */
+++		goto out_buf;
+++	if (depth < info->dqi_qtree_depth - 1)
+++		ret = find_tree_dqentry(info, dquot, blk, depth+1);
+++	else
+++		ret = find_block_dqentry(info, dquot, blk);
+++out_buf:
+++	freedqbuf(buf);
+++	return ret;
+++}
+++
+++/* Find entry for given id in the tree - wrapper function */
+++static inline loff_t find_dqentry(struct qtree_mem_dqinfo *info,
+++				  struct dquot *dquot)
+++{
+++	return find_tree_dqentry(info, dquot, QT_TREEOFF, 0);
+++}
+++
+++int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
+++{
+++	int type = dquot->dq_type;
+++	struct super_block *sb = dquot->dq_sb;
+++	loff_t offset;
+++	dqbuf_t ddquot;
+++	int ret = 0;
+++
+++#ifdef __QUOTA_QT_PARANOIA
+++	/* Invalidated quota? */
+++	if (!sb_dqopt(dquot->dq_sb)->files[type]) {
+++		printk(KERN_ERR "VFS: Quota invalidated while reading!\n");
+++		return -EIO;
+++	}
+++#endif
+++	/* Do we know offset of the dquot entry in the quota file? */
+++	if (!dquot->dq_off) {
+++		offset = find_dqentry(info, dquot);
+++		if (offset <= 0) {	/* Entry not present? */
+++			if (offset < 0)
+++				printk(KERN_ERR "VFS: Can't read quota "
+++				  "structure for id %u.\n", dquot->dq_id);
+++			dquot->dq_off = 0;
+++			set_bit(DQ_FAKE_B, &dquot->dq_flags);
+++			memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
+++			ret = offset;
+++			goto out;
+++		}
+++		dquot->dq_off = offset;
+++	}
+++	ddquot = getdqbuf(info->dqi_entry_size);
+++	if (!ddquot)
+++		return -ENOMEM;
+++	ret = sb->s_op->quota_read(sb, type, (char *)ddquot,
+++				   info->dqi_entry_size, dquot->dq_off);
+++	if (ret != info->dqi_entry_size) {
+++		if (ret >= 0)
+++			ret = -EIO;
+++		printk(KERN_ERR "VFS: Error while reading quota "
+++				"structure for id %u.\n", dquot->dq_id);
+++		set_bit(DQ_FAKE_B, &dquot->dq_flags);
+++		memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
+++		freedqbuf(ddquot);
+++		goto out;
+++	}
+++	spin_lock(&dq_data_lock);
+++	info->dqi_ops->disk2mem_dqblk(dquot, ddquot);
+++	if (!dquot->dq_dqb.dqb_bhardlimit &&
+++	    !dquot->dq_dqb.dqb_bsoftlimit &&
+++	    !dquot->dq_dqb.dqb_ihardlimit &&
+++	    !dquot->dq_dqb.dqb_isoftlimit)
+++		set_bit(DQ_FAKE_B, &dquot->dq_flags);
+++	spin_unlock(&dq_data_lock);
+++	freedqbuf(ddquot);
+++out:
+++	dqstats.reads++;
+++	return ret;
+++}
+++EXPORT_SYMBOL(qtree_read_dquot);
+++
+++/* Check whether dquot should not be deleted. We know we are
+++ * the only one operating on dquot (thanks to dq_lock) */
+++int qtree_release_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
+++{
+++	if (test_bit(DQ_FAKE_B, &dquot->dq_flags) && !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace))
+++		return qtree_delete_dquot(info, dquot);
+++	return 0;
+++}
+++EXPORT_SYMBOL(qtree_release_dquot);
++Index: linux-2.6.27.36/fs/quota_tree.h
++===================================================================
++--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++++ linux-2.6.27.36/fs/quota_tree.h	2009-10-08 16:32:48.000000000 +0200
++@@ -0,0 +1,25 @@
+++/*
+++ *	Definitions of structures for vfsv0 quota format
+++ */
+++
+++#ifndef _LINUX_QUOTA_TREE_H
+++#define _LINUX_QUOTA_TREE_H
+++
+++#include <linux/types.h>
+++#include <linux/quota.h>
+++
+++/*
+++ *  Structure of header of block with quota structures. It is padded to 16 bytes so
+++ *  there will be space for exactly 21 quota-entries in a block
+++ */
+++struct qt_disk_dqdbheader {
+++	__le32 dqdh_next_free;	/* Number of next block with free entry */
+++	__le32 dqdh_prev_free;	/* Number of previous block with free entry */
+++	__le16 dqdh_entries;	/* Number of valid entries in block */
+++	__le16 dqdh_pad1;
+++	__le32 dqdh_pad2;
+++};
+++
+++#define QT_TREEOFF	1		/* Offset of tree in file in blocks */
+++
+++#endif /* _LINUX_QUOTAIO_TREE_H */
++Index: linux-2.6.27.36/fs/quota_v2.c
++===================================================================
++--- linux-2.6.27.36.orig/fs/quota_v2.c	2009-10-05 17:19:01.000000000 +0200
+++++ linux-2.6.27.36/fs/quota_v2.c	2009-10-08 16:34:36.000000000 +0200
++@@ -6,6 +6,7 @@
++ #include <linux/fs.h>
++ #include <linux/mount.h>
++ #include <linux/dqblk_v2.h>
+++#include "quota_tree.h"
++ #include <linux/quotaio_v2.h>
++ #include <linux/kernel.h>
++ #include <linux/init.h>
++@@ -15,16 +16,22 @@
++ 
++ #include <asm/byteorder.h>
++ 
+++
++ MODULE_AUTHOR("Jan Kara");
++ MODULE_DESCRIPTION("Quota format v2 support");
++ MODULE_LICENSE("GPL");
++ 
++ #define __QUOTA_V2_PARANOIA
++ 
++-typedef char *dqbuf_t;
++-
++-#define GETIDINDEX(id, depth) (((id) >> ((V2_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
++-#define GETENTRIES(buf) ((struct v2_disk_dqblk *)(((char *)buf)+sizeof(struct v2_disk_dqdbheader)))
+++static void v2_mem2diskdqb(void *dp, struct dquot *dquot);
+++static void v2_disk2memdqb(struct dquot *dquot, void *dp);
+++static int v2_is_id(void *dp, struct dquot *dquot);
+++
+++static struct qtree_fmt_operations v2_qtree_ops = {
+++	.mem2disk_dqblk = v2_mem2diskdqb,
+++	.disk2mem_dqblk = v2_disk2memdqb,
+++	.is_id = v2_is_id,
+++};
++ 
++ /* Check whether given file is really vfsv0 quotafile */
++ static int v2_check_quota_file(struct super_block *sb, int type)
++@@ -50,7 +57,7 @@
++ static int v2_read_file_info(struct super_block *sb, int type)
++ {
++ 	struct v2_disk_dqinfo dinfo;
++-	struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
+++	struct mem_dqinfo *info = sb_dqinfo(sb, type);
++ 	ssize_t size;
++ 
++ 	size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
++@@ -66,9 +73,16 @@
++ 	info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
++ 	info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
++ 	info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
++-	info->u.v2_i.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
++-	info->u.v2_i.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
++-	info->u.v2_i.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
+++	info->u.v2_i.i.dqi_sb = sb;
+++	info->u.v2_i.i.dqi_type = type;
+++	info->u.v2_i.i.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
+++	info->u.v2_i.i.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
+++	info->u.v2_i.i.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
+++	info->u.v2_i.i.dqi_blocksize_bits = V2_DQBLKSIZE_BITS;
+++	info->u.v2_i.i.dqi_usable_bs = 1 << V2_DQBLKSIZE_BITS;
+++	info->u.v2_i.i.dqi_qtree_depth = qtree_depth(&info->u.v2_i.i);
+++	info->u.v2_i.i.dqi_entry_size = sizeof(struct v2_disk_dqblk);
+++	info->u.v2_i.i.dqi_ops = &v2_qtree_ops;
++ 	return 0;
++ }
++ 
++@@ -76,7 +90,7 @@
++ static int v2_write_file_info(struct super_block *sb, int type)
++ {
++ 	struct v2_disk_dqinfo dinfo;
++-	struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
+++	struct mem_dqinfo *info = sb_dqinfo(sb, type);
++ 	ssize_t size;
++ 
++ 	spin_lock(&dq_data_lock);
++@@ -85,9 +99,9 @@
++ 	dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);
++ 	dinfo.dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK);
++ 	spin_unlock(&dq_data_lock);
++-	dinfo.dqi_blocks = cpu_to_le32(info->u.v2_i.dqi_blocks);
++-	dinfo.dqi_free_blk = cpu_to_le32(info->u.v2_i.dqi_free_blk);
++-	dinfo.dqi_free_entry = cpu_to_le32(info->u.v2_i.dqi_free_entry);
+++	dinfo.dqi_blocks = cpu_to_le32(info->u.v2_i.i.dqi_blocks);
+++	dinfo.dqi_free_blk = cpu_to_le32(info->u.v2_i.i.dqi_free_blk);
+++	dinfo.dqi_free_entry = cpu_to_le32(info->u.v2_i.i.dqi_free_entry);
++ 	size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
++ 	       sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
++ 	if (size != sizeof(struct v2_disk_dqinfo)) {
++@@ -98,8 +112,11 @@
++ 	return 0;
++ }
++ 
++-static void disk2memdqb(struct mem_dqblk *m, struct v2_disk_dqblk *d)
+++static void v2_disk2memdqb(struct dquot *dquot, void *dp)
++ {
+++	struct v2_disk_dqblk *d = dp, empty;
+++	struct mem_dqblk *m = &dquot->dq_dqb;
+++
++ 	m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit);
++ 	m->dqb_isoftlimit = le32_to_cpu(d->dqb_isoftlimit);
++ 	m->dqb_curinodes = le32_to_cpu(d->dqb_curinodes);
++@@ -108,10 +125,20 @@
++ 	m->dqb_bsoftlimit = le32_to_cpu(d->dqb_bsoftlimit);
++ 	m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
++ 	m->dqb_btime = le64_to_cpu(d->dqb_btime);
+++	/* We need to escape back all-zero structure */
+++	memset(&empty, 0, sizeof(struct v2_disk_dqblk));
+++	empty.dqb_itime = cpu_to_le64(1);
+++	if (!memcmp(&empty, dp, sizeof(struct v2_disk_dqblk)))
+++		m->dqb_itime = 0;
++ }
++ 
++-static void mem2diskdqb(struct v2_disk_dqblk *d, struct mem_dqblk *m, qid_t id)
+++static void v2_mem2diskdqb(void *dp, struct dquot *dquot)
++ {
+++	struct v2_disk_dqblk *d = dp;
+++	struct mem_dqblk *m = &dquot->dq_dqb;
+++	struct qtree_mem_dqinfo *info =
+++			&sb_dqinfo(dquot->dq_sb, dquot->dq_type)->u.v2_i.i;
+++
++ 	d->dqb_ihardlimit = cpu_to_le32(m->dqb_ihardlimit);
++ 	d->dqb_isoftlimit = cpu_to_le32(m->dqb_isoftlimit);
++ 	d->dqb_curinodes = cpu_to_le32(m->dqb_curinodes);
++@@ -120,553 +147,35 @@
++ 	d->dqb_bsoftlimit = cpu_to_le32(m->dqb_bsoftlimit);
++ 	d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
++ 	d->dqb_btime = cpu_to_le64(m->dqb_btime);
++-	d->dqb_id = cpu_to_le32(id);
++-}
++-
++-static dqbuf_t getdqbuf(void)
++-{
++-	dqbuf_t buf = kmalloc(V2_DQBLKSIZE, GFP_NOFS);
++-	if (!buf)
++-		printk(KERN_WARNING "VFS: Not enough memory for quota buffers.\n");
++-	return buf;
++-}
++-
++-static inline void freedqbuf(dqbuf_t buf)
++-{
++-	kfree(buf);
++-}
++-
++-static inline ssize_t read_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
++-{
++-	memset(buf, 0, V2_DQBLKSIZE);
++-	return sb->s_op->quota_read(sb, type, (char *)buf,
++-	       V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
++-}
++-
++-static inline ssize_t write_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
++-{
++-	return sb->s_op->quota_write(sb, type, (char *)buf,
++-	       V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
+++	d->dqb_id = cpu_to_le32(dquot->dq_id);
+++	if (qtree_entry_unused(info, dp))
+++		d->dqb_itime = cpu_to_le64(1);
++ }
++ 
++-/* Remove empty block from list and return it */
++-static int get_free_dqblk(struct super_block *sb, int type)
+++static int v2_is_id(void *dp, struct dquot *dquot)
++ {
++-	dqbuf_t buf = getdqbuf();
++-	struct mem_dqinfo *info = sb_dqinfo(sb, type);
++-	struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
++-	int ret, blk;
+++	struct v2_disk_dqblk *d = dp;
+++	struct qtree_mem_dqinfo *info =
+++			&sb_dqinfo(dquot->dq_sb, dquot->dq_type)->u.v2_i.i;
++ 
++-	if (!buf)
++-		return -ENOMEM;
++-	if (info->u.v2_i.dqi_free_blk) {
++-		blk = info->u.v2_i.dqi_free_blk;
++-		if ((ret = read_blk(sb, type, blk, buf)) < 0)
++-			goto out_buf;
++-		info->u.v2_i.dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
++-	}
++-	else {
++-		memset(buf, 0, V2_DQBLKSIZE);
++-		/* Assure block allocation... */
++-		if ((ret = write_blk(sb, type, info->u.v2_i.dqi_blocks, buf)) < 0)
++-			goto out_buf;
++-		blk = info->u.v2_i.dqi_blocks++;
++-	}
++-	mark_info_dirty(sb, type);
++-	ret = blk;
++-out_buf:
++-	freedqbuf(buf);
++-	return ret;
++-}
++-
++-/* Insert empty block to the list */
++-static int put_free_dqblk(struct super_block *sb, int type, dqbuf_t buf, uint blk)
++-{
++-	struct mem_dqinfo *info = sb_dqinfo(sb, type);
++-	struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
++-	int err;
++-
++-	dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_blk);
++-	dh->dqdh_prev_free = cpu_to_le32(0);
++-	dh->dqdh_entries = cpu_to_le16(0);
++-	info->u.v2_i.dqi_free_blk = blk;
++-	mark_info_dirty(sb, type);
++-	/* Some strange block. We had better leave it... */
++-	if ((err = write_blk(sb, type, blk, buf)) < 0)
++-		return err;
++-	return 0;
++-}
++-
++-/* Remove given block from the list of blocks with free entries */
++-static int remove_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
++-{
++-	dqbuf_t tmpbuf = getdqbuf();
++-	struct mem_dqinfo *info = sb_dqinfo(sb, type);
++-	struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
++-	uint nextblk = le32_to_cpu(dh->dqdh_next_free), prevblk = le32_to_cpu(dh->dqdh_prev_free);
++-	int err;
++-
++-	if (!tmpbuf)
++-		return -ENOMEM;
++-	if (nextblk) {
++-		if ((err = read_blk(sb, type, nextblk, tmpbuf)) < 0)
++-			goto out_buf;
++-		((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = dh->dqdh_prev_free;
++-		if ((err = write_blk(sb, type, nextblk, tmpbuf)) < 0)
++-			goto out_buf;
++-	}
++-	if (prevblk) {
++-		if ((err = read_blk(sb, type, prevblk, tmpbuf)) < 0)
++-			goto out_buf;
++-		((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_next_free = dh->dqdh_next_free;
++-		if ((err = write_blk(sb, type, prevblk, tmpbuf)) < 0)
++-			goto out_buf;
++-	}
++-	else {
++-		info->u.v2_i.dqi_free_entry = nextblk;
++-		mark_info_dirty(sb, type);
++-	}
++-	freedqbuf(tmpbuf);
++-	dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
++-	/* No matter whether write succeeds block is out of list */
++-	if (write_blk(sb, type, blk, buf) < 0)
++-		printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk);
++-	return 0;
++-out_buf:
++-	freedqbuf(tmpbuf);
++-	return err;
++-}
++-
++-/* Insert given block to the beginning of list with free entries */
++-static int insert_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
++-{
++-	dqbuf_t tmpbuf = getdqbuf();
++-	struct mem_dqinfo *info = sb_dqinfo(sb, type);
++-	struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
++-	int err;
++-
++-	if (!tmpbuf)
++-		return -ENOMEM;
++-	dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_entry);
++-	dh->dqdh_prev_free = cpu_to_le32(0);
++-	if ((err = write_blk(sb, type, blk, buf)) < 0)
++-		goto out_buf;
++-	if (info->u.v2_i.dqi_free_entry) {
++-		if ((err = read_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
++-			goto out_buf;
++-		((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = cpu_to_le32(blk);
++-		if ((err = write_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
++-			goto out_buf;
++-	}
++-	freedqbuf(tmpbuf);
++-	info->u.v2_i.dqi_free_entry = blk;
++-	mark_info_dirty(sb, type);
++-	return 0;
++-out_buf:
++-	freedqbuf(tmpbuf);
++-	return err;
++-}
++-
++-/* Find space for dquot */
++-static uint find_free_dqentry(struct dquot *dquot, int *err)
++-{
++-	struct super_block *sb = dquot->dq_sb;
++-	struct mem_dqinfo *info = sb_dqopt(sb)->info+dquot->dq_type;
++-	uint blk, i;
++-	struct v2_disk_dqdbheader *dh;
++-	struct v2_disk_dqblk *ddquot;
++-	struct v2_disk_dqblk fakedquot;
++-	dqbuf_t buf;
++-
++-	*err = 0;
++-	if (!(buf = getdqbuf())) {
++-		*err = -ENOMEM;
+++	if (qtree_entry_unused(info, dp))
++ 		return 0;
++-	}
++-	dh = (struct v2_disk_dqdbheader *)buf;
++-	ddquot = GETENTRIES(buf);
++-	if (info->u.v2_i.dqi_free_entry) {
++-		blk = info->u.v2_i.dqi_free_entry;
++-		if ((*err = read_blk(sb, dquot->dq_type, blk, buf)) < 0)
++-			goto out_buf;
++-	}
++-	else {
++-		blk = get_free_dqblk(sb, dquot->dq_type);
++-		if ((int)blk < 0) {
++-			*err = blk;
++-			freedqbuf(buf);
++-			return 0;
++-		}
++-		memset(buf, 0, V2_DQBLKSIZE);
++-		/* This is enough as block is already zeroed and entry list is empty... */
++-		info->u.v2_i.dqi_free_entry = blk;
++-		mark_info_dirty(sb, dquot->dq_type);
++-	}
++-	if (le16_to_cpu(dh->dqdh_entries)+1 >= V2_DQSTRINBLK)	/* Block will be full? */
++-		if ((*err = remove_free_dqentry(sb, dquot->dq_type, buf, blk)) < 0) {
++-			printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk);
++-			goto out_buf;
++-		}
++-	le16_add_cpu(&dh->dqdh_entries, 1);
++-	memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
++-	/* Find free structure in block */
++-	for (i = 0; i < V2_DQSTRINBLK && memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)); i++);
++-#ifdef __QUOTA_V2_PARANOIA
++-	if (i == V2_DQSTRINBLK) {
++-		printk(KERN_ERR "VFS: find_free_dqentry(): Data block full but it shouldn't.\n");
++-		*err = -EIO;
++-		goto out_buf;
++-	}
++-#endif
++-	if ((*err = write_blk(sb, dquot->dq_type, blk, buf)) < 0) {
++-		printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota data block %u.\n", blk);
++-		goto out_buf;
++-	}
++-	dquot->dq_off = (blk<<V2_DQBLKSIZE_BITS)+sizeof(struct v2_disk_dqdbheader)+i*sizeof(struct v2_disk_dqblk);
++-	freedqbuf(buf);
++-	return blk;
++-out_buf:
++-	freedqbuf(buf);
++-	return 0;
++-}
++-
++-/* Insert reference to structure into the trie */
++-static int do_insert_tree(struct dquot *dquot, uint *treeblk, int depth)
++-{
++-	struct super_block *sb = dquot->dq_sb;
++-	dqbuf_t buf;
++-	int ret = 0, newson = 0, newact = 0;
++-	__le32 *ref;
++-	uint newblk;
++-
++-	if (!(buf = getdqbuf()))
++-		return -ENOMEM;
++-	if (!*treeblk) {
++-		ret = get_free_dqblk(sb, dquot->dq_type);
++-		if (ret < 0)
++-			goto out_buf;
++-		*treeblk = ret;
++-		memset(buf, 0, V2_DQBLKSIZE);
++-		newact = 1;
++-	}
++-	else {
++-		if ((ret = read_blk(sb, dquot->dq_type, *treeblk, buf)) < 0) {
++-			printk(KERN_ERR "VFS: Can't read tree quota block %u.\n", *treeblk);
++-			goto out_buf;
++-		}
++-	}
++-	ref = (__le32 *)buf;
++-	newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
++-	if (!newblk)
++-		newson = 1;
++-	if (depth == V2_DQTREEDEPTH-1) {
++-#ifdef __QUOTA_V2_PARANOIA
++-		if (newblk) {
++-			printk(KERN_ERR "VFS: Inserting already present quota entry (block %u).\n", le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]));
++-			ret = -EIO;
++-			goto out_buf;
++-		}
++-#endif
++-		newblk = find_free_dqentry(dquot, &ret);
++-	}
++-	else
++-		ret = do_insert_tree(dquot, &newblk, depth+1);
++-	if (newson && ret >= 0) {
++-		ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(newblk);
++-		ret = write_blk(sb, dquot->dq_type, *treeblk, buf);
++-	}
++-	else if (newact && ret < 0)
++-		put_free_dqblk(sb, dquot->dq_type, buf, *treeblk);
++-out_buf:
++-	freedqbuf(buf);
++-	return ret;
+++	return le32_to_cpu(d->dqb_id) == dquot->dq_id;
++ }
++ 
++-/* Wrapper for inserting quota structure into tree */
++-static inline int dq_insert_tree(struct dquot *dquot)
+++static int v2_read_dquot(struct dquot *dquot)
++ {
++-	int tmp = V2_DQTREEOFF;
++-	return do_insert_tree(dquot, &tmp, 0);
+++	return qtree_read_dquot(&sb_dqinfo(dquot->dq_sb, dquot->dq_type)->u.v2_i.i, dquot);
++ }
++ 
++-/*
++- *	We don't have to be afraid of deadlocks as we never have quotas on quota files...
++- */
++ static int v2_write_dquot(struct dquot *dquot)
++ {
++-	int type = dquot->dq_type;
++-	ssize_t ret;
++-	struct v2_disk_dqblk ddquot, empty;
++-
++-	/* dq_off is guarded by dqio_mutex */
++-	if (!dquot->dq_off)
++-		if ((ret = dq_insert_tree(dquot)) < 0) {
++-			printk(KERN_ERR "VFS: Error %zd occurred while creating quota.\n", ret);
++-			return ret;
++-		}
++-	spin_lock(&dq_data_lock);
++-	mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
++-	/* Argh... We may need to write structure full of zeroes but that would be
++-	 * treated as an empty place by the rest of the code. Format change would
++-	 * be definitely cleaner but the problems probably are not worth it */
++-	memset(&empty, 0, sizeof(struct v2_disk_dqblk));
++-	if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
++-		ddquot.dqb_itime = cpu_to_le64(1);
++-	spin_unlock(&dq_data_lock);
++-	ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
++-	      (char *)&ddquot, sizeof(struct v2_disk_dqblk), dquot->dq_off);
++-	if (ret != sizeof(struct v2_disk_dqblk)) {
++-		printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", dquot->dq_sb->s_id);
++-		if (ret >= 0)
++-			ret = -ENOSPC;
++-	}
++-	else
++-		ret = 0;
++-	dqstats.writes++;
++-
++-	return ret;
++-}
++-
++-/* Free dquot entry in data block */
++-static int free_dqentry(struct dquot *dquot, uint blk)
++-{
++-	struct super_block *sb = dquot->dq_sb;
++-	int type = dquot->dq_type;
++-	struct v2_disk_dqdbheader *dh;
++-	dqbuf_t buf = getdqbuf();
++-	int ret = 0;
++-
++-	if (!buf)
++-		return -ENOMEM;
++-	if (dquot->dq_off >> V2_DQBLKSIZE_BITS != blk) {
++-		printk(KERN_ERR "VFS: Quota structure has offset to other "
++-		  "block (%u) than it should (%u).\n", blk,
++-		  (uint)(dquot->dq_off >> V2_DQBLKSIZE_BITS));
++-		goto out_buf;
++-	}
++-	if ((ret = read_blk(sb, type, blk, buf)) < 0) {
++-		printk(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
++-		goto out_buf;
++-	}
++-	dh = (struct v2_disk_dqdbheader *)buf;
++-	le16_add_cpu(&dh->dqdh_entries, -1);
++-	if (!le16_to_cpu(dh->dqdh_entries)) {	/* Block got free? */
++-		if ((ret = remove_free_dqentry(sb, type, buf, blk)) < 0 ||
++-		    (ret = put_free_dqblk(sb, type, buf, blk)) < 0) {
++-			printk(KERN_ERR "VFS: Can't move quota data block (%u) "
++-			  "to free list.\n", blk);
++-			goto out_buf;
++-		}
++-	}
++-	else {
++-		memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0,
++-		  sizeof(struct v2_disk_dqblk));
++-		if (le16_to_cpu(dh->dqdh_entries) == V2_DQSTRINBLK-1) {
++-			/* Insert will write block itself */
++-			if ((ret = insert_free_dqentry(sb, type, buf, blk)) < 0) {
++-				printk(KERN_ERR "VFS: Can't insert quota data block (%u) to free entry list.\n", blk);
++-				goto out_buf;
++-			}
++-		}
++-		else
++-			if ((ret = write_blk(sb, type, blk, buf)) < 0) {
++-				printk(KERN_ERR "VFS: Can't write quota data "
++-				  "block %u\n", blk);
++-				goto out_buf;
++-			}
++-	}
++-	dquot->dq_off = 0;	/* Quota is now unattached */
++-out_buf:
++-	freedqbuf(buf);
++-	return ret;
++-}
++-
++-/* Remove reference to dquot from tree */
++-static int remove_tree(struct dquot *dquot, uint *blk, int depth)
++-{
++-	struct super_block *sb = dquot->dq_sb;
++-	int type = dquot->dq_type;
++-	dqbuf_t buf = getdqbuf();
++-	int ret = 0;
++-	uint newblk;
++-	__le32 *ref = (__le32 *)buf;
++-	
++-	if (!buf)
++-		return -ENOMEM;
++-	if ((ret = read_blk(sb, type, *blk, buf)) < 0) {
++-		printk(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
++-		goto out_buf;
++-	}
++-	newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
++-	if (depth == V2_DQTREEDEPTH-1) {
++-		ret = free_dqentry(dquot, newblk);
++-		newblk = 0;
++-	}
++-	else
++-		ret = remove_tree(dquot, &newblk, depth+1);
++-	if (ret >= 0 && !newblk) {
++-		int i;
++-		ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0);
++-		for (i = 0; i < V2_DQBLKSIZE && !buf[i]; i++);	/* Block got empty? */
++-		/* Don't put the root block into the free block list */
++-		if (i == V2_DQBLKSIZE && *blk != V2_DQTREEOFF) {
++-			put_free_dqblk(sb, type, buf, *blk);
++-			*blk = 0;
++-		}
++-		else
++-			if ((ret = write_blk(sb, type, *blk, buf)) < 0)
++-				printk(KERN_ERR "VFS: Can't write quota tree "
++-				  "block %u.\n", *blk);
++-	}
++-out_buf:
++-	freedqbuf(buf);
++-	return ret;	
++-}
++-
++-/* Delete dquot from tree */
++-static int v2_delete_dquot(struct dquot *dquot)
++-{
++-	uint tmp = V2_DQTREEOFF;
++-
++-	if (!dquot->dq_off)	/* Even not allocated? */
++-		return 0;
++-	return remove_tree(dquot, &tmp, 0);
++-}
++-
++-/* Find entry in block */
++-static loff_t find_block_dqentry(struct dquot *dquot, uint blk)
++-{
++-	dqbuf_t buf = getdqbuf();
++-	loff_t ret = 0;
++-	int i;
++-	struct v2_disk_dqblk *ddquot = GETENTRIES(buf);
++-
++-	if (!buf)
++-		return -ENOMEM;
++-	if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
++-		printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
++-		goto out_buf;
++-	}
++-	if (dquot->dq_id)
++-		for (i = 0; i < V2_DQSTRINBLK &&
++-		     le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++);
++-	else {	/* ID 0 as a bit more complicated searching... */
++-		struct v2_disk_dqblk fakedquot;
++-
++-		memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
++-		for (i = 0; i < V2_DQSTRINBLK; i++)
++-			if (!le32_to_cpu(ddquot[i].dqb_id) &&
++-			    memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)))
++-				break;
++-	}
++-	if (i == V2_DQSTRINBLK) {
++-		printk(KERN_ERR "VFS: Quota for id %u referenced "
++-		  "but not present.\n", dquot->dq_id);
++-		ret = -EIO;
++-		goto out_buf;
++-	}
++-	else
++-		ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct
++-		  v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
++-out_buf:
++-	freedqbuf(buf);
++-	return ret;
++-}
++-
++-/* Find entry for given id in the tree */
++-static loff_t find_tree_dqentry(struct dquot *dquot, uint blk, int depth)
++-{
++-	dqbuf_t buf = getdqbuf();
++-	loff_t ret = 0;
++-	__le32 *ref = (__le32 *)buf;
++-
++-	if (!buf)
++-		return -ENOMEM;
++-	if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
++-		printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
++-		goto out_buf;
++-	}
++-	ret = 0;
++-	blk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
++-	if (!blk)	/* No reference? */
++-		goto out_buf;
++-	if (depth < V2_DQTREEDEPTH-1)
++-		ret = find_tree_dqentry(dquot, blk, depth+1);
++-	else
++-		ret = find_block_dqentry(dquot, blk);
++-out_buf:
++-	freedqbuf(buf);
++-	return ret;
+++	return qtree_write_dquot(&sb_dqinfo(dquot->dq_sb, dquot->dq_type)->u.v2_i.i, dquot);
++ }
++ 
++-/* Find entry for given id in the tree - wrapper function */
++-static inline loff_t find_dqentry(struct dquot *dquot)
++-{
++-	return find_tree_dqentry(dquot, V2_DQTREEOFF, 0);
++-}
++-
++-static int v2_read_dquot(struct dquot *dquot)
++-{
++-	int type = dquot->dq_type;
++-	loff_t offset;
++-	struct v2_disk_dqblk ddquot, empty;
++-	int ret = 0;
++-
++-#ifdef __QUOTA_V2_PARANOIA
++-	/* Invalidated quota? */
++-	if (!dquot->dq_sb || !sb_dqopt(dquot->dq_sb)->files[type]) {
++-		printk(KERN_ERR "VFS: Quota invalidated while reading!\n");
++-		return -EIO;
++-	}
++-#endif
++-	offset = find_dqentry(dquot);
++-	if (offset <= 0) {	/* Entry not present? */
++-		if (offset < 0)
++-			printk(KERN_ERR "VFS: Can't read quota "
++-			  "structure for id %u.\n", dquot->dq_id);
++-		dquot->dq_off = 0;
++-		set_bit(DQ_FAKE_B, &dquot->dq_flags);
++-		memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
++-		ret = offset;
++-	}
++-	else {
++-		dquot->dq_off = offset;
++-		if ((ret = dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type,
++-		    (char *)&ddquot, sizeof(struct v2_disk_dqblk), offset))
++-		    != sizeof(struct v2_disk_dqblk)) {
++-			if (ret >= 0)
++-				ret = -EIO;
++-			printk(KERN_ERR "VFS: Error while reading quota "
++-			  "structure for id %u.\n", dquot->dq_id);
++-			memset(&ddquot, 0, sizeof(struct v2_disk_dqblk));
++-		}
++-		else {
++-			ret = 0;
++-			/* We need to escape back all-zero structure */
++-			memset(&empty, 0, sizeof(struct v2_disk_dqblk));
++-			empty.dqb_itime = cpu_to_le64(1);
++-			if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
++-				ddquot.dqb_itime = 0;
++-		}
++-		disk2memdqb(&dquot->dq_dqb, &ddquot);
++-		if (!dquot->dq_dqb.dqb_bhardlimit &&
++-			!dquot->dq_dqb.dqb_bsoftlimit &&
++-			!dquot->dq_dqb.dqb_ihardlimit &&
++-			!dquot->dq_dqb.dqb_isoftlimit)
++-			set_bit(DQ_FAKE_B, &dquot->dq_flags);
++-	}
++-	dqstats.reads++;
++-
++-	return ret;
++-}
++-
++-/* Check whether dquot should not be deleted. We know we are
++- * the only one operating on dquot (thanks to dq_lock) */
++ static int v2_release_dquot(struct dquot *dquot)
++ {
++-	if (test_bit(DQ_FAKE_B, &dquot->dq_flags) && !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace))
++-		return v2_delete_dquot(dquot);
++-	return 0;
+++	return qtree_release_dquot(&sb_dqinfo(dquot->dq_sb, dquot->dq_type)->u.v2_i.i, dquot);
++ }
++ 
++ static struct quota_format_ops v2_format_ops = {
++Index: linux-2.6.27.36/include/linux/dqblk_qtree.h
++===================================================================
++--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++++ linux-2.6.27.36/include/linux/dqblk_qtree.h	2009-10-08 16:32:48.000000000 +0200
++@@ -0,0 +1,56 @@
+++/*
+++ *	Definitions of structures and functions for quota formats using trie
+++ */
+++
+++#ifndef _LINUX_DQBLK_QTREE_H
+++#define _LINUX_DQBLK_QTREE_H
+++
+++#include <linux/types.h>
+++
+++/* Numbers of blocks needed for updates - we count with the smallest
+++ * possible block size (1024) */
+++#define QTREE_INIT_ALLOC 4
+++#define QTREE_INIT_REWRITE 2
+++#define QTREE_DEL_ALLOC 0
+++#define QTREE_DEL_REWRITE 6
+++
+++struct dquot;
+++
+++/* Operations */
+++struct qtree_fmt_operations {
+++	void (*mem2disk_dqblk)(void *disk, struct dquot *dquot);	/* Convert given entry from in memory format to disk one */
+++	void (*disk2mem_dqblk)(struct dquot *dquot, void *disk);	/* Convert given entry from disk format to in memory one */
+++	int (*is_id)(void *disk, struct dquot *dquot);	/* Is this structure for given id? */
+++};
+++
+++/* Inmemory copy of version specific information */
+++struct qtree_mem_dqinfo {
+++	struct super_block *dqi_sb;	/* Sb quota is on */
+++	int dqi_type;			/* Quota type */
+++	unsigned int dqi_blocks;	/* # of blocks in quota file */
+++	unsigned int dqi_free_blk;	/* First block in list of free blocks */
+++	unsigned int dqi_free_entry;	/* First block with free entry */
+++	unsigned int dqi_blocksize_bits;	/* Block size of quota file */
+++	unsigned int dqi_entry_size;	/* Size of quota entry in quota file */
+++	unsigned int dqi_usable_bs;	/* Space usable in block for quota data */
+++	unsigned int dqi_qtree_depth;	/* Precomputed depth of quota tree */
+++	struct qtree_fmt_operations *dqi_ops;	/* Operations for entry manipulation */
+++};
+++
+++int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot);
+++int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot);
+++int qtree_delete_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot);
+++int qtree_release_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot);
+++int qtree_entry_unused(struct qtree_mem_dqinfo *info, char *disk);
+++static inline int qtree_depth(struct qtree_mem_dqinfo *info)
+++{
+++	unsigned int epb = info->dqi_usable_bs >> 2;
+++	unsigned long long entries = epb;
+++	int i;
+++
+++	for (i = 1; entries < (1ULL << 32); i++)
+++		entries *= epb;
+++	return i;
+++}
+++
+++#endif /* _LINUX_DQBLK_QTREE_H */
++Index: linux-2.6.27.36/include/linux/dqblk_v2.h
++===================================================================
++--- linux-2.6.27.36.orig/include/linux/dqblk_v2.h	2009-10-05 17:19:01.000000000 +0200
+++++ linux-2.6.27.36/include/linux/dqblk_v2.h	2009-10-08 16:32:48.000000000 +0200
++@@ -1,26 +1,23 @@
++ /*
++- *	Definitions of structures for vfsv0 quota format
+++ *  Definitions for vfsv0 quota format
++  */
++ 
++ #ifndef _LINUX_DQBLK_V2_H
++ #define _LINUX_DQBLK_V2_H
++ 
++-#include <linux/types.h>
+++#include <linux/dqblk_qtree.h>
++ 
++-/* id numbers of quota format */
+++/* Id number of quota format */
++ #define QFMT_VFS_V0 2
++ 
++ /* Numbers of blocks needed for updates */
++-#define V2_INIT_ALLOC 4
++-#define V2_INIT_REWRITE 2
++-#define V2_DEL_ALLOC 0
++-#define V2_DEL_REWRITE 6
+++#define V2_INIT_ALLOC QTREE_INIT_ALLOC
+++#define V2_INIT_REWRITE QTREE_INIT_REWRITE
+++#define V2_DEL_ALLOC QTREE_DEL_ALLOC
+++#define V2_DEL_REWRITE QTREE_DEL_REWRITE
++ 
++-/* Inmemory copy of version specific information */
++ struct v2_mem_dqinfo {
++-	unsigned int dqi_blocks;
++-	unsigned int dqi_free_blk;
++-	unsigned int dqi_free_entry;
+++	struct qtree_mem_dqinfo i;
++ };
++ 
++ #endif /* _LINUX_DQBLK_V2_H */
+--- /dev/null
++++ lustre-1.8.5+dfsg/lustre/kernel_patches/patches/debian-2.6.26.diff
+@@ -0,0 +1,1210 @@
++diff -u -r debian-2.6.26/Documentation/filesystems/ext2.txt debian-2.6.26_lustre.1.8.2/Documentation/filesystems/ext2.txt
++--- debian-2.6.26/Documentation/filesystems/ext2.txt	2008-07-13 23:51:29.000000000 +0200
+++++ debian-2.6.26_lustre.1.8.2/Documentation/filesystems/ext2.txt	2010-02-12 15:11:19.000000000 +0100
++@@ -58,6 +58,22 @@
++ 
++ xip				Use execute in place (no caching) if possible
++ 
+++iopen                          Makes an invisible pseudo-directory called 
+++                               __iopen__ available in the root directory
+++                               of the filesystem.  Allows open-by-inode-
+++                               number.  i.e., inode 3145 can be accessed
+++                               via /mntpt/__iopen__/3145
+++
+++iopen_nopriv                   This option makes the iopen directory be
+++                               world-readable.  This may be safer since it
+++                               allows daemons to run as an unprivileged user,
+++                               however it significantly changes the security
+++                               model of a Unix filesystem, since previously
+++                               all files under a mode 700 directory were not
+++                               generally avilable even if the
+++                               permissions on the file itself is
+++                               world-readable.
+++
++ grpquota,noquota,quota,usrquota	Quota options are silently ignored by ext2.
++ 
++ 
++diff -u -r debian-2.6.26/block/blk-core.c debian-2.6.26_lustre.1.8.2/block/blk-core.c
++--- debian-2.6.26/block/blk-core.c	2008-07-13 23:51:29.000000000 +0200
+++++ debian-2.6.26_lustre.1.8.2/block/blk-core.c	2010-02-12 15:14:32.000000000 +0100
++@@ -1270,6 +1270,8 @@
++ 
++ #endif /* CONFIG_FAIL_MAKE_REQUEST */
++ 
+++int dev_check_rdonly(struct block_device *bdev);
+++
++ /*
++  * Check whether this bio extends beyond the end of the device.
++  */
++@@ -1371,6 +1373,12 @@
++ 
++ 		if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
++ 			goto end_io;
+++                /* this is cfs's dev_rdonly check */
+++                if (bio->bi_rw == WRITE &&
+++                                dev_check_rdonly(bio->bi_bdev)) {
+++                        bio_endio(bio, 0);
+++                        break;
+++                }
++ 
++ 		if (should_fail_request(bio))
++ 			goto end_io;
++@@ -2028,6 +2036,91 @@
++ }
++ EXPORT_SYMBOL(kblockd_flush_work);
++ 
+++ /*
+++ * Debug code for turning block devices "read-only" (will discard writes
+++ * silently).  This is for filesystem crash/recovery testing.
+++ */
+++struct deventry {
+++       dev_t dev;
+++       struct deventry *next;
+++};
+++
+++static struct deventry *devlist = NULL;
+++static spinlock_t devlock = SPIN_LOCK_UNLOCKED;
+++
+++int dev_check_rdonly(struct block_device *bdev)
+++{
+++       struct deventry *cur;
+++       if (!bdev) return 0;
+++       spin_lock(&devlock);
+++       cur = devlist;
+++       while(cur) {
+++               if (bdev->bd_dev == cur->dev) {
+++                       spin_unlock(&devlock);
+++                       return 1;
+++       }
+++               cur = cur->next;
+++       }
+++       spin_unlock(&devlock);
+++       return 0;
+++}
+++
+++void dev_set_rdonly(struct block_device *bdev)
+++{
+++       struct deventry *newdev, *cur;
+++
+++       if (!bdev)
+++               return;
+++       newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
+++       if (!newdev)
+++               return;
+++
+++       spin_lock(&devlock);
+++       cur = devlist;
+++       while(cur) {
+++               if (bdev->bd_dev == cur->dev) {
+++                       spin_unlock(&devlock);
+++                       kfree(newdev);
+++                       return;
+++               }
+++               cur = cur->next;
+++       }
+++       newdev->dev = bdev->bd_dev;
+++       newdev->next = devlist;
+++       devlist = newdev;
+++       spin_unlock(&devlock);
+++       printk(KERN_WARNING "Turning device %s (%#x) read-only\n",
+++              bdev->bd_disk ? bdev->bd_disk->disk_name : "", bdev->bd_dev);
+++}
+++
+++void dev_clear_rdonly(struct block_device *bdev)
+++{
+++       struct deventry *cur, *last = NULL;
+++       if (!bdev) return;
+++       spin_lock(&devlock);
+++       cur = devlist;
+++       while(cur) {
+++               if (bdev->bd_dev == cur->dev) {
+++                       if (last)
+++                               last->next = cur->next;
+++                       else
+++                               devlist = cur->next;
+++                       spin_unlock(&devlock);
+++                       kfree(cur);
+++                       printk(KERN_WARNING "Removing read-only on %s (%#x)\n",
+++                              bdev->bd_disk ? bdev->bd_disk->disk_name :
+++                                              "unknown block", bdev->bd_dev);
+++                       return;
+++               }
+++               last = cur;
+++               cur = cur->next;
+++       }
+++       spin_unlock(&devlock);
+++}
+++
+++EXPORT_SYMBOL(dev_set_rdonly);
+++EXPORT_SYMBOL(dev_clear_rdonly);
+++
++ int __init blk_dev_init(void)
++ {
++ 	int i;
++diff -u -r debian-2.6.26/drivers/md/raid5.c debian-2.6.26_lustre.1.8.2/drivers/md/raid5.c
++--- debian-2.6.26/drivers/md/raid5.c	2008-07-13 23:51:29.000000000 +0200
+++++ debian-2.6.26_lustre.1.8.2/drivers/md/raid5.c	2010-02-12 15:19:25.000000000 +0100
++@@ -1817,6 +1817,8 @@
++ 		bi->bi_next = *bip;
++ 	*bip = bi;
++ 	bi->bi_phys_segments ++;
+++        if (bio_sync(bi) && !forwrite)
+++                clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags); /* force to read from disk. */
++ 	spin_unlock_irq(&conf->device_lock);
++ 	spin_unlock(&sh->lock);
++ 
++@@ -3699,6 +3701,8 @@
++ 			      test_bit(BIO_UPTODATE, &bi->bi_flags)
++ 			        ? 0 : -EIO);
++ 	}
+++	if (bio_sync(bi))
+++		raid5_unplug_device(q);
++ 	return 0;
++ }
++ 
++diff -u -r debian-2.6.26/drivers/scsi/Kconfig debian-2.6.26_lustre.1.8.2/drivers/scsi/Kconfig
++--- debian-2.6.26/drivers/scsi/Kconfig	2009-12-26 09:14:53.000000000 +0100
+++++ debian-2.6.26_lustre.1.8.2/drivers/scsi/Kconfig	2010-02-12 15:20:02.000000000 +0100
++@@ -81,6 +81,14 @@
++ 	  In this case, do not compile the driver for your SCSI host adapter
++ 	  (below) as a module either.
++ 
+++config SD_IOSTATS
+++   bool "Enable SCSI disk I/O stats"
+++   depends on BLK_DEV_SD
+++   default y
+++   ---help---
+++     This enables SCSI disk I/O stats collection.  You must also enable
+++     /proc file system support if you want this feature.
+++
++ config CHR_DEV_ST
++ 	tristate "SCSI tape support"
++ 	depends on SCSI
++diff -u -r debian-2.6.26/drivers/scsi/scsi_proc.c debian-2.6.26_lustre.1.8.2/drivers/scsi/scsi_proc.c
++--- debian-2.6.26/drivers/scsi/scsi_proc.c	2008-07-13 23:51:29.000000000 +0200
+++++ debian-2.6.26_lustre.1.8.2/drivers/scsi/scsi_proc.c	2010-02-12 15:22:05.000000000 +0100
++@@ -40,7 +40,8 @@
++ /* 4K page size, but our output routines, use some slack for overruns */
++ #define PROC_BLOCK_SIZE (3*1024)
++ 
++-static struct proc_dir_entry *proc_scsi;
+++struct proc_dir_entry *proc_scsi;
+++EXPORT_SYMBOL(proc_scsi);
++ 
++ /* Protect sht->present and sht->proc_dir */
++ static DEFINE_MUTEX(global_host_template_mutex);
++diff -u -r debian-2.6.26/drivers/scsi/sd.c debian-2.6.26_lustre.1.8.2/drivers/scsi/sd.c
++--- debian-2.6.26/drivers/scsi/sd.c	2008-07-13 23:51:29.000000000 +0200
+++++ debian-2.6.26_lustre.1.8.2/drivers/scsi/sd.c	2010-02-17 14:13:32.000000000 +0100
++@@ -107,6 +107,24 @@
++  * object after last put) */
++ static DEFINE_MUTEX(sd_ref_mutex);
++ 
+++#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
+++# include <linux/proc_fs.h>
+++# include <linux/seq_file.h>
+++struct proc_dir_entry *sd_iostats_procdir = NULL;
+++char sd_iostats_procdir_name[] = "sd_iostats";
+++static struct file_operations sd_iostats_proc_fops;
+++
+++extern void sd_iostats_init(void);
+++extern void sd_iostats_fini(void);
+++void sd_iostats_start_req(struct scsi_cmnd *SCpnt);
+++void sd_iostats_finish_req(struct scsi_cmnd *SCpnt);
+++#else
+++static inline void sd_iostats_init(void) {}
+++static inline void sd_iostats_fini(void) {}
+++static inline void sd_iostats_start_req(struct scsi_cmnd *SCpnt) {}
+++static inline void sd_iostats_finish_req(struct scsi_cmnd *SCpnt) {}
+++#endif
+++
++ static const char *sd_cache_types[] = {
++ 	"write through", "none", "write back",
++ 	"write back, no read (daft)"
++@@ -531,6 +549,8 @@
++ 	}
++ 	SCpnt->sdb.length = this_count * sdp->sector_size;
++ 
+++	sd_iostats_start_req(SCpnt);
+++
++ 	/*
++ 	 * We shouldn't disconnect in the middle of a sector, so with a dumb
++ 	 * host adapter, it's safe to assume that we can at least transfer
++@@ -667,7 +687,7 @@
++ 	int diskinfo[4];
++ 
++ 	/* default to most commonly used values */
++-        diskinfo[0] = 0x40;	/* 1 << 6 */
+++	diskinfo[0] = 0x40;	/* 1 << 6 */
++        	diskinfo[1] = 0x20;	/* 1 << 5 */
++        	diskinfo[2] = sdkp->capacity >> 11;
++ 	
++@@ -1023,6 +1043,7 @@
++ 		break;
++ 	}
++  out:
+++	sd_iostats_finish_req(SCpnt);
++ 	return good_bytes;
++ }
++ 
++@@ -1711,6 +1732,36 @@
++ 	gd->flags = GENHD_FL_DRIVERFS;
++ 	if (sdp->removable)
++ 		gd->flags |= GENHD_FL_REMOVABLE;
+++#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
+++       sdkp->stats = kzalloc(sizeof(iostat_stats_t), GFP_KERNEL);
+++       if (!sdkp->stats) {
+++	       printk(KERN_WARNING "cannot allocate iostat structure for"
+++	                           "%s\n", gd->disk_name);
+++       } else {
+++	       do_gettimeofday(&sdkp->stats->iostat_timeval);
+++	       sdkp->stats->iostat_queue_stamp = jiffies;
+++	       spin_lock_init(&sdkp->stats->iostat_lock);
+++	       if (sd_iostats_procdir) {
+++	               struct proc_dir_entry *pde;
+++	               pde = create_proc_entry(gd->disk_name, S_IRUGO | S_IWUSR,
+++	                                       sd_iostats_procdir);
+++	               if (!pde) {
+++	                       printk(KERN_WARNING "Can't create /proc/scsi/"
+++	                                           "%s/%s\n",
+++	                                           sd_iostats_procdir_name,
+++	                                           gd->disk_name);
+++	                       kfree(sdkp->stats);
+++	                       sdkp->stats = NULL;
+++	               } else {
+++	                       pde->proc_fops = &sd_iostats_proc_fops;
+++	                       pde->data = gd;
+++	               }
+++	       } else {
+++	               kfree(sdkp->stats);
+++	               sdkp->stats = NULL;
+++	       }
+++       }
+++#endif
++ 
++ 	dev_set_drvdata(dev, sdkp);
++ 	add_disk(gd);
++@@ -1755,6 +1806,366 @@
++ 	return 0;
++ }
++ 
+++#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
+++static int
+++ sd_iostats_seq_show(struct seq_file *seq, void *v)
+++ {
+++	struct timeval     now;
+++	struct gendisk *disk = seq->private;
+++	iostat_stats_t    *stats;
+++	unsigned long long read_len;
+++	unsigned long long read_len_tot;
+++	unsigned long      read_num;
+++	unsigned long      read_num_tot;
+++	unsigned long long write_len;
+++	unsigned long long write_len_tot;
+++	unsigned long      write_num;
+++	unsigned long      write_num_tot;
+++	int                i;
+++	int                maxi;
+++ 
+++	stats = scsi_disk(disk)->stats;
+++	if (stats == NULL) {
+++	        printk(KERN_ERR "sd_iostats_seq_show: NULL stats entry\n");
+++	        BUG();
+++	}
+++ 
+++	do_gettimeofday(&now);
+++	now.tv_sec -= stats->iostat_timeval.tv_sec;
+++	now.tv_usec -= stats->iostat_timeval.tv_usec;
+++	if (now.tv_usec < 0) {
+++	        now.tv_usec += 1000000;
+++	        now.tv_sec--;
+++	}
+++ 
+++	/* this sampling races with updates */
+++	seq_printf(seq, "index:        %lu   snapshot_time:         %lu.%06lu\n",
+++	                (unsigned long) scsi_disk(disk)->index,
+++	                now.tv_sec, now.tv_usec);
+++ 
+++	for (i = IOSTAT_NCOUNTERS - 1; i > 0; i--)
+++	        if (stats->iostat_read_histogram[i].iostat_count != 0 ||
+++	                        stats->iostat_write_histogram[i].iostat_count != 0)
+++	                break;
+++	maxi = i;
+++ 
+++	seq_printf(seq, "%8s %8s %12s %8s %12s\n", "size", 
+++	                "reads", "total", "writes", "total");
+++ 
+++	read_len_tot = write_len_tot = 0;
+++	read_num_tot = write_num_tot = 0;
+++	for (i = 0; i <= maxi; i++) {
+++	        read_len = stats->iostat_read_histogram[i].iostat_size;
+++	        read_len_tot += read_len;
+++	        read_num = stats->iostat_read_histogram[i].iostat_count;
+++	        read_num_tot += read_num;
+++ 
+++	        write_len = stats->iostat_write_histogram[i].iostat_size;
+++	        write_len_tot += write_len;
+++	        write_num = stats->iostat_write_histogram[i].iostat_count;
+++	        write_num_tot += write_num;
+++ 
+++	        seq_printf (seq, "%8d %8lu %12llu %8lu %12llu\n", 
+++	                        512<<i, read_num, read_len, write_num, write_len);
+++	}
+++ 
+++	seq_printf(seq, "%8s %8lu %12llu %8lu %12llu\n\n", "total",
+++	                read_num_tot, read_len_tot, 
+++	                write_num_tot, write_len_tot);
+++ 
+++	seq_printf(seq, "%8s %8s %8s\n", "qdepth", "ticks", "%");
+++	for (i = 0; i < IOSTAT_NCOUNTERS; i++) {
+++	        unsigned long long ticks, percent;
+++	        ticks = stats->iostat_queue_ticks[i];
+++	        if (ticks == 0)
+++	                continue;
+++	        percent = stats->iostat_queue_ticks[i] * 100;
+++	        do_div(percent, stats->iostat_queue_ticks_sum);
+++	        seq_printf(seq, "%8d %8llu %8llu\n", i, ticks, percent);
+++	}
+++ 
+++	if (stats->iostat_reqs != 0) {
+++	        unsigned long long aveseek = 0, percent = 0;
+++ 
+++	        if (stats->iostat_seeks) {
+++	                aveseek = stats->iostat_seek_sectors;
+++	                do_div(aveseek, stats->iostat_seeks);
+++	                percent = stats->iostat_seeks * 100;
+++	                do_div(percent, stats->iostat_reqs);
+++	        }
+++ 
+++	        seq_printf(seq, "\n%llu sectors in %llu reqs: %llu seek(s) over "
+++	                        "%llu sectors in ave, %llu%% of all reqs\n",
+++	                        stats->iostat_sectors, stats->iostat_reqs,
+++	                        stats->iostat_seeks, aveseek, percent);
+++	}
+++ 
+++	seq_printf(seq, "\n%16s %8s %8s %8s %8s\n", "process time", "reads",
+++	                "%%", "writes", "%%");
+++	for (i = 0; i < IOSTAT_NCOUNTERS; i++) {
+++	        unsigned long read_percent = 0, write_percent = 0;
+++	        if (stats->iostat_wtime[i] == 0 &&
+++	                        stats->iostat_rtime[i] == 0)
+++	                continue;
+++	        if (stats->iostat_read_reqs)
+++	                read_percent = stats->iostat_rtime[i] * 100 / 
+++	                        stats->iostat_read_reqs;
+++	        if (stats->iostat_write_reqs)
+++	                write_percent = stats->iostat_wtime[i] * 100 / 
+++	                        stats->iostat_write_reqs;
+++	        seq_printf(seq, "%16u %8lu %8lu %8lu %8lu\n",
+++	                        jiffies_to_msecs(((1UL << i) >> 1) << 1),
+++	                        stats->iostat_rtime[i], read_percent,
+++	                        stats->iostat_wtime[i], write_percent);
+++	}
+++ 
+++	seq_printf(seq, "\n%16s %8s %8s %8s %8s\n", "time in queue", "reads",
+++	                "%%", "writes", "%%");
+++	for (i = 0; i < IOSTAT_NCOUNTERS; i++) {
+++	        unsigned long read_percent = 0, write_percent = 0;
+++	        if (stats->iostat_wtime_in_queue[i] == 0 &&
+++	                        stats->iostat_rtime_in_queue[i] == 0)
+++	                continue;
+++	        if (stats->iostat_read_reqs)
+++	                read_percent = stats->iostat_rtime_in_queue[i] * 100 / 
+++	                        stats->iostat_read_reqs;
+++	        if (stats->iostat_write_reqs)
+++	                write_percent = stats->iostat_wtime_in_queue[i] * 100 / 
+++	                        stats->iostat_write_reqs;
+++	        seq_printf(seq, "%16u %8lu %8lu %8lu %8lu\n",
+++	                        jiffies_to_msecs(((1UL << i) >> 1) << 1),
+++	                        stats->iostat_rtime_in_queue[i],
+++	                        read_percent,
+++	                        stats->iostat_wtime_in_queue[i],
+++	                        write_percent);
+++	}
+++ 
+++	return 0;
+++ }
+++ 
+++ static void *
+++ sd_iostats_seq_start(struct seq_file *p, loff_t *pos)
+++ {
+++	return (*pos == 0) ? (void *)1 : NULL;
+++ }
+++ 
+++ static void *
+++ sd_iostats_seq_next(struct seq_file *p, void *v, loff_t *pos)
+++ {
+++	++*pos;
+++	return NULL;
+++ }
+++ 
+++ static void
+++ sd_iostats_seq_stop(struct seq_file *p, void *v)
+++ {
+++ }
+++ 
+++ static struct seq_operations sd_iostats_seqops = {
+++	.start = sd_iostats_seq_start,
+++	.stop  = sd_iostats_seq_stop,
+++	.next  = sd_iostats_seq_next,
+++	.show  = sd_iostats_seq_show,
+++ };
+++ 
+++ static int
+++ sd_iostats_seq_open (struct inode *inode, struct file *file)
+++ {
+++	int rc;
+++ 
+++	rc = seq_open(file, &sd_iostats_seqops);
+++	if (rc != 0)
+++	        return rc;
+++ 
+++	((struct seq_file *)file->private_data)->private = PDE(inode)->data;
+++	return 0;
+++ }
+++ 
+++ static ssize_t
+++ sd_iostats_seq_write(struct file *file, const char *buffer,
+++	             size_t len, loff_t *off)
+++ {
+++	struct seq_file   *seq = file->private_data;
+++	struct gendisk *disk = seq->private;
+++	iostat_stats_t    *stats = scsi_disk(disk)->stats;
+++	unsigned long      flags;
+++	unsigned long      qdepth;
+++ 
+++ 
+++	spin_lock_irqsave (&stats->iostat_lock, flags);
+++	qdepth = stats->iostat_queue_depth;
+++	memset (stats, 0, offsetof(iostat_stats_t, iostat_lock));
+++	do_gettimeofday(&stats->iostat_timeval);
+++	stats->iostat_queue_stamp = jiffies;
+++	stats->iostat_queue_depth = qdepth;
+++	spin_unlock_irqrestore (&stats->iostat_lock, flags);
+++ 
+++	return len;
+++ }
+++ 
+++ static struct file_operations sd_iostats_proc_fops = {
+++	.owner   = THIS_MODULE,
+++	.open    = sd_iostats_seq_open,
+++	.read    = seq_read,
+++	.write   = sd_iostats_seq_write,
+++	.llseek  = seq_lseek,
+++	.release = seq_release,
+++ };
+++ 
+++ extern struct proc_dir_entry *proc_scsi;
+++ 
+++ void
+++ sd_iostats_init(void)
+++ {
+++	if (proc_scsi == NULL) {
+++	        printk(KERN_WARNING "No access to sd iostats: "
+++	                "proc_scsi is NULL\n");
+++	        return;
+++	}
+++ 
+++	sd_iostats_procdir = create_proc_entry(sd_iostats_procdir_name,
+++	                                       S_IFDIR | S_IRUGO | S_IXUGO,
+++	                                        proc_scsi);
+++	if (sd_iostats_procdir == NULL) {
+++	        printk(KERN_WARNING "No access to sd iostats: "
+++	                "can't create /proc/scsi/%s\n", sd_iostats_procdir_name);
+++	        return;
+++	}
+++ }
+++ 
+++ void sd_iostats_fini(void)
+++ {
+++	if (proc_scsi != NULL && sd_iostats_procdir != NULL)
+++	        remove_proc_entry(sd_iostats_procdir_name, proc_scsi);
+++ 
+++	sd_iostats_procdir = NULL;
+++ }
+++ 
+++ void sd_iostats_finish_req(struct scsi_cmnd *SCpnt)
+++ {
+++	struct request          *rq = SCpnt->request;
+++	iostat_stats_t          *stats;
+++	unsigned long           *tcounter;
+++	int                     tbucket;
+++	int                     tmp;
+++	unsigned long           irqflags;
+++	unsigned long           i;
+++ 
+++	stats = scsi_disk(rq->rq_disk)->stats;
+++	if (stats == NULL)
+++	        return;
+++ 
+++	tmp = jiffies - rq->start_time;
+++	for (tbucket = 0; tmp > 1; tbucket++)
+++	        tmp >>= 1;
+++	if (tbucket >= IOSTAT_NCOUNTERS)
+++	        tbucket = IOSTAT_NCOUNTERS - 1;
+++	//printk("%u ticks in D to %u\n", jiffies - rq->start_time, tbucket);
+++ 
+++	tcounter = rq_data_dir(rq) == WRITE ?
+++	        &stats->iostat_wtime[tbucket] : &stats->iostat_rtime[tbucket];
+++ 
+++	spin_lock_irqsave(&stats->iostat_lock, irqflags);
+++ 
+++	/* update delay stats */
+++	(*tcounter)++;
+++ 
+++	/* update queue depth stats */
+++	i = stats->iostat_queue_depth;
+++	if (i >= IOSTAT_NCOUNTERS)
+++	        i = IOSTAT_NCOUNTERS - 1;
+++	stats->iostat_queue_ticks[i] += jiffies - stats->iostat_queue_stamp;
+++	stats->iostat_queue_ticks_sum += jiffies - stats->iostat_queue_stamp;
+++	BUG_ON(stats->iostat_queue_depth == 0);
+++	stats->iostat_queue_depth--;
+++ 
+++	/* update seek stats. XXX: not sure about nr_sectors */
+++	stats->iostat_sectors += rq->nr_sectors;
+++	stats->iostat_reqs++;
+++	if (rq->sector != stats->iostat_next_sector) {
+++	        stats->iostat_seek_sectors +=
+++	                rq->sector > stats->iostat_next_sector ?
+++	                rq->sector - stats->iostat_next_sector :
+++	                stats->iostat_next_sector - rq->sector;
+++	        stats->iostat_seeks++;
+++	}
+++	stats->iostat_next_sector = rq->sector + rq->nr_sectors;
+++ 
+++	stats->iostat_queue_stamp = jiffies;
+++ 
+++	spin_unlock_irqrestore(&stats->iostat_lock, irqflags);
+++ }
+++ 
+++ void sd_iostats_start_req(struct scsi_cmnd *SCpnt)
+++ {
+++	struct request          *rq = SCpnt->request;
+++	iostat_stats_t          *stats;
+++	iostat_counter_t        *counter;
+++	int                     bucket;
+++	int                     tbucket;
+++	int                     tmp;
+++	unsigned long           irqflags;
+++	unsigned long           i;
+++	int                     nsect;
+++ 
+++	stats = scsi_disk(rq->rq_disk)->stats;
+++	if (stats == NULL)
+++	        return;
+++ 
+++	nsect = scsi_bufflen(SCpnt) >> 9;
+++	for (bucket = 0, tmp = nsect; tmp > 1; bucket++)
+++	        tmp >>= 1;
+++ 
+++	if (bucket >= IOSTAT_NCOUNTERS) {
+++	        printk (KERN_ERR "sd_iostats_bump: nsect %d too big\n", nsect);
+++	        BUG();
+++	}
+++ 
+++	counter = rq_data_dir(rq) == WRITE ?
+++	        &stats->iostat_write_histogram[bucket] :
+++	        &stats->iostat_read_histogram[bucket];
+++ 
+++	tmp = jiffies - rq->start_time;
+++	for (tbucket = 0; tmp > 1; tbucket++)
+++	        tmp >>= 1;
+++	if (tbucket >= IOSTAT_NCOUNTERS)
+++	        tbucket = IOSTAT_NCOUNTERS - 1;
+++	//printk("%u ticks in Q to %u\n", jiffies - rq->start_time, tbucket);
+++ 
+++	/* an ugly hack to know exact processing time. the right
+++	 * solution is to add one more field to struct request
+++	 * hopefully it will break nothing ... */
+++	rq->start_time = jiffies;
+++ 
+++	spin_lock_irqsave(&stats->iostat_lock, irqflags);
+++ 
+++	/* update queue depth stats */
+++	i = stats->iostat_queue_depth;
+++	if (i >= IOSTAT_NCOUNTERS)
+++	        i = IOSTAT_NCOUNTERS - 1;
+++	stats->iostat_queue_ticks[i] += jiffies - stats->iostat_queue_stamp;
+++	stats->iostat_queue_ticks_sum += jiffies - stats->iostat_queue_stamp;
+++	stats->iostat_queue_depth++;
+++ 
+++	/* update delay stats */
+++	if (rq_data_dir(rq) == WRITE) {
+++	        stats->iostat_wtime_in_queue[tbucket]++;
+++	        stats->iostat_write_reqs++;
+++	} else {
+++	        stats->iostat_rtime_in_queue[tbucket]++;
+++	        stats->iostat_read_reqs++;
+++	}
+++ 
+++	/* update size stats */
+++	counter->iostat_size += nsect;
+++	counter->iostat_count++;
+++ 
+++	stats->iostat_queue_stamp = jiffies;
+++ 
+++	spin_unlock_irqrestore(&stats->iostat_lock, irqflags);
+++}
+++#endif
+++
++ /**
++  *	scsi_disk_release - Called to free the scsi_disk structure
++  *	@dev: pointer to embedded class device
++@@ -1773,6 +2184,13 @@
++ 	idr_remove(&sd_index_idr, sdkp->index);
++ 	spin_unlock(&sd_index_lock);
++ 
+++#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
+++        if (sdkp->stats) {
+++                remove_proc_entry(disk->disk_name, sd_iostats_procdir);
+++                kfree(sdkp->stats);
+++                sdkp->stats = NULL;
+++        }
+++#endif
++ 	disk->private_data = NULL;
++ 	put_disk(disk);
++ 	put_device(&sdkp->device->sdev_gendev);
++@@ -1890,6 +2308,8 @@
++ 	if (!majors)
++ 		return -ENODEV;
++ 
+++	sd_iostats_init();
+++
++ 	err = class_register(&sd_disk_class);
++ 	if (err)
++ 		goto err_out;
++@@ -1905,6 +2325,7 @@
++ err_out:
++ 	for (i = 0; i < SD_MAJORS; i++)
++ 		unregister_blkdev(sd_major(i), "sd");
+++	sd_iostats_fini();
++ 	return err;
++ }
++ 
++diff -u -r debian-2.6.26/fs/block_dev.c debian-2.6.26_lustre.1.8.2/fs/block_dev.c
++--- debian-2.6.26/fs/block_dev.c	2008-07-13 23:51:29.000000000 +0200
+++++ debian-2.6.26_lustre.1.8.2/fs/block_dev.c	2010-02-17 14:19:50.000000000 +0100
++@@ -1125,6 +1125,7 @@
++ 		if (bdev != bdev->bd_contains)
++ 			victim = bdev->bd_contains;
++ 		bdev->bd_contains = NULL;
+++		dev_clear_rdonly(bdev);
++ 	}
++ 	unlock_kernel();
++ 	mutex_unlock(&bdev->bd_mutex);
++diff -u -r debian-2.6.26/fs/dcache.c debian-2.6.26_lustre.1.8.2/fs/dcache.c
++--- debian-2.6.26/fs/dcache.c	2009-12-26 09:14:56.000000000 +0100
+++++ debian-2.6.26_lustre.1.8.2/fs/dcache.c	2010-02-17 14:24:24.000000000 +0100
++@@ -250,6 +250,13 @@
++ 		spin_unlock(&dcache_lock);
++ 		return 0;
++ 	}
+++
+++        /* network invalidation by Lustre */
+++        if (dentry->d_flags & DCACHE_LUSTRE_INVALID) {
+++                spin_unlock(&dcache_lock);
+++                return 0;
+++        }
+++
++ 	/*
++ 	 * Check whether to do a partial shrink_dcache
++ 	 * to get rid of unused child entries.
++@@ -1427,14 +1434,23 @@
++  *
++  * Adds a dentry to the hash according to its name.
++  */
++- 
+++
+++void d_rehash_cond(struct dentry * entry, int lock)
+++{
+++        if (lock)
+++                spin_lock(&dcache_lock);
+++        spin_lock(&entry->d_lock);
+++        _d_rehash(entry);
+++        spin_unlock(&entry->d_lock);
+++        if (lock)
+++                spin_unlock(&dcache_lock);
+++}
+++
+++EXPORT_SYMBOL(d_rehash_cond);
+++
++ void d_rehash(struct dentry * entry)
++ {
++-	spin_lock(&dcache_lock);
++-	spin_lock(&entry->d_lock);
++-	_d_rehash(entry);
++-	spin_unlock(&entry->d_lock);
++-	spin_unlock(&dcache_lock);
+++	d_rehash_cond(entry, 1);
++ }
++ 
++ #define do_switch(x,y) do { \
++@@ -1510,7 +1526,7 @@
++  * Update the dcache to reflect the move of a file name. Negative
++  * dcache entries should not be moved in this way.
++  */
++-static void d_move_locked(struct dentry * dentry, struct dentry * target)
+++void d_move_locked(struct dentry * dentry, struct dentry * target)
++ {
++ 	struct hlist_head *list;
++ 
++@@ -1568,6 +1584,7 @@
++ 	spin_unlock(&dentry->d_lock);
++ 	write_sequnlock(&rename_lock);
++ }
+++EXPORT_SYMBOL(d_move_locked);
++ 
++ /**
++  * d_move - move a dentry
++@@ -2051,6 +2068,7 @@
++ 
++ 	return result;
++ }
+++EXPORT_SYMBOL(is_subdir);
++ 
++ void d_genocide(struct dentry *root)
++ {
++diff -u -r debian-2.6.26/fs/filesystems.c debian-2.6.26_lustre.1.8.2/fs/filesystems.c
++--- debian-2.6.26/fs/filesystems.c	2009-12-26 09:14:56.000000000 +0100
+++++ debian-2.6.26_lustre.1.8.2/fs/filesystems.c	2010-02-17 14:26:59.000000000 +0100
++@@ -28,7 +28,9 @@
++  */
++ 
++ static struct file_system_type *file_systems;
++-static DEFINE_RWLOCK(file_systems_lock);
+++DEFINE_RWLOCK(file_systems_lock);
+++
+++EXPORT_SYMBOL(file_systems_lock);
++ 
++ /* WARNING: This can be used only if we _already_ own a reference */
++ void get_filesystem(struct file_system_type *fs)
++diff -u -r debian-2.6.26/fs/inode.c debian-2.6.26_lustre.1.8.2/fs/inode.c
++--- debian-2.6.26/fs/inode.c	2008-07-13 23:51:29.000000000 +0200
+++++ debian-2.6.26_lustre.1.8.2/fs/inode.c	2010-02-17 14:27:51.000000000 +0100
++@@ -409,7 +409,9 @@
++ 	int nr_scanned;
++ 	unsigned long reap = 0;
++ 
++-	mutex_lock(&iprune_mutex);
+++	if (!mutex_trylock(&iprune_mutex))
+++		return;
+++
++ 	spin_lock(&inode_lock);
++ 	for (nr_scanned = 0; nr_scanned < nr_to_scan; nr_scanned++) {
++ 		struct inode *inode;
++diff -u -r debian-2.6.26/fs/jbd2/checkpoint.c debian-2.6.26_lustre.1.8.2/fs/jbd2/checkpoint.c
++--- debian-2.6.26/fs/jbd2/checkpoint.c	2008-07-13 23:51:29.000000000 +0200
+++++ debian-2.6.26_lustre.1.8.2/fs/jbd2/checkpoint.c	2010-02-17 14:28:49.000000000 +0100
++@@ -696,6 +696,7 @@
++ 	J_ASSERT(transaction->t_checkpoint_list == NULL);
++ 	J_ASSERT(transaction->t_checkpoint_io_list == NULL);
++ 	J_ASSERT(transaction->t_updates == 0);
+++	J_ASSERT(list_empty(&transaction->t_jcb));
++ 	J_ASSERT(journal->j_committing_transaction != transaction);
++ 	J_ASSERT(journal->j_running_transaction != transaction);
++ 
++diff -u -r debian-2.6.26/fs/jbd2/commit.c debian-2.6.26_lustre.1.8.2/fs/jbd2/commit.c
++--- debian-2.6.26/fs/jbd2/commit.c	2008-07-13 23:51:29.000000000 +0200
+++++ debian-2.6.26_lustre.1.8.2/fs/jbd2/commit.c	2010-02-17 14:29:44.000000000 +0100
++@@ -874,6 +874,30 @@
++            transaction can be removed from any checkpoint list it was on
++            before. */
++ 
+++        /*
+++         * Call any callbacks that had been registered for handles in this
+++         * transaction.  It is up to the callback to free any allocated
+++         * memory.
+++         *
+++         * The spinlocking (t_jcb_lock) here is surely unnecessary...
+++         */
+++        spin_lock(&commit_transaction->t_jcb_lock);
+++        if (!list_empty(&commit_transaction->t_jcb)) {
+++                struct list_head *p, *n;
+++                int error = is_journal_aborted(journal);
+++
+++                list_for_each_safe(p, n, &commit_transaction->t_jcb) {
+++                        struct journal_callback *jcb;
+++
+++                        jcb = list_entry(p, struct journal_callback, jcb_list);
+++                        list_del(p);
+++                        spin_unlock(&commit_transaction->t_jcb_lock);
+++                        jcb->jcb_func(jcb, error);
+++                        spin_lock(&commit_transaction->t_jcb_lock);
+++                }
+++        }
+++        spin_unlock(&commit_transaction->t_jcb_lock);
+++
++ 	jbd_debug(3, "JBD: commit phase 7\n");
++ 
++ 	J_ASSERT(commit_transaction->t_sync_datalist == NULL);
++diff -u -r debian-2.6.26/fs/jbd2/journal.c debian-2.6.26_lustre.1.8.2/fs/jbd2/journal.c
++--- debian-2.6.26/fs/jbd2/journal.c	2008-07-13 23:51:29.000000000 +0200
+++++ debian-2.6.26_lustre.1.8.2/fs/jbd2/journal.c	2010-02-17 14:38:15.000000000 +0100
++@@ -82,6 +82,8 @@
++ EXPORT_SYMBOL(jbd2_journal_invalidatepage);
++ EXPORT_SYMBOL(jbd2_journal_try_to_free_buffers);
++ EXPORT_SYMBOL(jbd2_journal_force_commit);
+++EXPORT_SYMBOL(jbd2_journal_callback_set);
+++EXPORT_SYMBOL(jbd2_journal_bmap);
++ 
++ static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
++ static void __journal_abort_soft (journal_t *journal, int errno);
++@@ -460,6 +462,7 @@
++ 	spin_unlock(&journal->j_state_lock);
++ 	return ret;
++ }
+++EXPORT_SYMBOL(jbd2_log_start_commit);
++ 
++ /*
++  * Force and wait upon a commit if the calling process is not within
++diff -u -r debian-2.6.26/fs/jbd2/transaction.c debian-2.6.26_lustre.1.8.2/fs/jbd2/transaction.c
++--- debian-2.6.26/fs/jbd2/transaction.c	2008-07-13 23:51:29.000000000 +0200
+++++ debian-2.6.26_lustre.1.8.2/fs/jbd2/transaction.c	2010-02-17 14:42:20.000000000 +0100
++@@ -51,10 +51,12 @@
++ 	transaction->t_state = T_RUNNING;
++ 	transaction->t_tid = journal->j_transaction_sequence++;
++ 	transaction->t_expires = jiffies + journal->j_commit_interval;
+++	INIT_LIST_HEAD(&transaction->t_jcb);
++ 	spin_lock_init(&transaction->t_handle_lock);
+++	spin_lock_init(&transaction->t_jcb_lock);
++ 
++ 	/* Set up the commit timer for the new transaction. */
++-	journal->j_commit_timer.expires = round_jiffies(transaction->t_expires);
+++	journal->j_commit_timer.expires = transaction->t_expires;
++ 	add_timer(&journal->j_commit_timer);
++ 
++ 	J_ASSERT(journal->j_running_transaction == NULL);
++@@ -252,6 +254,7 @@
++ 	memset(handle, 0, sizeof(*handle));
++ 	handle->h_buffer_credits = nblocks;
++ 	handle->h_ref = 1;
+++	INIT_LIST_HEAD(&handle->h_jcb);
++ 
++ 	lockdep_init_map(&handle->h_lockdep_map, "jbd2_handle",
++ 						&jbd2_handle_key, 0);
++@@ -1350,6 +1353,36 @@
++ }
++ 
++ /**
+++ * void jbd2_journal_callback_set() -  Register a callback function for this handle.
+++ * @handle: handle to attach the callback to.
+++ * @func: function to callback.
+++ * @jcb:  structure with additional information required by func() , and
+++ *      some space for jbd2 internal information.
+++ *
+++ * The function will be
+++ * called when the transaction that this handle is part of has been
+++ * committed to disk with the original callback data struct and the
+++ * error status of the journal as parameters.  There is no guarantee of
+++ * ordering between handles within a single transaction, nor between
+++ * callbacks registered on the same handle.
+++ *
+++ * The caller is responsible for allocating the journal_callback struct.
+++ * This is to allow the caller to add as much extra data to the callback
+++ * as needed, but reduce the overhead of multiple allocations.  The caller
+++ * allocated struct must start with a struct journal_callback at offset 0,
+++ * and has the caller-specific data afterwards.
+++ */
+++void jbd2_journal_callback_set(handle_t *handle,
+++                      void (*func)(struct journal_callback *jcb, int error),
+++                      struct journal_callback *jcb)
+++{
+++        spin_lock(&handle->h_transaction->t_jcb_lock);
+++        list_add_tail(&jcb->jcb_list, &handle->h_jcb);
+++        spin_unlock(&handle->h_transaction->t_jcb_lock);
+++        jcb->jcb_func = func;
+++}
+++
+++/**
++  * int jbd2_journal_stop() - complete a transaction
++  * @handle: tranaction to complete.
++  *
++@@ -1423,6 +1456,11 @@
++ 			wake_up(&journal->j_wait_transaction_locked);
++ 	}
++ 
+++        /* Move callbacks from the handle to the transaction. */
+++        spin_lock(&transaction->t_jcb_lock);
+++        list_splice(&handle->h_jcb, &transaction->t_jcb);
+++        spin_unlock(&transaction->t_jcb_lock);
+++
++ 	/*
++ 	 * If the handle is marked SYNC, we need to set another commit
++ 	 * going!  We also want to force a commit if the current
++diff -u -r debian-2.6.26/fs/namespace.c debian-2.6.26_lustre.1.8.2/fs/namespace.c
++--- debian-2.6.26/fs/namespace.c	2009-12-26 09:14:56.000000000 +0100
+++++ debian-2.6.26_lustre.1.8.2/fs/namespace.c	2010-02-17 14:43:07.000000000 +0100
++@@ -1660,6 +1660,7 @@
++ 
++ 	return do_add_mount(mnt, nd, mnt_flags, NULL);
++ }
+++EXPORT_SYMBOL(set_fs_pwd);
++ 
++ /*
++  * add a mount into a namespace's mount tree
++diff -u -r debian-2.6.26/include/linux/blkdev.h debian-2.6.26_lustre.1.8.2/include/linux/blkdev.h
++--- debian-2.6.26/include/linux/blkdev.h	2009-12-26 09:14:55.000000000 +0100
+++++ debian-2.6.26_lustre.1.8.2/include/linux/blkdev.h	2010-02-18 07:44:31.000000000 +0100
++@@ -806,7 +806,7 @@
++ #define MAX_PHYS_SEGMENTS 128
++ #define MAX_HW_SEGMENTS 128
++ #define SAFE_MAX_SECTORS 255
++-#define BLK_DEF_MAX_SECTORS 1024
+++#define BLK_DEF_MAX_SECTORS 2048
++ 
++ #define MAX_SEGMENT_SIZE	65536
++ 
++diff -u -r debian-2.6.26/include/linux/dcache.h debian-2.6.26_lustre.1.8.2/include/linux/dcache.h
++--- debian-2.6.26/include/linux/dcache.h	2008-07-13 23:51:29.000000000 +0200
+++++ debian-2.6.26_lustre.1.8.2/include/linux/dcache.h	2010-02-18 07:46:08.000000000 +0100
++@@ -173,6 +173,7 @@
++ 
++ #define DCACHE_REFERENCED	0x0008  /* Recently used, don't discard. */
++ #define DCACHE_UNHASHED		0x0010	
+++#define DCACHE_LUSTRE_INVALID   0x0040  /* Lustre invalidated */
++ 
++ #define DCACHE_INOTIFY_PARENT_WATCHED	0x0020 /* Parent inode is watched */
++ 
++@@ -250,6 +251,7 @@
++  * This adds the entry to the hash queues.
++  */
++ extern void d_rehash(struct dentry *);
+++extern void d_rehash_cond(struct dentry *, int lock);
++ 
++ /**
++  * d_add - add dentry to hash queues
++@@ -285,6 +287,7 @@
++ 
++ /* used for rename() and baskets */
++ extern void d_move(struct dentry *, struct dentry *);
+++extern void d_move_locked(struct dentry *, struct dentry *);
++ 
++ /* appendix may either be NULL or be used for transname suffixes */
++ extern struct dentry * d_lookup(struct dentry *, struct qstr *);
++diff -u -r debian-2.6.26/include/linux/fs.h debian-2.6.26_lustre.1.8.2/include/linux/fs.h
++--- debian-2.6.26/include/linux/fs.h	2008-07-13 23:51:29.000000000 +0200
+++++ debian-2.6.26_lustre.1.8.2/include/linux/fs.h	2010-02-18 07:57:56.000000000 +0100
++@@ -1832,6 +1832,10 @@
++ extern void submit_bio(int, struct bio *);
++ extern int bdev_read_only(struct block_device *);
++ #endif
+++#define HAVE_CLEAR_RDONLY_ON_PUT
+++extern void dev_set_rdonly(struct block_device *bdev);
+++extern int dev_check_rdonly(struct block_device *bdev);
+++extern void dev_clear_rdonly(struct block_device *bdev);
++ extern int set_blocksize(struct block_device *, int);
++ extern int sb_set_blocksize(struct super_block *, int);
++ extern int sb_min_blocksize(struct super_block *, int);
++@@ -1930,6 +1934,7 @@
++ 
++ extern const struct file_operations generic_ro_fops;
++ 
+++extern rwlock_t file_systems_lock;
++ #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
++ 
++ extern int vfs_readlink(struct dentry *, char __user *, int, const char *);
++diff -u -r debian-2.6.26/include/linux/jbd2.h debian-2.6.26_lustre.1.8.2/include/linux/jbd2.h
++--- debian-2.6.26/include/linux/jbd2.h	2008-07-13 23:51:29.000000000 +0200
+++++ debian-2.6.26_lustre.1.8.2/include/linux/jbd2.h	2010-02-18 08:08:30.000000000 +0100
++@@ -379,6 +379,27 @@
++ 	bit_spin_unlock(BH_JournalHead, &bh->b_state);
++ }
++ 
+++#define HAVE_JOURNAL_CALLBACK_STATUS
+++/**
+++ *   struct journal_callback - Base structure for callback information.
+++ *   @jcb_list: list information for other callbacks attached to the same handle.
+++ *   @jcb_func: Function to call with this callback structure.
+++ *
+++ *   This struct is a 'seed' structure for a using with your own callback
+++ *   structs. If you are using callbacks you must allocate one of these
+++ *   or another struct of your own definition which has this struct
+++ *   as it's first element and pass it to journal_callback_set().
+++ *
+++ *   This is used internally by jbd2 to maintain callback information.
+++ *
+++ *   See journal_callback_set for more information.
+++ **/
+++struct journal_callback {
+++        struct list_head jcb_list;              /* t_jcb_lock */
+++        void (*jcb_func)(struct journal_callback *jcb, int error);
+++        /* user data goes here */
+++};
+++
++ struct jbd2_revoke_table_s;
++ 
++ /**
++@@ -387,6 +408,7 @@
++  * @h_transaction: Which compound transaction is this update a part of?
++  * @h_buffer_credits: Number of remaining buffers we are allowed to dirty.
++  * @h_ref: Reference count on this handle
+++ * @h_jcb: List of application registered callbacks for this handle.
++  * @h_err: Field for caller's use to track errors through large fs operations
++  * @h_sync: flag for sync-on-close
++  * @h_jdata: flag to force data journaling
++@@ -412,6 +434,13 @@
++ 	/* operations */
++ 	int			h_err;
++ 
+++        /*
+++         * List of application registered callbacks for this handle. The
+++         * function(s) will be called after the transaction that this handle is
+++         * part of has been committed to disk. [t_jcb_lock]
+++         */
+++        struct list_head        h_jcb;
+++
++ 	/* Flags [no locking] */
++ 	unsigned int	h_sync:		1;	/* sync-on-close */
++ 	unsigned int	h_jdata:	1;	/* force data journaling */
++@@ -467,6 +496,9 @@
++  *    j_state_lock
++  *    ->j_list_lock			(journal_unmap_buffer)
++  *
+++ *    t_handle_lock
+++ *    ->t_jcb_lock
+++ *
++  */
++ 
++ struct transaction_s
++@@ -613,6 +645,15 @@
++ 	 */
++ 	int t_handle_count;
++ 
+++        /*
+++         * Protects the callback list
+++         */
+++        spinlock_t              t_jcb_lock;
+++        /*
+++         * List of registered callback functions for this transaction.
+++         * Called when the transaction is committed. [t_jcb_lock]
+++         */
+++        struct list_head        t_jcb;
++ };
++ 
++ struct transaction_run_stats_s {
++@@ -1016,6 +1057,9 @@
++ extern int	 jbd2_journal_flush (journal_t *);
++ extern void	 jbd2_journal_lock_updates (journal_t *);
++ extern void	 jbd2_journal_unlock_updates (journal_t *);
+++extern void      jbd2_journal_callback_set(handle_t *handle,
+++                                      void (*fn)(struct journal_callback *,int),
+++                                      struct journal_callback *jcb);
++ 
++ extern journal_t * jbd2_journal_init_dev(struct block_device *bdev,
++ 				struct block_device *fs_dev,
++diff -u -r debian-2.6.26/include/linux/mm.h debian-2.6.26_lustre.1.8.2/include/linux/mm.h
++--- debian-2.6.26/include/linux/mm.h	2009-12-26 09:14:57.000000000 +0100
+++++ debian-2.6.26_lustre.1.8.2/include/linux/mm.h	2010-02-18 08:10:11.000000000 +0100
++@@ -564,6 +564,8 @@
++ {
++ 	return __va(page_to_pfn(page) << PAGE_SHIFT);
++ }
+++/* truncate.c */
+++extern void truncate_complete_page(struct address_space *mapping,struct page *);
++ 
++ #if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL)
++ #define HASHED_PAGE_VIRTUAL
++diff -u -r debian-2.6.26/include/scsi/sd.h debian-2.6.26_lustre.1.8.2/include/scsi/sd.h
++--- debian-2.6.26/include/scsi/sd.h	2008-07-13 23:51:29.000000000 +0200
+++++ debian-2.6.26_lustre.1.8.2/include/scsi/sd.h	2010-02-17 14:18:52.000000000 +0100
++@@ -31,6 +31,47 @@
++  */
++ #define SD_BUF_SIZE		512
++ 
+++#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
+++typedef struct {
+++        unsigned long long iostat_size;
+++        unsigned long long iostat_count;
+++} iostat_counter_t;
+++
+++#define IOSTAT_NCOUNTERS 16
+++typedef struct {
+++        iostat_counter_t        iostat_read_histogram[IOSTAT_NCOUNTERS];
+++        iostat_counter_t        iostat_write_histogram[IOSTAT_NCOUNTERS];
+++        struct timeval          iostat_timeval;
+++
+++        /* queue depth: how well the pipe is filled up */
+++        unsigned long long      iostat_queue_ticks[IOSTAT_NCOUNTERS];
+++        unsigned long long      iostat_queue_ticks_sum;
+++        unsigned long           iostat_queue_depth;
+++        unsigned long           iostat_queue_stamp;
+++
+++        /* seeks: how linear the traffic is */
+++        unsigned long long      iostat_next_sector;
+++        unsigned long long      iostat_seek_sectors;
+++        unsigned long long      iostat_seeks;
+++        unsigned long long      iostat_sectors;
+++        unsigned long long      iostat_reqs;
+++        unsigned long           iostat_read_reqs;
+++        unsigned long           iostat_write_reqs;
+++
+++        /* process time: how long it takes to process requests */
+++        unsigned long           iostat_rtime[IOSTAT_NCOUNTERS];
+++        unsigned long           iostat_wtime[IOSTAT_NCOUNTERS];
+++
+++        /* queue time: how long process spent in elevator's queue */
+++        unsigned long           iostat_rtime_in_queue[IOSTAT_NCOUNTERS];
+++        unsigned long           iostat_wtime_in_queue[IOSTAT_NCOUNTERS];
+++
+++        /* must be the last field, as it's used to know size to be memset'ed */
+++        spinlock_t              iostat_lock;
+++} ____cacheline_aligned_in_smp iostat_stats_t;
+++#endif
+++
+++
++ struct scsi_disk {
++ 	struct scsi_driver *driver;	/* always &sd_template */
++ 	struct scsi_device *device;
++@@ -45,6 +86,9 @@
++ 	unsigned	WCE : 1;	/* state of disk WCE bit */
++ 	unsigned	RCD : 1;	/* state of disk RCD bit, unused */
++ 	unsigned	DPOFUA : 1;	/* state of disk DPOFUA bit */
+++#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
+++        iostat_stats_t  *stats;         /* scsi disk statistics */
+++#endif
++ };
++ #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
++ 
++diff -u -r debian-2.6.26/kernel/sched.c debian-2.6.26_lustre.1.8.2/kernel/sched.c
++--- debian-2.6.26/kernel/sched.c	2009-12-26 09:14:56.000000000 +0100
+++++ debian-2.6.26_lustre.1.8.2/kernel/sched.c	2010-02-18 08:11:02.000000000 +0100
++@@ -5477,6 +5477,7 @@
++ 
++ 	show_stack(p, NULL);
++ }
+++EXPORT_SYMBOL(sched_show_task);
++ 
++ void show_state_filter(unsigned long state_filter)
++ {
++diff -u -r debian-2.6.26/mm/truncate.c debian-2.6.26_lustre.1.8.2/mm/truncate.c
++--- debian-2.6.26/mm/truncate.c	2008-07-13 23:51:29.000000000 +0200
+++++ debian-2.6.26_lustre.1.8.2/mm/truncate.c	2010-02-18 08:12:58.000000000 +0100
++@@ -92,7 +92,7 @@
++  * its lock, b) when a concurrent invalidate_mapping_pages got there first and
++  * c) when tmpfs swizzles a page between a tmpfs inode and swapper_space.
++  */
++-static void
+++void
++ truncate_complete_page(struct address_space *mapping, struct page *page)
++ {
++ 	if (page->mapping != mapping)
++@@ -108,6 +108,7 @@
++ 	ClearPageMappedToDisk(page);
++ 	page_cache_release(page);	/* pagecache ref */
++ }
+++EXPORT_SYMBOL_GPL(truncate_complete_page);
++ 
++ /*
++  * This is for invalidate_mapping_pages().  That function can be called at
++diff -u -r debian-2.6.26/security/security.c debian-2.6.26_lustre.1.8.2/security/security.c
++--- debian-2.6.26/security/security.c	2009-12-26 09:14:57.000000000 +0100
+++++ debian-2.6.26_lustre.1.8.2/security/security.c	2010-02-18 08:13:38.000000000 +0100
++@@ -406,6 +406,7 @@
++ 		return 0;
++ 	return security_ops->inode_unlink(dir, dentry);
++ }
+++EXPORT_SYMBOL(security_inode_unlink);
++ 
++ int security_inode_symlink(struct inode *dir, struct dentry *dentry,
++ 			    const char *old_name)
+--- /dev/null
++++ lustre-1.8.5+dfsg/lustre/kernel_patches/patches/md-mmp-unplug-dev-2.6.27-vanilla.patch
+@@ -0,0 +1,22 @@
++Index: linux-2.6.27.36/drivers/md/raid5.c
++===================================================================
++--- linux-2.6.27.36.orig/drivers/md/raid5.c	2009-10-05 17:19:01.000000000 +0200
+++++ linux-2.6.27.36/drivers/md/raid5.c	2009-10-08 15:06:10.000000000 +0200
++@@ -1726,6 +1726,8 @@
++ 		bi->bi_next = *bip;
++ 	*bip = bi;
++ 	bi->bi_phys_segments ++;
+++        if (bio_sync(bi) && !forwrite)
+++               clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags); /* force to read from disk. */
++ 	spin_unlock_irq(&conf->device_lock);
++ 	spin_unlock(&sh->lock);
++ 
++@@ -3478,6 +3480,8 @@
++ 
++ 		bio_endio(bi, 0);
++ 	}
+++	if (bio_sync(bi))
+++		raid5_unplug_device(q);
++ 	return 0;
++ }
++ 
+--- /dev/null
++++ lustre-1.8.5+dfsg/lustre/kernel_patches/patches/jbd2-jcberr-2.6.26-vanilla.patch
+@@ -0,0 +1,211 @@
++Index: linux-source-2.6.26/include/linux/jbd2.h
++===================================================================
++--- linux-source-2.6.26.orig/include/linux/jbd2.h	2008-07-13 23:51:29.000000000 +0200
+++++ linux-source-2.6.26/include/linux/jbd2.h	2009-10-09 13:42:21.000000000 +0200
++@@ -379,6 +379,27 @@
++ 	bit_spin_unlock(BH_JournalHead, &bh->b_state);
++ }
++ 
+++#define HAVE_JOURNAL_CALLBACK_STATUS
+++/**
+++ *   struct journal_callback - Base structure for callback information.
+++ *   @jcb_list: list information for other callbacks attached to the same handle.
+++ *   @jcb_func: Function to call with this callback structure.
+++ *
+++ *   This struct is a 'seed' structure for a using with your own callback
+++ *   structs. If you are using callbacks you must allocate one of these
+++ *   or another struct of your own definition which has this struct
+++ *   as it's first element and pass it to journal_callback_set().
+++ *
+++ *   This is used internally by jbd2 to maintain callback information.
+++ *
+++ *   See journal_callback_set for more information.
+++ **/
+++struct journal_callback {
+++	struct list_head jcb_list;		/* t_jcb_lock */
+++	void (*jcb_func)(struct journal_callback *jcb, int error);
+++	/* user data goes here */
+++};
+++
++ struct jbd2_revoke_table_s;
++ 
++ /**
++@@ -387,6 +408,7 @@
++  * @h_transaction: Which compound transaction is this update a part of?
++  * @h_buffer_credits: Number of remaining buffers we are allowed to dirty.
++  * @h_ref: Reference count on this handle
+++ * @h_jcb: List of application registered callbacks for this handle.
++  * @h_err: Field for caller's use to track errors through large fs operations
++  * @h_sync: flag for sync-on-close
++  * @h_jdata: flag to force data journaling
++@@ -412,6 +434,13 @@
++ 	/* operations */
++ 	int			h_err;
++ 
+++	/*
+++	 * List of application registered callbacks for this handle. The
+++	 * function(s) will be called after the transaction that this handle is
+++	 * part of has been committed to disk. [t_jcb_lock]
+++	 */
+++	struct list_head	h_jcb;
+++
++ 	/* Flags [no locking] */
++ 	unsigned int	h_sync:		1;	/* sync-on-close */
++ 	unsigned int	h_jdata:	1;	/* force data journaling */
++@@ -467,6 +496,8 @@
++  *    j_state_lock
++  *    ->j_list_lock			(journal_unmap_buffer)
++  *
+++ *    t_handle_lock
+++ *    ->t_jcb_lock
++  */
++ 
++ struct transaction_s
++@@ -613,6 +644,15 @@
++ 	 */
++ 	int t_handle_count;
++ 
+++	/*
+++	 * Protects the callback list
+++	 */
+++	spinlock_t		t_jcb_lock;
+++	/*
+++	 * List of registered callback functions for this transaction.
+++	 * Called when the transaction is committed. [t_jcb_lock]
+++	 */
+++	struct list_head	t_jcb;
++ };
++ 
++ struct transaction_run_stats_s {
++@@ -1016,6 +1056,9 @@
++ extern int	 jbd2_journal_flush (journal_t *);
++ extern void	 jbd2_journal_lock_updates (journal_t *);
++ extern void	 jbd2_journal_unlock_updates (journal_t *);
+++extern void	 jbd2_journal_callback_set(handle_t *handle,
+++                                      void (*fn)(struct journal_callback *,int),
+++                                      struct journal_callback *jcb);
++ 
++ extern journal_t * jbd2_journal_init_dev(struct block_device *bdev,
++ 				struct block_device *fs_dev,
++Index: linux-source-2.6.26/fs/jbd2/checkpoint.c
++===================================================================
++--- linux-source-2.6.26.orig/fs/jbd2/checkpoint.c	2008-07-13 23:51:29.000000000 +0200
+++++ linux-source-2.6.26/fs/jbd2/checkpoint.c	2009-10-09 13:42:21.000000000 +0200
++@@ -696,6 +696,7 @@
++ 	J_ASSERT(transaction->t_checkpoint_list == NULL);
++ 	J_ASSERT(transaction->t_checkpoint_io_list == NULL);
++ 	J_ASSERT(transaction->t_updates == 0);
+++	J_ASSERT(list_empty(&transaction->t_jcb));
++ 	J_ASSERT(journal->j_committing_transaction != transaction);
++ 	J_ASSERT(journal->j_running_transaction != transaction);
++ 
++Index: linux-source-2.6.26/fs/jbd2/commit.c
++===================================================================
++--- linux-source-2.6.26.orig/fs/jbd2/commit.c	2008-07-13 23:51:29.000000000 +0200
+++++ linux-source-2.6.26/fs/jbd2/commit.c	2009-10-09 13:42:21.000000000 +0200
++@@ -854,6 +854,30 @@
++ 		/* AKPM: bforget here */
++ 	}
++ 
+++	/*
+++	 * Call any callbacks that had been registered for handles in this
+++	 * transaction.  It is up to the callback to free any allocated
+++	 * memory.
+++	 *
+++	 * The spinlocking (t_jcb_lock) here is surely unnecessary...
+++	 */
+++	spin_lock(&commit_transaction->t_jcb_lock);
+++	if (!list_empty(&commit_transaction->t_jcb)) {
+++		struct list_head *p, *n;
+++		int error = is_journal_aborted(journal);
+++
+++		list_for_each_safe(p, n, &commit_transaction->t_jcb) {
+++			struct journal_callback *jcb;
+++
+++			jcb = list_entry(p, struct journal_callback, jcb_list);
+++			list_del(p);
+++			spin_unlock(&commit_transaction->t_jcb_lock);
+++			jcb->jcb_func(jcb, error);
+++			spin_lock(&commit_transaction->t_jcb_lock);
+++		}
+++	}
+++	spin_unlock(&commit_transaction->t_jcb_lock);
+++
++ 	jbd_debug(3, "JBD: commit phase 6\n");
++ 
++ 	if (!JBD2_HAS_INCOMPAT_FEATURE(journal,
++Index: linux-source-2.6.26/fs/jbd2/journal.c
++===================================================================
++--- linux-source-2.6.26.orig/fs/jbd2/journal.c	2009-10-09 13:39:04.000000000 +0200
+++++ linux-source-2.6.26/fs/jbd2/journal.c	2009-10-09 13:43:03.000000000 +0200
++@@ -82,6 +82,9 @@
++ EXPORT_SYMBOL(jbd2_journal_invalidatepage);
++ EXPORT_SYMBOL(jbd2_journal_try_to_free_buffers);
++ EXPORT_SYMBOL(jbd2_journal_force_commit);
+++EXPORT_SYMBOL(jbd2_journal_callback_set);
+++EXPORT_SYMBOL(jbd2_journal_bmap);
+++
++ 
++ static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
++ static void __journal_abort_soft (journal_t *journal, int errno);
++Index: linux-source-2.6.26/fs/jbd2/transaction.c
++===================================================================
++--- linux-source-2.6.26.orig/fs/jbd2/transaction.c	2008-07-13 23:51:29.000000000 +0200
+++++ linux-source-2.6.26/fs/jbd2/transaction.c	2009-10-09 13:42:21.000000000 +0200
++@@ -252,6 +252,7 @@
++ 	memset(handle, 0, sizeof(*handle));
++ 	handle->h_buffer_credits = nblocks;
++ 	handle->h_ref = 1;
+++	INIT_LIST_HEAD(&handle->h_jcb);
++ 
++ 	lockdep_init_map(&handle->h_lockdep_map, "jbd2_handle",
++ 						&jbd2_handle_key, 0);
++@@ -1350,6 +1351,36 @@
++ }
++ 
++ /**
+++ * void jbd2_journal_callback_set() -  Register a callback function for this handle.
+++ * @handle: handle to attach the callback to.
+++ * @func: function to callback.
+++ * @jcb:  structure with additional information required by func() , and
+++ *	some space for jbd2 internal information.
+++ *
+++ * The function will be
+++ * called when the transaction that this handle is part of has been
+++ * committed to disk with the original callback data struct and the
+++ * error status of the journal as parameters.  There is no guarantee of
+++ * ordering between handles within a single transaction, nor between
+++ * callbacks registered on the same handle.
+++ *
+++ * The caller is responsible for allocating the journal_callback struct.
+++ * This is to allow the caller to add as much extra data to the callback
+++ * as needed, but reduce the overhead of multiple allocations.  The caller
+++ * allocated struct must start with a struct journal_callback at offset 0,
+++ * and has the caller-specific data afterwards.
+++ */
+++void jbd2_journal_callback_set(handle_t *handle,
+++		      void (*func)(struct journal_callback *jcb, int error),
+++		      struct journal_callback *jcb)
+++{
+++	spin_lock(&handle->h_transaction->t_jcb_lock);
+++	list_add_tail(&jcb->jcb_list, &handle->h_jcb);
+++	spin_unlock(&handle->h_transaction->t_jcb_lock);
+++	jcb->jcb_func = func;
+++}
+++
+++/**
++  * int jbd2_journal_stop() - complete a transaction
++  * @handle: tranaction to complete.
++  *
++@@ -1423,6 +1454,11 @@
++ 			wake_up(&journal->j_wait_transaction_locked);
++ 	}
++ 
+++	/* Move callbacks from the handle to the transaction. */
+++	spin_lock(&transaction->t_jcb_lock);
+++	list_splice(&handle->h_jcb, &transaction->t_jcb);
+++	spin_unlock(&transaction->t_jcb_lock);
+++
++ 	/*
++ 	 * If the handle is marked SYNC, we need to set another commit
++ 	 * going!  We also want to force a commit if the current
diff --git a/debian/patches/no-darwin.patch b/debian/patches/no-darwin.patch
index 861ddf4..525d796 100644
--- a/debian/patches/no-darwin.patch
+++ b/debian/patches/no-darwin.patch
@@ -21,18 +21,6 @@ Index: lustre/lnet/include/libcfs/Makefile.am
  	portals_utils.h types.h user-lock.h user-prim.h user-time.h \
 Index: lustre/lnet/include/libcfs/Makefile.am.~1~
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ lustre/lnet/include/libcfs/Makefile.am.~1~	2010-12-07 17:00:08.541545001 +0100
-@@ -0,0 +1,9 @@
-+SUBDIRS := linux
-+if DARWIN
-+SUBDIRS += darwin
-+endif
-+DIST_SUBDIRS := linux darwin
-+
-+EXTRA_DIST := curproc.h kp30.h libcfs.h list.h lltrace.h \
-+	portals_utils.h types.h user-lock.h user-prim.h user-time.h \
-+	user-tcpip.h user-bitops.h bitmap.h
 Index: lustre/lnet/include/lnet/Makefile.am
 ===================================================================
 --- lustre.orig/lnet/include/lnet/Makefile.am	2010-12-07 16:54:32.933545003 +0100
@@ -54,20 +42,6 @@ Index: lustre/lnet/include/lnet/Makefile.am
  	lib-lnet.h lib-types.h lnet.h lnetctl.h types.h \
 Index: lustre/lnet/include/lnet/Makefile.am.~1~
 ===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ lustre/lnet/include/lnet/Makefile.am.~1~	2010-12-07 17:00:08.541545001 +0100
-@@ -0,0 +1,11 @@
-+lnetdir=$(includedir)/lnet
-+
-+SUBDIRS := linux
-+if DARWIN
-+SUBDIRS += darwin
-+endif
-+DIST_SUBDIRS := linux darwin
-+
-+EXTRA_DIST = api.h api-support.h \
-+	lib-lnet.h lib-types.h lnet.h lnetctl.h types.h \
-+        socklnd.h ptllnd.h ptllnd_wire.h lnetst.h lnet-sysctl.h
 Index: lustre/lnet/klnds/socklnd/autoMakefile.am
 ===================================================================
 --- lustre.orig/lnet/klnds/socklnd/autoMakefile.am	2010-12-07 16:54:32.969545003 +0100
diff --git a/debian/patches/series b/debian/patches/series
index 2a370bf..ee2b8e3 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -24,3 +24,4 @@ fix_dentry_conf_test.patch
 spelling_errors.patch
 cacheflush_remove_mark_rodata.patch
 615749_no_add_needed
+modified-debian-specific-stuff.patch
diff --git a/ldiskfs/kernel_patches/series/ldiskfs-2.6.18-debian.series b/ldiskfs/kernel_patches/series/ldiskfs-2.6.18-debian.series
deleted file mode 100644
index 871ee47..0000000
--- a/ldiskfs/kernel_patches/series/ldiskfs-2.6.18-debian.series
+++ /dev/null
@@ -1,20 +0,0 @@
-ext3-wantedi-2.6-rhel4.patch
-iopen-2.6-fc5.patch
-ext3-map_inode_page-2.6.18.patch
-export-ext3-2.6-rhel4.patch
-ext3-include-fixes-2.6-rhel4.patch
-ext3-extents-2.6.18-vanilla.patch
-ext3-mballoc3-core.patch
-ext3-mballoc3-2.6.18.patch
-ext3-nlinks-2.6.9.patch
-ext3-ialloc-2.6.patch
-ext3-remove-cond_resched-calls-2.6.12.patch
-ext3-filterdata-sles10.patch
-ext3-16tb-overflow-fixes.patch
-ext3-uninit-2.6.18.patch
-ext3-nanosecond-2.6.18-vanilla.patch
-ext3-inode-version-2.6.18-vanilla.patch
-ext3-ea-expand-lose-block.patch
-ext3-mmp-2.6.18-vanilla.patch
-ext3-fiemap-2.6.18-vanilla.patch
-ext3-lookup-dotdot-2.6.9.patch
diff --git a/lustre/kernel_patches/patches/debian-2.6.26.diff b/lustre/kernel_patches/patches/debian-2.6.26.diff
deleted file mode 100644
index a1f22df..0000000
--- a/lustre/kernel_patches/patches/debian-2.6.26.diff
+++ /dev/null
@@ -1,1210 +0,0 @@
-diff -u -r debian-2.6.26/Documentation/filesystems/ext2.txt debian-2.6.26_lustre.1.8.2/Documentation/filesystems/ext2.txt
---- debian-2.6.26/Documentation/filesystems/ext2.txt	2008-07-13 23:51:29.000000000 +0200
-+++ debian-2.6.26_lustre.1.8.2/Documentation/filesystems/ext2.txt	2010-02-12 15:11:19.000000000 +0100
-@@ -58,6 +58,22 @@
- 
- xip				Use execute in place (no caching) if possible
- 
-+iopen                          Makes an invisible pseudo-directory called 
-+                               __iopen__ available in the root directory
-+                               of the filesystem.  Allows open-by-inode-
-+                               number.  i.e., inode 3145 can be accessed
-+                               via /mntpt/__iopen__/3145
-+
-+iopen_nopriv                   This option makes the iopen directory be
-+                               world-readable.  This may be safer since it
-+                               allows daemons to run as an unprivileged user,
-+                               however it significantly changes the security
-+                               model of a Unix filesystem, since previously
-+                               all files under a mode 700 directory were not
-+                               generally avilable even if the
-+                               permissions on the file itself is
-+                               world-readable.
-+
- grpquota,noquota,quota,usrquota	Quota options are silently ignored by ext2.
- 
- 
-diff -u -r debian-2.6.26/block/blk-core.c debian-2.6.26_lustre.1.8.2/block/blk-core.c
---- debian-2.6.26/block/blk-core.c	2008-07-13 23:51:29.000000000 +0200
-+++ debian-2.6.26_lustre.1.8.2/block/blk-core.c	2010-02-12 15:14:32.000000000 +0100
-@@ -1270,6 +1270,8 @@
- 
- #endif /* CONFIG_FAIL_MAKE_REQUEST */
- 
-+int dev_check_rdonly(struct block_device *bdev);
-+
- /*
-  * Check whether this bio extends beyond the end of the device.
-  */
-@@ -1371,6 +1373,12 @@
- 
- 		if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
- 			goto end_io;
-+                /* this is cfs's dev_rdonly check */
-+                if (bio->bi_rw == WRITE &&
-+                                dev_check_rdonly(bio->bi_bdev)) {
-+                        bio_endio(bio, 0);
-+                        break;
-+                }
- 
- 		if (should_fail_request(bio))
- 			goto end_io;
-@@ -2028,6 +2036,91 @@
- }
- EXPORT_SYMBOL(kblockd_flush_work);
- 
-+ /*
-+ * Debug code for turning block devices "read-only" (will discard writes
-+ * silently).  This is for filesystem crash/recovery testing.
-+ */
-+struct deventry {
-+       dev_t dev;
-+       struct deventry *next;
-+};
-+
-+static struct deventry *devlist = NULL;
-+static spinlock_t devlock = SPIN_LOCK_UNLOCKED;
-+
-+int dev_check_rdonly(struct block_device *bdev)
-+{
-+       struct deventry *cur;
-+       if (!bdev) return 0;
-+       spin_lock(&devlock);
-+       cur = devlist;
-+       while(cur) {
-+               if (bdev->bd_dev == cur->dev) {
-+                       spin_unlock(&devlock);
-+                       return 1;
-+       }
-+               cur = cur->next;
-+       }
-+       spin_unlock(&devlock);
-+       return 0;
-+}
-+
-+void dev_set_rdonly(struct block_device *bdev)
-+{
-+       struct deventry *newdev, *cur;
-+
-+       if (!bdev)
-+               return;
-+       newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
-+       if (!newdev)
-+               return;
-+
-+       spin_lock(&devlock);
-+       cur = devlist;
-+       while(cur) {
-+               if (bdev->bd_dev == cur->dev) {
-+                       spin_unlock(&devlock);
-+                       kfree(newdev);
-+                       return;
-+               }
-+               cur = cur->next;
-+       }
-+       newdev->dev = bdev->bd_dev;
-+       newdev->next = devlist;
-+       devlist = newdev;
-+       spin_unlock(&devlock);
-+       printk(KERN_WARNING "Turning device %s (%#x) read-only\n",
-+              bdev->bd_disk ? bdev->bd_disk->disk_name : "", bdev->bd_dev);
-+}
-+
-+void dev_clear_rdonly(struct block_device *bdev)
-+{
-+       struct deventry *cur, *last = NULL;
-+       if (!bdev) return;
-+       spin_lock(&devlock);
-+       cur = devlist;
-+       while(cur) {
-+               if (bdev->bd_dev == cur->dev) {
-+                       if (last)
-+                               last->next = cur->next;
-+                       else
-+                               devlist = cur->next;
-+                       spin_unlock(&devlock);
-+                       kfree(cur);
-+                       printk(KERN_WARNING "Removing read-only on %s (%#x)\n",
-+                              bdev->bd_disk ? bdev->bd_disk->disk_name :
-+                                              "unknown block", bdev->bd_dev);
-+                       return;
-+               }
-+               last = cur;
-+               cur = cur->next;
-+       }
-+       spin_unlock(&devlock);
-+}
-+
-+EXPORT_SYMBOL(dev_set_rdonly);
-+EXPORT_SYMBOL(dev_clear_rdonly);
-+
- int __init blk_dev_init(void)
- {
- 	int i;
-diff -u -r debian-2.6.26/drivers/md/raid5.c debian-2.6.26_lustre.1.8.2/drivers/md/raid5.c
---- debian-2.6.26/drivers/md/raid5.c	2008-07-13 23:51:29.000000000 +0200
-+++ debian-2.6.26_lustre.1.8.2/drivers/md/raid5.c	2010-02-12 15:19:25.000000000 +0100
-@@ -1817,6 +1817,8 @@
- 		bi->bi_next = *bip;
- 	*bip = bi;
- 	bi->bi_phys_segments ++;
-+        if (bio_sync(bi) && !forwrite)
-+                clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags); /* force to read from disk. */
- 	spin_unlock_irq(&conf->device_lock);
- 	spin_unlock(&sh->lock);
- 
-@@ -3699,6 +3701,8 @@
- 			      test_bit(BIO_UPTODATE, &bi->bi_flags)
- 			        ? 0 : -EIO);
- 	}
-+	if (bio_sync(bi))
-+		raid5_unplug_device(q);
- 	return 0;
- }
- 
-diff -u -r debian-2.6.26/drivers/scsi/Kconfig debian-2.6.26_lustre.1.8.2/drivers/scsi/Kconfig
---- debian-2.6.26/drivers/scsi/Kconfig	2009-12-26 09:14:53.000000000 +0100
-+++ debian-2.6.26_lustre.1.8.2/drivers/scsi/Kconfig	2010-02-12 15:20:02.000000000 +0100
-@@ -81,6 +81,14 @@
- 	  In this case, do not compile the driver for your SCSI host adapter
- 	  (below) as a module either.
- 
-+config SD_IOSTATS
-+   bool "Enable SCSI disk I/O stats"
-+   depends on BLK_DEV_SD
-+   default y
-+   ---help---
-+     This enables SCSI disk I/O stats collection.  You must also enable
-+     /proc file system support if you want this feature.
-+
- config CHR_DEV_ST
- 	tristate "SCSI tape support"
- 	depends on SCSI
-diff -u -r debian-2.6.26/drivers/scsi/scsi_proc.c debian-2.6.26_lustre.1.8.2/drivers/scsi/scsi_proc.c
---- debian-2.6.26/drivers/scsi/scsi_proc.c	2008-07-13 23:51:29.000000000 +0200
-+++ debian-2.6.26_lustre.1.8.2/drivers/scsi/scsi_proc.c	2010-02-12 15:22:05.000000000 +0100
-@@ -40,7 +40,8 @@
- /* 4K page size, but our output routines, use some slack for overruns */
- #define PROC_BLOCK_SIZE (3*1024)
- 
--static struct proc_dir_entry *proc_scsi;
-+struct proc_dir_entry *proc_scsi;
-+EXPORT_SYMBOL(proc_scsi);
- 
- /* Protect sht->present and sht->proc_dir */
- static DEFINE_MUTEX(global_host_template_mutex);
-diff -u -r debian-2.6.26/drivers/scsi/sd.c debian-2.6.26_lustre.1.8.2/drivers/scsi/sd.c
---- debian-2.6.26/drivers/scsi/sd.c	2008-07-13 23:51:29.000000000 +0200
-+++ debian-2.6.26_lustre.1.8.2/drivers/scsi/sd.c	2010-02-17 14:13:32.000000000 +0100
-@@ -107,6 +107,24 @@
-  * object after last put) */
- static DEFINE_MUTEX(sd_ref_mutex);
- 
-+#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
-+# include <linux/proc_fs.h>
-+# include <linux/seq_file.h>
-+struct proc_dir_entry *sd_iostats_procdir = NULL;
-+char sd_iostats_procdir_name[] = "sd_iostats";
-+static struct file_operations sd_iostats_proc_fops;
-+
-+extern void sd_iostats_init(void);
-+extern void sd_iostats_fini(void);
-+void sd_iostats_start_req(struct scsi_cmnd *SCpnt);
-+void sd_iostats_finish_req(struct scsi_cmnd *SCpnt);
-+#else
-+static inline void sd_iostats_init(void) {}
-+static inline void sd_iostats_fini(void) {}
-+static inline void sd_iostats_start_req(struct scsi_cmnd *SCpnt) {}
-+static inline void sd_iostats_finish_req(struct scsi_cmnd *SCpnt) {}
-+#endif
-+
- static const char *sd_cache_types[] = {
- 	"write through", "none", "write back",
- 	"write back, no read (daft)"
-@@ -531,6 +549,8 @@
- 	}
- 	SCpnt->sdb.length = this_count * sdp->sector_size;
- 
-+	sd_iostats_start_req(SCpnt);
-+
- 	/*
- 	 * We shouldn't disconnect in the middle of a sector, so with a dumb
- 	 * host adapter, it's safe to assume that we can at least transfer
-@@ -667,7 +687,7 @@
- 	int diskinfo[4];
- 
- 	/* default to most commonly used values */
--        diskinfo[0] = 0x40;	/* 1 << 6 */
-+	diskinfo[0] = 0x40;	/* 1 << 6 */
-        	diskinfo[1] = 0x20;	/* 1 << 5 */
-        	diskinfo[2] = sdkp->capacity >> 11;
- 	
-@@ -1023,6 +1043,7 @@
- 		break;
- 	}
-  out:
-+	sd_iostats_finish_req(SCpnt);
- 	return good_bytes;
- }
- 
-@@ -1711,6 +1732,36 @@
- 	gd->flags = GENHD_FL_DRIVERFS;
- 	if (sdp->removable)
- 		gd->flags |= GENHD_FL_REMOVABLE;
-+#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
-+       sdkp->stats = kzalloc(sizeof(iostat_stats_t), GFP_KERNEL);
-+       if (!sdkp->stats) {
-+	       printk(KERN_WARNING "cannot allocate iostat structure for"
-+	                           "%s\n", gd->disk_name);
-+       } else {
-+	       do_gettimeofday(&sdkp->stats->iostat_timeval);
-+	       sdkp->stats->iostat_queue_stamp = jiffies;
-+	       spin_lock_init(&sdkp->stats->iostat_lock);
-+	       if (sd_iostats_procdir) {
-+	               struct proc_dir_entry *pde;
-+	               pde = create_proc_entry(gd->disk_name, S_IRUGO | S_IWUSR,
-+	                                       sd_iostats_procdir);
-+	               if (!pde) {
-+	                       printk(KERN_WARNING "Can't create /proc/scsi/"
-+	                                           "%s/%s\n",
-+	                                           sd_iostats_procdir_name,
-+	                                           gd->disk_name);
-+	                       kfree(sdkp->stats);
-+	                       sdkp->stats = NULL;
-+	               } else {
-+	                       pde->proc_fops = &sd_iostats_proc_fops;
-+	                       pde->data = gd;
-+	               }
-+	       } else {
-+	               kfree(sdkp->stats);
-+	               sdkp->stats = NULL;
-+	       }
-+       }
-+#endif
- 
- 	dev_set_drvdata(dev, sdkp);
- 	add_disk(gd);
-@@ -1755,6 +1806,366 @@
- 	return 0;
- }
- 
-+#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
-+static int
-+ sd_iostats_seq_show(struct seq_file *seq, void *v)
-+ {
-+	struct timeval     now;
-+	struct gendisk *disk = seq->private;
-+	iostat_stats_t    *stats;
-+	unsigned long long read_len;
-+	unsigned long long read_len_tot;
-+	unsigned long      read_num;
-+	unsigned long      read_num_tot;
-+	unsigned long long write_len;
-+	unsigned long long write_len_tot;
-+	unsigned long      write_num;
-+	unsigned long      write_num_tot;
-+	int                i;
-+	int                maxi;
-+ 
-+	stats = scsi_disk(disk)->stats;
-+	if (stats == NULL) {
-+	        printk(KERN_ERR "sd_iostats_seq_show: NULL stats entry\n");
-+	        BUG();
-+	}
-+ 
-+	do_gettimeofday(&now);
-+	now.tv_sec -= stats->iostat_timeval.tv_sec;
-+	now.tv_usec -= stats->iostat_timeval.tv_usec;
-+	if (now.tv_usec < 0) {
-+	        now.tv_usec += 1000000;
-+	        now.tv_sec--;
-+	}
-+ 
-+	/* this sampling races with updates */
-+	seq_printf(seq, "index:        %lu   snapshot_time:         %lu.%06lu\n",
-+	                (unsigned long) scsi_disk(disk)->index,
-+	                now.tv_sec, now.tv_usec);
-+ 
-+	for (i = IOSTAT_NCOUNTERS - 1; i > 0; i--)
-+	        if (stats->iostat_read_histogram[i].iostat_count != 0 ||
-+	                        stats->iostat_write_histogram[i].iostat_count != 0)
-+	                break;
-+	maxi = i;
-+ 
-+	seq_printf(seq, "%8s %8s %12s %8s %12s\n", "size", 
-+	                "reads", "total", "writes", "total");
-+ 
-+	read_len_tot = write_len_tot = 0;
-+	read_num_tot = write_num_tot = 0;
-+	for (i = 0; i <= maxi; i++) {
-+	        read_len = stats->iostat_read_histogram[i].iostat_size;
-+	        read_len_tot += read_len;
-+	        read_num = stats->iostat_read_histogram[i].iostat_count;
-+	        read_num_tot += read_num;
-+ 
-+	        write_len = stats->iostat_write_histogram[i].iostat_size;
-+	        write_len_tot += write_len;
-+	        write_num = stats->iostat_write_histogram[i].iostat_count;
-+	        write_num_tot += write_num;
-+ 
-+	        seq_printf (seq, "%8d %8lu %12llu %8lu %12llu\n", 
-+	                        512<<i, read_num, read_len, write_num, write_len);
-+	}
-+ 
-+	seq_printf(seq, "%8s %8lu %12llu %8lu %12llu\n\n", "total",
-+	                read_num_tot, read_len_tot, 
-+	                write_num_tot, write_len_tot);
-+ 
-+	seq_printf(seq, "%8s %8s %8s\n", "qdepth", "ticks", "%");
-+	for (i = 0; i < IOSTAT_NCOUNTERS; i++) {
-+	        unsigned long long ticks, percent;
-+	        ticks = stats->iostat_queue_ticks[i];
-+	        if (ticks == 0)
-+	                continue;
-+	        percent = stats->iostat_queue_ticks[i] * 100;
-+	        do_div(percent, stats->iostat_queue_ticks_sum);
-+	        seq_printf(seq, "%8d %8llu %8llu\n", i, ticks, percent);
-+	}
-+ 
-+	if (stats->iostat_reqs != 0) {
-+	        unsigned long long aveseek = 0, percent = 0;
-+ 
-+	        if (stats->iostat_seeks) {
-+	                aveseek = stats->iostat_seek_sectors;
-+	                do_div(aveseek, stats->iostat_seeks);
-+	                percent = stats->iostat_seeks * 100;
-+	                do_div(percent, stats->iostat_reqs);
-+	        }
-+ 
-+	        seq_printf(seq, "\n%llu sectors in %llu reqs: %llu seek(s) over "
-+	                        "%llu sectors in ave, %llu%% of all reqs\n",
-+	                        stats->iostat_sectors, stats->iostat_reqs,
-+	                        stats->iostat_seeks, aveseek, percent);
-+	}
-+ 
-+	seq_printf(seq, "\n%16s %8s %8s %8s %8s\n", "process time", "reads",
-+	                "%%", "writes", "%%");
-+	for (i = 0; i < IOSTAT_NCOUNTERS; i++) {
-+	        unsigned long read_percent = 0, write_percent = 0;
-+	        if (stats->iostat_wtime[i] == 0 &&
-+	                        stats->iostat_rtime[i] == 0)
-+	                continue;
-+	        if (stats->iostat_read_reqs)
-+	                read_percent = stats->iostat_rtime[i] * 100 / 
-+	                        stats->iostat_read_reqs;
-+	        if (stats->iostat_write_reqs)
-+	                write_percent = stats->iostat_wtime[i] * 100 / 
-+	                        stats->iostat_write_reqs;
-+	        seq_printf(seq, "%16u %8lu %8lu %8lu %8lu\n",
-+	                        jiffies_to_msecs(((1UL << i) >> 1) << 1),
-+	                        stats->iostat_rtime[i], read_percent,
-+	                        stats->iostat_wtime[i], write_percent);
-+	}
-+ 
-+	seq_printf(seq, "\n%16s %8s %8s %8s %8s\n", "time in queue", "reads",
-+	                "%%", "writes", "%%");
-+	for (i = 0; i < IOSTAT_NCOUNTERS; i++) {
-+	        unsigned long read_percent = 0, write_percent = 0;
-+	        if (stats->iostat_wtime_in_queue[i] == 0 &&
-+	                        stats->iostat_rtime_in_queue[i] == 0)
-+	                continue;
-+	        if (stats->iostat_read_reqs)
-+	                read_percent = stats->iostat_rtime_in_queue[i] * 100 / 
-+	                        stats->iostat_read_reqs;
-+	        if (stats->iostat_write_reqs)
-+	                write_percent = stats->iostat_wtime_in_queue[i] * 100 / 
-+	                        stats->iostat_write_reqs;
-+	        seq_printf(seq, "%16u %8lu %8lu %8lu %8lu\n",
-+	                        jiffies_to_msecs(((1UL << i) >> 1) << 1),
-+	                        stats->iostat_rtime_in_queue[i],
-+	                        read_percent,
-+	                        stats->iostat_wtime_in_queue[i],
-+	                        write_percent);
-+	}
-+ 
-+	return 0;
-+ }
-+ 
-+ static void *
-+ sd_iostats_seq_start(struct seq_file *p, loff_t *pos)
-+ {
-+	return (*pos == 0) ? (void *)1 : NULL;
-+ }
-+ 
-+ static void *
-+ sd_iostats_seq_next(struct seq_file *p, void *v, loff_t *pos)
-+ {
-+	++*pos;
-+	return NULL;
-+ }
-+ 
-+ static void
-+ sd_iostats_seq_stop(struct seq_file *p, void *v)
-+ {
-+ }
-+ 
-+ static struct seq_operations sd_iostats_seqops = {
-+	.start = sd_iostats_seq_start,
-+	.stop  = sd_iostats_seq_stop,
-+	.next  = sd_iostats_seq_next,
-+	.show  = sd_iostats_seq_show,
-+ };
-+ 
-+ static int
-+ sd_iostats_seq_open (struct inode *inode, struct file *file)
-+ {
-+	int rc;
-+ 
-+	rc = seq_open(file, &sd_iostats_seqops);
-+	if (rc != 0)
-+	        return rc;
-+ 
-+	((struct seq_file *)file->private_data)->private = PDE(inode)->data;
-+	return 0;
-+ }
-+ 
-+ static ssize_t
-+ sd_iostats_seq_write(struct file *file, const char *buffer,
-+	             size_t len, loff_t *off)
-+ {
-+	struct seq_file   *seq = file->private_data;
-+	struct gendisk *disk = seq->private;
-+	iostat_stats_t    *stats = scsi_disk(disk)->stats;
-+	unsigned long      flags;
-+	unsigned long      qdepth;
-+ 
-+ 
-+	spin_lock_irqsave (&stats->iostat_lock, flags);
-+	qdepth = stats->iostat_queue_depth;
-+	memset (stats, 0, offsetof(iostat_stats_t, iostat_lock));
-+	do_gettimeofday(&stats->iostat_timeval);
-+	stats->iostat_queue_stamp = jiffies;
-+	stats->iostat_queue_depth = qdepth;
-+	spin_unlock_irqrestore (&stats->iostat_lock, flags);
-+ 
-+	return len;
-+ }
-+ 
-+ static struct file_operations sd_iostats_proc_fops = {
-+	.owner   = THIS_MODULE,
-+	.open    = sd_iostats_seq_open,
-+	.read    = seq_read,
-+	.write   = sd_iostats_seq_write,
-+	.llseek  = seq_lseek,
-+	.release = seq_release,
-+ };
-+ 
-+ extern struct proc_dir_entry *proc_scsi;
-+ 
-+ void
-+ sd_iostats_init(void)
-+ {
-+	if (proc_scsi == NULL) {
-+	        printk(KERN_WARNING "No access to sd iostats: "
-+	                "proc_scsi is NULL\n");
-+	        return;
-+	}
-+ 
-+	sd_iostats_procdir = create_proc_entry(sd_iostats_procdir_name,
-+	                                       S_IFDIR | S_IRUGO | S_IXUGO,
-+	                                        proc_scsi);
-+	if (sd_iostats_procdir == NULL) {
-+	        printk(KERN_WARNING "No access to sd iostats: "
-+	                "can't create /proc/scsi/%s\n", sd_iostats_procdir_name);
-+	        return;
-+	}
-+ }
-+ 
-+ void sd_iostats_fini(void)
-+ {
-+	if (proc_scsi != NULL && sd_iostats_procdir != NULL)
-+	        remove_proc_entry(sd_iostats_procdir_name, proc_scsi);
-+ 
-+	sd_iostats_procdir = NULL;
-+ }
-+ 
-+ void sd_iostats_finish_req(struct scsi_cmnd *SCpnt)
-+ {
-+	struct request          *rq = SCpnt->request;
-+	iostat_stats_t          *stats;
-+	unsigned long           *tcounter;
-+	int                     tbucket;
-+	int                     tmp;
-+	unsigned long           irqflags;
-+	unsigned long           i;
-+ 
-+	stats = scsi_disk(rq->rq_disk)->stats;
-+	if (stats == NULL)
-+	        return;
-+ 
-+	tmp = jiffies - rq->start_time;
-+	for (tbucket = 0; tmp > 1; tbucket++)
-+	        tmp >>= 1;
-+	if (tbucket >= IOSTAT_NCOUNTERS)
-+	        tbucket = IOSTAT_NCOUNTERS - 1;
-+	//printk("%u ticks in D to %u\n", jiffies - rq->start_time, tbucket);
-+ 
-+	tcounter = rq_data_dir(rq) == WRITE ?
-+	        &stats->iostat_wtime[tbucket] : &stats->iostat_rtime[tbucket];
-+ 
-+	spin_lock_irqsave(&stats->iostat_lock, irqflags);
-+ 
-+	/* update delay stats */
-+	(*tcounter)++;
-+ 
-+	/* update queue depth stats */
-+	i = stats->iostat_queue_depth;
-+	if (i >= IOSTAT_NCOUNTERS)
-+	        i = IOSTAT_NCOUNTERS - 1;
-+	stats->iostat_queue_ticks[i] += jiffies - stats->iostat_queue_stamp;
-+	stats->iostat_queue_ticks_sum += jiffies - stats->iostat_queue_stamp;
-+	BUG_ON(stats->iostat_queue_depth == 0);
-+	stats->iostat_queue_depth--;
-+ 
-+	/* update seek stats. XXX: not sure about nr_sectors */
-+	stats->iostat_sectors += rq->nr_sectors;
-+	stats->iostat_reqs++;
-+	if (rq->sector != stats->iostat_next_sector) {
-+	        stats->iostat_seek_sectors +=
-+	                rq->sector > stats->iostat_next_sector ?
-+	                rq->sector - stats->iostat_next_sector :
-+	                stats->iostat_next_sector - rq->sector;
-+	        stats->iostat_seeks++;
-+	}
-+	stats->iostat_next_sector = rq->sector + rq->nr_sectors;
-+ 
-+	stats->iostat_queue_stamp = jiffies;
-+ 
-+	spin_unlock_irqrestore(&stats->iostat_lock, irqflags);
-+ }
-+ 
-+ void sd_iostats_start_req(struct scsi_cmnd *SCpnt)
-+ {
-+	struct request          *rq = SCpnt->request;
-+	iostat_stats_t          *stats;
-+	iostat_counter_t        *counter;
-+	int                     bucket;
-+	int                     tbucket;
-+	int                     tmp;
-+	unsigned long           irqflags;
-+	unsigned long           i;
-+	int                     nsect;
-+ 
-+	stats = scsi_disk(rq->rq_disk)->stats;
-+	if (stats == NULL)
-+	        return;
-+ 
-+	nsect = scsi_bufflen(SCpnt) >> 9;
-+	for (bucket = 0, tmp = nsect; tmp > 1; bucket++)
-+	        tmp >>= 1;
-+ 
-+	if (bucket >= IOSTAT_NCOUNTERS) {
-+	        printk (KERN_ERR "sd_iostats_bump: nsect %d too big\n", nsect);
-+	        BUG();
-+	}
-+ 
-+	counter = rq_data_dir(rq) == WRITE ?
-+	        &stats->iostat_write_histogram[bucket] :
-+	        &stats->iostat_read_histogram[bucket];
-+ 
-+	tmp = jiffies - rq->start_time;
-+	for (tbucket = 0; tmp > 1; tbucket++)
-+	        tmp >>= 1;
-+	if (tbucket >= IOSTAT_NCOUNTERS)
-+	        tbucket = IOSTAT_NCOUNTERS - 1;
-+	//printk("%u ticks in Q to %u\n", jiffies - rq->start_time, tbucket);
-+ 
-+	/* an ugly hack to know exact processing time. the right
-+	 * solution is to add one more field to struct request
-+	 * hopefully it will break nothing ... */
-+	rq->start_time = jiffies;
-+ 
-+	spin_lock_irqsave(&stats->iostat_lock, irqflags);
-+ 
-+	/* update queue depth stats */
-+	i = stats->iostat_queue_depth;
-+	if (i >= IOSTAT_NCOUNTERS)
-+	        i = IOSTAT_NCOUNTERS - 1;
-+	stats->iostat_queue_ticks[i] += jiffies - stats->iostat_queue_stamp;
-+	stats->iostat_queue_ticks_sum += jiffies - stats->iostat_queue_stamp;
-+	stats->iostat_queue_depth++;
-+ 
-+	/* update delay stats */
-+	if (rq_data_dir(rq) == WRITE) {
-+	        stats->iostat_wtime_in_queue[tbucket]++;
-+	        stats->iostat_write_reqs++;
-+	} else {
-+	        stats->iostat_rtime_in_queue[tbucket]++;
-+	        stats->iostat_read_reqs++;
-+	}
-+ 
-+	/* update size stats */
-+	counter->iostat_size += nsect;
-+	counter->iostat_count++;
-+ 
-+	stats->iostat_queue_stamp = jiffies;
-+ 
-+	spin_unlock_irqrestore(&stats->iostat_lock, irqflags);
-+}
-+#endif
-+
- /**
-  *	scsi_disk_release - Called to free the scsi_disk structure
-  *	@dev: pointer to embedded class device
-@@ -1773,6 +2184,13 @@
- 	idr_remove(&sd_index_idr, sdkp->index);
- 	spin_unlock(&sd_index_lock);
- 
-+#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
-+        if (sdkp->stats) {
-+                remove_proc_entry(disk->disk_name, sd_iostats_procdir);
-+                kfree(sdkp->stats);
-+                sdkp->stats = NULL;
-+        }
-+#endif
- 	disk->private_data = NULL;
- 	put_disk(disk);
- 	put_device(&sdkp->device->sdev_gendev);
-@@ -1890,6 +2308,8 @@
- 	if (!majors)
- 		return -ENODEV;
- 
-+	sd_iostats_init();
-+
- 	err = class_register(&sd_disk_class);
- 	if (err)
- 		goto err_out;
-@@ -1905,6 +2325,7 @@
- err_out:
- 	for (i = 0; i < SD_MAJORS; i++)
- 		unregister_blkdev(sd_major(i), "sd");
-+	sd_iostats_fini();
- 	return err;
- }
- 
-diff -u -r debian-2.6.26/fs/block_dev.c debian-2.6.26_lustre.1.8.2/fs/block_dev.c
---- debian-2.6.26/fs/block_dev.c	2008-07-13 23:51:29.000000000 +0200
-+++ debian-2.6.26_lustre.1.8.2/fs/block_dev.c	2010-02-17 14:19:50.000000000 +0100
-@@ -1125,6 +1125,7 @@
- 		if (bdev != bdev->bd_contains)
- 			victim = bdev->bd_contains;
- 		bdev->bd_contains = NULL;
-+		dev_clear_rdonly(bdev);
- 	}
- 	unlock_kernel();
- 	mutex_unlock(&bdev->bd_mutex);
-diff -u -r debian-2.6.26/fs/dcache.c debian-2.6.26_lustre.1.8.2/fs/dcache.c
---- debian-2.6.26/fs/dcache.c	2009-12-26 09:14:56.000000000 +0100
-+++ debian-2.6.26_lustre.1.8.2/fs/dcache.c	2010-02-17 14:24:24.000000000 +0100
-@@ -250,6 +250,13 @@
- 		spin_unlock(&dcache_lock);
- 		return 0;
- 	}
-+
-+        /* network invalidation by Lustre */
-+        if (dentry->d_flags & DCACHE_LUSTRE_INVALID) {
-+                spin_unlock(&dcache_lock);
-+                return 0;
-+        }
-+
- 	/*
- 	 * Check whether to do a partial shrink_dcache
- 	 * to get rid of unused child entries.
-@@ -1427,14 +1434,23 @@
-  *
-  * Adds a dentry to the hash according to its name.
-  */
-- 
-+
-+void d_rehash_cond(struct dentry * entry, int lock)
-+{
-+        if (lock)
-+                spin_lock(&dcache_lock);
-+        spin_lock(&entry->d_lock);
-+        _d_rehash(entry);
-+        spin_unlock(&entry->d_lock);
-+        if (lock)
-+                spin_unlock(&dcache_lock);
-+}
-+
-+EXPORT_SYMBOL(d_rehash_cond);
-+
- void d_rehash(struct dentry * entry)
- {
--	spin_lock(&dcache_lock);
--	spin_lock(&entry->d_lock);
--	_d_rehash(entry);
--	spin_unlock(&entry->d_lock);
--	spin_unlock(&dcache_lock);
-+	d_rehash_cond(entry, 1);
- }
- 
- #define do_switch(x,y) do { \
-@@ -1510,7 +1526,7 @@
-  * Update the dcache to reflect the move of a file name. Negative
-  * dcache entries should not be moved in this way.
-  */
--static void d_move_locked(struct dentry * dentry, struct dentry * target)
-+void d_move_locked(struct dentry * dentry, struct dentry * target)
- {
- 	struct hlist_head *list;
- 
-@@ -1568,6 +1584,7 @@
- 	spin_unlock(&dentry->d_lock);
- 	write_sequnlock(&rename_lock);
- }
-+EXPORT_SYMBOL(d_move_locked);
- 
- /**
-  * d_move - move a dentry
-@@ -2051,6 +2068,7 @@
- 
- 	return result;
- }
-+EXPORT_SYMBOL(is_subdir);
- 
- void d_genocide(struct dentry *root)
- {
-diff -u -r debian-2.6.26/fs/filesystems.c debian-2.6.26_lustre.1.8.2/fs/filesystems.c
---- debian-2.6.26/fs/filesystems.c	2009-12-26 09:14:56.000000000 +0100
-+++ debian-2.6.26_lustre.1.8.2/fs/filesystems.c	2010-02-17 14:26:59.000000000 +0100
-@@ -28,7 +28,9 @@
-  */
- 
- static struct file_system_type *file_systems;
--static DEFINE_RWLOCK(file_systems_lock);
-+DEFINE_RWLOCK(file_systems_lock);
-+
-+EXPORT_SYMBOL(file_systems_lock);
- 
- /* WARNING: This can be used only if we _already_ own a reference */
- void get_filesystem(struct file_system_type *fs)
-diff -u -r debian-2.6.26/fs/inode.c debian-2.6.26_lustre.1.8.2/fs/inode.c
---- debian-2.6.26/fs/inode.c	2008-07-13 23:51:29.000000000 +0200
-+++ debian-2.6.26_lustre.1.8.2/fs/inode.c	2010-02-17 14:27:51.000000000 +0100
-@@ -409,7 +409,9 @@
- 	int nr_scanned;
- 	unsigned long reap = 0;
- 
--	mutex_lock(&iprune_mutex);
-+	if (!mutex_trylock(&iprune_mutex))
-+		return;
-+
- 	spin_lock(&inode_lock);
- 	for (nr_scanned = 0; nr_scanned < nr_to_scan; nr_scanned++) {
- 		struct inode *inode;
-diff -u -r debian-2.6.26/fs/jbd2/checkpoint.c debian-2.6.26_lustre.1.8.2/fs/jbd2/checkpoint.c
---- debian-2.6.26/fs/jbd2/checkpoint.c	2008-07-13 23:51:29.000000000 +0200
-+++ debian-2.6.26_lustre.1.8.2/fs/jbd2/checkpoint.c	2010-02-17 14:28:49.000000000 +0100
-@@ -696,6 +696,7 @@
- 	J_ASSERT(transaction->t_checkpoint_list == NULL);
- 	J_ASSERT(transaction->t_checkpoint_io_list == NULL);
- 	J_ASSERT(transaction->t_updates == 0);
-+	J_ASSERT(list_empty(&transaction->t_jcb));
- 	J_ASSERT(journal->j_committing_transaction != transaction);
- 	J_ASSERT(journal->j_running_transaction != transaction);
- 
-diff -u -r debian-2.6.26/fs/jbd2/commit.c debian-2.6.26_lustre.1.8.2/fs/jbd2/commit.c
---- debian-2.6.26/fs/jbd2/commit.c	2008-07-13 23:51:29.000000000 +0200
-+++ debian-2.6.26_lustre.1.8.2/fs/jbd2/commit.c	2010-02-17 14:29:44.000000000 +0100
-@@ -874,6 +874,30 @@
-            transaction can be removed from any checkpoint list it was on
-            before. */
- 
-+        /*
-+         * Call any callbacks that had been registered for handles in this
-+         * transaction.  It is up to the callback to free any allocated
-+         * memory.
-+         *
-+         * The spinlocking (t_jcb_lock) here is surely unnecessary...
-+         */
-+        spin_lock(&commit_transaction->t_jcb_lock);
-+        if (!list_empty(&commit_transaction->t_jcb)) {
-+                struct list_head *p, *n;
-+                int error = is_journal_aborted(journal);
-+
-+                list_for_each_safe(p, n, &commit_transaction->t_jcb) {
-+                        struct journal_callback *jcb;
-+
-+                        jcb = list_entry(p, struct journal_callback, jcb_list);
-+                        list_del(p);
-+                        spin_unlock(&commit_transaction->t_jcb_lock);
-+                        jcb->jcb_func(jcb, error);
-+                        spin_lock(&commit_transaction->t_jcb_lock);
-+                }
-+        }
-+        spin_unlock(&commit_transaction->t_jcb_lock);
-+
- 	jbd_debug(3, "JBD: commit phase 7\n");
- 
- 	J_ASSERT(commit_transaction->t_sync_datalist == NULL);
-diff -u -r debian-2.6.26/fs/jbd2/journal.c debian-2.6.26_lustre.1.8.2/fs/jbd2/journal.c
---- debian-2.6.26/fs/jbd2/journal.c	2008-07-13 23:51:29.000000000 +0200
-+++ debian-2.6.26_lustre.1.8.2/fs/jbd2/journal.c	2010-02-17 14:38:15.000000000 +0100
-@@ -82,6 +82,8 @@
- EXPORT_SYMBOL(jbd2_journal_invalidatepage);
- EXPORT_SYMBOL(jbd2_journal_try_to_free_buffers);
- EXPORT_SYMBOL(jbd2_journal_force_commit);
-+EXPORT_SYMBOL(jbd2_journal_callback_set);
-+EXPORT_SYMBOL(jbd2_journal_bmap);
- 
- static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
- static void __journal_abort_soft (journal_t *journal, int errno);
-@@ -460,6 +462,7 @@
- 	spin_unlock(&journal->j_state_lock);
- 	return ret;
- }
-+EXPORT_SYMBOL(jbd2_log_start_commit);
- 
- /*
-  * Force and wait upon a commit if the calling process is not within
-diff -u -r debian-2.6.26/fs/jbd2/transaction.c debian-2.6.26_lustre.1.8.2/fs/jbd2/transaction.c
---- debian-2.6.26/fs/jbd2/transaction.c	2008-07-13 23:51:29.000000000 +0200
-+++ debian-2.6.26_lustre.1.8.2/fs/jbd2/transaction.c	2010-02-17 14:42:20.000000000 +0100
-@@ -51,10 +51,12 @@
- 	transaction->t_state = T_RUNNING;
- 	transaction->t_tid = journal->j_transaction_sequence++;
- 	transaction->t_expires = jiffies + journal->j_commit_interval;
-+	INIT_LIST_HEAD(&transaction->t_jcb);
- 	spin_lock_init(&transaction->t_handle_lock);
-+	spin_lock_init(&transaction->t_jcb_lock);
- 
- 	/* Set up the commit timer for the new transaction. */
--	journal->j_commit_timer.expires = round_jiffies(transaction->t_expires);
-+	journal->j_commit_timer.expires = transaction->t_expires;
- 	add_timer(&journal->j_commit_timer);
- 
- 	J_ASSERT(journal->j_running_transaction == NULL);
-@@ -252,6 +254,7 @@
- 	memset(handle, 0, sizeof(*handle));
- 	handle->h_buffer_credits = nblocks;
- 	handle->h_ref = 1;
-+	INIT_LIST_HEAD(&handle->h_jcb);
- 
- 	lockdep_init_map(&handle->h_lockdep_map, "jbd2_handle",
- 						&jbd2_handle_key, 0);
-@@ -1350,6 +1353,36 @@
- }
- 
- /**
-+ * void jbd2_journal_callback_set() -  Register a callback function for this handle.
-+ * @handle: handle to attach the callback to.
-+ * @func: function to callback.
-+ * @jcb:  structure with additional information required by func() , and
-+ *      some space for jbd2 internal information.
-+ *
-+ * The function will be
-+ * called when the transaction that this handle is part of has been
-+ * committed to disk with the original callback data struct and the
-+ * error status of the journal as parameters.  There is no guarantee of
-+ * ordering between handles within a single transaction, nor between
-+ * callbacks registered on the same handle.
-+ *
-+ * The caller is responsible for allocating the journal_callback struct.
-+ * This is to allow the caller to add as much extra data to the callback
-+ * as needed, but reduce the overhead of multiple allocations.  The caller
-+ * allocated struct must start with a struct journal_callback at offset 0,
-+ * and has the caller-specific data afterwards.
-+ */
-+void jbd2_journal_callback_set(handle_t *handle,
-+                      void (*func)(struct journal_callback *jcb, int error),
-+                      struct journal_callback *jcb)
-+{
-+        spin_lock(&handle->h_transaction->t_jcb_lock);
-+        list_add_tail(&jcb->jcb_list, &handle->h_jcb);
-+        spin_unlock(&handle->h_transaction->t_jcb_lock);
-+        jcb->jcb_func = func;
-+}
-+
-+/**
-  * int jbd2_journal_stop() - complete a transaction
-  * @handle: tranaction to complete.
-  *
-@@ -1423,6 +1456,11 @@
- 			wake_up(&journal->j_wait_transaction_locked);
- 	}
- 
-+        /* Move callbacks from the handle to the transaction. */
-+        spin_lock(&transaction->t_jcb_lock);
-+        list_splice(&handle->h_jcb, &transaction->t_jcb);
-+        spin_unlock(&transaction->t_jcb_lock);
-+
- 	/*
- 	 * If the handle is marked SYNC, we need to set another commit
- 	 * going!  We also want to force a commit if the current
-diff -u -r debian-2.6.26/fs/namespace.c debian-2.6.26_lustre.1.8.2/fs/namespace.c
---- debian-2.6.26/fs/namespace.c	2009-12-26 09:14:56.000000000 +0100
-+++ debian-2.6.26_lustre.1.8.2/fs/namespace.c	2010-02-17 14:43:07.000000000 +0100
-@@ -1660,6 +1660,7 @@
- 
- 	return do_add_mount(mnt, nd, mnt_flags, NULL);
- }
-+EXPORT_SYMBOL(set_fs_pwd);
- 
- /*
-  * add a mount into a namespace's mount tree
-diff -u -r debian-2.6.26/include/linux/blkdev.h debian-2.6.26_lustre.1.8.2/include/linux/blkdev.h
---- debian-2.6.26/include/linux/blkdev.h	2009-12-26 09:14:55.000000000 +0100
-+++ debian-2.6.26_lustre.1.8.2/include/linux/blkdev.h	2010-02-18 07:44:31.000000000 +0100
-@@ -806,7 +806,7 @@
- #define MAX_PHYS_SEGMENTS 128
- #define MAX_HW_SEGMENTS 128
- #define SAFE_MAX_SECTORS 255
--#define BLK_DEF_MAX_SECTORS 1024
-+#define BLK_DEF_MAX_SECTORS 2048
- 
- #define MAX_SEGMENT_SIZE	65536
- 
-diff -u -r debian-2.6.26/include/linux/dcache.h debian-2.6.26_lustre.1.8.2/include/linux/dcache.h
---- debian-2.6.26/include/linux/dcache.h	2008-07-13 23:51:29.000000000 +0200
-+++ debian-2.6.26_lustre.1.8.2/include/linux/dcache.h	2010-02-18 07:46:08.000000000 +0100
-@@ -173,6 +173,7 @@
- 
- #define DCACHE_REFERENCED	0x0008  /* Recently used, don't discard. */
- #define DCACHE_UNHASHED		0x0010	
-+#define DCACHE_LUSTRE_INVALID   0x0040  /* Lustre invalidated */
- 
- #define DCACHE_INOTIFY_PARENT_WATCHED	0x0020 /* Parent inode is watched */
- 
-@@ -250,6 +251,7 @@
-  * This adds the entry to the hash queues.
-  */
- extern void d_rehash(struct dentry *);
-+extern void d_rehash_cond(struct dentry *, int lock);
- 
- /**
-  * d_add - add dentry to hash queues
-@@ -285,6 +287,7 @@
- 
- /* used for rename() and baskets */
- extern void d_move(struct dentry *, struct dentry *);
-+extern void d_move_locked(struct dentry *, struct dentry *);
- 
- /* appendix may either be NULL or be used for transname suffixes */
- extern struct dentry * d_lookup(struct dentry *, struct qstr *);
-diff -u -r debian-2.6.26/include/linux/fs.h debian-2.6.26_lustre.1.8.2/include/linux/fs.h
---- debian-2.6.26/include/linux/fs.h	2008-07-13 23:51:29.000000000 +0200
-+++ debian-2.6.26_lustre.1.8.2/include/linux/fs.h	2010-02-18 07:57:56.000000000 +0100
-@@ -1832,6 +1832,10 @@
- extern void submit_bio(int, struct bio *);
- extern int bdev_read_only(struct block_device *);
- #endif
-+#define HAVE_CLEAR_RDONLY_ON_PUT
-+extern void dev_set_rdonly(struct block_device *bdev);
-+extern int dev_check_rdonly(struct block_device *bdev);
-+extern void dev_clear_rdonly(struct block_device *bdev);
- extern int set_blocksize(struct block_device *, int);
- extern int sb_set_blocksize(struct super_block *, int);
- extern int sb_min_blocksize(struct super_block *, int);
-@@ -1930,6 +1934,7 @@
- 
- extern const struct file_operations generic_ro_fops;
- 
-+extern rwlock_t file_systems_lock;
- #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
- 
- extern int vfs_readlink(struct dentry *, char __user *, int, const char *);
-diff -u -r debian-2.6.26/include/linux/jbd2.h debian-2.6.26_lustre.1.8.2/include/linux/jbd2.h
---- debian-2.6.26/include/linux/jbd2.h	2008-07-13 23:51:29.000000000 +0200
-+++ debian-2.6.26_lustre.1.8.2/include/linux/jbd2.h	2010-02-18 08:08:30.000000000 +0100
-@@ -379,6 +379,27 @@
- 	bit_spin_unlock(BH_JournalHead, &bh->b_state);
- }
- 
-+#define HAVE_JOURNAL_CALLBACK_STATUS
-+/**
-+ *   struct journal_callback - Base structure for callback information.
-+ *   @jcb_list: list information for other callbacks attached to the same handle.
-+ *   @jcb_func: Function to call with this callback structure.
-+ *
-+ *   This struct is a 'seed' structure for a using with your own callback
-+ *   structs. If you are using callbacks you must allocate one of these
-+ *   or another struct of your own definition which has this struct
-+ *   as it's first element and pass it to journal_callback_set().
-+ *
-+ *   This is used internally by jbd2 to maintain callback information.
-+ *
-+ *   See journal_callback_set for more information.
-+ **/
-+struct journal_callback {
-+        struct list_head jcb_list;              /* t_jcb_lock */
-+        void (*jcb_func)(struct journal_callback *jcb, int error);
-+        /* user data goes here */
-+};
-+
- struct jbd2_revoke_table_s;
- 
- /**
-@@ -387,6 +408,7 @@
-  * @h_transaction: Which compound transaction is this update a part of?
-  * @h_buffer_credits: Number of remaining buffers we are allowed to dirty.
-  * @h_ref: Reference count on this handle
-+ * @h_jcb: List of application registered callbacks for this handle.
-  * @h_err: Field for caller's use to track errors through large fs operations
-  * @h_sync: flag for sync-on-close
-  * @h_jdata: flag to force data journaling
-@@ -412,6 +434,13 @@
- 	/* operations */
- 	int			h_err;
- 
-+        /*
-+         * List of application registered callbacks for this handle. The
-+         * function(s) will be called after the transaction that this handle is
-+         * part of has been committed to disk. [t_jcb_lock]
-+         */
-+        struct list_head        h_jcb;
-+
- 	/* Flags [no locking] */
- 	unsigned int	h_sync:		1;	/* sync-on-close */
- 	unsigned int	h_jdata:	1;	/* force data journaling */
-@@ -467,6 +496,9 @@
-  *    j_state_lock
-  *    ->j_list_lock			(journal_unmap_buffer)
-  *
-+ *    t_handle_lock
-+ *    ->t_jcb_lock
-+ *
-  */
- 
- struct transaction_s
-@@ -613,6 +645,15 @@
- 	 */
- 	int t_handle_count;
- 
-+        /*
-+         * Protects the callback list
-+         */
-+        spinlock_t              t_jcb_lock;
-+        /*
-+         * List of registered callback functions for this transaction.
-+         * Called when the transaction is committed. [t_jcb_lock]
-+         */
-+        struct list_head        t_jcb;
- };
- 
- struct transaction_run_stats_s {
-@@ -1016,6 +1057,9 @@
- extern int	 jbd2_journal_flush (journal_t *);
- extern void	 jbd2_journal_lock_updates (journal_t *);
- extern void	 jbd2_journal_unlock_updates (journal_t *);
-+extern void      jbd2_journal_callback_set(handle_t *handle,
-+                                      void (*fn)(struct journal_callback *,int),
-+                                      struct journal_callback *jcb);
- 
- extern journal_t * jbd2_journal_init_dev(struct block_device *bdev,
- 				struct block_device *fs_dev,
-diff -u -r debian-2.6.26/include/linux/mm.h debian-2.6.26_lustre.1.8.2/include/linux/mm.h
---- debian-2.6.26/include/linux/mm.h	2009-12-26 09:14:57.000000000 +0100
-+++ debian-2.6.26_lustre.1.8.2/include/linux/mm.h	2010-02-18 08:10:11.000000000 +0100
-@@ -564,6 +564,8 @@
- {
- 	return __va(page_to_pfn(page) << PAGE_SHIFT);
- }
-+/* truncate.c */
-+extern void truncate_complete_page(struct address_space *mapping,struct page *);
- 
- #if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL)
- #define HASHED_PAGE_VIRTUAL
-diff -u -r debian-2.6.26/include/scsi/sd.h debian-2.6.26_lustre.1.8.2/include/scsi/sd.h
---- debian-2.6.26/include/scsi/sd.h	2008-07-13 23:51:29.000000000 +0200
-+++ debian-2.6.26_lustre.1.8.2/include/scsi/sd.h	2010-02-17 14:18:52.000000000 +0100
-@@ -31,6 +31,47 @@
-  */
- #define SD_BUF_SIZE		512
- 
-+#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
-+typedef struct {
-+        unsigned long long iostat_size;
-+        unsigned long long iostat_count;
-+} iostat_counter_t;
-+
-+#define IOSTAT_NCOUNTERS 16
-+typedef struct {
-+        iostat_counter_t        iostat_read_histogram[IOSTAT_NCOUNTERS];
-+        iostat_counter_t        iostat_write_histogram[IOSTAT_NCOUNTERS];
-+        struct timeval          iostat_timeval;
-+
-+        /* queue depth: how well the pipe is filled up */
-+        unsigned long long      iostat_queue_ticks[IOSTAT_NCOUNTERS];
-+        unsigned long long      iostat_queue_ticks_sum;
-+        unsigned long           iostat_queue_depth;
-+        unsigned long           iostat_queue_stamp;
-+
-+        /* seeks: how linear the traffic is */
-+        unsigned long long      iostat_next_sector;
-+        unsigned long long      iostat_seek_sectors;
-+        unsigned long long      iostat_seeks;
-+        unsigned long long      iostat_sectors;
-+        unsigned long long      iostat_reqs;
-+        unsigned long           iostat_read_reqs;
-+        unsigned long           iostat_write_reqs;
-+
-+        /* process time: how long it takes to process requests */
-+        unsigned long           iostat_rtime[IOSTAT_NCOUNTERS];
-+        unsigned long           iostat_wtime[IOSTAT_NCOUNTERS];
-+
-+        /* queue time: how long process spent in elevator's queue */
-+        unsigned long           iostat_rtime_in_queue[IOSTAT_NCOUNTERS];
-+        unsigned long           iostat_wtime_in_queue[IOSTAT_NCOUNTERS];
-+
-+        /* must be the last field, as it's used to know size to be memset'ed */
-+        spinlock_t              iostat_lock;
-+} ____cacheline_aligned_in_smp iostat_stats_t;
-+#endif
-+
-+
- struct scsi_disk {
- 	struct scsi_driver *driver;	/* always &sd_template */
- 	struct scsi_device *device;
-@@ -45,6 +86,9 @@
- 	unsigned	WCE : 1;	/* state of disk WCE bit */
- 	unsigned	RCD : 1;	/* state of disk RCD bit, unused */
- 	unsigned	DPOFUA : 1;	/* state of disk DPOFUA bit */
-+#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
-+        iostat_stats_t  *stats;         /* scsi disk statistics */
-+#endif
- };
- #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
- 
-diff -u -r debian-2.6.26/kernel/sched.c debian-2.6.26_lustre.1.8.2/kernel/sched.c
---- debian-2.6.26/kernel/sched.c	2009-12-26 09:14:56.000000000 +0100
-+++ debian-2.6.26_lustre.1.8.2/kernel/sched.c	2010-02-18 08:11:02.000000000 +0100
-@@ -5477,6 +5477,7 @@
- 
- 	show_stack(p, NULL);
- }
-+EXPORT_SYMBOL(sched_show_task);
- 
- void show_state_filter(unsigned long state_filter)
- {
-diff -u -r debian-2.6.26/mm/truncate.c debian-2.6.26_lustre.1.8.2/mm/truncate.c
---- debian-2.6.26/mm/truncate.c	2008-07-13 23:51:29.000000000 +0200
-+++ debian-2.6.26_lustre.1.8.2/mm/truncate.c	2010-02-18 08:12:58.000000000 +0100
-@@ -92,7 +92,7 @@
-  * its lock, b) when a concurrent invalidate_mapping_pages got there first and
-  * c) when tmpfs swizzles a page between a tmpfs inode and swapper_space.
-  */
--static void
-+void
- truncate_complete_page(struct address_space *mapping, struct page *page)
- {
- 	if (page->mapping != mapping)
-@@ -108,6 +108,7 @@
- 	ClearPageMappedToDisk(page);
- 	page_cache_release(page);	/* pagecache ref */
- }
-+EXPORT_SYMBOL_GPL(truncate_complete_page);
- 
- /*
-  * This is for invalidate_mapping_pages().  That function can be called at
-diff -u -r debian-2.6.26/security/security.c debian-2.6.26_lustre.1.8.2/security/security.c
---- debian-2.6.26/security/security.c	2009-12-26 09:14:57.000000000 +0100
-+++ debian-2.6.26_lustre.1.8.2/security/security.c	2010-02-18 08:13:38.000000000 +0100
-@@ -406,6 +406,7 @@
- 		return 0;
- 	return security_ops->inode_unlink(dir, dentry);
- }
-+EXPORT_SYMBOL(security_inode_unlink);
- 
- int security_inode_symlink(struct inode *dir, struct dentry *dentry,
- 			    const char *old_name)
diff --git a/lustre/kernel_patches/patches/export-2.6.26-vanilla.patch b/lustre/kernel_patches/patches/export-2.6.26-vanilla.patch
deleted file mode 100644
index c8e1ae7..0000000
--- a/lustre/kernel_patches/patches/export-2.6.26-vanilla.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-Index: linux-source-2.6.26/fs/jbd2/journal.c
-===================================================================
---- linux-source-2.6.26.orig/fs/jbd2/journal.c	2009-10-09 13:49:43.000000000 +0200
-+++ linux-source-2.6.26/fs/jbd2/journal.c	2009-10-09 13:49:50.000000000 +0200
-@@ -460,6 +460,7 @@
- 	spin_unlock(&journal->j_state_lock);
- 	return ret;
- }
-+EXPORT_SYMBOL(jbd2_log_start_commit);
- 
- /*
-  * Force and wait upon a commit if the calling process is not within
-Index: linux-source-2.6.26/security/security.c
-===================================================================
---- linux-source-2.6.26.orig/security/security.c	2009-10-09 13:49:43.000000000 +0200
-+++ linux-source-2.6.26/security/security.c	2009-10-09 13:49:50.000000000 +0200
-@@ -68,6 +68,7 @@
- 
- 	return 0;
- }
-+EXPORT_SYMBOL(security_inode_unlink);
- 
- /* Save user chosen LSM */
- static int __init choose_lsm(char *str)
diff --git a/lustre/kernel_patches/patches/jbd2-jcberr-2.6.26-vanilla.patch b/lustre/kernel_patches/patches/jbd2-jcberr-2.6.26-vanilla.patch
deleted file mode 100644
index c4a4921..0000000
--- a/lustre/kernel_patches/patches/jbd2-jcberr-2.6.26-vanilla.patch
+++ /dev/null
@@ -1,211 +0,0 @@
-Index: linux-source-2.6.26/include/linux/jbd2.h
-===================================================================
---- linux-source-2.6.26.orig/include/linux/jbd2.h	2008-07-13 23:51:29.000000000 +0200
-+++ linux-source-2.6.26/include/linux/jbd2.h	2009-10-09 13:42:21.000000000 +0200
-@@ -379,6 +379,27 @@
- 	bit_spin_unlock(BH_JournalHead, &bh->b_state);
- }
- 
-+#define HAVE_JOURNAL_CALLBACK_STATUS
-+/**
-+ *   struct journal_callback - Base structure for callback information.
-+ *   @jcb_list: list information for other callbacks attached to the same handle.
-+ *   @jcb_func: Function to call with this callback structure.
-+ *
-+ *   This struct is a 'seed' structure for a using with your own callback
-+ *   structs. If you are using callbacks you must allocate one of these
-+ *   or another struct of your own definition which has this struct
-+ *   as it's first element and pass it to journal_callback_set().
-+ *
-+ *   This is used internally by jbd2 to maintain callback information.
-+ *
-+ *   See journal_callback_set for more information.
-+ **/
-+struct journal_callback {
-+	struct list_head jcb_list;		/* t_jcb_lock */
-+	void (*jcb_func)(struct journal_callback *jcb, int error);
-+	/* user data goes here */
-+};
-+
- struct jbd2_revoke_table_s;
- 
- /**
-@@ -387,6 +408,7 @@
-  * @h_transaction: Which compound transaction is this update a part of?
-  * @h_buffer_credits: Number of remaining buffers we are allowed to dirty.
-  * @h_ref: Reference count on this handle
-+ * @h_jcb: List of application registered callbacks for this handle.
-  * @h_err: Field for caller's use to track errors through large fs operations
-  * @h_sync: flag for sync-on-close
-  * @h_jdata: flag to force data journaling
-@@ -412,6 +434,13 @@
- 	/* operations */
- 	int			h_err;
- 
-+	/*
-+	 * List of application registered callbacks for this handle. The
-+	 * function(s) will be called after the transaction that this handle is
-+	 * part of has been committed to disk. [t_jcb_lock]
-+	 */
-+	struct list_head	h_jcb;
-+
- 	/* Flags [no locking] */
- 	unsigned int	h_sync:		1;	/* sync-on-close */
- 	unsigned int	h_jdata:	1;	/* force data journaling */
-@@ -467,6 +496,8 @@
-  *    j_state_lock
-  *    ->j_list_lock			(journal_unmap_buffer)
-  *
-+ *    t_handle_lock
-+ *    ->t_jcb_lock
-  */
- 
- struct transaction_s
-@@ -613,6 +644,15 @@
- 	 */
- 	int t_handle_count;
- 
-+	/*
-+	 * Protects the callback list
-+	 */
-+	spinlock_t		t_jcb_lock;
-+	/*
-+	 * List of registered callback functions for this transaction.
-+	 * Called when the transaction is committed. [t_jcb_lock]
-+	 */
-+	struct list_head	t_jcb;
- };
- 
- struct transaction_run_stats_s {
-@@ -1016,6 +1056,9 @@
- extern int	 jbd2_journal_flush (journal_t *);
- extern void	 jbd2_journal_lock_updates (journal_t *);
- extern void	 jbd2_journal_unlock_updates (journal_t *);
-+extern void	 jbd2_journal_callback_set(handle_t *handle,
-+                                      void (*fn)(struct journal_callback *,int),
-+                                      struct journal_callback *jcb);
- 
- extern journal_t * jbd2_journal_init_dev(struct block_device *bdev,
- 				struct block_device *fs_dev,
-Index: linux-source-2.6.26/fs/jbd2/checkpoint.c
-===================================================================
---- linux-source-2.6.26.orig/fs/jbd2/checkpoint.c	2008-07-13 23:51:29.000000000 +0200
-+++ linux-source-2.6.26/fs/jbd2/checkpoint.c	2009-10-09 13:42:21.000000000 +0200
-@@ -696,6 +696,7 @@
- 	J_ASSERT(transaction->t_checkpoint_list == NULL);
- 	J_ASSERT(transaction->t_checkpoint_io_list == NULL);
- 	J_ASSERT(transaction->t_updates == 0);
-+	J_ASSERT(list_empty(&transaction->t_jcb));
- 	J_ASSERT(journal->j_committing_transaction != transaction);
- 	J_ASSERT(journal->j_running_transaction != transaction);
- 
-Index: linux-source-2.6.26/fs/jbd2/commit.c
-===================================================================
---- linux-source-2.6.26.orig/fs/jbd2/commit.c	2008-07-13 23:51:29.000000000 +0200
-+++ linux-source-2.6.26/fs/jbd2/commit.c	2009-10-09 13:42:21.000000000 +0200
-@@ -854,6 +854,30 @@
- 		/* AKPM: bforget here */
- 	}
- 
-+	/*
-+	 * Call any callbacks that had been registered for handles in this
-+	 * transaction.  It is up to the callback to free any allocated
-+	 * memory.
-+	 *
-+	 * The spinlocking (t_jcb_lock) here is surely unnecessary...
-+	 */
-+	spin_lock(&commit_transaction->t_jcb_lock);
-+	if (!list_empty(&commit_transaction->t_jcb)) {
-+		struct list_head *p, *n;
-+		int error = is_journal_aborted(journal);
-+
-+		list_for_each_safe(p, n, &commit_transaction->t_jcb) {
-+			struct journal_callback *jcb;
-+
-+			jcb = list_entry(p, struct journal_callback, jcb_list);
-+			list_del(p);
-+			spin_unlock(&commit_transaction->t_jcb_lock);
-+			jcb->jcb_func(jcb, error);
-+			spin_lock(&commit_transaction->t_jcb_lock);
-+		}
-+	}
-+	spin_unlock(&commit_transaction->t_jcb_lock);
-+
- 	jbd_debug(3, "JBD: commit phase 6\n");
- 
- 	if (!JBD2_HAS_INCOMPAT_FEATURE(journal,
-Index: linux-source-2.6.26/fs/jbd2/journal.c
-===================================================================
---- linux-source-2.6.26.orig/fs/jbd2/journal.c	2009-10-09 13:39:04.000000000 +0200
-+++ linux-source-2.6.26/fs/jbd2/journal.c	2009-10-09 13:43:03.000000000 +0200
-@@ -82,6 +82,9 @@
- EXPORT_SYMBOL(jbd2_journal_invalidatepage);
- EXPORT_SYMBOL(jbd2_journal_try_to_free_buffers);
- EXPORT_SYMBOL(jbd2_journal_force_commit);
-+EXPORT_SYMBOL(jbd2_journal_callback_set);
-+EXPORT_SYMBOL(jbd2_journal_bmap);
-+
- 
- static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
- static void __journal_abort_soft (journal_t *journal, int errno);
-Index: linux-source-2.6.26/fs/jbd2/transaction.c
-===================================================================
---- linux-source-2.6.26.orig/fs/jbd2/transaction.c	2008-07-13 23:51:29.000000000 +0200
-+++ linux-source-2.6.26/fs/jbd2/transaction.c	2009-10-09 13:42:21.000000000 +0200
-@@ -252,6 +252,7 @@
- 	memset(handle, 0, sizeof(*handle));
- 	handle->h_buffer_credits = nblocks;
- 	handle->h_ref = 1;
-+	INIT_LIST_HEAD(&handle->h_jcb);
- 
- 	lockdep_init_map(&handle->h_lockdep_map, "jbd2_handle",
- 						&jbd2_handle_key, 0);
-@@ -1350,6 +1351,36 @@
- }
- 
- /**
-+ * void jbd2_journal_callback_set() -  Register a callback function for this handle.
-+ * @handle: handle to attach the callback to.
-+ * @func: function to callback.
-+ * @jcb:  structure with additional information required by func() , and
-+ *	some space for jbd2 internal information.
-+ *
-+ * The function will be
-+ * called when the transaction that this handle is part of has been
-+ * committed to disk with the original callback data struct and the
-+ * error status of the journal as parameters.  There is no guarantee of
-+ * ordering between handles within a single transaction, nor between
-+ * callbacks registered on the same handle.
-+ *
-+ * The caller is responsible for allocating the journal_callback struct.
-+ * This is to allow the caller to add as much extra data to the callback
-+ * as needed, but reduce the overhead of multiple allocations.  The caller
-+ * allocated struct must start with a struct journal_callback at offset 0,
-+ * and has the caller-specific data afterwards.
-+ */
-+void jbd2_journal_callback_set(handle_t *handle,
-+		      void (*func)(struct journal_callback *jcb, int error),
-+		      struct journal_callback *jcb)
-+{
-+	spin_lock(&handle->h_transaction->t_jcb_lock);
-+	list_add_tail(&jcb->jcb_list, &handle->h_jcb);
-+	spin_unlock(&handle->h_transaction->t_jcb_lock);
-+	jcb->jcb_func = func;
-+}
-+
-+/**
-  * int jbd2_journal_stop() - complete a transaction
-  * @handle: tranaction to complete.
-  *
-@@ -1423,6 +1454,11 @@
- 			wake_up(&journal->j_wait_transaction_locked);
- 	}
- 
-+	/* Move callbacks from the handle to the transaction. */
-+	spin_lock(&transaction->t_jcb_lock);
-+	list_splice(&handle->h_jcb, &transaction->t_jcb);
-+	spin_unlock(&transaction->t_jcb_lock);
-+
- 	/*
- 	 * If the handle is marked SYNC, we need to set another commit
- 	 * going!  We also want to force a commit if the current
diff --git a/lustre/kernel_patches/patches/md-mmp-unplug-dev-2.6.27-vanilla.patch b/lustre/kernel_patches/patches/md-mmp-unplug-dev-2.6.27-vanilla.patch
deleted file mode 100644
index c758cba..0000000
--- a/lustre/kernel_patches/patches/md-mmp-unplug-dev-2.6.27-vanilla.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-Index: linux-2.6.27.36/drivers/md/raid5.c
-===================================================================
---- linux-2.6.27.36.orig/drivers/md/raid5.c	2009-10-05 17:19:01.000000000 +0200
-+++ linux-2.6.27.36/drivers/md/raid5.c	2009-10-08 15:06:10.000000000 +0200
-@@ -1726,6 +1726,8 @@
- 		bi->bi_next = *bip;
- 	*bip = bi;
- 	bi->bi_phys_segments ++;
-+        if (bio_sync(bi) && !forwrite)
-+               clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags); /* force to read from disk. */
- 	spin_unlock_irq(&conf->device_lock);
- 	spin_unlock(&sh->lock);
- 
-@@ -3478,6 +3480,8 @@
- 
- 		bio_endio(bi, 0);
- 	}
-+	if (bio_sync(bi))
-+		raid5_unplug_device(q);
- 	return 0;
- }
- 
diff --git a/lustre/kernel_patches/patches/quota-Increase-size-of-variables-for-limits-and-ino.patch b/lustre/kernel_patches/patches/quota-Increase-size-of-variables-for-limits-and-ino.patch
deleted file mode 100644
index d582bb8..0000000
--- a/lustre/kernel_patches/patches/quota-Increase-size-of-variables-for-limits-and-ino.patch
+++ /dev/null
@@ -1,359 +0,0 @@
-From: Jan Kara <jack at suse.cz>
-References: fate#302681
-Subject: [PATCH 02/28] quota: Increase size of variables for limits and inode usage
-Patch-mainline: 2.6.29?
-
-So far quota was fine with quota block limits and inode limits/numbers in
-a 32-bit type. Now with rapid increase in storage sizes there are coming
-requests to be able to handle quota limits above 4TB / more that 2^32 inodes.
-So bump up sizes of types in mem_dqblk structure to 64-bits to be able to
-handle this. Also update inode allocation / checking functions to use qsize_t
-and make global structure keep quota limits in bytes so that things are
-consistent.
-
-Signed-off-by: Jan Kara <jack at suse.cz>
----
- fs/dquot.c               |   50 ++++++++++++++++++++++++++-------------------
- fs/quota_v1.c            |   25 +++++++++++++++++-----
- fs/quota_v2.c            |   21 +++++++++++++++---
- include/linux/quota.h    |   28 +++++++++++--------------
- include/linux/quotaops.h |    4 +-
- 5 files changed, 79 insertions(+), 49 deletions(-)
-
-diff --git a/fs/dquot.c b/fs/dquot.c
-index e1dac3e..758bf4a 100644
---- a/fs/dquot.c
-+++ b/fs/dquot.c
-@@ -833,7 +833,7 @@ static void drop_dquot_ref(struct super_block *sb, int type)
- 	}
- }
- 
--static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
-+static inline void dquot_incr_inodes(struct dquot *dquot, qsize_t number)
- {
- 	dquot->dq_dqb.dqb_curinodes += number;
- }
-@@ -843,7 +843,7 @@ static inline void dquot_incr_space(struct dquot *dquot, qsize_t number)
- 	dquot->dq_dqb.dqb_curspace += number;
- }
- 
--static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number)
-+static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
- {
- 	if (dquot->dq_dqb.dqb_curinodes > number)
- 		dquot->dq_dqb.dqb_curinodes -= number;
-@@ -860,7 +860,7 @@ static inline void dquot_decr_space(struct dquot *dquot, qsize_t number)
- 		dquot->dq_dqb.dqb_curspace -= number;
- 	else
- 		dquot->dq_dqb.dqb_curspace = 0;
--	if (toqb(dquot->dq_dqb.dqb_curspace) <= dquot->dq_dqb.dqb_bsoftlimit)
-+	if (dquot->dq_dqb.dqb_curspace <= dquot->dq_dqb.dqb_bsoftlimit)
- 		dquot->dq_dqb.dqb_btime = (time_t) 0;
- 	clear_bit(DQ_BLKS_B, &dquot->dq_flags);
- }
-@@ -1038,7 +1038,7 @@ static inline char ignore_hardlimit(struct dquot *dquot)
- }
- 
- /* needs dq_data_lock */
--static int check_idq(struct dquot *dquot, ulong inodes, char *warntype)
-+static int check_idq(struct dquot *dquot, qsize_t inodes, char *warntype)
- {
- 	*warntype = QUOTA_NL_NOWARN;
- 	if (inodes <= 0 || test_bit(DQ_FAKE_B, &dquot->dq_flags))
-@@ -1077,7 +1077,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
- 		return QUOTA_OK;
- 
- 	if (dquot->dq_dqb.dqb_bhardlimit &&
--	   toqb(dquot->dq_dqb.dqb_curspace + space) > dquot->dq_dqb.dqb_bhardlimit &&
-+	    dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bhardlimit &&
-             !ignore_hardlimit(dquot)) {
- 		if (!prealloc)
- 			*warntype = QUOTA_NL_BHARDWARN;
-@@ -1085,7 +1085,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
- 	}
- 
- 	if (dquot->dq_dqb.dqb_bsoftlimit &&
--	   toqb(dquot->dq_dqb.dqb_curspace + space) > dquot->dq_dqb.dqb_bsoftlimit &&
-+	    dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bsoftlimit &&
- 	    dquot->dq_dqb.dqb_btime && get_seconds() >= dquot->dq_dqb.dqb_btime &&
-             !ignore_hardlimit(dquot)) {
- 		if (!prealloc)
-@@ -1094,7 +1094,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
- 	}
- 
- 	if (dquot->dq_dqb.dqb_bsoftlimit &&
--	   toqb(dquot->dq_dqb.dqb_curspace + space) > dquot->dq_dqb.dqb_bsoftlimit &&
-+	    dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bsoftlimit &&
- 	    dquot->dq_dqb.dqb_btime == 0) {
- 		if (!prealloc) {
- 			*warntype = QUOTA_NL_BSOFTWARN;
-@@ -1111,7 +1111,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
- 	return QUOTA_OK;
- }
- 
--static int info_idq_free(struct dquot *dquot, ulong inodes)
-+static int info_idq_free(struct dquot *dquot, qsize_t inodes)
- {
- 	if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
- 	    dquot->dq_dqb.dqb_curinodes <= dquot->dq_dqb.dqb_isoftlimit)
-@@ -1128,15 +1128,13 @@ static int info_idq_free(struct dquot *dquot, ulong inodes)
- static int info_bdq_free(struct dquot *dquot, qsize_t space)
- {
- 	if (test_bit(DQ_FAKE_B, &dquot->dq_flags) ||
--	    toqb(dquot->dq_dqb.dqb_curspace) <= dquot->dq_dqb.dqb_bsoftlimit)
-+	    dquot->dq_dqb.dqb_curspace <= dquot->dq_dqb.dqb_bsoftlimit)
- 		return QUOTA_NL_NOWARN;
- 
--	if (toqb(dquot->dq_dqb.dqb_curspace - space) <=
--	    dquot->dq_dqb.dqb_bsoftlimit)
-+	if (dquot->dq_dqb.dqb_curspace - space <= dquot->dq_dqb.dqb_bsoftlimit)
- 		return QUOTA_NL_BSOFTBELOW;
--	if (toqb(dquot->dq_dqb.dqb_curspace) >= dquot->dq_dqb.dqb_bhardlimit &&
--	    toqb(dquot->dq_dqb.dqb_curspace - space) <
--						dquot->dq_dqb.dqb_bhardlimit)
-+	if (dquot->dq_dqb.dqb_curspace >= dquot->dq_dqb.dqb_bhardlimit &&
-+	    dquot->dq_dqb.dqb_curspace - space < dquot->dq_dqb.dqb_bhardlimit)
- 		return QUOTA_NL_BHARDBELOW;
- 	return QUOTA_NL_NOWARN;
- }
-@@ -1279,7 +1277,7 @@ warn_put_all:
- /*
-  * This operation can block, but only after everything is updated
-  */
--int dquot_alloc_inode(const struct inode *inode, unsigned long number)
-+int dquot_alloc_inode(const struct inode *inode, qsize_t number)
- {
- 	int cnt, ret = NO_QUOTA;
- 	char warntype[MAXQUOTAS];
-@@ -1364,7 +1362,7 @@ out_sub:
- /*
-  * This operation can block, but only after everything is updated
-  */
--int dquot_free_inode(const struct inode *inode, unsigned long number)
-+int dquot_free_inode(const struct inode *inode, qsize_t number)
- {
- 	unsigned int cnt;
- 	char warntype[MAXQUOTAS];
-@@ -1881,14 +1879,24 @@ int vfs_dq_quota_on_remount(struct super_block *sb)
- 	return ret;
- }
- 
-+static inline qsize_t qbtos(qsize_t blocks)
-+{
-+	return blocks << QIF_DQBLKSIZE_BITS;
-+}
-+
-+static inline qsize_t stoqb(qsize_t space)
-+{
-+	return (space + QIF_DQBLKSIZE - 1) >> QIF_DQBLKSIZE_BITS;
-+}
-+
- /* Generic routine for getting common part of quota structure */
- static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di)
- {
- 	struct mem_dqblk *dm = &dquot->dq_dqb;
- 
- 	spin_lock(&dq_data_lock);
--	di->dqb_bhardlimit = dm->dqb_bhardlimit;
--	di->dqb_bsoftlimit = dm->dqb_bsoftlimit;
-+	di->dqb_bhardlimit = stoqb(dm->dqb_bhardlimit);
-+	di->dqb_bsoftlimit = stoqb(dm->dqb_bsoftlimit);
- 	di->dqb_curspace = dm->dqb_curspace;
- 	di->dqb_ihardlimit = dm->dqb_ihardlimit;
- 	di->dqb_isoftlimit = dm->dqb_isoftlimit;
-@@ -1935,8 +1943,8 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
- 		check_blim = 1;
- 	}
- 	if (di->dqb_valid & QIF_BLIMITS) {
--		dm->dqb_bsoftlimit = di->dqb_bsoftlimit;
--		dm->dqb_bhardlimit = di->dqb_bhardlimit;
-+		dm->dqb_bsoftlimit = qbtos(di->dqb_bsoftlimit);
-+		dm->dqb_bhardlimit = qbtos(di->dqb_bhardlimit);
- 		check_blim = 1;
- 	}
- 	if (di->dqb_valid & QIF_INODES) {
-@@ -1954,7 +1962,7 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
- 		dm->dqb_itime = di->dqb_itime;
- 
- 	if (check_blim) {
--		if (!dm->dqb_bsoftlimit || toqb(dm->dqb_curspace) < dm->dqb_bsoftlimit) {
-+		if (!dm->dqb_bsoftlimit || dm->dqb_curspace < dm->dqb_bsoftlimit) {
- 			dm->dqb_btime = 0;
- 			clear_bit(DQ_BLKS_B, &dquot->dq_flags);
- 		}
-diff --git a/fs/quota_v1.c b/fs/quota_v1.c
-index 5ae15b1..3e078ee 100644
---- a/fs/quota_v1.c
-+++ b/fs/quota_v1.c
-@@ -14,14 +14,27 @@ MODULE_AUTHOR("Jan Kara");
- MODULE_DESCRIPTION("Old quota format support");
- MODULE_LICENSE("GPL");
- 
-+#define QUOTABLOCK_BITS 10
-+#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
-+
-+static inline qsize_t v1_stoqb(qsize_t space)
-+{
-+	return (space + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS;
-+}
-+
-+static inline qsize_t v1_qbtos(qsize_t blocks)
-+{
-+	return blocks << QUOTABLOCK_BITS;
-+}
-+
- static void v1_disk2mem_dqblk(struct mem_dqblk *m, struct v1_disk_dqblk *d)
- {
- 	m->dqb_ihardlimit = d->dqb_ihardlimit;
- 	m->dqb_isoftlimit = d->dqb_isoftlimit;
- 	m->dqb_curinodes = d->dqb_curinodes;
--	m->dqb_bhardlimit = d->dqb_bhardlimit;
--	m->dqb_bsoftlimit = d->dqb_bsoftlimit;
--	m->dqb_curspace = ((qsize_t)d->dqb_curblocks) << QUOTABLOCK_BITS;
-+	m->dqb_bhardlimit = v1_qbtos(d->dqb_bhardlimit);
-+	m->dqb_bsoftlimit = v1_qbtos(d->dqb_bsoftlimit);
-+	m->dqb_curspace = v1_qbtos(d->dqb_curblocks);
- 	m->dqb_itime = d->dqb_itime;
- 	m->dqb_btime = d->dqb_btime;
- }
-@@ -31,9 +44,9 @@ static void v1_mem2disk_dqblk(struct v1_disk_dqblk *d, struct mem_dqblk *m)
- 	d->dqb_ihardlimit = m->dqb_ihardlimit;
- 	d->dqb_isoftlimit = m->dqb_isoftlimit;
- 	d->dqb_curinodes = m->dqb_curinodes;
--	d->dqb_bhardlimit = m->dqb_bhardlimit;
--	d->dqb_bsoftlimit = m->dqb_bsoftlimit;
--	d->dqb_curblocks = toqb(m->dqb_curspace);
-+	d->dqb_bhardlimit = v1_stoqb(m->dqb_bhardlimit);
-+	d->dqb_bsoftlimit = v1_stoqb(m->dqb_bsoftlimit);
-+	d->dqb_curblocks = v1_stoqb(m->dqb_curspace);
- 	d->dqb_itime = m->dqb_itime;
- 	d->dqb_btime = m->dqb_btime;
- }
-diff --git a/fs/quota_v2.c b/fs/quota_v2.c
-index b53827d..51c4717 100644
---- a/fs/quota_v2.c
-+++ b/fs/quota_v2.c
-@@ -26,6 +26,19 @@ typedef char *dqbuf_t;
- #define GETIDINDEX(id, depth) (((id) >> ((V2_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
- #define GETENTRIES(buf) ((struct v2_disk_dqblk *)(((char *)buf)+sizeof(struct v2_disk_dqdbheader)))
- 
-+#define QUOTABLOCK_BITS 10
-+#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
-+
-+static inline qsize_t v2_stoqb(qsize_t space)
-+{
-+	return (space + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS;
-+}
-+
-+static inline qsize_t v2_qbtos(qsize_t blocks)
-+{
-+	return blocks << QUOTABLOCK_BITS;
-+}
-+
- /* Check whether given file is really vfsv0 quotafile */
- static int v2_check_quota_file(struct super_block *sb, int type)
- {
-@@ -104,8 +117,8 @@ static void disk2memdqb(struct mem_dqblk *m, struct v2_disk_dqblk *d)
- 	m->dqb_isoftlimit = le32_to_cpu(d->dqb_isoftlimit);
- 	m->dqb_curinodes = le32_to_cpu(d->dqb_curinodes);
- 	m->dqb_itime = le64_to_cpu(d->dqb_itime);
--	m->dqb_bhardlimit = le32_to_cpu(d->dqb_bhardlimit);
--	m->dqb_bsoftlimit = le32_to_cpu(d->dqb_bsoftlimit);
-+	m->dqb_bhardlimit = v2_qbtos(le32_to_cpu(d->dqb_bhardlimit));
-+	m->dqb_bsoftlimit = v2_qbtos(le32_to_cpu(d->dqb_bsoftlimit));
- 	m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
- 	m->dqb_btime = le64_to_cpu(d->dqb_btime);
- }
-@@ -116,8 +129,8 @@ static void mem2diskdqb(struct v2_disk_dqblk *d, struct mem_dqblk *m, qid_t id)
- 	d->dqb_isoftlimit = cpu_to_le32(m->dqb_isoftlimit);
- 	d->dqb_curinodes = cpu_to_le32(m->dqb_curinodes);
- 	d->dqb_itime = cpu_to_le64(m->dqb_itime);
--	d->dqb_bhardlimit = cpu_to_le32(m->dqb_bhardlimit);
--	d->dqb_bsoftlimit = cpu_to_le32(m->dqb_bsoftlimit);
-+	d->dqb_bhardlimit = cpu_to_le32(v2_qbtos(m->dqb_bhardlimit));
-+	d->dqb_bsoftlimit = cpu_to_le32(v2_qbtos(m->dqb_bsoftlimit));
- 	d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
- 	d->dqb_btime = cpu_to_le64(m->dqb_btime);
- 	d->dqb_id = cpu_to_le32(id);
-diff --git a/include/linux/quota.h b/include/linux/quota.h
-index eeae7a9..5167786 100644
---- a/include/linux/quota.h
-+++ b/include/linux/quota.h
-@@ -41,15 +41,6 @@
- #define __DQUOT_VERSION__	"dquot_6.5.1"
- #define __DQUOT_NUM_VERSION__	6*10000+5*100+1
- 
--/* Size of blocks in which are counted size limits */
--#define QUOTABLOCK_BITS 10
--#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
--
--/* Conversion routines from and to quota blocks */
--#define qb2kb(x) ((x) << (QUOTABLOCK_BITS-10))
--#define kb2qb(x) ((x) >> (QUOTABLOCK_BITS-10))
--#define toqb(x) (((x) + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS)
--
- #define MAXQUOTAS 2
- #define USRQUOTA  0		/* element used for user quotas */
- #define GRPQUOTA  1		/* element used for group quotas */
-@@ -82,6 +73,11 @@
- #define Q_GETQUOTA 0x800007	/* get user quota structure */
- #define Q_SETQUOTA 0x800008	/* set user quota structure */
- 
-+/* Size of block in which space limits are passed through the quota
-+ * interface */
-+#define QIF_DQBLKSIZE_BITS 10
-+#define QIF_DQBLKSIZE (1 << QIF_DQBLKSIZE_BITS)
-+
- /*
-  * Quota structure used for communication with userspace via quotactl
-  * Following flags are used to specify which fields are valid
-@@ -189,12 +185,12 @@ extern spinlock_t dq_data_lock;
-  * Data for one user/group kept in memory
-  */
- struct mem_dqblk {
--	__u32 dqb_bhardlimit;	/* absolute limit on disk blks alloc */
--	__u32 dqb_bsoftlimit;	/* preferred limit on disk blks */
-+	qsize_t dqb_bhardlimit;	/* absolute limit on disk blks alloc */
-+	qsize_t dqb_bsoftlimit;	/* preferred limit on disk blks */
- 	qsize_t dqb_curspace;	/* current used space */
--	__u32 dqb_ihardlimit;	/* absolute limit on allocated inodes */
--	__u32 dqb_isoftlimit;	/* preferred inode limit */
--	__u32 dqb_curinodes;	/* current # allocated inodes */
-+	qsize_t dqb_ihardlimit;	/* absolute limit on allocated inodes */
-+	qsize_t dqb_isoftlimit;	/* preferred inode limit */
-+	qsize_t dqb_curinodes;	/* current # allocated inodes */
- 	time_t dqb_btime;	/* time limit for excessive disk use */
- 	time_t dqb_itime;	/* time limit for excessive inode use */
- };
-@@ -289,9 +285,9 @@ struct dquot_operations {
- 	int (*initialize) (struct inode *, int);
- 	int (*drop) (struct inode *);
- 	int (*alloc_space) (struct inode *, qsize_t, int);
--	int (*alloc_inode) (const struct inode *, unsigned long);
-+	int (*alloc_inode) (const struct inode *, qsize_t);
- 	int (*free_space) (struct inode *, qsize_t);
--	int (*free_inode) (const struct inode *, unsigned long);
-+	int (*free_inode) (const struct inode *, qsize_t);
- 	int (*transfer) (struct inode *, struct iattr *);
- 	int (*write_dquot) (struct dquot *);		/* Ordinary dquot write */
- 	struct dquot *(*alloc_dquot)(struct super_block *, int);	/* Allocate memory for new dquot (can be NULL if no special entries dquot are needed) */
-diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
-index ca6b9b5..9e7bc4b 100644
---- a/include/linux/quotaops.h
-+++ b/include/linux/quotaops.h
-@@ -29,10 +29,10 @@ int dquot_initialize(struct inode *inode, int type);
- int dquot_drop(struct inode *inode);
- 
- int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
--int dquot_alloc_inode(const struct inode *inode, unsigned long number);
-+int dquot_alloc_inode(const struct inode *inode, qsize_t number);
- 
- int dquot_free_space(struct inode *inode, qsize_t number);
--int dquot_free_inode(const struct inode *inode, unsigned long number);
-+int dquot_free_inode(const struct inode *inode, qsize_t number);
- 
- int dquot_transfer(struct inode *inode, struct iattr *iattr);
- int dquot_commit(struct dquot *dquot);
--- 
-1.5.2.4
-
diff --git a/lustre/kernel_patches/patches/quota-Split-off-quota-tree-handling-into-a-separate.patch b/lustre/kernel_patches/patches/quota-Split-off-quota-tree-handling-into-a-separate.patch
deleted file mode 100644
index cc7e6b2..0000000
--- a/lustre/kernel_patches/patches/quota-Split-off-quota-tree-handling-into-a-separate.patch
+++ /dev/null
@@ -1,1593 +0,0 @@
-From: Jan Kara <jack at suse.cz>
-References: fate#302681
-Subject: [PATCH 12/28] quota: Split off quota tree handling into a separate file
-Patch-mainline: 2.6.29?
-
-There is going to be a new version of quota format having 64-bit
-quota limits and a new quota format for OCFS2. They are both
-going to use the same tree structure as VFSv0 quota format. So
-split out tree handling into a separate file and make size of
-leaf blocks, amount of space usable in each block (needed for
-checksumming) and structures contained in them configurable
-so that the code can be shared.
-
-Signed-off-by: Jan Kara <jack at suse.cz>
----
- fs/Kconfig                  |    5 
- fs/Makefile                 |    1 
- fs/quota_tree.c             |  645 ++++++++++++++++++++++++++++++++++++++++++++
- fs/quota_tree.h             |   25 +
- fs/quota_v2.c               |  598 +++-------------------------------------
- fs/quotaio_v2.h             |   33 --
- include/linux/dqblk_qtree.h |   56 +++
- include/linux/dqblk_v2.h    |   19 -
- 8 files changed, 800 insertions(+), 582 deletions(-)
- create mode 100644 fs/quota_tree.c
- create mode 100644 fs/quota_tree.h
- create mode 100644 include/linux/dqblk_qtree.h
-
-Index: linux-2.6.27.36/fs/Kconfig
-===================================================================
---- linux-2.6.27.36.orig/fs/Kconfig	2009-10-05 17:19:01.000000000 +0200
-+++ linux-2.6.27.36/fs/Kconfig	2009-10-08 16:32:48.000000000 +0200
-@@ -569,6 +569,10 @@
- 	  Note that this behavior is currently deprecated and may go away in
- 	  future. Please use notification via netlink socket instead.
- 
-+# Generic support for tree structured quota files. Seleted when needed.
-+config QUOTA_TREE
-+	 tristate
-+
- config QFMT_V1
- 	tristate "Old quota format support"
- 	depends on QUOTA
-@@ -580,6 +584,7 @@
- config QFMT_V2
- 	tristate "Quota format v2 support"
- 	depends on QUOTA
-+	select QUOTA_TREE
- 	help
- 	  This quota format allows using quotas with 32-bit UIDs/GIDs. If you
- 	  need this functionality say Y here.
-Index: linux-2.6.27.36/fs/Makefile
-===================================================================
---- linux-2.6.27.36.orig/fs/Makefile	2009-10-05 17:19:01.000000000 +0200
-+++ linux-2.6.27.36/fs/Makefile	2009-10-08 16:32:48.000000000 +0200
-@@ -53,6 +53,7 @@
- obj-$(CONFIG_QUOTA)		+= dquot.o
- obj-$(CONFIG_QFMT_V1)		+= quota_v1.o
- obj-$(CONFIG_QFMT_V2)		+= quota_v2.o
-+obj-$(CONFIG_QUOTA_TREE)	+= quota_tree.o
- obj-$(CONFIG_QUOTACTL)		+= quota.o
- 
- obj-$(CONFIG_DNOTIFY)		+= dnotify.o
-Index: linux-2.6.27.36/include/linux/quotaio_v2.h
-===================================================================
---- linux-2.6.27.36.orig/include/linux/quotaio_v2.h	2009-10-05 17:19:01.000000000 +0200
-+++ linux-2.6.27.36/include/linux/quotaio_v2.h	2009-10-08 16:32:48.000000000 +0200
-@@ -21,6 +21,12 @@
- 	0		/* GRPQUOTA */\
- }
- 
-+/* First generic header */
-+struct v2_disk_dqheader {
-+	__le32 dqh_magic;	/* Magic number identifying file */
-+	__le32 dqh_version;	/* File version */
-+};
-+
- /*
-  * The following structure defines the format of the disk quota file
-  * (as it appears on disk) - the file is a radix tree whose leaves point
-@@ -38,15 +44,6 @@
- 	__le64 dqb_itime;	/* time limit for excessive inode use */
- };
- 
--/*
-- * Here are header structures as written on disk and their in-memory copies
-- */
--/* First generic header */
--struct v2_disk_dqheader {
--	__le32 dqh_magic;	/* Magic number identifying file */
--	__le32 dqh_version;	/* File version */
--};
--
- /* Header with type and version specific information */
- struct v2_disk_dqinfo {
- 	__le32 dqi_bgrace;	/* Time before block soft limit becomes hard limit */
-@@ -57,23 +54,7 @@
- 	__le32 dqi_free_entry;	/* Number of block with at least one free entry */
- };
- 
--/*
-- *  Structure of header of block with quota structures. It is padded to 16 bytes so
-- *  there will be space for exactly 21 quota-entries in a block
-- */
--struct v2_disk_dqdbheader {
--	__le32 dqdh_next_free;	/* Number of next block with free entry */
--	__le32 dqdh_prev_free;	/* Number of previous block with free entry */
--	__le16 dqdh_entries;	/* Number of valid entries in block */
--	__le16 dqdh_pad1;
--	__le32 dqdh_pad2;
--};
--
- #define V2_DQINFOOFF	sizeof(struct v2_disk_dqheader)	/* Offset of info header in file */
--#define V2_DQBLKSIZE_BITS	10
--#define V2_DQBLKSIZE	(1 << V2_DQBLKSIZE_BITS)	/* Size of block with quota structures */
--#define V2_DQTREEOFF	1		/* Offset of tree in file in blocks */
--#define V2_DQTREEDEPTH	4		/* Depth of quota tree */
--#define V2_DQSTRINBLK	((V2_DQBLKSIZE - sizeof(struct v2_disk_dqdbheader)) / sizeof(struct v2_disk_dqblk))	/* Number of entries in one blocks */
-+#define V2_DQBLKSIZE_BITS 10				/* Size of leaf block in tree */
- 
- #endif /* _LINUX_QUOTAIO_V2_H */
-Index: linux-2.6.27.36/fs/quota_tree.c
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.27.36/fs/quota_tree.c	2009-10-08 16:32:48.000000000 +0200
-@@ -0,0 +1,645 @@
-+/*
-+ *	vfsv0 quota IO operations on file
-+ */
-+
-+#include <linux/errno.h>
-+#include <linux/fs.h>
-+#include <linux/mount.h>
-+#include <linux/dqblk_v2.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/quotaops.h>
-+
-+#include <asm/byteorder.h>
-+
-+#include "quota_tree.h"
-+
-+MODULE_AUTHOR("Jan Kara");
-+MODULE_DESCRIPTION("Quota trie support");
-+MODULE_LICENSE("GPL");
-+
-+#define __QUOTA_QT_PARANOIA
-+
-+typedef char *dqbuf_t;
-+
-+static int get_index(struct qtree_mem_dqinfo *info, qid_t id, int depth)
-+{
-+	unsigned int epb = info->dqi_usable_bs >> 2;
-+
-+	depth = info->dqi_qtree_depth - depth - 1;
-+	while (depth--)
-+		id /= epb;
-+	return id % epb;
-+}
-+
-+/* Number of entries in one blocks */
-+static inline int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info)
-+{
-+	return (info->dqi_usable_bs - sizeof(struct qt_disk_dqdbheader))
-+	       / info->dqi_entry_size;
-+}
-+
-+static dqbuf_t getdqbuf(size_t size)
-+{
-+	dqbuf_t buf = kmalloc(size, GFP_NOFS);
-+	if (!buf)
-+		printk(KERN_WARNING "VFS: Not enough memory for quota buffers.\n");
-+	return buf;
-+}
-+
-+static inline void freedqbuf(dqbuf_t buf)
-+{
-+	kfree(buf);
-+}
-+
-+static inline ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, dqbuf_t buf)
-+{
-+	struct super_block *sb = info->dqi_sb;
-+
-+	memset(buf, 0, info->dqi_usable_bs);
-+	return sb->s_op->quota_read(sb, info->dqi_type, (char *)buf,
-+	       info->dqi_usable_bs, blk << info->dqi_blocksize_bits);
-+}
-+
-+static inline ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, dqbuf_t buf)
-+{
-+	struct super_block *sb = info->dqi_sb;
-+
-+	return sb->s_op->quota_write(sb, info->dqi_type, (char *)buf,
-+	       info->dqi_usable_bs, blk << info->dqi_blocksize_bits);
-+}
-+
-+/* Remove empty block from list and return it */
-+static int get_free_dqblk(struct qtree_mem_dqinfo *info)
-+{
-+	dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
-+	struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
-+	int ret, blk;
-+
-+	if (!buf)
-+		return -ENOMEM;
-+	if (info->dqi_free_blk) {
-+		blk = info->dqi_free_blk;
-+		ret = read_blk(info, blk, buf);
-+		if (ret < 0)
-+			goto out_buf;
-+		info->dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
-+	}
-+	else {
-+		memset(buf, 0, info->dqi_usable_bs);
-+		/* Assure block allocation... */
-+		ret = write_blk(info, info->dqi_blocks, buf);
-+		if (ret < 0)
-+			goto out_buf;
-+		blk = info->dqi_blocks++;
-+	}
-+	mark_info_dirty(info->dqi_sb, info->dqi_type);
-+	ret = blk;
-+out_buf:
-+	freedqbuf(buf);
-+	return ret;
-+}
-+
-+/* Insert empty block to the list */
-+static int put_free_dqblk(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk)
-+{
-+	struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
-+	int err;
-+
-+	dh->dqdh_next_free = cpu_to_le32(info->dqi_free_blk);
-+	dh->dqdh_prev_free = cpu_to_le32(0);
-+	dh->dqdh_entries = cpu_to_le16(0);
-+	err = write_blk(info, blk, buf);
-+	if (err < 0)
-+		return err;
-+	info->dqi_free_blk = blk;
-+	mark_info_dirty(info->dqi_sb, info->dqi_type);
-+	return 0;
-+}
-+
-+/* Remove given block from the list of blocks with free entries */
-+static int remove_free_dqentry(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk)
-+{
-+	dqbuf_t tmpbuf = getdqbuf(info->dqi_usable_bs);
-+	struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
-+	uint nextblk = le32_to_cpu(dh->dqdh_next_free);
-+	uint prevblk = le32_to_cpu(dh->dqdh_prev_free);
-+	int err;
-+
-+	if (!tmpbuf)
-+		return -ENOMEM;
-+	if (nextblk) {
-+		err = read_blk(info, nextblk, tmpbuf);
-+		if (err < 0)
-+			goto out_buf;
-+		((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
-+							dh->dqdh_prev_free;
-+		err = write_blk(info, nextblk, tmpbuf);
-+		if (err < 0)
-+			goto out_buf;
-+	}
-+	if (prevblk) {
-+		err = read_blk(info, prevblk, tmpbuf);
-+		if (err < 0)
-+			goto out_buf;
-+		((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_next_free =
-+							dh->dqdh_next_free;
-+		err = write_blk(info, prevblk, tmpbuf);
-+		if (err < 0)
-+			goto out_buf;
-+	} else {
-+		info->dqi_free_entry = nextblk;
-+		mark_info_dirty(info->dqi_sb, info->dqi_type);
-+	}
-+	freedqbuf(tmpbuf);
-+	dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
-+	/* No matter whether write succeeds block is out of list */
-+	if (write_blk(info, blk, buf) < 0)
-+		printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk);
-+	return 0;
-+out_buf:
-+	freedqbuf(tmpbuf);
-+	return err;
-+}
-+
-+/* Insert given block to the beginning of list with free entries */
-+static int insert_free_dqentry(struct qtree_mem_dqinfo *info, dqbuf_t buf, uint blk)
-+{
-+	dqbuf_t tmpbuf = getdqbuf(info->dqi_usable_bs);
-+	struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf;
-+	int err;
-+
-+	if (!tmpbuf)
-+		return -ENOMEM;
-+	dh->dqdh_next_free = cpu_to_le32(info->dqi_free_entry);
-+	dh->dqdh_prev_free = cpu_to_le32(0);
-+	err = write_blk(info, blk, buf);
-+	if (err < 0)
-+		goto out_buf;
-+	if (info->dqi_free_entry) {
-+		err = read_blk(info, info->dqi_free_entry, tmpbuf);
-+		if (err < 0)
-+			goto out_buf;
-+		((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
-+							cpu_to_le32(blk);
-+		err = write_blk(info, info->dqi_free_entry, tmpbuf);
-+		if (err < 0)
-+			goto out_buf;
-+	}
-+	freedqbuf(tmpbuf);
-+	info->dqi_free_entry = blk;
-+	mark_info_dirty(info->dqi_sb, info->dqi_type);
-+	return 0;
-+out_buf:
-+	freedqbuf(tmpbuf);
-+	return err;
-+}
-+
-+/* Is the entry in the block free? */
-+int qtree_entry_unused(struct qtree_mem_dqinfo *info, char *disk)
-+{
-+	int i;
-+
-+	for (i = 0; i < info->dqi_entry_size; i++)
-+		if (disk[i])
-+			return 0;
-+	return 1;
-+}
-+EXPORT_SYMBOL(qtree_entry_unused);
-+
-+/* Find space for dquot */
-+static uint find_free_dqentry(struct qtree_mem_dqinfo *info,
-+			      struct dquot *dquot, int *err)
-+{
-+	uint blk, i;
-+	struct qt_disk_dqdbheader *dh;
-+	dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
-+	char *ddquot;
-+
-+	*err = 0;
-+	if (!buf) {
-+		*err = -ENOMEM;
-+		return 0;
-+	}
-+	dh = (struct qt_disk_dqdbheader *)buf;
-+	if (info->dqi_free_entry) {
-+		blk = info->dqi_free_entry;
-+		*err = read_blk(info, blk, buf);
-+		if (*err < 0)
-+			goto out_buf;
-+	} else {
-+		blk = get_free_dqblk(info);
-+		if ((int)blk < 0) {
-+			*err = blk;
-+			freedqbuf(buf);
-+			return 0;
-+		}
-+		memset(buf, 0, info->dqi_usable_bs);
-+		/* This is enough as block is already zeroed and entry list is empty... */
-+		info->dqi_free_entry = blk;
-+		mark_info_dirty(dquot->dq_sb, dquot->dq_type);
-+	}
-+	/* Block will be full? */
-+	if (le16_to_cpu(dh->dqdh_entries) + 1 >= qtree_dqstr_in_blk(info)) {
-+		*err = remove_free_dqentry(info, buf, blk);
-+		if (*err < 0) {
-+			printk(KERN_ERR "VFS: find_free_dqentry(): Can't "
-+			       "remove block (%u) from entry free list.\n",
-+			       blk);
-+			goto out_buf;
-+		}
-+	}
-+	le16_add_cpu(&dh->dqdh_entries, 1);
-+	/* Find free structure in block */
-+	for (i = 0, ddquot = ((char *)buf) + sizeof(struct qt_disk_dqdbheader);
-+	     i < qtree_dqstr_in_blk(info) && !qtree_entry_unused(info, ddquot);
-+	     i++, ddquot += info->dqi_entry_size);
-+#ifdef __QUOTA_QT_PARANOIA
-+	if (i == qtree_dqstr_in_blk(info)) {
-+		printk(KERN_ERR "VFS: find_free_dqentry(): Data block full "
-+				"but it shouldn't.\n");
-+		*err = -EIO;
-+		goto out_buf;
-+	}
-+#endif
-+	*err = write_blk(info, blk, buf);
-+	if (*err < 0) {
-+		printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota "
-+				"data block %u.\n", blk);
-+		goto out_buf;
-+	}
-+	dquot->dq_off = (blk << info->dqi_blocksize_bits) +
-+			sizeof(struct qt_disk_dqdbheader) +
-+			i * info->dqi_entry_size;
-+	freedqbuf(buf);
-+	return blk;
-+out_buf:
-+	freedqbuf(buf);
-+	return 0;
-+}
-+
-+/* Insert reference to structure into the trie */
-+static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
-+			  uint *treeblk, int depth)
-+{
-+	dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
-+	int ret = 0, newson = 0, newact = 0;
-+	__le32 *ref;
-+	uint newblk;
-+
-+	if (!buf)
-+		return -ENOMEM;
-+	if (!*treeblk) {
-+		ret = get_free_dqblk(info);
-+		if (ret < 0)
-+			goto out_buf;
-+		*treeblk = ret;
-+		memset(buf, 0, info->dqi_usable_bs);
-+		newact = 1;
-+	} else {
-+		ret = read_blk(info, *treeblk, buf);
-+		if (ret < 0) {
-+			printk(KERN_ERR "VFS: Can't read tree quota block "
-+					"%u.\n", *treeblk);
-+			goto out_buf;
-+		}
-+	}
-+	ref = (__le32 *)buf;
-+	newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]);
-+	if (!newblk)
-+		newson = 1;
-+	if (depth == info->dqi_qtree_depth - 1) {
-+#ifdef __QUOTA_QT_PARANOIA
-+		if (newblk) {
-+			printk(KERN_ERR "VFS: Inserting already present quota "
-+					"entry (block %u).\n",
-+			       le32_to_cpu(ref[get_index(info,
-+						dquot->dq_id, depth)]));
-+			ret = -EIO;
-+			goto out_buf;
-+		}
-+#endif
-+		newblk = find_free_dqentry(info, dquot, &ret);
-+	} else {
-+		ret = do_insert_tree(info, dquot, &newblk, depth+1);
-+	}
-+	if (newson && ret >= 0) {
-+		ref[get_index(info, dquot->dq_id, depth)] =
-+							cpu_to_le32(newblk);
-+		ret = write_blk(info, *treeblk, buf);
-+	} else if (newact && ret < 0) {
-+		put_free_dqblk(info, buf, *treeblk);
-+	}
-+out_buf:
-+	freedqbuf(buf);
-+	return ret;
-+}
-+
-+/* Wrapper for inserting quota structure into tree */
-+static inline int dq_insert_tree(struct qtree_mem_dqinfo *info,
-+				 struct dquot *dquot)
-+{
-+	int tmp = QT_TREEOFF;
-+	return do_insert_tree(info, dquot, &tmp, 0);
-+}
-+
-+/*
-+ *	We don't have to be afraid of deadlocks as we never have quotas on quota files...
-+ */
-+int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
-+{
-+	int type = dquot->dq_type;
-+	struct super_block *sb = dquot->dq_sb;
-+	ssize_t ret;
-+	dqbuf_t ddquot = getdqbuf(info->dqi_entry_size);
-+
-+	if (!ddquot)
-+		return -ENOMEM;
-+
-+	/* dq_off is guarded by dqio_mutex */
-+	if (!dquot->dq_off) {
-+		ret = dq_insert_tree(info, dquot);
-+		if (ret < 0) {
-+			printk(KERN_ERR "VFS: Error %zd occurred while "
-+					"creating quota.\n", ret);
-+			freedqbuf(ddquot);
-+			return ret;
-+		}
-+	}
-+	spin_lock(&dq_data_lock);
-+	info->dqi_ops->mem2disk_dqblk(ddquot, dquot);
-+	spin_unlock(&dq_data_lock);
-+	ret = sb->s_op->quota_write(sb, type, (char *)ddquot,
-+					info->dqi_entry_size, dquot->dq_off);
-+	if (ret != info->dqi_entry_size) {
-+		printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
-+		       sb->s_id);
-+		if (ret >= 0)
-+			ret = -ENOSPC;
-+	} else {
-+		ret = 0;
-+	}
-+	dqstats.writes++;
-+	freedqbuf(ddquot);
-+
-+	return ret;
-+}
-+EXPORT_SYMBOL(qtree_write_dquot);
-+
-+/* Free dquot entry in data block */
-+static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot,
-+			uint blk)
-+{
-+	struct qt_disk_dqdbheader *dh;
-+	dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
-+	int ret = 0;
-+
-+	if (!buf)
-+		return -ENOMEM;
-+	if (dquot->dq_off >> info->dqi_blocksize_bits != blk) {
-+		printk(KERN_ERR "VFS: Quota structure has offset to other "
-+		  "block (%u) than it should (%u).\n", blk,
-+		  (uint)(dquot->dq_off >> info->dqi_blocksize_bits));
-+		goto out_buf;
-+	}
-+	ret = read_blk(info, blk, buf);
-+	if (ret < 0) {
-+		printk(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
-+		goto out_buf;
-+	}
-+	dh = (struct qt_disk_dqdbheader *)buf;
-+	le16_add_cpu(&dh->dqdh_entries, -1);
-+	if (!le16_to_cpu(dh->dqdh_entries)) {	/* Block got free? */
-+		ret = remove_free_dqentry(info, buf, blk);
-+		if (ret >= 0)
-+			ret = put_free_dqblk(info, buf, blk);
-+		if (ret < 0) {
-+			printk(KERN_ERR "VFS: Can't move quota data block (%u) "
-+			  "to free list.\n", blk);
-+			goto out_buf;
-+		}
-+	} else {
-+		memset(buf +
-+		       (dquot->dq_off & ((1 << info->dqi_blocksize_bits) - 1)),
-+		       0, info->dqi_entry_size);
-+		if (le16_to_cpu(dh->dqdh_entries) ==
-+		    qtree_dqstr_in_blk(info) - 1) {
-+			/* Insert will write block itself */
-+			ret = insert_free_dqentry(info, buf, blk);
-+			if (ret < 0) {
-+				printk(KERN_ERR "VFS: Can't insert quota data "
-+				       "block (%u) to free entry list.\n", blk);
-+				goto out_buf;
-+			}
-+		} else {
-+			ret = write_blk(info, blk, buf);
-+			if (ret < 0) {
-+				printk(KERN_ERR "VFS: Can't write quota data "
-+				  "block %u\n", blk);
-+				goto out_buf;
-+			}
-+		}
-+	}
-+	dquot->dq_off = 0;	/* Quota is now unattached */
-+out_buf:
-+	freedqbuf(buf);
-+	return ret;
-+}
-+
-+/* Remove reference to dquot from tree */
-+static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,
-+		       uint *blk, int depth)
-+{
-+	dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
-+	int ret = 0;
-+	uint newblk;
-+	__le32 *ref = (__le32 *)buf;
-+
-+	if (!buf)
-+		return -ENOMEM;
-+	ret = read_blk(info, *blk, buf);
-+	if (ret < 0) {
-+		printk(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
-+		goto out_buf;
-+	}
-+	newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]);
-+	if (depth == info->dqi_qtree_depth - 1) {
-+		ret = free_dqentry(info, dquot, newblk);
-+		newblk = 0;
-+	} else {
-+		ret = remove_tree(info, dquot, &newblk, depth+1);
-+	}
-+	if (ret >= 0 && !newblk) {
-+		int i;
-+		ref[get_index(info, dquot->dq_id, depth)] = cpu_to_le32(0);
-+		/* Block got empty? */
-+		for (i = 0;
-+		     i < (info->dqi_usable_bs >> 2) && !ref[i];
-+		     i++);
-+		/* Don't put the root block into the free block list */
-+		if (i == (info->dqi_usable_bs >> 2)
-+		    && *blk != QT_TREEOFF) {
-+			put_free_dqblk(info, buf, *blk);
-+			*blk = 0;
-+		} else {
-+			ret = write_blk(info, *blk, buf);
-+			if (ret < 0)
-+				printk(KERN_ERR "VFS: Can't write quota tree "
-+				  "block %u.\n", *blk);
-+		}
-+	}
-+out_buf:
-+	freedqbuf(buf);
-+	return ret;
-+}
-+
-+/* Delete dquot from tree */
-+int qtree_delete_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
-+{
-+	uint tmp = QT_TREEOFF;
-+
-+	if (!dquot->dq_off)	/* Even not allocated? */
-+		return 0;
-+	return remove_tree(info, dquot, &tmp, 0);
-+}
-+EXPORT_SYMBOL(qtree_delete_dquot);
-+
-+/* Find entry in block */
-+static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info,
-+				 struct dquot *dquot, uint blk)
-+{
-+	dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
-+	loff_t ret = 0;
-+	int i;
-+	char *ddquot;
-+
-+	if (!buf)
-+		return -ENOMEM;
-+	ret = read_blk(info, blk, buf);
-+	if (ret < 0) {
-+		printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
-+		goto out_buf;
-+	}
-+	for (i = 0, ddquot = ((char *)buf) + sizeof(struct qt_disk_dqdbheader);
-+	     i < qtree_dqstr_in_blk(info) && !info->dqi_ops->is_id(ddquot, dquot);
-+	     i++, ddquot += info->dqi_entry_size);
-+	if (i == qtree_dqstr_in_blk(info)) {
-+		printk(KERN_ERR "VFS: Quota for id %u referenced "
-+		  "but not present.\n", dquot->dq_id);
-+		ret = -EIO;
-+		goto out_buf;
-+	} else {
-+		ret = (blk << info->dqi_blocksize_bits) + sizeof(struct
-+		  qt_disk_dqdbheader) + i * info->dqi_entry_size;
-+	}
-+out_buf:
-+	freedqbuf(buf);
-+	return ret;
-+}
-+
-+/* Find entry for given id in the tree */
-+static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info,
-+				struct dquot *dquot, uint blk, int depth)
-+{
-+	dqbuf_t buf = getdqbuf(info->dqi_usable_bs);
-+	loff_t ret = 0;
-+	__le32 *ref = (__le32 *)buf;
-+
-+	if (!buf)
-+		return -ENOMEM;
-+	ret = read_blk(info, blk, buf);
-+	if (ret < 0) {
-+		printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
-+		goto out_buf;
-+	}
-+	ret = 0;
-+	blk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]);
-+	if (!blk)	/* No reference? */
-+		goto out_buf;
-+	if (depth < info->dqi_qtree_depth - 1)
-+		ret = find_tree_dqentry(info, dquot, blk, depth+1);
-+	else
-+		ret = find_block_dqentry(info, dquot, blk);
-+out_buf:
-+	freedqbuf(buf);
-+	return ret;
-+}
-+
-+/* Find entry for given id in the tree - wrapper function */
-+static inline loff_t find_dqentry(struct qtree_mem_dqinfo *info,
-+				  struct dquot *dquot)
-+{
-+	return find_tree_dqentry(info, dquot, QT_TREEOFF, 0);
-+}
-+
-+int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
-+{
-+	int type = dquot->dq_type;
-+	struct super_block *sb = dquot->dq_sb;
-+	loff_t offset;
-+	dqbuf_t ddquot;
-+	int ret = 0;
-+
-+#ifdef __QUOTA_QT_PARANOIA
-+	/* Invalidated quota? */
-+	if (!sb_dqopt(dquot->dq_sb)->files[type]) {
-+		printk(KERN_ERR "VFS: Quota invalidated while reading!\n");
-+		return -EIO;
-+	}
-+#endif
-+	/* Do we know offset of the dquot entry in the quota file? */
-+	if (!dquot->dq_off) {
-+		offset = find_dqentry(info, dquot);
-+		if (offset <= 0) {	/* Entry not present? */
-+			if (offset < 0)
-+				printk(KERN_ERR "VFS: Can't read quota "
-+				  "structure for id %u.\n", dquot->dq_id);
-+			dquot->dq_off = 0;
-+			set_bit(DQ_FAKE_B, &dquot->dq_flags);
-+			memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
-+			ret = offset;
-+			goto out;
-+		}
-+		dquot->dq_off = offset;
-+	}
-+	ddquot = getdqbuf(info->dqi_entry_size);
-+	if (!ddquot)
-+		return -ENOMEM;
-+	ret = sb->s_op->quota_read(sb, type, (char *)ddquot,
-+				   info->dqi_entry_size, dquot->dq_off);
-+	if (ret != info->dqi_entry_size) {
-+		if (ret >= 0)
-+			ret = -EIO;
-+		printk(KERN_ERR "VFS: Error while reading quota "
-+				"structure for id %u.\n", dquot->dq_id);
-+		set_bit(DQ_FAKE_B, &dquot->dq_flags);
-+		memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
-+		freedqbuf(ddquot);
-+		goto out;
-+	}
-+	spin_lock(&dq_data_lock);
-+	info->dqi_ops->disk2mem_dqblk(dquot, ddquot);
-+	if (!dquot->dq_dqb.dqb_bhardlimit &&
-+	    !dquot->dq_dqb.dqb_bsoftlimit &&
-+	    !dquot->dq_dqb.dqb_ihardlimit &&
-+	    !dquot->dq_dqb.dqb_isoftlimit)
-+		set_bit(DQ_FAKE_B, &dquot->dq_flags);
-+	spin_unlock(&dq_data_lock);
-+	freedqbuf(ddquot);
-+out:
-+	dqstats.reads++;
-+	return ret;
-+}
-+EXPORT_SYMBOL(qtree_read_dquot);
-+
-+/* Check whether dquot should not be deleted. We know we are
-+ * the only one operating on dquot (thanks to dq_lock) */
-+int qtree_release_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot)
-+{
-+	if (test_bit(DQ_FAKE_B, &dquot->dq_flags) && !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace))
-+		return qtree_delete_dquot(info, dquot);
-+	return 0;
-+}
-+EXPORT_SYMBOL(qtree_release_dquot);
-Index: linux-2.6.27.36/fs/quota_tree.h
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.27.36/fs/quota_tree.h	2009-10-08 16:32:48.000000000 +0200
-@@ -0,0 +1,25 @@
-+/*
-+ *	Definitions of structures for vfsv0 quota format
-+ */
-+
-+#ifndef _LINUX_QUOTA_TREE_H
-+#define _LINUX_QUOTA_TREE_H
-+
-+#include <linux/types.h>
-+#include <linux/quota.h>
-+
-+/*
-+ *  Structure of header of block with quota structures. It is padded to 16 bytes so
-+ *  there will be space for exactly 21 quota-entries in a block
-+ */
-+struct qt_disk_dqdbheader {
-+	__le32 dqdh_next_free;	/* Number of next block with free entry */
-+	__le32 dqdh_prev_free;	/* Number of previous block with free entry */
-+	__le16 dqdh_entries;	/* Number of valid entries in block */
-+	__le16 dqdh_pad1;
-+	__le32 dqdh_pad2;
-+};
-+
-+#define QT_TREEOFF	1		/* Offset of tree in file in blocks */
-+
-+#endif /* _LINUX_QUOTAIO_TREE_H */
-Index: linux-2.6.27.36/fs/quota_v2.c
-===================================================================
---- linux-2.6.27.36.orig/fs/quota_v2.c	2009-10-05 17:19:01.000000000 +0200
-+++ linux-2.6.27.36/fs/quota_v2.c	2009-10-08 16:34:36.000000000 +0200
-@@ -6,6 +6,7 @@
- #include <linux/fs.h>
- #include <linux/mount.h>
- #include <linux/dqblk_v2.h>
-+#include "quota_tree.h"
- #include <linux/quotaio_v2.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
-@@ -15,16 +16,22 @@
- 
- #include <asm/byteorder.h>
- 
-+
- MODULE_AUTHOR("Jan Kara");
- MODULE_DESCRIPTION("Quota format v2 support");
- MODULE_LICENSE("GPL");
- 
- #define __QUOTA_V2_PARANOIA
- 
--typedef char *dqbuf_t;
--
--#define GETIDINDEX(id, depth) (((id) >> ((V2_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
--#define GETENTRIES(buf) ((struct v2_disk_dqblk *)(((char *)buf)+sizeof(struct v2_disk_dqdbheader)))
-+static void v2_mem2diskdqb(void *dp, struct dquot *dquot);
-+static void v2_disk2memdqb(struct dquot *dquot, void *dp);
-+static int v2_is_id(void *dp, struct dquot *dquot);
-+
-+static struct qtree_fmt_operations v2_qtree_ops = {
-+	.mem2disk_dqblk = v2_mem2diskdqb,
-+	.disk2mem_dqblk = v2_disk2memdqb,
-+	.is_id = v2_is_id,
-+};
- 
- /* Check whether given file is really vfsv0 quotafile */
- static int v2_check_quota_file(struct super_block *sb, int type)
-@@ -50,7 +57,7 @@
- static int v2_read_file_info(struct super_block *sb, int type)
- {
- 	struct v2_disk_dqinfo dinfo;
--	struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
-+	struct mem_dqinfo *info = sb_dqinfo(sb, type);
- 	ssize_t size;
- 
- 	size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
-@@ -66,9 +73,16 @@
- 	info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
- 	info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
- 	info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
--	info->u.v2_i.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
--	info->u.v2_i.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
--	info->u.v2_i.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
-+	info->u.v2_i.i.dqi_sb = sb;
-+	info->u.v2_i.i.dqi_type = type;
-+	info->u.v2_i.i.dqi_blocks = le32_to_cpu(dinfo.dqi_blocks);
-+	info->u.v2_i.i.dqi_free_blk = le32_to_cpu(dinfo.dqi_free_blk);
-+	info->u.v2_i.i.dqi_free_entry = le32_to_cpu(dinfo.dqi_free_entry);
-+	info->u.v2_i.i.dqi_blocksize_bits = V2_DQBLKSIZE_BITS;
-+	info->u.v2_i.i.dqi_usable_bs = 1 << V2_DQBLKSIZE_BITS;
-+	info->u.v2_i.i.dqi_qtree_depth = qtree_depth(&info->u.v2_i.i);
-+	info->u.v2_i.i.dqi_entry_size = sizeof(struct v2_disk_dqblk);
-+	info->u.v2_i.i.dqi_ops = &v2_qtree_ops;
- 	return 0;
- }
- 
-@@ -76,7 +90,7 @@
- static int v2_write_file_info(struct super_block *sb, int type)
- {
- 	struct v2_disk_dqinfo dinfo;
--	struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
-+	struct mem_dqinfo *info = sb_dqinfo(sb, type);
- 	ssize_t size;
- 
- 	spin_lock(&dq_data_lock);
-@@ -85,9 +99,9 @@
- 	dinfo.dqi_igrace = cpu_to_le32(info->dqi_igrace);
- 	dinfo.dqi_flags = cpu_to_le32(info->dqi_flags & DQF_MASK);
- 	spin_unlock(&dq_data_lock);
--	dinfo.dqi_blocks = cpu_to_le32(info->u.v2_i.dqi_blocks);
--	dinfo.dqi_free_blk = cpu_to_le32(info->u.v2_i.dqi_free_blk);
--	dinfo.dqi_free_entry = cpu_to_le32(info->u.v2_i.dqi_free_entry);
-+	dinfo.dqi_blocks = cpu_to_le32(info->u.v2_i.i.dqi_blocks);
-+	dinfo.dqi_free_blk = cpu_to_le32(info->u.v2_i.i.dqi_free_blk);
-+	dinfo.dqi_free_entry = cpu_to_le32(info->u.v2_i.i.dqi_free_entry);
- 	size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
- 	       sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
- 	if (size != sizeof(struct v2_disk_dqinfo)) {
-@@ -98,8 +112,11 @@
- 	return 0;
- }
- 
--static void disk2memdqb(struct mem_dqblk *m, struct v2_disk_dqblk *d)
-+static void v2_disk2memdqb(struct dquot *dquot, void *dp)
- {
-+	struct v2_disk_dqblk *d = dp, empty;
-+	struct mem_dqblk *m = &dquot->dq_dqb;
-+
- 	m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit);
- 	m->dqb_isoftlimit = le32_to_cpu(d->dqb_isoftlimit);
- 	m->dqb_curinodes = le32_to_cpu(d->dqb_curinodes);
-@@ -108,10 +125,20 @@
- 	m->dqb_bsoftlimit = le32_to_cpu(d->dqb_bsoftlimit);
- 	m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
- 	m->dqb_btime = le64_to_cpu(d->dqb_btime);
-+	/* We need to escape back all-zero structure */
-+	memset(&empty, 0, sizeof(struct v2_disk_dqblk));
-+	empty.dqb_itime = cpu_to_le64(1);
-+	if (!memcmp(&empty, dp, sizeof(struct v2_disk_dqblk)))
-+		m->dqb_itime = 0;
- }
- 
--static void mem2diskdqb(struct v2_disk_dqblk *d, struct mem_dqblk *m, qid_t id)
-+static void v2_mem2diskdqb(void *dp, struct dquot *dquot)
- {
-+	struct v2_disk_dqblk *d = dp;
-+	struct mem_dqblk *m = &dquot->dq_dqb;
-+	struct qtree_mem_dqinfo *info =
-+			&sb_dqinfo(dquot->dq_sb, dquot->dq_type)->u.v2_i.i;
-+
- 	d->dqb_ihardlimit = cpu_to_le32(m->dqb_ihardlimit);
- 	d->dqb_isoftlimit = cpu_to_le32(m->dqb_isoftlimit);
- 	d->dqb_curinodes = cpu_to_le32(m->dqb_curinodes);
-@@ -120,553 +147,35 @@
- 	d->dqb_bsoftlimit = cpu_to_le32(m->dqb_bsoftlimit);
- 	d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
- 	d->dqb_btime = cpu_to_le64(m->dqb_btime);
--	d->dqb_id = cpu_to_le32(id);
--}
--
--static dqbuf_t getdqbuf(void)
--{
--	dqbuf_t buf = kmalloc(V2_DQBLKSIZE, GFP_NOFS);
--	if (!buf)
--		printk(KERN_WARNING "VFS: Not enough memory for quota buffers.\n");
--	return buf;
--}
--
--static inline void freedqbuf(dqbuf_t buf)
--{
--	kfree(buf);
--}
--
--static inline ssize_t read_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
--{
--	memset(buf, 0, V2_DQBLKSIZE);
--	return sb->s_op->quota_read(sb, type, (char *)buf,
--	       V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
--}
--
--static inline ssize_t write_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
--{
--	return sb->s_op->quota_write(sb, type, (char *)buf,
--	       V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
-+	d->dqb_id = cpu_to_le32(dquot->dq_id);
-+	if (qtree_entry_unused(info, dp))
-+		d->dqb_itime = cpu_to_le64(1);
- }
- 
--/* Remove empty block from list and return it */
--static int get_free_dqblk(struct super_block *sb, int type)
-+static int v2_is_id(void *dp, struct dquot *dquot)
- {
--	dqbuf_t buf = getdqbuf();
--	struct mem_dqinfo *info = sb_dqinfo(sb, type);
--	struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
--	int ret, blk;
-+	struct v2_disk_dqblk *d = dp;
-+	struct qtree_mem_dqinfo *info =
-+			&sb_dqinfo(dquot->dq_sb, dquot->dq_type)->u.v2_i.i;
- 
--	if (!buf)
--		return -ENOMEM;
--	if (info->u.v2_i.dqi_free_blk) {
--		blk = info->u.v2_i.dqi_free_blk;
--		if ((ret = read_blk(sb, type, blk, buf)) < 0)
--			goto out_buf;
--		info->u.v2_i.dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
--	}
--	else {
--		memset(buf, 0, V2_DQBLKSIZE);
--		/* Assure block allocation... */
--		if ((ret = write_blk(sb, type, info->u.v2_i.dqi_blocks, buf)) < 0)
--			goto out_buf;
--		blk = info->u.v2_i.dqi_blocks++;
--	}
--	mark_info_dirty(sb, type);
--	ret = blk;
--out_buf:
--	freedqbuf(buf);
--	return ret;
--}
--
--/* Insert empty block to the list */
--static int put_free_dqblk(struct super_block *sb, int type, dqbuf_t buf, uint blk)
--{
--	struct mem_dqinfo *info = sb_dqinfo(sb, type);
--	struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
--	int err;
--
--	dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_blk);
--	dh->dqdh_prev_free = cpu_to_le32(0);
--	dh->dqdh_entries = cpu_to_le16(0);
--	info->u.v2_i.dqi_free_blk = blk;
--	mark_info_dirty(sb, type);
--	/* Some strange block. We had better leave it... */
--	if ((err = write_blk(sb, type, blk, buf)) < 0)
--		return err;
--	return 0;
--}
--
--/* Remove given block from the list of blocks with free entries */
--static int remove_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
--{
--	dqbuf_t tmpbuf = getdqbuf();
--	struct mem_dqinfo *info = sb_dqinfo(sb, type);
--	struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
--	uint nextblk = le32_to_cpu(dh->dqdh_next_free), prevblk = le32_to_cpu(dh->dqdh_prev_free);
--	int err;
--
--	if (!tmpbuf)
--		return -ENOMEM;
--	if (nextblk) {
--		if ((err = read_blk(sb, type, nextblk, tmpbuf)) < 0)
--			goto out_buf;
--		((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = dh->dqdh_prev_free;
--		if ((err = write_blk(sb, type, nextblk, tmpbuf)) < 0)
--			goto out_buf;
--	}
--	if (prevblk) {
--		if ((err = read_blk(sb, type, prevblk, tmpbuf)) < 0)
--			goto out_buf;
--		((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_next_free = dh->dqdh_next_free;
--		if ((err = write_blk(sb, type, prevblk, tmpbuf)) < 0)
--			goto out_buf;
--	}
--	else {
--		info->u.v2_i.dqi_free_entry = nextblk;
--		mark_info_dirty(sb, type);
--	}
--	freedqbuf(tmpbuf);
--	dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
--	/* No matter whether write succeeds block is out of list */
--	if (write_blk(sb, type, blk, buf) < 0)
--		printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk);
--	return 0;
--out_buf:
--	freedqbuf(tmpbuf);
--	return err;
--}
--
--/* Insert given block to the beginning of list with free entries */
--static int insert_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
--{
--	dqbuf_t tmpbuf = getdqbuf();
--	struct mem_dqinfo *info = sb_dqinfo(sb, type);
--	struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
--	int err;
--
--	if (!tmpbuf)
--		return -ENOMEM;
--	dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_entry);
--	dh->dqdh_prev_free = cpu_to_le32(0);
--	if ((err = write_blk(sb, type, blk, buf)) < 0)
--		goto out_buf;
--	if (info->u.v2_i.dqi_free_entry) {
--		if ((err = read_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
--			goto out_buf;
--		((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = cpu_to_le32(blk);
--		if ((err = write_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
--			goto out_buf;
--	}
--	freedqbuf(tmpbuf);
--	info->u.v2_i.dqi_free_entry = blk;
--	mark_info_dirty(sb, type);
--	return 0;
--out_buf:
--	freedqbuf(tmpbuf);
--	return err;
--}
--
--/* Find space for dquot */
--static uint find_free_dqentry(struct dquot *dquot, int *err)
--{
--	struct super_block *sb = dquot->dq_sb;
--	struct mem_dqinfo *info = sb_dqopt(sb)->info+dquot->dq_type;
--	uint blk, i;
--	struct v2_disk_dqdbheader *dh;
--	struct v2_disk_dqblk *ddquot;
--	struct v2_disk_dqblk fakedquot;
--	dqbuf_t buf;
--
--	*err = 0;
--	if (!(buf = getdqbuf())) {
--		*err = -ENOMEM;
-+	if (qtree_entry_unused(info, dp))
- 		return 0;
--	}
--	dh = (struct v2_disk_dqdbheader *)buf;
--	ddquot = GETENTRIES(buf);
--	if (info->u.v2_i.dqi_free_entry) {
--		blk = info->u.v2_i.dqi_free_entry;
--		if ((*err = read_blk(sb, dquot->dq_type, blk, buf)) < 0)
--			goto out_buf;
--	}
--	else {
--		blk = get_free_dqblk(sb, dquot->dq_type);
--		if ((int)blk < 0) {
--			*err = blk;
--			freedqbuf(buf);
--			return 0;
--		}
--		memset(buf, 0, V2_DQBLKSIZE);
--		/* This is enough as block is already zeroed and entry list is empty... */
--		info->u.v2_i.dqi_free_entry = blk;
--		mark_info_dirty(sb, dquot->dq_type);
--	}
--	if (le16_to_cpu(dh->dqdh_entries)+1 >= V2_DQSTRINBLK)	/* Block will be full? */
--		if ((*err = remove_free_dqentry(sb, dquot->dq_type, buf, blk)) < 0) {
--			printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk);
--			goto out_buf;
--		}
--	le16_add_cpu(&dh->dqdh_entries, 1);
--	memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
--	/* Find free structure in block */
--	for (i = 0; i < V2_DQSTRINBLK && memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)); i++);
--#ifdef __QUOTA_V2_PARANOIA
--	if (i == V2_DQSTRINBLK) {
--		printk(KERN_ERR "VFS: find_free_dqentry(): Data block full but it shouldn't.\n");
--		*err = -EIO;
--		goto out_buf;
--	}
--#endif
--	if ((*err = write_blk(sb, dquot->dq_type, blk, buf)) < 0) {
--		printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota data block %u.\n", blk);
--		goto out_buf;
--	}
--	dquot->dq_off = (blk<<V2_DQBLKSIZE_BITS)+sizeof(struct v2_disk_dqdbheader)+i*sizeof(struct v2_disk_dqblk);
--	freedqbuf(buf);
--	return blk;
--out_buf:
--	freedqbuf(buf);
--	return 0;
--}
--
--/* Insert reference to structure into the trie */
--static int do_insert_tree(struct dquot *dquot, uint *treeblk, int depth)
--{
--	struct super_block *sb = dquot->dq_sb;
--	dqbuf_t buf;
--	int ret = 0, newson = 0, newact = 0;
--	__le32 *ref;
--	uint newblk;
--
--	if (!(buf = getdqbuf()))
--		return -ENOMEM;
--	if (!*treeblk) {
--		ret = get_free_dqblk(sb, dquot->dq_type);
--		if (ret < 0)
--			goto out_buf;
--		*treeblk = ret;
--		memset(buf, 0, V2_DQBLKSIZE);
--		newact = 1;
--	}
--	else {
--		if ((ret = read_blk(sb, dquot->dq_type, *treeblk, buf)) < 0) {
--			printk(KERN_ERR "VFS: Can't read tree quota block %u.\n", *treeblk);
--			goto out_buf;
--		}
--	}
--	ref = (__le32 *)buf;
--	newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
--	if (!newblk)
--		newson = 1;
--	if (depth == V2_DQTREEDEPTH-1) {
--#ifdef __QUOTA_V2_PARANOIA
--		if (newblk) {
--			printk(KERN_ERR "VFS: Inserting already present quota entry (block %u).\n", le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]));
--			ret = -EIO;
--			goto out_buf;
--		}
--#endif
--		newblk = find_free_dqentry(dquot, &ret);
--	}
--	else
--		ret = do_insert_tree(dquot, &newblk, depth+1);
--	if (newson && ret >= 0) {
--		ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(newblk);
--		ret = write_blk(sb, dquot->dq_type, *treeblk, buf);
--	}
--	else if (newact && ret < 0)
--		put_free_dqblk(sb, dquot->dq_type, buf, *treeblk);
--out_buf:
--	freedqbuf(buf);
--	return ret;
-+	return le32_to_cpu(d->dqb_id) == dquot->dq_id;
- }
- 
--/* Wrapper for inserting quota structure into tree */
--static inline int dq_insert_tree(struct dquot *dquot)
-+static int v2_read_dquot(struct dquot *dquot)
- {
--	int tmp = V2_DQTREEOFF;
--	return do_insert_tree(dquot, &tmp, 0);
-+	return qtree_read_dquot(&sb_dqinfo(dquot->dq_sb, dquot->dq_type)->u.v2_i.i, dquot);
- }
- 
--/*
-- *	We don't have to be afraid of deadlocks as we never have quotas on quota files...
-- */
- static int v2_write_dquot(struct dquot *dquot)
- {
--	int type = dquot->dq_type;
--	ssize_t ret;
--	struct v2_disk_dqblk ddquot, empty;
--
--	/* dq_off is guarded by dqio_mutex */
--	if (!dquot->dq_off)
--		if ((ret = dq_insert_tree(dquot)) < 0) {
--			printk(KERN_ERR "VFS: Error %zd occurred while creating quota.\n", ret);
--			return ret;
--		}
--	spin_lock(&dq_data_lock);
--	mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
--	/* Argh... We may need to write structure full of zeroes but that would be
--	 * treated as an empty place by the rest of the code. Format change would
--	 * be definitely cleaner but the problems probably are not worth it */
--	memset(&empty, 0, sizeof(struct v2_disk_dqblk));
--	if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
--		ddquot.dqb_itime = cpu_to_le64(1);
--	spin_unlock(&dq_data_lock);
--	ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
--	      (char *)&ddquot, sizeof(struct v2_disk_dqblk), dquot->dq_off);
--	if (ret != sizeof(struct v2_disk_dqblk)) {
--		printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", dquot->dq_sb->s_id);
--		if (ret >= 0)
--			ret = -ENOSPC;
--	}
--	else
--		ret = 0;
--	dqstats.writes++;
--
--	return ret;
--}
--
--/* Free dquot entry in data block */
--static int free_dqentry(struct dquot *dquot, uint blk)
--{
--	struct super_block *sb = dquot->dq_sb;
--	int type = dquot->dq_type;
--	struct v2_disk_dqdbheader *dh;
--	dqbuf_t buf = getdqbuf();
--	int ret = 0;
--
--	if (!buf)
--		return -ENOMEM;
--	if (dquot->dq_off >> V2_DQBLKSIZE_BITS != blk) {
--		printk(KERN_ERR "VFS: Quota structure has offset to other "
--		  "block (%u) than it should (%u).\n", blk,
--		  (uint)(dquot->dq_off >> V2_DQBLKSIZE_BITS));
--		goto out_buf;
--	}
--	if ((ret = read_blk(sb, type, blk, buf)) < 0) {
--		printk(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
--		goto out_buf;
--	}
--	dh = (struct v2_disk_dqdbheader *)buf;
--	le16_add_cpu(&dh->dqdh_entries, -1);
--	if (!le16_to_cpu(dh->dqdh_entries)) {	/* Block got free? */
--		if ((ret = remove_free_dqentry(sb, type, buf, blk)) < 0 ||
--		    (ret = put_free_dqblk(sb, type, buf, blk)) < 0) {
--			printk(KERN_ERR "VFS: Can't move quota data block (%u) "
--			  "to free list.\n", blk);
--			goto out_buf;
--		}
--	}
--	else {
--		memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0,
--		  sizeof(struct v2_disk_dqblk));
--		if (le16_to_cpu(dh->dqdh_entries) == V2_DQSTRINBLK-1) {
--			/* Insert will write block itself */
--			if ((ret = insert_free_dqentry(sb, type, buf, blk)) < 0) {
--				printk(KERN_ERR "VFS: Can't insert quota data block (%u) to free entry list.\n", blk);
--				goto out_buf;
--			}
--		}
--		else
--			if ((ret = write_blk(sb, type, blk, buf)) < 0) {
--				printk(KERN_ERR "VFS: Can't write quota data "
--				  "block %u\n", blk);
--				goto out_buf;
--			}
--	}
--	dquot->dq_off = 0;	/* Quota is now unattached */
--out_buf:
--	freedqbuf(buf);
--	return ret;
--}
--
--/* Remove reference to dquot from tree */
--static int remove_tree(struct dquot *dquot, uint *blk, int depth)
--{
--	struct super_block *sb = dquot->dq_sb;
--	int type = dquot->dq_type;
--	dqbuf_t buf = getdqbuf();
--	int ret = 0;
--	uint newblk;
--	__le32 *ref = (__le32 *)buf;
--	
--	if (!buf)
--		return -ENOMEM;
--	if ((ret = read_blk(sb, type, *blk, buf)) < 0) {
--		printk(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
--		goto out_buf;
--	}
--	newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
--	if (depth == V2_DQTREEDEPTH-1) {
--		ret = free_dqentry(dquot, newblk);
--		newblk = 0;
--	}
--	else
--		ret = remove_tree(dquot, &newblk, depth+1);
--	if (ret >= 0 && !newblk) {
--		int i;
--		ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0);
--		for (i = 0; i < V2_DQBLKSIZE && !buf[i]; i++);	/* Block got empty? */
--		/* Don't put the root block into the free block list */
--		if (i == V2_DQBLKSIZE && *blk != V2_DQTREEOFF) {
--			put_free_dqblk(sb, type, buf, *blk);
--			*blk = 0;
--		}
--		else
--			if ((ret = write_blk(sb, type, *blk, buf)) < 0)
--				printk(KERN_ERR "VFS: Can't write quota tree "
--				  "block %u.\n", *blk);
--	}
--out_buf:
--	freedqbuf(buf);
--	return ret;	
--}
--
--/* Delete dquot from tree */
--static int v2_delete_dquot(struct dquot *dquot)
--{
--	uint tmp = V2_DQTREEOFF;
--
--	if (!dquot->dq_off)	/* Even not allocated? */
--		return 0;
--	return remove_tree(dquot, &tmp, 0);
--}
--
--/* Find entry in block */
--static loff_t find_block_dqentry(struct dquot *dquot, uint blk)
--{
--	dqbuf_t buf = getdqbuf();
--	loff_t ret = 0;
--	int i;
--	struct v2_disk_dqblk *ddquot = GETENTRIES(buf);
--
--	if (!buf)
--		return -ENOMEM;
--	if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
--		printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
--		goto out_buf;
--	}
--	if (dquot->dq_id)
--		for (i = 0; i < V2_DQSTRINBLK &&
--		     le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++);
--	else {	/* ID 0 as a bit more complicated searching... */
--		struct v2_disk_dqblk fakedquot;
--
--		memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
--		for (i = 0; i < V2_DQSTRINBLK; i++)
--			if (!le32_to_cpu(ddquot[i].dqb_id) &&
--			    memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)))
--				break;
--	}
--	if (i == V2_DQSTRINBLK) {
--		printk(KERN_ERR "VFS: Quota for id %u referenced "
--		  "but not present.\n", dquot->dq_id);
--		ret = -EIO;
--		goto out_buf;
--	}
--	else
--		ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct
--		  v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
--out_buf:
--	freedqbuf(buf);
--	return ret;
--}
--
--/* Find entry for given id in the tree */
--static loff_t find_tree_dqentry(struct dquot *dquot, uint blk, int depth)
--{
--	dqbuf_t buf = getdqbuf();
--	loff_t ret = 0;
--	__le32 *ref = (__le32 *)buf;
--
--	if (!buf)
--		return -ENOMEM;
--	if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
--		printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
--		goto out_buf;
--	}
--	ret = 0;
--	blk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
--	if (!blk)	/* No reference? */
--		goto out_buf;
--	if (depth < V2_DQTREEDEPTH-1)
--		ret = find_tree_dqentry(dquot, blk, depth+1);
--	else
--		ret = find_block_dqentry(dquot, blk);
--out_buf:
--	freedqbuf(buf);
--	return ret;
-+	return qtree_write_dquot(&sb_dqinfo(dquot->dq_sb, dquot->dq_type)->u.v2_i.i, dquot);
- }
- 
--/* Find entry for given id in the tree - wrapper function */
--static inline loff_t find_dqentry(struct dquot *dquot)
--{
--	return find_tree_dqentry(dquot, V2_DQTREEOFF, 0);
--}
--
--static int v2_read_dquot(struct dquot *dquot)
--{
--	int type = dquot->dq_type;
--	loff_t offset;
--	struct v2_disk_dqblk ddquot, empty;
--	int ret = 0;
--
--#ifdef __QUOTA_V2_PARANOIA
--	/* Invalidated quota? */
--	if (!dquot->dq_sb || !sb_dqopt(dquot->dq_sb)->files[type]) {
--		printk(KERN_ERR "VFS: Quota invalidated while reading!\n");
--		return -EIO;
--	}
--#endif
--	offset = find_dqentry(dquot);
--	if (offset <= 0) {	/* Entry not present? */
--		if (offset < 0)
--			printk(KERN_ERR "VFS: Can't read quota "
--			  "structure for id %u.\n", dquot->dq_id);
--		dquot->dq_off = 0;
--		set_bit(DQ_FAKE_B, &dquot->dq_flags);
--		memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
--		ret = offset;
--	}
--	else {
--		dquot->dq_off = offset;
--		if ((ret = dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type,
--		    (char *)&ddquot, sizeof(struct v2_disk_dqblk), offset))
--		    != sizeof(struct v2_disk_dqblk)) {
--			if (ret >= 0)
--				ret = -EIO;
--			printk(KERN_ERR "VFS: Error while reading quota "
--			  "structure for id %u.\n", dquot->dq_id);
--			memset(&ddquot, 0, sizeof(struct v2_disk_dqblk));
--		}
--		else {
--			ret = 0;
--			/* We need to escape back all-zero structure */
--			memset(&empty, 0, sizeof(struct v2_disk_dqblk));
--			empty.dqb_itime = cpu_to_le64(1);
--			if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
--				ddquot.dqb_itime = 0;
--		}
--		disk2memdqb(&dquot->dq_dqb, &ddquot);
--		if (!dquot->dq_dqb.dqb_bhardlimit &&
--			!dquot->dq_dqb.dqb_bsoftlimit &&
--			!dquot->dq_dqb.dqb_ihardlimit &&
--			!dquot->dq_dqb.dqb_isoftlimit)
--			set_bit(DQ_FAKE_B, &dquot->dq_flags);
--	}
--	dqstats.reads++;
--
--	return ret;
--}
--
--/* Check whether dquot should not be deleted. We know we are
-- * the only one operating on dquot (thanks to dq_lock) */
- static int v2_release_dquot(struct dquot *dquot)
- {
--	if (test_bit(DQ_FAKE_B, &dquot->dq_flags) && !(dquot->dq_dqb.dqb_curinodes | dquot->dq_dqb.dqb_curspace))
--		return v2_delete_dquot(dquot);
--	return 0;
-+	return qtree_release_dquot(&sb_dqinfo(dquot->dq_sb, dquot->dq_type)->u.v2_i.i, dquot);
- }
- 
- static struct quota_format_ops v2_format_ops = {
-Index: linux-2.6.27.36/include/linux/dqblk_qtree.h
-===================================================================
---- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.27.36/include/linux/dqblk_qtree.h	2009-10-08 16:32:48.000000000 +0200
-@@ -0,0 +1,56 @@
-+/*
-+ *	Definitions of structures and functions for quota formats using trie
-+ */
-+
-+#ifndef _LINUX_DQBLK_QTREE_H
-+#define _LINUX_DQBLK_QTREE_H
-+
-+#include <linux/types.h>
-+
-+/* Numbers of blocks needed for updates - we count with the smallest
-+ * possible block size (1024) */
-+#define QTREE_INIT_ALLOC 4
-+#define QTREE_INIT_REWRITE 2
-+#define QTREE_DEL_ALLOC 0
-+#define QTREE_DEL_REWRITE 6
-+
-+struct dquot;
-+
-+/* Operations */
-+struct qtree_fmt_operations {
-+	void (*mem2disk_dqblk)(void *disk, struct dquot *dquot);	/* Convert given entry from in memory format to disk one */
-+	void (*disk2mem_dqblk)(struct dquot *dquot, void *disk);	/* Convert given entry from disk format to in memory one */
-+	int (*is_id)(void *disk, struct dquot *dquot);	/* Is this structure for given id? */
-+};
-+
-+/* Inmemory copy of version specific information */
-+struct qtree_mem_dqinfo {
-+	struct super_block *dqi_sb;	/* Sb quota is on */
-+	int dqi_type;			/* Quota type */
-+	unsigned int dqi_blocks;	/* # of blocks in quota file */
-+	unsigned int dqi_free_blk;	/* First block in list of free blocks */
-+	unsigned int dqi_free_entry;	/* First block with free entry */
-+	unsigned int dqi_blocksize_bits;	/* Block size of quota file */
-+	unsigned int dqi_entry_size;	/* Size of quota entry in quota file */
-+	unsigned int dqi_usable_bs;	/* Space usable in block for quota data */
-+	unsigned int dqi_qtree_depth;	/* Precomputed depth of quota tree */
-+	struct qtree_fmt_operations *dqi_ops;	/* Operations for entry manipulation */
-+};
-+
-+int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot);
-+int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot);
-+int qtree_delete_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot);
-+int qtree_release_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot);
-+int qtree_entry_unused(struct qtree_mem_dqinfo *info, char *disk);
-+static inline int qtree_depth(struct qtree_mem_dqinfo *info)
-+{
-+	unsigned int epb = info->dqi_usable_bs >> 2;
-+	unsigned long long entries = epb;
-+	int i;
-+
-+	for (i = 1; entries < (1ULL << 32); i++)
-+		entries *= epb;
-+	return i;
-+}
-+
-+#endif /* _LINUX_DQBLK_QTREE_H */
-Index: linux-2.6.27.36/include/linux/dqblk_v2.h
-===================================================================
---- linux-2.6.27.36.orig/include/linux/dqblk_v2.h	2009-10-05 17:19:01.000000000 +0200
-+++ linux-2.6.27.36/include/linux/dqblk_v2.h	2009-10-08 16:32:48.000000000 +0200
-@@ -1,26 +1,23 @@
- /*
-- *	Definitions of structures for vfsv0 quota format
-+ *  Definitions for vfsv0 quota format
-  */
- 
- #ifndef _LINUX_DQBLK_V2_H
- #define _LINUX_DQBLK_V2_H
- 
--#include <linux/types.h>
-+#include <linux/dqblk_qtree.h>
- 
--/* id numbers of quota format */
-+/* Id number of quota format */
- #define QFMT_VFS_V0 2
- 
- /* Numbers of blocks needed for updates */
--#define V2_INIT_ALLOC 4
--#define V2_INIT_REWRITE 2
--#define V2_DEL_ALLOC 0
--#define V2_DEL_REWRITE 6
-+#define V2_INIT_ALLOC QTREE_INIT_ALLOC
-+#define V2_INIT_REWRITE QTREE_INIT_REWRITE
-+#define V2_DEL_ALLOC QTREE_DEL_ALLOC
-+#define V2_DEL_REWRITE QTREE_DEL_REWRITE
- 
--/* Inmemory copy of version specific information */
- struct v2_mem_dqinfo {
--	unsigned int dqi_blocks;
--	unsigned int dqi_free_blk;
--	unsigned int dqi_free_entry;
-+	struct qtree_mem_dqinfo i;
- };
- 
- #endif /* _LINUX_DQBLK_V2_H */
diff --git a/lustre/kernel_patches/patches/quota-support-64-bit-quota-format-2.6.27-vanilla.patch b/lustre/kernel_patches/patches/quota-support-64-bit-quota-format-2.6.27-vanilla.patch
deleted file mode 100644
index dcdff82..0000000
--- a/lustre/kernel_patches/patches/quota-support-64-bit-quota-format-2.6.27-vanilla.patch
+++ /dev/null
@@ -1,282 +0,0 @@
-From: Jan Kara <jack at suse.cz>
-
-Implement conversion functions for new version (version 1) of quota format
-which supports 64-bit block and inode limits and 64-bit inode usage.  The
-original implementation has been written by Andrew Perepechko.
-
-Signed-off-by: Andrew Perepechko <andrew.perepechko at sun.com>
-Signed-off-by: Jan Kara <jack at suse.cz>
-Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
----
-
- fs/quota_v2.c   |  140 ++++++++++++++++++++++++++++++++++++----------
- fs/quotaio_v2.h |   26 ++++++--
- 2 files changed, 132 insertions(+), 34 deletions(-)
-
-Index: linux-2.6.27.36/fs/quota_v2.c
-===================================================================
---- linux-2.6.27.36.orig/fs/quota_v2.c	2009-10-09 17:00:48.000000000 +0200
-+++ linux-2.6.27.36/fs/quota_v2.c	2009-10-09 17:03:35.000000000 +0200
-@@ -23,14 +23,24 @@
- 
- #define __QUOTA_V2_PARANOIA
- 
--static void v2_mem2diskdqb(void *dp, struct dquot *dquot);
--static void v2_disk2memdqb(struct dquot *dquot, void *dp);
--static int v2_is_id(void *dp, struct dquot *dquot);
--
--static struct qtree_fmt_operations v2_qtree_ops = {
--	.mem2disk_dqblk = v2_mem2diskdqb,
--	.disk2mem_dqblk = v2_disk2memdqb,
--	.is_id = v2_is_id,
-+static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot);
-+static void v2r0_disk2memdqb(struct dquot *dquot, void *dp);
-+static int v2r0_is_id(void *dp, struct dquot *dquot);
-+
-+static struct qtree_fmt_operations v2r0_qtree_ops = {
-+      .mem2disk_dqblk = v2r0_mem2diskdqb,
-+      .disk2mem_dqblk = v2r0_disk2memdqb,
-+      .is_id = v2r0_is_id,
-+};
-+
-+static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot);
-+static void v2r1_disk2memdqb(struct dquot *dquot, void *dp);
-+static int v2r1_is_id(void *dp, struct dquot *dquot);
-+
-+static struct qtree_fmt_operations v2r1_qtree_ops = {
-+      .mem2disk_dqblk = v2r1_mem2diskdqb,
-+      .disk2mem_dqblk = v2r1_disk2memdqb,
-+      .is_id = v2r1_is_id,
- };
- 
- #define QUOTABLOCK_BITS 10
-@@ -46,8 +56,7 @@
- 	return blocks << QUOTABLOCK_BITS;
- }
- 
--/* Check whether given file is really vfsv0 quotafile */
--static int v2_check_quota_file(struct super_block *sb, int type)
-+static int v2_check_quota_file_header(struct super_block *sb, int type)
- {
- 	struct v2_disk_dqheader dqhead;
- 	ssize_t size;
-@@ -58,12 +67,20 @@
- 	if (size != sizeof(struct v2_disk_dqheader)) {
- 		printk("quota_v2: failed read expected=%zd got=%zd\n",
- 			sizeof(struct v2_disk_dqheader), size);
--		return 0;
-+		return -EIO;
- 	}
--	if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
--	    le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
--		return 0;
--	return 1;
-+	if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type])
-+		return -ENOENT;
-+	if (le32_to_cpu(dqhead.dqh_version) > quota_versions[type])
-+		return -EOPNOTSUPP;
-+	return le32_to_cpu(dqhead.dqh_version);
-+}
-+
-+
-+/* Check whether given file is really vfsv0 quotafile */
-+static int v2_check_quota_file(struct super_block *sb, int type)
-+{
-+	return v2_check_quota_file_header(sb, type) >= 0;
- }
- 
- /* Read information header from quota file */
-@@ -72,7 +89,13 @@
- 	struct v2_disk_dqinfo dinfo;
- 	struct mem_dqinfo *info = sb_dqinfo(sb, type);
- 	ssize_t size;
-+	int version = v2_check_quota_file_header(sb, type);
- 
-+	if (version < 0) {
-+		printk(KERN_WARNING "Cannot identify quota file version on "
-+		       "device %s: %d\n", sb->s_id, version);
-+		return -1;
-+	}
- 	size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
- 	       sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
- 	if (size != sizeof(struct v2_disk_dqinfo)) {
-@@ -81,8 +104,14 @@
- 		return -1;
- 	}
- 	/* limits are stored as unsigned 32-bit data */
--	info->dqi_maxblimit = 0xffffffff;
--	info->dqi_maxilimit = 0xffffffff;
-+        if (version == 0) {
-+                /* limits are stored as unsigned 32-bit data */
-+                info->dqi_maxblimit = 0xffffffff;
-+                info->dqi_maxilimit = 0xffffffff;
-+        } else {
-+                info->dqi_maxblimit = 0x7fffffffffffffffULL;
-+                info->dqi_maxilimit = 0x7fffffffffffffffULL;
-+        }
- 	info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
- 	info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
- 	info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
-@@ -94,8 +123,13 @@
- 	info->u.v2_i.i.dqi_blocksize_bits = V2_DQBLKSIZE_BITS;
- 	info->u.v2_i.i.dqi_usable_bs = 1 << V2_DQBLKSIZE_BITS;
- 	info->u.v2_i.i.dqi_qtree_depth = qtree_depth(&info->u.v2_i.i);
--	info->u.v2_i.i.dqi_entry_size = sizeof(struct v2_disk_dqblk);
--	info->u.v2_i.i.dqi_ops = &v2_qtree_ops;
-+        if (version == 0) {
-+                qinfo->dqi_entry_size = sizeof(struct v2r0_disk_dqblk);
-+                qinfo->dqi_ops = &v2r0_qtree_ops;
-+        } else {
-+                qinfo->dqi_entry_size = sizeof(struct v2r1_disk_dqblk);
-+                qinfo->dqi_ops = &v2r1_qtree_ops;
-+        }
- 	return 0;
- }
- 
-@@ -125,9 +159,9 @@
- 	return 0;
- }
- 
--static void v2_disk2memdqb(struct dquot *dquot, void *dp)
-+static void v2r0_disk2memdqb(struct dquot *dquot, void *dp)
- {
--	struct v2_disk_dqblk *d = dp, empty;
-+	struct v2r0_disk_dqblk *d = dp, empty;
- 	struct mem_dqblk *m = &dquot->dq_dqb;
- 
- 	m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit);
-@@ -139,15 +173,15 @@
- 	m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
- 	m->dqb_btime = le64_to_cpu(d->dqb_btime);
- 	/* We need to escape back all-zero structure */
--	memset(&empty, 0, sizeof(struct v2_disk_dqblk));
-+	memset(&empty, 0, sizeof(struct v2r0_disk_dqblk));
- 	empty.dqb_itime = cpu_to_le64(1);
--	if (!memcmp(&empty, dp, sizeof(struct v2_disk_dqblk)))
-+	if (!memcmp(&empty, dp, sizeof(struct v2r0_disk_dqblk)))
- 		m->dqb_itime = 0;
- }
- 
--static void v2_mem2diskdqb(void *dp, struct dquot *dquot)
-+static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot)
- {
--	struct v2_disk_dqblk *d = dp;
-+	struct v2r0_disk_dqblk *d = dp;
- 	struct mem_dqblk *m = &dquot->dq_dqb;
- 	struct qtree_mem_dqinfo *info =
- 			&sb_dqinfo(dquot->dq_sb, dquot->dq_type)->u.v2_i.i;
-@@ -165,9 +199,60 @@
- 		d->dqb_itime = cpu_to_le64(1);
- }
- 
--static int v2_is_id(void *dp, struct dquot *dquot)
-+static int v2r0_is_id(void *dp, struct dquot *dquot)
-+{
-+	struct v2r0_disk_dqblk *d = dp;
-+	struct qtree_mem_dqinfo *info =
-+			sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
-+
-+	if (qtree_entry_unused(info, dp))
-+		return 0;
-+	return le32_to_cpu(d->dqb_id) == dquot->dq_id;
-+}
-+
-+static void v2r1_disk2memdqb(struct dquot *dquot, void *dp)
-+{
-+	struct v2r1_disk_dqblk *d = dp, empty;
-+	struct mem_dqblk *m = &dquot->dq_dqb;
-+
-+	m->dqb_ihardlimit = le64_to_cpu(d->dqb_ihardlimit);
-+	m->dqb_isoftlimit = le64_to_cpu(d->dqb_isoftlimit);
-+	m->dqb_curinodes = le64_to_cpu(d->dqb_curinodes);
-+	m->dqb_itime = le64_to_cpu(d->dqb_itime);
-+	m->dqb_bhardlimit = v2_qbtos(le64_to_cpu(d->dqb_bhardlimit));
-+	m->dqb_bsoftlimit = v2_qbtos(le64_to_cpu(d->dqb_bsoftlimit));
-+	m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
-+	m->dqb_btime = le64_to_cpu(d->dqb_btime);
-+	/* We need to escape back all-zero structure */
-+	memset(&empty, 0, sizeof(struct v2r1_disk_dqblk));
-+	empty.dqb_itime = cpu_to_le64(1);
-+	if (!memcmp(&empty, dp, sizeof(struct v2r1_disk_dqblk)))
-+		m->dqb_itime = 0;
-+}
-+
-+static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot)
-+{
-+	struct v2r1_disk_dqblk *d = dp;
-+	struct mem_dqblk *m = &dquot->dq_dqb;
-+	struct qtree_mem_dqinfo *info =
-+			sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
-+
-+	d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
-+	d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
-+	d->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
-+	d->dqb_itime = cpu_to_le64(m->dqb_itime);
-+	d->dqb_bhardlimit = cpu_to_le64(v2_stoqb(m->dqb_bhardlimit));
-+	d->dqb_bsoftlimit = cpu_to_le64(v2_stoqb(m->dqb_bsoftlimit));
-+	d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
-+	d->dqb_btime = cpu_to_le64(m->dqb_btime);
-+	d->dqb_id = cpu_to_le32(dquot->dq_id);
-+	if (qtree_entry_unused(info, dp))
-+		d->dqb_itime = cpu_to_le64(1);
-+}
-+
-+static int v2r1_is_id(void *dp, struct dquot *dquot)
- {
--	struct v2_disk_dqblk *d = dp;
-+	struct v2r1_disk_dqblk *d = dp;
- 	struct qtree_mem_dqinfo *info =
- 			&sb_dqinfo(dquot->dq_sb, dquot->dq_type)->u.v2_i.i;
- 
-Index: linux-2.6.27.36/include/linux/quotaio_v2.h
-===================================================================
---- linux-2.6.27.36.orig/include/linux/quotaio_v2.h	2009-10-09 17:00:48.000000000 +0200
-+++ linux-2.6.27.36/include/linux/quotaio_v2.h	2009-10-09 17:00:56.000000000 +0200
-@@ -17,8 +17,8 @@
- }
- 
- #define V2_INITQVERSIONS {\
--	0,		/* USRQUOTA */\
--	0		/* GRPQUOTA */\
-+	1,		/* USRQUOTA */\
-+	1		/* GRPQUOTA */\
- }
- 
- /* First generic header */
-@@ -28,11 +28,11 @@
- };
- 
- /*
-- * The following structure defines the format of the disk quota file
-- * (as it appears on disk) - the file is a radix tree whose leaves point
-- * to blocks of these structures.
-+ * The following structure defines the format of the disk quota file in version
-+ * 0 - the file is a radix tree whose leaves point to blocks of these
-+ * structures.
-  */
--struct v2_disk_dqblk {
-+struct v2r0_disk_dqblk {
- 	__le32 dqb_id;		/* id this quota applies to */
- 	__le32 dqb_ihardlimit;	/* absolute limit on allocated inodes */
- 	__le32 dqb_isoftlimit;	/* preferred inode limit */
-@@ -44,6 +44,20 @@
- 	__le64 dqb_itime;	/* time limit for excessive inode use */
- };
- 
-+/* The same structure in quota file version 1 */
-+struct v2r1_disk_dqblk {
-+	__le32 dqb_id;		/* id this quota applies to */
-+	__le32 dqb_padding;	/* padding field */
-+	__le64 dqb_ihardlimit;	/* absolute limit on allocated inodes */
-+	__le64 dqb_isoftlimit;	/* preferred inode limit */
-+	__le64 dqb_curinodes;	/* current # allocated inodes */
-+	__le64 dqb_bhardlimit;	/* absolute limit on disk space */
-+	__le64 dqb_bsoftlimit;	/* preferred limit on disk space */
-+	__le64 dqb_curspace;	/* current space occupied (in bytes) */
-+	__le64 dqb_btime;	/* time limit for excessive disk use */
-+	__le64 dqb_itime;	/* time limit for excessive inode use */
-+};
-+
- /* Header with type and version specific information */
- struct v2_disk_dqinfo {
- 	__le32 dqi_bgrace;	/* Time before block soft limit becomes hard limit */
diff --git a/lustre/kernel_patches/patches/sd_iostats-2.6.26-vanilla.patch b/lustre/kernel_patches/patches/sd_iostats-2.6.26-vanilla.patch
deleted file mode 100644
index f995730..0000000
--- a/lustre/kernel_patches/patches/sd_iostats-2.6.26-vanilla.patch
+++ /dev/null
@@ -1,579 +0,0 @@
-Index: linux-source-2.6.26/drivers/scsi/Kconfig
-===================================================================
---- linux-source-2.6.26.orig/drivers/scsi/Kconfig	2009-10-09 13:33:25.000000000 +0200
-+++ linux-source-2.6.26/drivers/scsi/Kconfig	2009-10-09 13:39:06.000000000 +0200
-@@ -81,6 +81,14 @@
- 	  In this case, do not compile the driver for your SCSI host adapter
- 	  (below) as a module either.
- 
-+config SD_IOSTATS
-+   bool "Enable SCSI disk I/O stats"
-+   depends on BLK_DEV_SD
-+   default y
-+   ---help---
-+     This enables SCSI disk I/O stats collection.  You must also enable
-+     /proc file system support if you want this feature.
-+
- config CHR_DEV_ST
- 	tristate "SCSI tape support"
- 	depends on SCSI
-Index: linux-source-2.6.26/drivers/scsi/scsi_proc.c
-===================================================================
---- linux-source-2.6.26.orig/drivers/scsi/scsi_proc.c	2009-10-09 13:33:25.000000000 +0200
-+++ linux-source-2.6.26/drivers/scsi/scsi_proc.c	2009-10-09 13:39:06.000000000 +0200
-@@ -40,7 +40,8 @@
- /* 4K page size, but our output routines, use some slack for overruns */
- #define PROC_BLOCK_SIZE (3*1024)
- 
--static struct proc_dir_entry *proc_scsi;
-+struct proc_dir_entry *proc_scsi;
-+EXPORT_SYMBOL(proc_scsi);
- 
- /* Protect sht->present and sht->proc_dir */
- static DEFINE_MUTEX(global_host_template_mutex);
-Index: linux-source-2.6.26/drivers/scsi/sd.c
-===================================================================
---- linux-source-2.6.26.orig/drivers/scsi/sd.c	2009-10-09 13:33:25.000000000 +0200
-+++ linux-source-2.6.26/drivers/scsi/sd.c	2009-10-09 13:39:50.000000000 +0200
-@@ -107,6 +107,24 @@
-  * object after last put) */
- static DEFINE_MUTEX(sd_ref_mutex);
- 
-+#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
-+# include <linux/proc_fs.h>
-+# include <linux/seq_file.h>
-+struct proc_dir_entry *sd_iostats_procdir = NULL;
-+char sd_iostats_procdir_name[] = "sd_iostats";
-+static struct file_operations sd_iostats_proc_fops;
-+
-+extern void sd_iostats_init(void);
-+extern void sd_iostats_fini(void);
-+void sd_iostats_start_req(struct scsi_cmnd *SCpnt);
-+void sd_iostats_finish_req(struct scsi_cmnd *SCpnt);
-+#else
-+static inline void sd_iostats_init(void) {}
-+static inline void sd_iostats_fini(void) {}
-+static inline void sd_iostats_start_req(struct scsi_cmnd *SCpnt) {}
-+static inline void sd_iostats_finish_req(struct scsi_cmnd *SCpnt) {}
-+#endif
-+
- static const char *sd_cache_types[] = {
- 	"write through", "none", "write back",
- 	"write back, no read (daft)"
-@@ -578,6 +596,8 @@
- 
- 	sdev = sdkp->device;
- 
-+	sd_iostats_start_req(SCpnt);
-+
- 	/*
- 	 * If the device is in error recovery, wait until it is done.
- 	 * If the device is offline, then disallow any access to it.
-@@ -1023,6 +1043,7 @@
- 		break;
- 	}
-  out:
-+ 	sd_iostats_finish_req(SCpnt);
- 	return good_bytes;
- }
- 
-@@ -1712,6 +1733,36 @@
- 	if (sdp->removable)
- 		gd->flags |= GENHD_FL_REMOVABLE;
- 
-+#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
-+	sdkp->stats = kzalloc(sizeof(iostat_stats_t), GFP_KERNEL);
-+	if (!sdkp->stats) {
-+		printk(KERN_WARNING "cannot allocate iostat structure for"
-+				    "%s\n", gd->disk_name);
-+	} else {
-+		do_gettimeofday(&sdkp->stats->iostat_timeval);
-+		sdkp->stats->iostat_queue_stamp = jiffies;
-+		spin_lock_init(&sdkp->stats->iostat_lock);
-+		if (sd_iostats_procdir) {
-+			struct proc_dir_entry *pde;
-+			pde = create_proc_entry(gd->disk_name, S_IRUGO | S_IWUSR,
-+					        sd_iostats_procdir);
-+			if (!pde) {
-+				printk(KERN_WARNING "Can't create /proc/scsi/"
-+						    "%s/%s\n",
-+						    sd_iostats_procdir_name,
-+						    gd->disk_name);
-+				kfree(sdkp->stats);
-+				sdkp->stats = NULL;
-+			} else {
-+				pde->proc_fops = &sd_iostats_proc_fops;
-+				pde->data = gd;
-+			}
-+		} else {
-+			kfree(sdkp->stats);
-+			sdkp->stats = NULL;
-+		}
-+	}
-+#endif
- 	dev_set_drvdata(dev, sdkp);
- 	add_disk(gd);
- 
-@@ -1755,6 +1806,366 @@
- 	return 0;
- }
- 
-+#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
-+static int
-+sd_iostats_seq_show(struct seq_file *seq, void *v)
-+{
-+	struct timeval     now;
-+	struct gendisk *disk = seq->private;
-+	iostat_stats_t    *stats;
-+	unsigned long long read_len;
-+	unsigned long long read_len_tot;
-+	unsigned long      read_num;
-+	unsigned long      read_num_tot;
-+	unsigned long long write_len;
-+	unsigned long long write_len_tot;
-+	unsigned long      write_num;
-+	unsigned long      write_num_tot;
-+	int                i;
-+	int                maxi;
-+
-+	stats = scsi_disk(disk)->stats;
-+	if (stats == NULL) {
-+		printk(KERN_ERR "sd_iostats_seq_show: NULL stats entry\n");
-+		BUG();
-+	}
-+
-+	do_gettimeofday(&now);
-+	now.tv_sec -= stats->iostat_timeval.tv_sec;
-+	now.tv_usec -= stats->iostat_timeval.tv_usec;
-+	if (now.tv_usec < 0) {
-+		now.tv_usec += 1000000;
-+		now.tv_sec--;
-+	}
-+
-+	/* this sampling races with updates */
-+	seq_printf(seq, "index:        %lu   snapshot_time:         %lu.%06lu\n",
-+			(unsigned long) scsi_disk(disk)->index,
-+			now.tv_sec, now.tv_usec);
-+
-+	for (i = IOSTAT_NCOUNTERS - 1; i > 0; i--)
-+		if (stats->iostat_read_histogram[i].iostat_count != 0 ||
-+				stats->iostat_write_histogram[i].iostat_count != 0)
-+			break;
-+	maxi = i;
-+
-+	seq_printf(seq, "%8s %8s %12s %8s %12s\n", "size", 
-+			"reads", "total", "writes", "total");
-+
-+	read_len_tot = write_len_tot = 0;
-+	read_num_tot = write_num_tot = 0;
-+	for (i = 0; i <= maxi; i++) {
-+		read_len = stats->iostat_read_histogram[i].iostat_size;
-+		read_len_tot += read_len;
-+		read_num = stats->iostat_read_histogram[i].iostat_count;
-+		read_num_tot += read_num;
-+
-+		write_len = stats->iostat_write_histogram[i].iostat_size;
-+		write_len_tot += write_len;
-+		write_num = stats->iostat_write_histogram[i].iostat_count;
-+		write_num_tot += write_num;
-+
-+		seq_printf (seq, "%8d %8lu %12llu %8lu %12llu\n", 
-+				512<<i, read_num, read_len, write_num, write_len);
-+	}
-+
-+	seq_printf(seq, "%8s %8lu %12llu %8lu %12llu\n\n", "total",
-+			read_num_tot, read_len_tot, 
-+			write_num_tot, write_len_tot);
-+
-+	seq_printf(seq, "%8s %8s %8s\n", "qdepth", "ticks", "%");
-+	for (i = 0; i < IOSTAT_NCOUNTERS; i++) {
-+		unsigned long long ticks, percent;
-+		ticks = stats->iostat_queue_ticks[i];
-+		if (ticks == 0)
-+			continue;
-+		percent = stats->iostat_queue_ticks[i] * 100;
-+		do_div(percent, stats->iostat_queue_ticks_sum);
-+		seq_printf(seq, "%8d %8llu %8llu\n", i, ticks, percent);
-+	}
-+
-+	if (stats->iostat_reqs != 0) {
-+		unsigned long long aveseek = 0, percent = 0;
-+
-+		if (stats->iostat_seeks) {
-+			aveseek = stats->iostat_seek_sectors;
-+			do_div(aveseek, stats->iostat_seeks);
-+			percent = stats->iostat_seeks * 100;
-+			do_div(percent, stats->iostat_reqs);
-+		}
-+
-+		seq_printf(seq, "\n%llu sectors in %llu reqs: %llu seek(s) over "
-+				"%llu sectors in ave, %llu%% of all reqs\n",
-+				stats->iostat_sectors, stats->iostat_reqs,
-+				stats->iostat_seeks, aveseek, percent);
-+	}
-+
-+	seq_printf(seq, "\n%16s %8s %8s %8s %8s\n", "process time", "reads",
-+			"%%", "writes", "%%");
-+	for (i = 0; i < IOSTAT_NCOUNTERS; i++) {
-+		unsigned long read_percent = 0, write_percent = 0;
-+		if (stats->iostat_wtime[i] == 0 &&
-+				stats->iostat_rtime[i] == 0)
-+			continue;
-+		if (stats->iostat_read_reqs)
-+			read_percent = stats->iostat_rtime[i] * 100 / 
-+				stats->iostat_read_reqs;
-+		if (stats->iostat_write_reqs)
-+			write_percent = stats->iostat_wtime[i] * 100 / 
-+				stats->iostat_write_reqs;
-+		seq_printf(seq, "%16u %8lu %8lu %8lu %8lu\n",
-+				jiffies_to_msecs(((1UL << i) >> 1) << 1),
-+				stats->iostat_rtime[i], read_percent,
-+				stats->iostat_wtime[i], write_percent);
-+	}
-+
-+	seq_printf(seq, "\n%16s %8s %8s %8s %8s\n", "time in queue", "reads",
-+			"%%", "writes", "%%");
-+	for (i = 0; i < IOSTAT_NCOUNTERS; i++) {
-+		unsigned long read_percent = 0, write_percent = 0;
-+		if (stats->iostat_wtime_in_queue[i] == 0 &&
-+				stats->iostat_rtime_in_queue[i] == 0)
-+			continue;
-+		if (stats->iostat_read_reqs)
-+			read_percent = stats->iostat_rtime_in_queue[i] * 100 / 
-+				stats->iostat_read_reqs;
-+		if (stats->iostat_write_reqs)
-+			write_percent = stats->iostat_wtime_in_queue[i] * 100 / 
-+				stats->iostat_write_reqs;
-+		seq_printf(seq, "%16u %8lu %8lu %8lu %8lu\n",
-+				jiffies_to_msecs(((1UL << i) >> 1) << 1),
-+				stats->iostat_rtime_in_queue[i],
-+				read_percent,
-+				stats->iostat_wtime_in_queue[i],
-+				write_percent);
-+	}
-+
-+	return 0;
-+}
-+
-+static void *
-+sd_iostats_seq_start(struct seq_file *p, loff_t *pos)
-+{
-+	return (*pos == 0) ? (void *)1 : NULL;
-+}
-+
-+static void *
-+sd_iostats_seq_next(struct seq_file *p, void *v, loff_t *pos)
-+{
-+	++*pos;
-+	return NULL;
-+}
-+
-+static void
-+sd_iostats_seq_stop(struct seq_file *p, void *v)
-+{
-+}
-+
-+static struct seq_operations sd_iostats_seqops = {
-+	.start = sd_iostats_seq_start,
-+	.stop  = sd_iostats_seq_stop,
-+	.next  = sd_iostats_seq_next,
-+	.show  = sd_iostats_seq_show,
-+};
-+
-+static int
-+sd_iostats_seq_open (struct inode *inode, struct file *file)
-+{
-+	int rc;
-+
-+	rc = seq_open(file, &sd_iostats_seqops);
-+	if (rc != 0)
-+		return rc;
-+
-+	((struct seq_file *)file->private_data)->private = PDE(inode)->data;
-+	return 0;
-+}
-+
-+static ssize_t
-+sd_iostats_seq_write(struct file *file, const char *buffer,
-+		     size_t len, loff_t *off)
-+{
-+	struct seq_file   *seq = file->private_data;
-+	struct gendisk *disk = seq->private;
-+	iostat_stats_t    *stats = scsi_disk(disk)->stats;
-+	unsigned long      flags;
-+	unsigned long      qdepth;
-+
-+
-+	spin_lock_irqsave (&stats->iostat_lock, flags);
-+	qdepth = stats->iostat_queue_depth;
-+	memset (stats, 0, offsetof(iostat_stats_t, iostat_lock));
-+	do_gettimeofday(&stats->iostat_timeval);
-+	stats->iostat_queue_stamp = jiffies;
-+	stats->iostat_queue_depth = qdepth;
-+	spin_unlock_irqrestore (&stats->iostat_lock, flags);
-+
-+	return len;
-+}
-+
-+static struct file_operations sd_iostats_proc_fops = {
-+	.owner   = THIS_MODULE,
-+	.open    = sd_iostats_seq_open,
-+	.read    = seq_read,
-+	.write   = sd_iostats_seq_write,
-+	.llseek  = seq_lseek,
-+	.release = seq_release,
-+};
-+
-+extern struct proc_dir_entry *proc_scsi;
-+
-+void
-+sd_iostats_init(void)
-+{
-+	if (proc_scsi == NULL) {
-+		printk(KERN_WARNING "No access to sd iostats: "
-+			"proc_scsi is NULL\n");
-+		return;
-+	}
-+
-+	sd_iostats_procdir = create_proc_entry(sd_iostats_procdir_name,
-+					       S_IFDIR | S_IRUGO | S_IXUGO,
-+					        proc_scsi);
-+	if (sd_iostats_procdir == NULL) {
-+		printk(KERN_WARNING "No access to sd iostats: "
-+			"can't create /proc/scsi/%s\n", sd_iostats_procdir_name);
-+		return;
-+	}
-+}
-+
-+void sd_iostats_fini(void)
-+{
-+	if (proc_scsi != NULL && sd_iostats_procdir != NULL)
-+		remove_proc_entry(sd_iostats_procdir_name, proc_scsi);
-+
-+	sd_iostats_procdir = NULL;
-+}
-+
-+void sd_iostats_finish_req(struct scsi_cmnd *SCpnt)
-+{
-+	struct request		*rq = SCpnt->request;
-+	iostat_stats_t		*stats;
-+	unsigned long		*tcounter;
-+	int			tbucket;
-+	int			tmp;
-+	unsigned long		irqflags;
-+	unsigned long		i;
-+
-+	stats = scsi_disk(rq->rq_disk)->stats;
-+	if (stats == NULL)
-+		return;
-+
-+	tmp = jiffies - rq->start_time;
-+	for (tbucket = 0; tmp > 1; tbucket++)
-+		tmp >>= 1;
-+	if (tbucket >= IOSTAT_NCOUNTERS)
-+		tbucket = IOSTAT_NCOUNTERS - 1;
-+	//printk("%u ticks in D to %u\n", jiffies - rq->start_time, tbucket);
-+
-+	tcounter = rq_data_dir(rq) == WRITE ?
-+		&stats->iostat_wtime[tbucket] : &stats->iostat_rtime[tbucket];
-+
-+	spin_lock_irqsave(&stats->iostat_lock, irqflags);
-+
-+	/* update delay stats */
-+	(*tcounter)++;
-+
-+	/* update queue depth stats */
-+	i = stats->iostat_queue_depth;
-+	if (i >= IOSTAT_NCOUNTERS)
-+		i = IOSTAT_NCOUNTERS - 1;
-+	stats->iostat_queue_ticks[i] += jiffies - stats->iostat_queue_stamp;
-+	stats->iostat_queue_ticks_sum += jiffies - stats->iostat_queue_stamp;
-+	BUG_ON(stats->iostat_queue_depth == 0);
-+	stats->iostat_queue_depth--;
-+
-+	/* update seek stats. XXX: not sure about nr_sectors */
-+	stats->iostat_sectors += rq->nr_sectors;
-+	stats->iostat_reqs++;
-+	if (rq->sector != stats->iostat_next_sector) {
-+		stats->iostat_seek_sectors +=
-+			rq->sector > stats->iostat_next_sector ?
-+			rq->sector - stats->iostat_next_sector :
-+			stats->iostat_next_sector - rq->sector;
-+		stats->iostat_seeks++;
-+	}
-+	stats->iostat_next_sector = rq->sector + rq->nr_sectors;
-+
-+	stats->iostat_queue_stamp = jiffies;
-+
-+	spin_unlock_irqrestore(&stats->iostat_lock, irqflags);
-+}
-+
-+void sd_iostats_start_req(struct scsi_cmnd *SCpnt)
-+{
-+	struct request		*rq = SCpnt->request;
-+	iostat_stats_t		*stats;
-+	iostat_counter_t	*counter;
-+	int			bucket;
-+	int			tbucket;
-+	int			tmp;
-+	unsigned long		irqflags;
-+	unsigned long		i;
-+	int			nsect;
-+
-+	stats = scsi_disk(rq->rq_disk)->stats;
-+	if (stats == NULL)
-+		return;
-+
-+	nsect = scsi_bufflen(SCpnt) >> 9;
-+	for (bucket = 0, tmp = nsect; tmp > 1; bucket++)
-+		tmp >>= 1;
-+
-+	if (bucket >= IOSTAT_NCOUNTERS) {
-+		printk (KERN_ERR "sd_iostats_bump: nsect %d too big\n", nsect);
-+		BUG();
-+	}
-+
-+	counter = rq_data_dir(rq) == WRITE ?
-+		&stats->iostat_write_histogram[bucket] :
-+		&stats->iostat_read_histogram[bucket];
-+
-+	tmp = jiffies - rq->start_time;
-+	for (tbucket = 0; tmp > 1; tbucket++)
-+		tmp >>= 1;
-+	if (tbucket >= IOSTAT_NCOUNTERS)
-+		tbucket = IOSTAT_NCOUNTERS - 1;
-+	//printk("%u ticks in Q to %u\n", jiffies - rq->start_time, tbucket);
-+
-+	/* an ugly hack to know exact processing time. the right
-+	 * solution is to add one more field to struct request
-+	 * hopefully it will break nothing ... */
-+	rq->start_time = jiffies;
-+
-+	spin_lock_irqsave(&stats->iostat_lock, irqflags);
-+
-+	/* update queue depth stats */
-+	i = stats->iostat_queue_depth;
-+	if (i >= IOSTAT_NCOUNTERS)
-+		i = IOSTAT_NCOUNTERS - 1;
-+	stats->iostat_queue_ticks[i] += jiffies - stats->iostat_queue_stamp;
-+	stats->iostat_queue_ticks_sum += jiffies - stats->iostat_queue_stamp;
-+	stats->iostat_queue_depth++;
-+
-+	/* update delay stats */
-+	if (rq_data_dir(rq) == WRITE) {
-+		stats->iostat_wtime_in_queue[tbucket]++;
-+		stats->iostat_write_reqs++;
-+	} else {
-+		stats->iostat_rtime_in_queue[tbucket]++;
-+		stats->iostat_read_reqs++;
-+	}
-+
-+	/* update size stats */
-+	counter->iostat_size += nsect;
-+	counter->iostat_count++;
-+
-+	stats->iostat_queue_stamp = jiffies;
-+
-+	spin_unlock_irqrestore(&stats->iostat_lock, irqflags);
-+}
-+#endif
-+
- /**
-  *	scsi_disk_release - Called to free the scsi_disk structure
-  *	@dev: pointer to embedded class device
-@@ -1773,10 +2184,16 @@
- 	idr_remove(&sd_index_idr, sdkp->index);
- 	spin_unlock(&sd_index_lock);
- 
-+#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
-+	if (sdkp->stats) {
-+		remove_proc_entry(disk->disk_name, sd_iostats_procdir);
-+		kfree(sdkp->stats);
-+		sdkp->stats = NULL;
-+	}
-+#endif
- 	disk->private_data = NULL;
- 	put_disk(disk);
- 	put_device(&sdkp->device->sdev_gendev);
--
- 	kfree(sdkp);
- }
- 
-@@ -1890,6 +2307,8 @@
- 	if (!majors)
- 		return -ENODEV;
- 
-+	sd_iostats_init();
-+
- 	err = class_register(&sd_disk_class);
- 	if (err)
- 		goto err_out;
-@@ -1905,6 +2324,7 @@
- err_out:
- 	for (i = 0; i < SD_MAJORS; i++)
- 		unregister_blkdev(sd_major(i), "sd");
-+	sd_iostats_fini();
- 	return err;
- }
- 
-Index: linux-source-2.6.26/include/scsi/sd.h
-===================================================================
---- linux-source-2.6.26.orig/include/scsi/sd.h	2009-10-09 13:33:25.000000000 +0200
-+++ linux-source-2.6.26/include/scsi/sd.h	2009-10-09 13:39:06.000000000 +0200
-@@ -31,6 +31,46 @@
-  */
- #define SD_BUF_SIZE		512
- 
-+#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
-+typedef struct {
-+	unsigned long long iostat_size;
-+	unsigned long long iostat_count;
-+} iostat_counter_t;
-+
-+#define IOSTAT_NCOUNTERS 16
-+typedef struct {
-+	iostat_counter_t	iostat_read_histogram[IOSTAT_NCOUNTERS];
-+	iostat_counter_t	iostat_write_histogram[IOSTAT_NCOUNTERS];
-+	struct timeval		iostat_timeval;
-+
-+	/* queue depth: how well the pipe is filled up */
-+	unsigned long long	iostat_queue_ticks[IOSTAT_NCOUNTERS];
-+	unsigned long long	iostat_queue_ticks_sum;
-+	unsigned long		iostat_queue_depth;
-+	unsigned long		iostat_queue_stamp;
-+
-+	/* seeks: how linear the traffic is */
-+	unsigned long long	iostat_next_sector;
-+	unsigned long long	iostat_seek_sectors;
-+	unsigned long long	iostat_seeks;
-+	unsigned long long	iostat_sectors;
-+	unsigned long long	iostat_reqs;
-+	unsigned long		iostat_read_reqs;
-+	unsigned long		iostat_write_reqs;
-+
-+	/* process time: how long it takes to process requests */
-+	unsigned long		iostat_rtime[IOSTAT_NCOUNTERS];
-+	unsigned long		iostat_wtime[IOSTAT_NCOUNTERS];
-+
-+	/* queue time: how long process spent in elevator's queue */
-+	unsigned long		iostat_rtime_in_queue[IOSTAT_NCOUNTERS];
-+	unsigned long		iostat_wtime_in_queue[IOSTAT_NCOUNTERS];
-+
-+	/* must be the last field, as it's used to know size to be memset'ed */
-+	spinlock_t		iostat_lock;
-+} ____cacheline_aligned_in_smp iostat_stats_t;
-+#endif
-+
- struct scsi_disk {
- 	struct scsi_driver *driver;	/* always &sd_template */
- 	struct scsi_device *device;
-@@ -45,6 +85,9 @@
- 	unsigned	WCE : 1;	/* state of disk WCE bit */
- 	unsigned	RCD : 1;	/* state of disk RCD bit, unused */
- 	unsigned	DPOFUA : 1;	/* state of disk DPOFUA bit */
-+#if (defined(CONFIG_SD_IOSTATS) && defined(CONFIG_PROC_FS))
-+	iostat_stats_t	*stats;		/* scsi disk statistics */
-+#endif
- };
- #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
- 
diff --git a/lustre/kernel_patches/series/2.6.26-vanilla.series b/lustre/kernel_patches/series/2.6.26-vanilla.series
deleted file mode 100644
index 9f3e523..0000000
--- a/lustre/kernel_patches/series/2.6.26-vanilla.series
+++ /dev/null
@@ -1,2 +0,0 @@
-lustre_version.patch
-debian-2.6.26.diff 
diff --git a/lustre/kernel_patches/series/2.6.27-vanilla.series b/lustre/kernel_patches/series/2.6.27-vanilla.series
deleted file mode 100644
index c54d51b..0000000
--- a/lustre/kernel_patches/series/2.6.27-vanilla.series
+++ /dev/null
@@ -1,15 +0,0 @@
-lustre_version.patch
-vfs_races-2.6.22-vanilla.patch
-iopen-misc-2.6.22-vanilla.patch
-export-truncate-2.6.18-vanilla.patch 
-export_symbols-2.6.22-vanilla.patch 
-dev_read_only-2.6.27-vanilla.patch 
-export-2.6.27-vanilla.patch 
-export-show_task-2.6.27-vanilla.patch 
-sd_iostats-2.6.27-vanilla.patch
-md-mmp-unplug-dev-2.6.27-vanilla.patch
-quota-Split-off-quota-tree-handling-into-a-separate.patch
-quota-Increase-size-of-variables-for-limits-and-ino.patch
-quota-support-64-bit-quota-format-2.6.27-vanilla.patch
-jbd2-jcberr-2.6-sles11.patch
-jbd2-commit-timer-no-jiffies-rounding.diff

-- 
Lustre Debian Packaging 



More information about the Pkg-lustre-svn-commit mailing list