Skip to content

Commit e656c7a

Browse files
Prakash Sangappaakpm00
authored andcommitted
mm: hugetlb pages should not be reserved by shmat() if SHM_NORESERVE
For shared memory of type SHM_HUGETLB, hugetlb pages are reserved in shmget() call. If SHM_NORESERVE flags is specified then the hugetlb pages are not reserved. However when the shared memory is attached with the shmat() call the hugetlb pages are getting reserved incorrectly for SHM_HUGETLB shared memory created with SHM_NORESERVE which is a bug. ------------------------------- Following test shows the issue. $cat shmhtb.c int main() { int shmflags = 0660 | IPC_CREAT | SHM_HUGETLB | SHM_NORESERVE; int shmid; shmid = shmget(SKEY, SHMSZ, shmflags); if (shmid < 0) { printf("shmat: shmget() failed, %d\n", errno); return 1; } printf("After shmget()\n"); system("cat /proc/meminfo | grep -i hugepages_"); shmat(shmid, NULL, 0); printf("\nAfter shmat()\n"); system("cat /proc/meminfo | grep -i hugepages_"); shmctl(shmid, IPC_RMID, NULL); return 0; } #sysctl -w vm.nr_hugepages=20 #./shmhtb After shmget() HugePages_Total: 20 HugePages_Free: 20 HugePages_Rsvd: 0 HugePages_Surp: 0 After shmat() HugePages_Total: 20 HugePages_Free: 20 HugePages_Rsvd: 5 <-- HugePages_Surp: 0 -------------------------------- Fix is to ensure that hugetlb pages are not reserved for SHM_HUGETLB shared memory in the shmat() call. Link: https://lkml.kernel.org/r/1706040282-12388-1-git-send-email-prakash.sangappa@oracle.com Signed-off-by: Prakash Sangappa <prakash.sangappa@oracle.com> Acked-by: Muchun Song <muchun.song@linux.dev> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent c8bdef1 commit e656c7a

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

fs/hugetlbfs/inode.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
100100
loff_t len, vma_len;
101101
int ret;
102102
struct hstate *h = hstate_file(file);
103+
vm_flags_t vm_flags;
103104

104105
/*
105106
* vma address alignment (but not the pgoff alignment) has
@@ -141,10 +142,20 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
141142
file_accessed(file);
142143

143144
ret = -ENOMEM;
145+
146+
vm_flags = vma->vm_flags;
147+
/*
148+
* for SHM_HUGETLB, the pages are reserved in the shmget() call so skip
149+
* reserving here. Note: only for SHM hugetlbfs file, the inode
150+
* flag S_PRIVATE is set.
151+
*/
152+
if (inode->i_flags & S_PRIVATE)
153+
vm_flags |= VM_NORESERVE;
154+
144155
if (!hugetlb_reserve_pages(inode,
145156
vma->vm_pgoff >> huge_page_order(h),
146157
len >> huge_page_shift(h), vma,
147-
vma->vm_flags))
158+
vm_flags))
148159
goto out;
149160

150161
ret = 0;

0 commit comments

Comments
 (0)