write_unlock(&fd->fd_lock);
}
-static int ll_io_read_page(const struct lu_env *env, struct cl_io *io,
+int ll_io_read_page(const struct lu_env *env, struct cl_io *io,
struct cl_page *page, struct file *file)
{
struct inode *inode = vvp_object_inode(page->cp_obj);
task_io_account_read(PAGE_SIZE * count);
}
+
if (anchor != NULL && !cl_page_is_owned(page, io)) { /* have sent */
rc = cl_sync_io_wait(env, anchor, 0);
/* TODO: discard all pages until page reinit route is implemented */
cl_page_list_discard(env, io, &queue->c2_qin);
- /*
- * Unlock unsent pages in case of error.
- */
+ /* Unlock unsent read pages in case of error. */
cl_page_list_disown(env, io, &queue->c2_qin);
+
cl_2queue_fini(env, queue);
RETURN(rc);
LASSERT(page->cp_type == CPT_CACHEABLE);
if (likely(!PageUptodate(vmpage))) {
cl_page_assume(env, io, page);
+
result = ll_io_read_page(env, io, page, file);
} else {
/* Page from a non-object file. */
}
RETURN(result);
}
-
-int ll_page_sync_io(const struct lu_env *env, struct cl_io *io,
- struct cl_page *page, enum cl_req_type crt)
-{
- struct cl_2queue *queue;
- int result;
-
- LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE);
-
- queue = &io->ci_queue;
- cl_2queue_init_page(queue, page);
-
- result = cl_io_submit_sync(env, io, crt, queue, 0);
- LASSERT(cl_page_is_owned(page, io));
-
- if (crt == CRT_READ)
- /*
- * in CRT_WRITE case page is left locked even in case of
- * error.
- */
- cl_page_list_disown(env, io, &queue->c2_qin);
- cl_2queue_fini(env, queue);
-
- return result;
-}
/**
* Prepare partially written-to page for a write.
+ * @pg is owned when passed in and disowned when it returns non-zero result to
+ * the caller.
*/
static int ll_prepare_partial_page(const struct lu_env *env, struct cl_io *io,
- struct cl_page *pg)
+ struct cl_page *pg, struct file *file)
{
struct cl_attr *attr = vvp_env_thread_attr(env);
struct cl_object *obj = io->ci_obj;
struct vvp_page *vpg = cl_object_page_slice(obj, pg);
loff_t offset = cl_offset(obj, vvp_index(vpg));
int result;
+ ENTRY;
cl_object_attr_lock(obj);
result = cl_object_attr_get(env, obj, attr);
cl_object_attr_unlock(obj);
- if (result == 0) {
- /*
- * If are writing to a new page, no need to read old data.
- * The extent locking will have updated the KMS, and for our
- * purposes here we can treat it like i_size.
- */
- if (attr->cat_kms <= offset) {
- char *kaddr = ll_kmap_atomic(vpg->vpg_page, KM_USER0);
+ if (result) {
+ cl_page_disown(env, io, pg);
+ GOTO(out, result);
+ }
- memset(kaddr, 0, cl_page_size(obj));
- ll_kunmap_atomic(kaddr, KM_USER0);
- } else if (vpg->vpg_defer_uptodate)
- vpg->vpg_ra_used = 1;
- else
- result = ll_page_sync_io(env, io, pg, CRT_READ);
+ /*
+ * If are writing to a new page, no need to read old data.
+ * The extent locking will have updated the KMS, and for our
+ * purposes here we can treat it like i_size.
+ */
+ if (attr->cat_kms <= offset) {
+ char *kaddr = ll_kmap_atomic(vpg->vpg_page, KM_USER0);
+
+ memset(kaddr, 0, cl_page_size(obj));
+ ll_kunmap_atomic(kaddr, KM_USER0);
+ GOTO(out, result = 0);
+ }
+
+ if (vpg->vpg_defer_uptodate) {
+ vpg->vpg_ra_used = 1;
+ GOTO(out, result = 0);
+ }
+
+ result = ll_io_read_page(env, io, pg, file);
+ if (result)
+ GOTO(out, result);
+
+ /* ll_io_read_page() disowns the page */
+ result = cl_page_own(env, io, pg);
+ if (!result) {
+ if (!PageUptodate(cl_page_vmpage(pg))) {
+ cl_page_disown(env, io, pg);
+ result = -EIO;
+ }
+ } else if (result == -ENOENT) {
+ /* page was truncated */
+ result = -EAGAIN;
}
+ EXIT;
+
+out:
return result;
}
* problem submitting the I/O. */
GOTO(out, result = -EBUSY);
}
-
+again:
/* To avoid deadlock, try to lock page first. */
vmpage = grab_cache_page_nowait(mapping, index);
/* TODO: can be optimized at OSC layer to check if it
* is a lockless IO. In that case, it's not necessary
* to read the data. */
- result = ll_prepare_partial_page(env, io, page);
- if (result == 0)
- SetPageUptodate(vmpage);
+ result = ll_prepare_partial_page(env, io, page, file);
+ if (result) {
+ /* vmpage should have been unlocked */
+ put_page(vmpage);
+ vmpage = NULL;
+
+ if (result == -EAGAIN)
+ goto again;
+
+ GOTO(out, result);
+ }
}
}
- if (result < 0)
- cl_page_unassume(env, io, page);
EXIT;
out:
if (result < 0) {