From 541b344bd2df472f2596ee484371f793725b0136 Mon Sep 17 00:00:00 2001
From: anserper <anserper>
Date: Fri, 31 Oct 2008 14:13:45 +0000
Subject: [PATCH] Branch b1_6 b=13904 i=Johann Lombardi i=ZhiYong Tian

64-bit quota support for kernel
---
 .../patches/quota-large-limits-rhel5.patch    | 616 ++++++++++++++++++
 .../patches/quota-large-limits-sles10.patch   | 616 ++++++++++++++++++
 lustre/kernel_patches/series/2.6-rhel5.series |   1 +
 .../kernel_patches/series/2.6-sles10.series   |   1 +
 .../series/2.6.22-vanilla.series              |   1 +
 5 files changed, 1235 insertions(+)
 create mode 100644 lustre/kernel_patches/patches/quota-large-limits-rhel5.patch
 create mode 100644 lustre/kernel_patches/patches/quota-large-limits-sles10.patch

diff --git a/lustre/kernel_patches/patches/quota-large-limits-rhel5.patch b/lustre/kernel_patches/patches/quota-large-limits-rhel5.patch
new file mode 100644
index 0000000000..4f3a3bc8ff
--- /dev/null
+++ b/lustre/kernel_patches/patches/quota-large-limits-rhel5.patch
@@ -0,0 +1,616 @@
+diff -rNpu linux-2.6.16.54-0.2.5/fs/dquot.c linux-2.6.16.54-0.2.5-quota/fs/dquot.c
+--- linux-2.6.16.54-0.2.5/fs/dquot.c	2008-03-18 15:48:26.000000000 +0300
++++ linux-2.6.16.54-0.2.5-quota/fs/dquot.c	2008-03-17 22:43:11.000000000 +0300
+@@ -1588,10 +1588,19 @@ int vfs_get_dqblk(struct super_block *sb
+ }
+ 
+ /* Generic routine for setting common part of quota structure */
+-static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
++static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
+ {
+ 	struct mem_dqblk *dm = &dquot->dq_dqb;
+ 	int check_blim = 0, check_ilim = 0;
++	struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type];
++
++	if ((di->dqb_valid & QIF_BLIMITS &&
++	     (di->dqb_bhardlimit > dqi->dqi_maxblimit ||
++	      di->dqb_bsoftlimit > dqi->dqi_maxblimit)) ||
++	    (di->dqb_valid & QIF_ILIMITS &&
++	     (di->dqb_ihardlimit > dqi->dqi_maxilimit ||
++	      di->dqb_isoftlimit > dqi->dqi_maxilimit)))
++		return -ERANGE;
+ 
+ 	spin_lock(&dq_data_lock);
+ 	if (di->dqb_valid & QIF_SPACE) {
+@@ -1623,7 +1632,7 @@ static void do_set_dqblk(struct dquot *d
+ 			clear_bit(DQ_BLKS_B, &dquot->dq_flags);
+ 		}
+ 		else if (!(di->dqb_valid & QIF_BTIME))	/* Set grace only if user hasn't provided his own... */
+-			dm->dqb_btime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_bgrace;
++			dm->dqb_btime = get_seconds() + dqi->dqi_bgrace;
+ 	}
+ 	if (check_ilim) {
+ 		if (!dm->dqb_isoftlimit || dm->dqb_curinodes < dm->dqb_isoftlimit) {
+@@ -1631,7 +1640,7 @@ static void do_set_dqblk(struct dquot *d
+ 			clear_bit(DQ_INODES_B, &dquot->dq_flags);
+ 		}
+ 		else if (!(di->dqb_valid & QIF_ITIME))	/* Set grace only if user hasn't provided his own... */
+-			dm->dqb_itime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace;
++			dm->dqb_itime = get_seconds() + dqi->dqi_igrace;
+ 	}
+ 	if (dm->dqb_bhardlimit || dm->dqb_bsoftlimit || dm->dqb_ihardlimit || dm->dqb_isoftlimit)
+ 		clear_bit(DQ_FAKE_B, &dquot->dq_flags);
+@@ -1639,21 +1648,24 @@ static void do_set_dqblk(struct dquot *d
+ 		set_bit(DQ_FAKE_B, &dquot->dq_flags);
+ 	spin_unlock(&dq_data_lock);
+ 	mark_dquot_dirty(dquot);
++
++	return 0;
+ }
+ 
+ int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di)
+ {
+ 	struct dquot *dquot;
++	int rc;
+ 
+ 	mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
+ 	if (!(dquot = dqget(sb, id, type))) {
+ 		mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
+ 		return -ESRCH;
+ 	}
+-	do_set_dqblk(dquot, di);
++	rc = do_set_dqblk(dquot, di);
+ 	dqput(dquot);
+ 	mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
+-	return 0;
++	return rc;
+ }
+ 
+ /* Generic routine for getting common part of quota file information */
+diff -rNpu linux-2.6.16.54-0.2.5/fs/quota_v1.c linux-2.6.16.54-0.2.5-quota/fs/quota_v1.c
+--- linux-2.6.16.54-0.2.5/fs/quota_v1.c	2006-03-20 08:53:29.000000000 +0300
++++ linux-2.6.16.54-0.2.5-quota/fs/quota_v1.c	2008-03-17 22:42:47.000000000 +0300
+@@ -139,6 +139,9 @@ static int v1_read_file_info(struct supe
+ 		goto out;
+ 	}
+ 	ret = 0;
++	/* limits are stored as unsigned 32-bit data */
++	dqopt->info[type].dqi_maxblimit = 0xffffffff;
++	dqopt->info[type].dqi_maxilimit = 0xffffffff;
+ 	dqopt->info[type].dqi_igrace = dqblk.dqb_itime ? dqblk.dqb_itime : MAX_IQ_TIME;
+ 	dqopt->info[type].dqi_bgrace = dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME;
+ out:
+diff -rNpu linux-2.6.16.54-0.2.5/fs/quota_v2.c linux-2.6.16.54-0.2.5-quota/fs/quota_v2.c
+--- linux-2.6.16.54-0.2.5/fs/quota_v2.c	2006-03-20 08:53:29.000000000 +0300
++++ linux-2.6.16.54-0.2.5-quota/fs/quota_v2.c	2008-03-18 11:58:02.000000000 +0300
+@@ -23,26 +23,64 @@ MODULE_LICENSE("GPL");
+ 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 GETENTRIES(buf) ((union v2_disk_dqblk *)(((char *)buf) + \
++			 sizeof(struct v2_disk_dqdbheader)))
++#define REV_ASSERT(r) BUG_ON((rev) != 0 && (rev) != 1)
++
++static const union v2_disk_dqblk emptydquot;
++static const union v2_disk_dqblk fakedquot[2] = {
++	{.r0 = {.dqb_itime = __constant_cpu_to_le64(1LLU)} },
++	{.r1 = {.dqb_itime = __constant_cpu_to_le64(1LLU)} }
++};
+ 
+-/* Check whether given file is really vfsv0 quotafile */
+-static int v2_check_quota_file(struct super_block *sb, int type)
++static inline uint v2_dqblksz(uint rev)
++{
++	uint sz;
++
++	REV_ASSERT(rev);
++
++	if (rev == 0)
++		sz = sizeof(struct v2_disk_dqblk_r0);
++	else
++		sz = sizeof(struct v2_disk_dqblk_r1);
++
++	return sz;
++}
++
++/* Number of quota entries in a block */
++static inline int v2_dqstrinblk(uint rev)
++{
++	return (V2_DQBLKSIZE-sizeof(struct v2_disk_dqdbheader))/v2_dqblksz(rev);
++}
++
++/* Get revision of a quota file, -1 if it does not look a quota file */
++static int v2_quota_file_revision(struct super_block *sb, int type)
+ {
+ 	struct v2_disk_dqheader dqhead;
+ 	ssize_t size;
+ 	static const uint quota_magics[] = V2_INITQMAGICS;
+-	static const uint quota_versions[] = V2_INITQVERSIONS;
++	static const uint quota_versions_r0[] = V2_INITQVERSIONS_R0;
++	static const uint quota_versions_r1[] = V2_INITQVERSIONS_R1;
+  
+ 	size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
+ 	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 -1;
+ 	}
+-	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]) {
++		if (le32_to_cpu(dqhead.dqh_version) == quota_versions_r0[type])
++			return 0;
++		if (le32_to_cpu(dqhead.dqh_version) == quota_versions_r1[type])
++			return 1;
++	}
++	return -1;
++}
++
++/* Check whether given file is really vfsv0 quotafile */
++static inline int v2_check_quota_file(struct super_block *sb, int type)
++{
++	return v2_quota_file_revision(sb, type) != -1;
+ }
+ 
+ /* Read information header from quota file */
+@@ -51,6 +89,13 @@ static int v2_read_file_info(struct supe
+ 	struct v2_disk_dqinfo dinfo;
+ 	struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
+ 	ssize_t size;
++	int rev;
++
++	rev = v2_quota_file_revision(sb, type);
++	if (rev < 0) {
++		printk(KERN_WARNING "Second quota file check failed.\n");
++		return -1;
++	}
+ 
+ 	size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
+ 	       sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
+@@ -65,6 +110,16 @@ static int v2_read_file_info(struct supe
+ 	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.dqi_revision = rev;
++	if (rev == 0) {
++		info->dqi_maxblimit = 0xffffffffULL;
++		info->dqi_maxilimit = 0xffffffffULL;
++	} else {
++		info->dqi_maxblimit = 0xffffffffffffffffULL;
++		info->dqi_maxilimit = 0xffffffffffffffffULL;
++	}
++
+ 	return 0;
+ }
+ 
+@@ -94,29 +149,61 @@ static int v2_write_file_info(struct sup
+ 	return 0;
+ }
+ 
+-static void disk2memdqb(struct mem_dqblk *m, struct v2_disk_dqblk *d)
++static void disk2memdqb(struct mem_dqblk *m, union v2_disk_dqblk *d, uint rev)
+ {
+-	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);
+-	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_curspace = le64_to_cpu(d->dqb_curspace);
+-	m->dqb_btime = le64_to_cpu(d->dqb_btime);
+-}
+-
+-static void mem2diskdqb(struct v2_disk_dqblk *d, struct mem_dqblk *m, qid_t id)
+-{
+-	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);
+-	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_curspace = cpu_to_le64(m->dqb_curspace);
+-	d->dqb_btime = cpu_to_le64(m->dqb_btime);
+-	d->dqb_id = cpu_to_le32(id);
++	REV_ASSERT(rev);
++
++	if (rev == 0) {
++		struct v2_disk_dqblk_r0 *ddqblk = &d->r0;
++		m->dqb_ihardlimit = le32_to_cpu(ddqblk->dqb_ihardlimit);
++		m->dqb_isoftlimit = le32_to_cpu(ddqblk->dqb_isoftlimit);
++		m->dqb_curinodes = le32_to_cpu(ddqblk->dqb_curinodes);
++		m->dqb_itime = le64_to_cpu(ddqblk->dqb_itime);
++		m->dqb_bhardlimit = le32_to_cpu(ddqblk->dqb_bhardlimit);
++		m->dqb_bsoftlimit = le32_to_cpu(ddqblk->dqb_bsoftlimit);
++		m->dqb_curspace = le64_to_cpu(ddqblk->dqb_curspace);
++		m->dqb_btime = le64_to_cpu(ddqblk->dqb_btime);
++	} else {
++		struct v2_disk_dqblk_r1 *ddqblk = &d->r1;
++		m->dqb_ihardlimit = le64_to_cpu(ddqblk->dqb_ihardlimit);
++		m->dqb_isoftlimit = le64_to_cpu(ddqblk->dqb_isoftlimit);
++		m->dqb_curinodes = le64_to_cpu(ddqblk->dqb_curinodes);
++		m->dqb_itime = le64_to_cpu(ddqblk->dqb_itime);
++		m->dqb_bhardlimit = le64_to_cpu(ddqblk->dqb_bhardlimit);
++		m->dqb_bsoftlimit = le64_to_cpu(ddqblk->dqb_bsoftlimit);
++		m->dqb_curspace = le64_to_cpu(ddqblk->dqb_curspace);
++		m->dqb_btime = le64_to_cpu(ddqblk->dqb_btime);
++	}
++}
++
++static void mem2diskdqb(union v2_disk_dqblk *d, struct mem_dqblk *m,
++			qid_t id, uint rev)
++{
++	REV_ASSERT(rev);
++
++	if (rev == 0) {
++		struct v2_disk_dqblk_r0 *ddqblk = &d->r0;
++		ddqblk->dqb_id = cpu_to_le32(id);
++		ddqblk->dqb_ihardlimit = cpu_to_le32((__u32)m->dqb_ihardlimit);
++		ddqblk->dqb_isoftlimit = cpu_to_le32((__u32)m->dqb_isoftlimit);
++		ddqblk->dqb_curinodes = cpu_to_le32((__u32)m->dqb_curinodes);
++		ddqblk->dqb_itime = cpu_to_le64(m->dqb_itime);
++		ddqblk->dqb_bhardlimit = cpu_to_le32((__u32)m->dqb_bhardlimit);
++		ddqblk->dqb_bsoftlimit = cpu_to_le32((__u32)m->dqb_bsoftlimit);
++		ddqblk->dqb_curspace = cpu_to_le64(m->dqb_curspace);
++		ddqblk->dqb_btime = cpu_to_le64(ddqblk->dqb_btime);
++	} else {
++		struct v2_disk_dqblk_r1 *ddqblk = &d->r1;
++		ddqblk->dqb_id = cpu_to_le32(id);
++		ddqblk->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
++		ddqblk->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
++		ddqblk->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
++		ddqblk->dqb_itime = cpu_to_le64(m->dqb_itime);
++		ddqblk->dqb_bhardlimit = cpu_to_le64(m->dqb_bhardlimit);
++		ddqblk->dqb_bsoftlimit = cpu_to_le64(m->dqb_bsoftlimit);
++		ddqblk->dqb_curspace = cpu_to_le64(m->dqb_curspace);
++		ddqblk->dqb_btime = cpu_to_le64(ddqblk->dqb_btime);
++	}
+ }
+ 
+ static dqbuf_t getdqbuf(void)
+@@ -268,10 +355,10 @@ static uint find_free_dqentry(struct dqu
+ {
+ 	struct super_block *sb = dquot->dq_sb;
+ 	struct mem_dqinfo *info = sb_dqopt(sb)->info+dquot->dq_type;
+-	uint blk, i;
++	uint blk, i, rev = info->u.v2_i.dqi_revision;
++	uint dqblksz = v2_dqblksz(rev), dqstrinblk = v2_dqstrinblk(rev);
+ 	struct v2_disk_dqdbheader *dh;
+-	struct v2_disk_dqblk *ddquot;
+-	struct v2_disk_dqblk fakedquot;
++	union v2_disk_dqblk *ddquot;
+ 	dqbuf_t buf;
+ 
+ 	*err = 0;
+@@ -298,17 +385,18 @@ static uint find_free_dqentry(struct dqu
+ 		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? */
++	/* Block will be full? */
++	if (le16_to_cpu(dh->dqdh_entries)+1 >= dqstrinblk)
+ 		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;
+ 		}
+ 	dh->dqdh_entries = cpu_to_le16(le16_to_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++);
++	for (i = 0; i < dqstrinblk && memcmp(&emptydquot, ddquot, dqblksz);
++	     i++, ddquot = (char *)ddquot + dqblksz);
+ #ifdef __QUOTA_V2_PARANOIA
+-	if (i == V2_DQSTRINBLK) {
++	if (i == dqstrinblk) {
+ 		printk(KERN_ERR "VFS: find_free_dqentry(): Data block full but it shouldn't.\n");
+ 		*err = -EIO;
+ 		goto out_buf;
+@@ -318,7 +406,8 @@ static uint find_free_dqentry(struct dqu
+ 		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);
++	dquot->dq_off = (blk<<V2_DQBLKSIZE_BITS)+
++			((char *)ddquot - (char *)buf);
+ 	freedqbuf(buf);
+ 	return blk;
+ out_buf:
+@@ -392,7 +481,9 @@ static int v2_write_dquot(struct dquot *
+ {
+ 	int type = dquot->dq_type;
+ 	ssize_t ret;
+-	struct v2_disk_dqblk ddquot, empty;
++	union v2_disk_dqblk ddquot;
++	uint rev = sb_dqopt(dquot->dq_sb)->info[type].u.v2_i.dqi_revision;
++	uint dqblksz = v2_dqblksz(rev);
+ 
+ 	/* dq_off is guarded by dqio_sem */
+ 	if (!dquot->dq_off)
+@@ -401,18 +492,22 @@ static int v2_write_dquot(struct dquot *
+ 			return ret;
+ 		}
+ 	spin_lock(&dq_data_lock);
+-	mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
++	mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id, rev);
+ 	/* 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);
++	if (!memcmp(&emptydquot, &ddquot, dqblksz)) {
++		if (rev == 0)
++			ddquot.r0.dqb_itime = cpu_to_le64(1);
++		else
++			ddquot.r1.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);
++	      (char *)&ddquot, dqblksz, dquot->dq_off);
++	if (ret != dqblksz) {
++		printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
++			dquot->dq_sb->s_id);
+ 		if (ret >= 0)
+ 			ret = -ENOSPC;
+ 	}
+@@ -431,6 +526,7 @@ static int free_dqentry(struct dquot *dq
+ 	struct v2_disk_dqdbheader *dh;
+ 	dqbuf_t buf = getdqbuf();
+ 	int ret = 0;
++	uint rev = sb_dqopt(sb)->info[type].u.v2_i.dqi_revision;
+ 
+ 	if (!buf)
+ 		return -ENOMEM;
+@@ -456,8 +552,8 @@ static int free_dqentry(struct dquot *dq
+ 	}
+ 	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) {
++		  v2_dqblksz(rev));
++		if (le16_to_cpu(dh->dqdh_entries) == v2_dqstrinblk(rev)-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);
+@@ -529,41 +625,56 @@ static int v2_delete_dquot(struct dquot 
+ 	return remove_tree(dquot, &tmp, 0);
+ }
+ 
++static inline __u32 dqid(union v2_disk_dqblk *ddquot, uint rev)
++{
++	__u32 dq_id;
++
++	REV_ASSERT(rev);
++
++	if (rev == 0)
++		dq_id = le32_to_cpu(ddquot->r0.dqb_id);
++	else
++		dq_id = le32_to_cpu(ddquot->r1.dqb_id);
++
++	return dq_id;
++}
++
+ /* 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);
++	union v2_disk_dqblk *ddquot = GETENTRIES(buf);
++	int type = dquot->dq_type;
++	uint rev = sb_dqopt(dquot->dq_sb)->info[type].u.v2_i.dqi_revision;
++	uint dqblksz = v2_dqblksz(rev), dqstrinblk = v2_dqstrinblk(rev);
+ 
+ 	if (!buf)
+ 		return -ENOMEM;
+-	if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
++
++	ret = read_blk(dquot->dq_sb, type, blk, buf);
++	if (ret < 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++);
++		for (i = 0; i < dqstrinblk && dqid(ddquot, rev) != dquot->dq_id;
++		     i++, ddquot = (char *)ddquot + dqblksz);
+ 	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)))
++		for (i = 0; i < dqstrinblk; i++, ddquot = (char *)ddquot+dqblksz)
++			if (!dqid(ddquot, rev) &&
++			    memcmp(&emptydquot, ddquot, dqblksz))
+ 				break;
+ 	}
+-	if (i == V2_DQSTRINBLK) {
++	if (i == 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);
++		ret = (blk << V2_DQBLKSIZE_BITS)+((char *)ddquot-(char *)buf);
+ out_buf:
+ 	freedqbuf(buf);
+ 	return ret;
+@@ -605,7 +716,7 @@ static int v2_read_dquot(struct dquot *d
+ {
+ 	int type = dquot->dq_type;
+ 	loff_t offset;
+-	struct v2_disk_dqblk ddquot, empty;
++	union v2_disk_dqblk ddquot;
+ 	int ret = 0;
+ 
+ #ifdef __QUOTA_V2_PARANOIA
+@@ -626,25 +737,30 @@ static int v2_read_dquot(struct dquot *d
+ 		ret = offset;
+ 	}
+ 	else {
++		uint rev = sb_dqopt(dquot->dq_sb)->info[type].u.v2_i.
++			   dqi_revision;
++		uint  dqblksz = v2_dqblksz(rev);
+ 		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)) {
++		ret = dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type,
++					   (char *)&ddquot, dqblksz, offset);
++		if (ret != dqblksz) {
+ 			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));
++			memset(&ddquot, 0, dqblksz);
+ 		}
+ 		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;
++			if (!memcmp(&fakedquot[rev], &ddquot, dqblksz)) {
++				if (rev == 0)
++					ddquot.r0.dqb_itime = cpu_to_le64(0);
++				else
++					ddquot.r1.dqb_itime = cpu_to_le64(0);
++			}
+ 		}
+-		disk2memdqb(&dquot->dq_dqb, &ddquot);
++		disk2memdqb(&dquot->dq_dqb, &ddquot, rev);
+ 		if (!dquot->dq_dqb.dqb_bhardlimit &&
+ 			!dquot->dq_dqb.dqb_bsoftlimit &&
+ 			!dquot->dq_dqb.dqb_ihardlimit &&
+diff -rNpu linux-2.6.16.54-0.2.5/include/linux/dqblk_v2.h linux-2.6.16.54-0.2.5-quota/include/linux/dqblk_v2.h
+--- linux-2.6.16.54-0.2.5/include/linux/dqblk_v2.h	2006-03-20 08:53:29.000000000 +0300
++++ linux-2.6.16.54-0.2.5-quota/include/linux/dqblk_v2.h	2008-03-17 23:39:54.000000000 +0300
+@@ -21,6 +21,7 @@ struct v2_mem_dqinfo {
+ 	unsigned int dqi_blocks;
+ 	unsigned int dqi_free_blk;
+ 	unsigned int dqi_free_entry;
++	unsigned int dqi_revision;
+ };
+ 
+ #endif /* _LINUX_DQBLK_V2_H */
+diff -rNpu linux-2.6.16.54-0.2.5/include/linux/quota.h linux-2.6.16.54-0.2.5-quota/include/linux/quota.h
+--- linux-2.6.16.54-0.2.5/include/linux/quota.h	2006-03-20 08:53:29.000000000 +0300
++++ linux-2.6.16.54-0.2.5-quota/include/linux/quota.h	2008-03-17 23:39:54.000000000 +0300
+@@ -148,12 +148,12 @@ struct if_dqinfo {
+  * 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 */
+ };
+@@ -169,6 +169,8 @@ struct mem_dqinfo {
+ 	unsigned long dqi_flags;
+ 	unsigned int dqi_bgrace;
+ 	unsigned int dqi_igrace;
++	qsize_t dqi_maxblimit;
++	qsize_t dqi_maxilimit;
+ 	union {
+ 		struct v1_mem_dqinfo v1_i;
+ 		struct v2_mem_dqinfo v2_i;
+diff -rNpu linux-2.6.16.54-0.2.5/include/linux/quotaio_v2.h linux-2.6.16.54-0.2.5-quota/include/linux/quotaio_v2.h
+--- linux-2.6.16.54-0.2.5/include/linux/quotaio_v2.h	2006-03-20 08:53:29.000000000 +0300
++++ linux-2.6.16.54-0.2.5-quota/include/linux/quotaio_v2.h	2008-03-17 23:39:54.000000000 +0300
+@@ -16,28 +16,51 @@
+ 	0xd9c01927	/* GRPQUOTA */\
+ }
+ 
+-#define V2_INITQVERSIONS {\
++#define V2_INITQVERSIONS_R0 {\
+ 	0,		/* USRQUOTA */\
+ 	0		/* GRPQUOTA */\
+ }
+ 
++#define V2_INITQVERSIONS_R1 {\
++	1,		/* USRQUOTA */\
++	1		/* GRPQUOTA */\
++}
++
+ /*
+  * 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.
+  */
+-struct v2_disk_dqblk {
++struct v2_disk_dqblk_r0 {
+ 	__le32 dqb_id;		/* id this quota applies to */
+ 	__le32 dqb_ihardlimit;	/* absolute limit on allocated inodes */
+ 	__le32 dqb_isoftlimit;	/* preferred inode limit */
+ 	__le32 dqb_curinodes;	/* current # allocated inodes */
+-	__le32 dqb_bhardlimit;	/* absolute limit on disk space (in QUOTABLOCK_SIZE) */
+-	__le32 dqb_bsoftlimit;	/* preferred limit on disk space (in QUOTABLOCK_SIZE) */
++	__le32 dqb_bhardlimit;	/* absolute limit on disk space */
++	__le32 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 */
++};
++
++struct v2_disk_dqblk_r1 {
++	__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 */
+ };
+ 
++union v2_disk_dqblk {
++	struct v2_disk_dqblk_r0 r0;
++	struct v2_disk_dqblk_r1 r1;
++};
++
+ /*
+  * Here are header structures as written on disk and their in-memory copies
+  */
+@@ -59,7 +82,7 @@ struct v2_disk_dqinfo {
+ 
+ /*
+  *  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
++ *  there will be space for exactly 21 (r0) or 14 (r1) quota-entries in a block
+  */
+ struct v2_disk_dqdbheader {
+ 	__le32 dqdh_next_free;	/* Number of next block with free entry */
+@@ -74,6 +97,5 @@ struct v2_disk_dqdbheader {
+ #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 */
+ 
+ #endif /* _LINUX_QUOTAIO_V2_H */
diff --git a/lustre/kernel_patches/patches/quota-large-limits-sles10.patch b/lustre/kernel_patches/patches/quota-large-limits-sles10.patch
new file mode 100644
index 0000000000..fcef1c2768
--- /dev/null
+++ b/lustre/kernel_patches/patches/quota-large-limits-sles10.patch
@@ -0,0 +1,616 @@
+diff -rNpu linux-2.6.16.54-0.2.5/fs/dquot.c linux-2.6.16.54-0.2.5-quota/fs/dquot.c
+--- linux-2.6.16.54-0.2.5/fs/dquot.c	2008-03-18 15:48:26.000000000 +0300
++++ linux-2.6.16.54-0.2.5-quota/fs/dquot.c	2008-03-17 22:43:11.000000000 +0300
+@@ -1588,10 +1588,19 @@ int vfs_get_dqblk(struct super_block *sb
+ }
+ 
+ /* Generic routine for setting common part of quota structure */
+-static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
++static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
+ {
+ 	struct mem_dqblk *dm = &dquot->dq_dqb;
+ 	int check_blim = 0, check_ilim = 0;
++	struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type];
++
++	if ((di->dqb_valid & QIF_BLIMITS &&
++	     (di->dqb_bhardlimit > dqi->dqi_maxblimit ||
++	      di->dqb_bsoftlimit > dqi->dqi_maxblimit)) ||
++	    (di->dqb_valid & QIF_ILIMITS &&
++	     (di->dqb_ihardlimit > dqi->dqi_maxilimit ||
++	      di->dqb_isoftlimit > dqi->dqi_maxilimit)))
++		return -ERANGE;
+ 
+ 	spin_lock(&dq_data_lock);
+ 	if (di->dqb_valid & QIF_SPACE) {
+@@ -1623,7 +1632,7 @@ static void do_set_dqblk(struct dquot *d
+ 			clear_bit(DQ_BLKS_B, &dquot->dq_flags);
+ 		}
+ 		else if (!(di->dqb_valid & QIF_BTIME))	/* Set grace only if user hasn't provided his own... */
+-			dm->dqb_btime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_bgrace;
++			dm->dqb_btime = get_seconds() + dqi->dqi_bgrace;
+ 	}
+ 	if (check_ilim) {
+ 		if (!dm->dqb_isoftlimit || dm->dqb_curinodes < dm->dqb_isoftlimit) {
+@@ -1631,7 +1640,7 @@ static void do_set_dqblk(struct dquot *d
+ 			clear_bit(DQ_INODES_B, &dquot->dq_flags);
+ 		}
+ 		else if (!(di->dqb_valid & QIF_ITIME))	/* Set grace only if user hasn't provided his own... */
+-			dm->dqb_itime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace;
++			dm->dqb_itime = get_seconds() + dqi->dqi_igrace;
+ 	}
+ 	if (dm->dqb_bhardlimit || dm->dqb_bsoftlimit || dm->dqb_ihardlimit || dm->dqb_isoftlimit)
+ 		clear_bit(DQ_FAKE_B, &dquot->dq_flags);
+@@ -1639,21 +1648,24 @@ static void do_set_dqblk(struct dquot *d
+ 		set_bit(DQ_FAKE_B, &dquot->dq_flags);
+ 	spin_unlock(&dq_data_lock);
+ 	mark_dquot_dirty(dquot);
++
++	return 0;
+ }
+ 
+ int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di)
+ {
+ 	struct dquot *dquot;
++	int rc;
+ 
+ 	down(&sb_dqopt(sb)->dqonoff_sem);
+ 	if (!(dquot = dqget(sb, id, type))) {
+ 		up(&sb_dqopt(sb)->dqonoff_sem);
+ 		return -ESRCH;
+ 	}
+-	do_set_dqblk(dquot, di);
++	rc = do_set_dqblk(dquot, di);
+ 	dqput(dquot);
+ 	up(&sb_dqopt(sb)->dqonoff_sem);
+-	return 0;
++	return rc;
+ }
+ 
+ /* Generic routine for getting common part of quota file information */
+diff -rNpu linux-2.6.16.54-0.2.5/fs/quota_v1.c linux-2.6.16.54-0.2.5-quota/fs/quota_v1.c
+--- linux-2.6.16.54-0.2.5/fs/quota_v1.c	2006-03-20 08:53:29.000000000 +0300
++++ linux-2.6.16.54-0.2.5-quota/fs/quota_v1.c	2008-03-17 22:42:47.000000000 +0300
+@@ -139,6 +139,9 @@ static int v1_read_file_info(struct supe
+ 		goto out;
+ 	}
+ 	ret = 0;
++	/* limits are stored as unsigned 32-bit data */
++	dqopt->info[type].dqi_maxblimit = 0xffffffff;
++	dqopt->info[type].dqi_maxilimit = 0xffffffff;
+ 	dqopt->info[type].dqi_igrace = dqblk.dqb_itime ? dqblk.dqb_itime : MAX_IQ_TIME;
+ 	dqopt->info[type].dqi_bgrace = dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME;
+ out:
+diff -rNpu linux-2.6.16.54-0.2.5/fs/quota_v2.c linux-2.6.16.54-0.2.5-quota/fs/quota_v2.c
+--- linux-2.6.16.54-0.2.5/fs/quota_v2.c	2006-03-20 08:53:29.000000000 +0300
++++ linux-2.6.16.54-0.2.5-quota/fs/quota_v2.c	2008-03-18 11:58:02.000000000 +0300
+@@ -23,26 +23,64 @@ MODULE_LICENSE("GPL");
+ 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 GETENTRIES(buf) ((union v2_disk_dqblk *)(((char *)buf) + \
++			 sizeof(struct v2_disk_dqdbheader)))
++#define REV_ASSERT(r) BUG_ON((rev) != 0 && (rev) != 1)
++
++static const union v2_disk_dqblk emptydquot;
++static const union v2_disk_dqblk fakedquot[2] = {
++	{.r0 = {.dqb_itime = __constant_cpu_to_le64(1LLU)} },
++	{.r1 = {.dqb_itime = __constant_cpu_to_le64(1LLU)} }
++};
+ 
+-/* Check whether given file is really vfsv0 quotafile */
+-static int v2_check_quota_file(struct super_block *sb, int type)
++static inline uint v2_dqblksz(uint rev)
++{
++	uint sz;
++
++	REV_ASSERT(rev);
++
++	if (rev == 0)
++		sz = sizeof(struct v2_disk_dqblk_r0);
++	else
++		sz = sizeof(struct v2_disk_dqblk_r1);
++
++	return sz;
++}
++
++/* Number of quota entries in a block */
++static inline int v2_dqstrinblk(uint rev)
++{
++	return (V2_DQBLKSIZE-sizeof(struct v2_disk_dqdbheader))/v2_dqblksz(rev);
++}
++
++/* Get revision of a quota file, -1 if it does not look a quota file */
++static int v2_quota_file_revision(struct super_block *sb, int type)
+ {
+ 	struct v2_disk_dqheader dqhead;
+ 	ssize_t size;
+ 	static const uint quota_magics[] = V2_INITQMAGICS;
+-	static const uint quota_versions[] = V2_INITQVERSIONS;
++	static const uint quota_versions_r0[] = V2_INITQVERSIONS_R0;
++	static const uint quota_versions_r1[] = V2_INITQVERSIONS_R1;
+  
+ 	size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
+ 	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 -1;
+ 	}
+-	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]) {
++		if (le32_to_cpu(dqhead.dqh_version) == quota_versions_r0[type])
++			return 0;
++		if (le32_to_cpu(dqhead.dqh_version) == quota_versions_r1[type])
++			return 1;
++	}
++	return -1;
++}
++
++/* Check whether given file is really vfsv0 quotafile */
++static inline int v2_check_quota_file(struct super_block *sb, int type)
++{
++	return v2_quota_file_revision(sb, type) != -1;
+ }
+ 
+ /* Read information header from quota file */
+@@ -51,6 +89,13 @@ static int v2_read_file_info(struct supe
+ 	struct v2_disk_dqinfo dinfo;
+ 	struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
+ 	ssize_t size;
++	int rev;
++
++	rev = v2_quota_file_revision(sb, type);
++	if (rev < 0) {
++		printk(KERN_WARNING "Second quota file check failed.\n");
++		return -1;
++	}
+ 
+ 	size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
+ 	       sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
+@@ -65,6 +110,16 @@ static int v2_read_file_info(struct supe
+ 	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.dqi_revision = rev;
++	if (rev == 0) {
++		info->dqi_maxblimit = 0xffffffffULL;
++		info->dqi_maxilimit = 0xffffffffULL;
++	} else {
++		info->dqi_maxblimit = 0xffffffffffffffffULL;
++		info->dqi_maxilimit = 0xffffffffffffffffULL;
++	}
++
+ 	return 0;
+ }
+ 
+@@ -94,29 +149,61 @@ static int v2_write_file_info(struct sup
+ 	return 0;
+ }
+ 
+-static void disk2memdqb(struct mem_dqblk *m, struct v2_disk_dqblk *d)
++static void disk2memdqb(struct mem_dqblk *m, union v2_disk_dqblk *d, uint rev)
+ {
+-	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);
+-	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_curspace = le64_to_cpu(d->dqb_curspace);
+-	m->dqb_btime = le64_to_cpu(d->dqb_btime);
+-}
+-
+-static void mem2diskdqb(struct v2_disk_dqblk *d, struct mem_dqblk *m, qid_t id)
+-{
+-	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);
+-	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_curspace = cpu_to_le64(m->dqb_curspace);
+-	d->dqb_btime = cpu_to_le64(m->dqb_btime);
+-	d->dqb_id = cpu_to_le32(id);
++	REV_ASSERT(rev);
++
++	if (rev == 0) {
++		struct v2_disk_dqblk_r0 *ddqblk = &d->r0;
++		m->dqb_ihardlimit = le32_to_cpu(ddqblk->dqb_ihardlimit);
++		m->dqb_isoftlimit = le32_to_cpu(ddqblk->dqb_isoftlimit);
++		m->dqb_curinodes = le32_to_cpu(ddqblk->dqb_curinodes);
++		m->dqb_itime = le64_to_cpu(ddqblk->dqb_itime);
++		m->dqb_bhardlimit = le32_to_cpu(ddqblk->dqb_bhardlimit);
++		m->dqb_bsoftlimit = le32_to_cpu(ddqblk->dqb_bsoftlimit);
++		m->dqb_curspace = le64_to_cpu(ddqblk->dqb_curspace);
++		m->dqb_btime = le64_to_cpu(ddqblk->dqb_btime);
++	} else {
++		struct v2_disk_dqblk_r1 *ddqblk = &d->r1;
++		m->dqb_ihardlimit = le64_to_cpu(ddqblk->dqb_ihardlimit);
++		m->dqb_isoftlimit = le64_to_cpu(ddqblk->dqb_isoftlimit);
++		m->dqb_curinodes = le64_to_cpu(ddqblk->dqb_curinodes);
++		m->dqb_itime = le64_to_cpu(ddqblk->dqb_itime);
++		m->dqb_bhardlimit = le64_to_cpu(ddqblk->dqb_bhardlimit);
++		m->dqb_bsoftlimit = le64_to_cpu(ddqblk->dqb_bsoftlimit);
++		m->dqb_curspace = le64_to_cpu(ddqblk->dqb_curspace);
++		m->dqb_btime = le64_to_cpu(ddqblk->dqb_btime);
++	}
++}
++
++static void mem2diskdqb(union v2_disk_dqblk *d, struct mem_dqblk *m,
++			qid_t id, uint rev)
++{
++	REV_ASSERT(rev);
++
++	if (rev == 0) {
++		struct v2_disk_dqblk_r0 *ddqblk = &d->r0;
++		ddqblk->dqb_id = cpu_to_le32(id);
++		ddqblk->dqb_ihardlimit = cpu_to_le32((__u32)m->dqb_ihardlimit);
++		ddqblk->dqb_isoftlimit = cpu_to_le32((__u32)m->dqb_isoftlimit);
++		ddqblk->dqb_curinodes = cpu_to_le32((__u32)m->dqb_curinodes);
++		ddqblk->dqb_itime = cpu_to_le64(m->dqb_itime);
++		ddqblk->dqb_bhardlimit = cpu_to_le32((__u32)m->dqb_bhardlimit);
++		ddqblk->dqb_bsoftlimit = cpu_to_le32((__u32)m->dqb_bsoftlimit);
++		ddqblk->dqb_curspace = cpu_to_le64(m->dqb_curspace);
++		ddqblk->dqb_btime = cpu_to_le64(ddqblk->dqb_btime);
++	} else {
++		struct v2_disk_dqblk_r1 *ddqblk = &d->r1;
++		ddqblk->dqb_id = cpu_to_le32(id);
++		ddqblk->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
++		ddqblk->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
++		ddqblk->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
++		ddqblk->dqb_itime = cpu_to_le64(m->dqb_itime);
++		ddqblk->dqb_bhardlimit = cpu_to_le64(m->dqb_bhardlimit);
++		ddqblk->dqb_bsoftlimit = cpu_to_le64(m->dqb_bsoftlimit);
++		ddqblk->dqb_curspace = cpu_to_le64(m->dqb_curspace);
++		ddqblk->dqb_btime = cpu_to_le64(ddqblk->dqb_btime);
++	}
+ }
+ 
+ static dqbuf_t getdqbuf(void)
+@@ -268,10 +355,10 @@ static uint find_free_dqentry(struct dqu
+ {
+ 	struct super_block *sb = dquot->dq_sb;
+ 	struct mem_dqinfo *info = sb_dqopt(sb)->info+dquot->dq_type;
+-	uint blk, i;
++	uint blk, i, rev = info->u.v2_i.dqi_revision;
++	uint dqblksz = v2_dqblksz(rev), dqstrinblk = v2_dqstrinblk(rev);
+ 	struct v2_disk_dqdbheader *dh;
+-	struct v2_disk_dqblk *ddquot;
+-	struct v2_disk_dqblk fakedquot;
++	union v2_disk_dqblk *ddquot;
+ 	dqbuf_t buf;
+ 
+ 	*err = 0;
+@@ -298,17 +385,18 @@ static uint find_free_dqentry(struct dqu
+ 		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? */
++	/* Block will be full? */
++	if (le16_to_cpu(dh->dqdh_entries)+1 >= dqstrinblk)
+ 		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;
+ 		}
+ 	dh->dqdh_entries = cpu_to_le16(le16_to_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++);
++	for (i = 0; i < dqstrinblk && memcmp(&emptydquot, ddquot, dqblksz);
++	     i++, ddquot = (char *)ddquot + dqblksz);
+ #ifdef __QUOTA_V2_PARANOIA
+-	if (i == V2_DQSTRINBLK) {
++	if (i == dqstrinblk) {
+ 		printk(KERN_ERR "VFS: find_free_dqentry(): Data block full but it shouldn't.\n");
+ 		*err = -EIO;
+ 		goto out_buf;
+@@ -318,7 +406,8 @@ static uint find_free_dqentry(struct dqu
+ 		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);
++	dquot->dq_off = (blk<<V2_DQBLKSIZE_BITS)+
++			((char *)ddquot - (char *)buf);
+ 	freedqbuf(buf);
+ 	return blk;
+ out_buf:
+@@ -392,7 +481,9 @@ static int v2_write_dquot(struct dquot *
+ {
+ 	int type = dquot->dq_type;
+ 	ssize_t ret;
+-	struct v2_disk_dqblk ddquot, empty;
++	union v2_disk_dqblk ddquot;
++	uint rev = sb_dqopt(dquot->dq_sb)->info[type].u.v2_i.dqi_revision;
++	uint dqblksz = v2_dqblksz(rev);
+ 
+ 	/* dq_off is guarded by dqio_sem */
+ 	if (!dquot->dq_off)
+@@ -401,18 +492,22 @@ static int v2_write_dquot(struct dquot *
+ 			return ret;
+ 		}
+ 	spin_lock(&dq_data_lock);
+-	mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
++	mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id, rev);
+ 	/* 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);
++	if (!memcmp(&emptydquot, &ddquot, dqblksz)) {
++		if (rev == 0)
++			ddquot.r0.dqb_itime = cpu_to_le64(1);
++		else
++			ddquot.r1.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);
++	      (char *)&ddquot, dqblksz, dquot->dq_off);
++	if (ret != dqblksz) {
++		printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
++			dquot->dq_sb->s_id);
+ 		if (ret >= 0)
+ 			ret = -ENOSPC;
+ 	}
+@@ -431,6 +526,7 @@ static int free_dqentry(struct dquot *dq
+ 	struct v2_disk_dqdbheader *dh;
+ 	dqbuf_t buf = getdqbuf();
+ 	int ret = 0;
++	uint rev = sb_dqopt(sb)->info[type].u.v2_i.dqi_revision;
+ 
+ 	if (!buf)
+ 		return -ENOMEM;
+@@ -456,8 +552,8 @@ static int free_dqentry(struct dquot *dq
+ 	}
+ 	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) {
++		  v2_dqblksz(rev));
++		if (le16_to_cpu(dh->dqdh_entries) == v2_dqstrinblk(rev)-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);
+@@ -529,41 +625,56 @@ static int v2_delete_dquot(struct dquot 
+ 	return remove_tree(dquot, &tmp, 0);
+ }
+ 
++static inline __u32 dqid(union v2_disk_dqblk *ddquot, uint rev)
++{
++	__u32 dq_id;
++
++	REV_ASSERT(rev);
++
++	if (rev == 0)
++		dq_id = le32_to_cpu(ddquot->r0.dqb_id);
++	else
++		dq_id = le32_to_cpu(ddquot->r1.dqb_id);
++
++	return dq_id;
++}
++
+ /* 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);
++	union v2_disk_dqblk *ddquot = GETENTRIES(buf);
++	int type = dquot->dq_type;
++	uint rev = sb_dqopt(dquot->dq_sb)->info[type].u.v2_i.dqi_revision;
++	uint dqblksz = v2_dqblksz(rev), dqstrinblk = v2_dqstrinblk(rev);
+ 
+ 	if (!buf)
+ 		return -ENOMEM;
+-	if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
++
++	ret = read_blk(dquot->dq_sb, type, blk, buf);
++	if (ret < 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++);
++		for (i = 0; i < dqstrinblk && dqid(ddquot, rev) != dquot->dq_id;
++		     i++, ddquot = (char *)ddquot + dqblksz);
+ 	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)))
++		for (i = 0; i < dqstrinblk; i++, ddquot = (char *)ddquot+dqblksz)
++			if (!dqid(ddquot, rev) &&
++			    memcmp(&emptydquot, ddquot, dqblksz))
+ 				break;
+ 	}
+-	if (i == V2_DQSTRINBLK) {
++	if (i == 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);
++		ret = (blk << V2_DQBLKSIZE_BITS)+((char *)ddquot-(char *)buf);
+ out_buf:
+ 	freedqbuf(buf);
+ 	return ret;
+@@ -605,7 +716,7 @@ static int v2_read_dquot(struct dquot *d
+ {
+ 	int type = dquot->dq_type;
+ 	loff_t offset;
+-	struct v2_disk_dqblk ddquot, empty;
++	union v2_disk_dqblk ddquot;
+ 	int ret = 0;
+ 
+ #ifdef __QUOTA_V2_PARANOIA
+@@ -626,25 +737,30 @@ static int v2_read_dquot(struct dquot *d
+ 		ret = offset;
+ 	}
+ 	else {
++		uint rev = sb_dqopt(dquot->dq_sb)->info[type].u.v2_i.
++			   dqi_revision;
++		uint  dqblksz = v2_dqblksz(rev);
+ 		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)) {
++		ret = dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type,
++					   (char *)&ddquot, dqblksz, offset);
++		if (ret != dqblksz) {
+ 			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));
++			memset(&ddquot, 0, dqblksz);
+ 		}
+ 		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;
++			if (!memcmp(&fakedquot[rev], &ddquot, dqblksz)) {
++				if (rev == 0)
++					ddquot.r0.dqb_itime = cpu_to_le64(0);
++				else
++					ddquot.r1.dqb_itime = cpu_to_le64(0);
++			}
+ 		}
+-		disk2memdqb(&dquot->dq_dqb, &ddquot);
++		disk2memdqb(&dquot->dq_dqb, &ddquot, rev);
+ 		if (!dquot->dq_dqb.dqb_bhardlimit &&
+ 			!dquot->dq_dqb.dqb_bsoftlimit &&
+ 			!dquot->dq_dqb.dqb_ihardlimit &&
+diff -rNpu linux-2.6.16.54-0.2.5/include/linux/dqblk_v2.h linux-2.6.16.54-0.2.5-quota/include/linux/dqblk_v2.h
+--- linux-2.6.16.54-0.2.5/include/linux/dqblk_v2.h	2006-03-20 08:53:29.000000000 +0300
++++ linux-2.6.16.54-0.2.5-quota/include/linux/dqblk_v2.h	2008-03-17 23:39:54.000000000 +0300
+@@ -21,6 +21,7 @@ struct v2_mem_dqinfo {
+ 	unsigned int dqi_blocks;
+ 	unsigned int dqi_free_blk;
+ 	unsigned int dqi_free_entry;
++	unsigned int dqi_revision;
+ };
+ 
+ #endif /* _LINUX_DQBLK_V2_H */
+diff -rNpu linux-2.6.16.54-0.2.5/include/linux/quota.h linux-2.6.16.54-0.2.5-quota/include/linux/quota.h
+--- linux-2.6.16.54-0.2.5/include/linux/quota.h	2006-03-20 08:53:29.000000000 +0300
++++ linux-2.6.16.54-0.2.5-quota/include/linux/quota.h	2008-03-17 23:39:54.000000000 +0300
+@@ -148,12 +148,12 @@ struct if_dqinfo {
+  * 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 */
+ };
+@@ -169,6 +169,8 @@ struct mem_dqinfo {
+ 	unsigned long dqi_flags;
+ 	unsigned int dqi_bgrace;
+ 	unsigned int dqi_igrace;
++	qsize_t dqi_maxblimit;
++	qsize_t dqi_maxilimit;
+ 	union {
+ 		struct v1_mem_dqinfo v1_i;
+ 		struct v2_mem_dqinfo v2_i;
+diff -rNpu linux-2.6.16.54-0.2.5/include/linux/quotaio_v2.h linux-2.6.16.54-0.2.5-quota/include/linux/quotaio_v2.h
+--- linux-2.6.16.54-0.2.5/include/linux/quotaio_v2.h	2006-03-20 08:53:29.000000000 +0300
++++ linux-2.6.16.54-0.2.5-quota/include/linux/quotaio_v2.h	2008-03-17 23:39:54.000000000 +0300
+@@ -16,28 +16,51 @@
+ 	0xd9c01927	/* GRPQUOTA */\
+ }
+ 
+-#define V2_INITQVERSIONS {\
++#define V2_INITQVERSIONS_R0 {\
+ 	0,		/* USRQUOTA */\
+ 	0		/* GRPQUOTA */\
+ }
+ 
++#define V2_INITQVERSIONS_R1 {\
++	1,		/* USRQUOTA */\
++	1		/* GRPQUOTA */\
++}
++
+ /*
+  * 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.
+  */
+-struct v2_disk_dqblk {
++struct v2_disk_dqblk_r0 {
+ 	__le32 dqb_id;		/* id this quota applies to */
+ 	__le32 dqb_ihardlimit;	/* absolute limit on allocated inodes */
+ 	__le32 dqb_isoftlimit;	/* preferred inode limit */
+ 	__le32 dqb_curinodes;	/* current # allocated inodes */
+-	__le32 dqb_bhardlimit;	/* absolute limit on disk space (in QUOTABLOCK_SIZE) */
+-	__le32 dqb_bsoftlimit;	/* preferred limit on disk space (in QUOTABLOCK_SIZE) */
++	__le32 dqb_bhardlimit;	/* absolute limit on disk space */
++	__le32 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 */
++};
++
++struct v2_disk_dqblk_r1 {
++	__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 */
+ };
+ 
++union v2_disk_dqblk {
++	struct v2_disk_dqblk_r0 r0;
++	struct v2_disk_dqblk_r1 r1;
++};
++
+ /*
+  * Here are header structures as written on disk and their in-memory copies
+  */
+@@ -59,7 +82,7 @@ struct v2_disk_dqinfo {
+ 
+ /*
+  *  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
++ *  there will be space for exactly 21 (r0) or 14 (r1) quota-entries in a block
+  */
+ struct v2_disk_dqdbheader {
+ 	__le32 dqdh_next_free;	/* Number of next block with free entry */
+@@ -74,6 +97,5 @@ struct v2_disk_dqdbheader {
+ #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 */
+ 
+ #endif /* _LINUX_QUOTAIO_V2_H */
diff --git a/lustre/kernel_patches/series/2.6-rhel5.series b/lustre/kernel_patches/series/2.6-rhel5.series
index 3fa02582e1..2cc60e8cf7 100644
--- a/lustre/kernel_patches/series/2.6-rhel5.series
+++ b/lustre/kernel_patches/series/2.6-rhel5.series
@@ -18,3 +18,4 @@ raid5-merge-ios-rhel5.patch
 raid5-zerocopy-rhel5.patch
 md-rebuild-policy.patch
 jbd-journal-chksum-2.6.18-vanilla.patch
+quota-large-limits-rhel5.patch
diff --git a/lustre/kernel_patches/series/2.6-sles10.series b/lustre/kernel_patches/series/2.6-sles10.series
index 75df8c8d1c..9a86b21d28 100644
--- a/lustre/kernel_patches/series/2.6-sles10.series
+++ b/lustre/kernel_patches/series/2.6-sles10.series
@@ -13,3 +13,4 @@ i_filter_data.patch
 quota-fix-oops-in-invalidate_dquots.patch
 fmode-exec-2.6-sles10.patch
 jbd-journal-chksum-2.6-sles10.patch
+quota-large-limits-sles10.patch
diff --git a/lustre/kernel_patches/series/2.6.22-vanilla.series b/lustre/kernel_patches/series/2.6.22-vanilla.series
index 6b48f98a57..2d29ae1ac3 100644
--- a/lustre/kernel_patches/series/2.6.22-vanilla.series
+++ b/lustre/kernel_patches/series/2.6.22-vanilla.series
@@ -10,3 +10,4 @@ export-2.6.18-vanilla.patch
 8kstack-2.6.12.patch
 export-show_task-2.6.18-vanilla.patch 
 sd_iostats-2.6.22-vanilla.patch
+quota-large-limits-rhel5.patch
-- 
GitLab