if (rec->cr_hdr.lrh_type != CHANGELOG_REC) {
rc = -EINVAL;
- CERROR("%s: not a changelog rec %x/%d in llog "DFID" rc = %d\n",
+ CERROR("%s: not a changelog rec %x/%d in llog : rc = %d\n",
crs->crs_obd->obd_name, rec->cr_hdr.lrh_type,
- rec->cr.cr_type,
- PFID(lu_object_fid(&llh->lgh_obj->do_lu)), rc);
+ rec->cr.cr_type, rc);
RETURN(rc);
}
+ /* Check if we can skip the entire llog plain */
+ if (llog_is_plain_skipable(llh->lgh_hdr, hdr, rec->cr.cr_index,
+ crs->crs_start_offset))
+ RETURN(LLOG_SKIP_PLAIN);
+
/* Skip undesired records */
if (rec->cr.cr_index < crs->crs_start_offset)
RETURN(0);
RETURN(rc);
}
+static int chlg_start_thread(struct file *file)
+{
+ struct chlg_reader_state *crs = file->private_data;
+ struct task_struct *task;
+ int rc = 0;
+
+ if (likely(crs->crs_prod_task))
+ return 0;
+ if (unlikely(file->f_mode & FMODE_READ) == 0)
+ return 0;
+
+ mutex_lock(&crs->crs_lock);
+ if (crs->crs_prod_task == NULL) {
+ task = kthread_run(chlg_load, crs, "chlg_load_thread");
+ if (IS_ERR(task)) {
+ rc = PTR_ERR(task);
+ CERROR("%s: cannot start changelog thread: rc = %d\n",
+ crs->crs_ced->ced_name, rc);
+ GOTO(out, rc);
+ }
+ crs->crs_prod_task = task;
+ }
+out:
+ mutex_unlock(&crs->crs_lock);
+ return rc;
+}
+
/**
* Read handler, dequeues records from the chlg_reader_state if any.
* No partial records are copied to userland so this function can return less
RETURN(-EAGAIN);
}
+ rc = chlg_start_thread(file);
+ if (rc)
+ RETURN(rc);
+
rc = wait_event_interruptible(crs->crs_waitq_cons,
crs->crs_rec_count > 0 || crs->crs_eof || crs->crs_err);
{
struct chlg_reader_state *crs;
struct chlg_registered_dev *dev;
- struct task_struct *task;
- int rc;
ENTRY;
dev = container_of(inode->i_cdev, struct chlg_registered_dev, ced_cdev);
INIT_LIST_HEAD(&crs->crs_rec_queue);
init_waitqueue_head(&crs->crs_waitq_prod);
init_waitqueue_head(&crs->crs_waitq_cons);
-
- if (file->f_mode & FMODE_READ) {
- task = kthread_run(chlg_load, crs, "chlg_load_thread");
- if (IS_ERR(task)) {
- rc = PTR_ERR(task);
- CERROR("%s: cannot start changelog thread: rc = %d\n",
- dev->ced_name, rc);
- GOTO(err_crs, rc);
- }
- crs->crs_prod_task = task;
- }
+ crs->crs_prod_task = NULL;
file->private_data = crs;
RETURN(0);
-
-err_crs:
- kref_put(&dev->ced_refs, chlg_dev_clear);
- OBD_FREE_PTR(crs);
- return rc;
}
/**
{
struct chlg_reader_state *crs = file->private_data;
unsigned int mask = 0;
+ int rc;
+
+ rc = chlg_start_thread(file);
+ if (rc)
+ RETURN(rc);
mutex_lock(&crs->crs_lock);
poll_wait(file, &crs->crs_waitq_cons, wait);
rc = chlg_minor_alloc(&minor);
if (rc)
- GOTO(out_unlock, rc);
+ GOTO(out_listrm, rc);
device_initialize(&entry->ced_device);
entry->ced_device.devt = MKDEV(MAJOR(mdc_changelog_dev), minor);
out_minor:
chlg_minor_free(minor);
+out_listrm:
list_del_init(&obd->u.cli.cl_chg_dev_linkage);
list_del(&entry->ced_link);