summaryrefslogtreecommitdiffstats
path: root/kernel/nsproxy.c
AgeCommit message (Expand)Author
2014-12-04bury struct proc_ns in fs/procAl Viro
2014-12-04copy address of proc_ns_ops into ns_commonAl Viro
2014-07-29namespaces: Use task_lock and not rcu to protect nsproxyEric W. Biederman
2013-09-07Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebi...Linus Torvalds
2013-08-30namespaces: Simplify copy_namespaces so it is clear what is going on.Eric W. Biederman
2013-08-27Rename nsproxy.pid_ns to nsproxy.pid_ns_for_childrenAndy Lutomirski
2013-08-26kernel/nsproxy.c: Improving a snippet of code.Raphael S.Carvalho
2013-05-01proc: Split the namespace stuff out into linux/proc_ns.hDavid Howells
2013-02-26Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vir...Linus Torvalds
2013-02-22new helper: file_inode(file)Al Viro
2013-02-21kernel/nsproxy.c: remove duplicate task_cred_xxx for user_nsYuanhan Liu
2012-11-20userns: Implement unshare of the user namespaceEric W. Biederman
2012-11-20userns: Make create_new_namespaces take a user_ns parameterEric W. Biederman
2012-11-20userns: Allow unprivileged use of setns.Eric W. Biederman
2012-11-20userns: Allow unprivileged users to create new namespacesEric W. Biederman
2012-11-19vfs: Add a user namespace reference from struct mnt_namespaceEric W. Biederman
2012-11-19pidns: Support unsharing the pid namespace.Eric W. Biederman
2012-11-19pidns: Use task_active_pid_ns where appropriateEric W. Biederman
2012-11-19pidns: Capture the user namespace and filter ns_last_pidEric W. Biederman
2012-11-18userns: make each net (net_ns) belong to a user_nsEric W. Biederman
2011-10-31kernel: Map most files to use export.h instead of module.hPaul Gortmaker
2011-07-20make sure that nsproxy_cache is initialized early enoughAl Viro
2011-05-26cgroup: remove the ns_cgroupDaniel Lezcano
2011-05-10ns: Introduce the setns syscallEric W. Biederman
2011-03-23userns: user namespaces: convert several capable() callsSerge E. Hallyn
2011-03-23userns: add a user namespace owner of ipc nsSerge E. Hallyn
2011-03-23userns: allow sethostname in a containerSerge E. Hallyn
2011-03-23userns: add a user_namespace as creator/owner of uts_namespaceSerge E. Hallyn
2010-03-30include cleanup: Update gfp.h and slab.h includes to prepare for breaking imp...Tejun Heo
2010-03-12nsproxy: remove INIT_NSPROXY()Alexey Dobriyan
2009-06-18nsproxy: extract create_nsproxy()Alexey Dobriyan
2008-11-24User namespaces: set of cleanups (v2)Serge Hallyn
2008-08-23removed unused #include <linux/version.h>'sAdrian Bunk
2008-07-25cgroup_clone: use pid of newly created task for new cgroupSerge E. Hallyn
2008-04-29ipc: sysvsem: refuse clone(CLONE_SYSVSEM|CLONE_NEWIPC)Serge E. Hallyn
2008-02-08namespaces: move the IPC namespace under IPC_NS optionPavel Emelyanov
2007-10-19pid namespaces: allow cloning of new namespacePavel Emelyanov
2007-10-19Make access to task's nsproxy lighterPavel Emelyanov
2007-10-19pid namespaces: define and use task_active_pid_ns() wrapperSukadev Bhattiprolu
2007-10-19cgroups: implement namespace tracking subsystemSerge E. Hallyn
2007-10-17Use KMEM_CACHE macro to create the nsproxy cachePavel Emelyanov
2007-10-10[NET]: Add network namespace clone & unshare support.Eric W. Biederman
2007-07-20mm: Remove slab destructors from kmem_cache_create().Paul Mundt
2007-07-16namespace: ensure clone_flags are always stored in an unsigned longEric W. Biederman
2007-07-16add a kmem_cache for nsproxy objectsCedric Le Goater
2007-07-16fix create_new_namespaces() return valueCedric Le Goater
2007-07-16user namespace: add unshareSerge E. Hallyn
2007-07-16user namespace: add the frameworkCedric Le Goater
2007-07-16remove CONFIG_UTS_NS and CONFIG_IPC_NSCedric Le Goater
2007-06-24fix refcounting of nsproxy object when unsharedCedric Le Goater
mment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
/*
 *  linux/mm/page_io.c
 *
 *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
 *
 *  Swap reorganised 29.12.95, 
 *  Asynchronous swapping added 30.12.95. Stephen Tweedie
 *  Removed race in async swapping. 14.4.1996. Bruno Haible
 *  Add swap of shared pages through the page cache. 20.2.1998. Stephen Tweedie
 *  Always use brw_page, life becomes simpler. 12 May 1998 Eric Biederman
 */

#include <linux/mm.h>
#include <linux/kernel_stat.h>
#include <linux/gfp.h>
#include <linux/pagemap.h>
#include <linux/swap.h>
#include <linux/bio.h>
#include <linux/swapops.h>
#include <linux/buffer_head.h>
#include <linux/writeback.h>
#include <linux/frontswap.h>
#include <linux/aio.h>
#include <linux/blkdev.h>
#include <asm/pgtable.h>

static struct bio *get_swap_bio(gfp_t gfp_flags,
				struct page *page, bio_end_io_t end_io)
{
	struct bio *bio;

	bio = bio_alloc(gfp_flags, 1);
	if (bio) {
		bio->bi_sector = map_swap_page(page, &bio->bi_bdev);
		bio->bi_sector <<= PAGE_SHIFT - 9;
		bio->bi_io_vec[0].bv_page = page;
		bio->bi_io_vec[0].bv_len = PAGE_SIZE;
		bio->bi_io_vec[0].bv_offset = 0;
		bio->bi_vcnt = 1;
		bio->bi_size = PAGE_SIZE;
		bio->bi_end_io = end_io;
	}
	return bio;
}

void end_swap_bio_write(struct bio *bio, int err)
{
	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
	struct page *page = bio->bi_io_vec[0].bv_page;

	if (!uptodate) {
		SetPageError(page);
		/*
		 * We failed to write the page out to swap-space.
		 * Re-dirty the page in order to avoid it being reclaimed.
		 * Also print a dire warning that things will go BAD (tm)
		 * very quickly.
		 *
		 * Also clear PG_reclaim to avoid rotate_reclaimable_page()
		 */
		set_page_dirty(page);
		printk(KERN_ALERT "Write-error on swap-device (%u:%u:%Lu)\n",
				imajor(bio->bi_bdev->bd_inode),
				iminor(bio->bi_bdev->bd_inode),
				(unsigned long long)bio->bi_sector);
		ClearPageReclaim(page);
	}
	end_page_writeback(page);
	bio_put(bio);
}

void end_swap_bio_read(struct bio *bio, int err)
{
	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
	struct page *page = bio->bi_io_vec[0].bv_page;

	if (!uptodate) {
		SetPageError(page);
		ClearPageUptodate(page);
		printk(KERN_ALERT "Read-error on swap-device (%u:%u:%Lu)\n",
				imajor(bio->bi_bdev->bd_inode),
				iminor(bio->bi_bdev->bd_inode),
				(unsigned long long)bio->bi_sector);
		goto out;
	}

	SetPageUptodate(page);

	/*
	 * There is no guarantee that the page is in swap cache - the software
	 * suspend code (at least) uses end_swap_bio_read() against a non-
	 * swapcache page.  So we must check PG_swapcache before proceeding with
	 * this optimization.
	 */
	if (likely(PageSwapCache(page))) {
		struct swap_info_struct *sis;

		sis = page_swap_info(page);
		if (sis->flags & SWP_BLKDEV) {
			/*
			 * The swap subsystem performs lazy swap slot freeing,
			 * expecting that the page will be swapped out again.
			 * So we can avoid an unnecessary write if the page
			 * isn't redirtied.
			 * This is good for real swap storage because we can
			 * reduce unnecessary I/O and enhance wear-leveling
			 * if an SSD is used as the as swap device.
			 * But if in-memory swap device (eg zram) is used,
			 * this causes a duplicated copy between uncompressed
			 * data in VM-owned memory and compressed data in
			 * zram-owned memory.  So let's free zram-owned memory
			 * and make the VM-owned decompressed page *dirty*,
			 * so the page should be swapped out somewhere again if
			 * we again wish to reclaim it.
			 */
			struct gendisk *disk = sis->bdev->bd_disk;
			if (disk->fops->swap_slot_free_notify) {
				swp_entry_t entry;
				unsigned long offset;

				entry.val = page_private(page);
				offset = swp_offset(entry);

				SetPageDirty(page);
				disk->fops->swap_slot_free_notify(sis->bdev,
						offset);
			}
		}
	}

out:
	unlock_page(page);
	bio_put(bio);
}

int generic_swapfile_activate(struct swap_info_struct *sis,
				struct file *swap_file,
				sector_t *span)
{
	struct address_space *mapping = swap_file->f_mapping;
	struct inode *inode = mapping->host;
	unsigned blocks_per_page;
	unsigned long page_no;
	unsigned blkbits;
	sector_t probe_block;
	sector_t last_block;
	sector_t lowest_block = -1;
	sector_t highest_block = 0;
	int nr_extents = 0;
	int ret;

	blkbits = inode->i_blkbits;
	blocks_per_page = PAGE_SIZE >> blkbits;

	/*
	 * Map all the blocks into the extent list.  This code doesn't try
	 * to be very smart.
	 */
	probe_block = 0;
	page_no = 0;
	last_block = i_size_read(inode) >> blkbits;
	while ((probe_block + blocks_per_page) <= last_block &&
			page_no < sis->max) {
		unsigned block_in_page;
		sector_t first_block;

		first_block = bmap(inode, probe_block);
		if (first_block == 0)
			goto bad_bmap;

		/*
		 * It must be PAGE_SIZE aligned on-disk
		 */
		if (first_block & (blocks_per_page - 1)) {
			probe_block++;
			goto reprobe;
		}

		for (block_in_page = 1; block_in_page < blocks_per_page;
					block_in_page++) {
			sector_t block;

			block = bmap(inode, probe_block + block_in_page);
			if (block == 0)
				goto bad_bmap;
			if (block != first_block + block_in_page) {
				/* Discontiguity */
				probe_block++;
				goto reprobe;
			}
		}

		first_block >>= (PAGE_SHIFT - blkbits);
		if (page_no) {	/* exclude the header page */
			if (first_block < lowest_block)
				lowest_block = first_block;
			if (first_block > highest_block)
				highest_block = first_block;
		}

		/*
		 * We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks
		 */
		ret = add_swap_extent(sis, page_no, 1, first_block);
		if (ret < 0)
			goto out;
		nr_extents += ret;
		page_no++;
		probe_block += blocks_per_page;
reprobe:
		continue;
	}
	ret = nr_extents;
	*span = 1 + highest_block - lowest_block;
	if (page_no == 0)
		page_no = 1;	/* force Empty message */
	sis->max = page_no;
	sis->pages = page_no - 1;
	sis->highest_bit = page_no - 1;
out:
	return ret;
bad_bmap:
	printk(KERN_ERR "swapon: swapfile has holes\n");
	ret = -EINVAL;
	goto out;
}

/*
 * We may have stale swap cache pages in memory: notice
 * them here and get rid of the unnecessary final write.
 */
int swap_writepage(struct page *page, struct writeback_control *wbc)
{
	int ret = 0;

	if (try_to_free_swap(page)) {
		unlock_page(page);
		goto out;
	}
	if (frontswap_store(page) == 0) {
		set_page_writeback(page);
		unlock_page(page);
		end_page_writeback(page);
		goto out;
	}
	ret = __swap_writepage(page, wbc, end_swap_bio_write);
out:
	return ret;
}

int __swap_writepage(struct page *page, struct writeback_control *wbc,
	void (*end_write_func)(struct bio *, int))
{
	struct bio *bio;
	int ret = 0, rw = WRITE;
	struct swap_info_struct *sis = page_swap_info(page);

	if (sis->flags & SWP_FILE) {
		struct kiocb kiocb;
		struct file *swap_file = sis->swap_file;
		struct address_space *mapping = swap_file->f_mapping;
		struct iovec iov = {
			.iov_base = kmap(page),
			.iov_len  = PAGE_SIZE,
		};

		init_sync_kiocb(&kiocb, swap_file);
		kiocb.ki_pos = page_file_offset(page);
		kiocb.ki_nbytes = PAGE_SIZE;

		set_page_writeback(page);
		unlock_page(page);
		ret = mapping->a_ops->direct_IO(KERNEL_WRITE,
						&kiocb, &iov,
						kiocb.ki_pos, 1);
		kunmap(page);
		if (ret == PAGE_SIZE) {
			count_vm_event(PSWPOUT);
			ret = 0;
		} else {
			/*
			 * In the case of swap-over-nfs, this can be a
			 * temporary failure if the system has limited
			 * memory for allocating transmit buffers.
			 * Mark the page dirty and avoid
			 * rotate_reclaimable_page but rate-limit the
			 * messages but do not flag PageError like
			 * the normal direct-to-bio case as it could
			 * be temporary.
			 */