/* Allocate new fid on passed client @seq and save it to @fid. */ int seq_client_alloc_fid(const struct lu_env *env, struct lu_client_seq *seq, struct lu_fid *fid) { cfs_waitlink_t link; int rc; ENTRY; LASSERT(seq != NULL); LASSERT(fid != NULL); cfs_waitlink_init(&link); cfs_mutex_lock(&seq->lcs_mutex); while (1) { seqno_t seqnr; if (!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 += 1; rc = 0; break; } rc = seq_fid_alloc_prep(seq, &link); if (rc) continue; rc = seq_client_alloc_seq(env, seq, &seqnr); if (rc) { CERROR("%s: Can't allocate new sequence, " "rc %d\n", seq->lcs_name, rc); seq_fid_alloc_fini(seq); cfs_mutex_unlock(&seq->lcs_mutex); RETURN(rc); } CDEBUG(D_INFO, "%s: Switch to sequence " "[0x%16.16"LPF64"x]\n", seq->lcs_name, seqnr); seq->lcs_fid.f_oid = LUSTRE_FID_INIT_OID; seq->lcs_fid.f_seq = seqnr; seq->lcs_fid.f_ver = 0; /* * Inform caller that sequence switch is performed to allow it * to setup FLD for it. */ rc = 1; seq_fid_alloc_fini(seq); break; } *fid = seq->lcs_fid; cfs_mutex_unlock(&seq->lcs_mutex); CDEBUG(D_INFO, "%s: Allocated FID "DFID"\n", seq->lcs_name, PFID(fid)); RETURN(rc); }
/** * 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); }
/** * Allocate the whole seq to the caller. **/ int seq_client_get_seq(const struct lu_env *env, struct lu_client_seq *seq, u64 *seqnr) { wait_queue_t link; int rc; LASSERT(seqnr != NULL); mutex_lock(&seq->lcs_mutex); init_waitqueue_entry_current(&link); while (1) { rc = seq_fid_alloc_prep(seq, &link); if (rc == 0) break; } rc = seq_client_alloc_seq(env, seq, seqnr); if (rc) { CERROR("%s: Can't allocate new sequence, " "rc %d\n", seq->lcs_name, rc); seq_fid_alloc_fini(seq); mutex_unlock(&seq->lcs_mutex); return rc; } CDEBUG(D_INFO, "%s: allocate sequence " "[0x%16.16"LPF64"x]\n", seq->lcs_name, *seqnr); /* Since the caller require the whole seq, * so marked this seq to be used */ if (seq->lcs_type == LUSTRE_SEQ_METADATA) seq->lcs_fid.f_oid = LUSTRE_METADATA_SEQ_MAX_WIDTH; else seq->lcs_fid.f_oid = LUSTRE_DATA_SEQ_MAX_WIDTH; seq->lcs_fid.f_seq = *seqnr; seq->lcs_fid.f_ver = 0; /* * Inform caller that sequence switch is performed to allow it * to setup FLD for it. */ seq_fid_alloc_fini(seq); mutex_unlock(&seq->lcs_mutex); return rc; }
/** * Allocate the whole non-used seq to the caller. * * \param[in] env pointer to the thread context * \param[in,out] seq pointer to the client sequence manager * \param[out] seqnr to hold the new allocated sequence * * \retval 0 for new sequence allocated. * \retval Negative error number on failure. */ int seq_client_get_seq(const struct lu_env *env, struct lu_client_seq *seq, u64 *seqnr) { wait_queue_t link; int rc; LASSERT(seqnr != NULL); mutex_lock(&seq->lcs_mutex); init_waitqueue_entry(&link, current); /* To guarantee that we can get a whole non-used sequence. */ while (seq_fid_alloc_prep(seq, &link) != 0); rc = seq_client_alloc_seq(env, seq, seqnr); seq_fid_alloc_fini(seq, rc ? 0 : *seqnr, true); if (rc) CERROR("%s: Can't allocate new sequence: rc = %d\n", seq->lcs_name, rc); mutex_unlock(&seq->lcs_mutex); return rc; }
/* Allocate new fid on passed client @seq and save it to @fid. */ int seq_client_alloc_fid(const struct lu_env *env, struct lu_client_seq *seq, struct lu_fid *fid) { wait_queue_entry_t link; int rc; LASSERT(seq); LASSERT(fid); 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 (!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 += 1; rc = 0; break; } rc = seq_fid_alloc_prep(seq, &link); if (rc) continue; rc = seq_client_alloc_seq(env, seq, &seqnr); if (rc) { CERROR("%s: Can't allocate new sequence, rc %d\n", seq->lcs_name, rc); seq_fid_alloc_fini(seq); mutex_unlock(&seq->lcs_mutex); return rc; } CDEBUG(D_INFO, "%s: Switch to sequence [0x%16.16llx]\n", seq->lcs_name, seqnr); seq->lcs_fid.f_oid = LUSTRE_FID_INIT_OID; seq->lcs_fid.f_seq = seqnr; seq->lcs_fid.f_ver = 0; /* * Inform caller that sequence switch is performed to allow it * to setup FLD for it. */ rc = 1; seq_fid_alloc_fini(seq); 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; }