From patchwork Mon Jun 6 12:32:44 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg Kurz X-Patchwork-Id: 630874 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3rNZCf0Nxkz9s5w for ; Mon, 6 Jun 2016 22:44:46 +1000 (AEST) Received: from localhost ([::1]:42102 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b9ttc-0001ou-4c for incoming@patchwork.ozlabs.org; Mon, 06 Jun 2016 08:44:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54396) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b9tj0-0001Ta-2O for qemu-devel@nongnu.org; Mon, 06 Jun 2016 08:33:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1b9tis-0001Tt-Lw for qemu-devel@nongnu.org; Mon, 06 Jun 2016 08:33:44 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:11583 helo=mx0b-001b2d01.pphosted.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b9tis-0001TH-D2 for qemu-devel@nongnu.org; Mon, 06 Jun 2016 08:33:38 -0400 Received: from pps.filterd (m0075771.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.11/8.16.0.11) with SMTP id u56CTZln034129 for ; Mon, 6 Jun 2016 08:33:37 -0400 Message-Id: <201606061233.u56CTZln034129@mx0a-001b2d01.pphosted.com> Received: from e06smtp06.uk.ibm.com (e06smtp06.uk.ibm.com [195.75.94.102]) by mx0a-001b2d01.pphosted.com with ESMTP id 23d3b7dfus-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 06 Jun 2016 08:33:37 -0400 Received: from localhost by e06smtp06.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 6 Jun 2016 13:33:34 +0100 Received: from d06dlp02.portsmouth.uk.ibm.com (9.149.20.14) by e06smtp06.uk.ibm.com (192.168.101.136) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 6 Jun 2016 13:33:18 +0100 X-IBM-Helo: d06dlp02.portsmouth.uk.ibm.com X-IBM-MailFrom: gkurz@linux.vnet.ibm.com X-IBM-RcptTo: qemu-devel@nongnu.org Received: from b06cxnps4076.portsmouth.uk.ibm.com (d06relay13.portsmouth.uk.ibm.com [9.149.109.198]) by d06dlp02.portsmouth.uk.ibm.com (Postfix) with ESMTP id C4803219005E for ; Mon, 6 Jun 2016 13:32:50 +0100 (BST) Received: from d06av01.portsmouth.uk.ibm.com (d06av01.portsmouth.uk.ibm.com [9.149.37.212]) by b06cxnps4076.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u56CXIik66453686 for ; Mon, 6 Jun 2016 12:33:18 GMT Received: from d06av01.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av01.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id u56CXHqi025024 for ; Mon, 6 Jun 2016 06:33:18 -0600 Received: from smtp.lab.toulouse-stg.fr.ibm.com (srv01.lab.toulouse-stg.fr.ibm.com [9.101.4.1]) by d06av01.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id u56CXHPM025001; Mon, 6 Jun 2016 06:33:17 -0600 Received: from bahia.huguette.org (icon-9-164-139-228.megacenter.de.ibm.com [9.164.139.228]) by smtp.lab.toulouse-stg.fr.ibm.com (Postfix) with ESMTP id D0A1A220164; Mon, 6 Jun 2016 14:33:16 +0200 (CEST) From: Greg Kurz To: qemu-devel@nongnu.org Date: Mon, 6 Jun 2016 14:32:44 +0200 X-Mailer: git-send-email 2.5.5 In-Reply-To: <1465216365-13078-1-git-send-email-gkurz@linux.vnet.ibm.com> References: <1465216365-13078-1-git-send-email-gkurz@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16060612-0024-0000-0000-000001DAE2C4 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 16060612-0025-0000-0000-00001F2D5B14 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-06-06_05:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=75 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1604210000 definitions=main-1606060149 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] X-Received-From: 148.163.156.1 Subject: [Qemu-devel] [PULL 6/7] 9p: add locking to V9fsDir X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell , "Aneesh Kumar K.V" , Greg Kurz Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" If several threads concurrently call readdir() with the same directory stream pointer, it is possible that they all get a pointer to the same dirent structure, whose content is overwritten each time readdir() is called. We must thus serialize accesses to the dirent structure. This may be achieved with a mutex like below: lock_mutex(); readdir(); // work with the dirent unlock_mutex(); This patch adds all the locking, to prepare the switch to readdir(). Reviewed-by: Eric Blake Signed-off-by: Greg Kurz --- hw/9pfs/9p.c | 21 +++++++++++++++++++++ hw/9pfs/9p.h | 16 ++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 803f525a2a3d..11085f45ada8 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -300,6 +300,9 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid) f->next = s->fid_list; s->fid_list = f; + v9fs_readdir_init(&f->fs.dir); + v9fs_readdir_init(&f->fs_reclaim.dir); + return f; } @@ -1636,6 +1639,9 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu, while (1) { v9fs_path_init(&path); + + v9fs_readdir_lock(&fidp->fs.dir); + err = v9fs_co_readdir_r(pdu, fidp, dent, &result); if (err || !result) { break; @@ -1654,6 +1660,9 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu, } /* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */ len = pdu_marshal(pdu, 11 + count, "S", &v9stat); + + v9fs_readdir_unlock(&fidp->fs.dir); + if ((len != (v9stat.size + 2)) || ((count + len) > max_count)) { /* Ran out of buffer. Set dir back to old position and return */ v9fs_co_seekdir(pdu, fidp, saved_dir_pos); @@ -1668,6 +1677,8 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu, saved_dir_pos = dent->d_off; } + v9fs_readdir_unlock(&fidp->fs.dir); + g_free(dent); v9fs_path_free(&path); if (err < 0) { @@ -1815,6 +1826,8 @@ static int v9fs_do_readdir(V9fsPDU *pdu, dent = g_malloc(sizeof(struct dirent)); while (1) { + v9fs_readdir_lock(&fidp->fs.dir); + err = v9fs_co_readdir_r(pdu, fidp, dent, &result); if (err || !result) { break; @@ -1822,6 +1835,8 @@ static int v9fs_do_readdir(V9fsPDU *pdu, v9fs_string_init(&name); v9fs_string_sprintf(&name, "%s", dent->d_name); if ((count + v9fs_readdir_data_size(&name)) > max_count) { + v9fs_readdir_unlock(&fidp->fs.dir); + /* Ran out of buffer. Set dir back to old position and return */ v9fs_co_seekdir(pdu, fidp, saved_dir_pos); v9fs_string_free(&name); @@ -1843,6 +1858,9 @@ static int v9fs_do_readdir(V9fsPDU *pdu, len = pdu_marshal(pdu, 11 + count, "Qqbs", &qid, dent->d_off, dent->d_type, &name); + + v9fs_readdir_unlock(&fidp->fs.dir); + if (len < 0) { v9fs_co_seekdir(pdu, fidp, saved_dir_pos); v9fs_string_free(&name); @@ -1853,6 +1871,9 @@ static int v9fs_do_readdir(V9fsPDU *pdu, v9fs_string_free(&name); saved_dir_pos = dent->d_off; } + + v9fs_readdir_unlock(&fidp->fs.dir); + g_free(dent); if (err < 0) { return err; diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h index 92ee309ef4ba..46d787627a4c 100644 --- a/hw/9pfs/9p.h +++ b/hw/9pfs/9p.h @@ -169,8 +169,24 @@ typedef struct V9fsXattr typedef struct V9fsDir { DIR *stream; + QemuMutex readdir_mutex; } V9fsDir; +static inline void v9fs_readdir_lock(V9fsDir *dir) +{ + qemu_mutex_lock(&dir->readdir_mutex); +} + +static inline void v9fs_readdir_unlock(V9fsDir *dir) +{ + qemu_mutex_unlock(&dir->readdir_mutex); +} + +static inline void v9fs_readdir_init(V9fsDir *dir) +{ + qemu_mutex_init(&dir->readdir_mutex); +} + /* * Filled by fs driver on open and other * calls.