Merge 072c92b1b1
("Merge tag 'audit-pr-20220823' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit") into android-mainline
Steps on the way to 6.0-rc2 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I4762c2adc4fffbf57bf8f5db33a85649eb27fe41
This commit is contained in:
commit
feeb390843
@ -1,2 +1,4 @@
|
||||
Alan Cox <alan@lxorguk.ukuu.org.uk>
|
||||
Alan Cox <root@hraefn.swansea.linux.org.uk>
|
||||
Christoph Hellwig <hch@lst.de>
|
||||
Marc Gonzalez <marc.w.gonzalez@free.fr>
|
||||
|
@ -9781,7 +9781,7 @@ M: Christian Brauner <brauner@kernel.org>
|
||||
M: Seth Forshee <sforshee@kernel.org>
|
||||
L: linux-fsdevel@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux.git
|
||||
T: git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping.git
|
||||
F: Documentation/filesystems/idmappings.rst
|
||||
F: tools/testing/selftests/mount_setattr/
|
||||
F: include/linux/mnt_idmapping.h
|
||||
|
@ -146,10 +146,10 @@ menu "Processor type and features"
|
||||
|
||||
choice
|
||||
prompt "Processor type"
|
||||
default PA7000
|
||||
default PA7000 if "$(ARCH)" = "parisc"
|
||||
|
||||
config PA7000
|
||||
bool "PA7000/PA7100"
|
||||
bool "PA7000/PA7100" if "$(ARCH)" = "parisc"
|
||||
help
|
||||
This is the processor type of your CPU. This information is
|
||||
used for optimizing purposes. In order to compile a kernel
|
||||
@ -160,21 +160,21 @@ config PA7000
|
||||
which is required on some machines.
|
||||
|
||||
config PA7100LC
|
||||
bool "PA7100LC"
|
||||
bool "PA7100LC" if "$(ARCH)" = "parisc"
|
||||
help
|
||||
Select this option for the PCX-L processor, as used in the
|
||||
712, 715/64, 715/80, 715/100, 715/100XC, 725/100, 743, 748,
|
||||
D200, D210, D300, D310 and E-class
|
||||
|
||||
config PA7200
|
||||
bool "PA7200"
|
||||
bool "PA7200" if "$(ARCH)" = "parisc"
|
||||
help
|
||||
Select this option for the PCX-T' processor, as used in the
|
||||
C100, C110, J100, J110, J210XC, D250, D260, D350, D360,
|
||||
K100, K200, K210, K220, K400, K410 and K420
|
||||
|
||||
config PA7300LC
|
||||
bool "PA7300LC"
|
||||
bool "PA7300LC" if "$(ARCH)" = "parisc"
|
||||
help
|
||||
Select this option for the PCX-L2 processor, as used in the
|
||||
744, A180, B132L, B160L, B180L, C132L, C160L, C180L,
|
||||
@ -224,17 +224,8 @@ config MLONGCALLS
|
||||
Enabling this option will probably slow down your kernel.
|
||||
|
||||
config 64BIT
|
||||
bool "64-bit kernel"
|
||||
def_bool "$(ARCH)" = "parisc64"
|
||||
depends on PA8X00
|
||||
help
|
||||
Enable this if you want to support 64bit kernel on PA-RISC platform.
|
||||
|
||||
At the moment, only people willing to use more than 2GB of RAM,
|
||||
or having a 64bit-only capable PA-RISC machine should say Y here.
|
||||
|
||||
Since there is no 64bit userland on PA-RISC, there is no point to
|
||||
enable this option otherwise. The 64bit kernel is significantly bigger
|
||||
and slower than the 32bit one.
|
||||
|
||||
choice
|
||||
prompt "Kernel page size"
|
||||
|
@ -12,14 +12,6 @@
|
||||
#include <asm/barrier.h>
|
||||
#include <linux/atomic.h>
|
||||
|
||||
/* compiler build environment sanity checks: */
|
||||
#if !defined(CONFIG_64BIT) && defined(__LP64__)
|
||||
#error "Please use 'ARCH=parisc' to build the 32-bit kernel."
|
||||
#endif
|
||||
#if defined(CONFIG_64BIT) && !defined(__LP64__)
|
||||
#error "Please use 'ARCH=parisc64' to build the 64-bit kernel."
|
||||
#endif
|
||||
|
||||
/* See http://marc.theaimsgroup.com/?t=108826637900003 for discussion
|
||||
* on use of volatile and __*_bit() (set/clear/change):
|
||||
* *_bit() want use of volatile.
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/pgtable.h>
|
||||
|
||||
.level PA_ASM_LEVEL
|
||||
.level 1.1
|
||||
|
||||
__INITDATA
|
||||
ENTRY(boot_args)
|
||||
@ -70,6 +70,47 @@ $bss_loop:
|
||||
stw,ma %arg2,4(%r1)
|
||||
stw,ma %arg3,4(%r1)
|
||||
|
||||
#if !defined(CONFIG_64BIT) && defined(CONFIG_PA20)
|
||||
/* This 32-bit kernel was compiled for PA2.0 CPUs. Check current CPU
|
||||
* and halt kernel if we detect a PA1.x CPU. */
|
||||
ldi 32,%r10
|
||||
mtctl %r10,%cr11
|
||||
.level 2.0
|
||||
mfctl,w %cr11,%r10
|
||||
.level 1.1
|
||||
comib,<>,n 0,%r10,$cpu_ok
|
||||
|
||||
load32 PA(msg1),%arg0
|
||||
ldi msg1_end-msg1,%arg1
|
||||
$iodc_panic:
|
||||
copy %arg0, %r10
|
||||
copy %arg1, %r11
|
||||
load32 PA(init_stack),%sp
|
||||
#define MEM_CONS 0x3A0
|
||||
ldw MEM_CONS+32(%r0),%arg0 // HPA
|
||||
ldi ENTRY_IO_COUT,%arg1
|
||||
ldw MEM_CONS+36(%r0),%arg2 // SPA
|
||||
ldw MEM_CONS+8(%r0),%arg3 // layers
|
||||
load32 PA(__bss_start),%r1
|
||||
stw %r1,-52(%sp) // arg4
|
||||
stw %r0,-56(%sp) // arg5
|
||||
stw %r10,-60(%sp) // arg6 = ptr to text
|
||||
stw %r11,-64(%sp) // arg7 = len
|
||||
stw %r0,-68(%sp) // arg8
|
||||
load32 PA(.iodc_panic_ret), %rp
|
||||
ldw MEM_CONS+40(%r0),%r1 // ENTRY_IODC
|
||||
bv,n (%r1)
|
||||
.iodc_panic_ret:
|
||||
b . /* wait endless with ... */
|
||||
or %r10,%r10,%r10 /* qemu idle sleep */
|
||||
msg1: .ascii "Can't boot kernel which was built for PA8x00 CPUs on this machine.\r\n"
|
||||
msg1_end:
|
||||
|
||||
$cpu_ok:
|
||||
#endif
|
||||
|
||||
.level PA_ASM_LEVEL
|
||||
|
||||
/* Initialize startup VM. Just map first 16/32 MB of memory */
|
||||
load32 PA(swapper_pg_dir),%r4
|
||||
mtctl %r4,%cr24 /* Initialize kernel root pointer */
|
||||
|
@ -93,7 +93,7 @@
|
||||
#define R1(i) (((i)>>21)&0x1f)
|
||||
#define R2(i) (((i)>>16)&0x1f)
|
||||
#define R3(i) ((i)&0x1f)
|
||||
#define FR3(i) ((((i)<<1)&0x1f)|(((i)>>6)&1))
|
||||
#define FR3(i) ((((i)&0x1f)<<1)|(((i)>>6)&1))
|
||||
#define IM(i,n) (((i)>>1&((1<<(n-1))-1))|((i)&1?((0-1L)<<(n-1)):0))
|
||||
#define IM5_2(i) IM((i)>>16,5)
|
||||
#define IM5_3(i) IM((i),5)
|
||||
|
@ -1146,14 +1146,15 @@ static ssize_t bd_stat_show(struct device *dev,
|
||||
static ssize_t debug_stat_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int version = 2;
|
||||
int version = 1;
|
||||
struct zram *zram = dev_to_zram(dev);
|
||||
ssize_t ret;
|
||||
|
||||
down_read(&zram->init_lock);
|
||||
ret = scnprintf(buf, PAGE_SIZE,
|
||||
"version: %d\n%8llu\n",
|
||||
"version: %d\n%8llu %8llu\n",
|
||||
version,
|
||||
(u64)atomic64_read(&zram->stats.writestall),
|
||||
(u64)atomic64_read(&zram->stats.miss_free));
|
||||
up_read(&zram->init_lock);
|
||||
|
||||
@ -1351,7 +1352,7 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long alloced_pages;
|
||||
unsigned long handle = 0;
|
||||
unsigned long handle = -ENOMEM;
|
||||
unsigned int comp_len = 0;
|
||||
void *src, *dst, *mem;
|
||||
struct zcomp_strm *zstrm;
|
||||
@ -1369,6 +1370,7 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
|
||||
}
|
||||
kunmap_atomic(mem);
|
||||
|
||||
compress_again:
|
||||
zstrm = zcomp_stream_get(zram->comp);
|
||||
src = kmap_atomic(page);
|
||||
ret = zcomp_compress(zstrm, src, &comp_len);
|
||||
@ -1377,20 +1379,39 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
|
||||
if (unlikely(ret)) {
|
||||
zcomp_stream_put(zram->comp);
|
||||
pr_err("Compression failed! err=%d\n", ret);
|
||||
zs_free(zram->mem_pool, handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (comp_len >= huge_class_size)
|
||||
comp_len = PAGE_SIZE;
|
||||
|
||||
handle = zs_malloc(zram->mem_pool, comp_len,
|
||||
__GFP_KSWAPD_RECLAIM |
|
||||
__GFP_NOWARN |
|
||||
__GFP_HIGHMEM |
|
||||
__GFP_MOVABLE);
|
||||
|
||||
/*
|
||||
* handle allocation has 2 paths:
|
||||
* a) fast path is executed with preemption disabled (for
|
||||
* per-cpu streams) and has __GFP_DIRECT_RECLAIM bit clear,
|
||||
* since we can't sleep;
|
||||
* b) slow path enables preemption and attempts to allocate
|
||||
* the page with __GFP_DIRECT_RECLAIM bit set. we have to
|
||||
* put per-cpu compression stream and, thus, to re-do
|
||||
* the compression once handle is allocated.
|
||||
*
|
||||
* if we have a 'non-null' handle here then we are coming
|
||||
* from the slow path and handle has already been allocated.
|
||||
*/
|
||||
if (IS_ERR((void *)handle))
|
||||
handle = zs_malloc(zram->mem_pool, comp_len,
|
||||
__GFP_KSWAPD_RECLAIM |
|
||||
__GFP_NOWARN |
|
||||
__GFP_HIGHMEM |
|
||||
__GFP_MOVABLE);
|
||||
if (IS_ERR((void *)handle)) {
|
||||
zcomp_stream_put(zram->comp);
|
||||
atomic64_inc(&zram->stats.writestall);
|
||||
handle = zs_malloc(zram->mem_pool, comp_len,
|
||||
GFP_NOIO | __GFP_HIGHMEM |
|
||||
__GFP_MOVABLE);
|
||||
if (!IS_ERR((void *)handle))
|
||||
goto compress_again;
|
||||
return PTR_ERR((void *)handle);
|
||||
}
|
||||
|
||||
@ -1948,6 +1969,7 @@ static int zram_add(void)
|
||||
if (ZRAM_LOGICAL_BLOCK_SIZE == PAGE_SIZE)
|
||||
blk_queue_max_write_zeroes_sectors(zram->disk->queue, UINT_MAX);
|
||||
|
||||
blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, zram->disk->queue);
|
||||
ret = device_add_disk(NULL, zram->disk, zram_disk_groups);
|
||||
if (ret)
|
||||
goto out_cleanup_disk;
|
||||
|
@ -81,6 +81,7 @@ struct zram_stats {
|
||||
atomic64_t huge_pages_since; /* no. of huge pages since zram set up */
|
||||
atomic64_t pages_stored; /* no. of pages currently stored */
|
||||
atomic_long_t max_used_pages; /* no. of maximum pages stored */
|
||||
atomic64_t writestall; /* no. of write slow paths */
|
||||
atomic64_t miss_free; /* no. of missed free */
|
||||
#ifdef CONFIG_ZRAM_WRITEBACK
|
||||
atomic64_t bd_count; /* no. of pages in backing device */
|
||||
|
@ -171,6 +171,7 @@ config MMC_SDHCI_OF_ASPEED
|
||||
config MMC_SDHCI_OF_ASPEED_TEST
|
||||
bool "Tests for the ASPEED SDHCI driver" if !KUNIT_ALL_TESTS
|
||||
depends on MMC_SDHCI_OF_ASPEED && KUNIT
|
||||
depends on (MMC_SDHCI_OF_ASPEED=m || KUNIT=y)
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
Enable KUnit tests for the ASPEED SDHCI driver. Select this
|
||||
|
@ -268,7 +268,7 @@ static int ioc_count;
|
||||
* Each bit can represent a number of pages.
|
||||
* LSbs represent lower addresses (IOVA's).
|
||||
*
|
||||
* This was was copied from sba_iommu.c. Don't try to unify
|
||||
* This was copied from sba_iommu.c. Don't try to unify
|
||||
* the two resource managers unless a way to have different
|
||||
* allocation policies is also adjusted. We'd like to avoid
|
||||
* I/O TLB thrashing by having resource allocation policy
|
||||
@ -1380,15 +1380,17 @@ ccio_init_resource(struct resource *res, char *name, void __iomem *ioaddr)
|
||||
}
|
||||
}
|
||||
|
||||
static void __init ccio_init_resources(struct ioc *ioc)
|
||||
static int __init ccio_init_resources(struct ioc *ioc)
|
||||
{
|
||||
struct resource *res = ioc->mmio_region;
|
||||
char *name = kmalloc(14, GFP_KERNEL);
|
||||
|
||||
if (unlikely(!name))
|
||||
return -ENOMEM;
|
||||
snprintf(name, 14, "GSC Bus [%d/]", ioc->hw_path);
|
||||
|
||||
ccio_init_resource(res, name, &ioc->ioc_regs->io_io_low);
|
||||
ccio_init_resource(res + 1, name, &ioc->ioc_regs->io_io_low_hv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int new_ioc_area(struct resource *res, unsigned long size,
|
||||
@ -1543,7 +1545,10 @@ static int __init ccio_probe(struct parisc_device *dev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
ccio_ioc_init(ioc);
|
||||
ccio_init_resources(ioc);
|
||||
if (ccio_init_resources(ioc)) {
|
||||
kfree(ioc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
hppa_dma_ops = &ccio_ops;
|
||||
|
||||
hba = kzalloc(sizeof(*hba), GFP_KERNEL);
|
||||
|
@ -646,7 +646,7 @@ int lcd_print( const char *str )
|
||||
cancel_delayed_work_sync(&led_task);
|
||||
|
||||
/* copy display string to buffer for procfs */
|
||||
strlcpy(lcd_text, str, sizeof(lcd_text));
|
||||
strscpy(lcd_text, str, sizeof(lcd_text));
|
||||
|
||||
/* Set LCD Cursor to 1st character */
|
||||
gsc_writeb(lcd_info.reset_cmd1, LCD_CMD_REG);
|
||||
|
14
fs/inode.c
14
fs/inode.c
@ -2018,23 +2018,25 @@ static int __file_remove_privs(struct file *file, unsigned int flags)
|
||||
{
|
||||
struct dentry *dentry = file_dentry(file);
|
||||
struct inode *inode = file_inode(file);
|
||||
int error;
|
||||
int error = 0;
|
||||
int kill;
|
||||
|
||||
if (IS_NOSEC(inode) || !S_ISREG(inode->i_mode))
|
||||
return 0;
|
||||
|
||||
kill = dentry_needs_remove_privs(dentry);
|
||||
if (kill <= 0)
|
||||
if (kill < 0)
|
||||
return kill;
|
||||
|
||||
if (flags & IOCB_NOWAIT)
|
||||
return -EAGAIN;
|
||||
if (kill) {
|
||||
if (flags & IOCB_NOWAIT)
|
||||
return -EAGAIN;
|
||||
|
||||
error = __remove_privs(file_mnt_user_ns(file), dentry, kill);
|
||||
}
|
||||
|
||||
error = __remove_privs(file_mnt_user_ns(file), dentry, kill);
|
||||
if (!error)
|
||||
inode_has_no_xattr(inode);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -2129,6 +2129,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
|
||||
else
|
||||
error = locks_lock_file_wait(f.file, &fl);
|
||||
|
||||
locks_release_private(&fl);
|
||||
out_putf:
|
||||
fdput(f);
|
||||
|
||||
|
@ -4238,6 +4238,13 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
|
||||
err = -EPERM;
|
||||
goto out_fput;
|
||||
}
|
||||
|
||||
/* We're not controlling the target namespace. */
|
||||
if (!ns_capable(mnt_userns, CAP_SYS_ADMIN)) {
|
||||
err = -EPERM;
|
||||
goto out_fput;
|
||||
}
|
||||
|
||||
kattr->mnt_userns = get_user_ns(mnt_userns);
|
||||
|
||||
out_fput:
|
||||
|
@ -2382,7 +2382,8 @@ static void nfs_dentry_remove_handle_error(struct inode *dir,
|
||||
{
|
||||
switch (error) {
|
||||
case -ENOENT:
|
||||
d_delete(dentry);
|
||||
if (d_really_is_positive(dentry))
|
||||
d_delete(dentry);
|
||||
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
|
||||
break;
|
||||
case 0:
|
||||
@ -2484,8 +2485,10 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry)
|
||||
*/
|
||||
error = -ETXTBSY;
|
||||
if (WARN_ON(dentry->d_flags & DCACHE_NFSFS_RENAMED) ||
|
||||
WARN_ON(dentry->d_fsdata == NFS_FSDATA_BLOCKED))
|
||||
WARN_ON(dentry->d_fsdata == NFS_FSDATA_BLOCKED)) {
|
||||
spin_unlock(&dentry->d_lock);
|
||||
goto out;
|
||||
}
|
||||
if (dentry->d_fsdata)
|
||||
/* old devname */
|
||||
kfree(dentry->d_fsdata);
|
||||
|
@ -221,8 +221,10 @@ nfs_file_fsync_commit(struct file *file, int datasync)
|
||||
int
|
||||
nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
||||
{
|
||||
struct nfs_open_context *ctx = nfs_file_open_context(file);
|
||||
struct inode *inode = file_inode(file);
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
long save_nredirtied = atomic_long_read(&nfsi->redirtied_pages);
|
||||
long nredirtied;
|
||||
int ret;
|
||||
|
||||
trace_nfs_fsync_enter(inode);
|
||||
@ -237,15 +239,10 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
|
||||
ret = pnfs_sync_inode(inode, !!datasync);
|
||||
if (ret != 0)
|
||||
break;
|
||||
if (!test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags))
|
||||
nredirtied = atomic_long_read(&nfsi->redirtied_pages);
|
||||
if (nredirtied == save_nredirtied)
|
||||
break;
|
||||
/*
|
||||
* If nfs_file_fsync_commit detected a server reboot, then
|
||||
* resend all dirty pages that might have been covered by
|
||||
* the NFS_CONTEXT_RESEND_WRITES flag
|
||||
*/
|
||||
start = 0;
|
||||
end = LLONG_MAX;
|
||||
save_nredirtied = nredirtied;
|
||||
}
|
||||
|
||||
trace_nfs_fsync_exit(inode, ret);
|
||||
|
@ -426,6 +426,7 @@ nfs_ilookup(struct super_block *sb, struct nfs_fattr *fattr, struct nfs_fh *fh)
|
||||
static void nfs_inode_init_regular(struct nfs_inode *nfsi)
|
||||
{
|
||||
atomic_long_set(&nfsi->nrequests, 0);
|
||||
atomic_long_set(&nfsi->redirtied_pages, 0);
|
||||
INIT_LIST_HEAD(&nfsi->commit_info.list);
|
||||
atomic_long_set(&nfsi->commit_info.ncommit, 0);
|
||||
atomic_set(&nfsi->commit_info.rpcs_out, 0);
|
||||
|
@ -340,6 +340,11 @@ static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!S_ISREG(fattr->mode)) {
|
||||
res = ERR_PTR(-EBADF);
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = ERR_PTR(-ENOMEM);
|
||||
len = strlen(SSC_READ_NAME_BODY) + 16;
|
||||
read_name = kzalloc(len, GFP_KERNEL);
|
||||
@ -357,6 +362,7 @@ static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt,
|
||||
r_ino->i_fop);
|
||||
if (IS_ERR(filep)) {
|
||||
res = ERR_CAST(filep);
|
||||
iput(r_ino);
|
||||
goto out_free_name;
|
||||
}
|
||||
|
||||
|
@ -2817,7 +2817,6 @@ int pnfs_write_done_resend_to_mds(struct nfs_pgio_header *hdr)
|
||||
/* Resend all requests through the MDS */
|
||||
nfs_pageio_init_write(&pgio, hdr->inode, FLUSH_STABLE, true,
|
||||
hdr->completion_ops);
|
||||
set_bit(NFS_CONTEXT_RESEND_WRITES, &hdr->args.context->flags);
|
||||
return nfs_pageio_resend(&pgio, hdr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pnfs_write_done_resend_to_mds);
|
||||
|
@ -1420,10 +1420,12 @@ static void nfs_initiate_write(struct nfs_pgio_header *hdr,
|
||||
*/
|
||||
static void nfs_redirty_request(struct nfs_page *req)
|
||||
{
|
||||
struct nfs_inode *nfsi = NFS_I(page_file_mapping(req->wb_page)->host);
|
||||
|
||||
/* Bump the transmission count */
|
||||
req->wb_nio++;
|
||||
nfs_mark_request_dirty(req);
|
||||
set_bit(NFS_CONTEXT_RESEND_WRITES, &nfs_req_openctx(req)->flags);
|
||||
atomic_long_inc(&nfsi->redirtied_pages);
|
||||
nfs_end_page_writeback(req);
|
||||
nfs_release_request(req);
|
||||
}
|
||||
@ -1904,7 +1906,7 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
|
||||
/* We have a mismatch. Write the page again */
|
||||
dprintk_cont(" mismatch\n");
|
||||
nfs_mark_request_dirty(req);
|
||||
set_bit(NFS_CONTEXT_RESEND_WRITES, &nfs_req_openctx(req)->flags);
|
||||
atomic_long_inc(&NFS_I(data->inode)->redirtied_pages);
|
||||
next:
|
||||
nfs_unlock_and_release_request(req);
|
||||
/* Latency breaker */
|
||||
|
@ -483,8 +483,7 @@ static noinline int ntfs_set_ea(struct inode *inode, const char *name,
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NTFS3_FS_POSIX_ACL
|
||||
static struct posix_acl *ntfs_get_acl_ex(struct user_namespace *mnt_userns,
|
||||
struct inode *inode, int type,
|
||||
static struct posix_acl *ntfs_get_acl_ex(struct inode *inode, int type,
|
||||
int locked)
|
||||
{
|
||||
struct ntfs_inode *ni = ntfs_i(inode);
|
||||
@ -519,7 +518,7 @@ static struct posix_acl *ntfs_get_acl_ex(struct user_namespace *mnt_userns,
|
||||
|
||||
/* Translate extended attribute to acl. */
|
||||
if (err >= 0) {
|
||||
acl = posix_acl_from_xattr(mnt_userns, buf, err);
|
||||
acl = posix_acl_from_xattr(&init_user_ns, buf, err);
|
||||
} else if (err == -ENODATA) {
|
||||
acl = NULL;
|
||||
} else {
|
||||
@ -542,8 +541,7 @@ struct posix_acl *ntfs_get_acl(struct inode *inode, int type, bool rcu)
|
||||
if (rcu)
|
||||
return ERR_PTR(-ECHILD);
|
||||
|
||||
/* TODO: init_user_ns? */
|
||||
return ntfs_get_acl_ex(&init_user_ns, inode, type, 0);
|
||||
return ntfs_get_acl_ex(inode, type, 0);
|
||||
}
|
||||
|
||||
static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns,
|
||||
@ -595,7 +593,7 @@ static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns,
|
||||
value = kmalloc(size, GFP_NOFS);
|
||||
if (!value)
|
||||
return -ENOMEM;
|
||||
err = posix_acl_to_xattr(mnt_userns, acl, value, size);
|
||||
err = posix_acl_to_xattr(&init_user_ns, acl, value, size);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
flags = 0;
|
||||
@ -646,7 +644,7 @@ static int ntfs_xattr_get_acl(struct user_namespace *mnt_userns,
|
||||
if (!acl)
|
||||
return -ENODATA;
|
||||
|
||||
err = posix_acl_to_xattr(mnt_userns, acl, buffer, size);
|
||||
err = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
|
||||
posix_acl_release(acl);
|
||||
|
||||
return err;
|
||||
@ -670,12 +668,12 @@ static int ntfs_xattr_set_acl(struct user_namespace *mnt_userns,
|
||||
if (!value) {
|
||||
acl = NULL;
|
||||
} else {
|
||||
acl = posix_acl_from_xattr(mnt_userns, value, size);
|
||||
acl = posix_acl_from_xattr(&init_user_ns, value, size);
|
||||
if (IS_ERR(acl))
|
||||
return PTR_ERR(acl);
|
||||
|
||||
if (acl) {
|
||||
err = posix_acl_valid(mnt_userns, acl);
|
||||
err = posix_acl_valid(&init_user_ns, acl);
|
||||
if (err)
|
||||
goto release_and_out;
|
||||
}
|
||||
|
@ -460,9 +460,12 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
|
||||
* of the POSIX ACLs retrieved from the lower layer to this function to not
|
||||
* alter the POSIX ACLs for the underlying filesystem.
|
||||
*/
|
||||
static void ovl_idmap_posix_acl(struct user_namespace *mnt_userns,
|
||||
static void ovl_idmap_posix_acl(struct inode *realinode,
|
||||
struct user_namespace *mnt_userns,
|
||||
struct posix_acl *acl)
|
||||
{
|
||||
struct user_namespace *fs_userns = i_user_ns(realinode);
|
||||
|
||||
for (unsigned int i = 0; i < acl->a_count; i++) {
|
||||
vfsuid_t vfsuid;
|
||||
vfsgid_t vfsgid;
|
||||
@ -470,11 +473,11 @@ static void ovl_idmap_posix_acl(struct user_namespace *mnt_userns,
|
||||
struct posix_acl_entry *e = &acl->a_entries[i];
|
||||
switch (e->e_tag) {
|
||||
case ACL_USER:
|
||||
vfsuid = make_vfsuid(mnt_userns, &init_user_ns, e->e_uid);
|
||||
vfsuid = make_vfsuid(mnt_userns, fs_userns, e->e_uid);
|
||||
e->e_uid = vfsuid_into_kuid(vfsuid);
|
||||
break;
|
||||
case ACL_GROUP:
|
||||
vfsgid = make_vfsgid(mnt_userns, &init_user_ns, e->e_gid);
|
||||
vfsgid = make_vfsgid(mnt_userns, fs_userns, e->e_gid);
|
||||
e->e_gid = vfsgid_into_kgid(vfsgid);
|
||||
break;
|
||||
}
|
||||
@ -536,7 +539,7 @@ struct posix_acl *ovl_get_acl(struct inode *inode, int type, bool rcu)
|
||||
if (!clone)
|
||||
clone = ERR_PTR(-ENOMEM);
|
||||
else
|
||||
ovl_idmap_posix_acl(mnt_user_ns(realpath.mnt), clone);
|
||||
ovl_idmap_posix_acl(realinode, mnt_user_ns(realpath.mnt), clone);
|
||||
/*
|
||||
* Since we're not in RCU path walk we always need to release the
|
||||
* original ACLs.
|
||||
|
@ -361,6 +361,7 @@ posix_acl_permission(struct user_namespace *mnt_userns, struct inode *inode,
|
||||
const struct posix_acl *acl, int want)
|
||||
{
|
||||
const struct posix_acl_entry *pa, *pe, *mask_obj;
|
||||
struct user_namespace *fs_userns = i_user_ns(inode);
|
||||
int found = 0;
|
||||
vfsuid_t vfsuid;
|
||||
vfsgid_t vfsgid;
|
||||
@ -376,7 +377,7 @@ posix_acl_permission(struct user_namespace *mnt_userns, struct inode *inode,
|
||||
goto check_perm;
|
||||
break;
|
||||
case ACL_USER:
|
||||
vfsuid = make_vfsuid(mnt_userns, &init_user_ns,
|
||||
vfsuid = make_vfsuid(mnt_userns, fs_userns,
|
||||
pa->e_uid);
|
||||
if (vfsuid_eq_kuid(vfsuid, current_fsuid()))
|
||||
goto mask;
|
||||
@ -390,7 +391,7 @@ posix_acl_permission(struct user_namespace *mnt_userns, struct inode *inode,
|
||||
}
|
||||
break;
|
||||
case ACL_GROUP:
|
||||
vfsgid = make_vfsgid(mnt_userns, &init_user_ns,
|
||||
vfsgid = make_vfsgid(mnt_userns, fs_userns,
|
||||
pa->e_gid);
|
||||
if (vfsgid_in_group_p(vfsgid)) {
|
||||
found = 1;
|
||||
@ -736,6 +737,7 @@ void posix_acl_getxattr_idmapped_mnt(struct user_namespace *mnt_userns,
|
||||
{
|
||||
struct posix_acl_xattr_header *header = value;
|
||||
struct posix_acl_xattr_entry *entry = (void *)(header + 1), *end;
|
||||
struct user_namespace *fs_userns = i_user_ns(inode);
|
||||
int count;
|
||||
vfsuid_t vfsuid;
|
||||
vfsgid_t vfsgid;
|
||||
@ -753,13 +755,13 @@ void posix_acl_getxattr_idmapped_mnt(struct user_namespace *mnt_userns,
|
||||
switch (le16_to_cpu(entry->e_tag)) {
|
||||
case ACL_USER:
|
||||
uid = make_kuid(&init_user_ns, le32_to_cpu(entry->e_id));
|
||||
vfsuid = make_vfsuid(mnt_userns, &init_user_ns, uid);
|
||||
vfsuid = make_vfsuid(mnt_userns, fs_userns, uid);
|
||||
entry->e_id = cpu_to_le32(from_kuid(&init_user_ns,
|
||||
vfsuid_into_kuid(vfsuid)));
|
||||
break;
|
||||
case ACL_GROUP:
|
||||
gid = make_kgid(&init_user_ns, le32_to_cpu(entry->e_id));
|
||||
vfsgid = make_vfsgid(mnt_userns, &init_user_ns, gid);
|
||||
vfsgid = make_vfsgid(mnt_userns, fs_userns, gid);
|
||||
entry->e_id = cpu_to_le32(from_kgid(&init_user_ns,
|
||||
vfsgid_into_kgid(vfsgid)));
|
||||
break;
|
||||
@ -775,6 +777,7 @@ void posix_acl_setxattr_idmapped_mnt(struct user_namespace *mnt_userns,
|
||||
{
|
||||
struct posix_acl_xattr_header *header = value;
|
||||
struct posix_acl_xattr_entry *entry = (void *)(header + 1), *end;
|
||||
struct user_namespace *fs_userns = i_user_ns(inode);
|
||||
int count;
|
||||
vfsuid_t vfsuid;
|
||||
vfsgid_t vfsgid;
|
||||
@ -793,13 +796,13 @@ void posix_acl_setxattr_idmapped_mnt(struct user_namespace *mnt_userns,
|
||||
case ACL_USER:
|
||||
uid = make_kuid(&init_user_ns, le32_to_cpu(entry->e_id));
|
||||
vfsuid = VFSUIDT_INIT(uid);
|
||||
uid = from_vfsuid(mnt_userns, &init_user_ns, vfsuid);
|
||||
uid = from_vfsuid(mnt_userns, fs_userns, vfsuid);
|
||||
entry->e_id = cpu_to_le32(from_kuid(&init_user_ns, uid));
|
||||
break;
|
||||
case ACL_GROUP:
|
||||
gid = make_kgid(&init_user_ns, le32_to_cpu(entry->e_id));
|
||||
vfsgid = VFSGIDT_INIT(gid);
|
||||
gid = from_vfsgid(mnt_userns, &init_user_ns, vfsgid);
|
||||
gid = from_vfsgid(mnt_userns, fs_userns, vfsgid);
|
||||
entry->e_id = cpu_to_le32(from_kgid(&init_user_ns, gid));
|
||||
break;
|
||||
default:
|
||||
|
@ -527,10 +527,12 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr,
|
||||
struct vm_area_struct *vma = walk->vma;
|
||||
bool locked = !!(vma->vm_flags & VM_LOCKED);
|
||||
struct page *page = NULL;
|
||||
bool migration = false;
|
||||
bool migration = false, young = false, dirty = false;
|
||||
|
||||
if (pte_present(*pte)) {
|
||||
page = vm_normal_page(vma, addr, *pte);
|
||||
young = pte_young(*pte);
|
||||
dirty = pte_dirty(*pte);
|
||||
} else if (is_swap_pte(*pte)) {
|
||||
swp_entry_t swpent = pte_to_swp_entry(*pte);
|
||||
|
||||
@ -560,8 +562,7 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr,
|
||||
if (!page)
|
||||
return;
|
||||
|
||||
smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte),
|
||||
locked, migration);
|
||||
smaps_account(mss, page, false, young, dirty, locked, migration);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
|
@ -1601,6 +1601,10 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
|
||||
wake_userfault(vma->vm_userfaultfd_ctx.ctx, &range);
|
||||
}
|
||||
|
||||
/* Reset ptes for the whole vma range if wr-protected */
|
||||
if (userfaultfd_wp(vma))
|
||||
uffd_wp_range(mm, vma, start, vma_end - start, false);
|
||||
|
||||
new_flags = vma->vm_flags & ~__VM_UFFD_FLAGS;
|
||||
prev = vma_merge(mm, prev, start, vma_end, new_flags,
|
||||
vma->anon_vma, vma->vm_file, vma->vm_pgoff,
|
||||
|
@ -2885,7 +2885,6 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
|
||||
#define FOLL_MIGRATION 0x400 /* wait for page to replace migration entry */
|
||||
#define FOLL_TRIED 0x800 /* a retry, previous pass started an IO */
|
||||
#define FOLL_REMOTE 0x2000 /* we are working on non-current tsk/mm */
|
||||
#define FOLL_COW 0x4000 /* internal GUP flag */
|
||||
#define FOLL_ANON 0x8000 /* don't do file mappings */
|
||||
#define FOLL_LONGTERM 0x10000 /* mapping lifetime is indefinite: see below */
|
||||
#define FOLL_SPLIT_PMD 0x20000 /* split huge pmd before returning */
|
||||
|
@ -83,7 +83,6 @@ struct nfs_open_context {
|
||||
fmode_t mode;
|
||||
|
||||
unsigned long flags;
|
||||
#define NFS_CONTEXT_RESEND_WRITES (1)
|
||||
#define NFS_CONTEXT_BAD (2)
|
||||
#define NFS_CONTEXT_UNLOCK (3)
|
||||
#define NFS_CONTEXT_FILE_OPEN (4)
|
||||
@ -182,6 +181,7 @@ struct nfs_inode {
|
||||
/* Regular file */
|
||||
struct {
|
||||
atomic_long_t nrequests;
|
||||
atomic_long_t redirtied_pages;
|
||||
struct nfs_mds_commit_info commit_info;
|
||||
struct mutex commit_mutex;
|
||||
};
|
||||
|
@ -29,15 +29,10 @@ struct shmem_inode_info {
|
||||
struct inode vfs_inode;
|
||||
};
|
||||
|
||||
#define SHMEM_FL_USER_VISIBLE FS_FL_USER_VISIBLE
|
||||
#define SHMEM_FL_USER_MODIFIABLE FS_FL_USER_MODIFIABLE
|
||||
#define SHMEM_FL_INHERITED FS_FL_USER_MODIFIABLE
|
||||
|
||||
/* Flags that are appropriate for regular files (all but dir-specific ones). */
|
||||
#define SHMEM_REG_FLMASK (~(FS_DIRSYNC_FL | FS_TOPDIR_FL))
|
||||
|
||||
/* Flags that are appropriate for non-directories/regular files. */
|
||||
#define SHMEM_OTHER_FLMASK (FS_NODUMP_FL | FS_NOATIME_FL)
|
||||
#define SHMEM_FL_USER_VISIBLE FS_FL_USER_VISIBLE
|
||||
#define SHMEM_FL_USER_MODIFIABLE \
|
||||
(FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL | FS_NOATIME_FL)
|
||||
#define SHMEM_FL_INHERITED (FS_NODUMP_FL | FS_NOATIME_FL)
|
||||
|
||||
struct shmem_sb_info {
|
||||
unsigned long max_blocks; /* How many blocks are allowed */
|
||||
|
@ -73,6 +73,8 @@ extern ssize_t mcopy_continue(struct mm_struct *dst_mm, unsigned long dst_start,
|
||||
extern int mwriteprotect_range(struct mm_struct *dst_mm,
|
||||
unsigned long start, unsigned long len,
|
||||
bool enable_wp, atomic_t *mmap_changing);
|
||||
extern void uffd_wp_range(struct mm_struct *dst_mm, struct vm_area_struct *vma,
|
||||
unsigned long start, unsigned long len, bool enable_wp);
|
||||
|
||||
/* mm helpers */
|
||||
static inline bool is_mergeable_vm_userfaultfd_ctx(struct vm_area_struct *vma,
|
||||
|
@ -20,12 +20,19 @@
|
||||
#define HIGHMEM_ZONE(xx)
|
||||
#endif
|
||||
|
||||
#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL, HIGHMEM_ZONE(xx) xx##_MOVABLE
|
||||
#ifdef CONFIG_ZONE_DEVICE
|
||||
#define DEVICE_ZONE(xx) xx##_DEVICE,
|
||||
#else
|
||||
#define DEVICE_ZONE(xx)
|
||||
#endif
|
||||
|
||||
#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL, \
|
||||
HIGHMEM_ZONE(xx) xx##_MOVABLE, DEVICE_ZONE(xx)
|
||||
|
||||
enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
|
||||
FOR_ALL_ZONES(PGALLOC),
|
||||
FOR_ALL_ZONES(ALLOCSTALL),
|
||||
FOR_ALL_ZONES(PGSCAN_SKIP),
|
||||
FOR_ALL_ZONES(PGALLOC)
|
||||
FOR_ALL_ZONES(ALLOCSTALL)
|
||||
FOR_ALL_ZONES(PGSCAN_SKIP)
|
||||
PGFREE, PGACTIVATE, PGDEACTIVATE, PGLAZYFREE,
|
||||
PGFAULT, PGMAJFAULT,
|
||||
PGLAZYFREED,
|
||||
|
@ -102,6 +102,7 @@ struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule, char *pa
|
||||
|
||||
ret = fsnotify_add_inode_mark(&audit_mark->mark, inode, 0);
|
||||
if (ret < 0) {
|
||||
audit_mark->path = NULL;
|
||||
fsnotify_put_mark(&audit_mark->mark);
|
||||
audit_mark = ERR_PTR(ret);
|
||||
}
|
||||
|
@ -1707,11 +1707,12 @@ static struct kprobe *__disable_kprobe(struct kprobe *p)
|
||||
/* Try to disarm and disable this/parent probe */
|
||||
if (p == orig_p || aggr_kprobe_disabled(orig_p)) {
|
||||
/*
|
||||
* If 'kprobes_all_disarmed' is set, 'orig_p'
|
||||
* should have already been disarmed, so
|
||||
* skip unneed disarming process.
|
||||
* Don't be lazy here. Even if 'kprobes_all_disarmed'
|
||||
* is false, 'orig_p' might not have been armed yet.
|
||||
* Note arm_all_kprobes() __tries__ to arm all kprobes
|
||||
* on the best effort basis.
|
||||
*/
|
||||
if (!kprobes_all_disarmed) {
|
||||
if (!kprobes_all_disarmed && !kprobe_disabled(orig_p)) {
|
||||
ret = disarm_kprobe(orig_p, true);
|
||||
if (ret) {
|
||||
p->flags &= ~KPROBE_FLAG_DISABLED;
|
||||
|
@ -2114,7 +2114,7 @@ static int find_module_sections(struct module *mod, struct load_info *info)
|
||||
sizeof(*mod->static_call_sites),
|
||||
&mod->num_static_call_sites);
|
||||
#endif
|
||||
#ifdef CONFIG_KUNIT
|
||||
#if IS_ENABLED(CONFIG_KUNIT)
|
||||
mod->kunit_suites = section_objs(info, ".kunit_test_suites",
|
||||
sizeof(*mod->kunit_suites),
|
||||
&mod->num_kunit_suites);
|
||||
|
@ -277,6 +277,7 @@ COND_SYSCALL(landlock_restrict_self);
|
||||
|
||||
/* mm/fadvise.c */
|
||||
COND_SYSCALL(fadvise64_64);
|
||||
COND_SYSCALL_COMPAT(fadvise64_64);
|
||||
|
||||
/* mm/, CONFIG_MMU only */
|
||||
COND_SYSCALL(swapon);
|
||||
|
68
mm/gup.c
68
mm/gup.c
@ -478,14 +478,42 @@ static int follow_pfn_pte(struct vm_area_struct *vma, unsigned long address,
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
/*
|
||||
* FOLL_FORCE can write to even unwritable pte's, but only
|
||||
* after we've gone through a COW cycle and they are dirty.
|
||||
*/
|
||||
static inline bool can_follow_write_pte(pte_t pte, unsigned int flags)
|
||||
/* FOLL_FORCE can write to even unwritable PTEs in COW mappings. */
|
||||
static inline bool can_follow_write_pte(pte_t pte, struct page *page,
|
||||
struct vm_area_struct *vma,
|
||||
unsigned int flags)
|
||||
{
|
||||
return pte_write(pte) ||
|
||||
((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte));
|
||||
/* If the pte is writable, we can write to the page. */
|
||||
if (pte_write(pte))
|
||||
return true;
|
||||
|
||||
/* Maybe FOLL_FORCE is set to override it? */
|
||||
if (!(flags & FOLL_FORCE))
|
||||
return false;
|
||||
|
||||
/* But FOLL_FORCE has no effect on shared mappings */
|
||||
if (vma->vm_flags & (VM_MAYSHARE | VM_SHARED))
|
||||
return false;
|
||||
|
||||
/* ... or read-only private ones */
|
||||
if (!(vma->vm_flags & VM_MAYWRITE))
|
||||
return false;
|
||||
|
||||
/* ... or already writable ones that just need to take a write fault */
|
||||
if (vma->vm_flags & VM_WRITE)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* See can_change_pte_writable(): we broke COW and could map the page
|
||||
* writable if we have an exclusive anonymous page ...
|
||||
*/
|
||||
if (!page || !PageAnon(page) || !PageAnonExclusive(page))
|
||||
return false;
|
||||
|
||||
/* ... and a write-fault isn't required for other reasons. */
|
||||
if (vma_soft_dirty_enabled(vma) && !pte_soft_dirty(pte))
|
||||
return false;
|
||||
return !userfaultfd_pte_wp(vma, pte);
|
||||
}
|
||||
|
||||
static struct page *follow_page_pte(struct vm_area_struct *vma,
|
||||
@ -528,12 +556,19 @@ static struct page *follow_page_pte(struct vm_area_struct *vma,
|
||||
}
|
||||
if ((flags & FOLL_NUMA) && pte_protnone(pte))
|
||||
goto no_page;
|
||||
if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, flags)) {
|
||||
pte_unmap_unlock(ptep, ptl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
page = vm_normal_page(vma, address, pte);
|
||||
|
||||
/*
|
||||
* We only care about anon pages in can_follow_write_pte() and don't
|
||||
* have to worry about pte_devmap() because they are never anon.
|
||||
*/
|
||||
if ((flags & FOLL_WRITE) &&
|
||||
!can_follow_write_pte(pte, page, vma, flags)) {
|
||||
page = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!page && pte_devmap(pte) && (flags & (FOLL_GET | FOLL_PIN))) {
|
||||
/*
|
||||
* Only return device mapping pages in the FOLL_GET or FOLL_PIN
|
||||
@ -986,17 +1021,6 @@ static int faultin_page(struct vm_area_struct *vma,
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* The VM_FAULT_WRITE bit tells us that do_wp_page has broken COW when
|
||||
* necessary, even if maybe_mkwrite decided not to set pte_write. We
|
||||
* can thus safely do subsequent page lookups as if they were reads.
|
||||
* But only do so when looping for pte_write is futile: in some cases
|
||||
* userspace may also be wanting to write to the gotten user page,
|
||||
* which a read fault here might prevent (a readonly page might get
|
||||
* reCOWed by userspace write).
|
||||
*/
|
||||
if ((ret & VM_FAULT_WRITE) && !(vma->vm_flags & VM_WRITE))
|
||||
*flags |= FOLL_COW;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1040,12 +1040,6 @@ struct page *follow_devmap_pmd(struct vm_area_struct *vma, unsigned long addr,
|
||||
|
||||
assert_spin_locked(pmd_lockptr(mm, pmd));
|
||||
|
||||
/*
|
||||
* When we COW a devmap PMD entry, we split it into PTEs, so we should
|
||||
* not be in this function with `flags & FOLL_COW` set.
|
||||
*/
|
||||
WARN_ONCE(flags & FOLL_COW, "mm: In follow_devmap_pmd with FOLL_COW set");
|
||||
|
||||
/* FOLL_GET and FOLL_PIN are mutually exclusive. */
|
||||
if (WARN_ON_ONCE((flags & (FOLL_PIN | FOLL_GET)) ==
|
||||
(FOLL_PIN | FOLL_GET)))
|
||||
@ -1395,14 +1389,42 @@ vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf)
|
||||
return VM_FAULT_FALLBACK;
|
||||
}
|
||||
|
||||
/*
|
||||
* FOLL_FORCE can write to even unwritable pmd's, but only
|
||||
* after we've gone through a COW cycle and they are dirty.
|
||||
*/
|
||||
static inline bool can_follow_write_pmd(pmd_t pmd, unsigned int flags)
|
||||
/* FOLL_FORCE can write to even unwritable PMDs in COW mappings. */
|
||||
static inline bool can_follow_write_pmd(pmd_t pmd, struct page *page,
|
||||
struct vm_area_struct *vma,
|
||||
unsigned int flags)
|
||||
{
|
||||
return pmd_write(pmd) ||
|
||||
((flags & FOLL_FORCE) && (flags & FOLL_COW) && pmd_dirty(pmd));
|
||||
/* If the pmd is writable, we can write to the page. */
|
||||
if (pmd_write(pmd))
|
||||
return true;
|
||||
|
||||
/* Maybe FOLL_FORCE is set to override it? */
|
||||
if (!(flags & FOLL_FORCE))
|
||||
return false;
|
||||
|
||||
/* But FOLL_FORCE has no effect on shared mappings */
|
||||
if (vma->vm_flags & (VM_MAYSHARE | VM_SHARED))
|
||||
return false;
|
||||
|
||||
/* ... or read-only private ones */
|
||||
if (!(vma->vm_flags & VM_MAYWRITE))
|
||||
return false;
|
||||
|
||||
/* ... or already writable ones that just need to take a write fault */
|
||||
if (vma->vm_flags & VM_WRITE)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* See can_change_pte_writable(): we broke COW and could map the page
|
||||
* writable if we have an exclusive anonymous page ...
|
||||
*/
|
||||
if (!page || !PageAnon(page) || !PageAnonExclusive(page))
|
||||
return false;
|
||||
|
||||
/* ... and a write-fault isn't required for other reasons. */
|
||||
if (vma_soft_dirty_enabled(vma) && !pmd_soft_dirty(pmd))
|
||||
return false;
|
||||
return !userfaultfd_huge_pmd_wp(vma, pmd);
|
||||
}
|
||||
|
||||
struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
|
||||
@ -1411,12 +1433,16 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct mm_struct *mm = vma->vm_mm;
|
||||
struct page *page = NULL;
|
||||
struct page *page;
|
||||
|
||||
assert_spin_locked(pmd_lockptr(mm, pmd));
|
||||
|
||||
if (flags & FOLL_WRITE && !can_follow_write_pmd(*pmd, flags))
|
||||
goto out;
|
||||
page = pmd_page(*pmd);
|
||||
VM_BUG_ON_PAGE(!PageHead(page) && !is_zone_device_page(page), page);
|
||||
|
||||
if ((flags & FOLL_WRITE) &&
|
||||
!can_follow_write_pmd(*pmd, page, vma, flags))
|
||||
return NULL;
|
||||
|
||||
/* Avoid dumping huge zero page */
|
||||
if ((flags & FOLL_DUMP) && is_huge_zero_pmd(*pmd))
|
||||
@ -1424,10 +1450,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
|
||||
|
||||
/* Full NUMA hinting faults to serialise migration in fault paths */
|
||||
if ((flags & FOLL_NUMA) && pmd_protnone(*pmd))
|
||||
goto out;
|
||||
|
||||
page = pmd_page(*pmd);
|
||||
VM_BUG_ON_PAGE(!PageHead(page) && !is_zone_device_page(page), page);
|
||||
return NULL;
|
||||
|
||||
if (!pmd_write(*pmd) && gup_must_unshare(flags, page))
|
||||
return ERR_PTR(-EMLINK);
|
||||
@ -1444,7 +1467,6 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
|
||||
page += (addr & ~HPAGE_PMD_MASK) >> PAGE_SHIFT;
|
||||
VM_BUG_ON_PAGE(!PageCompound(page) && !is_zone_device_page(page), page);
|
||||
|
||||
out:
|
||||
return page;
|
||||
}
|
||||
|
||||
|
26
mm/hugetlb.c
26
mm/hugetlb.c
@ -5241,6 +5241,21 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
VM_BUG_ON(unshare && (flags & FOLL_WRITE));
|
||||
VM_BUG_ON(!unshare && !(flags & FOLL_WRITE));
|
||||
|
||||
/*
|
||||
* hugetlb does not support FOLL_FORCE-style write faults that keep the
|
||||
* PTE mapped R/O such as maybe_mkwrite() would do.
|
||||
*/
|
||||
if (WARN_ON_ONCE(!unshare && !(vma->vm_flags & VM_WRITE)))
|
||||
return VM_FAULT_SIGSEGV;
|
||||
|
||||
/* Let's take out MAP_SHARED mappings first. */
|
||||
if (vma->vm_flags & VM_MAYSHARE) {
|
||||
if (unlikely(unshare))
|
||||
return 0;
|
||||
set_huge_ptep_writable(vma, haddr, ptep);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pte = huge_ptep_get(ptep);
|
||||
old_page = pte_page(pte);
|
||||
|
||||
@ -5781,12 +5796,11 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
* If we are going to COW/unshare the mapping later, we examine the
|
||||
* pending reservations for this page now. This will ensure that any
|
||||
* allocations necessary to record that reservation occur outside the
|
||||
* spinlock. For private mappings, we also lookup the pagecache
|
||||
* page now as it is used to determine if a reservation has been
|
||||
* consumed.
|
||||
* spinlock. Also lookup the pagecache page now as it is used to
|
||||
* determine if a reservation has been consumed.
|
||||
*/
|
||||
if ((flags & (FAULT_FLAG_WRITE|FAULT_FLAG_UNSHARE)) &&
|
||||
!huge_pte_write(entry)) {
|
||||
!(vma->vm_flags & VM_MAYSHARE) && !huge_pte_write(entry)) {
|
||||
if (vma_needs_reservation(h, vma, haddr) < 0) {
|
||||
ret = VM_FAULT_OOM;
|
||||
goto out_mutex;
|
||||
@ -5794,9 +5808,7 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
/* Just decrements count, does not deallocate */
|
||||
vma_end_reservation(h, vma, haddr);
|
||||
|
||||
if (!(vma->vm_flags & VM_MAYSHARE))
|
||||
pagecache_page = hugetlbfs_pagecache_page(h,
|
||||
vma, haddr);
|
||||
pagecache_page = hugetlbfs_pagecache_page(h, vma, haddr);
|
||||
}
|
||||
|
||||
ptl = huge_pte_lock(h, mm, ptep);
|
||||
|
@ -1646,8 +1646,11 @@ int vma_wants_writenotify(struct vm_area_struct *vma, pgprot_t vm_page_prot)
|
||||
pgprot_val(vm_pgprot_modify(vm_page_prot, vm_flags)))
|
||||
return 0;
|
||||
|
||||
/* Do we need to track softdirty? */
|
||||
if (vma_soft_dirty_enabled(vma))
|
||||
/*
|
||||
* Do we need to track softdirty? hugetlb does not support softdirty
|
||||
* tracking yet.
|
||||
*/
|
||||
if (vma_soft_dirty_enabled(vma) && !is_vm_hugetlb_page(vma))
|
||||
return 1;
|
||||
|
||||
/* Specialty mapping? */
|
||||
|
59
mm/shmem.c
59
mm/shmem.c
@ -1659,7 +1659,9 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp,
|
||||
new = page_folio(newpage);
|
||||
mem_cgroup_migrate(old, new);
|
||||
__inc_lruvec_page_state(newpage, NR_FILE_PAGES);
|
||||
__inc_lruvec_page_state(newpage, NR_SHMEM);
|
||||
__dec_lruvec_page_state(oldpage, NR_FILE_PAGES);
|
||||
__dec_lruvec_page_state(oldpage, NR_SHMEM);
|
||||
}
|
||||
xa_unlock_irq(&swap_mapping->i_pages);
|
||||
|
||||
@ -2281,16 +2283,34 @@ static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Mask out flags that are inappropriate for the given type of inode. */
|
||||
static unsigned shmem_mask_flags(umode_t mode, __u32 flags)
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
static int shmem_initxattrs(struct inode *, const struct xattr *, void *);
|
||||
|
||||
/*
|
||||
* chattr's fsflags are unrelated to extended attributes,
|
||||
* but tmpfs has chosen to enable them under the same config option.
|
||||
*/
|
||||
static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags)
|
||||
{
|
||||
if (S_ISDIR(mode))
|
||||
return flags;
|
||||
else if (S_ISREG(mode))
|
||||
return flags & SHMEM_REG_FLMASK;
|
||||
else
|
||||
return flags & SHMEM_OTHER_FLMASK;
|
||||
unsigned int i_flags = 0;
|
||||
|
||||
if (fsflags & FS_NOATIME_FL)
|
||||
i_flags |= S_NOATIME;
|
||||
if (fsflags & FS_APPEND_FL)
|
||||
i_flags |= S_APPEND;
|
||||
if (fsflags & FS_IMMUTABLE_FL)
|
||||
i_flags |= S_IMMUTABLE;
|
||||
/*
|
||||
* But FS_NODUMP_FL does not require any action in i_flags.
|
||||
*/
|
||||
inode_set_flags(inode, i_flags, S_NOATIME | S_APPEND | S_IMMUTABLE);
|
||||
}
|
||||
#else
|
||||
static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags)
|
||||
{
|
||||
}
|
||||
#define shmem_initxattrs NULL
|
||||
#endif
|
||||
|
||||
static struct inode *shmem_get_inode(struct super_block *sb, struct inode *dir,
|
||||
umode_t mode, dev_t dev, unsigned long flags)
|
||||
@ -2319,7 +2339,8 @@ static struct inode *shmem_get_inode(struct super_block *sb, struct inode *dir,
|
||||
info->i_crtime = inode->i_mtime;
|
||||
info->fsflags = (dir == NULL) ? 0 :
|
||||
SHMEM_I(dir)->fsflags & SHMEM_FL_INHERITED;
|
||||
info->fsflags = shmem_mask_flags(mode, info->fsflags);
|
||||
if (info->fsflags)
|
||||
shmem_set_inode_flags(inode, info->fsflags);
|
||||
INIT_LIST_HEAD(&info->shrinklist);
|
||||
INIT_LIST_HEAD(&info->swaplist);
|
||||
simple_xattrs_init(&info->xattrs);
|
||||
@ -2468,12 +2489,6 @@ int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
|
||||
static const struct inode_operations shmem_symlink_inode_operations;
|
||||
static const struct inode_operations shmem_short_symlink_operations;
|
||||
|
||||
#ifdef CONFIG_TMPFS_XATTR
|
||||
static int shmem_initxattrs(struct inode *, const struct xattr *, void *);
|
||||
#else
|
||||
#define shmem_initxattrs NULL
|
||||
#endif
|
||||
|
||||
static int
|
||||
shmem_write_begin(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned len,
|
||||
@ -2826,12 +2841,13 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
|
||||
|
||||
if (!(mode & FALLOC_FL_KEEP_SIZE) && offset + len > inode->i_size)
|
||||
i_size_write(inode, offset + len);
|
||||
inode->i_ctime = current_time(inode);
|
||||
undone:
|
||||
spin_lock(&inode->i_lock);
|
||||
inode->i_private = NULL;
|
||||
spin_unlock(&inode->i_lock);
|
||||
out:
|
||||
if (!error)
|
||||
file_modified(file);
|
||||
inode_unlock(inode);
|
||||
return error;
|
||||
}
|
||||
@ -3179,18 +3195,13 @@ static int shmem_fileattr_set(struct user_namespace *mnt_userns,
|
||||
|
||||
if (fileattr_has_fsx(fa))
|
||||
return -EOPNOTSUPP;
|
||||
if (fa->flags & ~SHMEM_FL_USER_MODIFIABLE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
info->fsflags = (info->fsflags & ~SHMEM_FL_USER_MODIFIABLE) |
|
||||
(fa->flags & SHMEM_FL_USER_MODIFIABLE);
|
||||
|
||||
inode->i_flags &= ~(S_APPEND | S_IMMUTABLE | S_NOATIME);
|
||||
if (info->fsflags & FS_APPEND_FL)
|
||||
inode->i_flags |= S_APPEND;
|
||||
if (info->fsflags & FS_IMMUTABLE_FL)
|
||||
inode->i_flags |= S_IMMUTABLE;
|
||||
if (info->fsflags & FS_NOATIME_FL)
|
||||
inode->i_flags |= S_NOATIME;
|
||||
|
||||
shmem_set_inode_flags(inode, info->fsflags);
|
||||
inode->i_ctime = current_time(inode);
|
||||
return 0;
|
||||
}
|
||||
|
@ -703,14 +703,29 @@ ssize_t mcopy_continue(struct mm_struct *dst_mm, unsigned long start,
|
||||
mmap_changing, 0);
|
||||
}
|
||||
|
||||
void uffd_wp_range(struct mm_struct *dst_mm, struct vm_area_struct *dst_vma,
|
||||
unsigned long start, unsigned long len, bool enable_wp)
|
||||
{
|
||||
struct mmu_gather tlb;
|
||||
pgprot_t newprot;
|
||||
|
||||
if (enable_wp)
|
||||
newprot = vm_get_page_prot(dst_vma->vm_flags & ~(VM_WRITE));
|
||||
else
|
||||
newprot = vm_get_page_prot(dst_vma->vm_flags);
|
||||
|
||||
tlb_gather_mmu(&tlb, dst_mm);
|
||||
change_protection(&tlb, dst_vma, start, start + len, newprot,
|
||||
enable_wp ? MM_CP_UFFD_WP : MM_CP_UFFD_WP_RESOLVE);
|
||||
tlb_finish_mmu(&tlb);
|
||||
}
|
||||
|
||||
int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start,
|
||||
unsigned long len, bool enable_wp,
|
||||
atomic_t *mmap_changing)
|
||||
{
|
||||
struct vm_area_struct *dst_vma;
|
||||
unsigned long page_mask;
|
||||
struct mmu_gather tlb;
|
||||
pgprot_t newprot;
|
||||
int err;
|
||||
|
||||
/*
|
||||
@ -750,15 +765,7 @@ int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start,
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (enable_wp)
|
||||
newprot = vm_get_page_prot(dst_vma->vm_flags & ~(VM_WRITE));
|
||||
else
|
||||
newprot = vm_get_page_prot(dst_vma->vm_flags);
|
||||
|
||||
tlb_gather_mmu(&tlb, dst_mm);
|
||||
change_protection(&tlb, dst_vma, start, start + len, newprot,
|
||||
enable_wp ? MM_CP_UFFD_WP : MM_CP_UFFD_WP_RESOLVE);
|
||||
tlb_finish_mmu(&tlb);
|
||||
uffd_wp_range(dst_mm, dst_vma, start, len, enable_wp);
|
||||
|
||||
err = 0;
|
||||
out_unlock:
|
||||
|
@ -1168,8 +1168,15 @@ int fragmentation_index(struct zone *zone, unsigned int order)
|
||||
#define TEXT_FOR_HIGHMEM(xx)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ZONE_DEVICE
|
||||
#define TEXT_FOR_DEVICE(xx) xx "_device",
|
||||
#else
|
||||
#define TEXT_FOR_DEVICE(xx)
|
||||
#endif
|
||||
|
||||
#define TEXTS_FOR_ZONES(xx) TEXT_FOR_DMA(xx) TEXT_FOR_DMA32(xx) xx "_normal", \
|
||||
TEXT_FOR_HIGHMEM(xx) xx "_movable",
|
||||
TEXT_FOR_HIGHMEM(xx) xx "_movable", \
|
||||
TEXT_FOR_DEVICE(xx)
|
||||
|
||||
const char * const vmstat_text[] = {
|
||||
/* enum zone_stat_item counters */
|
||||
|
@ -1902,7 +1902,7 @@ call_encode(struct rpc_task *task)
|
||||
break;
|
||||
case -EKEYEXPIRED:
|
||||
if (!task->tk_cred_retry) {
|
||||
rpc_exit(task, task->tk_status);
|
||||
rpc_call_rpcerror(task, task->tk_status);
|
||||
} else {
|
||||
task->tk_action = call_refresh;
|
||||
task->tk_cred_retry--;
|
||||
|
@ -36,4 +36,8 @@
|
||||
#include <linux/compiler-gcc.h>
|
||||
#endif
|
||||
|
||||
#ifndef asm_volatile_goto
|
||||
#define asm_volatile_goto(x...) asm goto(x)
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_COMPILER_TYPES_H */
|
||||
|
@ -40,6 +40,7 @@ ifeq (0,$(MAKELEVEL))
|
||||
endif
|
||||
endif
|
||||
selfdir = $(realpath $(dir $(filter %/lib.mk,$(MAKEFILE_LIST))))
|
||||
top_srcdir = $(selfdir)/../../..
|
||||
|
||||
# The following are built by lib.mk common compile rules.
|
||||
# TEST_CUSTOM_PROGS should be used by tests that require
|
||||
|
@ -17,6 +17,12 @@
|
||||
#include "defines.h"
|
||||
#include "main.h"
|
||||
|
||||
/*
|
||||
* FIXME: OpenSSL 3.0 has deprecated some functions. For now just ignore
|
||||
* the warnings.
|
||||
*/
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
struct q1q2_ctx {
|
||||
BN_CTX *bn_ctx;
|
||||
BIGNUM *m;
|
||||
|
Loading…
Reference in New Issue
Block a user