cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pagevec.c (3424B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <linux/ceph/ceph_debug.h>
      3
      4#include <linux/module.h>
      5#include <linux/sched.h>
      6#include <linux/slab.h>
      7#include <linux/file.h>
      8#include <linux/namei.h>
      9#include <linux/writeback.h>
     10
     11#include <linux/ceph/libceph.h>
     12
     13void ceph_put_page_vector(struct page **pages, int num_pages, bool dirty)
     14{
     15	int i;
     16
     17	for (i = 0; i < num_pages; i++) {
     18		if (dirty)
     19			set_page_dirty_lock(pages[i]);
     20		put_page(pages[i]);
     21	}
     22	kvfree(pages);
     23}
     24EXPORT_SYMBOL(ceph_put_page_vector);
     25
     26void ceph_release_page_vector(struct page **pages, int num_pages)
     27{
     28	int i;
     29
     30	for (i = 0; i < num_pages; i++)
     31		__free_pages(pages[i], 0);
     32	kfree(pages);
     33}
     34EXPORT_SYMBOL(ceph_release_page_vector);
     35
     36/*
     37 * allocate a vector new pages
     38 */
     39struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags)
     40{
     41	struct page **pages;
     42	int i;
     43
     44	pages = kmalloc_array(num_pages, sizeof(*pages), flags);
     45	if (!pages)
     46		return ERR_PTR(-ENOMEM);
     47	for (i = 0; i < num_pages; i++) {
     48		pages[i] = __page_cache_alloc(flags);
     49		if (pages[i] == NULL) {
     50			ceph_release_page_vector(pages, i);
     51			return ERR_PTR(-ENOMEM);
     52		}
     53	}
     54	return pages;
     55}
     56EXPORT_SYMBOL(ceph_alloc_page_vector);
     57
     58/*
     59 * copy user data into a page vector
     60 */
     61int ceph_copy_user_to_page_vector(struct page **pages,
     62					 const void __user *data,
     63					 loff_t off, size_t len)
     64{
     65	int i = 0;
     66	int po = off & ~PAGE_MASK;
     67	int left = len;
     68	int l, bad;
     69
     70	while (left > 0) {
     71		l = min_t(int, PAGE_SIZE-po, left);
     72		bad = copy_from_user(page_address(pages[i]) + po, data, l);
     73		if (bad == l)
     74			return -EFAULT;
     75		data += l - bad;
     76		left -= l - bad;
     77		po += l - bad;
     78		if (po == PAGE_SIZE) {
     79			po = 0;
     80			i++;
     81		}
     82	}
     83	return len;
     84}
     85EXPORT_SYMBOL(ceph_copy_user_to_page_vector);
     86
     87void ceph_copy_to_page_vector(struct page **pages,
     88				    const void *data,
     89				    loff_t off, size_t len)
     90{
     91	int i = 0;
     92	size_t po = off & ~PAGE_MASK;
     93	size_t left = len;
     94
     95	while (left > 0) {
     96		size_t l = min_t(size_t, PAGE_SIZE-po, left);
     97
     98		memcpy(page_address(pages[i]) + po, data, l);
     99		data += l;
    100		left -= l;
    101		po += l;
    102		if (po == PAGE_SIZE) {
    103			po = 0;
    104			i++;
    105		}
    106	}
    107}
    108EXPORT_SYMBOL(ceph_copy_to_page_vector);
    109
    110void ceph_copy_from_page_vector(struct page **pages,
    111				    void *data,
    112				    loff_t off, size_t len)
    113{
    114	int i = 0;
    115	size_t po = off & ~PAGE_MASK;
    116	size_t left = len;
    117
    118	while (left > 0) {
    119		size_t l = min_t(size_t, PAGE_SIZE-po, left);
    120
    121		memcpy(data, page_address(pages[i]) + po, l);
    122		data += l;
    123		left -= l;
    124		po += l;
    125		if (po == PAGE_SIZE) {
    126			po = 0;
    127			i++;
    128		}
    129	}
    130}
    131EXPORT_SYMBOL(ceph_copy_from_page_vector);
    132
    133/*
    134 * Zero an extent within a page vector.  Offset is relative to the
    135 * start of the first page.
    136 */
    137void ceph_zero_page_vector_range(int off, int len, struct page **pages)
    138{
    139	int i = off >> PAGE_SHIFT;
    140
    141	off &= ~PAGE_MASK;
    142
    143	dout("zero_page_vector_page %u~%u\n", off, len);
    144
    145	/* leading partial page? */
    146	if (off) {
    147		int end = min((int)PAGE_SIZE, off + len);
    148		dout("zeroing %d %p head from %d\n", i, pages[i],
    149		     (int)off);
    150		zero_user_segment(pages[i], off, end);
    151		len -= (end - off);
    152		i++;
    153	}
    154	while (len >= PAGE_SIZE) {
    155		dout("zeroing %d %p len=%d\n", i, pages[i], len);
    156		zero_user_segment(pages[i], 0, PAGE_SIZE);
    157		len -= PAGE_SIZE;
    158		i++;
    159	}
    160	/* trailing partial page? */
    161	if (len) {
    162		dout("zeroing %d %p tail to %d\n", i, pages[i], (int)len);
    163		zero_user_segment(pages[i], 0, len);
    164	}
    165}
    166EXPORT_SYMBOL(ceph_zero_page_vector_range);