[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Cleanup grant table code.



# HG changeset patch
# User cl349@xxxxxxxxxxxxxxxxxxxx
# Node ID 5b1ed5b394513cf79f07cece754d2de3b710430a
# Parent  eecb74e515fdebadb1a6f5f1b9ee658aad22c2dc
Cleanup grant table code.
- keep count of free references 
- let callbacks specify the number of references they need at least
- get rid of terminal reference
- simplify and more correct locking for callbacks
Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>

diff -r eecb74e515fd -r 5b1ed5b39451 
linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c     Tue Aug 23 09:33:48 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c     Tue Aug 23 13:11:31 2005
@@ -46,55 +46,76 @@
 EXPORT_SYMBOL(gnttab_grant_foreign_access_ref);
 EXPORT_SYMBOL(gnttab_grant_foreign_transfer_ref);
 
-static grant_ref_t gnttab_free_list[NR_GRANT_ENTRIES];
+#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
+#define GNTTAB_LIST_END (NR_GRANT_ENTRIES + 1)
+
+static grant_ref_t gnttab_list[NR_GRANT_ENTRIES];
+static int gnttab_free_count = NR_GRANT_ENTRIES;
 static grant_ref_t gnttab_free_head;
+static spinlock_t gnttab_list_lock = SPIN_LOCK_UNLOCKED;
 
 static grant_entry_t *shared;
 
 static struct gnttab_free_callback *gnttab_free_callback_list = NULL;
-static spinlock_t gnttab_free_callback_list_lock = SPIN_LOCK_UNLOCKED;
-
-/*
- * Lock-free grant-entry allocator
- */
-
-static inline int
-get_free_entry(
-    void)
-{
-    grant_ref_t fh, nfh = gnttab_free_head;
-    do { if ( unlikely((fh = nfh) == NR_GRANT_ENTRIES) ) return -1; }
-    while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh,
-                                    gnttab_free_list[fh])) != fh) );
-    return fh;
-}
-
-static void do_free_callbacks(unsigned long flags)
+
+static int
+get_free_entries(int count)
+{
+    unsigned long flags;
+    int ref;
+    grant_ref_t head;
+    spin_lock_irqsave(&gnttab_list_lock, flags);
+    if (gnttab_free_count < count) {
+       spin_unlock_irqrestore(&gnttab_list_lock, flags);
+       return -1;
+    }
+    ref = head = gnttab_free_head;
+    gnttab_free_count -= count;
+    while (count-- > 1)
+       head = gnttab_list[head];
+    gnttab_free_head = gnttab_list[head];
+    gnttab_list[head] = GNTTAB_LIST_END;
+    spin_unlock_irqrestore(&gnttab_list_lock, flags);
+    return ref;
+}
+
+#define get_free_entry() get_free_entries(1)
+
+static void
+do_free_callbacks(void)
 {
     struct gnttab_free_callback *callback = gnttab_free_callback_list, *next;
     gnttab_free_callback_list = NULL;
-    spin_unlock_irqrestore(&gnttab_free_callback_list_lock, flags);
     while (callback) {
        next = callback->next;
-       callback->next = NULL;
-       callback->fn(callback->arg);
+       if (gnttab_free_count >= callback->count) {
+           callback->next = NULL;
+           callback->fn(callback->arg);
+       } else {
+           callback->next = gnttab_free_callback_list;
+           gnttab_free_callback_list = callback;
+       }
        callback = next;
     }
 }
 
 static inline void
-put_free_entry(
-    grant_ref_t ref)
-{
-    grant_ref_t fh, nfh = gnttab_free_head;
+check_free_callbacks(void)
+{
+    if (unlikely(gnttab_free_callback_list))
+       do_free_callbacks();
+}
+
+static void
+put_free_entry(grant_ref_t ref)
+{
     unsigned long flags;
-    do { gnttab_free_list[ref] = fh = nfh; wmb(); }
-    while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh, ref)) != fh) );
-    spin_lock_irqsave(&gnttab_free_callback_list_lock, flags);
-    if ( unlikely(gnttab_free_callback_list) )
-       do_free_callbacks(flags);
-    else
-       spin_unlock_irqrestore(&gnttab_free_callback_list_lock, flags);
+    spin_lock_irqsave(&gnttab_list_lock, flags);
+    gnttab_list[ref] = gnttab_free_head;
+    gnttab_free_head = ref;
+    gnttab_free_count++;
+    check_free_callbacks();
+    spin_unlock_irqrestore(&gnttab_list_lock, flags);
 }
 
 /*
@@ -102,8 +123,7 @@
  */
 
 int
-gnttab_grant_foreign_access(
-    domid_t domid, unsigned long frame, int readonly)
+gnttab_grant_foreign_access(domid_t domid, unsigned long frame, int readonly)
 {
     int ref;
     
@@ -119,8 +139,8 @@
 }
 
 void
-gnttab_grant_foreign_access_ref(
-    grant_ref_t ref, domid_t domid, unsigned long frame, int readonly)
+gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
+                               unsigned long frame, int readonly)
 {
     shared[ref].frame = frame;
     shared[ref].domid = domid;
@@ -130,7 +150,7 @@
 
 
 int
-gnttab_query_foreign_access( grant_ref_t ref )
+gnttab_query_foreign_access(grant_ref_t ref)
 {
     u16 nflags;
 
@@ -140,7 +160,7 @@
 }
 
 void
-gnttab_end_foreign_access( grant_ref_t ref, int readonly )
+gnttab_end_foreign_access(grant_ref_t ref, int readonly)
 {
     u16 flags, nflags;
 
@@ -155,8 +175,7 @@
 }
 
 int
-gnttab_grant_foreign_transfer(
-    domid_t domid, unsigned long pfn )
+gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn)
 {
     int ref;
 
@@ -172,8 +191,8 @@
 }
 
 void
-gnttab_grant_foreign_transfer_ref(
-    grant_ref_t ref, domid_t domid, unsigned long pfn )
+gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid,
+                                 unsigned long pfn)
 {
     shared[ref].frame = pfn;
     shared[ref].domid = domid;
@@ -182,8 +201,7 @@
 }
 
 unsigned long
-gnttab_end_foreign_transfer(
-    grant_ref_t ref)
+gnttab_end_foreign_transfer(grant_ref_t ref)
 {
     unsigned long frame = 0;
     u16           flags;
@@ -212,80 +230,79 @@
 }
 
 void
-gnttab_free_grant_reference( grant_ref_t ref )
+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)...? */
+gnttab_free_grant_references(grant_ref_t head)
+{
     grant_ref_t ref;
-
-    while (*head != terminal) {
-       ref = *head;
-       *head = gnttab_free_list[*head];
-       put_free_entry(ref);
+    unsigned long flags;
+    int count = 1;
+    if (head == GNTTAB_LIST_END)
+       return;
+    spin_lock_irqsave(&gnttab_list_lock, flags);
+    ref = head;
+    while (gnttab_list[ref] != GNTTAB_LIST_END) {
+       ref = gnttab_list[ref];
+       count++;
     }
-}
-
-int
-gnttab_alloc_grant_references( u16 count,
-                               grant_ref_t *head,
-                               grant_ref_t *terminal )
-{
-    int i;
-    grant_ref_t h = gnttab_free_head;
-
-    for ( i = 0; i < count; i++ )
-        if ( unlikely(get_free_entry() == -1) )
-            goto not_enough_refs;
+    gnttab_list[ref] = gnttab_free_head;
+    gnttab_free_head = head;
+    gnttab_free_count += count;
+    check_free_callbacks();
+    spin_unlock_irqrestore(&gnttab_list_lock, flags);
+}
+
+int
+gnttab_alloc_grant_references(u16 count, grant_ref_t *head)
+{
+    int h = get_free_entries(count);
+
+    if (h == -1)
+       return -ENOSPC;
 
     *head = h;
-    *terminal = gnttab_free_head;
 
     return 0;
-
-not_enough_refs:
-    gnttab_free_head = h;
-    return -ENOSPC;
-}
-
-int
-gnttab_claim_grant_reference( grant_ref_t *private_head,
-                              grant_ref_t  terminal )
-{
-    grant_ref_t g;
-    if ( unlikely((g = *private_head) == terminal) )
+}
+
+int
+gnttab_claim_grant_reference(grant_ref_t *private_head)
+{
+    grant_ref_t g = *private_head;
+    if (unlikely(g == GNTTAB_LIST_END))
         return -ENOSPC;
-    *private_head = gnttab_free_list[g];
+    *private_head = gnttab_list[g];
     return g;
 }
 
 void
-gnttab_release_grant_reference( grant_ref_t *private_head,
-                                grant_ref_t  release )
-{
-    gnttab_free_list[release] = *private_head;
+gnttab_release_grant_reference(grant_ref_t *private_head, grant_ref_t  release)
+{
+    gnttab_list[release] = *private_head;
     *private_head = release;
 }
 
 void
 gnttab_request_free_callback(struct gnttab_free_callback *callback,
-                            void (*fn)(void *), void *arg)
+                            void (*fn)(void *), void *arg, u16 count)
 {
     unsigned long flags;
+    spin_lock_irqsave(&gnttab_list_lock, flags);
     if (callback->next)
-       return;
+       goto out;
     callback->fn = fn;
     callback->arg = arg;
-    spin_lock_irqsave(&gnttab_free_callback_list_lock, flags);
+    callback->count = count;
     callback->next = gnttab_free_callback_list;
     gnttab_free_callback_list = callback;
-    spin_unlock_irqrestore(&gnttab_free_callback_list_lock, flags);
+    check_free_callbacks();
+ out:
+    spin_unlock_irqrestore(&gnttab_list_lock, flags);
 }
 
 /*
@@ -296,8 +313,9 @@
 
 static struct proc_dir_entry *grant_pde;
 
-static int grant_ioctl(struct inode *inode, struct file *file,
-                       unsigned int cmd, unsigned long data)
+static int
+grant_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+           unsigned long data)
 {
     int                     ret;
     privcmd_hypercall_t     hypercall;
@@ -335,8 +353,9 @@
     ioctl:  grant_ioctl,
 };
 
-static int grant_read(char *page, char **start, off_t off,
-                      int count, int *eof, void *data)
+static int
+grant_read(char *page, char **start, off_t off, int count, int *eof,
+          void *data)
 {
     int             len;
     unsigned int    i;
@@ -365,8 +384,9 @@
     return len;
 }
 
-static int grant_write(struct file *file, const char __user *buffer,
-                       unsigned long count, void *data)
+static int
+grant_write(struct file *file, const char __user *buffer, unsigned long count,
+           void *data)
 {
     /* TODO: implement this */
     return -ENOSYS;
@@ -374,7 +394,8 @@
 
 #endif /* CONFIG_PROC_FS */
 
-int gnttab_resume(void)
+int
+gnttab_resume(void)
 {
     gnttab_setup_table_t setup;
     unsigned long        frames[NR_GRANT_FRAMES];
@@ -393,7 +414,8 @@
     return 0;
 }
 
-int gnttab_suspend(void)
+int
+gnttab_suspend(void)
 {
     int i;
 
@@ -403,7 +425,8 @@
     return 0;
 }
 
-static int __init gnttab_init(void)
+static int __init
+gnttab_init(void)
 {
     int i;
 
@@ -412,7 +435,7 @@
     shared = (grant_entry_t *)fix_to_virt(FIX_GNTTAB_END);
 
     for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
-        gnttab_free_list[i] = i + 1;
+        gnttab_list[i] = i + 1;
     
 #ifdef CONFIG_PROC_FS
     /*
diff -r eecb74e515fd -r 5b1ed5b39451 
linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c      Tue Aug 23 
09:33:48 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c      Tue Aug 23 
13:11:31 2005
@@ -237,15 +237,16 @@
     unsigned long id;
     unsigned int fsect, lsect;
     int ref;
-    grant_ref_t gref_head, gref_terminal;
+    grant_ref_t gref_head;
 
     if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
         return 1;
 
     if (gnttab_alloc_grant_references(BLKIF_MAX_SEGMENTS_PER_REQUEST,
-                                     &gref_head, &gref_terminal) < 0) {
+                                     &gref_head) < 0) {
            gnttab_request_free_callback(&info->callback,
-                                        blkif_restart_queue_callback, info);
+                                        blkif_restart_queue_callback, info,
+                                        BLKIF_MAX_SEGMENTS_PER_REQUEST);
            return 1;
     }
 
@@ -270,7 +271,7 @@
             fsect = bvec->bv_offset >> 9;
             lsect = fsect + (bvec->bv_len >> 9) - 1;
             /* install a grant reference. */
-            ref = gnttab_claim_grant_reference(&gref_head, gref_terminal);
+            ref = gnttab_claim_grant_reference(&gref_head);
             ASSERT( ref != -ENOSPC );
 
             gnttab_grant_foreign_access_ref(
@@ -294,7 +295,7 @@
     /* Keep a private copy so we can reissue requests when recovering. */
     pickle_request(&blk_shadow[id], ring_req);
 
-    gnttab_free_grant_references(&gref_head, gref_terminal);
+    gnttab_free_grant_references(gref_head);
 
     return 0;
 }
@@ -738,7 +739,7 @@
             blk_shadow[req->id].request = (unsigned long)id;
 
             /* install a grant reference. */
-            ref = gnttab_claim_grant_reference(&gref_head, gref_terminal);
+            ref = gnttab_claim_grant_reference(&gref_head);
             ASSERT( ref != -ENOSPC );
 
             gnttab_grant_foreign_access_ref(
@@ -790,7 +791,7 @@
     req->handle        = handle;
     req->nr_segments   = 1;
     /* install a grant reference. */
-    ref = gnttab_claim_grant_reference(&gref_head, gref_terminal);
+    ref = gnttab_claim_grant_reference(&gref_head);
     ASSERT( ref != -ENOSPC );
 
     gnttab_grant_foreign_access_ref(
diff -r eecb74e515fd -r 5b1ed5b39451 
linux-2.6-xen-sparse/include/asm-xen/gnttab.h
--- a/linux-2.6-xen-sparse/include/asm-xen/gnttab.h     Tue Aug 23 09:33:48 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/gnttab.h     Tue Aug 23 13:11:31 2005
@@ -19,68 +19,46 @@
 
 /* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
 #define NR_GRANT_FRAMES 4
-#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
 
 struct gnttab_free_callback {
     struct gnttab_free_callback *next;
     void (*fn)(void *);
     void *arg;
+    u16 count;
 };
 
-int
-gnttab_grant_foreign_access(
-    domid_t domid, unsigned long frame, int readonly);
+int gnttab_grant_foreign_access(domid_t domid, unsigned long frame,
+                               int readonly);
 
-void
-gnttab_end_foreign_access(
-    grant_ref_t ref, int readonly);
+void gnttab_end_foreign_access(grant_ref_t ref, int readonly);
 
-int
-gnttab_grant_foreign_transfer(
-    domid_t domid, unsigned long pfn);
+int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn);
 
-unsigned long
-gnttab_end_foreign_transfer(
-    grant_ref_t ref);
+unsigned long gnttab_end_foreign_transfer(grant_ref_t ref);
 
-int
-gnttab_query_foreign_access( 
-    grant_ref_t ref );
+int gnttab_query_foreign_access(grant_ref_t ref);
 
 /*
  * operations on reserved batches of grant references
  */
-int
-gnttab_alloc_grant_references(
-    u16 count, grant_ref_t *pprivate_head, grant_ref_t *private_terminal );
+int gnttab_alloc_grant_references(u16 count, grant_ref_t *pprivate_head);
 
-void
-gnttab_free_grant_reference(
-    grant_ref_t ref );
+void gnttab_free_grant_reference(grant_ref_t ref);
 
-void
-gnttab_free_grant_references(
-    grant_ref_t *head, grant_ref_t terminal );
+void gnttab_free_grant_references(grant_ref_t head);
 
-int
-gnttab_claim_grant_reference( grant_ref_t *pprivate_head, grant_ref_t terminal
-);
+int gnttab_claim_grant_reference(grant_ref_t *pprivate_head);
 
-void
-gnttab_release_grant_reference(
-    grant_ref_t *private_head, grant_ref_t release );
+void gnttab_release_grant_reference(grant_ref_t *private_head,
+                                   grant_ref_t release);
 
-void
-gnttab_request_free_callback(
-    struct gnttab_free_callback *callback, void (*fn)(void *), void *arg);
+void gnttab_request_free_callback(struct gnttab_free_callback *callback,
+                                 void (*fn)(void *), void *arg, u16 count);
 
-void
-gnttab_grant_foreign_access_ref(
-    grant_ref_t ref, domid_t domid, unsigned long frame, int readonly);
+void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
+                                    unsigned long frame, int readonly);
 
-void
-gnttab_grant_foreign_transfer_ref(
-    grant_ref_t, domid_t domid, unsigned long pfn);
-
+void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid,
+                                      unsigned long pfn);
 
 #endif /* __ASM_GNTTAB_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.