Whamcloud - gitweb
LU-5577 obdclass: change cl_fault_io->ft_nob to size_t
[fs/lustre-release.git] / lustre / llite / rw26.c
index 24414c9..b0eaf8e 100644 (file)
@@ -62,7 +62,6 @@
 
 #define DEBUG_SUBSYSTEM S_LLITE
 
-#include <lustre_lite.h>
 #include "llite_internal.h"
 #include <linux/lustre_compat25.h>
 
@@ -171,8 +170,7 @@ static int ll_releasepage(struct page *vmpage, RELEASEPAGE_ARG_TYPE gfp_mask)
         * If this page holds the last refc of cl_object, the following
         * call path may cause reschedule:
         *   cl_page_put -> cl_page_free -> cl_object_put ->
-        *     lu_object_put -> lu_object_free -> lov_delete_raid0 ->
-        *     cl_locks_prune.
+        *     lu_object_put -> lu_object_free -> lov_delete_raid0.
         *
         * However, the kernel can't get rid of this inode until all pages have
         * been cleaned up. Now that we hold page lock here, it's pretty safe
@@ -239,19 +237,19 @@ ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io,
                            int rw, struct inode *inode,
                            struct ll_dio_pages *pv)
 {
-        struct cl_page    *clp;
-        struct cl_2queue  *queue;
-        struct cl_object  *obj = io->ci_obj;
-        int i;
-        ssize_t rc = 0;
-        loff_t file_offset  = pv->ldp_start_offset;
-        long size           = pv->ldp_size;
-        int page_count      = pv->ldp_nr;
-        struct page **pages = pv->ldp_pages;
-        long page_size      = cl_page_size(obj);
-        bool do_io;
-        int  io_pages       = 0;
-        ENTRY;
+       struct cl_page    *clp;
+       struct cl_2queue  *queue;
+       struct cl_object  *obj = io->ci_obj;
+       int i;
+       ssize_t rc = 0;
+       loff_t file_offset  = pv->ldp_start_offset;
+       size_t size         = pv->ldp_size;
+       int page_count      = pv->ldp_nr;
+       struct page **pages = pv->ldp_pages;
+       size_t page_size    = cl_page_size(obj);
+       bool do_io;
+       int  io_pages       = 0;
+       ENTRY;
 
         queue = &io->ci_queue;
         cl_2queue_init(queue);
@@ -378,7 +376,6 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
         struct cl_io *io;
         struct file *file = iocb->ki_filp;
         struct inode *inode = file->f_mapping->host;
-        struct ccc_object *obj = cl_inode2ccc(inode);
         long count = iov_length(iov, nr_segs);
         long tot_bytes = 0, result = 0;
         struct ll_inode_info *lli = ll_i2info(inode);
@@ -412,14 +409,6 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
         io = ccc_env_io(env)->cui_cl.cis_io;
         LASSERT(io != NULL);
 
-       /* 0. Need locking between buffered and direct access. and race with
-        *    size changing by concurrent truncates and writes.
-        * 1. Need inode mutex to operate transient pages.
-        */
-       if (rw == READ)
-               mutex_lock(&inode->i_mutex);
-
-        LASSERT(obj->cob_transient_pages == 0);
         for (seg = 0; seg < nr_segs; seg++) {
                 long iov_left = iov[seg].iov_len;
                 unsigned long user_addr = (unsigned long)iov[seg].iov_base;
@@ -479,10 +468,6 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
                 }
         }
 out:
-       LASSERT(obj->cob_transient_pages == 0);
-       if (rw == READ)
-               mutex_unlock(&inode->i_mutex);
-
         if (tot_bytes > 0) {
                struct ccc_io *cio = ccc_env_io(env);
 
@@ -533,7 +518,7 @@ static int ll_write_begin(struct file *file, struct address_space *mapping,
                          struct page **pagep, void **fsdata)
 {
        struct ll_cl_context *lcc;
-       struct lu_env  *env;
+       const struct lu_env  *env;
        struct cl_io   *io;
        struct cl_page *page;
 
@@ -547,16 +532,16 @@ static int ll_write_begin(struct file *file, struct address_space *mapping,
 
        CDEBUG(D_VFSTRACE, "Writing %lu of %d to %d bytes\n", index, from, len);
 
-       lcc = ll_cl_init(file, NULL);
-       if (IS_ERR(lcc))
-               GOTO(out, result = PTR_ERR(lcc));
+       lcc = ll_cl_find(file);
+       if (lcc == NULL)
+               GOTO(out, result = -EIO);
 
        env = lcc->lcc_env;
        io  = lcc->lcc_io;
 
-       if (likely(to == PAGE_SIZE)) /* LU-4873 */
-               /* To avoid deadlock, try to lock page first. */
-               vmpage = grab_cache_page_nowait(mapping, index);
+       /* To avoid deadlock, try to lock page first. */
+       vmpage = grab_cache_page_nowait(mapping, index);
+
        if (unlikely(vmpage == NULL ||
                     PageDirty(vmpage) || PageWriteback(vmpage))) {
                struct ccc_io *cio = ccc_env_io(env);
@@ -620,8 +605,6 @@ out:
                        unlock_page(vmpage);
                        page_cache_release(vmpage);
                }
-               if (!IS_ERR(lcc))
-                       ll_cl_fini(lcc);
        } else {
                *pagep = vmpage;
                *fsdata = lcc;
@@ -634,7 +617,7 @@ static int ll_write_end(struct file *file, struct address_space *mapping,
                        struct page *vmpage, void *fsdata)
 {
        struct ll_cl_context *lcc = fsdata;
-       struct lu_env *env;
+       const struct lu_env *env;
        struct cl_io *io;
        struct ccc_io *cio;
        struct cl_page *page;
@@ -665,6 +648,11 @@ static int ll_write_end(struct file *file, struct address_space *mapping,
                        LASSERT(from == 0);
                cio->u.write.cui_to = from + copied;
 
+               /* To address the deadlock in balance_dirty_pages() where
+                * this dirty page may be written back in the same thread. */
+               if (PageDirty(vmpage))
+                       unplug = true;
+
                /* We may have one full RPC, commit it soon */
                if (plist->pl_nr >= PTLRPC_MAX_BRW_PAGES)
                        unplug = true;
@@ -674,15 +662,17 @@ static int ll_write_end(struct file *file, struct address_space *mapping,
        } else {
                cl_page_disown(env, io, page);
 
+               lcc->lcc_page = NULL;
+               lu_ref_del(&page->cp_reference, "cl_io", io);
+               cl_page_put(env, page);
+
                /* page list is not contiguous now, commit it now */
                unplug = true;
        }
-
        if (unplug ||
            file->f_flags & O_SYNC || IS_SYNC(file->f_dentry->d_inode))
                result = vvp_io_write_commit(env, io);
 
-       ll_cl_fini(lcc);
        RETURN(result >= 0 ? copied : result);
 }