From: Stef B. <st...@gm...> - 2010-04-25 21:44:31
|
Hello, I've got an fuse fs, using normal operations. Now I would like to write a lowlevel variant of it. I've read the example hello_ll.c. Before I start reading everything, can somebody give me some hints what to look for, what's the main difference with the "high level" operations? Thanks in advance, Stef |
From: Goswin v. B. <gos...@we...> - 2010-04-26 08:37:59
|
Stef Bon <st...@gm...> writes: > Hello, > > I've got an fuse fs, using normal operations. Now I would like to write a > lowlevel variant of it. I've read the example hello_ll.c. Before I > start reading everything, > can somebody give me some hints what to look for, what's the main > difference with the > "high level" operations? The high level interface works on paths while the low level interface works on inodes. For the low level interface to be usefull you need to be able to operate on an inode directly. If you need to lookup the path for an inode to work on it then you will just be reimplementing the high level intervace. MfG Goswin |
From: Stef B. <st...@gm...> - 2010-04-26 12:16:11
|
Hi, thanks for yor answer. I'm afraid this does not make it easier. My fs is an overlay fs, so the path is essential. Futher I'm using an additional fs (config) to adjust the behaviour of my fs. I do not know how to do this all when the parameter is inode, not path. I know that it all comes to handling inodes at the end, but in my fs the basename, the dirname, the target of a symlink is compared, I do not know how to deal with this when working with only inodes. The reason for me to try this is that I remember a reaction of Miklos: "The high level API is synchronous, single threaded mode will prevent any parallelism. The low level API is asynchronous, it allows processing requests in parallel within a single thread." When making my fs single theaded, it should allow async requests, well that means a lowlevel fs. I have to stick at single thread/high level for now. Things are already very complicated. I'm still looking how to make inotify work: I've written something about this on my website: ------------------------------------------------------------------ - I do not exactly how an inotify system call is handled in the kernel/VFS, but it should be passed to the fuse module, just like any other call, and mapped to a fs specific operation: .inotify_add_watch = myfs_inotify_add_watch, .inotify_rm_watch = myfs_inotify_rm_watch, The add_watch call should result in an fd, which should be managed with select/poll/epoll to read for incoming events. These events (standard inotify_event format?) should be forwared back to the original add_watch call. The latest is also an fd, but should it also be polled to be ready to be written to? I do not know. One parameter is of course the path. (!) To add these fd's to the main epoll instance is an challenging task. They have to treated not like the other operations, they are command driven. An inotify event can occur anytime. So the fd should be watched constantly. When setting a watch on the underlying fs, I think it's a good thing to add this to the already declared inotify instance. This instance it watched with epoll. Suppose there are more than one of those watches added (or activated). Now the system will pass through any event back to the inotify instance. When these are noted and managed with epoll, it's not so hard to match these events with the original inotify request on the fuse fs. To make this work an array or linked list with elements which pairs the original watch descriptor to the watch descriptor used by the fuse module is necessary. Stef 2010/4/26 Goswin von Brederlow <gos...@we...>: > Stef Bon <st...@gm...> writes: > >> Hello, >> >> I've got an fuse fs, using normal operations. Now I would like to write a >> lowlevel variant of it. I've read the example hello_ll.c. Before I >> start reading everything, >> can somebody give me some hints what to look for, what's the main >> difference with the >> "high level" operations? > > The high level interface works on paths while the low level interface > works on inodes. For the low level interface to be usefull you need to > be able to operate on an inode directly. If you need to lookup the path > for an inode to work on it then you will just be reimplementing the high > level intervace. > > MfG > Goswin > |
From: Goswin v. B. <gos...@we...> - 2010-04-26 19:27:55
|
Stef Bon <st...@gm...> writes: > Hi, > > thanks for yor answer. > I'm afraid this does not make it easier. > My fs is an overlay fs, so the path is essential. Futher I'm using an > additional fs (config) to adjust the behaviour of my fs. > I do not know how to do this all when the parameter is inode, not path. > I know that it all comes to handling inodes at the end, but in my fs > the basename, the dirname, the target of a symlink is compared, I do > not know how to deal with this when working with only inodes. You will need some way to get the path for an inode. Which is what the high level interface handles for you. In your case it might be desirable to do so. > The reason for me to try this is that I remember a reaction of Miklos: > > "The high level API is synchronous, single threaded mode will prevent > any parallelism. > > The low level API is asynchronous, it allows processing requests in > parallel within a single thread." > > When making my fs single theaded, it should allow async requests, well that > means a lowlevel fs. > > I have to stick at single thread/high level for now. Things are > already very complicated. I'm still looking how to make inotify work: Then that means you need to reimplement the high level interface but this time make it async. You can probably reuse a lot of the existing interface to make your async-high-level interface. All the code that stores path names for inodes and such. MfG Goswin |
From: Stef B. <st...@gm...> - 2010-04-27 08:40:55
|
Hi, am I the only one interested in this topic? I strikes me that there are no other reactions than yours Goswin. Also for you as developer of FUSE (you are!?) inotify is of interest? Or is everybody thinking it's too hard, too complicated? Stef 2010/4/26 Goswin von Brederlow <gos...@we...>: > Stef Bon <st...@gm...> writes: > >> Hi, >> >> thanks for yor answer. >> I'm afraid this does not make it easier. >> My fs is an overlay fs, so the path is essential. Futher I'm using an >> additional fs (config) to adjust the behaviour of my fs. >> I do not know how to do this all when the parameter is inode, not path. >> I know that it all comes to handling inodes at the end, but in my fs >> the basename, the dirname, the target of a symlink is compared, I do >> not know how to deal with this when working with only inodes. > > You will need some way to get the path for an inode. Which is what the > high level interface handles for you. In your case it might be desirable > to do so. > >> The reason for me to try this is that I remember a reaction of Miklos: >> >> "The high level API is synchronous, single threaded mode will prevent >> any parallelism. >> >> The low level API is asynchronous, it allows processing requests in >> parallel within a single thread." >> >> When making my fs single theaded, it should allow async requests, well that >> means a lowlevel fs. >> >> I have to stick at single thread/high level for now. Things are >> already very complicated. I'm still looking how to make inotify work: > > Then that means you need to reimplement the high level interface but > this time make it async. You can probably reuse a lot of the existing > interface to make your async-high-level interface. All the code that > stores path names for inodes and such. > > MfG > Goswin > |
From: <mat...@gm...> - 2010-04-27 09:23:28
|
On Apr 27, 2010 9:40am, Stef Bon <st...@gm...> wrote: > Hi, > am I the only one interested in this topic? I strikes me that there > are no other reactions than yours Goswin. > Also for you as developer of FUSE (you are!?) inotify is of interest? > Or is everybody thinking it's too hard, too complicated? I have an fs which used the high-level interface, and am in the process of moving it to the low-level interface. Mine works on paths so as Goswin says I'm basically reimplementing the high-level interface. This is a bit tricky as I can't find any documentation about the invariants of inode handling (reuse, generations, etc). My fs was always multi-threaded and does network I/O so the sync/async problem isn'ta big one for me - I used to have the threads that were cloned for the filesystem methods block on locks while another thread did the work, then I would unlock the method thread and return the answer when it was ready. This blocking now isn't necessary - the callbacks from my network I/O now call the fuse lowlevel callbacks directly. The *only* reason I changed to the lowlevel interface is to be able to call fuse_reply_buf and fuse_reply_iov from read to avoid the an extra copy into the buffer that the high-level interface insists on allocating for you (discussed on this list around 17th Feb 2010). In conclusion I'd say that if you have an fs like mine that works on paths (I use paths to send requests to a server) then moving to the low-level interface can be hard work, gains you very little (maybe a bit of code cleanliness from being properly async) and can be more of a pain to debug. Maybe with a couple of (incompatible?) changes to the high-level interface it would be appropriate for more people. Just my 2p, matt |
From: John M. <jo...@jm...> - 2010-04-27 12:30:22
|
On 2010-04-27, at 5:23 AM, mat...@gm... wrote: > On Apr 27, 2010 9:40am, Stef Bon <st...@gm...> wrote: >> am I the only one interested in this topic? I strikes me that there >> are no other reactions than yours Goswin. >> Also for you as developer of FUSE (you are!?) inotify is of interest? >> Or is everybody thinking it's too hard, too complicated? The low level interface also lets you: - support hard links properly. - support unlinked files that were open a bit more cleanly after a crash (something is tickling my brain about this - maybe I'm mistaken). - implement full NFS server support (lookup by inode number only, lookup parent of an inode). - notify the kernel of changes to your files and directories (for network file-systems). Otherwise, it's true that if your file-system is an overlay, then using the low-level interface means that you will re-implement parts of the high level interface (I did too). If you don't use an overlay, remember to set st_nlink of the directory to 2 + number of sub-directories, or the find command won't work (or was it rsync? ... either way). John. -- John Muir - jo...@jm... |
From: Sven U. <sve...@gm...> - 2010-04-27 14:49:41
|
Hello, > >> am I the only one interested in this topic? I strikes me that > >> there are no other reactions than yours Goswin. Well, I'm only using the high-level interface, as lookup by path and being multi-treaded fits me nicely (ok, I wouldn't mind being asynchronous, in particular when dealing with heavy load, but so far this wasn't a problem). > >> Also for you as developer of FUSE (you are!?) inotify is of > >> interest? Never needed inotify (then again, my FS is essentially RO, so there...) > - support hard links properly. Well, in my case, where files actually _are_ identified by path, this would be more difficult using the low-level interface. Or at least not any easier... > - implement full NFS server support (lookup by inode number only, > lookup parent of an inode). That one sounds interesting --- could you point me to some more information about this one? > If you don't use an overlay, remember to set st_nlink of the > directory to 2 + number of sub-directories, or the find command > won't work (or was it rsync? ... either way). Well, there's the -noleaf option to find, and many other FS are broken in the same way (AFS springs to mind, and I believe NFTS too). I just set it to 1, which seems to work better than expected. Sven -- _ ___ ___ ___ __| |/ __|| __|/ __| The dCache File System / _` | (__ | _| \__ \ An archive file-system for PB of data \__,_|\___||_| |___/ http://www.desy.de/~utcke/Data/ |
From: John M. <jo...@jm...> - 2010-04-27 15:14:24
|
On 2010-04-27, at 10:49 AM, Sven Utcke wrote: >> - implement full NFS server support (lookup by inode number only, >> lookup parent of an inode). The lowlevel lookup operation will get a name of "." when doing a lookup by inode number only, and ".." when doing a lookup of the parent inode number. The reason that this doesn't work in the high level interface is that the inode numbers are dynamic (mainly they do not live through restart of the file-system server), so you might lookup the wrong file. Regards, John. -- John Muir - jo...@jm... |
From: Allen P. <pul...@co...> - 2010-04-27 15:25:41
|
> Well, there's the -noleaf option to find, and many other FS > are broken in the same way (AFS springs to mind, and I > believe NFTS too). I just set it to 1, which seems to work > better than expected. This should work fine because find should have no trouble figuring out the link count is always 1 in your file system. In fact, find in GNU findutils v4.4.2 contains the following code: if (mode && S_ISDIR(mode) && (subdirs_left == 0)) { /* This is a subdirectory, but the number of directories we * have found now exceeds the number we would expect given * the hard link count on the parent. This is likely to be * a bug in the file system driver (e.g. Linux's * /proc file system) or may just be a fact that the OS * doesn't really handle hard links with Unix semantics. * In the latter case, -noleaf should be used routinely. */ error(0, 0, _("WARNING: Hard link count is wrong for %s (saw only st_nlink=%d but we already saw %d subdirectories): this may be a bug in your file system driver. Automatically turning on find's -noleaf option. Earlier results may have failed to include directories that should have been searched."), safely_quote_err_filename(0, pathname), statp->st_nlink, dircount); state.exit_status = 1; /* We know the result is wrong, now */ options.no_leaf_check = true; /* Don't make same mistake again */ subdirs_unreliable = 1; subdirs_left = 1; /* band-aid for this iteration. */ } |
From: Stef B. <st...@gm...> - 2010-04-27 17:11:59
|
Hello all, thanks for your reaction! I was thinking I'm alone in this topic, but this is obviously not true. Especially to John and Matt, I do appreciate it when you would put your fs's online, part of the wiki. Or a simple version of it, like fusexmp. This is part of the source of FUSE, and acts like a bind mount. There is already a fusexmp_fh, which has also have been of great use to me. If there is an simular version of that (like fusexmp_ll) I (and others) do not have to do the work all over again. But this is just an suggestion how. If someone can give a good example how to write a fuse low level fs, please share this. But - like Matt says - it's good to look at the reason why the high level interface is not async. Maybe there is a good reason for that, but maybe some of the main developers can say something about that. Stef Bon |
From: Miklos S. <mi...@sz...> - 2010-04-27 17:33:40
|
On Tue, 27 Apr 2010, Stef Bon wrote: > Hello all, > > thanks for your reaction! I was thinking I'm alone in this topic, but > this is obviously not true. > > Especially to John and Matt, I do appreciate it when you would put > your fs's online, part of the wiki. > Or a simple version of it, like fusexmp. This is part of the source of > FUSE, and acts like a bind mount. > There is already a fusexmp_fh, which has also have been of great use to me. > > If there is an simular version of that (like fusexmp_ll) I (and > others) do not have to do the work all over again. > But this is just an suggestion how. If someone can give a good example > how to write a fuse low level fs, please share this. Deltafs is also written with the low level interface: http://git.kernel.org/?p=linux/kernel/git/mszeredi/deltafs.git;a=tree > But - like Matt says - it's good to look at the reason why the high > level interface is not async. > Maybe there is a good reason for that, but maybe some of the main > developers can say something about that. The high level interface was created with simplicity in mind. Making it asynchronous would complicate it. There are plans to create a library API which does the inode->path conversion and which could ease the use of the low level API for applications using paths but wanting async processing (for example sshfs would benefit from this). Thanks, Miklos |
From: Stef B. <st...@gm...> - 2010-04-27 18:55:14
|
Thank you for this. 2010/4/27 Miklos Szeredi <mi...@sz...>: >>If someone can give a good example >> how to write a fuse low level fs, please share this. > > Deltafs is also written with the low level interface: > > http://git.kernel.org/?p=linux/kernel/git/mszeredi/deltafs.git;a=tree > Ok. This fs is a good example. I'll try to write a fusexmp_ll, which is not so hard when there is already deltafs. And it's a good exercise for me to get familiar with inode programming. When I've got a working version, I'll post it here, and maybe add it to the projects list. >> But - like Matt says - it's good to look at the reason why the high >> level interface is not async. >> Maybe there is a good reason for that, but maybe some of the main >> developers can say something about that. > > The high level interface was created with simplicity in mind. Making > it asynchronous would complicate it. > > There are plans to create a library API which does the inode->path > conversion and which could ease the use of the low level API for > applications using paths but wanting async processing (for example > sshfs would benefit from this). Ok, I do not know these plans, but when looking to how filesystemsin linux works in general, when file (or dir) is looked up, first all the parents are looked up. The path is the summation of all the parents (and the name of the file self). So when dealing with an inode, the path is always available (in the background). Stef > > Thanks, > Miklos > |
From: Sven U. <sve...@gm...> - 2010-04-27 20:39:22
|
> > But - like Matt says - it's good to look at the reason why the > > high level interface is not async. Maybe there is a good reason > > for that, but maybe some of the main developers can say something > > about that. > > The high level interface was created with simplicity in mind. > Making it asynchronous would complicate it. And, frankly, I appreciate that --- this way, if I want to know what a function is supposed to do and how to implement it, I can simply look up the corresponding POSIX function (well, nearly). Sven -- _ ___ ___ ___ __| |/ __|| __|/ __| The dCache File System / _` | (__ | _| \__ \ An archive file-system for PB of data \__,_|\___||_| |___/ http://www.desy.de/~utcke/Data/ |
From: Nikolaus R. <Nik...@ra...> - 2010-04-28 03:27:32
|
Sven Utcke <sve...@gm...> writes: >> > But - like Matt says - it's good to look at the reason why the >> > high level interface is not async. Maybe there is a good reason >> > for that, but maybe some of the main developers can say something >> > about that. >> >> The high level interface was created with simplicity in mind. >> Making it asynchronous would complicate it. > > And, frankly, I appreciate that --- this way, if I want to know what a > function is supposed to do and how to implement it, I can simply look > up the corresponding POSIX function (well, nearly). Personally I would be more interested in a synchronous low level interface, i.e., it should allow to work with inodes but without requiring reply_* functions. Best, -Nikolaus -- »Time flies like an arrow, fruit flies like a Banana.« PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C |
From: Sven U. <sve...@gm...> - 2010-04-28 08:18:18
|
> >> The high level interface was created with simplicity in mind. > >> Making it asynchronous would complicate it. > > > > And, frankly, I appreciate that --- this way, if I want to know > > what a function is supposed to do and how to implement it, I can > > simply look up the corresponding POSIX function (well, nearly). > > Personally I would be more interested in a synchronous low level > interface, i.e., it should allow to work with inodes but without > requiring reply_* functions. Why do you need inodes anyway? That said, I would have liked the high-level interface to use the inodes I supply (which _are_ guaranteed to stay constant over restarts, in my case --- maybe use a generated inode if the one provided is 0, or the provided one otherwise...) Sven -- _ ___ ___ ___ __| |/ __|| __|/ __| The dCache File System / _` | (__ | _| \__ \ An archive file-system for PB of data \__,_|\___||_| |___/ http://www.desy.de/~utcke/Data/ |
From: Goswin v. B. <gos...@we...> - 2010-04-29 13:41:53
|
Sven Utcke <sve...@gm...> writes: >> >> The high level interface was created with simplicity in mind. >> >> Making it asynchronous would complicate it. >> > >> > And, frankly, I appreciate that --- this way, if I want to know >> > what a function is supposed to do and how to implement it, I can >> > simply look up the corresponding POSIX function (well, nearly). >> >> Personally I would be more interested in a synchronous low level >> interface, i.e., it should allow to work with inodes but without >> requiring reply_* functions. > > Why do you need inodes anyway? Because passing around the path would mean allocating memory for it, parsing it again and again, breaks with bind mounts, breaks with deleted but still open files and breaks all the *at() functions. MfG Goswin |
From: Nikolaus R. <Nik...@ra...> - 2010-04-28 14:30:20
|
Sven Utcke <sve...@gm...> writes: >> >> The high level interface was created with simplicity in mind. >> >> Making it asynchronous would complicate it. >> > >> > And, frankly, I appreciate that --- this way, if I want to know >> > what a function is supposed to do and how to implement it, I can >> > simply look up the corresponding POSIX function (well, nearly). >> >> Personally I would be more interested in a synchronous low level >> interface, i.e., it should allow to work with inodes but without >> requiring reply_* functions. > > Why do you need inodes anyway? Because my file system is inode based. To look up a directory entry, I need the parent inode, not the path. > That said, I would have liked the > high-level interface to use the inodes I supply (which _are_ > guaranteed to stay constant over restarts, in my case --- maybe use > a generated inode if the one provided is 0, or the provided one > otherwise...) Isn't that what -o use_ino does? Best, -Nikolaus -- »Time flies like an arrow, fruit flies like a Banana.« PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C |
From: Nikolaus R. <Nik...@ra...> - 2010-04-27 21:27:38
|
John Muir <jo...@jm...> writes: > On 2010-04-27, at 10:49 AM, Sven Utcke wrote: > >>> - implement full NFS server support (lookup by inode number only, >>> lookup parent of an inode). > > The lowlevel lookup operation will get a name of "." when doing a > lookup by inode number only, and ".." when doing a lookup of the > parent inode number. I don't follow. Why should the (kernel) FUSE issue a lookup for '.'? It has to provide the parent inode to lookup(), so it already knows the result. I have never received lookups for either . or .., but I admit that I'm not exporting my FS over NFS. Best, -Nikolaus -- »Time flies like an arrow, fruit flies like a Banana.« PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C |
From: John M. <jo...@jm...> - 2010-04-27 22:12:37
|
On 2010-04-27, at 5:23 PM, Nikolaus Rath wrote: > John Muir <jo...@jm...> writes: >> On 2010-04-27, at 10:49 AM, Sven Utcke wrote: >> >>>> - implement full NFS server support (lookup by inode number only, >>>> lookup parent of an inode). >> >> The lowlevel lookup operation will get a name of "." when doing a >> lookup by inode number only, and ".." when doing a lookup of the >> parent inode number. > > I don't follow. Why should the (kernel) FUSE issue a lookup for '.'? It > has to provide the parent inode to lookup(), so it already knows the > result. Low-level lookup: void (*lookup) (fuse_req_t req, fuse_ino_t parent, const char *name); For the lookup by inode number case, the inode number is provided in the 'parent' argument for the lookup operation, and the name parameter is ".". The file-system implementation must find the inode (specified by parent) within the file-system, and return fuse_reply_entry (or fuse_reply_err if the inode no longer exists). For the lookup inode's parent case, the inode number is provided in the 'parent' argument for the lookup operation, and the name parameter is "..". The file-system implementation must find a parent directory of the inode (specified by parent) within the file-system, and return fuse_reply_entry (or fuse_reply_err if the inode no longer exists). Furthermore, the file-system would connect it into it's caches so that subsequent operations on that inode can proceed without additional lookups. These are required by the NFS server for the case where the NFS client has a cache of the files being modified (or an open file for example), and issues a request to the NFS server using only the NFS file handle (which includes the inode number). If the local kernel doesn't have the inode in it's cache, then the NFS server will issue a VFS callback defined in 'export_operations' (sb->s_export) to get an inode, or return ESTALE. John. |
From: Goswin v. B. <gos...@we...> - 2010-04-27 22:24:31
|
Nikolaus Rath <Nik...@ra...> writes: > John Muir <jo...@jm...> writes: >> On 2010-04-27, at 10:49 AM, Sven Utcke wrote: >> >>>> - implement full NFS server support (lookup by inode number only, >>>> lookup parent of an inode). >> >> The lowlevel lookup operation will get a name of "." when doing a >> lookup by inode number only, and ".." when doing a lookup of the >> parent inode number. > > I don't follow. Why should the (kernel) FUSE issue a lookup for '.'? It > has to provide the parent inode to lookup(), so it already knows the > result. > > I have never received lookups for either . or .., but I admit that I'm > not exporting my FS over NFS. The NFS protocol only gives you a NFS handle, which it too small to contain a path but large enough to contain inode numbers. Through that handle the kernel gets the inode of the directory/file an operation is to act upon and then you have to find that inode. Now with the highlevel interface the inode numbers are (usualy) dynamic. Between NFS operations a file can change inode numbers and another file even reuse the old inode number causing no end of confusion for NFS. MfG Goswin |
From: Nikolaus R. <Nik...@ra...> - 2010-04-27 22:27:33
|
Sven Utcke <sve...@gm...> writes: >> If you don't use an overlay, remember to set st_nlink of the >> directory to 2 + number of sub-directories, or the find command >> won't work (or was it rsync? ... either way). > > Well, there's the -noleaf option to find, and many other FS are broken > in the same way (AFS springs to mind, and I believe NFTS too). I just > set it to 1, which seems to work better than expected. Doesn't this depend on readdir() (not) returning . and ..? I would say that if readdir returns . and .., st_nlink should be 2 + number of subdirs, since this is the true number of references: 1 reference by "real" name in the parent directory + one reference by '.' + one reference by '..' from each sub directory. If readdir does not return . and .., on the other hand, I would always return st_nlink=1 and consider find (or rsync) broken if they get into trouble with that, not the FS. Best, -Nikolaus -- »Time flies like an arrow, fruit flies like a Banana.« PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C |
From: Goswin v. B. <gos...@we...> - 2010-04-28 07:25:44
|
Nikolaus Rath <Nik...@ra...> writes: > Sven Utcke <sve...@gm...> writes: >>> If you don't use an overlay, remember to set st_nlink of the >>> directory to 2 + number of sub-directories, or the find command >>> won't work (or was it rsync? ... either way). >> >> Well, there's the -noleaf option to find, and many other FS are broken >> in the same way (AFS springs to mind, and I believe NFTS too). I just >> set it to 1, which seems to work better than expected. > > Doesn't this depend on readdir() (not) returning . and ..? > > I would say that if readdir returns . and .., st_nlink should be 2 + > number of subdirs, since this is the true number of references: 1 > reference by "real" name in the parent directory + one reference by '.' > + one reference by '..' from each sub directory. > > If readdir does not return . and .., on the other hand, I would always > return st_nlink=1 and consider find (or rsync) broken if they get into > trouble with that, not the FS. > > > Best, > > -Nikolaus POSIX doesn't require st_nlink to be 2 + number of subdirs. That is just how most FSes work and find takes advantage of that fakt to know how many subdirs there are. That allows it to take shortcuts sometimes. And yes, you can consider find broken in that regard. It relies on undefined behaviour there. MfG Goswin |
From: Allen P. <pul...@co...> - 2010-04-28 12:33:43
|
> I just set st_nlink to 1, which seems to work better than expected. find in GNU findutils v4.4.2 also contains the following code: if (statp->st_nlink < 2) { subdirs_unreliable = true; subdirs_left = 0; } So it looks like that is correct: if you don't know what st_nlink "should" be, just set it to 1 and find will work fine. |
From: Nikolaus R. <Nik...@ra...> - 2010-04-28 14:28:08
|
"Allen Pulsifer" <pul...@co...> writes: >> I just set st_nlink to 1, which seems to work better than expected. > > find in GNU findutils v4.4.2 also contains the following code: > > if (statp->st_nlink < 2) > { > subdirs_unreliable = true; > subdirs_left = 0; > } That is buggy as well. If POSIX doesn't specify the st_nlink for directories, it may just as well be always '3', independent of the number of subdirs. Best, -Nikolaus -- »Time flies like an arrow, fruit flies like a Banana.« PGP fingerprint: 5B93 61F8 4EA2 E279 ABF6 02CF A9AD B7F8 AE4E 425C |