Merge branch 'akpm' (incoming from Andrew)
Merge more incoming from Andrew Morton: - Various fixes which were stalled or which I picked up recently - A large rotorooting of the AIO code. Allegedly to improve performance but I don't really have good performance numbers (I might have lost the email) and I can't raise Kent today. I held this out of 3.9 and we could give it another cycle if it's all too late/scary. I ended up taking only the first two thirds of the AIO rotorooting. I left the percpu parts and the batch completion for later. - Linus * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (33 commits) aio: don't include aio.h in sched.h aio: kill ki_retry aio: kill ki_key aio: give shared kioctx fields their own cachelines aio: kill struct aio_ring_info aio: kill batch allocation aio: change reqs_active to include unreaped completions aio: use cancellation list lazily aio: use flush_dcache_page() aio: make aio_read_evt() more efficient, convert to hrtimers wait: add wait_event_hrtimeout() aio: refcounting cleanup aio: make aio_put_req() lockless aio: do fget() after aio_get_req() aio: dprintk() -> pr_debug() aio: move private stuff out of aio.h aio: add kiocb_cancel() aio: kill return value of aio_complete() char: add aio_{read,write} to /dev/{null,zero} aio: remove retry-based AIO ...
This commit is contained in:
commit
5af43c24ca
|
@ -480,7 +480,9 @@ memory.stat file includes following statistics
|
|||
|
||||
# per-memory cgroup local status
|
||||
cache - # of bytes of page cache memory.
|
||||
rss - # of bytes of anonymous and swap cache memory.
|
||||
rss - # of bytes of anonymous and swap cache memory (includes
|
||||
transparent hugepages).
|
||||
rss_huge - # of bytes of anonymous transparent hugepages.
|
||||
mapped_file - # of bytes of mapped file (includes tmpfs/shmem)
|
||||
pgpgin - # of charging events to the memory cgroup. The charging
|
||||
event happens each time a page is accounted as either mapped
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/aio.h>
|
||||
#include <asm/ebcdic.h>
|
||||
#include "hypfs.h"
|
||||
|
||||
|
|
|
@ -253,24 +253,15 @@ void __init leon_smp_done(void)
|
|||
|
||||
/* Free unneeded trap tables */
|
||||
if (!cpu_present(1)) {
|
||||
ClearPageReserved(virt_to_page(&trapbase_cpu1));
|
||||
init_page_count(virt_to_page(&trapbase_cpu1));
|
||||
free_page((unsigned long)&trapbase_cpu1);
|
||||
totalram_pages++;
|
||||
free_reserved_page(virt_to_page(&trapbase_cpu1));
|
||||
num_physpages++;
|
||||
}
|
||||
if (!cpu_present(2)) {
|
||||
ClearPageReserved(virt_to_page(&trapbase_cpu2));
|
||||
init_page_count(virt_to_page(&trapbase_cpu2));
|
||||
free_page((unsigned long)&trapbase_cpu2);
|
||||
totalram_pages++;
|
||||
free_reserved_page(virt_to_page(&trapbase_cpu2));
|
||||
num_physpages++;
|
||||
}
|
||||
if (!cpu_present(3)) {
|
||||
ClearPageReserved(virt_to_page(&trapbase_cpu3));
|
||||
init_page_count(virt_to_page(&trapbase_cpu3));
|
||||
free_page((unsigned long)&trapbase_cpu3);
|
||||
totalram_pages++;
|
||||
free_reserved_page(virt_to_page(&trapbase_cpu3));
|
||||
num_physpages++;
|
||||
}
|
||||
/* Ok, they are spinning and ready to go. */
|
||||
|
|
|
@ -366,45 +366,14 @@ void __init mem_init(void)
|
|||
|
||||
void free_initmem (void)
|
||||
{
|
||||
unsigned long addr;
|
||||
unsigned long freed;
|
||||
|
||||
addr = (unsigned long)(&__init_begin);
|
||||
freed = (unsigned long)(&__init_end) - addr;
|
||||
for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
|
||||
struct page *p;
|
||||
|
||||
memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
|
||||
p = virt_to_page(addr);
|
||||
|
||||
ClearPageReserved(p);
|
||||
init_page_count(p);
|
||||
__free_page(p);
|
||||
totalram_pages++;
|
||||
num_physpages++;
|
||||
}
|
||||
printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n",
|
||||
freed >> 10);
|
||||
num_physpages += free_initmem_default(POISON_FREE_INITMEM);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
void free_initrd_mem(unsigned long start, unsigned long end)
|
||||
{
|
||||
if (start < end)
|
||||
printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
|
||||
(end - start) >> 10);
|
||||
for (; start < end; start += PAGE_SIZE) {
|
||||
struct page *p;
|
||||
|
||||
memset((void *)start, POISON_FREE_INITMEM, PAGE_SIZE);
|
||||
p = virt_to_page(start);
|
||||
|
||||
ClearPageReserved(p);
|
||||
init_page_count(p);
|
||||
__free_page(p);
|
||||
totalram_pages++;
|
||||
num_physpages++;
|
||||
}
|
||||
num_physpages += free_reserved_area(start, end, POISON_FREE_INITMEM,
|
||||
"initrd");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -2059,8 +2059,7 @@ void __init mem_init(void)
|
|||
/* We subtract one to account for the mem_map_zero page
|
||||
* allocated below.
|
||||
*/
|
||||
totalram_pages -= 1;
|
||||
num_physpages = totalram_pages;
|
||||
num_physpages = totalram_pages - 1;
|
||||
|
||||
/*
|
||||
* Set up the zero page, mark it reserved, so that page count
|
||||
|
@ -2071,7 +2070,7 @@ void __init mem_init(void)
|
|||
prom_printf("paging_init: Cannot alloc zero page.\n");
|
||||
prom_halt();
|
||||
}
|
||||
SetPageReserved(mem_map_zero);
|
||||
mark_page_reserved(mem_map_zero);
|
||||
|
||||
codepages = (((unsigned long) _etext) - ((unsigned long) _start));
|
||||
codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT;
|
||||
|
@ -2111,37 +2110,22 @@ void free_initmem(void)
|
|||
initend = (unsigned long)(__init_end) & PAGE_MASK;
|
||||
for (; addr < initend; addr += PAGE_SIZE) {
|
||||
unsigned long page;
|
||||
struct page *p;
|
||||
|
||||
page = (addr +
|
||||
((unsigned long) __va(kern_base)) -
|
||||
((unsigned long) KERNBASE));
|
||||
memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
|
||||
|
||||
if (do_free) {
|
||||
p = virt_to_page(page);
|
||||
|
||||
ClearPageReserved(p);
|
||||
init_page_count(p);
|
||||
__free_page(p);
|
||||
totalram_pages++;
|
||||
}
|
||||
if (do_free)
|
||||
free_reserved_page(virt_to_page(page));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
void free_initrd_mem(unsigned long start, unsigned long end)
|
||||
{
|
||||
if (start < end)
|
||||
printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
|
||||
for (; start < end; start += PAGE_SIZE) {
|
||||
struct page *p = virt_to_page(start);
|
||||
|
||||
ClearPageReserved(p);
|
||||
init_page_count(p);
|
||||
__free_page(p);
|
||||
totalram_pages++;
|
||||
}
|
||||
num_physpages += free_reserved_area(start, end, POISON_FREE_INITMEM,
|
||||
"initrd");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/ratelimit.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/times.h>
|
||||
#include <linux/uio.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/pfn.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
|
@ -627,6 +628,18 @@ static ssize_t write_null(struct file *file, const char __user *buf,
|
|||
return count;
|
||||
}
|
||||
|
||||
static ssize_t aio_read_null(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t pos)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t aio_write_null(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t pos)
|
||||
{
|
||||
return iov_length(iov, nr_segs);
|
||||
}
|
||||
|
||||
static int pipe_to_null(struct pipe_inode_info *info, struct pipe_buffer *buf,
|
||||
struct splice_desc *sd)
|
||||
{
|
||||
|
@ -670,6 +683,24 @@ static ssize_t read_zero(struct file *file, char __user *buf,
|
|||
return written ? written : -EFAULT;
|
||||
}
|
||||
|
||||
static ssize_t aio_read_zero(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t pos)
|
||||
{
|
||||
size_t written = 0;
|
||||
unsigned long i;
|
||||
ssize_t ret;
|
||||
|
||||
for (i = 0; i < nr_segs; i++) {
|
||||
ret = read_zero(iocb->ki_filp, iov[i].iov_base, iov[i].iov_len,
|
||||
&pos);
|
||||
if (ret < 0)
|
||||
break;
|
||||
written += ret;
|
||||
}
|
||||
|
||||
return written ? written : -EFAULT;
|
||||
}
|
||||
|
||||
static int mmap_zero(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
#ifndef CONFIG_MMU
|
||||
|
@ -738,6 +769,7 @@ static int open_port(struct inode *inode, struct file *filp)
|
|||
#define full_lseek null_lseek
|
||||
#define write_zero write_null
|
||||
#define read_full read_zero
|
||||
#define aio_write_zero aio_write_null
|
||||
#define open_mem open_port
|
||||
#define open_kmem open_mem
|
||||
#define open_oldmem open_mem
|
||||
|
@ -766,6 +798,8 @@ static const struct file_operations null_fops = {
|
|||
.llseek = null_lseek,
|
||||
.read = read_null,
|
||||
.write = write_null,
|
||||
.aio_read = aio_read_null,
|
||||
.aio_write = aio_write_null,
|
||||
.splice_write = splice_write_null,
|
||||
};
|
||||
|
||||
|
@ -782,6 +816,8 @@ static const struct file_operations zero_fops = {
|
|||
.llseek = zero_lseek,
|
||||
.read = read_zero,
|
||||
.write = write_zero,
|
||||
.aio_read = aio_read_zero,
|
||||
.aio_write = aio_write_zero,
|
||||
.mmap = mmap_zero,
|
||||
};
|
||||
|
||||
|
|
|
@ -62,13 +62,13 @@ static int __cxio_init_resource_fifo(struct kfifo *fifo,
|
|||
kfifo_in(fifo, (unsigned char *) &entry, sizeof(u32));
|
||||
if (random) {
|
||||
j = 0;
|
||||
random_bytes = random32();
|
||||
random_bytes = prandom_u32();
|
||||
for (i = 0; i < RANDOM_SIZE; i++)
|
||||
rarray[i] = i + skip_low;
|
||||
for (i = skip_low + RANDOM_SIZE; i < nr - skip_high; i++) {
|
||||
if (j >= RANDOM_SIZE) {
|
||||
j = 0;
|
||||
random_bytes = random32();
|
||||
random_bytes = prandom_u32();
|
||||
}
|
||||
idx = (random_bytes >> (j * 2)) & 0xF;
|
||||
kfifo_in(fifo,
|
||||
|
|
|
@ -54,7 +54,7 @@ u32 c4iw_id_alloc(struct c4iw_id_table *alloc)
|
|||
|
||||
if (obj < alloc->max) {
|
||||
if (alloc->flags & C4IW_ID_TABLE_F_RANDOM)
|
||||
alloc->last += random32() % RANDOM_SKIP;
|
||||
alloc->last += prandom_u32() % RANDOM_SKIP;
|
||||
else
|
||||
alloc->last = obj + 1;
|
||||
if (alloc->last >= alloc->max)
|
||||
|
@ -88,7 +88,7 @@ int c4iw_id_table_alloc(struct c4iw_id_table *alloc, u32 start, u32 num,
|
|||
alloc->start = start;
|
||||
alloc->flags = flags;
|
||||
if (flags & C4IW_ID_TABLE_F_RANDOM)
|
||||
alloc->last = random32() % RANDOM_SKIP;
|
||||
alloc->last = prandom_u32() % RANDOM_SKIP;
|
||||
else
|
||||
alloc->last = 0;
|
||||
alloc->max = num;
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/aio.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
|
|
@ -93,7 +93,7 @@ static void __propagate_pkey_ev(struct mlx4_ib_dev *dev, int port_num,
|
|||
__be64 mlx4_ib_gen_node_guid(void)
|
||||
{
|
||||
#define NODE_GUID_HI ((u64) (((u64)IB_OPENIB_OUI) << 40))
|
||||
return cpu_to_be64(NODE_GUID_HI | random32());
|
||||
return cpu_to_be64(NODE_GUID_HI | prandom_u32());
|
||||
}
|
||||
|
||||
__be64 mlx4_ib_get_new_demux_tid(struct mlx4_ib_demux_ctx *ctx)
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
#include <linux/vmalloc.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/aio.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <linux/delay.h>
|
||||
|
|
|
@ -460,7 +460,7 @@ static int ipoib_cm_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even
|
|||
goto err_qp;
|
||||
}
|
||||
|
||||
psn = random32() & 0xffffff;
|
||||
psn = prandom_u32() & 0xffffff;
|
||||
ret = ipoib_cm_modify_rx_qp(dev, cm_id, p->qp, psn);
|
||||
if (ret)
|
||||
goto err_modify;
|
||||
|
|
|
@ -4085,7 +4085,7 @@ static int cnic_cm_alloc_mem(struct cnic_dev *dev)
|
|||
if (!cp->csk_tbl)
|
||||
return -ENOMEM;
|
||||
|
||||
port_id = random32();
|
||||
port_id = prandom_u32();
|
||||
port_id %= CNIC_LOCAL_PORT_RANGE;
|
||||
if (cnic_init_id_tbl(&cp->csk_port_tbl, CNIC_LOCAL_PORT_RANGE,
|
||||
CNIC_LOCAL_PORT_MIN, port_id)) {
|
||||
|
@ -4145,7 +4145,7 @@ static int cnic_cm_init_bnx2_hw(struct cnic_dev *dev)
|
|||
{
|
||||
u32 seed;
|
||||
|
||||
seed = random32();
|
||||
seed = prandom_u32();
|
||||
cnic_ctx_wr(dev, 45, 0, seed);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -449,7 +449,7 @@ static int transmit(struct baycom_state *bc, int cnt, unsigned char stat)
|
|||
if ((--bc->hdlctx.slotcnt) > 0)
|
||||
return 0;
|
||||
bc->hdlctx.slotcnt = bc->ch_params.slottime;
|
||||
if ((random32() % 256) > bc->ch_params.ppersist)
|
||||
if ((prandom_u32() % 256) > bc->ch_params.ppersist)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -389,7 +389,7 @@ void hdlcdrv_arbitrate(struct net_device *dev, struct hdlcdrv_state *s)
|
|||
if ((--s->hdlctx.slotcnt) > 0)
|
||||
return;
|
||||
s->hdlctx.slotcnt = s->ch_params.slottime;
|
||||
if ((random32() % 256) > s->ch_params.ppersist)
|
||||
if ((prandom_u32() % 256) > s->ch_params.ppersist)
|
||||
return;
|
||||
start_tx(dev, s);
|
||||
}
|
||||
|
|
|
@ -638,7 +638,7 @@ static void yam_arbitrate(struct net_device *dev)
|
|||
yp->slotcnt = yp->slot / 10;
|
||||
|
||||
/* is random > persist ? */
|
||||
if ((random32() % 256) > yp->pers)
|
||||
if ((prandom_u32() % 256) > yp->pers)
|
||||
return;
|
||||
|
||||
yam_start_tx(dev, yp);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
static u32 random_N(unsigned int N)
|
||||
{
|
||||
return reciprocal_divide(random32(), N);
|
||||
return reciprocal_divide(prandom_u32(), N);
|
||||
}
|
||||
|
||||
static bool rnd_transmit(struct team *team, struct sk_buff *skb)
|
||||
|
|
|
@ -1117,7 +1117,7 @@ static void brcmf_p2p_afx_handler(struct work_struct *work)
|
|||
if (afx_hdl->is_listen && afx_hdl->my_listen_chan)
|
||||
/* 100ms ~ 300ms */
|
||||
err = brcmf_p2p_discover_listen(p2p, afx_hdl->my_listen_chan,
|
||||
100 * (1 + (random32() % 3)));
|
||||
100 * (1 + prandom_u32() % 3));
|
||||
else
|
||||
err = brcmf_p2p_act_frm_search(p2p, afx_hdl->peer_listen_chan);
|
||||
|
||||
|
|
|
@ -216,7 +216,7 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
mwifiex_form_mgmt_frame(skb, buf, len);
|
||||
mwifiex_queue_tx_pkt(priv, skb);
|
||||
|
||||
*cookie = random32() | 1;
|
||||
*cookie = prandom_u32() | 1;
|
||||
cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, GFP_ATOMIC);
|
||||
|
||||
wiphy_dbg(wiphy, "info: management frame transmitted\n");
|
||||
|
@ -271,7 +271,7 @@ mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
|
|||
duration);
|
||||
|
||||
if (!ret) {
|
||||
*cookie = random32() | 1;
|
||||
*cookie = prandom_u32() | 1;
|
||||
priv->roc_cfg.cookie = *cookie;
|
||||
priv->roc_cfg.chan = *chan;
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
enum rtc_type {
|
||||
rtc_undef = 0,
|
||||
rtc_r2025sd,
|
||||
rtc_r2221tl,
|
||||
rtc_rs5c372a,
|
||||
rtc_rs5c372b,
|
||||
rtc_rv5c386,
|
||||
|
@ -76,6 +77,7 @@ enum rtc_type {
|
|||
|
||||
static const struct i2c_device_id rs5c372_id[] = {
|
||||
{ "r2025sd", rtc_r2025sd },
|
||||
{ "r2221tl", rtc_r2221tl },
|
||||
{ "rs5c372a", rtc_rs5c372a },
|
||||
{ "rs5c372b", rtc_rs5c372b },
|
||||
{ "rv5c386", rtc_rv5c386 },
|
||||
|
@ -529,6 +531,7 @@ static int rs5c_oscillator_setup(struct rs5c372 *rs5c372)
|
|||
rs5c372->time24 = 1;
|
||||
break;
|
||||
case rtc_r2025sd:
|
||||
case rtc_r2221tl:
|
||||
case rtc_rv5c386:
|
||||
case rtc_rv5c387a:
|
||||
buf[0] |= RV5C387_CTRL1_24;
|
||||
|
@ -609,6 +612,7 @@ static int rs5c372_probe(struct i2c_client *client,
|
|||
rs5c372->time24 = 1;
|
||||
break;
|
||||
case rtc_r2025sd:
|
||||
case rtc_r2221tl:
|
||||
case rtc_rv5c386:
|
||||
case rtc_rv5c387a:
|
||||
if (rs5c372->regs[RS5C_REG_CTRL1] & RV5C387_CTRL1_24)
|
||||
|
@ -640,6 +644,7 @@ static int rs5c372_probe(struct i2c_client *client,
|
|||
dev_info(&client->dev, "%s found, %s, driver version " DRV_VERSION "\n",
|
||||
({ char *s; switch (rs5c372->type) {
|
||||
case rtc_r2025sd: s = "r2025sd"; break;
|
||||
case rtc_r2221tl: s = "r2221tl"; break;
|
||||
case rtc_rs5c372a: s = "rs5c372a"; break;
|
||||
case rtc_rs5c372b: s = "rs5c372b"; break;
|
||||
case rtc_rv5c386: s = "rv5c386"; break;
|
||||
|
|
|
@ -35,6 +35,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */
|
|||
#include <linux/sched.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/aio.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mtio.h>
|
||||
#include <linux/ioctl.h>
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/aio.h>
|
||||
#include "logger.h"
|
||||
|
||||
#include <asm/ioctls.h>
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/mmu_context.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
@ -513,6 +515,9 @@ static long ep_ioctl(struct file *fd, unsigned code, unsigned long value)
|
|||
struct kiocb_priv {
|
||||
struct usb_request *req;
|
||||
struct ep_data *epdata;
|
||||
struct kiocb *iocb;
|
||||
struct mm_struct *mm;
|
||||
struct work_struct work;
|
||||
void *buf;
|
||||
const struct iovec *iv;
|
||||
unsigned long nr_segs;
|
||||
|
@ -528,7 +533,6 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
|
|||
local_irq_disable();
|
||||
epdata = priv->epdata;
|
||||
// spin_lock(&epdata->dev->lock);
|
||||
kiocbSetCancelled(iocb);
|
||||
if (likely(epdata && epdata->ep && priv->req))
|
||||
value = usb_ep_dequeue (epdata->ep, priv->req);
|
||||
else
|
||||
|
@ -540,15 +544,12 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
|
|||
return value;
|
||||
}
|
||||
|
||||
static ssize_t ep_aio_read_retry(struct kiocb *iocb)
|
||||
static ssize_t ep_copy_to_user(struct kiocb_priv *priv)
|
||||
{
|
||||
struct kiocb_priv *priv = iocb->private;
|
||||
ssize_t len, total;
|
||||
void *to_copy;
|
||||
int i;
|
||||
|
||||
/* we "retry" to get the right mm context for this: */
|
||||
|
||||
/* copy stuff into user buffers */
|
||||
total = priv->actual;
|
||||
len = 0;
|
||||
|
@ -568,9 +569,26 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb)
|
|||
if (total == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void ep_user_copy_worker(struct work_struct *work)
|
||||
{
|
||||
struct kiocb_priv *priv = container_of(work, struct kiocb_priv, work);
|
||||
struct mm_struct *mm = priv->mm;
|
||||
struct kiocb *iocb = priv->iocb;
|
||||
size_t ret;
|
||||
|
||||
use_mm(mm);
|
||||
ret = ep_copy_to_user(priv);
|
||||
unuse_mm(mm);
|
||||
|
||||
/* completing the iocb can drop the ctx and mm, don't touch mm after */
|
||||
aio_complete(iocb, ret, ret);
|
||||
|
||||
kfree(priv->buf);
|
||||
kfree(priv);
|
||||
return len;
|
||||
}
|
||||
|
||||
static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
|
||||
|
@ -596,14 +614,14 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
|
|||
aio_complete(iocb, req->actual ? req->actual : req->status,
|
||||
req->status);
|
||||
} else {
|
||||
/* retry() won't report both; so we hide some faults */
|
||||
/* ep_copy_to_user() won't report both; we hide some faults */
|
||||
if (unlikely(0 != req->status))
|
||||
DBG(epdata->dev, "%s fault %d len %d\n",
|
||||
ep->name, req->status, req->actual);
|
||||
|
||||
priv->buf = req->buf;
|
||||
priv->actual = req->actual;
|
||||
kick_iocb(iocb);
|
||||
schedule_work(&priv->work);
|
||||
}
|
||||
spin_unlock(&epdata->dev->lock);
|
||||
|
||||
|
@ -633,8 +651,10 @@ fail:
|
|||
return value;
|
||||
}
|
||||
iocb->private = priv;
|
||||
priv->iocb = iocb;
|
||||
priv->iv = iv;
|
||||
priv->nr_segs = nr_segs;
|
||||
INIT_WORK(&priv->work, ep_user_copy_worker);
|
||||
|
||||
value = get_ready_ep(iocb->ki_filp->f_flags, epdata);
|
||||
if (unlikely(value < 0)) {
|
||||
|
@ -642,10 +662,11 @@ fail:
|
|||
goto fail;
|
||||
}
|
||||
|
||||
iocb->ki_cancel = ep_aio_cancel;
|
||||
kiocb_set_cancel_fn(iocb, ep_aio_cancel);
|
||||
get_ep(epdata);
|
||||
priv->epdata = epdata;
|
||||
priv->actual = 0;
|
||||
priv->mm = current->mm; /* mm teardown waits for iocbs in exit_aio() */
|
||||
|
||||
/* each kiocb is coupled to one usb_request, but we can't
|
||||
* allocate or submit those if the host disconnected.
|
||||
|
@ -674,7 +695,7 @@ fail:
|
|||
kfree(priv);
|
||||
put_ep(epdata);
|
||||
} else
|
||||
value = (iv ? -EIOCBRETRY : -EIOCBQUEUED);
|
||||
value = -EIOCBQUEUED;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -692,7 +713,6 @@ ep_aio_read(struct kiocb *iocb, const struct iovec *iov,
|
|||
if (unlikely(!buf))
|
||||
return -ENOMEM;
|
||||
|
||||
iocb->ki_retry = ep_aio_read_retry;
|
||||
return ep_aio_rwtail(iocb, buf, iocb->ki_left, epdata, iov, nr_segs);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/pagemap.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/aio.h>
|
||||
#include <net/9p/9p.h>
|
||||
#include <net/9p/client.h>
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/pagemap.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/pagevec.h>
|
||||
#include <linux/aio.h>
|
||||
#include "internal.h"
|
||||
|
||||
static int afs_write_back_from_locked_page(struct afs_writeback *wb,
|
||||
|
|
1
fs/bio.c
1
fs/bio.c
|
@ -19,6 +19,7 @@
|
|||
#include <linux/swap.h>
|
||||
#include <linux/bio.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/iocontext.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/namei.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/cleancache.h>
|
||||
#include <linux/aio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "internal.h"
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/backing-dev.h>
|
||||
#include <linux/mpage.h>
|
||||
#include <linux/aio.h>
|
||||
#include <linux/falloc.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/writeback.h>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/writeback.h>
|
||||
#include <linux/statfs.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/aio.h>
|
||||
#include <linux/bit_spinlock.h>
|
||||
#include <linux/xattr.h>
|
||||
#include <linux/posix_acl.h>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/mount.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
#include "super.h"
|
||||
#include "mds_client.h"
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include <linux/fs_struct.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/mmu_context.h>
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <linux/uio.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/prefetch.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
/*
|
||||
* How many user pages to map in one call to get_user_pages(). This determines
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/security.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/fs_stack.h>
|
||||
#include <linux/aio.h>
|
||||
#include "ecryptfs_kernel.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/mpage.h>
|
||||
#include <linux/fiemap.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/aio.h>
|
||||
#include "ext2.h"
|
||||
#include "acl.h"
|
||||
#include "xip.h"
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/writeback.h>
|
||||
#include <linux/mpage.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/aio.h>
|
||||
#include "ext3.h"
|
||||
#include "xattr.h"
|
||||
#include "acl.h"
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/jbd2.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/path.h>
|
||||
#include <linux/aio.h>
|
||||
#include <linux/quotaops.h>
|
||||
#include <linux/pagevec.h>
|
||||
#include "ext4.h"
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* (sct@redhat.com), 1993, 1998
|
||||
*/
|
||||
|
||||
#include <linux/aio.h>
|
||||
#include "ext4_jbd2.h"
|
||||
#include "truncate.h"
|
||||
#include "ext4_extents.h" /* Needed for EXT_MAX_BLOCKS */
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <linux/printk.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
#include "ext4_jbd2.h"
|
||||
#include "xattr.h"
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/pagevec.h>
|
||||
#include <linux/mpage.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/aio.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/bio.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/f2fs_fs.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/mpage.h>
|
||||
#include <linux/aio.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/backing-dev.h>
|
||||
#include <linux/blkdev.h>
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/mpage.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/aio.h>
|
||||
#include <linux/vfs.h>
|
||||
#include <linux/parser.h>
|
||||
#include <linux/uio.h>
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/aio.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/list.h>
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/pipe_fs_i.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/splice.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
MODULE_ALIAS_MISCDEV(FUSE_MINOR);
|
||||
MODULE_ALIAS("devname:fuse");
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
static const struct file_operations fuse_direct_io_file_operations;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/swap.h>
|
||||
#include <linux/gfs2_ondisk.h>
|
||||
#include <linux/backing-dev.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
#include "gfs2.h"
|
||||
#include "incore.h"
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <asm/uaccess.h>
|
||||
#include <linux/dlm.h>
|
||||
#include <linux/dlm_plock.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
#include "gfs2.h"
|
||||
#include "incore.h"
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/pagemap.h>
|
||||
#include <linux/mpage.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
#include "hfs_fs.h"
|
||||
#include "btree.h"
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/pagemap.h>
|
||||
#include <linux/mpage.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
#include "hfsplus_fs.h"
|
||||
#include "hfsplus_raw.h"
|
||||
|
|
|
@ -909,11 +909,8 @@ static int can_do_hugetlb_shm(void)
|
|||
|
||||
static int get_hstate_idx(int page_size_log)
|
||||
{
|
||||
struct hstate *h;
|
||||
struct hstate *h = hstate_sizelog(page_size_log);
|
||||
|
||||
if (!page_size_log)
|
||||
return default_hstate_idx;
|
||||
h = size_to_hstate(1 << page_size_log);
|
||||
if (!h)
|
||||
return -1;
|
||||
return h - hstates;
|
||||
|
@ -929,9 +926,12 @@ static struct dentry_operations anon_ops = {
|
|||
.d_dname = hugetlb_dname
|
||||
};
|
||||
|
||||
struct file *hugetlb_file_setup(const char *name, unsigned long addr,
|
||||
size_t size, vm_flags_t acctflag,
|
||||
struct user_struct **user,
|
||||
/*
|
||||
* Note that size should be aligned to proper hugepage size in caller side,
|
||||
* otherwise hugetlb_reserve_pages reserves one less hugepages than intended.
|
||||
*/
|
||||
struct file *hugetlb_file_setup(const char *name, size_t size,
|
||||
vm_flags_t acctflag, struct user_struct **user,
|
||||
int creat_flags, int page_size_log)
|
||||
{
|
||||
struct file *file = ERR_PTR(-ENOMEM);
|
||||
|
@ -939,8 +939,6 @@ struct file *hugetlb_file_setup(const char *name, unsigned long addr,
|
|||
struct path path;
|
||||
struct super_block *sb;
|
||||
struct qstr quick_string;
|
||||
struct hstate *hstate;
|
||||
unsigned long num_pages;
|
||||
int hstate_idx;
|
||||
|
||||
hstate_idx = get_hstate_idx(page_size_log);
|
||||
|
@ -980,12 +978,10 @@ struct file *hugetlb_file_setup(const char *name, unsigned long addr,
|
|||
if (!inode)
|
||||
goto out_dentry;
|
||||
|
||||
hstate = hstate_inode(inode);
|
||||
size += addr & ~huge_page_mask(hstate);
|
||||
num_pages = ALIGN(size, huge_page_size(hstate)) >>
|
||||
huge_page_shift(hstate);
|
||||
file = ERR_PTR(-ENOMEM);
|
||||
if (hugetlb_reserve_pages(inode, 0, num_pages, NULL, acctflag))
|
||||
if (hugetlb_reserve_pages(inode, 0,
|
||||
size >> huge_page_shift(hstate_inode(inode)), NULL,
|
||||
acctflag))
|
||||
goto out_inode;
|
||||
|
||||
d_instantiate(path.dentry, inode);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/pagemap.h>
|
||||
#include <linux/quotaops.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/aio.h>
|
||||
#include "jfs_incore.h"
|
||||
#include "jfs_inode.h"
|
||||
#include "jfs_filsys.h"
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include <linux/gfp.h>
|
||||
#include <linux/mpage.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/aio.h>
|
||||
#include "nilfs.h"
|
||||
#include "btnode.h"
|
||||
#include "segment.h"
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/swap.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/quotaops.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
#include "aops.h"
|
||||
#include "attrib.h"
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#ifndef OCFS2_AOPS_H
|
||||
#define OCFS2_AOPS_H
|
||||
|
||||
#include <linux/aio.h>
|
||||
|
||||
handle_t *ocfs2_start_walk_page_trans(struct inode *inode,
|
||||
struct page *page,
|
||||
unsigned from,
|
||||
|
|
|
@ -2322,7 +2322,7 @@ int ocfs2_inode_lock_full_nested(struct inode *inode,
|
|||
status = __ocfs2_cluster_lock(osb, lockres, level, dlm_flags,
|
||||
arg_flags, subclass, _RET_IP_);
|
||||
if (status < 0) {
|
||||
if (status != -EAGAIN && status != -EIOCBRETRY)
|
||||
if (status != -EAGAIN)
|
||||
mlog_errno(status);
|
||||
goto bail;
|
||||
}
|
||||
|
|
|
@ -147,8 +147,6 @@ void ocfs2_refresh_inode(struct inode *inode,
|
|||
int ocfs2_mark_inode_dirty(handle_t *handle,
|
||||
struct inode *inode,
|
||||
struct buffer_head *bh);
|
||||
int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb);
|
||||
int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb);
|
||||
struct buffer_head *ocfs2_bread(struct inode *inode,
|
||||
int block, int *err, int reada);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/audit.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/ioctls.h>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <linux/fcntl.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/aio.h>
|
||||
#include <linux/fsnotify.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/export.h>
|
||||
|
@ -329,16 +330,6 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count
|
|||
return count > MAX_RW_COUNT ? MAX_RW_COUNT : count;
|
||||
}
|
||||
|
||||
static void wait_on_retry_sync_kiocb(struct kiocb *iocb)
|
||||
{
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
if (!kiocbIsKicked(iocb))
|
||||
schedule();
|
||||
else
|
||||
kiocbClearKicked(iocb);
|
||||
__set_current_state(TASK_RUNNING);
|
||||
}
|
||||
|
||||
ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
|
||||
{
|
||||
struct iovec iov = { .iov_base = buf, .iov_len = len };
|
||||
|
@ -350,13 +341,7 @@ ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *pp
|
|||
kiocb.ki_left = len;
|
||||
kiocb.ki_nbytes = len;
|
||||
|
||||
for (;;) {
|
||||
ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
|
||||
if (ret != -EIOCBRETRY)
|
||||
break;
|
||||
wait_on_retry_sync_kiocb(&kiocb);
|
||||
}
|
||||
|
||||
ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos);
|
||||
if (-EIOCBQUEUED == ret)
|
||||
ret = wait_on_sync_kiocb(&kiocb);
|
||||
*ppos = kiocb.ki_pos;
|
||||
|
@ -406,13 +391,7 @@ ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, lof
|
|||
kiocb.ki_left = len;
|
||||
kiocb.ki_nbytes = len;
|
||||
|
||||
for (;;) {
|
||||
ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
|
||||
if (ret != -EIOCBRETRY)
|
||||
break;
|
||||
wait_on_retry_sync_kiocb(&kiocb);
|
||||
}
|
||||
|
||||
ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
|
||||
if (-EIOCBQUEUED == ret)
|
||||
ret = wait_on_sync_kiocb(&kiocb);
|
||||
*ppos = kiocb.ki_pos;
|
||||
|
@ -592,13 +571,7 @@ static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
|
|||
kiocb.ki_left = len;
|
||||
kiocb.ki_nbytes = len;
|
||||
|
||||
for (;;) {
|
||||
ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos);
|
||||
if (ret != -EIOCBRETRY)
|
||||
break;
|
||||
wait_on_retry_sync_kiocb(&kiocb);
|
||||
}
|
||||
|
||||
ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos);
|
||||
if (ret == -EIOCBQUEUED)
|
||||
ret = wait_on_sync_kiocb(&kiocb);
|
||||
*ppos = kiocb.ki_pos;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/writeback.h>
|
||||
#include <linux/quotaops.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
int reiserfs_commit_write(struct file *f, struct page *page,
|
||||
unsigned from, unsigned to);
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
*/
|
||||
|
||||
#include "ubifs.h"
|
||||
#include <linux/aio.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/slab.h>
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/crc-itu-t.h>
|
||||
#include <linux/mpage.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
#include "udf_i.h"
|
||||
#include "udf_sb.h"
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "xfs_vnodeops.h"
|
||||
#include "xfs_trace.h"
|
||||
#include "xfs_bmap.h"
|
||||
#include <linux/aio.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/mpage.h>
|
||||
#include <linux/pagevec.h>
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "xfs_ioctl.h"
|
||||
#include "xfs_trace.h"
|
||||
|
||||
#include <linux/aio.h>
|
||||
#include <linux/dcache.h>
|
||||
#include <linux/falloc.h>
|
||||
#include <linux/pagevec.h>
|
||||
|
|
|
@ -9,91 +9,32 @@
|
|||
|
||||
#include <linux/atomic.h>
|
||||
|
||||
#define AIO_MAXSEGS 4
|
||||
#define AIO_KIOGRP_NR_ATOMIC 8
|
||||
|
||||
struct kioctx;
|
||||
struct kiocb;
|
||||
|
||||
/* Notes on cancelling a kiocb:
|
||||
* If a kiocb is cancelled, aio_complete may return 0 to indicate
|
||||
* that cancel has not yet disposed of the kiocb. All cancel
|
||||
* operations *must* call aio_put_req to dispose of the kiocb
|
||||
* to guard against races with the completion code.
|
||||
*/
|
||||
#define KIOCB_C_CANCELLED 0x01
|
||||
#define KIOCB_C_COMPLETE 0x02
|
||||
#define KIOCB_KEY 0
|
||||
|
||||
#define KIOCB_SYNC_KEY (~0U)
|
||||
|
||||
/* ki_flags bits */
|
||||
/*
|
||||
* This may be used for cancel/retry serialization in the future, but
|
||||
* for now it's unused and we probably don't want modules to even
|
||||
* think they can use it.
|
||||
* We use ki_cancel == KIOCB_CANCELLED to indicate that a kiocb has been either
|
||||
* cancelled or completed (this makes a certain amount of sense because
|
||||
* successful cancellation - io_cancel() - does deliver the completion to
|
||||
* userspace).
|
||||
*
|
||||
* And since most things don't implement kiocb cancellation and we'd really like
|
||||
* kiocb completion to be lockless when possible, we use ki_cancel to
|
||||
* synchronize cancellation and completion - we only set it to KIOCB_CANCELLED
|
||||
* with xchg() or cmpxchg(), see batch_complete_aio() and kiocb_cancel().
|
||||
*/
|
||||
/* #define KIF_LOCKED 0 */
|
||||
#define KIF_KICKED 1
|
||||
#define KIF_CANCELLED 2
|
||||
#define KIOCB_CANCELLED ((void *) (~0ULL))
|
||||
|
||||
#define kiocbTryLock(iocb) test_and_set_bit(KIF_LOCKED, &(iocb)->ki_flags)
|
||||
#define kiocbTryKick(iocb) test_and_set_bit(KIF_KICKED, &(iocb)->ki_flags)
|
||||
typedef int (kiocb_cancel_fn)(struct kiocb *, struct io_event *);
|
||||
|
||||
#define kiocbSetLocked(iocb) set_bit(KIF_LOCKED, &(iocb)->ki_flags)
|
||||
#define kiocbSetKicked(iocb) set_bit(KIF_KICKED, &(iocb)->ki_flags)
|
||||
#define kiocbSetCancelled(iocb) set_bit(KIF_CANCELLED, &(iocb)->ki_flags)
|
||||
|
||||
#define kiocbClearLocked(iocb) clear_bit(KIF_LOCKED, &(iocb)->ki_flags)
|
||||
#define kiocbClearKicked(iocb) clear_bit(KIF_KICKED, &(iocb)->ki_flags)
|
||||
#define kiocbClearCancelled(iocb) clear_bit(KIF_CANCELLED, &(iocb)->ki_flags)
|
||||
|
||||
#define kiocbIsLocked(iocb) test_bit(KIF_LOCKED, &(iocb)->ki_flags)
|
||||
#define kiocbIsKicked(iocb) test_bit(KIF_KICKED, &(iocb)->ki_flags)
|
||||
#define kiocbIsCancelled(iocb) test_bit(KIF_CANCELLED, &(iocb)->ki_flags)
|
||||
|
||||
/* is there a better place to document function pointer methods? */
|
||||
/**
|
||||
* ki_retry - iocb forward progress callback
|
||||
* @kiocb: The kiocb struct to advance by performing an operation.
|
||||
*
|
||||
* This callback is called when the AIO core wants a given AIO operation
|
||||
* to make forward progress. The kiocb argument describes the operation
|
||||
* that is to be performed. As the operation proceeds, perhaps partially,
|
||||
* ki_retry is expected to update the kiocb with progress made. Typically
|
||||
* ki_retry is set in the AIO core and it itself calls file_operations
|
||||
* helpers.
|
||||
*
|
||||
* ki_retry's return value determines when the AIO operation is completed
|
||||
* and an event is generated in the AIO event ring. Except the special
|
||||
* return values described below, the value that is returned from ki_retry
|
||||
* is transferred directly into the completion ring as the operation's
|
||||
* resulting status. Once this has happened ki_retry *MUST NOT* reference
|
||||
* the kiocb pointer again.
|
||||
*
|
||||
* If ki_retry returns -EIOCBQUEUED it has made a promise that aio_complete()
|
||||
* will be called on the kiocb pointer in the future. The AIO core will
|
||||
* not ask the method again -- ki_retry must ensure forward progress.
|
||||
* aio_complete() must be called once and only once in the future, multiple
|
||||
* calls may result in undefined behaviour.
|
||||
*
|
||||
* If ki_retry returns -EIOCBRETRY it has made a promise that kick_iocb()
|
||||
* will be called on the kiocb pointer in the future. This may happen
|
||||
* through generic helpers that associate kiocb->ki_wait with a wait
|
||||
* queue head that ki_retry uses via current->io_wait. It can also happen
|
||||
* with custom tracking and manual calls to kick_iocb(), though that is
|
||||
* discouraged. In either case, kick_iocb() must be called once and only
|
||||
* once. ki_retry must ensure forward progress, the AIO core will wait
|
||||
* indefinitely for kick_iocb() to be called.
|
||||
*/
|
||||
struct kiocb {
|
||||
struct list_head ki_run_list;
|
||||
unsigned long ki_flags;
|
||||
int ki_users;
|
||||
unsigned ki_key; /* id of this request */
|
||||
atomic_t ki_users;
|
||||
|
||||
struct file *ki_filp;
|
||||
struct kioctx *ki_ctx; /* may be NULL for sync ops */
|
||||
int (*ki_cancel)(struct kiocb *, struct io_event *);
|
||||
ssize_t (*ki_retry)(struct kiocb *);
|
||||
struct kioctx *ki_ctx; /* NULL for sync ops */
|
||||
kiocb_cancel_fn *ki_cancel;
|
||||
void (*ki_dtor)(struct kiocb *);
|
||||
|
||||
union {
|
||||
|
@ -117,7 +58,6 @@ struct kiocb {
|
|||
|
||||
struct list_head ki_list; /* the aio core uses this
|
||||
* for cancellation */
|
||||
struct list_head ki_batch; /* batch allocation */
|
||||
|
||||
/*
|
||||
* If the aio_resfd field of the userspace iocb is not zero,
|
||||
|
@ -128,106 +68,40 @@ struct kiocb {
|
|||
|
||||
static inline bool is_sync_kiocb(struct kiocb *kiocb)
|
||||
{
|
||||
return kiocb->ki_key == KIOCB_SYNC_KEY;
|
||||
return kiocb->ki_ctx == NULL;
|
||||
}
|
||||
|
||||
static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
|
||||
{
|
||||
*kiocb = (struct kiocb) {
|
||||
.ki_users = 1,
|
||||
.ki_key = KIOCB_SYNC_KEY,
|
||||
.ki_users = ATOMIC_INIT(1),
|
||||
.ki_ctx = NULL,
|
||||
.ki_filp = filp,
|
||||
.ki_obj.tsk = current,
|
||||
};
|
||||
}
|
||||
|
||||
#define AIO_RING_MAGIC 0xa10a10a1
|
||||
#define AIO_RING_COMPAT_FEATURES 1
|
||||
#define AIO_RING_INCOMPAT_FEATURES 0
|
||||
struct aio_ring {
|
||||
unsigned id; /* kernel internal index number */
|
||||
unsigned nr; /* number of io_events */
|
||||
unsigned head;
|
||||
unsigned tail;
|
||||
|
||||
unsigned magic;
|
||||
unsigned compat_features;
|
||||
unsigned incompat_features;
|
||||
unsigned header_length; /* size of aio_ring */
|
||||
|
||||
|
||||
struct io_event io_events[0];
|
||||
}; /* 128 bytes + ring size */
|
||||
|
||||
#define AIO_RING_PAGES 8
|
||||
struct aio_ring_info {
|
||||
unsigned long mmap_base;
|
||||
unsigned long mmap_size;
|
||||
|
||||
struct page **ring_pages;
|
||||
spinlock_t ring_lock;
|
||||
long nr_pages;
|
||||
|
||||
unsigned nr, tail;
|
||||
|
||||
struct page *internal_pages[AIO_RING_PAGES];
|
||||
};
|
||||
|
||||
static inline unsigned aio_ring_avail(struct aio_ring_info *info,
|
||||
struct aio_ring *ring)
|
||||
{
|
||||
return (ring->head + info->nr - 1 - ring->tail) % info->nr;
|
||||
}
|
||||
|
||||
struct kioctx {
|
||||
atomic_t users;
|
||||
int dead;
|
||||
struct mm_struct *mm;
|
||||
|
||||
/* This needs improving */
|
||||
unsigned long user_id;
|
||||
struct hlist_node list;
|
||||
|
||||
wait_queue_head_t wait;
|
||||
|
||||
spinlock_t ctx_lock;
|
||||
|
||||
int reqs_active;
|
||||
struct list_head active_reqs; /* used for cancellation */
|
||||
struct list_head run_list; /* used for kicked reqs */
|
||||
|
||||
/* sys_io_setup currently limits this to an unsigned int */
|
||||
unsigned max_reqs;
|
||||
|
||||
struct aio_ring_info ring_info;
|
||||
|
||||
struct delayed_work wq;
|
||||
|
||||
struct rcu_head rcu_head;
|
||||
};
|
||||
|
||||
/* prototypes */
|
||||
extern unsigned aio_max_size;
|
||||
|
||||
#ifdef CONFIG_AIO
|
||||
extern ssize_t wait_on_sync_kiocb(struct kiocb *iocb);
|
||||
extern int aio_put_req(struct kiocb *iocb);
|
||||
extern void kick_iocb(struct kiocb *iocb);
|
||||
extern int aio_complete(struct kiocb *iocb, long res, long res2);
|
||||
extern void aio_put_req(struct kiocb *iocb);
|
||||
extern void aio_complete(struct kiocb *iocb, long res, long res2);
|
||||
struct mm_struct;
|
||||
extern void exit_aio(struct mm_struct *mm);
|
||||
extern long do_io_submit(aio_context_t ctx_id, long nr,
|
||||
struct iocb __user *__user *iocbpp, bool compat);
|
||||
void kiocb_set_cancel_fn(struct kiocb *req, kiocb_cancel_fn *cancel);
|
||||
#else
|
||||
static inline ssize_t wait_on_sync_kiocb(struct kiocb *iocb) { return 0; }
|
||||
static inline int aio_put_req(struct kiocb *iocb) { return 0; }
|
||||
static inline void kick_iocb(struct kiocb *iocb) { }
|
||||
static inline int aio_complete(struct kiocb *iocb, long res, long res2) { return 0; }
|
||||
static inline void aio_put_req(struct kiocb *iocb) { }
|
||||
static inline void aio_complete(struct kiocb *iocb, long res, long res2) { }
|
||||
struct mm_struct;
|
||||
static inline void exit_aio(struct mm_struct *mm) { }
|
||||
static inline long do_io_submit(aio_context_t ctx_id, long nr,
|
||||
struct iocb __user * __user *iocbpp,
|
||||
bool compat) { return 0; }
|
||||
static inline void kiocb_set_cancel_fn(struct kiocb *req,
|
||||
kiocb_cancel_fn *cancel) { }
|
||||
#endif /* CONFIG_AIO */
|
||||
|
||||
static inline struct kiocb *list_kiocb(struct list_head *h)
|
||||
|
|
|
@ -28,6 +28,7 @@ struct cgroup_subsys;
|
|||
struct inode;
|
||||
struct cgroup;
|
||||
struct css_id;
|
||||
struct eventfd_ctx;
|
||||
|
||||
extern int cgroup_init_early(void);
|
||||
extern int cgroup_init(void);
|
||||
|
|
|
@ -28,6 +28,5 @@
|
|||
#define EBADTYPE 527 /* Type not supported by server */
|
||||
#define EJUKEBOX 528 /* Request initiated, but will not complete before timeout */
|
||||
#define EIOCBQUEUED 529 /* iocb queued, will get completion event */
|
||||
#define EIOCBRETRY 530 /* iocb queued, will trigger a retry */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -189,8 +189,7 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb)
|
|||
|
||||
extern const struct file_operations hugetlbfs_file_operations;
|
||||
extern const struct vm_operations_struct hugetlb_vm_ops;
|
||||
struct file *hugetlb_file_setup(const char *name, unsigned long addr,
|
||||
size_t size, vm_flags_t acct,
|
||||
struct file *hugetlb_file_setup(const char *name, size_t size, vm_flags_t acct,
|
||||
struct user_struct **user, int creat_flags,
|
||||
int page_size_log);
|
||||
|
||||
|
@ -209,8 +208,8 @@ static inline int is_file_hugepages(struct file *file)
|
|||
|
||||
#define is_file_hugepages(file) 0
|
||||
static inline struct file *
|
||||
hugetlb_file_setup(const char *name, unsigned long addr, size_t size,
|
||||
vm_flags_t acctflag, struct user_struct **user, int creat_flags,
|
||||
hugetlb_file_setup(const char *name, size_t size, vm_flags_t acctflag,
|
||||
struct user_struct **user, int creat_flags,
|
||||
int page_size_log)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
|
@ -288,6 +287,13 @@ static inline struct hstate *hstate_file(struct file *f)
|
|||
return hstate_inode(file_inode(f));
|
||||
}
|
||||
|
||||
static inline struct hstate *hstate_sizelog(int page_size_log)
|
||||
{
|
||||
if (!page_size_log)
|
||||
return &default_hstate;
|
||||
return size_to_hstate(1 << page_size_log);
|
||||
}
|
||||
|
||||
static inline struct hstate *hstate_vma(struct vm_area_struct *vma)
|
||||
{
|
||||
return hstate_file(vma->vm_file);
|
||||
|
@ -352,11 +358,12 @@ static inline int hstate_index(struct hstate *h)
|
|||
return h - hstates;
|
||||
}
|
||||
|
||||
#else
|
||||
#else /* CONFIG_HUGETLB_PAGE */
|
||||
struct hstate {};
|
||||
#define alloc_huge_page_node(h, nid) NULL
|
||||
#define alloc_bootmem_huge_page(h) NULL
|
||||
#define hstate_file(f) NULL
|
||||
#define hstate_sizelog(s) NULL
|
||||
#define hstate_vma(v) NULL
|
||||
#define hstate_inode(i) NULL
|
||||
#define huge_page_size(h) PAGE_SIZE
|
||||
|
@ -371,6 +378,6 @@ static inline unsigned int pages_per_huge_page(struct hstate *h)
|
|||
}
|
||||
#define hstate_index_to_shift(index) 0
|
||||
#define hstate_index(h) 0
|
||||
#endif
|
||||
#endif /* CONFIG_HUGETLB_PAGE */
|
||||
|
||||
#endif /* _LINUX_HUGETLB_H */
|
||||
|
|
|
@ -951,13 +951,19 @@ void unmap_vmas(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
|
|||
* (see walk_page_range for more details)
|
||||
*/
|
||||
struct mm_walk {
|
||||
int (*pgd_entry)(pgd_t *, unsigned long, unsigned long, struct mm_walk *);
|
||||
int (*pud_entry)(pud_t *, unsigned long, unsigned long, struct mm_walk *);
|
||||
int (*pmd_entry)(pmd_t *, unsigned long, unsigned long, struct mm_walk *);
|
||||
int (*pte_entry)(pte_t *, unsigned long, unsigned long, struct mm_walk *);
|
||||
int (*pte_hole)(unsigned long, unsigned long, struct mm_walk *);
|
||||
int (*hugetlb_entry)(pte_t *, unsigned long,
|
||||
unsigned long, unsigned long, struct mm_walk *);
|
||||
int (*pgd_entry)(pgd_t *pgd, unsigned long addr,
|
||||
unsigned long next, struct mm_walk *walk);
|
||||
int (*pud_entry)(pud_t *pud, unsigned long addr,
|
||||
unsigned long next, struct mm_walk *walk);
|
||||
int (*pmd_entry)(pmd_t *pmd, unsigned long addr,
|
||||
unsigned long next, struct mm_walk *walk);
|
||||
int (*pte_entry)(pte_t *pte, unsigned long addr,
|
||||
unsigned long next, struct mm_walk *walk);
|
||||
int (*pte_hole)(unsigned long addr, unsigned long next,
|
||||
struct mm_walk *walk);
|
||||
int (*hugetlb_entry)(pte_t *pte, unsigned long hmask,
|
||||
unsigned long addr, unsigned long next,
|
||||
struct mm_walk *walk);
|
||||
struct mm_struct *mm;
|
||||
void *private;
|
||||
};
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/threads.h>
|
||||
#include <linux/nsproxy.h>
|
||||
#include <linux/kref.h>
|
||||
|
|
|
@ -29,13 +29,6 @@ u32 prandom_u32(void);
|
|||
void prandom_bytes(void *buf, int nbytes);
|
||||
void prandom_seed(u32 seed);
|
||||
|
||||
/*
|
||||
* These macros are preserved for backward compatibility and should be
|
||||
* removed as soon as a transition is finished.
|
||||
*/
|
||||
#define random32() prandom_u32()
|
||||
#define srandom32(seed) prandom_seed(seed)
|
||||
|
||||
u32 prandom_u32_state(struct rnd_state *);
|
||||
void prandom_bytes_state(struct rnd_state *state, void *buf, int nbytes);
|
||||
|
||||
|
|
|
@ -313,8 +313,6 @@ extern void schedule_preempt_disabled(void);
|
|||
struct nsproxy;
|
||||
struct user_namespace;
|
||||
|
||||
#include <linux/aio.h>
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
extern void arch_pick_mmap_layout(struct mm_struct *mm);
|
||||
extern unsigned long
|
||||
|
|
|
@ -330,6 +330,92 @@ do { \
|
|||
__ret; \
|
||||
})
|
||||
|
||||
#define __wait_event_hrtimeout(wq, condition, timeout, state) \
|
||||
({ \
|
||||
int __ret = 0; \
|
||||
DEFINE_WAIT(__wait); \
|
||||
struct hrtimer_sleeper __t; \
|
||||
\
|
||||
hrtimer_init_on_stack(&__t.timer, CLOCK_MONOTONIC, \
|
||||
HRTIMER_MODE_REL); \
|
||||
hrtimer_init_sleeper(&__t, current); \
|
||||
if ((timeout).tv64 != KTIME_MAX) \
|
||||
hrtimer_start_range_ns(&__t.timer, timeout, \
|
||||
current->timer_slack_ns, \
|
||||
HRTIMER_MODE_REL); \
|
||||
\
|
||||
for (;;) { \
|
||||
prepare_to_wait(&wq, &__wait, state); \
|
||||
if (condition) \
|
||||
break; \
|
||||
if (state == TASK_INTERRUPTIBLE && \
|
||||
signal_pending(current)) { \
|
||||
__ret = -ERESTARTSYS; \
|
||||
break; \
|
||||
} \
|
||||
if (!__t.task) { \
|
||||
__ret = -ETIME; \
|
||||
break; \
|
||||
} \
|
||||
schedule(); \
|
||||
} \
|
||||
\
|
||||
hrtimer_cancel(&__t.timer); \
|
||||
destroy_hrtimer_on_stack(&__t.timer); \
|
||||
finish_wait(&wq, &__wait); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/**
|
||||
* wait_event_hrtimeout - sleep until a condition gets true or a timeout elapses
|
||||
* @wq: the waitqueue to wait on
|
||||
* @condition: a C expression for the event to wait for
|
||||
* @timeout: timeout, as a ktime_t
|
||||
*
|
||||
* The process is put to sleep (TASK_UNINTERRUPTIBLE) until the
|
||||
* @condition evaluates to true or a signal is received.
|
||||
* The @condition is checked each time the waitqueue @wq is woken up.
|
||||
*
|
||||
* wake_up() has to be called after changing any variable that could
|
||||
* change the result of the wait condition.
|
||||
*
|
||||
* The function returns 0 if @condition became true, or -ETIME if the timeout
|
||||
* elapsed.
|
||||
*/
|
||||
#define wait_event_hrtimeout(wq, condition, timeout) \
|
||||
({ \
|
||||
int __ret = 0; \
|
||||
if (!(condition)) \
|
||||
__ret = __wait_event_hrtimeout(wq, condition, timeout, \
|
||||
TASK_UNINTERRUPTIBLE); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
/**
|
||||
* wait_event_interruptible_hrtimeout - sleep until a condition gets true or a timeout elapses
|
||||
* @wq: the waitqueue to wait on
|
||||
* @condition: a C expression for the event to wait for
|
||||
* @timeout: timeout, as a ktime_t
|
||||
*
|
||||
* The process is put to sleep (TASK_INTERRUPTIBLE) until the
|
||||
* @condition evaluates to true or a signal is received.
|
||||
* The @condition is checked each time the waitqueue @wq is woken up.
|
||||
*
|
||||
* wake_up() has to be called after changing any variable that could
|
||||
* change the result of the wait condition.
|
||||
*
|
||||
* The function returns 0 if @condition became true, -ERESTARTSYS if it was
|
||||
* interrupted by a signal, or -ETIME if the timeout elapsed.
|
||||
*/
|
||||
#define wait_event_interruptible_hrtimeout(wq, condition, timeout) \
|
||||
({ \
|
||||
long __ret = 0; \
|
||||
if (!(condition)) \
|
||||
__ret = __wait_event_hrtimeout(wq, condition, timeout, \
|
||||
TASK_INTERRUPTIBLE); \
|
||||
__ret; \
|
||||
})
|
||||
|
||||
#define __wait_event_interruptible_exclusive(wq, condition, ret) \
|
||||
do { \
|
||||
DEFINE_WAIT(__wait); \
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#define WRITEBACK_H
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
DECLARE_PER_CPU(int, dirty_throttle_leaks);
|
||||
|
|
|
@ -491,10 +491,14 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
|
|||
|
||||
sprintf (name, "SYSV%08x", key);
|
||||
if (shmflg & SHM_HUGETLB) {
|
||||
struct hstate *hs = hstate_sizelog((shmflg >> SHM_HUGE_SHIFT)
|
||||
& SHM_HUGE_MASK);
|
||||
size_t hugesize = ALIGN(size, huge_page_size(hs));
|
||||
|
||||
/* hugetlb_file_setup applies strict accounting */
|
||||
if (shmflg & SHM_NORESERVE)
|
||||
acctflag = VM_NORESERVE;
|
||||
file = hugetlb_file_setup(name, 0, size, acctflag,
|
||||
file = hugetlb_file_setup(name, hugesize, acctflag,
|
||||
&shp->mlock_user, HUGETLB_SHMFS_INODE,
|
||||
(shmflg >> SHM_HUGE_SHIFT) & SHM_HUGE_MASK);
|
||||
} else {
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
#include <linux/khugepaged.h>
|
||||
#include <linux/signalfd.h>
|
||||
#include <linux/uprobes.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/pgalloc.h>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/security.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/aio.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/kdb.h>
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/ptrace.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/audit.h>
|
||||
#include <linux/pid_namespace.h>
|
||||
#include <linux/syscalls.h>
|
||||
|
|
|
@ -92,16 +92,18 @@ enum mem_cgroup_stat_index {
|
|||
/*
|
||||
* For MEM_CONTAINER_TYPE_ALL, usage = pagecache + rss.
|
||||
*/
|
||||
MEM_CGROUP_STAT_CACHE, /* # of pages charged as cache */
|
||||
MEM_CGROUP_STAT_RSS, /* # of pages charged as anon rss */
|
||||
MEM_CGROUP_STAT_FILE_MAPPED, /* # of pages charged as file rss */
|
||||
MEM_CGROUP_STAT_SWAP, /* # of pages, swapped out */
|
||||
MEM_CGROUP_STAT_CACHE, /* # of pages charged as cache */
|
||||
MEM_CGROUP_STAT_RSS, /* # of pages charged as anon rss */
|
||||
MEM_CGROUP_STAT_RSS_HUGE, /* # of pages charged as anon huge */
|
||||
MEM_CGROUP_STAT_FILE_MAPPED, /* # of pages charged as file rss */
|
||||
MEM_CGROUP_STAT_SWAP, /* # of pages, swapped out */
|
||||
MEM_CGROUP_STAT_NSTATS,
|
||||
};
|
||||
|
||||
static const char * const mem_cgroup_stat_names[] = {
|
||||
"cache",
|
||||
"rss",
|
||||
"rss_huge",
|
||||
"mapped_file",
|
||||
"swap",
|
||||
};
|
||||
|
@ -917,6 +919,7 @@ static unsigned long mem_cgroup_read_events(struct mem_cgroup *memcg,
|
|||
}
|
||||
|
||||
static void mem_cgroup_charge_statistics(struct mem_cgroup *memcg,
|
||||
struct page *page,
|
||||
bool anon, int nr_pages)
|
||||
{
|
||||
preempt_disable();
|
||||
|
@ -932,6 +935,10 @@ static void mem_cgroup_charge_statistics(struct mem_cgroup *memcg,
|
|||
__this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_CACHE],
|
||||
nr_pages);
|
||||
|
||||
if (PageTransHuge(page))
|
||||
__this_cpu_add(memcg->stat->count[MEM_CGROUP_STAT_RSS_HUGE],
|
||||
nr_pages);
|
||||
|
||||
/* pagein of a big page is an event. So, ignore page size */
|
||||
if (nr_pages > 0)
|
||||
__this_cpu_inc(memcg->stat->events[MEM_CGROUP_EVENTS_PGPGIN]);
|
||||
|
@ -2914,7 +2921,7 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg,
|
|||
else
|
||||
anon = false;
|
||||
|
||||
mem_cgroup_charge_statistics(memcg, anon, nr_pages);
|
||||
mem_cgroup_charge_statistics(memcg, page, anon, nr_pages);
|
||||
unlock_page_cgroup(pc);
|
||||
|
||||
/*
|
||||
|
@ -3708,16 +3715,21 @@ void mem_cgroup_split_huge_fixup(struct page *head)
|
|||
{
|
||||
struct page_cgroup *head_pc = lookup_page_cgroup(head);
|
||||
struct page_cgroup *pc;
|
||||
struct mem_cgroup *memcg;
|
||||
int i;
|
||||
|
||||
if (mem_cgroup_disabled())
|
||||
return;
|
||||
|
||||
memcg = head_pc->mem_cgroup;
|
||||
for (i = 1; i < HPAGE_PMD_NR; i++) {
|
||||
pc = head_pc + i;
|
||||
pc->mem_cgroup = head_pc->mem_cgroup;
|
||||
pc->mem_cgroup = memcg;
|
||||
smp_wmb();/* see __commit_charge() */
|
||||
pc->flags = head_pc->flags & ~PCGF_NOCOPY_AT_SPLIT;
|
||||
}
|
||||
__this_cpu_sub(memcg->stat->count[MEM_CGROUP_STAT_RSS_HUGE],
|
||||
HPAGE_PMD_NR);
|
||||
}
|
||||
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
|
||||
|
@ -3773,11 +3785,11 @@ static int mem_cgroup_move_account(struct page *page,
|
|||
__this_cpu_inc(to->stat->count[MEM_CGROUP_STAT_FILE_MAPPED]);
|
||||
preempt_enable();
|
||||
}
|
||||
mem_cgroup_charge_statistics(from, anon, -nr_pages);
|
||||
mem_cgroup_charge_statistics(from, page, anon, -nr_pages);
|
||||
|
||||
/* caller should have done css_get */
|
||||
pc->mem_cgroup = to;
|
||||
mem_cgroup_charge_statistics(to, anon, nr_pages);
|
||||
mem_cgroup_charge_statistics(to, page, anon, nr_pages);
|
||||
move_unlock_mem_cgroup(from, &flags);
|
||||
ret = 0;
|
||||
unlock:
|
||||
|
@ -4152,7 +4164,7 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype,
|
|||
break;
|
||||
}
|
||||
|
||||
mem_cgroup_charge_statistics(memcg, anon, -nr_pages);
|
||||
mem_cgroup_charge_statistics(memcg, page, anon, -nr_pages);
|
||||
|
||||
ClearPageCgroupUsed(pc);
|
||||
/*
|
||||
|
@ -4502,7 +4514,7 @@ void mem_cgroup_replace_page_cache(struct page *oldpage,
|
|||
lock_page_cgroup(pc);
|
||||
if (PageCgroupUsed(pc)) {
|
||||
memcg = pc->mem_cgroup;
|
||||
mem_cgroup_charge_statistics(memcg, false, -1);
|
||||
mem_cgroup_charge_statistics(memcg, oldpage, false, -1);
|
||||
ClearPageCgroupUsed(pc);
|
||||
}
|
||||
unlock_page_cgroup(pc);
|
||||
|
@ -5030,6 +5042,10 @@ static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
|
|||
return res_counter_read_u64(&memcg->memsw, RES_USAGE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Transparent hugepages are still accounted for in MEM_CGROUP_STAT_RSS
|
||||
* as well as in MEM_CGROUP_STAT_RSS_HUGE.
|
||||
*/
|
||||
val = mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_CACHE);
|
||||
val += mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_RSS);
|
||||
|
||||
|
|
|
@ -1363,15 +1363,20 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
|
|||
file = fget(fd);
|
||||
if (!file)
|
||||
goto out;
|
||||
if (is_file_hugepages(file))
|
||||
len = ALIGN(len, huge_page_size(hstate_file(file)));
|
||||
} else if (flags & MAP_HUGETLB) {
|
||||
struct user_struct *user = NULL;
|
||||
|
||||
len = ALIGN(len, huge_page_size(hstate_sizelog(
|
||||
(flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK)));
|
||||
/*
|
||||
* VM_NORESERVE is used because the reservations will be
|
||||
* taken when vm_ops->mmap() is called
|
||||
* A dummy user value is used because we are not locking
|
||||
* memory so no accounting is necessary
|
||||
*/
|
||||
file = hugetlb_file_setup(HUGETLB_ANON_FILE, addr, len,
|
||||
file = hugetlb_file_setup(HUGETLB_ANON_FILE, len,
|
||||
VM_NORESERVE,
|
||||
&user, HUGETLB_ANONHUGE_INODE,
|
||||
(flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK);
|
||||
|
|
|
@ -14,9 +14,6 @@
|
|||
* use_mm
|
||||
* Makes the calling kernel thread take on the specified
|
||||
* mm context.
|
||||
* Called by the retry thread execute retries within the
|
||||
* iocb issuer's mm context, so that copy_from/to_user
|
||||
* operations work seamlessly for aio.
|
||||
* (Note: this routine is intended to be called only
|
||||
* from a kernel thread context)
|
||||
*/
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/buffer_head.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/frontswap.h>
|
||||
#include <linux/aio.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
static struct bio *get_swap_bio(gfp_t gfp_flags,
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
static struct vfsmount *shm_mnt;
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/backing-dev.h>
|
||||
#include <linux/memcontrol.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/uio.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
|
|
@ -1522,6 +1522,8 @@ static void __vunmap(const void *addr, int deallocate_pages)
|
|||
* Must not be called in NMI context (strictly speaking, only if we don't
|
||||
* have CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG, but making the calling
|
||||
* conventions for vfree() arch-depenedent would be a really bad idea)
|
||||
*
|
||||
* NOTE: assumes that the object at *addr has a size >= sizeof(llist_node)
|
||||
*
|
||||
*/
|
||||
void vfree(const void *addr)
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include <linux/key-type.h>
|
||||
#include <linux/task_work.h>
|
||||
|
||||
struct iovec;
|
||||
|
||||
#ifdef __KDEBUG
|
||||
#define kenter(FMT, ...) \
|
||||
printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/uio.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include "internal.h"
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/aio.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/control.h>
|
||||
|
|
Loading…
Reference in New Issue