Whamcloud - gitweb
b=22614 enlarge MDSSIZE/OSTSIZE to increase default journal size for conf-sanity
[fs/lustre-release.git] / lustre / lvfs / lustre_quota_fmt.c
index 6f0cb6d..d169bb7 100644 (file)
@@ -50,7 +50,9 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/quotaio_v1.h>
+#ifdef HAVE_QUOTAIO_V1_H
+# include <linux/quotaio_v1.h>
+#endif
 
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
@@ -77,42 +79,39 @@ static const union
 {
         struct lustre_disk_dqblk_v2 r1;
 } fakedquot[] = {
-        [LUSTRE_QUOTA_V2] = {.r1 = {.dqb_itime = __constant_cpu_to_le64(1LLU)} }
+        [LUSTRE_QUOTA_V2] = {.r1 = {.dqb_itime = __constant_cpu_to_le64(1LLU)}}
 };
 
 static const union
 {
         struct lustre_disk_dqblk_v2 r1;
 } emptydquot[] = {
-        [LUSTRE_QUOTA_V2] = {.r1 = { 0 } }
+        [LUSTRE_QUOTA_V2] = {.r1 = { 0 }}
 };
 
-int check_quota_file(struct file *f, struct inode *inode, int type, 
+extern void *lustre_quota_journal_start(struct inode *inode, int delete);
+extern void lustre_quota_journal_stop(void *handle);
+extern ssize_t lustre_read_quota(struct file *f, struct inode *inode, int type,
+                                 char *buf, int count, loff_t pos);
+extern ssize_t lustre_write_quota(struct file *f, char *buf, int count, loff_t pos);
+
+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;
         const uint *quota_versions = lustre_initqversions[version];
 
-        if (f) {
-                fs = get_fs();
-                set_fs(KERNEL_DS);
-                size = f->f_op->read(f, (char *)&dqhead,
-                                     sizeof(struct lustre_disk_dqheader), 
-                                     &offset);
-                set_fs(fs);
-        } else { 
-#ifndef KERNEL_SUPPORTS_QUOTA_READ
-                size = 0;
-#else
-                struct super_block *sb = inode->i_sb;
-                size = sb->s_op->quota_read(sb, type, (char *)&dqhead, 
-                                            sizeof(struct lustre_disk_dqheader), 0);
-#endif
+        if (!f && !inode) {
+                CERROR("check_quota_file failed!\n");
+                libcfs_debug_dumpstack(NULL);
+                return -EINVAL;
         }
+
+        size = lustre_read_quota(f, inode, type, (char *)&dqhead,
+                                 sizeof(struct lustre_disk_dqheader), 0);
+
         if (size != sizeof(struct lustre_disk_dqheader))
                 return -EINVAL;
         if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
@@ -132,16 +131,13 @@ int lustre_check_quota_file(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;
         ssize_t size;
-        loff_t offset = LUSTRE_DQINFOOFF;
 
-        fs = get_fs();
-        set_fs(KERNEL_DS);
-        size = f->f_op->read(f, (char *)&dinfo, 
-                             sizeof(struct lustre_disk_dqinfo), &offset);
-        set_fs(fs);
+        size = lustre_read_quota(f, NULL, 0, (char *)&dinfo,
+                                 sizeof(struct lustre_disk_dqinfo),
+                                 LUSTRE_DQINFOOFF);
+
         if (size != sizeof(struct lustre_disk_dqinfo)) {
                 CDEBUG(D_ERROR, "Can't read info structure on device %s.\n",
                        f->f_vfsmnt->mnt_sb->s_id);
@@ -161,7 +157,8 @@ int lustre_read_quota_file_info(struct file* f, struct lustre_mem_dqinfo* info)
  */
 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]);
+        return lustre_read_quota_file_info(lqi->qi_files[type],
+                                           &lqi->qi_info[type]);
 }
 
 /**
@@ -169,12 +166,10 @@ int lustre_read_quota_info(struct lustre_quota_info *lqi, int type)
  */
 int lustre_write_quota_info(struct lustre_quota_info *lqi, int type)
 {
-        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;
 
         info->dqi_flags &= ~DQF_INFO_DIRTY;
         dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);
@@ -183,11 +178,11 @@ int lustre_write_quota_info(struct lustre_quota_info *lqi, int type)
         dinfo.dqi_blocks = cpu_to_le32(info->dqi_blocks);
         dinfo.dqi_free_blk = cpu_to_le32(info->dqi_free_blk);
         dinfo.dqi_free_entry = cpu_to_le32(info->dqi_free_entry);
-        fs = get_fs();
-        set_fs(KERNEL_DS);
-        size = f->f_op->write(f, (char *)&dinfo, 
-                              sizeof(struct lustre_disk_dqinfo), &offset);
-        set_fs(fs);
+
+        size = lustre_write_quota(f, (char *)&dinfo,
+                                  sizeof(struct lustre_disk_dqinfo),
+                                  LUSTRE_DQINFOOFF);
+
         if (size != sizeof(struct lustre_disk_dqinfo)) {
                 CDEBUG(D_WARNING, 
                        "Can't write info structure on device %s.\n",
@@ -248,36 +243,35 @@ void freedqbuf(dqbuf_t buf)
         kfree(buf);
 }
 
-ssize_t read_blk(struct file *filp, uint blk, dqbuf_t buf)
+ssize_t read_blk(struct file *filp, struct inode *inode, int type,
+                 uint blk, dqbuf_t buf)
 {
-        mm_segment_t fs;
         ssize_t ret;
-        loff_t offset = blk << LUSTRE_DQBLKSIZE_BITS;
 
         memset(buf, 0, LUSTRE_DQBLKSIZE);
-        fs = get_fs();
-        set_fs(KERNEL_DS);
-        ret = filp->f_op->read(filp, (char *)buf, LUSTRE_DQBLKSIZE, &offset);
-        set_fs(fs);
+        ret = lustre_read_quota(filp, inode, type, (char *)buf, LUSTRE_DQBLKSIZE,
+                                blk << LUSTRE_DQBLKSIZE_BITS);
+
+        /* Reading past EOF just returns a block of zeros */
+        if (ret == -EBADR)
+                ret = 0;
+
         return ret;
 }
 
 ssize_t write_blk(struct file *filp, uint blk, dqbuf_t buf)
 {
-        mm_segment_t fs;
         ssize_t ret;
-        loff_t offset = blk << LUSTRE_DQBLKSIZE_BITS;
 
-        fs = get_fs();
-        set_fs(KERNEL_DS);
-        ret = filp->f_op->write(filp, (char *)buf, LUSTRE_DQBLKSIZE, &offset);
-        set_fs(fs);
+        ret = lustre_write_quota(filp, (char *)buf, LUSTRE_DQBLKSIZE,
+                                 blk << LUSTRE_DQBLKSIZE_BITS);
+
         return ret;
 }
 
 void lustre_mark_info_dirty(struct lustre_mem_dqinfo *info)
 {
-        set_bit(DQF_INFO_DIRTY_B, &info->dqi_flags);
+        cfs_set_bit(DQF_INFO_DIRTY_B, &info->dqi_flags);
 }
 
 /**
@@ -294,7 +288,7 @@ int get_free_dqblk(struct file *filp, struct lustre_mem_dqinfo *info)
                 return -ENOMEM;
         if (info->dqi_free_blk) {
                 blk = info->dqi_free_blk;
-                if ((ret = read_blk(filp, blk, buf)) < 0)
+                if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0)
                         goto out_buf;
                 info->dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
         } else {
@@ -349,7 +343,7 @@ int remove_free_dqentry(struct file *filp,
         if (!tmpbuf)
                 return -ENOMEM;
         if (nextblk) {
-                if ((err = read_blk(filp, nextblk, tmpbuf)) < 0)
+                if ((err = read_blk(filp, NULL, 0, nextblk, tmpbuf)) < 0)
                         goto out_buf;
                 ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
                     dh->dqdh_prev_free;
@@ -357,7 +351,7 @@ int remove_free_dqentry(struct file *filp,
                         goto out_buf;
         }
         if (prevblk) {
-                if ((err = read_blk(filp, prevblk, tmpbuf)) < 0)
+                if ((err = read_blk(filp, NULL, 0, prevblk, tmpbuf)) < 0)
                         goto out_buf;
                 ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_next_free =
                     dh->dqdh_next_free;
@@ -398,7 +392,7 @@ int insert_free_dqentry(struct file *filp,
         if ((err = write_blk(filp, blk, buf)) < 0)
                 goto out_buf;
         if (info->dqi_free_entry) {
-                if ((err = read_blk(filp, info->dqi_free_entry, tmpbuf)) < 0)
+                if ((err = read_blk(filp, NULL, 0, info->dqi_free_entry, tmpbuf)) < 0)
                         goto out_buf;
                 ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_prev_free =
                     cpu_to_le32(blk);
@@ -441,7 +435,7 @@ static uint find_free_dqentry(struct lustre_dquot *dquot, int *err,
         ddquot = GETENTRIES(buf, version);
         if (info->dqi_free_entry) {
                 blk = info->dqi_free_entry;
-                if ((*err = read_blk(filp, blk, buf)) < 0)
+                if ((*err = read_blk(filp, NULL, 0, blk, buf)) < 0)
                         goto out_buf;
         } else {
                 blk = get_free_dqblk(filp, info);
@@ -461,28 +455,29 @@ static uint find_free_dqentry(struct lustre_dquot *dquot, int *err,
         if (le16_to_cpu(dh->dqdh_entries) + 1 >= dqstrinblk)
                 if ((*err = remove_free_dqentry(filp, info, buf, blk)) < 0) {
                         CDEBUG(D_ERROR, 
-                               "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n",
-                               blk);
+                               "VFS: find_free_dqentry(): Can't remove block "
+                               "(%u) from entry free list.\n", blk);
                         goto out_buf;
                 }
         dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries) + 1);
         /* Find free structure in block */
         for (i = 0; i < dqstrinblk &&
              memcmp((char *)&emptydquot[version],
-                    (char*)ddquot + i * dqblk_sz,
-                    dqblk_sz); i++);
+                    (char *)ddquot + i * dqblk_sz, dqblk_sz);
+             i++);
 
         if (i == dqstrinblk) {
                 CDEBUG(D_ERROR, 
-                       "VFS: find_free_dqentry(): Data block full but it shouldn't.\n");
+                       "VFS: find_free_dqentry(): Data block full but it "
+                       "shouldn't.\n");
                 *err = -EIO;
                 goto out_buf;
         }
 
         if ((*err = write_blk(filp, blk, buf)) < 0) {
                 CDEBUG(D_ERROR,
-                       "VFS: find_free_dqentry(): Can't write quota data block %u.\n",
-                       blk);
+                       "VFS: find_free_dqentry(): Can't write quota data "
+                       "block %u.\n", blk);
                 goto out_buf;
         }
         dquot->dq_off =
@@ -499,7 +494,7 @@ 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;
@@ -520,9 +515,8 @@ static int do_insert_tree(struct lustre_dquot *dquot, uint * treeblk, int depth,
                 memset(buf, 0, LUSTRE_DQBLKSIZE);
                 newact = 1;
         } else {
-                if ((ret = read_blk(filp, *treeblk, buf)) < 0) {
-                        CDEBUG(D_ERROR,
-                               "VFS: Can't read tree quota block %u.\n",
+                if ((ret = read_blk(filp, NULL, 0, *treeblk, buf)) < 0) {
+                        CERROR("VFS: Can't read tree quota block %u.\n",
                                *treeblk);
                         goto out_buf;
                 }
@@ -535,7 +529,8 @@ static int do_insert_tree(struct lustre_dquot *dquot, uint * treeblk, int depth,
 
                 if (newblk) {
                         CDEBUG(D_ERROR, 
-                               "VFS: Inserting already present quota entry (block %u).\n",
+                               "VFS: Inserting already present quota entry "
+                               "(block %u).\n",
                                ref[GETIDINDEX(dquot->dq_id, depth)]);
                         ret = -EIO;
                         goto out_buf;
@@ -573,35 +568,32 @@ static int lustre_write_dquot(struct lustre_dquot *dquot,
 {
         int type = dquot->dq_type;
         struct file *filp;
-        mm_segment_t fs;
         loff_t offset;
         ssize_t ret;
         int dqblk_sz = lustre_disk_dqblk_sz[version];
-        char ddquot[dqblk_sz];
+        struct lustre_disk_dqblk_v2 ddquot;
 
-        ret = mem2diskdqb(ddquot, &dquot->dq_dqb, dquot->dq_id, version);
+        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, version)) < 0) {
                         CDEBUG(D_ERROR,
-                               "VFS: Error %Zd occurred while creating quota.\n",
-                               ret);
+                               "VFS: Error %Zd occurred while creating "
+                               "quota.\n", ret);
                         return ret;
                 }
         filp = dquot->dq_info->qi_files[type];
         offset = dquot->dq_off;
-        /* 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 */
-        if (!memcmp((char *)&emptydquot[version], ddquot, dqblk_sz))
-                ((struct lustre_disk_dqblk_v2 *)ddquot)->dqb_itime = cpu_to_le64(1);
-        fs = get_fs();
-        set_fs(KERNEL_DS);
-        ret = filp->f_op->write(filp, ddquot,
-                                dqblk_sz, &offset);
-        set_fs(fs);
+        /* 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 */
+        if (!memcmp((char *)&emptydquot[version], (char *)&ddquot, dqblk_sz))
+                ddquot.dqb_itime = cpu_to_le64(1);
+
+        ret = lustre_write_quota(filp, (char *)&ddquot, dqblk_sz, offset);
         if (ret != dqblk_sz) {
                 CDEBUG(D_WARNING, "VFS: dquota write failed on dev %s\n",
                        filp->f_dentry->d_sb->s_id);
@@ -631,11 +623,12 @@ static int free_dqentry(struct lustre_dquot *dquot, uint blk,
                 return -ENOMEM;
         if (dquot->dq_off >> LUSTRE_DQBLKSIZE_BITS != blk) {
                 CDEBUG(D_ERROR,
-                       "VFS: Quota structure has offset to other block (%u) than it should (%u).\n",
+                       "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) {
+        if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0) {
                 CDEBUG(D_ERROR, "VFS: Can't read quota data block %u\n", blk);
                 goto out_buf;
         }
@@ -645,8 +638,8 @@ static int free_dqentry(struct lustre_dquot *dquot, uint blk,
                 if ((ret = remove_free_dqentry(filp, info, buf, blk)) < 0 ||
                     (ret = put_free_dqblk(filp, info, buf, blk)) < 0) {
                         CDEBUG(D_ERROR,
-                               "VFS: Can't move quota data block (%u) to free list.\n",
-                               blk);
+                               "VFS: Can't move quota data block (%u) to free "
+                               "list.\n", blk);
                         goto out_buf;
                 }
         } else {
@@ -657,8 +650,8 @@ static int free_dqentry(struct lustre_dquot *dquot, uint blk,
                         if ((ret =
                              insert_free_dqentry(filp, info, buf, blk)) < 0) {
                                 CDEBUG(D_ERROR,
-                                       "VFS: Can't insert quota data block (%u) to free entry list.\n",
-                                       blk);
+                                       "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) {
@@ -689,8 +682,8 @@ static int remove_tree(struct lustre_dquot *dquot, uint * blk, int depth,
 
         if (!buf)
                 return -ENOMEM;
-        if ((ret = read_blk(filp, *blk, buf)) < 0) {
-                CDEBUG(D_ERROR, "VFS: Can't read quota data block %u\n", *blk);
+        if ((ret = read_blk(filp, NULL, 0, *blk, buf)) < 0) {
+                CERROR("VFS: Can't read quota data block %u\n", *blk);
                 goto out_buf;
         }
         newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]);
@@ -740,7 +733,8 @@ static loff_t find_block_dqentry(struct lustre_dquot *dquot, uint blk,
         dqbuf_t buf = getdqbuf();
         loff_t ret = 0;
         int i;
-        struct lustre_disk_dqblk_v2 *ddquot = (struct lustre_disk_dqblk_v2 *)GETENTRIES(buf, version);
+        struct lustre_disk_dqblk_v2 *ddquot =
+                (struct lustre_disk_dqblk_v2 *)GETENTRIES(buf, version);
         int dqblk_sz = lustre_disk_dqblk_sz[version];
         int dqstrinblk = lustre_dqstrinblk[version];
 
@@ -748,8 +742,8 @@ static loff_t find_block_dqentry(struct lustre_dquot *dquot, uint blk,
 
         if (!buf)
                 return -ENOMEM;
-        if ((ret = read_blk(filp, blk, buf)) < 0) {
-                CDEBUG(D_ERROR, "VFS: Can't read quota tree block %u.\n", blk);
+        if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0) {
+                CERROR("VFS: Can't read quota tree block %u.\n", blk);
                 goto out_buf;
         }
         if (dquot->dq_id)
@@ -760,8 +754,7 @@ static loff_t find_block_dqentry(struct lustre_dquot *dquot, uint blk,
                 for (i = 0; i < dqstrinblk; i++)
                         if (!le32_to_cpu(ddquot[i].dqb_id)
                             && memcmp((char *)&emptydquot[version],
-                                      ddquot + i*dqblk_sz,
-                                      dqblk_sz))
+                                      (char *)&ddquot[i], dqblk_sz))
                                 break;
         }
         if (i == dqstrinblk) {
@@ -783,7 +776,7 @@ out_buf:
 /**
  * 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];
@@ -793,8 +786,8 @@ static loff_t find_tree_dqentry(struct lustre_dquot *dquot, uint blk, int depth,
 
         if (!buf)
                 return -ENOMEM;
-        if ((ret = read_blk(filp, blk, buf)) < 0) {
-                CDEBUG(D_ERROR, "VFS: Can't read quota tree block %u.\n", blk);
+        if ((ret = read_blk(filp, NULL, 0, blk, buf)) < 0) {
+                CERROR("VFS: Can't read quota tree block %u.\n", blk);
                 goto out_buf;
         }
         ret = 0;
@@ -823,7 +816,6 @@ int lustre_read_dquot(struct lustre_dquot *dquot)
 {
         int type = dquot->dq_type;
         struct file *filp;
-        mm_segment_t fs;
         loff_t offset;
         int ret = 0, dqblk_sz;
         lustre_quota_version_t version;
@@ -831,7 +823,7 @@ int lustre_read_dquot(struct lustre_dquot *dquot)
         /* Invalidated quota? */
         if (!dquot->dq_info || !(filp = dquot->dq_info->qi_files[type])) {
                 CDEBUG(D_ERROR, "VFS: Quota invalidated while reading!\n");
-                return -EIO;
+                return -ESRCH;
         }
 
         version = dquot->dq_info->qi_version;
@@ -845,32 +837,29 @@ int lustre_read_dquot(struct lustre_dquot *dquot)
                                "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);
+                cfs_set_bit(DQ_FAKE_B, &dquot->dq_flags);
                 memset(&dquot->dq_dqb, 0, sizeof(struct lustre_mem_dqblk));
                 ret = offset;
         } else {
-                char ddquot[dqblk_sz];
+                struct lustre_disk_dqblk_v2 ddquot;
 
                 dquot->dq_off = offset;
-                fs = get_fs();
-                set_fs(KERNEL_DS);
-                if ((ret = filp->f_op->read(filp, ddquot, dqblk_sz, &offset)) !=
-                    dqblk_sz) {
+                if ((ret = lustre_read_quota(filp, NULL, type, (char *)&ddquot,
+                                             dqblk_sz, offset)) != dqblk_sz) {
                         if (ret >= 0)
                                 ret = -EIO;
                         CDEBUG(D_ERROR,
-                               "VFS: Error while reading quota structure for id %u.\n",
-                               dquot->dq_id);
-                        memset(ddquot, 0, dqblk_sz);
+                               "VFS: Error while reading quota structure for id "
+                               "%u.\n", dquot->dq_id);
+                        memset((char *)&ddquot, 0, dqblk_sz);
                 } else {
                         ret = 0;
                         /* We need to escape back all-zero structure */
                         if (!memcmp((char *)&fakedquot[version],
-                                    ddquot, dqblk_sz))
-                                ((struct lustre_disk_dqblk_v2 *)ddquot)->dqb_itime = cpu_to_le64(0);
+                                    (char *)&ddquot, dqblk_sz))
+                                ddquot.dqb_itime = cpu_to_le64(0);
                 }
-                set_fs(fs);
-                disk2memdqb(&dquot->dq_dqb, ddquot, version);
+                disk2memdqb(&dquot->dq_dqb, &ddquot, version);
         }
 
         return ret;
@@ -884,17 +873,30 @@ int lustre_commit_dquot(struct lustre_dquot *dquot)
 {
         int rc = 0;
         lustre_quota_version_t version = dquot->dq_info->qi_version;
+        void *handle;
+        struct inode *inode = dquot->dq_info->qi_files[dquot->dq_type]->f_dentry->d_inode;
+        int delete = 0;
 
         /* always clear the flag so we don't loop on an IO error... */
-        clear_bit(DQ_MOD_B, &dquot->dq_flags);
+        cfs_clear_bit(DQ_MOD_B, &dquot->dq_flags);
 
         /* The block/inode usage in admin quotafile isn't the real usage
          * 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))
+        if (cfs_test_bit(DQ_FAKE_B, &dquot->dq_flags))
+                delete = 1;
+        handle = lustre_quota_journal_start(inode, delete);
+        if (unlikely(IS_ERR(handle))) {
+                rc = PTR_ERR(handle);
+                CERROR("fail to lustre_quota_journal_start: rc = %d\n", rc);
+                return rc;
+        }
+
+        if (delete)
                 rc = lustre_delete_dquot(dquot, version);
         else
                 rc = lustre_write_dquot(dquot, version);
+        lustre_quota_journal_stop(handle);
 
         if (rc < 0)
                 return rc;
@@ -905,14 +907,14 @@ int lustre_commit_dquot(struct lustre_dquot *dquot)
         return rc;
 }
 
-int lustre_init_quota_header(struct lustre_quota_info *lqi, int type, int fakemagics)
+int lustre_init_quota_header(struct lustre_quota_info *lqi, int type,
+                             int fakemagics)
 {
         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;
         ssize_t size;
-        loff_t offset = 0;
         struct file *fp = lqi->qi_files[type];
         int rc = 0;
 
@@ -920,8 +922,8 @@ int lustre_init_quota_header(struct lustre_quota_info *lqi, int type, int fakema
         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);
+        size = lustre_write_quota(fp, (char *)&dqhead,
+                                  sizeof(struct lustre_disk_dqheader), 0);
 
         if (size != sizeof(struct lustre_disk_dqheader)) {
                 CDEBUG(D_ERROR, "error writing quoafile header (rc:%d)\n", rc);
@@ -959,26 +961,8 @@ int lustre_init_quota_info(struct lustre_quota_info *lqi, int type)
         return lustre_init_quota_info_generic(lqi, type, 0);
 }
 
-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);
-        } else {
-#ifndef KERNEL_SUPPORTS_QUOTA_READ
-                return -ENOTSUPP;
-#else
-                struct super_block *sb = inode->i_sb;
-                memset(buf, 0, LUSTRE_DQBLKSIZE);
-                return sb->s_op->quota_read(sb, type, (char *)buf,
-                                            LUSTRE_DQBLKSIZE, 
-                                            blk << LUSTRE_DQBLKSIZE_BITS);
-#endif
-        }
-}
-
 static int walk_block_dqentry(struct file *filp, struct inode *inode, int type,
-                              uint blk, struct list_head *list)
+                              uint blk, cfs_list_t *list)
 {
         dqbuf_t buf = getdqbuf();
         loff_t ret = 0;
@@ -986,12 +970,12 @@ static int walk_block_dqentry(struct file *filp, struct inode *inode, int type,
             (struct lustre_disk_dqdbheader *)buf;
         struct dqblk *blk_item;
         struct dqblk *pos;
-        struct list_head *tmp;
+        cfs_list_t *tmp;
 
         if (!buf)
                 return -ENOMEM;
-        if ((ret = quota_read(filp, inode, type, blk, buf)) < 0) {
-                CDEBUG(D_ERROR, "VFS: Can't read quota tree block %u.\n", blk);
+        if ((ret = read_blk(filp, inode, type, blk, buf)) < 0) {
+                CERROR("VFS: Can't read quota tree block %u.\n", blk);
                 goto out_buf;
         }
         ret = 0;
@@ -999,12 +983,12 @@ static int walk_block_dqentry(struct file *filp, struct inode *inode, int type,
         if (!le32_to_cpu(dqhead->dqdh_entries))
                 goto out_buf;
 
-        if (list_empty(list)) {
+        if (cfs_list_empty(list)) {
                 tmp = list;
                 goto done;
         }
 
-        list_for_each_entry(pos, list, link) {
+        cfs_list_for_each_entry(pos, list, link) {
                 if (blk == pos->blk)    /* we got this blk already */
                         goto out_buf;
                 if (blk > pos->blk)
@@ -1019,9 +1003,9 @@ done:
                 goto out_buf;
         }
         blk_item->blk = blk;
-        INIT_LIST_HEAD(&blk_item->link);
+        CFS_INIT_LIST_HEAD(&blk_item->link);
 
-        list_add_tail(&blk_item->link, tmp);
+        cfs_list_add_tail(&blk_item->link, tmp);
 
 out_buf:
         freedqbuf(buf);
@@ -1029,7 +1013,7 @@ out_buf:
 }
 
 int walk_tree_dqentry(struct file *filp, struct inode *inode, int type, 
-                      uint blk, int depth, struct list_head *list)
+                      uint blk, int depth, cfs_list_t *list)
 {
         dqbuf_t buf = getdqbuf();
         loff_t ret = 0;
@@ -1038,8 +1022,8 @@ int walk_tree_dqentry(struct file *filp, struct inode *inode, int type,
 
         if (!buf)
                 return -ENOMEM;
-        if ((ret = quota_read(filp, inode, type, blk, buf)) < 0) {
-                CDEBUG(D_ERROR, "VFS: Can't read quota tree block %u.\n", blk);
+        if ((ret = read_blk(filp, inode, type, blk, buf)) < 0) {
+                CERROR("VFS: Can't read quota tree block %u.\n", blk);
                 goto out_buf;
         }
         ret = 0;
@@ -1064,9 +1048,9 @@ out_buf:
  * Walk through the quota file (v2 format) to get all ids with quota limit
  */
 int lustre_get_qids(struct file *fp, struct inode *inode, int type,
-                    struct list_head *list)
+                    cfs_list_t *list)
 {
-        struct list_head blk_list;
+        cfs_list_t blk_list;
         struct dqblk *blk_item, *tmp;
         dqbuf_t buf = NULL;
         struct lustre_disk_dqblk_v2 *ddquot;
@@ -1075,6 +1059,8 @@ int lustre_get_qids(struct file *fp, struct inode *inode, int type,
 
         ENTRY;
 
+        LASSERT(ergo(fp == NULL, inode != NULL));
+
         if (check_quota_file(fp, inode, type, LUSTRE_QUOTA_V2) == 0)
                 version = LUSTRE_QUOTA_V2;
         else {
@@ -1082,18 +1068,18 @@ int lustre_get_qids(struct file *fp, struct inode *inode, int type,
                 RETURN(-EINVAL);
         }
 
-        if (!list_empty(list)) {
+        if (!cfs_list_empty(list)) {
                 CDEBUG(D_ERROR, "not empty list\n");
                 RETURN(-EINVAL);
         }
 
-        INIT_LIST_HEAD(&blk_list);
+        CFS_INIT_LIST_HEAD(&blk_list);
         rc = walk_tree_dqentry(fp, inode, type, LUSTRE_DQTREEOFF, 0, &blk_list);
         if (rc) {
                 CDEBUG(D_ERROR, "walk through quota file failed!(%d)\n", rc);
                 GOTO(out_free, rc);
         }
-        if (list_empty(&blk_list))
+        if (cfs_list_empty(&blk_list))
                 RETURN(0);
 
         buf = getdqbuf();
@@ -1101,14 +1087,13 @@ int lustre_get_qids(struct file *fp, struct inode *inode, int type,
                 RETURN(-ENOMEM);
         ddquot = (struct lustre_disk_dqblk_v2 *)GETENTRIES(buf, version);
 
-        list_for_each_entry(blk_item, &blk_list, link) {
+        cfs_list_for_each_entry(blk_item, &blk_list, link) {
                 loff_t ret = 0;
                 int i, dqblk_sz = lustre_disk_dqblk_sz[version];
 
                 memset(buf, 0, LUSTRE_DQBLKSIZE);
-                if ((ret = quota_read(fp, inode, type, blk_item->blk, buf))<0) {
-                        CDEBUG(D_ERROR,
-                               "VFS: Can't read quota tree block %u.\n",
+                if ((ret = read_blk(fp, inode, type, blk_item->blk, buf)) < 0) {
+                        CERROR("VFS: Can't read quota tree block %u.\n",
                                blk_item->blk);
                         GOTO(out_free, rc = ret);
                 }
@@ -1117,22 +1102,27 @@ int lustre_get_qids(struct file *fp, struct inode *inode, int type,
                         struct dquot_id *dqid;
                         /* skip empty entry */
                         if (!memcmp((char *)&emptydquot[version],
-                                    ddquot + i*dqblk_sz, dqblk_sz))
+                                    (char *)&ddquot[i], dqblk_sz))
                                 continue;
 
-                        dqid = kmalloc(sizeof(*dqid), GFP_NOFS);
-                        if (!dqid) 
+                        OBD_ALLOC_GFP(dqid, sizeof(*dqid), GFP_NOFS);
+                        if (!dqid)
                                 GOTO(out_free, rc = -ENOMEM);
 
-                        dqid->di_id = le32_to_cpu(ddquot[i].dqb_id);
-                        INIT_LIST_HEAD(&dqid->di_link);
-                        list_add(&dqid->di_link, list);
+                        dqid->di_id    = le32_to_cpu(ddquot[i].dqb_id);
+                        dqid->di_flag  = le64_to_cpu(ddquot[i].dqb_ihardlimit) ?
+                                         QI_SET : 0;
+                        dqid->di_flag |= le64_to_cpu(ddquot[i].dqb_bhardlimit) ?
+                                         QB_SET : 0;
+
+                        CFS_INIT_LIST_HEAD(&dqid->di_link);
+                        cfs_list_add(&dqid->di_link, list);
                 }
         }
 
 out_free:
-        list_for_each_entry_safe(blk_item, tmp, &blk_list, link) {
-                list_del_init(&blk_item->link);
+        cfs_list_for_each_entry_safe(blk_item, tmp, &blk_list, link) {
+                cfs_list_del_init(&blk_item->link);
                 kfree(blk_item);
         }
         if (buf)