From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:58915) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Sz4s1-0008LQ-0u for qemu-devel@nongnu.org; Wed, 08 Aug 2012 07:56:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Sz4rt-0000KV-OT for qemu-devel@nongnu.org; Wed, 08 Aug 2012 07:56:12 -0400 Received: from mail-pb0-f45.google.com ([209.85.160.45]:43223) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Sz4rt-0000In-IY for qemu-devel@nongnu.org; Wed, 08 Aug 2012 07:56:05 -0400 Received: by mail-pb0-f45.google.com with SMTP id rp12so891558pbb.4 for ; Wed, 08 Aug 2012 04:56:05 -0700 (PDT) Sender: Paolo Bonzini From: Paolo Bonzini Date: Wed, 8 Aug 2012 13:55:43 +0200 Message-Id: <1344426944-7638-2-git-send-email-pbonzini@redhat.com> In-Reply-To: <1344426944-7638-1-git-send-email-pbonzini@redhat.com> References: <1344426944-7638-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH 1/2] 9p-synth: fix read-side critical sections List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: harsh@linux.vnet.ibm.com, aneesh.kumar@linux.vnet.ibm.com The read-side critical sections in 9p-synth currently only include the navigation of the list. This is incorrect; it works for two reasons, first obviously because rcu_read_lock/unlock are still no-ops; second, because elements of the list are never deleted from the list (only added). In fact, only adding items is the reason why rcu_read_lock/unlock can be left as no-ops. If items were deleted, they could be reclaimed as soon as the read-side critical section ends. So, the read-side critical section must include all _usage_ of the node we got from the list too. Signed-off-by: Paolo Bonzini --- hw/9pfs/virtio-9p-synth.c | 35 ++++++++++++++++++++--------------- 1 file modificato, 20 inserzioni(+), 15 rimozioni(-) diff --git a/hw/9pfs/virtio-9p-synth.c b/hw/9pfs/virtio-9p-synth.c index 92e0b09..a91ebe1 100644 --- a/hw/9pfs/virtio-9p-synth.c +++ b/hw/9pfs/virtio-9p-synth.c @@ -237,14 +237,15 @@ static int v9fs_synth_get_dentry(V9fsSynthNode *dir, struct dirent *entry, } i++; } - rcu_read_unlock(); if (!node) { /* end of directory */ *result = NULL; - return 0; + goto out; } v9fs_synth_direntry(node, entry, off); *result = entry; +out: + rcu_read_unlock(); return 0; } @@ -466,6 +467,7 @@ static int v9fs_synth_name_to_path(FsContext *ctx, V9fsPath *dir_path, { V9fsSynthNode *node; V9fsSynthNode *dir_node; + int ret = 0; /* "." and ".." are not allowed */ if (!strcmp(name, ".") || !strcmp(name, "..")) { @@ -473,34 +475,37 @@ static int v9fs_synth_name_to_path(FsContext *ctx, V9fsPath *dir_path, return -1; } + + rcu_read_lock(); if (!dir_path) { dir_node = &v9fs_synth_root; } else { dir_node = *(V9fsSynthNode **)dir_path->data; } - if (!strcmp(name, "/")) { - node = dir_node; - goto out; - } - /* search for the name in the childern */ - rcu_read_lock(); - QLIST_FOREACH(node, &dir_node->child, sibling) { - if (!strcmp(node->name, name)) { - break; + + node = dir_node; + if (strcmp(name, "/") != 0) { + /* search for the name in the childern */ + QLIST_FOREACH(node, &dir_node->child, sibling) { + if (!strcmp(node->name, name)) { + break; + } } } - rcu_read_unlock(); if (!node) { errno = ENOENT; - return -1; + ret = -1; + goto err_out; } -out: + /* Copy the node pointer to fid */ target->data = g_malloc(sizeof(void *)); memcpy(target->data, &node, sizeof(void *)); target->size = sizeof(void *); - return 0; +err_out: + rcu_read_unlock(); + return ret; } static int v9fs_synth_renameat(FsContext *ctx, V9fsPath *olddir, -- 1.7.11.2