* GPL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*/
/*
/* NULL watched means all osc's in the lov (only for syncs) */
/* sync event should be send lov idx as data */
struct lov_obd *lov = &obd->u.lov;
- struct obd_device *tgt_obd;
- int i;
+ int i, is_sync;
+
+ data = &i;
+ is_sync = (ev == OBD_NOTIFY_SYNC) ||
+ (ev == OBD_NOTIFY_SYNC_NONBLOCK);
+
obd_getref(obd);
for (i = 0; i < lov->desc.ld_tgt_count; i++) {
+ if (!lov->lov_tgts[i])
+ continue;
+
/* don't send sync event if target not
* connected/activated */
- if (!lov->lov_tgts[i] ||
- !lov->lov_tgts[i]->ltd_active)
- continue;
-
- if ((ev == OBD_NOTIFY_SYNC) ||
- (ev == OBD_NOTIFY_SYNC_NONBLOCK))
- data = &i;
-
- tgt_obd = class_exp2obd(lov->lov_tgts[i]->ltd_exp);
+ if (is_sync && !lov->lov_tgts[i]->ltd_active)
+ continue;
- rc = obd_notify_observer(obd, tgt_obd, ev, data);
+ rc = obd_notify_observer(obd, lov->lov_tgts[i]->ltd_obd,
+ ev, data);
if (rc) {
CERROR("%s: notify %s of %s failed %d\n",
obd->obd_name,
obd->obd_observer->obd_name,
- tgt_obd->obd_name, rc);
- break;
+ lov->lov_tgts[i]->ltd_obd->obd_name,
+ rc);
}
}
obd_putref(obd);
RETURN(rc);
}
-int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
- __u32 index, int gen, int active)
+static int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp,
+ __u32 index, int gen, int active)
{
struct lov_obd *lov = &obd->u.lov;
struct lov_tgt_desc *tgt;
RETURN(rc);
}
- memset(tgt, 0, sizeof(*tgt));
tgt->ltd_uuid = *uuidp;
tgt->ltd_obd = tgt_obd;
/* XXX - add a sanity check on the generation number. */
CDEBUG(D_CONFIG, "idx=%d ltd_gen=%d ld_tgt_count=%d\n",
index, tgt->ltd_gen, lov->desc.ld_tgt_count);
+ rc = obd_notify(obd, tgt_obd, OBD_NOTIFY_CREATE, &index);
+
if (lov->lov_connects == 0) {
/* lov_connect hasn't been called yet. We'll do the
lov_connect_obd on this target when that fn first runs,
lov->lov_pools_hash_body = cfs_hash_create("POOLS", HASH_POOLS_CUR_BITS,
HASH_POOLS_MAX_BITS,
- &pool_hash_operations, CFS_HASH_REHASH);
+ HASH_POOLS_BKT_BITS, 0,
+ CFS_HASH_MIN_THETA,
+ CFS_HASH_MAX_THETA,
+ &pool_hash_operations,
+ CFS_HASH_DEFAULT);
CFS_INIT_LIST_HEAD(&lov->lov_pool_list);
lov->lov_pool_count = 0;
rc = lov_ost_pool_init(&lov->lov_packed, 0);
if (rc)
- RETURN(rc);
+ GOTO(out_free_statfs, rc);
rc = lov_ost_pool_init(&lov->lov_qos.lq_rr.lqr_pool, 0);
- if (rc) {
- lov_ost_pool_free(&lov->lov_packed);
- RETURN(rc);
- }
+ if (rc)
+ GOTO(out_free_lov_packed, rc);
lprocfs_lov_init_vars(&lvars);
lprocfs_obd_setup(obd, lvars.obd_vars);
NULL, NULL);
RETURN(0);
+
+out_free_lov_packed:
+ lov_ost_pool_free(&lov->lov_packed);
+out_free_statfs:
+ OBD_FREE_PTR(lov->lov_qos.lq_statfs_data);
+ return rc;
}
static int lov_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
* later in alloc_qos(), we will wait for those rpcs to complete if
* the osfs age is older than 2 * qos_maxage */
qos_statfs_update(exp->exp_obd,
- cfs_time_shift_64(-lov->desc.ld_qos_maxage) + CFS_HZ,
+ cfs_time_shift_64(-lov->desc.ld_qos_maxage +
+ OBD_STATFS_CACHE_SECONDS),
0);
rc = lov_prep_create_set(exp, &oinfo, ea, src_oa, oti, &set);
RETURN(rc);
}
+static int lov_sync_fs(struct obd_device *obd, struct obd_info *dummy,
+ int wait)
+{
+ struct lov_obd *lov;
+ struct obd_info oinfo = { { { 0 } } };
+ struct lov_request *req;
+ struct lov_request_set *set;
+ struct l_wait_info lwi = { 0 };
+ cfs_list_t *pos;
+ int rc = 0;
+ ENTRY;
+
+ lov = &obd->u.lov;
+ rc = lov_prep_sync_fs_set(obd, &oinfo, &set);
+ if (rc)
+ RETURN(rc);
+
+ cfs_list_for_each(pos, &set->set_list) {
+ struct obd_device *osc_obd;
+ req = cfs_list_entry(pos, struct lov_request, rq_link);
+
+ osc_obd = class_exp2obd(lov->lov_tgts[req->rq_idx]->ltd_exp);
+ rc = obd_sync_fs(osc_obd, &req->rq_oi, wait);
+ if (rc)
+ break;
+ }
+ /* if wait then check if all sync_fs IO's are done */
+ if (wait)
+ l_wait_event(set->set_waitq, lov_finished_set(set), &lwi);
+
+ rc = lov_fini_sync_fs_set(set);
+ RETURN(rc);
+}
+
static int lov_brw_check(struct lov_obd *lov, struct obd_info *lov_oinfo,
obd_count oa_bufs, struct brw_page *pga)
{
static int lov_cancel_unused(struct obd_export *exp,
struct lov_stripe_md *lsm,
- int flags, void *opaque)
+ ldlm_cancel_flags_t flags, void *opaque)
{
struct lov_obd *lov;
int rc = 0, i;
/* got statfs data */
rc = obd_statfs(osc_obd, &stat_buf,
- cfs_time_current_64() - CFS_HZ, 0);
+ cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
+ 0);
if (rc)
RETURN(rc);
if (cfs_copy_to_user(data->ioc_pbuf1, &stat_buf,
} else if (KEY_IS(KEY_FIEMAP)) {
rc = lov_fiemap(lov, keylen, key, vallen, val, lsm);
GOTO(out, rc);
+ } else if (KEY_IS(KEY_CONNECT_FLAG)) {
+ struct lov_tgt_desc *tgt;
+ __u64 ost_idx = *((__u64*)val);
+
+ LASSERT(*vallen == sizeof(__u64));
+ LASSERT(ost_idx < lov->desc.ld_tgt_count);
+ tgt = lov->lov_tgts[ost_idx];
+
+ if (!tgt || !tgt->ltd_exp)
+ GOTO(out, rc = -ESRCH);
+
+ *((__u64*)val) = tgt->ltd_exp->exp_connect_flags;
+ GOTO(out, rc = 0);
}
rc = -EINVAL;
.o_pool_del = lov_pool_del,
.o_getref = lov_getref,
.o_putref = lov_putref,
+ .o_sync_fs = lov_sync_fs,
};
static quota_interface_t *quota_interface;