Whamcloud - gitweb
LU-14687 llite: Return errors for aio
[fs/lustre-release.git] / lustre / llite / rw26.c
index 1415d79..6fdeba9 100644 (file)
@@ -27,7 +27,6 @@
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
  *
  * lustre/lustre/llite/rw26.c
  *
@@ -228,10 +227,10 @@ static ssize_t ll_get_user_pages(int rw, struct iov_iter *iter,
        if (*pages == NULL)
                return -ENOMEM;
 
-       down_read(&current->mm->mmap_sem);
+       mmap_read_lock(current->mm);
        result = get_user_pages(current, current->mm, addr, page_count,
                                rw == READ, 0, *pages, NULL);
-       up_read(&current->mm->mmap_sem);
+       mmap_read_unlock(current->mm);
 
        if (unlikely(result != page_count)) {
                ll_free_user_pages(*pages, page_count);
@@ -250,12 +249,12 @@ static ssize_t ll_get_user_pages(int rw, struct iov_iter *iter,
 
 /* iov_iter_alignment() is introduced in 3.16 similar to HAVE_DIO_ITER */
 #if defined(HAVE_DIO_ITER)
-static unsigned long ll_iov_iter_alignment(const struct iov_iter *i)
+static unsigned long iov_iter_alignment_vfs(const struct iov_iter *i)
 {
        return iov_iter_alignment(i);
 }
 #else /* copied from alignment_iovec() */
-static unsigned long ll_iov_iter_alignment(const struct iov_iter *i)
+static unsigned long iov_iter_alignment_vfs(const struct iov_iter *i)
 {
        const struct iovec *iov = i->iov;
        unsigned long res;
@@ -282,6 +281,35 @@ static unsigned long ll_iov_iter_alignment(const struct iov_iter *i)
 }
 #endif
 
+/*
+ * Lustre could relax a bit for alignment, io count is not
+ * necessary page alignment.
+ */
+static unsigned long ll_iov_iter_alignment(struct iov_iter *i)
+{
+       size_t orig_size = i->count;
+       size_t count = orig_size & ~PAGE_MASK;
+       unsigned long res;
+
+       if (!count)
+               return iov_iter_alignment_vfs(i);
+
+       if (orig_size > PAGE_SIZE) {
+               iov_iter_truncate(i, orig_size - count);
+               res = iov_iter_alignment_vfs(i);
+               iov_iter_reexpand(i, orig_size);
+
+               return res;
+       }
+
+       res = iov_iter_alignment_vfs(i);
+       /* start address is page aligned */
+       if ((res & ~PAGE_MASK) == orig_size)
+               return PAGE_SIZE;
+
+       return res;
+}
+
 /** direct IO pages */
 struct ll_dio_pages {
        struct cl_dio_aio       *ldp_aio;
@@ -308,7 +336,6 @@ ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io, size_t size,
        int io_pages    = 0;
        size_t page_size = cl_page_size(obj);
        int i;
-       pgoff_t index = offset >> PAGE_SHIFT;
        ssize_t rc = 0;
 
        ENTRY;
@@ -331,26 +358,14 @@ ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io, size_t size,
 
                page->cp_sync_io = anchor;
                if (inode && IS_ENCRYPTED(inode)) {
-                       struct page *vmpage = cl_page_vmpage(page);
-
                        /* In case of Direct IO on encrypted file, we need to
-                        * set the correct page index, and add a reference to
-                        * the mapping. This is required by llcrypt to proceed
-                        * to encryption/decryption, because each block is
-                        * encrypted independently, and each block's IV is set
-                        * to the logical block number within the file.
+                        * add a reference to the inode on the cl_page.
+                        * This info is required by llcrypt to proceed
+                        * to encryption/decryption.
                         * This is safe because we know these pages are private
-                        * to the thread doing the Direct IO, and despite
-                        * setting a mapping on the pages, cached lookups will
-                        * not find them.
-                        * Set PageChecked to detect special case of Direct IO
-                        * in osc_brw_fini_request().
-                        * Reference to the mapping and PageChecked flag are
-                        * removed in cl_aio_end().
+                        * to the thread doing the Direct IO.
                         */
-                       vmpage->index = index++;
-                       vmpage->mapping = inode->i_mapping;
-                       SetPageChecked(vmpage);
+                       page->cp_inode = inode;
                }
                cl_2queue_add(queue, page);
                /*
@@ -433,8 +448,8 @@ ll_direct_IO_impl(struct kiocb *iocb, struct iov_iter *iter, int rw)
                return 0;
 
        /* FIXME: io smaller than PAGE_SIZE is broken on ia64 ??? */
-       if ((file_offset & ~PAGE_MASK) || (count & ~PAGE_MASK))
-               return -EINVAL;
+       if (file_offset & ~PAGE_MASK)
+               RETURN(-EINVAL);
 
        CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p), size=%zd (max %lu), "
               "offset=%lld=%llx, pages %zd (max %lu)\n",
@@ -444,7 +459,7 @@ ll_direct_IO_impl(struct kiocb *iocb, struct iov_iter *iter, int rw)
 
        /* Check that all user buffers are aligned as well */
        if (ll_iov_iter_alignment(iter) & ~PAGE_MASK)
-               return -EINVAL;
+               RETURN(-EINVAL);
 
        lcc = ll_cl_find(file);
        if (lcc == NULL)
@@ -527,7 +542,8 @@ out:
                        vio->u.readwrite.vui_written += tot_bytes;
                else
                        vio->u.readwrite.vui_read += tot_bytes;
-               result = -EIOCBQUEUED;
+               if (result == 0)
+                       result = -EIOCBQUEUED;
        }
 
        return result;