Whamcloud - gitweb
New tag 2.7.66
[fs/lustre-release.git] / lustre / lod / lod_qos.c
index 24aff5a..cd7b7f5 100644 (file)
 
 #include <asm/div64.h>
 #include <libcfs/libcfs.h>
-#include <obd_class.h>
 #include <lustre/lustre_idl.h>
+#include <lustre_swab.h>
+#include <obd_class.h>
+
 #include "lod_internal.h"
 
 /*
@@ -197,10 +199,6 @@ static int lod_statfs_and_check(const struct lu_env *env, struct lod_device *d,
        LASSERT(ost);
 
        rc = dt_statfs(env, ost->ltd_ost, sfs);
-
-       if (rc == -ENOSPC)
-               RETURN(rc);
-
        if (rc && rc != -ENOTCONN)
                CERROR("%s: statfs: rc = %d\n", lod2obd(d)->obd_name, rc);
 
@@ -214,6 +212,9 @@ static int lod_statfs_and_check(const struct lu_env *env, struct lod_device *d,
                spin_lock(&d->lod_desc_lock);
                if (ost->ltd_active) {
                        ost->ltd_active = 0;
+                       if (rc == -ENOTCONN)
+                               ost->ltd_connecting = 1;
+
                        LASSERT(d->lod_desc.ld_active_tgt_count > 0);
                        d->lod_desc.ld_active_tgt_count--;
                        d->lod_qos.lq_dirty = 1;
@@ -230,6 +231,7 @@ static int lod_statfs_and_check(const struct lu_env *env, struct lod_device *d,
                spin_lock(&d->lod_desc_lock);
                if (ost->ltd_active == 0) {
                        ost->ltd_active = 1;
+                       ost->ltd_connecting = 0;
                        d->lod_desc.ld_active_tgt_count++;
                        d->lod_qos.lq_dirty = 1;
                        d->lod_qos.lq_rr.lqr_dirty = 1;
@@ -740,6 +742,30 @@ static int min_stripe_count(__u32 stripe_cnt, int flags)
 #define LOV_CREATE_RESEED_MIN  2000
 
 /**
+ * Check if an OST is full.
+ *
+ * Check whether an OST should be considered full based
+ * on the given statfs data.
+ *
+ * \param[in] msfs     statfs data
+ *
+ * \retval false       not full
+ * \retval true                full
+ */
+static int inline lod_qos_dev_is_full(struct obd_statfs *msfs)
+{
+       __u64 used;
+       int   bs = msfs->os_bsize;
+
+       LASSERT(((bs - 1) & bs) == 0);
+
+       /* the minimum of 0.1% used blocks and 1GB bytes. */
+       used = min_t(__u64, (msfs->os_blocks - msfs->os_bfree) >> 10,
+                       1 << (31 - ffs(bs)));
+       return (msfs->os_bavail < used);
+}
+
+/**
  * Initialize temporary OST-in-use array.
  *
  * Allocate or extend the array used to mark targets already assigned to a new
@@ -830,6 +856,14 @@ static int lod_check_and_reserve_ost(const struct lu_env *env,
        }
 
        /*
+        * skip full devices
+        */
+       if (lod_qos_dev_is_full(sfs)) {
+               QOS_DEBUG("#%d is full\n", ost_idx);
+               goto out_return;
+       }
+
+       /*
         * We expect number of precreated objects in f_ffree at
         * the first iteration, skip OSPs with no objects ready
         */
@@ -909,6 +943,7 @@ static int lod_alloc_rr(const struct lu_env *env, struct lod_object *lo,
        int                rc;
        __u32              ost_start_idx_temp;
        int                speed = 0;
+       int                ost_connecting = 0;
        __u32              stripe_idx = 0;
        __u32              stripe_cnt = lo->ldo_stripenr;
        __u32              stripe_cnt_min = min_stripe_count(stripe_cnt, flags);
@@ -984,11 +1019,16 @@ repeat_find:
                rc = lod_check_and_reserve_ost(env, m, sfs, ost_idx, speed,
                                               &stripe_idx, stripe, th);
                spin_lock(&lqr->lqr_alloc);
+
+               if (rc != 0 && OST_TGT(m, ost_idx)->ltd_connecting)
+                       ost_connecting = 1;
        }
        if ((speed < 2) && (stripe_idx < stripe_cnt_min)) {
                /* Try again, allowing slower OSCs */
                speed++;
                lqr->lqr_start_idx = ost_start_idx_temp;
+
+               ost_connecting = 0;
                goto repeat_find;
        }
 
@@ -1001,7 +1041,10 @@ repeat_find:
                rc = 0;
        } else {
                /* nobody provided us with a single object */
-               rc = -ENOSPC;
+               if (ost_connecting)
+                       rc = -EINPROGRESS;
+               else
+                       rc = -ENOSPC;
        }
 
 out:
@@ -1395,6 +1438,12 @@ static int lod_alloc_qos(const struct lu_env *env, struct lod_object *lo,
                        continue;
                }
 
+               /*
+                * skip full devices
+                */
+               if (lod_qos_dev_is_full(sfs))
+                       continue;
+
                /* Fail Check before osc_precreate() is called
                   so we can only 'fail' single OSC. */
                if (OBD_FAIL_CHECK(OBD_FAIL_MDS_OSC_PRECREATE) &&