struct obdo *opd_oa;
ldlm_mode_t opd_mode;
int opd_lock_match;
+ int opd_timeout;
};
static int ost_prolong_locks_iter(struct ldlm_lock *lock, void *data)
return LDLM_ITER_CONTINUE;
}
+ CDEBUG(D_DLMTRACE,"refresh lock: "LPU64"/"LPU64" ("LPU64"->"LPU64")\n",
+ lock->l_resource->lr_name.name[0],
+ lock->l_resource->lr_name.name[1],
+ opd->opd_policy.l_extent.start, opd->opd_policy.l_extent.end);
/* OK. this is a possible lock the user holds doing I/O
* let's refresh eviction timer for it */
- ldlm_refresh_waiting_lock(lock);
+ ldlm_refresh_waiting_lock(lock, opd->opd_timeout);
opd->opd_lock_match = 1;
return LDLM_ITER_CONTINUE;
}
-static int ost_rw_prolong_locks(struct obd_export *exp, struct obd_ioobj *obj,
+static int ost_rw_prolong_locks(struct ptlrpc_request *req, struct obd_ioobj *obj,
struct niobuf_remote *nb, struct obdo *oa,
ldlm_mode_t mode)
{
osc_build_res_name(obj->ioo_id, obj->ioo_gr, &res_id);
opd.opd_mode = mode;
- opd.opd_exp = exp;
+ opd.opd_exp = req->rq_export;
opd.opd_policy.l_extent.start = nb[0].offset & CFS_PAGE_MASK;
opd.opd_policy.l_extent.end = (nb[nrbufs - 1].offset +
nb[nrbufs - 1].len - 1) | ~CFS_PAGE_MASK;
- CDEBUG(D_DLMTRACE,"refresh locks: "LPU64"/"LPU64" ("LPU64"->"LPU64")\n",
+ /* prolong locks for the current service time of the corresponding
+ * portal (= OST_IO_PORTAL) */
+ opd.opd_timeout = AT_OFF ? obd_timeout / 2:
+ max(at_est2timeout(at_get(&req->rq_rqbd->
+ rqbd_service->srv_at_estimate)), ldlm_timeout);
+
+ CDEBUG(D_INFO,"refresh locks: "LPU64"/"LPU64" ("LPU64"->"LPU64")\n",
res_id.name[0], res_id.name[1], opd.opd_policy.l_extent.start,
opd.opd_policy.l_extent.end);
}
opd.opd_oa = oa;
- ldlm_resource_iterate(exp->exp_obd->obd_namespace, &res_id,
+ ldlm_resource_iterate(req->rq_export->exp_obd->obd_namespace, &res_id,
ost_prolong_locks_iter, &opd);
RETURN(opd.opd_lock_match);
}
if (desc == NULL) /* XXX: check all cleanup stuff */
GOTO(out, rc = -ENOMEM);
- ost_rw_prolong_locks(exp, ioo, remote_nb, &body->oa, LCK_PW | LCK_PR);
+ ost_rw_prolong_locks(req, ioo, remote_nb, &body->oa, LCK_PW | LCK_PR);
nob = 0;
for (i = 0; i < npages; i++) {
if (exp->exp_failed)
rc = -ENOTCONN;
else {
- sptlrpc_svc_wrap_bulk(req, desc);
-
- rc = ptlrpc_start_bulk_transfer(desc);
+ rc = sptlrpc_svc_wrap_bulk(req, desc);
+ if (rc == 0)
+ rc = ptlrpc_start_bulk_transfer(desc);
}
if (rc == 0) {
ost_bulk_timeout,
desc);
rc = l_wait_event(desc->bd_waitq,
- !ptlrpc_bulk_active(desc) ||
+ !ptlrpc_server_bulk_active(desc) ||
exp->exp_failed, &lwi);
LASSERT(rc == 0 || rc == -ETIMEDOUT);
/* Wait again if we changed deadline */
GOTO(out_lock, rc = -ETIMEDOUT);
}
- ost_rw_prolong_locks(exp, ioo, remote_nb,&body->oa, LCK_PW);
+ ost_rw_prolong_locks(req, ioo, remote_nb,&body->oa, LCK_PW);
/* obd_preprw clobbers oa->valid, so save what we need */
if (body->oa.o_valid & OBD_MD_FLCKSUM) {
local_nb[i].offset & ~CFS_PAGE_MASK,
local_nb[i].len);
+ rc = sptlrpc_svc_prep_bulk(req, desc);
+ if (rc != 0)
+ GOTO(out_lock, rc);
+
/* Check if client was evicted while we were doing i/o before touching
network */
if (desc->bd_export->exp_failed)
rc = -ENOTCONN;
else
- rc = ptlrpc_start_bulk_transfer (desc);
+ rc = ptlrpc_start_bulk_transfer(desc);
if (rc == 0) {
time_t start = cfs_time_current_sec();
do {
lwi = LWI_TIMEOUT_INTERVAL(timeout, cfs_time_seconds(1),
ost_bulk_timeout, desc);
rc = l_wait_event(desc->bd_waitq,
- !ptlrpc_bulk_active(desc) ||
+ !ptlrpc_server_bulk_active(desc) ||
desc->bd_export->exp_failed, &lwi);
LASSERT(rc == 0 || rc == -ETIMEDOUT);
/* Wait again if we changed deadline */
DEBUG_REQ(D_ERROR, req, "Eviction on bulk GET");
rc = -ENOTCONN;
ptlrpc_abort_bulk(desc);
- } else if (!desc->bd_success ||
- desc->bd_nob_transferred != desc->bd_nob) {
- DEBUG_REQ(D_ERROR, req, "%s bulk GET %d(%d)",
- desc->bd_success ?
- "truncated" : "network error on",
- desc->bd_nob_transferred, desc->bd_nob);
+ } else if (!desc->bd_success) {
+ DEBUG_REQ(D_ERROR, req, "network error on bulk GET");
/* XXX should this be a different errno? */
rc = -ETIMEDOUT;
+ } else {
+ rc = sptlrpc_svc_unwrap_bulk(req, desc);
}
} else {
DEBUG_REQ(D_ERROR, req, "ptlrpc_bulk_get failed: rc %d", rc);
}
no_reply = rc != 0;
- if (rc == 0)
- sptlrpc_svc_unwrap_bulk(req, desc);
-
repbody = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
sizeof(*repbody));
memcpy(&repbody->oa, &body->oa, sizeof(repbody->oa));
static int ost_set_info(struct obd_export *exp, struct ptlrpc_request *req)
{
+ struct ost_body *body = NULL, *repbody;
+ __u32 size[2] = { sizeof(struct ptlrpc_body), sizeof(*body) };
char *key, *val = NULL;
int keylen, vallen, rc = 0;
ENTRY;
}
keylen = lustre_msg_buflen(req->rq_reqmsg, REQ_REC_OFF);
- rc = lustre_pack_reply(req, 1, NULL, NULL);
- if (rc)
- RETURN(rc);
+ if (KEY_IS(KEY_GRANT_SHRINK)) {
+ rc = lustre_pack_reply(req, 2, size, NULL);
+ if (rc)
+ RETURN(rc);
+ } else {
+ rc = lustre_pack_reply(req, 1, NULL, NULL);
+ if (rc)
+ RETURN(rc);
+ }
vallen = lustre_msg_buflen(req->rq_reqmsg, REQ_REC_OFF + 1);
- if (vallen)
- val = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 1, 0);
+ if (vallen) {
+ if (KEY_IS(KEY_GRANT_SHRINK)) {
+ body = lustre_swab_reqbuf(req, REQ_REC_OFF + 1,
+ sizeof(*body),
+ lustre_swab_ost_body);
+ if (!body)
+ RETURN(-EFAULT);
+
+ repbody = lustre_msg_buf(req->rq_repmsg,
+ REPLY_REC_OFF,
+ sizeof(*repbody));
+ memcpy(repbody, body, sizeof(*body));
+ val = (char*)repbody;
+ } else
+ val = lustre_msg_buf(req->rq_reqmsg, REQ_REC_OFF + 1,0);
+ }
if (KEY_IS(KEY_EVICT_BY_NID)) {
if (val && vallen)
obd_export_evict_by_nid(exp->exp_obd, val);
-
GOTO(out, rc = 0);
+ } else if (KEY_IS(KEY_MDS_CONN) && lustre_msg_swabbed(req->rq_reqmsg)) {
+ /* Val's are not swabbed automatically */
+ __swab32s((__u32 *)val);
}
rc = obd_set_info_async(exp, keylen, key, vallen, val, NULL);
RETURN(rc);
}
-static int filter_export_check_flavor(struct filter_obd *filter,
- struct obd_export *exp,
- struct ptlrpc_request *req)
+/*
+ * FIXME
+ * this should be done in filter_connect()/filter_reconnect(), but
+ * we can't obtain information like NID, which stored in incoming
+ * request, thus can't decide what flavor to use. so we do it here.
+ *
+ * This hack should be removed after the OST stack be rewritten, just
+ * like what we are doing in mdt_obd_connect()/mdt_obd_reconnect().
+ */
+static int ost_connect_check_sptlrpc(struct ptlrpc_request *req)
{
- int rc = 0;
-
- /* FIXME
- * this should be done in filter_connect()/filter_reconnect(), but
- * we can't obtain information like NID, which stored in incoming
- * request, thus can't decide what flavor to use. so we do it here.
- *
- * This hack should be removed after the OST stack be rewritten, just
- * like what we are doing in mdt_obd_connect()/mdt_obd_reconnect().
- */
- if (exp->exp_flvr.sf_rpc != SPTLRPC_FLVR_INVALID)
- return 0;
-
- CDEBUG(D_SEC, "from %s\n", sptlrpc_part2name(req->rq_sp_from));
- spin_lock(&exp->exp_lock);
- exp->exp_sp_peer = req->rq_sp_from;
-
- read_lock(&filter->fo_sptlrpc_lock);
- sptlrpc_rule_set_choose(&filter->fo_sptlrpc_rset, exp->exp_sp_peer,
- req->rq_peer.nid, &exp->exp_flvr);
- read_unlock(&filter->fo_sptlrpc_lock);
-
- if (exp->exp_flvr.sf_rpc != req->rq_flvr.sf_rpc) {
- CERROR("invalid rpc flavor %x, expect %x, from %s\n",
- req->rq_flvr.sf_rpc, exp->exp_flvr.sf_rpc,
- libcfs_nid2str(req->rq_peer.nid));
- exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_INVALID;
- rc = -EACCES;
- }
+ struct obd_export *exp = req->rq_export;
+ struct filter_obd *filter = &exp->exp_obd->u.filter;
+ struct sptlrpc_flavor flvr;
+ int rc = 0;
+
+ if (exp->exp_flvr.sf_rpc == SPTLRPC_FLVR_INVALID) {
+ read_lock(&filter->fo_sptlrpc_lock);
+ sptlrpc_target_choose_flavor(&filter->fo_sptlrpc_rset,
+ req->rq_sp_from,
+ req->rq_peer.nid,
+ &flvr);
+ read_unlock(&filter->fo_sptlrpc_lock);
+
+ spin_lock(&exp->exp_lock);
+
+ exp->exp_sp_peer = req->rq_sp_from;
+ exp->exp_flvr = flvr;
+
+ if (exp->exp_flvr.sf_rpc != SPTLRPC_FLVR_ANY &&
+ exp->exp_flvr.sf_rpc != req->rq_flvr.sf_rpc) {
+ CERROR("unauthorized rpc flavor %x from %s, "
+ "expect %x\n", req->rq_flvr.sf_rpc,
+ libcfs_nid2str(req->rq_peer.nid),
+ exp->exp_flvr.sf_rpc);
+ rc = -EACCES;
+ }
- spin_unlock(&exp->exp_lock);
+ spin_unlock(&exp->exp_lock);
+ } else {
+ if (exp->exp_sp_peer != req->rq_sp_from) {
+ CERROR("RPC source %s doesn't match %s\n",
+ sptlrpc_part2name(req->rq_sp_from),
+ sptlrpc_part2name(exp->exp_sp_peer));
+ rc = -EACCES;
+ } else {
+ rc = sptlrpc_target_export_check(exp, req);
+ }
+ }
return rc;
}
end = (nb[ioo->ioo_bufcnt - 1].offset +
nb[ioo->ioo_bufcnt - 1].len - 1) | ~CFS_PAGE_MASK;
+ LASSERT(lock->l_resource != NULL);
+ if (!osc_res_name_eq(ioo->ioo_id, ioo->ioo_gr,
+ &lock->l_resource->lr_name))
+ RETURN(0);
+
if (!(lock->l_granted_mode & mode))
RETURN(0);
mode = LCK_PW;
if (opc == OST_READ)
mode |= LCK_PR;
- RETURN(ost_rw_prolong_locks(req->rq_export, ioo, nb, &body->oa, mode));
+ RETURN(ost_rw_prolong_locks(req, ioo, nb, &body->oa, mode));
}
-static int ost_punch_prolong_locks(struct obd_export *exp, struct obdo *oa)
+static int ost_punch_prolong_locks(struct ptlrpc_request *req, struct obdo *oa)
{
struct ldlm_res_id res_id = { .name = { oa->o_id } };
struct ost_prolong_data opd = { 0 };
end = start + oa->o_blocks;
opd.opd_mode = LCK_PW;
- opd.opd_exp = exp;
+ opd.opd_exp = req->rq_export;
opd.opd_policy.l_extent.start = start & CFS_PAGE_MASK;
if (oa->o_blocks == OBD_OBJECT_EOF || end < start)
opd.opd_policy.l_extent.end = OBD_OBJECT_EOF;
else
opd.opd_policy.l_extent.end = end | ~CFS_PAGE_MASK;
+ /* prolong locks for the current service time of the corresponding
+ * portal (= OST_IO_PORTAL) */
+ opd.opd_timeout = AT_OFF ? obd_timeout / 2:
+ max(at_est2timeout(at_get(&req->rq_rqbd->
+ rqbd_service->srv_at_estimate)), ldlm_timeout);
+
CDEBUG(D_DLMTRACE,"refresh locks: "LPU64"/"LPU64" ("LPU64"->"LPU64")\n",
res_id.name[0], res_id.name[1], opd.opd_policy.l_extent.start,
opd.opd_policy.l_extent.end);
opd.opd_oa = oa;
- ldlm_resource_iterate(exp->exp_obd->obd_namespace, &res_id,
+ ldlm_resource_iterate(req->rq_export->exp_obd->obd_namespace, &res_id,
ost_prolong_locks_iter, &opd);
RETURN(opd.opd_lock_match);
}
LASSERT(!(body->oa.o_valid & OBD_MD_FLFLAGS) ||
!(body->oa.o_flags & OBD_FL_TRUNCLOCK));
- RETURN(ost_punch_prolong_locks(req->rq_export, &body->oa));
+ RETURN(ost_punch_prolong_locks(req, &body->oa));
}
struct ptlrpc_hpreq_ops ost_hpreq_rw = {
RETURN(0);
if (!rc) {
rc = ost_init_sec_level(req);
- if (!rc) {
- struct obd_export *exp = req->rq_export;
-
- obd = exp->exp_obd;
- rc = filter_export_check_flavor(&obd->u.filter,
- exp, req);
- }
+ if (!rc)
+ rc = ost_connect_check_sptlrpc(req);
}
break;
}