Whamcloud - gitweb
LU-3469 osp: osp_sync() to flush pending changes synchronously
[fs/lustre-release.git] / lustre / osp / osp_dev.c
index 27e3011..45aff9f 100644 (file)
@@ -471,15 +471,95 @@ static int osp_statfs(const struct lu_env *env, struct dt_device *dev,
        RETURN(0);
 }
 
+static int osp_sync_timeout(void *data)
+{
+       return 1;
+}
+
 static int osp_sync(const struct lu_env *env, struct dt_device *dev)
 {
+       struct osp_device *d = dt2osp_dev(dev);
+       cfs_time_t         expire;
+       struct l_wait_info lwi = { 0 };
+       unsigned long      id, old;
+       int                rc = 0;
+       unsigned long      start = cfs_time_current();
        ENTRY;
 
-       /*
-        * XXX: wake up sync thread, command it to start flushing asap?
-        */
+       if (unlikely(d->opd_imp_active == 0))
+               RETURN(-ENOTCONN);
 
-       RETURN(0);
+       id = d->opd_syn_last_used_id;
+
+       CDEBUG(D_OTHER, "%s: id: used %lu, processed %lu\n",
+              d->opd_obd->obd_name, id, d->opd_syn_last_processed_id);
+
+       /* wait till all-in-line are processed */
+       while (d->opd_syn_last_processed_id < id) {
+
+               old = d->opd_syn_last_processed_id;
+
+               /* make sure the connection is fine */
+               expire = cfs_time_shift(obd_timeout);
+               lwi = LWI_TIMEOUT(expire - cfs_time_current(),
+                                 osp_sync_timeout, d);
+               l_wait_event(d->opd_syn_barrier_waitq,
+                            d->opd_syn_last_processed_id >= id,
+                            &lwi);
+
+               if (d->opd_syn_last_processed_id >= id)
+                       break;
+
+               if (d->opd_syn_last_processed_id != old) {
+                       /* some progress have been made,
+                        * keep trying... */
+                       continue;
+               }
+
+               /* no changes and expired, something is wrong */
+               GOTO(out, rc = -ETIMEDOUT);
+       }
+
+       /* block new processing (barrier>0 - few callers are possible */
+       atomic_inc(&d->opd_syn_barrier);
+
+       CDEBUG(D_OTHER, "%s: %u in flight\n", d->opd_obd->obd_name,
+              d->opd_syn_rpc_in_flight);
+
+       /* wait till all-in-flight are replied, so executed by the target */
+       /* XXX: this is used by LFSCK at the moment, which doesn't require
+        *      all the changes to be committed, but in general it'd be
+        *      better to wait till commit */
+       while (d->opd_syn_rpc_in_flight > 0) {
+
+               old = d->opd_syn_rpc_in_flight;
+
+               expire = cfs_time_shift(obd_timeout);
+               lwi = LWI_TIMEOUT(expire - cfs_time_current(),
+                                 osp_sync_timeout, d);
+               l_wait_event(d->opd_syn_barrier_waitq,
+                               d->opd_syn_rpc_in_flight == 0, &lwi);
+
+               if (d->opd_syn_rpc_in_flight == 0)
+                       break;
+
+               if (d->opd_syn_rpc_in_flight != old) {
+                       /* some progress have been made */
+                       continue;
+               }
+
+               /* no changes and expired, something is wrong */
+               GOTO(out, rc = -ETIMEDOUT);
+       }
+
+       CDEBUG(D_OTHER, "%s: done in %lu\n", d->opd_obd->obd_name,
+              cfs_time_current() - start);
+out:
+       /* resume normal processing (barrier=0) */
+       atomic_dec(&d->opd_syn_barrier);
+       __osp_sync_check_for_work(d);
+
+       RETURN(rc);
 }
 
 const struct dt_device_operations osp_dt_ops = {