diff --git a/lustre/ChangeLog b/lustre/ChangeLog
index dbf2052856843b34913516d9829724f8ddf68aaa..2813bb5d0a0bc3005aa5bbd52b9bd37ca3ba2fdc 100644
--- a/lustre/ChangeLog
+++ b/lustre/ChangeLog
@@ -159,6 +159,15 @@ Details    : When osc reconnect ost, OST(filter) should check whether it
 	     of "new granted" space, because client will call osc_init_grant
 	     to update the client grant space info.
 
+Severity   : normal
+Frequency  : when client reconnect to OST 
+Bugzilla   : 11662
+Description: Grant Leak when osc do resend and replay bulk write
+Details	   : When osc reconnect to OST, OST(filter)should clear grant info of
+	     bulk write request, because the grant info while be sync between
+	     OSC and OST when reconnect, and we should ignore the grant info
+	     these of resend/replay write req.
+
 Severity   : normal
 Frequency  : when client is evicted 
 Bugzilla   : 12371
diff --git a/lustre/obdfilter/filter_io.c b/lustre/obdfilter/filter_io.c
index 3948593da05c3dff56fe7f6eb00cc09b7462f3cc..2f486a2762cc1d94571631e1cfda606a5d133cd5 100644
--- a/lustre/obdfilter/filter_io.c
+++ b/lustre/obdfilter/filter_io.c
@@ -258,8 +258,10 @@ long filter_grant(struct obd_export *exp, obd_size current_grant,
                 }
         }
 
-        CDEBUG(D_CACHE,"%s: cli %s/%p wants: "LPU64" granting: "LPU64"\n",
-               obd->obd_name, exp->exp_client_uuid.uuid, exp, want, grant);
+        CDEBUG(D_CACHE,
+               "%s: cli %s/%p wants: "LPU64" current grant "LPU64 
+               " granting: "LPU64"\n", obd->obd_name, exp->exp_client_uuid.uuid,
+               exp, want, current_grant, grant);
         CDEBUG(D_CACHE,
                "%s: cli %s/%p tot cached:"LPU64" granted:"LPU64
                " num_exports: %d\n", obd->obd_name, exp->exp_client_uuid.uuid,
@@ -386,9 +388,9 @@ static int filter_preprw_read(int cmd, struct obd_export *exp, struct obdo *oa,
  * right on through.
  *
  * Caller must hold obd_osfs_lock. */
-static int filter_grant_check(struct obd_export *exp, int objcount,
-                              struct fsfilt_objinfo *fso, int niocount,
-                              struct niobuf_remote *rnb,
+static int filter_grant_check(struct obd_export *exp, struct obdo *oa, 
+                              int objcount, struct fsfilt_objinfo *fso, 
+                              int niocount, struct niobuf_remote *rnb,
                               struct niobuf_local *lnb, obd_size *left,
                               struct inode *inode)
 {
@@ -410,7 +412,8 @@ static int filter_grant_check(struct obd_export *exp, int objcount,
                         if (tmp)
                                 bytes += blocksize - tmp;
 
-                        if (rnb[n].flags & OBD_BRW_FROM_GRANT) {
+                        if ((rnb[n].flags & OBD_BRW_FROM_GRANT) &&
+                            (oa->o_valid & OBD_MD_FLGRANT)) {
                                 if (fed->fed_grant < used + bytes) {
                                         CDEBUG(D_CACHE,
                                                "%s: cli %s/%p claims %ld+%d "
@@ -552,26 +555,26 @@ static int filter_preprw_write(int cmd, struct obd_export *exp, struct obdo *oa,
          * already exist so we can store the reservation handle there. */
         fmd = filter_fmd_find(exp, obj->ioo_id, obj->ioo_gr);
 
+        LASSERT(oa != NULL);
         spin_lock(&exp->exp_obd->obd_osfs_lock);
-        if (oa) {
-                filter_grant_incoming(exp, oa);
-                if (fmd && fmd->fmd_mactime_xid > oti->oti_xid)
-                        oa->o_valid &= ~(OBD_MD_FLMTIME | OBD_MD_FLCTIME |
-                                         OBD_MD_FLATIME);
-                else
-                        obdo_to_inode(dentry->d_inode, oa, OBD_MD_FLATIME |
-                                      OBD_MD_FLMTIME | OBD_MD_FLCTIME);
-        }
+ 
+        filter_grant_incoming(exp, oa);
+        if (fmd && fmd->fmd_mactime_xid > oti->oti_xid)
+                oa->o_valid &= ~(OBD_MD_FLMTIME | OBD_MD_FLCTIME |
+                                 OBD_MD_FLATIME);
+        else
+                obdo_to_inode(dentry->d_inode, oa, OBD_MD_FLATIME |
+                              OBD_MD_FLMTIME | OBD_MD_FLCTIME);
         cleanup_phase = 3;
 
         left = filter_grant_space_left(exp);
 
-        rc = filter_grant_check(exp, objcount, &fso, niocount, nb, res,
+        rc = filter_grant_check(exp, oa, objcount, &fso, niocount, nb, res,
                                 &left, dentry->d_inode);
 
         /* do not zero out oa->o_valid as it is used in filter_commitrw_write()
          * for setting UID/GID and fid EA in first write time. */
-        if (oa && oa->o_valid & OBD_MD_FLGRANT) {
+        if (oa->o_valid & OBD_MD_FLGRANT) {
                 oa->o_grant = filter_grant(exp,oa->o_grant,oa->o_undirty,left);
                 oa->o_valid |= OBD_MD_FLGRANT;
         }
diff --git a/lustre/ost/ost_handler.c b/lustre/ost/ost_handler.c
index 19923939871af0e65c31f66a565f74b1a4d5f2b1..78672c9d29e1b6651b2944668f91388e3bf1dc5b 100644
--- a/lustre/ost/ost_handler.c
+++ b/lustre/ost/ost_handler.c
@@ -975,6 +975,14 @@ static int ost_brw_write(struct ptlrpc_request *req, struct obd_trans_info *oti)
         /* obd_preprw clobbers oa->valid, so save what we need */
         client_cksum = body->oa.o_valid & OBD_MD_FLCKSUM ? body->oa.o_cksum : 0;
 
+        /* Because we already sync grant info with client when reconnect,
+         * grant info will be cleared for resent req, then fed_grant and 
+         * total_grant will not be modified in following preprw_write*/ 
+        if (lustre_msg_get_flags(req->rq_reqmsg) & (MSG_RESENT | MSG_REPLAY)) {
+                DEBUG_REQ(D_CACHE, req, "clear resent/replay req grant info\n");
+                body->oa.o_valid &= ~OBD_MD_FLGRANT;
+        }
+
         rc = obd_preprw(OBD_BRW_WRITE, req->rq_export, &body->oa, objcount,
                         ioo, npages, pp_rnb, local_nb, oti);
         if (rc != 0)