*/
static int lod_statfs_and_check(const struct lu_env *env, struct lod_device *d,
struct lu_tgt_descs *ltd,
- struct lu_tgt_desc *tgt)
+ struct lu_tgt_desc *tgt, __u64 reserve)
{
+ struct obd_statfs_info info = { 0 };
struct lov_desc *desc = <d->ltd_lov_desc;
int rc;
ENTRY;
LASSERT(d);
LASSERT(tgt);
- rc = dt_statfs(env, tgt->ltd_tgt, &tgt->ltd_statfs);
+ info.os_enable_pre = 1;
+ rc = dt_statfs_info(env, tgt->ltd_tgt, &tgt->ltd_statfs, &info);
if (rc && rc != -ENOTCONN)
CERROR("%s: statfs: rc = %d\n", lod2obd(d)->obd_name, rc);
return rc;
}
+ if (reserve &&
+ (reserve + (info.os_reserved_mb_low << 20) >
+ tgt->ltd_statfs.os_bavail * tgt->ltd_statfs.os_bsize))
+ return -ENOSPC;
+
/* check whether device has changed state (active, inactive) */
if (rc != 0 && tgt->ltd_active) {
/* turned inactive? */
ltd_foreach_tgt(ltd, tgt) {
avail = tgt->ltd_statfs.os_bavail;
- if (lod_statfs_and_check(env, lod, ltd, tgt))
+ if (lod_statfs_and_check(env, lod, ltd, tgt, 0))
continue;
if (tgt->ltd_statfs.os_bavail != avail)
struct dt_object **stripe,
__u32 *ost_indices,
struct thandle *th,
- bool *overstriped)
+ bool *overstriped,
+ __u64 reserve)
{
struct lod_device *lod = lu2lod_dev(lo->ldo_obj.do_lu.lo_dev);
struct lod_avoid_guide *lag = &lod_env_info(env)->lti_avoid;
ENTRY;
- rc = lod_statfs_and_check(env, lod, &lod->lod_ost_descs, ost);
+ rc = lod_statfs_and_check(env, lod, &lod->lod_ost_descs, ost, reserve);
if (rc)
RETURN(rc);
*/
static int lod_ost_alloc_rr(const struct lu_env *env, struct lod_object *lo,
struct dt_object **stripe, __u32 *ost_indices,
- int flags, struct thandle *th, int comp_idx)
+ int flags, struct thandle *th, int comp_idx,
+ __u64 reserve)
{
struct lod_layout_component *lod_comp;
struct lod_device *m = lu2lod_dev(lo->ldo_obj.do_lu.lo_dev);
spin_unlock(&lqr->lqr_alloc);
rc = lod_check_and_reserve_ost(env, lo, lod_comp, ost_idx,
speed, &stripe_idx, stripe,
- ost_indices, th, &overstriped);
+ ost_indices, th, &overstriped,
+ reserve);
spin_lock(&lqr->lqr_alloc);
if (rc != 0 && OST_TGT(m, ost_idx)->ltd_connecting)
*/
static int lod_alloc_ost_list(const struct lu_env *env, struct lod_object *lo,
struct dt_object **stripe, __u32 *ost_indices,
- struct thandle *th, int comp_idx)
+ struct thandle *th, int comp_idx, __u64 reserve)
{
struct lod_layout_component *lod_comp;
struct lod_device *m = lu2lod_dev(lo->ldo_obj.do_lu.lo_dev);
}
rc = lod_statfs_and_check(env, m, &m->lod_ost_descs,
- LTD_TGT(&m->lod_ost_descs, ost_idx));
+ LTD_TGT(&m->lod_ost_descs, ost_idx),
+ reserve);
if (rc < 0) /* this OSP doesn't feel well */
break;
static int lod_ost_alloc_specific(const struct lu_env *env,
struct lod_object *lo,
struct dt_object **stripe, __u32 *ost_indices,
- int flags, struct thandle *th, int comp_idx)
+ int flags, struct thandle *th, int comp_idx,
+ __u64 reserve)
{
struct lod_layout_component *lod_comp;
struct lod_device *m = lu2lod_dev(lo->ldo_obj.do_lu.lo_dev);
* start OST, then it can be skipped, otherwise skip it only
* if it is inactive/recovering/out-of-space." */
- rc = lod_statfs_and_check(env, m, &m->lod_ost_descs, tgt);
+ rc = lod_statfs_and_check(env, m, &m->lod_ost_descs,
+ tgt, reserve);
if (rc) {
/* this OSP doesn't feel well */
continue;
*/
static int lod_ost_alloc_qos(const struct lu_env *env, struct lod_object *lo,
struct dt_object **stripe, __u32 *ost_indices,
- int flags, struct thandle *th, int comp_idx)
+ int flags, struct thandle *th, int comp_idx,
+ __u64 reserve)
{
struct lod_layout_component *lod_comp;
struct lod_device *lod = lu2lod_dev(lo->ldo_obj.do_lu.lo_dev);
ost = OST_TGT(lod, osts->op_array[i]);
ost->ltd_qos.ltq_usable = 0;
- rc = lod_statfs_and_check(env, lod, &lod->lod_ost_descs, ost);
+ rc = lod_statfs_and_check(env, lod, &lod->lod_ost_descs,
+ ost, reserve);
if (rc) {
/* this OSP doesn't feel well */
continue;
*/
int lod_qos_prep_create(const struct lu_env *env, struct lod_object *lo,
struct lu_attr *attr, struct thandle *th,
- int comp_idx)
+ int comp_idx, __u64 reserve)
{
struct lod_layout_component *lod_comp;
struct lod_device *d = lu2lod_dev(lod2lu_obj(lo)->lo_dev);
if (!ost_indices)
GOTO(out, rc = -ENOMEM);
+repeat:
lod_getref(&d->lod_ost_descs);
/* XXX: support for non-0 files w/o objects */
CDEBUG(D_OTHER, "tgt_count %d stripe_count %d\n",
if (lod_comp->llc_ostlist.op_array &&
lod_comp->llc_ostlist.op_count) {
rc = lod_alloc_ost_list(env, lo, stripe, ost_indices,
- th, comp_idx);
+ th, comp_idx, reserve);
} else if (lod_comp->llc_stripe_offset == LOV_OFFSET_DEFAULT) {
/**
* collect OSTs and OSSs used in other mirrors whose
lod_collect_avoidance(lo, lag, comp_idx);
rc = lod_ost_alloc_qos(env, lo, stripe, ost_indices,
- flag, th, comp_idx);
+ flag, th, comp_idx, reserve);
if (rc == -EAGAIN)
rc = lod_ost_alloc_rr(env, lo, stripe,
ost_indices, flag, th,
- comp_idx);
+ comp_idx, reserve);
} else {
rc = lod_ost_alloc_specific(env, lo, stripe,
ost_indices, flag, th,
- comp_idx);
+ comp_idx, reserve);
}
put_ldts:
lod_putref(d, &d->lod_ost_descs);
for (i = 0; i < stripe_len; i++)
if (stripe[i] != NULL)
dt_object_put(env, stripe[i]);
+
+ /* In case there is no space on any OST, let's ignore
+ * the @reserve space to avoid an error at the init
+ * time, probably the actual IO will be less than the
+ * given @reserve space (aka extension_size). */
+ if (reserve) {
+ reserve = 0;
+ goto repeat;
+ }
lod_comp->llc_stripe_count = 0;
} else {
lod_comp->llc_stripe = stripe;
extent = &lod_comp->llc_extent;
QOS_DEBUG("comp[%d] %lld "DEXT"\n", i, size, PEXT(extent));
if (!lo->ldo_is_composite || size >= extent->e_start) {
- rc = lod_qos_prep_create(env, lo, attr, th, i);
+ rc = lod_qos_prep_create(env, lo, attr, th, i, 0);
if (rc)
break;
}