@@ -363,6 +363,33 @@ static int chlg_load(void *args)
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) {
+ 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;
+ }
+ 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
@@ -396,6 +423,10 @@ static ssize_t chlg_read(struct file *file, char __user *buff, size_t count,
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);
@@ -601,8 +632,6 @@ static int chlg_open(struct inode *inode, struct file *file)
{
struct chlg_reader_state *crs;
struct chlg_registered_dev *dev;
- struct task_struct *task;
- int rc;
dev = container_of(inode->i_cdev, struct chlg_registered_dev, ced_cdev);
@@ -620,24 +649,10 @@ static int chlg_open(struct inode *inode, struct file *file)
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;
- }
- 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);
- kfree(crs);
- return rc;
}
/**
@@ -679,6 +694,11 @@ static unsigned int chlg_poll(struct file *file, poll_table *wait)
{
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);