+ /* turn on quota and read dqinfo if existed */
+ OBD_ALLOC_PTR(qctxt);
+ if (!qctxt) {
+ oqc->qc_stat = -ENOMEM;
+ RETURN(-ENOMEM);
+ }
+
+ for (i = 0; i < NR_DQHASH; i++)
+ INIT_HLIST_HEAD(&qctxt->qckt_hash[i]);
+ INIT_LIST_HEAD(&qctxt->qckt_list);
+
+ for (i = 0; i < MAXQUOTAS; i++) {
+ if (!Q_TYPESET(oqc, i))
+ continue;
+
+ rc = quota_onoff(sb, Q_QUOTAON, i);
+ if (!rc || rc == -EBUSY) {
+ rc = read_old_dqinfo(sb, i, qctxt->qckt_dqinfo);
+ if (rc)
+ GOTO(out, rc);
+ } else if (rc == -ENOENT) {
+ qctxt->qckt_first_check[i] = 1;
+ } else if (rc) {
+ GOTO(out, rc);
+ }
+ }
+
+ /* check quota and update in hash */
+ for (group = 0; group < sbi->s_groups_count; group++) {
+ ino = group * sbi->s_inodes_per_group + 1;
+ bitmap_bh = read_inode_bitmap(sb, group);
+ if (!bitmap_bh) {
+ CERROR("read_inode_bitmap group %d failed", group);
+ GOTO(out, -EIO);
+ }
+
+ for (i = 0; i < sbi->s_inodes_per_group; i++, ino++) {
+ if (ino < sbi->s_first_ino)
+ continue;
+
+ inode = ext3_iget_inuse(sb, bitmap_bh, i, ino);
+ rc = add_inode_quota(inode, qctxt, oqc);
+ iput(inode);
+ if (rc) {
+ brelse(bitmap_bh);
+ GOTO(out, rc);
+ }
+ }
+
+ brelse(bitmap_bh);
+ }
+
+ /* read old quota limits from old quota file. (only for the user
+ * has limits but hasn't file) */
+#ifdef HAVE_QUOTA_SUPPORT
+ for (i = 0; i < MAXQUOTAS; i++) {
+ struct list_head id_list;
+ struct dquot_id *dqid, *tmp;
+
+ if (!Q_TYPESET(oqc, i))
+ continue;
+
+ if (qctxt->qckt_first_check[i])
+ continue;
+
+
+ LASSERT(sb_dqopt(sb)->files[i] != NULL);
+ INIT_LIST_HEAD(&id_list);
+#ifndef KERNEL_SUPPORTS_QUOTA_READ
+ rc = lustre_get_qids(sb_dqopt(sb)->files[i], NULL, i, &id_list);
+#else
+ rc = lustre_get_qids(NULL, sb_dqopt(sb)->files[i], i, &id_list);
+#endif
+ if (rc)
+ CERROR("read old limits failed. (rc:%d)\n", rc);
+
+ list_for_each_entry_safe(dqid, tmp, &id_list, di_link) {
+ list_del_init(&dqid->di_link);
+
+ if (!rc)
+ cqget(sb, qctxt->qckt_hash, &qctxt->qckt_list,
+ dqid->di_id, i,
+ qctxt->qckt_first_check[i]);
+ kfree(dqid);
+ }
+ }
+#endif
+ /* turn off quota cause we are to dump chk_dqblk to files */
+ quota_onoff(sb, Q_QUOTAOFF, oqc->qc_type);
+
+ rc = create_new_quota_files(qctxt, oqc);
+ if (rc)
+ GOTO(out, rc);
+
+ /* we use vfs functions to set dqblk, so turn quota on */
+ rc = quota_onoff(sb, Q_QUOTAON, oqc->qc_type);
+out:
+ /* dump and free chk_dqblk */
+ rc = prune_chkquots(sb, qctxt, rc);
+ OBD_FREE_PTR(qctxt);
+
+ /* turn off quota, `lfs quotacheck` will turn on when all
+ * nodes quotacheck finish. */
+ quota_onoff(sb, Q_QUOTAOFF, oqc->qc_type);
+
+ oqc->qc_stat = rc;
+ if (rc)
+ CERROR("quotacheck failed: rc = %d\n", rc);
+
+ RETURN(rc);