From patchwork Wed May 25 12:40:42 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hannes Reinecke X-Patchwork-Id: 816062 Received: from mx4-phx2.redhat.com (mx4-phx2.redhat.com [209.132.183.25]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p4PChh49013509 for ; Wed, 25 May 2011 12:44:04 GMT Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx4-phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p4PCfclp014159; Wed, 25 May 2011 08:41:48 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p4PCf6lW001223 for ; Wed, 25 May 2011 08:41:06 -0400 Received: from mx1.redhat.com (ext-mx12.extmail.prod.ext.phx2.redhat.com [10.5.110.17]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p4PCf1nu007127 for ; Wed, 25 May 2011 08:41:01 -0400 Received: from mx1.suse.de (cantor.suse.de [195.135.220.2]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p4PCf0s2030294 for ; Wed, 25 May 2011 08:41:00 -0400 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.221.2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.suse.de (Postfix) with ESMTP id 379FC90847; Wed, 25 May 2011 14:41:00 +0200 (CEST) From: Hannes Reinecke Message-Id: <201105251240.p4PCegPo017758@pentland.suse.de> Date: Wed, 25 May 2011 14:40:42 +0200 To: Christophe Varoqui User-Agent: Heirloom mailx 12.2 01/07/07 MIME-Version: 1.0 X-RedHat-Spam-Score: -5.01 (RCVD_IN_DNSWL_HI,T_RP_MATCHES_RCVD) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Scanned-By: MIMEDefang 2.68 on 10.5.110.17 X-loop: dm-devel@redhat.com Cc: dm-devel@redhat.com Subject: [dm-devel] [PATCH] Use refcounting for sysfs devices X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk Reply-To: device-mapper development List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dm-devel-bounces@redhat.com Errors-To: dm-devel-bounces@redhat.com X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Wed, 25 May 2011 12:44:04 +0000 (UTC) As we're caching sysfs devices we need to introduce some sort of refcounting here. Otherwise the device might be removed from other threads while we're still accessing it. References: bnc#642846 Signed-off-by: Hannes Reinecke --- dm-devel mailing list dm-devel@redhat.com https://www.redhat.com/mailman/listinfo/dm-devel diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c index fc64881..ff63a1b 100644 --- a/libmultipath/sysfs.c +++ b/libmultipath/sysfs.c @@ -44,6 +44,7 @@ static LIST_HEAD(sysfs_dev_list); struct sysfs_dev { struct list_head node; struct sysfs_device dev; + int refcount; }; int sysfs_init(char *path, size_t len) @@ -152,6 +153,7 @@ struct sysfs_device *sysfs_device_get(const char *devpath) if (strcmp(sysdev_loop->dev.devpath, devpath_real) == 0) { dbg("found vanished dev in cache '%s'", sysdev_loop->dev.devpath); + sysdev_loop->refcount++; return &sysdev_loop->dev; } } @@ -167,6 +169,7 @@ struct sysfs_device *sysfs_device_get(const char *devpath) if (strcmp(sysdev_loop->dev.devpath, devpath_real) == 0) { dbg("found dev in cache '%s'", sysdev_loop->dev.devpath); dev = &sysdev_loop->dev; + sysdev_loop->refcount++; } } @@ -177,6 +180,7 @@ struct sysfs_device *sysfs_device_get(const char *devpath) if (sysdev == NULL) return NULL; memset(sysdev, 0x00, sizeof(struct sysfs_dev)); + sysdev->refcount = 1; list_add(&sysdev->node, &sysfs_dev_list); dev = &sysdev->dev; } @@ -243,6 +247,8 @@ struct sysfs_device *sysfs_device_verify(struct sysfs_device *dev) char path[PATH_SIZE]; struct stat statbuf; + if (!dev->devpath) + return NULL; strlcpy(path, sysfs_path, sizeof(path)); strlcat(path, dev->devpath, sizeof(path)); if (stat(dev->devpath, &statbuf) == 0 && @@ -258,15 +264,21 @@ void sysfs_device_put(struct sysfs_device *dev) list_for_each_entry(sysdev_loop, &sysfs_dev_list, node) { if (&sysdev_loop->dev == dev) { - dbg("removed dev '%s' from cache", - sysdev_loop->dev.devpath); - list_del(&sysdev_loop->node); - free(sysdev_loop); + sysdev_loop->refcount--; + if (!sysdev_loop->refcount) { + dbg("removed dev '%s' from cache", + sysdev_loop->dev.devpath); + list_del(&sysdev_loop->node); + free(sysdev_loop); + } else { + dbg("dev '%s' still in cache, refcount %d", + sysdev_loop->dev.devpath, + sysdev_loop->refcount); + } return; } } - dbg("dev '%s' not found in cache", - sysdev_loop->dev.devpath); + dbg("dev '%s' not found in cache", dev->devpath); return; }