[Pkg-lustre-svn-commit] r471 - in /trunk/debian: changelog patches/00list patches/bug13904-fix2.dpatch patches/bug15036-fix1.dpatch rules

winnie at users.alioth.debian.org winnie at users.alioth.debian.org
Tue Apr 22 14:15:20 UTC 2008


Author: winnie
Date: Tue Apr 22 14:15:17 2008
New Revision: 471

URL: http://svn.debian.org/wsvn/pkg-lustre/?sc=1&rev=471
Log:
Tryp to make quotas >4TB working

Added:
    trunk/debian/patches/bug13904-fix2.dpatch
    trunk/debian/patches/bug15036-fix1.dpatch
Modified:
    trunk/debian/changelog
    trunk/debian/patches/00list
    trunk/debian/rules

Modified: trunk/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-lustre/trunk/debian/changelog?rev=471&op=diff
==============================================================================
--- trunk/debian/changelog (original)
+++ trunk/debian/changelog Tue Apr 22 14:15:17 2008
@@ -2,9 +2,9 @@
 
   * Changed lustre version in rules.. forgot that in last upload
     - replaced static string with some basename/awk magic
-  * 
-
- -- Patrick Winnertz <winnie at debian.org>  Mon, 21 Apr 2008 20:36:44 +0200
+  * Try to make quotas > 4TB work 
+
+ -- Patrick Winnertz <winnie at debian.org>  Tue, 22 Apr 2008 16:14:21 +0200
 
 lustre (1.6.4.3-1) unstable; urgency=low
 

Modified: trunk/debian/patches/00list
URL: http://svn.debian.org/wsvn/pkg-lustre/trunk/debian/patches/00list?rev=471&op=diff
==============================================================================
--- trunk/debian/patches/00list (original)
+++ trunk/debian/patches/00list Tue Apr 22 14:15:17 2008
@@ -25,3 +25,5 @@
 bug6334-prevent_multiple_mounts.dpatch
 fix-lustre-manpage.dpatch
 enable-quota.dpatch
+bug13904-fix2.dpatch
+bug15036-fix1.dpatch

Added: trunk/debian/patches/bug13904-fix2.dpatch
URL: http://svn.debian.org/wsvn/pkg-lustre/trunk/debian/patches/bug13904-fix2.dpatch?rev=471&op=file
==============================================================================
--- trunk/debian/patches/bug13904-fix2.dpatch (added)
+++ trunk/debian/patches/bug13904-fix2.dpatch Tue Apr 22 14:15:17 2008
@@ -1,0 +1,2361 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Missing include of sys/quota.h
+
+ at DPATCH@
+Index: lustre/doc/lfs.1
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/doc/lfs.1,v
+retrieving revision 1.4.18.3
+diff -p -u -r1.4.18.3 lfs.1
+--- ./lustre/doc/lfs.1	22 Nov 2007 22:59:38 -0000	1.4.18.3
++++ ./lustre/doc/lfs.1	19 Dec 2007 20:24:32 -0000
+@@ -26,6 +26,8 @@ lfs \- Lustre utility to create a file w
+ .br
+ .B lfs quotaoff [-ug] <filesystem>
+ .br
++.B lfs quotainv [-ug] <filesystem>
++.br
+ .B lfs setquota [-u|-g] <name> <block-softlimit> <block-hardlimit> 
+              \fB<inode-softlimit> <inode-hardlimit> <filesystem>\fR
+ .br
+@@ -68,6 +70,9 @@ To turn filesystem quotas on. Options sp
+ .B quotaoff [-ugf] <filesystem>
+ To turn filesystem quotas off.  Options specify quota for users (-u) groups (-g) and force (-f)
+ .TP
++.B quotainv [-ug] <filesystem>
++Clear quota files, all of their quota entries, for (-u) users or (-g) groups; after quotainv one must use quotacheck before using quotas. USE THIS COMMAND WITH EXTREME CARE, ITS RESULTS CANNOT BE UNDONE.
++.TP
+ .B setquota  [-u|-g] <name> <block-softlimit> <block-hardlimit> <inode-softlimit> <inode-hardlimit> <filesystem>
+ To set filesystem quotas for users or groups. Limits are specific as blocks and inodes, see EXAMPLES
+ .TP
+Index: lustre/include/lustre_quota.h
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/include/lustre_quota.h,v
+retrieving revision 1.3.12.2
+diff -p -u -r1.3.12.2 lustre_quota.h
+--- ./lustre/include/lustre_quota.h	12 Jul 2007 08:36:46 -0000	1.3.12.2
++++ ./lustre/include/lustre_quota.h	19 Dec 2007 20:24:32 -0000
+@@ -42,12 +42,24 @@ struct lustre_mem_dqinfo {
+ struct lustre_quota_info {
+         struct file *qi_files[MAXQUOTAS];
+         struct lustre_mem_dqinfo qi_info[MAXQUOTAS];
++        lustre_quota_version_t qi_version;
+ };
+ 
+ #define DQ_STATUS_AVAIL         0x0     /* Available dquot */
+ #define DQ_STATUS_SET           0x01    /* Sombody is setting dquot */
+ #define DQ_STATUS_RECOVERY      0x02    /* dquot is in recovery */
+ 
++struct lustre_mem_dqblk {
++        __u64 dqb_bhardlimit;	/* absolute limit on disk blks alloc */
++        __u64 dqb_bsoftlimit;	/* preferred limit on disk blks */
++        __u64 dqb_curspace;	/* current used space */
++        __u64 dqb_ihardlimit;	/* absolute limit on allocated inodes */
++        __u64 dqb_isoftlimit;	/* preferred inode limit */
++        __u64 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 */
++};
++
+ struct lustre_dquot {
+         /* Hash list in memory, protect by dquot_hash_lock */
+         struct list_head dq_hash;
+@@ -63,7 +75,7 @@ struct lustre_dquot {
+         int dq_type;                    /* Type fo quota (USRQUOTA, GRPQUOUTA) */
+         unsigned short dq_status;       /* See DQ_STATUS_ */
+         unsigned long dq_flags;         /* See DQ_ in quota.h */
+-        struct mem_dqblk dq_dqb;        /* Diskquota usage */
++        struct lustre_mem_dqblk dq_dqb; /* Diskquota usage */
+ };
+ 
+ struct dquot_id {
+@@ -77,6 +89,7 @@ struct dquot_id {
+ #define QFILE_INIT_INFO         4
+ #define QFILE_RD_DQUOT          5
+ #define QFILE_WR_DQUOT          6
++#define QFILE_CONVERT           7
+ 
+ /* admin quotafile operations */
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+@@ -88,6 +101,7 @@ int lustre_commit_dquot(struct lustre_dq
+ int lustre_init_quota_info(struct lustre_quota_info *lqi, int type);
+ int lustre_get_qids(struct file *file, struct inode *inode, int type, 
+                     struct list_head *list);
++int lustre_quota_convert(struct lustre_quota_info *lqi, int type);
+ #else
+ 
+ #ifndef DQ_FAKE_B
+@@ -122,6 +136,11 @@ static inline int lustre_init_quota_info
+ {
+         return 0;
+ }
++static inline int lustre_quota_convert(struct lustre_quota_info *lqi,
++                                       int type)
++{
++        return 0;
++}
+ #endif  /* KERNEL_VERSION(2,5,0) */
+ 
+ #define LL_DQUOT_OFF(sb)    DQUOT_OFF(sb)
+@@ -461,4 +480,14 @@ extern quota_interface_t mdc_quota_inter
+ extern quota_interface_t lov_quota_interface;
+ #endif
+ 
++#define LUSTRE_ADMIN_QUOTAFILES_V1 {\
++        "admin_quotafile.usr",	/* user admin quotafile */\
++        "admin_quotafile.grp"	/* group admin quotafile */\
++}
++
++#define LUSTRE_ADMIN_QUOTAFILES_V2 {\
++        "admin_quotafile_v2.usr",       /* user admin quotafile */\
++        "admin_quotafile_v2.grp"        /* group admin quotafile */\
++}
++
+ #endif /* _LUSTRE_QUOTA_H */
+Index: lustre/include/linux/lustre_fsfilt.h
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/include/linux/lustre_fsfilt.h,v
+retrieving revision 1.41.32.4
+diff -p -u -r1.41.32.4 lustre_fsfilt.h
+--- ./lustre/include/linux/lustre_fsfilt.h	3 Sep 2007 06:05:42 -0000	1.41.32.4
++++ ./lustre/include/linux/lustre_fsfilt.h	19 Dec 2007 20:24:32 -0000
+@@ -404,7 +404,7 @@ static inline int fsfilt_quotainfo(struc
+ }
+ 
+ static inline int fsfilt_qids(struct obd_device *obd, struct file *file,
+-                              struct inode *inode, int type, 
++                              struct inode *inode, int type,
+                               struct list_head *list)
+ {
+         if (obd->obd_fsops->fs_qids)
+Index: lustre/include/lustre/lustre_idl.h
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/include/lustre/lustre_idl.h,v
+retrieving revision 1.3.12.16
+diff -p -u -r1.3.12.16 lustre_idl.h
+--- ./lustre/include/lustre/lustre_idl.h	10 Dec 2007 19:21:55 -0000	1.3.12.16
++++ ./lustre/include/lustre/lustre_idl.h	19 Dec 2007 20:24:33 -0000
+@@ -1493,4 +1493,5 @@ typedef enum {
+ #define QUOTA_RET_NOQUOTA      1 /* not support quota */
+ #define QUOTA_RET_NOLIMIT      2 /* quota limit isn't set */
+ #define QUOTA_RET_ACQUOTA      3 /* need to acquire extra quota */
++
+ #endif
+Index: lustre/include/lustre/lustre_user.h
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/include/lustre/lustre_user.h,v
+retrieving revision 1.18.34.1
+diff -p -u -r1.18.34.1 lustre_user.h
+--- ./lustre/include/lustre/lustre_user.h	27 Sep 2007 05:09:22 -0000	1.18.34.1
++++ ./lustre/include/lustre/lustre_user.h	19 Dec 2007 20:24:34 -0000
+@@ -163,12 +163,15 @@ static inline char *obd_uuid2str(struct 
+         return (char *)(uuid->uuid);
+ }
+ 
+-#define LUSTRE_Q_QUOTAON  0x800002     /* turn quotas on */
+-#define LUSTRE_Q_QUOTAOFF 0x800003     /* turn quotas off */
+-#define LUSTRE_Q_GETINFO  0x800005     /* get information about quota files */
+-#define LUSTRE_Q_SETINFO  0x800006     /* set information about quota files */
+-#define LUSTRE_Q_GETQUOTA 0x800007     /* get user quota structure */
+-#define LUSTRE_Q_SETQUOTA 0x800008     /* set user quota structure */
++/* these must be explicitly translated into linux Q_* in ll_dir_ioctl */
++#define LUSTRE_Q_QUOTAON    0x800002     /* turn quotas on */
++#define LUSTRE_Q_QUOTAOFF   0x800003     /* turn quotas off */
++#define LUSTRE_Q_GETINFO    0x800005     /* get information about quota files */
++#define LUSTRE_Q_SETINFO    0x800006     /* set information about quota files */
++#define LUSTRE_Q_GETQUOTA   0x800007     /* get user quota structure */
++#define LUSTRE_Q_SETQUOTA   0x800008     /* set user quota structure */
++/* lustre-specific control commands */
++#define LUSTRE_Q_INVALIDATE 0x80000b     /* invalidate quota data */
+ 
+ #define UGQUOTA 2       /* set both USRQUOTA and GRPQUOTA */
+ 
+@@ -218,6 +221,11 @@ struct mds_grp_downcall_data {
+ 
+ #endif /* !__KERNEL__ */
+ 
++typedef enum lustre_quota_version {
++        LUSTRE_QUOTA_V1 = 0,
++        LUSTRE_QUOTA_V2 = 1
++} lustre_quota_version_t;
++
+ /* XXX: same as if_dqinfo struct in kernel */
+ struct obd_dqinfo {
+         __u64 dqi_bgrace;
+Index: lustre/llite/dir.c
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/llite/dir.c,v
+retrieving revision 1.91.6.13
+diff -p -u -r1.91.6.13 dir.c
+--- ./lustre/llite/dir.c	27 Nov 2007 11:36:17 -0000	1.91.6.13
++++ ./lustre/llite/dir.c	19 Dec 2007 20:24:35 -0000
+@@ -967,6 +967,7 @@ static int ll_dir_ioctl(struct inode *in
+                 type = qctl->qc_type;
+                 id = qctl->qc_id;
+                 switch (cmd) {
++                case LUSTRE_Q_INVALIDATE:
+                 case Q_QUOTAON:
+                 case Q_QUOTAOFF:
+                 case Q_SETQUOTA:
+Index: lustre/lvfs/Makefile.in
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/lvfs/Makefile.in,v
+retrieving revision 1.12.16.2
+diff -p -u -r1.12.16.2 Makefile.in
+--- ./lustre/lvfs/Makefile.in	26 Jul 2007 06:24:10 -0000	1.12.16.2
++++ ./lustre/lvfs/Makefile.in	19 Dec 2007 20:24:35 -0000
+@@ -3,7 +3,7 @@ MODULES := lvfs
+ @QUOTA_TRUE at MODULES += quotafmt_test
+ 
+ lvfs-objs := lvfs_common.o lvfs_linux.o fsfilt.o upcall_cache.o prng.o lvfs_lib.o
+- at QUOTA_TRUE@lvfs-objs += lustre_quota_fmt.o
++ at QUOTA_TRUE@lvfs-objs += lustre_quota_fmt.o lustre_quota_fmt_convert.o
+ 
+ @QUOTA_TRUE at quotafmt-objs := quotafmt_test.o
+ 
+Index: lustre/lvfs/autoMakefile.am
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/lvfs/autoMakefile.am,v
+retrieving revision 1.14.16.3
+diff -p -u -r1.14.16.3 autoMakefile.am
+--- ./lustre/lvfs/autoMakefile.am	26 Jul 2007 06:46:08 -0000	1.14.16.3
++++ ./lustre/lvfs/autoMakefile.am	19 Dec 2007 20:24:35 -0000
+@@ -76,6 +76,7 @@ DIST_SOURCES = fsfilt.c fsfilt_ext3.c fs
+ 	lvfs_internal.h lvfs_linux.c lvfs_userfs.c \
+ 	upcall_cache.c prng.c lvfs_lib.c\
+ 	lustre_quota_fmt.c lustre_quota_fmt.h quotafmt_test.c \
++	lustre_quota_fmt_convert.c \
+         # quotacheck_test.c quotactl_test.c fsfilt_ext3_quota.h
+ 
+ MOSTLYCLEANFILES := @MOSTLYCLEANFILES@ 
+Index: lustre/lvfs/fsfilt_ext3.c
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/lvfs/fsfilt_ext3.c,v
+retrieving revision 1.58.28.19
+diff -p -u -r1.58.28.19 fsfilt_ext3.c
+--- ./lustre/lvfs/fsfilt_ext3.c	27 Nov 2007 11:36:18 -0000	1.58.28.19
++++ ./lustre/lvfs/fsfilt_ext3.c	19 Dec 2007 20:24:36 -0000
+@@ -2063,6 +2063,9 @@ static int fsfilt_ext3_quotainfo(struct 
+         case QFILE_INIT_INFO:
+                 rc = lustre_init_quota_info(lqi, type);
+                 break;
++        case QFILE_CONVERT:
++                rc = lustre_quota_convert(lqi, type);
++                break;
+         default:
+                 CERROR("Unsupported admin quota file cmd %d\n", cmd);
+                 LBUG();
+Index: lustre/lvfs/lustre_quota_fmt.c
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/lvfs/lustre_quota_fmt.c,v
+retrieving revision 1.2
+diff -p -u -r1.2 lustre_quota_fmt.c
+--- ./lustre/lvfs/lustre_quota_fmt.c	31 Mar 2007 00:16:22 -0000	1.2
++++ ./lustre/lvfs/lustre_quota_fmt.c	19 Dec 2007 20:24:37 -0000
+@@ -24,21 +24,33 @@
+ #include <asm/uaccess.h>
+ 
+ #include <lustre_quota.h>
++#include <obd_support.h>
+ #include "lustre_quota_fmt.h"
+ 
+-typedef char *dqbuf_t;
++static const uint lustre_initqversions[][MAXQUOTAS] = {
++        [LUSTRE_QUOTA_V1] = LUSTRE_INITQVERSIONS,
++        [LUSTRE_QUOTA_V2] = LUSTRE_INITQVERSIONS_V2
++};
++
++static const int lustre_dqstrinblk[] = {
++        [LUSTRE_QUOTA_V1] = LUSTRE_DQSTRINBLK,
++        [LUSTRE_QUOTA_V2] = LUSTRE_DQSTRINBLK_V2
++};
+ 
+-#define GETIDINDEX(id, depth) (((id) >> ((LUSTRE_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
+-#define GETENTRIES(buf) ((struct lustre_disk_dqblk *)(((char *)buf)+sizeof(struct lustre_disk_dqdbheader)))
++static const int lustre_disk_dqblk_sz[] = {
++        [LUSTRE_QUOTA_V1] = sizeof(struct lustre_disk_dqblk),
++        [LUSTRE_QUOTA_V2] = sizeof(struct lustre_disk_dqblk_v2)
++};
+ 
+-static int check_quota_file(struct file *f, struct inode *inode, int type)
++int check_quota_file(struct file *f, struct inode *inode, int type, 
++                     lustre_quota_version_t version)
+ {
+         struct lustre_disk_dqheader dqhead;
+         mm_segment_t fs;
+         ssize_t size;
+         loff_t offset = 0;
+         static const uint quota_magics[] = LUSTRE_INITQMAGICS;
+-        static const uint quota_versions[] = LUSTRE_INITQVERSIONS;
++        const uint *quota_versions = lustre_initqversions[version];
+ 
+         if (f) {
+                 fs = get_fs();
+@@ -57,27 +69,24 @@ static int check_quota_file(struct file 
+ #endif
+         }
+         if (size != sizeof(struct lustre_disk_dqheader))
+-                return 0;
++                return -EINVAL;
+         if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
+             le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
+-                return 0;
+-        return 1;
++                return -EINVAL;
++        return 0;
+ }
+ 
+ /* Check whether given file is really lustre admin quotafile */
+ int lustre_check_quota_file(struct lustre_quota_info *lqi, int type)
+ {
+         struct file *f = lqi->qi_files[type];
+-        return check_quota_file(f, NULL, type);
++        return check_quota_file(f, NULL, type, lqi->qi_version);
+ }
+ 
+-/* Read information header from quota file */
+-int lustre_read_quota_info(struct lustre_quota_info *lqi, int type)
++int lustre_read_quota_file_info(struct file* f, struct lustre_mem_dqinfo* info)
+ {
+         mm_segment_t fs;
+         struct lustre_disk_dqinfo dinfo;
+-        struct lustre_mem_dqinfo *info = &lqi->qi_info[type];
+-        struct file *f = lqi->qi_files[type];
+         ssize_t size;
+         loff_t offset = LUSTRE_DQINFOOFF;
+ 
+@@ -87,9 +96,9 @@ int lustre_read_quota_info(struct lustre
+                              sizeof(struct lustre_disk_dqinfo), &offset);
+         set_fs(fs);
+         if (size != sizeof(struct lustre_disk_dqinfo)) {
+-                printk(KERN_WARNING "Can't read info structure on device %s.\n",
++                CERROR("Can't read info structure on device %s.\n",
+                        f->f_vfsmnt->mnt_sb->s_id);
+-                return -1;
++                return -EINVAL;
+         }
+         info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
+         info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
+@@ -100,6 +109,12 @@ int lustre_read_quota_info(struct lustre
+         return 0;
+ }
+ 
++/* Read information header from quota file */
++int lustre_read_quota_info(struct lustre_quota_info *lqi, int type)
++{
++        return lustre_read_quota_file_info(lqi->qi_files[type], &lqi->qi_info[type]);
++}
++
+ /* Write information header to quota file */
+ int lustre_write_quota_info(struct lustre_quota_info *lqi, int type)
+ {
+@@ -131,33 +146,65 @@ int lustre_write_quota_info(struct lustr
+         return 0;
+ }
+ 
+-static void disk2memdqb(struct mem_dqblk *m, struct lustre_disk_dqblk *d)
++#define DQ2MQ(v) ((sizeof(v) == sizeof(__u64)) ? \
++                le64_to_cpu(v) : le32_to_cpu(v))
++
++#define MQ2DQ(v,newv) ((sizeof(v) == sizeof(__u64)) ? \
++                (v = cpu_to_le64((__u64)newv)) : (v = cpu_to_le32((__u32)newv)))
++
++#define DQF_GET(var,ver,field) ((ver == LUSTRE_QUOTA_V1)?\
++                DQ2MQ(((struct lustre_disk_dqblk*)(var))->field):\
++                DQ2MQ(((struct lustre_disk_dqblk_v2*)(var))->field))
++
++#define DQF_PUT(var,ver,field,val) ((ver == LUSTRE_QUOTA_V1)?\
++                MQ2DQ(((struct lustre_disk_dqblk*)(var))->field, val):\
++                MQ2DQ(((struct lustre_disk_dqblk_v2*)(var))->field, val))
++
++void disk2memdqb(struct lustre_mem_dqblk *m, void *d,
++                 lustre_quota_version_t version)
++{
++        m->dqb_ihardlimit = DQF_GET(d, version, dqb_ihardlimit);
++        m->dqb_isoftlimit = DQF_GET(d, version, dqb_isoftlimit);
++        m->dqb_curinodes = DQF_GET(d, version, dqb_curinodes);
++        m->dqb_itime = DQF_GET(d, version, dqb_itime);
++        m->dqb_bhardlimit = DQF_GET(d, version, dqb_bhardlimit);
++        m->dqb_bsoftlimit = DQF_GET(d, version, dqb_bsoftlimit);
++        m->dqb_curspace = DQF_GET(d, version, dqb_curspace);
++        m->dqb_btime = DQF_GET(d, version, dqb_btime);
++}
++
++static int check_quota_bounds(struct lustre_mem_dqblk *m, 
++                              lustre_quota_version_t version)
+ {
+-        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 lustre_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);
++        return (version == LUSTRE_QUOTA_V1  &&
++                m->dqb_ihardlimit <= MAX_UL &&
++                m->dqb_isoftlimit <= MAX_UL &&
++                m->dqb_curinodes <= MAX_UL  &&
++                m->dqb_bhardlimit <= MAX_UL &&
++                m->dqb_bsoftlimit <= MAX_UL) ||
++                version != LUSTRE_QUOTA_V1;
++}
++
++static int mem2diskdqb(void *d, struct lustre_mem_dqblk *m,
++                       qid_t id, lustre_quota_version_t version)
++{
++        if (!check_quota_bounds(m, version))
++                return -EINVAL;
++
++        DQF_PUT(d, version, dqb_ihardlimit, m->dqb_ihardlimit);
++        DQF_PUT(d, version, dqb_isoftlimit, m->dqb_isoftlimit);
++        DQF_PUT(d, version, dqb_curinodes, m->dqb_curinodes);
++        DQF_PUT(d, version, dqb_itime, m->dqb_itime);
++        DQF_PUT(d, version, dqb_bhardlimit, m->dqb_bhardlimit);
++        DQF_PUT(d, version, dqb_bsoftlimit, m->dqb_bsoftlimit);
++        DQF_PUT(d, version, dqb_curspace, m->dqb_curspace);
++        DQF_PUT(d, version, dqb_btime, m->dqb_btime);
++        DQF_PUT(d, version, dqb_id, id);
++
++        return 0;
+ }
+ 
+-static dqbuf_t getdqbuf(void)
++dqbuf_t getdqbuf(void)
+ {
+         dqbuf_t buf = kmalloc(LUSTRE_DQBLKSIZE, GFP_NOFS);
+         if (!buf)
+@@ -166,12 +213,12 @@ static dqbuf_t getdqbuf(void)
+         return buf;
+ }
+ 
+-static inline void freedqbuf(dqbuf_t buf)
++void freedqbuf(dqbuf_t buf)
+ {
+         kfree(buf);
+ }
+ 
+-static ssize_t read_blk(struct file *filp, uint blk, dqbuf_t buf)
++ssize_t read_blk(struct file *filp, uint blk, dqbuf_t buf)
+ {
+         mm_segment_t fs;
+         ssize_t ret;
+@@ -185,7 +232,7 @@ static ssize_t read_blk(struct file *fil
+         return ret;
+ }
+ 
+-static ssize_t write_blk(struct file *filp, uint blk, dqbuf_t buf)
++ssize_t write_blk(struct file *filp, uint blk, dqbuf_t buf)
+ {
+         mm_segment_t fs;
+         ssize_t ret;
+@@ -196,18 +243,15 @@ static ssize_t write_blk(struct file *fi
+         ret = filp->f_op->write(filp, (char *)buf, LUSTRE_DQBLKSIZE, &offset);
+         set_fs(fs);
+         return ret;
+-
+ }
+ 
+-static void lustre_mark_info_dirty(struct lustre_mem_dqinfo *info)
++void lustre_mark_info_dirty(struct lustre_mem_dqinfo *info)
+ {
+         set_bit(DQF_INFO_DIRTY_B, &info->dqi_flags);
+ }
+ 
+-#define lustre_info_dirty(info) test_bit(DQF_INFO_DIRTY_B, &(info)->dqi_flags)
+-
+ /* Remove empty block from list and return it */
+-static int get_free_dqblk(struct file *filp, struct lustre_mem_dqinfo *info)
++int get_free_dqblk(struct file *filp, struct lustre_mem_dqinfo *info)
+ {
+         dqbuf_t buf = getdqbuf();
+         struct lustre_disk_dqdbheader *dh =
+@@ -223,7 +267,8 @@ static int get_free_dqblk(struct file *f
+                 info->dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
+         } else {
+                 memset(buf, 0, LUSTRE_DQBLKSIZE);
+-                if ((ret = write_blk(filp, info->dqi_blocks, buf)) < 0) /* Assure block allocation... */
++                /* Assure block allocation... */
++                if ((ret = write_blk(filp, info->dqi_blocks, buf)) < 0)
+                         goto out_buf;
+                 blk = info->dqi_blocks++;
+         }
+@@ -235,8 +280,8 @@ out_buf:
+ }
+ 
+ /* Insert empty block to the list */
+-static int put_free_dqblk(struct file *filp, struct lustre_mem_dqinfo *info,
+-                          dqbuf_t buf, uint blk)
++int put_free_dqblk(struct file *filp, struct lustre_mem_dqinfo *info,
++                   dqbuf_t buf, uint blk)
+ {
+         struct lustre_disk_dqdbheader *dh =
+             (struct lustre_disk_dqdbheader *)buf;
+@@ -254,9 +299,9 @@ static int put_free_dqblk(struct file *f
+ }
+ 
+ /* Remove given block from the list of blocks with free entries */
+-static int remove_free_dqentry(struct file *filp,
+-                               struct lustre_mem_dqinfo *info, dqbuf_t buf,
+-                               uint blk)
++int remove_free_dqentry(struct file *filp,
++                        struct lustre_mem_dqinfo *info, dqbuf_t buf,
++                        uint blk)
+ {
+         dqbuf_t tmpbuf = getdqbuf();
+         struct lustre_disk_dqdbheader *dh =
+@@ -288,9 +333,10 @@ static int remove_free_dqentry(struct fi
+         }
+         freedqbuf(tmpbuf);
+         dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
+-        if (write_blk(filp, blk, buf) < 0)      /* No matter whether write succeeds block is out of list */
+-                printk(KERN_ERR
+-                       "VFS: Can't write block (%u) with free entries.\n", blk);
++        err = write_blk(filp, blk, buf);
++        if (err < 0)      /* No matter whether write succeeds block is out of list */
++                CERROR("VFS: Can't write block (%u) with "
++                       "free entries (rc=%d).\n", blk, err);
+         return 0;
+ out_buf:
+         freedqbuf(tmpbuf);
+@@ -298,9 +344,9 @@ out_buf:
+ }
+ 
+ /* Insert given block to the beginning of list with free entries */
+-static int insert_free_dqentry(struct file *filp,
+-                               struct lustre_mem_dqinfo *info, dqbuf_t buf,
+-                               uint blk)
++int insert_free_dqentry(struct file *filp,
++                        struct lustre_mem_dqinfo *info, dqbuf_t buf,
++                        uint blk)
+ {
+         dqbuf_t tmpbuf = getdqbuf();
+         struct lustre_disk_dqdbheader *dh =
+@@ -330,16 +376,21 @@ out_buf:
+         return err;
+ }
+ 
++
++
+ /* Find space for dquot */
+-static uint find_free_dqentry(struct lustre_dquot *dquot, int *err)
++static uint find_free_dqentry(struct lustre_dquot *dquot, int *err, 
++                              lustre_quota_version_t version)
+ {
+         struct lustre_quota_info *lqi = dquot->dq_info;
+         struct file *filp = lqi->qi_files[dquot->dq_type];
+         struct lustre_mem_dqinfo *info = &lqi->qi_info[dquot->dq_type];
+         uint blk, i;
+         struct lustre_disk_dqdbheader *dh;
+-        struct lustre_disk_dqblk *ddquot;
+-        struct lustre_disk_dqblk fakedquot;
++        void *ddquot;
++        int dqblk_sz = lustre_disk_dqblk_sz[version];
++        int dqstrinblk = lustre_dqstrinblk[version];
++        char fakedquot[dqblk_sz];
+         dqbuf_t buf;
+ 
+         *err = 0;
+@@ -348,7 +399,7 @@ static uint find_free_dqentry(struct lus
+                 return 0;
+         }
+         dh = (struct lustre_disk_dqdbheader *)buf;
+-        ddquot = GETENTRIES(buf);
++        ddquot = GETENTRIES(buf, version);
+         if (info->dqi_free_entry) {
+                 blk = info->dqi_free_entry;
+                 if ((*err = read_blk(filp, blk, buf)) < 0)
+@@ -361,39 +412,40 @@ static uint find_free_dqentry(struct lus
+                         return 0;
+                 }
+                 memset(buf, 0, LUSTRE_DQBLKSIZE);
+-                info->dqi_free_entry = blk;     /* This is enough as block is already zeroed and entry list is empty... */
++                info->dqi_free_entry = blk; /* This is enough as block is 
++                                               already zeroed and entry list
++                                               is empty... */
+                 lustre_mark_info_dirty(info);
+         }
+-        if (le16_to_cpu(dh->dqdh_entries) + 1 >= LUSTRE_DQSTRINBLK)     /* Block will be full? */
++
++        /* Will block be full */
++        if (le16_to_cpu(dh->dqdh_entries) + 1 >= dqstrinblk)
+                 if ((*err = remove_free_dqentry(filp, info, buf, blk)) < 0) {
+-                        printk(KERN_ERR
+-                               "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n",
+-                               blk);
++                        CERROR("VFS: 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 lustre_disk_dqblk));
++        memset(fakedquot, 0, dqblk_sz);
+         /* Find free structure in block */
+-        for (i = 0; i < LUSTRE_DQSTRINBLK && 
+-             memcmp(&fakedquot, ddquot + i, sizeof(fakedquot)); i++) ;
++        for (i = 0; i < dqstrinblk &&
++             memcmp(fakedquot, (char*)ddquot + i * dqblk_sz, 
++                    sizeof(fakedquot)); i++);
+ 
+-        if (i == LUSTRE_DQSTRINBLK) {
+-                printk(KERN_ERR
+-                       "VFS: find_free_dqentry(): Data block full but it shouldn't.\n");
++        if (i == dqstrinblk) {
++                CERROR("VFS: Data block full but it shouldn't.\n");
+                 *err = -EIO;
+                 goto out_buf;
+         }
+ 
+         if ((*err = write_blk(filp, blk, buf)) < 0) {
+-                printk(KERN_ERR
+-                       "VFS: find_free_dqentry(): Can't write quota data block %u.\n",
+-                       blk);
++                CERROR("VFS: Can't write quota data block %u.\n", blk);
+                 goto out_buf;
+         }
+         dquot->dq_off =
+             (blk << LUSTRE_DQBLKSIZE_BITS) +
+             sizeof(struct lustre_disk_dqdbheader) +
+-            i * sizeof(struct lustre_disk_dqblk);
++            i * dqblk_sz;
+         freedqbuf(buf);
+         return blk;
+ out_buf:
+@@ -402,7 +454,8 @@ out_buf:
+ }
+ 
+ /* Insert reference to structure into the trie */
+-static int do_insert_tree(struct lustre_dquot *dquot, uint * treeblk, int depth)
++static int do_insert_tree(struct lustre_dquot *dquot, uint * treeblk, int depth, 
++                          lustre_quota_version_t version)
+ {
+         struct lustre_quota_info *lqi = dquot->dq_info;
+         struct file *filp = lqi->qi_files[dquot->dq_type];
+@@ -423,8 +476,7 @@ static int do_insert_tree(struct lustre_
+                 newact = 1;
+         } else {
+                 if ((ret = read_blk(filp, *treeblk, buf)) < 0) {
+-                        printk(KERN_ERR
+-                               "VFS: Can't read tree quota block %u.\n",
++                        CERROR("VFS: Can't read tree quota block %u.\n",
+                                *treeblk);
+                         goto out_buf;
+                 }
+@@ -436,16 +488,16 @@ static int do_insert_tree(struct lustre_
+         if (depth == LUSTRE_DQTREEDEPTH - 1) {
+ 
+                 if (newblk) {
+-                        printk(KERN_ERR
+-                               "VFS: Inserting already present quota entry (block %u).\n",
++                        CERROR("VFS: Inserting already present quota entry "
++                               "(block %u).\n", 
+                                ref[GETIDINDEX(dquot->dq_id, depth)]);
+                         ret = -EIO;
+                         goto out_buf;
+                 }
+ 
+-                newblk = find_free_dqentry(dquot, &ret);
++                newblk = find_free_dqentry(dquot, &ret, version);
+         } else
+-                ret = do_insert_tree(dquot, &newblk, depth + 1);
++                ret = do_insert_tree(dquot, &newblk, depth + 1, version);
+         if (newson && ret >= 0) {
+                 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(newblk);
+                 ret = write_blk(filp, *treeblk, buf);
+@@ -457,46 +509,51 @@ out_buf:
+ }
+ 
+ /* Wrapper for inserting quota structure into tree */
+-static inline int dq_insert_tree(struct lustre_dquot *dquot)
++static inline int dq_insert_tree(struct lustre_dquot *dquot, 
++                                 lustre_quota_version_t version)
+ {
+         int tmp = LUSTRE_DQTREEOFF;
+-        return do_insert_tree(dquot, &tmp, 0);
++        return do_insert_tree(dquot, &tmp, 0, version);
+ }
+ 
+ /*
+- *	We don't have to be afraid of deadlocks as we never have quotas on quota files...
++ *  We don't have to be afraid of deadlocks as we never have quotas on quota files...
+  */
+-static int lustre_write_dquot(struct lustre_dquot *dquot)
++static int lustre_write_dquot(struct lustre_dquot *dquot, 
++                              lustre_quota_version_t version)
+ {
+         int type = dquot->dq_type;
+         struct file *filp;
+         mm_segment_t fs;
+         loff_t offset;
+         ssize_t ret;
+-        struct lustre_disk_dqblk ddquot, empty;
++        int dqblk_sz = lustre_disk_dqblk_sz[version];
++        char ddquot[dqblk_sz], empty[dqblk_sz];
++
++        ret = mem2diskdqb(ddquot, &dquot->dq_dqb, dquot->dq_id, version);
++        if (ret < 0)
++                return ret;
+ 
+         if (!dquot->dq_off)
+-                if ((ret = dq_insert_tree(dquot)) < 0) {
+-                        printk(KERN_ERR
+-                               "VFS: Error %Zd occurred while creating quota.\n",
++                if ((ret = dq_insert_tree(dquot, version)) < 0) {
++                        CERROR("VFS: Error %Zd occurred while creating quota.\n",
+                                ret);
+                         return ret;
+                 }
+         filp = dquot->dq_info->qi_files[type];
+         offset = dquot->dq_off;
+-        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 lustre_disk_dqblk));
+-        if (!memcmp(&empty, &ddquot, sizeof(struct lustre_disk_dqblk)))
+-                ddquot.dqb_itime = cpu_to_le64(1);
++        memset(empty, 0, dqblk_sz);
++        if (!memcmp(empty, ddquot, dqblk_sz))
++                DQF_PUT(ddquot, version, dqb_itime, 1);
+         fs = get_fs();
+         set_fs(KERNEL_DS);
+-        ret = filp->f_op->write(filp, (char *)&ddquot,
+-                                sizeof(struct lustre_disk_dqblk), &offset);
++        ret = filp->f_op->write(filp, ddquot,
++                                dqblk_sz, &offset);
+         set_fs(fs);
+-        if (ret != sizeof(struct lustre_disk_dqblk)) {
++        if (ret != dqblk_sz) {
+                 printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
+                        filp->f_dentry->d_sb->s_id);
+                 if (ret >= 0)
+@@ -508,25 +565,27 @@ static int lustre_write_dquot(struct lus
+ }
+ 
+ /* Free dquot entry in data block */
+-static int free_dqentry(struct lustre_dquot *dquot, uint blk)
++static int free_dqentry(struct lustre_dquot *dquot, uint blk, 
++                        lustre_quota_version_t version)
+ {
+         struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];
+         struct lustre_mem_dqinfo *info =
+             &dquot->dq_info->qi_info[dquot->dq_type];
+         struct lustre_disk_dqdbheader *dh;
+         dqbuf_t buf = getdqbuf();
++        int dqstrinblk = lustre_dqstrinblk[version];
+         int ret = 0;
+ 
+         if (!buf)
+                 return -ENOMEM;
+         if (dquot->dq_off >> LUSTRE_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 >> LUSTRE_DQBLKSIZE_BITS));
++                CERROR("VFS: Quota structure has offset to other block (%u) "
++                       "than it should (%u).\n", blk, 
++                       (uint)(dquot->dq_off >> LUSTRE_DQBLKSIZE_BITS));
+                 goto out_buf;
+         }
+         if ((ret = read_blk(filp, blk, buf)) < 0) {
+-                printk(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
++                CERROR("VFS: Can't read quota data block %u\n", blk);
+                 goto out_buf;
+         }
+         dh = (struct lustre_disk_dqdbheader *)buf;
+@@ -534,27 +593,23 @@ static int free_dqentry(struct lustre_dq
+         if (!le16_to_cpu(dh->dqdh_entries)) {   /* Block got free? */
+                 if ((ret = remove_free_dqentry(filp, info, buf, blk)) < 0 ||
+                     (ret = put_free_dqblk(filp, info, buf, blk)) < 0) {
+-                        printk(KERN_ERR
+-                               "VFS: Can't move quota data block (%u) to free list.\n",
+-                               blk);
++                        CERROR("VFS: Can't move quota data block (%u) "
++                               "to free list.\n", blk);
+                         goto out_buf;
+                 }
+         } else {
+-                memset(buf +
+-                       (dquot->dq_off & ((1 << LUSTRE_DQBLKSIZE_BITS) - 1)), 0,
+-                       sizeof(struct lustre_disk_dqblk));
+-                if (le16_to_cpu(dh->dqdh_entries) == LUSTRE_DQSTRINBLK - 1) {
++                memset(buf + (dquot->dq_off & ((1<<LUSTRE_DQBLKSIZE_BITS) - 1)),
++                       0, lustre_disk_dqblk_sz[version]);
++                if (le16_to_cpu(dh->dqdh_entries) == dqstrinblk - 1) {
+                         /* Insert will write block itself */
+                         if ((ret =
+                              insert_free_dqentry(filp, info, buf, blk)) < 0) {
+-                                printk(KERN_ERR
+-                                       "VFS: Can't insert quota data block (%u) to free entry list.\n",
+-                                       blk);
++                                CERROR("VFS: Can't insert quota data block (%u) "
++                                       "to free entry list.\n", blk);
+                                 goto out_buf;
+                         }
+                 } else if ((ret = write_blk(filp, blk, buf)) < 0) {
+-                        printk(KERN_ERR
+-                               "VFS: Can't write quota data block %u\n", blk);
++                        CERROR("VFS: Can't write quota data block %u\n", blk);
+                         goto out_buf;
+                 }
+         }
+@@ -565,7 +620,8 @@ out_buf:
+ }
+ 
+ /* Remove reference to dquot from tree */
+-static int remove_tree(struct lustre_dquot *dquot, uint * blk, int depth)
++static int remove_tree(struct lustre_dquot *dquot, uint * blk, int depth, 
++                       lustre_quota_version_t version)
+ {
+         struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];
+         struct lustre_mem_dqinfo *info =
+@@ -578,26 +634,26 @@ static int remove_tree(struct lustre_dqu
+         if (!buf)
+                 return -ENOMEM;
+         if ((ret = read_blk(filp, *blk, buf)) < 0) {
+-                printk(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
++                CERROR("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 == LUSTRE_DQTREEDEPTH - 1) {
+-                ret = free_dqentry(dquot, newblk);
++                ret = free_dqentry(dquot, newblk, version);
+                 newblk = 0;
+         } else
+-                ret = remove_tree(dquot, &newblk, depth + 1);
++                ret = remove_tree(dquot, &newblk, depth + 1, version);
+         if (ret >= 0 && !newblk) {
+                 int i;
+                 ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0);
+-                for (i = 0; i < LUSTRE_DQBLKSIZE && !buf[i]; i++) ;     /* Block got empty? */
++                for (i = 0; i < LUSTRE_DQBLKSIZE && !buf[i]; i++)
++                        /* Block got empty? */ ;
+                 /* don't put the root block into free blk list! */
+                 if (i == LUSTRE_DQBLKSIZE && *blk != LUSTRE_DQTREEOFF) {
+                         put_free_dqblk(filp, info, buf, *blk);
+                         *blk = 0;
+                 } else if ((ret = write_blk(filp, *blk, buf)) < 0)
+-                        printk(KERN_ERR
+-                               "VFS: Can't write quota tree block %u.\n", *blk);
++                        CERROR("VFS: Can't write quota tree block %u.\n", *blk);
+         }
+ out_buf:
+         freedqbuf(buf);
+@@ -605,47 +661,50 @@ out_buf:
+ }
+ 
+ /* Delete dquot from tree */
+-static int lustre_delete_dquot(struct lustre_dquot *dquot)
++static int lustre_delete_dquot(struct lustre_dquot *dquot, 
++                                lustre_quota_version_t version)
+ {
+         uint tmp = LUSTRE_DQTREEOFF;
+ 
+         if (!dquot->dq_off)     /* Even not allocated? */
+                 return 0;
+-        return remove_tree(dquot, &tmp, 0);
++        return remove_tree(dquot, &tmp, 0, version);
+ }
+ 
+ /* Find entry in block */
+-static loff_t find_block_dqentry(struct lustre_dquot *dquot, uint blk)
++static loff_t find_block_dqentry(struct lustre_dquot *dquot, uint blk, 
++                                 lustre_quota_version_t version)
+ {
+         struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];
+         dqbuf_t buf = getdqbuf();
+         loff_t ret = 0;
+         int i;
+-        struct lustre_disk_dqblk *ddquot = GETENTRIES(buf);
++        char *ddquot = GETENTRIES(buf, version);
++        int dqblk_sz = lustre_disk_dqblk_sz[version];
++        int dqstrinblk = lustre_dqstrinblk[version];
+ 
+         if (!buf)
+                 return -ENOMEM;
+         if ((ret = read_blk(filp, blk, buf)) < 0) {
+-                printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
++                CERROR("VFS: Can't read quota tree block %u.\n", blk);
+                 goto out_buf;
+         }
+         if (dquot->dq_id)
+-                for (i = 0;
+-                     i < LUSTRE_DQSTRINBLK
+-                     && le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++) ;
++                for (i = 0; i < dqstrinblk && 
++                     DQF_GET(ddquot+i*dqblk_sz, version, dqb_id) != dquot->dq_id;
++                     i++) ;
+         else {                  /* ID 0 as a bit more complicated searching... */
+-                struct lustre_disk_dqblk fakedquot;
++                char fakedquot[dqblk_sz];
+ 
+-                memset(&fakedquot, 0, sizeof(struct lustre_disk_dqblk));
+-                for (i = 0; i < LUSTRE_DQSTRINBLK; i++)
+-                        if (!le32_to_cpu(ddquot[i].dqb_id)
+-                            && memcmp(&fakedquot, ddquot + i,
+-                                      sizeof(struct lustre_disk_dqblk)))
++                memset(fakedquot, 0, sizeof(fakedquot));
++                for (i = 0; i < dqstrinblk; i++)
++                        if (!DQF_GET(ddquot + i*dqblk_sz, version, dqb_id)
++                            && memcmp(fakedquot, ddquot + i*dqblk_sz,
++                                      dqblk_sz))
+                                 break;
+         }
+-        if (i == LUSTRE_DQSTRINBLK) {
+-                printk(KERN_ERR
+-                       "VFS: Quota for id %u referenced but not present.\n",
++        if (i == dqstrinblk) {
++                CERROR("VFS: Quota for id %u referenced but not present.\n",
+                        dquot->dq_id);
+                 ret = -EIO;
+                 goto out_buf;
+@@ -653,14 +712,15 @@ static loff_t find_block_dqentry(struct 
+                 ret =
+                     (blk << LUSTRE_DQBLKSIZE_BITS) +
+                     sizeof(struct lustre_disk_dqdbheader) +
+-                    i * sizeof(struct lustre_disk_dqblk);
++                    i * dqblk_sz;
+ out_buf:
+         freedqbuf(buf);
+         return ret;
+ }
+ 
+ /* Find entry for given id in the tree */
+-static loff_t find_tree_dqentry(struct lustre_dquot *dquot, uint blk, int depth)
++static loff_t find_tree_dqentry(struct lustre_dquot *dquot, uint blk, int depth, 
++                                lustre_quota_version_t version)
+ {
+         struct file *filp = dquot->dq_info->qi_files[dquot->dq_type];
+         dqbuf_t buf = getdqbuf();
+@@ -670,7 +730,7 @@ static loff_t find_tree_dqentry(struct l
+         if (!buf)
+                 return -ENOMEM;
+         if ((ret = read_blk(filp, blk, buf)) < 0) {
+-                printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
++                CERROR("VFS: Can't read quota tree block %u.\n", blk);
+                 goto out_buf;
+         }
+         ret = 0;
+@@ -678,18 +738,19 @@ static loff_t find_tree_dqentry(struct l
+         if (!blk)               /* No reference? */
+                 goto out_buf;
+         if (depth < LUSTRE_DQTREEDEPTH - 1)
+-                ret = find_tree_dqentry(dquot, blk, depth + 1);
++                ret = find_tree_dqentry(dquot, blk, depth + 1, version);
+         else
+-                ret = find_block_dqentry(dquot, blk);
++                ret = find_block_dqentry(dquot, blk, version);
+ out_buf:
+         freedqbuf(buf);
+         return ret;
+ }
+ 
+ /* Find entry for given id in the tree - wrapper function */
+-static inline loff_t find_dqentry(struct lustre_dquot *dquot)
++static inline loff_t find_dqentry(struct lustre_dquot *dquot, 
++                                  lustre_quota_version_t version)
+ {
+-        return find_tree_dqentry(dquot, LUSTRE_DQTREEOFF, 0);
++        return find_tree_dqentry(dquot, LUSTRE_DQTREEOFF, 0, version);
+ }
+ 
+ int lustre_read_dquot(struct lustre_dquot *dquot)
+@@ -698,50 +759,50 @@ int lustre_read_dquot(struct lustre_dquo
+         struct file *filp;
+         mm_segment_t fs;
+         loff_t offset;
+-        struct lustre_disk_dqblk ddquot, empty;
+-        int ret = 0;
++        int ret = 0, dqblk_sz;
++        lustre_quota_version_t version;
+ 
+         /* Invalidated quota? */
+         if (!dquot->dq_info || !(filp = dquot->dq_info->qi_files[type])) {
+-                printk(KERN_ERR "VFS: Quota invalidated while reading!\n");
++                CERROR("VFS: Quota invalidated while reading!\n");
+                 return -EIO;
+         }
+ 
+-        offset = find_dqentry(dquot);
++        version = dquot->dq_info->qi_version;
++        dqblk_sz = lustre_disk_dqblk_sz[version];
++
++        offset = find_dqentry(dquot, version);
+         if (offset <= 0) {      /* Entry not present? */
+                 if (offset < 0)
+-                        printk(KERN_ERR
+-                               "VFS: Can't read quota structure for id %u.\n",
++                        CERROR("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));
++                memset(&dquot->dq_dqb, 0, sizeof(struct lustre_mem_dqblk));
+                 ret = offset;
+         } else {
++                char ddquot[dqblk_sz], empty[dqblk_sz];
++
+                 dquot->dq_off = offset;
+                 fs = get_fs();
+                 set_fs(KERNEL_DS);
+-                if ((ret = filp->f_op->read(filp, (char *)&ddquot,
+-                                            sizeof(struct lustre_disk_dqblk),
+-                                            &offset)) !=
+-                    sizeof(struct lustre_disk_dqblk)) {
++                if ((ret = filp->f_op->read(filp, ddquot, dqblk_sz, &offset)) !=
++                    dqblk_sz) {
+                         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 lustre_disk_dqblk));
++                        CERROR("VFS: Error while reading quota structure "
++                               "for id %u.\n", dquot->dq_id);
++                        memset(ddquot, 0, dqblk_sz);
+                 } else {
+                         ret = 0;
+                         /* We need to escape back all-zero structure */
+-                        memset(&empty, 0, sizeof(struct lustre_disk_dqblk));
+-                        empty.dqb_itime = cpu_to_le64(1);
+-                        if (!memcmp(&empty, &ddquot,
+-                                    sizeof(struct lustre_disk_dqblk)))
+-                                ddquot.dqb_itime = 0;
++                        memset(empty, 0, dqblk_sz);
++                        DQF_PUT(empty, version, dqb_itime, 1);
++                        if (!memcmp(empty, ddquot, dqblk_sz))
++                                DQF_PUT(ddquot, version, dqb_itime, 0);
+                 }
+                 set_fs(fs);
+-                disk2memdqb(&dquot->dq_dqb, &ddquot);
++                disk2memdqb(&dquot->dq_dqb, ddquot, version);
+         }
+ 
+         return ret;
+@@ -751,6 +812,8 @@ int lustre_read_dquot(struct lustre_dquo
+ int lustre_commit_dquot(struct lustre_dquot *dquot)
+ {
+         int rc = 0;
++        lustre_quota_version_t version = dquot->dq_info->qi_version;
++
+         /* always clear the flag so we don't loop on an IO error... */
+         clear_bit(DQ_MOD_B, &dquot->dq_flags);
+ 
+@@ -758,9 +821,9 @@ int lustre_commit_dquot(struct lustre_dq
+          * over all cluster, so keep the fake dquot entry on disk is
+          * meaningless, just remove it */
+         if (test_bit(DQ_FAKE_B, &dquot->dq_flags))
+-                rc = lustre_delete_dquot(dquot);
++                rc = lustre_delete_dquot(dquot, version);
+         else
+-                rc = lustre_write_dquot(dquot);
++                rc = lustre_write_dquot(dquot, version);
+ 
+         if (rc < 0)
+                 return rc;
+@@ -771,29 +834,41 @@ int lustre_commit_dquot(struct lustre_dq
+         return rc;
+ }
+ 
+-/* We need to export this function to initialize quotafile, because we haven't
+- * user level check utility */
+-int lustre_init_quota_info(struct lustre_quota_info *lqi, int type)
++int lustre_init_quota_header(struct lustre_quota_info *lqi, int type, int fakemagics)
+ {
+-        struct lustre_mem_dqinfo *dqinfo = &lqi->qi_info[type];
++        static const uint quota_magics[] = LUSTRE_INITQMAGICS;
++        static const uint fake_magics[] = LUSTRE_BADQMAGICS;
++        const uint* quota_versions = lustre_initqversions[lqi->qi_version];
+         struct lustre_disk_dqheader dqhead;
+-        struct file *fp = lqi->qi_files[type];
+         ssize_t size;
+         loff_t offset = 0;
++        struct file *fp = lqi->qi_files[type];
+         int rc = 0;
+-        static const uint quota_magics[] = LUSTRE_INITQMAGICS;
+-        static const uint quota_versions[] = LUSTRE_INITQVERSIONS;
+ 
+         /* write quotafile header */
+-        dqhead.dqh_magic = cpu_to_le32(quota_magics[type]);
++        dqhead.dqh_magic = cpu_to_le32(fakemagics ? 
++                                       fake_magics[type] : quota_magics[type]);
+         dqhead.dqh_version = cpu_to_le32(quota_versions[type]);
+         size = fp->f_op->write(fp, (char *)&dqhead,
+                                sizeof(struct lustre_disk_dqheader), &offset);
+ 
+         if (size != sizeof(struct lustre_disk_dqheader)) {
+-                printk(KERN_ERR "error writing quoafile header (rc:%d)\n", rc);
++                CERROR("error writing quotafile header (rc:%d)\n", rc);
+                 rc = size;
+         }
++
++        return rc;
++}
++
++/* We need to export this function to initialize quotafile, because we haven't
++ * user level check utility */
++int lustre_init_quota_info_generic(struct lustre_quota_info *lqi, int type,
++                                   int fakemagics)
++{
++        struct lustre_mem_dqinfo *dqinfo = &lqi->qi_info[type];
++        int rc;
++
++        rc = lustre_init_quota_header(lqi, type, fakemagics);
+         if (rc)
+                 return rc;
+ 
+@@ -806,13 +881,13 @@ int lustre_init_quota_info(struct lustre
+         return lustre_write_quota_info(lqi, type);
+ }
+ 
+-struct dqblk {
+-        struct list_head link;
+-        uint blk;
+-};
++int lustre_init_quota_info(struct lustre_quota_info *lqi, int type)
++{
++        return lustre_init_quota_info_generic(lqi, type, 0);
++}
+ 
+-static ssize_t quota_read(struct file *file, struct inode *inode, int type,
+-                          uint blk, dqbuf_t buf)
++ssize_t quota_read(struct file *file, struct inode *inode, int type,
++                   uint blk, dqbuf_t buf)
+ {
+         if (file) {
+                 return read_blk(file, blk, buf);
+@@ -843,7 +918,7 @@ static int walk_block_dqentry(struct fil
+         if (!buf)
+                 return -ENOMEM;
+         if ((ret = quota_read(filp, inode, type, blk, buf)) < 0) {
+-                printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
++                CERROR("VFS: Can't read quota tree block %u.\n", blk);
+                 goto out_buf;
+         }
+         ret = 0;
+@@ -880,8 +955,8 @@ out_buf:
+         return ret;
+ }
+ 
+-static int walk_tree_dqentry(struct file *filp, struct inode *inode, int type, 
+-                             uint blk, int depth, struct list_head *list)
++int walk_tree_dqentry(struct file *filp, struct inode *inode, int type, 
++                      uint blk, int depth, struct list_head *list)
+ {
+         dqbuf_t buf = getdqbuf();
+         loff_t ret = 0;
+@@ -891,7 +966,7 @@ static int walk_tree_dqentry(struct file
+         if (!buf)
+                 return -ENOMEM;
+         if ((ret = quota_read(filp, inode, type, blk, buf)) < 0) {
+-                printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
++                CERROR("VFS: Can't read quota tree block %u.\n", blk);
+                 goto out_buf;
+         }
+         ret = 0;
+@@ -902,7 +977,7 @@ static int walk_tree_dqentry(struct file
+                         continue;
+ 
+                 if (depth < LUSTRE_DQTREEDEPTH - 1)
+-                        ret = walk_tree_dqentry(filp, inode, type, blk, 
++                        ret = walk_tree_dqentry(filp, inode, type, blk,
+                                                 depth + 1, list);
+                 else
+                         ret = walk_block_dqentry(filp, inode, type, blk, list);
+@@ -919,61 +994,65 @@ int lustre_get_qids(struct file *fp, str
+         struct list_head blk_list;
+         struct dqblk *blk_item, *tmp;
+         dqbuf_t buf = NULL;
+-        struct lustre_disk_dqblk *ddquot;
++        char *ddquot;
+         int rc;
++        lustre_quota_version_t version;
+ 
+-        if (!check_quota_file(fp, inode, type)) {
+-                printk(KERN_ERR "unknown quota file format!\n");
+-                return -EINVAL;
++        ENTRY;
++
++        if (check_quota_file(fp, inode, type, LUSTRE_QUOTA_V1) == 0)
++                version = LUSTRE_QUOTA_V1;
++        else if (check_quota_file(fp, inode, type, LUSTRE_QUOTA_V2) == 0)
++                version = LUSTRE_QUOTA_V2;
++        else {
++                CERROR("unknown quota file format!\n");
++                RETURN(-EINVAL);
+         }
++
+         if (!list_empty(list)) {
+-                printk(KERN_ERR "not empty list\n");
+-                return -EINVAL;
++                CERROR("not empty list\n");
++                RETURN(-EINVAL);
+         }
+ 
+         INIT_LIST_HEAD(&blk_list);
+         rc = walk_tree_dqentry(fp, inode, type, LUSTRE_DQTREEOFF, 0, &blk_list);
+         if (rc) {
+-                printk(KERN_ERR "walk through quota file failed!(%d)\n", rc);
+-                goto out_free;
++                CERROR("walk through quota file failed!(%d)\n", rc);
++                GOTO(out_free, rc);
+         }
+         if (list_empty(&blk_list))
+-                return 0;
++                RETURN(0);
+ 
+         buf = getdqbuf();
+         if (!buf)
+-                return -ENOMEM;
+-        ddquot = GETENTRIES(buf);
++                RETURN(-ENOMEM);
++        ddquot = GETENTRIES(buf, version);
+ 
+         list_for_each_entry(blk_item, &blk_list, link) {
+                 loff_t ret = 0;
+-                int i;
+-                struct lustre_disk_dqblk fakedquot;
++                int i, dqblk_sz = lustre_disk_dqblk_sz[version];
++                char fakedquot[dqblk_sz];
+ 
+                 memset(buf, 0, LUSTRE_DQBLKSIZE);
+                 if ((ret = quota_read(fp, inode, type, blk_item->blk, buf))<0) {
+-                        printk(KERN_ERR
+-                               "VFS: Can't read quota tree block %u.\n",
++                        CERROR("VFS: Can't read quota tree block %u.\n",
+                                blk_item->blk);
+-                        rc = ret;
+-                        goto out_free;
++                        GOTO(out_free, rc = ret);
+                 }
+ 
+-                memset(&fakedquot, 0, sizeof(struct lustre_disk_dqblk));
+-                for (i = 0; i < LUSTRE_DQSTRINBLK; i++) {
++                memset(fakedquot, 0, dqblk_sz);
++                for (i = 0; i < lustre_dqstrinblk[version]; i++) {
+                         struct dquot_id *dqid;
+                         /* skip empty entry */
+-                        if (!memcmp
+-                            (&fakedquot, ddquot + i,
+-                             sizeof(struct lustre_disk_dqblk)))
++                        if (!memcmp(fakedquot, ddquot + i*dqblk_sz, dqblk_sz))
+                                 continue;
+ 
+                         dqid = kmalloc(sizeof(*dqid), GFP_NOFS);
+-                        if (!dqid) {
+-                                rc = -ENOMEM;
+-                                goto out_free;
+-                        }
+-                        dqid->di_id = le32_to_cpu(ddquot[i].dqb_id);
++                        if (!dqid) 
++                                GOTO(out_free, rc = -ENOMEM);
++
++                        dqid->di_id = DQF_GET(ddquot + i * dqblk_sz, 
++                                              version, dqb_id);
+                         INIT_LIST_HEAD(&dqid->di_link);
+                         list_add(&dqid->di_link, list);
+                 }
+@@ -986,12 +1065,14 @@ out_free:
+         }
+         if (buf)
+                 freedqbuf(buf);
+-        return rc;
++
++        RETURN(rc);
+ }
+ 
+-EXPORT_SYMBOL(lustre_check_quota_file);
++
+ EXPORT_SYMBOL(lustre_read_quota_info);
+ EXPORT_SYMBOL(lustre_write_quota_info);
++EXPORT_SYMBOL(lustre_check_quota_file);
+ EXPORT_SYMBOL(lustre_read_dquot);
+ EXPORT_SYMBOL(lustre_commit_dquot);
+ EXPORT_SYMBOL(lustre_init_quota_info);
+Index: lustre/lvfs/lustre_quota_fmt.h
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/lvfs/lustre_quota_fmt.h,v
+retrieving revision 1.2
+diff -p -u -r1.2 lustre_quota_fmt.h
+--- ./lustre/lvfs/lustre_quota_fmt.h	31 Mar 2007 00:16:22 -0000	1.2
++++ ./lustre/lvfs/lustre_quota_fmt.h	19 Dec 2007 20:24:37 -0000
+@@ -17,19 +17,26 @@
+  * Same with quota v2's magic
+  */
+ #define LUSTRE_INITQMAGICS {\
+-	0xd9c01f11,	/* USRQUOTA */\
+-	0xd9c01927	/* GRPQUOTA */\
++        0xd9c01f11,     /* USRQUOTA */\
++        0xd9c01927      /* GRPQUOTA */\
+ }
+ 
++/* Invalid magics that mark quota file as inconsistent */
++#define LUSTRE_BADQMAGICS {\
++        0xbadbadba,     /* USRQUOTA */\
++        0xbadbadba      /* GRPQUOTA */\
++}
++
++/* for the verson 1 of lustre_disk_dqblk*/
+ #define LUSTRE_INITQVERSIONS {\
+-	0,		/* USRQUOTA */\
+-	0		/* GRPQUOTA */\
++        0,              /* USRQUOTA */\
++        0               /* 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.
++ * to blocks of these structures. for the version 1.
+  */
+ struct lustre_disk_dqblk {
+         __u32 dqb_id;           /* id this quota applies to */
+@@ -43,6 +50,45 @@ struct lustre_disk_dqblk {
+         __u64 dqb_itime;        /* time limit for excessive inode use */
+ };
+ 
++/* Number of entries in one blocks(21 entries) */
++#define LUSTRE_DQSTRINBLK \
++                ((LUSTRE_DQBLKSIZE - sizeof(struct lustre_disk_dqdbheader)) \
++                / sizeof(struct lustre_disk_dqblk)) 
++#define GETENTRIES_V1(buf) (((char *)buf)+sizeof(struct lustre_disk_dqdbheader))
++
++/* for the verson 2 of lustre_disk_dqblk*/
++#define LUSTRE_INITQVERSIONS_V2 {\
++        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. for the version 2.
++ */
++struct lustre_disk_dqblk_v2 {
++        __u32 dqb_id;           /* id this quota applies to */
++        __u32 padding;
++        __u64 dqb_ihardlimit;   /* absolute limit on allocated inodes */
++        __u64 dqb_isoftlimit;   /* preferred inode limit */
++        __u64 dqb_curinodes;    /* current # allocated inodes */
++        __u64 dqb_bhardlimit;   /* absolute limit on disk space (in QUOTABLOCK_SIZE) */
++        __u64 dqb_bsoftlimit;   /* preferred limit on disk space (in QUOTABLOCK_SIZE) */
++        __u64 dqb_curspace;     /* current space occupied (in bytes) */
++        __u64 dqb_btime;        /* time limit for excessive disk use */
++        __u64 dqb_itime;        /* time limit for excessive inode use */
++};
++
++/* Number of entries in one blocks(14 entries) */
++#define LUSTRE_DQSTRINBLK_V2 \
++                ((LUSTRE_DQBLKSIZE - sizeof(struct lustre_disk_dqdbheader)) \
++		/ sizeof(struct lustre_disk_dqblk_v2)) 
++#define GETENTRIES_V2(buf) (((char *)buf)+sizeof(struct lustre_disk_dqdbheader))
++
++#define GETENTRIES(buf,version) ((version == LUSTRE_QUOTA_V1) ? \
++                                GETENTRIES_V1(buf) : GETENTRIES_V2(buf))
++
+ /*
+  * Here are header structures as written on disk and their in-memory copies
+  */
+@@ -79,6 +125,59 @@ struct lustre_disk_dqdbheader {
+ #define LUSTRE_DQBLKSIZE	(1 << LUSTRE_DQBLKSIZE_BITS)    /* Size of block with quota structures */
+ #define LUSTRE_DQTREEOFF	1       /* Offset of tree in file in blocks */
+ #define LUSTRE_DQTREEDEPTH	4       /* Depth of quota tree */
+-#define LUSTRE_DQSTRINBLK	((LUSTRE_DQBLKSIZE - sizeof(struct lustre_disk_dqdbheader)) / sizeof(struct lustre_disk_dqblk)) /* Number of entries in one blocks */
++
++typedef char *dqbuf_t;
++
++#define GETIDINDEX(id, depth) (((id) >> ((LUSTRE_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
++
++#define MAX_UL (0xffffffffUL)
++
++#define lustre_info_dirty(info) test_bit(DQF_INFO_DIRTY_B, &(info)->dqi_flags)
++
++struct dqblk {
++        struct list_head link;
++        uint blk;
++};
++
++/* come from lustre_fmt_common.c */
++dqbuf_t getdqbuf(void);
++void freedqbuf(dqbuf_t buf);
++void disk2memdqb(struct lustre_mem_dqblk *m, void *d,
++                        enum lustre_quota_version version);
++void lustre_mark_info_dirty(struct lustre_mem_dqinfo *info);
++int lustre_init_quota_header(struct lustre_quota_info *lqi, int type, 
++                             int fakemagics);
++int lustre_init_quota_info_generic(struct lustre_quota_info *lqi, int type,
++                                   int fakemagics);
++int lustre_read_quota_info(struct lustre_quota_info *lqi, int type);
++int lustre_read_quota_file_info(struct file* f, struct lustre_mem_dqinfo* info);
++int lustre_write_quota_info(struct lustre_quota_info *lqi, int type);
++ssize_t read_blk(struct file *filp, uint blk, dqbuf_t buf);
++ssize_t write_blk(struct file *filp, uint blk, dqbuf_t buf);
++int get_free_dqblk(struct file *filp, struct lustre_mem_dqinfo *info);
++int put_free_dqblk(struct file *filp, struct lustre_mem_dqinfo *info,
++                          dqbuf_t buf, uint blk);
++int remove_free_dqentry(struct file *filp,
++                               struct lustre_mem_dqinfo *info, dqbuf_t buf,
++                               uint blk);
++int insert_free_dqentry(struct file *filp,
++                               struct lustre_mem_dqinfo *info, dqbuf_t buf,
++                               uint blk);
++ssize_t quota_read(struct file *file, struct inode *inode, int type,
++                   uint blk, dqbuf_t buf);
++int walk_tree_dqentry(struct file *filp, struct inode *inode, int type,
++                      uint blk, int depth, struct list_head *list);
++int check_quota_file(struct file *f, struct inode *inode, int type,
++                     lustre_quota_version_t version);
++int lustre_check_quota_file(struct lustre_quota_info *lqi, int type);
++int lustre_read_dquot(struct lustre_dquot *dquot);
++int lustre_commit_dquot(struct lustre_dquot *dquot);
++int lustre_init_quota_info(struct lustre_quota_info *lqi, int type);
++int lustre_get_qids(struct file *fp, struct inode *inode, int type,
++                    struct list_head *list);
++
++
++/* come from lustre_quota_fmt_conver.c */
++int lustre_quota_convert(struct lustre_quota_info *lqi, int type);
+ 
+ #endif                          /* lustre_quota_fmt.h */
+Index: lustre/lvfs/lustre_quota_fmt_convert.c
+===================================================================
+RCS file: lustre/lvfs/lustre_quota_fmt_convert.c
+diff -N lustre/lvfs/lustre_quota_fmt_convert.c
+--- /dev/null	1 Jan 1970 00:00:00 -0000
++++ ./lustre/lvfs/lustre_quota_fmt_convert.c	19 Dec 2007 20:24:38 -0000
+@@ -0,0 +1,185 @@
++/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
++ * vim:expandtab:shiftwidth=8:tabstop=8:
++ *
++ * convert quota format.
++ *
++ *  from
++ *  linux/fs/quota_v2.c
++ */
++
++#ifndef EXPORT_SYMTAB
++# define EXPORT_SYMTAB
++#endif
++
++#include <linux/errno.h>
++#include <linux/fs.h>
++#include <linux/mount.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/quotaio_v1.h>
++
++#include <asm/byteorder.h>
++#include <asm/uaccess.h>
++
++#include <lustre_quota.h>
++#include <obd_support.h>
++#include "lustre_quota_fmt.h"
++
++static int admin_convert_dqinfo(struct file *fp_v1, struct file *fp_v2,
++                                struct lustre_quota_info *lqi, int type)
++{
++        struct lustre_mem_dqinfo *info_old, *info_new = &lqi->qi_info[type];
++        int rc;
++
++        OBD_ALLOC_PTR(info_old);
++        if (info_old == NULL)
++                return -ENOMEM;
++
++        rc = lustre_read_quota_file_info(fp_v1, info_old);
++        if (!rc) {
++                /* save essential fields: bgrace, igrace, flags */
++                info_new->dqi_bgrace = info_old->dqi_bgrace;
++                info_new->dqi_igrace = info_old->dqi_igrace;
++                info_new->dqi_flags  = info_old->dqi_flags;
++                rc = lustre_write_quota_info(lqi, type);
++        }
++
++        OBD_FREE_PTR(info_old);
++
++        return rc;
++}
++
++static int admin_convert_v1_to_v2(struct file *fp_v1, struct file *fp_v2,
++                                  struct lustre_quota_info *lqi, int type)
++{
++        struct list_head blk_list;
++        struct dqblk *blk_item, *tmp;
++        dqbuf_t buf = NULL;
++        struct lustre_disk_dqblk *ddquot;
++        struct lustre_dquot *dquot = NULL;
++        int rc;
++
++        ENTRY;
++
++        INIT_LIST_HEAD(&blk_list);
++
++        rc = admin_convert_dqinfo(fp_v1, fp_v2, lqi, type);
++        if (rc) {
++                CERROR("could not copy dqinfo!(%d)\n", rc);
++                GOTO(out_free, rc);
++        }
++
++        rc = walk_tree_dqentry(fp_v1, NULL, type, LUSTRE_DQTREEOFF, 0, &blk_list);
++        if (rc) {
++                CERROR("walk through quota file failed!(%d)\n", rc);
++                GOTO(out_free, rc);
++        }
++        if (list_empty(&blk_list))
++                RETURN(0);
++
++        buf = getdqbuf();
++        if (!buf)
++                GOTO(out_free, rc = -ENOMEM);
++
++        ddquot = (struct lustre_disk_dqblk*)GETENTRIES(buf, LUSTRE_QUOTA_V1);
++
++        OBD_ALLOC_PTR(dquot);
++        if (dquot == NULL)
++                GOTO(out_free, rc = -ENOMEM);
++
++        list_for_each_entry(blk_item, &blk_list, link) {
++                loff_t ret = 0;
++                int i;
++                struct lustre_disk_dqblk fakedquot;
++
++                memset(buf, 0, LUSTRE_DQBLKSIZE);
++                if ((ret = quota_read(fp_v1, NULL, type, blk_item->blk, buf))<0) {
++                        CERROR("VFS: Can't read quota tree block %u.\n",
++                               blk_item->blk);
++                        GOTO(out_free, rc = ret);
++                }
++
++                memset(&fakedquot, 0, sizeof(struct lustre_disk_dqblk));
++                for (i = 0; i < LUSTRE_DQSTRINBLK; i++) {
++                        /* skip empty entry */
++                        if (!memcmp
++                            (&fakedquot, ddquot + i,
++                             sizeof(struct lustre_disk_dqblk)))
++                                continue;
++
++                        memset(dquot, 0, sizeof(*dquot));
++
++                        dquot->dq_id = le32_to_cpu(ddquot[i].dqb_id);
++                        dquot->dq_type = type;
++                        dquot->dq_info = lqi;
++
++                        disk2memdqb(&dquot->dq_dqb, &ddquot[i], LUSTRE_QUOTA_V1);
++                        rc = lustre_commit_dquot(dquot);
++                        if (rc < 0)
++                                GOTO(out_free, rc);
++                }
++        }
++
++        EXIT;
++
++out_free:
++        list_for_each_entry_safe(blk_item, tmp, &blk_list, link) {
++                list_del_init(&blk_item->link);
++                kfree(blk_item);
++        }
++        if (buf)
++                freedqbuf(buf);
++        if (dquot)
++                OBD_FREE_PTR(dquot);
++        return rc;
++}
++
++int lustre_quota_convert(struct lustre_quota_info *lqi, int type)
++{
++        struct file *f_v2 = lqi->qi_files[type];
++        const char *qf_v1[] = LUSTRE_ADMIN_QUOTAFILES_V1;
++        char name[64];
++        struct file *f_v1;
++        int rc = 0;
++        ENTRY;
++
++        LASSERT(f_v2);
++
++        rc = lustre_init_quota_info_generic(lqi, type, 1);
++        if (rc) {
++                CERROR("could not initialize new quota file(%d)\n", rc);
++                RETURN(rc);
++        }
++
++        /* Open old quota file and copy to the new one */
++        sprintf(name, "OBJECTS/%s", qf_v1[type]);
++        f_v1 = filp_open(name, O_RDONLY, 0);
++        if (!IS_ERR(f_v1)) {
++                if (!check_quota_file(f_v1, NULL, type, LUSTRE_QUOTA_V1)) {
++                        rc = admin_convert_v1_to_v2(f_v1, f_v2, lqi, type);
++                        if (rc)
++                                CERROR("failed to convert v1 quota file"
++                                       " to v2 quota file.\n");
++                        else
++                                CDEBUG(D_INFO, "Found v1 quota file, "
++                                               "successfully converted to v2.\n");
++                }
++                else
++                        CERROR("old quota file is broken, "
++                               "new quota file will be empty\n");
++
++                filp_close(f_v1, 0);
++        } else if (PTR_ERR(f_v1) != -ENOENT) /* No quota file is ok */
++                CERROR("old quota file can not be open, "
++                       "new quota file will be empty (%ld)\n", PTR_ERR(f_v1));
++
++        /* mark corresponding quota file as correct */
++        if (!rc)
++                lustre_init_quota_header(lqi, type, 0);
++
++        RETURN(rc);
++}
++
++EXPORT_SYMBOL(lustre_quota_convert);
+Index: lustre/lvfs/quotafmt_test.c
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/lvfs/quotafmt_test.c,v
+retrieving revision 1.2
+diff -p -u -r1.2 quotafmt_test.c
+--- ./lustre/lvfs/quotafmt_test.c	31 Mar 2007 00:16:22 -0000	1.2
++++ ./lustre/lvfs/quotafmt_test.c	19 Dec 2007 20:24:38 -0000
+@@ -70,7 +70,7 @@ static int quotfmt_initialize(struct lus
+                                        sizeof(struct lustre_disk_dqheader),
+                                        &offset);
+                 if (size != sizeof(struct lustre_disk_dqheader)) {
+-                        CERROR("error writing quoafile header %s (rc = %d)\n",
++                        CERROR("error writing quotafile header %s (rc = %d)\n",
+                                name, rc);
+                         rc = size;
+                         break;
+@@ -129,7 +129,7 @@ static int quotfmt_test_1(struct lustre_
+         ENTRY;
+ 
+         for (i = 0; i < MAXQUOTAS; i++) {
+-                if (!lustre_check_quota_file(lqi, i))
++                if (lustre_check_quota_file(lqi, i))
+                         RETURN(-EINVAL);
+         }
+         RETURN(0);
+@@ -220,7 +220,7 @@ static void put_rand_dquot(struct lustre
+ static int write_check_dquot(struct lustre_quota_info *lqi)
+ {
+         struct lustre_dquot *dquot;
+-        struct mem_dqblk dqblk;
++        struct lustre_mem_dqblk dqblk;
+         int rc = 0;
+         ENTRY;
+ 
+Index: lustre/quota/quota_ctl.c
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/quota/quota_ctl.c,v
+retrieving revision 1.2.34.2
+diff -p -u -r1.2.34.2 quota_ctl.c
+--- ./lustre/quota/quota_ctl.c	27 Nov 2007 11:36:18 -0000	1.2.34.2
++++ ./lustre/quota/quota_ctl.c	19 Dec 2007 20:24:38 -0000
+@@ -74,6 +74,9 @@ int mds_quota_ctl(struct obd_export *exp
+         case Q_GETOQUOTA:
+                 rc = mds_get_obd_quota(obd, oqctl);
+                 break;
++        case LUSTRE_Q_INVALIDATE:
++                rc = mds_quota_invalidate(obd, oqctl);
++                break;
+         default:
+                 CERROR("%s: unsupported mds_quotactl command: %d\n",
+                        obd->obd_name, oqctl->qc_cmd);
+Index: lustre/quota/quota_interface.c
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/quota/quota_interface.c,v
+retrieving revision 1.3.12.3
+diff -p -u -r1.3.12.3 quota_interface.c
+--- ./lustre/quota/quota_interface.c	12 Jul 2007 08:36:47 -0000	1.3.12.3
++++ ./lustre/quota/quota_interface.c	19 Dec 2007 20:24:39 -0000
+@@ -175,7 +175,7 @@ EXPORT_SYMBOL(lprocfs_wr_itune);
+ #define USER_QUOTA      1
+ #define GROUP_QUOTA     2
+ 
+-#define MAX_STYPE_SIZE  4
++#define MAX_STYPE_SIZE  5
+ int lprocfs_rd_type(char *page, char **start, off_t off, int count, 
+                     int *eof, void *data)
+ {
+@@ -192,7 +192,28 @@ int lprocfs_rd_type(char *page, char **s
+                 if (type & GROUP_QUOTA)
+                         strcat(stype, "g");
+         }
+-        
++
++        /* append with quota version on MDS */
++        if (!strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME)) {
++                int rc;
++                lustre_quota_version_t version;
++
++                rc = mds_quota_get_version(obd, &version);
++                if (rc)
++                        return rc;
++
++                switch (version) {
++                        case LUSTRE_QUOTA_V1:
++                                strcat(stype, "1");
++                                break;
++                        case LUSTRE_QUOTA_V2:
++                                strcat(stype, "2");
++                                break;
++                        default:
++                                return -ENOSYS;
++                }
++        }
++
+         return snprintf(page, count, "%s\n", stype);
+ }
+ EXPORT_SYMBOL(lprocfs_rd_type);
+@@ -255,17 +276,52 @@ int lprocfs_wr_type(struct file *file, c
+         struct obd_device *obd = (struct obd_device *)data;
+         struct obd_device_target *obt = &obd->u.obt;
+         int type = 0;
++        unsigned long i;
+         char stype[MAX_STYPE_SIZE + 1] = "";
+         LASSERT(obd != NULL);
+ 
+-        if (copy_from_user(stype, buffer, MAX_STYPE_SIZE))
++        if (count > MAX_STYPE_SIZE)
++                return -EINVAL;
++
++        if (copy_from_user(stype, buffer, count))
+                 return -EFAULT;
+ 
+-        if (strchr(stype, 'u'))
+-                type |= USER_QUOTA;
+-        if (strchr(stype, 'g'))
+-                type |= GROUP_QUOTA;
+-        
++        for (i = 0 ; i < count ; i++) {
++                int rc;
++
++                switch (stype[i]) {
++                case 'u' : 
++                        type |= USER_QUOTA;
++                        break;
++                case 'g' : 
++                        type |= GROUP_QUOTA;
++                        break;
++                /* quota version specifiers */
++                case '1' : 
++                        if (strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME))
++                                break;
++
++                        rc = mds_quota_set_version(obd, LUSTRE_QUOTA_V1);
++                        if (rc) {
++                                CDEBUG(D_QUOTA, "failed to set quota v1! %d\n", rc);
++                                return rc;
++                        }
++                        break;
++                case '2' : 
++                        if (strcmp(obd->obd_type->typ_name, LUSTRE_MDS_NAME))
++                                break;
++
++                        rc = mds_quota_set_version(obd, LUSTRE_QUOTA_V2);
++                        if (rc) {
++                                CDEBUG(D_QUOTA, "could not set quota v2! %d\n", rc);
++                                return rc;
++                        }
++                        break;
++                default  : /* just skip stray symbols like \n */
++                        break;
++                }
++        }
++
+         obt->obt_qctxt.lqc_atype = type;
+ 
+         if (type == 0)
+@@ -496,6 +552,7 @@ static int mds_quota_setup(struct obd_de
+         int rc;
+         ENTRY;
+ 
++        mds->mds_quota_info.qi_version = LUSTRE_QUOTA_V2;
+         atomic_set(&obt->obt_quotachecking, 1);
+         /* initialize quota master and quota context */
+         sema_init(&mds->mds_qonoff_sem, 1);
+Index: lustre/quota/quota_internal.h
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/quota/quota_internal.h,v
+retrieving revision 1.3.12.1
+diff -p -u -r1.3.12.1 quota_internal.h
+--- ./lustre/quota/quota_internal.h	5 Sep 2007 09:50:17 -0000	1.3.12.1
++++ ./lustre/quota/quota_internal.h	19 Dec 2007 20:24:39 -0000
+@@ -27,8 +27,8 @@
+ 
+ #define DQUOT_DEBUG(dquot, fmt, arg...)                                       \
+         CDEBUG(D_QUOTA, "refcnt(%u) id(%u) type(%u) off(%llu) flags(%lu) "    \
+-               "bhardlimit(%u) curspace("LPX64") ihardlimit(%u) "             \
+-               "curinodes(%u): " fmt, dquot->dq_refcnt,                       \
++               "bhardlimit("LPU64") curspace("LPU64") ihardlimit("LPU64")"    \
++               "curinodes("LPU64"): " fmt, dquot->dq_refcnt,                  \
+                dquot->dq_id, dquot->dq_type, dquot->dq_off,  dquot->dq_flags, \
+                dquot->dq_dqb.dqb_bhardlimit, dquot->dq_dqb.dqb_curspace,      \
+                dquot->dq_dqb.dqb_ihardlimit, dquot->dq_dqb.dqb_curinodes,     \
+@@ -74,6 +74,10 @@ int mds_quota_adjust(struct obd_device *
+ int filter_quota_adjust(struct obd_device *obd, unsigned int qcids[],
+                         unsigned int qpids[], int rc, int opc);
+ int init_admin_quotafiles(struct obd_device *obd, struct obd_quotactl *oqctl);
++int mds_quota_get_version(struct obd_device *obd, lustre_quota_version_t *ver);
++int mds_quota_set_version(struct obd_device *obd, lustre_quota_version_t ver);
++int mds_quota_invalidate(struct obd_device *obd, struct obd_quotactl *oqctl);
++
+ int mds_admin_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl);
+ int mds_quota_on(struct obd_device *obd, struct obd_quotactl *oqctl);
+ int mds_quota_off(struct obd_device *obd, struct obd_quotactl *oqctl);
+Index: lustre/quota/quota_master.c
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/quota/quota_master.c,v
+retrieving revision 1.2.34.5
+diff -p -u -r1.2.34.5 quota_master.c
+--- ./lustre/quota/quota_master.c	27 Nov 2007 11:36:18 -0000	1.2.34.5
++++ ./lustre/quota/quota_master.c	19 Dec 2007 20:24:39 -0000
+@@ -361,31 +361,122 @@ int filter_quota_adjust(struct obd_devic
+         RETURN(0);
+ }
+ 
+-#define LUSTRE_ADMIN_QUOTAFILES {\
+-	"admin_quotafile.usr",	/* user admin quotafile */\
+-	"admin_quotafile.grp"	/* group admin quotafile */\
+-}
+ static const char prefix[] = "OBJECTS/";
+ 
++int mds_quota_get_version(struct obd_device *obd, 
++                          lustre_quota_version_t *version)
++{
++        struct mds_obd *mds = &obd->u.mds;
++        struct lustre_quota_info *qinfo = &mds->mds_quota_info;
++
++        *version = qinfo->qi_version;
++
++        return 0;
++}
++
++int mds_quota_set_version(struct obd_device *obd, lustre_quota_version_t version)
++{
++        struct mds_obd *mds = &obd->u.mds;
++        struct lustre_quota_info *qinfo = &mds->mds_quota_info;
++        int rc = 0, i;
++
++        if (version != LUSTRE_QUOTA_V1 &&
++            version != LUSTRE_QUOTA_V2)
++                return -EINVAL;
++
++        down(&mds->mds_qonoff_sem);
++
++        /* no need to change version? nothing to do then */
++        if (qinfo->qi_version == version)
++                goto out;
++
++        for (i = 0; i < MAXQUOTAS; i++) {
++                /* quota file has been opened ? */
++                if (qinfo->qi_files[i]) {
++                        rc = -EBUSY;
++                        goto out;
++                }
++        }
++
++        CDEBUG(D_INFO, "changing quota version %d -> %d\n", qinfo->qi_version,
++               version);
++
++        qinfo->qi_version = version;
++
++out:
++        up(&mds->mds_qonoff_sem);
++
++        return rc;
++}
++
++int mds_quota_invalidate(struct obd_device *obd, struct obd_quotactl *oqctl)
++{
++        struct mds_obd *mds = &obd->u.mds;
++        struct lustre_quota_info *qinfo = &mds->mds_quota_info;
++        int rc = 0, i;
++        char *quotafiles_v1[] = LUSTRE_ADMIN_QUOTAFILES_V1;
++        char *quotafiles_v2[] = LUSTRE_ADMIN_QUOTAFILES_V2;
++        char name[64];
++        struct lvfs_run_ctxt saved;
++
++        push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
++
++        down(&mds->mds_qonoff_sem);
++
++        for (i = 0; i < MAXQUOTAS; i++) {
++                struct file *fp;
++                char* quotafile = (qinfo->qi_version == LUSTRE_QUOTA_V1)?
++                                   quotafiles_v1[i]:quotafiles_v2[i];
++
++                if (!Q_TYPESET(oqctl, i))
++                        continue;
++
++                /* quota file has been opened ? */
++                if (qinfo->qi_files[i]) {
++                        rc = -EBUSY;
++                        goto out;
++                }
++
++                LASSERT(strlen(quotafile) + sizeof(prefix) <= sizeof(name));
++                sprintf(name, "%s%s", prefix, quotafile);
++
++                fp = filp_open(name, O_CREAT | O_TRUNC, 0644);
++                if (IS_ERR(fp)) {
++                        rc = PTR_ERR(fp);
++                        CERROR("error invalidating admin quotafile %s (rc:%d)\n",
++                               name, rc);
++                }
++                else
++                        filp_close(fp, 0);
++        }
++
++out:
++        up(&mds->mds_qonoff_sem);
++
++        pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
++
++        return rc;
++}
++
+ int init_admin_quotafiles(struct obd_device *obd, struct obd_quotactl *oqctl)
+ {
+         struct mds_obd *mds = &obd->u.mds;
+         struct lustre_quota_info *qinfo = &mds->mds_quota_info;
+-        const char *quotafiles[] = LUSTRE_ADMIN_QUOTAFILES;
++        char *quotafiles_v1[] = LUSTRE_ADMIN_QUOTAFILES_V1;
++        char *quotafiles_v2[] = LUSTRE_ADMIN_QUOTAFILES_V2;
+         struct lvfs_run_ctxt saved;
+         char name[64];
+         int i, rc = 0;
+-        struct dentry *dparent = mds->mds_objects_dir;
+-        struct inode *iparent = dparent->d_inode;
+         ENTRY;
+ 
+-        LASSERT(iparent);
+         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+ 
+         down(&mds->mds_qonoff_sem);
+-        for (i = 0; i < MAXQUOTAS; i++) {
+-                struct dentry *de;
++
++        for (i = 0; i < MAXQUOTAS && !rc; i++) {
+                 struct file *fp;
++                char* quotafile = (qinfo->qi_version == LUSTRE_QUOTA_V1)?
++                                        quotafiles_v1[i]:quotafiles_v2[i];
+ 
+                 if (!Q_TYPESET(oqctl, i))
+                         continue;
+@@ -397,33 +488,44 @@ int init_admin_quotafiles(struct obd_dev
+                         continue;
+                 }
+ 
+-                /* lookup quota file */
+-                rc = 0;
+-                LOCK_INODE_MUTEX(iparent);
+-                de = lookup_one_len(quotafiles[i], dparent,
+-                                    strlen(quotafiles[i]));
+-                UNLOCK_INODE_MUTEX(iparent);
+-                if (IS_ERR(de) || de->d_inode == NULL || 
+-                    !S_ISREG(de->d_inode->i_mode))
+-                        rc = IS_ERR(de) ? PTR_ERR(de) : -ENOENT;
+-                if (!IS_ERR(de))
+-                        dput(de);
++                LASSERT(strlen(quotafile) + sizeof(prefix) <= sizeof(name));
++                sprintf(name, "%s%s", prefix, quotafile);
+ 
+-                if (rc && rc != -ENOENT) {
+-                        CERROR("error lookup quotafile %s! (rc:%d)\n",
++                /* check if quota file exists and is correct */
++                fp = filp_open(name, O_RDONLY, 0);
++                if (!IS_ERR(fp)) {
++                        /* irregular file is not the right place for quota */
++                        if (!S_ISREG(fp->f_dentry->d_inode->i_mode)) {
++                                CERROR("admin quota file %s is not "
++                                       "regular!", quotafile);
++                                filp_close(fp, 0);
++                                rc = -EINVAL;
++                                break;
++                        }
++                        qinfo->qi_files[i] = fp;
++                        rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_CHK);
++                        qinfo->qi_files[i] = 0;
++                        filp_close(fp, 0);
++                }
++                else
++                        rc = PTR_ERR(fp);
++
++                if (!rc)
++                        continue;
++
++                /* -EINVAL may be returned by quotainfo for bad quota file */
++                if (rc != -ENOENT && rc != -EINVAL) {
++                        CERROR("error opening old quota file %s (%d)\n", 
+                                name, rc);
+                         break;
+-                } else if (!rc) {
+-                        continue;
+                 }
+ 
+-                LASSERT(strlen(quotafiles[i]) + sizeof(prefix) <= sizeof(name));
+-                sprintf(name, "%s%s", prefix, quotafiles[i]);
++                CDEBUG(D_INFO, "%s new quota file %s\n", name, 
++                       rc == -ENOENT ? "creating" : "overwriting");
+ 
+-                LASSERT(rc == -ENOENT);
+-                /* create quota file */
+-                fp = filp_open(name, O_CREAT | O_EXCL, 0644);
+-                if (IS_ERR(fp) || !S_ISREG(fp->f_dentry->d_inode->i_mode)) {
++                /* create quota file overwriting old if needed */
++                fp = filp_open(name, O_CREAT | O_TRUNC, 0644);
++                if (IS_ERR(fp)) {
+                         rc = PTR_ERR(fp);
+                         CERROR("error creating admin quotafile %s (rc:%d)\n",
+                                name, rc);
+@@ -431,15 +533,26 @@ int init_admin_quotafiles(struct obd_dev
+                 }
+ 
+                 qinfo->qi_files[i] = fp;
+-                rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_INIT_INFO);
+-                filp_close(fp, 0);
+-                qinfo->qi_files[i] = NULL;
+ 
+-                if (rc) {
+-                        CERROR("error init %s admin quotafile! (rc:%d)\n",
+-                               i == USRQUOTA ? "user" : "group", rc);
++                switch (qinfo->qi_version) {
++                case LUSTRE_QUOTA_V1:
++                        rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_INIT_INFO);
++                        if (rc)
++                                CERROR("error init %s admin quotafile! (rc:%d)\n",
++                                       i == USRQUOTA ? "user" : "group", rc);
+                         break;
++                case LUSTRE_QUOTA_V2:
++                        rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_CONVERT);
++                        if (rc)
++                                CERROR("error convert %s admin quotafile! (rc:%d)\n",
++                                       i == USRQUOTA ? "user" : "group", rc);
++                        break;
++                default:
++                        LBUG();
+                 }
++
++                filp_close(fp, 0);
++                qinfo->qi_files[i] = NULL;
+         }
+         up(&mds->mds_qonoff_sem);
+ 
+@@ -470,38 +583,61 @@ int mds_admin_quota_on(struct obd_device
+ {
+         struct mds_obd *mds = &obd->u.mds;
+         struct lustre_quota_info *qinfo = &mds->mds_quota_info;
+-        const char *quotafiles[] = LUSTRE_ADMIN_QUOTAFILES;
++        const char *quotafiles_v1[] = LUSTRE_ADMIN_QUOTAFILES_V1;
++        const char *quotafiles_v2[] = LUSTRE_ADMIN_QUOTAFILES_V2;
+         char name[64];
+         int i, rc = 0;
+-        struct inode *iparent = mds->mds_objects_dir->d_inode;
+         ENTRY;
+ 
+-        LASSERT(iparent);
+-
+         /* open admin quota files and read quotafile info */
+         for (i = 0; i < MAXQUOTAS; i++) {
+                 struct file *fp;
++                const char* quotafile = qinfo->qi_version == LUSTRE_QUOTA_V1?
++                                        quotafiles_v1[i] : quotafiles_v2[i];
+ 
+                 if (!Q_TYPESET(oqctl, i))
+                         continue;
+ 
+-                LASSERT(strlen(quotafiles[i]) + sizeof(prefix) <= sizeof(name));
+-                sprintf(name, "%s%s", prefix, quotafiles[i]);
++                LASSERT(strlen(quotafile) 
++                        + sizeof(prefix) <= sizeof(name));
++                sprintf(name, "%s%s", prefix, quotafile);
+ 
+                 if (qinfo->qi_files[i] != NULL) {
+                         rc = -EBUSY;
+                         break;
+                 }
+ 
+-                fp = filp_open(name, O_RDWR | O_EXCL, 0644);
++                fp = filp_open(name, O_RDWR, 0);
++                /* handle transparent migration to 64 bit quota file */
++                if (IS_ERR(fp) && PTR_ERR(fp) == -ENOENT && 
++                    qinfo->qi_version == LUSTRE_QUOTA_V2) {
++                        CDEBUG(D_INFO, "attempting to convert V1 quota file to V2 format.\n");
++                        fp = filp_open(name, O_CREAT | O_TRUNC, 0644);
++                        if (!IS_ERR(fp)) {
++                                qinfo->qi_files[i] = fp;
++                                rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_CONVERT);
++                                if (rc) {
++                                        CERROR("error convert %s admin quotafile! (rc:%d)\n",
++                                               i == USRQUOTA ? "user" : "group", rc);
++                                        break;
++                                }
++                        }
++                }
++
+                 if (IS_ERR(fp) || !S_ISREG(fp->f_dentry->d_inode->i_mode)) {
+-                        rc = PTR_ERR(fp);
+-                        CDEBUG(rc == -ENOENT ? D_QUOTA : D_ERROR,
+-                               "open %s failed! (rc:%d)\n", name, rc);
++                        rc = IS_ERR(fp) ? PTR_ERR(fp) : -EINVAL;
++                        CERROR("error open/create %s! (rc:%d)\n", name, rc);
+                         break;
+                 }
+                 qinfo->qi_files[i] = fp;
+ 
++                rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_CHK);
++                if (rc) {
++                        CERROR("invalid quota file %s! (rc:%d)\n",
++                               name, rc);
++                        break;
++                }
++
+                 rc = fsfilt_quotainfo(obd, qinfo, i, QFILE_RD_INFO);
+                 if (rc) {
+                         CERROR("error read quotainfo of %s! (rc:%d)\n",
+@@ -748,7 +884,7 @@ int mds_set_dqblk(struct obd_device *obd
+ {
+         struct mds_obd *mds = &obd->u.mds;
+         struct lustre_quota_info *qinfo = &mds->mds_quota_info;
+-        __u32 ihardlimit, isoftlimit, bhardlimit, bsoftlimit;
++        __u64 ihardlimit, isoftlimit, bhardlimit, bsoftlimit;
+         time_t btime, itime;
+         struct lustre_dquot *dquot;
+         struct obd_dqblk *dqblk = &oqctl->qc_dqblk;
+Index: lustre/tests/sanity-quota.sh
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/tests/sanity-quota.sh,v
+retrieving revision 1.7.10.20
+diff -p -u -r1.7.10.20 sanity-quota.sh
+--- ./lustre/tests/sanity-quota.sh	12 Dec 2007 20:31:53 -0000	1.7.10.20
++++ ./lustre/tests/sanity-quota.sh	19 Dec 2007 20:24:41 -0000
+@@ -1029,6 +1029,79 @@ test_14(){ # b=12223 -- setting quota on
+ }
+ run_test 14 "test setting quota on root ==="
+ 
++quota_set_version() {
++        do_facet mds "for i in /proc/fs/lustre/mds/${FSNAME}-MDT*/quota_type; do
++                echo $1 >> \\\$i;
++        done"
++}
++
++test_14a(){
++        # 1. check that required users exist
++        # 2. ensure that switch to new mode will start conversion
++        # 3. start quota in old mode and put some entries
++        # 4. restart quota in new mode forcing conversion and check the entries
++
++        MISSING_USERS=""
++        for i in `seq 1 30`; do
++                check_runas_id_ret quota15_$i
++                if [ "$?" != "0" ]; then
++                       MISSING_USERS="$MISSING_USERS quota15_$i"
++                fi
++        done
++
++        if [ -n "$MISSING_USERS" ]; then
++                echo "following users are missing: $MISSING_USERS, test skipped"
++                return
++        fi
++
++        $LFS quotaoff -ug $DIR
++        quota_set_version 1
++        $LFS quotacheck -ug $DIR
++
++        for i in `seq 1 30`; do 
++                $LFS setquota -u quota15_$i $i $i $i $i $DIR || error "lfs setquota failed"
++        done
++
++        $LFS quotaoff -ug $DIR
++        quota_set_version 2
++        $LFS quotainv -ug $DIR
++        $LFS quotacheck -ug $DIR
++
++        for i in `seq 1 30`; do 
++                # the format is "mntpnt   curspace[*]   bsoftlimit   bhardlimit   [time]   curinodes[*]    isoftlimit  ihardlimit"
++                ($LFS quota -u quota15_$i $DIR | grep -E '^ *'$DIR' *[0-9]+\** *'$i' *'$i' *[0-9]+\** *'$i' *'$i) \
++                 || error "lfs quota output is unexpected"
++                $LFS setquota -u quota15_$i 0 0 0 0 $DIR || error "ifs setquota clear failed"
++        done
++}
++run_test 14a "setting 30 quota entries in quota v1 file before conversion ==="
++
++test_15(){
++        LIMIT=$((24 * 1024 * 1024 * 1024 * 1024)) # 24 TB
++        PATTERN="`echo $DIR | sed 's/\//\\\\\//g'`"
++
++        # test for user
++        $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $DIR || error "failed setting user quota limit $LIMIT"
++        TOTAL_LIMIT="`$LFS quota -u $TSTUSR $DIR | awk '/^.*'$PATTERN'.*[[:digit:]+][[:space:]+]/ { print $4 }'`"
++        [ $TOTAL_LIMIT -eq $LIMIT ] || error "  (user)total limits = $TOTAL_LIMIT; limit = $LIMIT, failed!"
++        echo "  (user)total limits = $TOTAL_LIMIT; limit = $LIMIT, successful!"
++        $LFS setquota -u $TSTUSR 0 0 0 0 $DIR || error "failed removing user quota limit"
++
++        # test for group
++        $LFS setquota -g $TSTUSR 0 $LIMIT 0 0 $DIR || error "failed setting group quota limit $LIMIT"
++        TOTAL_LIMIT="`$LFS quota -g $TSTUSR $DIR | awk '/^.*'$PATTERN'.*[[:digit:]+][[:space:]+]/ { print $4 }'`"
++        [ $TOTAL_LIMIT -eq $LIMIT ] || error "  (group)total limits = $TOTAL_LIMIT; limit = $LIMIT, failed!"
++        echo "  (group)total limits = $TOTAL_LIMIT; limit = $LIMIT, successful!"
++        $LFS setquota -g $TSTUSR 0 0 0 0 $DIR || error "failed removing group quota limit"
++        $LFS quotaoff -ug $DIR
++        quota_set_version 1
++        $LFS quotacheck -ug $DIR || error "quotacheck failed"
++
++        echo "Testing that >4GB quota limits fail on volume with quota v1"
++        ! $LFS setquota -u $TSTUSR 0 $LIMIT 0 0 $DIR
++}
++run_test 15 "set block quota more than 4T ==="
++
+ # turn off quota
+ test_99()
+ {
+Index: lustre/tests/test-framework.sh
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/tests/test-framework.sh,v
+retrieving revision 1.42.10.46
+diff -p -u -r1.42.10.46 test-framework.sh
+--- ./lustre/tests/test-framework.sh	12 Dec 2007 21:08:16 -0000	1.42.10.46
++++ ./lustre/tests/test-framework.sh	19 Dec 2007 20:24:43 -0000
+@@ -1246,3 +1246,15 @@ check_runas_id() {
+         add user $myRUNAS_ID:$myRUNAS_ID on these nodes."
+     rm -rf $DIR/d0_runas_test
+ }
++
++check_runas_id_ret() {
++    local myRUNAS_ID=$1
++    shift
++    local myRUNAS=$@
++    mkdir $DIR/d0_runas_test
++    chmod 0755 $DIR
++    chown $myRUNAS_ID:$myRUNAS_ID $DIR/d0_runas_test
++    $myRUNAS touch $DIR/d0_runas_test/f$$ || return 1
++    rm -rf $DIR/d0_runas_test
++    return 0
++}
+Index: lustre/utils/lfs.c
+===================================================================
+RCS file: /cvsroot/cfs/lustre-core/utils/lfs.c,v
+retrieving revision 1.21.18.13
+diff -p -u -r1.21.18.13 lfs.c
+--- ./lustre/utils/lfs.c	29 Nov 2007 01:45:59 -0000	1.21.18.13
++++ ./lustre/utils/lfs.c	19 Dec 2007 20:24:46 -0000
+@@ -66,6 +66,7 @@ static int lfs_quotaon(int argc, char **
+ static int lfs_quotaoff(int argc, char **argv);
+ static int lfs_setquota(int argc, char **argv);
+ static int lfs_quota(int argc, char **argv);
++static int lfs_quotainv(int argc, char **argv);
+ #endif
+ static int lfs_join(int argc, char **argv);
+ 
+@@ -135,6 +136,8 @@ command_t cmdlist[] = {
+          "       setquota -t [ -u | -g ] <block-grace> <inode-grace> <filesystem>"},
+         {"quota", lfs_quota, 0, "Display disk usage and limits.\n"
+          "usage: quota [ -o obd_uuid ] [{-u|-g  <name>}|-t] <filesystem>"},
++        {"quotainv", lfs_quotainv, 0, "Invalidate quota data.\n"
++         "usage: quotainv [-u|-g] <filesystem>"},
+ #endif
+         {"help", Parser_help, 0, "help"},
+         {"exit", Parser_quit, 0, "quit"},
+@@ -1257,6 +1260,52 @@ static int lfs_quotaoff(int argc, char *
+         return 0;
+ }
+ 
++static int lfs_quotainv(int argc, char **argv)
++{
++        int c;
++        char *mnt;
++        struct if_quotactl qctl;
++        char *obd_type = (char *)qctl.obd_type;
++        int rc;
++
++        memset(&qctl, 0, sizeof(qctl));
++        qctl.qc_cmd = LUSTRE_Q_INVALIDATE;
++
++        optind = 0;
++        while ((c = getopt(argc, argv, "ug")) != -1) {
++                switch (c) {
++                case 'u':
++                        qctl.qc_type |= 0x01;
++                        break;
++                case 'g':
++                        qctl.qc_type |= 0x02;
++                        break;
++                default:
++                        fprintf(stderr, "error: %s: option '-%c' "
++                                        "unrecognized\n", argv[0], c);
++                        return CMD_HELP;
++                }
++        }
++
++        if (qctl.qc_type)
++                qctl.qc_type--;
++        else /* by default, invalidate quota for both user & group */
++                qctl.qc_type = 0x02;
++
++        if (argc == optind)
++                return CMD_HELP;
++
++        mnt = argv[optind];
++
++        rc = llapi_quotactl(mnt, &qctl);
++        if (rc) {
++                fprintf(stderr, "quotainv failed: %s\n", strerror(errno));
++                return rc;
++        }
++
++        return 0;
++}
++
+ static int name2id(unsigned int *id, char *name, int type)
+ {
+         if (type == USRQUOTA) {
+@@ -1380,6 +1429,17 @@ error:
+         return ULONG_MAX;
+ }
+ 
++#define ARG2ULL(nr, str, msg)                                           \
++do {                                                                    \
++        char *endp;                                                     \
++        nr = strtoull(str, &endp, 0);                                   \
++        if (*endp) {                                                    \
++                fprintf(stderr, "error: bad %s: %s\n", msg, str);       \
++                return CMD_HELP;                                        \
++        }                                                               \
++} while (0)
++
++
+ int lfs_setquota(int argc, char **argv)
+ {
+         int c;
+@@ -1432,10 +1492,10 @@ int lfs_setquota(int argc, char **argv)
+                         return CMD_HELP;
+                 }
+ 
+-                ARG2INT(dqb->dqb_bsoftlimit, argv[optind++], "block-softlimit");
+-                ARG2INT(dqb->dqb_bhardlimit, argv[optind++], "block-hardlimit");
+-                ARG2INT(dqb->dqb_isoftlimit, argv[optind++], "inode-softlimit");
+-                ARG2INT(dqb->dqb_ihardlimit, argv[optind++], "inode-hardlimit");
++                ARG2ULL(dqb->dqb_bsoftlimit, argv[optind++], "block-softlimit");
++                ARG2ULL(dqb->dqb_bhardlimit, argv[optind++], "block-hardlimit");
++                ARG2ULL(dqb->dqb_isoftlimit, argv[optind++], "inode-softlimit");
++                ARG2ULL(dqb->dqb_ihardlimit, argv[optind++], "inode-hardlimit");
+ 
+                 dqb->dqb_valid = QIF_LIMITS;
+         } else {

Added: trunk/debian/patches/bug15036-fix1.dpatch
URL: http://svn.debian.org/wsvn/pkg-lustre/trunk/debian/patches/bug15036-fix1.dpatch?rev=471&op=file
==============================================================================
--- trunk/debian/patches/bug15036-fix1.dpatch (added)
+++ trunk/debian/patches/bug15036-fix1.dpatch Tue Apr 22 14:15:17 2008
@@ -1,0 +1,55 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Missing include of sys/quota.h
+
+ at DPATCH@
+diff -urNad lustre-1.6.4.3~/lustre/lvfs/fsfilt_ext3.c lustre-1.6.4.3/lustre/lvfs/fsfilt_ext3.c
+--- lustre-1.6.4.3~/lustre/lvfs/fsfilt_ext3.c	2008-04-22 14:26:31.000000000 +0200
++++ lustre-1.6.4.3/lustre/lvfs/fsfilt_ext3.c	2008-04-22 14:26:31.000000000 +0200
+@@ -1551,12 +1551,12 @@
+         struct list_head        dqb_list;        /* in list also */
+         qid_t                   dqb_id;          /* uid/gid */
+         short                   dqb_type;        /* USRQUOTA/GRPQUOTA */
+-        __u32                   dqb_bhardlimit;  /* block hard limit */
+-        __u32                   dqb_bsoftlimit;  /* block soft limit */
++        qsize_t                 dqb_bhardlimit;  /* block hard limit */
++        qsize_t                 dqb_bsoftlimit;  /* block soft limit */
+         qsize_t                 dqb_curspace;    /* current space */
+-        __u32                   dqb_ihardlimit;  /* inode hard limit */
+-        __u32                   dqb_isoftlimit;  /* inode soft limit */
+-        __u32                   dqb_curinodes;   /* current inodes */
++        qsize_t                 dqb_ihardlimit;  /* inode hard limit */
++        qsize_t                 dqb_isoftlimit;  /* inode soft limit */
++        qsize_t                 dqb_curinodes;   /* current inodes */
+         __u64                   dqb_btime;       /* block grace time */
+         __u64                   dqb_itime;       /* inode grace time */
+         __u32                   dqb_valid;       /* flag for above fields */
+diff -urNad lustre-1.6.4.3~/lustre/quota/quota_ctl.c lustre-1.6.4.3/lustre/quota/quota_ctl.c
+--- lustre-1.6.4.3~/lustre/quota/quota_ctl.c	2008-04-22 14:26:31.000000000 +0200
++++ lustre-1.6.4.3/lustre/quota/quota_ctl.c	2008-04-22 14:26:31.000000000 +0200
+@@ -246,7 +246,7 @@
+         struct obd_device *obd = class_exp2obd(exp);
+         struct lov_obd *lov = &obd->u.lov;
+         __u64 curspace = 0;
+-        __u32 bhardlimit = 0;
++        __u64 bhardlimit = 0;
+         int i, rc = 0;
+         ENTRY;
+ 
+diff -urNad lustre-1.6.4.3~/lustre/quota/quota_master.c lustre-1.6.4.3/lustre/quota/quota_master.c
+--- lustre-1.6.4.3~/lustre/quota/quota_master.c	2008-04-22 14:26:31.000000000 +0200
++++ lustre-1.6.4.3/lustre/quota/quota_master.c	2008-04-22 15:36:54.000000000 +0200
+@@ -204,9 +204,9 @@
+         struct lustre_quota_info *info = &mds->mds_quota_info;
+         struct lustre_dquot *dquot = NULL;
+         __u64 *usage = NULL;
+-        __u32 hlimit = 0, slimit = 0;
+-        __u32 qdata_type = qdata->qd_flags & QUOTA_IS_GRP;
+-        __u32 is_blk = (qdata->qd_flags & QUOTA_IS_BLOCK) >> 1;
++        __u64 hlimit = 0, slimit = 0;
++        __u64 qdata_type = qdata->qd_flags & QUOTA_IS_GRP;
++        __u64 is_blk = (qdata->qd_flags & QUOTA_IS_BLOCK) >> 1;
+         time_t *time = NULL;
+         unsigned int grace = 0;
+         int rc = 0;

Modified: trunk/debian/rules
URL: http://svn.debian.org/wsvn/pkg-lustre/trunk/debian/rules?rev=471&op=diff
==============================================================================
--- trunk/debian/rules (original)
+++ trunk/debian/rules Tue Apr 22 14:15:17 2008
@@ -34,7 +34,7 @@
 # Lustre version to use
 VERSION=`cat $(TOP_DIR)/debian/lustre-version`
 SUPPORTED_KERNELS=2.6.18 2.6.20 2.6.22
-UPVERSION=`basename $(TOP_DIR) | awk -F- '{print $2}'`
+UPVERSION=`basename $(TOP_DIR) | awk -F- '{print $$2}'`
 
 # Packages
 PATCH_PKG=linux-patch-lustre




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