Whamcloud - gitweb
LU-657 obdfilter: commit pending journals if -ENOSPC
authorHongchao Zhang <hongchao.zhang@whamcloud.com>
Tue, 7 Aug 2012 00:43:11 +0000 (08:43 +0800)
committerOleg Drokin <green@whamcloud.com>
Thu, 9 Aug 2012 13:39:46 +0000 (09:39 -0400)
in filter_preprw_write, if there is no enough space for this
write operation, then commit the pending journals to get some
more disk space and retry it.

Signed-off-by: Hongchao Zhang <hongchao.zhang@whamcloud.com>
Change-Id: I46106b26443bb203eee6f01a0795b47be09170a6
Reviewed-on: http://review.whamcloud.com/3446
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Johann Lombardi <johann@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/obdfilter/filter_io.c

index 701cdfd..df261ab 100644 (file)
@@ -657,6 +657,7 @@ static int filter_preprw_write(int cmd, struct obd_export *exp, struct obdo *oa,
         obd_size left;
         unsigned long now = jiffies, timediff;
         int rc = 0, i, tot_bytes = 0, cleanup_phase = 0, localreq = 0;
+       int retries = 0;
         ENTRY;
         LASSERT(objcount == 1);
         LASSERT(obj->ioo_bufcnt > 0);
@@ -744,38 +745,55 @@ 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_seq);
 
-        LASSERT(oa != NULL);
-        cfs_spin_lock(&obd->obd_osfs_lock);
-        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);
-
-        fso.fso_dentry = dentry;
-        fso.fso_bufcnt = *npages;
-
-        rc = filter_grant_check(exp, oa, objcount, &fso, *npages, 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 OBD_FL_SHRINK_GRANT is set, the client just returned us some grant
-         * so no sense in allocating it some more. We either return the grant
-         * back to the client if we have plenty of space or we don't return
-         * anything if we are short. This was decided in filter_grant_incoming*/
-        if ((oa->o_valid & OBD_MD_FLGRANT) &&
-            (!(oa->o_valid & OBD_MD_FLFLAGS) ||
-             !(oa->o_flags & OBD_FL_SHRINK_GRANT)))
-                oa->o_grant = filter_grant(exp, oa->o_grant, oa->o_undirty,
-                                           left, 1);
-
-        cfs_spin_unlock(&obd->obd_osfs_lock);
+       LASSERT(oa != NULL);
+retry:
+       cfs_spin_lock(&obd->obd_osfs_lock);
+       if (retries == 0)
+               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);
+
+       fso.fso_dentry = dentry;
+       fso.fso_bufcnt = *npages;
+
+       rc = filter_grant_check(exp, oa, objcount, &fso, *npages, 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 OBD_FL_SHRINK_GRANT is set, the client just returned us some grant
+        * so no sense in allocating it some more. We either return the grant
+        * back to the client if we have plenty of space or we don't return
+        * anything if we are short. This was decided in filter_grant_incoming*/
+       if ((retries == 0) && (oa->o_valid & OBD_MD_FLGRANT) &&
+           (!(oa->o_valid & OBD_MD_FLFLAGS) ||
+            !(oa->o_flags & OBD_FL_SHRINK_GRANT)))
+               oa->o_grant = filter_grant(exp, oa->o_grant, oa->o_undirty,
+                                          left, 1);
+
+       cfs_spin_unlock(&obd->obd_osfs_lock);
+
+       if (rc == -ENOSPC && retries == 0) {
+               void *handle = NULL;
+
+               CDEBUG(D_INODE, "retry after commit pending journals");
+
+               retries = 1;
+               handle = fsfilt_start_log(obd, dentry->d_inode,
+                                         FSFILT_OP_SETATTR, NULL, 1);
+               if (handle != NULL) {
+                       fsfilt_commit_wait(obd, dentry->d_inode, handle);
+                       goto retry;
+               }
+       }
+
         filter_fmd_put(exp, fmd);
 
         OBD_FAIL_TIMEOUT(OBD_FAIL_OST_BRW_PAUSE_BULK2, (obd_timeout + 1) / 4);