From patchwork Fri Jun 4 13:42:58 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sripathi Kodi X-Patchwork-Id: 104275 Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o54DhJTw017391 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 4 Jun 2010 13:44:01 GMT Received: from localhost ([127.0.0.1] helo=sfs-ml-3.v29.ch3.sourceforge.com) by sfs-ml-3.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1OKXB4-0003BV-IA; Fri, 04 Jun 2010 13:43:14 +0000 Received: from sfi-mx-4.v28.ch3.sourceforge.com ([172.29.28.124] helo=mx.sourceforge.net) by sfs-ml-3.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1OKXB3-0003BF-5N for v9fs-developer@lists.sourceforge.net; Fri, 04 Jun 2010 13:43:13 +0000 Received-SPF: pass (sfi-mx-4.v28.ch3.sourceforge.com: domain of in.ibm.com designates 122.248.162.1 as permitted sender) client-ip=122.248.162.1; envelope-from=sripathik@in.ibm.com; helo=e28smtp01.in.ibm.com; Received: from e28smtp01.in.ibm.com ([122.248.162.1]) by sfi-mx-4.v28.ch3.sourceforge.com with esmtps (TLSv1:AES256-SHA:256) (Exim 4.69) id 1OKXB1-0002NT-LN for v9fs-developer@lists.sourceforge.net; Fri, 04 Jun 2010 13:43:13 +0000 Received: from d28relay05.in.ibm.com (d28relay05.in.ibm.com [9.184.220.62]) by e28smtp01.in.ibm.com (8.14.4/8.13.1) with ESMTP id o54Dh2iq020174 for ; Fri, 4 Jun 2010 19:13:02 +0530 Received: from d28av04.in.ibm.com (d28av04.in.ibm.com [9.184.220.66]) by d28relay05.in.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id o54Dh2Te3162302 for ; Fri, 4 Jun 2010 19:13:02 +0530 Received: from d28av04.in.ibm.com (loopback [127.0.0.1]) by d28av04.in.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id o54Dh25W030442 for ; Fri, 4 Jun 2010 23:43:02 +1000 Received: from sripathi.in.ibm.com ([9.77.199.101]) by d28av04.in.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id o54Dh13Y030430; Fri, 4 Jun 2010 23:43:02 +1000 Received: from localhost.localdomain (localhost [IPv6:::1]) by sripathi.in.ibm.com (Postfix) with ESMTP id AFCEEAF785; Fri, 4 Jun 2010 19:12:58 +0530 (IST) From: Sripathi Kodi To: qemu-devel@nongnu.org Date: Fri, 04 Jun 2010 19:12:58 +0530 Message-ID: <20100604134258.31714.57524.stgit@localhost.localdomain> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 X-Spam-Score: -1.3 (-) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -1.5 SPF_CHECK_PASS SPF reports sender host as permitted sender for sender-domain -0.0 SPF_PASS SPF: sender matches SPF record 0.2 AWL AWL: From: address is in the auto white-list X-Headers-End: 1OKXB1-0002NT-LN Cc: v9fs-developer@lists.sourceforge.net Subject: [V9fs-developer] [PATCH] [V4] virtio-9p: readdir implementation for 9p2000.L X-BeenThere: v9fs-developer@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: v9fs-developer-bounces@lists.sourceforge.net X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Fri, 04 Jun 2010 13:44:01 +0000 (UTC) diff --git a/hw/virtio-9p-debug.c b/hw/virtio-9p-debug.c index 2fb2673..a82b771 100644 --- a/hw/virtio-9p-debug.c +++ b/hw/virtio-9p-debug.c @@ -328,6 +328,19 @@ void pprint_pdu(V9fsPDU *pdu) } switch (pdu->id) { + case P9_TREADDIR: + fprintf(llogfile, "TREADDIR: ("); + pprint_int32(pdu, 0, &offset, "fid"); + pprint_int64(pdu, 0, &offset, ", initial offset"); + pprint_int32(pdu, 0, &offset, ", max count"); + break; + case P9_RREADDIR: + fprintf(llogfile, "RREADDIR: ("); + pprint_int32(pdu, 1, &offset, "count"); +#ifdef DEBUG_DATA + pprint_data(pdu, 1, &offset, ", data"); +#endif + break; case P9_TVERSION: fprintf(llogfile, "TVERSION: ("); pprint_int32(pdu, 0, &offset, "msize"); diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c index 2d1cbd5..9c7e256 100644 --- a/hw/virtio-9p.c +++ b/hw/virtio-9p.c @@ -1583,6 +1583,124 @@ out: qemu_free(vs); } +typedef struct V9fsReadDirState { + V9fsPDU *pdu; + V9fsFidState *fidp; + V9fsQID qid; + off_t saved_dir_pos; + struct dirent *dent; + int32_t count; + int32_t max_count; + size_t offset; + int64_t initial_offset; + V9fsString name; +} V9fsReadDirState; + +static void v9fs_readdir_post_seekdir(V9fsState *s, V9fsReadDirState *vs) +{ + vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count); + vs->offset += vs->count; + complete_pdu(s, vs->pdu, vs->offset); + qemu_free(vs); + return; +} + +/* Size of each dirent on the wire: size of qid (13) + size of offset (8) + * size of type (1) + size of name.size (2) + strlen(name.data) + */ +#define V9_READDIR_DATA_SZ (24 + strlen(vs->name.data)) + +static void v9fs_readdir_post_readdir(V9fsState *s, V9fsReadDirState *vs) +{ + int len; + size_t size; + + if (vs->dent) { + v9fs_string_init(&vs->name); + v9fs_string_sprintf(&vs->name, "%s", vs->dent->d_name); + + if ((vs->count + V9_READDIR_DATA_SZ) > vs->max_count) { + /* Ran out of buffer. Set dir back to old position and return */ + v9fs_do_seekdir(s, vs->fidp->dir, vs->saved_dir_pos); + v9fs_readdir_post_seekdir(s, vs); + return; + } + + /* Fill up just the path field of qid because the client uses + * only that. To fill the entire qid structure we will have + * to stat each dirent found, which is expensive + */ + size = MIN(sizeof(vs->dent->d_ino), sizeof(vs->qid.path)); + memcpy(&vs->qid.path, &vs->dent->d_ino, size); + + len = pdu_marshal(vs->pdu, vs->offset+4+vs->count, "Qqbs", + &vs->qid, vs->dent->d_off, + vs->dent->d_type, &vs->name); + vs->count += len; + v9fs_string_free(&vs->name); + vs->saved_dir_pos = vs->dent->d_off; + vs->dent = v9fs_do_readdir(s, vs->fidp->dir); + v9fs_readdir_post_readdir(s, vs); + return; + } + + vs->offset += pdu_marshal(vs->pdu, vs->offset, "d", vs->count); + vs->offset += vs->count; + complete_pdu(s, vs->pdu, vs->offset); + qemu_free(vs); + return; +} + +static void v9fs_readdir_post_telldir(V9fsState *s, V9fsReadDirState *vs) +{ + vs->dent = v9fs_do_readdir(s, vs->fidp->dir); + v9fs_readdir_post_readdir(s, vs); + return; +} + +static void v9fs_readdir_post_setdir(V9fsState *s, V9fsReadDirState *vs) +{ + vs->saved_dir_pos = v9fs_do_telldir(s, vs->fidp->dir); + v9fs_readdir_post_telldir(s, vs); + return; +} + +static void v9fs_readdir(V9fsState *s, V9fsPDU *pdu) +{ + int32_t fid; + V9fsReadDirState *vs; + ssize_t err = 0; + size_t offset = 7; + + vs = qemu_malloc(sizeof(*vs)); + vs->pdu = pdu; + vs->offset = 7; + vs->count = 0; + + pdu_unmarshal(vs->pdu, offset, "dqd", &fid, &vs->initial_offset, + &vs->max_count); + + vs->fidp = lookup_fid(s, fid); + if (vs->fidp == NULL || !(vs->fidp->dir)) { + err = -EINVAL; + goto out; + } + + if (vs->initial_offset == 0) { + v9fs_do_rewinddir(s, vs->fidp->dir); + } else { + v9fs_do_seekdir(s, vs->fidp->dir, vs->initial_offset); + } + + v9fs_readdir_post_setdir(s, vs); + return; + +out: + complete_pdu(s, pdu, err); + qemu_free(vs); + return; +} + static void v9fs_write_post_writev(V9fsState *s, V9fsWriteState *vs, ssize_t err) { @@ -2216,6 +2334,7 @@ out: typedef void (pdu_handler_t)(V9fsState *s, V9fsPDU *pdu); static pdu_handler_t *pdu_handlers[] = { + [P9_TREADDIR] = v9fs_readdir, [P9_TSTATFS] = v9fs_statfs, [P9_TVERSION] = v9fs_version, [P9_TATTACH] = v9fs_attach, diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h index 992c765..9773659 100644 --- a/hw/virtio-9p.h +++ b/hw/virtio-9p.h @@ -15,6 +15,8 @@ enum { P9_TSTATFS = 8, P9_RSTATFS, + P9_TREADDIR = 40, + P9_RREADDIR, P9_TVERSION = 100, P9_RVERSION, P9_TAUTH = 102,