@@ -255,6 +255,152 @@ static inline struct hugepage_subpool *subpool_vma(struct vm_area_struct *vma)
255
255
return subpool_inode (file_inode (vma -> vm_file ));
256
256
}
257
257
258
+ /*
259
+ * hugetlb vma_lock helper routines
260
+ */
261
+ static bool __vma_shareable_lock (struct vm_area_struct * vma )
262
+ {
263
+ return vma -> vm_flags & (VM_MAYSHARE | VM_SHARED ) &&
264
+ vma -> vm_private_data ;
265
+ }
266
+
267
+ void hugetlb_vma_lock_read (struct vm_area_struct * vma )
268
+ {
269
+ if (__vma_shareable_lock (vma )) {
270
+ struct hugetlb_vma_lock * vma_lock = vma -> vm_private_data ;
271
+
272
+ down_read (& vma_lock -> rw_sema );
273
+ }
274
+ }
275
+
276
+ void hugetlb_vma_unlock_read (struct vm_area_struct * vma )
277
+ {
278
+ if (__vma_shareable_lock (vma )) {
279
+ struct hugetlb_vma_lock * vma_lock = vma -> vm_private_data ;
280
+
281
+ up_read (& vma_lock -> rw_sema );
282
+ }
283
+ }
284
+
285
+ void hugetlb_vma_lock_write (struct vm_area_struct * vma )
286
+ {
287
+ if (__vma_shareable_lock (vma )) {
288
+ struct hugetlb_vma_lock * vma_lock = vma -> vm_private_data ;
289
+
290
+ down_write (& vma_lock -> rw_sema );
291
+ }
292
+ }
293
+
294
+ void hugetlb_vma_unlock_write (struct vm_area_struct * vma )
295
+ {
296
+ if (__vma_shareable_lock (vma )) {
297
+ struct hugetlb_vma_lock * vma_lock = vma -> vm_private_data ;
298
+
299
+ up_write (& vma_lock -> rw_sema );
300
+ }
301
+ }
302
+
303
+ int hugetlb_vma_trylock_write (struct vm_area_struct * vma )
304
+ {
305
+ struct hugetlb_vma_lock * vma_lock = vma -> vm_private_data ;
306
+
307
+ if (!__vma_shareable_lock (vma ))
308
+ return 1 ;
309
+
310
+ return down_write_trylock (& vma_lock -> rw_sema );
311
+ }
312
+
313
+ void hugetlb_vma_assert_locked (struct vm_area_struct * vma )
314
+ {
315
+ if (__vma_shareable_lock (vma )) {
316
+ struct hugetlb_vma_lock * vma_lock = vma -> vm_private_data ;
317
+
318
+ lockdep_assert_held (& vma_lock -> rw_sema );
319
+ }
320
+ }
321
+
322
+ void hugetlb_vma_lock_release (struct kref * kref )
323
+ {
324
+ struct hugetlb_vma_lock * vma_lock = container_of (kref ,
325
+ struct hugetlb_vma_lock , refs );
326
+
327
+ kfree (vma_lock );
328
+ }
329
+
330
+ static void __hugetlb_vma_unlock_write_put (struct hugetlb_vma_lock * vma_lock )
331
+ {
332
+ struct vm_area_struct * vma = vma_lock -> vma ;
333
+
334
+ /*
335
+ * vma_lock structure may or not be released as a result of put,
336
+ * it certainly will no longer be attached to vma so clear pointer.
337
+ * Semaphore synchronizes access to vma_lock->vma field.
338
+ */
339
+ vma_lock -> vma = NULL ;
340
+ vma -> vm_private_data = NULL ;
341
+ up_write (& vma_lock -> rw_sema );
342
+ kref_put (& vma_lock -> refs , hugetlb_vma_lock_release );
343
+ }
344
+
345
+ static void __hugetlb_vma_unlock_write_free (struct vm_area_struct * vma )
346
+ {
347
+ if (__vma_shareable_lock (vma )) {
348
+ struct hugetlb_vma_lock * vma_lock = vma -> vm_private_data ;
349
+
350
+ __hugetlb_vma_unlock_write_put (vma_lock );
351
+ }
352
+ }
353
+
354
+ static void hugetlb_vma_lock_free (struct vm_area_struct * vma )
355
+ {
356
+ /*
357
+ * Only present in sharable vmas.
358
+ */
359
+ if (!vma || !__vma_shareable_lock (vma ))
360
+ return ;
361
+
362
+ if (vma -> vm_private_data ) {
363
+ struct hugetlb_vma_lock * vma_lock = vma -> vm_private_data ;
364
+
365
+ down_write (& vma_lock -> rw_sema );
366
+ __hugetlb_vma_unlock_write_put (vma_lock );
367
+ }
368
+ }
369
+
370
+ static void hugetlb_vma_lock_alloc (struct vm_area_struct * vma )
371
+ {
372
+ struct hugetlb_vma_lock * vma_lock ;
373
+
374
+ /* Only establish in (flags) sharable vmas */
375
+ if (!vma || !(vma -> vm_flags & VM_MAYSHARE ))
376
+ return ;
377
+
378
+ /* Should never get here with non-NULL vm_private_data */
379
+ if (vma -> vm_private_data )
380
+ return ;
381
+
382
+ vma_lock = kmalloc (sizeof (* vma_lock ), GFP_KERNEL );
383
+ if (!vma_lock ) {
384
+ /*
385
+ * If we can not allocate structure, then vma can not
386
+ * participate in pmd sharing. This is only a possible
387
+ * performance enhancement and memory saving issue.
388
+ * However, the lock is also used to synchronize page
389
+ * faults with truncation. If the lock is not present,
390
+ * unlikely races could leave pages in a file past i_size
391
+ * until the file is removed. Warn in the unlikely case of
392
+ * allocation failure.
393
+ */
394
+ pr_warn_once ("HugeTLB: unable to allocate vma specific lock\n" );
395
+ return ;
396
+ }
397
+
398
+ kref_init (& vma_lock -> refs );
399
+ init_rwsem (& vma_lock -> rw_sema );
400
+ vma_lock -> vma = vma ;
401
+ vma -> vm_private_data = vma_lock ;
402
+ }
403
+
258
404
/* Helper that removes a struct file_region from the resv_map cache and returns
259
405
* it for use.
260
406
*/
@@ -6613,7 +6759,8 @@ bool hugetlb_reserve_pages(struct inode *inode,
6613
6759
}
6614
6760
6615
6761
/*
6616
- * vma specific semaphore used for pmd sharing synchronization
6762
+ * vma specific semaphore used for pmd sharing and fault/truncation
6763
+ * synchronization
6617
6764
*/
6618
6765
hugetlb_vma_lock_alloc (vma );
6619
6766
@@ -6869,149 +7016,6 @@ void adjust_range_if_pmd_sharing_possible(struct vm_area_struct *vma,
6869
7016
* end = ALIGN (* end , PUD_SIZE );
6870
7017
}
6871
7018
6872
- static bool __vma_shareable_flags_pmd (struct vm_area_struct * vma )
6873
- {
6874
- return vma -> vm_flags & (VM_MAYSHARE | VM_SHARED ) &&
6875
- vma -> vm_private_data ;
6876
- }
6877
-
6878
- void hugetlb_vma_lock_read (struct vm_area_struct * vma )
6879
- {
6880
- if (__vma_shareable_flags_pmd (vma )) {
6881
- struct hugetlb_vma_lock * vma_lock = vma -> vm_private_data ;
6882
-
6883
- down_read (& vma_lock -> rw_sema );
6884
- }
6885
- }
6886
-
6887
- void hugetlb_vma_unlock_read (struct vm_area_struct * vma )
6888
- {
6889
- if (__vma_shareable_flags_pmd (vma )) {
6890
- struct hugetlb_vma_lock * vma_lock = vma -> vm_private_data ;
6891
-
6892
- up_read (& vma_lock -> rw_sema );
6893
- }
6894
- }
6895
-
6896
- void hugetlb_vma_lock_write (struct vm_area_struct * vma )
6897
- {
6898
- if (__vma_shareable_flags_pmd (vma )) {
6899
- struct hugetlb_vma_lock * vma_lock = vma -> vm_private_data ;
6900
-
6901
- down_write (& vma_lock -> rw_sema );
6902
- }
6903
- }
6904
-
6905
- void hugetlb_vma_unlock_write (struct vm_area_struct * vma )
6906
- {
6907
- if (__vma_shareable_flags_pmd (vma )) {
6908
- struct hugetlb_vma_lock * vma_lock = vma -> vm_private_data ;
6909
-
6910
- up_write (& vma_lock -> rw_sema );
6911
- }
6912
- }
6913
-
6914
- int hugetlb_vma_trylock_write (struct vm_area_struct * vma )
6915
- {
6916
- struct hugetlb_vma_lock * vma_lock = vma -> vm_private_data ;
6917
-
6918
- if (!__vma_shareable_flags_pmd (vma ))
6919
- return 1 ;
6920
-
6921
- return down_write_trylock (& vma_lock -> rw_sema );
6922
- }
6923
-
6924
- void hugetlb_vma_assert_locked (struct vm_area_struct * vma )
6925
- {
6926
- if (__vma_shareable_flags_pmd (vma )) {
6927
- struct hugetlb_vma_lock * vma_lock = vma -> vm_private_data ;
6928
-
6929
- lockdep_assert_held (& vma_lock -> rw_sema );
6930
- }
6931
- }
6932
-
6933
- void hugetlb_vma_lock_release (struct kref * kref )
6934
- {
6935
- struct hugetlb_vma_lock * vma_lock = container_of (kref ,
6936
- struct hugetlb_vma_lock , refs );
6937
-
6938
- kfree (vma_lock );
6939
- }
6940
-
6941
- static void __hugetlb_vma_unlock_write_put (struct hugetlb_vma_lock * vma_lock )
6942
- {
6943
- struct vm_area_struct * vma = vma_lock -> vma ;
6944
-
6945
- /*
6946
- * vma_lock structure may or not be released as a result of put,
6947
- * it certainly will no longer be attached to vma so clear pointer.
6948
- * Semaphore synchronizes access to vma_lock->vma field.
6949
- */
6950
- vma_lock -> vma = NULL ;
6951
- vma -> vm_private_data = NULL ;
6952
- up_write (& vma_lock -> rw_sema );
6953
- kref_put (& vma_lock -> refs , hugetlb_vma_lock_release );
6954
- }
6955
-
6956
- static void __hugetlb_vma_unlock_write_free (struct vm_area_struct * vma )
6957
- {
6958
- if (__vma_shareable_flags_pmd (vma )) {
6959
- struct hugetlb_vma_lock * vma_lock = vma -> vm_private_data ;
6960
-
6961
- __hugetlb_vma_unlock_write_put (vma_lock );
6962
- }
6963
- }
6964
-
6965
- static void hugetlb_vma_lock_free (struct vm_area_struct * vma )
6966
- {
6967
- /*
6968
- * Only present in sharable vmas.
6969
- */
6970
- if (!vma || !__vma_shareable_flags_pmd (vma ))
6971
- return ;
6972
-
6973
- if (vma -> vm_private_data ) {
6974
- struct hugetlb_vma_lock * vma_lock = vma -> vm_private_data ;
6975
-
6976
- down_write (& vma_lock -> rw_sema );
6977
- __hugetlb_vma_unlock_write_put (vma_lock );
6978
- }
6979
- }
6980
-
6981
- static void hugetlb_vma_lock_alloc (struct vm_area_struct * vma )
6982
- {
6983
- struct hugetlb_vma_lock * vma_lock ;
6984
-
6985
- /* Only establish in (flags) sharable vmas */
6986
- if (!vma || !(vma -> vm_flags & VM_MAYSHARE ))
6987
- return ;
6988
-
6989
- /* Should never get here with non-NULL vm_private_data */
6990
- if (vma -> vm_private_data )
6991
- return ;
6992
-
6993
- vma_lock = kmalloc (sizeof (* vma_lock ), GFP_KERNEL );
6994
- if (!vma_lock ) {
6995
- /*
6996
- * If we can not allocate structure, then vma can not
6997
- * participate in pmd sharing. This is only a possible
6998
- * performance enhancement and memory saving issue.
6999
- * However, the lock is also used to synchronize page
7000
- * faults with truncation. If the lock is not present,
7001
- * unlikely races could leave pages in a file past i_size
7002
- * until the file is removed. Warn in the unlikely case of
7003
- * allocation failure.
7004
- */
7005
- pr_warn_once ("HugeTLB: unable to allocate vma specific lock\n" );
7006
- return ;
7007
- }
7008
-
7009
- kref_init (& vma_lock -> refs );
7010
- init_rwsem (& vma_lock -> rw_sema );
7011
- vma_lock -> vma = vma ;
7012
- vma -> vm_private_data = vma_lock ;
7013
- }
7014
-
7015
7019
/*
7016
7020
* Search for a shareable pmd page for hugetlb. In any case calls pmd_alloc()
7017
7021
* and returns the corresponding pte. While this is not necessary for the
@@ -7100,47 +7104,6 @@ int huge_pmd_unshare(struct mm_struct *mm, struct vm_area_struct *vma,
7100
7104
7101
7105
#else /* !CONFIG_ARCH_WANT_HUGE_PMD_SHARE */
7102
7106
7103
- void hugetlb_vma_lock_read (struct vm_area_struct * vma )
7104
- {
7105
- }
7106
-
7107
- void hugetlb_vma_unlock_read (struct vm_area_struct * vma )
7108
- {
7109
- }
7110
-
7111
- void hugetlb_vma_lock_write (struct vm_area_struct * vma )
7112
- {
7113
- }
7114
-
7115
- void hugetlb_vma_unlock_write (struct vm_area_struct * vma )
7116
- {
7117
- }
7118
-
7119
- int hugetlb_vma_trylock_write (struct vm_area_struct * vma )
7120
- {
7121
- return 1 ;
7122
- }
7123
-
7124
- void hugetlb_vma_assert_locked (struct vm_area_struct * vma )
7125
- {
7126
- }
7127
-
7128
- void hugetlb_vma_lock_release (struct kref * kref )
7129
- {
7130
- }
7131
-
7132
- static void __hugetlb_vma_unlock_write_free (struct vm_area_struct * vma )
7133
- {
7134
- }
7135
-
7136
- static void hugetlb_vma_lock_free (struct vm_area_struct * vma )
7137
- {
7138
- }
7139
-
7140
- static void hugetlb_vma_lock_alloc (struct vm_area_struct * vma )
7141
- {
7142
- }
7143
-
7144
7107
pte_t * huge_pmd_share (struct mm_struct * mm , struct vm_area_struct * vma ,
7145
7108
unsigned long addr , pud_t * pud )
7146
7109
{
0 commit comments