From mboxrd@z Thu Jan 1 00:00:00 1970 Message-ID: <1e20ebf729397d2587b84945563cf675@swtch.com> To: 9fans@cse.psu.edu Subject: Re: [9fans] 9p and how can I know when a write is finished From: "Russ Cox" Date: Wed, 1 Mar 2006 11:47:34 -0500 In-Reply-To: <3427729765b4e88fb0db2d794e3cdbc6@cat-v.org> MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit Topicbox-Message-UUID: 0771c5ce-ead1-11e9-9d60-3106f5b1d025 > I'm not sure if I'm misunderstanding this but, > i need to write to a ctl file some commands, > so to parse them correctly i need the complete > command (commands file should be 10k or so, but > may be more). Each write message looks logically separate, even if they are all coming from a single write(2) system call. If the data may be 10k or more, I wouldn't even assume they're all from the same system call, of course, and then there's not even any possibility of a guarantee. The convention in this case is to accumulate the writes for a particular open fid in a buffer associated with that fid, and then wait for the Tclunk. This is sometimes unsatisfactory because you might want to indicate that an error happened, and Tclunk can't fail (and close(2) doesn't return -1 on real fds). In wikifs I chose to allow a zero-length write at the end of a sequence of writes to mean "okay, I'm done, do the processing and return me an error if something goes wrong". But if you skip the zero-length write, wikifs will still do the processing on Tclunk. You just won't get any indication of errors in the file you just wrote. A better but more involved solution is to have a directory for each active conversation (a la /net or /dev/draw) and in that directory have a data file for the big stuff and a separate control file for the little stuff. In that case you might { cd /mnt/you/^`{cat} cp /tmp/blob data echo command >ctl } Wrong, the Tclunk is not warranteed to arrive any time soon. You are the one who is wrong. The Tclunk for an open fid *is* guaranteed to be sent as soon as all the client's references to that fid have been closed. Arguably this is a detail of the client implementation, and a client might choose to do otherwise, but every 9P client ever written (Plan 9, Inferno, lib9pclient, v9fs, ...) does follow this rule. To do otherwise would cause problems not only with exclusive-use files but also with file servers that give Tclunk special meaning, like: - in /net (like in the /mnt/you example above), network connections are not fully given up until all the fids in the corresponding directory are clunked. - in rio, once all the fids for a particular window are clunked, the window is closed - in rio, writes to /dev/snarf are collected and only become the new snarf buffer contents when the writing fid is clunked. - in plumber, writes to /mnt/plumb/rules are collected and only become the new rules file when the writing fid is clunked. - in plumber, if no one has /mnt/plumb/quux open and there is a message for the quux port, the plumber runs the start rule associated with quux to handle the message. - in acme, an external program is assumed to be managing a given window if it's event file is open. if this fid were not clunked in a timely manner when the file was closed, the window would no longer respond to button 2 events like Del. > Tclunk != close() This is true, but not for the reason above. If you consider: fd = open("/tmp/a", OREAD); fd2 = dup(fd, -1); close(fd); close(fd2); then the Tclunk will be sent after the close(fd2), because that's the last reference to that particular instance of the open fid. Russ