diff --git a/lustre/ChangeLog b/lustre/ChangeLog
index d4f37e213087c13ec8db46ab66f67280b2c8c2d6..08b767aefb070b4b706c1341ea569f6dc8e18c19 100644
--- a/lustre/ChangeLog
+++ b/lustre/ChangeLog
@@ -1656,6 +1656,15 @@ Description: Improve multi-block allocation algorithm to avoid fragmentation
 Details    : The mballoc3 code (ldiskfs2 only) adds new mechanisms to improve
 	     allocation locality and avoid filesystem fragmentation.
 
+Severity   : normal
+Frequency  : rare
+Bugzilla   : 14036
+Description: lfs quota fails with deactivated OSTS
+Details    : With this patch, three improvements are included:
+	     1. detete the softlimit in mds and osts when use "lfs quota".
+	     2. display the inaccurate data in the output of "lfs quota".
+	     3. try to get quota info when "lfs quota" is executed.
+
 ------------------------------------------------------------------------------
 
 2007-04-01  Cluster File Systems, Inc. <info@clusterfs.com>
diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c
index b8d97025023b0cf92d0d748f079df3634166d7a3..6e95fa3565f16b59550363d766b64cb55db45443 100644
--- a/lustre/llite/dir.c
+++ b/lustre/llite/dir.c
@@ -982,9 +982,12 @@ static int ll_dir_ioctl(struct inode *inode, struct file *file,
 
                         /* XXX: dqb_valid is borrowed as a flag to mark that
                          *      only mds quota is wanted */
-                        if (qctl->qc_dqblk.dqb_valid)
+                        if (qctl->qc_dqblk.dqb_valid) {
                                 qctl->obd_uuid = sbi->ll_mdc_exp->exp_obd->
                                                         u.cli.cl_target_uuid;
+                                qctl->qc_dqblk.dqb_valid = 0;
+                        }
+
                         break;
                 case Q_GETINFO:
                         break;
diff --git a/lustre/lvfs/fsfilt_ext3.c b/lustre/lvfs/fsfilt_ext3.c
index 1aa12a4dbe4f930fe768280bea8411c266c48161..e2f5e10d2b60b71cb6600f83f689ba6d2633e090 100644
--- a/lustre/lvfs/fsfilt_ext3.c
+++ b/lustre/lvfs/fsfilt_ext3.c
@@ -1522,6 +1522,8 @@ static int fsfilt_ext3_quotactl(struct super_block *sb,
                 if (!qcop->get_dqblk)
                         GOTO(out, rc = -ENOSYS);
                 rc = qcop->get_dqblk(sb, oqc->qc_type, oqc->qc_id, dqblk);
+                if (!rc)
+                        dqblk->dqb_valid = QIF_LIMITS | QIF_USAGE;
                 break;
         case Q_SYNC:
                 if (!sb->s_qcop->quota_sync)
diff --git a/lustre/quota/quota_ctl.c b/lustre/quota/quota_ctl.c
index 4f50f7d30ee17765e06aab7e9ce30828828326f3..8876603058cd1f1ebdbc4a6c9c61a916dedb36b1 100644
--- a/lustre/quota/quota_ctl.c
+++ b/lustre/quota/quota_ctl.c
@@ -223,19 +223,18 @@ int client_quota_ctl(struct obd_export *exp, struct obd_quotactl *oqctl)
         ptlrpc_req_set_repsize(req, 2, size);
 
         rc = ptlrpc_queue_wait(req);
-        if (!rc) {
-                oqc = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*oqc),
-                                         lustre_swab_obd_quotactl);
-                if (oqc == NULL) {
-                        CERROR ("Can't unpack obd_quotactl\n");
-                        GOTO(out, rc = -EPROTO);
-                }
-
-                *oqctl = *oqc;
+        oqc = lustre_swab_repbuf(req, REPLY_REC_OFF, sizeof(*oqc),
+                                 lustre_swab_obd_quotactl);
+        if (oqc == NULL) {
+                CERROR ("Can't unpack obd_quotactl\n");
+                GOTO(out, rc = -EPROTO);
         }
+
+        *oqctl = *oqc;
+        EXIT;
 out:
         ptlrpc_req_finished(req);
-        RETURN (rc);
+        return rc;
 }
 
 int lov_quota_ctl(struct obd_export *exp, struct obd_quotactl *oqctl)
@@ -261,11 +260,10 @@ int lov_quota_ctl(struct obd_export *exp, struct obd_quotactl *oqctl)
                         if (oqctl->qc_cmd == Q_GETOQUOTA) {
                                 CERROR("ost %d is inactive\n", i);
                                 rc = -EIO;
-                                break;
                         } else {
                                 CDEBUG(D_HA, "ost %d is inactive\n", i);
-                                continue;
                         }
+                        continue;
                 }
 
                 err = obd_quotactl(lov->lov_tgts[i]->ltd_exp, oqctl);
diff --git a/lustre/quota/quota_master.c b/lustre/quota/quota_master.c
index a321faa60d21c337aa8bd4c763a50313b104a12d..0a916a670e0dda6b74a5f44e9586501955a3fc57 100644
--- a/lustre/quota/quota_master.c
+++ b/lustre/quota/quota_master.c
@@ -877,7 +877,7 @@ static int mds_get_space(struct obd_device *obd, struct obd_quotactl *oqctl)
 {
         struct obd_quotactl *soqc;
         struct lvfs_run_ctxt saved;
-        int rc;
+        int rc, rc1;
         ENTRY;
 
         OBD_ALLOC_PTR(soqc);
@@ -889,25 +889,26 @@ static int mds_get_space(struct obd_device *obd, struct obd_quotactl *oqctl)
         soqc->qc_type = oqctl->qc_type;
 
         rc = obd_quotactl(obd->u.mds.mds_osc_exp, soqc);
-        if (rc)
-               GOTO(out, rc);
 
         oqctl->qc_dqblk.dqb_curspace = soqc->qc_dqblk.dqb_curspace;
 
         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
         soqc->qc_dqblk.dqb_curspace = 0;
-        rc = fsfilt_quotactl(obd, obd->u.obt.obt_sb, soqc);
+        rc1 = fsfilt_quotactl(obd, obd->u.obt.obt_sb, soqc);
         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
 
-        if (rc)
-                GOTO(out, rc);
-
         oqctl->qc_dqblk.dqb_curinodes += soqc->qc_dqblk.dqb_curinodes;
+        if (!rc1)
+                oqctl->qc_dqblk.dqb_valid |= QIF_INODES;
         oqctl->qc_dqblk.dqb_curspace += soqc->qc_dqblk.dqb_curspace;
-        EXIT;
-out:
+        if (!rc && !rc1)
+                oqctl->qc_dqblk.dqb_valid |= QIF_USAGE;
+
         OBD_FREE_PTR(soqc);
-        return rc;
+
+        if (!rc)
+                rc = rc1;
+        RETURN(rc);
 }
 
 int mds_get_dqblk(struct obd_device *obd, struct obd_quotactl *oqctl)
@@ -920,6 +921,7 @@ int mds_get_dqblk(struct obd_device *obd, struct obd_quotactl *oqctl)
         ENTRY;
 
         down(&mds->mds_qonoff_sem);
+        dqblk->dqb_valid = 0;
         if (qinfo->qi_files[oqctl->qc_type] == NULL)
                 GOTO(out, rc = -ESRCH);
 
@@ -934,6 +936,7 @@ int mds_get_dqblk(struct obd_device *obd, struct obd_quotactl *oqctl)
         dqblk->dqb_bsoftlimit = dquot->dq_dqb.dqb_bsoftlimit;
         dqblk->dqb_btime = dquot->dq_dqb.dqb_btime;
         dqblk->dqb_itime = dquot->dq_dqb.dqb_itime;
+        dqblk->dqb_valid |= QIF_LIMITS | QIF_TIMES;
         up(&dquot->dq_sem);
 
         lustre_dqput(dquot);
diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh
index 10fb9bc5c6c882db017d4a230b43005921030200..1ca29e7c4d5d84921b2153e8b8c25d809993ed87 100644
--- a/lustre/tests/sanity-quota.sh
+++ b/lustre/tests/sanity-quota.sh
@@ -977,11 +977,16 @@ run_test 13 "test multiple clients write block quota ==="
 check_if_quota_zero(){
         line=`$LFS quota -$1 $2 $DIR | wc -l`
 	for i in `seq 3 $line`; do
-	    for j in 3 4 6 7; do
+	    if [ $i -eq 3 ]; then
+		field="3 4 6 7"
+	    else
+		field="3 5"
+	    fi
+	    for j in $field; do
 		tmp=`$LFS quota -$1 $2 $DIR | sed -n ${i}p | 
                      awk  '{print $'"$j"'}'`
 		[ -n "$tmp" ] && [ $tmp -ne 0 ] && $LFS quota -$1 $2 $DIR && \
-		    error "quota on $1 isn't clean"
+		    error "quota on $2 isn't clean"
 	    done
 	done
 	echo "pass check_if_quota_zero"
diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c
index fa0f9e6f6f3f1805188d65dc73e9a2a0c8d009fd..bb0bb3b516195204b7d74ed8db1a89c2d8f41e93 100644
--- a/lustre/utils/lfs.c
+++ b/lustre/utils/lfs.c
@@ -1529,7 +1529,11 @@ static void print_quota_title(char *name, struct if_quotactl *qctl)
                "files", "quota", "limit", "grace");
 }
 
-static void print_quota(char *mnt, struct if_quotactl *qctl, int ost_only)
+#define GENERAL_QUOTA_INFO 1
+#define MDS_QUOTA_INFO     2
+#define OST_QUOTA_INFO     3
+
+static void print_quota(char *mnt, struct if_quotactl *qctl, int type)
 {
         time_t now;
 
@@ -1577,10 +1581,16 @@ static void print_quota(char *mnt, struct if_quotactl *qctl, int ost_only)
 
                         if (bover)
                                 diff2str(dqb->dqb_btime, timebuf, now);
-
-                        sprintf(numbuf[0], LPU64, toqb(dqb->dqb_curspace));
-                        sprintf(numbuf[1], LPU64, dqb->dqb_bsoftlimit);
-                        sprintf(numbuf[2], LPU64, dqb->dqb_bhardlimit);
+                        sprintf(numbuf[0], (dqb->dqb_valid & QIF_SPACE) ?
+                                LPU64 : "["LPU64"]", toqb(dqb->dqb_curspace));
+                        if (type == GENERAL_QUOTA_INFO)
+                                sprintf(numbuf[1], (dqb->dqb_valid & QIF_BLIMITS)
+                                        ? LPU64 : "["LPU64"]",
+                                        dqb->dqb_bsoftlimit);
+                        else
+                                sprintf(numbuf[1], "%s", "");
+                        sprintf(numbuf[2], (dqb->dqb_valid & QIF_BLIMITS)
+                                ? LPU64 : "["LPU64"]", dqb->dqb_bhardlimit);
                         printf(" %7s%c %6s %7s %7s",
                                numbuf[0], bover ? '*' : ' ', numbuf[1],
                                numbuf[2], bover > 1 ? timebuf : "");
@@ -1588,10 +1598,17 @@ static void print_quota(char *mnt, struct if_quotactl *qctl, int ost_only)
                         if (iover)
                                 diff2str(dqb->dqb_itime, timebuf, now);
 
-                        sprintf(numbuf[0], LPU64, dqb->dqb_curinodes);
-                        sprintf(numbuf[1], LPU64, dqb->dqb_isoftlimit);
-                        sprintf(numbuf[2], LPU64, dqb->dqb_ihardlimit);
-                        if (!ost_only)
+                        sprintf(numbuf[0], (dqb->dqb_valid & QIF_INODES) ?
+                                LPU64 : "["LPU64"]", dqb->dqb_curinodes);
+                       if (type == GENERAL_QUOTA_INFO)
+                                sprintf(numbuf[1], (dqb->dqb_valid & QIF_ILIMITS)
+                                        ? LPU64 : "["LPU64"]",
+                                        dqb->dqb_isoftlimit);
+                        else
+                                sprintf(numbuf[1], "%s", "");
+                        sprintf(numbuf[2], (dqb->dqb_valid & QIF_ILIMITS) ?
+                                LPU64 : "["LPU64"]", dqb->dqb_ihardlimit);
+                        if (type != OST_QUOTA_INFO)
                                 printf(" %7s%c %6s %7s %7s",
                                        numbuf[0], iover ? '*' : ' ', numbuf[1],
                                        numbuf[2], iover > 1 ? timebuf : "");
@@ -1609,7 +1626,7 @@ static void print_quota(char *mnt, struct if_quotactl *qctl, int ost_only)
         }
 }
 
-static void print_mds_quota(char *mnt, struct if_quotactl *qctl)
+static int print_mds_quota(char *mnt, struct if_quotactl *qctl)
 {
         int rc;
 
@@ -1618,24 +1635,24 @@ static void print_mds_quota(char *mnt, struct if_quotactl *qctl)
         rc = llapi_quotactl(mnt, qctl);
         if (rc) {
                 fprintf(stderr, "quotactl failed: %s\n", strerror(errno));
-                return;
+                return rc;
         }
-        qctl->qc_dqblk.dqb_valid = 0;
 
-        print_quota(obd_uuid2str(&qctl->obd_uuid), qctl, 0);
+        print_quota(obd_uuid2str(&qctl->obd_uuid), qctl, MDS_QUOTA_INFO);
+        return 0;
 }
 
-static void print_lov_quota(char *mnt, struct if_quotactl *qctl)
+static int print_lov_quota(char *mnt, struct if_quotactl *qctl)
 {
         DIR *dir;
         struct obd_uuid *uuids = NULL, *uuidp;
         int obdcount = 1024;
-        int i, rc;
+        int i, rc, rc1=0;
 
         dir = opendir(mnt);
         if (!dir) {
                 fprintf(stderr, "open %s failed: %s\n", mnt, strerror(errno));
-                return;
+                return -ENOENT;
         }
 
         uuids = (struct obd_uuid *)malloc(INIT_ALLOC_NUM_OSTS *
@@ -1668,17 +1685,21 @@ retry_get_uuids:
                 qctl->qc_dqblk.dqb_valid = 0;
                 rc = llapi_quotactl(mnt, qctl);
                 if (rc) {
+                        if (!rc1)
+                                rc1 = rc;
                         fprintf(stderr, "%s quotactl failed: %s\n",
                                 uuidp->uuid, strerror(errno));
                         continue;
                 }
 
-                print_quota((char *)uuidp->uuid, qctl, 1);
+                print_quota((char *)uuidp->uuid, qctl, OST_QUOTA_INFO);
         }
 
 out:
         closedir(dir);
-        return;
+        if (!rc)
+                rc = rc1;
+        return rc;
 }
 
 static int lfs_quota(int argc, char **argv)
@@ -1689,7 +1710,7 @@ static int lfs_quota(int argc, char **argv)
                                     .qc_type = 0x01 };
         char *obd_type = (char *)qctl.obd_type;
         char *obd_uuid = (char *)qctl.obd_uuid.uuid;
-        int rc;
+        int rc, rc1 = 0, rc2 = 0, rc3 = 0;
 
         optind = 0;
         while ((c = getopt(argc, argv, "ugto:")) != -1) {
@@ -1738,13 +1759,9 @@ static int lfs_quota(int argc, char **argv)
 
         mnt = argv[optind];
 
-        rc = llapi_quotactl(mnt, &qctl);
-        if (rc) {
-                if (*obd_type)
-                        fprintf(stderr, "%s %s ", obd_type, obd_uuid);
-                fprintf(stderr, "quota failed: %s\n", strerror(errno));
-                return rc;
-        }
+        rc1 = llapi_quotactl(mnt, &qctl);
+        if (rc1 && *obd_type)
+                fprintf(stderr, "%s %s ", obd_type, obd_uuid);
 
         if (!name)
                 rc = id2name(&name, getuid(), qctl.qc_type);
@@ -1754,13 +1771,17 @@ static int lfs_quota(int argc, char **argv)
                 name = obd_uuid;
         }
 
-        print_quota(mnt, &qctl, 0);
+        print_quota(mnt, &qctl, GENERAL_QUOTA_INFO);
 
         if (!*obd_uuid && qctl.qc_cmd != LUSTRE_Q_GETINFO) {
-                print_mds_quota(mnt, &qctl);
-                print_lov_quota(mnt, &qctl);
+                rc2 = print_mds_quota(mnt, &qctl);
+                rc3 = print_lov_quota(mnt, &qctl);
         }
 
+        if (rc1 || rc2 || rc3)
+                printf("Some errors happened when getting quota info. "
+                       "Some devices may be not working or deactivated. "
+                       "The data in \"[]\" is inaccurate.\n");
         return 0;
 }
 #endif /* HAVE_QUOTA_SUPPORT */