* [PATCH]QNX6 filesystem (RO) driver @ 2012-02-01 20:41 Kai Bankett 2012-02-12 4:56 ` Al Viro 0 siblings, 1 reply; 23+ messages in thread From: Kai Bankett @ 2012-02-01 20:41 UTC (permalink / raw) To: linux-fsdevel Hi, Onhttp://a6.ontika.net/patches/patch-3.2.2-qnx6.gz you find a patch for adding QNX6 FS readonly support (against 3.2.2) to the linux kernel. (well, at least I would like to open the discussion about it ... ;)) It's the first linux kernel driver I wrote, so please be kind to me in case some of my design decisions do violate some "common practice" well known to any regular reader of this list. I am very happy to work on the source in the "right" direction, if you suggest me the direction. So, suggestions, feedback, input, testing is highly welcome! I reverse engineered - I would say - whole QNX6 Filesystem from ground up. (hexedit, from superblock identification to adressing scheme to node kinds etc.) Successfully completed writing a FS resizing application before starting work on this kernel driver. (so you can expect more than just readonly to come ...) Some sidenotes worth mentioning: - Audi MMI FS support I've included support for the Audi MMI HDD filesystem (who's driving a recent Audi with 3G or 3G+ HDD multimedia system?) So I've added a "mmi_fs" mount option to tell the driver to use the right superblock layout and -offset for mounting that "modified" or "old development state" QNX6 derivate filesystem. Not sure if a mount option is the usual approach, but it workes well - at least for me. I took the decision to make that specific driver support configurable via kernel config. - Endianness support QNX6 offers to create filesystems either little- or big endian. That's an advantage if the created filesystem later is used on an architecture that got a different endianness. I introduced some TO_CPUxx() macros and a superblock detection mechanism for detecting the FS endianness. Could not test it on a different architecture than x86 and therefore I'm unsure if it works on a different endian linux system, but from (my) theory it should do. At least on x86 it's no problem to mount a different endian QNX6 FS and read from it - that's what I've tested. If the macros are the right approach ... well, happy to receive feedback ;) I also made the endianness support configurable - just to be on the safe side. - Checksums Superblock checksums are validated. Longfilenames in a qnx6fs got a checksum in the directory inode. That checksum algorithm is also build in, but just logs to the kernel log if it detects a wrong checksum. (so it's not a hard check) mmi_fs does not have that longfilename protection, so it's switched off there. So much for now ... Kai ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-01 20:41 [PATCH]QNX6 filesystem (RO) driver Kai Bankett @ 2012-02-12 4:56 ` Al Viro 2012-02-12 22:14 ` Kai Bankett 0 siblings, 1 reply; 23+ messages in thread From: Al Viro @ 2012-02-12 4:56 UTC (permalink / raw) To: Kai Bankett; +Cc: linux-fsdevel On Wed, Feb 01, 2012 at 09:41:35PM +0100, Kai Bankett wrote: > - Endianness support > QNX6 offers to create filesystems either little- or big endian. That's > an advantage if the created filesystem later is used on an architecture > that got a different endianness. > I introduced some TO_CPUxx() macros and a superblock detection mechanism > for detecting the FS endianness. > Could not test it on a different architecture than x86 and therefore I'm > unsure if it works on a different endian linux system, but from (my) > theory it should do. > At least on x86 it's no problem to mount a different endian QNX6 FS and > read from it - that's what I've tested. > If the macros are the right approach ... well, happy to receive feedback ;) Nope, that's not the right way to do it. Don't use __leNN for that; define your own types. Take a look at e.g. fs/sysv/sysv.h - __fs{16,32} in there and functions for work with those. And duplicate that. What's more, you really want the direction of conversion spelled out; sure, it's an involution and you'll get the same code in both directions. But it's much easier to verify that conversions are right that way. sparse is useful for that, BTW. And don't use the same variable for host- and fs-endian values - it's not worth the PITA. Don't bother with struct qnx6_ptr - sparse _will_ complain about all places where you do arithmetics on __bitwise types. While we are at it, please use explicitly-sized type when you are dealing with disk block numbers. And pick unsigned one... Note that unsigned long is target-dependent; on some it's 64bit, on some 32bit. For some things that's exactly what we want, for some... qnx6_find_bits(): what's wrong with ilog2()? Or order_base_2(), if you care about the case when argument itself may be not a power of 2. Both are in linux/log2.h... sb_set_blocksize() may fail; check return value... WTH are writepage and friends doing in read-only fs driver, especially seeing that you don't seem to have anything resembling a block allocator? qnx6_iget() - what, they really don't allow named pipes/sockets/device nodes on the filesystem? If not, you can just use init_special_inode() instead of that printk+iget_failed(). _Never_ do strlen() on unsanitized on-disk data; you can't guarantee a terminating '\0' in there. + /* "" means "." ---> so paths like "/usr/lib//libc.a" work */ + if (!len && (lf->lf_fname[0] == '.') && (lf->lf_fname[1] == '\0')) + return TO_CPU32(dir->i_sb, de->de_inode); Huh? That thing is not going to get called with len == 0 and paths like that are handled in fs/namei.c just fine without forcing every fs driver to do that kind of contortions. Moreover, . and .. are _also_ handled there - ->lookup() never has to deal with those. Incidentally, don't you have the name length right in the directory entry? Or is it just an upper limit? If it's exact, it would be faster to reject mismatches without looking at the name contents (and do memcmp() in case of match). ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-12 4:56 ` Al Viro @ 2012-02-12 22:14 ` Kai Bankett 2012-02-12 22:43 ` Al Viro 0 siblings, 1 reply; 23+ messages in thread From: Kai Bankett @ 2012-02-12 22:14 UTC (permalink / raw) To: Al Viro; +Cc: linux-fsdevel Updated patch: http://a6.ontika.net/patches/patch-3.2.5-qnx6.gz Signed-off-by: Kai Bankett <chaosman@ontika.net> On 02/12/2012 05:56 AM, Al Viro wrote: > On Wed, Feb 01, 2012 at 09:41:35PM +0100, Kai Bankett wrote: > >> - Endianness support >> QNX6 offers to create filesystems either little- or big endian. That's >> an advantage if the created filesystem later is used on an architecture >> that got a different endianness. >> I introduced some TO_CPUxx() macros and a superblock detection mechanism >> for detecting the FS endianness. >> Could not test it on a different architecture than x86 and therefore I'm >> unsure if it works on a different endian linux system, but from (my) >> theory it should do. >> At least on x86 it's no problem to mount a different endian QNX6 FS and >> read from it - that's what I've tested. >> If the macros are the right approach ... well, happy to receive feedback ;) > Nope, that's not the right way to do it. Don't use __leNN for that; define > your own types. Take a look at e.g. fs/sysv/sysv.h - __fs{16,32} in there > and functions for work with those. And duplicate that. What's more, you > really want the direction of conversion spelled out; sure, it's an involution > and you'll get the same code in both directions. But it's much easier to > verify that conversions are right that way. sparse is useful for that, BTW. > And don't use the same variable for host- and fs-endian values - it's not > worth the PITA. Thanks alot. That was exactly what I was looking for when implementing that TO_CPU stuff. Looked around in some other fs drivers, but did not have a look in the sysv. You are right, using the alignment functions asymetric makes understanding the code far easier as one can directly see in which direction things are moved. At least sparse seems to be fine with my work ... > > Don't bother with struct qnx6_ptr - sparse _will_ complain about all places > where you do arithmetics on __bitwise types. > > While we are at it, please use explicitly-sized type when you are dealing > with disk block numbers. And pick unsigned one... I decided to use unsigned int. All adressing is using 32bit pointers. So this seems to make most sense to me. > > Note that unsigned long is target-dependent; on some it's 64bit, on some > 32bit. For some things that's exactly what we want, for some... Fixed. I decided to stay with unsigned int. Just a couple of blocks (12 blocks of 32bit). So, in case someone is really creating a full 32bit * blocksize fs, there could be a problem. I currently can not test how QNX would deal with that special situation - sorry. I hope that's ok ... > > qnx6_find_bits(): what's wrong with ilog2()? Or order_base_2(), if you > care about the case when argument itself may be not a power of 2. Both > are in linux/log2.h... Great. Exactly what I was looking for! Fixed. > > sb_set_blocksize() may fail; check return value... Fixed > WTH are writepage and friends doing in read-only fs driver, especially > seeing that you don't seem to have anything resembling a block allocator? Fixed Those were leftovers from the qnx4 fs driver. Maybe it would be a good idea if I create a patch for the qnx4 driver for removing those? > qnx6_iget() - what, they really don't allow named pipes/sockets/device > nodes on the filesystem? If not, you can just use init_special_inode() > instead of that printk+iget_failed(). At least so far I could not find any additional extras. I followed your advise and used init_special_inode() to get rid of that printk+stuff. > > _Never_ do strlen() on unsanitized on-disk data; you can't guarantee a > terminating '\0' in there. Fixed. Full ack. One more leftover from the qnx4 driver. However, it seems that the qnx4 driver cannot live without. (at least from a quick check, I'm not deep enough in the qnx4 fs) > + /* "" means "." ---> so paths like "/usr/lib//libc.a" work */ > + if (!len&& (lf->lf_fname[0] == '.')&& (lf->lf_fname[1] == '\0')) > + return TO_CPU32(dir->i_sb, de->de_inode); > > Huh? That thing is not going to get called with len == 0 and paths like > that are handled in fs/namei.c just fine without forcing every fs driver > to do that kind of contortions. Moreover, . and .. are _also_ handled > there - ->lookup() never has to deal with those. Removed. Leftover from qnx4 driver. In my eyes that one could well be also removed from there. > Incidentally, don't you have the name length right in the directory > entry? Or is it just an upper limit? If it's exact, it would be faster > to reject mismatches without looking at the name contents (and do memcmp() > in case of match). > Yes, I have the name length in the directory entry, but only for short filenames. For long filenames the length field in the directory entry is always 0xff. I just moved the length check up by one if-clause. Personally I don't think that moving it around further makes that much sense, as the length for short filenames is also checked before copying the filename. The way it currently is it's at least symmetrical between short und long filename handling code. I hope I got all the points and fixes right? Additionally I removed the old bitmap.c. Currently it was not used anyways. I also cleaned up the previously (at least in my eyes) ugly qnx6_super_block and mmi superblock structure. As the superblock root nodes (inode, bitmap and longfilename) all got the same structure, I've added a qnx6_root_inode structure for each root node in the superblock. Thank you very much for the extremely helpful feedback! Kai ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-12 22:14 ` Kai Bankett @ 2012-02-12 22:43 ` Al Viro 2012-02-15 2:52 ` Kai Bankett 0 siblings, 1 reply; 23+ messages in thread From: Al Viro @ 2012-02-12 22:43 UTC (permalink / raw) To: Kai Bankett; +Cc: linux-fsdevel On Sun, Feb 12, 2012 at 11:14:38PM +0100, Kai Bankett wrote: re junk removal from qnx4 - sure, just make is a separate patch. > >qnx6_iget() - what, they really don't allow named pipes/sockets/device > >nodes on the filesystem? If not, you can just use init_special_inode() > >instead of that printk+iget_failed(). > At least so far I could not find any additional extras. > I followed your advise and used init_special_inode() to get rid of > that printk+stuff. Umm... How does qnx encode device numbers for block/character devices? > Yes, I have the name length in the directory entry, but only for > short filenames. > For long filenames the length field in the directory entry is always 0xff. > I just moved the length check up by one if-clause. > Personally I don't think that moving it around further makes that > much sense, as the length for short filenames is also checked before > copying the filename. > The way it currently is it's at least symmetrical between short und > long filename handling code. > > I hope I got all the points and fixes right? A few more things: * duplicating di_block_ptr[] array seems to be pointless * qnx6_get_inode_loc(), qnx6_dir_lfile_block() and qnx6_block_map() seem to have a lot of duplicated code, at the very least. Looks like a missing helper function... Incidentally, I'd switched qnx6_get_devblock() and qnx6_check_blockptr() to __fs32 argument, along with making QNX6_PTR_UNSET (~(__fs32)0) * what is actually stored in ->de_size for long entries in case of big-endian fs? 4 bytes of de_inode - fine, as as for short ones, but then what? If it's really 32bit big-endian 0xff, it will have the first byte equal to 0, which would confuse the living hell out of your code. Or is it actually __u8 + 3 bytes of padding? Then it would be compatible with short dir entries, but conversions would be the wrong thing to do there... * I seriously suspect that you want to cook yourself a couple of unhashed in-core struct inode for Longfile and Inode ones; then get_inode_loc(), dir_lfile_block() and block_map() would become identical *and* you just might be able to use page cache instead of all that messing with buffer_heads in readdir et.al. Just do new_inode() and fill di_block_ptr/levels/i_mode/i_size and ->a_ops. iput() both in ->put_super() and that's it... For directories in pagecache see how e.g. ext2 is doing it - or minixfs, for that matter. * mmu_private is never used. Just lose it... ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-12 22:43 ` Al Viro @ 2012-02-15 2:52 ` Kai Bankett 2012-02-15 6:10 ` Al Viro 0 siblings, 1 reply; 23+ messages in thread From: Kai Bankett @ 2012-02-15 2:52 UTC (permalink / raw) To: Al Viro; +Cc: linux-fsdevel On 02/12/2012 11:43 PM, Al Viro wrote: > On Sun, Feb 12, 2012 at 11:14:38PM +0100, Kai Bankett wrote: > > re junk removal from qnx4 - sure, just make is a separate patch. > >>> qnx6_iget() - what, they really don't allow named pipes/sockets/device >>> nodes on the filesystem? If not, you can just use init_special_inode() >>> instead of that printk+iget_failed(). >> At least so far I could not find any additional extras. >> I followed your advise and used init_special_inode() to get rid of >> that printk+stuff. > Umm... How does qnx encode device numbers for block/character devices? Actually I have to check again. My statement was not meant to say "there are none", but so far I have not seen any. I did my reverse engineering on test qnx6 filesystems created with QNX. So far I have not analyzed these special cases. I will have to try to generate some. Will come back on that one after some analysis. Maybe I will have time tomorrow to dig a bit deeper into that ... Anyways, the init_special_inode() at the final end seems to be right there, so at least one point less on the list. > A few more things: > * duplicating di_block_ptr[] array seems to be pointless Again, well spotted. Just removed the "raw" thing. To me just taking the required stuff into qnx6_inode_info gives better control and more speed. > * qnx6_get_inode_loc(), qnx6_dir_lfile_block() and qnx6_block_map() > seem to have a lot of duplicated code, at the very least. Looks like > a missing helper function... Yep. With the write code it will become even more. Solution found. Just block_map() survived. > Incidentally, I'd switched qnx6_get_devblock() > and qnx6_check_blockptr() to __fs32 argument, along with making QNX6_PTR_UNSET > (~(__fs32)0) That was my exactly first approach. However, I finally decided to move away from that. My thinking was that maybe qnx6_get_devblock() in the future may be called from with a non-__fs32 value holding function. Also, If I see it right, it won't save any cpu cycles + getting to a "uniformed" endianess directly at the fs address pointer reading functions makes the endianess border very clear when reading the source. Feedback very welcome. Easy to change, if you think __fs32 arguments make more sense. > * what is actually stored in ->de_size for long entries in case > of big-endian fs? 4 bytes of de_inode - fine, as as for short ones, but > then what? If it's really 32bit big-endian 0xff, it will have the first byte > equal to 0, which would confuse the living hell out of your code. Or is > it actually __u8 + 3 bytes of padding? Then it would be compatible with > short dir entries, but conversions would be the wrong thing to do there... Checked against a hexdump. The de_size for long filename direntries is just a single byte. Corrected - thanks. > * I seriously suspect that you want to cook yourself a couple of > unhashed in-core struct inode for Longfile and Inode ones; then get_inode_loc(), > dir_lfile_block() and block_map() would become identical *and* you just might > be able to use page cache instead of all that messing with buffer_heads in > readdir et.al. Just do new_inode() and fill di_block_ptr/levels/i_mode/i_size > and ->a_ops. iput() both in ->put_super() and that's it... For directories > in pagecache see how e.g. ext2 is doing it - or minixfs, for that matter. I had a look at that point. After successfully switching find_enty() to pagemap I spend quite some time on switching long_match() to pagemap cache. At the end I gave up. Things just became too complicated. Far more complicated than bh stuff. At least if I get no further clue on how to manage the different pagesizes efficient - compared to the very efficient bh code - I cannot see light at the end of the tunnel. For long Filenames, the Filename always is stored in a seperate block. Whatever I tried, I did not get the pagemap code as efficient, as it abstracts from blocksize. (that's where it got it's stength - IHMO) Ok, I could save the block adressing steps, but I will add so many other steps on the way ... I am really unsure if that pays off at the end. At least code complexity rises extremely. Extremley happy if you could give me some additional guidance an that point. > * mmu_private is never used. Just lose it... > It's history. Updated Patch: http://a6.ontika.net/patches/patch-3.2.5-qnx6-v2.gz Signed-off-by: Kai Bankett <chaosman@ontika.net> ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-15 2:52 ` Kai Bankett @ 2012-02-15 6:10 ` Al Viro 2012-02-15 6:14 ` Al Viro 2012-02-15 6:47 ` Al Viro 0 siblings, 2 replies; 23+ messages in thread From: Al Viro @ 2012-02-15 6:10 UTC (permalink / raw) To: Kai Bankett; +Cc: linux-fsdevel On Wed, Feb 15, 2012 at 03:52:01AM +0100, Kai Bankett wrote: > After successfully switching find_enty() to pagemap I spend quite > some time on switching long_match() to pagemap cache. > At the end I gave up. Things just became too complicated. Not if you have a separate struct inode for /.longfile - then it's simply read_cache_page() + kmap(). > Far more complicated than bh stuff. > At least if I get no further clue on how to manage the different > pagesizes efficient - compared to the very efficient bh code - I > cannot see light at the end of the tunnel. > For long Filenames, the Filename always is stored in a seperate > block. Whatever I tried, I did not get the pagemap code as > efficient, as it abstracts from blocksize. (that's where it got it's > stength - IHMO) > Ok, I could save the block adressing steps, but I will add so many > other steps on the way ... I am really unsure if that pays off at > the end. At least code complexity rises extremely. You do realize that buffer cache does _not_ exist separately from pagecache, right? It's just the pagecache of underlying block device; see __find_get_block_slow() for what really happens behind the scene. The difference between page and buffer cache is not in abstracting the size away; that's trivial. The real difference is that one is that between virtually-indexed and physically-indexed caches. Essentially, qnx6_get_block() is address translation for that sucker. And buffer_head is just a TLB entry. Think of struct address_space as MMU context; we have one for identity mapping of block device and what you are doing is manually asking for address translation and feeding the resulting physical address into that identity mapped context. You could use the address spaces of directory and /.longfiles resp. instead and let the normal logics to take care of things. Moreover, you get address translation cached that way - no need to recalculate physical block addresses every time. That map_bh() in qnx6_get_block() is there exactly for that reason... Block size is not an issue, really - readdir() should just map pages one by one and loop over entries in those; when it hits longname, it would just do read_cache_page() on longfiles inode and look into it; that's all. I.e. you need something like struct qnx6_long_filename *qnx6_longname(sbi, de, p) { u32 s = fs32_to_cpu(sbi, de->de_long_inode); /* in 512-byte units */ u32 n = s >> (PAGE_CACHE_SHIFT - 9); /* in pages */ u32 offs = (s << 9) & ~PAGE_CACHE_MASK; /* within page */ struct qnx6_long_filename *lf; struct address_space *mapping = sbi->longfiles->i_mapping; struct page *page = read_mapping_page(mapping, n, NULL); if (IS_ERR(page)) return ERR_CAST(page); kmap(*p = page); return (struct qnx6_long_filename *)(page_address(page) + offs); } and have readdir do lf = qnx6_longname(sbi, de, &page); if (IS_ERR(lf)) { err = PTR_ERR(lf); goto out; } if (filldir(....) < 0) { put_page(page); err = 0; goto out; } put_page(page); where put_page() is exactly what we do in e.g. ext2_put_page() - kunmap() followed by page_cache_release(). And the same sucker would be used by qnx6_find_entry(), of course. BTW, after looking at your readdir() - you have a serious bug there. It bloody ignores ->f_pos - it *always* starts reading from the beginning of directory. Try to do ls on really big directory and you'll have trouble - beginning of directory returned several times. It will stop eventually, since you do increment ->f_pos, but... Another bug there: you leak lf_bh on "too long longname" failure exit... Looking at namei.c: you know, (void*)((char*)de + QNX6_DIR_ENTRY_SIZE) is a really weird way to spell de + 1, seeing that actual argument is always qnx6_dirent *... I think you are overdesigning things; unlike ext2, your entries are fixed-sized and that kills most of the complexity in there. So you don't need to bother with last_byte() - just do an analog that would return the index of _entry_ within page; PAGE_CACHE_SIZE / <entry size> for all pages but the last one and (i_size & ~PAGE_CACHE_MASK) / <entry size> for the last page. And just have something like for ( ; n < npages; n++, start = 0) { int limit = last_entry(inode, n); <get and map page> de = page_address(page); for (i = start, de += start; i < limit; i++, de++) { /* handle this entry */ } } for your loops over directory contents, both in readdir and find_entry. One more thing: why do you bother passing inodebits separately to block_map()? You are guaranteed that block_map(..., n, ..., inodebits) is equal to block_map(..., n >> inodebits, ..., 0) It's really not hard to prove - introduce __bitdelta and __levelsub and maintain them so that levelsub == __levelsub << inodebits bitdelta == __bitdelta + inodebits all the time. Then observe that (no - levelsub) >> bitdelta is equal to (no - (__levelsub << inodebits)) >> (__bitdelta + inodebits), i.e. to ((no >> inodebits) - __levelsub) >> __bitdelta. Now you can lose levelsub - it's not used anymore. And after _that_ neither is __bitdelta. And after that you can rename __levelsub and __bitdelta to levelsub and bitdelta resp. and see that you have reproduced the original function with original uses of inodebits replaced with 0 and all instances of no with no >> inodebits. The only exception is that debugging printk ("no too large" case) actually prints what it claims to print ;-) Allocation of private inodes is easy - static struct inode *qnx6_private_inode(struct super_block *s, struct qnx6_root_node *p) { struct inode *inode = new_inode(s); if (inode) { struct qnx6_inode_info *ei = QNX6_I(inode); struct qnx6_sb_info *sbi = QNX6_SB(s); inode->i_size = fs64_to_cpu(sbi, p->size); memcpy(ei->di_block_ptr, p->ptr, sizeof(p->ptr)); ei->di_filelevels = p->levels; inode->i_mode = S_IFREG | S_IRUSR; /* that will do */ inode->i_mapping->a_ops = &qnx6_aops; } return inode; } and that's it. With that (and inodebits killed) you can turn block_map into qnx6_block_map(inode, block_nr) - superblock will be inode->i_sb... ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-15 6:10 ` Al Viro @ 2012-02-15 6:14 ` Al Viro 2012-02-15 6:47 ` Al Viro 1 sibling, 0 replies; 23+ messages in thread From: Al Viro @ 2012-02-15 6:14 UTC (permalink / raw) To: Kai Bankett; +Cc: linux-fsdevel On Wed, Feb 15, 2012 at 06:10:12AM +0000, Al Viro wrote: > ((no >> inodebits) - __levelsub) >> __bitdelta. Now you can lose levelsub - > it's not used anymore. And after _that_ neither is __bitdelta. And after ^^^^^^^^^^ Sorry about the braino; that would be "neither is bitdelta", of course... ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-15 6:10 ` Al Viro 2012-02-15 6:14 ` Al Viro @ 2012-02-15 6:47 ` Al Viro 2012-02-15 7:11 ` Al Viro 1 sibling, 1 reply; 23+ messages in thread From: Al Viro @ 2012-02-15 6:47 UTC (permalink / raw) To: Kai Bankett; +Cc: linux-fsdevel On Wed, Feb 15, 2012 at 06:10:12AM +0000, Al Viro wrote: [snip] OK, I've dumped something that compiles in #qnx6 in vfs.git; I don't promise anything beyond that - consider that as slightly more elaborate variant of the previous mail. At that stage I would definitely prefer to see fixes, etc. *folded* into the patch before it gets merged, so do not treat that branch as anything other than convenient (for me) way to post a series of incrementals. Oh, and the final result will obviously need s-o-b by Kai + sane commit message, etc. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-15 6:47 ` Al Viro @ 2012-02-15 7:11 ` Al Viro 2012-02-15 7:57 ` Al Viro 0 siblings, 1 reply; 23+ messages in thread From: Al Viro @ 2012-02-15 7:11 UTC (permalink / raw) To: Kai Bankett; +Cc: linux-fsdevel On Wed, Feb 15, 2012 at 06:47:28AM +0000, Al Viro wrote: > On Wed, Feb 15, 2012 at 06:10:12AM +0000, Al Viro wrote: > > [snip] > > OK, I've dumped something that compiles in #qnx6 in vfs.git; I don't promise > anything beyond that - consider that as slightly more elaborate variant of > the previous mail. At that stage I would definitely prefer to see fixes, > etc. *folded* into the patch before it gets merged, so do not treat that > branch as anything other than convenient (for me) way to post a series of > incrementals. > > Oh, and the final result will obviously need s-o-b by Kai + sane commit > message, etc. If you prefer to test on top of -stable, just copy d_make_root() from current mainline into fs/dcache.c and export it - that's the only dependency on the stuff from the last merge window. Or just open-code the sucker into your fill_super... One more thing - unless I'm misreading the code it looks like your ->sb becomes a dangling pointer once fill_super finishes and ->statfs() is dereferencing it... ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-15 7:11 ` Al Viro @ 2012-02-15 7:57 ` Al Viro 2012-02-15 14:40 ` Al Viro 0 siblings, 1 reply; 23+ messages in thread From: Al Viro @ 2012-02-15 7:57 UTC (permalink / raw) To: Kai Bankett; +Cc: linux-fsdevel On Wed, Feb 15, 2012 at 07:11:19AM +0000, Al Viro wrote: > One more thing - unless I'm misreading the code it looks like your ->sb becomes > a dangling pointer once fill_super finishes and ->statfs() is dereferencing > it... BTW, what happens if root directory grows to more than one level of pointers? AFAICS, qnx6_checkroot() assumes that it won't happen... And why not do that after getting the root inode, anyway? ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-15 7:57 ` Al Viro @ 2012-02-15 14:40 ` Al Viro 2012-02-15 16:27 ` Kai Bankett 2012-02-16 10:00 ` Al Viro 0 siblings, 2 replies; 23+ messages in thread From: Al Viro @ 2012-02-15 14:40 UTC (permalink / raw) To: Kai Bankett; +Cc: linux-fsdevel On Wed, Feb 15, 2012 at 07:57:50AM +0000, Al Viro wrote: > On Wed, Feb 15, 2012 at 07:11:19AM +0000, Al Viro wrote: > > > One more thing - unless I'm misreading the code it looks like your ->sb becomes > > a dangling pointer once fill_super finishes and ->statfs() is dereferencing > > it... > > BTW, what happens if root directory grows to more than one level of > pointers? AFAICS, qnx6_checkroot() assumes that it won't happen... > And why not do that after getting the root inode, anyway? Ho-hum... I've added conversion of qnx6_iget() to pagecache and checkroot move past getting root; result: * qnx6_bread/qnx6_getblk are gone * qnx6_block_map() has only one caller left * s_inodebits/s_dirent_blk/s_inodes_blk gone s_ptrbits remains, of course, but that one has to survive - it determines the way indirect blocks' tree is branched. Remaining issues I see: * sbi->sb dangling pointer (those brelse() in success case of fill_super()). Probably only one of them needs to be dropped at that point, leaving the other in sbi->sb_bh to be dropped by put_super * sb_set_blocksize() can and will invalidate buffer_heads of the wrong size. qnx6_fill_super() probably needs to redo sb_bread() on the primary superblock after it has done the second sb_set_blocksize(). * readdir handling of errors (especially in longname case) needs to be done better. Other than that... this stuff could use some tidying up, but that's not a big deal. I really wonder if these config options are worthwhile - might be better to stick endianness and mmi to y unconditionally. And of course all those incrementals are completely untested and might very well br broken. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-15 14:40 ` Al Viro @ 2012-02-15 16:27 ` Kai Bankett 2012-02-15 21:35 ` Al Viro 2012-02-16 10:00 ` Al Viro 1 sibling, 1 reply; 23+ messages in thread From: Kai Bankett @ 2012-02-15 16:27 UTC (permalink / raw) To: Al Viro; +Cc: Kai Bankett, linux-fsdevel > On Wed, Feb 15, 2012 at 07:57:50AM +0000, Al Viro wrote: >> On Wed, Feb 15, 2012 at 07:11:19AM +0000, Al Viro wrote: >> >> > One more thing - unless I'm misreading the code it looks like your >> ->sb becomes >> > a dangling pointer once fill_super finishes and ->statfs() is >> dereferencing >> > it... >> >> BTW, what happens if root directory grows to more than one level of >> pointers? AFAICS, qnx6_checkroot() assumes that it won't happen... >> And why not do that after getting the root inode, anyway? > > Ho-hum... I've added conversion of qnx6_iget() to pagecache and > checkroot move past getting root; result: > * qnx6_bread/qnx6_getblk are gone > * qnx6_block_map() has only one caller left > * s_inodebits/s_dirent_blk/s_inodes_blk gone > s_ptrbits remains, of course, but that one has to survive - it determines > the way indirect blocks' tree is branched. > > Remaining issues I see: > * sbi->sb dangling pointer (those brelse() in success case of > fill_super()). Probably only one of them needs to be dropped at that > point, leaving the other in sbi->sb_bh to be dropped by put_super > * sb_set_blocksize() can and will invalidate buffer_heads of the > wrong size. qnx6_fill_super() probably needs to redo sb_bread() on the > primary superblock after it has done the second sb_set_blocksize(). > * readdir handling of errors (especially in longname case) needs > to be done better. > > Other than that... this stuff could use some tidying up, but that's not > a big deal. I really wonder if these config options are worthwhile - > might be better to stick endianness and mmi to y unconditionally. And > of course all those incrementals are completely untested and might very > well br broken. I've fixed sbi->sb and sb_set_blocksize(). I also fixed inodebits thing. (stupid me ... ;)) Missing brelse()'s in dir_longfilename fixed. (together with error handling) Where do I find your vfs.git tree? Cloned git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git, but could not find it there. If I got it right, you would like to always receive complete patches - right? ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-15 16:27 ` Kai Bankett @ 2012-02-15 21:35 ` Al Viro 0 siblings, 0 replies; 23+ messages in thread From: Al Viro @ 2012-02-15 21:35 UTC (permalink / raw) To: Kai Bankett; +Cc: linux-fsdevel On Wed, Feb 15, 2012 at 05:27:42PM +0100, Kai Bankett wrote: > Where do I find your vfs.git tree? Cloned > git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs.git, but could not > find it there. Um? It is there, the branch is called qnx6... FWIW, its head is commit aeee926a72fad9cc6d021c20900dd919769d2fe5; if something's fishy with branches, check if that commit is there. > If I got it right, you would like to always receive complete patches - right? Until it's in the mainline - yes. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-15 14:40 ` Al Viro 2012-02-15 16:27 ` Kai Bankett @ 2012-02-16 10:00 ` Al Viro 2012-02-17 15:06 ` Kai Bankett 1 sibling, 1 reply; 23+ messages in thread From: Al Viro @ 2012-02-16 10:00 UTC (permalink / raw) To: Kai Bankett; +Cc: linux-fsdevel On Wed, Feb 15, 2012 at 02:40:37PM +0000, Al Viro wrote: > Other than that... this stuff could use some tidying up, but that's not > a big deal. I really wonder if these config options are worthwhile - > might be better to stick endianness and mmi to y unconditionally. And > of course all those incrementals are completely untested and might very > well br broken. FWIW, having looked at that code again, I'm definitely in favour of dumping the ENDIANNESS and MMI config options; the latter is not time-critical at all (of anything even remotely hot it only affects the checksum verification for longnames on readdir *and* its only effect is possible short-circuiting a relatively long calculation - I've just spotted and fixed a braino in that ifdef from hell, BTW). And the former... I would be _very_ surprised if disabling it would be a visible win on any workloads. BTW, reporting non-options in ->show_options() is probably a bad idea; sure, you end up ignoring options in your ->mount(), so it won't confuse any userland scripts too badly, but... ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-16 10:00 ` Al Viro @ 2012-02-17 15:06 ` Kai Bankett 2012-02-17 16:20 ` Al Viro 0 siblings, 1 reply; 23+ messages in thread From: Kai Bankett @ 2012-02-17 15:06 UTC (permalink / raw) To: Al Viro; +Cc: linux-fsdevel > On Wed, Feb 15, 2012 at 02:40:37PM +0000, Al Viro wrote: > > FWIW, having looked at that code again, I'm definitely in favour of > dumping > the ENDIANNESS and MMI config options; the latter is not time-critical at > all > - removed both options The MMI option was more meant to make that specific extra functionality more present to the kernel (compile) user. - removed the endian_swap mount option (the reported option) I agree it shall be just sufficient to silently mount the fs. Different endianness is not of any big importance for using it. Sounds to me more like something for any userland tools if someone desires more information about low-level fs-structure stuff. - fixed a page adressing bug in long_filename() Long filename blocks are not always 512 bytes. Yes, the longfilename structure itself is limited to 512bytes, but that's a result of the smallest supported blocksize to be 512 bytes. Longfile limit is 510 + 2 bytes length field = longfile record. However, in a 1k blocksize filesystem, it will still eat up a whole block. - fixed broken mmi superblock handling, broken by the switch to pagemap, root_node etc. stuff ;) - Documentation file added That should give a quick overview on how the qnx6fs bits and pieces fit in the whole context. Feedback very welcome! (as always) I hope that someone with coding skills after reading that introduction, should be able to fiddle out the rest by reading the driver source. - Lost sb fixed Active sb-bh is now released in put_super() - not before. - dir_longfilename() return codes cleaned up - qnx6fs.h cleaned up - switched from for-loops to memcpy()'s in super_mmi() and iput() to copy data from one struct to the other - became friend with git and created the attached patch with it (hope the commit format is now proper) + wanted to say "Thank you!" for the absolut fantastic work you've done on the pagemap stuff! Patch here: http://a6.ontika.net/patches/0001-fs-initial-qnx6fs-addition.patch.gz It's against vfs.fs git tree. Kai ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-17 15:06 ` Kai Bankett @ 2012-02-17 16:20 ` Al Viro 2012-02-17 17:53 ` Kai Bankett 0 siblings, 1 reply; 23+ messages in thread From: Al Viro @ 2012-02-17 16:20 UTC (permalink / raw) To: Kai Bankett; +Cc: linux-fsdevel On Fri, Feb 17, 2012 at 04:06:19PM +0100, Kai Bankett wrote: > - fixed broken mmi superblock handling, broken by the switch to pagemap, > root_node etc. stuff ;) + bh1 = sb_bread(s, s->s_blocksize); in there looks rather fishy... qnx6_lfile_checksum() doesn't use superblock argument anymore (used to be used for conversion, but since you are passing length from the caller...) qnx6_longname() - since you are passing superblock anyway, sbi is redundant... + inode->i_blocks = (inode->i_size >> sb->s_blocksize_bits) + << (sb->s_blocksize_bits - 9); looks too convoluted and if you really want to be pedantic, not 100% correct - you end up rounding it down, not up. FWIW, I would probably simply do (inode->i_size + 511) >> 9 and devil take the rounding effects on big block sizes; it's an approximation anyway, since you are not counting indirect blocks... Other than that (and assuming it survives your testing), I'm fine with that variant. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-17 16:20 ` Al Viro @ 2012-02-17 17:53 ` Kai Bankett 2012-02-17 18:35 ` Al Viro 0 siblings, 1 reply; 23+ messages in thread From: Kai Bankett @ 2012-02-17 17:53 UTC (permalink / raw) To: Al Viro; +Cc: Kai Bankett, linux-fsdevel > On Fri, Feb 17, 2012 at 04:06:19PM +0100, Kai Bankett wrote: > > + bh1 = sb_bread(s, s->s_blocksize); > in there looks rather fishy... Fixed. > > qnx6_lfile_checksum() doesn't use superblock argument anymore (used to > be used for conversion, but since you are passing length from the > caller...) > > qnx6_longname() - since you are passing superblock anyway, sbi is > redundant... Removed. > > FWIW, I would probably simply do (inode->i_size + 511) >> 9 and devil > take the rounding effects on big block sizes; it's an approximation > anyway, since you are not counting indirect blocks... > Changed. Fair enough and safes cpu cycles. > Other than that (and assuming it survives your testing), I'm fine with > that variant. At least no problems with all my test images. Just ran a complete test (file reads, dir(s), filepermissions, symlink, hardlink, longfilenames, longdirectories etc.) over (mmi/be/le/1k/2k blocksize images). http://a6.ontika.net/patches/0001-fs-initial-qnx6fs-addition.patch.gz ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-17 17:53 ` Kai Bankett @ 2012-02-17 18:35 ` Al Viro 2012-02-17 18:53 ` Al Viro 0 siblings, 1 reply; 23+ messages in thread From: Al Viro @ 2012-02-17 18:35 UTC (permalink / raw) To: Kai Bankett; +Cc: linux-fsdevel On Fri, Feb 17, 2012 at 06:53:52PM +0100, Kai Bankett wrote: > > Other than that (and assuming it survives your testing), I'm fine with > > that variant. > > At least no problems with all my test images. Just ran a complete test > (file reads, dir(s), filepermissions, symlink, hardlink, longfilenames, > longdirectories etc.) over (mmi/be/le/1k/2k blocksize images). > > http://a6.ontika.net/patches/0001-fs-initial-qnx6fs-addition.patch.gz Hmmm... + if (len == de->de_size) + /* normal filename */ + ino = qnx6_match(s, len, name, de); + if (ino) + goto found; + else if ((de->de_size == 0xff) && Actually, gcc ought to have screamed at that. Note that "else" here matches the second "if", not the first one. And you are not guaranteed that ino has _ever_ been assigned anything; that comparison is deep in nasal daemon country... ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-17 18:35 ` Al Viro @ 2012-02-17 18:53 ` Al Viro 2012-02-17 21:38 ` Kai Bankett 0 siblings, 1 reply; 23+ messages in thread From: Al Viro @ 2012-02-17 18:53 UTC (permalink / raw) To: Kai Bankett; +Cc: linux-fsdevel On Fri, Feb 17, 2012 at 06:35:49PM +0000, Al Viro wrote: > On Fri, Feb 17, 2012 at 06:53:52PM +0100, Kai Bankett wrote: > > > Other than that (and assuming it survives your testing), I'm fine with > > > that variant. > > > > At least no problems with all my test images. Just ran a complete test > > (file reads, dir(s), filepermissions, symlink, hardlink, longfilenames, > > longdirectories etc.) over (mmi/be/le/1k/2k blocksize images). > > > > http://a6.ontika.net/patches/0001-fs-initial-qnx6fs-addition.patch.gz > > Hmmm... > > + if (len == de->de_size) > + /* normal filename */ > + ino = qnx6_match(s, len, name, de); > + if (ino) > + goto found; > + else if ((de->de_size == 0xff) && > > Actually, gcc ought to have screamed at that. Note that "else" here matches > the second "if", not the first one. And you are not guaranteed that > ino has _ever_ been assigned anything; that comparison is deep in nasal > daemon country... And in the same area, what happens if you have a long entry *and* ask for lookup for name that is exactly 255 bytes long? AFAICS, qnx6_match() will proceed to do memcmp() on 255 bytes - note that you pass it "len", not "thislen". Might (at least in theory) run out of page before it stops... Something like if (len <= QNX6_SHORT_NAME_MAX) { if (de->de_size != len) continue; <qnx6_match> } else { if (de->de_size != 0xff) continue; <qnx6_long_match> } would probably make sense... Wait. You've mentioned something about special characters in names forcing a longname entry even for short ones. Could you elaborate? ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-17 18:53 ` Al Viro @ 2012-02-17 21:38 ` Kai Bankett 2012-02-21 22:04 ` Al Viro 0 siblings, 1 reply; 23+ messages in thread From: Kai Bankett @ 2012-02-17 21:38 UTC (permalink / raw) To: Al Viro; +Cc: linux-fsdevel Am 02/17/2012 07:53 PM, schrieb Al Viro: >> Hmmm... >> >> + if (len == de->de_size) >> + /* normal filename */ >> + ino = qnx6_match(s, len, name, de); >> + if (ino) >> + goto found; >> + else if ((de->de_size == 0xff)&& >> >> Actually, gcc ought to have screamed at that. Note that "else" here matches >> the second "if", not the first one. And you are not guaranteed that >> ino has _ever_ been assigned anything; that comparison is deep in nasal >> daemon country... At least code was robust enough to deal with it ;) I guess ino was set to 0 anyways by compiler? At least it does not seem to have been sort of random. Otherwise testing would have shown strange effects - right? However, fixed. I just re-added the braces. At some point in time there were some ... seem they got lost somewhere in mod space. > And in the same area, what happens if you have a long entry *and* ask for > lookup for name that is exactly 255 bytes long? AFAICS, qnx6_match() will > proceed to do memcmp() on 255 bytes - note that you pass it "len", not > "thislen". Might (at least in theory) run out of page before it stops...( > > Something like > if (len<= QNX6_SHORT_NAME_MAX) { > if (de->de_size != len) > continue; > <qnx6_match> > } else { > if (de->de_size != 0xff) > continue; > <qnx6_long_match> > } > would probably make sense... Wait. You've mentioned something about > special characters in names forcing a longname entry even for short > ones. Could you elaborate? I just checked, but could not get qnx to split a short name in a long filename node. So we can bury that one ... also does not really make sense to design it that way. To me the length field clearly is the master. For short filenames always de_size < 0xff and equal the filename length. If de_size == 0xff, filename length has to be taken out of lf node. The interesting question is: What is in between? To me, the answer is: File-system error land. Just re-pull the patch and take a look ... http://a6.ontika.net/patches/0001-fs-initial-qnx6fs-addition.patch.gz BTW, I had a look at character and block device files. QNX drivers just dynamically add them to /dev if a driver offers any. There seems to be no way to create or move any by hand + they are not written to the fs. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-17 21:38 ` Kai Bankett @ 2012-02-21 22:04 ` Al Viro 2012-02-21 22:09 ` Al Viro 0 siblings, 1 reply; 23+ messages in thread From: Al Viro @ 2012-02-21 22:04 UTC (permalink / raw) To: Kai Bankett; +Cc: linux-fsdevel On Fri, Feb 17, 2012 at 10:38:12PM +0100, Kai Bankett wrote: > At least code was robust enough to deal with it ;) > I guess ino was set to 0 anyways by compiler? At least it does not > seem to have been sort of random. Nope. Uninitialized is uninitialized - in reality it's "whatever happens to be in that word on stack", in theory it's "compiler has every right to do _anything_ to reads from it". Nasal daemon country... > Otherwise testing would have shown strange effects - right? Depends. > http://a6.ontika.net/patches/0001-fs-initial-qnx6fs-addition.patch.gz Still a problem with memcmp() use in qnx6_long_match() - suppose you've got lf_size (on corrupt fs) set to 3Kb. With 2Kb blocks and odd ->de_long_inode. You are doing a lookup for 3Kb name. What we get is qnx6_longname() returning a pointer 2Kb into 4Kb page. And qnx6_long_match() proceeding to do memcmp() on 3Kb starting from that point. Oops - literally. What we need to do is either * silently return 0 on thislen > QNX6_LONG_NAME_MAX, or * return 0 and yell about corrupt /longfiles, or * have qnx6_lookup() check that len <= QNX6_LONG_NAME_MAX and return ERR_PTR(-ENAMETOOLONG) if it isn't. And lose the thislen check completely. I'd probably go for the last variant; it's consistent with what other filesystems are doing and it would avoid mess if we ever try to do r/w variant. BTW, thislen check in qnx6_match() is also pointless - we'd already checked that in caller. Otherwise it would be wrong in the same way as for long ones... ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-21 22:04 ` Al Viro @ 2012-02-21 22:09 ` Al Viro 2012-02-22 11:58 ` Kai Bankett 0 siblings, 1 reply; 23+ messages in thread From: Al Viro @ 2012-02-21 22:09 UTC (permalink / raw) To: Kai Bankett; +Cc: linux-fsdevel On Tue, Feb 21, 2012 at 10:04:55PM +0000, Al Viro wrote: > What we need to do is either > * silently return 0 on thislen > QNX6_LONG_NAME_MAX, or > * return 0 and yell about corrupt /longfiles, or > * have qnx6_lookup() check that len <= QNX6_LONG_NAME_MAX and > return ERR_PTR(-ENAMETOOLONG) if it isn't. And lose the thislen check > completely. > > I'd probably go for the last variant; it's consistent with what other > filesystems are doing and it would avoid mess if we ever try to do > r/w variant. Oh, wait - you already are doing that in ->lookup()? Then it's definitely "let's lose thislen checks in qnx6_long_match() and qnx6_match()". Dead code is dead code... Pushed with that correction. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH]QNX6 filesystem (RO) driver 2012-02-21 22:09 ` Al Viro @ 2012-02-22 11:58 ` Kai Bankett 0 siblings, 0 replies; 23+ messages in thread From: Kai Bankett @ 2012-02-22 11:58 UTC (permalink / raw) To: Al Viro; +Cc: linux-fsdevel > On Tue, Feb 21, 2012 at 10:04:55PM +0000, Al Viro wrote: >> What we need to do is either >> * silently return 0 on thislen > QNX6_LONG_NAME_MAX, or >> * return 0 and yell about corrupt /longfiles, or >> * have qnx6_lookup() check that len <= QNX6_LONG_NAME_MAX and >> return ERR_PTR(-ENAMETOOLONG) if it isn't. And lose the thislen check >> completely. >> >> I'd probably go for the last variant; it's consistent with what other >> filesystems are doing and it would avoid mess if we ever try to do >> r/w variant. > > Oh, wait - you already are doing that in ->lookup()? Then it's definitely > "let's lose thislen checks in qnx6_long_match() and qnx6_match()". Dead > code is dead code... > Correct - dead code. Removed in the patch... (same location as before) A r/o driver to me always looks like "giving up half the way". (ok, maybe just one third the way) Well, I'm sure I've collected enough fs information for impelemting r/w. However, doing that still means a whole bunch of work. Already started with some parts, but that was still completely based on buffer_head stuff. My suggestion would be to do it in smaller incremental steps. (e.g. start with Bitmap handling stuff and then move on) At least I spent a lot of time on analyzing and understanding how that bitmap system area is used any calculated. I'd prefer to dump it soon out of my brain to get freed up some space ;) It would be very helpful to get some ideas on how to implement that failsafe stuff properly. (QNX calls it CoW - Copy on Write) I've described it's basic mechanics in qnx6.txt. I'm just - let's carefully say - clueless on how to approach that beast properly. Maybe first just implement simple write support (just on the active superblock) and then later - if still not tired - extend the failsafe support. Kai ^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2012-02-22 11:58 UTC | newest] Thread overview: 23+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-02-01 20:41 [PATCH]QNX6 filesystem (RO) driver Kai Bankett 2012-02-12 4:56 ` Al Viro 2012-02-12 22:14 ` Kai Bankett 2012-02-12 22:43 ` Al Viro 2012-02-15 2:52 ` Kai Bankett 2012-02-15 6:10 ` Al Viro 2012-02-15 6:14 ` Al Viro 2012-02-15 6:47 ` Al Viro 2012-02-15 7:11 ` Al Viro 2012-02-15 7:57 ` Al Viro 2012-02-15 14:40 ` Al Viro 2012-02-15 16:27 ` Kai Bankett 2012-02-15 21:35 ` Al Viro 2012-02-16 10:00 ` Al Viro 2012-02-17 15:06 ` Kai Bankett 2012-02-17 16:20 ` Al Viro 2012-02-17 17:53 ` Kai Bankett 2012-02-17 18:35 ` Al Viro 2012-02-17 18:53 ` Al Viro 2012-02-17 21:38 ` Kai Bankett 2012-02-21 22:04 ` Al Viro 2012-02-21 22:09 ` Al Viro 2012-02-22 11:58 ` Kai Bankett
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).