#include <linux/poll.h>
#include <linux/device.h>
#include <linux/cdev.h>
+#include <linux/idr.h>
#include <lustre_log.h>
#include <uapi/linux/lustre/lustre_ioctl.h>
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);
crs->crs_rec_count++;
mutex_unlock(&crs->crs_lock);
- wake_up_all(&crs->crs_waitq_cons);
+ wake_up(&crs->crs_waitq_cons);
RETURN(0);
}
int rc;
ENTRY;
- crs->crs_last_catidx = -1;
+ crs->crs_last_catidx = 0;
crs->crs_last_idx = 0;
again:
if (rc < 0)
crs->crs_err = rc;
- wake_up_all(&crs->crs_waitq_cons);
+ wake_up(&crs->crs_waitq_cons);
if (llh != NULL)
llog_cat_close(NULL, llh);
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);
if (written_total > 0) {
rc = written_total;
- wake_up_all(&crs->crs_waitq_prod);
+ wake_up(&crs->crs_waitq_prod);
} else if (rc == 0) {
rc = crs->crs_err;
}
}
mutex_unlock(&crs->crs_lock);
- wake_up_all(&crs->crs_waitq_prod);
+ wake_up(&crs->crs_waitq_prod);
return 0;
}
{
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);