* netfs.c (netfs_attempt_sync): Sync every directory associated with the supplied node. (netfs_attempt_syncfs): Send file_syncfs to every directory maintained by unionfs. ---
Hello, On Tue, Nov 17, 2009 at 09:58:15PM +0100, olafbuddenha...@gmx.net wrote: > On Tue, Nov 17, 2009 at 12:30:56PM +0200, Sergiu Ivanov wrote: > > On Fri, Nov 06, 2009 at 09:58:31AM +0100, olafbuddenha...@gmx.net > > wrote: > > > > Well, did you actually test how it behaves with really readonly > > > filesystems? (Most notably that it doesn't return an error status?) > > > > As an example of a readonly filesystem I took xmlfs and took a glance > > at it's implementation of netfs sync stubs. And then it flashed in my > > mind that all implementations of sync stubs that I've seen and which > > did nothing returned 0. I can't remember this being specified as a > > convention somewhere, though. > > OK, misunderstanding here: I didn't mean translators that do not > implement writing -- I meant filesystems *mounted* readonly. Ah, I see. I did the following: # settrans -a tmp /hurd/ext2fs /dev/hd2 ext2fs: /dev/hd2: warning: FILESYSTEM NOT UNMOUNTED CLEANLY; PLEASE fsck ext2fs: /dev/hd2: warning: MOUNTED READ-ONLY; MUST USE `fsysopts --writable' $ settrans -a foo unionfs tmp $ syncfs foo $ syncfs foo/home/scolobb (As a special note I remark that foo/home/scolobb does exist.) The first warning by ext2fs is due to the fact that I actually remounted the (already mounted) /home partition. (I hope I haven't screwed things up.) The second one shows that the filesystem has been mounted read-only. I guess this is what you mean. First of all, syncfs foo invokes netfs_attempt_syncfs, wherein all calls to file_syncfs happily return 0. On the other hand, syncfs foo/home/scolobb also invokes netfs_attempt_syncfs (not netfs_attempt_sync as I would suppose). To invoke netfs_attempt_sync, I sketched the following simple program: #define _GNU_SOURCE 1 #include <hurd.h> #include <hurd/fs.h> #include <fcntl.h> #include <stdio.h> int main (void) { mach_port_t p = file_name_lookup ("foo/home/", O_READ, 0); file_sync (p, 1, 0); mach_port_deallocate (mach_task_self (), p); return 0; } /* main */ Which did cause invocation of netfs_attempt_sync and I could see that file_sync also returns 0 when invoked on a port to a read-only filesystem. Thus, if I did everything correctly, it seems that we have no problems syncing really read-only filesystems either. > > + /* The index of the currently analyzed filesystem. */ > > + int i = 0; > > You forgot to change it for the second loop... Ah, yes :-( Fixed. Regads, scolobb --- netfs.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 78 insertions(+), 3 deletions(-) diff --git a/netfs.c b/netfs.c index 89d1bf6..4c9f9a3 100644 --- a/netfs.c +++ b/netfs.c @@ -1,5 +1,6 @@ /* Hurd unionfs - Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. + Written by Moritz Schulte <mor...@duesseldorf.ccc.de>. This program is free software; you can redistribute it and/or @@ -282,7 +283,45 @@ error_t netfs_attempt_sync (struct iouser *cred, struct node *np, int wait) { - return EOPNOTSUPP; + /* The error we are going to report back (last failure wins). */ + error_t final_err = 0; + + /* The information about the currently analyzed filesystem. */ + ulfs_t * ulfs; + + /* The index of the currently analyzed filesystem. */ + int i; + + mutex_lock (&ulfs_lock); + + /* Sync every directory associated with `np`. + + TODO: Rewrite this after having modified ulfs.c and node.c to + store the paths and ports to the underlying directories in one + place, because now iterating over both lists looks ugly. */ + i = 0; + node_ulfs_iterate_unlocked (np) + { + error_t err; + + /* Get the information about the current filesystem. */ + err = ulfs_get_num (i, &ulfs); + assert (!err); + + /* Since `np` may not necessarily be present in every underlying + directory, having a null port is perfectly valid. */ + if (node_ulfs->port != MACH_PORT_NULL) + { + err = file_sync (node_ulfs->port, wait, 0); + if (err) + final_err = err; + } + + ++i; + } + + mutex_unlock (&ulfs_lock); + return final_err; } /* This should sync the entire remote filesystem. If WAIT is set, @@ -290,7 +329,43 @@ netfs_attempt_sync (struct iouser *cred, struct node *np, error_t netfs_attempt_syncfs (struct iouser *cred, int wait) { - return 0; + /* The error we are going to report back (last failure wins). */ + error_t final_err = 0; + + /* The information about the currently analyzed filesystem. */ + ulfs_t * ulfs; + + /* The index of the currently analyzed filesystem. */ + int i; + + mutex_lock (&ulfs_lock); + + /* Sync every unioned directory maintained by unionfs. + + TODO: Rewrite this after having modified ulfs.c and node.c to + store the paths and ports to the underlying directories in one + place, because now iterating over both lists looks ugly. */ + i = 0; + node_ulfs_iterate_unlocked (netfs_root_node) + { + error_t err; + + /* Get the information about the current filesystem. */ + err = ulfs_get_num (i, &ulfs); + assert (err == 0); + + /* Note that, unlike the situation in netfs_attempt_sync, having a + null port on the unionfs root node is abnormal. */ + assert (node_ulfs->port != MACH_PORT_NULL); + err = file_syncfs (node_ulfs->port, wait, 0); + if (err) + final_err = err; + + ++i; + } + + mutex_unlock (&ulfs_lock); + return final_err; } /* lookup */ -- 1.6.5.2