[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