linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Andrew Morton <akpm@linux-foundation.org>
To: Mike Kravetz <mike.kravetz@oracle.com>
Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org,
	linux-api@vger.kernel.org,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>,
	David Rientjes <rientjes@google.com>,
	Hugh Dickins <hughd@google.com>,
	Davidlohr Bueso <dave@stgolabs.net>,
	Aneesh Kumar <aneesh.kumar@linux.vnet.ibm.com>,
	Hillf Danton <hillf.zj@alibaba-inc.com>,
	Christoph Hellwig <hch@infradead.org>,
	Michal Hocko <mhocko@suse.cz>
Subject: Re: [PATCH v4 09/10] hugetlbfs: add hugetlbfs_fallocate()
Date: Wed, 22 Jul 2015 15:03:45 -0700	[thread overview]
Message-ID: <20150722150345.f8d5b0042cfa7112bd95d9ef@linux-foundation.org> (raw)
In-Reply-To: <1437502184-14269-10-git-send-email-mike.kravetz@oracle.com>

On Tue, 21 Jul 2015 11:09:43 -0700 Mike Kravetz <mike.kravetz@oracle.com> wrote:

> This is based on the shmem version, but it has diverged quite
> a bit.  We have no swap to worry about, nor the new file sealing.
> Add synchronication via the fault mutex table to coordinate
> page faults,  fallocate allocation and fallocate hole punch.
> 
> What this allows us to do is move physical memory in and out of
> a hugetlbfs file without having it mapped.  This also gives us
> the ability to support MADV_REMOVE since it is currently
> implemented using fallocate().  MADV_REMOVE lets madvise() remove
> pages from the middle of a hugetlbfs file, which wasn't possible
> before.
> 
> hugetlbfs fallocate only operates on whole huge pages.
> 
> ...
>
> +static long hugetlbfs_fallocate(struct file *file, int mode, loff_t offset,
> +				loff_t len)
> +{
> +	struct inode *inode = file_inode(file);
> +	struct address_space *mapping = inode->i_mapping;
> +	struct hstate *h = hstate_inode(inode);
> +	struct vm_area_struct pseudo_vma;
> +	struct mm_struct *mm = current->mm;
> +	loff_t hpage_size = huge_page_size(h);
> +	unsigned long hpage_shift = huge_page_shift(h);
> +	pgoff_t start, index, end;
> +	int error;
> +	u32 hash;
> +
> +	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
> +		return -EOPNOTSUPP;

EOPNOTSUPP is a networking thing.  It's inappropriate here.

The problem is that if this error is ever returned to userspace, the
user will be sitting looking at "Operation not supported on transport
endpoint" and wondering what went wrong in the networking stack.

> +	if (mode & FALLOC_FL_PUNCH_HOLE)
> +		return hugetlbfs_punch_hole(inode, offset, len);
> +
> +	/*
> +	 * Default preallocate case.
> +	 * For this range, start is rounded down and end is rounded up
> +	 * as well as being converted to page offsets.
> +	 */
> +	start = offset >> hpage_shift;
> +	end = (offset + len + hpage_size - 1) >> hpage_shift;
> +
> +	mutex_lock(&inode->i_mutex);
> +
> +	/* We need to check rlimit even when FALLOC_FL_KEEP_SIZE */
> +	error = inode_newsize_ok(inode, offset + len);
> +	if (error)
> +		goto out;
> +
> +	/*
> +	 * Initialize a pseudo vma that just contains the policy used
> +	 * when allocating the huge pages.  The actual policy field
> +	 * (vm_policy) is determined based on the index in the loop below.
> +	 */
> +	memset(&pseudo_vma, 0, sizeof(struct vm_area_struct));
> +	pseudo_vma.vm_flags = (VM_HUGETLB | VM_MAYSHARE | VM_SHARED);
> +	pseudo_vma.vm_file = file;

triviata: we could have just done

	struct vm_area_struct pseudo_vma = {
		.vm_flags = ...
		.vm_file = file;
	};

> +	for (index = start; index < end; index++) {
> +		/*
> +		 * This is supposed to be the vaddr where the page is being
> +		 * faulted in, but we have no vaddr here.
> +		 */
> +		struct page *page;
> +		unsigned long addr;
> +		int avoid_reserve = 0;
> +
> +		cond_resched();
> +
> +		/*
> +		 * fallocate(2) manpage permits EINTR; we may have been
> +		 * interrupted because we are using up too much memory.
> +		 */
> +		if (signal_pending(current)) {
> +			error = -EINTR;
> +			break;
> +		}
> +
> +		/* Get policy based on index */
> +		pseudo_vma.vm_policy =
> +			mpol_shared_policy_lookup(&HUGETLBFS_I(inode)->policy,
> +							index);
> +
> +		/* addr is the offset within the file (zero based) */

So use loff_t?

> +		addr = index * hpage_size;
> +
> +		/* mutex taken here, fault path and hole punch */
> +		hash = hugetlb_fault_mutex_hash(h, mm, &pseudo_vma, mapping,
> +						index, addr);
> +		mutex_lock(&hugetlb_fault_mutex_table[hash]);
> +
> +		/* See if already present in mapping to avoid alloc/free */
> +		page = find_get_page(mapping, index);
> +		if (page) {
> +			put_page(page);
> +			mutex_unlock(&hugetlb_fault_mutex_table[hash]);
> +			mpol_cond_put(pseudo_vma.vm_policy);
> +			continue;
> +		}
> +
> +		/* Allocate page and add to page cache */
> +		page = alloc_huge_page(&pseudo_vma, addr, avoid_reserve);
> +		mpol_cond_put(pseudo_vma.vm_policy);
> +		if (IS_ERR(page)) {
> +			mutex_unlock(&hugetlb_fault_mutex_table[hash]);
> +			error = PTR_ERR(page);
> +			goto out;
> +		}
> +		clear_huge_page(page, addr, pages_per_huge_page(h));
> +		__SetPageUptodate(page);
> +		error = huge_add_to_page_cache(page, mapping, index);
> +		if (unlikely(error)) {
> +			put_page(page);
> +			mutex_unlock(&hugetlb_fault_mutex_table[hash]);
> +			goto out;
> +		}
> +
> +		mutex_unlock(&hugetlb_fault_mutex_table[hash]);
> +
> +		/*
> +		 * page_put due to reference from alloc_huge_page()
> +		 * unlock_page because locked by add_to_page_cache()
> +		 */
> +		put_page(page);
> +		unlock_page(page);
> +	}
> +
> +	if (!(mode & FALLOC_FL_KEEP_SIZE) && offset + len > inode->i_size)
> +		i_size_write(inode, offset + len);
> +	inode->i_ctime = CURRENT_TIME;
> +	spin_lock(&inode->i_lock);
> +	inode->i_private = NULL;
> +	spin_unlock(&inode->i_lock);
> +out:
> +	mutex_unlock(&inode->i_mutex);
> +	return error;
> 
> ...
>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

  reply	other threads:[~2015-07-22 22:03 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-21 18:09 [PATCH v4 00/10] hugetlbfs: add fallocate support Mike Kravetz
2015-07-21 18:09 ` [PATCH v4 01/10] mm/hugetlb: add cache of descriptors to resv_map for region_add Mike Kravetz
2015-07-22 22:03   ` Andrew Morton
2015-07-21 18:09 ` [PATCH v4 02/10] mm/hugetlb: add region_del() to delete a specific range of entries Mike Kravetz
2015-07-21 18:09 ` [PATCH v4 03/10] mm/hugetlb: expose hugetlb fault mutex for use by fallocate Mike Kravetz
2015-07-22 22:03   ` Andrew Morton
2015-07-21 18:09 ` [PATCH v4 04/10] hugetlbfs: hugetlb_vmtruncate_list() needs to take a range to delete Mike Kravetz
2015-07-21 18:09 ` [PATCH v4 05/10] hugetlbfs: truncate_hugepages() takes a range of pages Mike Kravetz
2015-07-21 18:09 ` [PATCH v4 06/10] mm/hugetlb: vma_has_reserves() needs to handle fallocate hole punch Mike Kravetz
2015-07-21 18:09 ` [PATCH v4 07/10] mm/hugetlb: alloc_huge_page handle areas hole punched by fallocate Mike Kravetz
2015-07-21 18:09 ` [PATCH v4 08/10] hugetlbfs: New huge_add_to_page_cache helper routine Mike Kravetz
2015-07-21 18:09 ` [PATCH v4 09/10] hugetlbfs: add hugetlbfs_fallocate() Mike Kravetz
2015-07-22 22:03   ` Andrew Morton [this message]
2015-07-22 22:23     ` Mike Kravetz
2015-07-22 22:30       ` Andrew Morton
2015-07-21 18:09 ` [PATCH v4 10/10] mm: madvise allow remove operation for hugetlbfs Mike Kravetz
2015-07-22 22:03 ` [PATCH v4 00/10] hugetlbfs: add fallocate support Andrew Morton
2015-07-22 22:06 ` Andrew Morton
2015-07-22 22:19   ` Davidlohr Bueso
2015-07-22 22:30     ` Andrew Morton
2015-07-22 22:34       ` Davidlohr Bueso
2015-07-22 22:37         ` Andrew Morton
2015-07-22 22:50           ` Davidlohr Bueso
2015-07-22 22:54             ` Davidlohr Bueso
2015-07-22 23:18       ` Mike Kravetz
2015-07-22 23:54         ` Davidlohr Bueso
2015-07-23  0:05           ` David Rientjes
2015-07-23 15:17         ` Eric B Munson
2015-07-23 17:05           ` Mike Kravetz
2015-07-23 17:17             ` Eric B Munson
2015-07-23 17:29               ` Mike Kravetz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150722150345.f8d5b0042cfa7112bd95d9ef@linux-foundation.org \
    --to=akpm@linux-foundation.org \
    --cc=aneesh.kumar@linux.vnet.ibm.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=dave@stgolabs.net \
    --cc=hch@infradead.org \
    --cc=hillf.zj@alibaba-inc.com \
    --cc=hughd@google.com \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mhocko@suse.cz \
    --cc=mike.kravetz@oracle.com \
    --cc=n-horiguchi@ah.jp.nec.com \
    --cc=rientjes@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox