[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