Exemple #1
0
/* simple helper to fault in pages and copy.  This should go away
 * and be replaced with calls into generic code.
 */
static noinline int btrfs_copy_from_user(loff_t pos, int num_pages,
					 int write_bytes,
					 struct page **prepared_pages,
					 struct iov_iter *i)
{
	size_t copied = 0;
	int pg = 0;
	int offset = pos & (PAGE_CACHE_SIZE - 1);
	int total_copied = 0;

	while (write_bytes > 0) {
		size_t count = min_t(size_t,
				     PAGE_CACHE_SIZE - offset, write_bytes);
		struct page *page = prepared_pages[pg];
		/*
		 * Copy data from userspace to the current page
		 *
		 * Disable pagefault to avoid recursive lock since
		 * the pages are already locked
		 */
		pagefault_disable();
		copied = iov_iter_copy_from_user_atomic(page, i, offset, count);
		pagefault_enable();

		/* Flush processor's dcache for this page */
		flush_dcache_page(page);

		/*
		 * if we get a partial write, we can end up with
		 * partially up to date pages.  These add
		 * a lot of complexity, so make sure they don't
		 * happen by forcing this copy to be retried.
		 *
		 * The rest of the btrfs_file_write code will fall
		 * back to page at a time copies after we return 0.
		 */
		if (!PageUptodate(page) && copied < count)
			copied = 0;

		iov_iter_advance(i, copied);
		write_bytes -= copied;
		total_copied += copied;

		/* Return to btrfs_file_aio_write to fault page */
		if (unlikely(copied == 0)) {
			break;
		}

		if (unlikely(copied < PAGE_CACHE_SIZE - offset)) {
			offset += copied;
		} else {
			pg++;
			offset = 0;
		}
	}
	return total_copied;
}
Exemple #2
0
/* simple helper to fault in pages and copy.  This should go away
 * and be replaced with calls into generic code.
 */
static noinline int btrfs_copy_from_user(loff_t pos, int num_pages,
        int write_bytes,
        struct page **prepared_pages,
        struct iov_iter *i)
{
    size_t copied = 0;
    int pg = 0;
    int offset = pos & (PAGE_CACHE_SIZE - 1);
    int total_copied = 0;

    while (write_bytes > 0) {
        size_t count = min_t(size_t,
                             PAGE_CACHE_SIZE - offset, write_bytes);
        struct page *page = prepared_pages[pg];
        /*
         * Copy data from userspace to the current page
         *
         * Disable pagefault to avoid recursive lock since
         * the pages are already locked
         */
        pagefault_disable();
        copied = iov_iter_copy_from_user_atomic(page, i, offset, count);
        pagefault_enable();

        /* Flush processor's dcache for this page */
        flush_dcache_page(page);
        iov_iter_advance(i, copied);
        write_bytes -= copied;
        total_copied += copied;

        /* Return to btrfs_file_aio_write to fault page */
        if (unlikely(copied == 0)) {
            break;
        }

        if (unlikely(copied < PAGE_CACHE_SIZE - offset)) {
            offset += copied;
        } else {
            pg++;
            offset = 0;
        }
    }
    return total_copied;
}