Skip to contentSkip to conversation

hugetlb patch for 2.5.47 + ALL_PATCHES_FROM_BILL

PATCH Rohit Seth 1 participant 1 message Nov 13, 2002

lore
Share & tools
lore

Rohit Seth

author
#0 lore raw

Attahched is the patch for 2.5.47+12_patches_from_William_Irwin. These are essentially the bug fixes and bit of clean up.

thanks,
rohit

arch/i386/mm/hugetlbpage.c +24 -14
@@ -73,7 +73,7 @@
 /*
  * Call without htlbpage_lock, returns with htlbpage_lock held.
  */
-struct hugetlb_key *alloc_key(int key, unsigned long len, int prot, int flag, int *new)
+struct hugetlb_key *alloc_key(int key, unsigned long len, int prot, int flag)
 {
 	struct hugetlb_key *hugetlb_key;
 
@@ -101,8 +101,6 @@
 					hugetlb_key->gid = current->fsgid;
 					hugetlb_key->mode = prot;
 					hugetlb_key->size = len;
-					atomic_set(&hugetlb_key->count, 1);
-					*new = 1;
 				}
 			}
 		} else if (key_busy(hugetlb_key)) {
@@ -111,26 +109,35 @@
 		} else if (check_size_prot(hugetlb_key, len, prot, flag) < 0) {
 			hugetlb_key->key = 0;
 			hugetlb_key = ERR_PTR(-EINVAL);
-		} else
-			*new = 0;
+		} 
 	} while (hugetlb_key == ERR_PTR(-EAGAIN));
+	if (!IS_ERR(hugetlb_key))
+		atomic_inc(&hugetlb_key->count);
 	return hugetlb_key;
 }
 
 void hugetlb_release_key(struct hugetlb_key *key)
 {
 	unsigned long index;
+	unsigned long max_idx;
 
-	if (!atomic_dec_and_lock(&key->count, &htlbpage_lock))
+	if (!atomic_dec_and_test(&key->count)) {
+		spin_lock(&htlbpage_lock);
+		clear_key_busy(key);
+		spin_unlock(&htlbpage_lock);
 		return;	
+	}
 
-	for (index = 0; index < key->size; ++index) {
+	max_idx = (key->size >> HPAGE_SHIFT);
+	for (index = 0; index < max_idx; ++index) {
 		struct page *page = radix_tree_lookup(&key->tree, index);
 		if (!page)
 			continue;
 		huge_page_release(page);
 	}
+	spin_lock(&htlbpage_lock);
 	key->key = 0;
+	clear_key_busy(key);
 	INIT_RADIX_TREE(&key->tree, GFP_ATOMIC);
 	spin_unlock(&htlbpage_lock);
 }
@@ -334,16 +341,23 @@
 	unsigned long address;
 	pte_t *pte;
 	struct page *page;
+	struct hugetlb_key *key = vma->vm_private_data;
 
 	BUG_ON(start & (HPAGE_SIZE - 1));
 	BUG_ON(end & (HPAGE_SIZE - 1));
 
+	spin_lock(&htlbpage_lock);
+	if (key ) 
+		mark_key_busy(key);
+	spin_unlock(&htlbpage_lock);
 	for (address = start; address < end; address += HPAGE_SIZE) {
 		pte = huge_pte_offset(mm, address);
 		page = pte_page(*pte);
 		huge_page_release(page);
 		pte_clear(pte);
 	}
+	if (key)
+		hugetlb_release_key(key);
 	mm->rss -= (end - start) >> PAGE_SHIFT;
 	flush_tlb_range(vma, start, end);
 }
@@ -417,7 +431,6 @@
 				goto out;
 			}
 			key_add_page(page, key, idx);
-			unlock_page(page);
 		}
 		set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
 	}
@@ -433,14 +446,11 @@
 	struct vm_area_struct *vma;
 	struct hugetlb_key *hugetlb_key;
 	int retval = -ENOMEM;
-	int newalloc = 0;
 
-	hugetlb_key = alloc_key(key, len, prot, flag, &newalloc);
-	if (IS_ERR(hugetlb_key)) {
-		spin_unlock(&htlbpage_lock);
+	hugetlb_key = alloc_key(key, len, prot, flag );
+	spin_unlock(&htlbpage_lock);
+	if (IS_ERR(hugetlb_key)) 
 		return PTR_ERR(hugetlb_key);
-	} else
-		spin_unlock(&htlbpage_lock);
 
 	addr = do_mmap_pgoff(NULL, addr, len, (unsigned long) prot,
 			MAP_NORESERVE|MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0);