/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2012, 2013, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
if (loghandle == NULL)
return ERR_PTR(-ENOMEM);
- cfs_init_rwsem(&loghandle->lgh_lock);
- cfs_spin_lock_init(&loghandle->lgh_hdr_lock);
+ init_rwsem(&loghandle->lgh_lock);
+ spin_lock_init(&loghandle->lgh_hdr_lock);
CFS_INIT_LIST_HEAD(&loghandle->u.phd.phd_entry);
+ cfs_atomic_set(&loghandle->lgh_refcount, 1);
return loghandle;
}
*/
void llog_free_handle(struct llog_handle *loghandle)
{
- if (!loghandle)
- return;
+ LASSERT(loghandle != NULL);
+ /* failed llog_init_handle */
if (!loghandle->lgh_hdr)
goto out;
+
if (loghandle->lgh_hdr->llh_flags & LLOG_F_IS_PLAIN)
- cfs_list_del_init(&loghandle->u.phd.phd_entry);
- if (loghandle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)
+ LASSERT(cfs_list_empty(&loghandle->u.phd.phd_entry));
+ else if (loghandle->lgh_hdr->llh_flags & LLOG_F_IS_CAT)
LASSERT(cfs_list_empty(&loghandle->u.chd.chd_head));
LASSERT(sizeof(*(loghandle->lgh_hdr)) == LLOG_CHUNK_SIZE);
OBD_FREE(loghandle->lgh_hdr, LLOG_CHUNK_SIZE);
-
out:
OBD_FREE_PTR(loghandle);
}
+void llog_handle_get(struct llog_handle *loghandle)
+{
+ cfs_atomic_inc(&loghandle->lgh_refcount);
+}
+
+void llog_handle_put(struct llog_handle *loghandle)
+{
+ LASSERT(cfs_atomic_read(&loghandle->lgh_refcount) > 0);
+ if (cfs_atomic_dec_and_test(&loghandle->lgh_refcount))
+ llog_free_handle(loghandle);
+}
+
/* returns negative on error; 0 if success; 1 if success & log destroyed */
int llog_cancel_rec(const struct lu_env *env, struct llog_handle *loghandle,
int index)
int rc = 0;
ENTRY;
- CDEBUG(D_RPCTRACE, "Canceling %d in log "LPX64"\n",
- index, loghandle->lgh_id.lgl_oid);
+ CDEBUG(D_RPCTRACE, "Canceling %d in log "DOSTID"\n",
+ index, POSTID(&loghandle->lgh_id.lgl_oi));
if (index == 0) {
CERROR("Can't cancel index 0 which is header\n");
RETURN(-EINVAL);
}
- cfs_spin_lock(&loghandle->lgh_hdr_lock);
+ spin_lock(&loghandle->lgh_hdr_lock);
if (!ext2_clear_bit(index, llh->llh_bitmap)) {
- cfs_spin_unlock(&loghandle->lgh_hdr_lock);
- CDEBUG(D_RPCTRACE, "Catalog index %u already clear?\n", index);
- RETURN(-ENOENT);
- }
+ spin_unlock(&loghandle->lgh_hdr_lock);
+ CDEBUG(D_RPCTRACE, "Catalog index %u already clear?\n", index);
+ RETURN(-ENOENT);
+ }
- llh->llh_count--;
+ llh->llh_count--;
- if ((llh->llh_flags & LLOG_F_ZAP_WHEN_EMPTY) &&
- (llh->llh_count == 1) &&
- (loghandle->lgh_last_idx == (LLOG_BITMAP_BYTES * 8) - 1)) {
- cfs_spin_unlock(&loghandle->lgh_hdr_lock);
+ if ((llh->llh_flags & LLOG_F_ZAP_WHEN_EMPTY) &&
+ (llh->llh_count == 1) &&
+ (loghandle->lgh_last_idx == (LLOG_BITMAP_BYTES * 8) - 1)) {
+ spin_unlock(&loghandle->lgh_hdr_lock);
rc = llog_destroy(env, loghandle);
if (rc < 0) {
- CERROR("%s: can't destroy empty llog #"LPX64"#"LPX64
+ CERROR("%s: can't destroy empty llog #"DOSTID
"#%08x: rc = %d\n",
loghandle->lgh_ctxt->loc_obd->obd_name,
- loghandle->lgh_id.lgl_oid,
- loghandle->lgh_id.lgl_oseq,
+ POSTID(&loghandle->lgh_id.lgl_oi),
loghandle->lgh_id.lgl_ogen, rc);
GOTO(out_err, rc);
}
RETURN(1);
}
- cfs_spin_unlock(&loghandle->lgh_hdr_lock);
+ spin_unlock(&loghandle->lgh_hdr_lock);
- rc = llog_write_rec(env, loghandle, &llh->llh_hdr, NULL, 0, NULL, 0);
+ rc = llog_write(env, loghandle, &llh->llh_hdr, NULL, 0, NULL, 0);
if (rc < 0) {
- CERROR("%s: fail to write header for llog #"LPX64"#"LPX64
+ CERROR("%s: fail to write header for llog #"DOSTID
"#%08x: rc = %d\n",
loghandle->lgh_ctxt->loc_obd->obd_name,
- loghandle->lgh_id.lgl_oid,
- loghandle->lgh_id.lgl_oseq,
+ POSTID(&loghandle->lgh_id.lgl_oi),
loghandle->lgh_id.lgl_ogen, rc);
GOTO(out_err, rc);
}
RETURN(0);
out_err:
- cfs_spin_lock(&loghandle->lgh_hdr_lock);
+ spin_lock(&loghandle->lgh_hdr_lock);
ext2_set_bit(index, llh->llh_bitmap);
llh->llh_count++;
- cfs_spin_unlock(&loghandle->lgh_hdr_lock);
+ spin_unlock(&loghandle->lgh_hdr_lock);
return rc;
}
EXPORT_SYMBOL(llog_cancel_rec);
}
EXPORT_SYMBOL(llog_init_handle);
+int llog_copy_handler(const struct lu_env *env,
+ struct llog_handle *llh,
+ struct llog_rec_hdr *rec,
+ void *data)
+{
+ struct llog_rec_hdr local_rec = *rec;
+ struct llog_handle *local_llh = (struct llog_handle *)data;
+ char *cfg_buf = (char*) (rec + 1);
+ struct lustre_cfg *lcfg;
+ int rc = 0;
+ ENTRY;
+
+ /* Append all records */
+ local_rec.lrh_len -= sizeof(*rec) + sizeof(struct llog_rec_tail);
+ rc = llog_write(env, local_llh, &local_rec, NULL, 0,
+ (void *)cfg_buf, -1);
+
+ lcfg = (struct lustre_cfg *)cfg_buf;
+ CDEBUG(D_INFO, "idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
+ rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
+ lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
+
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_copy_handler);
+
static int llog_process_thread(void *arg)
{
struct llog_process_info *lpi = arg;
cfs_daemonize_ctxt("llog_process_thread");
/* client env has no keys, tags is just 0 */
- rc = lu_env_init(&env, LCT_LOCAL);
+ rc = lu_env_init(&env, LCT_LOCAL | LCT_MG_THREAD);
if (rc)
goto out;
lpi->lpi_env = &env;
lu_env_fini(&env);
out:
- cfs_complete(&lpi->lpi_completion);
+ complete(&lpi->lpi_completion);
return rc;
}
#endif
/* The new thread can't use parent env,
* init the new one in llog_process_thread_daemonize. */
lpi->lpi_env = NULL;
- cfs_init_completion(&lpi->lpi_completion);
+ init_completion(&lpi->lpi_completion);
rc = cfs_create_thread(llog_process_thread_daemonize, lpi,
CFS_DAEMON_FLAGS);
if (rc < 0) {
OBD_FREE_PTR(lpi);
RETURN(rc);
}
- cfs_wait_for_completion(&lpi->lpi_completion);
+ wait_for_completion(&lpi->lpi_completion);
} else {
lpi->lpi_env = env;
llog_process_thread(lpi);
OBD_FREE_PTR(lpi);
RETURN(rc);
}
+EXPORT_SYMBOL(llog_process_or_fork);
int llog_process(const struct lu_env *env, struct llog_handle *loghandle,
llog_cb_t cb, void *data, void *catdata)
EXPORT_SYMBOL(llog_reverse_process);
/**
+ * new llog API
+ *
+ * API functions:
+ * llog_open - open llog, may not exist
+ * llog_exist - check if llog exists
+ * llog_close - close opened llog, pair for open, frees llog_handle
+ * llog_declare_create - declare llog creation
+ * llog_create - create new llog on disk, need transaction handle
+ * llog_declare_write_rec - declaration of llog write
+ * llog_write_rec - write llog record on disk, need transaction handle
+ * llog_declare_add - declare llog catalog record addition
+ * llog_add - add llog record in catalog, need transaction handle
+ */
+int llog_exist(struct llog_handle *loghandle)
+{
+ struct llog_operations *lop;
+ int rc;
+
+ ENTRY;
+
+ rc = llog_handle2ops(loghandle, &lop);
+ if (rc)
+ RETURN(rc);
+ if (lop->lop_exist == NULL)
+ RETURN(-EOPNOTSUPP);
+
+ rc = lop->lop_exist(loghandle);
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_exist);
+
+int llog_declare_create(const struct lu_env *env,
+ struct llog_handle *loghandle, struct thandle *th)
+{
+ struct llog_operations *lop;
+ int raised, rc;
+
+ ENTRY;
+
+ rc = llog_handle2ops(loghandle, &lop);
+ if (rc)
+ RETURN(rc);
+ if (lop->lop_declare_create == NULL)
+ RETURN(-EOPNOTSUPP);
+
+ raised = cfs_cap_raised(CFS_CAP_SYS_RESOURCE);
+ if (!raised)
+ cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
+ rc = lop->lop_declare_create(env, loghandle, th);
+ if (!raised)
+ cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_declare_create);
+
+int llog_create(const struct lu_env *env, struct llog_handle *handle,
+ struct thandle *th)
+{
+ struct llog_operations *lop;
+ int raised, rc;
+
+ ENTRY;
+
+ rc = llog_handle2ops(handle, &lop);
+ if (rc)
+ RETURN(rc);
+ if (lop->lop_create == NULL)
+ RETURN(-EOPNOTSUPP);
+
+ raised = cfs_cap_raised(CFS_CAP_SYS_RESOURCE);
+ if (!raised)
+ cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
+ rc = lop->lop_create(env, handle, th);
+ if (!raised)
+ cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_create);
+
+int llog_declare_write_rec(const struct lu_env *env,
+ struct llog_handle *handle,
+ struct llog_rec_hdr *rec, int idx,
+ struct thandle *th)
+{
+ struct llog_operations *lop;
+ int raised, rc;
+
+ ENTRY;
+
+ rc = llog_handle2ops(handle, &lop);
+ if (rc)
+ RETURN(rc);
+ LASSERT(lop);
+ if (lop->lop_declare_write_rec == NULL)
+ RETURN(-EOPNOTSUPP);
+
+ raised = cfs_cap_raised(CFS_CAP_SYS_RESOURCE);
+ if (!raised)
+ cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
+ rc = lop->lop_declare_write_rec(env, handle, rec, idx, th);
+ if (!raised)
+ cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_declare_write_rec);
+
+int llog_write_rec(const struct lu_env *env, struct llog_handle *handle,
+ struct llog_rec_hdr *rec, struct llog_cookie *logcookies,
+ int numcookies, void *buf, int idx, struct thandle *th)
+{
+ struct llog_operations *lop;
+ int raised, rc, buflen;
+
+ ENTRY;
+
+ rc = llog_handle2ops(handle, &lop);
+ if (rc)
+ RETURN(rc);
+
+ LASSERT(lop);
+ if (lop->lop_write_rec == NULL)
+ RETURN(-EOPNOTSUPP);
+
+ if (buf)
+ buflen = rec->lrh_len + sizeof(struct llog_rec_hdr) +
+ sizeof(struct llog_rec_tail);
+ else
+ buflen = rec->lrh_len;
+ LASSERT(cfs_size_round(buflen) == buflen);
+
+ raised = cfs_cap_raised(CFS_CAP_SYS_RESOURCE);
+ if (!raised)
+ cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
+ rc = lop->lop_write_rec(env, handle, rec, logcookies, numcookies,
+ buf, idx, th);
+ if (!raised)
+ cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_write_rec);
+
+int llog_add(const struct lu_env *env, struct llog_handle *lgh,
+ struct llog_rec_hdr *rec, struct llog_cookie *logcookies,
+ void *buf, struct thandle *th)
+{
+ int raised, rc;
+
+ ENTRY;
+
+ if (lgh->lgh_logops->lop_add == NULL)
+ RETURN(-EOPNOTSUPP);
+
+ raised = cfs_cap_raised(CFS_CAP_SYS_RESOURCE);
+ if (!raised)
+ cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
+ rc = lgh->lgh_logops->lop_add(env, lgh, rec, logcookies, buf, th);
+ if (!raised)
+ cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_add);
+
+int llog_declare_add(const struct lu_env *env, struct llog_handle *lgh,
+ struct llog_rec_hdr *rec, struct thandle *th)
+{
+ int raised, rc;
+
+ ENTRY;
+
+ if (lgh->lgh_logops->lop_declare_add == NULL)
+ RETURN(-EOPNOTSUPP);
+
+ raised = cfs_cap_raised(CFS_CAP_SYS_RESOURCE);
+ if (!raised)
+ cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
+ rc = lgh->lgh_logops->lop_declare_add(env, lgh, rec, th);
+ if (!raised)
+ cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_declare_add);
+
+/**
* Helper function to open llog or create it if doesn't exist.
* It hides all transaction handling from caller.
*/
}
EXPORT_SYMBOL(llog_erase);
+/*
+ * Helper function for write record in llog.
+ * It hides all transaction handling from caller.
+ * Valid only with local llog.
+ */
+int llog_write(const struct lu_env *env, struct llog_handle *loghandle,
+ struct llog_rec_hdr *rec, struct llog_cookie *reccookie,
+ int cookiecount, void *buf, int idx)
+{
+ int rc;
+
+ ENTRY;
+
+ LASSERT(loghandle);
+ LASSERT(loghandle->lgh_ctxt);
+
+ if (loghandle->lgh_obj != NULL) {
+ struct dt_device *dt;
+ struct thandle *th;
+
+ dt = lu2dt_dev(loghandle->lgh_obj->do_lu.lo_dev);
+
+ th = dt_trans_create(env, dt);
+ if (IS_ERR(th))
+ RETURN(PTR_ERR(th));
+
+ rc = llog_declare_write_rec(env, loghandle, rec, idx, th);
+ if (rc)
+ GOTO(out_trans, rc);
+
+ rc = dt_trans_start_local(env, dt, th);
+ if (rc)
+ GOTO(out_trans, rc);
+
+ down_write(&loghandle->lgh_lock);
+ rc = llog_write_rec(env, loghandle, rec, reccookie,
+ cookiecount, buf, idx, th);
+ up_write(&loghandle->lgh_lock);
+out_trans:
+ dt_trans_stop(env, dt, th);
+ } else { /* lvfs compatibility */
+ down_write(&loghandle->lgh_lock);
+ rc = llog_write_rec(env, loghandle, rec, reccookie,
+ cookiecount, buf, idx, NULL);
+ up_write(&loghandle->lgh_lock);
+ }
+ RETURN(rc);
+}
+EXPORT_SYMBOL(llog_write);
+
int llog_open(const struct lu_env *env, struct llog_ctxt *ctxt,
struct llog_handle **lgh, struct llog_logid *logid,
char *name, enum llog_open_param open_param)
if (rc)
GOTO(out, rc);
if (lop->lop_close == NULL)
- GOTO(out, -EOPNOTSUPP);
+ GOTO(out, rc = -EOPNOTSUPP);
rc = lop->lop_close(env, loghandle);
out:
- llog_free_handle(loghandle);
+ llog_handle_put(loghandle);
RETURN(rc);
}
EXPORT_SYMBOL(llog_close);