From: David Vrabel Subject: [PATCHv6 3/5] gnttab: split grant table lock into table and maptrack locks Date: Wed, 22 Apr 2015 17:00:34 +0100 Message-ID: <1429718436-9782-4-git-send-email-david.vrabel@citrix.com> References: <1429718436-9782-1-git-send-email-david.vrabel@citrix.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from mail6.bemta14.messagelabs.com ([193.109.254.103]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1Ykx5U-00028b-SF for xen-devel@lists.xenproject.org; Wed, 22 Apr 2015 16:01:20 +0000 In-Reply-To: <1429718436-9782-1-git-send-email-david.vrabel@citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xenproject.org Cc: Keir Fraser , Jan Beulich , Christoph Egger , Tim Deegan , David Vrabel , Matt Wilson , Ian Campbell List-Id: xen-devel@lists.xenproject.org From: Matt Wilson The maptrack lock protects the maptrack state only. Signed-off-by: Matt Wilson Signed-off-by: David Vrabel --- Subsequent changes make both these locks uncontented. Is this patch really necessary? -- dvrabel --- xen/common/grant_table.c | 33 ++++++++++++++++++++++++++++----- xen/include/xen/grant_table.h | 7 ++++++- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index 3a555f9..a5470c8 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -264,10 +264,10 @@ static inline void put_maptrack_handle( struct grant_table *t, int handle) { - spin_lock(&t->lock); + spin_lock(&t->maptrack_lock); maptrack_entry(t, handle).ref = t->maptrack_head; t->maptrack_head = handle; - spin_unlock(&t->lock); + spin_unlock(&t->maptrack_lock); } static inline int @@ -279,7 +279,7 @@ get_maptrack_handle( struct grant_mapping *new_mt; unsigned int new_mt_limit, nr_frames; - spin_lock(&lgt->lock); + spin_lock(&lgt->maptrack_lock); while ( unlikely((handle = __get_maptrack_handle(lgt)) == -1) ) { @@ -308,12 +308,15 @@ get_maptrack_handle( nr_frames + 1); } - spin_unlock(&lgt->lock); + spin_unlock(&lgt->maptrack_lock); return handle; } -/* Number of grant table entries. Caller must hold d's grant table lock. */ +/* + * Number of grant table entries. Caller must hold d's grant table + * read lock. + */ static unsigned int nr_grant_entries(struct grant_table *gt) { ASSERT(gt->gt_version != 0); @@ -531,6 +534,13 @@ static int grant_map_exists(const struct domain *ld, return -EINVAL; } +/* + * Count the number of mapped ro or rw entries tracked in the left + * grant table given a provided mfn provided by a foreign domain. + * + * This function takes the maptrack lock from the left grant table and + * must be called with the right grant table's rwlock held. + */ static void mapcount( struct grant_table *lgt, struct domain *rd, unsigned long mfn, unsigned int *wrc, unsigned int *rdc) @@ -540,6 +550,16 @@ static void mapcount( *wrc = *rdc = 0; + /* + * While taking the local maptrack spinlock prevents any mapping + * changes, the remote active entries could be changing while we + * are counting. The caller has to hold the grant table lock, or + * some other mechanism should be used to prevent concurrent + * changes during this operation. + */ + ASSERT(spin_is_locked(&rd->grant_table->lock)); + spin_lock(&lgt->maptrack_lock); + for ( handle = 0; handle < lgt->maptrack_limit; handle++ ) { struct active_grant_entry *act; @@ -552,6 +572,8 @@ static void mapcount( if ( act->frame == mfn ) (map->flags & GNTMAP_readonly) ? (*rdc)++ : (*wrc)++; } + + spin_unlock(&lgt->maptrack_lock); } /* @@ -2980,6 +3002,7 @@ grant_table_create( /* Simple stuff. */ spin_lock_init(&t->lock); + spin_lock_init(&t->maptrack_lock); t->nr_grant_frames = INITIAL_NR_GRANT_FRAMES; /* Active grant table. */ diff --git a/xen/include/xen/grant_table.h b/xen/include/xen/grant_table.h index 32f5786..8ff1883 100644 --- a/xen/include/xen/grant_table.h +++ b/xen/include/xen/grant_table.h @@ -82,7 +82,12 @@ struct grant_table { struct grant_mapping **maptrack; unsigned int maptrack_head; unsigned int maptrack_limit; - /* Lock protecting updates to active and shared grant tables. */ + /* Lock protecting the maptrack page list, head, and limit */ + spinlock_t maptrack_lock; + /* + * Lock protecting updates to grant table state (version, active + * entry list, etc.) + */ spinlock_t lock; /* The defined versions are 1 and 2. Set to 0 if we don't know what version to use yet. */ -- 1.7.10.4