Grant table updates for block device changes.
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Mon, 22 Aug 2005 20:52:38 +0000 (20:52 +0000)
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Mon, 22 Aug 2005 20:52:38 +0000 (20:52 +0000)
- add gnttab_free_grant_reference
- make gnttab_free_grant_references interface consistent with other gnttab
  functions
- add support for callback when references are freed
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c
linux-2.6-xen-sparse/include/asm-xen/gnttab.h

index 63deb685f37da369e8a5d18670fddfbe14469657..99c68ae11ec94ed47d54df4d7520237bf3b6e228 100644 (file)
@@ -50,6 +50,8 @@ static grant_ref_t gnttab_free_head;
 
 static grant_entry_t *shared;
 
+static struct gnttab_free_callback *gnttab_free_callback_list = NULL;
+
 /*
  * Lock-free grant-entry allocator
  */
@@ -65,6 +67,16 @@ get_free_entry(
     return fh;
 }
 
+static void do_free_callbacks(void)
+{
+    struct gnttab_free_callback *callback = gnttab_free_callback_list;
+    gnttab_free_callback_list = NULL;
+    while (callback) {
+       schedule_work(callback->work);
+       callback = callback->next;
+    }
+}
+
 static inline void
 put_free_entry(
     grant_ref_t ref)
@@ -72,6 +84,8 @@ put_free_entry(
     grant_ref_t fh, nfh = gnttab_free_head;
     do { gnttab_free_list[ref] = fh = nfh; wmb(); }
     while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh, ref)) != fh) );
+    if ( unlikely(gnttab_free_callback_list) )
+       do_free_callbacks();
 }
 
 /*
@@ -189,17 +203,23 @@ gnttab_end_foreign_transfer(
 }
 
 void
-gnttab_free_grant_references( u16 count, grant_ref_t head )
+gnttab_free_grant_reference( grant_ref_t ref )
+{
+
+    put_free_entry(ref);
+}
+
+void
+gnttab_free_grant_references( grant_ref_t *head,
+                              grant_ref_t terminal )
 {
     /* TODO: O(N)...? */
-    grant_ref_t to_die = 0, next = head;
-    int i;
+    grant_ref_t ref;
 
-    for ( i = 0; i < count; i++ )
-    {
-        to_die = next;
-        next = gnttab_free_list[next];
-        put_free_entry( to_die );
+    while (*head != terminal) {
+       ref = *head;
+       *head = gnttab_free_list[*head];
+       put_free_entry(ref);
     }
 }
 
@@ -244,6 +264,15 @@ gnttab_release_grant_reference( grant_ref_t *private_head,
     *private_head = release;
 }
 
+void
+gnttab_request_free_callback(struct gnttab_free_callback *callback,
+                            struct work_struct *work)
+{
+    callback->work = work;
+    callback->next = gnttab_free_callback_list;
+    gnttab_free_callback_list = callback;
+}
+
 /*
  * ProcFS operations
  */
index 642a74dbf9b8da6c46010ed4d8788bfdf68e72ea..292652c68125e035d958e9d3343b167e05eb04f3 100644 (file)
 #define NR_GRANT_FRAMES 4
 #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
 
+struct work_struct;
+
+struct gnttab_free_callback {
+    struct gnttab_free_callback *next;
+    struct work_struct *work;
+};
+
 int
 gnttab_grant_foreign_access(
     domid_t domid, unsigned long frame, int readonly);
@@ -48,9 +55,13 @@ int
 gnttab_alloc_grant_references(
     u16 count, grant_ref_t *pprivate_head, grant_ref_t *private_terminal );
 
+void
+gnttab_free_grant_reference(
+    grant_ref_t ref );
+
 void
 gnttab_free_grant_references(
-    u16 count, grant_ref_t private_head );
+    grant_ref_t *head, grant_ref_t terminal );
 
 int
 gnttab_claim_grant_reference( grant_ref_t *pprivate_head, grant_ref_t terminal
@@ -60,6 +71,10 @@ void
 gnttab_release_grant_reference(
     grant_ref_t *private_head, grant_ref_t release );
 
+void
+gnttab_request_free_callback(
+    struct gnttab_free_callback *callback, struct work_struct *work );
+
 void
 gnttab_grant_foreign_access_ref(
     grant_ref_t ref, domid_t domid, unsigned long frame, int readonly);