Whamcloud - gitweb
LU-13528 llite: prevent MAX_DIO_SIZE 32-bit truncation
[fs/lustre-release.git] / lustre / llite / rw26.c
index 7507d6e..5c4dd7b 100644 (file)
@@ -185,7 +185,7 @@ static void ll_free_user_pages(struct page **pages, int npages)
 #if defined(HAVE_DIO_ITER)
        kvfree(pages);
 #else
-       OBD_FREE_LARGE(pages, npages * sizeof(*pages));
+       OBD_FREE_PTR_ARRAY_LARGE(pages, npages);
 #endif
 }
 
@@ -224,7 +224,7 @@ static ssize_t ll_get_user_pages(int rw, struct iov_iter *iter,
 
        size = min_t(size_t, maxsize, iter->iov->iov_len);
        page_count = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       OBD_ALLOC_LARGE(*pages, page_count * sizeof(**pages));
+       OBD_ALLOC_PTR_ARRAY_LARGE(*pages, page_count);
        if (*pages == NULL)
                return -ENOMEM;
 
@@ -384,7 +384,7 @@ ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io, size_t size,
  * then truncate this to be a full-sized RPC.  For 4kB PAGE_SIZE this is
  * up to 22MB for 128kB kmalloc and up to 682MB for 4MB kmalloc. */
 #define MAX_DIO_SIZE ((MAX_MALLOC / sizeof(struct brw_page) * PAGE_SIZE) & \
-                     ~(DT_MAX_BRW_SIZE - 1))
+                     ~((size_t)DT_MAX_BRW_SIZE - 1))
 
 static ssize_t
 ll_direct_IO_impl(struct kiocb *iocb, struct iov_iter *iter, int rw)
@@ -598,11 +598,11 @@ out:
        return result;
 }
 
-static int ll_tiny_write_begin(struct page *vmpage)
+static int ll_tiny_write_begin(struct page *vmpage, struct address_space *mapping)
 {
        /* Page must be present, up to date, dirty, and not in writeback. */
        if (!vmpage || !PageUptodate(vmpage) || !PageDirty(vmpage) ||
-           PageWriteback(vmpage))
+           PageWriteback(vmpage) || vmpage->mapping != mapping)
                return -ENODATA;
 
        return 0;
@@ -630,7 +630,7 @@ static int ll_write_begin(struct file *file, struct address_space *mapping,
        lcc = ll_cl_find(file);
        if (lcc == NULL) {
                vmpage = grab_cache_page_nowait(mapping, index);
-               result = ll_tiny_write_begin(vmpage);
+               result = ll_tiny_write_begin(vmpage, mapping);
                GOTO(out, result);
        }
 
@@ -689,6 +689,15 @@ again:
                }
        }
 
+       /* page was truncated */
+       if (mapping != vmpage->mapping) {
+               CDEBUG(D_VFSTRACE, "page: %lu was truncated\n", index);
+               unlock_page(vmpage);
+               put_page(vmpage);
+               vmpage = NULL;
+               goto again;
+       }
+
        page = cl_page_find(env, clob, vmpage->index, vmpage, CPT_CACHEABLE);
        if (IS_ERR(page))
                GOTO(out, result = PTR_ERR(page));