Thread (7 messages) 7 messages, 2 authors, 2012-11-02

Re: hfsplus BUG(), kmap and journalling.

From: Vyacheslav Dubeyko <slava@dubeyko.com>
Date: 2012-10-30 11:45:57

Hi Hin-Tak,

On Tue, 2012-10-30 at 08:24 +0000, Hin-Tak Leung wrote:
[snip]
quoted
Usually, hfs_bnode_read() is called after searching of some object in b-tree.
It needs to initialize struct hfsplus_find_data by means of hfs_find_init()
before any search and operations inside b-tree node. And then, it needs to
call hfs_find_exit(). The hfsplus_find_data structure contains mutex that it
locks of b-tree during hfs_find_init() call and unlock during
hfs_find_exit(). And, usually, hfs_bnode_read() is placed
between hfs_find_init()/hfs_find_exit() calls. So, as I can understand, your
mutex inside hfs_bnode_read() is useless. But, maybe, not all hfs_bnode_read()
calls are placed inside hfs_find_init()/hfs_find_exit() calls. It needs to check.
quoted
I can't clear understand about what simultaneous kmap()'s you are talking.
As
I can see, usually, (especially, in the case of hfs_bnode_read()) pairs of
kmap()/kunmap() localize in small parts of code and I expect that it executes
fast. Do I misunderstand something?
Perhaps it is easier to show some code for the discussion. The attached 
serializes kmap in hfs_bnode_read() . This makes the driver works more reliably, 
somehow. In real usage, multiple instances of hfs_bnode_read() do get invoked in 
parallel. I assume that is because of both SMP as well as file system access 
itself are parallelized at various level - e.g. recursion like running du 
probably invokes a few instances of readdir/getdents?
As I understand, readdir/getdents syscalls call hfsplus_readdir()
method, as a result. It is called hfs_find_init() in the begin of
hfsplus_readdir() (as in hfsplus_lookup() also). The hfs_find_init()
method locks the mutex on the whole catalog tree. Then, it can be called
hfs_bnode_read() and other methods that operates by b-tree content in
the environment of locked b-tree. And, finally, it is called
hfs_find_exit() method at the end of hfsplus_readdir(). The
hfs_find_exit() method unlock the mutex. So, even if you have several
threads with readdir/getdents calls then only one thread will operate
with the b-tree inside hfsplus_readdir() operation.

What serialized kmap in hfs_bnode_read() do you mean? How is it possible
to have such situation for locked b-tree?

quoted
quoted
I tried swapping those by kmap_atomic()/kunmap_atomic() (beware the arguments are different for unmap) - but the kernel immediately warned that *_atom() code is used where code can sleep.
Could you describe in more details about warning?
In hfs_bnode_read(), I tried changing kmap/kunmap to 
kmap_atomic()/kunmap_atomic() . (Sorry I deleted the change since it does not 
work - but it shouldn't be too difficult to redo since it is just changing two 
lines in hfs_bnode_read()) - then I get many:

BUG: scheduling while atomic: ...
It is strange. I need to check it.

[snip]
BTW, I think I see another bug - unrelated to journalling - in the current hfs+ 
code: folder counts are not updated correctly. It seems that hfs+ folders have 
recursive folder counts (i.e. a parent dir knows how many sub-dir's it has, 
without needing to recurse down), and this is currently not updated correctly. 
One way of demo'ing this is to:

    (make sure fs is fsck-clean ; mount)

    cp -ipr somedir_with_some_files/ some_hfs+_place/someplace_inside/

    (umount; run fsck_hfs again, now it complains about folder counts)

The actual message looks a it like this:

** Checking catalog hierarchy.
    HasFolderCount flag needs to be set (id = 393055)
    (It should be 0x10 instead of 0)
    Incorrect folder count in a directory (id = 205)
    (It should be 18 instead of 17)
Sorry, I can't reproduce this issue. I tried to reproduce as you
described. Maybe, do you miss something?

With the best regards,
Vyacheslav Dubeyko.

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help