int osc_object_is_contended(struct osc_object *obj)
{
struct osc_device *dev = lu2osc_dev(obj->oo_cl.co_lu.lo_dev);
int osc_contention_time = dev->od_contention_time;
unsigned long cur_time = cfs_time_current();
unsigned long retry_time;
if (OBD_FAIL_CHECK(OBD_FAIL_OSC_OBJECT_CONTENTION))
return 1;
if (!obj->oo_contended)
return 0;
/*
* I like copy-paste. the code is copied from
* ll_file_is_contended.
*/
retry_time = cfs_time_add(obj->oo_contention_time,
cfs_time_seconds(osc_contention_time));
if (cfs_time_after(cur_time, retry_time)) {
osc_object_clear_contended(obj);
return 0;
}
return 1;
}
/**
* Disconnect a bulk desc from the network. Idempotent. Not
* thread-safe (i.e. only interlocks with completion callback).
* Returns 1 on success or 0 if network unregistration failed for whatever
* reason.
*/
int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async)
{
struct ptlrpc_bulk_desc *desc = req->rq_bulk;
wait_queue_head_t *wq;
int rc;
LASSERT(!in_interrupt()); /* might sleep */
/* Let's setup deadline for reply unlink. */
if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_LONG_BULK_UNLINK) &&
async && req->rq_bulk_deadline == 0 && cfs_fail_val == 0)
req->rq_bulk_deadline = ktime_get_real_seconds() + LONG_UNLINK;
if (ptlrpc_client_bulk_active(req) == 0) /* completed or */
return 1; /* never registered */
LASSERT(desc->bd_req == req); /* bd_req NULL until registered */
/* the unlink ensures the callback happens ASAP and is the last
* one. If it fails, it must be because completion just happened,
* but we must still wait_event() in this case to give liblustre
* a chance to run client_bulk_callback()
*/
mdunlink_iterate_helper(desc->bd_mds, desc->bd_md_max_brw);
if (ptlrpc_client_bulk_active(req) == 0) /* completed or */
return 1; /* never registered */
/* Move to "Unregistering" phase as bulk was not unlinked yet. */
ptlrpc_rqphase_move(req, RQ_PHASE_UNREG_BULK);
/* Do not wait for unlink to finish. */
if (async)
return 0;
if (req->rq_set)
wq = &req->rq_set->set_waitq;
else
wq = &req->rq_reply_waitq;
for (;;) {
/* Network access will complete in finite time but the HUGE
* timeout lets us CWARN for visibility of sluggish LNDs
*/
int cnt = 0;
while (cnt < LONG_UNLINK &&
(rc = wait_event_idle_timeout(*wq,
!ptlrpc_client_bulk_active(req),
HZ)) == 0)
cnt += 1;
if (rc > 0) {
ptlrpc_rqphase_move(req, req->rq_next_phase);
return 1;
}
DEBUG_REQ(D_WARNING, req, "Unexpectedly long timeout: desc %p",
desc);
}
return 0;
}
/**
* Disconnect a bulk desc from the network. Idempotent. Not
* thread-safe (i.e. only interlocks with completion callback).
* Returns 1 on success or 0 if network unregistration failed for whatever
* reason.
*/
int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async)
{
struct ptlrpc_bulk_desc *desc = req->rq_bulk;
struct l_wait_info lwi;
int rc;
ENTRY;
LASSERT(!in_interrupt()); /* might sleep */
/* Let's setup deadline for reply unlink. */
if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_LONG_BULK_UNLINK) &&
async && req->rq_bulk_deadline == 0)
req->rq_bulk_deadline = cfs_time_current_sec() + LONG_UNLINK;
if (ptlrpc_client_bulk_active(req) == 0) /* completed or */
RETURN(1); /* never registered */
LASSERT(desc->bd_req == req); /* bd_req NULL until registered */
/* the unlink ensures the callback happens ASAP and is the last
* one. If it fails, it must be because completion just happened,
* but we must still l_wait_event() in this case to give liblustre
* a chance to run client_bulk_callback() */
mdunlink_iterate_helper(desc->bd_mds, desc->bd_md_max_brw);
if (ptlrpc_client_bulk_active(req) == 0) /* completed or */
RETURN(1); /* never registered */
/* Move to "Unregistering" phase as bulk was not unlinked yet. */
ptlrpc_rqphase_move(req, RQ_PHASE_UNREGISTERING);
/* Do not wait for unlink to finish. */
if (async)
RETURN(0);
for (;;) {
#ifdef __KERNEL__
/* The wq argument is ignored by user-space wait_event macros */
wait_queue_head_t *wq = (req->rq_set != NULL) ?
&req->rq_set->set_waitq :
&req->rq_reply_waitq;
#endif
/* Network access will complete in finite time but the HUGE
* timeout lets us CWARN for visibility of sluggish NALs */
lwi = LWI_TIMEOUT_INTERVAL(cfs_time_seconds(LONG_UNLINK),
cfs_time_seconds(1), NULL, NULL);
rc = l_wait_event(*wq, !ptlrpc_client_bulk_active(req), &lwi);
if (rc == 0) {
ptlrpc_rqphase_move(req, req->rq_next_phase);
RETURN(1);
}
LASSERT(rc == -ETIMEDOUT);
DEBUG_REQ(D_WARNING, req, "Unexpectedly long timeout: desc %p",
desc);
}
RETURN(0);
}
/* Add log records for each OSC that this object is striped over, and return
* cookies for each one. We _would_ have nice abstraction here, except that
* we need to keep cookies in stripe order, even if some are NULL, so that
* the right cookies are passed back to the right OSTs at the client side.
* Unset cookies should be all-zero (which will never occur naturally). */
static int lov_llog_origin_add(const struct lu_env *env,
struct llog_ctxt *ctxt,
struct llog_rec_hdr *rec,
struct lov_stripe_md *lsm,
struct llog_cookie *logcookies, int numcookies)
{
struct obd_device *obd = ctxt->loc_obd;
struct lov_obd *lov = &obd->u.lov;
int i, rc = 0, cookies = 0;
ENTRY;
LASSERTF(logcookies && numcookies >= lsm->lsm_stripe_count,
"logcookies %p, numcookies %d lsm->lsm_stripe_count %d \n",
logcookies, numcookies, lsm->lsm_stripe_count);
for (i = 0; i < lsm->lsm_stripe_count; i++) {
struct lov_oinfo *loi = lsm->lsm_oinfo[i];
struct obd_device *child =
lov->lov_tgts[loi->loi_ost_idx]->ltd_exp->exp_obd;
struct llog_ctxt *cctxt = llog_get_context(child, ctxt->loc_idx);
/* fill mds unlink/setattr log record */
switch (rec->lrh_type) {
case MDS_UNLINK_REC: {
struct llog_unlink_rec *lur = (struct llog_unlink_rec *)rec;
lur->lur_oid = ostid_id(&loi->loi_oi);
lur->lur_oseq = (__u32)ostid_seq(&loi->loi_oi);
break;
}
case MDS_SETATTR64_REC: {
struct llog_setattr64_rec *lsr = (struct llog_setattr64_rec *)rec;
lsr->lsr_oi = loi->loi_oi;
break;
}
default:
break;
}
/* inject error in llog_obd_add() below */
if (OBD_FAIL_CHECK(OBD_FAIL_MDS_FAIL_LOV_LOG_ADD)) {
llog_ctxt_put(cctxt);
cctxt = NULL;
}
rc = llog_obd_add(env, cctxt, rec, NULL, logcookies + cookies,
numcookies - cookies);
llog_ctxt_put(cctxt);
if (rc < 0) {
CERROR("Can't add llog (rc = %d) for stripe %d\n",
rc, cookies);
memset(logcookies + cookies, 0,
sizeof(struct llog_cookie));
rc = 1; /* skip this cookie */
}
/* Note that rc is always 1 if llog_obd_add was successful */
cookies += rc;
}
RETURN(cookies);
}
开发者ID:Lezval,项目名称:lustre,代码行数:63,代码来源:lov_log.c
示例8: mdt_getxattr_pack_reply
/* return EADATA length to the caller. negative value means error */
static int mdt_getxattr_pack_reply(struct mdt_thread_info * info)
{
struct req_capsule *pill = info->mti_pill ;
struct ptlrpc_request *req = mdt_info_req(info);
char *xattr_name;
__u64 valid = info->mti_body->valid;
static const char user_string[] = "user.";
int size, rc;
ENTRY;
if (OBD_FAIL_CHECK(OBD_FAIL_MDS_GETXATTR_PACK))
RETURN(-ENOMEM);
/* Determine how many bytes we need */
if (valid & OBD_MD_FLXATTR) {
xattr_name = req_capsule_client_get(pill, &RMF_NAME);
if (!xattr_name)
RETURN(-EFAULT);
if (!(req->rq_export->exp_connect_flags & OBD_CONNECT_XATTR) &&
!strncmp(xattr_name, user_string, sizeof(user_string) - 1))
RETURN(-EOPNOTSUPP);
size = mo_xattr_get(info->mti_env,
mdt_object_child(info->mti_object),
&LU_BUF_NULL, xattr_name);
} else if (valid & OBD_MD_FLXATTRLS) {
size = mo_xattr_list(info->mti_env,
mdt_object_child(info->mti_object),
&LU_BUF_NULL);
} else {
CDEBUG(D_INFO, "Valid bits: "LPX64"\n", info->mti_body->valid);
RETURN(-EINVAL);
}
if (size == -ENODATA) {
size = 0;
} else if (size < 0) {
CERROR("Error geting EA size: %d\n", size);
RETURN(size);
}
if (info->mti_body->eadatasize != 0 &&
info->mti_body->eadatasize < size)
RETURN(-ERANGE);
req_capsule_set_size(pill, &RMF_EADATA, RCL_SERVER,
info->mti_body->eadatasize == 0 ? 0 : size);
rc = req_capsule_server_pack(pill);
if (rc) {
LASSERT(rc < 0);
RETURN(rc);
}
RETURN(size);
}
开发者ID:LLNL,项目名称:lustre,代码行数:57,代码来源:mdt_xattr.c
示例9: seq_client_alloc_fid
/**
* Allocate new fid on passed client @seq and save it to @fid.
*
* \param[in] env pointer to the thread context
* \param[in,out] seq pointer to the client sequence manager
* \param[out] fid to hold the new allocated fid
*
* \retval 1 for notify the caller that sequence switch
* is performed to allow it to setup FLD for it.
* \retval 0 for new FID allocated in current sequence.
* \retval Negative error number on failure.
*/
int seq_client_alloc_fid(const struct lu_env *env,
struct lu_client_seq *seq, struct lu_fid *fid)
{
wait_queue_t link;
int rc;
ENTRY;
LASSERT(seq != NULL);
LASSERT(fid != NULL);
init_waitqueue_entry(&link, current);
mutex_lock(&seq->lcs_mutex);
if (OBD_FAIL_CHECK(OBD_FAIL_SEQ_EXHAUST))
seq->lcs_fid.f_oid = seq->lcs_width;
while (1) {
u64 seqnr;
if (unlikely(!fid_is_zero(&seq->lcs_fid) &&
fid_oid(&seq->lcs_fid) < seq->lcs_width)) {
/* Just bump last allocated fid and return to caller. */
seq->lcs_fid.f_oid++;
rc = 0;
break;
}
/* Release seq::lcs_mutex via seq_fid_alloc_prep() to avoid
* deadlock during seq_client_alloc_seq(). */
rc = seq_fid_alloc_prep(seq, &link);
if (rc)
continue;
rc = seq_client_alloc_seq(env, seq, &seqnr);
/* Re-take seq::lcs_mutex via seq_fid_alloc_fini(). */
seq_fid_alloc_fini(seq, rc ? 0 : seqnr, false);
if (rc) {
CERROR("%s: Can't allocate new sequence: rc = %d\n",
seq->lcs_name, rc);
mutex_unlock(&seq->lcs_mutex);
RETURN(rc);
}
rc = 1;
break;
}
*fid = seq->lcs_fid;
mutex_unlock(&seq->lcs_mutex);
CDEBUG(D_INFO, "%s: Allocated FID "DFID"\n", seq->lcs_name, PFID(fid));
RETURN(rc);
}
/*
* This function implements new seq allocation algorithm using async
* updates to seq file on disk. ref bug 18857 for details.
* there are four variable to keep track of this process
*
* lss_space; - available lss_space
* lss_lowater_set; - lu_seq_range for all seqs before barrier, i.e. safe to use
* lss_hiwater_set; - lu_seq_range after barrier, i.e. allocated but may be
* not yet committed
*
* when lss_lowater_set reaches the end it is replaced with hiwater one and
* a write operation is initiated to allocate new hiwater range.
* if last seq write opearion is still not commited, current operation is
* flaged as sync write op.
*/
static int range_alloc_set(const struct lu_env *env,
struct lu_seq_range *out,
struct lu_server_seq *seq)
{
struct lu_seq_range *space = &seq->lss_space;
struct lu_seq_range *loset = &seq->lss_lowater_set;
struct lu_seq_range *hiset = &seq->lss_hiwater_set;
int rc = 0;
if (lu_seq_range_is_zero(loset))
__seq_set_init(env, seq);
if (OBD_FAIL_CHECK(OBD_FAIL_SEQ_ALLOC)) /* exhaust set */
loset->lsr_start = loset->lsr_end;
if (lu_seq_range_is_exhausted(loset)) {
/* reached high water mark. */
struct lu_device *dev = seq->lss_site->ss_lu->ls_top_dev;
int obd_num_clients = dev->ld_obd->obd_num_exports;
__u64 set_sz;
/* calculate new seq width based on number of clients */
set_sz = max(seq->lss_set_width,
obd_num_clients * seq->lss_width);
set_sz = min(lu_seq_range_space(space), set_sz);
/* Switch to hiwater range now */
*loset = *hiset;
/* allocate new hiwater range */
range_alloc(hiset, space, set_sz);
/* update ondisk seq with new *space */
rc = seq_store_update(env, seq, NULL, seq->lss_need_sync);
}
LASSERTF(!lu_seq_range_is_exhausted(loset) ||
lu_seq_range_is_sane(loset),
DRANGE"\n", PRANGE(loset));
if (rc == 0)
range_alloc(out, loset, seq->lss_width);
RETURN(rc);
}
/**
* Match client and OST server connection feature flags.
*
* Compute the compatibility flags for a connection request based on
* features mutually supported by client and server.
*
* The obd_export::exp_connect_data.ocd_connect_flags field in \a exp
* must not be updated here, otherwise a partially initialized value may
* be exposed. After the connection request is successfully processed,
* the top-level tgt_connect() request handler atomically updates the export
* connect flags from the obd_connect_data::ocd_connect_flags field of the
* reply. \see tgt_connect().
*
* \param[in] env execution environment
* \param[in] exp the obd_export associated with this
* client/target pair
* \param[in] data stores data for this connect request
* \param[in] new_connection is this connection new or not
*
* \retval 0 if success
* \retval -EPROTO client and server feature requirements are
* incompatible
* \retval -EBADF OST index in connect request doesn't match
* real OST index
*/
static int ofd_parse_connect_data(const struct lu_env *env,
struct obd_export *exp,
struct obd_connect_data *data,
bool new_connection)
{
struct ofd_device *ofd = ofd_exp(exp);
struct filter_export_data *fed = &exp->exp_filter_data;
if (!data)
RETURN(0);
CDEBUG(D_RPCTRACE, "%s: cli %s/%p ocd_connect_flags: "LPX64
" ocd_version: %x ocd_grant: %d ocd_index: %u"
" ocd_group %u\n",
exp->exp_obd->obd_name, exp->exp_client_uuid.uuid, exp,
data->ocd_connect_flags, data->ocd_version,
data->ocd_grant, data->ocd_index, data->ocd_group);
if (fed->fed_group != 0 && fed->fed_group != data->ocd_group) {
CWARN("!!! This export (nid %s) used object group %d "
"earlier; now it's trying to use group %d! This could "
"be a bug in the MDS. Please report to "
"https://jira.hpdd.intel.com/\n",
obd_export_nid2str(exp), fed->fed_group,
data->ocd_group);
RETURN(-EPROTO);
}
fed->fed_group = data->ocd_group;
data->ocd_connect_flags &= OST_CONNECT_SUPPORTED;
data->ocd_version = LUSTRE_VERSION_CODE;
/* Kindly make sure the SKIP_ORPHAN flag is from MDS. */
if (data->ocd_connect_flags & OBD_CONNECT_MDS)
CDEBUG(D_HA, "%s: Received MDS connection for group %u\n",
exp->exp_obd->obd_name, data->ocd_group);
else if (data->ocd_connect_flags & OBD_CONNECT_SKIP_ORPHAN)
RETURN(-EPROTO);
if (ofd_grant_param_supp(exp)) {
exp->exp_filter_data.fed_pagesize = data->ocd_blocksize;
/* ocd_{blocksize,inodespace} are log2 values */
data->ocd_blocksize = ofd->ofd_blockbits;
data->ocd_inodespace = ofd->ofd_dt_conf.ddp_inodespace;
/* ocd_grant_extent is in 1K blocks */
data->ocd_grant_extent = ofd->ofd_dt_conf.ddp_grant_frag >> 10;
}
if (data->ocd_connect_flags & OBD_CONNECT_GRANT)
data->ocd_grant = ofd_grant_connect(env, exp, data->ocd_grant,
new_connection);
if (data->ocd_connect_flags & OBD_CONNECT_INDEX) {
struct lr_server_data *lsd = &ofd->ofd_lut.lut_lsd;
int index = lsd->lsd_osd_index;
if (index != data->ocd_index) {
LCONSOLE_ERROR_MSG(0x136, "Connection from %s to index"
" %u doesn't match actual OST index"
" %u in last_rcvd file, bad "
"configuration?\n",
obd_export_nid2str(exp), index,
data->ocd_index);
RETURN(-EBADF);
}
if (!(lsd->lsd_feature_compat & OBD_COMPAT_OST)) {
/* this will only happen on the first connect */
lsd->lsd_feature_compat |= OBD_COMPAT_OST;
/* sync is not needed here as lut_client_add will
* set exp_need_sync flag */
tgt_server_data_update(env, &ofd->ofd_lut, 0);
}
}
if (OBD_FAIL_CHECK(OBD_FAIL_OST_BRW_SIZE)) {
data->ocd_brw_size = 65536;
//.........这里部分代码省略.........
请发表评论