From: James Simmons Date: Thu, 18 Jul 2013 16:44:22 +0000 (-0400) Subject: LU-3305 quota: Update SuSE kernel to handle quota changes in 2.4+ X-Git-Tag: 2.4.53~13 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=88d9dcf58c94919629d6d96c68dc7277e62db7da LU-3305 quota: Update SuSE kernel to handle quota changes in 2.4+ This patch address two issues needed for SuSE systems. The first is 64 bit quotas are not properly support in SLES11 SP1. We update quota-support-64-bit-quota-format, which is no longer needed for RHEL system, to allow 64 bit quotas for SP1. The second is the port of the patch to handle the global lock contention inside the dqget()/dqput(). We'd avoid calling dqget()/dqput() in dquot_initialize(). Signed-off-by: James Simmons Change-Id: I16a989a68925dfcd098415f6e1f621a6e5c2a9b1 Reviewed-on: http://review.whamcloud.com/7032 Reviewed-by: Bob Glossman Reviewed-by: Niu Yawei Tested-by: Hudson Tested-by: Maloo Reviewed-by: Oleg Drokin --- diff --git a/lustre/kernel_patches/patches/quota-avoid-dqget-calls-sles11sp2.patch b/lustre/kernel_patches/patches/quota-avoid-dqget-calls-sles11sp2.patch new file mode 100644 index 0000000..cd39fe1 --- /dev/null +++ b/lustre/kernel_patches/patches/quota-avoid-dqget-calls-sles11sp2.patch @@ -0,0 +1,56 @@ +--- linux-3.0/fs/quota/dquot.c.orig 2013-07-18 09:46:28.000000000 -0400 ++++ linux-3.0/fs/quota/dquot.c 2013-07-18 09:49:20.000000000 -0400 +@@ -1342,7 +1342,7 @@ + static void __dquot_initialize(struct inode *inode, int type) + { + unsigned int id = 0; +- int cnt; ++ int cnt, ret = 0, dq_get = 0; + struct dquot *got[MAXQUOTAS]; + struct super_block *sb = inode->i_sb; + qsize_t rsv; +@@ -1352,7 +1352,14 @@ + if (!dquot_active(inode)) + return; + +- /* First get references to structures we might need. */ ++ /* In most case, the i_dquot should have been initialized, except ++ * the newly allocated one. We'd always try to skip the dqget() and ++ * dqput() calls to avoid unnecessary global lock contention. */ ++ if (!(inode->i_state & I_NEW)) ++ goto init_idquot; ++ ++get_dquots: ++ dq_get = 1; + for (cnt = 0; cnt < MAXQUOTAS; cnt++) { + got[cnt] = NULL; + if (type != -1 && cnt != type) +@@ -1367,7 +1374,7 @@ + } + got[cnt] = dqget(sb, id, cnt); + } +- ++init_idquot: + spin_lock(&inode->i_lock); + if (IS_NOQUOTA(inode)) + goto out_err; +@@ -1381,6 +1388,10 @@ + if (!got[cnt]) + continue; + if (!inode->i_dquot[cnt]) { ++ if (dq_get == 0) { ++ spin_unlock(&inode->i_lock); ++ goto get_dquots; ++ } + inode->i_dquot[cnt] = got[cnt]; + got[cnt] = NULL; + /* +@@ -1388,7 +1399,7 @@ + * did a write before quota was turned on + */ + rsv = inode_get_rsv_space(inode); +- if (unlikely(rsv)) { ++ if (unlikely(rsv) && likely(inode->i_dquot[cnt])) { + spin_lock(&dq_data_lock); + dquot_resv_space(inode->i_dquot[cnt], rsv); + spin_unlock(&dq_data_lock); diff --git a/lustre/kernel_patches/patches/replace_dqptr_sem-sles11.patch b/lustre/kernel_patches/patches/quota-replace-dqptr-sem-sles11.patch similarity index 95% rename from lustre/kernel_patches/patches/replace_dqptr_sem-sles11.patch rename to lustre/kernel_patches/patches/quota-replace-dqptr-sem-sles11.patch index 1d15116..4aeb39e 100644 --- a/lustre/kernel_patches/patches/replace_dqptr_sem-sles11.patch +++ b/lustre/kernel_patches/patches/quota-replace-dqptr-sem-sles11.patch @@ -1,6 +1,6 @@ -diff -urp linux-2.6.32.46-0.orig/fs/quota/dquot.c linux-2.6.32.46-0/fs/quota/dquot.c ---- linux-2.6.32.46-0.orig/fs/quota/dquot.c 2013-04-26 11:56:35.000000000 -0400 -+++ linux-2.6.32.46-0/fs/quota/dquot.c 2013-04-26 12:00:44.000000000 -0400 +diff -urp linux-2.6.32-53.7.orig/fs/quota/dquot.c linux-2.6.32.46-0/fs/quota/dquot.c +--- linux-2.6.32-53.7.orig/fs/quota/dquot.c 2013-04-26 11:56:35.000000000 -0400 ++++ linux-2.6.32-53.7/fs/quota/dquot.c 2013-04-26 12:00:44.000000000 -0400 @@ -89,22 +89,17 @@ /* * There are three quota SMP locks. dq_list_lock protects all lists with quotas @@ -571,9 +571,9 @@ diff -urp linux-2.6.32.46-0.orig/fs/quota/dquot.c linux-2.6.32.46-0/fs/quota/dqu } mutex_unlock(&dqopt->dqonoff_mutex); out_fmt: -diff -urp linux-2.6.32.46-0.orig/fs/quota/quota.c linux-2.6.32.46-0/fs/quota/quota.c ---- linux-2.6.32.46-0.orig/fs/quota/quota.c 2009-12-02 22:51:21.000000000 -0500 -+++ linux-2.6.32.46-0/fs/quota/quota.c 2013-04-26 11:59:22.000000000 -0400 +diff -urp linux-2.6.32-53.7.orig/fs/quota/quota.c linux-2.6.32.46-0/fs/quota/quota.c +--- linux-2.6.32-53.7.orig/fs/quota/quota.c 2009-12-02 22:51:21.000000000 -0500 ++++ linux-2.6.32-53.7/fs/quota/quota.c 2013-04-26 11:59:22.000000000 -0400 @@ -255,13 +255,13 @@ static int do_quotactl(struct super_bloc case Q_GETFMT: { __u32 fmt; @@ -591,9 +591,9 @@ diff -urp linux-2.6.32.46-0.orig/fs/quota/quota.c linux-2.6.32.46-0/fs/quota/quo if (copy_to_user(addr, &fmt, sizeof(fmt))) return -EFAULT; return 0; -diff -urp linux-2.6.32.46-0.orig/fs/stat.c linux-2.6.32.46-0/fs/stat.c ---- linux-2.6.32.46-0.orig/fs/stat.c 2013-04-26 11:56:28.000000000 -0400 -+++ linux-2.6.32.46-0/fs/stat.c 2013-04-26 11:59:22.000000000 -0400 +diff -urp linux-2.6.32-53.7.orig/fs/stat.c linux-2.6.32.46-0/fs/stat.c +--- linux-2.6.32-53.7.orig/fs/stat.c 2013-04-26 11:56:28.000000000 -0400 ++++ linux-2.6.32-53.7/fs/stat.c 2013-04-26 11:59:22.000000000 -0400 @@ -422,9 +422,8 @@ void inode_add_bytes(struct inode *inode EXPORT_SYMBOL(inode_add_bytes); @@ -635,9 +635,9 @@ diff -urp linux-2.6.32.46-0.orig/fs/stat.c linux-2.6.32.46-0/fs/stat.c spin_unlock(&inode->i_lock); return ret; } -diff -urp linux-2.6.32.46-0.orig/fs/super.c linux-2.6.32.46-0/fs/super.c ---- linux-2.6.32.46-0.orig/fs/super.c 2013-04-26 11:56:52.000000000 -0400 -+++ linux-2.6.32.46-0/fs/super.c 2013-04-26 11:59:22.000000000 -0400 +diff -urp linux-2.6.32-53.7.orig/fs/super.c linux-2.6.32.46-0/fs/super.c +--- linux-2.6.32-53.7.orig/fs/super.c 2013-04-26 11:56:52.000000000 -0400 ++++ linux-2.6.32-53.7/fs/super.c 2013-04-26 11:59:22.000000000 -0400 @@ -98,7 +98,6 @@ static struct super_block *alloc_super(s mutex_init(&s->s_vfs_rename_mutex); mutex_init(&s->s_dquot.dqio_mutex); @@ -646,9 +646,9 @@ diff -urp linux-2.6.32.46-0.orig/fs/super.c linux-2.6.32.46-0/fs/super.c init_waitqueue_head(&s->s_wait_unfrozen); s->s_maxbytes = MAX_NON_LFS; s->dq_op = sb_dquot_ops; -diff -urp linux-2.6.32.46-0.orig/include/linux/fs.h linux-2.6.32.46-0/include/linux/fs.h ---- linux-2.6.32.46-0.orig/include/linux/fs.h 2013-04-26 11:56:52.000000000 -0400 -+++ linux-2.6.32.46-0/include/linux/fs.h 2013-04-26 11:59:22.000000000 -0400 +diff -urp linux-2.6.32-53.7.orig/include/linux/fs.h linux-2.6.32.46-0/include/linux/fs.h +--- linux-2.6.32-53.7.orig/include/linux/fs.h 2013-04-26 11:56:52.000000000 -0400 ++++ linux-2.6.32-53.7/include/linux/fs.h 2013-04-26 11:59:22.000000000 -0400 @@ -2356,7 +2356,9 @@ extern void generic_fillattr(struct inod extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); void __inode_add_bytes(struct inode *inode, loff_t bytes); diff --git a/lustre/kernel_patches/patches/replace_dqptr_sem-sles11sp2.patch b/lustre/kernel_patches/patches/quota-replace-dqptr-sem-sles11sp2.patch similarity index 100% rename from lustre/kernel_patches/patches/replace_dqptr_sem-sles11sp2.patch rename to lustre/kernel_patches/patches/quota-replace-dqptr-sem-sles11sp2.patch diff --git a/lustre/kernel_patches/patches/quota-support-64-bit-quota-format.patch b/lustre/kernel_patches/patches/quota-support-64-bit-quota-format.patch index 627c0fc..a1ae56b 100644 --- a/lustre/kernel_patches/patches/quota-support-64-bit-quota-format.patch +++ b/lustre/kernel_patches/patches/quota-support-64-bit-quota-format.patch @@ -7,16 +7,11 @@ original implementation has been written by Andrew Perepechko. Signed-off-by: Andrew Perepechko Signed-off-by: Jan Kara Signed-off-by: Andrew Morton ---- - fs/quota_v2.c | 140 ++++++++++++++++++++++++++++++++++++---------- - fs/quotaio_v2.h | 26 ++++++-- - 2 files changed, 132 insertions(+), 34 deletions(-) - -diff -puN fs/quota/quota_v2.c~quota-support-64-bit-quota-format fs/quota/quota_v2.c ---- a/fs/quota/quota_v2.c~quota-support-64-bit-quota-format -+++ a/fs/quota/quota_v2.c -@@ -23,14 +23,24 @@ MODULE_LICENSE("GPL"); +diff --git a/fs/quota/quota_v2.c a/fs/quota/quota_v2.c +--- a/fs/quota/quota_v2.c ++++ b/fs/quota/quota_v2.c +@@ -23,14 +23,23 @@ #define __QUOTA_V2_PARANOIA @@ -31,6 +26,9 @@ diff -puN fs/quota/quota_v2.c~quota-support-64-bit-quota-format fs/quota/quota_v +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 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 v2r0_qtree_ops = { + .mem2disk_dqblk = v2r0_mem2diskdqb, @@ -38,10 +36,6 @@ diff -puN fs/quota/quota_v2.c~quota-support-64-bit-quota-format fs/quota/quota_v + .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, @@ -49,57 +43,64 @@ diff -puN fs/quota/quota_v2.c~quota-support-64-bit-quota-format fs/quota/quota_v }; #define QUOTABLOCK_BITS 10 -@@ -46,8 +56,7 @@ static inline qsize_t v2_qbtos(qsize_t b +@@ -46,23 +55,32 @@ 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) ++static int v2_read_header(struct super_block *sb, int type, ++ struct v2_disk_dqheader *dqhead) ++{ ++ ssize_t size; ++ ++ 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", ++ sizeof(struct v2_disk_dqheader), size); ++ return 0; ++ } ++ return 1; ++} ++ + /* Check whether given file is really vfsv0 quotafile */ + static int v2_check_quota_file(struct super_block *sb, int type) { struct v2_disk_dqheader dqhead; - ssize_t size; -@@ -58,12 +67,20 @@ static int v2_check_quota_file(struct su - 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] || +- ssize_t size; + static const uint quota_magics[] = V2_INITQMAGICS; + static const uint quota_versions[] = V2_INITQVERSIONS; + +- 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); ++ if (!v2_read_header(sb, type, &dqhead)) + return 0; +- } + 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; ++ le32_to_cpu(dqhead.dqh_version) > quota_versions[type]) + return 0; + return 1; } - - /* Read information header from quota file */ -@@ -73,7 +90,13 @@ static int v2_read_file_info(struct supe +@@ -71,9 +89,15 @@ + static int v2_read_file_info(struct super_block *sb, int type) + { + struct v2_disk_dqinfo dinfo; ++ struct v2_disk_dqheader dqhead; struct mem_dqinfo *info = sb_dqinfo(sb, type); struct qtree_mem_dqinfo *qinfo; 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); ++ unsigned int version; ++ ++ if (!v2_read_header(sb, type, &dqhead)) + return -1; -+ } ++ version = le32_to_cpu(dqhead.dqh_version); + size = sb->s_op->quota_read(sb, type, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF); - if (size != sizeof(struct v2_disk_dqinfo)) { -@@ -88,9 +111,14 @@ static int v2_read_file_info(struct supe +@@ -89,9 +113,15 @@ return -1; } qinfo = info->dqi_priv; @@ -111,13 +112,14 @@ diff -puN fs/quota/quota_v2.c~quota-support-64-bit-quota-format fs/quota/quota_v + info->dqi_maxblimit = 0xffffffff; + info->dqi_maxilimit = 0xffffffff; + } else { -+ info->dqi_maxblimit = 0x7fffffffffffffffULL; -+ info->dqi_maxilimit = 0x7fffffffffffffffULL; ++ /* used space is stored as unsigned 64-bit value */ ++ info->dqi_maxblimit = 0xffffffffffffffffULL; /* 2^64-1 */ ++ info->dqi_maxilimit = 0xffffffffffffffffULL; + } 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); -@@ -102,8 +130,13 @@ static int v2_read_file_info(struct supe +@@ -103,8 +133,13 @@ qinfo->dqi_blocksize_bits = V2_DQBLKSIZE_BITS; qinfo->dqi_usable_bs = 1 << V2_DQBLKSIZE_BITS; qinfo->dqi_qtree_depth = qtree_depth(qinfo); @@ -133,7 +135,7 @@ diff -puN fs/quota/quota_v2.c~quota-support-64-bit-quota-format fs/quota/quota_v return 0; } -@@ -134,9 +167,9 @@ static int v2_write_file_info(struct sup +@@ -135,9 +170,9 @@ return 0; } @@ -145,7 +147,7 @@ diff -puN fs/quota/quota_v2.c~quota-support-64-bit-quota-format fs/quota/quota_v struct mem_dqblk *m = &dquot->dq_dqb; m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit); -@@ -148,15 +181,15 @@ static void v2_disk2memdqb(struct dquot +@@ -149,15 +184,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 */ @@ -165,7 +167,7 @@ diff -puN fs/quota/quota_v2.c~quota-support-64-bit-quota-format fs/quota/quota_v struct mem_dqblk *m = &dquot->dq_dqb; struct qtree_mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; -@@ -174,9 +207,60 @@ static void v2_mem2diskdqb(void *dp, str +@@ -175,9 +210,60 @@ d->dqb_itime = cpu_to_le64(1); } @@ -206,7 +208,7 @@ diff -puN fs/quota/quota_v2.c~quota-support-64-bit-quota-format fs/quota/quota_v + 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; ++ 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); @@ -228,9 +230,45 @@ diff -puN fs/quota/quota_v2.c~quota-support-64-bit-quota-format fs/quota/quota_v struct qtree_mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv; -diff -puN fs/quota/quotaio_v2.h~quota-support-64-bit-quota-format fs/quota/quotaio_v2.h ---- a/fs/quota/quotaio_v2.h~quota-support-64-bit-quota-format -+++ a/fs/quota/quotaio_v2.h +@@ -301,20 +303,32 @@ static struct quota_format_ops v2_format + .release_dqblk = v2_release_dquot, + }; + +-static struct quota_format_type v2_quota_format = { ++static struct quota_format_type v2r0_quota_format = { + .qf_fmt_id = QFMT_VFS_V0, + .qf_ops = &v2_format_ops, + .qf_owner = THIS_MODULE + }; + ++static struct quota_format_type v2r1_quota_format = { ++ .qf_fmt_id = QFMT_VFS_V1, ++ .qf_ops = &v2_format_ops, ++ .qf_owner = THIS_MODULE ++}; ++ + static int __init init_v2_quota_format(void) + { +- return register_quota_format(&v2_quota_format); ++ int ret; ++ ++ ret = register_quota_format(&v2r0_quota_format); ++ if (ret) ++ return ret; ++ return register_quota_format(&v2r1_quota_format); + } + + static void __exit exit_v2_quota_format(void) + { +- unregister_quota_format(&v2_quota_format); ++ unregister_quota_format(&v2r0_quota_format); ++ unregister_quota_format(&v2r1_quota_format); + } + + module_init(init_v2_quota_format); +diff --git a/fs/quota/quotaio_v2.h b/fs/quota/quotaio_v2.h +--- a/fs/quota/quotaio_v2.h ++++ b/fs/quota/quotaio_v2.h @@ -17,8 +17,8 @@ } @@ -280,3 +318,23 @@ diff -puN fs/quota/quotaio_v2.h~quota-support-64-bit-quota-format fs/quota/quota struct v2_disk_dqinfo { __le32 dqi_bgrace; /* Time before block soft limit becomes hard limit */ _ +diff --git a/include/linux/quota.h b/include/linux/quota.h +--- a/include/linux/quota.h ++++ b/include/linux/quota.h +@@ -73,6 +73,8 @@ + /* Quota format type IDs */ + #define QFMT_VFS_OLD 1 + #define QFMT_VFS_V0 2 ++#define QFMT_OCFS2 3 ++#define QFMT_VFS_V1 4 + + /* Size of block in which space limits are passed through the quota + * interface */ +@@ -398,6 +398,7 @@ struct quota_module_name { + #define INIT_QUOTA_MODULE_NAMES {\ + {QFMT_VFS_OLD, "quota_v1"},\ + {QFMT_VFS_V0, "quota_v2"},\ ++ {QFMT_VFS_V1, "quota_v2"},\ + {0, NULL}} + + #else diff --git a/lustre/kernel_patches/series/2.6-sles11.series b/lustre/kernel_patches/series/2.6-sles11.series index 8d9fd42..569f10f 100644 --- a/lustre/kernel_patches/series/2.6-sles11.series +++ b/lustre/kernel_patches/series/2.6-sles11.series @@ -5,4 +5,5 @@ quota-support-64-bit-quota-format.patch export-2.6.32-vanilla.patch jbd2-jcberr-2.6-rhel6.patch bh_lru_size_config.patch -replace_dqptr_sem-sles11.patch +quota-replace-dqptr-sem-sles11.patch +quota-avoid-dqget-calls.patch diff --git a/lustre/kernel_patches/series/3.0-sles11.series b/lustre/kernel_patches/series/3.0-sles11.series index b7a51fd..0b42b86 100644 --- a/lustre/kernel_patches/series/3.0-sles11.series +++ b/lustre/kernel_patches/series/3.0-sles11.series @@ -1,4 +1,5 @@ raid5-mmp-unplug-dev-sles11sp2.patch -replace_dqptr_sem-sles11sp2.patch +quota-replace-dqptr-sem-sles11sp2.patch +quota-avoid-dqget-calls-sles11sp2.patch blkdev_tunables-3.0-sles11.patch bh_lru_size_config.patch