gtfs: Support intra-directory rename 9p can handle it. This actually has a couple benefits apart from passing a Go test: - No needless copies for large files - Atomic rename for intra-directory files, which is a common pattern for updating a file atomically. Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
diff --git a/kern/drivers/dev/gtfs.c b/kern/drivers/dev/gtfs.c index 6a596ea..a7284ba 100644 --- a/kern/drivers/dev/gtfs.c +++ b/kern/drivers/dev/gtfs.c
@@ -517,6 +517,15 @@ poperror(); } +static void gtfs_wstat_rename(struct fs_file *f, const char *name) +{ + struct dir dir; + + init_empty_dir(&dir); + dir.name = (char*)name; + wstat_dir(f, &dir); +} + static void gtfs_tf_rename(struct tree_file *tf, struct tree_file *old_parent, struct tree_file *new_parent, const char *name, int flags) @@ -524,9 +533,16 @@ struct chan *tf_c = tf_to_gtfs_priv(tf)->be_walk; struct chan *np_c = tf_to_gtfs_priv(new_parent)->be_walk; - if (!devtab[tf_c->type].rename) + if (!devtab[tf_c->type].rename) { + /* 9p can handle intra-directory renames, though some Akaros #devices + * might throw. */ + if (old_parent == new_parent) { + gtfs_wstat_rename(&tf->file, name); + return; + } error(EXDEV, "%s: %s doesn't support rename", devname(), devtab[tf_c->type].name); + } devtab[tf_c->type].rename(tf_c, np_c, name, flags); } @@ -858,6 +874,7 @@ .write = tree_chan_write, .bwrite = devbwrite, .remove = gtfs_remove, + .rename = tree_chan_rename, .wstat = gtfs_wstat, .power = devpower, .chaninfo = devchaninfo,