[openib-general] Re: [PATCH] process locked in D state.

Michael S. Tsirkin mst at mellanox.co.il
Tue Jun 28 02:25:22 PDT 2005


> By your patch you completely removed locked_vm accounting on deregister
> path. I don't think this was your intention.

Of course. Closing the file should be handled separately from regular
deregistration. A new patch (below) fixes that.

---

Dont touch locked_vm when file is being closed, since a well-behaved
user is either exiting or has freed all mrs already, and a malicious
user is only hurting himself by making locked_vm seem higher than the
actual usage.

Note that current code doesnt seem to handle the later case anyway,
since there's a window after close() returns where locked_vm isnt updated yet.

Signed-off-by: Michael S. Tsirkin <mst at mellanox.co.il>

Index: core/uverbs_mem.c
===================================================================
--- core/uverbs_mem.c	(revision 2726)
+++ core/uverbs_mem.c	(working copy)
@@ -37,13 +37,6 @@
 
 #include "uverbs.h"
 
-struct ib_umem_account_work {
-	struct work_struct work;
-	struct mm_struct  *mm;
-	unsigned long      diff;
-};
-
-
 static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int dirty)
 {
 	struct ib_umem_chunk *chunk, *tmp;
@@ -167,15 +160,9 @@ out:
 	return ret;
 }
 
-static void ib_umem_account(void *work_ptr)
+void ib_umem_put(struct ib_device *dev, struct ib_umem *umem)
 {
-	struct ib_umem_account_work *work = work_ptr;
-
-	down_write(&work->mm->mmap_sem);
-	work->mm->locked_vm -= work->diff;
-	up_write(&work->mm->mmap_sem);
-	mmput(work->mm);
-	kfree(work);
+	__ib_umem_release(dev, umem, 1);
 }
 
 void ib_umem_release(struct ib_device *dev, struct ib_umem *umem)
@@ -185,35 +172,11 @@ void ib_umem_release(struct ib_device *d
 	__ib_umem_release(dev, umem, 1);
 
 	mm = get_task_mm(current);
-	if (mm) {
-		/*
-		 * We may be called with the mm's mmap_sem already
-		 * held.  This can happen when a userspace munmap() is
-		 * the call that drops the last reference to our file
-		 * and calls our release method.  If there are memory
-		 * regions to destroy, we'll end up here and not be
-		 * able to take the mmap_sem.
-		 *
-		 * To handle this, we try to grab the mmap_sem, and if
-		 * we can't get it immediately, we defer the
-		 * accounting to the system workqueue.
-		 */
-		if (down_write_trylock(&mm->mmap_sem)) {
-			mm->locked_vm -= PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT;
-			up_write(&mm->mmap_sem);
-			mmput(mm);
-		} else {
-			struct ib_umem_account_work *work;
-
-			work = kmalloc(sizeof *work, GFP_KERNEL);
-			if (!work)
-				return;
-
-			INIT_WORK(&work->work, ib_umem_account, work);
-			work->mm   = mm;
-			work->diff = PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT;
+	if (!mm)
+		return;
 
-			schedule_work(&work->work);
-		}
-	}
+	down_write(&mm->mmap_sem);
+	mm->locked_vm -= PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT;
+	up_write(&mm->mmap_sem);
+	mmput(mm);
 }
Index: core/uverbs_main.c
===================================================================
--- core/uverbs_main.c	(revision 2726)
+++ core/uverbs_main.c	(working copy)
@@ -133,7 +133,7 @@ static int ib_dealloc_ucontext(struct ib
 		struct ib_umem_object *memobj;
 
 		memobj = container_of(uobj, struct ib_umem_object, uobject);
-		ib_umem_release(mr->device, &memobj->umem);
+		ib_umem_put(mr->device, &memobj->umem);
 
 		idr_remove(&ib_uverbs_mr_idr, uobj->id);
 		ib_dereg_mr(mr);
Index: core/uverbs.h
===================================================================
--- core/uverbs.h	(revision 2726)
+++ core/uverbs.h	(working copy)
@@ -104,6 +104,7 @@ void ib_uverbs_qp_event_handler(struct i
 int ib_umem_get(struct ib_device *dev, struct ib_umem *mem,
 		void *addr, size_t size, int write);
 void ib_umem_release(struct ib_device *dev, struct ib_umem *umem);
+void ib_umem_put(struct ib_device *dev, struct ib_umem *umem);
 
 #define IB_UVERBS_DECLARE_CMD(name)					\
 	ssize_t ib_uverbs_##name(struct ib_uverbs_file *file,		\
-- 
MST



More information about the general mailing list