aboutsummaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
authorseebs <seebs@seebs-eee.(none)>2010-08-17 16:12:13 -0500
committerseebs <seebs@seebs-eee.(none)>2010-08-17 16:40:15 -0500
commit6ea4acf2af23b5940521825a849deefc07fe9d47 (patch)
tree2a94b834fa0a5a8d0b08f61a412c3dc9a82e7eec /doc
parentb66645f72f9ebc0ab2a8aeaf1df8e8219624f61c (diff)
downloadpseudo-6ea4acf2af23b5940521825a849deefc07fe9d47.tar.gz
pseudo-6ea4acf2af23b5940521825a849deefc07fe9d47.tar.bz2
pseudo-6ea4acf2af23b5940521825a849deefc07fe9d47.zip
Draft one effort at making unlink more robust and fixing an obvious
bug in the speculative-unlink operation. The intent is to mark and then confirm or cancel the delete. This removes the quirk where we tried to stash old database entries, which didn't handle directories anyway; "rmdir non-empty-directory" is a bit too common a case to dismiss as unthinkable.
Diffstat (limited to 'doc')
-rw-r--r--doc/database32
1 files changed, 31 insertions, 1 deletions
diff --git a/doc/database b/doc/database
index da8f750..7003aff 100644
--- a/doc/database
+++ b/doc/database
@@ -14,6 +14,7 @@ FILES:
gid (integer)
mode (integer)
rdev (integer)
+ deleting (integer)
There are two indexes on the file database, one by path and one by device
and inode. Earlier versions of pseudo ignored symlinks, but this turned
@@ -30,10 +31,38 @@ to obtain the device and inode, then modifying all matching records.
If a file shows up with no name (this should VERY rarely happen), it is stored
in the database with the special name 'NAMELESS FILE'. This name can never
-be sent by the client (all names are sent as absolute paths). If a later
+be sent by the client (all names are sent as absolute paths). If a laterThe
request comes in with a valid name, the 'NAMELESS FILE' is renamed to it so
it can be unlinked later.
+The "deleting" field is used to track files which are in the midst of
+being possibly-deleted. The issue is that if you issue an unlink database
+operation only after removing a file, there is a window during which
+another program can genuinely create a new file with the same name or
+inode, and that request can reach the daemon before the unlink operation
+does. To address this, three operations are addded: may-unlink, did-unlink,
+and cancel-unlink. The may-unlink operation tags a file for possible
+deletion, setting "deleting" to 1. A clash involving a file marked for
+deletion is resolved by deleting the existing database entry without
+complaint. A did-unlink operation deletes a file ONLY if it is marked
+for deletion. A cancel-unlink operation unmarks a file for deletion.
+
+You can still have a race condition here, but it seems a lot less likely.
+The failure would be:
+ Process A marks file X for deletion.
+ Process A unlinks file X.
+ Process B creates file X.
+ Process B requests a link for X.
+ The server unlinks the previously marked X.
+ The server creates a new link for X, not marked for deletion.
+ Process B marks file X for deletion.
+ Process A's delete-marked-file request finally shows up.
+ The server unlinks the newly-marked X.
+ Process B fails to delete the file.
+ Process B attempts to cancel the mark-for-deletion.
+
+This shouldn't be a common occurrence.
+
Rename operations use a pair of paths, separated by a null byte; the client
sends the total length of both names (plus the null byte), and the server
knows to split them around the null byte. The impact of a rename on things
@@ -88,3 +117,4 @@ opened. These values are not completely reliable. A value of 0 is typical
for non-open operations, and a value outside the 0-15 range (usually -1)
indicates that something went wrong trying to identify the mode of a given
open.
+