From: Hans Reiser It addresses all major lkml complains: vfs cleanup, kcond removal, type safe list removal, etc. It is probably possible to do more cleanups abd they are in progress. But lets send something now to get new list of things to fix. This patch has decent stability. CC: vs Signed-off-by: Andrew Morton --- dev/null |10333 -------------------------- fs/reiser4/Kconfig | 2 fs/reiser4/Makefile | 35 fs/reiser4/as_ops.c | 417 - fs/reiser4/block_alloc.c | 295 fs/reiser4/block_alloc.h | 78 fs/reiser4/blocknrset.c | 161 fs/reiser4/carry.c | 419 - fs/reiser4/carry.h | 110 fs/reiser4/carry_ops.c | 591 - fs/reiser4/carry_ops.h | 3 fs/reiser4/cluster.c | 34 fs/reiser4/cluster.h | 143 fs/reiser4/context.c | 282 fs/reiser4/context.h | 120 fs/reiser4/coord.c | 212 fs/reiser4/coord.h | 114 fs/reiser4/crypt.c | 32 fs/reiser4/debug.c | 205 fs/reiser4/debug.h | 33 fs/reiser4/dformat.h | 49 fs/reiser4/dscale.c | 20 fs/reiser4/dscale.h | 4 fs/reiser4/emergency_flush.c | 336 fs/reiser4/emergency_flush.h | 36 fs/reiser4/entd.c | 379 fs/reiser4/entd.h | 61 fs/reiser4/eottl.c | 462 - fs/reiser4/estimate.c | 28 fs/reiser4/export_ops.c | 296 fs/reiser4/flush.c | 1004 +- fs/reiser4/flush.h | 97 fs/reiser4/flush_queue.c | 243 fs/reiser4/forward.h | 27 fs/reiser4/fsdata.c | 782 + fs/reiser4/fsdata.h | 222 fs/reiser4/init_super.c | 974 +- fs/reiser4/init_super.h | 3 fs/reiser4/inode.c | 353 fs/reiser4/inode.h | 97 fs/reiser4/jnode.c | 552 - fs/reiser4/jnode.h | 200 fs/reiser4/kassign.c | 365 fs/reiser4/kassign.h | 43 fs/reiser4/key.c | 30 fs/reiser4/key.h | 80 fs/reiser4/ktxnmgrd.c | 328 fs/reiser4/ktxnmgrd.h | 24 fs/reiser4/lock.c | 390 fs/reiser4/lock.h | 59 fs/reiser4/oid.c | 39 fs/reiser4/page_cache.c | 260 fs/reiser4/page_cache.h | 18 fs/reiser4/plugin/compress/compress.c | 249 fs/reiser4/plugin/compress/compress.h | 6 fs/reiser4/plugin/compress/compress_mode.c | 21 fs/reiser4/plugin/compress/lzoconf.h | 174 fs/reiser4/plugin/compress/minilzo.c | 1918 ++-- fs/reiser4/plugin/compress/minilzo.h | 34 fs/reiser4/plugin/digest.c | 4 fs/reiser4/plugin/dir/dir.h | 92 fs/reiser4/plugin/dir/hashed_dir.c | 1448 --- fs/reiser4/plugin/dir/seekable_dir.c | 46 fs/reiser4/plugin/dir_plugin_common.c | 868 ++ fs/reiser4/plugin/disk_format/disk_format.c | 5 fs/reiser4/plugin/disk_format/disk_format.h | 14 fs/reiser4/plugin/disk_format/disk_format40.c | 254 fs/reiser4/plugin/disk_format/disk_format40.h | 3 fs/reiser4/plugin/fibration.c | 45 fs/reiser4/plugin/fibration.h | 2 fs/reiser4/plugin/file/cryptcompress.c | 3553 ++++++++ fs/reiser4/plugin/file/cryptcompress.h | 481 + fs/reiser4/plugin/file/file.c | 1825 ++-- fs/reiser4/plugin/file/file.h | 130 fs/reiser4/plugin/file/funcs.h | 6 fs/reiser4/plugin/file/invert.c | 74 fs/reiser4/plugin/file/symfile.c | 11 fs/reiser4/plugin/file/symlink.c | 92 fs/reiser4/plugin/file/tail_conversion.c | 258 fs/reiser4/plugin/file_ops.c | 251 fs/reiser4/plugin/file_ops_readdir.c | 657 + fs/reiser4/plugin/file_plugin_common.c | 911 ++ fs/reiser4/plugin/hash.c | 102 fs/reiser4/plugin/inode_ops.c | 936 ++ fs/reiser4/plugin/inode_ops_rename.c | 904 ++ fs/reiser4/plugin/item/acl.h | 14 fs/reiser4/plugin/item/blackbox.c | 28 fs/reiser4/plugin/item/blackbox.h | 14 fs/reiser4/plugin/item/cde.c | 511 - fs/reiser4/plugin/item/cde.h | 33 fs/reiser4/plugin/item/ctail.c | 633 - fs/reiser4/plugin/item/ctail.h | 35 fs/reiser4/plugin/item/extent.c | 183 fs/reiser4/plugin/item/extent.h | 124 fs/reiser4/plugin/item/extent_file_ops.c | 778 + fs/reiser4/plugin/item/extent_flush_ops.c | 531 - fs/reiser4/plugin/item/extent_item_ops.c | 386 fs/reiser4/plugin/item/internal.c | 120 fs/reiser4/plugin/item/internal.h | 22 fs/reiser4/plugin/item/item.c | 700 - fs/reiser4/plugin/item/item.h | 157 fs/reiser4/plugin/item/sde.c | 94 fs/reiser4/plugin/item/sde.h | 14 fs/reiser4/plugin/item/static_stat.c | 776 - fs/reiser4/plugin/item/static_stat.h | 44 fs/reiser4/plugin/item/tail.c | 242 fs/reiser4/plugin/item/tail.h | 27 fs/reiser4/plugin/node/node.c | 14 fs/reiser4/plugin/node/node.h | 48 fs/reiser4/plugin/node/node40.c | 1001 +- fs/reiser4/plugin/node/node40.h | 40 fs/reiser4/plugin/object.c | 1714 ---- fs/reiser4/plugin/object.h | 120 fs/reiser4/plugin/plugin.c | 242 fs/reiser4/plugin/plugin.h | 746 + fs/reiser4/plugin/plugin_header.h | 46 fs/reiser4/plugin/plugin_set.c | 206 fs/reiser4/plugin/plugin_set.h | 70 fs/reiser4/plugin/regular.c | 44 fs/reiser4/plugin/security/perm.c | 80 fs/reiser4/plugin/security/perm.h | 15 fs/reiser4/plugin/space/bitmap.c | 429 - fs/reiser4/plugin/space/bitmap.h | 18 fs/reiser4/plugin/tail_policy.c | 74 fs/reiser4/pool.c | 128 fs/reiser4/pool.h | 37 fs/reiser4/readahead.c | 161 fs/reiser4/readahead.h | 21 fs/reiser4/reiser4.h | 11 fs/reiser4/safe_link.c | 100 fs/reiser4/safe_link.h | 4 fs/reiser4/seal.c | 91 fs/reiser4/seal.h | 2 fs/reiser4/search.c | 412 - fs/reiser4/spin_macros.h | 3 fs/reiser4/status_flags.c | 44 fs/reiser4/status_flags.h | 12 fs/reiser4/super.c | 285 fs/reiser4/super.h | 279 fs/reiser4/super_ops.c | 703 + fs/reiser4/tap.c | 82 fs/reiser4/tap.h | 20 fs/reiser4/tree.c | 648 - fs/reiser4/tree.h | 202 fs/reiser4/tree_mod.c | 96 fs/reiser4/tree_walk.c | 346 fs/reiser4/tree_walk.h | 33 fs/reiser4/txnmgr.c | 1293 +-- fs/reiser4/txnmgr.h | 188 fs/reiser4/vfs_ops.c | 1477 --- fs/reiser4/vfs_ops.h | 109 fs/reiser4/wander.c | 596 - fs/reiser4/wander.h | 2 fs/reiser4/writeout.h | 3 fs/reiser4/znode.c | 452 - fs/reiser4/znode.h | 84 156 files changed, 25966 insertions(+), 29185 deletions(-) diff -puN fs/reiser4/as_ops.c~reiser4-big-update fs/reiser4/as_ops.c --- devel/fs/reiser4/as_ops.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/as_ops.c 2005-09-15 19:51:08.000000000 -0700 @@ -47,25 +47,9 @@ /* address space operations */ -static int reiser4_readpage(struct file *, struct page *); - -static int reiser4_prepare_write(struct file *, - struct page *, unsigned, unsigned); - -static int reiser4_commit_write(struct file *, - struct page *, unsigned, unsigned); - -static int reiser4_set_page_dirty (struct page *); -static sector_t reiser4_bmap(struct address_space *, sector_t); -/* static int reiser4_direct_IO(int, struct inode *, - struct kiobuf *, unsigned long, int); */ - -/* address space operations */ - /* clear PAGECACHE_TAG_DIRTY tag of a page. This is used in uncapture_page. This resembles test_clear_page_dirty. The only difference is that page's mapping exists and REISER4_MOVED tag is checked */ -reiser4_internal void -reiser4_clear_page_dirty(struct page *page) +void reiser4_clear_page_dirty(struct page *page) { struct address_space *mapping; unsigned long flags; @@ -83,108 +67,86 @@ reiser4_clear_page_dirty(struct page *pa read_unlock_irqrestore(&mapping->tree_lock, flags); } -/* as_ops->set_page_dirty() VFS method in reiser4_address_space_operations. - - It is used by others (except reiser4) to set reiser4 pages dirty. Reiser4 - itself uses set_page_dirty_internal(). - - The difference is that reiser4_set_page_dirty sets MOVED tag on the page and clears DIRTY tag. Pages tagged as MOVED - get processed by reiser4_writepages() to do reiser4 specific work over dirty pages (allocation jnode, capturing, atom - creation) which cannot be done in the contexts where reiser4_set_page_dirty is called. - set_page_dirty_internal sets DIRTY tag and clear MOVED -*/ -static int reiser4_set_page_dirty(struct page *page /* page to mark dirty */) +/** + * reiser4_set_page_dirty - set dirty bit, tag in page tree, dirty accounting + * @page: page to be dirtied + * + * Operation of struct address_space_operations. This implementation is used by + * unix and crc file plugins. + * + * This is called when reiser4 page gets dirtied outside of reiser4, for + * example, when dirty bit is moved from pte to physical page. + * + * Tags page in the mapping's page tree with special tag so that it is possible + * to do all the reiser4 specific work wrt dirty pages (jnode creation, + * capturing by an atom) later because it can not be done in the contexts where + * set_page_dirty is called. + */ +int reiser4_set_page_dirty(struct page *page) { /* this page can be unformatted only */ assert("vs-1734", (page->mapping && page->mapping->host && - get_super_fake(page->mapping->host->i_sb) != page->mapping->host && - get_cc_fake(page->mapping->host->i_sb) != page->mapping->host && - get_super_private(page->mapping->host->i_sb)->bitmap != page->mapping->host)); + get_super_fake(page->mapping->host->i_sb) != + page->mapping->host + && get_cc_fake(page->mapping->host->i_sb) != + page->mapping->host + && get_bitmap_fake(page->mapping->host->i_sb) != + page->mapping->host)); if (!TestSetPageDirty(page)) { struct address_space *mapping = page->mapping; if (mapping) { - read_lock_irq(&mapping->tree_lock); + write_lock_irq(&mapping->tree_lock); + /* check for race with truncate */ if (page->mapping) { assert("vs-1652", page->mapping == mapping); if (mapping_cap_account_dirty(mapping)) inc_page_state(nr_dirty); radix_tree_tag_set(&mapping->page_tree, - page->index, PAGECACHE_TAG_REISER4_MOVED); + page->index, + PAGECACHE_TAG_REISER4_MOVED); } - read_unlock_irq(&mapping->tree_lock); + write_unlock_irq(&mapping->tree_lock); __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); } } return 0; } -/* ->readpage() VFS method in reiser4 address_space_operations - method serving file mmapping -*/ -static int -reiser4_readpage(struct file *f /* file to read from */ , - struct page *page /* page where to read data - * into */ ) -{ - struct inode *inode; - file_plugin *fplug; - int result; - reiser4_context ctx; - - /* - * basically calls ->readpage method of object plugin and handles - * errors. - */ - - assert("umka-078", f != NULL); - assert("umka-079", page != NULL); - assert("nikita-2280", PageLocked(page)); - assert("vs-976", !PageUptodate(page)); - - assert("vs-318", page->mapping && page->mapping->host); - assert("nikita-1352", (f == NULL) || (f->f_dentry->d_inode == page->mapping->host)); - - /* ->readpage can be called from page fault service routine */ - assert("nikita-3174", schedulable()); - - inode = page->mapping->host; - init_context(&ctx, inode->i_sb); - fplug = inode_file_plugin(inode); - if (fplug->readpage != NULL) - result = fplug->readpage(f, page); - else - result = RETERR(-EINVAL); - - reiser4_exit_context(&ctx); - return result; -} - static int filler(void *vp, struct page *page) { - return reiser4_readpage(vp, page); + return page->mapping->a_ops->readpage(vp, page); } -/* ->readpages() VFS method in reiser4 address_space_operations - method serving page cache readahead - - if readpages hook is set in file data - it is called - otherwise read_cache_pages is used -*/ -static int +/** + * reiser4_readpages - submit read for a set of pages + * @file: file to read + * @mapping: address space + * @pages: list of pages to submit read for + * @nr_pages: number of pages no the list + * + * Operation of struct address_space_operations. This implementation is used by + * unix and crc file plugins. + * + * Calls read_cache_pages or readpages hook if it is set. + */ +int reiser4_readpages(struct file *file, struct address_space *mapping, struct list_head *pages, unsigned nr_pages) { - reiser4_context ctx; + reiser4_context *ctx; reiser4_file_fsdata *fsdata; - init_context(&ctx, mapping->host->i_sb); + ctx = init_context(mapping->host->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + fsdata = reiser4_get_file_fsdata(file); if (IS_ERR(fsdata)) { - reiser4_exit_context(&ctx); + reiser4_exit_context(ctx); return PTR_ERR(fsdata); } @@ -194,118 +156,10 @@ reiser4_readpages(struct file *file, str assert("vs-1738", lock_stack_isclean(get_current_lock_stack())); read_cache_pages(mapping, pages, filler, file); } - reiser4_exit_context(&ctx); + reiser4_exit_context(ctx); return 0; } -/* prepares @page to be written. This means, that if we want to modify only some - part of page, page should be read first and than modified. Actually this function - almost the same as reiser4_readpage(). The differentce is only that, it does not - unlock the page in the case of error. This is needed because loop back device - driver expects it locked. */ -static int reiser4_prepare_write(struct file *file, struct page *page, - unsigned from, unsigned to) -{ - int result; - file_plugin * fplug; - struct inode * inode; - reiser4_context ctx; - - inode = page->mapping->host; - init_context(&ctx, inode->i_sb); - fplug = inode_file_plugin(inode); - - if (fplug->prepare_write != NULL) - result = fplug->prepare_write(file, page, from, to); - else - result = RETERR(-EINVAL); - - /* don't commit transaction under inode semaphore */ - context_set_commit_async(&ctx); - reiser4_exit_context(&ctx); - - return result; -} - -/* captures jnode of @page to current atom. */ -static int reiser4_commit_write(struct file *file, struct page *page, - unsigned from, unsigned to) -{ - int result; - file_plugin *fplug; - struct inode *inode; - reiser4_context ctx; - - assert("umka-3101", file != NULL); - assert("umka-3102", page != NULL); - assert("umka-3093", PageLocked(page)); - - SetPageUptodate(page); - - inode = page->mapping->host; - init_context(&ctx, inode->i_sb); - fplug = inode_file_plugin(inode); - - if (fplug->capturepage) - result = fplug->capturepage(page); - else - result = RETERR(-EINVAL); - - /* here page is return locked. */ - assert("umka-3103", PageLocked(page)); - - /* don't commit transaction under inode semaphore */ - context_set_commit_async(&ctx); - reiser4_exit_context(&ctx); - return result; -} - -/* ->writepages() - ->vm_writeback() - ->set_page_dirty() - ->prepare_write() - ->commit_write() -*/ - -/* ->bmap() VFS method in reiser4 address_space_operations */ -reiser4_internal int -reiser4_lblock_to_blocknr(struct address_space *mapping, - sector_t lblock, reiser4_block_nr *blocknr) -{ - file_plugin *fplug; - int result; - reiser4_context ctx; - - init_context(&ctx, mapping->host->i_sb); - - fplug = inode_file_plugin(mapping->host); - if (fplug && fplug->get_block) { - *blocknr = generic_block_bmap(mapping, lblock, fplug->get_block); - result = 0; - } else - result = RETERR(-EINVAL); - reiser4_exit_context(&ctx); - return result; -} - -/* ->bmap() VFS method in reiser4 address_space_operations */ -static sector_t -reiser4_bmap(struct address_space *mapping, sector_t lblock) -{ - reiser4_block_nr blocknr; - int result; - - result = reiser4_lblock_to_blocknr(mapping, lblock, &blocknr); - if (result == 0) - if (sizeof blocknr == sizeof(sector_t) || - !blocknr_is_fake(&blocknr)) - return blocknr; - else - return 0; - else - return result; -} - /* ->invalidatepage method for reiser4 */ /* @@ -316,14 +170,18 @@ reiser4_bmap(struct address_space *mappi * completed. */ -reiser4_internal int -reiser4_invalidatepage(struct page *page /* page to invalidate */, - unsigned long offset /* starting offset for partial - * invalidation */) +/** + * reiser4_invalidatepage + * @page: page to invalidate + * @offset: starting offset for partial invalidation + * + */ +int reiser4_invalidatepage(struct page *page, unsigned long offset) { int ret = 0; - reiser4_context ctx; + reiser4_context *ctx; struct inode *inode; + jnode *node; /* * This is called to truncate file's page. @@ -342,7 +200,6 @@ reiser4_invalidatepage(struct page *page * top-to-bottom style: items are killed in cut_tree_object() and * pages belonging to extent are invalidated in kill_hook_extent(). So * probably now additional call to capture is not needed here. - * */ assert("nikita-3137", PageLocked(page)); @@ -360,13 +217,34 @@ reiser4_invalidatepage(struct page *page return 0; if (get_cc_fake(inode->i_sb) == inode) return 0; - if (get_super_private(inode->i_sb)->bitmap == inode) + if (get_bitmap_fake(inode->i_sb) == inode) return 0; - assert("vs-1426", PagePrivate(page)); - assert("vs-1427", page->mapping == jnode_get_mapping(jnode_by_page(page))); + assert("vs-1427", + page->mapping == jnode_get_mapping(jnode_by_page(page))); + assert("", jprivate(page) != NULL); + assert("", offset == 0); + + node = jprivate(page); + LOCK_JNODE(node); + if (!JF_ISSET(node, JNODE_DIRTY) && !JF_ISSET(node, JNODE_FLUSH_QUEUED) && + !JF_ISSET(node, JNODE_WRITEBACK)) { + /* there is not need to capture */ + jref(node); + JF_SET(node, JNODE_HEARD_BANSHEE); + page_clear_jnode(page, node); + uncapture_jnode(node); + unhash_unformatted_jnode(node); + jput(node); + return 0; + } + UNLOCK_JNODE(node); + + + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); - init_context(&ctx, inode->i_sb); /* capture page being truncated. */ ret = try_capture_page_to_invalidate(page); if (ret != 0) { @@ -375,28 +253,24 @@ reiser4_invalidatepage(struct page *page } if (offset == 0) { - jnode *node; - /* remove jnode from transaction and detach it from page. */ - node = jnode_by_page(page); - if (node != NULL) { - assert("vs-1435", !JF_ISSET(node, JNODE_CC)); - jref(node); - JF_SET(node, JNODE_HEARD_BANSHEE); - /* page cannot be detached from jnode concurrently, - * because it is locked */ - uncapture_page(page); - - /* this detaches page from jnode, so that jdelete will not try to lock page which is already locked */ - UNDER_SPIN_VOID(jnode, - node, - page_clear_jnode(page, node)); - unhash_unformatted_jnode(node); + assert("vs-1435", !JF_ISSET(node, JNODE_CC)); + jref(node); + JF_SET(node, JNODE_HEARD_BANSHEE); + /* page cannot be detached from jnode concurrently, because it + * is locked */ + uncapture_page(page); + + /* this detaches page from jnode, so that jdelete will not try + * to lock page which is already locked */ + UNDER_SPIN_VOID(jnode, + node, page_clear_jnode(page, node)); + unhash_unformatted_jnode(node); - jput(node); - } + jput(node); } - reiser4_exit_context(&ctx); + + reiser4_exit_context(ctx); return ret; } @@ -406,12 +280,9 @@ reiser4_invalidatepage(struct page *page #define INC_NSTAT(node, counter) INC_STAT(jnode_page(node), node, counter) -int is_cced(const jnode *node); - /* help function called from reiser4_releasepage(). It returns true if jnode * can be detached from its page and page released. */ -static int -releasable(const jnode *node /* node to check */) +static int releasable(const jnode * node /* node to check */ ) { assert("nikita-2781", node != NULL); assert("nikita-2783", spin_jnode_is_locked(node)); @@ -434,7 +305,7 @@ releasable(const jnode *node /* node to /* emergency flushed page can be released. This is what emergency * flush is all about after all. */ if (JF_ISSET(node, JNODE_EFLUSH)) { - return 1; /* yeah! */ + return 1; /* yeah! */ } /* can only release page if real block number is assigned to @@ -473,7 +344,7 @@ releasable(const jnode *node /* node to } #if REISER4_DEBUG -int jnode_is_releasable(jnode *node) +int jnode_is_releasable(jnode * node) { return UNDER_SPIN(jload, node, releasable(node)); } @@ -488,8 +359,7 @@ int jnode_is_releasable(jnode *node) * * Check for releasability is done by releasable() function. */ -reiser4_internal int -reiser4_releasepage(struct page *page, int gfp UNUSED_ARG) +int reiser4_releasepage(struct page *page, int gfp UNUSED_ARG) { jnode *node; @@ -551,89 +421,6 @@ reiser4_releasepage(struct page *page, i } } -#undef INC_NSTAT -#undef INC_STAT - -/* reiser4 writepages() address space operation this captures anonymous pages - and anonymous jnodes. Anonymous pages are pages which are dirtied via - mmapping. Anonymous jnodes are ones which were created by reiser4_writepage - */ -reiser4_internal int -reiser4_writepages(struct address_space *mapping, - struct writeback_control *wbc) -{ - int ret = 0; - struct inode *inode; - file_plugin *fplug; - - inode = mapping->host; - fplug = inode_file_plugin(inode); - if (fplug != NULL && fplug->capture != NULL) { - /* call file plugin method to capture anonymous pages and - anonymous jnodes */ - ret = fplug->capture(inode, wbc); - if (is_in_reiser4_context()) { - if (get_current_context()->nr_captured >= CAPTURE_APAGE_BURST) { - /* there are already pages to flush, flush them - out, do not delay until end of - reiser4_sync_inodes */ - writeout(inode->i_sb, wbc); - get_current_context()->nr_captured = 0; - } - } - } - - return ret; -} - -/* start actual IO on @page */ -reiser4_internal int reiser4_start_up_io(struct page *page) -{ - block_sync_page(page); - return 0; -} - -/* - * reiser4 methods for VM - */ -struct address_space_operations reiser4_as_operations = { - /* called during memory pressure by kswapd */ - .writepage = reiser4_writepage, - /* called to read page from the storage when page is added into page - cache. This is done by page-fault handler. */ - .readpage = reiser4_readpage, - /* Start IO on page. This is called from wait_on_page_bit() and - lock_page() and its purpose is to actually start io by jabbing - device drivers. */ - .sync_page = reiser4_start_up_io, - /* called from - * reiser4_sync_inodes()->generic_sync_sb_inodes()->...->do_writepages() - * - * captures anonymous pages for given inode - */ - .writepages = reiser4_writepages, - /* marks page dirty. Note that this is never called by reiser4 - * directly. Reiser4 uses set_page_dirty_internal(). Reiser4 set page - * dirty is called for pages dirtied though mmap and moves dirty page - * to the special ->moved_list in its mapping. */ - .set_page_dirty = reiser4_set_page_dirty, - /* called during read-ahead */ - .readpages = reiser4_readpages, - .prepare_write = reiser4_prepare_write, /* loop back device driver and generic_file_write() call-back */ - .commit_write = reiser4_commit_write, /* loop back device driver and generic_file_write() call-back */ - /* map logical block number to disk block number. Used by FIBMAP ioctl - * and ..bmap pseudo file. */ - .bmap = reiser4_bmap, - /* called just before page is taken out from address space (on - truncate, umount, or similar). */ - .invalidatepage = reiser4_invalidatepage, - /* called when VM is about to take page from address space (due to - memory pressure). */ - .releasepage = reiser4_releasepage, - /* not yet implemented */ - .direct_IO = NULL -}; - /* Make Linus happy. Local variables: c-indentation-style: "K&R" diff -puN fs/reiser4/block_alloc.c~reiser4-big-update fs/reiser4/block_alloc.c --- devel/fs/reiser4/block_alloc.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/block_alloc.c 2005-09-15 19:51:08.000000000 -0700 @@ -8,7 +8,6 @@ #include "block_alloc.h" #include "tree.h" #include "super.h" -#include "lib.h" #include /* for __u?? */ #include /* for struct super_block */ @@ -120,23 +119,20 @@ impossible to overload this counter during one transaction life. */ /* Initialize a blocknr hint. */ -reiser4_internal void -blocknr_hint_init(reiser4_blocknr_hint * hint) +void blocknr_hint_init(reiser4_blocknr_hint * hint) { - memset(hint, 0, sizeof (reiser4_blocknr_hint)); + memset(hint, 0, sizeof(reiser4_blocknr_hint)); } /* Release any resources of a blocknr hint. */ -reiser4_internal void -blocknr_hint_done(reiser4_blocknr_hint * hint UNUSED_ARG) +void blocknr_hint_done(reiser4_blocknr_hint * hint UNUSED_ARG) { - /* No resources should be freed in current blocknr_hint implementation.*/ + /* No resources should be freed in current blocknr_hint implementation. */ } /* see above for explanation of fake block number. */ /* Audited by: green(2002.06.11) */ -reiser4_internal int -blocknr_is_fake(const reiser4_block_nr * da) +int blocknr_is_fake(const reiser4_block_nr * da) { /* The reason for not simply returning result of '&' operation is that while return value is (possibly 32bit) int, the reiser4_block_nr is @@ -148,30 +144,19 @@ blocknr_is_fake(const reiser4_block_nr * /* Static functions for / block counters arithmetic. Mostly, they are isolated to not to code same assertions in several places. */ -static void -sub_from_ctx_grabbed(reiser4_context *ctx, __u64 count) +static void sub_from_ctx_grabbed(reiser4_context * ctx, __u64 count) { BUG_ON(ctx->grabbed_blocks < count); assert("zam-527", ctx->grabbed_blocks >= count); ctx->grabbed_blocks -= count; } -static void -add_to_ctx_grabbed(reiser4_context *ctx, __u64 count) +static void add_to_ctx_grabbed(reiser4_context * ctx, __u64 count) { -#if REISER4_DEBUG -#ifdef CONFIG_FRAME_POINTER - ctx->grabbed_at[0] = __builtin_return_address(0); - ctx->grabbed_at[1] = __builtin_return_address(1); - ctx->grabbed_at[2] = __builtin_return_address(2); - ctx->grabbed_at[3] = __builtin_return_address(3); -#endif -#endif ctx->grabbed_blocks += count; } -static void -sub_from_sb_grabbed(reiser4_super_info_data *sbinfo, __u64 count) +static void sub_from_sb_grabbed(reiser4_super_info_data * sbinfo, __u64 count) { assert("zam-525", sbinfo->blocks_grabbed >= count); sbinfo->blocks_grabbed -= count; @@ -179,69 +164,68 @@ sub_from_sb_grabbed(reiser4_super_info_d /* Decrease the counter of block reserved for flush in super block. */ static void -sub_from_sb_flush_reserved (reiser4_super_info_data *sbinfo, __u64 count) +sub_from_sb_flush_reserved(reiser4_super_info_data * sbinfo, __u64 count) { - assert ("vpf-291", sbinfo->blocks_flush_reserved >= count); + assert("vpf-291", sbinfo->blocks_flush_reserved >= count); sbinfo->blocks_flush_reserved -= count; } static void -sub_from_sb_fake_allocated(reiser4_super_info_data *sbinfo, __u64 count, reiser4_ba_flags_t flags) +sub_from_sb_fake_allocated(reiser4_super_info_data * sbinfo, __u64 count, + reiser4_ba_flags_t flags) { if (flags & BA_FORMATTED) { assert("zam-806", sbinfo->blocks_fake_allocated >= count); sbinfo->blocks_fake_allocated -= count; } else { - assert("zam-528", sbinfo->blocks_fake_allocated_unformatted >= count); + assert("zam-528", + sbinfo->blocks_fake_allocated_unformatted >= count); sbinfo->blocks_fake_allocated_unformatted -= count; } } -static void -sub_from_sb_used(reiser4_super_info_data *sbinfo, __u64 count) +static void sub_from_sb_used(reiser4_super_info_data * sbinfo, __u64 count) { - assert("zam-530", sbinfo->blocks_used >= count + sbinfo->min_blocks_used); + assert("zam-530", + sbinfo->blocks_used >= count + sbinfo->min_blocks_used); sbinfo->blocks_used -= count; } static void -sub_from_cluster_reserved(reiser4_super_info_data *sbinfo, __u64 count) +sub_from_cluster_reserved(reiser4_super_info_data * sbinfo, __u64 count) { assert("edward-501", sbinfo->blocks_clustered >= count); sbinfo->blocks_clustered -= count; } /* Increase the counter of block reserved for flush in atom. */ -static void -add_to_atom_flush_reserved_nolock (txn_atom * atom, __u32 count) +static void add_to_atom_flush_reserved_nolock(txn_atom * atom, __u32 count) { - assert ("zam-772", atom != NULL); - assert ("zam-773", spin_atom_is_locked (atom)); + assert("zam-772", atom != NULL); + assert("zam-773", spin_atom_is_locked(atom)); atom->flush_reserved += count; } /* Decrease the counter of block reserved for flush in atom. */ -static void -sub_from_atom_flush_reserved_nolock (txn_atom * atom, __u32 count) +static void sub_from_atom_flush_reserved_nolock(txn_atom * atom, __u32 count) { - assert ("zam-774", atom != NULL); - assert ("zam-775", spin_atom_is_locked (atom)); - assert ("nikita-2790", atom->flush_reserved >= count); + assert("zam-774", atom != NULL); + assert("zam-775", spin_atom_is_locked(atom)); + assert("nikita-2790", atom->flush_reserved >= count); atom->flush_reserved -= count; } /* super block has 6 counters: free, used, grabbed, fake allocated (formatted and unformatted) and flush reserved. Their sum must be number of blocks on a device. This function checks this */ -reiser4_internal int -check_block_counters(const struct super_block *super) +int check_block_counters(const struct super_block *super) { __u64 sum; sum = reiser4_grabbed_blocks(super) + reiser4_free_blocks(super) + - reiser4_data_blocks(super) + reiser4_fake_allocated(super) + - reiser4_fake_allocated_unformatted(super) + flush_reserved(super) + - reiser4_clustered_blocks(super); + reiser4_data_blocks(super) + reiser4_fake_allocated(super) + + reiser4_fake_allocated_unformatted(super) + flush_reserved(super) + + reiser4_clustered_blocks(super); if (reiser4_block_count(super) != sum) { printk("super block counters: " "used %llu, free %llu, " @@ -251,7 +235,8 @@ check_block_counters(const struct super_ (unsigned long long)reiser4_free_blocks(super), (unsigned long long)reiser4_grabbed_blocks(super), (unsigned long long)reiser4_fake_allocated(super), - (unsigned long long)reiser4_fake_allocated_unformatted(super), + (unsigned long long) + reiser4_fake_allocated_unformatted(super), (unsigned long long)flush_reserved(super), (unsigned long long)reiser4_clustered_blocks(super), (unsigned long long)sum, @@ -274,7 +259,7 @@ check_block_counters(const struct super_ */ static int -reiser4_grab(reiser4_context *ctx, __u64 count, reiser4_ba_flags_t flags) +reiser4_grab(reiser4_context * ctx, __u64 count, reiser4_ba_flags_t flags) { __u64 free_blocks; int ret = 0, use_reserved = flags & BA_RESERVED; @@ -314,20 +299,20 @@ reiser4_grab(reiser4_context *ctx, __u64 /* disable grab space in current context */ ctx->grab_enabled = 0; -unlock_and_ret: + unlock_and_ret: reiser4_spin_unlock_sb(sbinfo); return ret; } -reiser4_internal int -reiser4_grab_space(__u64 count, reiser4_ba_flags_t flags) +int reiser4_grab_space(__u64 count, reiser4_ba_flags_t flags) { int ret; reiser4_context *ctx; assert("nikita-2964", ergo(flags & BA_CAN_COMMIT, - lock_stack_isclean(get_current_lock_stack()))); + lock_stack_isclean(get_current_lock_stack + ()))); ctx = get_current_context(); if (!(flags & BA_FORCE) && !is_grab_enabled(ctx)) { return 0; @@ -367,8 +352,8 @@ reiser4_grab_space(__u64 count, reiser4_ * */ -reiser4_internal int reiser4_grab_reserved(struct super_block *super, - __u64 count, reiser4_ba_flags_t flags) +int reiser4_grab_reserved(struct super_block *super, + __u64 count, reiser4_ba_flags_t flags) { reiser4_super_info_data *sbinfo = get_super_private(super); @@ -377,8 +362,10 @@ reiser4_internal int reiser4_grab_reserv /* Check the delete semaphore already taken by us, we assume that * reading of machine word is atomic. */ if (sbinfo->delete_sema_owner == current) { - if (reiser4_grab_space(count, (flags | BA_RESERVED) & ~BA_CAN_COMMIT)) { - warning("zam-1003", "nested call of grab_reserved fails count=(%llu)", + if (reiser4_grab_space + (count, (flags | BA_RESERVED) & ~BA_CAN_COMMIT)) { + warning("zam-1003", + "nested call of grab_reserved fails count=(%llu)", (unsigned long long)count); reiser4_release_reserved(super); return RETERR(-ENOSPC); @@ -393,7 +380,8 @@ reiser4_internal int reiser4_grab_reserv if (reiser4_grab_space(count, flags | BA_RESERVED)) { warning("zam-833", - "reserved space is not enough (%llu)", (unsigned long long)count); + "reserved space is not enough (%llu)", + (unsigned long long)count); reiser4_release_reserved(super); return RETERR(-ENOSPC); } @@ -401,8 +389,7 @@ reiser4_internal int reiser4_grab_reserv return 0; } -reiser4_internal void -reiser4_release_reserved(struct super_block *super) +void reiser4_release_reserved(struct super_block *super) { reiser4_super_info_data *info; @@ -413,8 +400,7 @@ reiser4_release_reserved(struct super_bl } } -static reiser4_super_info_data * -grabbed2fake_allocated_head(void) +static reiser4_super_info_data *grabbed2fake_allocated_head(void) { reiser4_context *ctx; reiser4_super_info_data *sbinfo; @@ -432,34 +418,31 @@ grabbed2fake_allocated_head(void) /* is called after @count fake block numbers are allocated and pointer to those blocks are inserted into tree. */ -static void -grabbed2fake_allocated_formatted(void) +static void grabbed2fake_allocated_formatted(void) { reiser4_super_info_data *sbinfo; sbinfo = grabbed2fake_allocated_head(); - sbinfo->blocks_fake_allocated ++; + sbinfo->blocks_fake_allocated++; assert("vs-922", check_block_counters(reiser4_get_current_sb())); reiser4_spin_unlock_sb(sbinfo); } -static void -grabbed2fake_allocated_unformatted(void) +static void grabbed2fake_allocated_unformatted(void) { reiser4_super_info_data *sbinfo; sbinfo = grabbed2fake_allocated_head(); - sbinfo->blocks_fake_allocated_unformatted ++; + sbinfo->blocks_fake_allocated_unformatted++; assert("vs-9221", check_block_counters(reiser4_get_current_sb())); reiser4_spin_unlock_sb(sbinfo); } -reiser4_internal void -grabbed2cluster_reserved(int count) +void grabbed2cluster_reserved(int count) { reiser4_context *ctx; reiser4_super_info_data *sbinfo; @@ -478,8 +461,7 @@ grabbed2cluster_reserved(int count) reiser4_spin_unlock_sb(sbinfo); } -reiser4_internal void -cluster_reserved2grabbed(int count) +void cluster_reserved2grabbed(int count) { reiser4_context *ctx; reiser4_super_info_data *sbinfo; @@ -498,8 +480,7 @@ cluster_reserved2grabbed(int count) add_to_ctx_grabbed(ctx, count); } -reiser4_internal void -cluster_reserved2free(int count) +void cluster_reserved2free(int count) { reiser4_context *ctx; reiser4_super_info_data *sbinfo; @@ -523,7 +504,7 @@ static reiser4_block_nr fake_gen = 0; /* obtain a block number for new formatted node which will be used to refer to this newly allocated node until real allocation is done */ -static inline void assign_fake_blocknr(reiser4_block_nr *blocknr) +static inline void assign_fake_blocknr(reiser4_block_nr * blocknr) { spin_lock(&fake_lock); *blocknr = fake_gen++; @@ -534,8 +515,7 @@ static inline void assign_fake_blocknr(r assert("zam-394", zlook(current_tree, blocknr) == NULL); } -reiser4_internal int -assign_fake_blocknr_formatted(reiser4_block_nr *blocknr) +int assign_fake_blocknr_formatted(reiser4_block_nr * blocknr) { assign_fake_blocknr(blocknr); grabbed2fake_allocated_formatted(); @@ -544,23 +524,22 @@ assign_fake_blocknr_formatted(reiser4_bl } /* return fake blocknr which will be used for unformatted nodes */ -reiser4_internal reiser4_block_nr -fake_blocknr_unformatted(void) +reiser4_block_nr fake_blocknr_unformatted(void) { reiser4_block_nr blocknr; assign_fake_blocknr(&blocknr); grabbed2fake_allocated_unformatted(); - /*XXXXX*/inc_unalloc_unfm_ptr(); + inc_unalloc_unfm_ptr(); return blocknr; } - /* adjust sb block counters, if real (on-disk) block allocation immediately follows grabbing of free disk space. */ static void -grabbed2used(reiser4_context *ctx, reiser4_super_info_data *sbinfo, __u64 count) +grabbed2used(reiser4_context * ctx, reiser4_super_info_data * sbinfo, + __u64 count) { sub_from_ctx_grabbed(ctx, count); @@ -576,7 +555,8 @@ grabbed2used(reiser4_context *ctx, reise /* adjust sb block counters when @count unallocated blocks get mapped to disk */ static void -fake_allocated2used(reiser4_super_info_data *sbinfo, __u64 count, reiser4_ba_flags_t flags) +fake_allocated2used(reiser4_super_info_data * sbinfo, __u64 count, + reiser4_ba_flags_t flags) { reiser4_spin_lock_sb(sbinfo); @@ -588,15 +568,14 @@ fake_allocated2used(reiser4_super_info_d reiser4_spin_unlock_sb(sbinfo); } -static void -flush_reserved2used(txn_atom * atom, __u64 count) +static void flush_reserved2used(txn_atom * atom, __u64 count) { reiser4_super_info_data *sbinfo; assert("zam-787", atom != NULL); assert("zam-788", spin_atom_is_locked(atom)); - sub_from_atom_flush_reserved_nolock(atom, (__u32)count); + sub_from_atom_flush_reserved_nolock(atom, (__u32) count); sbinfo = get_current_super_private(); reiser4_spin_lock_sb(sbinfo); @@ -604,14 +583,15 @@ flush_reserved2used(txn_atom * atom, __u sub_from_sb_flush_reserved(sbinfo, count); sbinfo->blocks_used += count; - assert ("zam-789", check_block_counters(reiser4_get_current_sb())); + assert("zam-789", check_block_counters(reiser4_get_current_sb())); reiser4_spin_unlock_sb(sbinfo); } /* update the per fs blocknr hint default value. */ -reiser4_internal void -update_blocknr_hint_default (const struct super_block *s, const reiser4_block_nr * block) +void +update_blocknr_hint_default(const struct super_block *s, + const reiser4_block_nr * block) { reiser4_super_info_data *sbinfo = get_super_private(s); @@ -622,7 +602,8 @@ update_blocknr_hint_default (const struc sbinfo->blocknr_hint_default = *block; } else { warning("zam-676", - "block number %llu is too large to be used in a blocknr hint\n", (unsigned long long) *block); + "block number %llu is too large to be used in a blocknr hint\n", + (unsigned long long)*block); dump_stack(); DEBUGON(1); } @@ -630,9 +611,9 @@ update_blocknr_hint_default (const struc } /* get current value of the default blocknr hint. */ -reiser4_internal void get_blocknr_hint_default(reiser4_block_nr * result) +void get_blocknr_hint_default(reiser4_block_nr * result) { - reiser4_super_info_data * sbinfo = get_current_super_private(); + reiser4_super_info_data *sbinfo = get_current_super_private(); reiser4_spin_lock_sb(sbinfo); *result = sbinfo->blocknr_hint_default; @@ -657,7 +638,7 @@ reiser4_internal void get_blocknr_hint_d * * @return -- 0 if success, error code otherwise. */ -reiser4_internal int +int reiser4_alloc_blocks(reiser4_blocknr_hint * hint, reiser4_block_nr * blk, reiser4_block_nr * len, reiser4_ba_flags_t flags) { @@ -666,7 +647,7 @@ reiser4_alloc_blocks(reiser4_blocknr_hin reiser4_super_info_data *sbinfo; int ret; - assert ("zam-986", hint != NULL); + assert("zam-986", hint != NULL); ctx = get_current_context(); sbinfo = get_super_private(ctx->super); @@ -685,17 +666,20 @@ reiser4_alloc_blocks(reiser4_blocknr_hin return ret; } - ret = sa_alloc_blocks(get_space_allocator(ctx->super), hint, (int) needed, blk, len); + ret = + sa_alloc_blocks(get_space_allocator(ctx->super), hint, (int)needed, + blk, len); if (!ret) { assert("zam-680", *blk < reiser4_block_count(ctx->super)); - assert("zam-681", *blk + *len <= reiser4_block_count(ctx->super)); + assert("zam-681", + *blk + *len <= reiser4_block_count(ctx->super)); if (flags & BA_PERMANENT) { /* we assume that current atom exists at this moment */ - txn_atom * atom = get_current_atom_locked (); - atom -> nr_blocks_allocated += *len; - UNLOCK_ATOM (atom); + txn_atom *atom = get_current_atom_locked(); + atom->nr_blocks_allocated += *len; + UNLOCK_ATOM(atom); } switch (hint->block_stage) { @@ -708,16 +692,18 @@ reiser4_alloc_blocks(reiser4_blocknr_hin break; case BLOCK_FLUSH_RESERVED: { - txn_atom *atom = get_current_atom_locked (); + txn_atom *atom = get_current_atom_locked(); flush_reserved2used(atom, *len); - UNLOCK_ATOM (atom); + UNLOCK_ATOM(atom); } break; default: impossible("zam-531", "wrong block stage"); } } else { - assert ("zam-821", ergo(hint->max_dist == 0 && !hint->backward, ret != -ENOSPC)); + assert("zam-821", + ergo(hint->max_dist == 0 + && !hint->backward, ret != -ENOSPC)); if (hint->block_stage == BLOCK_NOT_COUNTED) grabbed2free(ctx, sbinfo, needed); } @@ -730,7 +716,8 @@ reiser4_alloc_blocks(reiser4_blocknr_hin /* adjust sb block counters when @count unallocated blocks get unmapped from disk */ static void -used2fake_allocated(reiser4_super_info_data *sbinfo, __u64 count, int formatted) +used2fake_allocated(reiser4_super_info_data * sbinfo, __u64 count, + int formatted) { reiser4_spin_lock_sb(sbinfo); @@ -747,18 +734,18 @@ used2fake_allocated(reiser4_super_info_d } static void -used2flush_reserved(reiser4_super_info_data *sbinfo, txn_atom * atom, __u64 count, - reiser4_ba_flags_t flags UNUSED_ARG) +used2flush_reserved(reiser4_super_info_data * sbinfo, txn_atom * atom, + __u64 count, reiser4_ba_flags_t flags UNUSED_ARG) { assert("nikita-2791", atom != NULL); assert("nikita-2792", spin_atom_is_locked(atom)); - add_to_atom_flush_reserved_nolock(atom, (__u32)count); + add_to_atom_flush_reserved_nolock(atom, (__u32) count); reiser4_spin_lock_sb(sbinfo); sbinfo->blocks_flush_reserved += count; - /*add_to_sb_flush_reserved(sbinfo, count);*/ + /*add_to_sb_flush_reserved(sbinfo, count); */ sub_from_sb_used(sbinfo, count); assert("nikita-2681", check_block_counters(reiser4_get_current_sb())); @@ -768,7 +755,8 @@ used2flush_reserved(reiser4_super_info_d /* disk space, virtually used by fake block numbers is counted as "grabbed" again. */ static void -fake_allocated2grabbed(reiser4_context *ctx, reiser4_super_info_data *sbinfo, __u64 count, reiser4_ba_flags_t flags) +fake_allocated2grabbed(reiser4_context * ctx, reiser4_super_info_data * sbinfo, + __u64 count, reiser4_ba_flags_t flags) { add_to_ctx_grabbed(ctx, count); @@ -784,8 +772,7 @@ fake_allocated2grabbed(reiser4_context * reiser4_spin_unlock_sb(sbinfo); } -reiser4_internal void -fake_allocated2free(__u64 count, reiser4_ba_flags_t flags) +void fake_allocated2free(__u64 count, reiser4_ba_flags_t flags) { reiser4_context *ctx; reiser4_super_info_data *sbinfo; @@ -797,8 +784,7 @@ fake_allocated2free(__u64 count, reiser4 grabbed2free(ctx, sbinfo, count); } -reiser4_internal void -grabbed2free_mark(__u64 mark) +void grabbed2free_mark(__u64 mark) { reiser4_context *ctx; reiser4_super_info_data *sbinfo; @@ -806,20 +792,18 @@ grabbed2free_mark(__u64 mark) ctx = get_current_context(); sbinfo = get_super_private(ctx->super); - assert("nikita-3007", (__s64)mark >= 0); - assert("nikita-3006", - ctx->grabbed_blocks >= mark); + assert("nikita-3007", (__s64) mark >= 0); + assert("nikita-3006", ctx->grabbed_blocks >= mark); grabbed2free(ctx, sbinfo, ctx->grabbed_blocks - mark); } /* Adjust free blocks count for blocks which were reserved but were not used. */ -reiser4_internal void -grabbed2free(reiser4_context *ctx, reiser4_super_info_data *sbinfo, - __u64 count) +void +grabbed2free(reiser4_context * ctx, reiser4_super_info_data * sbinfo, + __u64 count) { sub_from_ctx_grabbed(ctx, count); - reiser4_spin_lock_sb(sbinfo); sub_from_sb_grabbed(sbinfo, count); @@ -829,8 +813,7 @@ grabbed2free(reiser4_context *ctx, reise reiser4_spin_unlock_sb(sbinfo); } -reiser4_internal void -grabbed2flush_reserved_nolock(txn_atom * atom, __u64 count) +void grabbed2flush_reserved_nolock(txn_atom * atom, __u64 count) { reiser4_context *ctx; reiser4_super_info_data *sbinfo; @@ -849,22 +832,21 @@ grabbed2flush_reserved_nolock(txn_atom * sbinfo->blocks_flush_reserved += count; sub_from_sb_grabbed(sbinfo, count); - assert ("vpf-292", check_block_counters(ctx->super)); + assert("vpf-292", check_block_counters(ctx->super)); reiser4_spin_unlock_sb(sbinfo); } -reiser4_internal void -grabbed2flush_reserved(__u64 count) +void grabbed2flush_reserved(__u64 count) { - txn_atom * atom = get_current_atom_locked (); + txn_atom *atom = get_current_atom_locked(); - grabbed2flush_reserved_nolock (atom, count); + grabbed2flush_reserved_nolock(atom, count); - UNLOCK_ATOM (atom); + UNLOCK_ATOM(atom); } -reiser4_internal void flush_reserved2grabbed(txn_atom * atom, __u64 count) +void flush_reserved2grabbed(txn_atom * atom, __u64 count) { reiser4_context *ctx; reiser4_super_info_data *sbinfo; @@ -877,21 +859,20 @@ reiser4_internal void flush_reserved2gra add_to_ctx_grabbed(ctx, count); - sub_from_atom_flush_reserved_nolock(atom, (__u32)count); + sub_from_atom_flush_reserved_nolock(atom, (__u32) count); reiser4_spin_lock_sb(sbinfo); sbinfo->blocks_grabbed += count; sub_from_sb_flush_reserved(sbinfo, count); - assert ("vpf-292", check_block_counters (ctx->super)); + assert("vpf-292", check_block_counters(ctx->super)); - reiser4_spin_unlock_sb (sbinfo); + reiser4_spin_unlock_sb(sbinfo); } /* release all blocks grabbed in context which where not used. */ -reiser4_internal void -all_grabbed2free(void) +void all_grabbed2free(void) { reiser4_context *ctx = get_current_context(); @@ -901,7 +882,8 @@ all_grabbed2free(void) /* adjust sb block counters if real (on-disk) blocks do not become unallocated after freeing, @count blocks become "grabbed". */ static void -used2grabbed(reiser4_context *ctx, reiser4_super_info_data *sbinfo, __u64 count) +used2grabbed(reiser4_context * ctx, reiser4_super_info_data * sbinfo, + __u64 count) { add_to_ctx_grabbed(ctx, count); @@ -916,8 +898,7 @@ used2grabbed(reiser4_context *ctx, reise } /* this used to be done through used2grabbed and grabbed2free*/ -static void -used2free(reiser4_super_info_data *sbinfo, __u64 count) +static void used2free(reiser4_super_info_data * sbinfo, __u64 count) { reiser4_spin_lock_sb(sbinfo); @@ -933,14 +914,14 @@ used2free(reiser4_super_info_data *sbinf /* check "allocated" state of given block range */ static void -reiser4_check_blocks(const reiser4_block_nr * start, const reiser4_block_nr * len, int desired) +reiser4_check_blocks(const reiser4_block_nr * start, + const reiser4_block_nr * len, int desired) { sa_check_blocks(start, len, desired); } /* check "allocated" state of given block */ -void -reiser4_check_block(const reiser4_block_nr * block, int desired) +void reiser4_check_block(const reiser4_block_nr * block, int desired) { const reiser4_block_nr one = 1; @@ -961,7 +942,7 @@ reiser4_check_block(const reiser4_block_ /* BA_FORMATTED bit is only used when BA_DEFER in not present: it is used to distinguish blocks allocated for unformatted and formatted nodes */ -reiser4_internal int +int reiser4_dealloc_blocks(const reiser4_block_nr * start, const reiser4_block_nr * len, block_stage_t target_stage, reiser4_ba_flags_t flags) @@ -993,7 +974,9 @@ reiser4_dealloc_blocks(const reiser4_blo atom = get_current_atom_locked(); assert("zam-430", atom != NULL); - ret = blocknr_set_add_extent(atom, &atom->delete_set, &bsep, start, len); + ret = + blocknr_set_add_extent(atom, &atom->delete_set, + &bsep, start, len); if (ret == -ENOMEM) return ret; @@ -1008,14 +991,15 @@ reiser4_dealloc_blocks(const reiser4_blo } else { assert("zam-425", get_current_super_private() != NULL); - sa_dealloc_blocks(get_space_allocator(ctx->super), *start, *len); + sa_dealloc_blocks(get_space_allocator(ctx->super), *start, + *len); if (flags & BA_PERMANENT) { /* These blocks were counted as allocated, we have to revert it * back if allocation is discarded. */ - txn_atom * atom = get_current_atom_locked (); + txn_atom *atom = get_current_atom_locked(); atom->nr_blocks_allocated -= *len; - UNLOCK_ATOM (atom); + UNLOCK_ATOM(atom); } switch (target_stage) { @@ -1033,14 +1017,15 @@ reiser4_dealloc_blocks(const reiser4_blo used2fake_allocated(sbinfo, *len, flags & BA_FORMATTED); break; - case BLOCK_FLUSH_RESERVED: { - txn_atom *atom; + case BLOCK_FLUSH_RESERVED:{ + txn_atom *atom; - atom = get_current_atom_locked(); - used2flush_reserved(sbinfo, atom, *len, flags & BA_FORMATTED); - UNLOCK_ATOM(atom); - break; - } + atom = get_current_atom_locked(); + used2flush_reserved(sbinfo, atom, *len, + flags & BA_FORMATTED); + UNLOCK_ATOM(atom); + break; + } default: impossible("zam-532", "wrong block stage"); } @@ -1050,8 +1035,7 @@ reiser4_dealloc_blocks(const reiser4_blo } /* wrappers for block allocator plugin methods */ -reiser4_internal int -pre_commit_hook(void) +int pre_commit_hook(void) { assert("zam-502", get_current_super_private() != NULL); sa_pre_commit_hook(); @@ -1060,7 +1044,8 @@ pre_commit_hook(void) /* an actor which applies delete set to block allocator data */ static int -apply_dset(txn_atom * atom UNUSED_ARG, const reiser4_block_nr * a, const reiser4_block_nr * b, void *data UNUSED_ARG) +apply_dset(txn_atom * atom UNUSED_ARG, const reiser4_block_nr * a, + const reiser4_block_nr * b, void *data UNUSED_ARG) { reiser4_context *ctx; reiser4_super_info_data *sbinfo; @@ -1091,8 +1076,7 @@ apply_dset(txn_atom * atom UNUSED_ARG, c return 0; } -reiser4_internal void -post_commit_hook(void) +void post_commit_hook(void) { txn_atom *atom; @@ -1108,8 +1092,7 @@ post_commit_hook(void) sa_post_commit_hook(); } -reiser4_internal void -post_write_back_hook(void) +void post_write_back_hook(void) { assert("zam-504", get_current_super_private() != NULL); diff -puN fs/reiser4/block_alloc.h~reiser4-big-update fs/reiser4/block_alloc.h --- devel/fs/reiser4/block_alloc.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/block_alloc.h 2005-09-15 19:51:08.000000000 -0700 @@ -22,15 +22,15 @@ /* specification how block allocation was counted in sb block counters */ typedef enum { - BLOCK_NOT_COUNTED = 0, /* reiser4 has no info about this block yet */ - BLOCK_GRABBED = 1, /* free space grabbed for further allocation - of this block */ - BLOCK_FLUSH_RESERVED = 2, /* block is reserved for flush needs. */ - BLOCK_UNALLOCATED = 3, /* block is used for existing in-memory object - ( unallocated formatted or unformatted - node) */ - BLOCK_ALLOCATED = 4 /* block is mapped to disk, real on-disk block - number assigned */ + BLOCK_NOT_COUNTED = 0, /* reiser4 has no info about this block yet */ + BLOCK_GRABBED = 1, /* free space grabbed for further allocation + of this block */ + BLOCK_FLUSH_RESERVED = 2, /* block is reserved for flush needs. */ + BLOCK_UNALLOCATED = 3, /* block is used for existing in-memory object + ( unallocated formatted or unformatted + node) */ + BLOCK_ALLOCATED = 4 /* block is mapped to disk, real on-disk block + number assigned */ } block_stage_t; /* a hint for block allocator */ @@ -51,30 +51,30 @@ struct reiser4_blocknr_hint { block_stage_t block_stage; /* If direction = 1 allocate blocks in backward direction from the end * of disk to the beginning of disk. */ - int backward:1; + unsigned int backward:1; }; /* These flags control block allocation/deallocation behavior */ enum reiser4_ba_flags { /* do allocatations from reserved (5%) area */ - BA_RESERVED = (1 << 0), + BA_RESERVED = (1 << 0), /* block allocator can do commit trying to recover free space */ - BA_CAN_COMMIT = (1 << 1), + BA_CAN_COMMIT = (1 << 1), /* if operation will be applied to formatted block */ - BA_FORMATTED = (1 << 2), + BA_FORMATTED = (1 << 2), /* defer actual block freeing until transaction commit */ - BA_DEFER = (1 << 3), + BA_DEFER = (1 << 3), /* allocate blocks for permanent fs objects (formatted or unformatted), not wandered of log blocks */ - BA_PERMANENT = (1 << 4), + BA_PERMANENT = (1 << 4), /* grab space even it was disabled */ - BA_FORCE = (1 << 5), + BA_FORCE = (1 << 5), /* use default start value for free blocks search. */ BA_USE_DEFAULT_SEARCH_START = (1 << 6) @@ -84,41 +84,41 @@ typedef enum reiser4_ba_flags reiser4_ba extern void blocknr_hint_init(reiser4_blocknr_hint * hint); extern void blocknr_hint_done(reiser4_blocknr_hint * hint); -extern void update_blocknr_hint_default(const struct super_block *, const reiser4_block_nr *); +extern void update_blocknr_hint_default(const struct super_block *, + const reiser4_block_nr *); extern void get_blocknr_hint_default(reiser4_block_nr *); -extern reiser4_block_nr reiser4_fs_reserved_space(struct super_block * super); +extern reiser4_block_nr reiser4_fs_reserved_space(struct super_block *super); int assign_fake_blocknr_formatted(reiser4_block_nr *); reiser4_block_nr fake_blocknr_unformatted(void); - /* free -> grabbed -> fake_allocated -> used */ - -int reiser4_grab_space (__u64 count, reiser4_ba_flags_t flags); -void all_grabbed2free (void); -void grabbed2free (reiser4_context *, - reiser4_super_info_data *, __u64 count); -void fake_allocated2free (__u64 count, reiser4_ba_flags_t flags); +int reiser4_grab_space(__u64 count, reiser4_ba_flags_t flags); +void all_grabbed2free(void); +void grabbed2free(reiser4_context *, reiser4_super_info_data *, __u64 count); +void fake_allocated2free(__u64 count, reiser4_ba_flags_t flags); void grabbed2flush_reserved_nolock(txn_atom * atom, __u64 count); -void grabbed2flush_reserved (__u64 count); -int reiser4_alloc_blocks (reiser4_blocknr_hint * hint, - reiser4_block_nr * start, - reiser4_block_nr * len, - reiser4_ba_flags_t flags); -int reiser4_dealloc_blocks (const reiser4_block_nr *, - const reiser4_block_nr *, - block_stage_t, reiser4_ba_flags_t flags); - -static inline int reiser4_alloc_block (reiser4_blocknr_hint * hint, reiser4_block_nr * start, - reiser4_ba_flags_t flags) +void grabbed2flush_reserved(__u64 count); +int reiser4_alloc_blocks(reiser4_blocknr_hint * hint, + reiser4_block_nr * start, + reiser4_block_nr * len, reiser4_ba_flags_t flags); +int reiser4_dealloc_blocks(const reiser4_block_nr *, + const reiser4_block_nr *, + block_stage_t, reiser4_ba_flags_t flags); + +static inline int reiser4_alloc_block(reiser4_blocknr_hint * hint, + reiser4_block_nr * start, + reiser4_ba_flags_t flags) { reiser4_block_nr one = 1; return reiser4_alloc_blocks(hint, start, &one, flags); } -static inline int reiser4_dealloc_block (const reiser4_block_nr * block, block_stage_t stage, reiser4_ba_flags_t flags) +static inline int reiser4_dealloc_block(const reiser4_block_nr * block, + block_stage_t stage, + reiser4_ba_flags_t flags) { const reiser4_block_nr one = 1; return reiser4_dealloc_blocks(block, &one, stage, flags); @@ -128,8 +128,8 @@ static inline int reiser4_dealloc_block reiser4_grab_space(count, flags | BA_FORCE) extern void grabbed2free_mark(__u64 mark); -extern int reiser4_grab_reserved(struct super_block *, - __u64, reiser4_ba_flags_t); +extern int reiser4_grab_reserved(struct super_block *, + __u64, reiser4_ba_flags_t); extern void reiser4_release_reserved(struct super_block *super); /* grabbed -> fake_allocated */ diff -puN fs/reiser4/blocknrset.c~reiser4-big-update fs/reiser4/blocknrset.c --- devel/fs/reiser4/blocknrset.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/blocknrset.c 2005-09-15 19:51:08.000000000 -0700 @@ -5,7 +5,6 @@ #include "debug.h" #include "dformat.h" -#include "type_safe_list.h" #include "txnmgr.h" #include @@ -34,17 +33,17 @@ typedef struct blocknr_pair blocknr_pair #define BLOCKNR_SET_ENTRY_SIZE 128 /* The number of blocks that can fit the blocknr data area. */ -#define BLOCKNR_SET_ENTRIES_NUMBER \ - ((BLOCKNR_SET_ENTRY_SIZE - \ - 2 * sizeof (unsigned) - \ - sizeof (blocknr_set_list_link)) / \ - sizeof (reiser4_block_nr)) +#define BLOCKNR_SET_ENTRIES_NUMBER \ + ((BLOCKNR_SET_ENTRY_SIZE - \ + 2 * sizeof (unsigned) - \ + sizeof(struct list_head)) / \ + sizeof(reiser4_block_nr)) /* An entry of the blocknr_set */ struct blocknr_set_entry { unsigned nr_singles; unsigned nr_pairs; - blocknr_set_list_link link; + struct list_head link; reiser4_block_nr entries[BLOCKNR_SET_ENTRIES_NUMBER]; }; @@ -54,42 +53,35 @@ struct blocknr_pair { reiser4_block_nr b; }; -/* The list definition. */ -TYPE_SAFE_LIST_DEFINE(blocknr_set, blocknr_set_entry, link); - /* Return the number of blocknr slots available in a blocknr_set_entry. */ /* Audited by: green(2002.06.11) */ -static unsigned -bse_avail(blocknr_set_entry * bse) +static unsigned bse_avail(blocknr_set_entry * bse) { unsigned used = bse->nr_singles + 2 * bse->nr_pairs; assert("jmacd-5088", BLOCKNR_SET_ENTRIES_NUMBER >= used); - cassert(sizeof (blocknr_set_entry) == BLOCKNR_SET_ENTRY_SIZE); + cassert(sizeof(blocknr_set_entry) == BLOCKNR_SET_ENTRY_SIZE); return BLOCKNR_SET_ENTRIES_NUMBER - used; } /* Initialize a blocknr_set_entry. */ -/* Audited by: green(2002.06.11) */ -static void -bse_init(blocknr_set_entry * bse) +static void bse_init(blocknr_set_entry *bse) { bse->nr_singles = 0; bse->nr_pairs = 0; - blocknr_set_list_clean(bse); + INIT_LIST_HEAD(&bse->link); } /* Allocate and initialize a blocknr_set_entry. */ /* Audited by: green(2002.06.11) */ -static blocknr_set_entry * -bse_alloc(void) +static blocknr_set_entry *bse_alloc(void) { blocknr_set_entry *e; - if ((e = (blocknr_set_entry *) kmalloc(sizeof (blocknr_set_entry), GFP_KERNEL)) == NULL) { + if ((e = (blocknr_set_entry *) kmalloc(sizeof(blocknr_set_entry), + GFP_KERNEL)) == NULL) return NULL; - } bse_init(e); @@ -98,8 +90,7 @@ bse_alloc(void) /* Free a blocknr_set_entry. */ /* Audited by: green(2002.06.11) */ -static void -bse_free(blocknr_set_entry * bse) +static void bse_free(blocknr_set_entry * bse) { kfree(bse); } @@ -116,18 +107,19 @@ bse_put_single(blocknr_set_entry * bse, /* Get a pair of block numbers */ /* Audited by: green(2002.06.11) */ -static inline blocknr_pair * -bse_get_pair(blocknr_set_entry * bse, unsigned pno) +static inline blocknr_pair *bse_get_pair(blocknr_set_entry * bse, unsigned pno) { assert("green-1", BLOCKNR_SET_ENTRIES_NUMBER >= 2 * (pno + 1)); - return (blocknr_pair *) (bse->entries + BLOCKNR_SET_ENTRIES_NUMBER - 2 * (pno + 1)); + return (blocknr_pair *) (bse->entries + BLOCKNR_SET_ENTRIES_NUMBER - + 2 * (pno + 1)); } /* Add a pair of block numbers to a blocknr_set_entry */ /* Audited by: green(2002.06.11) */ static void -bse_put_pair(blocknr_set_entry * bse, const reiser4_block_nr * a, const reiser4_block_nr * b) +bse_put_pair(blocknr_set_entry * bse, const reiser4_block_nr * a, + const reiser4_block_nr * b) { blocknr_pair *pair; @@ -150,11 +142,9 @@ bse_put_pair(blocknr_set_entry * bse, co returned with the atom unlocked for the operation to be tried again. If the operation succeeds, 0 is returned. If new_bsep is non-NULL and not used during the call, it will be freed automatically. */ -/* Audited by: green(2002.06.11) */ -static int -blocknr_set_add(txn_atom * atom, - blocknr_set * bset, - blocknr_set_entry ** new_bsep, const reiser4_block_nr * a, const reiser4_block_nr * b) +static int blocknr_set_add(txn_atom *atom, blocknr_set *bset, + blocknr_set_entry **new_bsep, const reiser4_block_nr *a, + const reiser4_block_nr *b) { blocknr_set_entry *bse; unsigned entries_needed; @@ -162,23 +152,24 @@ blocknr_set_add(txn_atom * atom, assert("jmacd-5101", a != NULL); entries_needed = (b == NULL) ? 1 : 2; - if (blocknr_set_list_empty(&bset->entries) || bse_avail(blocknr_set_list_front(&bset->entries)) - < entries_needed) { + if (list_empty(&bset->entries) || + bse_avail(list_entry(bset->entries.next, blocknr_set_entry, link)) < entries_needed) { /* See if a bse was previously allocated. */ if (*new_bsep == NULL) { UNLOCK_ATOM(atom); *new_bsep = bse_alloc(); - return (*new_bsep != NULL) ? -E_REPEAT : RETERR(-ENOMEM); + return (*new_bsep != NULL) ? -E_REPEAT : + RETERR(-ENOMEM); } /* Put it on the head of the list. */ - blocknr_set_list_push_front(&bset->entries, *new_bsep); + list_add(&((*new_bsep)->link), &bset->entries); *new_bsep = NULL; } /* Add the single or pair. */ - bse = blocknr_set_list_front(&bset->entries); + bse = list_entry(bset->entries.next, blocknr_set_entry, link); if (b == NULL) { bse_put_single(bse, a); } else { @@ -200,13 +191,16 @@ blocknr_set_add(txn_atom * atom, /* Auditor note: Entire call chain cannot hold any spinlocks, because kmalloc might schedule. The only exception is atom spinlock, which is properly freed. */ -reiser4_internal int +int blocknr_set_add_extent(txn_atom * atom, blocknr_set * bset, - blocknr_set_entry ** new_bsep, const reiser4_block_nr * start, const reiser4_block_nr * len) + blocknr_set_entry ** new_bsep, + const reiser4_block_nr * start, + const reiser4_block_nr * len) { assert("jmacd-5102", start != NULL && len != NULL && *len > 0); - return blocknr_set_add(atom, bset, new_bsep, start, *len == 1 ? NULL : len); + return blocknr_set_add(atom, bset, new_bsep, start, + *len == 1 ? NULL : len); } /* Add a block pair to the block set. It adds exactly a pair, which is checked @@ -215,30 +209,31 @@ blocknr_set_add_extent(txn_atom * atom, /* Auditor note: Entire call chain cannot hold any spinlocks, because kmalloc might schedule. The only exception is atom spinlock, which is properly freed. */ -reiser4_internal int +int blocknr_set_add_pair(txn_atom * atom, blocknr_set * bset, - blocknr_set_entry ** new_bsep, const reiser4_block_nr * a, const reiser4_block_nr * b) + blocknr_set_entry ** new_bsep, const reiser4_block_nr * a, + const reiser4_block_nr * b) { assert("jmacd-5103", a != NULL && b != NULL); return blocknr_set_add(atom, bset, new_bsep, a, b); } /* Initialize a blocknr_set. */ -/* Audited by: green(2002.06.11) */ -reiser4_internal void -blocknr_set_init(blocknr_set * bset) +void blocknr_set_init(blocknr_set *bset) { - blocknr_set_list_init(&bset->entries); + INIT_LIST_HEAD(&bset->entries); } /* Release the entries of a blocknr_set. */ -/* Audited by: green(2002.06.11) */ -reiser4_internal void -blocknr_set_destroy(blocknr_set * bset) +void blocknr_set_destroy(blocknr_set *bset) { - while (!blocknr_set_list_empty(&bset->entries)) { - bse_free(blocknr_set_list_pop_front(&bset->entries)); + blocknr_set_entry *bse; + + while (!list_empty_careful(&bset->entries)) { + bse = list_entry(bset->entries.next, blocknr_set_entry, link); + list_del_init(&bse->link); + bse_free(bse); } } @@ -252,34 +247,41 @@ blocknr_set_destroy(blocknr_set * bset) actual processing of this set. Testing this kind of stuff right here is also complicated by the fact that these sets are not sorted and going through whole set on each element addition is going to be CPU-heavy task */ -reiser4_internal void -blocknr_set_merge(blocknr_set * from, blocknr_set * into) +void blocknr_set_merge(blocknr_set * from, blocknr_set * into) { blocknr_set_entry *bse_into = NULL; /* If @from is empty, no work to perform. */ - if (blocknr_set_list_empty(&from->entries)) { + if (list_empty_careful(&from->entries)) { return; } /* If @into is not empty, try merging partial-entries. */ - if (!blocknr_set_list_empty(&into->entries)) { + if (!list_empty_careful(&into->entries)) { /* Neither set is empty, pop the front to members and try to combine them. */ blocknr_set_entry *bse_from; unsigned into_avail; - bse_into = blocknr_set_list_pop_front(&into->entries); - bse_from = blocknr_set_list_pop_front(&from->entries); + bse_into = list_entry(into->entries.next, blocknr_set_entry, link); + list_del_init(&bse_into->link); + bse_from = list_entry(from->entries.next, blocknr_set_entry, link); + list_del_init(&bse_from->link); /* Combine singles. */ - for (into_avail = bse_avail(bse_into); into_avail != 0 && bse_from->nr_singles != 0; into_avail -= 1) { - bse_put_single(bse_into, &bse_from->entries[--bse_from->nr_singles]); + for (into_avail = bse_avail(bse_into); + into_avail != 0 && bse_from->nr_singles != 0; + into_avail -= 1) { + bse_put_single(bse_into, + &bse_from->entries[--bse_from-> + nr_singles]); } /* Combine pairs. */ - for (; into_avail > 1 && bse_from->nr_pairs != 0; into_avail -= 2) { - blocknr_pair *pair = bse_get_pair(bse_from, --bse_from->nr_pairs); + for (; into_avail > 1 && bse_from->nr_pairs != 0; + into_avail -= 2) { + blocknr_pair *pair = + bse_get_pair(bse_from, --bse_from->nr_pairs); bse_put_pair(bse_into, &pair->a, &pair->b); } @@ -291,23 +293,24 @@ blocknr_set_merge(blocknr_set * from, bl it could have one slot avail and bse_from has one pair left). Push it back onto the list. bse_from becomes bse_into, which will be the new partial. */ - blocknr_set_list_push_front(&into->entries, bse_into); + list_add(&bse_into->link, &into->entries); bse_into = bse_from; } } /* Splice lists together. */ - blocknr_set_list_splice(&into->entries, &from->entries); + list_splice(&from->entries, &into->entries); + INIT_LIST_HEAD(&from->entries); /* Add the partial entry back to the head of the list. */ if (bse_into != NULL) { - blocknr_set_list_push_front(&into->entries, bse_into); + list_add(&bse_into->link, &into->entries); } } /* Iterate over all blocknr set elements. */ -reiser4_internal int -blocknr_set_iterator(txn_atom * atom, blocknr_set * bset, blocknr_set_actor_f actor, void *data, int delete) +int blocknr_set_iterator(txn_atom *atom, blocknr_set *bset, + blocknr_set_actor_f actor, void *data, int delete) { blocknr_set_entry *entry; @@ -317,9 +320,9 @@ blocknr_set_iterator(txn_atom * atom, bl assert("zam-431", bset != 0); assert("zam-432", actor != NULL); - entry = blocknr_set_list_front(&bset->entries); - while (!blocknr_set_list_end(&bset->entries, entry)) { - blocknr_set_entry *tmp = blocknr_set_list_next(entry); + entry = list_entry(bset->entries.next, blocknr_set_entry, link); + while (&bset->entries != &entry->link) { + blocknr_set_entry *tmp = list_entry(entry->link.next, blocknr_set_entry, link); unsigned int i; int ret; @@ -343,7 +346,7 @@ blocknr_set_iterator(txn_atom * atom, bl } if (delete) { - blocknr_set_list_remove(entry); + list_del(&entry->link); bse_free(entry); } @@ -354,12 +357,12 @@ blocknr_set_iterator(txn_atom * atom, bl } /* - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - scroll-step: 1 - End: -*/ + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 79 + * scroll-step: 1 + * End: + */ diff -puN fs/reiser4/carry.c~reiser4-big-update fs/reiser4/carry.c --- devel/fs/reiser4/carry.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/carry.c 2005-09-15 19:51:08.000000000 -0700 @@ -38,7 +38,6 @@ USAGE: - int some_tree_operation( znode *node, ... ) { // Allocate on a stack pool of carry objects: operations and nodes. @@ -161,7 +160,8 @@ int lock_carry_node_tail(carry_node * no /* carry processing proper */ static int carry_on_level(carry_level * doing, carry_level * todo); -static carry_op *add_op(carry_level * level, pool_ordering order, carry_op * reference); +static carry_op *add_op(carry_level * level, pool_ordering order, + carry_op * reference); /* handlers for carry operations. */ @@ -180,19 +180,16 @@ typedef enum { static int carry_level_invariant(carry_level * level, carry_queue_state state); #endif -static int -perthread_pages_reserve(int nrpages, int gfp) +static int perthread_pages_reserve(int nrpages, int gfp) { return 0; } -static void -perthread_pages_release(int nrpages) +static void perthread_pages_release(int nrpages) { } -static int -perthread_pages_count(void) +static int perthread_pages_count(void) { return 0; } @@ -208,29 +205,26 @@ perthread_pages_count(void) For usage, see comment at the top of fs/reiser4/carry.c */ -reiser4_internal int -carry(carry_level * doing /* set of carry operations to be performed */ , - carry_level * done /* set of nodes, already performed at the +int carry(carry_level * doing /* set of carry operations to be performed */ , + carry_level * done /* set of nodes, already performed at the * previous level. NULL in most cases */ ) { int result = 0; - carry_level done_area; - carry_level todo_area; /* queue of new requests */ carry_level *todo; int wasreserved; int reserve; - ON_DEBUG(STORE_COUNTERS;) + ON_DEBUG(STORE_COUNTERS); assert("nikita-888", doing != NULL); + BUG_ON(done != NULL); - todo = &todo_area; + todo = doing + 1; init_carry_level(todo, doing->pool); - if (done == NULL) { - /* queue of requests performed on the previous level */ - done = &done_area; - init_carry_level(done, doing->pool); - } + + /* queue of requests preformed on the previous level */ + done = todo + 1; + init_carry_level(done, doing->pool); wasreserved = perthread_pages_count(); reserve = carry_estimate_reserve(doing); @@ -253,7 +247,7 @@ carry(carry_level * doing /* set of carr (3) some unexpected error occurred while balancing on the upper levels. In this case all changes are rolled back. - */ + */ while (1) { result = lock_carry_level(doing); if (result == 0) { @@ -274,7 +268,7 @@ carry(carry_level * doing /* set of carr all pending transcrashes and thus pushing tree back to the consistent state. Alternatvely, just panic. - */ + */ fatal_carry_error(doing, result); return result; } @@ -304,7 +298,7 @@ carry(carry_level * doing /* set of carr /* all counters, but x_refs should remain the same. x_refs can change owing to transaction manager */ - ON_DEBUG(CHECK_COUNTERS;) + ON_DEBUG(CHECK_COUNTERS); return result; } @@ -321,14 +315,13 @@ carry(carry_level * doing /* set of carr node and counter and operations carried upward from this node. */ -static int -carry_on_level(carry_level * doing /* queue of carry operations to - * do on this level */ , - carry_level * todo /* queue where new carry - * operations to be performed on - * the * parent level are - * accumulated during @doing - * processing. */ ) +static int carry_on_level(carry_level * doing /* queue of carry operations to + * do on this level */ , + carry_level * todo /* queue where new carry + * operations to be performed on + * the * parent level are + * accumulated during @doing + * processing. */ ) { int result; int (*f) (carry_op *, carry_level *, carry_level *); @@ -353,7 +346,7 @@ carry_on_level(carry_level * doing /* qu more efficiently when batched together. Above is an optimization left for the future. - */ + */ /* Important, but delayed optimization: it's possible to batch operations together and perform them more efficiently as a result. For example, deletion of several neighboring items from a @@ -361,7 +354,7 @@ carry_on_level(carry_level * doing /* qu Before processing queue, it should be scanned and "mergeable" operations merged. - */ + */ result = 0; for_all_ops(doing, op, tmp_op) { carry_opcode opcode; @@ -373,7 +366,7 @@ carry_on_level(carry_level * doing /* qu result = f(op, doing, todo); /* locking can fail with -E_REPEAT. Any different error is fatal and will be handled by fatal_carry_error() sledgehammer. - */ + */ if (result != 0) break; } @@ -385,14 +378,17 @@ carry_on_level(carry_level * doing /* qu info.doing = doing; info.todo = todo; - assert("nikita-3002", carry_level_invariant(doing, CARRY_DOING)); + assert("nikita-3002", + carry_level_invariant(doing, CARRY_DOING)); for_all_nodes(doing, scan, tmp_scan) { znode *node; node = carry_real(scan); assert("nikita-2547", node != NULL); if (node_is_empty(node)) { - result = node_plugin_by_node(node)->prepare_removal(node, &info); + result = + node_plugin_by_node(node)-> + prepare_removal(node, &info); if (result != 0) break; } @@ -415,15 +411,14 @@ carry_on_level(carry_level * doing /* qu caller to guarantee proper ordering of node queue. */ -reiser4_internal carry_op * -post_carry(carry_level * level /* queue where new operation is to - * be posted at */ , - carry_opcode op /* opcode of operation */ , - znode * node /* node on which this operation - * will operate */ , - int apply_to_parent_p /* whether operation will operate - * directly on @node or on it - * parent. */ ) +carry_op *post_carry(carry_level * level /* queue where new operation is to + * be posted at */ , + carry_opcode op /* opcode of operation */ , + znode * node /* node on which this operation + * will operate */ , + int apply_to_parent_p /* whether operation will operate + * directly on @node or on it + * parent. */ ) { carry_op *result; carry_node *child; @@ -448,10 +443,9 @@ post_carry(carry_level * level /* queue return result; } -/* initialise carry queue */ -reiser4_internal void -init_carry_level(carry_level * level /* level to initialise */ , - carry_pool * pool /* pool @level will allocate objects +/* initialize carry queue */ +void init_carry_level(carry_level * level /* level to initialize */ , + carry_pool * pool /* pool @level will allocate objects * from */ ) { assert("nikita-1045", level != NULL); @@ -460,28 +454,29 @@ init_carry_level(carry_level * level /* memset(level, 0, sizeof *level); level->pool = pool; - pool_level_list_init(&level->nodes); - pool_level_list_init(&level->ops); + INIT_LIST_HEAD(&level->nodes); + INIT_LIST_HEAD(&level->ops); } -/* allocate carry pool and initialise pools within queue */ -reiser4_internal carry_pool * -init_carry_pool(void) +/* allocate carry pool and initialize pools within queue */ +carry_pool *init_carry_pool(int size) { - carry_pool * pool; + carry_pool *pool; - pool = kmalloc(sizeof(carry_pool), GFP_KERNEL); + assert("", size >= sizeof(carry_pool) + 3 * sizeof(carry_level)); + pool = kmalloc(size, GFP_KERNEL); if (pool == NULL) return ERR_PTR(RETERR(-ENOMEM)); - reiser4_init_pool(&pool->op_pool, sizeof (carry_op), CARRIES_POOL_SIZE, (char *) pool->op); - reiser4_init_pool(&pool->node_pool, sizeof (carry_node), NODES_LOCKED_POOL_SIZE, (char *) pool->node); + reiser4_init_pool(&pool->op_pool, sizeof(carry_op), CARRIES_POOL_SIZE, + (char *)pool->op); + reiser4_init_pool(&pool->node_pool, sizeof(carry_node), + NODES_LOCKED_POOL_SIZE, (char *)pool->node); return pool; } /* finish with queue pools */ -reiser4_internal void -done_carry_pool(carry_pool * pool /* pool to destroy */ ) +void done_carry_pool(carry_pool * pool /* pool to destroy */ ) { reiser4_done_pool(&pool->op_pool); reiser4_done_pool(&pool->node_pool); @@ -497,31 +492,34 @@ done_carry_pool(carry_pool * pool /* poo automatically. To control ordering use @order and @reference parameters. */ -reiser4_internal carry_node * -add_carry_skip(carry_level * level /* &carry_level to add node - * to */ , - pool_ordering order /* where to insert: at the - * beginning of @level, - * before @reference, after - * @reference, at the end - * of @level */ , - carry_node * reference /* reference node for - * insertion */ ) +carry_node *add_carry_skip(carry_level * level /* &carry_level to add node + * to */ , + pool_ordering order /* where to insert: at the + * beginning of @level, + * before @reference, after + * @reference, at the end + * of @level */ , + carry_node * reference /* reference node for + * insertion */ ) { ON_DEBUG(carry_node * orig_ref = reference); if (order == POOLO_BEFORE) { reference = find_left_carry(reference, level); if (reference == NULL) - reference = carry_node_front(level); + reference = list_entry(level->nodes.next, carry_node, + header.level_linkage); else - reference = carry_node_next(reference); + reference = list_entry(reference->header.level_linkage.next, + carry_node, header.level_linkage); } else if (order == POOLO_AFTER) { reference = find_right_carry(reference, level); if (reference == NULL) - reference = carry_node_back(level); + reference = list_entry(level->nodes.prev, carry_node, + header.level_linkage); else - reference = carry_node_prev(reference); + reference = list_entry(reference->header.level_linkage.prev, + carry_node, header.level_linkage); } assert("nikita-2209", ergo(orig_ref != NULL, @@ -529,19 +527,20 @@ add_carry_skip(carry_level * level /* &c return add_carry(level, order, reference); } -reiser4_internal carry_node * -add_carry(carry_level * level /* &carry_level to add node - * to */ , - pool_ordering order /* where to insert: at the - * beginning of @level, before - * @reference, after @reference, - * at the end of @level */ , - carry_node * reference /* reference node for - * insertion */ ) +carry_node *add_carry(carry_level * level /* &carry_level to add node + * to */ , + pool_ordering order /* where to insert: at the + * beginning of @level, before + * @reference, after @reference, + * at the end of @level */ , + carry_node * reference /* reference node for + * insertion */ ) { carry_node *result; - result = (carry_node *) add_obj(&level->pool->node_pool, &level->nodes, order, &reference->header); + result = + (carry_node *) add_obj(&level->pool->node_pool, &level->nodes, + order, &reference->header); if (!IS_ERR(result) && (result != NULL)) ++level->nodes_num; return result; @@ -554,16 +553,18 @@ add_carry(carry_level * level /* &carry_ @order and @reference parameters. */ -static carry_op * -add_op(carry_level * level /* &carry_level to add node to */ , - pool_ordering order /* where to insert: at the beginning of - * @level, before @reference, after - * @reference, at the end of @level */ , - carry_op * reference /* reference node for insertion */ ) +static carry_op *add_op(carry_level * level /* &carry_level to add node to */ , + pool_ordering order /* where to insert: at the beginning of + * @level, before @reference, after + * @reference, at the end of @level */ , + carry_op * + reference /* reference node for insertion */ ) { carry_op *result; - result = (carry_op *) add_obj(&level->pool->op_pool, &level->ops, order, &reference->header); + result = + (carry_op *) add_obj(&level->pool->op_pool, &level->ops, order, + &reference->header); if (!IS_ERR(result) && (result != NULL)) ++level->ops_num; return result; @@ -578,11 +579,10 @@ add_op(carry_level * level /* &carry_lev parent, it has corresponding bit (JNODE_ORPHAN) set in zstate. */ -static carry_node * -find_begetting_brother(carry_node * node /* node to start search - * from */ , - carry_level * kin UNUSED_ARG /* level to - * scan */ ) +static carry_node *find_begetting_brother(carry_node * node /* node to start search + * from */ , + carry_level * kin UNUSED_ARG /* level to + * scan */ ) { carry_node *scan; @@ -592,9 +592,12 @@ find_begetting_brother(carry_node * node assert("nikita-1619", ergo(carry_real(node) != NULL, ZF_ISSET(carry_real(node), JNODE_ORPHAN))); - for (scan = node;; scan = carry_node_prev(scan)) { - assert("nikita-1617", !carry_node_end(kin, scan)); - if ((scan->node != node->node) && !ZF_ISSET(scan->node, JNODE_ORPHAN)) { + for (scan = node;; + scan = list_entry(scan->header.level_linkage.prev, carry_node, + header.level_linkage)) { + assert("nikita-1617", &kin->nodes != &scan->header.level_linkage); + if ((scan->node != node->node) && + !ZF_ISSET(scan->node, JNODE_ORPHAN)) { assert("nikita-1618", carry_real(scan) != NULL); break; } @@ -620,8 +623,7 @@ carry_node_cmp(carry_level * level, carr impossible("nikita-2201", "End of level reached"); } -reiser4_internal carry_node * -find_carry_node(carry_level * level, const znode * node) +carry_node *find_carry_node(carry_level * level, const znode * node) { carry_node *scan; carry_node *tmp_scan; @@ -636,16 +638,15 @@ find_carry_node(carry_level * level, con return NULL; } -reiser4_internal znode * -carry_real(const carry_node * node) +znode *carry_real(const carry_node * node) { assert("nikita-3061", node != NULL); return node->lock_handle.node; } -reiser4_internal carry_node * -insert_carry_node(carry_level * doing, carry_level * todo, const znode * node) +carry_node *insert_carry_node(carry_level * doing, carry_level * todo, + const znode * node) { carry_node *base; carry_node *scan; @@ -664,8 +665,8 @@ insert_carry_node(carry_level * doing, c return scan; } -static carry_node * -add_carry_atplace(carry_level *doing, carry_level *todo, znode *node) +static carry_node *add_carry_atplace(carry_level * doing, carry_level * todo, + znode * node) { carry_node *reference; @@ -682,16 +683,15 @@ add_carry_atplace(carry_level *doing, ca /* like post_carry(), but designed to be called from node plugin methods. This function is different from post_carry() in that it finds proper place to insert node in the queue. */ -reiser4_internal carry_op * -node_post_carry(carry_plugin_info * info /* carry parameters - * passed down to node - * plugin */ , - carry_opcode op /* opcode of operation */ , - znode * node /* node on which this - * operation will operate */ , - int apply_to_parent_p /* whether operation will - * operate directly on @node - * or on it parent. */ ) +carry_op *node_post_carry(carry_plugin_info * info /* carry parameters + * passed down to node + * plugin */ , + carry_opcode op /* opcode of operation */ , + znode * node /* node on which this + * operation will operate */ , + int apply_to_parent_p /* whether operation will + * operate directly on @node + * or on it parent. */ ) { carry_op *result; carry_node *child; @@ -720,8 +720,7 @@ node_post_carry(carry_plugin_info * info } /* lock all carry nodes in @level */ -static int -lock_carry_level(carry_level * level /* level to lock */ ) +static int lock_carry_level(carry_level * level /* level to lock */ ) { int result; carry_node *node; @@ -751,10 +750,10 @@ lock_carry_level(carry_level * level /* */ -ON_DEBUG(extern atomic_t delim_key_version;) +ON_DEBUG(extern atomic_t delim_key_version; + ) -static void -sync_dkeys(znode *spot /* node to update */) +static void sync_dkeys(znode * spot /* node to update */ ) { reiser4_key pivot; reiser4_tree *tree; @@ -780,7 +779,7 @@ sync_dkeys(znode *spot /* node to update @spot. Scan them and update their left and right delimiting keys to match left delimiting key of @spot. Also, update right delimiting key of first non-empty left neighbor. - */ + */ while (1) { if (!ZF_ISSET(spot, JNODE_LEFT_CONNECTED)) break; @@ -789,15 +788,6 @@ sync_dkeys(znode *spot /* node to update if (spot == NULL) break; -#if 0 - /* on the leaf level we can only increase right delimiting key - * of a node on which we don't hold a long term lock. */ - assert("nikita-2930", - ergo(!znode_is_write_locked(spot) && - znode_get_level(spot) == LEAF_LEVEL, - keyge(&pivot, znode_get_rd_key(spot)))); -#endif - znode_set_rd_key(spot, &pivot); /* don't sink into the domain of another balancing */ if (!znode_is_write_locked(spot)) @@ -812,13 +802,10 @@ sync_dkeys(znode *spot /* node to update RUNLOCK_TREE(tree); } -ON_DEBUG(void check_dkeys(const znode *);) - /* unlock all carry nodes in @level */ -static void -unlock_carry_level(carry_level * level /* level to unlock */ , - int failure /* true if unlocking owing to - * failure */ ) +static void unlock_carry_level(carry_level * level /* level to unlock */ , + int failure /* true if unlocking owing to + * failure */ ) { carry_node *node; carry_node *tmp_node; @@ -841,7 +828,7 @@ unlock_carry_level(carry_level * level / /* nodes can be unlocked in arbitrary order. In preemptible environment it's better to unlock in reverse order of locking, though. - */ + */ for_all_nodes_back(level, node, tmp_node) { /* all allocated nodes should be already linked to their parents at this moment. */ @@ -856,8 +843,7 @@ unlock_carry_level(carry_level * level / /* finish with @level Unlock nodes and release all allocated resources */ -static void -done_carry_level(carry_level * level /* level to finish */ ) +static void done_carry_level(carry_level * level /* level to finish */ ) { carry_node *node; carry_node *tmp_node; @@ -868,8 +854,8 @@ done_carry_level(carry_level * level /* unlock_carry_level(level, 0); for_all_nodes(level, node, tmp_node) { - assert("nikita-2113", locks_list_is_clean(&node->lock_handle)); - assert("nikita-2114", owners_list_is_clean(&node->lock_handle)); + assert("nikita-2113", list_empty_careful(&node->lock_handle.locks_link)); + assert("nikita-2114", list_empty_careful(&node->lock_handle.owners_link)); reiser4_pool_free(&level->pool->node_pool, &node->header); } for_all_ops(level, op, tmp_op) @@ -886,8 +872,7 @@ done_carry_level(carry_level * level /* fills ->real_node from this lock handle. */ -reiser4_internal int -lock_carry_node_tail(carry_node * node /* node to complete locking of */ ) +int lock_carry_node_tail(carry_node * node /* node to complete locking of */ ) { assert("nikita-1052", node != NULL); assert("nikita-1187", carry_real(node) != NULL); @@ -901,7 +886,7 @@ lock_carry_node_tail(carry_node * node / already in memory. Corresponding zrelse() is in unlock_carry_node() - */ + */ return zload(carry_real(node)); } @@ -922,9 +907,8 @@ lock_carry_node_tail(carry_node * node / operation (->real_node field of carry_node) from base. */ -reiser4_internal int -lock_carry_node(carry_level * level /* level @node is in */ , - carry_node * node /* node to lock */ ) +int lock_carry_node(carry_level * level /* level @node is in */ , + carry_node * node /* node to lock */ ) { int result; znode *reference_point; @@ -959,14 +943,16 @@ lock_carry_node(carry_level * level /* l find_begetting_brother() are write-locked by this thread, and thus, their sibling linkage cannot change. - */ + */ reference_point = UNDER_RW (tree, znode_get_tree(reference_point), read, find_begetting_brother(node, level)->node); assert("nikita-1186", reference_point != NULL); } if (node->parent && (result == 0)) { - result = reiser4_get_parent(&tmp_lh, reference_point, ZNODE_WRITE_LOCK); + result = + reiser4_get_parent(&tmp_lh, reference_point, + ZNODE_WRITE_LOCK); if (result != 0) { ; /* nothing */ } else if (znode_get_level(tmp_lh.node) == 0) { @@ -976,7 +962,9 @@ lock_carry_node(carry_level * level /* l reference_point = level->new_root; move_lh(&lh, &node->lock_handle); } - } else if ((level->new_root != NULL) && (level->new_root != znode_parent_nolock(reference_point))) { + } else if ((level->new_root != NULL) + && (level->new_root != + znode_parent_nolock(reference_point))) { /* parent of node exists, but this level aready created different new root, so */ warning("nikita-1109", @@ -992,8 +980,10 @@ lock_carry_node(carry_level * level /* l if (node->left && (result == 0)) { assert("nikita-1183", node->parent); assert("nikita-883", reference_point != NULL); - result = reiser4_get_left_neighbor( - &tmp_lh, reference_point, ZNODE_WRITE_LOCK, GN_CAN_USE_UPPER_LEVELS); + result = + reiser4_get_left_neighbor(&tmp_lh, reference_point, + ZNODE_WRITE_LOCK, + GN_CAN_USE_UPPER_LEVELS); if (result == 0) { done_lh(&lh); move_lh(&lh, &tmp_lh); @@ -1001,7 +991,9 @@ lock_carry_node(carry_level * level /* l } } if (!node->parent && !node->left && !node->left_before) { - result = longterm_lock_znode(&lh, reference_point, ZNODE_WRITE_LOCK, ZNODE_LOCK_HIPRI); + result = + longterm_lock_znode(&lh, reference_point, ZNODE_WRITE_LOCK, + ZNODE_LOCK_HIPRI); } if (result == 0) { move_lh(&node->lock_handle, &lh); @@ -1042,13 +1034,16 @@ unlock_carry_node(carry_level * level, Prepare node for removal. Last zput() will finish with it. - */ + */ ZF_SET(real_node, JNODE_HEARD_BANSHEE); } if (node->free) { - assert("nikita-2177", locks_list_is_clean(&node->lock_handle)); - assert("nikita-2112", owners_list_is_clean(&node->lock_handle)); - reiser4_pool_free(&level->pool->node_pool, &node->header); + assert("nikita-2177", + list_empty_careful(&node->lock_handle.locks_link)); + assert("nikita-2112", + list_empty_careful(&node->lock_handle.owners_link)); + reiser4_pool_free(&level->pool->node_pool, + &node->header); } } } @@ -1085,7 +1080,6 @@ factors means rolling back to a consiste It would be a nice feature though to support rollback without rebooting followed by remount, but this can wait for later versions. - 2. once isolated transactions will be implemented it will be possible to roll back offending transaction. @@ -1093,13 +1087,12 @@ followed by remount, but this can wait f it more before deciding if it should be done. -Hans */ -static void -fatal_carry_error(carry_level * doing UNUSED_ARG /* carry level - * where - * unrecoverable - * error - * occurred */ , - int ecode /* error code */ ) +static void fatal_carry_error(carry_level * doing UNUSED_ARG /* carry level + * where + * unrecoverable + * error + * occurred */ , + int ecode /* error code */ ) { assert("nikita-1230", doing != NULL); assert("nikita-1231", ecode < 0); @@ -1117,12 +1110,11 @@ fatal_carry_error(carry_level * doing UN locked. */ -static int -add_new_root(carry_level * level /* carry level in context of which - * operation is performed */ , - carry_node * node /* carry node for existing root */ , - znode * fake /* "fake" znode already locked by - * us */ ) +static int add_new_root(carry_level * level /* carry level in context of which + * operation is performed */ , + carry_node * node /* carry node for existing root */ , + znode * fake /* "fake" znode already locked by + * us */ ) { int result; @@ -1136,13 +1128,15 @@ add_new_root(carry_level * level /* carr /* @node is root and it's already locked by us. This means that nobody else can be trying to add/remove tree root right now. - */ + */ if (level->new_root == NULL) level->new_root = add_tree_root(node->node, fake); if (!IS_ERR(level->new_root)) { assert("nikita-1210", znode_is_root(level->new_root)); node->deallocate = 1; - result = longterm_lock_znode(&node->lock_handle, level->new_root, ZNODE_WRITE_LOCK, ZNODE_LOCK_LOPRI); + result = + longterm_lock_znode(&node->lock_handle, level->new_root, + ZNODE_WRITE_LOCK, ZNODE_LOCK_LOPRI); if (result == 0) zput(level->new_root); } else { @@ -1161,18 +1155,17 @@ add_new_root(carry_level * level /* carr This is carry related routing that calls new_node() to allocate new node. */ -reiser4_internal carry_node * -add_new_znode(znode * brother /* existing left neighbor of new - * node */ , - carry_node * ref /* carry node after which new - * carry node is to be inserted - * into queue. This affects - * locking. */ , - carry_level * doing /* carry queue where new node is - * to be added */ , - carry_level * todo /* carry queue where COP_INSERT - * operation to add pointer to - * new node will ne added */ ) +carry_node *add_new_znode(znode * brother /* existing left neighbor of new + * node */ , + carry_node * ref /* carry node after which new + * carry node is to be inserted + * into queue. This affects + * locking. */ , + carry_level * doing /* carry queue where new node is + * to be added */ , + carry_level * todo /* carry queue where COP_INSERT + * operation to add pointer to + * new node will ne added */ ) { carry_node *fresh; znode *new_znode; @@ -1190,7 +1183,7 @@ add_new_znode(znode * brother /* existin (2) new node is added on the right of @brother - */ + */ fresh = add_carry_skip(doing, ref ? POOLO_AFTER : POOLO_LAST, ref); if (IS_ERR(fresh)) @@ -1231,7 +1224,8 @@ add_new_znode(znode * brother /* existin /* initially new node spawns empty key range */ WLOCK_DK(znode_get_tree(brother)); znode_set_ld_key(new_znode, - znode_set_rd_key(new_znode, znode_get_rd_key(brother))); + znode_set_rd_key(new_znode, + znode_get_rd_key(brother))); WUNLOCK_DK(znode_get_tree(brother)); return fresh; } @@ -1248,7 +1242,7 @@ static int carry_estimate_reserve(carry_ result = 0; for_all_ops(level, op, tmp_op) - result += op_dispatch_table[op->op].estimate(op, level); + result += op_dispatch_table[op->op].estimate(op, level); return result; } @@ -1258,8 +1252,7 @@ static int carry_estimate_reserve(carry_ debugging is turned off to print dumps at errors. */ #if REISER4_DEBUG -static int -carry_level_invariant(carry_level * level, carry_queue_state state) +static int carry_level_invariant(carry_level * level, carry_queue_state state) { carry_node *node; carry_node *tmp_node; @@ -1305,15 +1298,13 @@ carry_level_invariant(carry_level * leve #endif /* get symbolic name for boolean */ -static const char * -tf(int boolean /* truth value */ ) +static const char *tf(int boolean /* truth value */ ) { return boolean ? "t" : "f"; } /* symbolic name for carry operation */ -static const char * -carry_op_name(carry_opcode op /* carry opcode */ ) +static const char *carry_op_name(carry_opcode op /* carry opcode */ ) { switch (op) { case COP_INSERT: @@ -1341,24 +1332,24 @@ carry_op_name(carry_opcode op /* carry o } /* dump information about carry node */ -static void -print_carry(const char *prefix /* prefix to print */ , - carry_node * node /* node to print */ ) +static void print_carry(const char *prefix /* prefix to print */ , + carry_node * node /* node to print */ ) { if (node == NULL) { printk("%s: null\n", prefix); return; } - printk("%s: %p parent: %s, left: %s, unlock: %s, free: %s, dealloc: %s\n", - prefix, node, tf(node->parent), tf(node->left), tf(node->unlock), tf(node->free), tf(node->deallocate)); + printk + ("%s: %p parent: %s, left: %s, unlock: %s, free: %s, dealloc: %s\n", + prefix, node, tf(node->parent), tf(node->left), tf(node->unlock), + tf(node->free), tf(node->deallocate)); print_znode("\tnode", node->node); print_znode("\treal_node", carry_real(node)); } /* dump information about carry operation */ -static void -print_op(const char *prefix /* prefix to print */ , - carry_op * op /* operation to print */ ) +static void print_op(const char *prefix /* prefix to print */ , + carry_op * op /* operation to print */ ) { if (op == NULL) { printk("%s: null\n", prefix); @@ -1369,7 +1360,8 @@ print_op(const char *prefix /* prefix to switch (op->op) { case COP_INSERT: case COP_PASTE: - print_coord("\tcoord", op->u.insert.d ? op->u.insert.d->coord : NULL, 0); + print_coord("\tcoord", + op->u.insert.d ? op->u.insert.d->coord : NULL, 0); print_key("\tkey", op->u.insert.d ? op->u.insert.d->key : NULL); print_carry("\tchild", op->u.insert.child); break; @@ -1378,11 +1370,15 @@ print_op(const char *prefix /* prefix to break; case COP_CUT: if (op->u.cut_or_kill.is_cut) { - print_coord("\tfrom", op->u.cut_or_kill.u.kill->params.from, 0); - print_coord("\tto", op->u.cut_or_kill.u.kill->params.to, 0); + print_coord("\tfrom", + op->u.cut_or_kill.u.kill->params.from, 0); + print_coord("\tto", op->u.cut_or_kill.u.kill->params.to, + 0); } else { - print_coord("\tfrom", op->u.cut_or_kill.u.cut->params.from, 0); - print_coord("\tto", op->u.cut_or_kill.u.cut->params.to, 0); + print_coord("\tfrom", + op->u.cut_or_kill.u.cut->params.from, 0); + print_coord("\tto", op->u.cut_or_kill.u.cut->params.to, + 0); } break; case COP_UPDATE: @@ -1395,9 +1391,8 @@ print_op(const char *prefix /* prefix to } /* dump information about all nodes and operations in a @level */ -static void -print_level(const char *prefix /* prefix to print */ , - carry_level * level /* level to print */ ) +static void print_level(const char *prefix /* prefix to print */ , + carry_level * level /* level to print */ ) { carry_node *node; carry_node *tmp_node; diff -puN fs/reiser4/carry.h~reiser4-big-update fs/reiser4/carry.h --- devel/fs/reiser4/carry.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/carry.h 2005-09-15 19:51:08.000000000 -0700 @@ -30,28 +30,28 @@ typedef struct carry_node { reiser4_pool_header header; /* base node from which real_node is calculated. See - fs/reiser4/carry.c:lock_carry_node(). */ + fs/reiser4/carry.c:lock_carry_node(). */ znode *node; /* how to get ->real_node */ - /* to get ->real_node obtain parent of ->node*/ + /* to get ->real_node obtain parent of ->node */ __u32 parent:1; /* to get ->real_node obtain left neighbor of parent of - ->node*/ + ->node */ __u32 left:1; __u32 left_before:1; /* locking */ /* this node was locked by carry process and should be - unlocked when carry leaves a level */ + unlocked when carry leaves a level */ __u32 unlock:1; /* disk block for this node was allocated by carry process and - should be deallocated when carry leaves a level */ + should be deallocated when carry leaves a level */ __u32 deallocate:1; /* this carry node was allocated by carry process and should be - freed when carry leaves a level */ + freed when carry leaves a level */ __u32 free:1; /* type of lock we want to take on this node */ @@ -84,7 +84,7 @@ typedef enum { /* update delimiting key in least common ancestor of two nodes. This is performed when items are moved between two nodes. - */ + */ COP_UPDATE, /* insert flow */ COP_INSERT_FLOW, @@ -130,7 +130,7 @@ typedef enum { * is used when carry() client doesn't initially possess lock handle * on the insertion point node, for example, by extent insertion * code. See carry_extent(). */ - CARRY_TRACK_NODE = 2 + CARRY_TRACK_NODE = 2 } carry_track_type; /* data supplied to COP_{INSERT|PASTE} by callers */ @@ -171,7 +171,7 @@ struct carry_kill_data { struct cut_kill_params params; /* parameter to be passed to the ->kill_hook() method of item * plugin */ - /*void *iplug_params;*/ /* FIXME: unused currently */ + /*void *iplug_params; *//* FIXME: unused currently */ /* if not NULL---inode whose items are being removed. This is needed * for ->kill_hook() of extent item to update VM structures when * removing pages. */ @@ -188,6 +188,7 @@ struct carry_kill_data { lock_handle *right; /* flags modifying behavior of kill. Currently, it may have DELETE_RETAIN_EMPTY set. */ unsigned flags; + char *buf; }; /* &carry_tree_op - operation to "carry" upward. @@ -226,7 +227,7 @@ typedef struct carry_op { for modify: parent of modified node - */ + */ carry_node *node; union { struct { @@ -303,8 +304,8 @@ struct carry_level { /* this level may be restarted */ __u32 restartable:1; /* list of carry nodes on this level, ordered by key order */ - pool_level_list_head nodes; - pool_level_list_head ops; + struct list_head nodes; + struct list_head ops; /* pool where new objects are allocated from */ carry_pool *pool; int ops_num; @@ -314,7 +315,7 @@ struct carry_level { /* This is set by caller (insert_by_key(), resize_item(), etc.) when they want ->tracked to automagically wander to the node where insertion point moved after insert or paste. - */ + */ carry_track_type track_type; /* lock handle supplied by user that we are tracking. See above. */ @@ -330,21 +331,26 @@ struct carry_plugin_info { int carry(carry_level * doing, carry_level * done); -carry_node *add_carry(carry_level * level, pool_ordering order, carry_node * reference); -carry_node *add_carry_skip(carry_level * level, pool_ordering order, carry_node * reference); +carry_node *add_carry(carry_level * level, pool_ordering order, + carry_node * reference); +carry_node *add_carry_skip(carry_level * level, pool_ordering order, + carry_node * reference); extern carry_node *insert_carry_node(carry_level * doing, carry_level * todo, const znode * node); -extern carry_pool *init_carry_pool(void); +extern carry_pool *init_carry_pool(int); extern void done_carry_pool(carry_pool * pool); extern void init_carry_level(carry_level * level, carry_pool * pool); -extern carry_op *post_carry(carry_level * level, carry_opcode op, znode * node, int apply_to_parent); -extern carry_op *node_post_carry(carry_plugin_info * info, carry_opcode op, znode * node, int apply_to_parent_p); +extern carry_op *post_carry(carry_level * level, carry_opcode op, znode * node, + int apply_to_parent); +extern carry_op *node_post_carry(carry_plugin_info * info, carry_opcode op, + znode * node, int apply_to_parent_p); -carry_node *add_new_znode(znode * brother, carry_node * reference, carry_level * doing, carry_level * todo); +carry_node *add_new_znode(znode * brother, carry_node * reference, + carry_level * doing, carry_level * todo); carry_node *find_carry_node(carry_level * level, const znode * node); @@ -352,43 +358,61 @@ extern znode *carry_real(const carry_nod /* helper macros to iterate over carry queues */ -#define carry_node_next( node ) \ - ( ( carry_node * ) pool_level_list_next( &( node ) -> header ) ) +#define carry_node_next( node ) \ + list_entry((node)->header.level_linkage.next, carry_node, \ + header.level_linkage) + +#define carry_node_prev( node ) \ + list_entry((node)->header.level_linkage.prev, carry_node, \ + header.level_linkage) -#define carry_node_prev( node ) \ - ( ( carry_node * ) pool_level_list_prev( &( node ) -> header ) ) +#define carry_node_front( level ) \ + list_entry((level)->nodes.next, carry_node, header.level_linkage) -#define carry_node_front( level ) \ - ( ( carry_node * ) pool_level_list_front( &( level ) -> nodes ) ) +#define carry_node_back( level ) \ + list_entry((level)->nodes.prev, carry_node, header.level_linkage) -#define carry_node_back( level ) \ - ( ( carry_node * ) pool_level_list_back( &( level ) -> nodes ) ) - -#define carry_node_end( level, node ) \ - ( pool_level_list_end( &( level ) -> nodes, &( node ) -> header ) ) +#define carry_node_end( level, node ) \ + (&(level)->nodes == &(node)->header.level_linkage) /* macro to iterate over all operations in a @level */ -#define for_all_ops( level /* carry level (of type carry_level *) */, \ - op /* pointer to carry operation, modified by loop (of \ - * type carry_op *) */, \ - tmp /* pointer to carry operation (of type carry_op *), \ - * used to make iterator stable in the face of \ - * deletions from the level */ ) \ +#define for_all_ops( level /* carry level (of type carry_level *) */, \ + op /* pointer to carry operation, modified by loop (of \ + * type carry_op *) */, \ + tmp /* pointer to carry operation (of type carry_op *), \ + * used to make iterator stable in the face of \ + * deletions from the level */ ) \ +for (op = list_entry(level->ops.next, carry_op, header.level_linkage), \ + tmp = list_entry(op->header.level_linkage.next, carry_op, header.level_linkage); \ + &op->header.level_linkage != &level->ops; \ + op = tmp, \ + tmp = list_entry(op->header.level_linkage.next, carry_op, header.level_linkage)) + +#if 0 for( op = ( carry_op * ) pool_level_list_front( &level -> ops ), \ tmp = ( carry_op * ) pool_level_list_next( &op -> header ) ; \ ! pool_level_list_end( &level -> ops, &op -> header ) ; \ op = tmp, tmp = ( carry_op * ) pool_level_list_next( &op -> header ) ) +#endif -/* macro to iterate over all nodes in a @level */ -#define for_all_nodes( level /* carry level (of type carry_level *) */, \ - node /* pointer to carry node, modified by loop (of \ - * type carry_node *) */, \ - tmp /* pointer to carry node (of type carry_node *), \ - * used to make iterator stable in the face of * \ - * deletions from the level */ ) \ +/* macro to iterate over all nodes in a @level */ \ +#define for_all_nodes( level /* carry level (of type carry_level *) */, \ + node /* pointer to carry node, modified by loop (of \ + * type carry_node *) */, \ + tmp /* pointer to carry node (of type carry_node *), \ + * used to make iterator stable in the face of * \ + * deletions from the level */ ) \ +for (node = list_entry(level->nodes.next, carry_node, header.level_linkage), \ + tmp = list_entry(node->header.level_linkage.next, carry_node, header.level_linkage); \ + &node->header.level_linkage != &level->nodes; \ + node = tmp, \ + tmp = list_entry(node->header.level_linkage.next, carry_node, header.level_linkage)) + +#if 0 for( node = carry_node_front( level ), \ tmp = carry_node_next( node ) ; ! carry_node_end( level, node ) ; \ node = tmp, tmp = carry_node_next( node ) ) +#endif /* macro to iterate over all nodes in a @level in reverse order diff -puN fs/reiser4/carry_ops.c~reiser4-big-update fs/reiser4/carry_ops.c --- devel/fs/reiser4/carry_ops.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/carry_ops.c 2005-09-15 19:51:08.000000000 -0700 @@ -24,7 +24,8 @@ #include static int carry_shift_data(sideof side, coord_t * insert_coord, znode * node, - carry_level * doing, carry_level * todo, unsigned int including_insert_coord_p); + carry_level * doing, carry_level * todo, + unsigned int including_insert_coord_p); extern int lock_carry_node(carry_level * level, carry_node * node); extern int lock_carry_node_tail(carry_node * node); @@ -35,10 +36,9 @@ extern int lock_carry_node_tail(carry_no comments in the body. */ -static carry_node * -find_left_neighbor(carry_op * op /* node to find left - * neighbor of */ , - carry_level * doing /* level to scan */ ) +static carry_node *find_left_neighbor(carry_op * op /* node to find left + * neighbor of */ , + carry_level * doing /* level to scan */ ) { int result; carry_node *node; @@ -58,7 +58,8 @@ find_left_neighbor(carry_op * op /* node RUNLOCK_TREE(tree); left = node; do { - left = carry_node_prev(left); + left = list_entry(left->header.level_linkage.prev, + carry_node, header.level_linkage); assert("nikita-3408", !carry_node_end(doing, left)); } while (carry_real(left) == carry_real(node)); @@ -114,10 +115,9 @@ find_left_neighbor(carry_op * op /* node comments in the body. */ -static carry_node * -find_right_neighbor(carry_op * op /* node to find right - * neighbor of */ , - carry_level * doing /* level to scan */ ) +static carry_node *find_right_neighbor(carry_op * op /* node to find right + * neighbor of */ , + carry_level * doing /* level to scan */ ) { int result; carry_node *node; @@ -186,7 +186,8 @@ find_right_neighbor(carry_op * op /* nod */ right = node; do { - right = carry_node_next(right); + right = list_entry(right->header.level_linkage.next, + carry_node, header.level_linkage); assert("nikita-3408", !carry_node_end(doing, right)); } while (carry_real(right) == carry_real(node)); @@ -229,12 +230,11 @@ find_right_neighbor(carry_op * op /* nod How much space in @node is required for completion of @op, where @op is insert or paste operation. */ -static unsigned int -space_needed_for_op(znode * node /* znode data are - * inserted or - * pasted in */ , - carry_op * op /* carry - operation */ ) +static unsigned int space_needed_for_op(znode * node /* znode data are + * inserted or + * pasted in */ , + carry_op * op /* carry + operation */ ) { assert("nikita-919", op != NULL); @@ -244,21 +244,21 @@ space_needed_for_op(znode * node /* znod case COP_INSERT: return space_needed(node, NULL, op->u.insert.d->data, 1); case COP_PASTE: - return space_needed(node, op->u.insert.d->coord, op->u.insert.d->data, 0); + return space_needed(node, op->u.insert.d->coord, + op->u.insert.d->data, 0); } } /* how much space in @node is required to insert or paste @data at @coord. */ -reiser4_internal unsigned int -space_needed(const znode * node /* node data are inserted or - * pasted in */ , - const coord_t * coord /* coord where data are - * inserted or pasted - * at */ , - const reiser4_item_data * data /* data to insert or - * paste */ , - int insertion /* non-0 is inserting, 0---paste */ ) +unsigned int space_needed(const znode * node /* node data are inserted or + * pasted in */ , + const coord_t * coord /* coord where data are + * inserted or pasted + * at */ , + const reiser4_item_data * data /* data to insert or + * paste */ , + int insertion /* non-0 is inserting, 0---paste */ ) { int result; item_plugin *iplug; @@ -283,17 +283,16 @@ space_needed(const znode * node /* node nplug = node->nplug; /* and add node overhead */ if (nplug->item_overhead != NULL) { - result += nplug->item_overhead(node, 0); + result += nplug->item_overhead(node, NULL); } } return result; } /* find &coord in parent where pointer to new child is to be stored. */ -static int -find_new_child_coord(carry_op * op /* COP_INSERT carry operation to - * insert pointer to new - * child */ ) +static int find_new_child_coord(carry_op * op /* COP_INSERT carry operation to + * insert pointer to new + * child */ ) { int result; znode *node; @@ -307,16 +306,17 @@ find_new_child_coord(carry_op * op /* CO assert("nikita-944", node_plugin_by_node(node) != NULL); child = carry_real(op->u.insert.child); - result = find_new_child_ptr(node, child, op->u.insert.brother, op->u.insert.d->coord); + result = + find_new_child_ptr(node, child, op->u.insert.brother, + op->u.insert.d->coord); build_child_ptr_data(child, op->u.insert.d->data); return result; } /* additional amount of free space in @node required to complete @op */ -static int -free_space_shortage(znode * node /* node to check */ , - carry_op * op /* operation being performed */ ) +static int free_space_shortage(znode * node /* node to check */ , + carry_op * op /* operation being performed */ ) { assert("nikita-1061", node != NULL); assert("nikita-1062", op != NULL); @@ -339,8 +339,7 @@ free_space_shortage(znode * node /* node /* helper function: update node pointer in operation after insertion point was probably shifted into @target. */ -static znode * -sync_op(carry_op * op, carry_node * target) +static znode *sync_op(carry_op * op, carry_node * target) { znode *insertion_node; @@ -380,7 +379,8 @@ make_space_tail(carry_op * op, carry_lev done_lh(doing->tracked); init_lh(doing->tracked); result = longterm_lock_znode(doing->tracked, node, - ZNODE_WRITE_LOCK, ZNODE_LOCK_HIPRI); + ZNODE_WRITE_LOCK, + ZNODE_LOCK_HIPRI); } else result = 0; return result; @@ -397,10 +397,9 @@ make_space_tail(carry_op * op, carry_lev See carry_flow() on detail about flow insertion */ -static int -make_space(carry_op * op /* carry operation, insert or paste */ , - carry_level * doing /* current carry queue */ , - carry_level * todo /* carry queue on the parent level */ ) +static int make_space(carry_op * op /* carry operation, insert or paste */ , + carry_level * doing /* current carry queue */ , + carry_level * todo /* carry queue on the parent level */ ) { znode *node; int result; @@ -439,13 +438,13 @@ make_space(carry_op * op /* carry operat /* If there is not enough space in a node, try to shift something to the left neighbor. This is a bit tricky, as locking to the left is low priority. This is handled by restart logic in carry(). - */ + */ not_enough_space = free_space_shortage(node, op); if (not_enough_space <= 0) /* it is possible that carry was called when there actually was enough space in the node. For example, when inserting leftmost item so that delimiting keys have to be updated. - */ + */ return make_space_tail(op, doing, orig_node); if (!(flags & COPI_DONT_SHIFT_LEFT)) { carry_node *left; @@ -460,7 +459,7 @@ make_space(carry_op * op /* carry operat occurred. This shouldn't happen. Issue a warning and continue as if left neighbor weren't existing. - */ + */ warning("nikita-924", "Error accessing left neighbor: %li", PTR_ERR(left)); @@ -483,7 +482,7 @@ make_space(carry_op * op /* carry operat may be, there is enough free space in @left. Various balancing decisions are valid here. The same for the shifiting to the right. - */ + */ } } /* If there still is not enough space, shift to the right */ @@ -502,7 +501,7 @@ make_space(carry_op * op /* carry operat shift everything possible on the right of but excluding insertion coord into the right neighbor - */ + */ result = carry_shift_data(RIGHT_SIDE, coord, carry_real(right), doing, todo, @@ -518,10 +517,10 @@ make_space(carry_op * op /* carry operat We try to allocate new blocks if COPI_DONT_ALLOCATE is not set in the carry operation flags (currently this is needed during flush only). - */ + */ for (blk_alloc = 0; not_enough_space > 0 && result == 0 && blk_alloc < 2 && - !(flags & COPI_DONT_ALLOCATE); ++blk_alloc) { + !(flags & COPI_DONT_ALLOCATE); ++blk_alloc) { carry_node *fresh; /* new node we are allocating */ coord_t coord_shadow; /* remembered insertion point before * shifting data into new node */ @@ -542,7 +541,7 @@ make_space(carry_op * op /* carry operat into their parents in the order of creation, which means that @node will be valid "cookie" at the time of insertion. - */ + */ fresh = add_new_znode(node, op->node, doing, todo); if (IS_ERR(fresh)) return PTR_ERR(fresh); @@ -562,17 +561,17 @@ make_space(carry_op * op /* carry operat shift everything possible on the right of and including insertion coord into the right neighbor. - */ + */ coord_dup(&coord_shadow, op->u.insert.d->coord); node_shadow = op->node; /* move insertion point into newly created node if: - . insertion point is rightmost in the source node, or - . this is not the first node we are allocating in a row. - */ + . insertion point is rightmost in the source node, or + . this is not the first node we are allocating in a row. + */ gointo = - (blk_alloc > 0) || - coord_is_after_rightmost(op->u.insert.d->coord); + (blk_alloc > 0) || + coord_is_after_rightmost(op->u.insert.d->coord); result = carry_shift_data(RIGHT_SIDE, coord, carry_real(fresh), doing, todo, gointo); @@ -585,7 +584,7 @@ make_space(carry_op * op /* carry operat insertion point back to the @shadow_node so that next new node would be inserted between @shadow_node and @fresh. - */ + */ coord_normalize(&coord_shadow); coord_dup(coord, &coord_shadow); node = coord->node; @@ -594,8 +593,9 @@ make_space(carry_op * op /* carry operat /* still not enough space?! Maybe there is enough space in the source node (i.e., node data are moved from) now. - */ - not_enough_space = free_space_shortage(node, op); + */ + not_enough_space = + free_space_shortage(node, op); } } } @@ -653,20 +653,20 @@ make_space(carry_op * op /* carry operat by calling item plugin method. */ -static int -insert_paste_common(carry_op * op /* carry operation being - * performed */ , - carry_level * doing /* current carry level */ , - carry_level * todo /* next carry level */ , - carry_insert_data * cdata /* pointer to - * cdata */ , - coord_t * coord /* insertion/paste coord */ , - reiser4_item_data * data /* data to be - * inserted/pasted */ ) +static int insert_paste_common(carry_op * op /* carry operation being + * performed */ , + carry_level * doing /* current carry level */ , + carry_level * todo /* next carry level */ , + carry_insert_data * cdata /* pointer to + * cdata */ , + coord_t * coord /* insertion/paste coord */ , + reiser4_item_data * data /* data to be + * inserted/pasted */ ) { assert("nikita-981", op != NULL); assert("nikita-980", todo != NULL); - assert("nikita-979", (op->op == COP_INSERT) || (op->op == COP_PASTE) || (op->op == COP_EXTENT)); + assert("nikita-979", (op->op == COP_INSERT) || (op->op == COP_PASTE) + || (op->op == COP_EXTENT)); if (op->u.insert.type == COPT_PASTE_RESTARTED) { /* nothing to do. Fall through to make_space(). */ @@ -688,15 +688,17 @@ insert_paste_common(carry_op * op /* car But node can change also. Probably some pieces have to be added to the lock_carry_node(), to lock node by its key. - */ + */ /* NOTE-NIKITA Lookup bias is fixed to FIND_EXACT. Complain if you need something else. */ op->u.insert.d->coord = coord; node = carry_real(op->node); intra_node = node_plugin_by_node(node)->lookup - (node, op->u.insert.d->key, FIND_EXACT, op->u.insert.d->coord); + (node, op->u.insert.d->key, FIND_EXACT, + op->u.insert.d->coord); if ((intra_node != NS_FOUND) && (intra_node != NS_NOT_FOUND)) { - warning("nikita-1715", "Intra node lookup failure: %i", intra_node); + warning("nikita-1715", "Intra node lookup failure: %i", + intra_node); print_znode("node", node); return intra_node; } @@ -704,7 +706,7 @@ insert_paste_common(carry_op * op /* car /* if we are asked to insert pointer to the child into internal node, first convert pointer to the child into coord within parent node. - */ + */ znode *child; int result; @@ -715,7 +717,9 @@ insert_paste_common(carry_op * op /* car result = find_new_child_coord(op); child = carry_real(op->u.insert.child); if (result != NS_NOT_FOUND) { - warning("nikita-993", "Cannot find a place for child pointer: %i", result); + warning("nikita-993", + "Cannot find a place for child pointer: %i", + result); print_znode("child", child); print_znode("parent", carry_real(op->node)); return result; @@ -729,7 +733,7 @@ insert_paste_common(carry_op * op /* car I am going to come up with better solution. You are not expected to understand this. - -- v6root/usr/sys/ken/slp.c + -- v6root/usr/sys/ken/slp.c Basically, what happens here is the following: carry came to the parent level and is about to insert internal item @@ -743,7 +747,7 @@ insert_paste_common(carry_op * op /* car level already split parent node, so that insertion point moved into another node. Handle this by creating new carry node for insertion point if necessary. - */ + */ if (carry_real(op->node) != op->u.insert.d->coord->node) { pool_ordering direction; znode *z1; @@ -781,7 +785,9 @@ insert_paste_common(carry_op * op /* car * search tree) is leftmost key in the child node. */ op->u.insert.d->key = UNDER_RW(dk, znode_get_tree(child), read, - leftmost_key_in_node(child, znode_get_ld_key(child))); + leftmost_key_in_node(child, + znode_get_ld_key + (child))); op->u.insert.d->data->arg = op->u.insert.brother; } else { assert("vs-243", op->u.insert.d->coord != NULL); @@ -803,12 +809,11 @@ insert_paste_common(carry_op * op /* car operation. */ -static int -carry_insert(carry_op * op /* operation to perform */ , - carry_level * doing /* queue of operations @op - * is part of */ , - carry_level * todo /* queue where new operations - * are accumulated */ ) +static int carry_insert(carry_op * op /* operation to perform */ , + carry_level * doing /* queue of operations @op + * is part of */ , + carry_level * todo /* queue where new operations + * are accumulated */ ) { znode *node; carry_insert_data cdata; @@ -832,13 +837,15 @@ carry_insert(carry_op * op /* operation assert("nikita-1039", node != NULL); assert("nikita-1040", node_plugin_by_node(node) != NULL); - assert("nikita-949", space_needed_for_op(node, op) <= znode_free_space(node)); + assert("nikita-949", + space_needed_for_op(node, op) <= znode_free_space(node)); /* ask node layout to create new item. */ info.doing = doing; info.todo = todo; result = node_plugin_by_node(node)->create_item - (op->u.insert.d->coord, op->u.insert.d->key, op->u.insert.d->data, &info); + (op->u.insert.d->coord, op->u.insert.d->key, op->u.insert.d->data, + &info); doing->restartable = 0; znode_make_dirty(node); @@ -855,12 +862,12 @@ carry_insert(carry_op * op /* operation #define flow_insert_flow(op) ( ( op ) -> u.insert_flow.flow ) #define flow_insert_data(op) ( ( op ) -> u.insert_flow.data ) -static size_t -item_data_overhead(carry_op * op) +static size_t item_data_overhead(carry_op * op) { if (flow_insert_data(op)->iplug->b.estimate == NULL) return 0; - return (flow_insert_data(op)->iplug->b.estimate(NULL /* estimate insertion */, flow_insert_data(op)) - + return (flow_insert_data(op)->iplug->b. + estimate(NULL /* estimate insertion */ , flow_insert_data(op)) - flow_insert_data(op)->length); } @@ -870,8 +877,7 @@ item_data_overhead(carry_op * op) would reduce some flexibility in future changes */ static int can_paste(coord_t *, const reiser4_key *, const reiser4_item_data *); -static size_t -flow_insertion_overhead(carry_op * op) +static size_t flow_insertion_overhead(carry_op * op) { znode *node; size_t insertion_overhead; @@ -879,14 +885,16 @@ flow_insertion_overhead(carry_op * op) node = flow_insert_point(op)->node; insertion_overhead = 0; if (node->nplug->item_overhead && - !can_paste(flow_insert_point(op), &flow_insert_flow(op)->key, flow_insert_data(op))) - insertion_overhead = node->nplug->item_overhead(node, 0) + item_data_overhead(op); + !can_paste(flow_insert_point(op), &flow_insert_flow(op)->key, + flow_insert_data(op))) + insertion_overhead = + node->nplug->item_overhead(node, NULL) + + item_data_overhead(op); return insertion_overhead; } /* how many bytes of flow does fit to the node */ -static int -what_can_fit_into_node(carry_op * op) +static int what_can_fit_into_node(carry_op * op) { size_t free, overhead; @@ -903,15 +911,14 @@ what_can_fit_into_node(carry_op * op) /* in make_space_for_flow_insertion we need to check either whether whole flow fits into a node or whether minimal fraction of flow fits into a node */ -static int -enough_space_for_whole_flow(carry_op * op) +static int enough_space_for_whole_flow(carry_op * op) { - return (unsigned) what_can_fit_into_node(op) == op->u.insert_flow.flow->length; + return (unsigned)what_can_fit_into_node(op) == + op->u.insert_flow.flow->length; } #define MIN_FLOW_FRACTION 1 -static int -enough_space_for_min_flow_fraction(carry_op * op) +static int enough_space_for_min_flow_fraction(carry_op * op) { assert("vs-902", coord_is_after_rightmost(flow_insert_point(op))); @@ -929,7 +936,9 @@ make_space_by_shift_left(carry_op * op, left = find_left_neighbor(op, doing); if (unlikely(IS_ERR(left))) { - warning("vs-899", "make_space_by_shift_left: " "error accessing left neighbor: %li", PTR_ERR(left)); + warning("vs-899", + "make_space_by_shift_left: " + "error accessing left neighbor: %li", PTR_ERR(left)); return 1; } if (left == NULL) @@ -940,9 +949,8 @@ make_space_by_shift_left(carry_op * op, orig = flow_insert_point(op)->node; /* try to shift content of node @orig from its head upto insert point including insertion point into the left neighbor */ - carry_shift_data(LEFT_SIDE, flow_insert_point(op), - carry_real(left), doing, todo, 1 /* including insert - * point */); + carry_shift_data(LEFT_SIDE, flow_insert_point(op), carry_real(left), doing, todo, 1 /* including insert + * point */ ); if (carry_real(left) != flow_insert_point(op)->node) { /* insertion point did not move */ return 1; @@ -968,7 +976,8 @@ make_space_by_shift_left(carry_op * op, the right of insertion point was shifted to it and node got enough free space to put minimal fraction of flow into it */ static int -make_space_by_shift_right(carry_op * op, carry_level * doing, carry_level * todo) +make_space_by_shift_right(carry_op * op, carry_level * doing, + carry_level * todo) { carry_node *right; @@ -981,11 +990,10 @@ make_space_by_shift_right(carry_op * op, if (right) { /* shift everything possible on the right of but excluding insertion coord into the right neighbor */ - carry_shift_data(RIGHT_SIDE, flow_insert_point(op), - carry_real(right), doing, todo, 0 /* not - * including - * insert - * point */); + carry_shift_data(RIGHT_SIDE, flow_insert_point(op), carry_real(right), doing, todo, 0 /* not + * including + * insert + * point */ ); } else { /* right neighbor either does not exist or is unformatted node */ @@ -1028,13 +1036,13 @@ make_space_by_new_nodes(carry_op * op, c } op->u.insert_flow.new_nodes++; if (!coord_is_after_rightmost(flow_insert_point(op))) { - carry_shift_data(RIGHT_SIDE, flow_insert_point(op), - carry_real(new), doing, todo, 0 /* not - * including - * insert - * point */); + carry_shift_data(RIGHT_SIDE, flow_insert_point(op), carry_real(new), doing, todo, 0 /* not + * including + * insert + * point */ ); - assert("vs-901", coord_is_after_rightmost(flow_insert_point(op))); + assert("vs-901", + coord_is_after_rightmost(flow_insert_point(op))); if (enough_space_for_min_flow_fraction(op)) { return 0; @@ -1062,7 +1070,8 @@ make_space_by_new_nodes(carry_op * op, c } static int -make_space_for_flow_insertion(carry_op * op, carry_level * doing, carry_level * todo) +make_space_for_flow_insertion(carry_op * op, carry_level * doing, + carry_level * todo) { __u32 flags = op->u.insert_flow.flags; @@ -1071,7 +1080,8 @@ make_space_for_flow_insertion(carry_op * return 0; } - if (!(flags & COPI_DONT_SHIFT_LEFT) && (make_space_by_shift_left(op, doing, todo) == 0)) { + if (!(flags & COPI_DONT_SHIFT_LEFT) + && (make_space_by_shift_left(op, doing, todo) == 0)) { /* insert point is shifted to left neighbor of original insert point node and is set after last unit in that node. It has enough space to fit at least minimal fraction of flow. */ @@ -1083,7 +1093,8 @@ make_space_for_flow_insertion(carry_op * return 0; } - if (!(flags & COPI_DONT_SHIFT_RIGHT) && (make_space_by_shift_right(op, doing, todo) == 0)) { + if (!(flags & COPI_DONT_SHIFT_RIGHT) + && (make_space_by_shift_right(op, doing, todo) == 0)) { /* insert point is still set to the same node, but there is nothing to the right of insert point. */ return 0; @@ -1134,8 +1145,11 @@ carry_insert_flow(carry_op * op, carry_l if (can_paste(insert_point, &f->key, flow_insert_data(op))) { /* insert point is set to item of file we are writing to and we have to append to it */ assert("vs-903", insert_point->between == AFTER_UNIT); - nplug->change_item_size(insert_point, flow_insert_data(op)->length); - flow_insert_data(op)->iplug->b.paste(insert_point, flow_insert_data(op), &info); + nplug->change_item_size(insert_point, + flow_insert_data(op)->length); + flow_insert_data(op)->iplug->b.paste(insert_point, + flow_insert_data + (op), &info); } else { /* new item must be inserted */ pos_in_node_t new_pos; @@ -1155,26 +1169,30 @@ carry_insert_flow(carry_op * op, carry_l new_pos = 0; break; default: - impossible("vs-906", "carry_insert_flow: invalid coord"); + impossible("vs-906", + "carry_insert_flow: invalid coord"); new_pos = 0; break; } - nplug->create_item(insert_point, &f->key, flow_insert_data(op), &info); + nplug->create_item(insert_point, &f->key, + flow_insert_data(op), &info); coord_set_item_pos(insert_point, new_pos); } coord_init_after_item_end(insert_point); doing->restartable = 0; znode_make_dirty(insert_point->node); - move_flow_forward(f, (unsigned) flow_insert_data(op)->length); + move_flow_forward(f, (unsigned)flow_insert_data(op)->length); } if (orig_node != flow_insert_point(op)->node) { /* move lock to new insert point */ done_lh(orig_lh); init_lh(orig_lh); - result = longterm_lock_znode(orig_lh, flow_insert_point(op)->node, ZNODE_WRITE_LOCK, ZNODE_LOCK_HIPRI); + result = + longterm_lock_znode(orig_lh, flow_insert_point(op)->node, + ZNODE_WRITE_LOCK, ZNODE_LOCK_HIPRI); } return result; @@ -1189,11 +1207,10 @@ carry_insert_flow(carry_op * op, carry_l twig level is never killed. */ -static int -carry_delete(carry_op * op /* operation to be performed */ , - carry_level * doing UNUSED_ARG /* current carry - * level */ , - carry_level * todo /* next carry level */ ) +static int carry_delete(carry_op * op /* operation to be performed */ , + carry_level * doing UNUSED_ARG /* current carry + * level */ , + carry_level * todo /* next carry level */ ) { int result; coord_t coord; @@ -1218,7 +1235,7 @@ carry_delete(carry_op * op /* operation parent = carry_real(op->node); child = op->u.delete.child ? - carry_real(op->u.delete.child) : op->node->node; + carry_real(op->u.delete.child) : op->node->node; tree = znode_get_tree(child); RLOCK_TREE(tree); @@ -1241,7 +1258,7 @@ carry_delete(carry_op * op /* operation /* Twig level horrors: tree should be of height at least 2. So, last pointer from the root at twig level is preserved even if child is empty. This is ugly, but so it was architectured. - */ + */ if (znode_is_root(parent) && znode_get_level(parent) <= REISER4_MIN_TREE_HEIGHT && @@ -1285,9 +1302,10 @@ carry_delete(carry_op * op /* operation kdata.params.smallest_removed = NULL; kdata.params.truncate = 1; kdata.flags = op->u.delete.flags; - kdata.inode = 0; - kdata.left = 0; - kdata.right = 0; + kdata.inode = NULL; + kdata.left = NULL; + kdata.right = NULL; + kdata.buf = NULL; /* ... and call it. */ result = node_plugin_by_node(parent)->cut_and_kill(&kdata, &info); @@ -1310,10 +1328,9 @@ carry_delete(carry_op * op /* operation Cuts part or whole content of node. */ -static int -carry_cut(carry_op * op /* operation to be performed */ , - carry_level * doing /* current carry level */ , - carry_level * todo /* next carry level */ ) +static int carry_cut(carry_op * op /* operation to be performed */ , + carry_level * doing /* current carry level */ , + carry_level * todo /* next carry level */ ) { int result; carry_plugin_info info; @@ -1339,7 +1356,8 @@ carry_cut(carry_op * op /* operation to /* helper function for carry_paste(): returns true if @op can be continued as paste */ static int -can_paste(coord_t * icoord, const reiser4_key * key, const reiser4_item_data * data) +can_paste(coord_t * icoord, const reiser4_key * key, + const reiser4_item_data * data) { coord_t circa; item_plugin *new_iplug; @@ -1365,7 +1383,8 @@ can_paste(coord_t * icoord, const reiser ignore ->between field */ if (old_iplug == new_iplug && item_can_contain_key(&circa, key, data)) { result = 1; - } else if (icoord->between == BEFORE_UNIT || icoord->between == BEFORE_ITEM) { + } else if (icoord->between == BEFORE_UNIT + || icoord->between == BEFORE_ITEM) { /* otherwise, try to glue to the item at the left, if any */ coord_dup(&circa, icoord); if (coord_set_to_left(&circa)) { @@ -1373,20 +1392,23 @@ can_paste(coord_t * icoord, const reiser coord_init_before_item(icoord); } else { old_iplug = item_plugin_by_coord(&circa); - result = (old_iplug == new_iplug) && item_can_contain_key(icoord, key, data); + result = (old_iplug == new_iplug) + && item_can_contain_key(icoord, key, data); if (result) { coord_dup(icoord, &circa); icoord->between = AFTER_UNIT; } } - } else if (icoord->between == AFTER_UNIT || icoord->between == AFTER_ITEM) { + } else if (icoord->between == AFTER_UNIT + || icoord->between == AFTER_ITEM) { coord_dup(&circa, icoord); /* otherwise, try to glue to the item at the right, if any */ if (coord_set_to_right(&circa)) { result = 0; coord_init_after_item(icoord); } else { - int (*cck) (const coord_t *, const reiser4_key *, const reiser4_item_data *); + int (*cck) (const coord_t *, const reiser4_key *, + const reiser4_item_data *); old_iplug = item_plugin_by_coord(&circa); @@ -1396,7 +1418,8 @@ can_paste(coord_t * icoord, const reiser method? So it is not expandable. */ result = 0; else { - result = (old_iplug == new_iplug) && cck(&circa /*icoord */ , key, data); + result = (old_iplug == new_iplug) + && cck(&circa /*icoord */ , key, data); if (result) { coord_dup(icoord, &circa); icoord->between = BEFORE_UNIT; @@ -1425,11 +1448,10 @@ can_paste(coord_t * icoord, const reiser comments in insert_paste_common(). */ -static int -carry_paste(carry_op * op /* operation to be performed */ , - carry_level * doing UNUSED_ARG /* current carry - * level */ , - carry_level * todo /* next carry level */ ) +static int carry_paste(carry_op * op /* operation to be performed */ , + carry_level * doing UNUSED_ARG /* current carry + * level */ , + carry_level * todo /* next carry level */ ) { znode *node; carry_insert_data cdata; @@ -1470,7 +1492,8 @@ carry_paste(carry_op * op /* operation t assert("nikita-985", node != NULL); assert("nikita-986", node_plugin_by_node(node) != NULL); - assert("nikita-987", space_needed_for_op(node, op) <= znode_free_space(node)); + assert("nikita-987", + space_needed_for_op(node, op) <= znode_free_space(node)); assert("nikita-1286", coord_is_existing_item(coord)); @@ -1503,12 +1526,11 @@ carry_paste(carry_op * op /* operation t } /* handle carry COP_EXTENT operation. */ -static int -carry_extent(carry_op * op /* operation to perform */ , - carry_level * doing /* queue of operations @op - * is part of */ , - carry_level * todo /* queue where new operations - * are accumulated */ ) +static int carry_extent(carry_op * op /* operation to perform */ , + carry_level * doing /* queue of operations @op + * is part of */ , + carry_level * todo /* queue where new operations + * are accumulated */ ) { znode *node; carry_insert_data cdata; @@ -1532,14 +1554,14 @@ carry_extent(carry_op * op /* operation at the leaf level, but I1 and I2 are in the same formatted leaf node N1. To insert extent one has to - (1) reach node N1 and shift data between N1, its neighbors and - possibly newly allocated nodes until I1 and I2 fall into different - nodes. Since I1 and I2 are still neighboring items in logical key - order, they will be necessary utmost items in their respective - nodes. + (1) reach node N1 and shift data between N1, its neighbors and + possibly newly allocated nodes until I1 and I2 fall into different + nodes. Since I1 and I2 are still neighboring items in logical key + order, they will be necessary utmost items in their respective + nodes. - (2) After this new extent item is inserted into node on the twig - level. + (2) After this new extent item is inserted into node on the twig + level. Fortunately this process can reuse almost all code from standard insertion procedure (viz. make_space() and insert_paste_common()), @@ -1550,7 +1572,7 @@ carry_extent(carry_op * op /* operation instruct free_space_shortage() to keep make_space() shifting data until insertion point is at the node border. - */ + */ /* perform common functionality of insert and paste. */ result = insert_paste_common(op, doing, todo, &cdata, &coord, &data); @@ -1574,7 +1596,7 @@ carry_extent(carry_op * op /* operation for the formatted leaf nodes. Because of this when search finds two adjacent extents on the twig level, it has to "drill" to the leaf level, creating new node. Here we are removing this node. - */ + */ if (node_is_empty(node)) { delete_dummy = node_post_carry(&info, COP_DELETE, node, 1); if (IS_ERR(delete_dummy)) @@ -1594,12 +1616,13 @@ carry_extent(carry_op * op /* operation /* NOTE-NIKITA insertion by key is simplest option here. Another possibility is to insert on the left or right of already existing item. - */ + */ insert_extent->u.insert.type = COPT_KEY; insert_extent->u.insert.d = op->u.extent.d; assert("nikita-1719", op->u.extent.d->key != NULL); insert_extent->u.insert.d->data->arg = op->u.extent.d->coord; - insert_extent->u.insert.flags = znode_get_tree(node)->carry.new_extent_flags; + insert_extent->u.insert.flags = + znode_get_tree(node)->carry.new_extent_flags; /* * if carry was asked to track lock handle we should actually track @@ -1625,18 +1648,17 @@ carry_extent(carry_op * op /* operation internal item involved. Updates item key. Updates delimiting keys of child nodes involved. */ -static int -update_delimiting_key(znode * parent /* node key is updated - * in */ , - znode * left /* child of @parent */ , - znode * right /* child of @parent */ , - carry_level * doing /* current carry - * level */ , - carry_level * todo /* parent carry - * level */ , - const char **error_msg /* place to - * store error - * message */ ) +static int update_delimiting_key(znode * parent /* node key is updated + * in */ , + znode * left /* child of @parent */ , + znode * right /* child of @parent */ , + carry_level * doing /* current carry + * level */ , + carry_level * todo /* parent carry + * level */ , + const char **error_msg /* place to + * store error + * message */ ) { coord_t left_pos; coord_t right_pos; @@ -1711,10 +1733,9 @@ update_delimiting_key(znode * parent /* Update delimiting keys. */ -static int -carry_update(carry_op * op /* operation to be performed */ , - carry_level * doing /* current carry level */ , - carry_level * todo /* next carry level */ ) +static int carry_update(carry_op * op /* operation to be performed */ , + carry_level * doing /* current carry level */ , + carry_level * todo /* next carry level */ ) { int result; carry_node *missing UNUSED_ARG; @@ -1768,7 +1789,8 @@ carry_update(carry_op * op /* operation ->update_item_key() method of node plugin, if necessary. */ if (result != 0) { - warning("nikita-999", "Error updating delimiting key: %s (%i)", error_msg ? : "", result); + warning("nikita-999", "Error updating delimiting key: %s (%i)", + error_msg ? : "", result); print_znode("left", left); print_znode("right", right); print_znode("lchild", lchild ? lchild->node : NULL); @@ -1778,18 +1800,17 @@ carry_update(carry_op * op /* operation } /* move items from @node during carry */ -static int -carry_shift_data(sideof side /* in what direction to move data */ , - coord_t * insert_coord /* coord where new item - * is to be inserted */ , - znode * node /* node which data are moved from */ , - carry_level * doing /* active carry queue */ , - carry_level * todo /* carry queue where new - * operations are to be put - * in */ , - unsigned int including_insert_coord_p /* true if - * @insertion_coord - * can be moved */ ) +static int carry_shift_data(sideof side /* in what direction to move data */ , + coord_t * insert_coord /* coord where new item + * is to be inserted */ , + znode * node /* node which data are moved from */ , + carry_level * doing /* active carry queue */ , + carry_level * todo /* carry queue where new + * operations are to be put + * in */ , + unsigned int including_insert_coord_p /* true if + * @insertion_coord + * can be moved */ ) { int result; znode *source; @@ -1804,7 +1825,7 @@ carry_shift_data(sideof side /* in what nplug = node_plugin_by_node(node); result = nplug->shift(insert_coord, node, (side == LEFT_SIDE) ? SHIFT_LEFT : SHIFT_RIGHT, 0, - (int) including_insert_coord_p, &info); + (int)including_insert_coord_p, &info); /* the only error ->shift() method of node plugin can return is -ENOMEM due to carry node/operation allocation. */ assert("nikita-915", result >= 0 || result == -ENOMEM); @@ -1823,7 +1844,13 @@ carry_shift_data(sideof side /* in what } typedef carry_node *(*carry_iterator) (carry_node * node); -static carry_node *find_dir_carry(carry_node * node, carry_level * level, carry_iterator iterator); +static carry_node *find_dir_carry(carry_node * node, carry_level * level, + carry_iterator iterator); + +static carry_node *pool_level_list_prev(carry_node *node) +{ + return list_entry(node->header.level_linkage.prev, carry_node, header.level_linkage); +} /* look for the left neighbor of given carry node in a carry queue. @@ -1831,12 +1858,17 @@ static carry_node *find_dir_carry(carry_ really gives any advantage. More statistics required. */ -reiser4_internal carry_node * -find_left_carry(carry_node * node /* node to fine left neighbor - * of */ , - carry_level * level /* level to scan */ ) +carry_node *find_left_carry(carry_node * node /* node to find left neighbor + * of */ , + carry_level * level /* level to scan */ ) +{ + return find_dir_carry(node, level, + (carry_iterator) pool_level_list_prev); +} + +static carry_node *pool_level_list_next(carry_node *node) { - return find_dir_carry(node, level, (carry_iterator) pool_level_list_prev); + return list_entry(node->header.level_linkage.next, carry_node, header.level_linkage); } /* look for the right neighbor of given carry node in a @@ -1846,12 +1878,12 @@ find_left_carry(carry_node * node /* nod really gives any advantage. More statistics required. */ -reiser4_internal carry_node * -find_right_carry(carry_node * node /* node to fine right neighbor - * of */ , - carry_level * level /* level to scan */ ) +carry_node *find_right_carry(carry_node * node /* node to find right neighbor + * of */ , + carry_level * level /* level to scan */ ) { - return find_dir_carry(node, level, (carry_iterator) pool_level_list_next); + return find_dir_carry(node, level, + (carry_iterator) pool_level_list_next); } /* look for the left or right neighbor of given carry node in a carry @@ -1859,13 +1891,12 @@ find_right_carry(carry_node * node /* no Helper function used by find_{left|right}_carry(). */ -static carry_node * -find_dir_carry(carry_node * node /* node to start scanning - * from */ , - carry_level * level /* level to scan */ , - carry_iterator iterator /* operation to - * move to the next - * node */ ) +static carry_node *find_dir_carry(carry_node * node /* node to start scanning + * from */ , + carry_level * level /* level to scan */ , + carry_iterator iterator /* operation to + * move to the next + * node */ ) { carry_node *neighbor; @@ -1877,7 +1908,8 @@ find_dir_carry(carry_node * node /* node neighbor = node; while (1) { neighbor = iterator(neighbor); - if (pool_level_list_end(&level->nodes, &neighbor->header)) + if (carry_node_end(level, neighbor)) + /* list head is reached */ return NULL; if (carry_real(neighbor) != carry_real(node)) return neighbor; @@ -1932,8 +1964,7 @@ find_dir_carry(carry_node * node /* node #define TREE_HEIGHT_CAP (5) /* return capped tree height for the @tree. See comment above. */ -static int -cap_tree_height(reiser4_tree * tree) +static int cap_tree_height(reiser4_tree * tree) { return max_t(int, tree->height, TREE_HEIGHT_CAP); } @@ -1951,8 +1982,7 @@ static int bytes_to_pages(int bytes) } /* how many pages are required to allocate znodes during item insertion. */ -static int -carry_estimate_znodes(void) +static int carry_estimate_znodes(void) { /* * Note, that there we have some problem here: there is no way to @@ -1967,89 +1997,67 @@ carry_estimate_znodes(void) /* * how many pages are required to load bitmaps. One bitmap per level. */ -static int -carry_estimate_bitmaps(void) +static int carry_estimate_bitmaps(void) { if (reiser4_is_set(reiser4_get_current_sb(), REISER4_DONT_LOAD_BITMAP)) { int bytes; - bytes = capped_height() * - (0 + /* bnode should be added, but its is private to - * bitmap.c, skip for now. */ - 2 * sizeof(jnode)); /* working and commit jnodes */ - return bytes_to_pages(bytes) + 2; /* and their contents */ + bytes = capped_height() * (0 + /* bnode should be added, but its is private to + * bitmap.c, skip for now. */ + 2 * sizeof(jnode)); /* working and commit jnodes */ + return bytes_to_pages(bytes) + 2; /* and their contents */ } else /* bitmaps were pre-loaded during mount */ return 0; } /* worst case item insertion memory requirements */ -static int -carry_estimate_insert(carry_op * op, carry_level * level) +static int carry_estimate_insert(carry_op * op, carry_level * level) { - return - carry_estimate_bitmaps() + - carry_estimate_znodes() + - 1 + /* new atom */ - capped_height() + /* new block on each level */ - 1 + /* and possibly extra new block at the leaf level */ - 3; /* loading of leaves into memory */ + return carry_estimate_bitmaps() + carry_estimate_znodes() + 1 + /* new atom */ + capped_height() + /* new block on each level */ + 1 + /* and possibly extra new block at the leaf level */ + 3; /* loading of leaves into memory */ } /* worst case item deletion memory requirements */ -static int -carry_estimate_delete(carry_op * op, carry_level * level) +static int carry_estimate_delete(carry_op * op, carry_level * level) { - return - carry_estimate_bitmaps() + - carry_estimate_znodes() + - 1 + /* new atom */ - 3; /* loading of leaves into memory */ + return carry_estimate_bitmaps() + carry_estimate_znodes() + 1 + /* new atom */ + 3; /* loading of leaves into memory */ } /* worst case tree cut memory requirements */ -static int -carry_estimate_cut(carry_op * op, carry_level * level) +static int carry_estimate_cut(carry_op * op, carry_level * level) { - return - carry_estimate_bitmaps() + - carry_estimate_znodes() + - 1 + /* new atom */ - 3; /* loading of leaves into memory */ + return carry_estimate_bitmaps() + carry_estimate_znodes() + 1 + /* new atom */ + 3; /* loading of leaves into memory */ } /* worst case memory requirements of pasting into item */ -static int -carry_estimate_paste(carry_op * op, carry_level * level) +static int carry_estimate_paste(carry_op * op, carry_level * level) { - return - carry_estimate_bitmaps() + - carry_estimate_znodes() + - 1 + /* new atom */ - capped_height() + /* new block on each level */ - 1 + /* and possibly extra new block at the leaf level */ - 3; /* loading of leaves into memory */ + return carry_estimate_bitmaps() + carry_estimate_znodes() + 1 + /* new atom */ + capped_height() + /* new block on each level */ + 1 + /* and possibly extra new block at the leaf level */ + 3; /* loading of leaves into memory */ } /* worst case memory requirements of extent insertion */ -static int -carry_estimate_extent(carry_op * op, carry_level * level) +static int carry_estimate_extent(carry_op * op, carry_level * level) { - return - carry_estimate_insert(op, level) + /* insert extent */ - carry_estimate_delete(op, level); /* kill leaf */ + return carry_estimate_insert(op, level) + /* insert extent */ + carry_estimate_delete(op, level); /* kill leaf */ } /* worst case memory requirements of key update */ -static int -carry_estimate_update(carry_op * op, carry_level * level) +static int carry_estimate_update(carry_op * op, carry_level * level) { return 0; } /* worst case memory requirements of flow insertion */ -static int -carry_estimate_insert_flow(carry_op * op, carry_level * level) +static int carry_estimate_insert_flow(carry_op * op, carry_level * level) { int newnodes; @@ -2064,35 +2072,34 @@ carry_estimate_insert_flow(carry_op * op /* This is dispatch table for carry operations. It can be trivially abstracted into useful plugin: tunable balancing policy is a good thing. */ -reiser4_internal carry_op_handler op_dispatch_table[COP_LAST_OP] = { +carry_op_handler op_dispatch_table[COP_LAST_OP] = { [COP_INSERT] = { - .handler = carry_insert, - .estimate = carry_estimate_insert - }, + .handler = carry_insert, + .estimate = carry_estimate_insert} + , [COP_DELETE] = { - .handler = carry_delete, - .estimate = carry_estimate_delete - }, + .handler = carry_delete, + .estimate = carry_estimate_delete} + , [COP_CUT] = { - .handler = carry_cut, - .estimate = carry_estimate_cut - }, + .handler = carry_cut, + .estimate = carry_estimate_cut} + , [COP_PASTE] = { - .handler = carry_paste, - .estimate = carry_estimate_paste - }, + .handler = carry_paste, + .estimate = carry_estimate_paste} + , [COP_EXTENT] = { - .handler = carry_extent, - .estimate = carry_estimate_extent - }, + .handler = carry_extent, + .estimate = carry_estimate_extent} + , [COP_UPDATE] = { - .handler = carry_update, - .estimate = carry_estimate_update - }, + .handler = carry_update, + .estimate = carry_estimate_update} + , [COP_INSERT_FLOW] = { - .handler = carry_insert_flow, - .estimate = carry_estimate_insert_flow - } + .handler = carry_insert_flow, + .estimate = carry_estimate_insert_flow} }; /* Make Linus happy. diff -puN fs/reiser4/carry_ops.h~reiser4-big-update fs/reiser4/carry_ops.h --- devel/fs/reiser4/carry_ops.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/carry_ops.h 2005-09-15 19:51:08.000000000 -0700 @@ -22,7 +22,8 @@ typedef struct carry_op_handler { thing. */ extern carry_op_handler op_dispatch_table[COP_LAST_OP]; -unsigned int space_needed(const znode * node, const coord_t * coord, const reiser4_item_data * data, int inserting); +unsigned int space_needed(const znode * node, const coord_t * coord, + const reiser4_item_data * data, int inserting); extern carry_node *find_left_carry(carry_node * node, carry_level * level); extern carry_node *find_right_carry(carry_node * node, carry_level * level); diff -puN fs/reiser4/cluster.c~reiser4-big-update fs/reiser4/cluster.c --- devel/fs/reiser4/cluster.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/cluster.c 2005-09-15 19:51:08.000000000 -0700 @@ -10,7 +10,6 @@ /* Concepts of clustering. Definition of cluster size. Data clusters, page clusters, disk clusters. - In order to compress plain text we first should split it into chunks. Then we process each chunk independently by the following function: @@ -74,8 +73,7 @@ sure that is good style? and where is the code that goes with this comment....;-) ) */ -static int -change_cluster(struct inode * inode, reiser4_plugin * plugin) +static int change_cluster(struct inode *inode, reiser4_plugin * plugin) { int result = 0; @@ -93,24 +91,24 @@ change_cluster(struct inode * inode, rei } static reiser4_plugin_ops cluster_plugin_ops = { - .init = NULL, - .load = NULL, + .init = NULL, + .load = NULL, .save_len = NULL, - .save = NULL, - .change = &change_cluster + .save = NULL, + .change = &change_cluster }; -#define SUPPORT_CLUSTER(SHIFT, ID, LABEL, DESC) \ - [CLUSTER_ ## ID ## _ID] = { \ - .h = { \ - .type_id = REISER4_CLUSTER_PLUGIN_TYPE, \ - .id = CLUSTER_ ## ID ## _ID, \ - .pops = &cluster_plugin_ops, \ - .label = LABEL, \ - .desc = DESC, \ - .linkage = TYPE_SAFE_LIST_LINK_ZERO \ - }, \ - .shift = SHIFT \ +#define SUPPORT_CLUSTER(SHIFT, ID, LABEL, DESC) \ + [CLUSTER_ ## ID ## _ID] = { \ + .h = { \ + .type_id = REISER4_CLUSTER_PLUGIN_TYPE, \ + .id = CLUSTER_ ## ID ## _ID, \ + .pops = &cluster_plugin_ops, \ + .label = LABEL, \ + .desc = DESC, \ + .linkage = {NULL, NULL} \ + }, \ + .shift = SHIFT \ } cluster_plugin cluster_plugins[LAST_CLUSTER_ID] = { diff -puN fs/reiser4/cluster.h~reiser4-big-update fs/reiser4/cluster.h --- devel/fs/reiser4/cluster.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/cluster.h 2005-09-15 19:51:08.000000000 -0700 @@ -6,6 +6,8 @@ #if !defined( __FS_REISER4_CLUSTER_H__ ) #define __FS_REISER4_CLUSTER_H__ +#include "inode.h" + static inline loff_t min_count(loff_t a, loff_t b) { return (a < b ? a : b); @@ -16,7 +18,7 @@ static inline loff_t max_count(loff_t a, return (a > b ? a : b); } -static inline int inode_cluster_shift (struct inode * inode) +static inline int inode_cluster_shift(struct inode *inode) { assert("edward-92", inode != NULL); assert("edward-93", reiser4_inode_data(inode) != NULL); @@ -24,142 +26,124 @@ static inline int inode_cluster_shift (s return inode_cluster_plugin(inode)->shift; } -static inline unsigned -cluster_nrpages_shift(struct inode * inode) +static inline unsigned cluster_nrpages_shift(struct inode *inode) { return inode_cluster_shift(inode) - PAGE_CACHE_SHIFT; } /* cluster size in page units */ -static inline unsigned cluster_nrpages (struct inode * inode) +static inline unsigned cluster_nrpages(struct inode *inode) { return 1U << cluster_nrpages_shift(inode); } -static inline size_t inode_cluster_size (struct inode * inode) +static inline size_t inode_cluster_size(struct inode *inode) { assert("edward-96", inode != NULL); return 1U << inode_cluster_shift(inode); } -static inline unsigned long -pg_to_clust(unsigned long idx, struct inode * inode) +static inline unsigned long pg_to_clust(unsigned long idx, struct inode *inode) { return idx >> cluster_nrpages_shift(inode); } -static inline unsigned long -clust_to_pg(unsigned long idx, struct inode * inode) +static inline unsigned long clust_to_pg(unsigned long idx, struct inode *inode) { return idx << cluster_nrpages_shift(inode); } static inline unsigned long -pg_to_clust_to_pg(unsigned long idx, struct inode * inode) +pg_to_clust_to_pg(unsigned long idx, struct inode *inode) { return clust_to_pg(pg_to_clust(idx, inode), inode); } -static inline unsigned long -off_to_pg(loff_t off) +static inline unsigned long off_to_pg(loff_t off) { return (off >> PAGE_CACHE_SHIFT); } -static inline loff_t -pg_to_off(unsigned long idx) +static inline loff_t pg_to_off(unsigned long idx) { - return ((loff_t)(idx) << PAGE_CACHE_SHIFT); + return ((loff_t) (idx) << PAGE_CACHE_SHIFT); } -static inline unsigned long -off_to_clust(loff_t off, struct inode * inode) +static inline unsigned long off_to_clust(loff_t off, struct inode *inode) { return off >> inode_cluster_shift(inode); } -static inline loff_t -clust_to_off(unsigned long idx, struct inode * inode) +static inline loff_t clust_to_off(unsigned long idx, struct inode *inode) { - return (loff_t)idx << inode_cluster_shift(inode); + return (loff_t) idx << inode_cluster_shift(inode); } -static inline unsigned long -count_to_nr(loff_t count, unsigned shift) +static inline unsigned long count_to_nr(loff_t count, unsigned shift) { return (count + (1UL << shift) - 1) >> shift; } /* number of pages occupied by @count bytes */ -static inline unsigned long -count_to_nrpages(loff_t count) +static inline unsigned long count_to_nrpages(loff_t count) { return count_to_nr(count, PAGE_CACHE_SHIFT); } /* number of clusters occupied by @count bytes */ -static inline cloff_t -count_to_nrclust(loff_t count, struct inode * inode) +static inline cloff_t count_to_nrclust(loff_t count, struct inode *inode) { return count_to_nr(count, inode_cluster_shift(inode)); } /* number of clusters occupied by @count pages */ -static inline cloff_t -pgcount_to_nrclust(pgoff_t count, struct inode * inode) +static inline cloff_t pgcount_to_nrclust(pgoff_t count, struct inode *inode) { return count_to_nr(count, cluster_nrpages_shift(inode)); } -static inline loff_t -off_to_clust_to_off(loff_t off, struct inode * inode) +static inline loff_t off_to_clust_to_off(loff_t off, struct inode *inode) { return clust_to_off(off_to_clust(off, inode), inode); } -static inline unsigned long -off_to_clust_to_pg(loff_t off, struct inode * inode) +static inline unsigned long off_to_clust_to_pg(loff_t off, struct inode *inode) { return clust_to_pg(off_to_clust(off, inode), inode); } -static inline unsigned -off_to_pgoff(loff_t off) +static inline unsigned off_to_pgoff(loff_t off) { return off & (PAGE_CACHE_SIZE - 1); } -static inline unsigned -off_to_cloff(loff_t off, struct inode * inode) +static inline unsigned off_to_cloff(loff_t off, struct inode *inode) { - return off & ((loff_t)(inode_cluster_size(inode)) - 1); + return off & ((loff_t) (inode_cluster_size(inode)) - 1); } static inline unsigned -pg_to_off_to_cloff(unsigned long idx, struct inode * inode) +pg_to_off_to_cloff(unsigned long idx, struct inode *inode) { return off_to_cloff(pg_to_off(idx), inode); } /* if @size != 0, returns index of the page which contains the last byte of the file */ -static inline pgoff_t -size_to_pg(loff_t size) +static inline pgoff_t size_to_pg(loff_t size) { return (size ? off_to_pg(size - 1) : 0); } /* minimal index of the page which doesn't contain file data */ -static inline pgoff_t -size_to_next_pg(loff_t size) +static inline pgoff_t size_to_next_pg(loff_t size) { return (size ? off_to_pg(size - 1) + 1 : 0); } -static inline unsigned -off_to_pgcount(loff_t off, unsigned long idx) +static inline unsigned off_to_pgcount(loff_t off, unsigned long idx) { if (idx > off_to_pg(off)) return 0; @@ -169,7 +153,7 @@ off_to_pgcount(loff_t off, unsigned long } static inline unsigned -off_to_count(loff_t off, unsigned long idx, struct inode * inode) +off_to_count(loff_t off, unsigned long idx, struct inode *inode) { if (idx > off_to_clust(off, inode)) return 0; @@ -179,7 +163,7 @@ off_to_count(loff_t off, unsigned long i } static inline unsigned -fsize_to_count(reiser4_cluster_t * clust, struct inode * inode) +fsize_to_count(reiser4_cluster_t * clust, struct inode *inode) { assert("edward-288", clust != NULL); assert("edward-289", inode != NULL); @@ -187,41 +171,40 @@ fsize_to_count(reiser4_cluster_t * clust return off_to_count(inode->i_size, clust->index, inode); } -static inline void -reiser4_slide_init (reiser4_slide_t * win){ +static inline void reiser4_slide_init(reiser4_slide_t * win) +{ assert("edward-1084", win != NULL); memset(win, 0, sizeof *win); } static inline void -reiser4_cluster_init (reiser4_cluster_t * clust, reiser4_slide_t * window){ +reiser4_cluster_init(reiser4_cluster_t * clust, reiser4_slide_t * window) +{ assert("edward-84", clust != NULL); memset(clust, 0, sizeof *clust); clust->dstat = INVAL_DISK_CLUSTER; clust->win = window; } -static inline int -dclust_get_extension(hint_t * hint) +static inline int dclust_get_extension(hint_t * hint) { return hint->ext_coord.extension.ctail.shift; } -static inline void -dclust_set_extension(hint_t * hint) +static inline void dclust_set_extension(hint_t * hint) { - assert("edward-1270", item_id_by_coord(&hint->ext_coord.coord) == CTAIL_ID); - hint->ext_coord.extension.ctail.shift = cluster_shift_by_coord(&hint->ext_coord.coord); + assert("edward-1270", + item_id_by_coord(&hint->ext_coord.coord) == CTAIL_ID); + hint->ext_coord.extension.ctail.shift = + cluster_shift_by_coord(&hint->ext_coord.coord); } -static inline int -hint_is_unprepped_dclust(hint_t * hint) +static inline int hint_is_unprepped_dclust(hint_t * hint) { return dclust_get_extension(hint) == (int)UCTAIL_SHIFT; } -static inline void -coord_set_between_clusters(coord_t * coord) +static inline void coord_set_between_clusters(coord_t * coord) { #if REISER4_DEBUG int result; @@ -239,29 +222,33 @@ coord_set_between_clusters(coord_t * coo int inflate_cluster(reiser4_cluster_t *, struct inode *); int find_cluster(reiser4_cluster_t *, struct inode *, int read, int write); -void forget_cluster_pages(struct page ** page, int nrpages); +void forget_cluster_pages(struct page **page, int nrpages); int flush_cluster_pages(reiser4_cluster_t *, jnode *, struct inode *); int deflate_cluster(reiser4_cluster_t *, struct inode *); -void truncate_page_cluster(struct inode * inode, cloff_t start); -void set_hint_cluster(struct inode * inode, hint_t * hint, unsigned long index, znode_lock_mode mode); +void truncate_page_cluster(struct inode *inode, cloff_t start); +void set_hint_cluster(struct inode *inode, hint_t * hint, unsigned long index, + znode_lock_mode mode); void invalidate_hint_cluster(reiser4_cluster_t * clust); -int get_disk_cluster_locked(reiser4_cluster_t * clust, struct inode * inode, znode_lock_mode lock_mode); +int get_disk_cluster_locked(reiser4_cluster_t * clust, struct inode *inode, + znode_lock_mode lock_mode); void reset_cluster_params(reiser4_cluster_t * clust); -int prepare_page_cluster(struct inode *inode, reiser4_cluster_t *clust, int capture); +int prepare_page_cluster(struct inode *inode, reiser4_cluster_t * clust, + int capture); void release_cluster_pages_nocapture(reiser4_cluster_t *); void put_cluster_handle(reiser4_cluster_t * clust, tfm_action act); -int grab_tfm_stream(struct inode * inode, tfm_cluster_t * tc, tfm_action act, tfm_stream_id id); -int tfm_cluster_is_uptodate (tfm_cluster_t * tc); -void tfm_cluster_set_uptodate (tfm_cluster_t * tc); -void tfm_cluster_clr_uptodate (tfm_cluster_t * tc); -unsigned long clust_by_coord(const coord_t * coord, struct inode * inode); +int grab_tfm_stream(struct inode *inode, tfm_cluster_t * tc, tfm_action act, + tfm_stream_id id); +int tfm_cluster_is_uptodate(tfm_cluster_t * tc); +void tfm_cluster_set_uptodate(tfm_cluster_t * tc); +void tfm_cluster_clr_uptodate(tfm_cluster_t * tc); +unsigned long clust_by_coord(const coord_t * coord, struct inode *inode); /* move cluster handle to the target position specified by the page of index @pgidx */ static inline void -move_cluster_forward(reiser4_cluster_t * clust, struct inode * inode, - pgoff_t pgidx, int * progress) +move_cluster_forward(reiser4_cluster_t * clust, struct inode *inode, + pgoff_t pgidx, int *progress) { assert("edward-1297", clust != NULL); assert("edward-1298", inode != NULL); @@ -280,24 +267,24 @@ move_cluster_forward(reiser4_cluster_t * } static inline int -alloc_clust_pages(reiser4_cluster_t * clust, struct inode * inode ) +alloc_clust_pages(reiser4_cluster_t * clust, struct inode *inode) { assert("edward-791", clust != NULL); assert("edward-792", inode != NULL); - clust->pages = reiser4_kmalloc(sizeof(*clust->pages) << inode_cluster_shift(inode), GFP_KERNEL); + clust->pages = + kmalloc(sizeof(*clust->pages) << inode_cluster_shift(inode), + GFP_KERNEL); if (!clust->pages) return -ENOMEM; return 0; } -static inline void -free_clust_pages(reiser4_cluster_t * clust) +static inline void free_clust_pages(reiser4_cluster_t * clust) { - reiser4_kfree(clust->pages); + kfree(clust->pages); } -#endif /* __FS_REISER4_CLUSTER_H__ */ - +#endif /* __FS_REISER4_CLUSTER_H__ */ /* Make Linus happy. Local variables: diff -puN fs/reiser4/context.c~reiser4-big-update fs/reiser4/context.c --- devel/fs/reiser4/context.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/context.c 2005-09-15 19:51:08.000000000 -0700 @@ -37,90 +37,88 @@ #include "super.h" #include "context.h" -#include /* balance_dirty_pages() */ +#include /* balance_dirty_pages() */ #include -#if REISER4_DEBUG -/* List of all currently active contexts, used for debugging purposes. */ -static context_list_head active_contexts; -/* lock protecting access to active_contexts. */ -spinlock_t active_contexts_lock; +static void _init_context(reiser4_context * context, struct super_block *super) +{ + memset(context, 0, sizeof(*context)); + + context->super = super; + context->magic = context_magic; + context->outer = current->journal_info; + current->journal_info = (void *)context; + context->nr_children = 0; + + init_lock_stack(&context->stack); -#endif /* REISER4_DEBUG */ + txn_begin(context); + + /* initialize head of tap list */ + INIT_LIST_HEAD(&context->taps); +#if REISER4_DEBUG + context->task = current; +#endif + grab_space_enable(); +} -/* initialise context and bind it to the current thread +/* initialize context and bind it to the current thread This function should be called at the beginning of reiser4 part of syscall. */ -reiser4_internal int -init_context(reiser4_context * context /* pointer to the reiser4 context - * being initalised */ , - struct super_block *super /* super block we are going to - * work with */) +reiser4_context *init_context(struct super_block *super /* super block we are going to + * work with */ ) { + reiser4_context *context; + assert("nikita-2662", !in_interrupt() && !in_irq()); - assert("nikita-3356", context != NULL); assert("nikita-3357", super != NULL); assert("nikita-3358", super->s_op == NULL || is_reiser4_super(super)); - memset(context, 0, sizeof *context); - - if (is_in_reiser4_context()) { - reiser4_context *parent; - - parent = (reiser4_context *) current->journal_info; - /* NOTE-NIKITA this is dubious */ - if (parent->super == super) { - context->parent = parent; -#if (REISER4_DEBUG) - ++context->parent->nr_children; -#endif - return 0; - } + context = get_current_context_check(); + if (context && context->super == super) { + context = (reiser4_context *) current->journal_info; + context->nr_children++; + return context; } - context->super = super; - context->magic = context_magic; - context->outer = current->journal_info; - current->journal_info = (void *) context; + context = kmalloc(sizeof(*context), GFP_KERNEL); + if (context == NULL) + return ERR_PTR(RETERR(-ENOMEM)); - init_lock_stack(&context->stack); + _init_context(context, super); + return context; +} - txn_begin(context); +/* this is used in scan_mgr which is called with spinlock held and in + reiser4_fill_super magic */ +void init_stack_context(reiser4_context *context, struct super_block *super) +{ + assert("nikita-2662", !in_interrupt() && !in_irq()); + assert("nikita-3357", super != NULL); + assert("nikita-3358", super->s_op == NULL || is_reiser4_super(super)); + assert("vs-12", !is_in_reiser4_context()); - context->parent = context; - tap_list_init(&context->taps); -#if REISER4_DEBUG - context_list_clean(context); /* to satisfy assertion */ - spin_lock(&active_contexts_lock); - context_list_check(&active_contexts); - context_list_push_front(&active_contexts, context); - spin_unlock(&active_contexts_lock); - context->task = current; -#endif - grab_space_enable(); - return 0; + _init_context(context, super); + context->on_stack = 1; + return; } /* cast lock stack embedded into reiser4 context up to its container */ -reiser4_internal reiser4_context * -get_context_by_lock_stack(lock_stack * owner) +reiser4_context *get_context_by_lock_stack(lock_stack * owner) { return container_of(owner, reiser4_context, stack); } /* true if there is already _any_ reiser4 context for the current thread */ -reiser4_internal int -is_in_reiser4_context(void) +int is_in_reiser4_context(void) { reiser4_context *ctx; ctx = current->journal_info; - return - ctx != NULL && - ((unsigned long) ctx->magic) == context_magic; + return ctx != NULL && ((unsigned long)ctx->magic) == context_magic; } /* @@ -140,63 +138,23 @@ is_in_reiser4_context(void) * because some important lock (like ->i_sem on the parent directory) is * held. To achieve this, ->nobalance flag can be set in the current context. */ -static void -balance_dirty_pages_at(reiser4_context * context) +static void balance_dirty_pages_at(reiser4_context *context) { - reiser4_super_info_data * sbinfo = get_super_private(context->super); + reiser4_super_info_data *sbinfo = get_super_private(context->super); /* * call balance_dirty_pages_ratelimited() to process formatted nodes - * dirtied during this system call. + * dirtied during this system call. Do that only if we are not in mount + * and there were nodes dirtied in this context and we are not in + * writepage (to avoid deadlock) and not in pdflush */ - if (context->nr_marked_dirty != 0 && /* were any nodes dirtied? */ - /* aren't we called early during mount? */ - sbinfo->fake && - /* don't call balance dirty pages from ->writepage(): it's - * deadlock prone */ + if (sbinfo != NULL && sbinfo->fake != NULL && + context->nr_marked_dirty != 0 && !(current->flags & PF_MEMALLOC) && - /* and don't stall pdflush */ !current_is_pdflush()) balance_dirty_pages_ratelimited(sbinfo->fake->i_mapping); } -/* - * exit reiser4 context. Call balance_dirty_pages_at() if necessary. Close - * transaction. Call done_context() to do context related book-keeping. - */ -reiser4_internal void reiser4_exit_context(reiser4_context * context) -{ - assert("nikita-3021", schedulable()); - - if (context == context->parent) { - if (!context->nobalance) { - txn_restart(context); - balance_dirty_pages_at(context); - } - - /* if filesystem is mounted with -o sync or -o dirsync - commit - transaction. FIXME: TXNH_DONT_COMMIT is used to avoid - commiting on exit_context when inode semaphore is held and - to have ktxnmgrd to do commit instead to get better - concurrent filesystem accesses. But, when one mounts with -o - sync, he cares more about reliability than about - performance. So, for now we have this simple mount -o sync - support. */ - if (context->super->s_flags & (MS_SYNCHRONOUS | MS_DIRSYNC)) { - txn_atom *atom; - - atom = get_current_atom_locked_nocheck(); - if (atom) { - atom->flags |= ATOM_FORCE_COMMIT; - context->trans->flags &= ~TXNH_DONT_COMMIT; - UNLOCK_ATOM(atom); - } - } - txn_end(context); - } - done_context(context); -} - /* release resources associated with context. This function should be called at the end of "session" with reiser4, @@ -206,28 +164,23 @@ reiser4_internal void reiser4_exit_conte thread released all locks and closed transcrash etc. */ -reiser4_internal void -done_context(reiser4_context * context /* context being released */) +static void done_context(reiser4_context * context /* context being released */ ) { - reiser4_context *parent; assert("nikita-860", context != NULL); - - parent = context->parent; - assert("nikita-2174", parent != NULL); - assert("nikita-2093", parent == parent->parent); - assert("nikita-859", parent->magic == context_magic); - assert("vs-646", (reiser4_context *) current->journal_info == parent); + assert("nikita-859", context->magic == context_magic); + assert("vs-646", (reiser4_context *) current->journal_info == context); assert("zam-686", !in_interrupt() && !in_irq()); /* only do anything when leaving top-level reiser4 context. All nested * contexts are just dummies. */ - if (parent == context) { - assert("jmacd-673", parent->trans == NULL); - assert("jmacd-1002", lock_stack_isclean(&parent->stack)); + if (context->nr_children == 0) { + assert("jmacd-673", context->trans == NULL); + assert("jmacd-1002", lock_stack_isclean(&context->stack)); assert("nikita-1936", no_counters_are_held()); - assert("nikita-3403", !delayed_inode_updates(context->dirty)); - assert("nikita-2626", tap_list_empty(taps_list())); - assert("zam-1004", get_super_private(context->super)->delete_sema_owner != current); + assert("nikita-2626", list_empty_careful(taps_list())); + assert("zam-1004", ergo(get_super_private(context->super), + get_super_private(context->super)->delete_sema_owner != + current)); /* release all grabbed but as yet unused blocks */ if (context->grabbed_blocks != 0) @@ -249,74 +202,63 @@ done_context(reiser4_context * context / spin_lock_stack(&context->stack); spin_unlock_stack(&context->stack); -#if REISER4_DEBUG - /* remove from active contexts */ - spin_lock(&active_contexts_lock); - context_list_remove(parent); - spin_unlock(&active_contexts_lock); -#endif assert("zam-684", context->nr_children == 0); /* restore original ->fs_context value */ current->journal_info = context->outer; + if (context->on_stack == 0) + kfree(context); } else { + context->nr_children--; #if REISER4_DEBUG - parent->nr_children--; - assert("zam-685", parent->nr_children >= 0); + assert("zam-685", context->nr_children >= 0); #endif } } -/* Initialize list of all contexts */ -reiser4_internal int -init_context_mgr(void) -{ -#if REISER4_DEBUG - spin_lock_init(&active_contexts_lock); - context_list_init(&active_contexts); -#endif - return 0; -} - -#if REISER4_DEBUG -/* debugging function: output reiser4 context contexts in the human readable - * form */ -static void -print_context(const char *prefix, reiser4_context * context) +/* + * exit reiser4 context. Call balance_dirty_pages_at() if necessary. Close + * transaction. Call done_context() to do context related book-keeping. + */ +void reiser4_exit_context(reiser4_context * context) { - if (context == NULL) { - printk("%s: null context\n", prefix); - return; - } - print_lock_counters("\tlocks", &context->locks); - printk("pid: %i, comm: %s\n", context->task->pid, context->task->comm); - print_lock_stack("\tlock stack", &context->stack); - info_atom("\tatom", context->trans_in_ctx.atom); -} + assert("nikita-3021", schedulable()); -/* debugging: dump contents of all active contexts */ -void -print_contexts(void) -{ - reiser4_context *context; + if (context->nr_children == 0) { + if (!context->nobalance) { + txn_restart(context); + balance_dirty_pages_at(context); + } - spin_lock(&active_contexts_lock); + /* if filesystem is mounted with -o sync or -o dirsync - commit + transaction. FIXME: TXNH_DONT_COMMIT is used to avoid + commiting on exit_context when inode semaphore is held and + to have ktxnmgrd to do commit instead to get better + concurrent filesystem accesses. But, when one mounts with -o + sync, he cares more about reliability than about + performance. So, for now we have this simple mount -o sync + support. */ + if (context->super->s_flags & (MS_SYNCHRONOUS | MS_DIRSYNC)) { + txn_atom *atom; - for_all_type_safe_list(context, &active_contexts, context) { - print_context("context", context); + atom = get_current_atom_locked_nocheck(); + if (atom) { + atom->flags |= ATOM_FORCE_COMMIT; + context->trans->flags &= ~TXNH_DONT_COMMIT; + UNLOCK_ATOM(atom); + } + } + txn_end(context); } - - spin_unlock(&active_contexts_lock); + done_context(context); } -#endif - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - scroll-step: 1 - End: -*/ +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 120 + * scroll-step: 1 + * End: + */ diff -puN fs/reiser4/context.h~reiser4-big-update fs/reiser4/context.h --- devel/fs/reiser4/context.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/context.h 2005-09-15 19:51:08.000000000 -0700 @@ -10,7 +10,6 @@ #include "debug.h" #include "spin_macros.h" #include "dformat.h" -#include "type_safe_list.h" #include "tap.h" #include "lock.h" @@ -19,60 +18,6 @@ #include #include /* for struct task_struct */ -/* list of active lock stacks */ -#if REISER4_DEBUG -TYPE_SAFE_LIST_DECLARE(context); -#endif - -ON_DEBUG(TYPE_SAFE_LIST_DECLARE(flushers);) - -#if REISER4_DEBUG - -/* - * Stat-data update tracking. - * - * Some reiser4 functions (reiser4_{del,add}_nlink() take an additional - * parameter indicating whether stat-data update should be performed. This is - * because sometimes fields of the same inode are modified several times - * during single system and updating stat-data (which implies tree lookup and, - * sometimes, tree balancing) on each inode modification is too expensive. To - * avoid unnecessary stat-data updates, we pass flag to not update it during - * inode field updates, and update it manually at the end of the system call. - * - * This introduces a possibility of "missed stat data update" when final - * stat-data update is not performed in some code path. To detect and track - * down such situations following code was developed. - * - * dirty_inode_info is an array of slots. Each slot keeps information about - * "delayed stat data update", that is about a call to a function modifying - * inode field that was instructed to not update stat data. Direct call to - * reiser4_update_sd() clears corresponding slot. On leaving reiser4 context - * all slots are scanned and information about still not forced updates is - * printed. - */ - -/* how many delayed stat data update slots to remember */ -#define TRACKED_DELAYED_UPDATE (0) - -typedef struct { - ino_t ino; /* inode number of object with delayed stat data - * update */ - int delayed; /* 1 if update is delayed, 0 if update for forced */ - void *stack[4]; /* stack back-trace of the call chain where update was - * delayed */ -} dirty_inode_info[TRACKED_DELAYED_UPDATE]; - -extern void mark_inode_update(struct inode *object, int immediate); -extern int delayed_inode_updates(dirty_inode_info info); - -#else - -typedef struct {} dirty_inode_info; - -#define mark_inode_update(object, immediate) noop -#define delayed_inode_updates(info) noop - -#endif /* reiser4 per-thread context */ struct reiser4_context { @@ -100,24 +45,25 @@ struct reiser4_context { /* per-thread grabbed (for further allocation) blocks counter */ reiser4_block_nr grabbed_blocks; - /* parent context */ - reiser4_context *parent; - /* list of taps currently monitored. See tap.c */ - tap_list_head taps; + struct list_head taps; /* grabbing space is enabled */ - int grab_enabled :1; - /* should be set when we are write dirty nodes to disk in jnode_flush or + unsigned int grab_enabled:1; + /* should be set when we are write dirty nodes to disk in jnode_flush or * reiser4_write_logs() */ - int writeout_mode :1; + unsigned int writeout_mode:1; /* true, if current thread is an ent thread */ - int entd :1; + unsigned int entd:1; /* true, if balance_dirty_pages() should not be run when leaving this * context. This is used to avoid lengthly balance_dirty_pages() * operation when holding some important resource, like directory * ->i_sem */ - int nobalance :1; + unsigned int nobalance:1; + + /* this bit is used on done_context to decide whether context is + kmalloc-ed and has to be kfree-ed */ + unsigned int on_stack:1; /* count non-trivial jnode_set_dirty() calls */ unsigned long nr_marked_dirty; @@ -128,14 +74,12 @@ struct reiser4_context { * reiser4_sync_inodes reaches some threshold - some atoms get * flushed */ int nr_captured; + int nr_children; /* number of child contexts */ #if REISER4_DEBUG - /* A link of all active contexts. */ - context_list_link contexts_link; /* debugging information about reiser4 locks held by the current * thread */ lock_counters_info locks; - int nr_children; /* number of child contexts */ - struct task_struct *task; /* so we can easily find owner of the stack */ + struct task_struct *task; /* so we can easily find owner of the stack */ /* * disk space grabbing debugging support @@ -145,27 +89,15 @@ struct reiser4_context { reiser4_block_nr grabbed_initially; /* list of all threads doing flush currently */ - flushers_list_link flushers_link; + struct list_head flushers_link; /* information about last error encountered by reiser4 */ err_site err; - /* information about delayed stat data updates. See above. */ - dirty_inode_info dirty; - -#ifdef CONFIG_FRAME_POINTER - void *grabbed_at[4]; -#endif #endif }; -#if REISER4_DEBUG -TYPE_SAFE_LIST_DEFINE(context, reiser4_context, contexts_link); -TYPE_SAFE_LIST_DEFINE(flushers, reiser4_context, flushers_link); -#endif - extern reiser4_context *get_context_by_lock_stack(lock_stack *); /* Debugging helps. */ -extern int init_context_mgr(void); #if REISER4_DEBUG extern void print_contexts(void); #endif @@ -174,8 +106,9 @@ extern void print_contexts(void); #define current_blocksize reiser4_get_current_sb()->s_blocksize #define current_blocksize_bits reiser4_get_current_sb()->s_blocksize_bits -extern int init_context(reiser4_context * context, struct super_block *super); -extern void done_context(reiser4_context * context); +extern reiser4_context *init_context(struct super_block *); +extern void init_stack_context(reiser4_context *, struct super_block *); +extern void reiser4_exit_context(reiser4_context *); /* magic constant we store in reiser4_context allocated at the stack. Used to catch accesses to staled or uninitialized contexts. */ @@ -186,18 +119,17 @@ extern int is_in_reiser4_context(void); /* * return reiser4_context for the thread @tsk */ -static inline reiser4_context * -get_context(const struct task_struct *tsk) +static inline reiser4_context *get_context(const struct task_struct *tsk) { - assert("vs-1682", ((reiser4_context *) tsk->journal_info)->magic == context_magic); + assert("vs-1682", + ((reiser4_context *) tsk->journal_info)->magic == context_magic); return (reiser4_context *) tsk->journal_info; } /* * return reiser4 context of the current thread, or NULL if there is none. */ -static inline reiser4_context * -get_current_context_check(void) +static inline reiser4_context *get_current_context_check(void) { if (is_in_reiser4_context()) return get_context(current); @@ -205,11 +137,10 @@ get_current_context_check(void) return NULL; } -static inline reiser4_context * get_current_context(void);/* __attribute__((const));*/ +static inline reiser4_context *get_current_context(void); /* __attribute__((const)); */ /* return context associated with current thread */ -static inline reiser4_context * -get_current_context(void) +static inline reiser4_context *get_current_context(void) { return get_context(current); } @@ -251,12 +182,12 @@ static inline void grab_space_disable(vo get_current_context()->grab_enabled = 0; } -static inline void grab_space_set_enabled (int enabled) +static inline void grab_space_set_enabled(int enabled) { get_current_context()->grab_enabled = enabled; } -static inline int is_grab_enabled(reiser4_context *ctx) +static inline int is_grab_enabled(reiser4_context * ctx) { return ctx->grab_enabled; } @@ -267,13 +198,10 @@ static inline int is_grab_enabled(reiser * directory. Commit will be performed by ktxnmgrd. */ static inline void context_set_commit_async(reiser4_context * context) { - context = context->parent; context->nobalance = 1; context->trans->flags |= TXNH_DONT_COMMIT; } -extern void reiser4_exit_context(reiser4_context * context); - /* __REISER4_CONTEXT_H__ */ #endif diff -puN fs/reiser4/coord.c~reiser4-big-update fs/reiser4/coord.c --- devel/fs/reiser4/coord.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/coord.c 2005-09-15 19:51:08.000000000 -0700 @@ -10,7 +10,7 @@ /* Internal constructor. */ static inline void -coord_init_values(coord_t *coord, const znode *node, pos_in_node_t item_pos, +coord_init_values(coord_t * coord, const znode * node, pos_in_node_t item_pos, pos_in_node_t unit_pos, between_enum between) { coord->node = (znode *) node; @@ -25,8 +25,7 @@ coord_init_values(coord_t *coord, const /* after shifting of node content, coord previously set properly may become invalid, try to "normalize" it. */ -reiser4_internal void -coord_normalize(coord_t *coord) +void coord_normalize(coord_t * coord) { znode *node; @@ -37,15 +36,19 @@ coord_normalize(coord_t *coord) if (node_is_empty(node)) { coord_init_first_unit(coord, node); - } else if ((coord->between == AFTER_ITEM) || (coord->between == AFTER_UNIT)) { + } else if ((coord->between == AFTER_ITEM) + || (coord->between == AFTER_UNIT)) { return; - } else if (coord->item_pos == coord_num_items(coord) && coord->between == BEFORE_ITEM) { + } else if (coord->item_pos == coord_num_items(coord) + && coord->between == BEFORE_ITEM) { coord_dec_item_pos(coord); coord->between = AFTER_ITEM; - } else if (coord->unit_pos == coord_num_units(coord) && coord->between == BEFORE_UNIT) { + } else if (coord->unit_pos == coord_num_units(coord) + && coord->between == BEFORE_UNIT) { coord->unit_pos--; coord->between = AFTER_UNIT; - } else if (coord->item_pos == coord_num_items(coord) && coord->unit_pos == 0 && coord->between == BEFORE_UNIT) { + } else if (coord->item_pos == coord_num_items(coord) + && coord->unit_pos == 0 && coord->between == BEFORE_UNIT) { coord_dec_item_pos(coord); coord->unit_pos = 0; coord->between = AFTER_ITEM; @@ -53,8 +56,7 @@ coord_normalize(coord_t *coord) } /* Copy a coordinate. */ -reiser4_internal void -coord_dup(coord_t * coord, const coord_t * old_coord) +void coord_dup(coord_t * coord, const coord_t * old_coord) { assert("jmacd-9800", coord_check(old_coord)); coord_dup_nocheck(coord, old_coord); @@ -62,8 +64,7 @@ coord_dup(coord_t * coord, const coord_t /* Copy a coordinate without check. Useful when old_coord->node is not loaded. As in cbk_tree_lookup -> connect_znode -> connect_one_side */ -reiser4_internal void -coord_dup_nocheck(coord_t * coord, const coord_t * old_coord) +void coord_dup_nocheck(coord_t * coord, const coord_t * old_coord) { coord->node = old_coord->node; coord_set_item_pos(coord, old_coord->item_pos); @@ -75,22 +76,19 @@ coord_dup_nocheck(coord_t * coord, const } /* Initialize an invalid coordinate. */ -reiser4_internal void -coord_init_invalid(coord_t * coord, const znode * node) +void coord_init_invalid(coord_t * coord, const znode * node) { coord_init_values(coord, node, 0, 0, INVALID_COORD); } -reiser4_internal void -coord_init_first_unit_nocheck(coord_t * coord, const znode * node) +void coord_init_first_unit_nocheck(coord_t * coord, const znode * node) { coord_init_values(coord, node, 0, 0, AT_UNIT); } /* Initialize a coordinate to point at the first unit of the first item. If the node is empty, it is positioned at the EMPTY_NODE. */ -reiser4_internal void -coord_init_first_unit(coord_t * coord, const znode * node) +void coord_init_first_unit(coord_t * coord, const znode * node) { int is_empty = node_is_empty(node); @@ -101,12 +99,13 @@ coord_init_first_unit(coord_t * coord, c /* Initialize a coordinate to point at the last unit of the last item. If the node is empty, it is positioned at the EMPTY_NODE. */ -reiser4_internal void -coord_init_last_unit(coord_t * coord, const znode * node) +void coord_init_last_unit(coord_t * coord, const znode * node) { int is_empty = node_is_empty(node); - coord_init_values(coord, node, (is_empty ? 0 : node_num_items(node) - 1), 0, (is_empty ? EMPTY_NODE : AT_UNIT)); + coord_init_values(coord, node, + (is_empty ? 0 : node_num_items(node) - 1), 0, + (is_empty ? EMPTY_NODE : AT_UNIT)); if (!is_empty) coord->unit_pos = coord_last_unit_pos(coord); assert("jmacd-9802", coord_check(coord)); @@ -114,49 +113,46 @@ coord_init_last_unit(coord_t * coord, co /* Initialize a coordinate to before the first item. If the node is empty, it is positioned at the EMPTY_NODE. */ -reiser4_internal void -coord_init_before_first_item(coord_t * coord, const znode * node) +void coord_init_before_first_item(coord_t * coord, const znode * node) { int is_empty = node_is_empty(node); - coord_init_values(coord, node, 0, 0, (is_empty ? EMPTY_NODE : BEFORE_UNIT)); + coord_init_values(coord, node, 0, 0, + (is_empty ? EMPTY_NODE : BEFORE_UNIT)); assert("jmacd-9803", coord_check(coord)); } /* Initialize a coordinate to after the last item. If the node is empty, it is positioned at the EMPTY_NODE. */ -reiser4_internal void -coord_init_after_last_item(coord_t * coord, const znode * node) +void coord_init_after_last_item(coord_t * coord, const znode * node) { int is_empty = node_is_empty(node); coord_init_values(coord, node, - (is_empty ? 0 : node_num_items(node) - 1), 0, (is_empty ? EMPTY_NODE : AFTER_ITEM)); + (is_empty ? 0 : node_num_items(node) - 1), 0, + (is_empty ? EMPTY_NODE : AFTER_ITEM)); assert("jmacd-9804", coord_check(coord)); } /* Initialize a coordinate to after last unit in the item. Coord must be set already to existing item */ -reiser4_internal void -coord_init_after_item_end(coord_t * coord) +void coord_init_after_item_end(coord_t * coord) { coord->between = AFTER_UNIT; coord->unit_pos = coord_last_unit_pos(coord); } /* Initialize a coordinate to before the item. Coord must be set already to existing item */ -reiser4_internal void -coord_init_before_item(coord_t * coord) +void coord_init_before_item(coord_t * coord) { coord->unit_pos = 0; coord->between = BEFORE_ITEM; } /* Initialize a coordinate to after the item. Coord must be set already to existing item */ -reiser4_internal void -coord_init_after_item(coord_t * coord) +void coord_init_after_item(coord_t * coord) { coord->unit_pos = 0; coord->between = AFTER_ITEM; @@ -164,15 +160,13 @@ coord_init_after_item(coord_t * coord) /* Initialize a coordinate by 0s. Used in places where init_coord was used and it was not clear how actually */ -reiser4_internal void -coord_init_zero(coord_t * coord) +void coord_init_zero(coord_t * coord) { - memset(coord, 0, sizeof (*coord)); + memset(coord, 0, sizeof(*coord)); } /* Return the number of units at the present item. Asserts coord_is_existing_item(). */ -reiser4_internal unsigned -coord_num_units(const coord_t * coord) +unsigned coord_num_units(const coord_t * coord) { assert("jmacd-9806", coord_is_existing_item(coord)); @@ -181,8 +175,7 @@ coord_num_units(const coord_t * coord) /* Returns true if the coord was initializewd by coord_init_invalid (). */ /* Audited by: green(2002.06.15) */ -reiser4_internal int -coord_is_invalid(const coord_t * coord) +int coord_is_invalid(const coord_t * coord) { return coord->between == INVALID_COORD; } @@ -190,8 +183,7 @@ coord_is_invalid(const coord_t * coord) /* Returns true if the coordinate is positioned at an existing item, not before or after an item. It may be placed at, before, or after any unit within the item, whether existing or not. */ -reiser4_internal int -coord_is_existing_item(const coord_t * coord) +int coord_is_existing_item(const coord_t * coord) { switch (coord->between) { case EMPTY_NODE: @@ -213,8 +205,7 @@ coord_is_existing_item(const coord_t * c /* Returns true if the coordinate is positioned at an existing unit, not before or after a unit. */ /* Audited by: green(2002.06.15) */ -reiser4_internal int -coord_is_existing_unit(const coord_t * coord) +int coord_is_existing_unit(const coord_t * coord) { switch (coord->between) { case EMPTY_NODE: @@ -226,7 +217,8 @@ coord_is_existing_unit(const coord_t * c return 0; case AT_UNIT: - return (coord->item_pos < coord_num_items(coord) && coord->unit_pos < coord_num_units(coord)); + return (coord->item_pos < coord_num_items(coord) + && coord->unit_pos < coord_num_units(coord)); } impossible("jmacd-9902", "unreachable"); @@ -236,16 +228,15 @@ coord_is_existing_unit(const coord_t * c /* Returns true if the coordinate is positioned at the first unit of the first item. Not true for empty nodes nor coordinates positioned before the first item. */ /* Audited by: green(2002.06.15) */ -reiser4_internal int -coord_is_leftmost_unit(const coord_t * coord) +int coord_is_leftmost_unit(const coord_t * coord) { - return (coord->between == AT_UNIT && coord->item_pos == 0 && coord->unit_pos == 0); + return (coord->between == AT_UNIT && coord->item_pos == 0 + && coord->unit_pos == 0); } #if REISER4_DEBUG /* For assertions only, checks for a valid coordinate. */ -int -coord_check(const coord_t * coord) +int coord_check(const coord_t * coord) { if (coord->node == NULL) { return 0; @@ -265,7 +256,8 @@ coord_check(const coord_t * coord) case BEFORE_UNIT: case AFTER_UNIT: - if (node_is_empty(coord->node) && (coord->item_pos == 0) && (coord->unit_pos == 0)) + if (node_is_empty(coord->node) && (coord->item_pos == 0) + && (coord->unit_pos == 0)) return 1; case AT_UNIT: break; @@ -288,7 +280,8 @@ coord_check(const coord_t * coord) return 1; if (coord_is_iplug_set(coord) && - coord->unit_pos > item_plugin_by_coord(coord)->b.nr_units(coord) - 1) { + coord->unit_pos > + item_plugin_by_coord(coord)->b.nr_units(coord) - 1) { return 0; } return 1; @@ -297,8 +290,7 @@ coord_check(const coord_t * coord) /* Adjust coordinate boundaries based on the number of items prior to coord_next/prev. Returns 1 if the new position is does not exist. */ -static int -coord_adjust_items(coord_t * coord, unsigned items, int is_next) +static int coord_adjust_items(coord_t * coord, unsigned items, int is_next) { /* If the node is invalid, leave it. */ if (coord->between == INVALID_COORD) { @@ -336,8 +328,7 @@ coord_adjust_items(coord_t * coord, unsi /* Advances the coordinate by one unit to the right. If empty, no change. If coord_is_rightmost_unit, advances to AFTER THE LAST ITEM. Returns 0 if new position is an existing unit. */ -reiser4_internal int -coord_next_unit(coord_t * coord) +int coord_next_unit(coord_t * coord) { unsigned items = coord_num_items(coord); @@ -397,8 +388,7 @@ coord_next_unit(coord_t * coord) /* Advances the coordinate by one item to the right. If empty, no change. If coord_is_rightmost_unit, advances to AFTER THE LAST ITEM. Returns 0 if new position is an existing item. */ -reiser4_internal int -coord_next_item(coord_t * coord) +int coord_next_item(coord_t * coord) { unsigned items = coord_num_items(coord); @@ -443,8 +433,7 @@ coord_next_item(coord_t * coord) /* Advances the coordinate by one unit to the left. If empty, no change. If coord_is_leftmost_unit, advances to BEFORE THE FIRST ITEM. Returns 0 if new position is an existing unit. */ -reiser4_internal int -coord_prev_unit(coord_t * coord) +int coord_prev_unit(coord_t * coord) { unsigned items = coord_num_items(coord); @@ -473,7 +462,8 @@ coord_prev_unit(coord_t * coord) case AFTER_UNIT: /* What if unit_pos is out-of-range? */ - assert("jmacd-5442", coord->unit_pos <= coord_last_unit_pos(coord)); + assert("jmacd-5442", + coord->unit_pos <= coord_last_unit_pos(coord)); coord->between = AT_UNIT; return 0; @@ -502,8 +492,7 @@ coord_prev_unit(coord_t * coord) /* Advances the coordinate by one item to the left. If empty, no change. If coord_is_leftmost_unit, advances to BEFORE THE FIRST ITEM. Returns 0 if new position is an existing item. */ -reiser4_internal int -coord_prev_item(coord_t * coord) +int coord_prev_item(coord_t * coord) { unsigned items = coord_num_items(coord); @@ -543,8 +532,7 @@ coord_prev_item(coord_t * coord) } /* Calls either coord_init_first_unit or coord_init_last_unit depending on sideof argument. */ -reiser4_internal void -coord_init_sideof_unit(coord_t * coord, const znode * node, sideof dir) +void coord_init_sideof_unit(coord_t * coord, const znode * node, sideof dir) { assert("jmacd-9821", dir == LEFT_SIDE || dir == RIGHT_SIDE); if (dir == LEFT_SIDE) { @@ -557,8 +545,7 @@ coord_init_sideof_unit(coord_t * coord, /* Calls either coord_is_before_leftmost or coord_is_after_rightmost depending on sideof argument. */ /* Audited by: green(2002.06.15) */ -reiser4_internal int -coord_is_after_sideof_unit(coord_t * coord, sideof dir) +int coord_is_after_sideof_unit(coord_t * coord, sideof dir) { assert("jmacd-9822", dir == LEFT_SIDE || dir == RIGHT_SIDE); if (dir == LEFT_SIDE) { @@ -570,8 +557,7 @@ coord_is_after_sideof_unit(coord_t * coo /* Calls either coord_next_unit or coord_prev_unit depending on sideof argument. */ /* Audited by: green(2002.06.15) */ -reiser4_internal int -coord_sideof_unit(coord_t * coord, sideof dir) +int coord_sideof_unit(coord_t * coord, sideof dir) { assert("jmacd-9823", dir == LEFT_SIDE || dir == RIGHT_SIDE); if (dir == LEFT_SIDE) { @@ -587,34 +573,21 @@ coord_sideof_unit(coord_t * coord, sideo #define DEBUG_COORD_FIELDS (0) #endif -reiser4_internal int -coords_equal(const coord_t * c1, const coord_t * c2) +int coords_equal(const coord_t * c1, const coord_t * c2) { assert("nikita-2840", c1 != NULL); assert("nikita-2841", c2 != NULL); -#if 0 - /* assertion to track changes in coord_t */ - cassert(sizeof(*c1) == sizeof(c1->node) + - sizeof(c1->item_pos) + - sizeof(c1->unit_pos) + - sizeof(c1->iplugid) + - sizeof(c1->between) + - sizeof(c1->pad) + - sizeof(c1->offset) + - DEBUG_COORD_FIELDS); -#endif return - c1->node == c2->node && - c1->item_pos == c2->item_pos && - c1->unit_pos == c2->unit_pos && - c1->between == c2->between; + c1->node == c2->node && + c1->item_pos == c2->item_pos && + c1->unit_pos == c2->unit_pos && c1->between == c2->between; } /* If coord_is_after_rightmost return NCOORD_ON_THE_RIGHT, if coord_is_after_leftmost return NCOORD_ON_THE_LEFT, otherwise return NCOORD_INSIDE. */ /* Audited by: green(2002.06.15) */ -reiser4_internal coord_wrt_node coord_wrt(const coord_t * coord) +coord_wrt_node coord_wrt(const coord_t * coord) { if (coord_is_before_leftmost(coord)) { return COORD_ON_THE_LEFT; @@ -630,8 +603,7 @@ reiser4_internal coord_wrt_node coord_wr /* Returns true if the coordinate is positioned after the last item or after the last unit of the last item or it is an empty node. */ /* Audited by: green(2002.06.15) */ -reiser4_internal int -coord_is_after_rightmost(const coord_t * coord) +int coord_is_after_rightmost(const coord_t * coord) { assert("jmacd-7313", coord_check(coord)); @@ -659,8 +631,7 @@ coord_is_after_rightmost(const coord_t * /* Returns true if the coordinate is positioned before the first item or it is an empty node. */ -reiser4_internal int -coord_is_before_leftmost(const coord_t * coord) +int coord_is_before_leftmost(const coord_t * coord) { /* FIXME-VS: coord_check requires node to be loaded whereas it is not necessary to check if coord is set before leftmost @@ -687,8 +658,7 @@ coord_is_before_leftmost(const coord_t * /* Returns true if the coordinate is positioned after a item, before a item, after the last unit of an item, before the first unit of an item, or at an empty node. */ /* Audited by: green(2002.06.15) */ -reiser4_internal int -coord_is_between_items(const coord_t * coord) +int coord_is_between_items(const coord_t * coord) { assert("jmacd-7313", coord_check(coord)); @@ -715,8 +685,7 @@ coord_is_between_items(const coord_t * c /* Returns true if the coordinates are positioned at adjacent units, regardless of before-after or item boundaries. */ -reiser4_internal int -coord_are_neighbors(coord_t * c1, coord_t * c2) +int coord_are_neighbors(coord_t * c1, coord_t * c2) { coord_t *left; coord_t *right; @@ -727,7 +696,7 @@ coord_are_neighbors(coord_t * c1, coord_ assert("nikita-1244", coord_is_existing_unit(c1)); assert("nikita-1245", coord_is_existing_unit(c2)); - left = right = 0; + left = right = NULL; switch (coord_compare(c1, c2)) { case COORD_CMP_ON_LEFT: left = c1; @@ -746,7 +715,8 @@ coord_are_neighbors(coord_t * c1, coord_ if (left->item_pos == right->item_pos) { return left->unit_pos + 1 == right->unit_pos; } else if (left->item_pos + 1 == right->item_pos) { - return (left->unit_pos == coord_last_unit_pos(left)) && (right->unit_pos == 0); + return (left->unit_pos == coord_last_unit_pos(left)) + && (right->unit_pos == 0); } else { return 0; } @@ -755,7 +725,7 @@ coord_are_neighbors(coord_t * c1, coord_ /* Assuming two coordinates are positioned in the same node, return COORD_CMP_ON_RIGHT, COORD_CMP_ON_LEFT, or COORD_CMP_SAME depending on c1's position relative to c2. */ /* Audited by: green(2002.06.15) */ -reiser4_internal coord_cmp coord_compare(coord_t * c1, coord_t * c2) +coord_cmp coord_compare(coord_t * c1, coord_t * c2) { assert("vs-209", c1->node == c2->node); assert("vs-194", coord_is_existing_unit(c1) @@ -774,8 +744,7 @@ reiser4_internal coord_cmp coord_compare /* If the coordinate is between items, shifts it to the right. Returns 0 on success and non-zero if there is no position to the right. */ -reiser4_internal int -coord_set_to_right(coord_t * coord) +int coord_set_to_right(coord_t * coord) { unsigned items = coord_num_items(coord); @@ -834,8 +803,7 @@ coord_set_to_right(coord_t * coord) /* If the coordinate is between items, shifts it to the left. Returns 0 on success and non-zero if there is no position to the left. */ -reiser4_internal int -coord_set_to_left(coord_t * coord) +int coord_set_to_left(coord_t * coord) { unsigned items = coord_num_items(coord); @@ -895,8 +863,7 @@ coord_set_to_left(coord_t * coord) return 0; } -reiser4_internal const char * -coord_tween_tostring(between_enum n) +static const char *coord_tween_tostring(between_enum n) { switch (n) { case BEFORE_UNIT: @@ -913,40 +880,53 @@ coord_tween_tostring(between_enum n) return "empty node"; case INVALID_COORD: return "invalid"; - default:{ - static char buf[30]; + default: + { + static char buf[30]; - sprintf(buf, "unknown: %i", n); - return buf; - } + sprintf(buf, "unknown: %i", n); + return buf; + } } } -reiser4_internal void -print_coord(const char *mes, const coord_t * coord, int node) +void print_coord(const char *mes, const coord_t * coord, int node) { if (coord == NULL) { printk("%s: null\n", mes); return; } printk("%s: item_pos = %d, unit_pos %d, tween=%s, iplug=%d\n", - mes, coord->item_pos, coord->unit_pos, coord_tween_tostring(coord->between), coord->iplugid); + mes, coord->item_pos, coord->unit_pos, + coord_tween_tostring(coord->between), coord->iplugid); if (node) print_znode("\tnode", coord->node); } -reiser4_internal int -item_utmost_child_real_block(const coord_t * coord, sideof side, reiser4_block_nr * blk) +int +item_utmost_child_real_block(const coord_t * coord, sideof side, + reiser4_block_nr * blk) { - return item_plugin_by_coord(coord)->f.utmost_child_real_block(coord, side, blk); + return item_plugin_by_coord(coord)->f.utmost_child_real_block(coord, + side, + blk); } -reiser4_internal int -item_utmost_child(const coord_t * coord, sideof side, jnode ** child) +int item_utmost_child(const coord_t * coord, sideof side, jnode ** child) { return item_plugin_by_coord(coord)->f.utmost_child(coord, side, child); } +/* @count bytes of flow @f got written, update correspondingly f->length, + f->data and f->key */ +void move_flow_forward(flow_t * f, unsigned count) +{ + if (f->data) + f->data += count; + f->length -= count; + set_key_offset(&f->key, get_key_offset(&f->key) + count); +} + /* Local variables: c-indentation-style: "K&R" diff -puN fs/reiser4/coord.h~reiser4-big-update fs/reiser4/coord.h --- devel/fs/reiser4/coord.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/coord.h 2005-09-15 19:51:08.000000000 -0700 @@ -8,6 +8,7 @@ #include "forward.h" #include "debug.h" #include "dformat.h" +#include "key.h" /* insertions happen between coords in the tree, so we need some means of specifying the sense of betweenness. */ @@ -45,11 +46,11 @@ struct coord { is invalidated (set to 0xff) on each modification of ->item_pos, and all such modifications are funneled through coord_*_item_pos() functions below. - */ + */ /* 8 */ char iplugid; /* position of coord w.r.t. to neighboring items and/or units. Values are taken from &between_enum above. - */ + */ /* 9 */ char between; /* padding. It will be added by the compiler anyway to conform to the * C language alignment requirements. We keep it here to be on the @@ -66,55 +67,48 @@ struct coord { #define INVALID_PLUGID ((char)((1 << 8) - 1)) #define INVALID_OFFSET -1 -static inline void -coord_clear_iplug(coord_t * coord) +static inline void coord_clear_iplug(coord_t * coord) { assert("nikita-2835", coord != NULL); coord->iplugid = INVALID_PLUGID; - coord->offset = INVALID_OFFSET; + coord->offset = INVALID_OFFSET; } -static inline int -coord_is_iplug_set(const coord_t * coord) +static inline int coord_is_iplug_set(const coord_t * coord) { assert("nikita-2836", coord != NULL); return coord->iplugid != INVALID_PLUGID; } -static inline void -coord_set_item_pos(coord_t * coord, pos_in_node_t pos) +static inline void coord_set_item_pos(coord_t * coord, pos_in_node_t pos) { assert("nikita-2478", coord != NULL); coord->item_pos = pos; coord_clear_iplug(coord); } -static inline void -coord_dec_item_pos(coord_t * coord) +static inline void coord_dec_item_pos(coord_t * coord) { assert("nikita-2480", coord != NULL); --coord->item_pos; coord_clear_iplug(coord); } -static inline void -coord_inc_item_pos(coord_t * coord) +static inline void coord_inc_item_pos(coord_t * coord) { assert("nikita-2481", coord != NULL); ++coord->item_pos; coord_clear_iplug(coord); } -static inline void -coord_add_item_pos(coord_t * coord, int delta) +static inline void coord_add_item_pos(coord_t * coord, int delta) { assert("nikita-2482", coord != NULL); coord->item_pos += delta; coord_clear_iplug(coord); } -static inline void -coord_invalid_item_pos(coord_t * coord) +static inline void coord_invalid_item_pos(coord_t * coord) { assert("nikita-2832", coord != NULL); coord->item_pos = (unsigned short)~0; @@ -122,8 +116,7 @@ coord_invalid_item_pos(coord_t * coord) } /* Reverse a direction. */ -static inline sideof -sideof_reverse(sideof side) +static inline sideof sideof_reverse(sideof side) { return side == LEFT_SIDE ? RIGHT_SIDE : LEFT_SIDE; } @@ -171,7 +164,8 @@ void coord_init_before_item(coord_t *); void coord_init_after_item(coord_t *); /* Calls either coord_init_first_unit or coord_init_last_unit depending on sideof argument. */ -extern void coord_init_sideof_unit(coord_t * coord, const znode * node, sideof dir); +extern void coord_init_sideof_unit(coord_t * coord, const znode * node, + sideof dir); /* Initialize a coordinate by 0s. Used in places where init_coord was used and it was not clear how actually @@ -194,8 +188,7 @@ unsigned coord_num_units(const coord_t * /* Return the last valid unit number at the present item (i.e., coord_num_units() - 1). */ -static inline unsigned -coord_last_unit_pos(const coord_t * coord) +static inline unsigned coord_last_unit_pos(const coord_t * coord) { return coord_num_units(coord) - 1; } @@ -204,10 +197,9 @@ coord_last_unit_pos(const coord_t * coor /* For assertions only, checks for a valid coordinate. */ extern int coord_check(const coord_t * coord); -extern unsigned long znode_times_locked(const znode *z); +extern unsigned long znode_times_locked(const znode * z); -static inline void -coord_update_v(coord_t * coord) +static inline void coord_update_v(coord_t * coord) { coord->plug_v = coord->body_v = znode_times_locked(coord->node); } @@ -313,14 +305,74 @@ extern int coord_sideof_unit(coord_t * c for( coord_init_before_first_item( ( coord ), ( node ) ) ; \ coord_next_item( coord ) == 0 ; ) -#if REISER4_DEBUG -extern const char *coord_tween_tostring(between_enum n); -#endif - /* COORD/ITEM METHODS */ -extern int item_utmost_child_real_block(const coord_t * coord, sideof side, reiser4_block_nr * blk); -extern int item_utmost_child(const coord_t * coord, sideof side, jnode ** child); +extern int item_utmost_child_real_block(const coord_t * coord, sideof side, + reiser4_block_nr * blk); +extern int item_utmost_child(const coord_t * coord, sideof side, + jnode ** child); + +/* a flow is a sequence of bytes being written to or read from the tree. The + tree will slice the flow into items while storing it into nodes, but all of + that is hidden from anything outside the tree. */ + +struct flow { + reiser4_key key; /* key of start of flow's sequence of bytes */ + loff_t length; /* length of flow's sequence of bytes */ + char *data; /* start of flow's sequence of bytes */ + int user; /* if 1 data is user space, 0 - kernel space */ + rw_op op; /* NIKITA-FIXME-HANS: comment is where? */ +}; + +void move_flow_forward(flow_t * f, unsigned count); + +/* &reiser4_item_data - description of data to be inserted or pasted + + Q: articulate the reasons for the difference between this and flow. + + A: Becides flow we insert into tree other things: stat data, directory + entry, etc. To insert them into tree one has to provide this structure. If + one is going to insert flow - he can use insert_flow, where this structure + does not have to be created +*/ +struct reiser4_item_data { + /* actual data to be inserted. If NULL, ->create_item() will not + do xmemcpy itself, leaving this up to the caller. This can + save some amount of unnecessary memory copying, for example, + during insertion of stat data. + + */ + char *data; + /* 1 if 'char * data' contains pointer to user space and 0 if it is + kernel space */ + int user; + /* amount of data we are going to insert or paste */ + int length; + /* "Arg" is opaque data that is passed down to the + ->create_item() method of node layout, which in turn + hands it to the ->create_hook() of item being created. This + arg is currently used by: + + . ->create_hook() of internal item + (fs/reiser4/plugin/item/internal.c:internal_create_hook()), + . ->paste() method of directory item. + . ->create_hook() of extent item + + For internal item, this is left "brother" of new node being + inserted and it is used to add new node into sibling list + after parent to it was just inserted into parent. + + While ->arg does look somewhat of unnecessary compication, + it actually saves a lot of headache in many places, because + all data necessary to insert or paste new data into tree are + collected in one place, and this eliminates a lot of extra + argument passing and storing everywhere. + + */ + void *arg; + /* plugin of item we are inserting */ + item_plugin *iplug; +}; /* __REISER4_COORD_H__ */ #endif diff -puN fs/reiser4/crypt.c~reiser4-big-update fs/reiser4/crypt.c --- devel/fs/reiser4/crypt.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/crypt.c 2005-09-15 19:51:08.000000000 -0700 @@ -3,7 +3,7 @@ #include "debug.h" #include "plugin/plugin.h" -#include "plugin/cryptcompress.h" +#include "plugin/file/cryptcompress.h" #include #include @@ -26,28 +26,29 @@ @pad */ UNUSED_ARG static int -align_stream_common(__u8 *pad /* pointer to the first byte of aligning format */, - int flow_size /* size of non-aligned flow */, - int blocksize /* crypto-block size */) +align_stream_common(__u8 * + pad /* pointer to the first byte of aligning format */ , + int flow_size /* size of non-aligned flow */ , + int blocksize /* crypto-block size */ ) { int pad_size; assert("edward-01", pad != NULL); assert("edward-02", flow_size != 0); - assert("edward-03", blocksize != 0 || blocksize <= MAX_CRYPTO_BLOCKSIZE); + assert("edward-03", blocksize != 0 + || blocksize <= MAX_CRYPTO_BLOCKSIZE); pad_size = blocksize - (flow_size % blocksize); - get_random_bytes (pad, pad_size); + get_random_bytes(pad, pad_size); return pad_size; } /* common scale method (look for description of this method in plugin/plugin.h) for all symmetric algorithms which doesn't scale anything */ -static loff_t scale_common(struct inode * inode UNUSED_ARG, - size_t blocksize UNUSED_ARG /* crypto block size, which is returned - by blocksize method of crypto plugin */, - loff_t src_off /* offset to scale */) +static loff_t scale_common(struct inode *inode UNUSED_ARG, size_t blocksize UNUSED_ARG /* crypto block size, which is returned + by blocksize method of crypto plugin */ , + loff_t src_off /* offset to scale */ ) { return src_off; } @@ -55,7 +56,6 @@ static loff_t scale_common(struct inode REGISTER_NONE_ALG(crypt, CRYPTO) /* EDWARD-FIXME-HANS: why is this not in the plugin directory? */ - /* crypto plugins */ crypto_plugin crypto_plugins[LAST_CRYPTO_ID] = { [NONE_CRYPTO_ID] = { @@ -67,16 +67,16 @@ crypto_plugin crypto_plugins[LAST_CRYPTO transformed, specify this crypto pluigin */ .label = "none", .desc = "absence of crypto transform", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .alloc = alloc_none_crypt, .free = free_none_crypt, .nr_keywords = NONE_EXPKEY_WORDS, .scale = scale_common, - .align_stream = NULL, - .setkey = NULL, - .encrypt = NULL, - .decrypt = NULL + .align_stream = NULL, + .setkey = NULL, + .encrypt = NULL, + .decrypt = NULL } }; diff -puN fs/reiser4/debug.c~reiser4-big-update fs/reiser4/debug.c --- devel/fs/reiser4/debug.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/debug.c 2005-09-15 19:51:08.000000000 -0700 @@ -12,13 +12,6 @@ * locking: schedulable(), lock_counters(), print_lock_counters(), * no_counters_are_held(), commit_check_locks() * - * {debug,trace,log}_flags: reiser4_are_all_debugged(), - * reiser4_is_debugged(), get_current_trace_flags(), - * get_current_log_flags(). - * - * kmalloc/kfree leak detection: reiser4_kmalloc(), reiser4_kfree(), - * reiser4_kfree_in_sb(). - * * error code monitoring (see comment before RETERR macro): return_err(), * report_err(). * @@ -61,15 +54,9 @@ static char panic_buf[REISER4_PANIC_MSG_ */ static spinlock_t panic_guard = SPIN_LOCK_UNLOCKED; -#if REISER4_DEBUG -static int -reiser4_is_debugged(struct super_block *super, __u32 flag); -#endif - /* Your best friend. Call it on each occasion. This is called by fs/reiser4/debug.h:reiser4_panic(). */ -reiser4_internal void -reiser4_do_panic(const char *format /* format string */ , ... /* rest */) +void reiser4_do_panic(const char *format /* format string */ , ... /* rest */ ) { static int in_panic = 0; va_list args; @@ -101,61 +88,24 @@ reiser4_do_panic(const char *format /* f * */ DEBUGON(1); - -#if REISER4_DEBUG - if (get_current_context_check() != NULL) { - struct super_block *super; - reiser4_context *ctx; - - /* - * if we are within reiser4 context, print it contents: - */ - - /* lock counters... */ - ON_DEBUG(print_lock_counters("pins held", lock_counters())); - /* other active contexts... */ - ON_DEBUG(print_contexts()); - ctx = get_current_context(); - super = ctx->super; - if (get_super_private(super) != NULL && - reiser4_is_debugged(super, REISER4_VERBOSE_PANIC)) - /* znodes... */ - print_znodes("znodes", current_tree); - { - extern spinlock_t active_contexts_lock; - - /* - * remove context from the list of active - * contexts. This is precaution measure: - * current is going to die, and leaving - * context on the list would render latter - * corrupted. - */ - spin_lock(&active_contexts_lock); - context_list_remove(ctx->parent); - spin_unlock(&active_contexts_lock); - } - } -#endif } - BUG(); /* to make gcc happy about noreturn attribute */ panic("%s", panic_buf); } -reiser4_internal void +void reiser4_print_prefix(const char *level, int reperr, const char *mid, const char *function, const char *file, int lineno) { const char *comm; - int pid; + int pid; if (unlikely(in_interrupt() || in_irq())) { comm = "interrupt"; - pid = 0; + pid = 0; } else { comm = current->comm; - pid = current->pid; + pid = current->pid; } printk("%sreiser4[%.16s(%i)]: %s (%s:%i)[%s]:\n", level, comm, pid, function, file, lineno, mid); @@ -165,8 +115,7 @@ reiser4_print_prefix(const char *level, /* Preemption point: this should be called periodically during long running operations (carry, allocate, and squeeze are best examples) */ -reiser4_internal int -preempt_point(void) +int preempt_point(void) { assert("nikita-3008", schedulable()); cond_resched(); @@ -195,8 +144,7 @@ int schedulable(void) constraints and various assertions. */ -lock_counters_info * -lock_counters(void) +lock_counters_info *lock_counters(void) { reiser4_context *ctx = get_current_context(); assert("jmacd-1123", ctx != NULL); @@ -206,8 +154,7 @@ lock_counters(void) /* * print human readable information about locks held by the reiser4 context. */ -void -print_lock_counters(const char *prefix, const lock_counters_info * info) +void print_lock_counters(const char *prefix, const lock_counters_info * info) { printk("%s: jnode: %i, tree: %i (r:%i,w:%i), dk: %i (r:%i,w:%i)\n" "jload: %i, " @@ -222,27 +169,21 @@ print_lock_counters(const char *prefix, info->spin_locked_jnode, info->rw_locked_tree, info->read_locked_tree, info->write_locked_tree, - info->rw_locked_dk, info->read_locked_dk, info->write_locked_dk, - info->spin_locked_jload, info->spin_locked_txnh, info->spin_locked_atom, info->spin_locked_stack, info->spin_locked_txnmgr, info->spin_locked_ktxnmgrd, info->spin_locked_fq, info->spin_locked_super, info->spin_locked_inode_object, - info->rw_locked_cbk_cache, info->read_locked_cbk_cache, info->write_locked_cbk_cache, - info->spin_locked_epoch, info->spin_locked_super_eflush, - info->rw_locked_zlock, info->read_locked_zlock, info->write_locked_zlock, - info->spin_locked, info->long_term_locked_znode, info->inode_sem_r, info->inode_sem_w, @@ -252,40 +193,38 @@ print_lock_counters(const char *prefix, /* * return true, iff no locks are held. */ -int -no_counters_are_held(void) +int no_counters_are_held(void) { lock_counters_info *counters; counters = lock_counters(); return - (counters->rw_locked_zlock == 0) && - (counters->read_locked_zlock == 0) && - (counters->write_locked_zlock == 0) && - (counters->spin_locked_jnode == 0) && - (counters->rw_locked_tree == 0) && - (counters->read_locked_tree == 0) && - (counters->write_locked_tree == 0) && - (counters->rw_locked_dk == 0) && - (counters->read_locked_dk == 0) && - (counters->write_locked_dk == 0) && - (counters->spin_locked_txnh == 0) && - (counters->spin_locked_atom == 0) && - (counters->spin_locked_stack == 0) && - (counters->spin_locked_txnmgr == 0) && - (counters->spin_locked_inode_object == 0) && - (counters->spin_locked == 0) && - (counters->long_term_locked_znode == 0) && - (counters->inode_sem_r == 0) && - (counters->inode_sem_w == 0); + (counters->rw_locked_zlock == 0) && + (counters->read_locked_zlock == 0) && + (counters->write_locked_zlock == 0) && + (counters->spin_locked_jnode == 0) && + (counters->rw_locked_tree == 0) && + (counters->read_locked_tree == 0) && + (counters->write_locked_tree == 0) && + (counters->rw_locked_dk == 0) && + (counters->read_locked_dk == 0) && + (counters->write_locked_dk == 0) && + (counters->spin_locked_txnh == 0) && + (counters->spin_locked_atom == 0) && + (counters->spin_locked_stack == 0) && + (counters->spin_locked_txnmgr == 0) && + (counters->spin_locked_inode_object == 0) && + (counters->spin_locked == 0) && + (counters->long_term_locked_znode == 0) && + (counters->inode_sem_r == 0) && + (counters->inode_sem_w == 0) && (counters->d_refs == 0); } /* * return true, iff transaction commit can be done under locks held by the * current thread. */ -int -commit_check_locks(void) +int commit_check_locks(void) { lock_counters_info *counters; int inode_sem_r; @@ -309,81 +248,10 @@ commit_check_locks(void) } /* - * check that some bits specified by @flags are set in ->debug_flags of the - * super block. - */ -static int -reiser4_is_debugged(struct super_block *super, __u32 flag) -{ - return get_super_private(super)->debug_flags & flag; -} - -/* REISER4_DEBUG */ -#endif - -/* allocate memory. This calls kmalloc(), performs some additional checks, and - keeps track of how many memory was allocated on behalf of current super - block. */ -reiser4_internal void * -reiser4_kmalloc(size_t size /* number of bytes to allocate */ , - int gfp_flag /* allocation flag */ ) -{ - void *result; - - assert("nikita-3009", ergo(gfp_flag & __GFP_WAIT, schedulable())); - - result = kmalloc(size, gfp_flag); -#if REISER4_DEBUG - if (result != NULL) { - reiser4_super_info_data *sbinfo; - - sbinfo = get_current_super_private(); - assert("nikita-1407", sbinfo != NULL); - reiser4_spin_lock_sb(sbinfo); - sbinfo->kmallocs ++; - reiser4_spin_unlock_sb(sbinfo); - } -#endif - return result; -} - -/* release memory allocated by reiser4_kmalloc() and update counter. */ -reiser4_internal void -reiser4_kfree(void *area /* memory to from */) -{ - assert("nikita-1410", area != NULL); - return reiser4_kfree_in_sb(area, reiser4_get_current_sb()); -} - -/* release memory allocated by reiser4_kmalloc() for the specified - * super-block. This is useful when memory is released outside of reiser4 - * context */ -reiser4_internal void -reiser4_kfree_in_sb(void *area /* memory to from */, struct super_block *sb) -{ - assert("nikita-2729", area != NULL); -#if REISER4_DEBUG - { - reiser4_super_info_data *sbinfo; - - sbinfo = get_super_private(sb); - reiser4_spin_lock_sb(sbinfo); - assert("nikita-2730", sbinfo->kmallocs > 0); - sbinfo->kmallocs --; - reiser4_spin_unlock_sb(sbinfo); - } -#endif - kfree(area); -} - -#if REISER4_DEBUG - -/* * fill "error site" in the current reiser4 context. See comment before RETERR * macro for more details. */ -void -return_err(int code, const char *file, int line) +void return_err(int code, const char *file, int line) { if (code < 0 && is_in_reiser4_context()) { reiser4_context *ctx = get_current_context(); @@ -392,13 +260,6 @@ return_err(int code, const char *file, i ctx->err.code = code; ctx->err.file = file; ctx->err.line = line; -#ifdef CONFIG_FRAME_POINTER - ctx->err.bt[0] =__builtin_return_address(0); - ctx->err.bt[1] =__builtin_return_address(1); - ctx->err.bt[2] =__builtin_return_address(2); - ctx->err.bt[3] =__builtin_return_address(3); - ctx->err.bt[4] =__builtin_return_address(4); -#endif } } } @@ -406,8 +267,7 @@ return_err(int code, const char *file, i /* * report error information recorder by return_err(). */ -static void -report_err(void) +static void report_err(void) { reiser4_context *ctx = get_current_context_check(); @@ -419,9 +279,10 @@ report_err(void) } } -#endif /* REISER4_DEBUG */ +#endif /* REISER4_DEBUG */ #if KERNEL_DEBUGGER + /* * this functions just drops into kernel debugger. It is a convenient place to * put breakpoint in. diff -puN fs/reiser4/debug.h~reiser4-big-update fs/reiser4/debug.h --- devel/fs/reiser4/debug.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/debug.h 2005-09-15 19:51:08.000000000 -0700 @@ -8,7 +8,6 @@ #include "forward.h" #include "reiser4.h" - /* generic function to produce formatted output, decorating it with whatever standard prefixes/postfixes we want. "Fun" is a function that will be actually called, can be printk, panic etc. @@ -145,7 +144,7 @@ extern lock_counters_info *lock_counters * assertions */ #define LOCK_CNT_GTZ(counter) IN_CONTEXT(lock_counters()->counter > 0, 1) -#else /* REISER4_DEBUG */ +#else /* REISER4_DEBUG */ /* no-op versions on the above */ @@ -158,8 +157,7 @@ typedef struct lock_counters_info { #define LOCK_CNT_NIL(counter) (1) #define LOCK_CNT_GTZ(counter) (1) -#endif /* REISER4_DEBUG */ - +#endif /* REISER4_DEBUG */ /* flags controlling debugging behavior. Are set through debug_flags=N mount option. */ @@ -210,7 +208,7 @@ extern int is_in_reiser4_context(void); reiser4_panic( label, "NOT YET IMPLEMENTED: " format , ## __VA_ARGS__ ) extern void reiser4_do_panic(const char *format, ...) -__attribute__ ((noreturn, format(printf, 1, 2))); + __attribute__ ((noreturn, format(printf, 1, 2))); extern void reiser4_print_prefix(const char *level, int reperr, const char *mid, const char *function, @@ -219,13 +217,10 @@ extern void reiser4_print_prefix(const c extern int preempt_point(void); extern void reiser4_print_stats(void); -extern void *reiser4_kmalloc(size_t size, int gfp_flag); -extern void reiser4_kfree(void *area); -extern void reiser4_kfree_in_sb(void *area, struct super_block *sb); #if REISER4_DEBUG extern void print_lock_counters(const char *prefix, - const lock_counters_info * info); + const lock_counters_info * info); extern int no_counters_are_held(void); extern int commit_check_locks(void); #else @@ -233,7 +228,6 @@ extern int commit_check_locks(void); #define commit_check_locks() (1) #endif - /* true if @i is power-of-two. Useful for rate-limited warnings, etc. */ #define IS_POW(i) \ ({ \ @@ -246,14 +240,15 @@ extern int commit_check_locks(void); #define KERNEL_DEBUGGER (1) #if KERNEL_DEBUGGER + +extern void debugtrap(void); + /* * Check condition @cond and drop into kernel debugger (kgdb) if it's true. If * kgdb is not compiled in, do nothing. */ #define DEBUGON(cond) \ ({ \ - extern void debugtrap(void); \ - \ if (unlikely(cond)) \ debugtrap(); \ }) @@ -296,12 +291,9 @@ extern int commit_check_locks(void); * data-type to store information about where error happened ("error site"). */ typedef struct err_site { - int code; /* error code */ - const char *file; /* source file, filled by __FILE__ */ - int line; /* source file line, filled by __LINE__ */ -#ifdef CONFIG_FRAME_POINTER - void *bt[5]; -#endif + int code; /* error code */ + const char *file; /* source file, filled by __FILE__ */ + int line; /* source file line, filled by __LINE__ */ } err_site; extern void return_err(int code, const char *file, int line); @@ -324,7 +316,8 @@ extern void return_err(int code, const c * no-op versions of the above */ -typedef struct err_site {} err_site; +typedef struct err_site { +} err_site; #define RETERR(code) code #endif @@ -337,8 +330,6 @@ typedef struct err_site {} err_site; #define ON_LARGE_KEY(...) #endif -#define reiser4_internal - /* __FS_REISER4_DEBUG_H__ */ #endif diff -puN fs/reiser4/dformat.h~reiser4-big-update fs/reiser4/dformat.h --- devel/fs/reiser4/dformat.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/dformat.h 2005-09-15 19:51:08.000000000 -0700 @@ -13,7 +13,6 @@ #if !defined( __FS_REISER4_DFORMAT_H__ ) #define __FS_REISER4_DFORMAT_H__ - #include #include #include @@ -43,59 +42,51 @@ typedef struct d64 { #define PACKED __attribute__((packed)) -static inline __u8 -d8tocpu(const d8 * ondisk /* on-disk value to convert */ ) +static inline __u8 d8tocpu(const d8 * ondisk /* on-disk value to convert */ ) { return ondisk->datum; } -static inline __u16 -d16tocpu(const d16 * ondisk /* on-disk value to convert */ ) +static inline __u16 d16tocpu(const d16 * ondisk /* on-disk value to convert */ ) { return __le16_to_cpu(get_unaligned(&ondisk->datum)); } -static inline __u32 -d32tocpu(const d32 * ondisk /* on-disk value to convert */ ) +static inline __u32 d32tocpu(const d32 * ondisk /* on-disk value to convert */ ) { return __le32_to_cpu(get_unaligned(&ondisk->datum)); } -static inline __u64 -d64tocpu(const d64 * ondisk /* on-disk value to convert */ ) +static inline __u64 d64tocpu(const d64 * ondisk /* on-disk value to convert */ ) { return __le64_to_cpu(get_unaligned(&ondisk->datum)); } -static inline d8 * -cputod8(unsigned int oncpu /* CPU value to convert */ , - d8 * ondisk /* result */ ) +static inline d8 *cputod8(unsigned int oncpu /* CPU value to convert */ , + d8 * ondisk /* result */ ) { assert("nikita-1264", oncpu < 0x100); put_unaligned(oncpu, &ondisk->datum); return ondisk; } -static inline d16 * -cputod16(unsigned int oncpu /* CPU value to convert */ , - d16 * ondisk /* result */ ) +static inline d16 *cputod16(unsigned int oncpu /* CPU value to convert */ , + d16 * ondisk /* result */ ) { assert("nikita-1265", oncpu < 0x10000); put_unaligned(__cpu_to_le16(oncpu), &ondisk->datum); return ondisk; } -static inline d32 * -cputod32(__u32 oncpu /* CPU value to convert */ , - d32 * ondisk /* result */ ) +static inline d32 *cputod32(__u32 oncpu /* CPU value to convert */ , + d32 * ondisk /* result */ ) { put_unaligned(__cpu_to_le32(oncpu), &ondisk->datum); return ondisk; } -static inline d64 * -cputod64(__u64 oncpu /* CPU value to convert */ , - d64 * ondisk /* result */ ) +static inline d64 *cputod64(__u64 oncpu /* CPU value to convert */ , + d64 * ondisk /* result */ ) { put_unaligned(__cpu_to_le64(oncpu), &ondisk->datum); return ondisk; @@ -113,8 +104,7 @@ union reiser4_dblock_nr { d64 blk; }; -static inline reiser4_block_nr -dblock_to_cpu(const reiser4_dblock_nr * dblock) +static inline reiser4_block_nr dblock_to_cpu(const reiser4_dblock_nr * dblock) { return d64tocpu(&dblock->blk); } @@ -126,13 +116,12 @@ cpu_to_dblock(reiser4_block_nr block, re } /* true if disk addresses are the same */ -static inline int -disk_addr_eq(const reiser4_block_nr * b1 /* first block - * number to - * compare */ , - const reiser4_block_nr * b2 /* second block - * number to - * compare */ ) +static inline int disk_addr_eq(const reiser4_block_nr * b1 /* first block + * number to + * compare */ , + const reiser4_block_nr * b2 /* second block + * number to + * compare */ ) { assert("nikita-1033", b1 != NULL); assert("nikita-1266", b2 != NULL); diff -puN fs/reiser4/dscale.c~reiser4-big-update fs/reiser4/dscale.c --- devel/fs/reiser4/dscale.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/dscale.c 2005-09-15 19:51:08.000000000 -0700 @@ -49,7 +49,7 @@ static int gettag(const unsigned char *a } /* clear tag from value. Clear tag embedded into @value. */ -static void cleartag(__u64 *value, int tag) +static void cleartag(__u64 * value, int tag) { /* * W-w-what ?! @@ -94,7 +94,7 @@ static int dscale_range(__u64 value) /* restore value stored at @adderss by dscale_write() and return number of * bytes consumed */ -reiser4_internal int dscale_read(unsigned char *address, __u64 *value) +int dscale_read(unsigned char *address, __u64 * value) { int tag; @@ -104,7 +104,7 @@ reiser4_internal int dscale_read(unsigne case 3: /* In this case tag is stored in an extra byte, skip this byte * and decode value stored in the next 8 bytes.*/ - *value = __be64_to_cpu(get_unaligned((__u64 *)(address + 1))); + *value = __be64_to_cpu(get_unaligned((__u64 *) (address + 1))); /* worst case: 8 bytes for value itself plus one byte for * tag. */ return 9; @@ -112,22 +112,22 @@ reiser4_internal int dscale_read(unsigne *value = get_unaligned(address); break; case 1: - *value = __be16_to_cpu(get_unaligned((__u16 *)address)); + *value = __be16_to_cpu(get_unaligned((__u16 *) address)); break; case 2: - *value = __be32_to_cpu(get_unaligned((__u32 *)address)); + *value = __be32_to_cpu(get_unaligned((__u32 *) address)); break; default: return RETERR(-EIO); } /* clear tag embedded into @value */ cleartag(value, tag); - /* number of bytes consumed is (2 ^ tag)---see table 1.*/ + /* number of bytes consumed is (2 ^ tag)---see table 1. */ return 1 << tag; } /* store @value at @address and return number of bytes consumed */ -reiser4_internal int dscale_write(unsigned char *address, __u64 value) +int dscale_write(unsigned char *address, __u64 value) { int tag; int shift; @@ -143,20 +143,20 @@ reiser4_internal int dscale_write(unsign } /* number of bytes required to store @value */ -reiser4_internal int dscale_bytes(__u64 value) +int dscale_bytes(__u64 value) { int bytes; bytes = 1 << dscale_range(value); if (bytes == 8) - ++ bytes; + ++bytes; return bytes; } /* returns true if @value and @other require the same number of bytes to be * stored. Used by detect when data structure (like stat-data) has to be * expanded or contracted. */ -reiser4_internal int dscale_fit(__u64 value, __u64 other) +int dscale_fit(__u64 value, __u64 other) { return dscale_range(value) == dscale_range(other); } diff -puN fs/reiser4/dscale.h~reiser4-big-update fs/reiser4/dscale.h --- devel/fs/reiser4/dscale.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/dscale.h 2005-09-15 19:51:08.000000000 -0700 @@ -8,10 +8,10 @@ #include "dformat.h" -extern int dscale_read (unsigned char *address, __u64 *value); +extern int dscale_read(unsigned char *address, __u64 * value); extern int dscale_write(unsigned char *address, __u64 value); extern int dscale_bytes(__u64 value); -extern int dscale_fit (__u64 value, __u64 other); +extern int dscale_fit(__u64 value, __u64 other); /* __FS_REISER4_DSCALE_H__ */ #endif diff -puN fs/reiser4/emergency_flush.c~reiser4-big-update fs/reiser4/emergency_flush.c --- devel/fs/reiser4/emergency_flush.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/emergency_flush.c 2005-09-15 19:51:08.000000000 -0700 @@ -173,7 +173,6 @@ WHERE TO WRITE PAGE INTO? - So, it was decided that flush has to be performed from a separate thread. Reiser4 has a thread used to periodically commit old transactions, and this thread can be used for the flushing. That is, flushing thread @@ -249,11 +248,14 @@ static int flushable(const jnode * node, struct page *page, int); static int needs_allocation(const jnode * node); -static eflush_node_t *ef_alloc(int flags); -static reiser4_ba_flags_t ef_block_flags(const jnode *node); -static int ef_free_block(jnode *node, const reiser4_block_nr *blk, block_stage_t stage, eflush_node_t *ef); -static int ef_prepare(jnode *node, reiser4_block_nr *blk, eflush_node_t **enode, reiser4_blocknr_hint *hint); -static int eflush_add(jnode *node, reiser4_block_nr *blocknr, eflush_node_t *ef); +static eflush_node_t *ef_alloc(unsigned int flags); +static reiser4_ba_flags_t ef_block_flags(const jnode * node); +static int ef_free_block(jnode * node, const reiser4_block_nr * blk, + block_stage_t stage, eflush_node_t * ef); +static int ef_prepare(jnode * node, reiser4_block_nr * blk, + eflush_node_t ** enode, reiser4_blocknr_hint * hint); +static int eflush_add(jnode * node, reiser4_block_nr * blocknr, + eflush_node_t * ef); /* slab for eflush_node_t's */ static kmem_cache_t *eflush_slab; @@ -270,8 +272,7 @@ static kmem_cache_t *eflush_slab; * Return 0 if page was successfully paged out. 1 if it is busy, error * otherwise. */ -reiser4_internal int -emergency_flush(struct page *page) +int emergency_flush(struct page *page) { struct super_block *sb; jnode *node; @@ -351,7 +352,8 @@ emergency_flush(struct page *page) atom = node->atom; - if (!flushable(node, page, 1) || needs_allocation(node) || !jnode_is_dirty(node)) { + if (!flushable(node, page, 1) || needs_allocation(node) + || !jnode_is_dirty(node)) { UNLOCK_JLOAD(node); UNLOCK_JNODE(node); UNLOCK_ATOM(atom); @@ -387,29 +389,28 @@ emergency_flush(struct page *page) return result; } -static int -flushable(const jnode * node, struct page *page, int check_eflush) +static int flushable(const jnode * node, struct page *page, int check_eflush) { assert("nikita-2725", node != NULL); assert("nikita-2726", spin_jnode_is_locked(node)); assert("nikita-3388", spin_jload_is_locked(node)); - if (jnode_is_loaded(node)) { /* loaded */ + if (jnode_is_loaded(node)) { /* loaded */ return 0; } - if (JF_ISSET(node, JNODE_FLUSH_QUEUED)) { /* already pending io */ + if (JF_ISSET(node, JNODE_FLUSH_QUEUED)) { /* already pending io */ return 0; } - if (JF_ISSET(node, JNODE_EPROTECTED)) { /* protected from e-flush */ + if (JF_ISSET(node, JNODE_EPROTECTED)) { /* protected from e-flush */ return 0; } if (JF_ISSET(node, JNODE_HEARD_BANSHEE)) { return 0; } - if (page == NULL) { /* nothing to flush */ + if (page == NULL) { /* nothing to flush */ return 0; } - if (PageWriteback(page)) { /* already under io */ + if (PageWriteback(page)) { /* already under io */ return 0; } /* don't flush bitmaps or journal records */ @@ -420,7 +421,7 @@ flushable(const jnode * node, struct pag if (jnode_is_cluster_page(node)) { return 0; } - if (check_eflush && JF_ISSET(node, JNODE_EFLUSH)) { /* already flushed */ + if (check_eflush && JF_ISSET(node, JNODE_EFLUSH)) { /* already flushed */ return 0; } return 1; @@ -429,15 +430,13 @@ flushable(const jnode * node, struct pag #undef INC_STAT /* does node need allocation for eflushing? */ -static int -needs_allocation(const jnode * node) +static int needs_allocation(const jnode * node) { - return !(JF_ISSET(node, JNODE_RELOC) && !blocknr_is_fake(jnode_get_block(node))); + return !(JF_ISSET(node, JNODE_RELOC) + && !blocknr_is_fake(jnode_get_block(node))); } - -static inline int -jnode_eq(jnode * const * j1, jnode * const * j2) +static inline int jnode_eq(jnode * const *j1, jnode * const *j2) { assert("nikita-2733", j1 != NULL); assert("nikita-2734", j2 != NULL); @@ -445,8 +444,7 @@ jnode_eq(jnode * const * j1, jnode * con return *j1 == *j2; } -static ef_hash_table * -get_jnode_enhash(const jnode *node) +static ef_hash_table *get_jnode_enhash(const jnode * node) { struct super_block *super; @@ -456,8 +454,7 @@ get_jnode_enhash(const jnode *node) return &get_super_private(super)->efhash_table; } -static inline __u32 -jnode_hfn(ef_hash_table *table, jnode * const * j) +static inline __u32 jnode_hfn(ef_hash_table * table, jnode * const *j) { __u32 val; @@ -469,56 +466,81 @@ jnode_hfn(ef_hash_table *table, jnode * return val & (table->_buckets - 1); } - /* The hash table definition */ #define KMALLOC(size) vmalloc(size) #define KFREE(ptr, size) vfree(ptr) -TYPE_SAFE_HASH_DEFINE(ef, eflush_node_t, jnode *, node, linkage, jnode_hfn, jnode_eq); +TYPE_SAFE_HASH_DEFINE(ef, eflush_node_t, jnode *, node, linkage, jnode_hfn, + jnode_eq); #undef KFREE #undef KMALLOC -reiser4_internal int -eflush_init(void) +/** + * init_eflush - create eflush node cache + * + * Initializes slab cache of eflush nodes. It is part of reiser4 module + * initialization. + */ +int init_eflush(void) { - eflush_slab = kmem_cache_create("eflush", sizeof (eflush_node_t), + eflush_slab = kmem_cache_create("eflush", sizeof(eflush_node_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (eflush_slab == NULL) return RETERR(-ENOMEM); - else - return 0; + return 0; } -reiser4_internal int -eflush_done(void) +/** + * done_eflush - delete eflush nodeznode cache + * + * This is called on reiser4 module unloading or system shutdown. + */ +void done_eflush(void) { - return kmem_cache_destroy(eflush_slab); + destroy_reiser4_cache(&eflush_slab); } -reiser4_internal int -eflush_init_at(struct super_block *super) +int eflush_init_at(struct super_block *super) { - return ef_hash_init(&get_super_private(super)->efhash_table, - 8192); + return ef_hash_init(&get_super_private(super)->efhash_table, 8192); } -reiser4_internal void -eflush_done_at(struct super_block *super) +void eflush_done_at(struct super_block *super) { ef_hash_done(&get_super_private(super)->efhash_table); } -static eflush_node_t * -ef_alloc(int flags) +static eflush_node_t *ef_alloc(unsigned int flags) { return kmem_cache_alloc(eflush_slab, flags); } +static void inc_unfm_ef(void) +{ + reiser4_super_info_data *sbinfo; + + sbinfo = get_super_private(get_current_context()->super); + reiser4_spin_lock_sb(sbinfo); + sbinfo->eflushed_unformatted++; + reiser4_spin_unlock_sb(sbinfo); +} + +static void dec_unfm_ef(void) +{ + reiser4_super_info_data *sbinfo; + + sbinfo = get_super_private(get_current_context()->super); + reiser4_spin_lock_sb(sbinfo); + BUG_ON(sbinfo->eflushed_unformatted == 0); + sbinfo->eflushed_unformatted--; + reiser4_spin_unlock_sb(sbinfo); +} + #define EFLUSH_MAGIC 4335203 static int -eflush_add(jnode *node, reiser4_block_nr *blocknr, eflush_node_t *ef) +eflush_add(jnode * node, reiser4_block_nr * blocknr, eflush_node_t * ef) { - reiser4_tree *tree; + reiser4_tree *tree; assert("nikita-2737", node != NULL); assert("nikita-2738", JF_ISSET(node, JNODE_EFLUSH)); @@ -535,27 +557,23 @@ eflush_add(jnode *node, reiser4_block_nr jref(node); spin_lock_eflush(tree->super); ef_hash_insert(get_jnode_enhash(node), ef); - ON_DEBUG(++ get_super_private(tree->super)->eflushed); + ON_DEBUG(++get_super_private(tree->super)->eflushed); spin_unlock_eflush(tree->super); if (jnode_is_unformatted(node)) { - struct inode *inode; + struct inode *inode; reiser4_inode *info; - WLOCK_TREE(tree); - inode = mapping_jnode(node)->host; info = reiser4_inode_data(inode); if (!ef->hadatom) { + write_lock_irq(&inode->i_mapping->tree_lock); radix_tree_tag_set(jnode_tree_by_reiser4_inode(info), - index_jnode(node), EFLUSH_TAG_ANONYMOUS); - ON_DEBUG(info->anonymous_eflushed ++); - } else { - ON_DEBUG(info->captured_eflushed ++); + index_jnode(node), + EFLUSH_TAG_ANONYMOUS); + write_unlock_irq(&inode->i_mapping->tree_lock); } - WUNLOCK_TREE(tree); - /*XXXX*/ inc_unfm_ef(); } @@ -574,7 +592,7 @@ eflush_add(jnode *node, reiser4_block_nr atom = jnode_get_atom(node); if (atom != NULL) { - ++ atom->flushed; + ++atom->flushed; ef->incatom = 1; UNLOCK_ATOM(atom); } @@ -587,17 +605,15 @@ eflush_add(jnode *node, reiser4_block_nr /* Arrghh... cast to keep hash table code happy. */ #define C(node) ((jnode *const *)&(node)) -reiser4_internal reiser4_block_nr * -eflush_get(const jnode *node) +reiser4_block_nr *eflush_get(const jnode * node) { eflush_node_t *ef; - reiser4_tree *tree; + reiser4_tree *tree; assert("nikita-2740", node != NULL); assert("nikita-2741", JF_ISSET(node, JNODE_EFLUSH)); assert("nikita-2767", spin_jnode_is_locked(node)); - tree = jnode_get_tree(node); spin_lock_eflush(tree->super); ef = ef_hash_find(get_jnode_enhash(node), C(node)); @@ -608,17 +624,16 @@ eflush_get(const jnode *node) } /* free resources taken for emergency flushing of the node */ -reiser4_internal void -eflush_free (jnode * node) +void eflush_free(jnode * node) { eflush_node_t *ef; ef_hash_table *table; - reiser4_tree *tree; - txn_atom *atom; - struct inode *inode = NULL; + reiser4_tree *tree; + txn_atom *atom; + struct inode *inode = NULL; reiser4_block_nr blk; - assert ("zam-1026", spin_jnode_is_locked(node)); + assert("zam-1026", spin_jnode_is_locked(node)); table = get_jnode_enhash(node); tree = jnode_get_tree(node); @@ -629,13 +644,13 @@ eflush_free (jnode * node) assert("nikita-2745", ef != NULL); blk = ef->blocknr; ef_hash_remove(table, ef); - ON_DEBUG(-- get_super_private(tree->super)->eflushed); + ON_DEBUG(--get_super_private(tree->super)->eflushed); spin_unlock_eflush(tree->super); if (ef->incatom) { atom = jnode_get_atom(node); assert("nikita-3311", atom != NULL); - -- atom->flushed; + --atom->flushed; UNLOCK_ATOM(atom); } @@ -644,35 +659,29 @@ eflush_free (jnode * node) if (jnode_is_unformatted(node)) { reiser4_inode *info; - WLOCK_TREE(tree); - inode = mapping_jnode(node)->host; info = reiser4_inode_data(inode); /* clear e-flush specific tags from node's radix tree slot */ if (!ef->hadatom) { - radix_tree_tag_clear( - jnode_tree_by_reiser4_inode(info), index_jnode(node), - EFLUSH_TAG_ANONYMOUS); - ON_DEBUG(info->anonymous_eflushed --); - } else - ON_DEBUG(info->captured_eflushed --); - - assert("nikita-3355", jnode_tree_by_reiser4_inode(info)->rnode != NULL); - - WUNLOCK_TREE(tree); + write_lock_irq(&inode->i_mapping->tree_lock); + radix_tree_tag_clear(jnode_tree_by_reiser4_inode(info), + index_jnode(node), + EFLUSH_TAG_ANONYMOUS); + write_unlock_irq(&inode->i_mapping->tree_lock); + } - /*XXXX*/ + assert("nikita-3355", + jnode_tree_by_reiser4_inode(info)->rnode != NULL); dec_unfm_ef(); - } UNLOCK_JNODE(node); #if REISER4_DEBUG if (blocknr_is_fake(jnode_get_block(node))) - assert ("zam-817", ef->initial_stage == BLOCK_UNALLOCATED); + assert("zam-817", ef->initial_stage == BLOCK_UNALLOCATED); else - assert ("zam-818", ef->initial_stage == BLOCK_GRABBED); + assert("zam-818", ef->initial_stage == BLOCK_GRABBED); #endif jput(node); @@ -686,44 +695,44 @@ eflush_free (jnode * node) LOCK_JNODE(node); } -reiser4_internal void -eflush_del (jnode * node, int page_locked) +void eflush_del(jnode * node, int page_locked) { - struct page * page; + struct page *page; - assert("nikita-2743", node != NULL); - assert("nikita-2770", spin_jnode_is_locked(node)); + assert("nikita-2743", node != NULL); + assert("nikita-2770", spin_jnode_is_locked(node)); - if (!JF_ISSET(node, JNODE_EFLUSH)) - return; - - if (page_locked) { - page = jnode_page(node); - assert("nikita-2806", page != NULL); - assert("nikita-2807", PageLocked(page)); - } else { - UNLOCK_JNODE(node); - page = jnode_get_page_locked(node, GFP_NOFS); - LOCK_JNODE(node); - if (page == NULL) { - warning ("zam-1025", "eflush_del failed to get page back\n"); - return; - } - if (unlikely(!JF_ISSET(node, JNODE_EFLUSH))) - /* race: some other thread unflushed jnode. */ - goto out; - } - - if (PageWriteback(page)) { - UNLOCK_JNODE(node); - page_cache_get(page); - reiser4_wait_page_writeback(page); - page_cache_release(page); - LOCK_JNODE(node); - if (unlikely(!JF_ISSET(node, JNODE_EFLUSH))) - /* race: some other thread unflushed jnode. */ - goto out; - } + if (!JF_ISSET(node, JNODE_EFLUSH)) + return; + + if (page_locked) { + page = jnode_page(node); + assert("nikita-2806", page != NULL); + assert("nikita-2807", PageLocked(page)); + } else { + UNLOCK_JNODE(node); + page = jnode_get_page_locked(node, GFP_NOFS); + LOCK_JNODE(node); + if (page == NULL) { + warning("zam-1025", + "eflush_del failed to get page back\n"); + return; + } + if (unlikely(!JF_ISSET(node, JNODE_EFLUSH))) + /* race: some other thread unflushed jnode. */ + goto out; + } + + if (PageWriteback(page)) { + UNLOCK_JNODE(node); + page_cache_get(page); + reiser4_wait_page_writeback(page); + page_cache_release(page); + LOCK_JNODE(node); + if (unlikely(!JF_ISSET(node, JNODE_EFLUSH))) + /* race: some other thread unflushed jnode. */ + goto out; + } /* we have to make page dirty again. Note that we do not have to do here anything specific to reiser4 but usual dirty page accounting. If */ @@ -733,35 +742,18 @@ eflush_del (jnode * node, int page_locke inc_page_state(nr_dirty); } -#if 0 - if (JF_ISSET(node, JNODE_KEEPME)) - /* jnode is already tagged in reiser4_inode's tree of jnodes */ - reiser4_set_page_dirty2(page); - else - /* jnode had atom when */ - /* - * either jnode was dirty or page was dirtied through mmap. Page's dirty - * bit was cleared before io was submitted. If page is left clean, we - * would have dirty jnode with clean page. Neither ->writepage() nor - * ->releasepage() can free it. Re-dirty page, so ->writepage() will be - * called again if necessary. - */ - set_page_dirty_internal(page, 0); -#endif - - assert("nikita-2766", atomic_read(&node->x_count) > 1); - /* release allocated disk block and in-memory structures */ - eflush_free(node); + assert("nikita-2766", atomic_read(&node->x_count) > 1); + /* release allocated disk block and in-memory structures */ + eflush_free(node); assert("vs-1736", PageLocked(page)); - JF_CLR(node, JNODE_EFLUSH); - ON_DEBUG(JF_SET(node, JNODE_UNEFLUSHED)); - out: - if (!page_locked) - unlock_page(page); + JF_CLR(node, JNODE_EFLUSH); + ON_DEBUG(JF_SET(node, JNODE_UNEFLUSHED)); + out: + if (!page_locked) + unlock_page(page); } -reiser4_internal int -emergency_unflush(jnode *node) +int emergency_unflush(jnode * node) { int result; @@ -777,7 +769,6 @@ emergency_unflush(jnode *node) page = jnode_page(node); assert("nikita-2779", page != NULL); wait_on_page_writeback(page); - jrelse(node); } } else @@ -785,15 +776,14 @@ emergency_unflush(jnode *node) return result; } -static reiser4_ba_flags_t -ef_block_flags(const jnode *node) +static reiser4_ba_flags_t ef_block_flags(const jnode * node) { return jnode_is_znode(node) ? BA_FORMATTED : 0; } -static int ef_free_block(jnode *node, - const reiser4_block_nr *blk, - block_stage_t stage, eflush_node_t *ef) +static int ef_free_block(jnode * node, + const reiser4_block_nr * blk, + block_stage_t stage, eflush_node_t * ef) { int result = 0; @@ -814,16 +804,17 @@ static int ef_free_block(jnode *node, JF_SET(node, JNODE_FLUSH_RESERVED); UNLOCK_JNODE(node); } else { - reiser4_context * ctx = get_current_context(); + reiser4_context *ctx = get_current_context(); grabbed2free(ctx, get_super_private(ctx->super), - (__u64)1); + (__u64) 1); } } return result; } static int -ef_prepare(jnode *node, reiser4_block_nr *blk, eflush_node_t **efnode, reiser4_blocknr_hint * hint) +ef_prepare(jnode * node, reiser4_block_nr * blk, eflush_node_t ** efnode, + reiser4_blocknr_hint * hint) { int result; int usedreserve; @@ -834,9 +825,9 @@ ef_prepare(jnode *node, reiser4_block_nr assert("nikita-2763", spin_jnode_is_locked(node)); assert("nikita-3387", spin_jload_is_locked(node)); - hint->blk = EFLUSH_START_BLOCK; - hint->max_dist = 0; - hint->level = jnode_get_level(node); + hint->blk = EFLUSH_START_BLOCK; + hint->max_dist = 0; + hint->level = jnode_get_level(node); usedreserve = 0; if (blocknr_is_fake(jnode_get_block(node))) hint->block_stage = BLOCK_UNALLOCATED; @@ -844,9 +835,11 @@ ef_prepare(jnode *node, reiser4_block_nr txn_atom *atom; switch (jnode_is_leaf(node)) { default: - /* We cannot just ask block allocator to take block from + /* + * We cannot just ask block allocator to take block from * flush reserved space, because there is no current - * atom at this point. */ + * atom at this point. + */ atom = jnode_get_atom(node); if (atom != NULL) { if (JF_ISSET(node, JNODE_FLUSH_RESERVED)) { @@ -858,11 +851,13 @@ ef_prepare(jnode *node, reiser4_block_nr } else UNLOCK_ATOM(atom); } - /* fall through */ - /* node->atom == NULL if page was dirtied through - * mmap */ + /* + * fall through. + * node->atom == NULL if page was dirtied through mmap + */ case 0: - result = reiser4_grab_space_force((__u64)1, BA_RESERVED); + result = + reiser4_grab_space_force((__u64) 1, BA_RESERVED); grab_space_enable(); if (result) { warning("nikita-3323", @@ -874,8 +869,10 @@ ef_prepare(jnode *node, reiser4_block_nr hint->block_stage = BLOCK_GRABBED; } - /* XXX protect @node from being concurrently eflushed. Otherwise, - * there is a danger of underflowing block space */ + /* + * XXX protect @node from being concurrently eflushed. Otherwise, there + * is a danger of underflowing block space + */ UNLOCK_JLOAD(node); UNLOCK_JNODE(node); @@ -884,7 +881,6 @@ ef_prepare(jnode *node, reiser4_block_nr result = RETERR(-ENOMEM); goto out; } - #if REISER4_DEBUG (*efnode)->initial_stage = hint->block_stage; #endif @@ -893,13 +889,13 @@ ef_prepare(jnode *node, reiser4_block_nr result = reiser4_alloc_block(hint, blk, ef_block_flags(node)); if (result) kmem_cache_free(eflush_slab, *efnode); - out: + out: LOCK_JNODE(node); LOCK_JLOAD(node); return result; } -#endif /* REISER4_USE_EFLUSH */ +#endif /* REISER4_USE_EFLUSH */ /* Make Linus happy. Local variables: diff -puN fs/reiser4/emergency_flush.h~reiser4-big-update fs/reiser4/emergency_flush.h --- devel/fs/reiser4/emergency_flush.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/emergency_flush.h 2005-09-15 19:51:08.000000000 -0700 @@ -15,42 +15,42 @@ typedef struct eflush_node eflush_node_t TYPE_SAFE_HASH_DECLARE(ef, eflush_node_t); struct eflush_node { - jnode *node; + jnode *node; reiser4_block_nr blocknr; - ef_hash_link linkage; - struct list_head inode_link; /* for per inode list of eflush nodes */ + ef_hash_link linkage; + struct list_head inode_link; /* for per inode list of eflush nodes */ struct list_head inode_anon_link; - int hadatom :1; - int incatom :1; - int reserve :1; + unsigned int hadatom:1; + unsigned int incatom:1; + unsigned int reserve:1; #if REISER4_DEBUG - block_stage_t initial_stage; + block_stage_t initial_stage; #endif }; -int eflush_init(void); -int eflush_done(void); +extern int init_eflush(void); +extern void done_eflush(void); -extern int eflush_init_at(struct super_block *super); +extern int eflush_init_at(struct super_block *super); extern void eflush_done_at(struct super_block *super); -extern reiser4_block_nr *eflush_get(const jnode *node); -extern void eflush_del(jnode *node, int page_locked); +extern reiser4_block_nr *eflush_get(const jnode * node); +extern void eflush_del(jnode * node, int page_locked); extern void eflush_free(jnode *); extern int emergency_flush(struct page *page); -extern int emergency_unflush(jnode *node); +extern int emergency_unflush(jnode * node); /* tag to tag eflushed anonymous jnodes in reiser4_inode's radix tree of jnodes */ #define EFLUSH_TAG_ANONYMOUS PAGECACHE_TAG_DIRTY -#else /* REISER4_USE_EFLUSH */ +#else /* REISER4_USE_EFLUSH */ -#define eflush_init() (0) -#define eflush_done() (0) +#define init_eflush() (0) +#define done_eflush() do {} while (0) #define eflush_init_at(super) (0) -#define eflush_done_at(super) (0) +#define eflush_done_at(super) do {} while (0) #define eflush_get(node) NULL #define eflush_del(node, flag) do{}while(0) @@ -59,7 +59,7 @@ extern int emergency_unflush(jnode *node #define emergency_unflush(node) (0) #define emergency_flush(page) (1) -#endif /* REISER4_USE_EFLUSH */ +#endif /* REISER4_USE_EFLUSH */ /* __EMERGENCY_FLUSH_H__ */ #endif diff -puN fs/reiser4/entd.c~reiser4-big-update fs/reiser4/entd.c --- devel/fs/reiser4/entd.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/entd.c 2005-09-15 19:51:08.000000000 -0700 @@ -4,7 +4,6 @@ /* Ent daemon. */ #include "debug.h" -#include "kcond.h" #include "txnmgr.h" #include "tree.h" #include "entd.h" @@ -13,21 +12,21 @@ #include "reiser4.h" #include "vfs_ops.h" #include "page_cache.h" +#include "inode.h" #include /* struct task_struct */ #include #include #include -#include /* INITIAL_JIFFIES */ -#include /* bdi_write_congested */ - -TYPE_SAFE_LIST_DEFINE(wbq, struct wbq, link); +#include /* INITIAL_JIFFIES */ +#include /* bdi_write_congested */ +#include #define DEF_PRIORITY 12 #define MAX_ENTD_ITERS 10 -#define ENTD_ASYNC_REQUESTS_LIMIT 32 +#define ENTD_ASYNC_REQUESTS_LIMIT 0 -static void entd_flush(struct super_block *super); +static void entd_flush(struct super_block *); static int entd(void *arg); /* @@ -38,69 +37,106 @@ static int entd(void *arg); "ent:%s%s", super->s_id, (state)) /* get ent context for the @super */ -static inline entd_context * -get_entd_context(struct super_block *super) +static inline entd_context *get_entd_context(struct super_block *super) { return &get_super_private(super)->entd; } -/* initialize ent thread context */ -reiser4_internal void -init_entd_context(struct super_block *super) +/** + * init_entd - initialize entd context and start kernel daemon + * @super: super block to start ent thread for + * + * Creates entd contexts, starts kernel thread and waits until it + * initializes. + */ +void init_entd(struct super_block *super) { - entd_context * ctx; + entd_context *ctx; assert("nikita-3104", super != NULL); ctx = get_entd_context(super); memset(ctx, 0, sizeof *ctx); - kcond_init(&ctx->startup); - kcond_init(&ctx->wait); - init_completion(&ctx->finish); spin_lock_init(&ctx->guard); + init_waitqueue_head(&ctx->wait); + + /* + * prepare synchronization object to synchronize with ent thread + * initialization + */ + init_completion(&ctx->start_finish_completion); - /* start ent thread.. */ + /* start entd */ kernel_thread(entd, super, CLONE_VM | CLONE_FS | CLONE_FILES); - spin_lock(&ctx->guard); - /* and wait for its initialization to finish */ - while (ctx->tsk == NULL) - kcond_wait(&ctx->startup, &ctx->guard, 0); - spin_unlock(&ctx->guard); + /* wait for entd initialization */ + wait_for_completion(&ctx->start_finish_completion); + #if REISER4_DEBUG - flushers_list_init(&ctx->flushers_list); + INIT_LIST_HEAD(&ctx->flushers_list); #endif - wbq_list_init(&ctx->wbq_list); + INIT_LIST_HEAD(&ctx->wbq_list); } -static void wakeup_wbq (entd_context * ent, struct wbq * rq) +static void __put_wbq(entd_context * ent, struct wbq *rq) { - wbq_list_remove(rq); - ent->nr_synchronous_requests --; - rq->wbc->nr_to_write --; + rq->wbc->nr_to_write--; up(&rq->sem); } -static void wakeup_all_wbq (entd_context * ent) +/* ent should be locked */ +static struct wbq *__get_wbq(entd_context * ent) { - struct wbq * rq; + struct wbq *wbq; - spin_lock(&ent->guard); - while (!wbq_list_empty(&ent->wbq_list)) { - rq = wbq_list_front(&ent->wbq_list); - wakeup_wbq(ent, rq); + if (list_empty_careful(&ent->wbq_list)) { + return NULL; } + ent->nr_synchronous_requests --; + ent->nr_all_requests --; + wbq = list_entry(ent->wbq_list.next, struct wbq, link); + list_del_init(&wbq->link); + return wbq; +} + +struct wbq * get_wbq(struct super_block * super) +{ + struct wbq *result; + entd_context * ent = get_entd_context(super); + + spin_lock(&ent->guard); + result = __get_wbq(ent); + spin_unlock(&ent->guard); + + return result; +} + +void put_wbq(struct super_block *super, struct wbq * rq) +{ + entd_context * ent = get_entd_context(super); + + spin_lock(&ent->guard); + __put_wbq(ent, rq); + spin_unlock(&ent->guard); +} + +static void wakeup_all_wbq(entd_context * ent) +{ + struct wbq *rq; + + spin_lock(&ent->guard); + while ((rq = __get_wbq(ent)) != NULL) + __put_wbq(ent, rq); spin_unlock(&ent->guard); } /* ent thread function */ -static int -entd(void *arg) +static int entd(void *arg) { struct super_block *super; struct task_struct *me; - entd_context *ent; + entd_context *ent; super = arg; /* standard kernel thread prologue */ @@ -117,37 +153,39 @@ entd(void *arg) /* do_fork() just copies task_struct into the new thread. ->fs_context shouldn't be copied of course. This shouldn't be a problem for the rest of the code though. - */ + */ me->journal_info = NULL; ent = get_entd_context(super); spin_lock(&ent->guard); ent->tsk = me; - /* signal waiters that initialization is completed */ - kcond_broadcast(&ent->startup); spin_unlock(&ent->guard); - while (1) { - int result = 0; - if (me->flags & PF_FREEZE) + /* initialization is done */ + complete(&ent->start_finish_completion); + + while (!ent->done) { + if (freezing(me)) refrigerator(); spin_lock(&ent->guard); while (ent->nr_all_requests != 0) { - assert("zam-1043", ent->nr_all_requests >= ent->nr_synchronous_requests); + assert("zam-1043", + ent->nr_all_requests >= + ent->nr_synchronous_requests); if (ent->nr_synchronous_requests != 0) { - struct wbq * rq = wbq_list_front(&ent->wbq_list); + struct wbq *rq = list_entry(ent->wbq_list.next, struct wbq, link); - if (++ rq->nr_entd_iters > MAX_ENTD_ITERS) { - ent->nr_all_requests --; - wakeup_wbq(ent, rq); + if (++rq->nr_entd_iters > MAX_ENTD_ITERS) { + rq = __get_wbq(ent); + __put_wbq(ent, rq); continue; } } else { /* endless loop avoidance. */ - ent->nr_all_requests --; + ent->nr_all_requests--; } spin_unlock(&ent->guard); @@ -155,180 +193,252 @@ entd(void *arg) entd_flush(super); spin_lock(&ent->guard); } + spin_unlock(&ent->guard); entd_set_comm("."); - /* wait for work */ - result = kcond_wait(&ent->wait, &ent->guard, 1); - if (result != -EINTR && result != 0) - /* some other error */ - warning("nikita-3099", "Error: %i", result); + { + DEFINE_WAIT(__wait); - /* we are asked to exit */ - if (ent->done) { - spin_unlock(&ent->guard); - break; - } + for (;;) { + int dontsleep; - spin_unlock(&ent->guard); + prepare_to_wait(&ent->wait, &__wait, TASK_UNINTERRUPTIBLE); + spin_lock(&ent->guard); + dontsleep = ent->done || ent->nr_all_requests != 0; + spin_unlock(&ent->guard); + if (dontsleep) + break; + schedule(); + } + finish_wait(&ent->wait, &__wait); + } } wakeup_all_wbq(ent); - complete_and_exit(&ent->finish, 0); + complete_and_exit(&ent->start_finish_completion, 0); /* not reached. */ return 0; } -/* called by umount */ -reiser4_internal void -done_entd_context(struct super_block *super) +/** + * done_entd - stop entd kernel thread + * @super: super block to stop ent thread for + * + * It is called on umount. Sends stop signal to entd and wait until it handles + * it. + */ +void done_entd(struct super_block *super) { - entd_context * ent; + entd_context *ent; assert("nikita-3103", super != NULL); ent = get_entd_context(super); + /* + * prepare synchronization object to synchronize with entd + * completion + */ + init_completion(&ent->start_finish_completion); + spin_lock(&ent->guard); ent->done = 1; - kcond_signal(&ent->wait); spin_unlock(&ent->guard); + wake_up(&ent->wait); - /* wait until daemon finishes */ - wait_for_completion(&ent->finish); + /* wait until entd finishes */ + wait_for_completion(&ent->start_finish_completion); } /* called at the beginning of jnode_flush to register flusher thread with ent * daemon */ -reiser4_internal void enter_flush (struct super_block * super) +void enter_flush(struct super_block *super) { - entd_context * ent; + entd_context *ent; - assert ("zam-1029", super != NULL); + assert("zam-1029", super != NULL); ent = get_entd_context(super); - assert ("zam-1030", ent != NULL); + assert("zam-1030", ent != NULL); spin_lock(&ent->guard); - ent->flushers ++; + ent->flushers++; #if REISER4_DEBUG - flushers_list_push_front(&ent->flushers_list, get_current_context()); + list_add(&get_current_context()->flushers_link, &ent->flushers_list); #endif spin_unlock(&ent->guard); } /* called at the end of jnode_flush */ -reiser4_internal void leave_flush (struct super_block * super) +void leave_flush(struct super_block *super) { - entd_context * ent; + entd_context *ent; + int wake_up_ent; - assert ("zam-1027", super != NULL); + assert("zam-1027", super != NULL); ent = get_entd_context(super); - assert ("zam-1028", ent != NULL); + assert("zam-1028", ent != NULL); spin_lock(&ent->guard); - ent->flushers --; - if (ent->flushers == 0 && ent->nr_synchronous_requests != 0) - kcond_signal(&ent->wait); + ent->flushers--; + wake_up_ent = (ent->flushers == 0 && ent->nr_synchronous_requests != 0); #if REISER4_DEBUG - flushers_list_remove_clean(get_current_context()); + list_del_init(&get_current_context()->flushers_link); #endif spin_unlock(&ent->guard); + if (wake_up_ent) + wake_up(&ent->wait); +} + +#define ENTD_CAPTURE_APAGE_BURST (32l) + +/* Ask as_ops->writepages() to process given page */ +static jnode * capture_given_page(struct page *page) +{ + struct address_space * mapping; + struct writeback_control wbc = { + .bdi = NULL, + .sync_mode = WB_SYNC_NONE, + .older_than_this = NULL, + .nonblocking = 0, + .start = page->index << PAGE_CACHE_SHIFT, + .end = page->index << PAGE_CACHE_SHIFT, + .nr_to_write = 1, + }; + jnode * node; + + mapping = page->mapping; + if (mapping == NULL) + return NULL; + if (mapping->a_ops && mapping->a_ops->writepages) + mapping->a_ops->writepages(mapping, &wbc); + lock_page(page); + node = jprivate(page); + if (node != NULL) + jref(node); + unlock_page(page); + return node; } -/* signal to ent thread that it has more work to do */ -static void kick_entd(entd_context * ent) +jnode * get_jnode_by_wbq(struct super_block *super, struct wbq *rq) { - kcond_signal(&ent->wait); + struct page * page = NULL; + jnode * node = NULL; + int result; + + if (rq == NULL) + return NULL; + + assert("zam-1052", rq->page != NULL); + + page = rq->page; + node = capture_given_page(page); + if (node == NULL) + return NULL; + spin_lock_jnode(node); + result = try_capture(node, ZNODE_WRITE_LOCK, TXN_CAPTURE_NONBLOCKING, 0); + spin_unlock_jnode(node); + if (result) { + jput(node); + return NULL; + } + return node; } static void entd_flush(struct super_block *super) { - long nr_submitted = 0; - int result; reiser4_context ctx; struct writeback_control wbc = { - .bdi = NULL, - .sync_mode = WB_SYNC_NONE, + .bdi = NULL, + .sync_mode = WB_SYNC_NONE, .older_than_this = NULL, - .nr_to_write = 32, - .nonblocking = 0, + .nr_to_write = ENTD_CAPTURE_APAGE_BURST, + .nonblocking = 0, }; - init_context(&ctx, super); - + init_stack_context(&ctx, super); ctx.entd = 1; generic_sync_sb_inodes(super, &wbc); - result = flush_some_atom(&nr_submitted, &wbc, JNODE_FLUSH_WRITE_BLOCKS); - if (result != 0) - warning("nikita-3100", "Flush failed: %i", result); + wbc.nr_to_write = ENTD_CAPTURE_APAGE_BURST; + writeout(super, &wbc); context_set_commit_async(&ctx); reiser4_exit_context(&ctx); } -void write_page_by_ent (struct page * page, struct writeback_control * wbc) +int write_page_by_ent(struct page *page, struct writeback_control *wbc) { - struct super_block * sb; - entd_context * ent; + struct super_block *sb; + entd_context *ent; struct wbq rq; int phantom; + int wake_up_entd; sb = page->mapping->host->i_sb; ent = get_entd_context(sb); + if (ent == NULL || ent->done) + /* entd is not running. */ + return 0; phantom = jprivate(page) == NULL || !jnode_check_dirty(jprivate(page)); +#if 1 + BUG_ON(page->mapping == NULL); /* re-dirty page */ - set_page_dirty_internal(page, phantom); + if (!TestSetPageDirty(page)) { + if (mapping_cap_account_dirty(page->mapping)) + inc_page_state(nr_dirty); + } + /*reiser4_set_page_dirty(page);*/ + /*set_page_dirty_internal(page, phantom);*/ /* unlock it to avoid deadlocks with the thread which will do actual i/o */ unlock_page(page); - - /* entd is not running. */ - if (ent == NULL || ent->done) - return; +#endif /* init wbq */ - wbq_list_clean(&rq); + INIT_LIST_HEAD(&rq.link); rq.nr_entd_iters = 0; rq.page = page; rq.wbc = wbc; + rq.phantom = phantom; spin_lock(&ent->guard); - if (ent->flushers == 0) - kick_entd(ent); - ent->nr_all_requests ++; - if (ent->nr_all_requests <= ent->nr_synchronous_requests + ENTD_ASYNC_REQUESTS_LIMIT) { + wake_up_entd = (ent->flushers == 0); + ent->nr_all_requests++; + if (ent->nr_all_requests <= + ent->nr_synchronous_requests + ENTD_ASYNC_REQUESTS_LIMIT) { + BUG_ON(1); spin_unlock(&ent->guard); - return; + if (wake_up_entd) + wake_up(&ent->wait); + lock_page(page); + return 0; } + sema_init(&rq.sem, 0); - wbq_list_push_back(&ent->wbq_list, &rq); - ent->nr_synchronous_requests ++; + list_add_tail(&rq.link, &ent->wbq_list); + ent->nr_synchronous_requests++; spin_unlock(&ent->guard); + if (wake_up_entd) + wake_up(&ent->wait); down(&rq.sem); /* don't release rq until wakeup_wbq stops using it. */ spin_lock(&ent->guard); spin_unlock(&ent->guard); - /* wbq dequeued by the ent thread (by another then current thread). */ -} - -/* ent should be locked */ -static struct wbq * get_wbq (entd_context * ent) -{ - if (wbq_list_empty(&ent->wbq_list)) { - spin_unlock(&ent->guard); - return NULL; + if (!PageDirty(page)) { + /* Eventually ENTD has written the page to disk. */ + return 1; } - return wbq_list_front(&ent->wbq_list); + lock_page(page); + return WRITEPAGE_ACTIVATE; } - -void ent_writes_page (struct super_block * sb, struct page * page) +void ent_writes_page(struct super_block *sb, struct page *page) { - entd_context * ent = get_entd_context(sb); - struct wbq * rq; + entd_context *ent = get_entd_context(sb); + struct wbq *rq; assert("zam-1041", ent != NULL); @@ -339,20 +449,17 @@ void ent_writes_page (struct super_block spin_lock(&ent->guard); if (ent->nr_all_requests > 0) { - ent->nr_all_requests --; - rq = get_wbq(ent); - if (rq == NULL) - /* get_wbq() releases entd->guard spinlock if NULL is - * returned. */ - return; - wakeup_wbq(ent, rq); + rq = __get_wbq(ent); + if (rq != NULL) + __put_wbq(ent, rq); } spin_unlock(&ent->guard); } -int wbq_available (void) { - struct super_block * sb = reiser4_get_current_sb(); - entd_context * ent = get_entd_context(sb); +int wbq_available(void) +{ + struct super_block *sb = reiser4_get_current_sb(); + entd_context *ent = get_entd_context(sb); return ent->nr_all_requests; } diff -puN fs/reiser4/entd.h~reiser4-big-update fs/reiser4/entd.h --- devel/fs/reiser4/entd.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/entd.h 2005-09-15 19:51:08.000000000 -0700 @@ -5,70 +5,65 @@ #ifndef __ENTD_H__ #define __ENTD_H__ -#include "kcond.h" #include "context.h" #include #include +#include #include #include /* for struct task_struct */ -#include "type_safe_list.h" - -TYPE_SAFE_LIST_DECLARE(wbq); /* write-back request. */ struct wbq { - wbq_list_link link; - struct writeback_control * wbc; - struct page * page; + struct list_head link; /* list head of this list is in entd context */ + struct writeback_control *wbc; + struct page *page; struct semaphore sem; - int nr_entd_iters; + int nr_entd_iters; + unsigned int phantom:1; }; /* ent-thread context. This is used to synchronize starting/stopping ent * threads. */ typedef struct entd_context { /* - * condition variable that is signaled by ent thread after it - * successfully started up. - */ - kcond_t startup; - /* * completion that is signaled by ent thread just before it * terminates. */ - struct completion finish; - /* - * condition variable that ent thread waits on for more work. It's - * signaled by write_page_by_ent(). - */ - kcond_t wait; + struct completion start_finish_completion; + /* wait queue that ent thread waits on for more work. It's + * signaled by write_page_by_ent(). */ + wait_queue_head_t wait; /* spinlock protecting other fields */ - spinlock_t guard; + spinlock_t guard; /* ent thread */ struct task_struct *tsk; /* set to indicate that ent thread should leave. */ - int done; + int done; /* counter of active flushers */ - int flushers; + int flushers; #if REISER4_DEBUG /* list of all active flushers */ - flushers_list_head flushers_list; + struct list_head flushers_list; #endif - int nr_all_requests; - int nr_synchronous_requests; - wbq_list_head wbq_list; + int nr_all_requests; + int nr_synchronous_requests; + struct list_head wbq_list; /* struct wbq are elements of this list */ } entd_context; -extern void init_entd_context(struct super_block *super); -extern void done_entd_context(struct super_block *super); +extern void init_entd(struct super_block *); +extern void done_entd(struct super_block *); -extern void enter_flush(struct super_block *super); -extern void leave_flush(struct super_block *super); +extern void enter_flush(struct super_block *); +extern void leave_flush(struct super_block *); -extern void write_page_by_ent(struct page *, struct writeback_control *); -extern int wbq_available (void); -extern void ent_writes_page (struct super_block *, struct page *); +extern int write_page_by_ent(struct page *, struct writeback_control *); +extern int wbq_available(void); +extern void ent_writes_page(struct super_block *, struct page *); + +extern struct wbq *get_wbq(struct super_block *); +extern void put_wbq(struct super_block *, struct wbq *); +extern jnode *get_jnode_by_wbq(struct super_block *, struct wbq *); /* __ENTD_H__ */ #endif diff -puN fs/reiser4/eottl.c~reiser4-big-update fs/reiser4/eottl.c --- devel/fs/reiser4/eottl.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/eottl.c 2005-09-15 19:51:08.000000000 -0700 @@ -16,107 +16,110 @@ #include /* for __u?? */ -/* Extents on the twig level (EOTTL) handling. - - EOTTL poses some problems to the tree traversal, that are better - explained by example. - - Suppose we have block B1 on the twig level with the following items: - - 0. internal item I0 with key (0:0:0:0) (locality, key-type, object-id, offset) - 1. extent item E1 with key (1:4:100:0), having 10 blocks of 4k each - 2. internal item I2 with key (10:0:0:0) - - We are trying to insert item with key (5:0:0:0). Lookup finds node - B1, and then intra-node lookup is done. This lookup finished on the - E1, because the key we are looking for is larger than the key of E1 - and is smaller than key the of I2. - - Here search is stuck. - - After some thought it is clear what is wrong here: extents on the - twig level break some basic property of the *search* tree (on the - pretext, that they restore property of balanced tree). - - Said property is the following: if in the internal node of the search - tree we have [ ... Key1 Pointer Key2 ... ] then, all data that are or - will be keyed in the tree with the Key such that Key1 <= Key < Key2 - are accessible through the Pointer. - - This is not true, when Pointer is Extent-Pointer, simply because - extent cannot expand indefinitely to the right to include any item - with - - Key1 <= Key <= Key2. - - For example, our E1 extent is only responsible for the data with keys - - (1:4:100:0) <= key <= (1:4:100:0xffffffffffffffff), and - - so, key range - - ( (1:4:100:0xffffffffffffffff), (10:0:0:0) ) - - is orphaned: there is no way to get there from the tree root. - - In other words, extent pointers are different than normal child - pointers as far as search tree is concerned, and this creates such - problems. - - Possible solution for this problem is to insert our item into node - pointed to by I2. There are some problems through: - - (1) I2 can be in a different node. - (2) E1 can be immediately followed by another extent E2. - - (1) is solved by calling reiser4_get_right_neighbor() and accounting - for locks/coords as necessary. - - (2) is more complex. Solution here is to insert new empty leaf node - and insert internal item between E1 and E2 pointing to said leaf - node. This is further complicated by possibility that E2 is in a - different node, etc. - - Problems: - - (1) if there was internal item I2 immediately on the right of an - extent E1 we and we decided to insert new item S1 into node N2 - pointed to by I2, then key of S1 will be less than smallest key in - the N2. Normally, search key checks that key we are looking for is in - the range of keys covered by the node key is being looked in. To work - around of this situation, while preserving useful consistency check - new flag CBK_TRUST_DK was added to the cbk falgs bitmask. This flag - is automatically set on entrance to the coord_by_key() and is only - cleared when we are about to enter situation described above. - - (2) If extent E1 is immediately followed by another extent E2 and we - are searching for the key that is between E1 and E2 we only have to - insert new empty leaf node when coord_by_key was called for - insertion, rather than just for lookup. To distinguish these cases, - new flag CBK_FOR_INSERT was added to the cbk falgs bitmask. This flag - is automatically set by coord_by_key calls performed by - insert_by_key() and friends. - - (3) Insertion of new empty leaf node (possibly) requires - balancing. In any case it requires modification of node content which - is only possible under write lock. It may well happen that we only - have read lock on the node where new internal pointer is to be - inserted (common case: lookup of non-existent stat-data that fells - between two extents). If only read lock is held, tree traversal is - restarted with lock_level modified so that next time we hit this - problem, write lock will be held. Once we have write lock, balancing - will be performed. -*/ - - -/* look to an unit next to @coord. If it is an internal one - 1 is returned, - @coord is set to that unit. If that unit is in right neighbor, @lh is moved, - neighbor is loaded, original node is zrelsed, @coord is set to first unit - of neighbor. Otherwise, 0 is returned, @coord and @lh are left unchanged. - 2 is returned to restart search. -*/ +/* + * Extents on the twig level (EOTTL) handling. + * + * EOTTL poses some problems to the tree traversal, that are better explained + * by example. + * + * Suppose we have block B1 on the twig level with the following items: + * + * 0. internal item I0 with key (0:0:0:0) (locality, key-type, object-id, + * offset) + * 1. extent item E1 with key (1:4:100:0), having 10 blocks of 4k each + * 2. internal item I2 with key (10:0:0:0) + * + * We are trying to insert item with key (5:0:0:0). Lookup finds node B1, and + * then intra-node lookup is done. This lookup finished on the E1, because the + * key we are looking for is larger than the key of E1 and is smaller than key + * the of I2. + * + * Here search is stuck. + * + * After some thought it is clear what is wrong here: extents on the twig level + * break some basic property of the *search* tree (on the pretext, that they + * restore property of balanced tree). + * + * Said property is the following: if in the internal node of the search tree + * we have [ ... Key1 Pointer Key2 ... ] then, all data that are or will be + * keyed in the tree with the Key such that Key1 <= Key < Key2 are accessible + * through the Pointer. + * + * This is not true, when Pointer is Extent-Pointer, simply because extent + * cannot expand indefinitely to the right to include any item with + * + * Key1 <= Key <= Key2. + * + * For example, our E1 extent is only responsible for the data with keys + * + * (1:4:100:0) <= key <= (1:4:100:0xffffffffffffffff), and + * + * so, key range + * + * ( (1:4:100:0xffffffffffffffff), (10:0:0:0) ) + * + * is orphaned: there is no way to get there from the tree root. + * + * In other words, extent pointers are different than normal child pointers as + * far as search tree is concerned, and this creates such problems. + * + * Possible solution for this problem is to insert our item into node pointed + * to by I2. There are some problems through: + * + * (1) I2 can be in a different node. + * (2) E1 can be immediately followed by another extent E2. + * + * (1) is solved by calling reiser4_get_right_neighbor() and accounting + * for locks/coords as necessary. + * + * (2) is more complex. Solution here is to insert new empty leaf node and + * insert internal item between E1 and E2 pointing to said leaf node. This is + * further complicated by possibility that E2 is in a different node, etc. + * + * Problems: + * + * (1) if there was internal item I2 immediately on the right of an extent E1 + * we and we decided to insert new item S1 into node N2 pointed to by I2, then + * key of S1 will be less than smallest key in the N2. Normally, search key + * checks that key we are looking for is in the range of keys covered by the + * node key is being looked in. To work around of this situation, while + * preserving useful consistency check new flag CBK_TRUST_DK was added to the + * cbk falgs bitmask. This flag is automatically set on entrance to the + * coord_by_key() and is only cleared when we are about to enter situation + * described above. + * + * (2) If extent E1 is immediately followed by another extent E2 and we are + * searching for the key that is between E1 and E2 we only have to insert new + * empty leaf node when coord_by_key was called for insertion, rather than just + * for lookup. To distinguish these cases, new flag CBK_FOR_INSERT was added to + * the cbk falgs bitmask. This flag is automatically set by coord_by_key calls + * performed by insert_by_key() and friends. + * + * (3) Insertion of new empty leaf node (possibly) requires balancing. In any + * case it requires modification of node content which is only possible under + * write lock. It may well happen that we only have read lock on the node where + * new internal pointer is to be inserted (common case: lookup of non-existent + * stat-data that fells between two extents). If only read lock is held, tree + * traversal is restarted with lock_level modified so that next time we hit + * this problem, write lock will be held. Once we have write lock, balancing + * will be performed. + */ + +/** + * is_next_item_internal - check whether next item is internal + * @coord: coordinate of extent item in twig node + * @key: search key + * @lh: twig node lock handle + * + * Looks at the unit next to @coord. If it is an internal one - 1 is returned, + * @coord is set to that unit. If that unit is in right neighbor, @lh is moved + * to that node, @coord is set to its first unit. If next item is not internal + * or does not exist then 0 is returned, @coord and @lh are left unchanged. 2 + * is returned if search restart has to be done. + */ static int -is_next_item_internal(coord_t *coord, const reiser4_key *key, lock_handle *lh) +is_next_item_internal(coord_t *coord, const reiser4_key *key, + lock_handle *lh) { coord_t next; lock_handle rn; @@ -124,7 +127,7 @@ is_next_item_internal(coord_t *coord, co coord_dup(&next, coord); if (coord_next_unit(&next) == 0) { - /* next unit is int this node */ + /* next unit is in this node */ if (item_is_internal(&next)) { coord_dup(coord, &next); return 1; @@ -133,14 +136,26 @@ is_next_item_internal(coord_t *coord, co return 0; } - assert("vs-5", UNDER_RW(dk, current_tree, read, keylt(key, znode_get_rd_key(coord->node)))); + /* + * next unit either does not exist or is in right neighbor. If it is in + * right neighbor we have to check right delimiting key because + * concurrent thread could get their first and insert item with a key + * smaller than @key + */ + result = UNDER_RW(dk, current_tree, read, + keycmp(key, znode_get_rd_key(coord->node))); + assert("vs-6", result != EQUAL_TO); + if (result == GREATER_THAN) + return 2; - /* next unit either does not exist or is in right neighbor */ + /* lock right neighbor */ init_lh(&rn); result = reiser4_get_right_neighbor(&rn, coord->node, - znode_is_wlocked(coord->node) ? ZNODE_WRITE_LOCK : ZNODE_READ_LOCK, + znode_is_wlocked(coord->node) ? + ZNODE_WRITE_LOCK : ZNODE_READ_LOCK, GN_CAN_USE_UPPER_LEVELS); - if (result == -E_NO_NEIGHBOR){ + if (result == -E_NO_NEIGHBOR) { + /* we are on the rightmost edge of the tree */ done_lh(&rn); return 0; } @@ -151,11 +166,14 @@ is_next_item_internal(coord_t *coord, co return result; } - /* check where anything managed to happen with right neighbor */ - result = UNDER_RW(dk, current_tree, read, keycmp(key, znode_get_ld_key(rn.node))); + /* + * check whether concurrent thread managed to insert item with a key + * smaller than @key + */ + result = UNDER_RW(dk, current_tree, read, + keycmp(key, znode_get_ld_key(rn.node))); assert("vs-6", result != EQUAL_TO); if (result == GREATER_THAN) { - warning("vs-7", "smaller keys managed to get inserted to the right neighbor"); done_lh(&rn); return 2; } @@ -169,26 +187,37 @@ is_next_item_internal(coord_t *coord, co coord_init_first_unit(&next, rn.node); if (item_is_internal(&next)) { + /* + * next unit is in right neighbor and it is an unit of internal + * item. Unlock coord->node. Move @lh to right neighbor. @coord + * is set to the first unit of right neighbor. + */ coord_dup(coord, &next); zrelse(rn.node); done_lh(lh); move_lh(lh, &rn); - /* coord and lock handle changed. Original node is not zrelsed, - though */ return 1; } - /* next item is extent */ + /* + * next unit is unit of extent item. Return without chaning @lh and + * @coord. + */ assert("vs-6", item_is_extent(&next)); zrelse(rn.node); done_lh(&rn); return 0; } -/* inserting empty leaf after (or between) item of not internal type we have to - know which right delimiting key corresponding znode has to be inserted with */ -static reiser4_key * -rd_key(coord_t *coord, reiser4_key *key) +/** + * rd_key - calculate key of an item next to the given one + * @coord: position in a node + * @key: storage for result key + * + * @coord is set between items or after the last item in a node. Calculate key + * of item to the right of @coord. + */ +static reiser4_key *rd_key(const coord_t *coord, reiser4_key *key) { coord_t dup; @@ -198,45 +227,49 @@ rd_key(coord_t *coord, reiser4_key *key) RLOCK_DK(current_tree); if (coord_set_to_right(&dup) == 0) - /* get right delimiting key from an item to the right of @coord */ + /* next item is in this node. Return its key. */ unit_key_by_coord(&dup, key); else - /* use right delimiting key of parent znode */ + /* + * next item either does not exist or is in right + * neighbor. Return znode's right delimiting key. + */ *key = *znode_get_rd_key(coord->node); RUNLOCK_DK(current_tree); return key; } - -ON_DEBUG(void check_dkeys(const znode *);) - -/* this is used to insert empty node into leaf level if tree lookup can not go - further down because it stopped between items of not internal type */ +/** + * add_empty_leaf - insert empty leaf between two extents + * @insert_coord: position in twig node between two extents + * @lh: twig node lock handle + * @key: left delimiting key of new node + * @rdkey: right delimiting key of new node + * + * Inserts empty leaf node between two extent items. It is necessary when we + * have to insert an item on leaf level between two extents (items on the twig + * level). + * + */ static int -add_empty_leaf(coord_t *insert_coord, lock_handle *lh, const reiser4_key *key, const reiser4_key *rdkey) +add_empty_leaf(coord_t *insert_coord, lock_handle *lh, + const reiser4_key *key, const reiser4_key *rdkey) { int result; carry_pool *pool; - carry_level todo; + carry_level *todo; + reiser4_item_data *item; + carry_insert_data *cdata; carry_op *op; znode *node; - reiser4_item_data item; - carry_insert_data cdata; reiser4_tree *tree; - pool = init_carry_pool(); - if (IS_ERR(pool)) - return PTR_ERR(pool); - init_carry_level(&todo, pool); assert("vs-49827", znode_contains_key_lock(insert_coord->node, key)); - tree = znode_get_tree(insert_coord->node); node = new_node(insert_coord->node, LEAF_LEVEL); - if (IS_ERR(node)) { - done_carry_pool(pool); + if (IS_ERR(node)) return PTR_ERR(node); - } /* setup delimiting keys for node being inserted */ WLOCK_DK(tree); @@ -247,21 +280,36 @@ add_empty_leaf(coord_t *insert_coord, lo WUNLOCK_DK(tree); ZF_SET(node, JNODE_ORPHAN); - op = post_carry(&todo, COP_INSERT, insert_coord->node, 0); + + /* + * allocate carry_pool, 3 carry_level-s, reiser4_item_data and + * carry_insert_data + */ + pool = init_carry_pool(sizeof(*pool) + 3 * sizeof(*todo) + + sizeof(*item) + sizeof(*cdata)); + if (IS_ERR(pool)) + return PTR_ERR(pool); + todo = (carry_level *) (pool + 1); + init_carry_level(todo, pool); + + item = (reiser4_item_data *) (todo + 3); + cdata = (carry_insert_data *) (item + 1); + + op = post_carry(todo, COP_INSERT, insert_coord->node, 0); if (!IS_ERR(op)) { - cdata.coord = insert_coord; - cdata.key = key; - cdata.data = &item; - op->u.insert.d = &cdata; + cdata->coord = insert_coord; + cdata->key = key; + cdata->data = item; + op->u.insert.d = cdata; op->u.insert.type = COPT_ITEM_DATA; - build_child_ptr_data(node, &item); - item.arg = NULL; + build_child_ptr_data(node, item); + item->arg = NULL; /* have @insert_coord to be set at inserted item after insertion is done */ - todo.track_type = CARRY_TRACK_CHANGE; - todo.tracked = lh; + todo->track_type = CARRY_TRACK_CHANGE; + todo->tracked = lh; - result = carry(&todo, 0); + result = carry(todo, NULL); if (result == 0) { /* * pin node in memory. This is necessary for @@ -283,25 +331,31 @@ add_empty_leaf(coord_t *insert_coord, lo if (result == 0) { znode_make_dirty(node); - /* when internal item pointing to @node - was inserted into twig node - create_hook_internal did not connect - it properly because its right - neighbor was not known. Do it - here */ + /* + * when internal item pointing to @node + * was inserted into twig node + * create_hook_internal did not connect + * it properly because its right + * neighbor was not known. Do it + * here + */ WLOCK_TREE(tree); - assert("nikita-3312", znode_is_right_connected(node)); - assert("nikita-2984", node->right == NULL); + assert("nikita-3312", + znode_is_right_connected(node)); + assert("nikita-2984", + node->right == NULL); ZF_CLR(node, JNODE_RIGHT_CONNECTED); WUNLOCK_TREE(tree); - result = connect_znode(insert_coord, node); + result = + connect_znode(insert_coord, node); if (result == 0) ON_DEBUG(check_dkeys(node)); done_lh(lh); move_lh(lh, &local_lh); assert("vs-1676", node_is_empty(node)); - coord_init_first_unit(insert_coord, node); + coord_init_first_unit(insert_coord, + node); } else { warning("nikita-3136", "Cannot lock child"); @@ -318,10 +372,17 @@ add_empty_leaf(coord_t *insert_coord, lo return result; } -/* handle extent-on-the-twig-level cases in tree traversal */ -reiser4_internal int -handle_eottl(cbk_handle *h /* cbk handle */ , - int *outcome /* how traversal should proceed */ ) +/** + * handle_eottl - handle extent-on-the-twig-level cases in tree traversal + * @h: search handle + * @outcome: flag saying whether search has to restart or is done + * + * Handles search on twig level. If this function completes search itself then + * it returns 1. If search has to go one level down then 0 is returned. If + * error happens then LOOKUP_DONE is returned via @outcome and error code is saved + * in @h->result. + */ +int handle_eottl(cbk_handle *h, int *outcome) { int result; reiser4_key key; @@ -329,18 +390,23 @@ handle_eottl(cbk_handle *h /* cbk handle coord = h->coord; - if (h->level != TWIG_LEVEL || (coord_is_existing_item(coord) && item_is_internal(coord))) { + if (h->level != TWIG_LEVEL || + (coord_is_existing_item(coord) && item_is_internal(coord))) { /* Continue to traverse tree downward. */ return 0; } - /* strange item type found on non-stop level?! Twig - horrors? */ + + /* + * make sure that @h->coord is set to twig node and that it is either + * set to extent item or after extent item + */ assert("vs-356", h->level == TWIG_LEVEL); assert("vs-357", ( { coord_t lcoord; coord_dup(&lcoord, coord); check_me("vs-733", coord_set_to_left(&lcoord) == 0); - item_is_extent(&lcoord);} + item_is_extent(&lcoord); + } )); if (*outcome == NS_FOUND) { @@ -367,17 +433,21 @@ handle_eottl(cbk_handle *h /* cbk handle return 1; } if (result == 0) { + /* + * item to the right is also an extent one. Allocate a new node + * and insert pointer to it after item h -> coord. + * + * This is a result of extents being located at the twig + * level. For explanation, see comment just above + * is_next_item_internal(). + */ znode *loaded; - /* item to the right is also an extent one. Allocate a new node - and insert pointer to it after item h -> coord. - This is a result of extents being located at the twig - level. For explanation, see comment just above - is_next_item_internal(). - */ if (cbk_lock_mode(h->level, h) != ZNODE_WRITE_LOCK) { - /* we got node read locked, restart coord_by_key to - have write lock on twig level */ + /* + * we got node read locked, restart coord_by_key to + * have write lock on twig level + */ h->lock_level = TWIG_LEVEL; h->lock_mode = ZNODE_WRITE_LOCK; *outcome = LOOKUP_REST; @@ -385,7 +455,9 @@ handle_eottl(cbk_handle *h /* cbk handle } loaded = coord->node; - result = add_empty_leaf(coord, h->active_lh, h->key, rd_key(coord, &key)); + result = + add_empty_leaf(coord, h->active_lh, h->key, + rd_key(coord, &key)); if (result) { h->error = "could not add empty leaf"; h->result = result; @@ -396,25 +468,27 @@ handle_eottl(cbk_handle *h /* cbk handle is unlocked, h->coord is set as EMPTY */ assert("vs-13", coord->between == EMPTY_NODE); assert("vs-14", znode_is_write_locked(coord->node)); - assert("vs-15", WITH_DATA(coord->node, node_is_empty(coord->node))); + assert("vs-15", + WITH_DATA(coord->node, node_is_empty(coord->node))); assert("vs-16", jnode_is_leaf(ZJNODE(coord->node))); assert("vs-17", coord->node == h->active_lh->node); *outcome = LOOKUP_DONE; h->result = CBK_COORD_NOTFOUND; return 1; } else if (result == 1) { - /* this is special case mentioned in the comment on - tree.h:cbk_flags. We have found internal item immediately - on the right of extent, and we are going to insert new item - there. Key of item we are going to insert is smaller than - leftmost key in the node pointed to by said internal item - (otherwise search wouldn't come to the extent in the first - place). - - This is a result of extents being located at the twig - level. For explanation, see comment just above - is_next_item_internal(). - */ + /* + * this is special case mentioned in the comment on + * tree.h:cbk_flags. We have found internal item immediately on + * the right of extent, and we are going to insert new item + * there. Key of item we are going to insert is smaller than + * leftmost key in the node pointed to by said internal item + * (otherwise search wouldn't come to the extent in the first + * place). + * + * This is a result of extents being located at the twig + * level. For explanation, see comment just above + * is_next_item_internal(). + */ h->flags &= ~CBK_TRUST_DK; } else { assert("vs-8", result == 2); @@ -425,13 +499,13 @@ handle_eottl(cbk_handle *h /* cbk handle return 0; } -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - scroll-step: 1 - End: -*/ +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 120 + * scroll-step: 1 + * End: + */ diff -puN fs/reiser4/estimate.c~reiser4-big-update fs/reiser4/estimate.c --- devel/fs/reiser4/estimate.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/estimate.c 2005-09-15 19:51:08.000000000 -0700 @@ -34,29 +34,25 @@ max_balance_overhead(reiser4_block_nr ch /* this returns maximal possible number of nodes which can be modified plus number of new nodes which can be required to perform insertion of one item into the tree */ /* it is only called when tree height changes, or gets initialized */ -reiser4_internal reiser4_block_nr -calc_estimate_one_insert(tree_level height) +reiser4_block_nr calc_estimate_one_insert(tree_level height) { return 1 + max_balance_overhead(1, height); } -reiser4_internal reiser4_block_nr -estimate_one_insert_item(reiser4_tree *tree) +reiser4_block_nr estimate_one_insert_item(reiser4_tree * tree) { return tree->estimate_one_insert; } /* this returns maximal possible number of nodes which can be modified plus number of new nodes which can be required to perform insertion of one unit into an item in the tree */ -reiser4_internal reiser4_block_nr -estimate_one_insert_into_item(reiser4_tree *tree) +reiser4_block_nr estimate_one_insert_into_item(reiser4_tree * tree) { /* estimate insert into item just like item insertion */ return tree->estimate_one_insert; } -reiser4_internal reiser4_block_nr -estimate_one_item_removal(reiser4_tree *tree) +reiser4_block_nr estimate_one_item_removal(reiser4_tree * tree) { /* on item removal reiser4 does not try to pack nodes more complact, so, only one node may be dirtied on leaf level */ @@ -66,27 +62,27 @@ estimate_one_item_removal(reiser4_tree * /* on leaf level insert_flow may add CARRY_FLOW_NEW_NODES_LIMIT new nodes and dirty 3 existing nodes (insert point and both its neighbors). Max_balance_overhead should estimate number of blocks which may change/get added on internal levels */ -reiser4_internal reiser4_block_nr -estimate_insert_flow(tree_level height) +reiser4_block_nr estimate_insert_flow(tree_level height) { - return 3 + CARRY_FLOW_NEW_NODES_LIMIT + max_balance_overhead(3 + CARRY_FLOW_NEW_NODES_LIMIT, height); + return 3 + CARRY_FLOW_NEW_NODES_LIMIT + max_balance_overhead(3 + + CARRY_FLOW_NEW_NODES_LIMIT, + height); } /* returnes max number of nodes can be occupied by disk cluster */ -reiser4_internal reiser4_block_nr -estimate_disk_cluster(struct inode * inode) +reiser4_block_nr estimate_disk_cluster(struct inode * inode) { return 2 + cluster_nrpages(inode); } /* how many nodes might get dirty and added nodes during insertion of a disk cluster */ -reiser4_internal reiser4_block_nr -estimate_insert_cluster(struct inode * inode, int unprepped) +reiser4_block_nr estimate_insert_cluster(struct inode * inode, int unprepped) { int per_cluster; per_cluster = (unprepped ? 1 : cluster_nrpages(inode)); - return 3 + per_cluster + max_balance_overhead(3 + per_cluster, REISER4_MAX_ZTREE_HEIGHT); + return 3 + per_cluster + max_balance_overhead(3 + per_cluster, + REISER4_MAX_ZTREE_HEIGHT); } /* Make Linus happy. diff -puN /dev/null fs/reiser4/export_ops.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/fs/reiser4/export_ops.c 2005-09-15 19:51:08.000000000 -0700 @@ -0,0 +1,296 @@ +/* Copyright 2005 by Hans Reiser, licensing governed by + * reiser4/README */ + +#include "inode.h" +#include "plugin/plugin.h" + + +/* + * Supported file-handle types + */ +typedef enum { + FH_WITH_PARENT = 0x10, /* file handle with parent */ + FH_WITHOUT_PARENT = 0x11 /* file handle without parent */ +} reiser4_fhtype; + +#define NFSERROR (255) + +/* initialize place-holder for object */ +static void object_on_wire_init(reiser4_object_on_wire *o) +{ + o->plugin = NULL; +} + +/* finish with @o */ +static void object_on_wire_done(reiser4_object_on_wire *o) +{ + if (o->plugin != NULL) + o->plugin->wire.done(o); +} + +/* + * read serialized object identity from @addr and store information about + * object in @obj. This is dual to encode_inode(). + */ +static char *decode_inode(struct super_block *s, char *addr, + reiser4_object_on_wire * obj) +{ + file_plugin *fplug; + + /* identifier of object plugin is stored in the first two bytes, + * followed by... */ + fplug = file_plugin_by_disk_id(get_tree(s), (d16 *) addr); + if (fplug != NULL) { + addr += sizeof(d16); + obj->plugin = fplug; + assert("nikita-3520", fplug->wire.read != NULL); + /* plugin specific encoding of object identity. */ + addr = fplug->wire.read(addr, obj); + } else + addr = ERR_PTR(RETERR(-EINVAL)); + return addr; +} + +/** + * reiser4_decode_fh - decode_fh of export operations + * @super: super block + * @fh: nfsd file handle + * @len: length of file handle + * @fhtype: type of file handle + * @acceptable: acceptability testing function + * @context: argument for @acceptable + * + * Returns dentry referring to the same file as @fh. + */ +static struct dentry *reiser4_decode_fh(struct super_block *super, __u32 *fh, + int len, int fhtype, + int (*acceptable) (void *context, + struct dentry *de), + void *context) +{ + reiser4_context *ctx; + reiser4_object_on_wire object; + reiser4_object_on_wire parent; + char *addr; + int with_parent; + + ctx = init_context(super); + if (IS_ERR(ctx)) + return (struct dentry *)ctx; + + assert("vs-1482", + fhtype == FH_WITH_PARENT || fhtype == FH_WITHOUT_PARENT); + + with_parent = (fhtype == FH_WITH_PARENT); + + addr = (char *)fh; + + object_on_wire_init(&object); + object_on_wire_init(&parent); + + addr = decode_inode(super, addr, &object); + if (!IS_ERR(addr)) { + if (with_parent) + addr = decode_inode(super, addr, &parent); + if (!IS_ERR(addr)) { + struct dentry *d; + typeof(super->s_export_op->find_exported_dentry) fn; + + fn = super->s_export_op->find_exported_dentry; + assert("nikita-3521", fn != NULL); + d = fn(super, &object, with_parent ? &parent : NULL, + acceptable, context); + if (d != NULL && !IS_ERR(d)) + /* FIXME check for -ENOMEM */ + reiser4_get_dentry_fsdata(d)->stateless = 1; + addr = (char *)d; + } + } + + object_on_wire_done(&object); + object_on_wire_done(&parent); + + reiser4_exit_context(ctx); + return (void *)addr; +} + +/* + * Object serialization support. + * + * To support knfsd file system provides export_operations that are used to + * construct and interpret NFS file handles. As a generalization of this, + * reiser4 object plugins have serialization support: it provides methods to + * create on-wire representation of identity of reiser4 object, and + * re-create/locate object given its on-wire identity. + * + */ + +/* + * return number of bytes that on-wire representation of @inode's identity + * consumes. + */ +static int encode_inode_size(struct inode *inode) +{ + assert("nikita-3514", inode != NULL); + assert("nikita-3515", inode_file_plugin(inode) != NULL); + assert("nikita-3516", inode_file_plugin(inode)->wire.size != NULL); + + return inode_file_plugin(inode)->wire.size(inode) + sizeof(d16); +} + +/* + * store on-wire representation of @inode's identity at the area beginning at + * @start. + */ +static char *encode_inode(struct inode *inode, char *start) +{ + assert("nikita-3517", inode != NULL); + assert("nikita-3518", inode_file_plugin(inode) != NULL); + assert("nikita-3519", inode_file_plugin(inode)->wire.write != NULL); + + /* + * first, store two-byte identifier of object plugin, then + */ + save_plugin_id(file_plugin_to_plugin(inode_file_plugin(inode)), + (d16 *) start); + start += sizeof(d16); + /* + * call plugin to serialize object's identity + */ + return inode_file_plugin(inode)->wire.write(inode, start); +} + +/* this returns number of 32 bit long numbers encoded in @lenp. 255 is + * returned if file handle can not be stored */ +/** + * reiser4_encode_fh - encode_fh of export operations + * @dentry: + * @fh: + * @lenp: + * @need_parent: + * + */ +static int +reiser4_encode_fh(struct dentry *dentry, __u32 *fh, int *lenp, + int need_parent) +{ + struct inode *inode; + struct inode *parent; + char *addr; + int need; + int delta; + int result; + reiser4_context *ctx; + + /* + * knfsd asks as to serialize object in @dentry, and, optionally its + * parent (if need_parent != 0). + * + * encode_inode() and encode_inode_size() is used to build + * representation of object and its parent. All hard work is done by + * object plugins. + */ + inode = dentry->d_inode; + parent = dentry->d_parent->d_inode; + + addr = (char *)fh; + + need = encode_inode_size(inode); + if (need < 0) + return NFSERROR; + if (need_parent) { + delta = encode_inode_size(parent); + if (delta < 0) + return NFSERROR; + need += delta; + } + + ctx = init_context(dentry->d_inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + if (need <= sizeof(__u32) * (*lenp)) { + addr = encode_inode(inode, addr); + if (need_parent) + addr = encode_inode(parent, addr); + + /* store in lenp number of 32bit words required for file + * handle. */ + *lenp = (need + sizeof(__u32) - 1) >> 2; + result = need_parent ? FH_WITH_PARENT : FH_WITHOUT_PARENT; + } else + /* no enough space in file handle */ + result = NFSERROR; + reiser4_exit_context(ctx); + return result; +} + +/** + * reiser4_get_dentry_parent - get_parent of export operations + * @child: + * + */ +static struct dentry *reiser4_get_dentry_parent(struct dentry *child) +{ + struct inode *dir; + dir_plugin *dplug; + + assert("nikita-3527", child != NULL); + /* see comment in reiser4_get_dentry() about following assertion */ + assert("nikita-3528", is_in_reiser4_context()); + + dir = child->d_inode; + assert("nikita-3529", dir != NULL); + dplug = inode_dir_plugin(dir); + assert("nikita-3531", ergo(dplug != NULL, dplug->get_parent != NULL)); + if (dplug != NULL) + return dplug->get_parent(dir); + else + return ERR_PTR(RETERR(-ENOTDIR)); +} + +/** + * reiser4_get_dentry - get_dentry of export operations + * @super: + * @data: + * + * + */ +static struct dentry *reiser4_get_dentry(struct super_block *super, void *data) +{ + reiser4_object_on_wire *o; + + assert("nikita-3522", super != NULL); + assert("nikita-3523", data != NULL); + /* + * this is only supposed to be called by + * + * reiser4_decode_fh->find_exported_dentry + * + * so, reiser4_context should be here already. + */ + assert("nikita-3526", is_in_reiser4_context()); + + o = (reiser4_object_on_wire *)data; + assert("nikita-3524", o->plugin != NULL); + assert("nikita-3525", o->plugin->wire.get != NULL); + + return o->plugin->wire.get(super, o); +} + +struct export_operations reiser4_export_operations = { + .encode_fh = reiser4_encode_fh, + .decode_fh = reiser4_decode_fh, + .get_parent = reiser4_get_dentry_parent, + .get_dentry = reiser4_get_dentry +}; + +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 79 + * End: + */ diff -L fs/reiser4/file_ops.c -puN fs/reiser4/file_ops.c~reiser4-big-update /dev/null --- devel/fs/reiser4/file_ops.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,422 +0,0 @@ -/* Copyright 2003 by Hans Reiser, licensing governed by reiser4/README */ - -/* - * Interface to VFS. Reiser4 file_operations are defined here. - * - * This file contains definitions of functions that are installed into ->i_fop - * field of reiser4 inodes. - * - * By the most part these functions simply find object plugin of inode - * involved, and call appropriate plugin method to do the actual work. - */ - -#include "forward.h" -#include "debug.h" -#include "dformat.h" -#include "coord.h" -#include "plugin/item/item.h" -#include "plugin/file/file.h" -#include "plugin/security/perm.h" -#include "plugin/disk_format/disk_format.h" -#include "plugin/plugin.h" -#include "plugin/plugin_set.h" -#include "plugin/object.h" -#include "txnmgr.h" -#include "jnode.h" -#include "znode.h" -#include "block_alloc.h" -#include "tree.h" -#include "vfs_ops.h" -#include "inode.h" -#include "page_cache.h" -#include "ktxnmgrd.h" -#include "super.h" -#include "reiser4.h" -#include "entd.h" -#include "emergency_flush.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* file operations */ - -static loff_t reiser4_llseek(struct file *, loff_t, int); -static ssize_t reiser4_read(struct file *, char *, size_t, loff_t *); -static ssize_t reiser4_write(struct file *, const char *, size_t, loff_t *); -static int reiser4_readdir(struct file *, void *, filldir_t); -static int reiser4_ioctl(struct inode *, struct file *, unsigned int cmd, unsigned long arg); -static int reiser4_mmap(struct file *, struct vm_area_struct *); -static int reiser4_release(struct inode *, struct file *); -static int reiser4_fsync(struct file *, struct dentry *, int datasync); -static int reiser4_open(struct inode *, struct file *); -static ssize_t reiser4_sendfile(struct file *, loff_t *, size_t, read_actor_t, void __user *); - -#if 0 -static unsigned int reiser4_poll(struct file *, struct poll_table_struct *); -static int reiser4_flush(struct file *); -static int reiser4_fasync(int, struct file *, int); -static int reiser4_lock(struct file *, int, struct file_lock *); -static ssize_t reiser4_readv(struct file *, const struct iovec *, unsigned long, loff_t *); -static ssize_t reiser4_writev(struct file *, const struct iovec *, unsigned long, loff_t *); -static ssize_t reiser4_sendpage(struct file *, struct page *, int, size_t, loff_t *, int); -static unsigned long reiser4_get_unmapped_area(struct file *, unsigned long, - unsigned long, unsigned long, unsigned long); -#endif - -/* - * ->llseek() file operation for reiser4. Calls ->seek() method of object - * plugin. - */ -static loff_t -reiser4_llseek(struct file *file, loff_t off, int origin) -{ - loff_t result; - file_plugin *fplug; - struct inode *inode = file->f_dentry->d_inode; - loff_t(*seek_fn) (struct file *, loff_t, int); - reiser4_context ctx; - - init_context(&ctx, inode->i_sb); - - fplug = inode_file_plugin(inode); - assert("nikita-2291", fplug != NULL); - seek_fn = fplug->seek ? : generic_file_llseek; - result = seek_fn(file, off, origin); - reiser4_exit_context(&ctx); - return result; -} - -/* reiser4_readdir() - our readdir() method. - - readdir(2)/getdents(2) interface is based on implicit assumption that - readdir can be restarted from any particular point by supplying file - system with off_t-full of data. That is, file system fill ->d_off - field in struct dirent and later user passes ->d_off to the - seekdir(3), which is, actually, implemented by glibc as lseek(2) on - directory. - - Reiser4 cannot restart readdir from 64 bits of data, because two last - components of the key of directory entry are unknown, which given 128 - bits: locality and type fields in the key of directory entry are - always known, to start readdir() from given point objectid and offset - fields have to be filled. - - See plugin/dir/dir.c:readdir_common() for the details of our solution. -*/ -static int -reiser4_readdir(struct file *f /* directory file being read */ , - void *dirent /* opaque data passed to us by VFS */ , - filldir_t filldir /* filler function passed to us - * by VFS */ ) -{ - dir_plugin *dplug; - int result; - struct inode *inode; - reiser4_context ctx; - - inode = f->f_dentry->d_inode; - init_context(&ctx, inode->i_sb); - - dplug = inode_dir_plugin(inode); - if ((dplug != NULL) && (dplug->readdir != NULL)) - result = dplug->readdir(f, dirent, filldir); - else - result = RETERR(-ENOTDIR); - - /* - * directory st_atime is updated by callers (if necessary). - */ - context_set_commit_async(&ctx); - reiser4_exit_context(&ctx); - return result; -} - -/* - reiser4_ioctl - handler for ioctl for inode supported commands: -*/ -static int -reiser4_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) -{ - int result; - reiser4_context ctx; - - init_context(&ctx, inode->i_sb); - - if (inode_file_plugin(inode)->ioctl == NULL) - result = -ENOSYS; - else - result = inode_file_plugin(inode)->ioctl(inode, filp, cmd, arg); - - reiser4_exit_context(&ctx); - return result; -} - -/* ->mmap() VFS method in reiser4 file_operations */ -static int -reiser4_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct inode *inode; - int result; - reiser4_context ctx; - - init_context(&ctx, file->f_dentry->d_inode->i_sb); - - inode = file->f_dentry->d_inode; - assert("nikita-2936", inode_file_plugin(inode)->mmap != NULL); - result = inode_file_plugin(inode)->mmap(file, vma); - reiser4_exit_context(&ctx); - return result; -} - -/* reiser4 implementation of ->read() VFS method, member of reiser4 struct file_operations - - reads some part of a file from the filesystem into the user space buffer - - gets the plugin for the file and calls its read method which does everything except some initialization - -*/ -static ssize_t -reiser4_read(struct file *file /* file to read from */ , - char *buf /* user-space buffer to put data read - * from the file */ , - size_t count /* bytes to read */ , - loff_t * off /* current position within the file, which needs to be increased by the act of reading. Reads - * start from here. */ ) -{ - ssize_t result; - struct inode *inode; - reiser4_context ctx; - - assert("umka-072", file != NULL); - assert("umka-074", off != NULL); - - inode = file->f_dentry->d_inode; - init_context(&ctx, inode->i_sb); - - result = perm_chk(inode, read, file, buf, count, off); - if (likely(result == 0)) { - file_plugin *fplug; - - fplug = inode_file_plugin(inode); - assert("nikita-417", fplug != NULL); - assert("nikita-2935", fplug->write != NULL); - - /* unix_file_read is one method that might be invoked below */ - result = fplug->read(file, buf, count, off); - } - context_set_commit_async(&ctx); - reiser4_exit_context(&ctx); - return result; -} - -/* ->write() VFS method in reiser4 file_operations */ -static ssize_t -reiser4_write(struct file *file /* file to write on */ , - const char *buf /* user-space buffer to get data - * to write into the file */ , - size_t size /* bytes to write */ , - loff_t * off /* offset to start writing - * from. This is updated to indicate - * actual number of bytes written */ ) -{ - struct inode *inode; - ssize_t result; - reiser4_context ctx; - - assert("nikita-1421", file != NULL); - assert("nikita-1424", off != NULL); - - inode = file->f_dentry->d_inode; - init_context(&ctx, inode->i_sb); - - result = perm_chk(inode, write, file, buf, size, off); - if (likely(result == 0)) { - file_plugin *fplug; - - fplug = inode_file_plugin(inode); - assert("nikita-2934", fplug->read != NULL); - - result = fplug->write(file, buf, size, off); - } - context_set_commit_async(&ctx); - reiser4_exit_context(&ctx); - return result; -} - -/* Release reiser4 file. This is f_op->release() method. Called when last - holder closes a file */ -static int -reiser4_release(struct inode *i /* inode released */ , - struct file *f /* file released */ ) -{ - file_plugin *fplug; - int result; - reiser4_context ctx; - - assert("umka-081", i != NULL); - assert("nikita-1447", f != NULL); - - init_context(&ctx, i->i_sb); - fplug = inode_file_plugin(i); - assert("umka-082", fplug != NULL); - - - if (fplug->release != NULL && get_current_context() == &ctx) - result = fplug->release(i, f); - else - /* - no ->release method defined, or we are within reiser4 - context already. How latter is possible? Simple: - - (gdb) bt - #0 get_exclusive_access () - #2 0xc01e56d3 in release_unix_file () - #3 0xc01c3643 in reiser4_release () - #4 0xc014cae0 in __fput () - #5 0xc013ffc3 in remove_vm_struct () - #6 0xc0141786 in exit_mmap () - #7 0xc0118480 in mmput () - #8 0xc0133205 in oom_kill () - #9 0xc01332d1 in out_of_memory () - #10 0xc013bc1d in try_to_free_pages () - #11 0xc013427b in __alloc_pages () - #12 0xc013f058 in do_anonymous_page () - #13 0xc013f19d in do_no_page () - #14 0xc013f60e in handle_mm_fault () - #15 0xc01131e5 in do_page_fault () - #16 0xc0104935 in error_code () - #17 0xc025c0c6 in __copy_to_user_ll () - #18 0xc01d496f in read_tail () - #19 0xc01e4def in read_unix_file () - #20 0xc01c3504 in reiser4_read () - #21 0xc014bd4f in vfs_read () - #22 0xc014bf66 in sys_read () - */ - result = 0; - - reiser4_free_file_fsdata(f); - - reiser4_exit_context(&ctx); - return result; -} - -/* - * ->open file operation for reiser4. This is optional method. It's only - * present for mounts that support pseudo files. When "nopseudo" mount option - * is used, this method is zeroed, which speeds open(2) system call a bit. - */ -static int -reiser4_open(struct inode * inode, struct file * file) -{ - int result; - - reiser4_context ctx; - file_plugin *fplug; - - init_context(&ctx, inode->i_sb); - fplug = inode_file_plugin(inode); - - if (fplug->open != NULL) - result = fplug->open(inode, file); - else - result = 0; - - reiser4_exit_context(&ctx); - return result; -} - -/* ->fsync file operation for reiser4. */ -static int -reiser4_fsync(struct file *file, struct dentry *dentry, int datasync) -{ - int result; - reiser4_context ctx; - file_plugin *fplug; - struct inode *inode; - - inode = dentry->d_inode; - init_context(&ctx, inode->i_sb); - fplug = inode_file_plugin(inode); - if (fplug->sync != NULL) - result = fplug->sync(inode, datasync); - else - result = 0; - context_set_commit_async(&ctx); - reiser4_exit_context(&ctx); - return result; -} - -/* Reads @count bytes from @file and calls @actor for every read page. This is - needed for loop back devices support. */ -static ssize_t reiser4_sendfile(struct file *file, loff_t *ppos, - size_t count, read_actor_t actor, - void __user *target) -{ - int result; - file_plugin *fplug; - reiser4_context ctx; - struct inode *inode; - - inode = file->f_dentry->d_inode; - init_context(&ctx, inode->i_sb); - - fplug = inode_file_plugin(inode); - - if (fplug->sendfile != NULL) - result = fplug->sendfile(file, ppos, count, actor, target); - else - result = RETERR(-EINVAL); - - reiser4_exit_context(&ctx); - return result; -} - - -struct file_operations reiser4_file_operations = { - .llseek = reiser4_llseek, /* d */ - .read = reiser4_read, /* d */ - .write = reiser4_write, /* d */ - .readdir = reiser4_readdir, /* d */ -/* .poll = reiser4_poll, */ - .ioctl = reiser4_ioctl, - .mmap = reiser4_mmap, /* d */ - .open = reiser4_open, -/* .flush = reiser4_flush, */ - .release = reiser4_release, /* d */ - .fsync = reiser4_fsync /* d */, - .sendfile = reiser4_sendfile, -/* .fasync = reiser4_fasync, */ -/* .lock = reiser4_lock, */ -/* .readv = reiser4_readv, */ -/* .writev = reiser4_writev, */ -/* .sendpage = reiser4_sendpage, */ -/* .get_unmapped_area = reiser4_get_unmapped_area */ -}; - - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - End: -*/ diff -puN fs/reiser4/flush.c~reiser4-big-update fs/reiser4/flush.c --- devel/fs/reiser4/flush.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/flush.c 2005-09-15 19:51:08.000000000 -0700 @@ -7,7 +7,6 @@ #include "dformat.h" #include "key.h" #include "coord.h" -#include "type_safe_list.h" #include "plugin/item/item.h" #include "plugin/plugin.h" #include "plugin/object.h" @@ -373,7 +372,8 @@ static void scan_init(flush_scan * scan) static void scan_done(flush_scan * scan); /* Flush-scan algorithm. */ -static int scan_left(flush_scan * scan, flush_scan * right, jnode * node, unsigned limit); +static int scan_left(flush_scan * scan, flush_scan * right, jnode * node, + unsigned limit); static int scan_right(flush_scan * scan, jnode * node, unsigned limit); static int scan_common(flush_scan * scan, flush_scan * other); static int scan_formatted(flush_scan * scan); @@ -393,26 +393,32 @@ static int squeeze_right_non_twig(znode static int shift_one_internal_unit(znode * left, znode * right); /* Flush reverse parent-first relocation routines. */ -static int reverse_relocate_if_close_enough(const reiser4_block_nr * pblk, const reiser4_block_nr * nblk); -static int reverse_relocate_test(jnode * node, const coord_t * parent_coord, flush_pos_t * pos); -static int reverse_relocate_check_dirty_parent(jnode * node, const coord_t * parent_coord, flush_pos_t * pos); +static int reverse_relocate_if_close_enough(const reiser4_block_nr * pblk, + const reiser4_block_nr * nblk); +static int reverse_relocate_test(jnode * node, const coord_t * parent_coord, + flush_pos_t * pos); +static int reverse_relocate_check_dirty_parent(jnode * node, + const coord_t * parent_coord, + flush_pos_t * pos); /* Flush allocate write-queueing functions: */ -static int allocate_znode(znode * node, const coord_t * parent_coord, flush_pos_t * pos); -static int allocate_znode_update(znode * node, const coord_t * parent_coord, flush_pos_t * pos); -static int lock_parent_and_allocate_znode (znode *, flush_pos_t *); +static int allocate_znode(znode * node, const coord_t * parent_coord, + flush_pos_t * pos); +static int allocate_znode_update(znode * node, const coord_t * parent_coord, + flush_pos_t * pos); +static int lock_parent_and_allocate_znode(znode *, flush_pos_t *); /* Flush helper functions: */ -static int jnode_lock_parent_coord(jnode * node, - coord_t * coord, - lock_handle * parent_lh, - load_count * parent_zh, +static int jnode_lock_parent_coord(jnode * node, + coord_t * coord, + lock_handle * parent_lh, + load_count * parent_zh, znode_lock_mode mode, int try); -static int neighbor_in_slum(znode * node, lock_handle * right_lock, sideof side, znode_lock_mode mode, int check_dirty); +static int neighbor_in_slum(znode * node, lock_handle * right_lock, sideof side, + znode_lock_mode mode, int check_dirty); static int znode_same_parents(znode * a, znode * b); -static int -znode_check_flushprepped(znode * node) +static int znode_check_flushprepped(znode * node) { return jnode_check_flushprepped(ZJNODE(node)); } @@ -433,26 +439,25 @@ assert("nikita-3435", \ extent_is_unallocated(&scan->parent_coord), \ extent_unit_index(&scan->parent_coord) == index_jnode(scan->node))) - /* This flush_cnt variable is used to track the number of concurrent flush operations, useful for debugging. It is initialized in txnmgr.c out of laziness (because flush has no static initializer function...) */ -ON_DEBUG(atomic_t flush_cnt;) - +ON_DEBUG(atomic_t flush_cnt; + ) /* check fs backing device for write congestion */ -static int check_write_congestion (void) +static int check_write_congestion(void) { struct super_block *sb; - struct backing_dev_info * bdi; + struct backing_dev_info *bdi; sb = reiser4_get_current_sb(); bdi = get_super_fake(sb)->i_mapping->backing_dev_info; - return bdi_write_congested(bdi); + return bdi_write_congested(bdi); } /* conditionally write flush queue */ -static int write_prepped_nodes (flush_pos_t * pos) +static int write_prepped_nodes(flush_pos_t * pos) { int ret; @@ -472,13 +477,13 @@ static int write_prepped_nodes (flush_po /* Proper release all flush pos. resources then move flush position to new locked node */ -static void move_flush_pos (flush_pos_t * pos, lock_handle * new_lock, - load_count * new_load, const coord_t * new_coord) +static void move_flush_pos(flush_pos_t * pos, lock_handle * new_lock, + load_count * new_load, const coord_t * new_coord) { - assert ("zam-857", new_lock->node == new_load->node); + assert("zam-857", new_lock->node == new_load->node); if (new_coord) { - assert ("zam-858", new_coord->node == new_lock->node); + assert("zam-858", new_coord->node == new_lock->node); coord_dup(&pos->coord, new_coord); } else { coord_init_first_unit(&pos->coord, new_lock->node); @@ -495,7 +500,7 @@ static void move_flush_pos (flush_pos_t } /* delete empty node which link from the parent still exists. */ -static int delete_empty_node (znode * node) +static int delete_empty_node(znode * node) { reiser4_key smallest_removed; @@ -507,7 +512,7 @@ static int delete_empty_node (znode * no } /* Prepare flush position for alloc_pos_and_ancestors() and squalloc() */ -static int prepare_flush_pos(flush_pos_t *pos, jnode * org) +static int prepare_flush_pos(flush_pos_t * pos, jnode * org) { int ret; load_count load; @@ -526,7 +531,9 @@ static int prepare_flush_pos(flush_pos_t if (ret) return ret; - pos->state = (jnode_get_level(org) == LEAF_LEVEL) ? POS_ON_LEAF : POS_ON_INTERNAL; + pos->state = + (jnode_get_level(org) == + LEAF_LEVEL) ? POS_ON_LEAF : POS_ON_INTERNAL; move_flush_pos(pos, &lock, &load, NULL); } else { coord_t parent_coord; @@ -534,11 +541,18 @@ static int prepare_flush_pos(flush_pos_t &load, ZNODE_WRITE_LOCK, 0); if (ret) goto done; + if (!item_is_extent(&parent_coord)) { + /* file was converted to tail, org became HB, we found internal + item */ + ret = -EAGAIN; + goto done; + } pos->state = POS_ON_EPOINT; move_flush_pos(pos, &lock, &load, &parent_coord); pos->child = jref(org); - if (extent_is_unallocated(&parent_coord) && extent_unit_index(&parent_coord) != index_jnode(org)) { + if (extent_is_unallocated(&parent_coord) + && extent_unit_index(&parent_coord) != index_jnode(org)) { /* @org is not first child of its parent unit. This may happen because longerm lock of its parent node was released between scan_left and scan_right. For now work around this having flush to repeat */ @@ -546,7 +560,7 @@ static int prepare_flush_pos(flush_pos_t } } - done: + done: done_load_count(&load); done_lh(&lock); return ret; @@ -632,16 +646,17 @@ static int prepare_flush_pos(flush_pos_t */ static int -jnode_flush(jnode *node, long *nr_written, flush_queue_t *fq, int flags) +jnode_flush(jnode * node, long nr_to_write, long *nr_written, + flush_queue_t * fq, int flags) { long ret = 0; - flush_scan right_scan; - flush_scan left_scan; - flush_pos_t flush_pos; + flush_scan *right_scan; + flush_scan *left_scan; + flush_pos_t *flush_pos; int todo; struct super_block *sb; reiser4_super_info_data *sbinfo; - jnode * leftmost_in_slum = NULL; + jnode *leftmost_in_slum = NULL; assert("jmacd-76619", lock_stack_isclean(get_current_lock_stack())); assert("nikita-3022", schedulable()); @@ -650,6 +665,14 @@ jnode_flush(jnode *node, long *nr_writte assert("nikita-3185", get_current_super_private()->delete_sema_owner != current); + /* allocate right_scan, left_scan and flush_pos */ + right_scan = + kmalloc(2 * sizeof(*right_scan) + sizeof(*flush_pos), GFP_KERNEL); + if (right_scan == NULL) + return RETERR(-ENOMEM); + left_scan = right_scan + 1; + flush_pos = (flush_pos_t *) (left_scan + 1); + sb = reiser4_get_current_sb(); sbinfo = get_super_private(sb); if (!reiser4_is_set(sb, REISER4_MTFLUSH)) { @@ -664,17 +687,15 @@ jnode_flush(jnode *node, long *nr_writte enter_flush(sb); /* Initialize a flush position. */ - pos_init(&flush_pos); - - flush_pos.nr_written = nr_written; - flush_pos.fq = fq; - flush_pos.flags = flags; + pos_init(flush_pos); - scan_init(&right_scan); - scan_init(&left_scan); + flush_pos->nr_written = nr_written; + flush_pos->fq = fq; + flush_pos->flags = flags; + flush_pos->nr_to_write = nr_to_write; - /*IF_TRACE (TRACE_FLUSH_VERB, print_tree_rec ("parent_first", current_tree, REISER4_TREE_BRIEF)); */ - /*IF_TRACE (TRACE_FLUSH_VERB, print_tree_rec ("parent_first", current_tree, REISER4_TREE_CHECK)); */ + scan_init(right_scan); + scan_init(left_scan); /* First scan left and remember the leftmost scan position. If the leftmost position is unformatted we remember its parent_coord. We scan until counting @@ -687,14 +708,14 @@ jnode_flush(jnode *node, long *nr_writte scan without redoing the tree traversal (necessary to find parent) and, hence, is kept during leftward scan. As a result, we have to use try-lock when taking long term locks during the leftward scan. - */ - ret = scan_left(&left_scan, &right_scan, + */ + ret = scan_left(left_scan, right_scan, node, sbinfo->flush.scan_maxnodes); if (ret != 0) goto failed; - leftmost_in_slum = jref(left_scan.node); - scan_done(&left_scan); + leftmost_in_slum = jref(left_scan->node); + scan_done(left_scan); /* Then possibly go right to decide if we will use a policy of relocating leaves. This is only done if we did not scan past (and count) enough nodes during the @@ -702,23 +723,24 @@ jnode_flush(jnode *node, long *nr_writte that at least FLUSH_RELOCATE_THRESHOLD number of nodes are being flushed. The scan limit is the difference between left_scan.count and the threshold. */ - todo = sbinfo->flush.relocate_threshold - left_scan.count; + todo = sbinfo->flush.relocate_threshold - left_scan->count; /* scan right is inherently deadlock prone, because we are * (potentially) holding a lock on the twig node at this moment. * FIXME: this is incorrect comment: lock is not held */ if (todo > 0) { - ret = scan_right(&right_scan, node, (unsigned)todo); + ret = scan_right(right_scan, node, (unsigned)todo); if (ret != 0) goto failed; } /* Only the right-scan count is needed, release any rightward locks right away. */ - scan_done(&right_scan); + scan_done(right_scan); /* ... and the answer is: we should relocate leaf nodes if at least FLUSH_RELOCATE_THRESHOLD nodes were found. */ - flush_pos.leaf_relocate = JF_ISSET(node, JNODE_REPACK) || - (left_scan.count + right_scan.count >= sbinfo->flush.relocate_threshold); + flush_pos->leaf_relocate = JF_ISSET(node, JNODE_REPACK) || + (left_scan->count + right_scan->count >= + sbinfo->flush.relocate_threshold); /* Funny business here. We set the 'point' in the flush_position at prior to starting squalloc regardless of whether the first point is @@ -744,38 +766,40 @@ jnode_flush(jnode *node, long *nr_writte /* Check jnode state after flush_scan completed. Having a lock on this node or its parent (in case of unformatted) helps us in case of concurrent flushing. */ - if (jnode_check_flushprepped(leftmost_in_slum) && !jnode_convertible(leftmost_in_slum)) { + if (jnode_check_flushprepped(leftmost_in_slum) + && !jnode_convertible(leftmost_in_slum)) { ret = 0; goto failed; } /* Now setup flush_pos using scan_left's endpoint. */ - ret = prepare_flush_pos(&flush_pos, leftmost_in_slum); + ret = prepare_flush_pos(flush_pos, leftmost_in_slum); if (ret) goto failed; - if (znode_get_level(flush_pos.coord.node) == LEAF_LEVEL - && node_is_empty(flush_pos.coord.node)) { - znode * empty = flush_pos.coord.node; + if (znode_get_level(flush_pos->coord.node) == LEAF_LEVEL + && node_is_empty(flush_pos->coord.node)) { + znode *empty = flush_pos->coord.node; - assert ("zam-1022", !ZF_ISSET(empty, JNODE_HEARD_BANSHEE)); + assert("zam-1022", !ZF_ISSET(empty, JNODE_HEARD_BANSHEE)); ret = delete_empty_node(empty); goto failed; } - if (jnode_check_flushprepped(leftmost_in_slum) && !jnode_convertible(leftmost_in_slum)) { + if (jnode_check_flushprepped(leftmost_in_slum) + && !jnode_convertible(leftmost_in_slum)) { ret = 0; goto failed; } /* Set pos->preceder and (re)allocate pos and its ancestors if it is needed */ - ret = alloc_pos_and_ancestors(&flush_pos); + ret = alloc_pos_and_ancestors(flush_pos); if (ret) goto failed; /* Do the main rightward-bottom-up squeeze and allocate loop. */ - ret = squalloc(&flush_pos); - pos_stop(&flush_pos); + ret = squalloc(flush_pos); + pos_stop(flush_pos); if (ret) goto failed; @@ -813,7 +837,7 @@ jnode_flush(jnode *node, long *nr_writte starting point. That should be stored away in the flush_handle using a seal, I believe. Holding a jref() on the future starting point may break other code that deletes that node. - */ + */ /* FIXME_NFQUCMPD: Also, we don't want to do any flushing when flush is called above the twig level. If the VM calls flush above the twig level, do nothing @@ -824,17 +848,17 @@ jnode_flush(jnode *node, long *nr_writte level, the remaining unallocated nodes should be given write-optimized locations. (Possibly, the remaining unallocated twigs should be allocated just before their leftmost child.) - */ + */ /* Any failure reaches this point. */ -failed: + failed: switch (ret) { - case -E_REPEAT: - case -EINVAL: - case -E_DEADLOCK: - case -E_NO_NEIGHBOR: - case -ENOENT: + case -E_REPEAT: + case -EINVAL: + case -E_DEADLOCK: + case -E_NO_NEIGHBOR: + case -ENOENT: /* FIXME(C): Except for E_DEADLOCK, these should probably be handled properly in each case. They already are handled in many cases. */ /* Something bad happened, but difficult to avoid... Try again! */ @@ -844,9 +868,10 @@ failed: if (leftmost_in_slum) jput(leftmost_in_slum); - pos_done(&flush_pos); - scan_done(&left_scan); - scan_done(&right_scan); + pos_done(flush_pos); + scan_done(left_scan); + scan_done(right_scan); + kfree(right_scan); ON_DEBUG(atomic_dec(&flush_cnt)); @@ -870,7 +895,7 @@ failed: * turn rapid flush mode off. */ -static int rapid_flush (flush_pos_t * pos) +static int rapid_flush(flush_pos_t * pos) { if (!wbq_available()) return 0; @@ -882,34 +907,99 @@ static int rapid_flush (flush_pos_t * po #define rapid_flush(pos) (0) -#endif /* REISER4_USE_RAPID_FLUSH */ +#endif /* REISER4_USE_RAPID_FLUSH */ + +static jnode * find_flush_start_jnode( + jnode * start, + txn_atom * atom, + flush_queue_t * fq, + int *nr_queued, + int flags) +{ + jnode * node; + + if (start != NULL) { + LOCK_JNODE(start); + if (jnode_is_dirty(start) && !JF_ISSET(start, JNODE_OVRWR)) { + assert("zam-1056", start->atom == atom); + node = start; + goto enter; + } + UNLOCK_JNODE(start); + } + /* + * In this loop we process all already prepped (RELOC or OVRWR) and dirtied again + * nodes. The atom spin lock is not released until all dirty nodes processed or + * not prepped node found in the atom dirty lists. + */ + while ((node = find_first_dirty_jnode(atom, flags))) { + LOCK_JNODE(node); + enter: + assert("zam-881", jnode_is_dirty(node)); + assert("zam-898", !JF_ISSET(node, JNODE_OVRWR)); + + if (JF_ISSET(node, JNODE_WRITEBACK)) { + /* move node to the end of atom's writeback list */ + list_del_init(&node->capture_link); + list_add_tail(&node->capture_link, ATOM_WB_LIST(atom)); + + ON_DEBUG(count_jnode(atom, node, DIRTY_LIST, + WB_LIST, 1)); + + } else if (jnode_is_znode(node) + && znode_above_root(JZNODE(node))) { + /* + * A special case for znode-above-root. The above-root (fake) + * znode is captured and dirtied when the tree height changes or + * when the root node is relocated. This causes atoms to fuse so + * that changes at the root are serialized. However, this node is + * never flushed. This special case used to be in lock.c to + * prevent the above-root node from ever being captured, but now + * that it is captured we simply prevent it from flushing. The + * log-writer code relies on this to properly log superblock + * modifications of the tree height. + */ + jnode_make_wander_nolock(node); + } else if (JF_ISSET(node, JNODE_RELOC)) { + queue_jnode(fq, node); + ++(*nr_queued); + } else + break; + + UNLOCK_JNODE(node); + } + return node; +} + /* Flush some nodes of current atom, usually slum, return -E_REPEAT if there are more nodes * to flush, return 0 if atom's dirty lists empty and keep current atom locked, return * other errors as they are. */ -reiser4_internal int -flush_current_atom (int flags, long *nr_submitted, txn_atom ** atom) +int +flush_current_atom(int flags, long nr_to_write, long *nr_submitted, + txn_atom ** atom, jnode *start) { - reiser4_super_info_data * sinfo = get_current_super_private(); + reiser4_super_info_data *sinfo = get_current_super_private(); flush_queue_t *fq = NULL; - jnode * node; + jnode *node; int nr_queued; int ret; - assert ("zam-889", atom != NULL && *atom != NULL); - assert ("zam-890", spin_atom_is_locked(*atom)); - assert ("zam-892", get_current_context()->trans->atom == *atom); + assert("zam-889", atom != NULL && *atom != NULL); + assert("zam-890", spin_atom_is_locked(*atom)); + assert("zam-892", get_current_context()->trans->atom == *atom); - while(1) { + nr_to_write = LONG_MAX; + while (1) { ret = fq_by_atom(*atom, &fq); if (ret != -E_REPEAT) break; *atom = get_current_atom_locked(); } - if (ret) + if (ret) return ret; - assert ("zam-891", spin_atom_is_locked(*atom)); + assert("zam-891", spin_atom_is_locked(*atom)); /* parallel flushers limit */ if (sinfo->tmgr.atom_max_flushers != 0) { @@ -928,63 +1018,34 @@ flush_current_atom (int flags, long *nr_ writeout_mode_enable(); nr_queued = 0; - - /* In this loop we process all already prepped (RELOC or OVRWR) and dirtied again - * nodes. The atom spin lock is not released until all dirty nodes processed or - * not prepped node found in the atom dirty lists. */ - while ((node = find_first_dirty_jnode(*atom, flags))) { - LOCK_JNODE(node); - - assert ("zam-881", jnode_is_dirty(node)); - assert ("zam-898", !JF_ISSET(node, JNODE_OVRWR)); - - if (JF_ISSET(node, JNODE_WRITEBACK)) { - capture_list_remove_clean(node); - capture_list_push_back(ATOM_WB_LIST(*atom), node); - /*XXXX*/ON_DEBUG(count_jnode(*atom, node, DIRTY_LIST, WB_LIST, 1)); - - } else if (jnode_is_znode(node) && znode_above_root(JZNODE(node))) { - /* A special case for znode-above-root. The above-root (fake) - znode is captured and dirtied when the tree height changes or - when the root node is relocated. This causes atoms to fuse so - that changes at the root are serialized. However, this node is - never flushed. This special case used to be in lock.c to - prevent the above-root node from ever being captured, but now - that it is captured we simply prevent it from flushing. The - log-writer code relies on this to properly log superblock - modifications of the tree height. */ - jnode_make_wander_nolock(node); - } else if (JF_ISSET(node, JNODE_RELOC)) { - queue_jnode(fq, node); - ++ nr_queued; - } else - break; - - UNLOCK_JNODE(node); - } + node = find_flush_start_jnode(start, *atom, fq, &nr_queued, flags); if (node == NULL) { if (nr_queued == 0) { - writeout_mode_disable(); - (*atom)->nr_flushers --; - atom_send_event(*atom); + (*atom)->nr_flushers--; fq_put_nolock(fq); + atom_send_event(*atom); /* current atom remains locked */ + writeout_mode_disable(); return 0; } UNLOCK_ATOM(*atom); } else { jref(node); + BUG_ON((*atom)->super != node->tree->super); UNLOCK_ATOM(*atom); UNLOCK_JNODE(node); - ret = jnode_flush(node, nr_submitted, fq, flags); + BUG_ON(nr_to_write == 0); + ret = jnode_flush(node, nr_to_write, nr_submitted, fq, flags); jput(node); } - ret = write_fq(fq, nr_submitted, WRITEOUT_SINGLE_STREAM | WRITEOUT_FOR_PAGE_RECLAIM); + ret = + write_fq(fq, nr_submitted, + WRITEOUT_SINGLE_STREAM | WRITEOUT_FOR_PAGE_RECLAIM); *atom = get_current_atom_locked(); - (*atom)->nr_flushers --; + (*atom)->nr_flushers--; fq_put_nolock(fq); atom_send_event(*atom); UNLOCK_ATOM(*atom); @@ -1006,7 +1067,8 @@ flush_current_atom (int flags, long *nr_ In the _forward_ parent-first relocate context (not here) we actually call the block allocator to try and find a closer location. */ static int -reverse_relocate_if_close_enough(const reiser4_block_nr * pblk, const reiser4_block_nr * nblk) +reverse_relocate_if_close_enough(const reiser4_block_nr * pblk, + const reiser4_block_nr * nblk) { reiser4_block_nr dist; @@ -1033,7 +1095,8 @@ reverse_relocate_if_close_enough(const r (not here), relocation decisions are handled in two places: allocate_znode() and extent_needs_allocation(). */ static int -reverse_relocate_test(jnode * node, const coord_t * parent_coord, flush_pos_t * pos) +reverse_relocate_test(jnode * node, const coord_t * parent_coord, + flush_pos_t * pos) { reiser4_block_nr pblk = 0; reiser4_block_nr nblk = 0; @@ -1083,7 +1146,8 @@ reverse_relocate_test(jnode * node, cons /* This function calls reverse_relocate_test to make a reverse-parent-first relocation decision and then, if yes, it marks the parent dirty. */ static int -reverse_relocate_check_dirty_parent(jnode * node, const coord_t * parent_coord, flush_pos_t * pos) +reverse_relocate_check_dirty_parent(jnode * node, const coord_t * parent_coord, + flush_pos_t * pos) { int ret; @@ -1100,11 +1164,13 @@ reverse_relocate_check_dirty_parent(jnod int grabbed; grabbed = get_current_context()->grabbed_blocks; - if (reiser4_grab_space_force((__u64)1, BA_RESERVED) != 0) - reiser4_panic("umka-1250", - "No space left during flush."); + if (reiser4_grab_space_force((__u64) 1, BA_RESERVED) != + 0) + reiser4_panic("umka-1250", + "No space left during flush."); - assert("jmacd-18923", znode_is_write_locked(parent_coord->node)); + assert("jmacd-18923", + znode_is_write_locked(parent_coord->node)); znode_make_dirty(parent_coord->node); grabbed2free_mark(grabbed); } @@ -1117,7 +1183,7 @@ reverse_relocate_check_dirty_parent(jnod PARENT-FIRST LOOP BEGINS) */ /* Get the leftmost child for given coord. */ -static int get_leftmost_child_of_unit (const coord_t * coord, jnode ** child) +static int get_leftmost_child_of_unit(const coord_t * coord, jnode ** child) { int ret; @@ -1161,7 +1227,9 @@ static int alloc_pos_and_ancestors(flush /* The parent may not be dirty, in which case we should decide whether to relocate the child now. If decision is made to relocate the child, the parent is marked dirty. */ - ret = reverse_relocate_check_dirty_parent(pos->child, &pos->coord, pos); + ret = + reverse_relocate_check_dirty_parent(pos->child, &pos->coord, + pos); if (ret) goto exit; @@ -1177,7 +1245,9 @@ static int alloc_pos_and_ancestors(flush } else { if (!znode_is_root(pos->lock.node)) { /* all formatted nodes except tree root */ - ret = reiser4_get_parent(&plock, pos->lock.node, ZNODE_WRITE_LOCK); + ret = + reiser4_get_parent(&plock, pos->lock.node, + ZNODE_WRITE_LOCK); if (ret) goto exit; @@ -1185,11 +1255,16 @@ static int alloc_pos_and_ancestors(flush if (ret) goto exit; - ret = find_child_ptr(plock.node, pos->lock.node, &pcoord); + ret = + find_child_ptr(plock.node, pos->lock.node, &pcoord); if (ret) goto exit; - ret = reverse_relocate_check_dirty_parent(ZJNODE(pos->lock.node), &pcoord, pos); + ret = + reverse_relocate_check_dirty_parent(ZJNODE + (pos->lock. + node), &pcoord, + pos); if (ret) goto exit; @@ -1200,7 +1275,7 @@ static int alloc_pos_and_ancestors(flush ret = allocate_znode(pos->lock.node, &pcoord, pos); } -exit: + exit: done_load_count(&pload); done_lh(&plock); return ret; @@ -1229,7 +1304,8 @@ static int alloc_one_ancestor(const coor /* If the ancestor is clean or already allocated, or if the child is not a leftmost child, stop going up, even leaving coord->node not flushprepped. */ - if (znode_check_flushprepped(coord->node)|| !coord_is_leftmost_unit(coord)) + if (znode_check_flushprepped(coord->node) + || !coord_is_leftmost_unit(coord)) return 0; init_lh(&alock); @@ -1240,14 +1316,18 @@ static int alloc_one_ancestor(const coor parent in case we will relocate the child. */ if (!znode_is_root(coord->node)) { - ret = jnode_lock_parent_coord( - ZJNODE(coord->node), &acoord, &alock, &aload, ZNODE_WRITE_LOCK, 0); + ret = + jnode_lock_parent_coord(ZJNODE(coord->node), &acoord, + &alock, &aload, ZNODE_WRITE_LOCK, + 0); if (ret != 0) { /* FIXME(C): check EINVAL, E_DEADLOCK */ goto exit; } - ret = reverse_relocate_check_dirty_parent(ZJNODE(coord->node), &acoord, pos); + ret = + reverse_relocate_check_dirty_parent(ZJNODE(coord->node), + &acoord, pos); if (ret != 0) { goto exit; } @@ -1265,7 +1345,7 @@ static int alloc_one_ancestor(const coor call. */ ret = allocate_znode(coord->node, &acoord, pos); -exit: + exit: done_load_count(&aload); done_lh(&alock); return ret; @@ -1285,23 +1365,12 @@ exit: There is one other place where we may set the flush_position's preceder hint, which is during scan-left. */ -static int -set_preceder(const coord_t * coord_in, flush_pos_t * pos) +static int set_preceder(const coord_t * coord_in, flush_pos_t * pos) { int ret; coord_t coord; lock_handle left_lock; - load_count left_load; - -#if 0 - /* do not trust to allocation of nodes above twigs, use the block number of last - * write (write optimized approach). */ - if (znode_get_level(coord_in->node) > TWIG_LEVEL + 1) { - get_blocknr_hint_default(&pos->preceder.blk); - reiser4_stat_inc(block_alloc.nohint); - return 0; - } -#endif + load_count left_load; coord_dup(&coord, coord_in); @@ -1314,14 +1383,16 @@ set_preceder(const coord_t * coord_in, f if (!coord_is_leftmost_unit(&coord)) { coord_prev_unit(&coord); } else { - ret = reiser4_get_left_neighbor(&left_lock, coord.node, ZNODE_READ_LOCK, GN_SAME_ATOM); + ret = + reiser4_get_left_neighbor(&left_lock, coord.node, + ZNODE_READ_LOCK, GN_SAME_ATOM); if (ret) { /* If we fail for any reason it doesn't matter because the preceder is only a hint. We are low-priority at this point, so this must be the case. */ if (ret == -E_REPEAT || ret == -E_NO_NEIGHBOR || - ret == -ENOENT || ret == -EINVAL || ret == -E_DEADLOCK) - { + ret == -ENOENT || ret == -EINVAL + || ret == -E_DEADLOCK) { ret = 0; } goto exit; @@ -1334,8 +1405,10 @@ set_preceder(const coord_t * coord_in, f coord_init_last_unit(&coord, left_lock.node); } - ret = item_utmost_child_real_block(&coord, RIGHT_SIDE, &pos->preceder.blk); -exit: + ret = + item_utmost_child_real_block(&coord, RIGHT_SIDE, + &pos->preceder.blk); + exit: check_preceder(pos->preceder.blk); done_load_count(&left_load); done_lh(&left_lock); @@ -1376,10 +1449,10 @@ exit: /* SQUEEZE CODE */ - /* squalloc_right_twig helper function, cut a range of extent items from cut node to->node from the beginning up to coord @to. */ -static int squalloc_right_twig_cut(coord_t * to, reiser4_key * to_key, znode * left) +static int squalloc_right_twig_cut(coord_t * to, reiser4_key * to_key, + znode * left) { coord_t from; reiser4_key from_key; @@ -1395,11 +1468,6 @@ static int squalloc_right_twig_cut(coord SQUEEZE_SOURCE_EMPTY when no more can be shifted. If the next item is an internal item it calls shift_one_internal_unit and may then return SUBTREE_MOVED. */ -squeeze_result squalloc_extent(znode *left, const coord_t *, flush_pos_t *, reiser4_key *stop_key); -#if REISER4_DEBUG -void *shift_check_prepare(const znode *left, const znode *right); -void shift_check(void *vp, const znode *left, const znode *right); -#endif static int squeeze_right_twig(znode * left, znode * right, flush_pos_t * pos) { int ret = SUBTREE_MOVED; @@ -1420,14 +1488,15 @@ static int squeeze_right_twig(znode * le stop_key = *min_key(); ret = squalloc_extent(left, &coord, pos, &stop_key); if (ret != SQUEEZE_CONTINUE) { - ON_DEBUG(reiser4_kfree(vp)); + ON_DEBUG(kfree(vp)); break; } assert("vs-1465", !keyeq(&stop_key, min_key())); /* Helper function to do the cutting. */ set_key_offset(&stop_key, get_key_offset(&stop_key) - 1); - check_me("vs-1466", squalloc_right_twig_cut(&coord, &stop_key, left) == 0); + check_me("vs-1466", + squalloc_right_twig_cut(&coord, &stop_key, left) == 0); ON_DEBUG(shift_check(vp, left, coord.node)); } @@ -1459,7 +1528,7 @@ static int squeeze_right_twig(znode * le extents, so we stop here. */ ret = shift_one_internal_unit(left, right); -out: + out: assert("jmacd-8612", ret < 0 || ret == SQUEEZE_TARGET_FULL || ret == SUBTREE_MOVED || ret == SQUEEZE_SOURCE_EMPTY); @@ -1478,17 +1547,16 @@ out: } #if REISER4_DEBUG -static void -item_convert_invariant(flush_pos_t * pos) +static void item_convert_invariant(flush_pos_t * pos) { assert("edward-1225", coord_is_existing_item(&pos->coord)); if (chaining_data_present(pos)) { - item_plugin * iplug = item_convert_plug(pos); + item_plugin *iplug = item_convert_plug(pos); - assert("edward-1000", iplug == item_plugin_by_coord(&pos->coord)); + assert("edward-1000", + iplug == item_plugin_by_coord(&pos->coord)); assert("edward-1001", iplug->f.convert != NULL); - } - else + } else assert("edward-1226", pos->child == NULL); } #else @@ -1504,7 +1572,7 @@ item_convert_invariant(flush_pos_t * pos static int convert_node(flush_pos_t * pos, znode * node) { int ret = 0; - item_plugin * iplug; + item_plugin *iplug; assert("edward-304", pos != NULL); assert("edward-305", pos->child == NULL); @@ -1541,18 +1609,18 @@ static int convert_node(flush_pos_t * po break; if (should_chain_next_node(pos)) { /* go to next node */ - move_chaining_data(pos, 0 /* to next node */); + move_chaining_data(pos, 0 /* to next node */ ); break; } /* repeat this node */ - move_chaining_data(pos, 1 /* this node */); + move_chaining_data(pos, 1 /* this node */ ); continue; } /* Node is not over. Check if there is attached convert data. If so roll one item position back and repeat on this node - */ + */ if (chaining_data_present(pos)) { if (iplug != item_plugin_by_coord(&pos->coord)) @@ -1561,12 +1629,12 @@ static int convert_node(flush_pos_t * po ret = coord_prev_item(&pos->coord); assert("edward-1003", !ret); - move_chaining_data(pos, 1 /* this node */); + move_chaining_data(pos, 1 /* this node */ ); } } JF_CLR(ZJNODE(node), JNODE_CONVERTIBLE); znode_make_dirty(node); - exit: + exit: assert("edward-1004", !ret); return ret; } @@ -1591,7 +1659,8 @@ static int convert_node(flush_pos_t * po is returned. */ -static int squeeze_right_neighbor(flush_pos_t * pos, znode * left, znode * right) +static int squeeze_right_neighbor(flush_pos_t * pos, znode * left, + znode * right) { int ret; @@ -1617,11 +1686,14 @@ static int squeeze_right_neighbor(flush_ } assert("jmacd-2011", (ret < 0 || - ret == SQUEEZE_SOURCE_EMPTY || ret == SQUEEZE_TARGET_FULL || ret == SUBTREE_MOVED)); + ret == SQUEEZE_SOURCE_EMPTY + || ret == SQUEEZE_TARGET_FULL + || ret == SUBTREE_MOVED)); return ret; } -static int squeeze_right_twig_and_advance_coord (flush_pos_t * pos, znode * right) +static int squeeze_right_twig_and_advance_coord(flush_pos_t * pos, + znode * right) { int ret; @@ -1637,30 +1709,14 @@ static int squeeze_right_twig_and_advanc return 0; } -#if 0 -/* "prepped" check for parent node without long-term locking it */ -static inline int fast_check_parent_flushprepped (znode * node) -{ - reiser4_tree * tree = current_tree; - int prepped = 1; - - RLOCK_TREE(tree); - - if (node->in_parent.node || !jnode_is_flushprepped(ZJNODE(node))) - prepped = 0; - - RUNLOCK_TREE(tree); - - return prepped; -} -#endif - /* forward declaration */ -static int squalloc_upper_levels (flush_pos_t *, znode *, znode *); +static int squalloc_upper_levels(flush_pos_t *, znode *, znode *); /* do a fast check for "same parents" condition before calling * squalloc_upper_levels() */ -static inline int check_parents_and_squalloc_upper_levels (flush_pos_t * pos, znode *left, znode * right) +static inline int check_parents_and_squalloc_upper_levels(flush_pos_t * pos, + znode * left, + znode * right) { if (znode_same_parents(left, right)) return 0; @@ -1673,7 +1729,7 @@ static inline int check_parents_and_squa share at least the parent of the @right is after the @left but before the @right in parent-first order, we have to (re)allocate it before the @right gets (re)allocated. */ -static int squalloc_upper_levels (flush_pos_t * pos, znode *left, znode * right) +static int squalloc_upper_levels(flush_pos_t * pos, znode * left, znode * right) { int ret; @@ -1683,14 +1739,13 @@ static int squalloc_upper_levels (flush_ load_count left_parent_load; load_count right_parent_load; - init_lh(&left_parent_lock); init_lh(&right_parent_lock); init_load_count(&left_parent_load); init_load_count(&right_parent_load); - ret = reiser4_get_parent(&left_parent_lock, left, ZNODE_WRITE_LOCK); + ret = reiser4_get_parent(&left_parent_lock, left, ZNODE_WRITE_LOCK); if (ret) goto out; @@ -1715,7 +1770,8 @@ static int squalloc_upper_levels (flush_ allocated. So, only twigs are used as a preceder for allocating of the rest of the slum. */ if (znode_get_level(right_parent_lock.node) == TWIG_LEVEL) { - pos->preceder.blk = *znode_get_block(right_parent_lock.node); + pos->preceder.blk = + *znode_get_block(right_parent_lock.node); check_preceder(pos->preceder.blk); } goto out; @@ -1729,7 +1785,9 @@ static int squalloc_upper_levels (flush_ if (ret) goto out; - ret = squeeze_right_neighbor(pos, left_parent_lock.node, right_parent_lock.node); + ret = + squeeze_right_neighbor(pos, left_parent_lock.node, + right_parent_lock.node); /* We stop if error. We stop if some items/units were shifted (ret == 0) * and thus @right changed its parent. It means we have not process * right_parent node prior to processing of @right. Positive return @@ -1740,14 +1798,16 @@ static int squalloc_upper_levels (flush_ /* parent(@left) and parent(@right) may have different parents also. We * do a recursive call for checking that. */ - ret = check_parents_and_squalloc_upper_levels(pos, left_parent_lock.node, right_parent_lock.node); + ret = + check_parents_and_squalloc_upper_levels(pos, left_parent_lock.node, + right_parent_lock.node); if (ret) goto out; /* allocate znode when going down */ ret = lock_parent_and_allocate_znode(right_parent_lock.node, pos); - out: + out: done_load_count(&left_parent_load); done_load_count(&right_parent_load); @@ -1759,12 +1819,12 @@ static int squalloc_upper_levels (flush_ /* Check the leftmost child "flushprepped" status, also returns true if child * node was not found in cache. */ -static int leftmost_child_of_unit_check_flushprepped (const coord_t *coord) +static int leftmost_child_of_unit_check_flushprepped(const coord_t * coord) { int ret; int prepped; - jnode * child; + jnode *child; ret = get_leftmost_child_of_unit(coord, &child); @@ -1785,14 +1845,14 @@ static int leftmost_child_of_unit_check_ } /* (re)allocate znode with automated getting parent node */ -static int lock_parent_and_allocate_znode (znode * node, flush_pos_t * pos) +static int lock_parent_and_allocate_znode(znode * node, flush_pos_t * pos) { int ret; lock_handle parent_lock; load_count parent_load; coord_t pcoord; - assert ("zam-851", znode_is_write_locked(node)); + assert("zam-851", znode_is_write_locked(node)); init_lh(&parent_lock); init_load_count(&parent_load); @@ -1811,7 +1871,7 @@ static int lock_parent_and_allocate_znod ret = allocate_znode(node, &pcoord, pos); - out: + out: done_load_count(&parent_load); done_lh(&parent_lock); return ret; @@ -1819,7 +1879,7 @@ static int lock_parent_and_allocate_znod /* Process nodes on leaf level until unformatted node or rightmost node in the * slum reached. */ -static int handle_pos_on_formatted (flush_pos_t * pos) +static int handle_pos_on_formatted(flush_pos_t * pos) { int ret; lock_handle right_lock; @@ -1835,8 +1895,12 @@ static int handle_pos_on_formatted (flus } while (1) { - ret = neighbor_in_slum(pos->lock.node, &right_lock, RIGHT_SIDE, ZNODE_WRITE_LOCK, - !should_convert_next_node(pos, right_lock.node)); + ret = + neighbor_in_slum(pos->lock.node, &right_lock, RIGHT_SIDE, + ZNODE_WRITE_LOCK, + !should_convert_next_node(pos, + right_lock. + node)); if (ret) break; @@ -1844,8 +1908,10 @@ static int handle_pos_on_formatted (flus * can be optimal. For now we choose to live with the risk that it will * be suboptimal because it would be quite complex to code it to be * smarter. */ - if (znode_check_flushprepped(right_lock.node) && !znode_convertible(right_lock.node)) { - assert("edward-1005", !should_convert_next_node(pos, right_lock.node)); + if (znode_check_flushprepped(right_lock.node) + && !znode_convertible(right_lock.node)) { + assert("edward-1005", + !should_convert_next_node(pos, right_lock.node)); pos_stop(pos); break; } @@ -1866,8 +1932,10 @@ static int handle_pos_on_formatted (flus } } - /* squeeze _before_ going upward. */ - ret = squeeze_right_neighbor(pos, pos->lock.node, right_lock.node); + /* squeeze _before_ going upward. */ + ret = + squeeze_right_neighbor(pos, pos->lock.node, + right_lock.node); if (ret < 0) break; @@ -1881,9 +1949,9 @@ static int handle_pos_on_formatted (flus if (node_is_empty(right_lock.node)) { done_load_count(&right_load); done_lh(&right_lock); - } - else - move_flush_pos(pos, &right_lock, &right_load, NULL); + } else + move_flush_pos(pos, &right_lock, + &right_load, NULL); continue; } pos_stop(pos); @@ -1899,7 +1967,9 @@ static int handle_pos_on_formatted (flus /* parent(right_lock.node) has to be processed before * (right_lock.node) due to "parent-first" allocation order. */ - ret = check_parents_and_squalloc_upper_levels(pos, pos->lock.node, right_lock.node); + ret = + check_parents_and_squalloc_upper_levels(pos, pos->lock.node, + right_lock.node); if (ret) break; /* (re)allocate _after_ going upward */ @@ -1933,11 +2003,11 @@ static int handle_pos_on_formatted (flus /* Process nodes on leaf level until unformatted node or rightmost node in the * slum reached. */ -static int handle_pos_on_leaf (flush_pos_t * pos) +static int handle_pos_on_leaf(flush_pos_t * pos) { int ret; - assert ("zam-845", pos->state == POS_ON_LEAF); + assert("zam-845", pos->state == POS_ON_LEAF); ret = handle_pos_on_formatted(pos); @@ -1951,14 +2021,14 @@ static int handle_pos_on_leaf (flush_pos } /* Process slum on level > 1 */ -static int handle_pos_on_internal (flush_pos_t * pos) +static int handle_pos_on_internal(flush_pos_t * pos) { - assert ("zam-850", pos->state == POS_ON_INTERNAL); + assert("zam-850", pos->state == POS_ON_INTERNAL); return handle_pos_on_formatted(pos); } /* check whether squalloc should stop before processing given extent */ -static int squalloc_extent_should_stop (flush_pos_t * pos) +static int squalloc_extent_should_stop(flush_pos_t * pos) { assert("zam-869", item_is_extent(&pos->coord)); @@ -1969,10 +2039,14 @@ static int squalloc_extent_should_stop ( assert("vs-1383", jnode_is_unformatted(pos->child)); prepped = jnode_check_flushprepped(pos->child); - pos->pos_in_unit = jnode_get_index(pos->child) - extent_unit_index(&pos->coord); - assert("vs-1470", pos->pos_in_unit < extent_unit_width(&pos->coord)); - assert("nikita-3434", ergo(extent_is_unallocated(&pos->coord), - pos->pos_in_unit == 0)); + pos->pos_in_unit = + jnode_get_index(pos->child) - + extent_unit_index(&pos->coord); + assert("vs-1470", + pos->pos_in_unit < extent_unit_width(&pos->coord)); + assert("nikita-3434", + ergo(extent_is_unallocated(&pos->coord), + pos->pos_in_unit == 0)); jput(pos->child); pos->child = NULL; @@ -1986,19 +2060,17 @@ static int squalloc_extent_should_stop ( return leftmost_child_of_unit_check_flushprepped(&pos->coord); } -int alloc_extent(flush_pos_t *flush_pos); - /* Handle the case when regular reiser4 tree (znodes connected one to its * neighbors by sibling pointers) is interrupted on leaf level by one or more * unformatted nodes. By having a lock on twig level and use extent code * routines to process unformatted nodes we swim around an irregular part of * reiser4 tree. */ -static int handle_pos_on_twig (flush_pos_t * pos) +static int handle_pos_on_twig(flush_pos_t * pos) { int ret; - assert ("zam-844", pos->state == POS_ON_EPOINT); - assert ("zam-843", item_is_extent(&pos->coord)); + assert("zam-844", pos->state == POS_ON_EPOINT); + assert("zam-843", item_is_extent(&pos->coord)); /* We decide should we continue slum processing with current extent unit: if leftmost child of current extent unit is flushprepped @@ -2013,7 +2085,8 @@ static int handle_pos_on_twig (flush_pos return ret; } - while (pos_valid(pos) && coord_is_existing_unit(&pos->coord) && item_is_extent(&pos->coord)) { + while (pos_valid(pos) && coord_is_existing_unit(&pos->coord) + && item_is_extent(&pos->coord)) { ret = alloc_extent(pos); if (ret) { break; @@ -2030,7 +2103,7 @@ static int handle_pos_on_twig (flush_pos return 0; } - assert ("zam-860", item_is_extent(&pos->coord)); + assert("zam-860", item_is_extent(&pos->coord)); /* "slum" is over */ pos->state = POS_INVALID; @@ -2040,17 +2113,16 @@ static int handle_pos_on_twig (flush_pos /* When we about to return flush position from twig to leaf level we can process * the right twig node or move position to the leaf. This processes right twig * if it is possible and jump to leaf level if not. */ -static int handle_pos_end_of_twig (flush_pos_t * pos) +static int handle_pos_end_of_twig(flush_pos_t * pos) { int ret; lock_handle right_lock; load_count right_load; coord_t at_right; - jnode * child = NULL; + jnode *child = NULL; - - assert ("zam-848", pos->state == POS_END_OF_TWIG); - assert ("zam-849", coord_is_after_rightmost(&pos->coord)); + assert("zam-848", pos->state == POS_END_OF_TWIG); + assert("zam-849", coord_is_after_rightmost(&pos->coord)); init_lh(&right_lock); init_load_count(&right_load); @@ -2058,7 +2130,9 @@ static int handle_pos_end_of_twig (flush /* We get a lock on the right twig node even it is not dirty because * slum continues or discontinues on leaf level not on next twig. This * lock on the right twig is needed for getting its leftmost child. */ - ret = reiser4_get_right_neighbor(&right_lock, pos->lock.node, ZNODE_WRITE_LOCK, GN_SAME_ATOM); + ret = + reiser4_get_right_neighbor(&right_lock, pos->lock.node, + ZNODE_WRITE_LOCK, GN_SAME_ATOM); if (ret) goto out; @@ -2070,9 +2144,10 @@ static int handle_pos_end_of_twig (flush if (znode_check_dirty(right_lock.node)) { /* If right twig node is dirty we always attempt to squeeze it * content to the left... */ -became_dirty: - ret = squeeze_right_twig_and_advance_coord(pos, right_lock.node); - if (ret <=0) { + became_dirty: + ret = + squeeze_right_twig_and_advance_coord(pos, right_lock.node); + if (ret <= 0) { /* pos->coord is on internal item, go to leaf level, or * we have an error which will be caught in squalloc() */ pos->state = POS_TO_LEAF; @@ -2087,13 +2162,20 @@ became_dirty: /* ... and prep it if it is not yet prepped */ if (!znode_check_flushprepped(right_lock.node)) { - /* As usual, process parent before ...*/ - ret = check_parents_and_squalloc_upper_levels(pos, pos->lock.node, right_lock.node); + /* As usual, process parent before ... */ + ret = + check_parents_and_squalloc_upper_levels(pos, + pos->lock. + node, + right_lock. + node); if (ret) goto out; /* ... processing the child */ - ret = lock_parent_and_allocate_znode(right_lock.node, pos); + ret = + lock_parent_and_allocate_znode(right_lock.node, + pos); if (ret) goto out; } @@ -2109,7 +2191,9 @@ became_dirty: /* check clean twig for possible relocation */ if (!znode_check_flushprepped(right_lock.node)) { - ret = reverse_relocate_check_dirty_parent(child, &at_right, pos); + ret = + reverse_relocate_check_dirty_parent(child, + &at_right, pos); if (ret) goto out; if (znode_check_dirty(right_lock.node)) @@ -2117,7 +2201,7 @@ became_dirty: } } - assert ("zam-875", znode_check_flushprepped(right_lock.node)); + assert("zam-875", znode_check_flushprepped(right_lock.node)); /* Update the preceder by a block number of just processed right twig * node. The code above could miss the preceder updating because @@ -2131,7 +2215,7 @@ became_dirty: pos->state = item_is_extent(&at_right) ? POS_ON_EPOINT : POS_TO_LEAF; move_flush_pos(pos, &right_lock, &right_load, &at_right); - out: + out: done_load_count(&right_load); done_lh(&right_lock); @@ -2143,15 +2227,15 @@ became_dirty: /* Move the pos->lock to leaf node pointed by pos->coord, check should we * continue there. */ -static int handle_pos_to_leaf (flush_pos_t * pos) +static int handle_pos_to_leaf(flush_pos_t * pos) { int ret; lock_handle child_lock; load_count child_load; - jnode * child; + jnode *child; - assert ("zam-846", pos->state == POS_TO_LEAF); - assert ("zam-847", item_is_internal(&pos->coord)); + assert("zam-846", pos->state == POS_TO_LEAF); + assert("zam-847", item_is_internal(&pos->coord)); init_lh(&child_lock); init_load_count(&child_load); @@ -2169,7 +2253,9 @@ static int handle_pos_to_leaf (flush_pos goto out; } - ret = longterm_lock_znode(&child_lock, JZNODE(child), ZNODE_WRITE_LOCK, ZNODE_LOCK_LOPRI); + ret = + longterm_lock_znode(&child_lock, JZNODE(child), ZNODE_WRITE_LOCK, + ZNODE_LOCK_LOPRI); if (ret) goto out; @@ -2189,16 +2275,17 @@ static int handle_pos_to_leaf (flush_pos ret = delete_empty_node(JZNODE(child)); pos->state = POS_INVALID; } - out: + out: done_load_count(&child_load); done_lh(&child_lock); jput(child); return ret; } + /* move pos from leaf to twig, and move lock from leaf to twig. */ /* Move pos->lock to upper (twig) level */ -static int handle_pos_to_twig (flush_pos_t * pos) +static int handle_pos_to_twig(flush_pos_t * pos) { int ret; @@ -2206,12 +2293,13 @@ static int handle_pos_to_twig (flush_pos load_count parent_load; coord_t pcoord; - assert ("zam-852", pos->state == POS_TO_TWIG); + assert("zam-852", pos->state == POS_TO_TWIG); init_lh(&parent_lock); init_load_count(&parent_load); - ret = reiser4_get_parent(&parent_lock, pos->lock.node, ZNODE_WRITE_LOCK); + ret = + reiser4_get_parent(&parent_lock, pos->lock.node, ZNODE_WRITE_LOCK); if (ret) goto out; @@ -2223,7 +2311,7 @@ static int handle_pos_to_twig (flush_pos if (ret) goto out; - assert ("zam-870", item_is_internal(&pcoord)); + assert("zam-870", item_is_internal(&pcoord)); coord_next_item(&pcoord); if (coord_is_after_rightmost(&pcoord)) @@ -2240,25 +2328,25 @@ static int handle_pos_to_twig (flush_pos move_flush_pos(pos, &parent_lock, &parent_load, &pcoord); - out: + out: done_load_count(&parent_load); done_lh(&parent_lock); return ret; } -typedef int (*pos_state_handle_t)(flush_pos_t*); +typedef int (*pos_state_handle_t) (flush_pos_t *); static pos_state_handle_t flush_pos_handlers[] = { /* process formatted nodes on leaf level, keep lock on a leaf node */ - [POS_ON_LEAF] = handle_pos_on_leaf, + [POS_ON_LEAF] = handle_pos_on_leaf, /* process unformatted nodes, keep lock on twig node, pos->coord points to extent currently * being processed */ - [POS_ON_EPOINT] = handle_pos_on_twig, + [POS_ON_EPOINT] = handle_pos_on_twig, /* move a lock from leaf node to its parent for further processing of unformatted nodes */ - [POS_TO_TWIG] = handle_pos_to_twig, + [POS_TO_TWIG] = handle_pos_to_twig, /* move a lock from twig to leaf level when a processing of unformatted nodes finishes, * pos->coord points to the leaf node we jump to */ - [POS_TO_LEAF] = handle_pos_to_leaf, + [POS_TO_LEAF] = handle_pos_to_leaf, /* after processing last extent in the twig node, attempting to shift items from the twigs * right neighbor and process them while shifting */ [POS_END_OF_TWIG] = handle_pos_end_of_twig, @@ -2268,14 +2356,14 @@ static pos_state_handle_t flush_pos_hand /* Advance flush position horizontally, prepare for flushing ((re)allocate, squeeze, * encrypt) nodes and their ancestors in "parent-first" order */ -static int squalloc (flush_pos_t * pos) +static int squalloc(flush_pos_t * pos) { int ret = 0; /* maybe needs to be made a case statement with handle_pos_on_leaf as first case, for * greater CPU efficiency? Measure and see.... -Hans */ while (pos_valid(pos)) { - ret = flush_pos_handlers[pos->state](pos); + ret = flush_pos_handlers[pos->state] (pos); if (ret < 0) break; @@ -2292,7 +2380,7 @@ static int squalloc (flush_pos_t * pos) return ret; } -static void update_ldkey(znode *node) +static void update_ldkey(znode * node) { reiser4_key ldkey; @@ -2306,11 +2394,11 @@ static void update_ldkey(znode *node) /* this is to be called after calling of shift node's method to shift data from @right to @left. It sets left delimiting keys of @left and @right to keys of first items of @left and @right correspondingly and sets right delimiting key of @left to first key of @right */ -static void -update_znode_dkeys(znode *left, znode *right) +static void update_znode_dkeys(znode * left, znode * right) { assert("nikita-1470", rw_dk_is_write_locked(znode_get_tree(right))); - assert("vs-1629", znode_is_write_locked(left) && znode_is_write_locked(right)); + assert("vs-1629", znode_is_write_locked(left) + && znode_is_write_locked(right)); /* we need to update left delimiting of left if it was empty before shift */ update_ldkey(left); @@ -2336,32 +2424,34 @@ shift_everything_left(znode * right, zno info.doing = NULL; info.todo = todo; return nplug->shift(&from, left, SHIFT_LEFT, - 1 /* delete @right if it becomes empty */, - 1 /* move coord @from to node @left if everything will be shifted */, + 1 /* delete @right if it becomes empty */ , + 1 + /* move coord @from to node @left if everything will be shifted */ + , &info); } /* Shift as much as possible from @right to @left using the memcpy-optimized shift_everything_left. @left and @right are formatted neighboring nodes on leaf level. */ -static int -squeeze_right_non_twig(znode * left, znode * right) +static int squeeze_right_non_twig(znode * left, znode * right) { int ret; carry_pool *pool; - carry_level todo; + carry_level *todo; assert("nikita-2246", znode_get_level(left) == znode_get_level(right)); if (!znode_is_dirty(left) || !znode_is_dirty(right)) return SQUEEZE_TARGET_FULL; - pool = init_carry_pool(); + pool = init_carry_pool(sizeof(*pool) + 3 * sizeof(*todo)); if (IS_ERR(pool)) return PTR_ERR(pool); - init_carry_level(&todo, pool); + todo = (carry_level *) (pool + 1); + init_carry_level(todo, pool); - ret = shift_everything_left(right, left, &todo); + ret = shift_everything_left(right, left, todo); if (ret > 0) { /* something was shifted */ reiser4_tree *tree; @@ -2381,12 +2471,14 @@ squeeze_right_non_twig(znode * left, zno node. */ grabbed = get_current_context()->grabbed_blocks; ret = reiser4_grab_space_force(tree->height, BA_RESERVED); - assert("nikita-3003", ret == 0); /* reserved space is exhausted. Ask Hans. */ - ret = carry(&todo, NULL /* previous level */ ); + assert("nikita-3003", ret == 0); /* reserved space is exhausted. Ask Hans. */ + ret = carry(todo, NULL /* previous level */ ); grabbed2free_mark(grabbed); } else { /* Shifting impossible, we return appropriate result code */ - ret = node_is_empty(right) ? SQUEEZE_SOURCE_EMPTY : SQUEEZE_TARGET_FULL; + ret = + node_is_empty(right) ? SQUEEZE_SOURCE_EMPTY : + SQUEEZE_TARGET_FULL; } done_carry_pool(pool); @@ -2397,51 +2489,69 @@ squeeze_right_non_twig(znode * left, zno /* Shift first unit of first item if it is an internal one. Return SQUEEZE_TARGET_FULL if it fails to shift an item, otherwise return SUBTREE_MOVED. */ -static int -shift_one_internal_unit(znode * left, znode * right) +static int shift_one_internal_unit(znode * left, znode * right) { int ret; carry_pool *pool; - carry_level todo; - coord_t coord; + carry_level *todo; + coord_t *coord; + carry_plugin_info *info; int size, moved; - carry_plugin_info info; assert("nikita-2247", znode_get_level(left) == znode_get_level(right)); assert("nikita-2435", znode_is_write_locked(left)); assert("nikita-2436", znode_is_write_locked(right)); - assert("nikita-2434", UNDER_RW(tree, znode_get_tree(left), read, left->right == right)); + assert("nikita-2434", + UNDER_RW(tree, znode_get_tree(left), read, + left->right == right)); + + pool = + init_carry_pool(sizeof(*pool) + 3 * sizeof(*todo) + sizeof(*coord) + + sizeof(*info) +#if REISER4_DEBUG + + sizeof(*coord) + 2 * sizeof(reiser4_key) +#endif + ); + if (IS_ERR(pool)) + return PTR_ERR(pool); + todo = (carry_level *) (pool + 1); + init_carry_level(todo, pool); - coord_init_first_unit(&coord, right); + coord = (coord_t *) (todo + 3); + coord_init_first_unit(coord, right); + info = (carry_plugin_info *) (coord + 1); #if REISER4_DEBUG if (!node_is_empty(left)) { - coord_t last; - reiser4_key right_key; - reiser4_key left_key; - - coord_init_last_unit(&last, left); + coord_t *last; + reiser4_key *right_key; + reiser4_key *left_key; + + last = (coord_t *) (info + 1); + right_key = (reiser4_key *) (last + 1); + left_key = right_key + 1; + coord_init_last_unit(last, left); assert("nikita-2463", - keyle(item_key_by_coord(&last, &left_key), item_key_by_coord(&coord, &right_key))); + keyle(item_key_by_coord(last, left_key), + item_key_by_coord(coord, right_key))); } #endif - assert("jmacd-2007", item_is_internal(&coord)); + assert("jmacd-2007", item_is_internal(coord)); - pool = init_carry_pool(); - if (IS_ERR(pool)) - return PTR_ERR(pool); - init_carry_level(&todo, pool); - - size = item_length_by_coord(&coord); - info.todo = &todo; - info.doing = NULL; - - ret = node_plugin_by_node(left)->shift(&coord, left, SHIFT_LEFT, - 1 /* delete @right if it becomes empty */, - 0 /* do not move coord @coord to node @left */, - &info); + size = item_length_by_coord(coord); + info->todo = todo; + info->doing = NULL; + + ret = node_plugin_by_node(left)->shift(coord, left, SHIFT_LEFT, + 1 + /* delete @right if it becomes empty */ + , + 0 + /* do not move coord @coord to node @left */ + , + info); /* If shift returns positive, then we shifted the item. */ assert("vs-423", ret <= 0 || size == ret); @@ -2460,9 +2570,9 @@ shift_one_internal_unit(znode * left, zn /* reserve space for delimiting keys after shifting */ grabbed = get_current_context()->grabbed_blocks; ret = reiser4_grab_space_force(tree->height, BA_RESERVED); - assert("nikita-3003", ret == 0); /* reserved space is exhausted. Ask Hans. */ + assert("nikita-3003", ret == 0); /* reserved space is exhausted. Ask Hans. */ - ret = carry(&todo, NULL /* previous level */ ); + ret = carry(todo, NULL /* previous level */ ); grabbed2free_mark(grabbed); } @@ -2479,14 +2589,15 @@ shift_one_internal_unit(znode * left, zn /* ALLOCATE INTERFACE */ /* Audited by: umka (2002.06.11) */ -reiser4_internal void -jnode_set_block(jnode * node /* jnode to update */ , - const reiser4_block_nr * blocknr /* new block nr */ ) +void jnode_set_block(jnode * node /* jnode to update */ , + const reiser4_block_nr * blocknr /* new block nr */ ) { assert("nikita-2020", node != NULL); assert("umka-055", blocknr != NULL); - assert("zam-819", ergo(JF_ISSET(node, JNODE_EFLUSH), node->blocknr == 0)); - assert("vs-1453", ergo(JF_ISSET(node, JNODE_EFLUSH), jnode_is_unformatted(node))); + assert("zam-819", + ergo(JF_ISSET(node, JNODE_EFLUSH), node->blocknr == 0)); + assert("vs-1453", + ergo(JF_ISSET(node, JNODE_EFLUSH), jnode_is_unformatted(node))); node->blocknr = *blocknr; } @@ -2497,7 +2608,7 @@ allocate_znode_loaded(znode * node, const coord_t * parent_coord, flush_pos_t * pos) { int ret; - reiser4_super_info_data * sbinfo = get_current_super_private(); + reiser4_super_info_data *sbinfo = get_current_super_private(); /* FIXME(D): We have the node write-locked and should have checked for ! allocated() somewhere before reaching this point, but there can be a race, so this assertion is bogus. */ @@ -2506,10 +2617,10 @@ allocate_znode_loaded(znode * node, assert("jmacd-7989", coord_is_invalid(parent_coord) || znode_is_write_locked(parent_coord->node)); - if (ZF_ISSET(node, JNODE_REPACK) || znode_created(node) || znode_is_root(node) || + if (ZF_ISSET(node, JNODE_REPACK) || znode_created(node) + || znode_is_root(node) || /* We have enough nodes to relocate no matter what. */ - (pos->leaf_relocate != 0 && znode_get_level(node) == LEAF_LEVEL)) - { + (pos->leaf_relocate != 0 && znode_get_level(node) == LEAF_LEVEL)) { /* No need to decide with new nodes, they are treated the same as relocate. If the root node is dirty, relocate. */ if (pos->preceder.blk == 0) { @@ -2539,10 +2650,16 @@ allocate_znode_loaded(znode * node, jnode_make_wander(ZJNODE(node)); } else { - dist = (nblk < pos->preceder.blk) ? (pos->preceder.blk - nblk) : (nblk - pos->preceder.blk); + dist = + (nblk < + pos->preceder.blk) ? (pos->preceder.blk - + nblk) : (nblk - + pos->preceder.blk); /* See if we can find a closer block (forward direction only). */ - pos->preceder.max_dist = min((reiser4_block_nr)sbinfo->flush.relocate_distance, dist); + pos->preceder.max_dist = + min((reiser4_block_nr) sbinfo->flush. + relocate_distance, dist); pos->preceder.level = znode_get_level(node); ret = allocate_znode_update(node, parent_coord, pos); @@ -2561,7 +2678,9 @@ allocate_znode_loaded(znode * node, } else { /* Otherwise, try to relocate to the best position. */ best_reloc: - ret = allocate_znode_update(node, parent_coord, pos); + ret = + allocate_znode_update(node, parent_coord, + pos); if (ret != 0) return ret; @@ -2576,7 +2695,7 @@ allocate_znode_loaded(znode * node, check_preceder(pos->preceder.blk); pos->alloc_cnt += 1; - assert ("jmacd-4277", !blocknr_is_fake(&pos->preceder.blk)); + assert("jmacd-4277", !blocknr_is_fake(&pos->preceder.blk)); return 0; } @@ -2592,13 +2711,13 @@ allocate_znode(znode * node, const coord return WITH_DATA(node, allocate_znode_loaded(node, parent_coord, pos)); } - /* A subroutine of allocate_znode, this is called first to see if there is a close position to relocate to. It may return ENOSPC if there is no close position. If there is no close position it may not relocate. This takes care of updating the parent node with the relocated block address. */ static int -allocate_znode_update(znode * node, const coord_t * parent_coord, flush_pos_t * pos) +allocate_znode_update(znode * node, const coord_t * parent_coord, + flush_pos_t * pos) { int ret; reiser4_block_nr blk; @@ -2616,7 +2735,7 @@ allocate_znode_update(znode * node, cons return ret; if (ZF_ISSET(node, JNODE_CREATED)) { - assert ("zam-816", blocknr_is_fake(znode_get_block(node))); + assert("zam-816", blocknr_is_fake(znode_get_block(node))); pos->preceder.block_stage = BLOCK_UNALLOCATED; } else { pos->preceder.block_stage = BLOCK_GRABBED; @@ -2630,10 +2749,10 @@ allocate_znode_update(znode * node, cons * that @node can possibly go into overwrite set and * reserved block for its wandering location. */ - txn_atom * atom = get_current_atom_locked(); + txn_atom *atom = get_current_atom_locked(); assert("nikita-3449", ZF_ISSET(node, JNODE_FLUSH_RESERVED)); - flush_reserved2grabbed(atom, (__u64)1); + flush_reserved2grabbed(atom, (__u64) 1); spin_unlock_atom(atom); /* * we are trying to move node into relocate @@ -2643,20 +2762,23 @@ allocate_znode_update(znode * node, cons ZF_CLR(node, JNODE_FLUSH_RESERVED); flush_reserved_used = 1; } else { - ret = reiser4_grab_space_force((__u64)1, BA_RESERVED); + ret = reiser4_grab_space_force((__u64) 1, BA_RESERVED); if (ret != 0) goto exit; } } - /* We may do not use 5% of reserved disk space here and flush will not pack tightly. */ - ret = reiser4_alloc_block(&pos->preceder, &blk, BA_FORMATTED | BA_PERMANENT); - if(ret) + /* We may do not use 5% of reserved disk space here and flush will not pack tightly. */ + ret = + reiser4_alloc_block(&pos->preceder, &blk, + BA_FORMATTED | BA_PERMANENT); + if (ret) goto exit; - if (!ZF_ISSET(node, JNODE_CREATED) && - (ret = reiser4_dealloc_block(znode_get_block(node), 0, BA_DEFER | BA_FORMATTED))) + (ret = + reiser4_dealloc_block(znode_get_block(node), 0, + BA_DEFER | BA_FORMATTED))) goto exit; if (likely(!znode_is_root(node))) { @@ -2692,8 +2814,8 @@ allocate_znode_update(znode * node, cons } ret = znode_rehash(node, &blk); -exit: - if(ret) { + exit: + if (ret) { /* Get flush reserved block back if something fails, because * callers assume that on error block wasn't relocated and its * flush reserved block wasn't used. */ @@ -2702,7 +2824,7 @@ exit: * ok, we failed to move node into relocate * set. Restore status quo. */ - grabbed2flush_reserved((__u64)1); + grabbed2flush_reserved((__u64) 1); ZF_SET(node, JNODE_FLUSH_RESERVED); } } @@ -2722,21 +2844,21 @@ exit: /* Hans adds this note: remember to ask how expensive this operation is vs. storing parent pointer in jnodes. */ static int -jnode_lock_parent_coord(jnode * node, - coord_t * coord, - lock_handle * parent_lh, - load_count * parent_zh, - znode_lock_mode parent_mode, - int try) +jnode_lock_parent_coord(jnode * node, + coord_t * coord, + lock_handle * parent_lh, + load_count * parent_zh, + znode_lock_mode parent_mode, int try) { int ret; assert("edward-53", jnode_is_unformatted(node) || jnode_is_znode(node)); - assert("edward-54", jnode_is_unformatted(node) || znode_is_any_locked(JZNODE(node))); + assert("edward-54", jnode_is_unformatted(node) + || znode_is_any_locked(JZNODE(node))); if (!jnode_is_znode(node)) { reiser4_key key; - tree_level stop_level = TWIG_LEVEL ; + tree_level stop_level = TWIG_LEVEL; lookup_bias bias = FIND_EXACT; assert("edward-168", !(jnode_get_type(node) == JNODE_BITMAP)); @@ -2772,11 +2894,13 @@ jnode_lock_parent_coord(jnode * assert("jmacd-1812", coord != NULL); ret = coord_by_key(jnode_get_tree(node), &key, coord, parent_lh, - parent_mode, bias, stop_level, stop_level, CBK_UNIQUE, 0/*ra_info*/); + parent_mode, bias, stop_level, stop_level, + CBK_UNIQUE, NULL /*ra_info */ ); switch (ret) { case CBK_COORD_NOTFOUND: assert("edward-1038", - ergo(jnode_is_cluster_page(node), JF_ISSET(node, JNODE_HEARD_BANSHEE))); + ergo(jnode_is_cluster_page(node), + JF_ISSET(node, JNODE_HEARD_BANSHEE))); if (!JF_ISSET(node, JNODE_HEARD_BANSHEE)) { warning("nikita-3177", "Parent not found"); print_jnode("node", node); @@ -2801,7 +2925,7 @@ jnode_lock_parent_coord(jnode * races with write() are possible check_child_cluster (parent_lh->node); } - */ + */ break; default: return ret; @@ -2819,7 +2943,8 @@ jnode_lock_parent_coord(jnode * if (try) flags |= GN_TRY_LOCK; - ret = reiser4_get_parent_flags(parent_lh, z, parent_mode, flags); + ret = + reiser4_get_parent_flags(parent_lh, z, parent_mode, flags); if (ret != 0) /* -E_REPEAT is ok here, it is handled by the caller. */ return ret; @@ -2830,13 +2955,16 @@ jnode_lock_parent_coord(jnode * ret = incr_load_count_znode(parent_zh, parent_lh->node); if (ret != 0) { - warning("jmacd-976812386", "incr_load_count_znode failed: %d", ret); + warning("jmacd-976812386", + "incr_load_count_znode failed: %d", + ret); return ret; } ret = find_child_ptr(parent_lh->node, z, coord); if (ret != 0) { - warning("jmacd-976812", "find_child_ptr failed: %d", ret); + warning("jmacd-976812", + "find_child_ptr failed: %d", ret); return ret; } } @@ -2849,25 +2977,20 @@ jnode_lock_parent_coord(jnode * If there is no next neighbor or the neighbor is not in memory or if there is a neighbor but it is not dirty or not in the same atom, -E_NO_NEIGHBOR is returned. In some cases the slum may include nodes which are not dirty, if so @check_dirty should be 0 */ -static int -neighbor_in_slum( - - znode * node, /* starting point */ - - lock_handle * lock, /* lock on starting point */ - - sideof side, /* left or right direction we seek the next node in */ - - znode_lock_mode mode, /* kind of lock we want */ - - int check_dirty /* true if the neighbor should be dirty */ - ) -{ +static int neighbor_in_slum(znode * node, /* starting point */ + lock_handle * lock, /* lock on starting point */ + sideof side, /* left or right direction we seek the next node in */ + znode_lock_mode mode, /* kind of lock we want */ + int check_dirty) +{ /* true if the neighbor should be dirty */ int ret; assert("jmacd-6334", znode_is_connected(node)); - ret = reiser4_get_neighbor(lock, node, mode, GN_SAME_ATOM | (side == LEFT_SIDE ? GN_GO_LEFT : 0)); + ret = + reiser4_get_neighbor(lock, node, mode, + GN_SAME_ATOM | (side == + LEFT_SIDE ? GN_GO_LEFT : 0)); if (ret) { /* May return -ENOENT or -E_NO_NEIGHBOR. */ @@ -2890,8 +3013,7 @@ neighbor_in_slum( /* Return true if two znodes have the same parent. This is called with both nodes write-locked (for squeezing) so no tree lock is needed. */ -static int -znode_same_parents(znode * a, znode * b) +static int znode_same_parents(znode * a, znode * b) { assert("jmacd-7011", znode_is_write_locked(a)); assert("jmacd-7012", znode_is_write_locked(b)); @@ -2905,10 +3027,9 @@ znode_same_parents(znode * a, znode * b) /* FLUSH SCAN */ /* Initialize the flush_scan data structure. */ -static void -scan_init(flush_scan * scan) +static void scan_init(flush_scan * scan) { - memset(scan, 0, sizeof (*scan)); + memset(scan, 0, sizeof(*scan)); init_lh(&scan->node_lock); init_lh(&scan->parent_lock); init_load_count(&scan->parent_load); @@ -2917,8 +3038,7 @@ scan_init(flush_scan * scan) } /* Release any resources held by the flush scan, e.g., release locks, free memory, etc. */ -static void -scan_done(flush_scan * scan) +static void scan_done(flush_scan * scan) { done_load_count(&scan->node_load); if (scan->node != NULL) { @@ -2931,8 +3051,7 @@ scan_done(flush_scan * scan) } /* Returns true if flush scanning is finished. */ -reiser4_internal int -scan_finished(flush_scan * scan) +int scan_finished(flush_scan * scan) { return scan->stop || (scan->direction == RIGHT_SIDE && scan->count >= scan->max_count); @@ -2940,8 +3059,7 @@ scan_finished(flush_scan * scan) /* Return true if the scan should continue to the @tonode. True if the node meets the same_slum_check condition. If not, deref the "left" node and stop the scan. */ -reiser4_internal int -scan_goto(flush_scan * scan, jnode * tonode) +int scan_goto(flush_scan * scan, jnode * tonode) { int go = same_slum_check(scan->node, tonode, 1, 0); @@ -2956,8 +3074,9 @@ scan_goto(flush_scan * scan, jnode * ton /* Set the current scan->node, refcount it, increment count by the @add_count (number to count, e.g., skipped unallocated nodes), deref previous current, and copy the current parent coordinate. */ -reiser4_internal int -scan_set_current(flush_scan * scan, jnode * node, unsigned add_count, const coord_t * parent) +int +scan_set_current(flush_scan * scan, jnode * node, unsigned add_count, + const coord_t * parent) { /* Release the old references, take the new reference. */ done_load_count(&scan->node_load); @@ -2982,8 +3101,7 @@ scan_set_current(flush_scan * scan, jnod } /* Return true if scanning in the leftward direction. */ -reiser4_internal int -scanning_left(flush_scan * scan) +int scanning_left(flush_scan * scan) { return scan->direction == LEFT_SIDE; } @@ -3060,8 +3178,7 @@ scan_left(flush_scan * scan, flush_scan FLUSH_RELOCATE_THRESHOLD nodes for flushing. Otherwise, the limit parameter is set to the difference between scan-left's count and FLUSH_RELOCATE_THRESHOLD, meaning scan-right counts as high as FLUSH_RELOCATE_THRESHOLD and then stops. */ -static int -scan_right(flush_scan * scan, jnode * node, unsigned limit) +static int scan_right(flush_scan * scan, jnode * node, unsigned limit) { int ret; @@ -3077,13 +3194,13 @@ scan_right(flush_scan * scan, jnode * no } /* Common code to perform left or right scanning. */ -static int -scan_common(flush_scan * scan, flush_scan * other) +static int scan_common(flush_scan * scan, flush_scan * other) { int ret; assert("nikita-2376", scan->node != NULL); - assert("edward-54", jnode_is_unformatted(scan->node) || jnode_is_znode(scan->node)); + assert("edward-54", jnode_is_unformatted(scan->node) + || jnode_is_znode(scan->node)); /* Special case for starting at an unformatted node. Optimization: we only want to search for the parent (which requires a tree traversal) once. Obviously, we @@ -3108,8 +3225,7 @@ scan_common(flush_scan * scan, flush_sca return 0; } -static int -scan_unformatted(flush_scan * scan, flush_scan * other) +static int scan_unformatted(flush_scan * scan, flush_scan * other) { int ret = 0; int try = 0; @@ -3117,9 +3233,9 @@ scan_unformatted(flush_scan * scan, flus if (!coord_is_invalid(&scan->parent_coord)) goto scan; - /* set parent coord from */ + /* set parent coord from */ if (!jnode_is_unformatted(scan->node)) { - /* formatted position*/ + /* formatted position */ lock_handle lock; assert("edward-301", jnode_is_znode(scan->node)); @@ -3135,12 +3251,16 @@ scan_unformatted(flush_scan * scan, flus * there is already lock held by this thread, * jnode_lock_parent_coord() should use try-lock. */ - try = scanning_left(scan) && !lock_stack_isclean(get_current_lock_stack()); + try = scanning_left(scan) + && !lock_stack_isclean(get_current_lock_stack()); /* Need the node locked to get the parent lock, We have to take write lock since there is at least one call path where this znode is already write-locked by us. */ - ret = longterm_lock_znode(&lock, JZNODE(scan->node), ZNODE_WRITE_LOCK, - scanning_left(scan) ? ZNODE_LOCK_LOPRI : ZNODE_LOCK_HIPRI); + ret = + longterm_lock_znode(&lock, JZNODE(scan->node), + ZNODE_WRITE_LOCK, + scanning_left(scan) ? ZNODE_LOCK_LOPRI : + ZNODE_LOCK_HIPRI); if (ret != 0) /* EINVAL or E_DEADLOCK here mean... try again! At this point we've scanned too far and can't back out, just start over. */ @@ -3164,8 +3284,11 @@ scan_unformatted(flush_scan * scan, flus } else { /* unformatted position */ - ret = jnode_lock_parent_coord(scan->node, &scan->parent_coord, &scan->parent_lock, - &scan->parent_load, ZNODE_WRITE_LOCK, try); + ret = + jnode_lock_parent_coord(scan->node, &scan->parent_coord, + &scan->parent_lock, + &scan->parent_load, + ZNODE_WRITE_LOCK, try); if (IS_CBKERR(ret)) return ret; @@ -3181,7 +3304,7 @@ scan_unformatted(flush_scan * scan, flus copy_lh(&other->parent_lock, &scan->parent_lock); copy_load_count(&other->parent_load, &scan->parent_load); } - scan: + scan: return scan_by_coord(scan); } @@ -3193,8 +3316,7 @@ scan_unformatted(flush_scan * scan, flus - node->left/right belongs to the same atom - scan has not reached maximum count */ -static int -scan_formatted(flush_scan * scan) +static int scan_formatted(flush_scan * scan) { int ret; znode *neighbor = NULL; @@ -3247,7 +3369,8 @@ scan_formatted(flush_scan * scan) /* If neighbor is NULL then we reached the end of a formatted region, or else the sibling is out of memory, now check for an extent to the left (as long as LEAF_LEVEL). */ - if (neighbor != NULL || jnode_get_level(scan->node) != LEAF_LEVEL || scan_finished(scan)) { + if (neighbor != NULL || jnode_get_level(scan->node) != LEAF_LEVEL + || scan_finished(scan)) { scan->stop = 1; return 0; } @@ -3265,8 +3388,7 @@ scan_formatted(flush_scan * scan) When called from scan_formatted, we skip first iteration (to make sure that right(left)most item of the left(right) neighbor on the parent level is of the same type and set appropriate coord). */ -static int -scan_by_coord(flush_scan * scan) +static int scan_by_coord(flush_scan * scan) { int ret = 0; int scan_this_coord; @@ -3280,7 +3402,7 @@ scan_by_coord(flush_scan * scan) init_load_count(&next_load); scan_this_coord = (jnode_is_unformatted(scan->node) ? 1 : 0); - /* set initial item id */ + /* set initial item id */ iplug = item_plugin_by_coord(&scan->parent_coord); for (; !scan_finished(scan); scan_this_coord = 1) { @@ -3308,12 +3430,18 @@ scan_by_coord(flush_scan * scan) /* NOTE-JMACD: In this case, apply the same end-of-node logic but don't scan the first coordinate. */ - assert("jmacd-1231", item_is_internal(&scan->parent_coord)); + assert("jmacd-1231", + item_is_internal(&scan->parent_coord)); } - if(iplug->f.utmost_child == NULL || znode_get_level(scan->parent_coord.node) != TWIG_LEVEL) { + if (iplug->f.utmost_child == NULL + || znode_get_level(scan->parent_coord.node) != TWIG_LEVEL) { /* stop this coord and continue on parrent level */ - ret = scan_set_current(scan, ZJNODE(zref(scan->parent_coord.node)), 1, NULL); + ret = + scan_set_current(scan, + ZJNODE(zref + (scan->parent_coord.node)), + 1, NULL); if (ret != 0) goto exit; break; @@ -3328,8 +3456,10 @@ scan_by_coord(flush_scan * scan) if (coord_is_after_sideof_unit(&next_coord, scan->direction)) { /* We take the write lock because we may start flushing from this * coordinate. */ - ret = neighbor_in_slum(next_coord.node, &next_lock, scan->direction, ZNODE_WRITE_LOCK, 1 /* check dirty */); - + ret = + neighbor_in_slum(next_coord.node, &next_lock, + scan->direction, ZNODE_WRITE_LOCK, + 1 /* check dirty */ ); if (ret == -E_NO_NEIGHBOR) { scan->stop = 1; ret = 0; @@ -3345,13 +3475,17 @@ scan_by_coord(flush_scan * scan) goto exit; } - coord_init_sideof_unit(&next_coord, next_lock.node, sideof_reverse(scan->direction)); + coord_init_sideof_unit(&next_coord, next_lock.node, + sideof_reverse(scan->direction)); } iplug = item_plugin_by_coord(&next_coord); /* Get the next child. */ - ret = iplug->f.utmost_child(&next_coord, sideof_reverse(scan->direction), &child); + ret = + iplug->f.utmost_child(&next_coord, + sideof_reverse(scan->direction), + &child); if (ret != 0) goto exit; /* If the next child is not in memory, or, item_utmost_child @@ -3363,7 +3497,8 @@ scan_by_coord(flush_scan * scan) break; } - assert("nikita-2374", jnode_is_unformatted(child) || jnode_is_znode(child)); + assert("nikita-2374", jnode_is_unformatted(child) + || jnode_is_znode(child)); /* See if it is dirty, part of the same atom. */ if (!scan_goto(scan, child)) { @@ -3390,9 +3525,9 @@ scan_by_coord(flush_scan * scan) } assert("jmacd-6233", scan_finished(scan) || jnode_is_znode(scan->node)); - exit: + exit: checkchild(scan); - race: /* skip the above check */ + race: /* skip the above check */ if (jnode_is_znode(scan->node)) { done_lh(&scan->parent_lock); done_load_count(&scan->parent_load); @@ -3406,8 +3541,7 @@ scan_by_coord(flush_scan * scan) /* FLUSH POS HELPERS */ /* Initialize the fields of a flush_position. */ -static void -pos_init(flush_pos_t * pos) +static void pos_init(flush_pos_t * pos) { memset(pos, 0, sizeof *pos); @@ -3431,15 +3565,13 @@ pos_init(flush_pos_t * pos) flush order is either non-existant, not dirty, or not in the same atom. */ - -static int pos_valid (flush_pos_t * pos) +static int pos_valid(flush_pos_t * pos) { return pos->state != POS_INVALID; } /* Release any resources of a flush_position. Called when jnode_flush finishes. */ -static void -pos_done(flush_pos_t * pos) +static void pos_done(flush_pos_t * pos) { pos_stop(pos); blocknr_hint_done(&pos->preceder); @@ -3449,8 +3581,7 @@ pos_done(flush_pos_t * pos) /* Reset the point and parent. Called during flush subroutines to terminate the squalloc loop. */ -static int -pos_stop(flush_pos_t * pos) +static int pos_stop(flush_pos_t * pos) { pos->state = POS_INVALID; done_lh(&pos->lock); @@ -3466,13 +3597,12 @@ pos_stop(flush_pos_t * pos) } /* Return the flush_position's block allocator hint. */ -reiser4_internal reiser4_blocknr_hint * -pos_hint(flush_pos_t * pos) +reiser4_blocknr_hint *pos_hint(flush_pos_t * pos) { return &pos->preceder; } -reiser4_internal flush_queue_t * pos_fq(flush_pos_t * pos) +flush_queue_t *pos_fq(flush_pos_t * pos) { return pos->fq; } diff -puN fs/reiser4/flush.h~reiser4-big-update fs/reiser4/flush.h --- devel/fs/reiser4/flush.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/flush.h 2005-09-15 19:51:08.000000000 -0700 @@ -5,7 +5,7 @@ #if !defined(__REISER4_FLUSH_H__) #define __REISER4_FLUSH_H__ -#include "plugin/cryptcompress.h" +#include "cluster.h" /* The flush_scan data structure maintains the state of an in-progress flush-scan on a single level of the tree. A flush-scan is used for counting the number of adjacent @@ -57,17 +57,17 @@ struct flush_scan { }; typedef struct convert_item_info { - dc_item_stat d_cur; /* disk cluster state of the current item */ - dc_item_stat d_next; /* disk cluster state of the next slum item */ - struct inode * inode; + dc_item_stat d_cur; /* disk cluster state of the current item */ + dc_item_stat d_next; /* disk cluster state of the next slum item */ + struct inode *inode; flow_t flow; } convert_item_info_t; typedef struct convert_info { - int count; /* for squalloc terminating */ - reiser4_cluster_t clust; /* transform cluster */ - item_plugin * iplug; /* current item plugin */ - convert_item_info_t * itm; /* current item info */ + int count; /* for squalloc terminating */ + reiser4_cluster_t clust; /* transform cluster */ + item_plugin *iplug; /* current item plugin */ + convert_item_info_t *itm; /* current item info */ } convert_info_t; typedef enum flush_position_state { @@ -82,11 +82,8 @@ typedef enum flush_position_state { POS_END_OF_TWIG, /* special case of POS_ON_TWIG, when coord is after * rightmost unit of the current twig */ POS_ON_INTERNAL /* same as POS_ON_LEAF, but points to internal node */ - } flushpos_state_t; - - /* An encapsulation of the current flush point and all the parameters that are passed through the entire squeeze-and-allocate stage of the flush routine. A single flush_position object is constructed after left- and right-scanning finishes. */ @@ -97,7 +94,7 @@ struct flush_position { lock_handle lock; /* current lock we hold */ load_count load; /* load status for current locked formatted node */ - jnode * child; /* for passing a reference to unformatted child + jnode *child; /* for passing a reference to unformatted child * across pos state changes */ reiser4_blocknr_hint preceder; /* The flush 'hint' state. */ @@ -109,64 +106,56 @@ struct flush_position { long *nr_written; /* number of nodes submitted to disk */ int flags; /* a copy of jnode_flush flags argument */ - znode * prev_twig; /* previous parent pointer value, used to catch + znode *prev_twig; /* previous parent pointer value, used to catch * processing of new twig node */ - convert_info_t * sq; /* convert info */ + convert_info_t *sq; /* convert info */ - unsigned long pos_in_unit; /* for extents only. Position - within an extent unit of first - jnode of slum */ + unsigned long pos_in_unit; /* for extents only. Position + within an extent unit of first + jnode of slum */ + long nr_to_write; /* number of unformatted nodes to handle on flush */ }; -static inline int -item_convert_count (flush_pos_t * pos) +static inline int item_convert_count(flush_pos_t * pos) { return pos->sq->count; } -static inline void -inc_item_convert_count (flush_pos_t * pos) +static inline void inc_item_convert_count(flush_pos_t * pos) { pos->sq->count++; } -static inline void -set_item_convert_count (flush_pos_t * pos, int count) +static inline void set_item_convert_count(flush_pos_t * pos, int count) { pos->sq->count = count; } -static inline item_plugin * -item_convert_plug (flush_pos_t * pos) +static inline item_plugin *item_convert_plug(flush_pos_t * pos) { return pos->sq->iplug; } -static inline convert_info_t * -convert_data (flush_pos_t * pos) +static inline convert_info_t *convert_data(flush_pos_t * pos) { return pos->sq; } -static inline convert_item_info_t * -item_convert_data (flush_pos_t * pos) +static inline convert_item_info_t *item_convert_data(flush_pos_t * pos) { assert("edward-955", convert_data(pos)); return pos->sq->itm; } -static inline tfm_cluster_t * -tfm_cluster_sq (flush_pos_t * pos) +static inline tfm_cluster_t *tfm_cluster_sq(flush_pos_t * pos) { return &pos->sq->clust.tc; } -static inline tfm_stream_t * -tfm_stream_sq (flush_pos_t * pos, tfm_stream_id id) +static inline tfm_stream_t *tfm_stream_sq(flush_pos_t * pos, tfm_stream_id id) { assert("edward-854", pos->sq != NULL); return tfm_stream(tfm_cluster_sq(pos), id); } -static inline int -chaining_data_present (flush_pos_t * pos) +static inline int chaining_data_present(flush_pos_t * pos) { return convert_data(pos) && item_convert_data(pos); } @@ -174,8 +163,8 @@ chaining_data_present (flush_pos_t * pos /* Returns true if next node contains next item of the disk cluster so item convert data should be moved to the right slum neighbor. */ -static inline int -should_chain_next_node(flush_pos_t * pos) { +static inline int should_chain_next_node(flush_pos_t * pos) +{ int result = 0; assert("edward-1007", chaining_data_present(pos)); @@ -194,8 +183,8 @@ should_chain_next_node(flush_pos_t * pos /* update item state in a disk cluster to assign conversion mode */ static inline void -move_chaining_data(flush_pos_t * pos, - int this_node /* where is next item */) { +move_chaining_data(flush_pos_t * pos, int this_node /* where is next item */ ) +{ assert("edward-1010", chaining_data_present(pos)); @@ -223,44 +212,48 @@ move_chaining_data(flush_pos_t * pos, } } -static inline int -should_convert_node(flush_pos_t * pos, znode * node) +static inline int should_convert_node(flush_pos_t * pos, znode * node) { return znode_convertible(node); } /* true if there is attached convert item info */ -static inline int -should_convert_next_node(flush_pos_t * pos, znode * node) +static inline int should_convert_next_node(flush_pos_t * pos, znode * node) { return convert_data(pos) && item_convert_data(pos); } #define SQUALLOC_THRESHOLD 256 -static inline int -should_terminate_squalloc(flush_pos_t * pos) +static inline int should_terminate_squalloc(flush_pos_t * pos) { return convert_data(pos) && - !item_convert_data(pos) && - item_convert_count(pos) >= SQUALLOC_THRESHOLD; + !item_convert_data(pos) && + item_convert_count(pos) >= SQUALLOC_THRESHOLD; } void free_convert_data(flush_pos_t * pos); /* used in extent.c */ -int scan_set_current(flush_scan * scan, jnode * node, unsigned add_size, const coord_t * parent); +int scan_set_current(flush_scan * scan, jnode * node, unsigned add_size, + const coord_t * parent); int scan_finished(flush_scan * scan); int scanning_left(flush_scan * scan); int scan_goto(flush_scan * scan, jnode * tonode); txn_atom *atom_locked_by_fq(flush_queue_t * fq); - -int init_fqs(void); -void done_fqs(void); +int alloc_extent(flush_pos_t *flush_pos); +squeeze_result squalloc_extent(znode *left, const coord_t *, flush_pos_t *, + reiser4_key *stop_key); +extern int init_fqs(void); +extern void done_fqs(void); #if REISER4_DEBUG + +extern void check_fq(const txn_atom *atom); +extern atomic_t flush_cnt; + #define check_preceder(blk) \ assert("nikita-2588", blk < reiser4_block_count(reiser4_get_current_sb())); -extern void check_pos(flush_pos_t *pos); +extern void check_pos(flush_pos_t * pos); #else #define check_preceder(b) noop #define check_pos(pos) noop diff -puN fs/reiser4/flush_queue.c~reiser4-big-update fs/reiser4/flush_queue.c --- devel/fs/reiser4/flush_queue.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/flush_queue.c 2005-09-15 19:51:08.000000000 -0700 @@ -1,7 +1,6 @@ /* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */ #include "debug.h" -#include "type_safe_list.h" #include "super.h" #include "txnmgr.h" #include "jnode.h" @@ -10,6 +9,7 @@ #include "wander.h" #include "vfs_ops.h" #include "writeout.h" +#include "flush.h" #include #include @@ -22,8 +22,6 @@ kept on the flush queue until memory pressure or atom commit asks flush queues to write some or all from their jnodes. */ -TYPE_SAFE_LIST_DEFINE(fq, flush_queue_t, alink); - #if REISER4_DEBUG # define spin_ordering_pred_fq(fq) (1) #endif @@ -58,8 +56,7 @@ SPIN_LOCK_FUNCTIONS(fq, flush_queue_t, g #define mark_fq_ready(fq) do { (fq)->state &= ~FQ_IN_USE; } while (0) /* get lock on atom from locked flush queue object */ -static txn_atom * -atom_get_locked_by_fq(flush_queue_t * fq) +static txn_atom *atom_get_locked_by_fq(flush_queue_t * fq) { /* This code is similar to jnode_get_atom(), look at it for the * explanation. */ @@ -67,7 +64,7 @@ atom_get_locked_by_fq(flush_queue_t * fq assert("zam-729", spin_fq_is_locked(fq)); - while(1) { + while (1) { atom = fq->atom; if (atom == NULL) break; @@ -93,20 +90,18 @@ atom_get_locked_by_fq(flush_queue_t * fq return atom; } -reiser4_internal txn_atom * -atom_locked_by_fq(flush_queue_t * fq) +txn_atom *atom_locked_by_fq(flush_queue_t * fq) { return UNDER_SPIN(fq, fq, atom_get_locked_by_fq(fq)); } -static void -init_fq(flush_queue_t * fq) +static void init_fq(flush_queue_t * fq) { memset(fq, 0, sizeof *fq); atomic_set(&fq->nr_submitted, 0); - capture_list_init(ATOM_FQ_LIST(fq)); + INIT_LIST_HEAD(ATOM_FQ_LIST(fq)); sema_init(&fq->io_sem, 0); spin_fq_init(fq); @@ -115,25 +110,35 @@ init_fq(flush_queue_t * fq) /* slab for flush queues */ static kmem_cache_t *fq_slab; -reiser4_internal int init_fqs(void) + +/** + * init_fqs - create flush queue cache + * + * Initializes slab cache of flush queues. It is part of reiser4 module + * initialization. + */ +int init_fqs(void) { fq_slab = kmem_cache_create("fq", - sizeof (flush_queue_t), - 0, - SLAB_HWCACHE_ALIGN, - NULL, - NULL); - return (fq_slab == NULL) ? RETERR(-ENOMEM) : 0; + sizeof(flush_queue_t), + 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + if (fq_slab == NULL) + return RETERR(-ENOMEM); + return 0; } -reiser4_internal void done_fqs(void) +/** + * done_fqs - delete flush queue cache + * + * This is called on reiser4 module unloading or system shutdown. + */ +void done_fqs(void) { - kmem_cache_destroy(fq_slab); + destroy_reiser4_cache(&fq_slab); } /* create new flush queue object */ -static flush_queue_t * -create_fq(int gfp) +static flush_queue_t *create_fq(unsigned int gfp) { flush_queue_t *fq; @@ -145,36 +150,32 @@ create_fq(int gfp) } /* adjust atom's and flush queue's counters of queued nodes */ -static void -count_enqueued_node(flush_queue_t * fq) +static void count_enqueued_node(flush_queue_t * fq) { ON_DEBUG(fq->atom->num_queued++); } -static void -count_dequeued_node(flush_queue_t * fq) +static void count_dequeued_node(flush_queue_t * fq) { assert("zam-993", fq->atom->num_queued > 0); ON_DEBUG(fq->atom->num_queued--); } /* attach flush queue object to the atom */ -static void -attach_fq(txn_atom * atom, flush_queue_t * fq) +static void attach_fq(txn_atom *atom, flush_queue_t *fq) { assert("zam-718", spin_atom_is_locked(atom)); - fq_list_push_front(&atom->flush_queues, fq); + list_add(&fq->alink, &atom->flush_queues); fq->atom = atom; ON_DEBUG(atom->nr_flush_queues++); } -static void -detach_fq(flush_queue_t * fq) +static void detach_fq(flush_queue_t * fq) { assert("zam-731", spin_atom_is_locked(fq->atom)); spin_lock_fq(fq); - fq_list_remove_clean(fq); + list_del_init(&fq->alink); assert("vs-1456", fq->atom->nr_flush_queues > 0); ON_DEBUG(fq->atom->nr_flush_queues--); fq->atom = NULL; @@ -182,18 +183,16 @@ detach_fq(flush_queue_t * fq) } /* destroy flush queue object */ -static void -done_fq(flush_queue_t * fq) +static void done_fq(flush_queue_t * fq) { - assert("zam-763", capture_list_empty(ATOM_FQ_LIST(fq))); + assert("zam-763", list_empty_careful(ATOM_FQ_LIST(fq))); assert("zam-766", atomic_read(&fq->nr_submitted) == 0); kmem_cache_free(fq_slab, fq); } /* */ -reiser4_internal void -mark_jnode_queued(flush_queue_t *fq, jnode *node) +void mark_jnode_queued(flush_queue_t * fq, jnode * node) { JF_SET(node, JNODE_FLUSH_QUEUED); count_enqueued_node(fq); @@ -201,8 +200,7 @@ mark_jnode_queued(flush_queue_t *fq, jno /* Putting jnode into the flush queue. Both atom and jnode should be spin-locked. */ -reiser4_internal void -queue_jnode(flush_queue_t * fq, jnode * node) +void queue_jnode(flush_queue_t * fq, jnode * node) { assert("zam-711", spin_jnode_is_locked(node)); assert("zam-713", node->atom != NULL); @@ -217,19 +215,20 @@ queue_jnode(flush_queue_t * fq, jnode * assert("vs-1481", NODE_LIST(node) != FQ_LIST); mark_jnode_queued(fq, node); - capture_list_remove_clean(node); - capture_list_push_back(ATOM_FQ_LIST(fq), node); - /*XXXX*/ON_DEBUG(count_jnode(node->atom, node, NODE_LIST(node), FQ_LIST, 1)); + list_del(&node->capture_link); + list_add_tail(&node->capture_link, ATOM_FQ_LIST(fq)); + + ON_DEBUG(count_jnode(node->atom, node, NODE_LIST(node), + FQ_LIST, 1)); } /* repeatable process for waiting io completion on a flush queue object */ -static int -wait_io(flush_queue_t * fq, int *nr_io_errors) +static int wait_io(flush_queue_t * fq, int *nr_io_errors) { assert("zam-738", fq->atom != NULL); assert("zam-739", spin_atom_is_locked(fq->atom)); assert("zam-736", fq_in_use(fq)); - assert("zam-911", capture_list_empty(ATOM_FQ_LIST(fq))); + assert("zam-911", list_empty_careful(ATOM_FQ_LIST(fq))); if (atomic_read(&fq->nr_submitted) != 0) { struct super_block *super; @@ -243,7 +242,7 @@ wait_io(flush_queue_t * fq, int *nr_io_e /* FIXME: this is instead of blk_run_queues() */ blk_run_address_space(get_super_fake(super)->i_mapping); - if ( !(super->s_flags & MS_RDONLY) ) + if (!(super->s_flags & MS_RDONLY)) down(&fq->io_sem); /* Ask the caller to re-acquire the locks and call this @@ -257,11 +256,10 @@ wait_io(flush_queue_t * fq, int *nr_io_e } /* wait on I/O completion, re-submit dirty nodes to write */ -static int -finish_fq(flush_queue_t * fq, int *nr_io_errors) +static int finish_fq(flush_queue_t * fq, int *nr_io_errors) { int ret; - txn_atom * atom = fq->atom; + txn_atom *atom = fq->atom; assert("zam-801", atom != NULL); assert("zam-744", spin_atom_is_locked(atom)); @@ -281,17 +279,18 @@ finish_fq(flush_queue_t * fq, int *nr_io /* wait for all i/o for given atom to be completed, actually do one iteration on that and return -E_REPEAT if there more iterations needed */ -static int -finish_all_fq(txn_atom * atom, int *nr_io_errors) +static int finish_all_fq(txn_atom * atom, int *nr_io_errors) { flush_queue_t *fq; + struct list_head *pos; assert("zam-730", spin_atom_is_locked(atom)); - if (fq_list_empty(&atom->flush_queues)) + if (list_empty_careful(&atom->flush_queues)) return 0; - for_all_type_safe_list(fq, &atom->flush_queues, fq) { + list_for_each(pos, &atom->flush_queues) { + fq = list_entry(pos, flush_queue_t, alink); if (fq_ready(fq)) { int ret; @@ -300,7 +299,7 @@ finish_all_fq(txn_atom * atom, int *nr_i ON_DEBUG(fq->owner = current); ret = finish_fq(fq, nr_io_errors); - if ( *nr_io_errors ) + if (*nr_io_errors) reiser4_handle_error(); if (ret) { @@ -319,8 +318,7 @@ finish_all_fq(txn_atom * atom, int *nr_i } /* wait all i/o for current atom */ -reiser4_internal int -current_atom_finish_all_fq(void) +int current_atom_finish_all_fq(void) { txn_atom *atom; int nr_io_errors = 0; @@ -355,11 +353,13 @@ current_atom_finish_all_fq(void) /* change node->atom field for all jnode from given list */ static void -scan_fq_and_update_atom_ref(capture_list_head * list, txn_atom * atom) +scan_fq_and_update_atom_ref(struct list_head *list, txn_atom *atom) { jnode *cur; + struct list_head *pos; - for_all_type_safe_list(capture, list, cur) { + list_for_each(pos, list) { + cur = list_entry(pos, jnode, capture_link); LOCK_JNODE(cur); cur->atom = atom; UNLOCK_JNODE(cur); @@ -367,23 +367,25 @@ scan_fq_and_update_atom_ref(capture_list } /* support for atom fusion operation */ -reiser4_internal void -fuse_fq(txn_atom * to, txn_atom * from) +void fuse_fq(txn_atom *to, txn_atom *from) { flush_queue_t *fq; + struct list_head *pos; assert("zam-720", spin_atom_is_locked(to)); assert("zam-721", spin_atom_is_locked(from)); - - for_all_type_safe_list(fq, &from->flush_queues, fq) { + list_for_each(pos, &from->flush_queues) { + fq = list_entry(pos, flush_queue_t, alink); scan_fq_and_update_atom_ref(ATOM_FQ_LIST(fq), to); spin_lock_fq(fq); fq->atom = to; spin_unlock_fq(fq); } - fq_list_splice(&to->flush_queues, &from->flush_queues); + list_splice(&from->flush_queues, &to->flush_queues); + INIT_LIST_HEAD(&from->flush_queues); + #if REISER4_DEBUG to->num_queued += from->num_queued; @@ -393,21 +395,22 @@ fuse_fq(txn_atom * to, txn_atom * from) } #if REISER4_DEBUG -int atom_fq_parts_are_clean (txn_atom * atom) +int atom_fq_parts_are_clean(txn_atom * atom) { assert("zam-915", atom != NULL); - return fq_list_empty(&atom->flush_queues); + return list_empty_careful(&atom->flush_queues); } #endif /* Bio i/o completion routine for reiser4 write operations. */ static int -end_io_handler(struct bio *bio, unsigned int bytes_done UNUSED_ARG, int err UNUSED_ARG) +end_io_handler(struct bio *bio, unsigned int bytes_done UNUSED_ARG, + int err UNUSED_ARG) { int i; int nr_errors = 0; flush_queue_t *fq; - assert ("zam-958", bio->bi_rw & WRITE); + assert("zam-958", bio->bi_rw & WRITE); /* i/o op. is not fully completed */ if (bio->bi_size != 0) @@ -457,8 +460,7 @@ end_io_handler(struct bio *bio, unsigned /* Count I/O requests which will be submitted by @bio in given flush queues @fq */ -reiser4_internal void -add_fq_to_bio(flush_queue_t * fq, struct bio *bio) +void add_fq_to_bio(flush_queue_t * fq, struct bio *bio) { bio->bi_private = fq; bio->bi_end_io = end_io_handler; @@ -470,16 +472,16 @@ add_fq_to_bio(flush_queue_t * fq, struct /* Move all queued nodes out from @fq->prepped list. */ static void release_prepped_list(flush_queue_t * fq) { - txn_atom * atom; + txn_atom *atom; - assert ("zam-904", fq_in_use(fq)); + assert("zam-904", fq_in_use(fq)); atom = UNDER_SPIN(fq, fq, atom_get_locked_by_fq(fq)); - while(!capture_list_empty(ATOM_FQ_LIST(fq))) { - jnode * cur; + while (!list_empty(ATOM_FQ_LIST(fq))) { + jnode *cur; - cur = capture_list_front(ATOM_FQ_LIST(fq)); - capture_list_remove_clean(cur); + cur = list_entry(ATOM_FQ_LIST(fq)->next, jnode, capture_link); + list_del_init(&cur->capture_link); count_dequeued_node(fq); LOCK_JNODE(cur); @@ -489,17 +491,20 @@ static void release_prepped_list(flush_q JF_CLR(cur, JNODE_FLUSH_QUEUED); if (JF_ISSET(cur, JNODE_DIRTY)) { - capture_list_push_back(ATOM_DIRTY_LIST(atom, jnode_get_level(cur)), cur); - ON_DEBUG(count_jnode(atom, cur, FQ_LIST, DIRTY_LIST, 1)); + list_add_tail(&cur->capture_link, + ATOM_DIRTY_LIST(atom, jnode_get_level(cur))); + ON_DEBUG(count_jnode(atom, cur, FQ_LIST, + DIRTY_LIST, 1)); } else { - capture_list_push_back(ATOM_CLEAN_LIST(atom), cur); - ON_DEBUG(count_jnode(atom, cur, FQ_LIST, CLEAN_LIST, 1)); + list_add_tail(&cur->capture_link, ATOM_CLEAN_LIST(atom)); + ON_DEBUG(count_jnode(atom, cur, FQ_LIST, + CLEAN_LIST, 1)); } UNLOCK_JNODE(cur); } - if (-- atom->nr_running_queues == 0) + if (--atom->nr_running_queues == 0) atom_send_event(atom); UNLOCK_ATOM(atom); @@ -510,22 +515,22 @@ static void release_prepped_list(flush_q @fq: flush queue object which contains jnodes we can (and will) write. @return: number of submitted blocks (>=0) if success, otherwise -- an error code (<0). */ -reiser4_internal int -write_fq(flush_queue_t * fq, long * nr_submitted, int flags) +int write_fq(flush_queue_t * fq, long *nr_submitted, int flags) { int ret; - txn_atom * atom; + txn_atom *atom; while (1) { atom = UNDER_SPIN(fq, fq, atom_get_locked_by_fq(fq)); - assert ("zam-924", atom); + assert("zam-924", atom); /* do not write fq in parallel. */ - if (atom->nr_running_queues == 0 || !(flags & WRITEOUT_SINGLE_STREAM)) + if (atom->nr_running_queues == 0 + || !(flags & WRITEOUT_SINGLE_STREAM)) break; atom_wait_event(atom); } - atom->nr_running_queues ++; + atom->nr_running_queues++; UNLOCK_ATOM(atom); ret = write_jnode_list(ATOM_FQ_LIST(fq), fq, nr_submitted, flags); @@ -541,15 +546,14 @@ write_fq(flush_queue_t * fq, long * nr_s atom lock is obtained by different ways in different parts of reiser4, usually it is current atom, but we need a possibility for getting fq for the atom of given jnode. */ -static int -fq_by_atom_gfp(txn_atom * atom, flush_queue_t ** new_fq, int gfp) +static int fq_by_atom_gfp(txn_atom *atom, flush_queue_t **new_fq, int gfp) { flush_queue_t *fq; assert("zam-745", spin_atom_is_locked(atom)); - fq = fq_list_front(&atom->flush_queues); - while (!fq_list_end(&atom->flush_queues, fq)) { + fq = list_entry(atom->flush_queues.next, flush_queue_t, alink); + while (&atom->flush_queues != &fq->alink) { spin_lock_fq(fq); if (fq_ready(fq)) { @@ -568,7 +572,7 @@ fq_by_atom_gfp(txn_atom * atom, flush_qu spin_unlock_fq(fq); - fq = fq_list_next(fq); + fq = list_entry(fq->alink.next, flush_queue_t, alink); } /* Use previously allocated fq object */ @@ -591,16 +595,14 @@ fq_by_atom_gfp(txn_atom * atom, flush_qu return RETERR(-E_REPEAT); } -reiser4_internal int -fq_by_atom(txn_atom * atom, flush_queue_t ** new_fq) +int fq_by_atom(txn_atom * atom, flush_queue_t ** new_fq) { return fq_by_atom_gfp(atom, new_fq, GFP_KERNEL); } /* A wrapper around fq_by_atom for getting a flush queue object for current * atom, if success fq->atom remains locked. */ -reiser4_internal flush_queue_t * -get_fq_for_current_atom(void) +flush_queue_t *get_fq_for_current_atom(void) { flush_queue_t *fq = NULL; txn_atom *atom; @@ -617,18 +619,16 @@ get_fq_for_current_atom(void) } /* Releasing flush queue object after exclusive use */ -reiser4_internal void -fq_put_nolock(flush_queue_t * fq) +void fq_put_nolock(flush_queue_t *fq) { assert("zam-747", fq->atom != NULL); - assert("zam-902", capture_list_empty(ATOM_FQ_LIST(fq))); + assert("zam-902", list_empty_careful(ATOM_FQ_LIST(fq))); mark_fq_ready(fq); assert("vs-1245", fq->owner == current); ON_DEBUG(fq->owner = NULL); } -reiser4_internal void -fq_put(flush_queue_t * fq) +void fq_put(flush_queue_t * fq) { txn_atom *atom; @@ -647,18 +647,17 @@ fq_put(flush_queue_t * fq) /* A part of atom object initialization related to the embedded flush queue list head */ -reiser4_internal void -init_atom_fq_parts(txn_atom * atom) +void init_atom_fq_parts(txn_atom *atom) { - fq_list_init(&atom->flush_queues); + INIT_LIST_HEAD(&atom->flush_queues); } /* get a flush queue for an atom pointed by given jnode (spin-locked) ; returns * both atom and jnode locked and found and took exclusive access for flush * queue object. */ -reiser4_internal int fq_by_jnode_gfp(jnode * node, flush_queue_t ** fq, int gfp) +int fq_by_jnode_gfp(jnode * node, flush_queue_t ** fq, int gfp) { - txn_atom * atom; + txn_atom *atom; int ret; assert("zam-835", spin_jnode_is_locked(node)); @@ -691,7 +690,7 @@ reiser4_internal int fq_by_jnode_gfp(jno * time */ goto lock_again; return ret; - } + } /* It is correct to lock atom first, then lock a jnode */ LOCK_JNODE(node); @@ -710,14 +709,13 @@ reiser4_internal int fq_by_jnode_gfp(jno UNLOCK_ATOM(atom); - lock_again: + lock_again: LOCK_JNODE(node); } return 0; } - #if REISER4_DEBUG void check_fq(const txn_atom *atom) @@ -725,13 +723,14 @@ void check_fq(const txn_atom *atom) /* check number of nodes on all atom's flush queues */ flush_queue_t *fq; int count; - jnode *node; + struct list_head *pos1, *pos2; count = 0; - for_all_type_safe_list(fq, &atom->flush_queues, fq) { + list_for_each(pos1, &atom->flush_queues) { + fq = list_entry(pos1, flush_queue_t, alink); spin_lock_fq(fq); - for_all_type_safe_list(capture, ATOM_FQ_LIST(fq), node) - count ++; + list_for_each(pos2, ATOM_FQ_LIST(fq)) + count++; spin_unlock_fq(fq); } if (count != atom->fq) @@ -741,13 +740,13 @@ void check_fq(const txn_atom *atom) #endif -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 80 - scroll-step: 1 - End: -*/ +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 79 + * scroll-step: 1 + * End: + */ diff -puN fs/reiser4/forward.h~reiser4-big-update fs/reiser4/forward.h --- devel/fs/reiser4/forward.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/forward.h 2005-09-15 19:51:08.000000000 -0700 @@ -44,7 +44,6 @@ typedef struct reiser4_super_info_data r /* next two objects are fields of reiser4_super_info_data */ typedef struct reiser4_oid_allocator reiser4_oid_allocator; typedef struct reiser4_space_allocator reiser4_space_allocator; -typedef struct reiser4_file_fsdata reiser4_file_fsdata; typedef struct flush_scan flush_scan; typedef struct flush_position flush_pos_t; @@ -88,7 +87,7 @@ typedef enum { /* search exactly for the coord with key given */ FIND_EXACT, /* search for coord with the maximal key not greater than one - given */ + given */ FIND_MAX_NOT_MORE_THAN /*LEFT_SLANT_BIAS */ } lookup_bias; @@ -102,7 +101,7 @@ typedef enum { It is supposed that internal tree used by reiser4 to store file system data and meta data will have height 2 initially (when created by mkfs). - */ + */ TWIG_LEVEL = 2, } tree_level; @@ -113,12 +112,12 @@ typedef enum { /* enumeration of possible mutual position of item and coord. This enum is return type of ->is_in_item() item plugin method which see. */ typedef enum { - /* coord is on the left of an item*/ + /* coord is on the left of an item */ IP_ON_THE_LEFT, /* coord is inside item */ IP_INSIDE, /* coord is inside item, but to the right of the rightmost unit of - this item */ + this item */ IP_RIGHT_EDGE, /* coord is on the right of an item */ IP_ON_THE_RIGHT @@ -178,13 +177,13 @@ typedef enum { typedef enum { STATIC_STAT_DATA_ID = 0x0, SIMPLE_DIR_ENTRY_ID = 0x1, - COMPOUND_DIR_ID = 0x2, - NODE_POINTER_ID = 0x3, - EXTENT_POINTER_ID = 0x5, - FORMATTING_ID = 0x6, - CTAIL_ID = 0x7, - BLACK_BOX_ID = 0x8, - LAST_ITEM_ID = 0x9 + COMPOUND_DIR_ID = 0x2, + NODE_POINTER_ID = 0x3, + EXTENT_POINTER_ID = 0x5, + FORMATTING_ID = 0x6, + CTAIL_ID = 0x7, + BLACK_BOX_ID = 0x8, + LAST_ITEM_ID = 0x9 } item_id; /* Flags passed to jnode_flush() to allow it to distinguish default settings based on @@ -229,8 +228,8 @@ typedef enum { } cop_insert_flag; typedef enum { - SAFE_UNLINK, /* safe-link for unlink */ - SAFE_TRUNCATE /* safe-link for truncate */ + SAFE_UNLINK, /* safe-link for unlink */ + SAFE_TRUNCATE /* safe-link for truncate */ } reiser4_safe_link_t; /* this is to show on which list of atom jnode is */ diff -puN /dev/null fs/reiser4/fsdata.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/fs/reiser4/fsdata.c 2005-09-15 19:51:08.000000000 -0700 @@ -0,0 +1,782 @@ +/* Copyright 2001, 2002, 2003, 2004, 2005 by Hans Reiser, licensing governed by + * reiser4/README */ + +#include "fsdata.h" +#include "inode.h" + + +/* cache or dir_cursors */ +static kmem_cache_t *d_cursor_cache; +static struct shrinker *d_cursor_shrinker; + +/* list of unused cursors */ +static LIST_HEAD(cursor_cache); + +/* number of cursors in list of ununsed cursors */ +static unsigned long d_cursor_unused = 0; + +/* spinlock protecting manipulations with dir_cursor's hash table and lists */ +static spinlock_t d_lock = SPIN_LOCK_UNLOCKED; + +static void kill_cursor(dir_cursor *); + +/** + * d_cursor_shrink - shrink callback for cache of dir_cursor-s + * @nr: number of objects to free + * @mask: GFP mask + * + * Shrinks d_cursor_cache. Scan LRU list of unused cursors, freeing requested + * number. Return number of still freeable cursors. + */ +static int d_cursor_shrink(int nr, unsigned int mask) +{ + if (nr != 0) { + dir_cursor *scan; + int killed; + + killed = 0; + spin_lock(&d_lock); + while (!list_empty(&cursor_cache)) { + scan = list_entry(cursor_cache.next, dir_cursor, alist); + assert("nikita-3567", scan->ref == 0); + kill_cursor(scan); + ++killed; + --nr; + if (nr == 0) + break; + } + spin_unlock(&d_lock); + } + return d_cursor_unused; +} + +/** + * init_d_cursor - create d_cursor cache + * + * Initializes slab cache of d_cursors. It is part of reiser4 module + * initialization. + */ +int init_d_cursor(void) +{ + d_cursor_cache = kmem_cache_create("d_cursor", sizeof(dir_cursor), 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if (d_cursor_cache == NULL) + return RETERR(-ENOMEM); + + /* + * actually, d_cursors are "priceless", because there is no way to + * recover information stored in them. On the other hand, we don't + * want to consume all kernel memory by them. As a compromise, just + * assign higher "seeks" value to d_cursor cache, so that it will be + * shrunk only if system is really tight on memory. + */ + d_cursor_shrinker = set_shrinker(DEFAULT_SEEKS << 3, + d_cursor_shrink); + if (d_cursor_shrinker == NULL) { + destroy_reiser4_cache(&d_cursor_cache); + d_cursor_cache = NULL; + return RETERR(-ENOMEM); + } + return 0; +} + +/** + * done_d_cursor - delete d_cursor cache and d_cursor shrinker + * + * This is called on reiser4 module unloading or system shutdown. + */ +void done_d_cursor(void) +{ + BUG_ON(d_cursor_shrinker == NULL); + remove_shrinker(d_cursor_shrinker); + d_cursor_shrinker = NULL; + + destroy_reiser4_cache(&d_cursor_cache); +} + +#define D_CURSOR_TABLE_SIZE (256) + +static inline unsigned long +d_cursor_hash(d_cursor_hash_table *table, const d_cursor_key *key) +{ + assert("nikita-3555", IS_POW(D_CURSOR_TABLE_SIZE)); + return (key->oid + key->cid) & (D_CURSOR_TABLE_SIZE - 1); +} + +static inline int d_cursor_eq(const d_cursor_key *k1, const d_cursor_key *k2) +{ + return k1->cid == k2->cid && k1->oid == k2->oid; +} + +/* + * define functions to manipulate reiser4 super block's hash table of + * dir_cursors + */ +#define KMALLOC(size) kmalloc((size), GFP_KERNEL) +#define KFREE(ptr, size) kfree(ptr) +TYPE_SAFE_HASH_DEFINE(d_cursor, + dir_cursor, + d_cursor_key, key, hash, d_cursor_hash, d_cursor_eq); +#undef KFREE +#undef KMALLOC + +/** + * init_super_d_info - initialize per-super-block d_cursor resources + * @super: super block to initialize + * + * Initializes per-super-block d_cursor's hash table and radix tree. It is part + * of mount. + */ +int init_super_d_info(struct super_block *super) +{ + d_cursor_info *p; + + p = &get_super_private(super)->d_info; + + INIT_RADIX_TREE(&p->tree, GFP_KERNEL); + return d_cursor_hash_init(&p->table, D_CURSOR_TABLE_SIZE); +} + +/** + * done_super_d_info - release per-super-block d_cursor resources + * @super: super block being umounted + * + * Frees hash table. Radix tree of d_cursors has nothing to free. It is called + * on umount. + */ +void done_super_d_info(struct super_block *super) +{ + BUG_ON(get_super_private(super)->d_info.tree.rnode != NULL); + d_cursor_hash_done(&get_super_private(super)->d_info.table); +} + +/** + * kill_cursor - free dir_cursor and reiser4_file_fsdata attached to it + * @cursor: cursor to free + * + * Removes reiser4_file_fsdata attached to @cursor from readdir list of + * reiser4_inode, frees that reiser4_file_fsdata. Removes @cursor from from + * indices, hash table, list of unused cursors and frees it. + */ +static void kill_cursor(dir_cursor *cursor) +{ + unsigned long index; + + assert("nikita-3566", cursor->ref == 0); + assert("nikita-3572", cursor->fsdata != NULL); + + index = (unsigned long)cursor->key.oid; + list_del_init(&cursor->fsdata->dir.linkage); + free_fsdata(cursor->fsdata); + cursor->fsdata = NULL; + + if (list_empty_careful(&cursor->list)) + /* this is last cursor for a file. Kill radix-tree entry */ + radix_tree_delete(&cursor->info->tree, index); + else { + void **slot; + + /* + * there are other cursors for the same oid. + */ + + /* + * if radix tree point to the cursor being removed, re-target + * radix tree slot to the next cursor in the (non-empty as was + * checked above) element of the circular list of all cursors + * for this oid. + */ + slot = radix_tree_lookup_slot(&cursor->info->tree, index); + assert("nikita-3571", *slot != NULL); + if (*slot == cursor) + *slot = list_entry(cursor->list.next, dir_cursor, list); + /* remove cursor from circular list */ + list_del_init(&cursor->list); + } + /* remove cursor from the list of unused cursors */ + list_del_init(&cursor->alist); + /* remove cursor from the hash table */ + d_cursor_hash_remove(&cursor->info->table, cursor); + /* and free it */ + kmem_cache_free(d_cursor_cache, cursor); + --d_cursor_unused; +} + +/* possible actions that can be performed on all cursors for the given file */ +enum cursor_action { + /* + * load all detached state: this is called when stat-data is loaded + * from the disk to recover information about all pending readdirs + */ + CURSOR_LOAD, + /* + * detach all state from inode, leaving it in the cache. This is called + * when inode is removed form the memory by memory pressure + */ + CURSOR_DISPOSE, + /* + * detach cursors from the inode, and free them. This is called when + * inode is destroyed + */ + CURSOR_KILL +}; + +/* + * return d_cursor data for the file system @inode is in. + */ +static inline d_cursor_info *d_info(struct inode *inode) +{ + return &get_super_private(inode->i_sb)->d_info; +} + +/* + * lookup d_cursor in the per-super-block radix tree. + */ +static inline dir_cursor *lookup(d_cursor_info * info, unsigned long index) +{ + return (dir_cursor *) radix_tree_lookup(&info->tree, index); +} + +/* + * attach @cursor to the radix tree. There may be multiple cursors for the + * same oid, they are chained into circular list. + */ +static void bind_cursor(dir_cursor * cursor, unsigned long index) +{ + dir_cursor *head; + + head = lookup(cursor->info, index); + if (head == NULL) { + /* this is the first cursor for this index */ + INIT_LIST_HEAD(&cursor->list); + radix_tree_insert(&cursor->info->tree, index, cursor); + } else { + /* some cursor already exists. Chain ours */ + list_add(&cursor->list, &head->list); + } +} + +/* + * detach fsdata (if detachable) from file descriptor, and put cursor on the + * "unused" list. Called when file descriptor is not longer in active use. + */ +static void clean_fsdata(struct file *file) +{ + dir_cursor *cursor; + reiser4_file_fsdata *fsdata; + + assert("nikita-3570", file_is_stateless(file)); + + fsdata = (reiser4_file_fsdata *) file->private_data; + if (fsdata != NULL) { + cursor = fsdata->cursor; + if (cursor != NULL) { + spin_lock(&d_lock); + --cursor->ref; + if (cursor->ref == 0) { + list_add_tail(&cursor->alist, &cursor_cache); + ++d_cursor_unused; + } + spin_unlock(&d_lock); + file->private_data = NULL; + } + } +} + +/* + * global counter used to generate "client ids". These ids are encoded into + * high bits of fpos. + */ +static __u32 cid_counter = 0; +#define CID_SHIFT (20) +#define CID_MASK (0xfffffull) + +/** + * insert_cursor - allocate file_fsdata, insert cursor to tree and hash table + * @cursor: + * @file: + * @inode: + * + * Allocates reiser4_file_fsdata, attaches it to @cursor, inserts cursor to + * reiser4 super block's hash table and radix tree. + add detachable readdir + * state to the @f + */ +static int insert_cursor(dir_cursor *cursor, struct file *file, + struct inode *inode) +{ + int result; + reiser4_file_fsdata *fsdata; + + memset(cursor, 0, sizeof *cursor); + + /* this is either first call to readdir, or rewind. Anyway, create new + * cursor. */ + fsdata = create_fsdata(NULL); + if (fsdata != NULL) { + result = radix_tree_preload(GFP_KERNEL); + if (result == 0) { + d_cursor_info *info; + oid_t oid; + + info = d_info(inode); + oid = get_inode_oid(inode); + /* cid occupies higher 12 bits of f->f_pos. Don't + * allow it to become negative: this confuses + * nfsd_readdir() */ + cursor->key.cid = (++cid_counter) & 0x7ff; + cursor->key.oid = oid; + cursor->fsdata = fsdata; + cursor->info = info; + cursor->ref = 1; + spin_lock_inode(inode); + /* install cursor as @f's private_data, discarding old + * one if necessary */ +#if REISER4_DEBUG + if (file->private_data) + warning("", "file has fsdata already"); +#endif + clean_fsdata(file); + reiser4_free_file_fsdata(file); + file->private_data = fsdata; + fsdata->cursor = cursor; + spin_unlock_inode(inode); + spin_lock(&d_lock); + /* insert cursor into hash table */ + d_cursor_hash_insert(&info->table, cursor); + /* and chain it into radix-tree */ + bind_cursor(cursor, (unsigned long)oid); + spin_unlock(&d_lock); + radix_tree_preload_end(); + file->f_pos = ((__u64) cursor->key.cid) << CID_SHIFT; + } + } else + result = RETERR(-ENOMEM); + return result; +} + +/** + * process_cursors - do action on each cursor attached to inode + * @inode: + * @act: action to do + * + * Finds all cursors of @inode in reiser4's super block radix tree of cursors + * and performs action specified by @act on each of cursors. + */ +static void process_cursors(struct inode *inode, enum cursor_action act) +{ + oid_t oid; + dir_cursor *start; + struct list_head *head; + reiser4_context *ctx; + d_cursor_info *info; + + /* this can be called by + * + * kswapd->...->prune_icache->..reiser4_destroy_inode + * + * without reiser4_context + */ + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) { + warning("vs-23", "failed to init context"); + return; + } + + assert("nikita-3558", inode != NULL); + + info = d_info(inode); + oid = get_inode_oid(inode); + spin_lock_inode(inode); + head = get_readdir_list(inode); + spin_lock(&d_lock); + /* find any cursor for this oid: reference to it is hanging of radix + * tree */ + start = lookup(info, (unsigned long)oid); + if (start != NULL) { + dir_cursor *scan; + reiser4_file_fsdata *fsdata; + + /* process circular list of cursors for this oid */ + scan = start; + do { + dir_cursor *next; + + next = list_entry(scan->list.next, dir_cursor, list); + fsdata = scan->fsdata; + assert("nikita-3557", fsdata != NULL); + if (scan->key.oid == oid) { + switch (act) { + case CURSOR_DISPOSE: + list_del_init(&fsdata->dir.linkage); + break; + case CURSOR_LOAD: + list_add(&fsdata->dir.linkage, head); + break; + case CURSOR_KILL: + kill_cursor(scan); + break; + } + } + if (scan == next) + /* last cursor was just killed */ + break; + scan = next; + } while (scan != start); + } + spin_unlock(&d_lock); + /* check that we killed 'em all */ + assert("nikita-3568", + ergo(act == CURSOR_KILL, + list_empty_careful(get_readdir_list(inode)))); + assert("nikita-3569", + ergo(act == CURSOR_KILL, lookup(info, oid) == NULL)); + spin_unlock_inode(inode); + reiser4_exit_context(ctx); +} + +/** + * dispose_cursors - removes cursors from inode's list + * @inode: inode to dispose cursors of + * + * For each of cursors corresponding to @inode - removes reiser4_file_fsdata + * attached to cursor from inode's readdir list. This is called when inode is + * removed from the memory by memory pressure. + */ +void dispose_cursors(struct inode *inode) +{ + process_cursors(inode, CURSOR_DISPOSE); +} + +/** + * load_cursors - attach cursors to inode + * @inode: inode to load cursors to + * + * For each of cursors corresponding to @inode - attaches reiser4_file_fsdata + * attached to cursor to inode's readdir list. This is done when inode is + * loaded into memory. + */ +void load_cursors(struct inode *inode) +{ + process_cursors(inode, CURSOR_LOAD); +} + +/** + * kill_cursors - kill all inode cursors + * @inode: inode to kill cursors of + * + * Frees all cursors for this inode. This is called when inode is destroyed. + */ +void kill_cursors(struct inode *inode) +{ + process_cursors(inode, CURSOR_KILL); +} + +/** + * file_is_stateless - + * @file: + * + * true, if file descriptor @f is created by NFS server by "demand" to serve + * one file system operation. This means that there may be "detached state" + * for underlying inode. + */ +int file_is_stateless(struct file *file) +{ + return reiser4_get_dentry_fsdata(file->f_dentry)->stateless; +} + +/** + * get_dir_fpos - + * @dir: + * + * Calculates ->fpos from user-supplied cookie. Normally it is dir->f_pos, but + * in the case of stateless directory operation (readdir-over-nfs), client id + * was encoded in the high bits of cookie and should me masked off. + */ +loff_t get_dir_fpos(struct file *dir) +{ + if (file_is_stateless(dir)) + return dir->f_pos & CID_MASK; + else + return dir->f_pos; +} + +/** + * try_to_attach_fsdata - ??? + * @file: + * @inode: + * + * Finds or creates cursor for readdir-over-nfs. + */ +int try_to_attach_fsdata(struct file *file, struct inode *inode) +{ + loff_t pos; + int result; + dir_cursor *cursor; + + /* + * we are serialized by inode->i_sem + */ + if (!file_is_stateless(file)) + return 0; + + pos = file->f_pos; + result = 0; + if (pos == 0) { + /* + * first call to readdir (or rewind to the beginning of + * directory) + */ + cursor = kmem_cache_alloc(d_cursor_cache, GFP_KERNEL); + if (cursor != NULL) + result = insert_cursor(cursor, file, inode); + else + result = RETERR(-ENOMEM); + } else { + /* try to find existing cursor */ + d_cursor_key key; + + key.cid = pos >> CID_SHIFT; + key.oid = get_inode_oid(inode); + spin_lock(&d_lock); + cursor = d_cursor_hash_find(&d_info(inode)->table, &key); + if (cursor != NULL) { + /* cursor was found */ + if (cursor->ref == 0) { + /* move it from unused list */ + list_del_init(&cursor->alist); + --d_cursor_unused; + } + ++cursor->ref; + } + spin_unlock(&d_lock); + if (cursor != NULL) { + spin_lock_inode(inode); + assert("nikita-3556", cursor->fsdata->back == NULL); + clean_fsdata(file); + reiser4_free_file_fsdata(file); + file->private_data = cursor->fsdata; + spin_unlock_inode(inode); + } + } + return result; +} + +/** + * detach_fsdata - ??? + * @file: + * + * detach fsdata, if necessary + */ +void detach_fsdata(struct file *file) +{ + struct inode *inode; + + if (!file_is_stateless(file)) + return; + + inode = file->f_dentry->d_inode; + spin_lock_inode(inode); + clean_fsdata(file); + spin_unlock_inode(inode); +} + +/* slab for reiser4_dentry_fsdata */ +static kmem_cache_t *dentry_fsdata_cache; + +/** + * init_dentry_fsdata - create cache of dentry_fsdata + * + * Initializes slab cache of structures attached to denty->d_fsdata. It is + * part of reiser4 module initialization. + */ +int init_dentry_fsdata(void) +{ + dentry_fsdata_cache = kmem_cache_create("dentry_fsdata", + sizeof(reiser4_dentry_fsdata), + 0, + SLAB_HWCACHE_ALIGN | + SLAB_RECLAIM_ACCOUNT, NULL, + NULL); + if (dentry_fsdata_cache == NULL) + return RETERR(-ENOMEM); + return 0; +} + +/** + * done_dentry_fsdata - delete cache of dentry_fsdata + * + * This is called on reiser4 module unloading or system shutdown. + */ +void done_dentry_fsdata(void) +{ + destroy_reiser4_cache(&dentry_fsdata_cache); +} + +/** + * reiser4_get_dentry_fsdata - get fs-specific dentry data + * @dentry: queried dentry + * + * Allocates if necessary and returns per-dentry data that we attach to each + * dentry. + */ +reiser4_dentry_fsdata *reiser4_get_dentry_fsdata(struct dentry *dentry) +{ + assert("nikita-1365", dentry != NULL); + + if (dentry->d_fsdata == NULL) { + dentry->d_fsdata = kmem_cache_alloc(dentry_fsdata_cache, + GFP_KERNEL); + if (dentry->d_fsdata == NULL) + return ERR_PTR(RETERR(-ENOMEM)); + memset(dentry->d_fsdata, 0, sizeof(reiser4_dentry_fsdata)); + } + return dentry->d_fsdata; +} + +/** + * reiser4_free_dentry_fsdata - detach and free dentry_fsdata + * @dentry: dentry to free fsdata of + * + * Detaches and frees fs-specific dentry data + */ +void reiser4_free_dentry_fsdata(struct dentry *dentry) +{ + if (dentry->d_fsdata != NULL) { + kmem_cache_free(dentry_fsdata_cache, dentry->d_fsdata); + dentry->d_fsdata = NULL; + } +} + + +/* slab for reiser4_file_fsdata */ +static kmem_cache_t *file_fsdata_cache; + +/** + * init_file_fsdata - create cache of reiser4_file_fsdata + * + * Initializes slab cache of structures attached to file->private_data. It is + * part of reiser4 module initialization. + */ +int init_file_fsdata(void) +{ + file_fsdata_cache = kmem_cache_create("file_fsdata", + sizeof(reiser4_file_fsdata), + 0, + SLAB_HWCACHE_ALIGN | + SLAB_RECLAIM_ACCOUNT, NULL, NULL); + if (file_fsdata_cache == NULL) + return RETERR(-ENOMEM); + return 0; +} + +/** + * done_file_fsdata - delete cache of reiser4_file_fsdata + * + * This is called on reiser4 module unloading or system shutdown. + */ +void done_file_fsdata(void) +{ + destroy_reiser4_cache(&file_fsdata_cache); +} + +/** + * create_fsdata - allocate and initialize reiser4_file_fsdata + * @file: what to create file_fsdata for, may be NULL + * + * Allocates and initializes reiser4_file_fsdata structure. + */ +reiser4_file_fsdata *create_fsdata(struct file *file) +{ + reiser4_file_fsdata *fsdata; + + fsdata = kmem_cache_alloc(file_fsdata_cache, GFP_KERNEL); + if (fsdata != NULL) { + memset(fsdata, 0, sizeof *fsdata); + fsdata->ra1.max_window_size = VM_MAX_READAHEAD * 1024; + fsdata->back = file; + INIT_LIST_HEAD(&fsdata->dir.linkage); + } + return fsdata; +} + +/** + * free_fsdata - free reiser4_file_fsdata + * @fsdata: object to free + * + * Dual to create_fsdata(). Free reiser4_file_fsdata. + */ +void free_fsdata(reiser4_file_fsdata *fsdata) +{ + BUG_ON(fsdata == NULL); + kmem_cache_free(file_fsdata_cache, fsdata); +} + +/** + * reiser4_get_file_fsdata - get fs-specific file data + * @file: queried file + * + * Returns fs-specific data of @file. If it is NULL, allocates it and attaches + * to @file. + */ +reiser4_file_fsdata *reiser4_get_file_fsdata(struct file *file) +{ + assert("nikita-1603", file != NULL); + + if (file->private_data == NULL) { + reiser4_file_fsdata *fsdata; + struct inode *inode; + + fsdata = create_fsdata(file); + if (fsdata == NULL) + return ERR_PTR(RETERR(-ENOMEM)); + + inode = file->f_dentry->d_inode; + spin_lock_inode(inode); + if (file->private_data == NULL) { + file->private_data = fsdata; + fsdata = NULL; + } + spin_unlock_inode(inode); + if (fsdata != NULL) + /* other thread initialized ->fsdata */ + kmem_cache_free(file_fsdata_cache, fsdata); + } + assert("nikita-2665", file->private_data != NULL); + return file->private_data; +} + +/** + * reiser4_free_file_fsdata - detach from struct file and free reiser4_file_fsdata + * @file: + * + * Detaches reiser4_file_fsdata from @file, removes reiser4_file_fsdata from + * readdir list, frees if it is not linked to d_cursor object. + */ +void reiser4_free_file_fsdata(struct file *file) +{ + reiser4_file_fsdata *fsdata; + + spin_lock_inode(file->f_dentry->d_inode); + fsdata = file->private_data; + if (fsdata != NULL) { + list_del_init(&fsdata->dir.linkage); + if (fsdata->cursor == NULL) + free_fsdata(fsdata); + } + file->private_data = NULL; + + spin_unlock_inode(file->f_dentry->d_inode); +} + + + +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 79 + * End: + */ diff -puN /dev/null fs/reiser4/fsdata.h --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/fs/reiser4/fsdata.h 2005-09-15 19:51:08.000000000 -0700 @@ -0,0 +1,222 @@ +/* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by + * reiser4/README */ + +#if !defined( __REISER4_FSDATA_H__ ) +#define __REISER4_FSDATA_H__ + +#include "debug.h" +#include "kassign.h" +#include "seal.h" +#include "type_safe_hash.h" +#include "plugin/file/file.h" +#include "readahead.h" + +/* + * comment about reiser4_dentry_fsdata + * + * + */ + +/* + * locking: fields of per file descriptor readdir_pos and ->f_pos are + * protected by ->i_sem on inode. Under this lock following invariant + * holds: + * + * file descriptor is "looking" at the entry_no-th directory entry from + * the beginning of directory. This entry has key dir_entry_key and is + * pos-th entry with duplicate-key sequence. + * + */ + +/* logical position within directory */ +typedef struct { + /* key of directory entry (actually, part of a key sufficient to + identify directory entry) */ + de_id dir_entry_key; + /* ordinal number of directory entry among all entries with the same + key. (Starting from 0.) */ + unsigned pos; +} dir_pos; + +typedef struct { + /* f_pos corresponding to this readdir position */ + __u64 fpos; + /* logical position within directory */ + dir_pos position; + /* logical number of directory entry within + directory */ + __u64 entry_no; +} readdir_pos; + +/* + * this is used to speed up lookups for directory entry: on initial call to + * ->lookup() seal and coord of directory entry (if found, that is) are stored + * in struct dentry and reused later to avoid tree traversals. + */ +typedef struct de_location { + /* seal covering directory entry */ + seal_t entry_seal; + /* coord of directory entry */ + coord_t entry_coord; + /* ordinal number of directory entry among all entries with the same + key. (Starting from 0.) */ + int pos; +} de_location; + +/** + * reiser4_dentry_fsdata - reiser4-specific data attached to dentries + * + * This is allocated dynamically and released in d_op->d_release() + * + * Currently it only contains cached location (hint) of directory entry, but + * it is expected that other information will be accumulated here. + */ +typedef struct reiser4_dentry_fsdata { + /* + * here will go fields filled by ->lookup() to speedup next + * create/unlink, like blocknr of znode with stat-data, or key of + * stat-data. + */ + de_location dec; + int stateless; /* created through reiser4_decode_fh, needs special + * treatment in readdir. */ +} reiser4_dentry_fsdata; + +extern int init_dentry_fsdata(void); +extern void done_dentry_fsdata(void); +extern reiser4_dentry_fsdata *reiser4_get_dentry_fsdata(struct dentry *); +extern void reiser4_free_dentry_fsdata(struct dentry *dentry); + + +/** + * reiser4_file_fsdata - reiser4-specific data attached to file->private_data + * + * This is allocated dynamically and released in inode->i_fop->release + */ +typedef struct reiser4_file_fsdata { + /* + * pointer back to the struct file which this reiser4_file_fsdata is + * part of + */ + struct file *back; + /* detached cursor for stateless readdir. */ + struct dir_cursor *cursor; + /* + * We need both directory and regular file parts here, because there + * are file system objects that are files and directories. + */ + struct { + /* + * position in directory. It is updated each time directory is + * modified + */ + readdir_pos readdir; + /* head of this list is reiser4_inode->lists.readdir_list */ + struct list_head linkage; + } dir; + /* hints to speed up operations with regular files: read and write. */ + struct { + hint_t hint; + } reg; + /* */ + struct { + /* this is called by reiser4_readpages if set */ + void (*readpages) (struct address_space *, + struct list_head * pages, void *data); + /* reiser4_readpaextended coord. It is set by read_extent before + calling page_cache_readahead */ + void *data; + } ra2; + struct reiser4_file_ra_state ra1; + +} reiser4_file_fsdata; + +extern int init_file_fsdata(void); +extern void done_file_fsdata(void); +extern reiser4_file_fsdata *reiser4_get_file_fsdata(struct file *); +extern void reiser4_free_file_fsdata(struct file *); +extern reiser4_file_fsdata *create_fsdata(struct file *); +extern void free_fsdata(reiser4_file_fsdata *); + + +/* + * d_cursor is reiser4_file_fsdata not attached to struct file. d_cursors are + * used to address problem reiser4 has with readdir accesses via NFS. See + * plugin/file_ops_readdir.c for more details. + */ +typedef struct { + __u16 cid; + __u64 oid; +} d_cursor_key; + +/* + * define structures d_cursor_hash_table d_cursor_hash_link which are used to + * maintain hash table of dir_cursor-s in reiser4's super block + */ +typedef struct dir_cursor dir_cursor; +TYPE_SAFE_HASH_DECLARE(d_cursor, dir_cursor); + +typedef struct d_cursor_info d_cursor_info; + +struct dir_cursor { + int ref; + reiser4_file_fsdata *fsdata; + + /* link to reiser4 super block hash table of cursors */ + d_cursor_hash_link hash; + + /* + * this is to link cursors to reiser4 super block's radix tree of + * cursors if there are more than one cursor of the same objectid + */ + struct list_head list; + d_cursor_key key; + d_cursor_info *info; + /* list of unused cursors */ + struct list_head alist; +}; + +extern int init_d_cursor(void); +extern void done_d_cursor(void); + +extern int init_super_d_info(struct super_block *); +extern void done_super_d_info(struct super_block *); + +extern int file_is_stateless(struct file *); +extern loff_t get_dir_fpos(struct file *); +extern int try_to_attach_fsdata(struct file *, struct inode *); +extern void detach_fsdata(struct file *); + + +/* these are needed for "stateless" readdir. See plugin/file_ops_readdir.c for + more details */ +void dispose_cursors(struct inode *inode); +void load_cursors(struct inode *inode); +void kill_cursors(struct inode *inode); + + + + +void adjust_dir_file(struct inode *dir, const struct dentry *de, int offset, int adj); + +/* + * this structure is embedded to reise4_super_info_data. It maintains d_cursors + * (detached readdir state). See plugin/file_ops_readdir.c for more details. + */ +struct d_cursor_info { + d_cursor_hash_table table; + struct radix_tree_root tree; +}; + +/* __REISER4_FSDATA_H__ */ +#endif + +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 120 + * End: + */ diff -puN fs/reiser4/init_super.c~reiser4-big-update fs/reiser4/init_super.c --- devel/fs/reiser4/init_super.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/init_super.c 2005-09-15 19:51:08.000000000 -0700 @@ -1,61 +1,30 @@ /* Copyright by Hans Reiser, 2003 */ -#include "forward.h" -#include "debug.h" -#include "dformat.h" -#include "txnmgr.h" -#include "jnode.h" -#include "znode.h" -#include "tree.h" -#include "vfs_ops.h" -#include "inode.h" -#include "page_cache.h" -#include "ktxnmgrd.h" #include "super.h" -#include "reiser4.h" -#include "entd.h" -#include "emergency_flush.h" -#include "safe_link.h" -#include "plugin/dir/dir.h" - -#include -#include -#include -#include -#include -#include -#include - -#define _INIT_PARAM_LIST (struct super_block * s, reiser4_context * ctx, void * data, int silent) -#define _DONE_PARAM_LIST (struct super_block * s) +#include "inode.h" +#include "plugin/plugin_set.h" -#define _INIT_(subsys) static int _init_##subsys _INIT_PARAM_LIST -#define _DONE_(subsys) static void _done_##subsys _DONE_PARAM_LIST +#include -#define _DONE_EMPTY(subsys) _DONE_(subsys) {} -_INIT_(mount_flags_check) +/** + * init_fs_info - allocate reiser4 specific super block + * @super: super block of filesystem + * + * Allocates and initialize reiser4_super_info_data, attaches it to + * super->s_fs_info, initializes structures maintaining d_cursor-s. + */ +int init_fs_info(struct super_block *super) { -/* if (bdev_read_only(s->s_bdev) || (s->s_flags & MS_RDONLY)) { - warning("nikita-3322", "Readonly reiser4 is not yet supported"); - return RETERR(-EROFS); - }*/ - return 0; -} - -_DONE_EMPTY(mount_flags_check) + reiser4_super_info_data *sbinfo; -_INIT_(sinfo) -{ - reiser4_super_info_data * sbinfo; - - sbinfo = kmalloc(sizeof (reiser4_super_info_data), GFP_KERNEL); + sbinfo = kmalloc(sizeof(reiser4_super_info_data), GFP_KERNEL); if (!sbinfo) return RETERR(-ENOMEM); - s->s_fs_info = sbinfo; - s->s_op = NULL; - memset(sbinfo, 0, sizeof (*sbinfo)); + super->s_fs_info = sbinfo; + super->s_op = NULL; + memset(sbinfo, 0, sizeof(*sbinfo)); ON_DEBUG(INIT_LIST_HEAD(&sbinfo->all_jnodes)); ON_DEBUG(spin_lock_init(&sbinfo->all_guard)); @@ -63,343 +32,672 @@ _INIT_(sinfo) sema_init(&sbinfo->delete_sema, 1); sema_init(&sbinfo->flush_sema, 1); spin_super_init(sbinfo); +#if REISER4_USE_EFLUSH spin_super_eflush_init(sbinfo); +#endif + /* initialize per-super-block d_cursor resources */ + init_super_d_info(super); return 0; } -_DONE_(sinfo) -{ - assert("zam-990", s->s_fs_info != NULL); - rcu_barrier(); - kfree(s->s_fs_info); - s->s_fs_info = NULL; +/** + * done_fs_info - free reiser4 specific super block + * @super: super block of filesystem + * + * Performs some sanity checks, releases structures maintaining d_cursor-s, + * frees reiser4_super_info_data. + */ +void done_fs_info(struct super_block *super) +{ + assert("zam-990", super->s_fs_info != NULL); + + /* release per-super-block d_cursor resources */ + done_super_d_info(super); + + /* make sure that there are not jnodes already */ + assert("", list_empty(&get_super_private(super)->all_jnodes)); + assert("", get_current_context()->trans->atom == NULL); + check_block_counters(super); + kfree(super->s_fs_info); + super->s_fs_info = NULL; +} + +/* type of option parseable by parse_option() */ +typedef enum { + /* value of option is arbitrary string */ + OPT_STRING, + + /* + * option specifies bit in a bitmask. When option is set - bit in + * sbinfo->fs_flags is set. Examples are bsdgroups, 32bittimes, mtflush, + * dont_load_bitmap, atomic_write. + */ + OPT_BIT, + + /* + * value of option should conform to sprintf() format. Examples are + * tmgr.atom_max_size=N, tmgr.atom_max_age=N + */ + OPT_FORMAT, + + /* + * option can take one of predefined values. Example is onerror=panic or + * onerror=remount-ro + */ + OPT_ONEOF, +} opt_type_t; + +typedef struct opt_bitmask_bit { + const char *bit_name; + int bit_nr; +} opt_bitmask_bit; + +/* description of option parseable by parse_option() */ +typedef struct opt_desc { + /* option name. + + parsed portion of string has a form "name=value". + */ + const char *name; + /* type of option */ + opt_type_t type; + union { + /* where to store value of string option (type == OPT_STRING) */ + char **string; + /* description of bits for bit option (type == OPT_BIT) */ + struct { + int nr; + void *addr; + } bit; + /* description of format and targets for format option (type + == OPT_FORMAT) */ + struct { + const char *format; + int nr_args; + void *arg1; + void *arg2; + void *arg3; + void *arg4; + } f; + struct { + int *result; + const char *list[10]; + } oneof; + struct { + void *addr; + int nr_bits; + opt_bitmask_bit *bits; + } bitmask; + } u; +} opt_desc_t; + +/** + * parse_option - parse one option + * @opt_strin: starting point of parsing + * @opt: option description + * + * foo=bar, + * ^ ^ ^ + * | | +-- replaced to '\0' + * | +-- val_start + * +-- opt_string + * Figures out option type and handles option correspondingly. + */ +static int parse_option(char *opt_string, opt_desc_t *opt) +{ + char *val_start; + int result; + const char *err_msg; + + /* NOTE-NIKITA think about using lib/cmdline.c functions here. */ + + val_start = strchr(opt_string, '='); + if (val_start != NULL) { + *val_start = '\0'; + ++val_start; + } + + err_msg = NULL; + result = 0; + switch (opt->type) { + case OPT_STRING: + if (val_start == NULL) { + err_msg = "String arg missing"; + result = RETERR(-EINVAL); + } else + *opt->u.string = val_start; + break; + case OPT_BIT: + if (val_start != NULL) + err_msg = "Value ignored"; + else + set_bit(opt->u.bit.nr, opt->u.bit.addr); + break; + case OPT_FORMAT: + if (val_start == NULL) { + err_msg = "Formatted arg missing"; + result = RETERR(-EINVAL); + break; + } + if (sscanf(val_start, opt->u.f.format, + opt->u.f.arg1, opt->u.f.arg2, opt->u.f.arg3, + opt->u.f.arg4) != opt->u.f.nr_args) { + err_msg = "Wrong conversion"; + result = RETERR(-EINVAL); + } + break; + case OPT_ONEOF: + { + int i = 0; + + if (val_start == NULL) { + err_msg = "Value is missing"; + result = RETERR(-EINVAL); + break; + } + err_msg = "Wrong option value"; + result = RETERR(-EINVAL); + while (opt->u.oneof.list[i]) { + if (!strcmp(opt->u.oneof.list[i], val_start)) { + result = 0; + err_msg = NULL; + *opt->u.oneof.result = i; + break; + } + i++; + } + break; + } + default: + wrong_return_value("nikita-2100", "opt -> type"); + break; + } + if (err_msg != NULL) { + warning("nikita-2496", "%s when parsing option \"%s%s%s\"", + err_msg, opt->name, val_start ? "=" : "", + val_start ? : ""); + } + return result; } -_INIT_(context) -{ - return init_context(ctx, s); +/** + * parse_options - parse reiser4 mount options + * @opt_string: starting point + * @opts: array of option description + * @nr_opts: number of elements in @opts + * + * Parses comma separated list of reiser4 mount options. + */ +static int parse_options(char *opt_string, opt_desc_t *opts, int nr_opts) +{ + int result; + + result = 0; + while ((result == 0) && opt_string && *opt_string) { + int j; + char *next; + + next = strchr(opt_string, ','); + if (next != NULL) { + *next = '\0'; + ++next; + } + for (j = 0; j < nr_opts; ++j) { + if (!strncmp(opt_string, opts[j].name, + strlen(opts[j].name))) { + result = parse_option(opt_string, &opts[j]); + break; + } + } + if (j == nr_opts) { + warning("nikita-2307", "Unrecognized option: \"%s\"", + opt_string); + /* traditionally, -EINVAL is returned on wrong mount + option */ + result = RETERR(-EINVAL); + } + opt_string = next; + } + return result; } -_DONE_(context) -{ - reiser4_super_info_data * sbinfo; +#define NUM_OPT( label, fmt, addr ) \ + { \ + .name = ( label ), \ + .type = OPT_FORMAT, \ + .u = { \ + .f = { \ + .format = ( fmt ), \ + .nr_args = 1, \ + .arg1 = ( addr ), \ + .arg2 = NULL, \ + .arg3 = NULL, \ + .arg4 = NULL \ + } \ + } \ + } - sbinfo = get_super_private(s); +#define SB_FIELD_OPT( field, fmt ) NUM_OPT( #field, fmt, &sbinfo -> field ) - /* we don't want ->write_super to be called any more. */ - if (s->s_op) - s->s_op->write_super = NULL; -#if REISER4_DEBUG - { - struct list_head *scan; +#define BIT_OPT(label, bitnr) \ + { \ + .name = label, \ + .type = OPT_BIT, \ + .u = { \ + .bit = { \ + .nr = bitnr, \ + .addr = &sbinfo->fs_flags \ + } \ + } \ + } - /* print jnodes that survived umount. */ - list_for_each(scan, &sbinfo->all_jnodes) { - jnode *busy; +#define MAX_NR_OPTIONS (30) - busy = list_entry(scan, jnode, jnodes); - info_jnode("\nafter umount", busy); - } +/** + * init_super_data - initialize reiser4 private super block + * @super: super block to initialize + * @opt_string: list of reiser4 mount options + * + * Sets various reiser4 parameters to default values. Parses mount options and + * overwrites default settings. + */ +int init_super_data(struct super_block *super, char *opt_string) +{ + int result; + opt_desc_t *opts, *p; + reiser4_super_info_data *sbinfo = get_super_private(super); + + /* initialize super, export, dentry operations */ + sbinfo->ops.super = reiser4_super_operations; + sbinfo->ops.export = reiser4_export_operations; + sbinfo->ops.dentry = reiser4_dentry_operations; + super->s_op = &sbinfo->ops.super; + super->s_export_op = &sbinfo->ops.export; + + /* initialize transaction manager parameters to default values */ + sbinfo->tmgr.atom_max_size = totalram_pages / 4; + sbinfo->tmgr.atom_max_age = REISER4_ATOM_MAX_AGE / HZ; + sbinfo->tmgr.atom_min_size = 256; + sbinfo->tmgr.atom_max_flushers = ATOM_MAX_FLUSHERS; + + /* initialize cbk cache parameter */ + sbinfo->tree.cbk_cache.nr_slots = CBK_CACHE_SLOTS; + + /* initialize flush parameters */ + sbinfo->flush.relocate_threshold = FLUSH_RELOCATE_THRESHOLD; + sbinfo->flush.relocate_distance = FLUSH_RELOCATE_DISTANCE; + sbinfo->flush.written_threshold = FLUSH_WRITTEN_THRESHOLD; + sbinfo->flush.scan_maxnodes = FLUSH_SCAN_MAXNODES; + + sbinfo->optimal_io_size = REISER4_OPTIMAL_IO_SIZE; + + /* preliminary tree initializations */ + sbinfo->tree.super = super; + sbinfo->tree.carry.new_node_flags = REISER4_NEW_NODE_FLAGS; + sbinfo->tree.carry.new_extent_flags = REISER4_NEW_EXTENT_FLAGS; + sbinfo->tree.carry.paste_flags = REISER4_PASTE_FLAGS; + sbinfo->tree.carry.insert_flags = REISER4_INSERT_FLAGS; + + /* initialize default readahead params */ + sbinfo->ra_params.max = num_physpages / 4; + sbinfo->ra_params.flags = 0; + + /* allocate memory for structure describing reiser4 mount options */ + opts = kmalloc(sizeof(opt_desc_t) * MAX_NR_OPTIONS, GFP_KERNEL); + if (opts == NULL) + return RETERR(-ENOMEM); + + /* initialize structure describing reiser4 mount options */ + p = opts; + +#if REISER4_DEBUG +# define OPT_ARRAY_CHECK if ((p) > (opts) + MAX_NR_OPTIONS) { \ + warning ("zam-1046", "opt array is overloaded"); break; \ } - if (sbinfo->kmallocs > 0) - warning("nikita-2622", - "%i areas still allocated", sbinfo->kmallocs); +#else +# define OPT_ARRAY_CHECK noop #endif - get_current_context()->trans = NULL; - done_context(get_current_context()); -} +#define PUSH_OPT(...) \ +do { \ + opt_desc_t o = __VA_ARGS__; \ + OPT_ARRAY_CHECK; \ + *p ++ = o; \ +} while (0) + +#define PUSH_SB_FIELD_OPT(field, format) PUSH_OPT(SB_FIELD_OPT(field, format)) +#define PUSH_BIT_OPT(name, bit) PUSH_OPT(BIT_OPT(name, bit)) + + /* + * tmgr.atom_max_size=N + * Atoms containing more than N blocks will be forced to commit. N is + * decimal. + */ + PUSH_SB_FIELD_OPT(tmgr.atom_max_size, "%u"); + /* + * tmgr.atom_max_age=N + * Atoms older than N seconds will be forced to commit. N is decimal. + */ + PUSH_SB_FIELD_OPT(tmgr.atom_max_age, "%u"); + /* + * tmgr.atom_min_size=N + * In committing an atom to free dirty pages, force the atom less than + * N in size to fuse with another one. + */ + PUSH_SB_FIELD_OPT(tmgr.atom_min_size, "%u"); + /* + * tmgr.atom_max_flushers=N + * limit of concurrent flushers for one atom. 0 means no limit. + */ + PUSH_SB_FIELD_OPT(tmgr.atom_max_flushers, "%u"); + /* + * tree.cbk_cache_slots=N + * Number of slots in the cbk cache. + */ + PUSH_SB_FIELD_OPT(tree.cbk_cache.nr_slots, "%u"); + /* + * If flush finds more than FLUSH_RELOCATE_THRESHOLD adjacent dirty + * leaf-level blocks it will force them to be relocated. + */ + PUSH_SB_FIELD_OPT(flush.relocate_threshold, "%u"); + /* + * If flush finds can find a block allocation closer than at most + * FLUSH_RELOCATE_DISTANCE from the preceder it will relocate to that + * position. + */ + PUSH_SB_FIELD_OPT(flush.relocate_distance, "%u"); + /* + * If we have written this much or more blocks before encountering busy + * jnode in flush list - abort flushing hoping that next time we get + * called this jnode will be clean already, and we will save some + * seeks. + */ + PUSH_SB_FIELD_OPT(flush.written_threshold, "%u"); + /* The maximum number of nodes to scan left on a level during flush. */ + PUSH_SB_FIELD_OPT(flush.scan_maxnodes, "%u"); + /* preferred IO size */ + PUSH_SB_FIELD_OPT(optimal_io_size, "%u"); + /* carry flags used for insertion of new nodes */ + PUSH_SB_FIELD_OPT(tree.carry.new_node_flags, "%u"); + /* carry flags used for insertion of new extents */ + PUSH_SB_FIELD_OPT(tree.carry.new_extent_flags, "%u"); + /* carry flags used for paste operations */ + PUSH_SB_FIELD_OPT(tree.carry.paste_flags, "%u"); + /* carry flags used for insert operations */ + PUSH_SB_FIELD_OPT(tree.carry.insert_flags, "%u"); -_INIT_(parse_options) -{ - return reiser4_parse_options(s, data); -} +#ifdef CONFIG_REISER4_BADBLOCKS + /* + * Alternative master superblock location in case if it's original + * location is not writeable/accessable. This is offset in BYTES. + */ + PUSH_SB_FIELD_OPT(altsuper, "%lu"); +#endif -_DONE_(parse_options) -{ - return; -} + /* turn on BSD-style gid assignment */ + PUSH_BIT_OPT("bsdgroups", REISER4_BSD_GID); + /* turn on 32 bit times */ + PUSH_BIT_OPT("32bittimes", REISER4_32_BIT_TIMES); + /* turn off concurrent flushing */ + PUSH_BIT_OPT("mtflush", REISER4_MTFLUSH); + /* + * Don't load all bitmap blocks at mount time, it is useful for + * machines with tiny RAM and large disks. + */ + PUSH_BIT_OPT("dont_load_bitmap", REISER4_DONT_LOAD_BITMAP); + /* disable transaction commits during write() */ + PUSH_BIT_OPT("atomic_write", REISER4_ATOMIC_WRITE); -_INIT_(object_ops) -{ - build_object_ops(s, &get_super_private(s)->ops); - return 0; -} + PUSH_OPT( + { + /* + * tree traversal readahead parameters: + * -o readahead:MAXNUM:FLAGS + * MAXNUM - max number fo nodes to request readahead for: -1UL + * will set it to max_sane_readahead() + * FLAGS - combination of bits: RA_ADJCENT_ONLY, RA_ALL_LEVELS, + * CONTINUE_ON_PRESENT + */ + .name = "readahead", + .type = OPT_FORMAT, + .u = { + .f = { + .format = "%u:%u", + .nr_args = 2, + .arg1 = &sbinfo->ra_params.max, + .arg2 = &sbinfo->ra_params.flags, + .arg3 = NULL, + .arg4 = NULL + } + } + } + ); + + /* What to do in case of fs error */ + PUSH_OPT( + { + .name = "onerror", + .type = OPT_ONEOF, + .u = { + .oneof = { + .result = &sbinfo->onerror, + .list = { + "panic", "remount-ro", NULL + }, + } + } + } + ); -_DONE_EMPTY(object_ops) + /* modify default settings to values set by mount options */ + result = parse_options(opt_string, opts, p - opts); + kfree(opts); + if (result != 0) + return result; + + /* correct settings to sanity values */ + sbinfo->tmgr.atom_max_age *= HZ; + if (sbinfo->tmgr.atom_max_age <= 0) + /* overflow */ + sbinfo->tmgr.atom_max_age = REISER4_ATOM_MAX_AGE; + + /* round optimal io size up to 512 bytes */ + sbinfo->optimal_io_size >>= VFS_BLKSIZE_BITS; + sbinfo->optimal_io_size <<= VFS_BLKSIZE_BITS; + if (sbinfo->optimal_io_size == 0) { + warning("nikita-2497", "optimal_io_size is too small"); + return RETERR(-EINVAL); + } -_INIT_(read_super) + /* disable single-threaded flush as it leads to deadlock */ + sbinfo->fs_flags |= (1 << REISER4_MTFLUSH); + return result; +} + +/** + * init_read_super - read reiser4 master super block + * @super: super block to fill + * @silent: if 0 - print warnings + * + * Reads reiser4 master super block either from predefined location or from + * location specified by altsuper mount option, initializes disk format plugin. + */ +int init_read_super(struct super_block *super, int silent) { struct buffer_head *super_bh; struct reiser4_master_sb *master_sb; - int plugin_id; - reiser4_super_info_data * sbinfo = get_super_private(s); + reiser4_super_info_data *sbinfo = get_super_private(super); unsigned long blocksize; read_super_block: #ifdef CONFIG_REISER4_BADBLOCKS - if ( sbinfo->altsuper ) - super_bh = sb_bread(s, (sector_t) (sbinfo->altsuper >> s->s_blocksize_bits)); + if (sbinfo->altsuper) + /* + * read reiser4 master super block at position specified by + * mount option + */ + super_bh = sb_bread(super, + (sector_t)(sbinfo->altsuper / super->s_blocksize)); else #endif - /* look for reiser4 magic at hardcoded place */ - super_bh = sb_bread(s, (sector_t) (REISER4_MAGIC_OFFSET / s->s_blocksize)); - + /* read reiser4 master super block at 16-th 4096 block */ + super_bh = sb_bread(super, + (sector_t)(REISER4_MAGIC_OFFSET / super->s_blocksize)); if (!super_bh) return RETERR(-EIO); - master_sb = (struct reiser4_master_sb *) super_bh->b_data; + master_sb = (struct reiser4_master_sb *)super_bh->b_data; /* check reiser4 magic string */ - if (!strncmp(master_sb->magic, REISER4_SUPER_MAGIC_STRING, sizeof(REISER4_SUPER_MAGIC_STRING))) { - /* reset block size if it is not a right one FIXME-VS: better comment is needed */ + if (!strncmp(master_sb->magic, REISER4_SUPER_MAGIC_STRING, + sizeof(REISER4_SUPER_MAGIC_STRING))) { + /* reiser4 master super block contains filesystem blocksize */ blocksize = d16tocpu(&master_sb->blocksize); if (blocksize != PAGE_CACHE_SIZE) { + /* + * currenly reiser4's blocksize must be equal to + * pagesize + */ if (!silent) - warning("nikita-2609", "%s: wrong block size %ld\n", s->s_id, blocksize); + warning("nikita-2609", + "%s: wrong block size %ld\n", super->s_id, + blocksize); brelse(super_bh); return RETERR(-EINVAL); } - if (blocksize != s->s_blocksize) { + if (blocksize != super->s_blocksize) { + /* + * filesystem uses different blocksize. Reread master + * super block with correct blocksize + */ brelse(super_bh); - if (!sb_set_blocksize(s, (int) blocksize)) { + if (!sb_set_blocksize(super, (int)blocksize)) return RETERR(-EINVAL); - } goto read_super_block; } - plugin_id = d16tocpu(&master_sb->disk_plugin_id); - /* only two plugins are available for now */ - assert("vs-476", plugin_id == FORMAT40_ID); - sbinfo->df_plug = disk_format_plugin_by_id(plugin_id); - sbinfo->diskmap_block = d64tocpu(&master_sb->diskmap); - brelse(super_bh); - } else { - if (!silent) { - warning("nikita-2608", "%s: wrong master super block magic.", s->s_id); + sbinfo->df_plug = disk_format_plugin_by_id(d16tocpu(&master_sb->disk_plugin_id)); + if (sbinfo->df_plug == NULL) { + if (!silent) + warning("nikita-26091", + "%s: unknown disk format plugin %d\n", + super->s_id, + d16tocpu(&master_sb->disk_plugin_id)); + brelse(super_bh); + return RETERR(-EINVAL); } - - /* no standard reiser4 super block found */ + sbinfo->diskmap_block = d64tocpu(&master_sb->diskmap); brelse(super_bh); - /* FIXME-VS: call guess method for all available layout - plugins */ - /* umka (2002.06.12) Is it possible when format-specific super - block exists but there no master super block? */ - return RETERR(-EINVAL); + return 0; } - return 0; -} - -_DONE_EMPTY(read_super) - -_INIT_(tree0) -{ - reiser4_super_info_data * sbinfo = get_super_private(s); - init_tree_0(&sbinfo->tree); - sbinfo->tree.super = s; - return 0; -} - -_DONE_EMPTY(tree0) - -_INIT_(txnmgr) -{ - txnmgr_init(&get_super_private(s)->tmgr); - return 0; -} - -_DONE_(txnmgr) -{ - txnmgr_done(&get_super_private(s)->tmgr); -} - -_INIT_(ktxnmgrd_context) -{ - return init_ktxnmgrd_context(&get_super_private(s)->tmgr); -} - -_DONE_(ktxnmgrd_context) -{ - done_ktxnmgrd_context(&get_super_private(s)->tmgr); -} - -_INIT_(ktxnmgrd) -{ - return start_ktxnmgrd(&get_super_private(s)->tmgr); -} - -_DONE_(ktxnmgrd) -{ - stop_ktxnmgrd(&get_super_private(s)->tmgr); -} - -_INIT_(formatted_fake) -{ - return init_formatted_fake(s); -} - -_DONE_(formatted_fake) -{ - reiser4_super_info_data * sbinfo; - - sbinfo = get_super_private(s); - - rcu_barrier(); - - /* done_formatted_fake just has finished with last jnodes (bitmap - * ones) */ - done_tree(&sbinfo->tree); - /* call finish_rcu(), because some znode were "released" in - * done_tree(). */ - rcu_barrier(); - done_formatted_fake(s); -} - -_INIT_(entd) -{ - init_entd_context(s); - return 0; -} - -_DONE_(entd) -{ - done_entd_context(s); -} - -_DONE_(disk_format); - -_INIT_(disk_format) -{ - return get_super_private(s)->df_plug->get_ready(s, data); -} - -_DONE_(disk_format) -{ - reiser4_super_info_data *sbinfo = get_super_private(s); - - sbinfo->df_plug->release(s); -} - -_INIT_(sb_counters) -{ - /* There are some 'committed' versions of reiser4 super block - counters, which correspond to reiser4 on-disk state. These counters - are initialized here */ - reiser4_super_info_data *sbinfo = get_super_private(s); - - sbinfo->blocks_free_committed = sbinfo->blocks_free; - sbinfo->nr_files_committed = oids_used(s); - - return 0; -} - -_DONE_EMPTY(sb_counters) - -_INIT_(d_cursor) -{ - /* this should be done before reading inode of root directory, because - * reiser4_iget() used load_cursors(). */ - return d_cursor_init_at(s); -} - -_DONE_(d_cursor) -{ - d_cursor_done_at(s); + /* there is no reiser4 on the device */ + if (!silent) + warning("nikita-2608", + "%s: wrong master super block magic", super->s_id); + brelse(super_bh); + return RETERR(-EINVAL); } static struct { reiser4_plugin_type type; - reiser4_plugin_id id; + reiser4_plugin_id id; } default_plugins[PSET_LAST] = { [PSET_FILE] = { .type = REISER4_FILE_PLUGIN_TYPE, - .id = UNIX_FILE_PLUGIN_ID + .id = UNIX_FILE_PLUGIN_ID }, [PSET_DIR] = { .type = REISER4_DIR_PLUGIN_TYPE, - .id = HASHED_DIR_PLUGIN_ID + .id = HASHED_DIR_PLUGIN_ID }, [PSET_HASH] = { .type = REISER4_HASH_PLUGIN_TYPE, - .id = R5_HASH_ID + .id = R5_HASH_ID }, [PSET_FIBRATION] = { .type = REISER4_FIBRATION_PLUGIN_TYPE, - .id = FIBRATION_DOT_O + .id = FIBRATION_DOT_O }, [PSET_PERM] = { .type = REISER4_PERM_PLUGIN_TYPE, - .id = RWX_PERM_ID + .id = RWX_PERM_ID }, [PSET_FORMATTING] = { .type = REISER4_FORMATTING_PLUGIN_TYPE, - .id = SMALL_FILE_FORMATTING_ID + .id = SMALL_FILE_FORMATTING_ID }, [PSET_SD] = { .type = REISER4_ITEM_PLUGIN_TYPE, - .id = STATIC_STAT_DATA_ID + .id = STATIC_STAT_DATA_ID }, [PSET_DIR_ITEM] = { .type = REISER4_ITEM_PLUGIN_TYPE, - .id = COMPOUND_DIR_ID + .id = COMPOUND_DIR_ID }, [PSET_CRYPTO] = { .type = REISER4_CRYPTO_PLUGIN_TYPE, - .id = NONE_CRYPTO_ID + .id = NONE_CRYPTO_ID }, [PSET_DIGEST] = { .type = REISER4_DIGEST_PLUGIN_TYPE, - .id = NONE_DIGEST_ID + .id = NONE_DIGEST_ID }, [PSET_COMPRESSION] = { .type = REISER4_COMPRESSION_PLUGIN_TYPE, - .id = LZO1_COMPRESSION_ID + .id = LZO1_COMPRESSION_ID }, [PSET_COMPRESSION_MODE] = { .type = REISER4_COMPRESSION_MODE_PLUGIN_TYPE, - .id = SMART_COMPRESSION_MODE_ID + .id = SMART_COMPRESSION_MODE_ID }, [PSET_CLUSTER] = { .type = REISER4_CLUSTER_PLUGIN_TYPE, - .id = CLUSTER_64K_ID + .id = CLUSTER_64K_ID }, [PSET_REGULAR_ENTRY] = { .type = REISER4_REGULAR_PLUGIN_TYPE, - .id = UF_REGULAR_ID + .id = UF_REGULAR_ID } }; /* access to default plugin table */ -reiser4_internal reiser4_plugin * -get_default_plugin(pset_member memb) +reiser4_plugin *get_default_plugin(pset_member memb) { - return plugin_by_id(default_plugins[memb].type, default_plugins[memb].id); + return plugin_by_id(default_plugins[memb].type, + default_plugins[memb].id); } -_INIT_(fs_root) +/** + * init_root_inode - obtain inode of root directory + * @super: super block of filesystem + * + * Obtains inode of root directory (reading it from disk), initializes plugin + * set it was not initialized. + */ +int init_root_inode(struct super_block *super) { - reiser4_super_info_data *sbinfo = get_super_private(s); - struct inode * inode; + reiser4_super_info_data *sbinfo = get_super_private(super); + struct inode *inode; int result = 0; - inode = reiser4_iget(s, sbinfo->df_plug->root_dir_key(s), 0); + inode = reiser4_iget(super, sbinfo->df_plug->root_dir_key(super), 0); if (IS_ERR(inode)) return RETERR(PTR_ERR(inode)); - s->s_root = d_alloc_root(inode); - if (!s->s_root) { + super->s_root = d_alloc_root(inode); + if (!super->s_root) { iput(inode); return RETERR(-ENOMEM); } - s->s_root->d_op = &sbinfo->ops.dentry; + super->s_root->d_op = &sbinfo->ops.dentry; if (!is_inode_loaded(inode)) { - pset_member memb; + pset_member memb; - for (memb = 0; memb < PSET_LAST; ++ memb) { + for (memb = 0; memb < PSET_LAST; ++memb) { reiser4_plugin *plug; plug = get_default_plugin(memb); @@ -413,7 +711,7 @@ _INIT_(fs_root) plugin_set *pset; pset = reiser4_inode_data(inode)->pset; - for (memb = 0; memb < PSET_LAST; ++ memb) + for (memb = 0; memb < PSET_LAST; ++memb) assert("nikita-3500", pset_get(pset, memb) != NULL); } @@ -422,117 +720,33 @@ _INIT_(fs_root) result); reiser4_iget_complete(inode); } - s->s_maxbytes = MAX_LFS_FILESIZE; + super->s_maxbytes = MAX_LFS_FILESIZE; return result; } -_DONE_(fs_root) -{ - shrink_dcache_parent(s->s_root); - assert("vs-1714", hlist_empty(&s->s_anon)); - dput(s->s_root); - s->s_root = NULL; - invalidate_inodes(s); - -} - -_INIT_(safelink) -{ - process_safelinks(s); - /* failure to process safe-links is not critical. Continue with - * mount. */ - return 0; -} - -_DONE_(safelink) -{ -} - -_INIT_(exit_context) -{ - reiser4_exit_context(ctx); - return 0; -} - -_DONE_EMPTY(exit_context) - -struct reiser4_subsys { - int (*init) _INIT_PARAM_LIST; - void (*done) _DONE_PARAM_LIST; -}; - -#define _SUBSYS(subsys) {.init = &_init_##subsys, .done = &_done_##subsys} -static struct reiser4_subsys subsys_array[] = { - _SUBSYS(mount_flags_check), - _SUBSYS(sinfo), - _SUBSYS(context), - _SUBSYS(parse_options), - _SUBSYS(object_ops), - _SUBSYS(read_super), - _SUBSYS(tree0), - _SUBSYS(txnmgr), - _SUBSYS(ktxnmgrd_context), - _SUBSYS(ktxnmgrd), - _SUBSYS(entd), - _SUBSYS(formatted_fake), - _SUBSYS(disk_format), - _SUBSYS(sb_counters), - _SUBSYS(d_cursor), - _SUBSYS(fs_root), - _SUBSYS(safelink), - _SUBSYS(exit_context) -}; - -#define REISER4_NR_SUBSYS (sizeof(subsys_array) / sizeof(struct reiser4_subsys)) - -static void done_super (struct super_block * s, int last_done) -{ - int i; - for (i = last_done; i >= 0; i--) - subsys_array[i].done(s); -} - -/* read super block from device and fill remaining fields in @s. - - This is read_super() of the past. */ -reiser4_internal int -reiser4_fill_super (struct super_block * s, void * data, int silent) -{ - reiser4_context ctx; - int i; - int ret; - - assert ("zam-989", s != NULL); - - for (i = 0; i < REISER4_NR_SUBSYS; i++) { - ret = subsys_array[i].init(s, &ctx, data, silent); - if (ret) { - done_super(s, i - 1); - return ret; - } - } - return 0; -} - -#if 0 - -int reiser4_done_super (struct super_block * s) -{ - reiser4_context ctx; - - init_context(&ctx, s); - done_super(s, REISER4_NR_SUBSYS - 1); - return 0; -} - -#endif - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 80 - End: -*/ +/** + * done_root_inode - put inode of root directory + * @super: super block of filesystem + * + * Puts inode of root directory. + */ +void done_root_inode(struct super_block *super) +{ + /* remove unused children of the parent dentry */ + shrink_dcache_parent(super->s_root); + assert("vs-1714", hlist_empty(&super->s_anon)); + dput(super->s_root); + super->s_root = NULL; + /* discard all inodes of filesystem */ + invalidate_inodes(super); +} + +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 79 + * End: + */ diff -puN fs/reiser4/init_super.h~reiser4-big-update fs/reiser4/init_super.h --- devel/fs/reiser4/init_super.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/init_super.h 2005-09-15 19:51:08.000000000 -0700 @@ -1,4 +1,3 @@ /* Copyright by Hans Reiser, 2003 */ -extern int reiser4_fill_super (struct super_block * s, void * data, int silent); -extern int reiser4_done_super (struct super_block * s); + diff -puN fs/reiser4/inode.c~reiser4-big-update fs/reiser4/inode.c --- devel/fs/reiser4/inode.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/inode.c 2005-09-15 19:51:08.000000000 -0700 @@ -13,7 +13,6 @@ #include "plugin/security/perm.h" #include "plugin/plugin.h" #include "plugin/object.h" -#include "plugin/dir/dir.h" #include "znode.h" #include "vfs_ops.h" #include "inode.h" @@ -24,8 +23,7 @@ /* return reiser4 internal tree which inode belongs to */ /* Audited by: green(2002.06.17) */ -reiser4_internal reiser4_tree * -tree_by_inode(const struct inode * inode /* inode queried */ ) +reiser4_tree *tree_by_inode(const struct inode *inode /* inode queried */ ) { assert("nikita-256", inode != NULL); assert("nikita-257", inode->i_sb != NULL); @@ -33,45 +31,41 @@ tree_by_inode(const struct inode * inode } /* return reiser4-specific inode flags */ -static inline unsigned long * -inode_flags(const struct inode * const inode) +static inline unsigned long *inode_flags(const struct inode *const inode) { assert("nikita-2842", inode != NULL); return &reiser4_inode_data(inode)->flags; } /* set reiser4-specific flag @f in @inode */ -reiser4_internal void -inode_set_flag(struct inode * inode, reiser4_file_plugin_flags f) +void inode_set_flag(struct inode *inode, reiser4_file_plugin_flags f) { assert("nikita-2248", inode != NULL); - set_bit((int) f, inode_flags(inode)); + set_bit((int)f, inode_flags(inode)); } /* clear reiser4-specific flag @f in @inode */ -reiser4_internal void -inode_clr_flag(struct inode * inode, reiser4_file_plugin_flags f) +void inode_clr_flag(struct inode *inode, reiser4_file_plugin_flags f) { assert("nikita-2250", inode != NULL); - clear_bit((int) f, inode_flags(inode)); + clear_bit((int)f, inode_flags(inode)); } /* true if reiser4-specific flag @f is set in @inode */ -reiser4_internal int -inode_get_flag(const struct inode * inode, reiser4_file_plugin_flags f) +int inode_get_flag(const struct inode *inode, reiser4_file_plugin_flags f) { assert("nikita-2251", inode != NULL); - return test_bit((int) f, inode_flags(inode)); + return test_bit((int)f, inode_flags(inode)); } /* convert oid to inode number */ -reiser4_internal ino_t oid_to_ino(oid_t oid) +ino_t oid_to_ino(oid_t oid) { return (ino_t) oid; } /* convert oid to user visible inode number */ -reiser4_internal ino_t oid_to_uino(oid_t oid) +ino_t oid_to_uino(oid_t oid) { /* reiser4 object is uniquely identified by oid which is 64 bit quantity. Kernel in-memory inode is indexed (in the hash table) by @@ -82,7 +76,7 @@ reiser4_internal ino_t oid_to_uino(oid_t But user space expects unique 32 bit inode number. Obviously this is impossible. Work-around is to somehow hash oid into user visible inode number. - */ + */ oid_t max_ino = (ino_t) ~ 0; if (REISER4_INO_IS_OID || (oid <= max_ino)) @@ -92,26 +86,20 @@ reiser4_internal ino_t oid_to_uino(oid_t to use for process: after wrap-around start from some offset rather than from 0. Idea is that there are some long living objects with which we don't want to collide. - */ + */ return REISER4_UINO_SHIFT + ((oid - max_ino) & (max_ino >> 1)); } /* check that "inode" is on reiser4 file-system */ -reiser4_internal int -is_reiser4_inode(const struct inode *inode /* inode queried */ ) +int is_reiser4_inode(const struct inode *inode /* inode queried */ ) { - return - inode != NULL && - (is_reiser4_super(inode->i_sb) || - inode->i_op == &reiser4_inode_operations); - + return inode != NULL && is_reiser4_super(inode->i_sb); } /* Maximal length of a name that can be stored in directory @inode. This is used in check during file creation and lookup. */ -reiser4_internal int -reiser4_max_filename_len(const struct inode *inode /* inode queried */ ) +int reiser4_max_filename_len(const struct inode *inode /* inode queried */ ) { assert("nikita-287", is_reiser4_inode(inode)); assert("nikita-1710", inode_dir_item_plugin(inode)); @@ -122,26 +110,29 @@ reiser4_max_filename_len(const struct in } /* Maximal number of hash collisions for this directory. */ -reiser4_internal int -max_hash_collisions(const struct inode *dir /* inode queried */ ) +int max_hash_collisions(const struct inode *dir /* inode queried */ ) { assert("nikita-1711", dir != NULL); #if REISER4_USE_COLLISION_LIMIT return reiser4_inode_data(dir)->plugin.max_collisions; #else - (void) dir; + (void)dir; return ~0; #endif } /* Install file, inode, and address_space operation on @inode, depending on its mode. */ -reiser4_internal int -setup_inode_ops(struct inode *inode /* inode to intialise */ , - reiser4_object_create_data * data /* parameters to create +int setup_inode_ops(struct inode *inode /* inode to intialize */ , + reiser4_object_create_data * data /* parameters to create * object */ ) { reiser4_super_info_data *sinfo; + file_plugin *fplug; + dir_plugin *dplug; + + fplug = inode_file_plugin(inode); + dplug = inode_dir_plugin(inode); sinfo = get_super_private(inode->i_sb); @@ -149,9 +140,11 @@ setup_inode_ops(struct inode *inode /* i case S_IFSOCK: case S_IFBLK: case S_IFCHR: - case S_IFIFO:{ + case S_IFIFO: + { dev_t rdev; /* to keep gcc happy */ + assert("vs-46", fplug != NULL); /* ugly hack with rdev */ if (data == NULL) { rdev = inode->i_rdev; @@ -159,28 +152,43 @@ setup_inode_ops(struct inode *inode /* i } else rdev = data->rdev; inode->i_blocks = 0; - inode->i_op = &sinfo->ops.special; - /* other fields are already initialised. */ + assert("vs-42", fplug->h.id == SPECIAL_FILE_PLUGIN_ID); + inode->i_op = &file_plugins[fplug->h.id].inode_ops; + /* initialize inode->i_fop and inode->i_rdev for block and char + devices */ init_special_inode(inode, inode->i_mode, rdev); + /* all address space operations are null */ + inode->i_mapping->a_ops = + &file_plugins[fplug->h.id].as_ops; break; } case S_IFLNK: - inode->i_op = &sinfo->ops.symlink; + assert("vs-46", fplug != NULL); + assert("vs-42", fplug->h.id == SYMLINK_FILE_PLUGIN_ID); + inode->i_op = &file_plugins[fplug->h.id].inode_ops; inode->i_fop = NULL; - inode->i_mapping->a_ops = &sinfo->ops.as; + /* all address space operations are null */ + inode->i_mapping->a_ops = &file_plugins[fplug->h.id].as_ops; break; case S_IFDIR: - inode->i_op = &sinfo->ops.dir; - inode->i_fop = &sinfo->ops.file; - inode->i_mapping->a_ops = &sinfo->ops.as; + assert("vs-46", dplug != NULL); + assert("vs-43", (dplug->h.id == HASHED_DIR_PLUGIN_ID || + dplug->h.id == SEEKABLE_HASHED_DIR_PLUGIN_ID)); + inode->i_op = &dir_plugins[dplug->h.id].inode_ops; + inode->i_fop = &dir_plugins[dplug->h.id].file_ops; + inode->i_mapping->a_ops = &dir_plugins[dplug->h.id].as_ops; break; case S_IFREG: - inode->i_op = &sinfo->ops.regular; - inode->i_fop = &sinfo->ops.file; - inode->i_mapping->a_ops = &sinfo->ops.as; + assert("vs-46", fplug != NULL); + assert("vs-43", (fplug->h.id == UNIX_FILE_PLUGIN_ID || + fplug->h.id == CRC_FILE_PLUGIN_ID)); + inode->i_op = &file_plugins[fplug->h.id].inode_ops; + inode->i_fop = &file_plugins[fplug->h.id].file_ops; + inode->i_mapping->a_ops = &file_plugins[fplug->h.id].as_ops; break; default: - warning("nikita-291", "wrong file mode: %o for %llu", inode->i_mode, + warning("nikita-291", "wrong file mode: %o for %llu", + inode->i_mode, (unsigned long long)get_inode_oid(inode)); reiser4_make_bad_inode(inode); return RETERR(-EINVAL); @@ -188,11 +196,10 @@ setup_inode_ops(struct inode *inode /* i return 0; } -/* initialise inode from disk data. Called with inode locked. +/* initialize inode from disk data. Called with inode locked. Return inode locked. */ -static int -init_inode(struct inode *inode /* inode to intialise */ , - coord_t * coord /* coord of stat data */ ) +static int init_inode(struct inode *inode /* inode to intialise */ , + coord_t * coord /* coord of stat data */ ) { int result; item_plugin *iplug; @@ -226,11 +233,11 @@ init_inode(struct inode *inode /* inode if (result == 0 && inode->i_sb->s_root && inode->i_sb->s_root->d_inode) { struct inode *root; - pset_member ind; + pset_member ind; /* take missing plugins from file-system defaults */ root = inode->i_sb->s_root->d_inode; - /* file and directory plugins are already initialised. */ + /* file and directory plugins are already initialized. */ for (ind = PSET_DIR + 1; ind < PSET_LAST; ++ind) { result = grab_plugin(inode, root, ind); if (result != 0) @@ -239,7 +246,8 @@ init_inode(struct inode *inode /* inode if (result != 0) { warning("nikita-3447", "Cannot set up plugins for %lli", - (unsigned long long)get_inode_oid(inode)); + (unsigned long long) + get_inode_oid(inode)); } } } @@ -252,10 +260,9 @@ init_inode(struct inode *inode /* inode Must be called with inode locked. Return inode still locked. */ -static int -read_inode(struct inode *inode /* inode to read from disk */ , - const reiser4_key * key /* key of stat data */, - int silent) +static int read_inode(struct inode *inode /* inode to read from disk */ , + const reiser4_key * key /* key of stat data */ , + int silent) { int result; lock_handle lh; @@ -294,7 +301,9 @@ read_inode(struct inode *inode /* inode load_cursors(inode); /* Check the opened inode for consistency. */ - result = get_super_private(inode->i_sb)->df_plug->check_open(inode); + result = + get_super_private(inode->i_sb)->df_plug-> + check_open(inode); } } /* lookup_sd() doesn't release coord because we want znode @@ -308,10 +317,9 @@ read_inode(struct inode *inode /* inode } /* initialise new reiser4 inode being inserted into hash table. */ -static int -init_locked_inode(struct inode *inode /* new inode */ , - void *opaque /* key of stat data passed to the - * iget5_locked as cookie */ ) +static int init_locked_inode(struct inode *inode /* new inode */ , + void *opaque /* key of stat data passed to the + * iget5_locked as cookie */ ) { reiser4_key *key; @@ -331,45 +339,44 @@ init_locked_inode(struct inode *inode /* (objectids) are distinguished by their packing locality. */ -static int -reiser4_inode_find_actor(struct inode *inode /* inode from hash table to - * check */ , - void *opaque /* "cookie" passed to - * iget5_locked(). This is stat data - * key */ ) +static int reiser4_inode_find_actor(struct inode *inode /* inode from hash table to + * check */ , + void *opaque /* "cookie" passed to + * iget5_locked(). This is stat data + * key */ ) { reiser4_key *key; key = opaque; return - /* oid is unique, so first term is enough, actually. */ - get_inode_oid(inode) == get_key_objectid(key) && - /* - * also, locality should be checked, but locality is stored in - * the reiser4-specific part of the inode, and actor can be - * called against arbitrary inode that happened to be in this - * hash chain. Hence we first have to check that this is - * reiser4 inode at least. is_reiser4_inode() is probably too - * early to call, as inode may have ->i_op not yet - * initialised. - */ - is_reiser4_super(inode->i_sb) && - /* - * usually objectid is unique, but pseudo files use counter to - * generate objectid. All pseudo files are placed into special - * (otherwise unused) locality. - */ - reiser4_inode_data(inode)->locality_id == get_key_locality(key); + /* oid is unique, so first term is enough, actually. */ + get_inode_oid(inode) == get_key_objectid(key) && + /* + * also, locality should be checked, but locality is stored in + * the reiser4-specific part of the inode, and actor can be + * called against arbitrary inode that happened to be in this + * hash chain. Hence we first have to check that this is + * reiser4 inode at least. is_reiser4_inode() is probably too + * early to call, as inode may have ->i_op not yet + * initialised. + */ + is_reiser4_super(inode->i_sb) && + /* + * usually objectid is unique, but pseudo files use counter to + * generate objectid. All pseudo files are placed into special + * (otherwise unused) locality. + */ + reiser4_inode_data(inode)->locality_id == get_key_locality(key); } /* hook for kmem_cache_create */ -void loading_init_once(reiser4_inode *info) +void loading_init_once(reiser4_inode * info) { sema_init(&info->loading, 1); } /* for reiser4_alloc_inode */ -void loading_alloc(reiser4_inode *info) +void loading_alloc(reiser4_inode * info) { #if REISER4_DEBUG assert("vs-1717", down_trylock(&info->loading) == 0); @@ -378,7 +385,7 @@ void loading_alloc(reiser4_inode *info) } /* for reiser4_destroy */ -void loading_destroy(reiser4_inode *info) +void loading_destroy(reiser4_inode * info) { #if REISER4_DEBUG assert("vs-1717", down_trylock(&info->loading) == 0); @@ -386,25 +393,28 @@ void loading_destroy(reiser4_inode *info #endif } -static void loading_down(reiser4_inode *info) +static void loading_down(reiser4_inode * info) { down(&info->loading); } -static void loading_up(reiser4_inode *info) +static void loading_up(reiser4_inode * info) { up(&info->loading); } -/* - * this is our helper function a la iget(). This is be called by +/** + * reiser4_iget - obtain inode via iget5_locked, read from disk if necessary + * @super: super block of filesystem + * @key: key of inode's stat-data + * @silent: + * + * This is our helper function a la iget(). This is be called by * reiser4_lookup() and reiser4_read_super(). Return inode locked or error * encountered. */ -reiser4_internal struct inode * -reiser4_iget(struct super_block *super /* super block */ , - const reiser4_key * key /* key of inode's stat-data */, - int silent) +struct inode *reiser4_iget(struct super_block *super, const reiser4_key *key, + int silent) { struct inode *inode; int result; @@ -416,12 +426,11 @@ reiser4_iget(struct super_block *super / result = 0; /* call iget(). Our ->read_inode() is dummy, so this will either - find inode in cache or return uninitialised inode */ + find inode in cache or return uninitialised inode */ inode = iget5_locked(super, - (unsigned long) get_key_objectid(key), + (unsigned long)get_key_objectid(key), reiser4_inode_find_actor, - init_locked_inode, - (reiser4_key *) key); + init_locked_inode, (reiser4_key *) key); if (inode == NULL) return ERR_PTR(RETERR(-ENOMEM)); if (is_bad_inode(inode)) { @@ -446,7 +455,7 @@ reiser4_iget(struct super_block *super / assert("nikita-1941", !is_inode_loaded(inode)); assert("nikita-1949", reiser4_inode_find_actor(inode, - (reiser4_key *)key)); + (reiser4_key *) key)); /* now, inode has objectid as ->i_ino and locality in reiser4-specific part. This is enough for read_inode() to read stat data from the disk */ @@ -483,7 +492,7 @@ reiser4_iget(struct super_block *super / /* reiser4_iget() may return not fully initialized inode, this function should * be called after one completes reiser4 inode initializing. */ -reiser4_internal void reiser4_iget_complete (struct inode * inode) +void reiser4_iget_complete(struct inode *inode) { assert("zam-988", is_reiser4_inode(inode)); @@ -493,8 +502,7 @@ reiser4_internal void reiser4_iget_compl } } -reiser4_internal void -reiser4_make_bad_inode(struct inode *inode) +void reiser4_make_bad_inode(struct inode *inode) { assert("nikita-1934", inode != NULL); @@ -504,106 +512,92 @@ reiser4_make_bad_inode(struct inode *ino return; } -reiser4_internal file_plugin * -inode_file_plugin(const struct inode * inode) +file_plugin *inode_file_plugin(const struct inode * inode) { assert("nikita-1997", inode != NULL); return reiser4_inode_data(inode)->pset->file; } -reiser4_internal dir_plugin * -inode_dir_plugin(const struct inode * inode) +dir_plugin *inode_dir_plugin(const struct inode * inode) { assert("nikita-1998", inode != NULL); return reiser4_inode_data(inode)->pset->dir; } -reiser4_internal perm_plugin * -inode_perm_plugin(const struct inode * inode) +perm_plugin *inode_perm_plugin(const struct inode * inode) { assert("nikita-1999", inode != NULL); return reiser4_inode_data(inode)->pset->perm; } -reiser4_internal formatting_plugin * -inode_formatting_plugin(const struct inode * inode) +formatting_plugin *inode_formatting_plugin(const struct inode * inode) { assert("nikita-2000", inode != NULL); return reiser4_inode_data(inode)->pset->formatting; } -reiser4_internal hash_plugin * -inode_hash_plugin(const struct inode * inode) +hash_plugin *inode_hash_plugin(const struct inode * inode) { assert("nikita-2001", inode != NULL); return reiser4_inode_data(inode)->pset->hash; } -reiser4_internal fibration_plugin * -inode_fibration_plugin(const struct inode * inode) +fibration_plugin *inode_fibration_plugin(const struct inode * inode) { assert("nikita-2001", inode != NULL); return reiser4_inode_data(inode)->pset->fibration; } -reiser4_internal crypto_plugin * -inode_crypto_plugin(const struct inode * inode) +crypto_plugin *inode_crypto_plugin(const struct inode * inode) { assert("edward-36", inode != NULL); return reiser4_inode_data(inode)->pset->crypto; } -reiser4_internal compression_plugin * -inode_compression_plugin(const struct inode * inode) +compression_plugin *inode_compression_plugin(const struct inode * inode) { assert("edward-37", inode != NULL); return reiser4_inode_data(inode)->pset->compression; } -reiser4_internal compression_mode_plugin * -inode_compression_mode_plugin(const struct inode * inode) +compression_mode_plugin *inode_compression_mode_plugin(const struct inode * + inode) { assert("edward-1330", inode != NULL); return reiser4_inode_data(inode)->pset->compression_mode; } -reiser4_internal cluster_plugin * -inode_cluster_plugin(const struct inode * inode) +cluster_plugin *inode_cluster_plugin(const struct inode * inode) { assert("edward-1328", inode != NULL); return reiser4_inode_data(inode)->pset->cluster; } -reiser4_internal regular_plugin * -inode_regular_plugin(const struct inode * inode) +regular_plugin *inode_regular_plugin(const struct inode * inode) { assert("edward-1329", inode != NULL); return reiser4_inode_data(inode)->pset->regular_entry; } -reiser4_internal digest_plugin * -inode_digest_plugin(const struct inode * inode) +digest_plugin *inode_digest_plugin(const struct inode * inode) { assert("edward-86", inode != NULL); return reiser4_inode_data(inode)->pset->digest; } -reiser4_internal item_plugin * -inode_sd_plugin(const struct inode * inode) +item_plugin *inode_sd_plugin(const struct inode * inode) { assert("vs-534", inode != NULL); return reiser4_inode_data(inode)->pset->sd; } -reiser4_internal item_plugin * -inode_dir_item_plugin(const struct inode * inode) +item_plugin *inode_dir_item_plugin(const struct inode * inode) { assert("vs-534", inode != NULL); return reiser4_inode_data(inode)->pset->dir_item; } -reiser4_internal void -inode_set_extension(struct inode *inode, sd_ext_bits ext) +void inode_set_extension(struct inode *inode, sd_ext_bits ext) { reiser4_inode *state; @@ -619,7 +613,7 @@ inode_set_extension(struct inode *inode, inode_clr_flag(inode, REISER4_SDLEN_KNOWN); } -reiser4_internal void +void inode_set_plugin(struct inode *inode, reiser4_plugin * plug, pset_member memb) { assert("nikita-2718", inode != NULL); @@ -628,8 +622,7 @@ inode_set_plugin(struct inode *inode, re reiser4_inode_data(inode)->plugin_mask |= (1 << memb); } -reiser4_internal void -inode_check_scale_nolock(struct inode *inode, __u64 old, __u64 new) +void inode_check_scale_nolock(struct inode *inode, __u64 old, __u64 new) { assert("edward-1287", inode != NULL); if (!dscale_fit(old, new)) @@ -637,12 +630,11 @@ inode_check_scale_nolock(struct inode *i return; } -reiser4_internal void -inode_check_scale(struct inode *inode, __u64 old, __u64 new) +void inode_check_scale(struct inode *inode, __u64 old, __u64 new) { assert("nikita-2875", inode != NULL); spin_lock_inode(inode); - inode_check_scale_nolock(inode, old, new); + inode_check_scale_nolock(inode, old, new); spin_unlock_inode(inode); } @@ -651,9 +643,9 @@ inode_check_scale(struct inode *inode, _ * and body is ordered within a tree with respect to other objects within the * same parent directory. */ -reiser4_internal void +void init_inode_ordering(struct inode *inode, - reiser4_object_create_data *crd, int create) + reiser4_object_create_data * crd, int create) { reiser4_key key; @@ -678,8 +670,7 @@ init_inode_ordering(struct inode *inode, set_inode_ordering(inode, get_key_ordering(&key)); } -reiser4_internal znode * -inode_get_vroot(struct inode *inode) +znode *inode_get_vroot(struct inode *inode) { reiser4_block_nr blk; znode *result; @@ -696,8 +687,7 @@ inode_get_vroot(struct inode *inode) return result; } -reiser4_internal void -inode_set_vroot(struct inode *inode, znode *vroot) +void inode_set_vroot(struct inode *inode, znode * vroot) { reiser4_inode *info; @@ -709,78 +699,33 @@ inode_set_vroot(struct inode *inode, zno #if REISER4_DEBUG -void -inode_invariant(const struct inode *inode) +void inode_invariant(const struct inode *inode) { - reiser4_inode * object; + reiser4_inode *object; object = reiser4_inode_data(inode); assert("nikita-3077", spin_inode_object_is_locked(object)); - - spin_lock_eflush(inode->i_sb); - - assert("nikita-3146", object->anonymous_eflushed >= 0 && object->captured_eflushed >= 0); - assert("nikita-3441", ergo(object->anonymous_eflushed > 0 || object->captured_eflushed > 0, - jnode_tree_by_reiser4_inode(object)->rnode != NULL)); - - spin_unlock_eflush(inode->i_sb); } -int -inode_has_no_jnodes(reiser4_inode *r4_inode) +int inode_has_no_jnodes(reiser4_inode * r4_inode) { return jnode_tree_by_reiser4_inode(r4_inode)->rnode == NULL && - r4_inode->nr_jnodes == 0 && - r4_inode->captured_eflushed == 0 && - r4_inode->anonymous_eflushed == 0; + r4_inode->nr_jnodes == 0; } -void -mark_inode_update(struct inode *object, int immediate) -{ - int i; - int pos; - reiser4_context *ctx; - - ctx = get_current_context(); - for (i = 0, pos = -1; i < TRACKED_DELAYED_UPDATE; ++i) { - if (ctx->dirty[i].ino == object->i_ino) { - pos = i; - break; - } else if (ctx->dirty[i].ino == 0) - pos = i; - } - if (pos == -1) - ;/*warning("nikita-3402", "Too many delayed inode updates");*/ - else if (immediate) { - ctx->dirty[pos].ino = 0; - } else { - ctx->dirty[pos].ino = object->i_ino; - ctx->dirty[pos].delayed = 1; -#ifdef CONFIG_FRAME_POINTER - ctx->dirty[pos].stack[0] = __builtin_return_address(0); - ctx->dirty[pos].stack[1] = __builtin_return_address(1); - ctx->dirty[pos].stack[2] = __builtin_return_address(2); - ctx->dirty[pos].stack[3] = __builtin_return_address(3); #endif - } -} - -int -delayed_inode_updates(dirty_inode_info info) -{ - int i; - - for (i = 0; i < TRACKED_DELAYED_UPDATE; ++i) { - if (info[i].ino != 0 && info[i].delayed) - return 1; - } - return 0; +/* true if directory is empty (only contains dot and dotdot) */ +/* FIXME: shouldn't it be dir plugin method? */ +int is_dir_empty(const struct inode *dir) +{ + assert("nikita-1976", dir != NULL); + + /* rely on our method to maintain directory i_size being equal to the + number of entries. */ + return dir->i_size <= 2 ? 0 : RETERR(-ENOTEMPTY); } -#endif - /* Make Linus happy. Local variables: c-indentation-style: "K&R" diff -puN fs/reiser4/inode.h~reiser4-big-update fs/reiser4/inode.h --- devel/fs/reiser4/inode.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/inode.h 2005-09-15 19:51:08.000000000 -0700 @@ -9,15 +9,16 @@ #include "debug.h" #include "spin_macros.h" #include "key.h" -#include "kcond.h" #include "seal.h" #include "plugin/plugin.h" -#include "plugin/cryptcompress.h" +#include "plugin/file/cryptcompress.h" +#include "plugin/file/file.h" +#include "plugin/dir/dir.h" #include "plugin/plugin_set.h" #include "plugin/security/perm.h" -#include "plugin/pseudo/pseudo.h" #include "vfs_ops.h" #include "jnode.h" +#include "fsdata.h" #include /* for __u?? , ino_t */ #include /* for struct super_block, struct @@ -36,8 +37,8 @@ typedef enum { /* stat data wasn't yet created */ REISER4_NO_SD = 1, /* internal immutable flag. Currently is only used - to avoid race condition during file creation. - See comment in create_object(). */ + to avoid race condition during file creation. + See comment in create_object(). */ REISER4_IMMUTABLE = 2, /* inode was read from storage */ REISER4_LOADED = 3, @@ -46,7 +47,7 @@ typedef enum { REISER4_GENERIC_PTR_USED = 4, /* set if size of stat-data item for this inode is known. If this is * set we can avoid recalculating size of stat-data on each update. */ - REISER4_SDLEN_KNOWN = 5, + REISER4_SDLEN_KNOWN = 5, /* reiser4_inode->crypt points to the crypto stat */ REISER4_CRYPTO_STAT_LOADED = 6, /* cryptcompress_inode_data points to the secret key */ @@ -70,7 +71,6 @@ typedef enum { s_op->allocate_inode() method. So, it is possible to adjust size of inode at the time of its creation. - Invariants involving parts of this data-type: [inode->eflushed] @@ -79,10 +79,8 @@ typedef enum { typedef struct reiser4_inode reiser4_inode; /* return pointer to reiser4-specific part of inode */ -static inline reiser4_inode * -reiser4_inode_data(const struct inode * inode /* inode queried */); - -#include "plugin/file/file.h" +static inline reiser4_inode *reiser4_inode_data(const struct inode *inode + /* inode queried */ ); #if BITS_PER_LONG == 64 @@ -122,7 +120,7 @@ struct reiser4_inode { /* bitmask of non-default plugins for this inode */ __u16 plugin_mask; union { - readdir_list_head readdir_list; + struct list_head readdir_list; struct list_head not_used; } lists; /* per-inode flags. Filled by values of reiser4_file_plugin_flags */ @@ -132,20 +130,15 @@ struct reiser4_inode { unix_file_info_t unix_file_info; /* fields specific to cryptcompress plugin */ cryptcompress_info_t cryptcompress_info; - /* fields specific to pseudo file plugin */ - pseudo_info_t pseudo_info; } file_plugin_data; - struct rw_semaphore coc_sem; /* filemap_nopage takes it for read, copy_on_capture - for write. Under this it - tries to unmap page for which it is called. This prevents process from using page which - was copied on capture */ + struct rw_semaphore coc_sem; /* filemap_nopage takes it for read, copy_on_capture - for write. Under this it + tries to unmap page for which it is called. This prevents process from using page which + was copied on capture */ /* tree of jnodes. Phantom jnodes (ones not attched to any atom) are tagged in that tree by EFLUSH_TAG_ANONYMOUS */ struct radix_tree_root jnodes_tree; #if REISER4_DEBUG - /* numbers of eflushed jnodes of each type in the above tree */ - int anonymous_eflushed; - int captured_eflushed; /* number of unformatted node jnodes of this file in jnode hash table */ unsigned long nr_jnodes; #endif @@ -168,17 +161,18 @@ typedef struct reiser4_inode_object { } reiser4_inode_object; /* return pointer to the reiser4 specific portion of @inode */ -static inline reiser4_inode * -reiser4_inode_data(const struct inode * inode /* inode queried */) +static inline reiser4_inode *reiser4_inode_data(const struct inode *inode + /* inode queried */ ) { assert("nikita-254", inode != NULL); return &container_of(inode, reiser4_inode_object, vfs_inode)->p; } -static inline struct inode * -inode_by_reiser4_inode(const reiser4_inode *r4_inode /* inode queried */) +static inline struct inode *inode_by_reiser4_inode(const reiser4_inode * + r4_inode /* inode queried */ + ) { - return &container_of(r4_inode, reiser4_inode_object, p)->vfs_inode; + return &container_of(r4_inode, reiser4_inode_object, p)->vfs_inode; } /* @@ -196,14 +190,12 @@ inode_by_reiser4_inode(const reiser4_ino #if REISER4_INO_IS_OID -static inline oid_t -get_inode_oid(const struct inode *inode) +static inline oid_t get_inode_oid(const struct inode *inode) { return inode->i_ino; } -static inline void -set_inode_oid(struct inode *inode, oid_t oid) +static inline void set_inode_oid(struct inode *inode, oid_t oid) { inode->i_ino = oid; } @@ -211,19 +203,17 @@ set_inode_oid(struct inode *inode, oid_t /* REISER4_INO_IS_OID */ #else -static inline oid_t -get_inode_oid(const struct inode *inode) +static inline oid_t get_inode_oid(const struct inode *inode) { return - ((__u64)reiser4_inode_data(inode)->oid_hi << OID_HI_SHIFT) | - inode->i_ino; + ((__u64) reiser4_inode_data(inode)->oid_hi << OID_HI_SHIFT) | + inode->i_ino; } -static inline void -set_inode_oid(struct inode *inode, oid_t oid) +static inline void set_inode_oid(struct inode *inode, oid_t oid) { assert("nikita-2519", inode != NULL); - inode->i_ino = (ino_t)(oid); + inode->i_ino = (ino_t) (oid); reiser4_inode_data(inode)->oid_hi = (oid) >> OID_HI_SHIFT; assert("nikita-2521", get_inode_oid(inode) == (oid)); } @@ -231,8 +221,7 @@ set_inode_oid(struct inode *inode, oid_t /* REISER4_INO_IS_OID */ #endif -static inline oid_t -get_inode_locality(const struct inode *inode) +static inline oid_t get_inode_locality(const struct inode *inode) { return reiser4_inode_data(inode)->locality_id; } @@ -256,8 +245,8 @@ static inline void set_inode_ordering(co #endif /* return inode in which @uf_info is embedded */ -static inline struct inode * -unix_file_info_to_inode(const unix_file_info_t *uf_info) +static inline struct inode *unix_file_info_to_inode(const unix_file_info_t * + uf_info) { return &container_of(uf_info, reiser4_inode_object, p.file_plugin_data.unix_file_info)->vfs_inode; @@ -301,18 +290,20 @@ extern int inode_has_no_jnodes(reiser4_i }) extern znode *inode_get_vroot(struct inode *inode); -extern void inode_set_vroot(struct inode *inode, znode *vroot); +extern void inode_set_vroot(struct inode *inode, znode * vroot); extern int reiser4_max_filename_len(const struct inode *inode); extern int max_hash_collisions(const struct inode *dir); extern void reiser4_unlock_inode(struct inode *inode); extern int is_reiser4_inode(const struct inode *inode); extern int setup_inode_ops(struct inode *inode, reiser4_object_create_data *); -extern struct inode *reiser4_iget(struct super_block *super, const reiser4_key * key, int silent); -extern void reiser4_iget_complete (struct inode * inode); +extern struct inode *reiser4_iget(struct super_block *super, + const reiser4_key * key, int silent); +extern void reiser4_iget_complete(struct inode *inode); extern void inode_set_flag(struct inode *inode, reiser4_file_plugin_flags f); extern void inode_clr_flag(struct inode *inode, reiser4_file_plugin_flags f); -extern int inode_get_flag(const struct inode *inode, reiser4_file_plugin_flags f); +extern int inode_get_flag(const struct inode *inode, + reiser4_file_plugin_flags f); /* has inode been initialized? */ static inline int @@ -331,7 +322,8 @@ extern fibration_plugin *inode_fibration extern crypto_plugin *inode_crypto_plugin(const struct inode *inode); extern digest_plugin *inode_digest_plugin(const struct inode *inode); extern compression_plugin *inode_compression_plugin(const struct inode *inode); -extern compression_mode_plugin *inode_compression_mode_plugin(const struct inode *inode); +extern compression_mode_plugin *inode_compression_mode_plugin(const struct inode + *inode); extern cluster_plugin *inode_cluster_plugin(const struct inode *inode); extern regular_plugin *inode_regular_plugin(const struct inode *inode); extern item_plugin *inode_sd_plugin(const struct inode *inode); @@ -343,6 +335,7 @@ extern void reiser4_make_bad_inode(struc extern void inode_set_extension(struct inode *inode, sd_ext_bits ext); extern void inode_check_scale(struct inode *inode, __u64 old, __u64 new); +extern void inode_check_scale_nolock(struct inode * inode, __u64 old, __u64 new); /* * update field @field in inode @i to contain value @value. @@ -377,23 +370,21 @@ extern void inode_check_scale(struct ino }) /* See comment before readdir_common() for description. */ -static inline readdir_list_head * -get_readdir_list(const struct inode *inode) +static inline struct list_head *get_readdir_list(const struct inode *inode) { return &reiser4_inode_data(inode)->lists.readdir_list; } extern void init_inode_ordering(struct inode *inode, - reiser4_object_create_data *crd, int create); + reiser4_object_create_data * crd, int create); -static inline struct radix_tree_root * -jnode_tree_by_inode(struct inode *inode) +static inline struct radix_tree_root *jnode_tree_by_inode(struct inode *inode) { return &reiser4_inode_data(inode)->jnodes_tree; } -static inline struct radix_tree_root * -jnode_tree_by_reiser4_inode(reiser4_inode *r4_inode) +static inline struct radix_tree_root *jnode_tree_by_reiser4_inode(reiser4_inode + * r4_inode) { return &r4_inode->jnodes_tree; } @@ -402,6 +393,8 @@ jnode_tree_by_reiser4_inode(reiser4_inod extern void print_inode(const char *prefix, const struct inode *i); #endif +int is_dir_empty(const struct inode *); + /* __REISER4_INODE_H__ */ #endif diff -L fs/reiser4/inode_ops.c -puN fs/reiser4/inode_ops.c~reiser4-big-update /dev/null --- devel/fs/reiser4/inode_ops.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,612 +0,0 @@ -/* Copyright 2003, 2004 by Hans Reiser, licensing governed by - * reiser4/README */ - -/* Interface to VFS. Reiser4 inode_operations are defined here. */ - -#include "forward.h" -#include "debug.h" -#include "dformat.h" -#include "coord.h" -#include "plugin/item/item.h" -#include "plugin/file/file.h" -#include "plugin/security/perm.h" -#include "plugin/disk_format/disk_format.h" -#include "plugin/plugin.h" -#include "plugin/plugin_set.h" -#include "plugin/object.h" -#include "txnmgr.h" -#include "jnode.h" -#include "znode.h" -#include "block_alloc.h" -#include "tree.h" -#include "vfs_ops.h" -#include "inode.h" -#include "page_cache.h" -#include "ktxnmgrd.h" -#include "super.h" -#include "reiser4.h" -#include "entd.h" -#include "emergency_flush.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* inode operations */ - -static int reiser4_create(struct inode *, struct dentry *, int, - struct nameidata *); -static struct dentry *reiser4_lookup(struct inode *, struct dentry *, - struct nameidata *); -static int reiser4_link(struct dentry *, struct inode *, struct dentry *); -static int reiser4_unlink(struct inode *, struct dentry *); -static int reiser4_rmdir(struct inode *, struct dentry *); -static int reiser4_symlink(struct inode *, struct dentry *, const char *); -static int reiser4_mkdir(struct inode *, struct dentry *, int); -static int reiser4_mknod(struct inode *, struct dentry *, int, dev_t); -static int reiser4_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); -static int reiser4_readlink(struct dentry *, char *, int); -static int reiser4_follow_link(struct dentry *, struct nameidata *); -static void reiser4_truncate(struct inode *); -static int reiser4_permission(struct inode *, int, struct nameidata *); -static int reiser4_setattr(struct dentry *, struct iattr *); -static int reiser4_getattr(struct vfsmount *mnt, struct dentry *, struct kstat *); - -#if 0 -static int reiser4_setxattr(struct dentry *, const char *, void *, size_t, int); -static ssize_t reiser4_getxattr(struct dentry *, const char *, void *, size_t); -static ssize_t reiser4_listxattr(struct dentry *, char *, size_t); -static int reiser4_removexattr(struct dentry *, const char *); -#endif - -reiser4_internal int invoke_create_method(struct inode *parent, - struct dentry *dentry, - reiser4_object_create_data * data); - -/* ->create() VFS method in reiser4 inode_operations */ -static int -reiser4_create(struct inode *parent /* inode of parent - * directory */, - struct dentry *dentry /* dentry of new object to - * create */, - int mode /* new object mode */, - struct nameidata *nameidata) -{ - reiser4_object_create_data data; - - memset(&data, 0, sizeof data); - data.mode = S_IFREG | mode; - data.id = inode_regular_plugin(parent)->id; - return invoke_create_method(parent, dentry, &data); -} - -/* ->mkdir() VFS method in reiser4 inode_operations */ -static int -reiser4_mkdir(struct inode *parent /* inode of parent - * directory */ , - struct dentry *dentry /* dentry of new object to - * create */ , - int mode /* new object's mode */ ) -{ - reiser4_object_create_data data; - - data.mode = S_IFDIR | mode; - data.id = DIRECTORY_FILE_PLUGIN_ID; - return invoke_create_method(parent, dentry, &data); -} - -/* ->symlink() VFS method in reiser4 inode_operations */ -static int -reiser4_symlink(struct inode *parent /* inode of parent - * directory */ , - struct dentry *dentry /* dentry of new object to - * create */ , - const char *linkname /* pathname to put into - * symlink */ ) -{ - reiser4_object_create_data data; - - data.name = linkname; - data.id = SYMLINK_FILE_PLUGIN_ID; - data.mode = S_IFLNK | S_IRWXUGO; - return invoke_create_method(parent, dentry, &data); -} - -/* ->mknod() VFS method in reiser4 inode_operations */ -static int -reiser4_mknod(struct inode *parent /* inode of parent directory */ , - struct dentry *dentry /* dentry of new object to - * create */ , - int mode /* new object's mode */ , - dev_t rdev /* minor and major of new device node */ ) -{ - reiser4_object_create_data data; - - data.mode = mode; - data.rdev = rdev; - data.id = SPECIAL_FILE_PLUGIN_ID; - return invoke_create_method(parent, dentry, &data); -} - -/* ->rename() inode operation */ -static int -reiser4_rename(struct inode *old_dir, struct dentry *old, struct inode *new_dir, struct dentry *new) -{ - int result; - reiser4_context ctx; - - assert("nikita-2314", old_dir != NULL); - assert("nikita-2315", old != NULL); - assert("nikita-2316", new_dir != NULL); - assert("nikita-2317", new != NULL); - - init_context(&ctx, old_dir->i_sb); - - result = perm_chk(old_dir, rename, old_dir, old, new_dir, new); - if (result == 0) { - dir_plugin *dplug; - - dplug = inode_dir_plugin(old_dir); - if (dplug == NULL) - result = RETERR(-ENOTDIR); - else if (dplug->rename == NULL) - result = RETERR(-EPERM); - else - result = dplug->rename(old_dir, old, new_dir, new); - } - context_set_commit_async(&ctx); - reiser4_exit_context(&ctx); - return result; -} - -/* reiser4_lookup() - entry point for ->lookup() method. - - This is a wrapper for lookup_object which is a wrapper for the directory - plugin that does the lookup. - - This is installed in ->lookup() in reiser4_inode_operations. -*/ -static struct dentry * -reiser4_lookup(struct inode *parent, /* directory within which we are to - * look for the name specified in - * dentry */ - struct dentry *dentry, /* this contains the name that is to - be looked for on entry, and on exit - contains a filled in dentry with a - pointer to the inode (unless name - not found) */ - struct nameidata *nameidata) -{ - dir_plugin *dplug; - int retval; - struct dentry *result; - reiser4_context ctx; - int (*lookup) (struct inode * parent_inode, struct dentry **dentry); - - assert("nikita-403", parent != NULL); - assert("nikita-404", dentry != NULL); - - init_context(&ctx, parent->i_sb); - - /* find @parent directory plugin and make sure that it has lookup - method */ - dplug = inode_dir_plugin(parent); - if (dplug != NULL && dplug->lookup != NULL) - /* if parent directory has directory plugin with ->lookup - * method, use the latter to do lookup */ - lookup = dplug->lookup; -#if ENABLE_REISER4_PSEUDO - else if (!reiser4_is_set(parent->i_sb, REISER4_NO_PSEUDO)) - /* even if there is no ->lookup method, pseudo file lookup - * should still be performed, but only unless we are in - * "no-pseudo" mode */ - lookup = lookup_pseudo_file; -#endif /* ENABLE_REISER4_PSEUDO */ - else - lookup = NULL; - if (lookup != NULL) { - struct dentry *name; - - name = dentry; - /* call its lookup method */ - retval = lookup(parent, &name); - if (retval == 0) { - if (name == NULL) { - /* - * new object was looked up. Initialize it. - */ - struct inode *obj; - file_plugin *fplug; - - obj = dentry->d_inode; - assert("nikita-2645", obj != NULL); - fplug = inode_file_plugin(obj); - retval = fplug->bind(obj, parent); - } - } else if (retval == -ENOENT) { - /* object not found */ - if (!IS_DEADDIR(parent)) - d_add(dentry, NULL); - retval = 0; - name = NULL; - } - - if (retval == 0) - /* success */ - result = name; - else - result = ERR_PTR(retval); - } else - result = ERR_PTR(-ENOTDIR); - - /* prevent balance_dirty_pages() from being called: we don't want to - * do this under directory i_sem. */ - context_set_commit_async(&ctx); - reiser4_exit_context(&ctx); - return result; -} - -/* ->readlink() inode method, returns content of symbolic link */ -static int -reiser4_readlink(struct dentry *dentry, char *buf, int buflen) -{ - assert("vs-852", S_ISLNK(dentry->d_inode->i_mode)); - if (!dentry->d_inode->u.generic_ip || !inode_get_flag(dentry->d_inode, REISER4_GENERIC_PTR_USED)) - return RETERR(-EINVAL); - return vfs_readlink(dentry, buf, buflen, dentry->d_inode->u.generic_ip); -} - -/* ->follow_link() inode method. Follows a symbolic link */ -static int -reiser4_follow_link(struct dentry *dentry, struct nameidata *data) -{ - assert("vs-851", S_ISLNK(dentry->d_inode->i_mode)); - - if (!dentry->d_inode->u.generic_ip || !inode_get_flag(dentry->d_inode, REISER4_GENERIC_PTR_USED)) - return RETERR(-EINVAL); - return vfs_follow_link(data, dentry->d_inode->u.generic_ip); -} - -/* ->setattr() inode operation - - Called from notify_change. */ -static int -reiser4_setattr(struct dentry *dentry, struct iattr *attr) -{ - struct inode *inode; - int result; - reiser4_context ctx; - - assert("nikita-2269", attr != NULL); - - inode = dentry->d_inode; - assert("vs-1108", inode != NULL); - init_context(&ctx, inode->i_sb); - result = perm_chk(inode, setattr, dentry, attr); - if (result == 0) { - if (!inode_get_flag(inode, REISER4_IMMUTABLE)) { - file_plugin *fplug; - - fplug = inode_file_plugin(inode); - assert("nikita-2271", fplug != NULL); - assert("nikita-2296", fplug->setattr != NULL); - result = fplug->setattr(inode, attr); - } else - result = RETERR(-E_REPEAT); - } - context_set_commit_async(&ctx); - reiser4_exit_context(&ctx); - return result; -} - -/* ->getattr() inode operation called (indirectly) by sys_stat(). */ -static int -reiser4_getattr(struct vfsmount *mnt UNUSED_ARG, struct dentry *dentry, struct kstat *stat) -{ - struct inode *inode; - int result; - reiser4_context ctx; - - inode = dentry->d_inode; - init_context(&ctx, inode->i_sb); - result = perm_chk(inode, getattr, mnt, dentry, stat); - if (result == 0) { - file_plugin *fplug; - - fplug = inode_file_plugin(inode); - assert("nikita-2295", fplug != NULL); - assert("nikita-2297", fplug->getattr != NULL); - result = fplug->getattr(mnt, dentry, stat); - } - reiser4_exit_context(&ctx); - return result; -} - -/* helper function: call object plugin to truncate file to @size */ -static int -truncate_object(struct inode *inode /* object to truncate */ , - loff_t size /* size to truncate object to */ ) -{ - file_plugin *fplug; - int result; - - assert("nikita-1026", inode != NULL); - assert("nikita-1027", is_reiser4_inode(inode)); - assert("nikita-1028", inode->i_sb != NULL); - - fplug = inode_file_plugin(inode); - assert("vs-142", fplug != NULL); - - assert("nikita-2933", fplug->truncate != NULL); - result = fplug->truncate(inode, size); - if (result != 0) - warning("nikita-1602", "Truncate error: %i for %lli", result, - (unsigned long long)get_inode_oid(inode)); - - return result; -} - -/* ->truncate() VFS method in reiser4 inode_operations */ -static void -reiser4_truncate(struct inode *inode /* inode to truncate */ ) -{ - reiser4_context ctx; - - assert("umka-075", inode != NULL); - - init_context(&ctx, inode->i_sb); - - truncate_object(inode, inode->i_size); - - /* for mysterious reasons ->truncate() VFS call doesn't return - value */ - reiser4_exit_context(&ctx); -} - -/* ->permission() method in reiser4_inode_operations. */ -static int -reiser4_permission(struct inode *inode /* object */ , - int mask, /* mode bits to check permissions - * for */ - struct nameidata *nameidata) -{ - /* reiser4_context creation/destruction removed from here, - because permission checks currently don't require this. - - Permission plugin have to create context itself if necessary. */ - assert("nikita-1687", inode != NULL); - - return perm_chk(inode, mask, inode, mask); -} - -/* common part of both unlink and rmdir. */ -static int -unlink_file(struct inode *parent /* parent directory */ , - struct dentry *victim /* name of object being - * unlinked */ ) -{ - int result; - dir_plugin *dplug; - reiser4_context ctx; - - init_context(&ctx, parent->i_sb); - - assert("nikita-1435", parent != NULL); - assert("nikita-1436", victim != NULL); - - dplug = inode_dir_plugin(parent); - assert("nikita-1429", dplug != NULL); - if (dplug->unlink != NULL) - result = dplug->unlink(parent, victim); - else - result = RETERR(-EPERM); - /* @victim can be already removed from the disk by this time. Inode is - then marked so that iput() wouldn't try to remove stat data. But - inode itself is still there. - */ - /* we cannot release directory semaphore here, because name has - * already been deleted, but dentry (@victim) still exists. */ - /* prevent balance_dirty_pages() from being called: we don't want to - * do this under directory i_sem. */ - - context_set_commit_async(&ctx); - reiser4_exit_context(&ctx); - return result; -} - -/* ->unlink() VFS method in reiser4 inode_operations - - remove link from @parent directory to @victim object: delegate work - to object plugin -*/ -/* Audited by: umka (2002.06.12) */ -static int -reiser4_unlink(struct inode *parent /* parent directory */ , - struct dentry *victim /* name of object being - * unlinked */ ) -{ - assert("nikita-2011", parent != NULL); - assert("nikita-2012", victim != NULL); - assert("nikita-2013", victim->d_inode != NULL); - if (inode_dir_plugin(victim->d_inode) == NULL) - return unlink_file(parent, victim); - else - return RETERR(-EISDIR); -} - -/* ->rmdir() VFS method in reiser4 inode_operations - - The same as unlink, but only for directories. - -*/ -/* Audited by: umka (2002.06.12) */ -static int -reiser4_rmdir(struct inode *parent /* parent directory */ , - struct dentry *victim /* name of directory being - * unlinked */ ) -{ - assert("nikita-2014", parent != NULL); - assert("nikita-2015", victim != NULL); - assert("nikita-2016", victim->d_inode != NULL); - - if (inode_dir_plugin(victim->d_inode) != NULL) - /* there is no difference between unlink and rmdir for - reiser4 */ - return unlink_file(parent, victim); - else - return RETERR(-ENOTDIR); -} - -/* ->link() VFS method in reiser4 inode_operations - - entry point for ->link() method. - - This is installed as ->link inode operation for reiser4 - inodes. Delegates all work to object plugin -*/ -/* Audited by: umka (2002.06.12) */ -static int -reiser4_link(struct dentry *existing /* dentry of existing - * object */ , - struct inode *parent /* parent directory */ , - struct dentry *where /* new name for @existing */ ) -{ - int result; - dir_plugin *dplug; - reiser4_context ctx; - - assert("umka-080", existing != NULL); - assert("nikita-1031", parent != NULL); - - init_context(&ctx, parent->i_sb); - context_set_commit_async(&ctx); - - dplug = inode_dir_plugin(parent); - assert("nikita-1430", dplug != NULL); - if (dplug->link != NULL) { - result = dplug->link(parent, existing, where); - if (result == 0) - d_instantiate(where, existing->d_inode); - } else { - result = RETERR(-EPERM); - } - up(&existing->d_inode->i_sem); - up(&parent->i_sem); - reiser4_exit_context(&ctx); - down(&parent->i_sem); - down(&existing->d_inode->i_sem); - return result; -} - -/* call ->create() directory plugin method. */ -reiser4_internal int -invoke_create_method(struct inode *parent /* parent directory */ , - struct dentry *dentry /* dentry of new - * object */ , - reiser4_object_create_data * data /* information - * necessary - * to create - * new - * object */ ) -{ - int result; - dir_plugin *dplug; - reiser4_context ctx; - - init_context(&ctx, parent->i_sb); - context_set_commit_async(&ctx); - - assert("nikita-426", parent != NULL); - assert("nikita-427", dentry != NULL); - assert("nikita-428", data != NULL); - - dplug = inode_dir_plugin(parent); - if (dplug == NULL) - result = RETERR(-ENOTDIR); - else if (dplug->create_child != NULL) { - struct inode *child; - - child = NULL; - - data->parent = parent; - data->dentry = dentry; - - result = dplug->create_child(data, &child); - if (unlikely(result != 0)) { - if (child != NULL) { - /* - * what we actually want to check in the - * assertion below is that @child only - * contains items that iput()->... is going to - * remove (usually stat-data). Obvious check - * for child->i_size == 0 doesn't work for - * symlinks. - */ - assert("nikita-3140", S_ISLNK(child->i_mode) || - child->i_size == 0); - reiser4_make_bad_inode(child); - iput(child); - } - } else { - d_instantiate(dentry, child); - } - } else - result = RETERR(-EPERM); - - reiser4_exit_context(&ctx); - return result; -} - -struct inode_operations reiser4_inode_operations = { - .create = reiser4_create, /* d */ - .lookup = reiser4_lookup, /* d */ - .link = reiser4_link, /* d */ - .unlink = reiser4_unlink, /* d */ - .symlink = reiser4_symlink, /* d */ - .mkdir = reiser4_mkdir, /* d */ - .rmdir = reiser4_rmdir, /* d */ - .mknod = reiser4_mknod, /* d */ - .rename = reiser4_rename, /* d */ - .readlink = NULL, - .follow_link = NULL, - .truncate = reiser4_truncate, /* d */ - .permission = reiser4_permission, /* d */ - .setattr = reiser4_setattr, /* d */ - .getattr = reiser4_getattr, /* d */ -}; - -struct inode_operations reiser4_symlink_inode_operations = { - .setattr = reiser4_setattr, /* d */ - .getattr = reiser4_getattr, /* d */ - .readlink = reiser4_readlink, - .follow_link = reiser4_follow_link -}; - -struct inode_operations reiser4_special_inode_operations = { - .setattr = reiser4_setattr, /* d */ - .getattr = reiser4_getattr /* d */ -}; - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - End: -*/ diff -puN fs/reiser4/jnode.c~reiser4-big-update fs/reiser4/jnode.c --- devel/fs/reiser4/jnode.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/jnode.c 2005-09-15 19:51:08.000000000 -0700 @@ -103,10 +103,11 @@ #include "reiser4.h" #include "debug.h" #include "dformat.h" +#include "jnode.h" #include "plugin/plugin_header.h" #include "plugin/plugin.h" #include "txnmgr.h" -#include "jnode.h" +/*#include "jnode.h"*/ #include "znode.h" #include "tree.h" #include "tree_walk.h" @@ -114,11 +115,11 @@ #include "inode.h" #include "page_cache.h" -#include /* UML needs this for PAGE_OFFSET */ +#include /* UML needs this for PAGE_OFFSET */ #include #include #include -#include /* for vmalloc(), vfree() */ +#include /* for vmalloc(), vfree() */ #include #include /* for struct address_space */ #include /* for inode_lock */ @@ -134,7 +135,7 @@ static int jnode_invariant(const jnode * #endif /* true if valid page is attached to jnode */ -static inline int jnode_is_parsed (jnode * node) +static inline int jnode_is_parsed(jnode * node) { return JF_ISSET(node, JNODE_PARSED); } @@ -142,8 +143,7 @@ static inline int jnode_is_parsed (jnode /* hash table support */ /* compare two jnode keys for equality. Used by hash-table macros */ -static inline int -jnode_key_eq(const jnode_key_t * k1, const jnode_key_t * k2) +static inline int jnode_key_eq(const jnode_key_t * k1, const jnode_key_t * k2) { assert("nikita-2350", k1 != NULL); assert("nikita-2351", k2 != NULL); @@ -153,7 +153,7 @@ jnode_key_eq(const jnode_key_t * k1, con /* Hash jnode by its key (inode plus offset). Used by hash-table macros */ static inline __u32 -jnode_key_hashfn(j_hash_table *table, const jnode_key_t * key) +jnode_key_hashfn(j_hash_table * table, const jnode_key_t * key) { assert("nikita-2352", key != NULL); assert("nikita-3346", IS_POW(table->_buckets)); @@ -165,21 +165,20 @@ jnode_key_hashfn(j_hash_table *table, co /* The hash table definition */ #define KMALLOC(size) vmalloc(size) #define KFREE(ptr, size) vfree(ptr) -TYPE_SAFE_HASH_DEFINE(j, jnode, jnode_key_t, key.j, link.j, jnode_key_hashfn, jnode_key_eq); +TYPE_SAFE_HASH_DEFINE(j, jnode, jnode_key_t, key.j, link.j, jnode_key_hashfn, + jnode_key_eq); #undef KFREE #undef KMALLOC /* call this to initialise jnode hash table */ -reiser4_internal int -jnodes_tree_init(reiser4_tree * tree /* tree to initialise jnodes for */ ) +int jnodes_tree_init(reiser4_tree * tree /* tree to initialise jnodes for */ ) { assert("nikita-2359", tree != NULL); return j_hash_init(&tree->jhash_table, 16384); } /* call this to destroy jnode hash table. This is called during umount. */ -reiser4_internal int -jnodes_tree_done(reiser4_tree * tree /* tree to destroy jnodes for */ ) +int jnodes_tree_done(reiser4_tree * tree /* tree to destroy jnodes for */ ) { j_hash_table *jtable; jnode *node; @@ -191,59 +190,51 @@ jnodes_tree_done(reiser4_tree * tree /* * Scan hash table and free all jnodes. */ jtable = &tree->jhash_table; - for_all_in_htable(jtable, j, node, next) { - assert("nikita-2361", !atomic_read(&node->x_count)); - jdrop(node); - } + if (jtable->_table) { + for_all_in_htable(jtable, j, node, next) { + assert("nikita-2361", !atomic_read(&node->x_count)); + jdrop(node); + } - j_hash_done(&tree->jhash_table); + j_hash_done(&tree->jhash_table); + } return 0; } -/* Initialize static variables in this file. */ -reiser4_internal int -jnode_init_static(void) +/** + * init_jnodes - create jnode cache + * + * Initializes slab cache jnodes. It is part of reiser4 module initialization. + */ +int init_jnodes(void) { assert("umka-168", _jnode_slab == NULL); - _jnode_slab = kmem_cache_create("jnode", sizeof (jnode), 0, - SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, - NULL, NULL); - + _jnode_slab = kmem_cache_create("jnode", sizeof(jnode), 0, + SLAB_HWCACHE_ALIGN | + SLAB_RECLAIM_ACCOUNT, NULL, NULL); if (_jnode_slab == NULL) - goto error; + return RETERR(-ENOMEM); return 0; - -error: - - if (_jnode_slab != NULL) - kmem_cache_destroy(_jnode_slab); - - return RETERR(-ENOMEM); } -/* Dual to jnode_init_static */ -reiser4_internal int -jnode_done_static(void) +/** + * done_znodes - delete znode cache + * + * This is called on reiser4 module unloading or system shutdown. + */ +void done_jnodes(void) { - int ret = 0; - - if (_jnode_slab != NULL) { - ret = kmem_cache_destroy(_jnode_slab); - _jnode_slab = NULL; - } - - return ret; + destroy_reiser4_cache(&_jnode_slab); } /* Initialize a jnode. */ -reiser4_internal void -jnode_init(jnode * node, reiser4_tree * tree, jnode_type type) +void jnode_init(jnode * node, reiser4_tree * tree, jnode_type type) { assert("umka-175", node != NULL); - memset(node, 0, sizeof (jnode)); + memset(node, 0, sizeof(jnode)); ON_DEBUG(node->magic = JMAGIC); jnode_set_type(node, type); atomic_set(&node->d_count, 0); @@ -252,7 +243,7 @@ jnode_init(jnode * node, reiser4_tree * spin_jload_init(node); node->atom = NULL; node->tree = tree; - capture_list_clean(node); + INIT_LIST_HEAD(&node->capture_link); ASSIGN_NODE_LIST(node, NOT_CAPTURED); @@ -274,8 +265,7 @@ jnode_init(jnode * node, reiser4_tree * /* * Remove jnode from ->all_jnodes list. */ -static void -jnode_done(jnode * node, reiser4_tree * tree) +static void jnode_done(jnode * node, reiser4_tree * tree) { reiser4_super_info_data *sbinfo; @@ -289,8 +279,7 @@ jnode_done(jnode * node, reiser4_tree * #endif /* return already existing jnode of page */ -reiser4_internal jnode * -jnode_by_page(struct page *pg) +jnode *jnode_by_page(struct page *pg) { assert("nikita-2066", pg != NULL); assert("nikita-2400", PageLocked(pg)); @@ -300,20 +289,19 @@ jnode_by_page(struct page *pg) } /* exported functions to allocate/free jnode objects outside this file */ -reiser4_internal jnode * -jalloc(void) +jnode *jalloc(void) { jnode *jal = kmem_cache_alloc(_jnode_slab, GFP_KERNEL); return jal; } /* return jnode back to the slab allocator */ -reiser4_internal inline void -jfree(jnode * node) +inline void jfree(jnode * node) { assert("zam-449", node != NULL); - assert("nikita-2663", capture_list_is_clean(node) && NODE_LIST(node) == NOT_CAPTURED); + assert("nikita-2663", (list_empty_careful(&node->capture_link) && + NODE_LIST(node) == NOT_CAPTURED)); assert("nikita-2774", !JF_ISSET(node, JNODE_EFLUSH)); assert("nikita-3222", list_empty(&node->jnodes)); assert("nikita-3221", jnode_page(node) == NULL); @@ -329,10 +317,9 @@ jfree(jnode * node) * This function is supplied as RCU callback. It actually frees jnode when * last reference to it is gone. */ -static void -jnode_free_actor(struct rcu_head *head) +static void jnode_free_actor(struct rcu_head *head) { - jnode * node; + jnode *node; jnode_type jtype; node = container_of(head, jnode, rcu); @@ -359,19 +346,17 @@ jnode_free_actor(struct rcu_head *head) * Free a jnode. Post a callback to be executed later through RCU when all * references to @node are released. */ -static inline void -jnode_free(jnode * node, jnode_type jtype) +static inline void jnode_free(jnode * node, jnode_type jtype) { if (jtype != JNODE_INODE) { - /*assert("nikita-3219", list_empty(&node->rcu.list));*/ + /*assert("nikita-3219", list_empty(&node->rcu.list)); */ call_rcu(&node->rcu, jnode_free_actor); } else jnode_list_remove(node); } /* allocate new unformatted jnode */ -static jnode * -jnew_unformatted(void) +static jnode *jnew_unformatted(void) { jnode *jal; @@ -380,15 +365,14 @@ jnew_unformatted(void) return NULL; jnode_init(jal, current_tree, JNODE_UNFORMATTED_BLOCK); - jal->key.j.mapping = 0; + jal->key.j.mapping = NULL; jal->key.j.index = (unsigned long)-1; jal->key.j.objectid = 0; return jal; } /* look for jnode with given mapping and offset within hash table */ -reiser4_internal jnode * -jlookup(reiser4_tree * tree, oid_t objectid, unsigned long index) +jnode *jlookup(reiser4_tree * tree, oid_t objectid, unsigned long index) { jnode_key_t jkey; jnode *node; @@ -416,16 +400,14 @@ jlookup(reiser4_tree * tree, oid_t objec } /* per inode radix tree of jnodes is protected by tree's read write spin lock */ -static jnode * -jfind_nolock(struct address_space *mapping, unsigned long index) +static jnode *jfind_nolock(struct address_space *mapping, unsigned long index) { assert("vs-1694", mapping->host != NULL); return radix_tree_lookup(jnode_tree_by_inode(mapping->host), index); } -reiser4_internal jnode * -jfind(struct address_space *mapping, unsigned long index) +jnode *jfind(struct address_space * mapping, unsigned long index) { reiser4_tree *tree; jnode *node; @@ -441,36 +423,38 @@ jfind(struct address_space *mapping, uns return node; } -static void inode_attach_jnode(jnode *node) +static void inode_attach_jnode(jnode * node) { struct inode *inode; reiser4_inode *info; struct radix_tree_root *rtree; assert("nikita-34391", rw_tree_is_write_locked(jnode_get_tree(node))); - assert ("zam-1043", node->key.j.mapping != NULL); + assert("zam-1043", node->key.j.mapping != NULL); inode = node->key.j.mapping->host; info = reiser4_inode_data(inode); rtree = jnode_tree_by_reiser4_inode(info); - if (rtree->height == 0) { - /* prevent inode from being pruned when it has jnodes attached to it */ + if (rtree->height == 0) { + /* prevent inode from being pruned when it has jnodes attached + to it */ write_lock_irq(&inode->i_data.tree_lock); - inode->i_data.nrpages ++; + inode->i_data.nrpages++; write_unlock_irq(&inode->i_data.tree_lock); } assert("zam-1049", equi(rtree->rnode != NULL, info->nr_jnodes != 0)); - check_me("zam-1045", !radix_tree_insert(rtree, node->key.j.index, node)); - ON_DEBUG(info->nr_jnodes ++); + check_me("zam-1045", + !radix_tree_insert(rtree, node->key.j.index, node)); + ON_DEBUG(info->nr_jnodes++); } -static void inode_detach_jnode(jnode *node) +static void inode_detach_jnode(jnode * node) { struct inode *inode; reiser4_inode *info; struct radix_tree_root *rtree; assert("nikita-34392", rw_tree_is_write_locked(jnode_get_tree(node))); - assert ("zam-1044", node->key.j.mapping != NULL); + assert("zam-1044", node->key.j.mapping != NULL); inode = node->key.j.mapping->host; info = reiser4_inode_data(inode); rtree = jnode_tree_by_reiser4_inode(info); @@ -478,14 +462,14 @@ static void inode_detach_jnode(jnode *no assert("zam-1051", info->nr_jnodes != 0); assert("zam-1052", rtree->rnode != NULL); assert("vs-1730", !JF_ISSET(node, JNODE_EFLUSH)); - ON_DEBUG(info->nr_jnodes --); + ON_DEBUG(info->nr_jnodes--); /* delete jnode from inode's radix tree of jnodes */ check_me("zam-1046", radix_tree_delete(rtree, node->key.j.index)); - if (rtree->height == 0) { + if (rtree->height == 0) { /* inode can be pruned now */ write_lock_irq(&inode->i_data.tree_lock); - inode->i_data.nrpages --; + inode->i_data.nrpages--; write_unlock_irq(&inode->i_data.tree_lock); } } @@ -496,7 +480,8 @@ static void inode_detach_jnode(jnode *no fs/reiser4/plugin/item/extent_file_ops.c:index_extent_jnode when new jnode is created */ static void -hash_unformatted_jnode(jnode *node, struct address_space *mapping, unsigned long index) +hash_unformatted_jnode(jnode * node, struct address_space *mapping, + unsigned long index) { j_hash_table *jtable; @@ -506,9 +491,9 @@ hash_unformatted_jnode(jnode *node, stru assert("vs-1444", node->key.j.index == (unsigned long)-1); assert("nikita-3439", rw_tree_is_write_locked(jnode_get_tree(node))); - node->key.j.mapping = mapping; + node->key.j.mapping = mapping; node->key.j.objectid = get_inode_oid(mapping->host); - node->key.j.index = index; + node->key.j.index = index; jtable = &jnode_get_tree(node)->jhash_table; @@ -523,16 +508,17 @@ hash_unformatted_jnode(jnode *node, stru inode_attach_jnode(node); } -static void -unhash_unformatted_node_nolock(jnode *node) +static void unhash_unformatted_node_nolock(jnode * node) { assert("vs-1683", node->key.j.mapping != NULL); - assert("vs-1684", node->key.j.objectid == get_inode_oid(node->key.j.mapping->host)); + assert("vs-1684", + node->key.j.objectid == + get_inode_oid(node->key.j.mapping->host)); /* remove jnode from hash-table */ j_hash_remove_rcu(&node->tree->jhash_table, node); inode_detach_jnode(node); - node->key.j.mapping = 0; + node->key.j.mapping = NULL; node->key.j.index = (unsigned long)-1; node->key.j.objectid = 0; @@ -541,8 +527,7 @@ unhash_unformatted_node_nolock(jnode *no /* remove jnode from hash table and from inode's tree of jnodes. This is used in reiser4_invalidatepage and in kill_hook_extent -> truncate_inode_jnodes -> uncapture_jnode */ -reiser4_internal void -unhash_unformatted_jnode(jnode *node) +void unhash_unformatted_jnode(jnode * node) { assert("vs-1445", jnode_is_unformatted(node)); WLOCK_TREE(node->tree); @@ -557,9 +542,8 @@ unhash_unformatted_jnode(jnode *node) * allocate new jnode, insert it, and also insert into radix tree for the * given inode/mapping. */ -reiser4_internal jnode * -find_get_jnode(reiser4_tree * tree, struct address_space *mapping, oid_t oid, - unsigned long index) +jnode *find_get_jnode(reiser4_tree * tree, struct address_space *mapping, + oid_t oid, unsigned long index) { jnode *result; jnode *shadow; @@ -589,17 +573,16 @@ find_get_jnode(reiser4_tree * tree, stru } WUNLOCK_TREE(tree); - assert("nikita-2955", ergo(result != NULL, jnode_invariant(result, 0, 0))); + assert("nikita-2955", + ergo(result != NULL, jnode_invariant(result, 0, 0))); radix_tree_preload_end(); return result; } - /* jget() (a la zget() but for unformatted nodes). Returns (and possibly creates) jnode corresponding to page @pg. jnode is attached to page and inserted into jnode hash-table. */ -static jnode * -do_jget(reiser4_tree * tree, struct page * pg) +static jnode *do_jget(reiser4_tree * tree, struct page *pg) { /* * There are two ways to create jnode: starting with pre-existing page @@ -645,10 +628,9 @@ do_jget(reiser4_tree * tree, struct page /* * return jnode for @pg, creating it if necessary. */ -reiser4_internal jnode * -jnode_of_page(struct page * pg) +jnode *jnode_of_page(struct page * pg) { - jnode * result; + jnode *result; assert("umka-176", pg != NULL); assert("nikita-2394", PageLocked(pg)); @@ -659,14 +641,18 @@ jnode_of_page(struct page * pg) assert("nikita-3210", result == jprivate(pg)); assert("nikita-2046", jnode_page(jprivate(pg)) == pg); if (jnode_is_unformatted(jprivate(pg))) { - assert("nikita-2364", jprivate(pg)->key.j.index == pg->index); + assert("nikita-2364", + jprivate(pg)->key.j.index == pg->index); assert("nikita-2367", jprivate(pg)->key.j.mapping == pg->mapping); assert("nikita-2365", - jprivate(pg)->key.j.objectid == get_inode_oid(pg->mapping->host)); + jprivate(pg)->key.j.objectid == + get_inode_oid(pg->mapping->host)); assert("vs-1200", - jprivate(pg)->key.j.objectid == pg->mapping->host->i_ino); - assert("nikita-2356", jnode_is_unformatted(jnode_by_page(pg))); + jprivate(pg)->key.j.objectid == + pg->mapping->host->i_ino); + assert("nikita-2356", + jnode_is_unformatted(jnode_by_page(pg))); } assert("nikita-2956", jnode_invariant(jprivate(pg), 0, 0)); } @@ -675,8 +661,7 @@ jnode_of_page(struct page * pg) /* attach page to jnode: set ->pg pointer in jnode, and ->private one in the * page.*/ -reiser4_internal void -jnode_attach_page(jnode * node, struct page *pg) +void jnode_attach_page(jnode * node, struct page *pg) { assert("nikita-2060", node != NULL); assert("nikita-2061", pg != NULL); @@ -689,14 +674,13 @@ jnode_attach_page(jnode * node, struct p assert("nikita-2397", spin_jnode_is_locked(node)); page_cache_get(pg); - pg->private = (unsigned long) node; + pg->private = (unsigned long)node; node->pg = pg; SetPagePrivate(pg); } /* Dual to jnode_attach_page: break a binding between page and jnode */ -reiser4_internal void -page_clear_jnode(struct page *page, jnode * node) +void page_clear_jnode(struct page *page, jnode * node) { assert("nikita-2424", page != NULL); assert("nikita-2425", PageLocked(page)); @@ -714,13 +698,15 @@ page_clear_jnode(struct page *page, jnod } /* it is only used in one place to handle error */ -reiser4_internal void -page_detach_jnode(struct page *page, struct address_space *mapping, unsigned long index) +void +page_detach_jnode(struct page *page, struct address_space *mapping, + unsigned long index) { assert("nikita-2395", page != NULL); lock_page(page); - if ((page->mapping == mapping) && (page->index == index) && PagePrivate(page)) { + if ((page->mapping == mapping) && (page->index == index) + && PagePrivate(page)) { jnode *node; node = jprivate(page); @@ -737,8 +723,7 @@ page_detach_jnode(struct page *page, str the opposite direction. This is done through standard trylock-and-release loop. */ -static struct page * -jnode_lock_page(jnode * node) +static struct page *jnode_lock_page(jnode * node) { struct page *page; @@ -756,7 +741,7 @@ jnode_lock_page(jnode * node) /* no need to page_cache_get( page ) here, because page cannot be evicted from memory without detaching it from jnode and this requires spin lock on jnode that we already hold. - */ + */ if (!TestSetPageLocked(page)) { /* We won a lock on jnode page, proceed. */ break; @@ -770,7 +755,7 @@ jnode_lock_page(jnode * node) returned to the free pool, or re-assigned while we were waiting on locked bit. This will be rechecked on the next loop iteration. - */ + */ page_cache_release(page); /* try again */ @@ -782,8 +767,7 @@ jnode_lock_page(jnode * node) * is JNODE_PARSED bit is not set, call ->parse() method of jnode, to verify * validness of jnode content. */ -static inline int -jparse(jnode * node) +static inline int jparse(jnode * node) { int result; @@ -802,10 +786,9 @@ jparse(jnode * node) /* Lock a page attached to jnode, create and attach page to jnode if it had no * one. */ -reiser4_internal struct page * -jnode_get_page_locked(jnode * node, int gfp_flags) +struct page *jnode_get_page_locked(jnode * node, int gfp_flags) { - struct page * page; + struct page *page; LOCK_JNODE(node); page = jnode_page(node); @@ -833,14 +816,14 @@ jnode_get_page_locked(jnode * node, int UNLOCK_JNODE(node); page_cache_release(page); - assert ("zam-894", jnode_page(node) == page); + assert("zam-894", jnode_page(node) == page); return page; } /* Start read operation for jnode's page if page is not up-to-date. */ -static int jnode_start_read (jnode * node, struct page * page) +static int jnode_start_read(jnode * node, struct page *page) { - assert ("zam-893", PageLocked(page)); + assert("zam-893", PageLocked(page)); if (PageUptodate(page)) { unlock_page(page); @@ -850,7 +833,7 @@ static int jnode_start_read (jnode * nod } #if REISER4_DEBUG -static void check_jload(jnode * node, struct page * page) +static void check_jload(jnode * node, struct page *page) { if (jnode_is_znode(node)) { node40_header *nh; @@ -858,7 +841,7 @@ static void check_jload(jnode * node, st z = JZNODE(node); if (znode_is_any_locked(z)) { - nh = (node40_header *)kmap(page); + nh = (node40_header *) kmap(page); /* this only works for node40-only file systems. For * debugging. */ assert("nikita-3253", @@ -875,18 +858,17 @@ static void check_jload(jnode * node, st /* prefetch jnode to speed up next call to jload. Call this when you are going * to call jload() shortly. This will bring appropriate portion of jnode into * CPU cache. */ -reiser4_internal void jload_prefetch(jnode *node) +void jload_prefetch(jnode * node) { prefetchw(&node->x_count); } /* load jnode's data into memory */ -reiser4_internal int -jload_gfp (jnode * node /* node to load */, - int gfp_flags /* allocation flags*/, - int do_kmap /* true if page should be kmapped */) +int jload_gfp(jnode * node /* node to load */ , + int gfp_flags /* allocation flags */ , + int do_kmap /* true if page should be kmapped */ ) { - struct page * page; + struct page *page; int result = 0; int parsed; @@ -956,16 +938,16 @@ jload_gfp (jnode * node /* node to load return 0; - failed: + failed: jrelse_tail(node); return result; } /* start asynchronous reading for given jnode's page. */ -reiser4_internal int jstartio (jnode * node) +int jstartio(jnode * node) { - struct page * page; + struct page *page; page = jnode_get_page_locked(node, GFP_KERNEL); if (IS_ERR(page)) @@ -974,12 +956,11 @@ reiser4_internal int jstartio (jnode * n return jnode_start_read(node, page); } - /* Initialize a node by calling appropriate plugin instead of reading * node from disk as in jload(). */ -reiser4_internal int jinit_new (jnode * node, int gfp_flags) +int jinit_new(jnode * node, int gfp_flags) { - struct page * page; + struct page *page; int result; jref(node); @@ -997,7 +978,7 @@ reiser4_internal int jinit_new (jnode * node->data = kmap(page); if (!jnode_is_parsed(node)) { - jnode_plugin * jplug = jnode_ops(node); + jnode_plugin *jplug = jnode_ops(node); result = UNDER_SPIN(jnode, node, jplug->init(node)); if (result) { kunmap(page); @@ -1008,26 +989,25 @@ reiser4_internal int jinit_new (jnode * return 0; - failed: + failed: jrelse(node); return result; } /* release a reference to jnode acquired by jload(), decrement ->d_count */ -reiser4_internal void -jrelse_tail(jnode * node /* jnode to release references to */) +void jrelse_tail(jnode * node /* jnode to release references to */ ) { assert("nikita-489", atomic_read(&node->d_count) > 0); atomic_dec(&node->d_count); /* release reference acquired in jload_gfp() or jinit_new() */ jput(node); - LOCK_CNT_DEC(d_refs); + if (jnode_is_unformatted(node) || jnode_is_znode(node)) + LOCK_CNT_DEC(d_refs); } /* drop reference to node data. When last reference is dropped, data are unloaded. */ -reiser4_internal void -jrelse(jnode * node /* jnode to release references to */) +void jrelse(jnode * node /* jnode to release references to */ ) { struct page *page; @@ -1073,8 +1053,7 @@ static void jnode_finish_io(jnode * node * separate function, because we want fast path of jput() to be inline and, * therefore, small. */ -reiser4_internal void -jput_final(jnode * node) +void jput_final(jnode * node) { int r_i_p; @@ -1102,8 +1081,7 @@ jput_final(jnode * node) /* if !r_i_p some other thread is already killing it */ } -reiser4_internal int -jwait_io(jnode * node, int rw) +int jwait_io(jnode * node, int rw) { struct page *page; int result; @@ -1139,8 +1117,7 @@ jwait_io(jnode * node, int rw) */ /* set jnode type. This is done during jnode initialization. */ -static void -jnode_set_type(jnode * node, jnode_type type) +static void jnode_set_type(jnode * node, jnode_type type) { static unsigned long type_to_mask[] = { [JNODE_UNFORMATTED_BLOCK] = 1, @@ -1159,23 +1136,20 @@ jnode_set_type(jnode * node, jnode_type /* ->init() method of jnode plugin for jnodes that don't require plugin * specific initialization. */ -static int -init_noinit(jnode * node UNUSED_ARG) +static int init_noinit(jnode * node UNUSED_ARG) { return 0; } /* ->parse() method of jnode plugin for jnodes that don't require plugin * specific pasring. */ -static int -parse_noparse(jnode * node UNUSED_ARG) +static int parse_noparse(jnode * node UNUSED_ARG) { return 0; } /* ->mapping() method for unformatted jnode */ -reiser4_internal struct address_space * -mapping_jnode(const jnode * node) +struct address_space *mapping_jnode(const jnode * node) { struct address_space *map; @@ -1192,8 +1166,7 @@ mapping_jnode(const jnode * node) } /* ->index() method for unformatted jnodes */ -reiser4_internal unsigned long -index_jnode(const jnode * node) +unsigned long index_jnode(const jnode * node) { assert("vs-1447", !JF_ISSET(node, JNODE_CC)); /* index is stored in jnode */ @@ -1201,8 +1174,7 @@ index_jnode(const jnode * node) } /* ->remove() method for unformatted jnodes */ -static inline void -remove_jnode(jnode * node, reiser4_tree * tree) +static inline void remove_jnode(jnode * node, reiser4_tree * tree) { /* remove jnode from hash table and radix tree */ if (node->key.j.mapping) @@ -1210,18 +1182,15 @@ remove_jnode(jnode * node, reiser4_tree } /* ->mapping() method for znodes */ -static struct address_space * -mapping_znode(const jnode * node) +static struct address_space *mapping_znode(const jnode * node) { assert("vs-1447", !JF_ISSET(node, JNODE_CC)); /* all znodes belong to fake inode */ return get_super_fake(jnode_get_tree(node)->super)->i_mapping; } -extern int znode_shift_order; /* ->index() method for znodes */ -static unsigned long -index_znode(const jnode * node) +static unsigned long index_znode(const jnode * node) { unsigned long addr; assert("nikita-3317", (1 << znode_shift_order) < sizeof(znode)); @@ -1232,16 +1201,15 @@ index_znode(const jnode * node) } /* ->mapping() method for bitmap jnode */ -static struct address_space * -mapping_bitmap(const jnode * node) +static struct address_space *mapping_bitmap(const jnode * node) { /* all bitmap blocks belong to special bitmap inode */ - return get_super_private(jnode_get_tree(node)->super)->bitmap->i_mapping; + return get_super_private(jnode_get_tree(node)->super)->bitmap-> + i_mapping; } /* ->index() method for jnodes that are indexed by address */ -static unsigned long -index_is_address(const jnode * node) +static unsigned long index_is_address(const jnode * node) { unsigned long ind; @@ -1250,8 +1218,7 @@ index_is_address(const jnode * node) } /* resolve race with jput */ -reiser4_internal jnode * -jnode_rip_sync(reiser4_tree *t, jnode * node) +jnode *jnode_rip_sync(reiser4_tree * t, jnode * node) { /* * This is used as part of RCU-based jnode handling. @@ -1284,9 +1251,7 @@ jnode_rip_sync(reiser4_tree *t, jnode * return node; } - -reiser4_internal reiser4_key * -jnode_build_key(const jnode * node, reiser4_key * key) +reiser4_key *jnode_build_key(const jnode * node, reiser4_key * key) { struct inode *inode; item_plugin *iplug; @@ -1296,8 +1261,7 @@ jnode_build_key(const jnode * node, reis assert("nikita-3093", key != NULL); assert("nikita-3094", jnode_is_unformatted(node)); - - off = ((loff_t)index_jnode(node)) << PAGE_CACHE_SHIFT; + off = ((loff_t) index_jnode(node)) << PAGE_CACHE_SHIFT; inode = mapping_jnode(node)->host; if (node->parent_item_id != 0) @@ -1311,8 +1275,8 @@ jnode_build_key(const jnode * node, reis file_plugin *fplug; fplug = inode_file_plugin(inode); - assert ("zam-1007", fplug != NULL); - assert ("zam-1008", fplug->key_by_inode != NULL); + assert("zam-1007", fplug != NULL); + assert("zam-1008", fplug->key_by_inode != NULL); fplug->key_by_inode(inode, off, key); } @@ -1320,18 +1284,14 @@ jnode_build_key(const jnode * node, reis return key; } -extern int zparse(znode * node); - /* ->parse() method for formatted nodes */ -static int -parse_znode(jnode * node) +static int parse_znode(jnode * node) { return zparse(JZNODE(node)); } /* ->delete() method for formatted nodes */ -static void -delete_znode(jnode * node, reiser4_tree * tree) +static void delete_znode(jnode * node, reiser4_tree * tree) { znode *z; @@ -1348,8 +1308,7 @@ delete_znode(jnode * node, reiser4_tree } /* ->remove() method for formatted nodes */ -static int -remove_znode(jnode * node, reiser4_tree * tree) +static int remove_znode(jnode * node, reiser4_tree * tree) { znode *z; @@ -1368,8 +1327,7 @@ remove_znode(jnode * node, reiser4_tree } /* ->init() method for formatted nodes */ -static int -init_znode(jnode * node) +static int init_znode(jnode * node) { znode *z; @@ -1378,13 +1336,8 @@ init_znode(jnode * node) return z->nplug->init(z); } -/* jplug->clone for formatted nodes (znodes) */ -znode *zalloc(int gfp_flag); -void zinit(znode *, const znode * parent, reiser4_tree *); - /* ->clone() method for formatted nodes */ -static jnode * -clone_formatted(jnode *node) +static jnode *clone_formatted(jnode * node) { znode *clone; @@ -1392,7 +1345,7 @@ clone_formatted(jnode *node) clone = zalloc(GFP_KERNEL); if (clone == NULL) return ERR_PTR(RETERR(-ENOMEM)); - zinit(clone, 0, current_tree); + zinit(clone, NULL, current_tree); jnode_set_block(ZJNODE(clone), jnode_get_block(node)); /* ZJNODE(clone)->key.z is not initialized */ clone->level = JZNODE(node)->level; @@ -1401,8 +1354,7 @@ clone_formatted(jnode *node) } /* jplug->clone for unformatted nodes */ -static jnode * -clone_unformatted(jnode *node) +static jnode *clone_unformatted(jnode * node) { jnode *clone; @@ -1421,7 +1373,6 @@ clone_unformatted(jnode *node) /* * Setup jnode plugin methods for various jnode types. */ - jnode_plugin jnode_plugins[LAST_JNODE_TYPE] = { [JNODE_UNFORMATTED_BLOCK] = { .h = { @@ -1430,7 +1381,7 @@ jnode_plugin jnode_plugins[LAST_JNODE_TY .pops = NULL, .label = "unformatted", .desc = "unformatted node", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .init = init_noinit, .parse = parse_noparse, @@ -1445,7 +1396,7 @@ jnode_plugin jnode_plugins[LAST_JNODE_TY .pops = NULL, .label = "formatted", .desc = "formatted tree node", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .init = init_znode, .parse = parse_znode, @@ -1460,7 +1411,7 @@ jnode_plugin jnode_plugins[LAST_JNODE_TY .pops = NULL, .label = "bitmap", .desc = "bitmap node", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .init = init_noinit, .parse = parse_noparse, @@ -1475,7 +1426,7 @@ jnode_plugin jnode_plugins[LAST_JNODE_TY .pops = NULL, .label = "io head", .desc = "io head", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .init = init_noinit, .parse = parse_noparse, @@ -1490,7 +1441,7 @@ jnode_plugin jnode_plugins[LAST_JNODE_TY .pops = NULL, .label = "inode", .desc = "inode's builtin jnode", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .init = NULL, .parse = NULL, @@ -1531,8 +1482,7 @@ jnode_plugin jnode_plugins[LAST_JNODE_TY * under tree lock. If it returns true, jnode is irrevocably committed to be * deleted/removed. */ -static inline int -jnode_is_busy(const jnode * node, jnode_type jtype) +static inline int jnode_is_busy(const jnode * node, jnode_type jtype) { /* if other thread managed to acquire a reference to this jnode, don't * free it. */ @@ -1617,12 +1567,11 @@ void jnode_list_remove(jnode * node) * this is called by jput_final() to remove jnode when last reference to it is * released. */ -static int -jnode_try_drop(jnode * node) +static int jnode_try_drop(jnode * node) { int result; reiser4_tree *tree; - jnode_type jtype; + jnode_type jtype; assert("nikita-2491", node != NULL); assert("nikita-2583", JF_ISSET(node, JNODE_RIP)); @@ -1666,13 +1615,12 @@ jnode_try_drop(jnode * node) } /* jdelete() -- Delete jnode from the tree and file system */ -static int -jdelete(jnode * node /* jnode to finish with */) +static int jdelete(jnode * node /* jnode to finish with */ ) { struct page *page; int result; reiser4_tree *tree; - jnode_type jtype; + jnode_type jtype; assert("nikita-467", node != NULL); assert("nikita-2531", JF_ISSET(node, JNODE_RIP)); @@ -1730,11 +1678,10 @@ jdelete(jnode * node /* jnode to finish 0: successfully dropped jnode */ -static int -jdrop_in_tree(jnode * node, reiser4_tree * tree) +static int jdrop_in_tree(jnode * node, reiser4_tree * tree) { struct page *page; - jnode_type jtype; + jnode_type jtype; int result; assert("zam-602", node != NULL); @@ -1742,7 +1689,6 @@ jdrop_in_tree(jnode * node, reiser4_tree assert("nikita-2403", !JF_ISSET(node, JNODE_HEARD_BANSHEE)); // assert( "nikita-2532", JF_ISSET( node, JNODE_RIP ) ); - jtype = jnode_get_type(node); page = jnode_lock_page(node); @@ -1782,19 +1728,16 @@ jdrop_in_tree(jnode * node, reiser4_tree /* This function frees jnode "if possible". In particular, [dcx]_count has to be 0 (where applicable). */ -reiser4_internal void -jdrop(jnode * node) +void jdrop(jnode * node) { jdrop_in_tree(node, jnode_get_tree(node)); } - /* IO head jnode implementation; The io heads are simple j-nodes with limited functionality (these j-nodes are not in any hash table) just for reading from and writing to disk. */ -reiser4_internal jnode * -alloc_io_head(const reiser4_block_nr * block) +jnode *alloc_io_head(const reiser4_block_nr * block) { jnode *jal = jalloc(); @@ -1808,8 +1751,7 @@ alloc_io_head(const reiser4_block_nr * b return jal; } -reiser4_internal void -drop_io_head(jnode * node) +void drop_io_head(jnode * node) { assert("zam-648", jnode_get_type(node) == JNODE_IO_HEAD); @@ -1818,23 +1760,20 @@ drop_io_head(jnode * node) } /* protect keep jnode data from reiser4_releasepage() */ -reiser4_internal void -pin_jnode_data(jnode * node) +void pin_jnode_data(jnode * node) { assert("zam-671", jnode_page(node) != NULL); page_cache_get(jnode_page(node)); } /* make jnode data free-able again */ -reiser4_internal void -unpin_jnode_data(jnode * node) +void unpin_jnode_data(jnode * node) { assert("zam-672", jnode_page(node) != NULL); page_cache_release(jnode_page(node)); } -reiser4_internal struct address_space * -jnode_get_mapping(const jnode * node) +struct address_space *jnode_get_mapping(const jnode * node) { assert("nikita-3162", node != NULL); return jnode_ops(node)->mapping(node); @@ -1842,60 +1781,44 @@ jnode_get_mapping(const jnode * node) #if REISER4_DEBUG /* debugging aid: jnode invariant */ -reiser4_internal int -jnode_invariant_f(const jnode * node, - char const **msg) +int jnode_invariant_f(const jnode * node, char const **msg) { #define _ergo(ant, con) \ ((*msg) = "{" #ant "} ergo {" #con "}", ergo((ant), (con))) #define _check(exp) ((*msg) = #exp, (exp)) - return - _check(node != NULL) && - - /* [jnode-queued] */ - - /* only relocated node can be queued, except that when znode - * is being deleted, its JNODE_RELOC bit is cleared */ - _ergo(JF_ISSET(node, JNODE_FLUSH_QUEUED), - JF_ISSET(node, JNODE_RELOC) || - JF_ISSET(node, JNODE_HEARD_BANSHEE)) && - - _check(node->jnodes.prev != NULL) && - _check(node->jnodes.next != NULL) && - - /* [jnode-dirty] invariant */ - - /* dirty inode is part of atom */ - _ergo(jnode_is_dirty(node), node->atom != NULL) && - - /* [jnode-oid] invariant */ - - /* for unformatted node ->objectid and ->mapping fields are - * consistent */ - _ergo(jnode_is_unformatted(node) && node->key.j.mapping != NULL, - node->key.j.objectid == get_inode_oid(node->key.j.mapping->host)) && - /* [jnode-atom-valid] invariant */ - - /* node atom has valid state */ - _ergo(node->atom != NULL, - node->atom->stage != ASTAGE_INVALID) && - - /* [jnode-page-binding] invariant */ - - /* if node points to page, it points back to node */ - _ergo(node->pg != NULL, jprivate(node->pg) == node) && - - /* [jnode-refs] invariant */ - - /* only referenced jnode can be loaded */ - _check(atomic_read(&node->x_count) >= atomic_read(&node->d_count)); + return _check(node != NULL) && + /* [jnode-queued] */ + /* only relocated node can be queued, except that when znode + * is being deleted, its JNODE_RELOC bit is cleared */ + _ergo(JF_ISSET(node, JNODE_FLUSH_QUEUED), + JF_ISSET(node, JNODE_RELOC) || + JF_ISSET(node, JNODE_HEARD_BANSHEE)) && + _check(node->jnodes.prev != NULL) && + _check(node->jnodes.next != NULL) && + /* [jnode-dirty] invariant */ + /* dirty inode is part of atom */ + _ergo(jnode_is_dirty(node), node->atom != NULL) && + /* [jnode-oid] invariant */ + /* for unformatted node ->objectid and ->mapping fields are + * consistent */ + _ergo(jnode_is_unformatted(node) && node->key.j.mapping != NULL, + node->key.j.objectid == + get_inode_oid(node->key.j.mapping->host)) && + /* [jnode-atom-valid] invariant */ + /* node atom has valid state */ + _ergo(node->atom != NULL, node->atom->stage != ASTAGE_INVALID) && + /* [jnode-page-binding] invariant */ + /* if node points to page, it points back to node */ + _ergo(node->pg != NULL, jprivate(node->pg) == node) && + /* [jnode-refs] invariant */ + /* only referenced jnode can be loaded */ + _check(atomic_read(&node->x_count) >= atomic_read(&node->d_count)); } /* debugging aid: check znode invariant and panic if it doesn't hold */ -static int -jnode_invariant(const jnode * node, int tlocked, int jlocked) +static int jnode_invariant(const jnode * node, int tlocked, int jlocked) { char const *failed_msg; int result; @@ -1922,8 +1845,7 @@ jnode_invariant(const jnode * node, int return result; } -static const char * -jnode_type_name(jnode_type type) +static const char *jnode_type_name(jnode_type type) { switch (type) { case JNODE_UNFORMATTED_BLOCK: @@ -1951,9 +1873,8 @@ jnode_type_name(jnode_type type) ( JF_ISSET( ( node ), ( flag ) ) ? ((#flag "|")+6) : "" ) /* debugging aid: output human readable information about @node */ -reiser4_internal void -info_jnode(const char *prefix /* prefix to print */ , - const jnode * node /* node to print */ ) +void info_jnode(const char *prefix /* prefix to print */ , + const jnode * node /* node to print */ ) { assert("umka-068", prefix != NULL); @@ -1962,35 +1883,34 @@ info_jnode(const char *prefix /* prefix return; } - printk("%s: %p: state: %lx: [%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s], level: %i," - " block: %s, d_count: %d, x_count: %d, " - "pg: %p, atom: %p, lock: %i:%i, type: %s, ", - prefix, node, node->state, - jnode_state_name(node, JNODE_PARSED), - jnode_state_name(node, JNODE_HEARD_BANSHEE), - jnode_state_name(node, JNODE_LEFT_CONNECTED), - jnode_state_name(node, JNODE_RIGHT_CONNECTED), - jnode_state_name(node, JNODE_ORPHAN), - jnode_state_name(node, JNODE_CREATED), - jnode_state_name(node, JNODE_RELOC), - jnode_state_name(node, JNODE_OVRWR), - jnode_state_name(node, JNODE_DIRTY), - jnode_state_name(node, JNODE_IS_DYING), - jnode_state_name(node, JNODE_EFLUSH), - jnode_state_name(node, JNODE_FLUSH_QUEUED), - jnode_state_name(node, JNODE_RIP), - jnode_state_name(node, JNODE_MISSED_IN_CAPTURE), - jnode_state_name(node, JNODE_WRITEBACK), - jnode_state_name(node, JNODE_NEW), - jnode_state_name(node, JNODE_DKSET), - jnode_state_name(node, JNODE_EPROTECTED), - jnode_state_name(node, JNODE_REPACK), - jnode_state_name(node, JNODE_CLUSTER_PAGE), - jnode_get_level(node), sprint_address(jnode_get_block(node)), - atomic_read(&node->d_count), atomic_read(&node->x_count), - jnode_page(node), node->atom, - 0, 0, - jnode_type_name(jnode_get_type(node))); + printk + ("%s: %p: state: %lx: [%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s], level: %i," + " block: %s, d_count: %d, x_count: %d, " + "pg: %p, atom: %p, lock: %i:%i, type: %s, ", prefix, node, + node->state, jnode_state_name(node, JNODE_PARSED), + jnode_state_name(node, JNODE_HEARD_BANSHEE), jnode_state_name(node, + JNODE_LEFT_CONNECTED), + jnode_state_name(node, JNODE_RIGHT_CONNECTED), + jnode_state_name(node, JNODE_ORPHAN), jnode_state_name(node, + JNODE_CREATED), + jnode_state_name(node, JNODE_RELOC), jnode_state_name(node, + JNODE_OVRWR), + jnode_state_name(node, JNODE_DIRTY), jnode_state_name(node, + JNODE_IS_DYING), + jnode_state_name(node, JNODE_EFLUSH), jnode_state_name(node, + JNODE_FLUSH_QUEUED), + jnode_state_name(node, JNODE_RIP), jnode_state_name(node, + JNODE_MISSED_IN_CAPTURE), + jnode_state_name(node, JNODE_WRITEBACK), jnode_state_name(node, + JNODE_NEW), + jnode_state_name(node, JNODE_DKSET), jnode_state_name(node, + JNODE_EPROTECTED), + jnode_state_name(node, JNODE_REPACK), jnode_state_name(node, + JNODE_CLUSTER_PAGE), + jnode_get_level(node), sprint_address(jnode_get_block(node)), + atomic_read(&node->d_count), atomic_read(&node->x_count), + jnode_page(node), node->atom, 0, 0, + jnode_type_name(jnode_get_type(node))); if (jnode_is_unformatted(node)) { printk("inode: %llu, index: %lu, ", node->key.j.objectid, node->key.j.index); @@ -1998,9 +1918,8 @@ info_jnode(const char *prefix /* prefix } /* debugging aid: output human readable information about @node */ -reiser4_internal void -print_jnode(const char *prefix /* prefix to print */ , - const jnode * node /* node to print */) +void print_jnode(const char *prefix /* prefix to print */ , + const jnode * node /* node to print */ ) { if (jnode_is_znode(node)) print_znode(prefix, JZNODE(node)); @@ -2008,10 +1927,10 @@ print_jnode(const char *prefix /* prefix info_jnode(prefix, node); } -#endif /* REISER4_DEBUG */ +#endif /* REISER4_DEBUG */ /* this is only used to created jnode during capture copy */ -reiser4_internal jnode *jclone(jnode *node) +jnode *jclone(jnode * node) { jnode *clone; @@ -2026,7 +1945,6 @@ reiser4_internal jnode *jclone(jnode *no return clone; } - /* Make Linus happy. Local variables: c-indentation-style: "K&R" diff -puN fs/reiser4/jnode.h~reiser4-big-update fs/reiser4/jnode.h --- devel/fs/reiser4/jnode.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/jnode.h 2005-09-15 19:51:08.000000000 -0700 @@ -8,7 +8,6 @@ #include "forward.h" #include "type_safe_hash.h" -#include "type_safe_list.h" #include "txnmgr.h" #include "key.h" #include "debug.h" @@ -99,7 +98,7 @@ typedef struct { struct jnode { #if REISER4_DEBUG -#define JMAGIC 0x52654973 /* "ReIs" */ +#define JMAGIC 0x52654973 /* "ReIs" */ int magic; #endif /* FIRST CACHE LINE (16 bytes): data used by jload */ @@ -112,13 +111,13 @@ struct jnode { /* counter of references to jnode itself. Increased on jref(). Decreased on jput(). - */ + */ /* 8 */ atomic_t x_count; /* counter of references to jnode's data. Pin data page(s) in memory while this is greater than 0. Increased on jload(). Decreased on jrelse(). - */ + */ /* 12 */ atomic_t d_count; /* SECOND CACHE LINE: data used by hash table lookups */ @@ -142,7 +141,7 @@ struct jnode { /* 36 */ struct page *pg; /* pointer to node itself. This is page_address(node->pg) when page is attached to the jnode - */ + */ /* 40 */ void *data; /* 44 */ reiser4_tree *tree; @@ -155,11 +154,12 @@ struct jnode { /* 52 */ txn_atom *atom; /* capture list */ - /* 56 */ capture_list_link capture_link; + /* 56 */ struct list_head capture_link; /* FIFTH CACHE LINE */ - /* 64 */ struct rcu_head rcu; /* crosses cache line */ + /* 64 */ struct rcu_head rcu; + /* crosses cache line */ /* SIXTH CACHE LINE */ @@ -176,55 +176,52 @@ struct jnode { /* list of all jnodes for debugging purposes. */ struct list_head jnodes; /* how many times this jnode was written in one transaction */ - int written; + int written; /* this indicates which atom's list the jnode is on */ - atom_list list1; + atom_list list; #endif -} __attribute__((aligned(16))); - +} __attribute__ ((aligned(16))); /* * jnode types. Enumeration of existing jnode types. */ typedef enum { - JNODE_UNFORMATTED_BLOCK, /* unformatted block */ - JNODE_FORMATTED_BLOCK, /* formatted block, znode */ - JNODE_BITMAP, /* bitmap */ - JNODE_IO_HEAD, /* jnode representing a block in the - * wandering log */ - JNODE_INODE, /* jnode embedded into inode */ + JNODE_UNFORMATTED_BLOCK, /* unformatted block */ + JNODE_FORMATTED_BLOCK, /* formatted block, znode */ + JNODE_BITMAP, /* bitmap */ + JNODE_IO_HEAD, /* jnode representing a block in the + * wandering log */ + JNODE_INODE, /* jnode embedded into inode */ LAST_JNODE_TYPE } jnode_type; -TYPE_SAFE_LIST_DEFINE(capture, jnode, capture_link); - /* jnode states */ typedef enum { /* jnode's page is loaded and data checked */ JNODE_PARSED = 0, - /* node was deleted, not all locks on it were released. This + /* node was deleted, not all locks on it were released. This node is empty and is going to be removed from the tree shortly. */ JNODE_HEARD_BANSHEE = 1, - /* left sibling pointer is valid */ + /* left sibling pointer is valid */ JNODE_LEFT_CONNECTED = 2, - /* right sibling pointer is valid */ + /* right sibling pointer is valid */ JNODE_RIGHT_CONNECTED = 3, - /* znode was just created and doesn't yet have a pointer from + /* znode was just created and doesn't yet have a pointer from its parent */ JNODE_ORPHAN = 4, - /* this node was created by its transaction and has not been assigned - a block address. */ + /* this node was created by its transaction and has not been assigned + a block address. */ JNODE_CREATED = 5, - /* this node is currently relocated */ + /* this node is currently relocated */ JNODE_RELOC = 6, - /* this node is currently wandered */ + /* this node is currently wandered */ JNODE_OVRWR = 7, - /* this znode has been modified */ + /* this znode has been modified */ JNODE_DIRTY = 8, /* znode lock is being invalidated */ @@ -242,11 +239,11 @@ typedef enum { JNODE_TYPE_2 = 14, JNODE_TYPE_3 = 15, - /* jnode is being destroyed */ + /* jnode is being destroyed */ JNODE_RIP = 16, - /* znode was not captured during locking (it might so be because - ->level != LEAF_LEVEL and lock_mode == READ_LOCK) */ + /* znode was not captured during locking (it might so be because + ->level != LEAF_LEVEL and lock_mode == READ_LOCK) */ JNODE_MISSED_IN_CAPTURE = 17, /* write is in progress */ @@ -305,27 +302,23 @@ typedef enum { /* Macros for accessing the jnode state. */ -static inline void -JF_CLR(jnode * j, int f) +static inline void JF_CLR(jnode * j, int f) { assert("unknown-1", j->magic == JMAGIC); clear_bit(f, &j->state); } -static inline int -JF_ISSET(const jnode * j, int f) +static inline int JF_ISSET(const jnode * j, int f) { assert("unknown-2", j->magic == JMAGIC); return test_bit(f, &((jnode *) j)->state); } -static inline void -JF_SET(jnode * j, int f) +static inline void JF_SET(jnode * j, int f) { assert("unknown-3", j->magic == JMAGIC); set_bit(f, &j->state); } -static inline int -JF_TEST_AND_SET(jnode * j, int f) +static inline int JF_TEST_AND_SET(jnode * j, int f) { assert("unknown-4", j->magic == JMAGIC); return test_and_set_bit(f, &j->state); @@ -354,15 +347,13 @@ SPIN_LOCK_FUNCTIONS(jnode, jnode, guard) SPIN_LOCK_FUNCTIONS(jload, jnode, load); -static inline int -jnode_is_in_deleteset(const jnode * node) +static inline int jnode_is_in_deleteset(const jnode * node) { return JF_ISSET(node, JNODE_RELOC); } - -extern int jnode_init_static(void); -extern int jnode_done_static(void); +extern int init_jnodes(void); +extern void done_jnodes(void); /* Jnode routines */ extern jnode *jalloc(void); @@ -385,9 +376,9 @@ extern void jnode_init(jnode * node, rei extern void jnode_make_dirty(jnode * node) NONNULL; extern void jnode_make_clean(jnode * node) NONNULL; extern void jnode_make_wander_nolock(jnode * node) NONNULL; -extern void jnode_make_wander(jnode*) NONNULL; -extern void znode_make_reloc(znode*, flush_queue_t*) NONNULL; -extern void unformatted_make_reloc(jnode*, flush_queue_t*) NONNULL; +extern void jnode_make_wander(jnode *) NONNULL; +extern void znode_make_reloc(znode *, flush_queue_t *) NONNULL; +extern void unformatted_make_reloc(jnode *, flush_queue_t *) NONNULL; extern void jnode_set_block(jnode * node, const reiser4_block_nr * blocknr) NONNULL; @@ -395,8 +386,9 @@ extern void jnode_set_block(jnode * node extern struct address_space *jnode_get_mapping(const jnode * node) NONNULL; /* block number of node */ -static inline const reiser4_block_nr * -jnode_get_block(const jnode * node /* jnode to query */) +static inline const reiser4_block_nr *jnode_get_block(const jnode * + node /* jnode to query */ + ) { assert("nikita-528", node != NULL); @@ -406,8 +398,7 @@ jnode_get_block(const jnode * node /* jn /* block number for IO. Usually this is the same as jnode_get_block(), unless * jnode was emergency flushed---then block number chosen by eflush is * used. */ -static inline const reiser4_block_nr * -jnode_get_io_block(const jnode * node) +static inline const reiser4_block_nr *jnode_get_io_block(const jnode * node) { assert("nikita-2768", node != NULL); assert("nikita-2769", spin_jnode_is_locked(node)); @@ -420,7 +411,7 @@ jnode_get_io_block(const jnode * node) /* Jnode flush interface. */ extern reiser4_blocknr_hint *pos_hint(flush_pos_t * pos); -extern flush_queue_t * pos_fq(flush_pos_t * pos); +extern flush_queue_t *pos_fq(flush_pos_t * pos); /* FIXME-VS: these are used in plugin/item/extent.c */ @@ -469,8 +460,7 @@ extern void print_jnode(const char *pref int znode_is_root(const znode * node) NONNULL; /* bump reference counter on @node */ -static inline void -add_x_ref(jnode * node /* node to increase x_count of */ ) +static inline void add_x_ref(jnode * node /* node to increase x_count of */ ) { assert("nikita-1911", node != NULL); @@ -478,8 +468,7 @@ add_x_ref(jnode * node /* node to increa LOCK_CNT_INC(x_refs); } -static inline void -dec_x_ref(jnode * node) +static inline void dec_x_ref(jnode * node) { assert("nikita-3215", node != NULL); assert("nikita-3216", atomic_read(&node->x_count) > 0); @@ -490,8 +479,7 @@ dec_x_ref(jnode * node) } /* jref() - increase counter of references to jnode/znode (x_count) */ -static inline jnode * -jref(jnode * node) +static inline jnode *jref(jnode * node) { assert("jmacd-508", (node != NULL) && !IS_ERR(node)); add_x_ref(node); @@ -499,23 +487,20 @@ jref(jnode * node) } /* get the page of jnode */ -static inline struct page * -jnode_page(const jnode * node) +static inline struct page *jnode_page(const jnode * node) { return node->pg; } /* return pointer to jnode data */ -static inline char * -jdata(const jnode * node) +static inline char *jdata(const jnode * node) { assert("nikita-1415", node != NULL); assert("nikita-3198", jnode_page(node) != NULL); return node->data; } -static inline int -jnode_is_loaded(const jnode * node) +static inline int jnode_is_loaded(const jnode * node) { assert("zam-506", node != NULL); return atomic_read(&node->d_count) > 0; @@ -526,24 +511,13 @@ extern void page_detach_jnode(struct pag unsigned long index) NONNULL; extern void page_clear_jnode(struct page *page, jnode * node) NONNULL; -static inline void -jnode_set_reloc(jnode * node) +static inline void jnode_set_reloc(jnode * node) { assert("nikita-2431", node != NULL); assert("nikita-2432", !JF_ISSET(node, JNODE_OVRWR)); JF_SET(node, JNODE_RELOC); } -/* bump data counter on @node */ -static inline void add_d_ref(jnode * node /* node to increase d_count of */ ) -{ - assert("nikita-1962", node != NULL); - - atomic_inc(&node->d_count); - LOCK_CNT_INC(d_refs); -} - - /* jload/jwrite/junload give a bread/bwrite/brelse functionality for jnodes */ extern int jload_gfp(jnode * node, int gfp, int do_kmap) NONNULL; @@ -564,8 +538,7 @@ void jload_prefetch(jnode *); extern jnode *alloc_io_head(const reiser4_block_nr * block) NONNULL; extern void drop_io_head(jnode * node) NONNULL; -static inline reiser4_tree * -jnode_get_tree(const jnode * node) +static inline reiser4_tree *jnode_get_tree(const jnode * node) { assert("nikita-2691", node != NULL); return node->tree; @@ -574,8 +547,7 @@ jnode_get_tree(const jnode * node) extern void pin_jnode_data(jnode *); extern void unpin_jnode_data(jnode *); -static inline jnode_type -jnode_get_type(const jnode * node) +static inline jnode_type jnode_get_type(const jnode * node) { static const unsigned long state_mask = (1 << JNODE_TYPE_1) | (1 << JNODE_TYPE_2) | (1 << JNODE_TYPE_3); @@ -590,7 +562,7 @@ jnode_get_type(const jnode * node) /* 010 */ [2] = JNODE_BITMAP, /* 011 */ - [3] = LAST_JNODE_TYPE, /*invalid */ + [3] = LAST_JNODE_TYPE, /*invalid */ /* 100 */ [4] = JNODE_INODE, /* 101 */ @@ -605,32 +577,29 @@ jnode_get_type(const jnode * node) } /* returns true if node is a znode */ -static inline int -jnode_is_znode(const jnode * node) +static inline int jnode_is_znode(const jnode * node) { return jnode_get_type(node) == JNODE_FORMATTED_BLOCK; } /* return true if "node" is dirty */ -static inline int -jnode_is_dirty(const jnode * node) +static inline int jnode_is_dirty(const jnode * node) { assert("nikita-782", node != NULL); - assert("jmacd-1800", spin_jnode_is_locked(node) || (jnode_is_znode(node) && znode_is_any_locked(JZNODE(node)))); + assert("jmacd-1800", spin_jnode_is_locked(node) + || (jnode_is_znode(node) && znode_is_any_locked(JZNODE(node)))); return JF_ISSET(node, JNODE_DIRTY); } /* return true if "node" is dirty, node is unlocked */ -static inline int -jnode_check_dirty(jnode * node) +static inline int jnode_check_dirty(jnode * node) { assert("jmacd-7798", node != NULL); assert("jmacd-7799", spin_jnode_is_not_locked(node)); return UNDER_SPIN(jnode, node, jnode_is_dirty(node)); } -static inline int -jnode_is_flushprepped(const jnode * node) +static inline int jnode_is_flushprepped(const jnode * node) { assert("jmacd-78212", node != NULL); assert("jmacd-71276", spin_jnode_is_locked(node)); @@ -642,8 +611,7 @@ jnode_is_flushprepped(const jnode * node process. This implies the block address has been finalized for the duration of this atom (or it is clean and will remain in place). If this returns true you may use the block number as a hint. */ -static inline int -jnode_check_flushprepped(jnode * node) +static inline int jnode_check_flushprepped(jnode * node) { /* It must be clean or relocated or wandered. New allocations are set to relocate. */ assert("jmacd-71275", spin_jnode_is_not_locked(node)); @@ -651,38 +619,33 @@ jnode_check_flushprepped(jnode * node) } /* returns true if node is unformatted */ -static inline int -jnode_is_unformatted(const jnode * node) +static inline int jnode_is_unformatted(const jnode * node) { assert("jmacd-0123", node != NULL); return jnode_get_type(node) == JNODE_UNFORMATTED_BLOCK; } /* returns true if node represents a cluster cache page */ -static inline int -jnode_is_cluster_page(const jnode * node) +static inline int jnode_is_cluster_page(const jnode * node) { assert("edward-50", node != NULL); return (JF_ISSET(node, JNODE_CLUSTER_PAGE)); } /* returns true is node is builtin inode's jnode */ -static inline int -jnode_is_inode(const jnode * node) +static inline int jnode_is_inode(const jnode * node) { assert("vs-1240", node != NULL); return jnode_get_type(node) == JNODE_INODE; } -static inline jnode_plugin * -jnode_ops_of(const jnode_type type) +static inline jnode_plugin *jnode_ops_of(const jnode_type type) { assert("nikita-2367", type < LAST_JNODE_TYPE); return jnode_plugin_by_id((reiser4_plugin_id) type); } -static inline jnode_plugin * -jnode_ops(const jnode * node) +static inline jnode_plugin *jnode_ops(const jnode * node) { assert("nikita-2366", node != NULL); @@ -690,25 +653,32 @@ jnode_ops(const jnode * node) } /* Get the index of a block. */ -static inline unsigned long -jnode_get_index(jnode * node) +static inline unsigned long jnode_get_index(jnode * node) { return jnode_ops(node)->index(node); } /* return true if "node" is the root */ -static inline int -jnode_is_root(const jnode * node) +static inline int jnode_is_root(const jnode * node) { return jnode_is_znode(node) && znode_is_root(JZNODE(node)); } -extern struct address_space * mapping_jnode(const jnode * node); +extern struct address_space *mapping_jnode(const jnode * node); extern unsigned long index_jnode(const jnode * node); static inline void jput(jnode * node); extern void jput_final(jnode * node); +/* bump data counter on @node */ +static inline void add_d_ref(jnode * node /* node to increase d_count of */ ) +{ + assert("nikita-1962", node != NULL); + + atomic_inc(&node->d_count); + if (jnode_is_unformatted(node) || jnode_is_znode(node)) + LOCK_CNT_INC(d_refs); +} /* jput() - decrement x_count reference counter on znode. @@ -717,8 +687,7 @@ extern void jput_final(jnode * node); pressured out of memory before the parent. The jnode remains hashed as long as the VM allows its page to stay in memory. */ -static inline void -jput(jnode * node) +static inline void jput(jnode * node) { assert("jmacd-509", node != NULL); assert("jmacd-510", atomic_read(&node->x_count) > 0); @@ -740,18 +709,23 @@ jput(jnode * node) extern void jrelse(jnode * node); extern void jrelse_tail(jnode * node); -extern jnode *jnode_rip_sync(reiser4_tree *t, jnode * node); +extern jnode *jnode_rip_sync(reiser4_tree * t, jnode * node); /* resolve race with jput */ -static inline jnode * -jnode_rip_check(reiser4_tree *tree, jnode * node) +static inline jnode *jnode_rip_check(reiser4_tree * tree, jnode * node) { if (unlikely(JF_ISSET(node, JNODE_RIP))) node = jnode_rip_sync(tree, node); return node; } -extern reiser4_key * jnode_build_key(const jnode * node, reiser4_key * key); +extern reiser4_key *jnode_build_key(const jnode *node, reiser4_key * key); + +#if REISER4_DEBUG +extern int jnode_invariant_f(const jnode *node, char const **msg); +#endif + +extern jnode_plugin jnode_plugins[LAST_JNODE_TYPE]; /* __JNODE_H__ */ #endif diff -puN fs/reiser4/kassign.c~reiser4-big-update fs/reiser4/kassign.c --- devel/fs/reiser4/kassign.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/kassign.c 2005-09-15 19:51:08.000000000 -0700 @@ -205,26 +205,13 @@ #include /* for __u?? */ #include /* for struct super_block, etc */ -#if REISER4_LARGE_KEY -#define ORDERING_CHARS (sizeof(__u64) - 1) -#define OID_CHARS (sizeof(__u64)) -#else -#define ORDERING_CHARS (0) -#define OID_CHARS (sizeof(__u64) - 1) -#endif - -#define OFFSET_CHARS (sizeof(__u64)) - -#define INLINE_CHARS (ORDERING_CHARS + OID_CHARS) - /* bitmask for H bit (see comment at the beginning of this file */ -static const __u64 longname_mark = 0x0100000000000000ull; +static const __u64 longname_mark = 0x0100000000000000ull; /* bitmask for F and H portions of the key. */ static const __u64 fibration_mask = 0xff00000000000000ull; /* return true if name is not completely encoded in @key */ -reiser4_internal int -is_longname_key(const reiser4_key *key) +int is_longname_key(const reiser4_key * key) { __u64 highpart; @@ -242,10 +229,12 @@ is_longname_key(const reiser4_key *key) } /* return true if @name is too long to be completely encoded in the key */ -reiser4_internal int -is_longname(const char *name UNUSED_ARG, int len) +int is_longname(const char *name UNUSED_ARG, int len) { - return len > ORDERING_CHARS + OID_CHARS + OFFSET_CHARS; + if (REISER4_LARGE_KEY) + return len > 23; + else + return len > 15; } /* code ascii string into __u64. @@ -255,10 +244,9 @@ is_longname(const char *name UNUSED_ARG, endian-safe encoding. memcpy(2) will not do. */ -static __u64 -pack_string(const char *name /* string to encode */ , - int start_idx /* highest byte in result from - * which to start encoding */ ) +static __u64 pack_string(const char *name /* string to encode */ , + int start_idx /* highest byte in result from + * which to start encoding */ ) { unsigned i; __u64 str; @@ -266,33 +254,28 @@ pack_string(const char *name /* string t str = 0; for (i = 0; (i < sizeof str - start_idx) && name[i]; ++i) { str <<= 8; - str |= (unsigned char) name[i]; + str |= (unsigned char)name[i]; } str <<= (sizeof str - i - start_idx) << 3; return str; } -#if !REISER4_DEBUG -static -#endif /* opposite to pack_string(). Takes value produced by pack_string(), restores * string encoded in it and stores result in @buf */ -reiser4_internal char * -unpack_string(__u64 value, char *buf) +char *unpack_string(__u64 value, char *buf) { do { *buf = value >> (64 - 8); if (*buf) - ++ buf; + ++buf; value <<= 8; - } while(value != 0); + } while (value != 0); *buf = 0; return buf; } /* obtain name encoded in @key and store it in @buf */ -reiser4_internal char * -extract_name_from_key(const reiser4_key *key, char *buf) +char *extract_name_from_key(const reiser4_key * key, char *buf) { char *c; @@ -308,189 +291,137 @@ extract_name_from_key(const reiser4_key return buf; } -/* build key for directory entry. - ->build_entry_key() for directory plugin */ -reiser4_internal void -build_entry_key_common(const struct inode *dir /* directory where entry is - * (or will be) in.*/ , - const struct qstr *qname /* name of file referenced - * by this entry */ , - reiser4_key * result /* resulting key of directory - * entry */ ) +/** + * complete_entry_key - calculate entry key by name + * @dir: directory where entry is (or will be) in + * @name: name to calculate key of + * @len: lenth of name + * @result: place to store result in + * + * Sets fields of entry key @result which depend on file name. + * When REISER4_LARGE_KEY is defined three fields of @result are set: ordering, + * objectid and offset. Otherwise, objectid and offset are set. + */ +void complete_entry_key(const struct inode *dir, const char *name, + int len, reiser4_key *result) { +#if REISER4_LARGE_KEY __u64 ordering; __u64 objectid; __u64 offset; - const char *name; - int len; - -#if REISER4_LARGE_KEY -#define second_el ordering -#else -#define second_el objectid -#endif assert("nikita-1139", dir != NULL); - assert("nikita-1140", qname != NULL); - assert("nikita-1141", qname->name != NULL); assert("nikita-1142", result != NULL); - - name = qname->name; - len = qname->len; - assert("nikita-2867", strlen(name) == len); - reiser4_key_init(result); - /* locality of directory entry's key is objectid of parent - directory */ - set_key_locality(result, get_inode_oid(dir)); - /* minor packing locality is constant */ - set_key_type(result, KEY_FILE_NAME_MINOR); - /* dot is special case---we always want it to be first entry in - a directory. Actually, we just want to have smallest - directory entry. - */ - if (len == 1 && name[0] == '.') - return; - - /* This is our brand new proposed key allocation algorithm for - directory entries: - - If name is shorter than 7 + 8 = 15 characters, put first 7 - characters into objectid field and remaining characters (if - any) into offset field. Dream long dreamt came true: file - name as a key! - - If file name is longer than 15 characters, put first 7 - characters into objectid and hash of remaining characters - into offset field. - - To distinguish above cases, in latter set up unused high bit - in objectid field. - - - With large keys (REISER4_LARGE_KEY) algorithm is updated - appropriately. - */ - - /* objectid of key is composed of seven first characters of - file's name. This imposes global ordering on directory - entries. - */ - second_el = pack_string(name, 1); - if (REISER4_LARGE_KEY) { - if (len > ORDERING_CHARS) - objectid = pack_string(name + ORDERING_CHARS, 0); - else - objectid = 0ull; - } + /* + * key allocation algorithm for directory entries in case of large + * keys: + * + * If name is not longer than 7 + 8 + 8 = 23 characters, put first 7 + * characters into ordering field of key, next 8 charactes (if any) + * into objectid field of key and next 8 ones (of any) into offset + * field of key + * + * If file name is longer than 23 characters, put first 7 characters + * into key's ordering, next 8 to objectid and hash of remaining + * characters into offset field. + * + * To distinguish above cases, in latter set up unused high bit in + * ordering field. + */ - if (!is_longname(name, len)) { - if (len > INLINE_CHARS) - offset = pack_string(name + INLINE_CHARS, 0); - else + /* [0-6] characters to ordering */ + ordering = pack_string(name, 1); + if (len > 7) { + /* [7-14] characters to objectid */ + objectid = pack_string(name + 7, 0); + if (len > 15) { + if (len <= 23) { + /* [15-23] characters to offset */ + offset = pack_string(name + 15, 0); + } else { + /* note in a key the fact that offset contains hash. */ + ordering |= longname_mark; + + /* offset is the hash of the file name's tail. */ + offset = inode_hash_plugin(dir)->hash(name + 15, + len - 15); + } + } else { offset = 0ull; + } } else { - /* note in a key the fact that offset contains hash. */ - second_el |= longname_mark; - - /* offset is the hash of the file name. */ - offset = inode_hash_plugin(dir)->hash(name + INLINE_CHARS, - len - INLINE_CHARS); + objectid = 0ull; + offset = 0ull; } assert("nikita-3480", inode_fibration_plugin(dir) != NULL); - second_el |= inode_fibration_plugin(dir)->fibre(dir, name, len); + ordering |= inode_fibration_plugin(dir)->fibre(dir, name, len); set_key_ordering(result, ordering); set_key_fulloid(result, objectid); set_key_offset(result, offset); return; -} -/* build key for directory entry. - ->build_entry_key() for directory plugin +#else + __u64 objectid; + __u64 offset; - This is for directories where we want repeatable and restartable readdir() - even in case 32bit user level struct dirent (readdir(3)). -*/ -reiser4_internal void -build_entry_key_stable_entry(const struct inode *dir /* directory where - * entry is (or - * will be) in. */ , - const struct qstr *name /* name of file - * referenced by - * this entry */ , - reiser4_key * result /* resulting key of - * directory entry */ ) -{ - oid_t objectid; - - assert("nikita-2283", dir != NULL); - assert("nikita-2284", name != NULL); - assert("nikita-2285", name->name != NULL); - assert("nikita-2286", result != NULL); + assert("nikita-1139", dir != NULL); + assert("nikita-1142", result != NULL); + assert("nikita-2867", strlen(name) == len); - reiser4_key_init(result); - /* locality of directory entry's key is objectid of parent - directory */ - set_key_locality(result, get_inode_oid(dir)); - /* minor packing locality is constant */ - set_key_type(result, KEY_FILE_NAME_MINOR); - /* dot is special case---we always want it to be first entry in - a directory. Actually, we just want to have smallest - directory entry. - */ - if ((name->len == 1) && (name->name[0] == '.')) - return; + /* + * key allocation algorithm for directory entries in case of not large + * keys: + * + * If name is not longer than 7 + 8 = 15 characters, put first 7 + * characters into objectid field of key, next 8 charactes (if any) + * into offset field of key + * + * If file name is longer than 15 characters, put first 7 characters + * into key's objectid, and hash of remaining characters into offset + * field. + * + * To distinguish above cases, in latter set up unused high bit in + * objectid field. + */ - /* objectid of key is 31 lowest bits of hash. */ - objectid = inode_hash_plugin(dir)->hash(name->name, (int) name->len) & 0x7fffffff; + /* [0-6] characters to objectid */ + objectid = pack_string(name, 1); + if (len > 7) { + if (len <= 15) { + /* [7-14] characters to offset */ + offset = pack_string(name + 7, 0); + } else { + /* note in a key the fact that offset contains hash. */ + objectid |= longname_mark; + + /* offset is the hash of the file name. */ + offset = inode_hash_plugin(dir)->hash(name + 7, + len - 7); + } + } else + offset = 0ull; - assert("nikita-2303", !(objectid & ~KEY_OBJECTID_MASK)); - set_key_objectid(result, objectid); + assert("nikita-3480", inode_fibration_plugin(dir) != NULL); + objectid |= inode_fibration_plugin(dir)->fibre(dir, name, len); - /* offset is always 0. */ - set_key_offset(result, (__u64) 0); + set_key_fulloid(result, objectid); + set_key_offset(result, offset); return; -} - -/* build key to be used by ->readdir() method. - - See reiser4_readdir() for more detailed comment. - Common implementation of dir plugin's method build_readdir_key -*/ -reiser4_internal int -build_readdir_key_common(struct file *dir /* directory being read */ , - reiser4_key * result /* where to store key */ ) -{ - reiser4_file_fsdata *fdata; - struct inode *inode; - - assert("nikita-1361", dir != NULL); - assert("nikita-1362", result != NULL); - assert("nikita-1363", dir->f_dentry != NULL); - inode = dir->f_dentry->d_inode; - assert("nikita-1373", inode != NULL); - - fdata = reiser4_get_file_fsdata(dir); - if (IS_ERR(fdata)) - return PTR_ERR(fdata); - assert("nikita-1364", fdata != NULL); - return extract_key_from_de_id(get_inode_oid(inode), &fdata->dir.readdir.position.dir_entry_key, result); - +#endif /* ! REISER4_LARGE_KEY */ } /* true, if @key is the key of "." */ -reiser4_internal int -is_dot_key(const reiser4_key * key /* key to check */ ) +int is_dot_key(const reiser4_key * key /* key to check */ ) { assert("nikita-1717", key != NULL); assert("nikita-1718", get_key_type(key) == KEY_FILE_NAME_MINOR); return - (get_key_ordering(key) == 0ull) && - (get_key_objectid(key) == 0ull) && - (get_key_offset(key) == 0ull); + (get_key_ordering(key) == 0ull) && + (get_key_objectid(key) == 0ull) && (get_key_offset(key) == 0ull); } /* build key for stat-data. @@ -499,10 +430,9 @@ is_dot_key(const reiser4_key * key /* ke method in the future. For now, let it be here. */ -reiser4_internal reiser4_key * -build_sd_key(const struct inode * target /* inode of an object */ , - reiser4_key * result /* resulting key of @target - stat-data */ ) +reiser4_key *build_sd_key(const struct inode * target /* inode of an object */ , + reiser4_key * result /* resulting key of @target + stat-data */ ) { assert("nikita-261", result != NULL); @@ -522,9 +452,8 @@ build_sd_key(const struct inode * target See &obj_key_id */ -reiser4_internal int -build_obj_key_id(const reiser4_key * key /* key to encode */ , - obj_key_id * id /* id where key is encoded in */ ) +int build_obj_key_id(const reiser4_key * key /* key to encode */ , + obj_key_id * id /* id where key is encoded in */ ) { assert("nikita-1151", key != NULL); assert("nikita-1152", id != NULL); @@ -536,9 +465,8 @@ build_obj_key_id(const reiser4_key * key /* encode reference to @obj in @id. This is like build_obj_key_id() above, but takes inode as parameter. */ -reiser4_internal int -build_inode_key_id(const struct inode *obj /* object to build key of */ , - obj_key_id * id /* result */ ) +int build_inode_key_id(const struct inode *obj /* object to build key of */ , + obj_key_id * id /* result */ ) { reiser4_key sdkey; @@ -555,10 +483,9 @@ build_inode_key_id(const struct inode *o Restore key of object stat-data from @id. This is dual to build_obj_key_id() above. */ -reiser4_internal int -extract_key_from_id(const obj_key_id * id /* object key id to extract key +int extract_key_from_id(const obj_key_id * id /* object key id to extract key * from */ , - reiser4_key * key /* result */ ) + reiser4_key * key /* result */ ) { assert("nikita-1153", id != NULL); assert("nikita-1154", key != NULL); @@ -571,10 +498,9 @@ extract_key_from_id(const obj_key_id * i /* extract objectid of directory from key of directory entry within said directory. */ -reiser4_internal oid_t -extract_dir_id_from_key(const reiser4_key * de_key /* key of - * directory - * entry */ ) +oid_t extract_dir_id_from_key(const reiser4_key * de_key /* key of + * directory + * entry */ ) { assert("nikita-1314", de_key != NULL); return get_key_locality(de_key); @@ -588,12 +514,11 @@ extract_dir_id_from_key(const reiser4_ke to objectid of their directory. */ -reiser4_internal int -build_de_id(const struct inode *dir /* inode of directory */ , - const struct qstr *name /* name to be given to @obj by +int build_de_id(const struct inode *dir /* inode of directory */ , + const struct qstr *name /* name to be given to @obj by * directory entry being * constructed */ , - de_id * id /* short key of directory entry */ ) + de_id * id /* short key of directory entry */ ) { reiser4_key key; @@ -613,10 +538,9 @@ build_de_id(const struct inode *dir /* i to objectid of their directory. */ -reiser4_internal int -build_de_id_by_key(const reiser4_key * entry_key /* full key of directory +int build_de_id_by_key(const reiser4_key * entry_key /* full key of directory * entry */ , - de_id * id /* short key of directory entry */ ) + de_id * id /* short key of directory entry */ ) { memcpy(id, ((__u64 *) entry_key) + 1, sizeof *id); return 0; @@ -628,11 +552,10 @@ build_de_id_by_key(const reiser4_key * e key of directory entry within directory item. */ -reiser4_internal int -extract_key_from_de_id(const oid_t locality /* locality of directory +int extract_key_from_de_id(const oid_t locality /* locality of directory * entry */ , - const de_id * id /* directory entry id */ , - reiser4_key * key /* result */ ) + const de_id * id /* directory entry id */ , + reiser4_key * key /* result */ ) { /* no need to initialise key here: all fields are overwritten */ memcpy(((__u64 *) key) + 1, id, sizeof *id); @@ -642,9 +565,8 @@ extract_key_from_de_id(const oid_t local } /* compare two &de_id's */ -reiser4_internal cmp_t -de_id_cmp(const de_id * id1 /* first &de_id to compare */ , - const de_id * id2 /* second &de_id to compare */ ) +cmp_t de_id_cmp(const de_id * id1 /* first &de_id to compare */ , + const de_id * id2 /* second &de_id to compare */ ) { /* NOTE-NIKITA ugly implementation */ reiser4_key k1; @@ -656,14 +578,13 @@ de_id_cmp(const de_id * id1 /* first &de } /* compare &de_id with key */ -reiser4_internal cmp_t -de_id_key_cmp(const de_id * id /* directory entry id to compare */ , - const reiser4_key * key /* key to compare */ ) +cmp_t de_id_key_cmp(const de_id * id /* directory entry id to compare */ , + const reiser4_key * key /* key to compare */ ) { - cmp_t result; + cmp_t result; reiser4_key *k1; - k1 = (reiser4_key *)(((unsigned long)id) - sizeof key->el[0]); + k1 = (reiser4_key *) (((unsigned long)id) - sizeof key->el[0]); result = KEY_DIFF_EL(k1, key, 1); if (result == EQUAL_TO) { result = KEY_DIFF_EL(k1, key, 2); @@ -681,7 +602,7 @@ int inode_onwire_size(const struct inode { int result; - result = dscale_bytes(get_inode_oid(inode)); + result = dscale_bytes(get_inode_oid(inode)); result += dscale_bytes(get_inode_locality(inode)); /* @@ -702,7 +623,7 @@ char *build_inode_onwire(const struct in start += dscale_write(start, get_inode_oid(inode)); if (REISER4_LARGE_KEY) { - cputod64(get_inode_ordering(inode), (d64 *)start); + cputod64(get_inode_ordering(inode), (d64 *) start); start += sizeof(get_inode_ordering(inode)); } return start; @@ -711,15 +632,15 @@ char *build_inode_onwire(const struct in /* * extract key that was previously encoded by build_inode_onwire() at @addr */ -char *extract_obj_key_id_from_onwire(char *addr, obj_key_id *key_id) +char *extract_obj_key_id_from_onwire(char *addr, obj_key_id * key_id) { __u64 val; addr += dscale_read(addr, &val); val = (val << KEY_LOCALITY_SHIFT) | KEY_SD_MINOR; - cputod64(val, (d64 *)key_id->locality); + cputod64(val, (d64 *) key_id->locality); addr += dscale_read(addr, &val); - cputod64(val, (d64 *)key_id->objectid); + cputod64(val, (d64 *) key_id->objectid); #if REISER4_LARGE_KEY memcpy(&key_id->ordering, addr, sizeof key_id->ordering); addr += sizeof key_id->ordering; diff -puN fs/reiser4/kassign.h~reiser4-big-update fs/reiser4/kassign.h --- devel/fs/reiser4/kassign.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/kassign.h 2005-09-15 19:51:08.000000000 -0700 @@ -43,10 +43,12 @@ */ typedef struct obj_key_id { - d8 locality[sizeof (__u64)]; - ON_LARGE_KEY(d8 ordering[sizeof (__u64)];) - d8 objectid[sizeof (__u64)]; -} obj_key_id; + d8 locality[sizeof(__u64)]; + ON_LARGE_KEY(d8 ordering[sizeof(__u64)]; + ) + d8 objectid[sizeof(__u64)]; +} +obj_key_id; /* Information sufficient to uniquely identify directory entry within compressed directory item. @@ -54,10 +56,11 @@ typedef struct obj_key_id { For alignment issues see &obj_key_id above. */ typedef struct de_id { - ON_LARGE_KEY(d8 ordering[sizeof (__u64)];) - d8 objectid[sizeof (__u64)]; - d8 offset[sizeof (__u64)]; -} de_id; + ON_LARGE_KEY(d8 ordering[sizeof(__u64)];) + d8 objectid[sizeof(__u64)]; + d8 offset[sizeof(__u64)]; +} +de_id; extern int inode_onwire_size(const struct inode *obj); extern char *build_inode_onwire(const struct inode *obj, char *area); @@ -67,21 +70,31 @@ extern int build_inode_key_id(const stru extern int extract_key_from_id(const obj_key_id * id, reiser4_key * key); extern int build_obj_key_id(const reiser4_key * key, obj_key_id * id); extern oid_t extract_dir_id_from_key(const reiser4_key * de_key); -extern int build_de_id(const struct inode *dir, const struct qstr *name, de_id * id); +extern int build_de_id(const struct inode *dir, const struct qstr *name, + de_id * id); extern int build_de_id_by_key(const reiser4_key * entry_key, de_id * id); -extern int extract_key_from_de_id(const oid_t locality, const de_id * id, reiser4_key * key); +extern int extract_key_from_de_id(const oid_t locality, const de_id * id, + reiser4_key * key); extern cmp_t de_id_cmp(const de_id * id1, const de_id * id2); extern cmp_t de_id_key_cmp(const de_id * id, const reiser4_key * key); extern int build_readdir_key_common(struct file *dir, reiser4_key * result); -extern void build_entry_key_common(const struct inode *dir, const struct qstr *name, reiser4_key * result); -extern void build_entry_key_stable_entry(const struct inode *dir, const struct qstr *name, reiser4_key * result); +extern void build_entry_key_common(const struct inode *dir, + const struct qstr *name, + reiser4_key * result); +extern void build_entry_key_stable_entry(const struct inode *dir, + const struct qstr *name, + reiser4_key * result); extern int is_dot_key(const reiser4_key * key); -extern reiser4_key *build_sd_key(const struct inode *target, reiser4_key * result); +extern reiser4_key *build_sd_key(const struct inode *target, + reiser4_key * result); -extern int is_longname_key(const reiser4_key *key); +extern int is_longname_key(const reiser4_key * key); extern int is_longname(const char *name, int len); -extern char *extract_name_from_key(const reiser4_key *key, char *buf); +extern char *extract_name_from_key(const reiser4_key * key, char *buf); +extern char *unpack_string(__u64 value, char *buf); +extern void complete_entry_key(const struct inode *dir, const char *name, + int len, reiser4_key *result); /* __KASSIGN_H__ */ #endif diff -L fs/reiser4/kcond.c -puN fs/reiser4/kcond.c~reiser4-big-update /dev/null --- devel/fs/reiser4/kcond.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,283 +0,0 @@ -/* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */ - -/* Kernel condition variables implementation. - - This is simplistic (90 LOC mod comments) condition variable - implementation. Condition variable is the most natural "synchronization - object" in some circumstances. - - Each CS text-book on multi-threading should discuss condition - variables. Also see man/info for: - - pthread_cond_init(3), - pthread_cond_destroy(3), - pthread_cond_signal(3), - pthread_cond_broadcast(3), - pthread_cond_wait(3), - pthread_cond_timedwait(3). - - See comments in kcond_wait(). - - TODO - - 1. Add an option (to kcond_init?) to make conditional variable async-safe - so that signals and broadcasts can be done from interrupt - handlers. Requires using spin_lock_irq in kcond_*(). - - 2. "Predicated" sleeps: add predicate function to the qlink and only wake - sleeper if predicate is true. Probably requires additional parameters to - the kcond_{signal,broadcast}() to supply cookie to the predicate. Standard - wait_queues already have this functionality. Idea is that if one has - object behaving like finite state automaton it is possible to use single - per-object condition variable to signal all state transitions. Predicates - allow waiters to select only transitions they are interested in without - going through context switch. - - 3. It is relatively easy to add support for sleeping on the several - condition variables at once. Does anybody need this? - -*/ - -#include "debug.h" -#include "kcond.h" -#include "spin_macros.h" - -#include -#include - -static void kcond_timeout(unsigned long datum); -static void kcond_remove(kcond_t * cvar, kcond_queue_link_t * link); - -/* initialize condition variable. Initializer for global condition variables - is macro in kcond.h */ -reiser4_internal kcond_t * -kcond_init(kcond_t * cvar /* cvar to init */ ) -{ - assert("nikita-1868", cvar != NULL); - - memset(cvar, 0, sizeof *cvar); - spin_lock_init(&cvar->lock); - cvar->queue = NULL; - return cvar; -} - -/* Wait until condition variable is signalled. Call this with @lock locked. - If @signl is true, then sleep on condition variable will be interruptible - by signals. -EINTR is returned if sleep were interrupted by signal and 0 - otherwise. - - kcond_t is just a queue protected by spinlock. Whenever thread is going to - sleep on the kcond_t it does the following: - - (1) prepares "queue link" @qlink which is semaphore constructed locally on - the stack of the thread going to sleep. - - (2) takes @cvar spinlock - - (3) adds @qlink to the @cvar queue of waiters - - (4) releases @cvar spinlock - - (5) sleeps on semaphore constructed at step (1) - - When @cvar will be signalled or broadcasted all semaphors enqueued to the - @cvar queue will be upped and kcond_wait() will return. - - By use of local semaphore for each waiter we avoid races between going to - sleep and waking up---endemic plague of condition variables. - - For example, should kcond_broadcast() come in between steps (4) and (5) it - would call up() on semaphores already in a queue and hence, down() in the - step (5) would return immediately. - -*/ -reiser4_internal int -kcond_wait(kcond_t * cvar /* cvar to wait for */ , - spinlock_t * lock /* lock to use */ , - int signl /* if 0, ignore signals during sleep */ ) -{ - kcond_queue_link_t qlink; - int result; - - assert("nikita-1869", cvar != NULL); - assert("nikita-1870", lock != NULL); - assert("nikita-1871", check_spin_is_locked(lock)); - - spin_lock(&cvar->lock); - qlink.next = cvar->queue; - cvar->queue = &qlink; - init_MUTEX_LOCKED(&qlink.wait); - spin_unlock(&cvar->lock); - spin_unlock(lock); - - result = 0; - if (signl) - result = down_interruptible(&qlink.wait); - else - down(&qlink.wait); - spin_lock(&cvar->lock); - if (result != 0) { - /* if thread was woken up by signal, @qlink is probably still - in the queue, remove it. */ - kcond_remove(cvar, &qlink); - } - /* if it wasn't woken up by signal, spinlock here is still useful, - because we want to wait until kcond_{broadcast|signal} - finishes. Otherwise down() could interleave with up() in such a way - that, that kcond_wait() would exit and up() would see garbage in a - semaphore. - */ - spin_unlock(&cvar->lock); - spin_lock(lock); - return result; -} - -typedef struct { - kcond_queue_link_t *link; - int *woken_up; -} kcond_timer_arg; - -/* like kcond_wait(), but with timeout */ -reiser4_internal int -kcond_timedwait(kcond_t * cvar /* cvar to wait for */ , - spinlock_t * lock /* lock to use */ , - signed long timeout /* timeout in jiffies */ , - int signl /* if 0, ignore signals during sleep */ ) -{ - struct timer_list timer; - kcond_queue_link_t qlink; - int result; - int woken_up; - kcond_timer_arg targ; - - assert("nikita-2437", cvar != NULL); - assert("nikita-2438", lock != NULL); - assert("nikita-2439", check_spin_is_locked(lock)); - - spin_lock(&cvar->lock); - qlink.next = cvar->queue; - cvar->queue = &qlink; - init_MUTEX_LOCKED(&qlink.wait); - spin_unlock(&cvar->lock); - spin_unlock(lock); - - assert("nikita-3011", schedulable()); - - /* prepare timer */ - init_timer(&timer); - timer.expires = jiffies + timeout; - timer.data = (unsigned long) &targ; - timer.function = kcond_timeout; - - woken_up = 0; - - targ.link = &qlink; - targ.woken_up = &woken_up; - - /* ... and set it up */ - add_timer(&timer); - - result = 0; - if (signl) - result = down_interruptible(&qlink.wait); - else - down(&qlink.wait); - - /* cancel timer */ - del_timer_sync(&timer); - - if (woken_up) - result = -ETIMEDOUT; - - spin_lock(&cvar->lock); - if (result != 0) { - /* if thread was woken up by signal, or due to time-out, - @qlink is probably still in the queue, remove it. */ - kcond_remove(cvar, &qlink); - } - spin_unlock(&cvar->lock); - - spin_lock(lock); - return result; -} - -/* Signal condition variable: wake up one waiter, if any. */ -reiser4_internal int -kcond_signal(kcond_t * cvar /* cvar to signal */ ) -{ - kcond_queue_link_t *queue_head; - - assert("nikita-1872", cvar != NULL); - - spin_lock(&cvar->lock); - - queue_head = cvar->queue; - if (queue_head != NULL) { - cvar->queue = queue_head->next; - up(&queue_head->wait); - } - spin_unlock(&cvar->lock); - return 1; -} - -/* Broadcast condition variable: wake up all waiters. */ -reiser4_internal int -kcond_broadcast(kcond_t * cvar /* cvar to broadcast */ ) -{ - kcond_queue_link_t *queue_head; - - assert("nikita-1875", cvar != NULL); - - spin_lock(&cvar->lock); - - for (queue_head = cvar->queue; queue_head != NULL; queue_head = queue_head->next) - up(&queue_head->wait); - - cvar->queue = NULL; - spin_unlock(&cvar->lock); - return 1; -} - -/* timer expiration function used by kcond_timedwait */ -static void -kcond_timeout(unsigned long datum) -{ - kcond_timer_arg *arg; - - arg = (kcond_timer_arg *) datum; - *arg->woken_up = 1; - up(&arg->link->wait); -} - -/* helper function to remove @link from @cvar queue */ -static void -kcond_remove(kcond_t * cvar /* cvar to operate on */ , - kcond_queue_link_t * link /* link to remove */ ) -{ - kcond_queue_link_t *scan; - kcond_queue_link_t *prev; - - assert("nikita-2440", cvar != NULL); - assert("nikita-2441", check_spin_is_locked(&cvar->lock)); - - for (scan = cvar->queue, prev = NULL; scan != NULL; prev = scan, scan = scan->next) { - if (scan == link) { - if (prev == NULL) - cvar->queue = scan->next; - else - prev->next = scan->next; - break; - } - } -} - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - scroll-step: 1 - End: -*/ diff -L fs/reiser4/kcond.h -puN fs/reiser4/kcond.h~reiser4-big-update /dev/null --- devel/fs/reiser4/kcond.h +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,56 +0,0 @@ -/* Copyright 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */ - -/* Declaration of kernel condition variables and API. See kcond.c for more - info. */ - -#ifndef __KCOND_H__ -#define __KCOND_H__ - -#include -#include - -typedef struct kcond_queue_link_s kcond_queue_link_t; - -/* condition variable */ -typedef struct kcond_s { - /* lock protecting integrity of @queue */ - spinlock_t lock; - /* queue of waiters */ - kcond_queue_link_t *queue; -} kcond_t; - -/* queue link added to the kcond->queue by each waiter */ -struct kcond_queue_link_s { - /* next link in the queue */ - kcond_queue_link_t *next; - /* semaphore to signal on wake up */ - struct semaphore wait; -}; - -extern kcond_t *kcond_init(kcond_t * cvar); - -extern int kcond_wait(kcond_t * cvar, spinlock_t * lock, int signl); -extern int kcond_timedwait(kcond_t * cvar, spinlock_t * lock, signed long timeout, int signl); -extern int kcond_signal(kcond_t * cvar); -extern int kcond_broadcast(kcond_t * cvar); - -extern void kcond_print(kcond_t * cvar); - -#define KCOND_STATIC_INIT \ - { \ - .lock = SPIN_LOCK_UNLOCKED, \ - .queue = NULL \ - } - -/* __KCOND_H__ */ -#endif - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - End: -*/ diff -puN fs/reiser4/Kconfig~reiser4-big-update fs/reiser4/Kconfig --- devel/fs/reiser4/Kconfig~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/Kconfig 2005-09-15 19:51:08.000000000 -0700 @@ -1,6 +1,6 @@ config REISER4_FS tristate "Reiser4 (EXPERIMENTAL)" - depends on EXPERIMENTAL && !4KSTACKS + depends on EXPERIMENTAL select ZLIB_INFLATE select ZLIB_DEFLATE help diff -puN fs/reiser4/key.c~reiser4-big-update fs/reiser4/key.c --- devel/fs/reiser4/key.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/key.c 2005-09-15 19:51:08.000000000 -0700 @@ -32,31 +32,27 @@ static const reiser4_key MAXIMAL_KEY = { }; /* Initialise key. */ -reiser4_internal void -reiser4_key_init(reiser4_key * key /* key to init */ ) +void reiser4_key_init(reiser4_key * key /* key to init */ ) { assert("nikita-1169", key != NULL); memset(key, 0, sizeof *key); } /* minimal possible key in the tree. Return pointer to the static storage. */ -reiser4_internal const reiser4_key * -min_key(void) +const reiser4_key *min_key(void) { return &MINIMAL_KEY; } /* maximum possible key in the tree. Return pointer to the static storage. */ -reiser4_internal const reiser4_key * -max_key(void) +const reiser4_key *max_key(void) { return &MAXIMAL_KEY; } #if REISER4_DEBUG /* debugging aid: print symbolic name of key type */ -static const char * -type_name(unsigned int key_type /* key type */ ) +static const char *type_name(unsigned int key_type /* key type */ ) { switch (key_type) { case KEY_FILE_NAME_MINOR: @@ -74,12 +70,9 @@ type_name(unsigned int key_type /* key t } } -extern char *unpack_string(__u64 value, char *buf); - /* debugging aid: print human readable information about key */ -reiser4_internal void -print_key(const char *prefix /* prefix to print */ , - const reiser4_key * key /* key to print */ ) +void print_key(const char *prefix /* prefix to print */ , + const reiser4_key * key /* key to print */ ) { /* turn bold on */ /* printf ("\033[1m"); */ @@ -92,15 +85,13 @@ print_key(const char *prefix /* prefix t get_key_type(key), get_key_ordering(key), get_key_band(key), - get_key_objectid(key), - get_key_offset(key)); + get_key_objectid(key), get_key_offset(key)); else printk("%s: (%Lx:%x:%Lx:%Lx:%Lx)", prefix, get_key_locality(key), get_key_type(key), get_key_band(key), - get_key_objectid(key), - get_key_offset(key)); + get_key_objectid(key), get_key_offset(key)); /* * if this is a key of directory entry, try to decode part of * a name stored in the key, and output it. @@ -136,9 +127,8 @@ print_key(const char *prefix /* prefix t #endif /* like print_key() but outputs key representation into @buffer. */ -reiser4_internal int -sprintf_key(char *buffer /* buffer to print key into */ , - const reiser4_key * key /* key to print */ ) +int sprintf_key(char *buffer /* buffer to print key into */ , + const reiser4_key * key /* key to print */ ) { if (REISER4_LARGE_KEY) return sprintf(buffer, "(%Lx:%x:%Lx:%Lx:%Lx:%Lx)", diff -puN fs/reiser4/key.h~reiser4-big-update fs/reiser4/key.h --- devel/fs/reiser4/key.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/key.h 2005-09-15 19:51:08.000000000 -0700 @@ -81,8 +81,8 @@ typedef enum { /* minor "locale", aka item type. Sits in 1st element */ KEY_TYPE_INDEX = 0, ON_LARGE_KEY(KEY_ORDERING_INDEX,) - /* "object band". Sits in 2nd element */ - KEY_BAND_INDEX, + /* "object band". Sits in 2nd element */ + KEY_BAND_INDEX, /* objectid. Sits in 2nd element */ KEY_OBJECTID_INDEX = KEY_BAND_INDEX, /* full objectid. Sits in 2nd element */ @@ -108,24 +108,27 @@ union reiser4_key { int pad; }; -/* bitmasks showing where within reiser4_key particular key is - stored. */ -typedef enum { - /* major locality occupies higher 60 bits of the first element */ - KEY_LOCALITY_MASK = 0xfffffffffffffff0ull, - /* minor locality occupies lower 4 bits of the first element */ - KEY_TYPE_MASK = 0xfull, - /* controversial band occupies higher 4 bits of the 2nd element */ - KEY_BAND_MASK = 0xf000000000000000ull, - /* objectid occupies lower 60 bits of the 2nd element */ - KEY_OBJECTID_MASK = 0x0fffffffffffffffull, - /* full 64bit objectid*/ - KEY_FULLOID_MASK = 0xffffffffffffffffull, - /* offset is just 3rd L.M.Nt itself */ - KEY_OFFSET_MASK = 0xffffffffffffffffull, - /* ordering is whole second element */ - KEY_ORDERING_MASK = 0xffffffffffffffffull, -} reiser4_key_field_mask; +/* bitmasks showing where within reiser4_key particular key is stored. */ +/* major locality occupies higher 60 bits of the first element */ +#define KEY_LOCALITY_MASK 0xfffffffffffffff0ull + +/* minor locality occupies lower 4 bits of the first element */ +#define KEY_TYPE_MASK 0xfull + +/* controversial band occupies higher 4 bits of the 2nd element */ +#define KEY_BAND_MASK 0xf000000000000000ull + +/* objectid occupies lower 60 bits of the 2nd element */ +#define KEY_OBJECTID_MASK 0x0fffffffffffffffull + +/* full 64bit objectid*/ +#define KEY_FULLOID_MASK 0xffffffffffffffffull + +/* offset is just 3rd L.M.Nt itself */ +#define KEY_OFFSET_MASK 0xffffffffffffffffull + +/* ordering is whole second element */ +#define KEY_ORDERING_MASK 0xffffffffffffffffull /* how many bits key element should be shifted to left to get particular field */ typedef enum { @@ -204,12 +207,12 @@ DEFINE_KEY_FIELD(offset, OFFSET, __u64); /* define get_key_ordering(), set_key_ordering() */ DEFINE_KEY_FIELD(ordering, ORDERING, __u64); #else -static inline __u64 get_key_ordering(const reiser4_key *key) +static inline __u64 get_key_ordering(const reiser4_key * key) { return 0; } -static inline void set_key_ordering(reiser4_key *key, __u64 val) +static inline void set_key_ordering(reiser4_key * key, __u64 val) { } #endif @@ -253,9 +256,8 @@ extern const reiser4_key *max_key(void); /* compare `k1' and `k2'. This function is a heart of "key allocation policy". All you need to implement new policy is to add yet another clause here. */ -static inline cmp_t -keycmp(const reiser4_key * k1 /* first key to compare */ , - const reiser4_key * k2 /* second key to compare */ ) +static inline cmp_t keycmp(const reiser4_key * k1 /* first key to compare */ , + const reiser4_key * k2 /* second key to compare */ ) { cmp_t result; @@ -306,9 +308,8 @@ keycmp(const reiser4_key * k1 /* first k } /* true if @k1 equals @k2 */ -static inline int -keyeq(const reiser4_key * k1 /* first key to compare */ , - const reiser4_key * k2 /* second key to compare */ ) +static inline int keyeq(const reiser4_key * k1 /* first key to compare */ , + const reiser4_key * k2 /* second key to compare */ ) { assert("nikita-1879", k1 != NULL); assert("nikita-1880", k2 != NULL); @@ -316,9 +317,8 @@ keyeq(const reiser4_key * k1 /* first ke } /* true if @k1 is less than @k2 */ -static inline int -keylt(const reiser4_key * k1 /* first key to compare */ , - const reiser4_key * k2 /* second key to compare */ ) +static inline int keylt(const reiser4_key * k1 /* first key to compare */ , + const reiser4_key * k2 /* second key to compare */ ) { assert("nikita-1952", k1 != NULL); assert("nikita-1953", k2 != NULL); @@ -326,9 +326,8 @@ keylt(const reiser4_key * k1 /* first ke } /* true if @k1 is less than or equal to @k2 */ -static inline int -keyle(const reiser4_key * k1 /* first key to compare */ , - const reiser4_key * k2 /* second key to compare */ ) +static inline int keyle(const reiser4_key * k1 /* first key to compare */ , + const reiser4_key * k2 /* second key to compare */ ) { assert("nikita-1954", k1 != NULL); assert("nikita-1955", k2 != NULL); @@ -336,9 +335,8 @@ keyle(const reiser4_key * k1 /* first ke } /* true if @k1 is greater than @k2 */ -static inline int -keygt(const reiser4_key * k1 /* first key to compare */ , - const reiser4_key * k2 /* second key to compare */ ) +static inline int keygt(const reiser4_key * k1 /* first key to compare */ , + const reiser4_key * k2 /* second key to compare */ ) { assert("nikita-1959", k1 != NULL); assert("nikita-1960", k2 != NULL); @@ -346,9 +344,8 @@ keygt(const reiser4_key * k1 /* first ke } /* true if @k1 is greater than or equal to @k2 */ -static inline int -keyge(const reiser4_key * k1 /* first key to compare */ , - const reiser4_key * k2 /* second key to compare */ ) +static inline int keyge(const reiser4_key * k1 /* first key to compare */ , + const reiser4_key * k2 /* second key to compare */ ) { assert("nikita-1956", k1 != NULL); assert("nikita-1957", k2 != NULL); /* October 4: sputnik launched @@ -356,8 +353,7 @@ keyge(const reiser4_key * k1 /* first ke return keycmp(k1, k2) != LESS_THAN; } -static inline void -prefetchkey(reiser4_key *key) +static inline void prefetchkey(reiser4_key * key) { prefetch(key); prefetch(&key->el[KEY_CACHELINE_END]); diff -puN fs/reiser4/ktxnmgrd.c~reiser4-big-update fs/reiser4/ktxnmgrd.c --- devel/fs/reiser4/ktxnmgrd.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/ktxnmgrd.c 2005-09-15 19:51:08.000000000 -0700 @@ -23,7 +23,6 @@ */ #include "debug.h" -#include "kcond.h" #include "txnmgr.h" #include "tree.h" #include "ktxnmgrd.h" @@ -31,54 +30,38 @@ #include "reiser4.h" #include /* for struct task_struct */ +#include #include #include #include -static int scan_mgr(txn_mgr * mgr); +static int scan_mgr(struct super_block *); -reiser4_internal int -init_ktxnmgrd_context(txn_mgr * mgr) -{ - ktxnmgrd_context * ctx; - - assert ("zam-1013", mgr != NULL); - assert ("zam-1014", mgr->daemon == NULL); - - ctx = reiser4_kmalloc(sizeof(ktxnmgrd_context), GFP_KERNEL); - if (ctx == NULL) - return RETERR(-ENOMEM); - - assert("nikita-2442", ctx != NULL); - - memset(ctx, 0, sizeof *ctx); - init_completion(&ctx->finish); - kcond_init(&ctx->startup); - kcond_init(&ctx->wait); - spin_lock_init(&ctx->guard); - ctx->timeout = REISER4_TXNMGR_TIMEOUT; - mgr->daemon = ctx; - return 0; -} - -/* change current->comm so that ps, top, and friends will see changed - state. This serves no useful purpose whatsoever, but also costs - nothing. May be it will make lonely system administrator feeling less alone - at 3 A.M. -*/ +/* + * change current->comm so that ps, top, and friends will see changed + * state. This serves no useful purpose whatsoever, but also costs nothing. May + * be it will make lonely system administrator feeling less alone at 3 A.M. + */ #define set_comm( state ) \ snprintf( current -> comm, sizeof( current -> comm ), \ "%s:%s:%s", __FUNCTION__, (super)->s_id, ( state ) ) -/* The background transaction manager daemon, started as a kernel thread - during reiser4 initialization. */ -static int -ktxnmgrd(void *arg) +/** + * ktxnmgrd - kernel txnmgr daemon + * @arg: pointer to super block + * + * The background transaction manager daemon, started as a kernel thread during + * reiser4 initialization. + */ +static int ktxnmgrd(void *arg) { struct task_struct *me; - struct super_block * super; + struct super_block *super; ktxnmgrd_context *ctx; - txn_mgr * mgr; + txn_mgr *mgr; + + super = arg; + mgr = &get_super_private(super)->tmgr; /* standard kernel thread prologue */ me = current; @@ -91,184 +74,227 @@ ktxnmgrd(void *arg) recalc_sigpending(); spin_unlock_irq(&me->sighand->siglock); - /* do_fork() just copies task_struct into the new - thread. ->fs_context shouldn't be copied of course. This shouldn't - be a problem for the rest of the code though. - */ + /* + * do_fork() just copies task_struct into the new thread. ->fs_context + * shouldn't be copied of course. This shouldn't be a problem for the + * rest of the code though. + */ me->journal_info = NULL; - mgr = arg; ctx = mgr->daemon; - spin_lock(&ctx->guard); ctx->tsk = me; - super = container_of(mgr, reiser4_super_info_data, tmgr)->tree.super; - kcond_broadcast(&ctx->startup); - while (1) { - int result; + /* initialization is done */ + complete(&ctx->start_finish_completion); + + while (1) { /* software suspend support. */ - if (me->flags & PF_FREEZE) { - spin_unlock(&ctx->guard); + if (freezing(me)) refrigerator(); - spin_lock(&ctx->guard); - } - set_comm("wait"); - /* wait for @ctx -> timeout or explicit wake up. + { + DEFINE_WAIT(__wait); - kcond_wait() is called with last argument 1 enabling wakeup - by signals so that this thread is not counted in - load-average. This doesn't require any special handling, - because all signals were blocked. - */ - result = kcond_timedwait(&ctx->wait, - &ctx->guard, ctx->timeout, 1); - - if (result != -ETIMEDOUT && result != -EINTR && result != 0) { - /* some other error */ - warning("nikita-2443", "Error: %i", result); - continue; + prepare_to_wait(&ctx->wait, &__wait, TASK_INTERRUPTIBLE); + /* we are asked to exit */ + if (ctx->done) + break; + schedule_timeout(ctx->timeout); + finish_wait(&ctx->wait, &__wait); } + set_comm("run"); - /* we are asked to exit */ - if (ctx->done) - break; - - set_comm(result ? "timed" : "run"); - - /* wait timed out or ktxnmgrd was woken up by explicit request - to commit something. Scan list of atoms in txnmgr and look - for too old atoms. - */ + spin_lock(&ctx->guard); + /* + * wait timed out or ktxnmgrd was woken up by explicit request + * to commit something. Scan list of atoms in txnmgr and look + * for too old atoms. + */ do { ctx->rescan = 0; - scan_mgr(mgr); + scan_mgr(super); spin_lock(&ctx->guard); if (ctx->rescan) { - /* the list could be modified while ctx - spinlock was released, we have to - repeat scanning from the - beginning */ + /* + * the list could be modified while ctx + * spinlock was released, we have to repeat + * scanning from the beginning + */ break; } } while (ctx->rescan); + spin_unlock(&ctx->guard); } - spin_unlock(&ctx->guard); - - complete_and_exit(&ctx->finish, 0); + complete_and_exit(&ctx->start_finish_completion, 0); /* not reached. */ return 0; } #undef set_comm -reiser4_internal void -ktxnmgrd_kick(txn_mgr * mgr) +/** + * start_ktxnmgrd - start txnmgr daemon + * @mgr: pointer to transaction manager embedded in reiser4 super block + * + * Starts ktxnmgrd and wait untils it initializes. + */ +static int start_ktxnmgrd(struct super_block *super) { - assert("nikita-3234", mgr != NULL); - assert("nikita-3235", mgr->daemon != NULL); - kcond_signal(&mgr->daemon->wait); -} + txn_mgr *mgr; + ktxnmgrd_context *ctx; -reiser4_internal int -is_current_ktxnmgrd(void) -{ - return (get_current_super_private()->tmgr.daemon->tsk == current); -} + mgr = &get_super_private(super)->tmgr; + assert("zam-1015", mgr->daemon != NULL); -/* scan one transaction manager for old atoms; should be called with ktxnmgrd - * spinlock, releases this spin lock at exit */ -static int -scan_mgr(txn_mgr * mgr) -{ - int ret; - reiser4_context ctx; - reiser4_tree *tree; + ctx = mgr->daemon; - assert("nikita-2454", mgr != NULL); + spin_lock(&ctx->guard); + ctx->rescan = 1; + ctx->done = 0; + spin_unlock(&ctx->guard); - /* NOTE-NIKITA this only works for atoms embedded into super blocks. */ - tree = &container_of(mgr, reiser4_super_info_data, tmgr)->tree; - assert("nikita-2455", tree != NULL); - assert("nikita-2456", tree->super != NULL); + /* + * prepare synchronization object to synchronize with ktxnmgrd + * initialization + */ + init_completion(&ctx->start_finish_completion); - init_context(&ctx, tree->super); + /* start ktxnmgrd */ + kernel_thread(ktxnmgrd, super, CLONE_KERNEL); - ret = commit_some_atoms(mgr); + /* wait for ktxnmgrd initialization */ + wait_for_completion(&ctx->start_finish_completion); - reiser4_exit_context(&ctx); - return ret; -} + assert("nikita-2452", ctx->tsk != NULL); + return 0; +} -reiser4_internal int start_ktxnmgrd (txn_mgr * mgr) +/** + * init_ktxnmgrd - initialize ktxnmgrd context and start kernel daemon + * @super: pointer to super block + * + * Allocates and initializes ktxnmgrd_context, attaches it to transaction + * manager. Starts kernel txnmgr daemon. This is called on mount. + */ +int init_ktxnmgrd(struct super_block *super) { - ktxnmgrd_context * ctx; + txn_mgr *mgr; + ktxnmgrd_context *ctx; - assert("nikita-2448", mgr != NULL); - assert("zam-1015", mgr->daemon != NULL); + mgr = &get_super_private(super)->tmgr; - ctx = mgr->daemon; + assert("zam-1014", mgr->daemon == NULL); - spin_lock(&ctx->guard); + ctx = kmalloc(sizeof(ktxnmgrd_context), GFP_KERNEL); + if (ctx == NULL) + return RETERR(-ENOMEM); - ctx->rescan = 1; - ctx->done = 0; + assert("nikita-2442", ctx != NULL); - spin_unlock(&ctx->guard); + memset(ctx, 0, sizeof *ctx); + init_waitqueue_head(&ctx->wait); - kernel_thread(ktxnmgrd, mgr, CLONE_KERNEL); + /*kcond_init(&ctx->startup);*/ + spin_lock_init(&ctx->guard); + ctx->timeout = REISER4_TXNMGR_TIMEOUT; + mgr->daemon = ctx; - spin_lock(&ctx->guard); + /* start txnmgr daemon */ + start_ktxnmgrd(super); - /* daemon thread is not yet initialized */ - if (ctx->tsk == NULL) - /* wait until initialization completes */ - kcond_wait(&ctx->startup, &ctx->guard, 0); + return 0; +} - assert("nikita-2452", ctx->tsk != NULL); +void ktxnmgrd_kick(txn_mgr *mgr) +{ + assert("nikita-3234", mgr != NULL); + assert("nikita-3235", mgr->daemon != NULL); + wake_up(&mgr->daemon->wait); +} - spin_unlock(&ctx->guard); - return 0; +int is_current_ktxnmgrd(void) +{ + return (get_current_super_private()->tmgr.daemon->tsk == current); } -reiser4_internal void stop_ktxnmgrd (txn_mgr * mgr) +/** + * scan_mgr - commit atoms which are to be committed + * @super: super block to commit atoms of + * + * Commits old atoms. + */ +static int scan_mgr(struct super_block *super) { - ktxnmgrd_context * ctx; + int ret; + reiser4_context ctx; + + init_stack_context(&ctx, super); - assert ("zam-1016", mgr != NULL); - assert ("zam-1017", mgr->daemon != NULL); + ret = commit_some_atoms(&get_super_private(super)->tmgr); + + reiser4_exit_context(&ctx); + return ret; +} + +/** + * stop_ktxnmgrd - ktxnmgrd stop kernel thread + * @mgr: pointer to transaction manager embedded in reiser4 super block + * + * Sends stop signal to ktxnmgrd and wait until it handles it. + */ +static void stop_ktxnmgrd(txn_mgr *mgr) +{ + ktxnmgrd_context *ctx; + + assert("zam-1016", mgr != NULL); + assert("zam-1017", mgr->daemon != NULL); ctx = mgr->daemon; + /* + * prepare synchronization object to synchronize with ktxnmgrd + * completion + */ + init_completion(&ctx->start_finish_completion); + spin_lock(&ctx->guard); ctx->tsk = NULL; ctx->done = 1; spin_unlock(&ctx->guard); - kcond_signal(&ctx->wait); + wake_up(&ctx->wait); - /* wait until daemon finishes */ - wait_for_completion(&ctx->finish); + /* wait until ktxnmgrd finishes */ + wait_for_completion(&ctx->start_finish_completion); } -reiser4_internal void -done_ktxnmgrd_context (txn_mgr * mgr) +/** + * done_ktxnmgrd - stop kernel thread and frees ktxnmgrd context + * @mgr: + * + * This is called on umount. Stops ktxnmgrd and free t + */ +void done_ktxnmgrd(struct super_block *super) { - assert ("zam-1011", mgr != NULL); - assert ("zam-1012", mgr->daemon != NULL); + txn_mgr *mgr; + + mgr = &get_super_private(super)->tmgr; + assert("zam-1012", mgr->daemon != NULL); - reiser4_kfree(mgr->daemon); + stop_ktxnmgrd(mgr); + + kfree(mgr->daemon); mgr->daemon = NULL; } -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - End: -*/ +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 120 + * End: + */ diff -puN fs/reiser4/ktxnmgrd.h~reiser4-big-update fs/reiser4/ktxnmgrd.h --- devel/fs/reiser4/ktxnmgrd.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/ktxnmgrd.h 2005-09-15 19:51:08.000000000 -0700 @@ -6,11 +6,11 @@ #ifndef __KTXNMGRD_H__ #define __KTXNMGRD_H__ -#include "kcond.h" #include "txnmgr.h" #include "spin_macros.h" #include +#include #include #include #include @@ -19,12 +19,10 @@ /* in this structure all data necessary to start up, shut down and communicate * with ktxnmgrd are kept. */ struct ktxnmgrd_context { - /* conditional variable used to synchronize start up of ktxnmgrd */ - kcond_t startup; /* completion used to synchronize shut down of ktxnmgrd */ - struct completion finish; - /* condition variable on which ktxnmgrd sleeps */ - kcond_t wait; + struct completion start_finish_completion; + /* wait queue head on which ktxnmgrd sleeps */ + wait_queue_head_t wait; /* spin lock protecting all fields of this structure */ spinlock_t guard; /* timeout of sleeping on ->wait */ @@ -32,21 +30,17 @@ struct ktxnmgrd_context { /* kernel thread running ktxnmgrd */ struct task_struct *tsk; /* list of all file systems served by this ktxnmgrd */ - txn_mgrs_list_head queue; + struct list_head queue; /* is ktxnmgrd being shut down? */ - int done:1; + unsigned int done:1; /* should ktxnmgrd repeat scanning of atoms? */ - int rescan:1; + unsigned int rescan:1; }; -extern int init_ktxnmgrd_context(txn_mgr *); -extern void done_ktxnmgrd_context(txn_mgr *); - -extern int start_ktxnmgrd(txn_mgr *); -extern void stop_ktxnmgrd(txn_mgr *); +extern int init_ktxnmgrd(struct super_block *); +extern void done_ktxnmgrd(struct super_block *); extern void ktxnmgrd_kick(txn_mgr * mgr); - extern int is_current_ktxnmgrd(void); /* __KTXNMGRD_H__ */ diff -L fs/reiser4/lib.h -puN fs/reiser4/lib.h~reiser4-big-update /dev/null --- devel/fs/reiser4/lib.h +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,75 +0,0 @@ -/* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */ - -#if !defined (__FS_REISER4_LIB_H__) -#define __FS_REISER4_LIB_H__ - -/* These 2 functions of 64 bit numbers division were taken from - include/sound/pcm.h */ - -/* Helper function for 64 bits numbers division. */ -static inline void -divl(__u32 high, __u32 low, __u32 div, __u32 * q, __u32 * r) -{ - __u64 n = (__u64) high << 32 | low; - __u64 d = (__u64) div << 31; - __u32 q1 = 0; - int c = 32; - - while (n > 0xffffffffU) { - q1 <<= 1; - if (n >= d) { - n -= d; - q1 |= 1; - } - d >>= 1; - c--; - } - q1 <<= c; - if (n) { - low = n; - *q = q1 | (low / div); - if (r) - *r = low % div; - } else { - if (r) - *r = 0; - *q = q1; - } - return; -} - -/* Function for 64 bits numbers division. */ -static inline __u64 -div64_32(__u64 n, __u32 div, __u32 * rem) -{ - __u32 low, high; - - low = n & 0xffffffff; - high = n >> 32; - if (high) { - __u32 high1 = high % div; - __u32 low1 = low; - high /= div; - divl(high1, low1, div, &low, rem); - return (__u64) high << 32 | low; - } else { - if (rem) - *rem = low % div; - return low / div; - } - - return 0; -} - -#endif /* __FS_REISER4_LIB_H__ */ - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - scroll-step: 1 - End: -*/ diff -puN fs/reiser4/lock.c~reiser4-big-update fs/reiser4/lock.c --- devel/fs/reiser4/lock.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/lock.c 2005-09-15 19:51:08.000000000 -0700 @@ -18,14 +18,12 @@ Deadlock occurs when we have a loop constructed from process locked sets and lock request vectors. - NOTE: The reiser4 "tree" is a tree on disk, but its cached representation in memory is extended with "znodes" with which we connect nodes with their left and right neighbors using sibling pointers stored in the znodes. When we perform balancing operations we often go from left to right and from right to left. - +-P1-+ +-P3-+ |+--+| V1 |+--+| ||N1|| -------> ||N3|| @@ -223,20 +221,20 @@ static int request_is_deadlock_safe(znod #endif /* Returns a lock owner associated with current thread */ -reiser4_internal lock_stack * -get_current_lock_stack(void) +lock_stack *get_current_lock_stack(void) { return &get_current_context()->stack; } /* Wakes up all low priority owners informing them about possible deadlock */ -static void -wake_up_all_lopri_owners(znode * node) +static void wake_up_all_lopri_owners(znode * node) { lock_handle *handle; + struct list_head *pos; assert("nikita-1824", rw_zlock_is_locked(&node->lock)); - for_all_type_safe_list(owners, &node->lock.owners, handle) { + list_for_each(pos, &node->lock.owners) { + handle = list_entry(pos, lock_handle, owners_link); spin_lock_stack(handle->owner); assert("nikita-1832", handle->node == node); @@ -267,44 +265,50 @@ link_object(lock_handle * handle, lock_s handle->owner = owner; handle->node = node; - assert("reiser4-4", ergo(locks_list_empty(&owner->locks), owner->nr_locks == 0)); - locks_list_push_back(&owner->locks, handle); - owner->nr_locks ++; + assert("reiser4-4", + ergo(list_empty_careful(&owner->locks), owner->nr_locks == 0)); - owners_list_push_front(&node->lock.owners, handle); + /* add lock handle to the end of lock_stack's list of locks */ + list_add_tail(&handle->locks_link, &owner->locks); + owner->nr_locks++; + + /* add lock handle to the head of znode's list of owners */ + list_add(&handle->owners_link, &node->lock.owners); handle->signaled = 0; } /* Breaks a relation between a lock and its owner */ -static inline void -unlink_object(lock_handle * handle) +static inline void unlink_object(lock_handle * handle) { assert("zam-354", handle->owner != NULL); assert("nikita-1608", handle->node != NULL); assert("nikita-1633", rw_zlock_is_locked(&handle->node->lock)); assert("nikita-1829", handle->owner == get_current_lock_stack()); - assert("reiser4-5", handle->owner->nr_locks > 0); - locks_list_remove_clean(handle); - handle->owner->nr_locks --; - assert("reiser4-6", ergo(locks_list_empty(&handle->owner->locks), handle->owner->nr_locks == 0)); - owners_list_remove_clean(handle); + /* remove lock handle from lock_stack's list of locks */ + list_del_init(&handle->locks_link); + handle->owner->nr_locks--; + assert("reiser4-6", + ergo(list_empty_careful(&handle->owner->locks), + handle->owner->nr_locks == 0)); + + /* remove lock handle from znode's list of owners */ + list_del_init(&handle->owners_link); /* indicates that lock handle is free now */ handle->owner = NULL; } /* Actually locks an object knowing that we are able to do this */ -static void -lock_object(lock_stack * owner) +static void lock_object(lock_stack * owner) { lock_request *request; - znode *node; + znode *node; assert("nikita-1839", owner == get_current_lock_stack()); request = &owner->request; - node = request->node; + node = request->node; assert("nikita-1834", rw_zlock_is_locked(&node->lock)); if (request->mode == ZNODE_READ_LOCK) { node->lock.nr_readers++; @@ -324,20 +328,22 @@ lock_object(lock_stack * owner) } /* Check for recursive write locking */ -static int -recursive(lock_stack * owner) +static int recursive(lock_stack * owner) { int ret; znode *node; + lock_handle *lh; node = owner->request.node; /* Owners list is not empty for a locked node */ - assert("zam-314", !owners_list_empty(&node->lock.owners)); + assert("zam-314", !list_empty_careful(&node->lock.owners)); assert("nikita-1841", owner == get_current_lock_stack()); assert("nikita-1848", rw_zlock_is_locked(&node->lock)); - ret = (owners_list_front(&node->lock.owners)->owner == owner); + + lh = list_entry(node->lock.owners.next, lock_handle, owners_link); + ret = (lh->owner == owner); /* Recursive read locking should be done usual way */ assert("zam-315", !ret || owner->request.mode == ZNODE_WRITE_LOCK); @@ -349,12 +355,12 @@ recursive(lock_stack * owner) #if REISER4_DEBUG /* Returns true if the lock is held by the calling thread. */ -int -znode_is_any_locked(const znode * node) +int znode_is_any_locked(const znode * node) { lock_handle *handle; lock_stack *stack; int ret; + struct list_head *pos; if (!znode_is_locked(node)) { return 0; @@ -366,7 +372,8 @@ znode_is_any_locked(const znode * node) ret = 0; - for_all_type_safe_list(locks, &stack->locks, handle) { + list_for_each(pos, &stack->locks) { + handle = list_entry(pos, lock_handle, locks_link); if (handle->node == node) { ret = 1; break; @@ -381,8 +388,7 @@ znode_is_any_locked(const znode * node) #endif /* Returns true if a write lock is held by the calling thread. */ -reiser4_internal int -znode_is_write_locked(const znode * node) +int znode_is_write_locked(const znode * node) { lock_stack *stack; lock_handle *handle; @@ -395,8 +401,12 @@ znode_is_write_locked(const znode * node stack = get_current_lock_stack(); - /* If it is write locked, then all owner handles must equal the current stack. */ - handle = owners_list_front(&node->lock.owners); + /* + * When znode is write locked, all owner handles point to the same lock + * stack. Get pointer to lock stack from the first lock handle from + * znode's owner list + */ + handle = list_entry(node->lock.owners.next, lock_handle, owners_link); return (handle->owner == stack); } @@ -412,16 +422,15 @@ znode_is_write_locked(const znode * node flag) and counting this event in nr_signaled field of owner's lock stack object and wakeup owner's process. */ -static inline int -check_deadlock_condition(znode * node) +static inline int check_deadlock_condition(znode * node) { assert("nikita-1833", rw_zlock_is_locked(&node->lock)); - return node->lock.nr_hipri_requests > 0 && node->lock.nr_hipri_owners == 0; + return node->lock.nr_hipri_requests > 0 + && node->lock.nr_hipri_owners == 0; } /* checks lock/request compatibility */ -static int -check_lock_object(lock_stack * owner) +static int check_lock_object(lock_stack * owner) { znode *node = owner->request.node; @@ -448,8 +457,7 @@ check_lock_object(lock_stack * owner) } /* check for lock/request compatibility and update tree statistics */ -static int -can_lock_object(lock_stack * owner) +static int can_lock_object(lock_stack * owner) { int result; @@ -460,8 +468,7 @@ can_lock_object(lock_stack * owner) /* Setting of a high priority to the process. It clears "signaled" flags because znode locked by high-priority process can't satisfy our "deadlock condition". */ -static void -set_high_priority(lock_stack * owner) +static void set_high_priority(lock_stack * owner) { assert("nikita-1846", owner == get_current_lock_stack()); /* Do nothing if current priority is already high */ @@ -473,8 +480,8 @@ set_high_priority(lock_stack * owner) * * (Interrupts also are not involved.) */ - lock_handle *item = locks_list_front(&owner->locks); - while (!locks_list_end(&owner->locks, item)) { + lock_handle *item = list_entry(owner->locks.next, lock_handle, locks_link); + while (&owner->locks != &item->locks_link) { znode *node = item->node; WLOCK_ZLOCK(&node->lock); @@ -487,7 +494,7 @@ set_high_priority(lock_stack * owner) item->signaled = 0; WUNLOCK_ZLOCK(&node->lock); - item = locks_list_next(item); + item = list_entry(item->locks_link.next, lock_handle, locks_link); } owner->curpri = 1; atomic_set(&owner->nr_signaled, 0); @@ -495,8 +502,7 @@ set_high_priority(lock_stack * owner) } /* Sets a low priority to the process. */ -static void -set_low_priority(lock_stack * owner) +static void set_low_priority(lock_stack * owner) { assert("nikita-3075", owner == get_current_lock_stack()); /* Do nothing if current priority is already low */ @@ -504,9 +510,9 @@ set_low_priority(lock_stack * owner) /* scan all locks (lock handles) held by @owner, which is actually current thread, and check whether we are reaching deadlock possibility anywhere. - */ - lock_handle *handle = locks_list_front(&owner->locks); - while (!locks_list_end(&owner->locks, handle)) { + */ + lock_handle *handle = list_entry(owner->locks.next, lock_handle, locks_link); + while (&owner->locks != &handle->locks_link) { znode *node = handle->node; WLOCK_ZLOCK(&node->lock); /* this thread just was hipri owner of @node, so @@ -525,7 +531,7 @@ set_low_priority(lock_stack * owner) atomic_inc(&owner->nr_signaled); } WUNLOCK_ZLOCK(&node->lock); - handle = locks_list_next(handle); + handle = list_entry(handle->locks_link.next, lock_handle, locks_link); } owner->curpri = 0; } @@ -558,14 +564,13 @@ set_low_priority(lock_stack * owner) * Effect of this optimization wasn't big, after all. * */ -static void -wake_up_requestor(znode *node) +static void wake_up_requestor(znode * node) { #if NR_CPUS > 2 - requestors_list_head *creditors; - lock_stack *convoy[MAX_CONVOY_SIZE]; - int convoyused; - int convoylimit; + struct list_head *creditors; + lock_stack *convoy[MAX_CONVOY_SIZE]; + int convoyused; + int convoylimit; assert("nikita-3180", node != NULL); assert("nikita-3181", rw_zlock_is_locked(&node->lock)); @@ -573,8 +578,8 @@ wake_up_requestor(znode *node) convoyused = 0; convoylimit = min(num_online_cpus() - 1, MAX_CONVOY_SIZE); creditors = &node->lock.requestors; - if (!requestors_list_empty(creditors)) { - convoy[0] = requestors_list_front(creditors); + if (!list_empty_careful(creditors)) { + convoy[0] = list_entry(creditors->next, lock_stack, requestors_link); convoyused = 1; /* * it has been verified experimentally, that there are no @@ -585,12 +590,12 @@ wake_up_requestor(znode *node) convoylimit > 1) { lock_stack *item; - for (item = requestors_list_next(convoy[0]); - ! requestors_list_end(creditors, item); - item = requestors_list_next(item)) { + for (item = list_entry(convoy[0]->requestors_link.next, lock_stack, requestors_link); + creditors != &item->requestors_link; + item = list_entry(item->requestors_link.next, lock_stack, requestors_link)) { if (item->request.mode == ZNODE_READ_LOCK) { convoy[convoyused] = item; - ++ convoyused; + ++convoyused; /* * it is safe to spin lock multiple * lock stacks here, because lock @@ -615,16 +620,17 @@ wake_up_requestor(znode *node) WUNLOCK_ZLOCK(&node->lock); while (convoyused > 0) { - -- convoyused; + --convoyused; __reiser4_wake_up(convoy[convoyused]); spin_unlock(&convoy[convoyused]->sguard.lock); } #else /* uniprocessor case: keep it simple */ - if (!requestors_list_empty(&node->lock.requestors)) { + if (!list_empty_careful(&node->lock.requestors)) { lock_stack *requestor; - requestor = requestors_list_front(&node->lock.requestors); + requestor = list_entry(node->lock.requestors.next, lock_stack, + requestors_link); reiser4_wake_up(requestor); } @@ -635,8 +641,7 @@ wake_up_requestor(znode *node) #undef MAX_CONVOY_SIZE /* release long-term lock, acquired by longterm_lock_znode() */ -reiser4_internal void -longterm_unlock_znode(lock_handle * handle) +void longterm_unlock_znode(lock_handle * handle) { znode *node = handle->node; lock_stack *oldowner = handle->owner; @@ -657,7 +662,6 @@ longterm_unlock_znode(lock_handle * hand LOCK_CNT_DEC(long_term_locked_znode); - /* * to minimize amount of operations performed under lock, pre-compute * all variables used within critical section. This makes code @@ -665,13 +669,13 @@ longterm_unlock_znode(lock_handle * hand */ /* was this lock of hi or lo priority */ - hipri = oldowner->curpri ? -1 : 0; + hipri = oldowner->curpri ? -1 : 0; /* number of readers */ readers = node->lock.nr_readers; /* +1 if write lock, -1 if read lock */ - rdelta = (readers > 0) ? -1 : +1; + rdelta = (readers > 0) ? -1 : +1; /* true if node is to die and write lock is released */ - youdie = ZF_ISSET(node, JNODE_HEARD_BANSHEE) && (readers < 0); + youdie = ZF_ISSET(node, JNODE_HEARD_BANSHEE) && (readers < 0); WLOCK_ZLOCK(&node->lock); @@ -704,11 +708,11 @@ longterm_unlock_znode(lock_handle * hand /* If the node is locked it must have an owners list. Likewise, if the node is unlocked it must have an empty owners list. */ assert("zam-319", equi(znode_is_locked(node), - !owners_list_empty(&node->lock.owners))); + !list_empty_careful(&node->lock.owners))); #if REISER4_DEBUG if (!znode_is_locked(node)) - ++ node->times_locked; + ++node->times_locked; #endif /* If there are pending lock requests we wake up a requestor */ @@ -728,7 +732,7 @@ longterm_unlock_znode(lock_handle * hand /* final portion of longterm-lock */ static int -lock_tail(lock_stack *owner, int wake_up_next, int ok, znode_lock_mode mode) +lock_tail(lock_stack * owner, int wake_up_next, int ok, znode_lock_mode mode) { znode *node = owner->request.node; @@ -753,7 +757,7 @@ lock_tail(lock_stack *owner, int wake_up znode was already referenced at the entry to this function, hence taking spin-lock here is not necessary (see comment in the zref()). - */ + */ zref(node); LOCK_CNT_INC(long_term_locked_znode); @@ -769,13 +773,12 @@ lock_tail(lock_stack *owner, int wake_up * lock without any special flags. This is the kind of lock that any tree * traversal takes on the root node of the tree, which is very frequent. */ -static int -longterm_lock_tryfast(lock_stack * owner) +static int longterm_lock_tryfast(lock_stack * owner) { - int result; - int wake_up_next = 0; - znode *node; - zlock *lock; + int result; + int wake_up_next = 0; + znode *node; + zlock *lock; node = owner->request.node; lock = &node->lock; @@ -789,8 +792,9 @@ longterm_lock_tryfast(lock_stack * owner if (likely(result != -EINVAL)) { spin_lock_znode(node); - result = try_capture( - ZJNODE(node), ZNODE_READ_LOCK, 0, 1/* can copy on capture */); + result = + try_capture(ZJNODE(node), ZNODE_READ_LOCK, 0, + 1 /* can copy on capture */ ); spin_unlock_znode(node); WLOCK_ZLOCK(lock); if (unlikely(result != 0)) { @@ -810,27 +814,25 @@ longterm_lock_tryfast(lock_stack * owner } /* locks given lock object */ -reiser4_internal int -longterm_lock_znode( - /* local link object (allocated by lock owner thread, usually on its own - * stack) */ - lock_handle * handle, - /* znode we want to lock. */ - znode * node, - /* {ZNODE_READ_LOCK, ZNODE_WRITE_LOCK}; */ - znode_lock_mode mode, - /* {0, -EINVAL, -E_DEADLOCK}, see return codes description. */ - znode_lock_request request) -{ - int ret; - int hipri = (request & ZNODE_LOCK_HIPRI) != 0; - int wake_up_next = 0; - int non_blocking = 0; - int has_atom; - txn_capture cap_flags; - zlock *lock; - txn_handle *txnh; - tree_level level; +int longterm_lock_znode( + /* local link object (allocated by lock owner thread, usually on its own + * stack) */ + lock_handle * handle, + /* znode we want to lock. */ + znode * node, + /* {ZNODE_READ_LOCK, ZNODE_WRITE_LOCK}; */ + znode_lock_mode mode, + /* {0, -EINVAL, -E_DEADLOCK}, see return codes description. */ + znode_lock_request request) { + int ret; + int hipri = (request & ZNODE_LOCK_HIPRI) != 0; + int wake_up_next = 0; + int non_blocking = 0; + int has_atom; + txn_capture cap_flags; + zlock *lock; + txn_handle *txnh; + tree_level level; /* Get current process context */ lock_stack *owner = get_current_lock_stack(); @@ -910,9 +912,10 @@ longterm_lock_znode( break; } - assert("nikita-1844", (ret == 0) || ((ret == -E_REPEAT) && !non_blocking)); + assert("nikita-1844", (ret == 0) + || ((ret == -E_REPEAT) && !non_blocking)); /* If we can get the lock... Try to capture first before - taking the lock.*/ + taking the lock. */ /* first handle commonest case where node and txnh are already * in the same atom. */ @@ -979,8 +982,9 @@ longterm_lock_znode( */ WUNLOCK_ZLOCK(lock); spin_lock_znode(node); - ret = try_capture( - ZJNODE(node), mode, cap_flags, 1/* can copy on capture*/); + ret = + try_capture(ZJNODE(node), mode, cap_flags, + 1 /* can copy on capture */ ); spin_unlock_znode(node); WLOCK_ZLOCK(lock); if (unlikely(ret != 0)) { @@ -1029,17 +1033,17 @@ longterm_lock_znode( if (lock->nr_hipri_owners == 0) wake_up_all_lopri_owners(node); /* And prepare a lock request */ - requestors_list_push_front(&lock->requestors, owner); + list_add(&owner->requestors_link, &lock->requestors); } else { /* If we are going in low priority direction then we set low priority to our process. This is the only case when a process may become low priority */ /* And finally prepare a lock request */ - requestors_list_push_back(&lock->requestors, owner); + list_add_tail(&owner->requestors_link, &lock->requestors); } /* Ok, here we have prepared a lock request, so unlock - a znode ...*/ + a znode ... */ WUNLOCK_ZLOCK(lock); /* ... and sleep */ go_to_sleep(owner); @@ -1051,7 +1055,7 @@ longterm_lock_znode( lock->nr_hipri_requests--; } - requestors_list_remove(owner); + list_del_init(&owner->requestors_link); } assert("jmacd-807/a", rw_zlock_is_locked(&node->lock)); @@ -1060,15 +1064,15 @@ longterm_lock_znode( /* lock object invalidation means changing of lock object state to `INVALID' and waiting for all other processes to cancel theirs lock requests. */ -reiser4_internal void -invalidate_lock(lock_handle * handle /* path to lock - * owner and lock - * object is being - * invalidated. */ ) +void invalidate_lock(lock_handle * handle /* path to lock + * owner and lock + * object is being + * invalidated. */ ) { znode *node = handle->node; lock_stack *owner = handle->owner; lock_stack *rq; + struct list_head *pos; assert("zam-325", owner == get_current_lock_stack()); assert("zam-103", znode_is_write_locked(node)); @@ -1086,14 +1090,15 @@ invalidate_lock(lock_handle * handle /* node->lock.nr_readers = 0; /* all requestors will be informed that lock is invalidated. */ - for_all_type_safe_list(requestors, &node->lock.requestors, rq) { + list_for_each(pos, &node->lock.requestors) { + rq = list_entry(pos, lock_stack, requestors_link); reiser4_wake_up(rq); } /* We use that each unlock() will wakeup first item from requestors list; our lock stack is the last one. */ - while (!requestors_list_empty(&node->lock.requestors)) { - requestors_list_push_back(&node->lock.requestors, owner); + while (!list_empty_careful(&node->lock.requestors)) { + list_add_tail(&owner->requestors_link, &node->lock.requestors); prepare_to_sleep(owner); @@ -1101,52 +1106,45 @@ invalidate_lock(lock_handle * handle /* go_to_sleep(owner); WLOCK_ZLOCK(&node->lock); - requestors_list_remove(owner); + list_del_init(&owner->requestors_link); } WUNLOCK_ZLOCK(&node->lock); } /* Initializes lock_stack. */ -reiser4_internal void -init_lock_stack(lock_stack * owner /* pointer to - * allocated - * structure. */ ) -{ - /* xmemset(,0,) is done already as a part of reiser4 context - * initialization */ - /* xmemset(owner, 0, sizeof (lock_stack)); */ - locks_list_init(&owner->locks); - requestors_list_clean(owner); +void init_lock_stack(lock_stack * owner /* pointer to + * allocated + * structure. */ ) +{ + INIT_LIST_HEAD(&owner->locks); + INIT_LIST_HEAD(&owner->requestors_link); spin_stack_init(owner); owner->curpri = 1; sema_init(&owner->sema, 0); } /* Initializes lock object. */ -reiser4_internal void -reiser4_init_lock(zlock * lock /* pointer on allocated - * uninitialized lock object - * structure. */ ) +void reiser4_init_lock(zlock * lock /* pointer on allocated + * uninitialized lock object + * structure. */ ) { - memset(lock, 0, sizeof (zlock)); + memset(lock, 0, sizeof(zlock)); rw_zlock_init(lock); - requestors_list_init(&lock->requestors); - owners_list_init(&lock->owners); + INIT_LIST_HEAD(&lock->requestors); + INIT_LIST_HEAD(&lock->owners); } /* lock handle initialization */ -reiser4_internal void -init_lh(lock_handle * handle) +void init_lh(lock_handle * handle) { memset(handle, 0, sizeof *handle); - locks_list_clean(handle); - owners_list_clean(handle); + INIT_LIST_HEAD(&handle->locks_link); + INIT_LIST_HEAD(&handle->owners_link); } /* freeing of lock handle resources */ -reiser4_internal void -done_lh(lock_handle * handle) +void done_lh(lock_handle * handle) { assert("zam-342", handle != NULL); if (handle->owner != NULL) @@ -1165,7 +1163,7 @@ move_lh_internal(lock_handle * new, lock /* locks_list, modified by link_object() is not protected by anything. This is valid because only current thread ever modifies locks_list of its lock_stack. - */ + */ assert("nikita-1827", owner == get_current_lock_stack()); assert("nikita-1831", new->owner == NULL); @@ -1196,21 +1194,18 @@ move_lh_internal(lock_handle * new, lock WUNLOCK_ZLOCK(&node->lock); } -reiser4_internal void -move_lh(lock_handle * new, lock_handle * old) +void move_lh(lock_handle * new, lock_handle * old) { move_lh_internal(new, old, /*unlink_old */ 1); } -reiser4_internal void -copy_lh(lock_handle * new, lock_handle * old) +void copy_lh(lock_handle * new, lock_handle * old) { move_lh_internal(new, old, /*unlink_old */ 0); } /* after getting -E_DEADLOCK we unlock znodes until this function returns false */ -reiser4_internal int -check_deadlock(void) +int check_deadlock(void) { lock_stack *owner = get_current_lock_stack(); return atomic_read(&owner->nr_signaled) != 0; @@ -1218,8 +1213,7 @@ check_deadlock(void) /* Before going to sleep we re-check "release lock" requests which might come from threads with hi-pri lock priorities. */ -reiser4_internal int -prepare_to_sleep(lock_stack * owner) +int prepare_to_sleep(lock_stack * owner) { assert("nikita-1847", owner == get_current_lock_stack()); /* NOTE(Zam): We cannot reset the lock semaphore here because it may @@ -1230,21 +1224,21 @@ prepare_to_sleep(lock_stack * owner) could we loosen by semaphore reset. The less complex scheme without resetting the semaphore is enough to not to loose wake-ups. - if (0) { + if (0) { - NOTE-NIKITA: I commented call to sema_init() out hoping - that it is the reason or thread sleeping in - down(&owner->sema) without any other thread running. - - Anyway, it is just an optimization: is semaphore is not - reinitialised at this point, in the worst case - longterm_lock_znode() would have to iterate its loop once - more. - spin_lock_stack(owner); - sema_init(&owner->sema, 0); - spin_unlock_stack(owner); - } - */ + NOTE-NIKITA: I commented call to sema_init() out hoping + that it is the reason or thread sleeping in + down(&owner->sema) without any other thread running. + + Anyway, it is just an optimization: is semaphore is not + reinitialised at this point, in the worst case + longterm_lock_znode() would have to iterate its loop once + more. + spin_lock_stack(owner); + sema_init(&owner->sema, 0); + spin_unlock_stack(owner); + } + */ /* We return -E_DEADLOCK if one or more "give me the lock" messages are * counted in nr_signaled */ @@ -1256,15 +1250,13 @@ prepare_to_sleep(lock_stack * owner) } /* Wakes up a single thread */ -reiser4_internal void -__reiser4_wake_up(lock_stack * owner) +void __reiser4_wake_up(lock_stack * owner) { up(&owner->sema); } /* Puts a thread to sleep */ -reiser4_internal void -go_to_sleep(lock_stack * owner) +void go_to_sleep(lock_stack * owner) { /* Well, we might sleep here, so holding of any spinlocks is no-no */ assert("nikita-3027", schedulable()); @@ -1272,10 +1264,9 @@ go_to_sleep(lock_stack * owner) down(&owner->sema); } -reiser4_internal int -lock_stack_isclean(lock_stack * owner) +int lock_stack_isclean(lock_stack * owner) { - if (locks_list_empty(&owner->locks)) { + if (list_empty_careful(&owner->locks)) { assert("zam-353", atomic_read(&owner->nr_signaled) == 0); return 1; } @@ -1285,10 +1276,10 @@ lock_stack_isclean(lock_stack * owner) #if REISER4_DEBUG /* Debugging help */ -reiser4_internal void -print_lock_stack(const char *prefix, lock_stack * owner) +void print_lock_stack(const char *prefix, lock_stack * owner) { lock_handle *handle; + struct list_head *pos; spin_lock_stack(owner); @@ -1297,16 +1288,20 @@ print_lock_stack(const char *prefix, loc printk(".... curpri %s\n", owner->curpri ? "high" : "low"); if (owner->request.mode != 0) { - printk(".... current request: %s", owner->request.mode == ZNODE_WRITE_LOCK ? "write" : "read"); + printk(".... current request: %s", + owner->request.mode == + ZNODE_WRITE_LOCK ? "write" : "read"); print_address("", znode_get_block(owner->request.node)); } printk(".... current locks:\n"); - for_all_type_safe_list(locks, &owner->locks, handle) { + list_for_each(pos, &owner->locks) { + handle = list_entry(pos, lock_handle, locks_link); if (handle->node != NULL) print_address(znode_is_rlocked(handle->node) ? - "...... read" : "...... write", znode_get_block(handle->node)); + "...... read" : "...... write", + znode_get_block(handle->node)); } spin_unlock_stack(owner); @@ -1316,30 +1311,36 @@ print_lock_stack(const char *prefix, loc * debugging functions */ +void list_check(struct list_head *head) +{ + struct list_head *pos; + + list_for_each (pos, head) + assert("", (pos->prev != NULL && pos->next != NULL && + pos->prev->next == pos && pos->next->prev == pos)); +} + /* check consistency of locking data-structures hanging of the @stack */ -static void -check_lock_stack(lock_stack * stack) +static void check_lock_stack(lock_stack * stack) { spin_lock_stack(stack); /* check that stack->locks is not corrupted */ - locks_list_check(&stack->locks); + list_check(&stack->locks); spin_unlock_stack(stack); } /* check consistency of locking data structures */ -void -check_lock_data(void) +void check_lock_data(void) { check_lock_stack(&get_current_context()->stack); } /* check consistency of locking data structures for @node */ -void -check_lock_node_data(znode * node) +void check_lock_node_data(znode * node) { RLOCK_ZLOCK(&node->lock); - owners_list_check(&node->lock.owners); - requestors_list_check(&node->lock.requestors); + list_check(&node->lock.owners); + list_check(&node->lock.requestors); RUNLOCK_ZLOCK(&node->lock); } @@ -1350,6 +1351,7 @@ request_is_deadlock_safe(znode * node, z znode_lock_request request) { lock_stack *owner; + struct list_head *pos; owner = get_current_lock_stack(); /* @@ -1360,8 +1362,11 @@ request_is_deadlock_safe(znode * node, z znode_get_level(node) != 0) { lock_handle *item; - for_all_type_safe_list(locks, &owner->locks, item) { - znode *other = item->node; + list_for_each(pos, &owner->locks) { + znode *other; + + item = list_entry(pos, lock_handle, locks_link); + other = item->node; if (znode_get_level(other) == 0) continue; @@ -1376,8 +1381,7 @@ request_is_deadlock_safe(znode * node, z /* return pointer to static storage with name of lock_mode. For debugging */ -reiser4_internal const char * -lock_mode_name(znode_lock_mode lock /* lock mode to get name of */ ) +const char *lock_mode_name(znode_lock_mode lock /* lock mode to get name of */ ) { if (lock == ZNODE_READ_LOCK) return "read"; diff -puN fs/reiser4/lock.h~reiser4-big-update fs/reiser4/lock.h --- devel/fs/reiser4/lock.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/lock.h 2005-09-15 19:51:08.000000000 -0700 @@ -11,9 +11,8 @@ #include "spin_macros.h" #include "key.h" #include "coord.h" -#include "type_safe_list.h" #include "plugin/node/node.h" -#include "jnode.h" +#include "txnmgr.h" #include "readahead.h" #include @@ -22,23 +21,6 @@ #include #include -/* per-znode lock requests queue; list items are lock owner objects - which want to lock given znode. - - Locking: protected by znode spin lock. */ -TYPE_SAFE_LIST_DECLARE(requestors); -/* per-znode list of lock handles for this znode - - Locking: protected by znode spin lock. */ -TYPE_SAFE_LIST_DECLARE(owners); -/* per-owner list of lock handles that point to locked znodes which - belong to one lock owner - - Locking: this list is only accessed by the thread owning the lock stack this - list is attached to. Hence, no locking is necessary. -*/ -TYPE_SAFE_LIST_DECLARE(locks); - /* Per-znode lock object */ struct zlock { reiser4_rw_data guard; @@ -52,9 +34,9 @@ struct zlock { unsigned nr_hipri_requests; /* A linked list of lock_handle objects that contains pointers for all lock_stacks which have this lock object locked */ - owners_list_head owners; + struct list_head owners; /* A linked list of lock_stacks that wait for this lock */ - requestors_list_head requestors; + struct list_head requestors; }; #define rw_ordering_pred_zlock(lock) \ @@ -72,7 +54,6 @@ RW_LOCK_FUNCTIONS(zlock, zlock, guard); (((mode) == ZNODE_WRITE_LOCK && !lock_is_locked(lock)) \ || ((mode) == ZNODE_READ_LOCK && lock_can_be_rlocked(lock))) - /* Since we have R/W znode locks we need additional bidirectional `link' objects to implement n<->m relationship between lock owners and lock objects. We call them `lock handles'. @@ -84,16 +65,16 @@ struct lock_handle { lock owner and counted in owner->nr_signalled Locking: this is accessed under spin lock on ->node. - */ + */ int signaled; /* A link to owner of a lock */ lock_stack *owner; /* A link to znode locked */ znode *node; /* A list of all locks for a process */ - locks_list_link locks_link; + struct list_head locks_link; /* A list of all owners for a znode */ - owners_list_link owners_link; + struct list_head owners_link; }; typedef struct lock_request { @@ -115,21 +96,21 @@ struct lock_stack { This is only accessed by the current thread and thus requires no locking. - */ + */ int curpri; /* A list of all locks owned by this process. Elements can be added to * this list only by the current thread. ->node pointers in this list * can be only changed by the current thread. */ - locks_list_head locks; - int nr_locks; /* number of lock handles in the above list */ + struct list_head locks; + int nr_locks; /* number of lock handles in the above list */ /* When lock_stack waits for the lock, it puts itself on double-linked requestors list of that lock */ - requestors_list_link requestors_link; + struct list_head requestors_link; /* Current lock request info. This is only accessed by the current thread and thus requires no locking. - */ + */ lock_request request; /* It is a lock_stack's synchronization object for when process sleeps when requested lock not on this lock_stack but which it wishes to @@ -160,19 +141,15 @@ struct lock_stack { struct semaphore sema; }; -/* defining of list manipulation functions for lists above */ -TYPE_SAFE_LIST_DEFINE(requestors, lock_stack, requestors_link); -TYPE_SAFE_LIST_DEFINE(owners, lock_handle, owners_link); -TYPE_SAFE_LIST_DEFINE(locks, lock_handle, locks_link); /* User-visible znode locking functions */ -extern int longterm_lock_znode (lock_handle * handle, - znode * node, - znode_lock_mode mode, - znode_lock_request request); +extern int longterm_lock_znode(lock_handle * handle, + znode * node, + znode_lock_mode mode, + znode_lock_request request); extern void longterm_unlock_znode(lock_handle * handle); @@ -196,7 +173,8 @@ extern int lock_stack_isclean(lock_stack /* zlock object state check macros: only used in assertions. Both forms imply that the lock is held by the current thread. */ -extern int znode_is_write_locked(const znode * node); +extern int znode_is_write_locked(const znode *); +extern void invalidate_lock(lock_handle *); #if REISER4_DEBUG #define spin_ordering_pred_stack_addendum (1) @@ -219,8 +197,7 @@ extern int znode_is_write_locked(const z /* Same for lock_stack */ SPIN_LOCK_FUNCTIONS(stack, lock_stack, sguard); -static inline void -reiser4_wake_up(lock_stack * owner) +static inline void reiser4_wake_up(lock_stack * owner) { spin_lock_stack(owner); __reiser4_wake_up(owner); diff -puN fs/reiser4/Makefile~reiser4-big-update fs/reiser4/Makefile --- devel/fs/reiser4/Makefile~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/Makefile 2005-09-15 19:51:08.000000000 -0700 @@ -27,19 +27,19 @@ reiser4-y := \ eottl.o \ search.o \ page_cache.o \ - kcond.o \ seal.o \ dscale.o \ flush_queue.o \ ktxnmgrd.o \ blocknrset.o \ super.o \ + super_ops.o \ + fsdata.o \ + export_ops.o \ oid.o \ tree_walk.o \ inode.o \ vfs_ops.o \ - inode_ops.o \ - file_ops.o \ as_ops.o \ emergency_flush.o \ entd.o\ @@ -54,8 +54,18 @@ reiser4-y := \ plugin/plugin_set.o \ plugin/node/node.o \ plugin/object.o \ - plugin/symlink.o \ - plugin/cryptcompress.o \ + plugin/inode_ops.o \ + plugin/inode_ops_rename.o \ + plugin/file_ops.o \ + plugin/file_ops_readdir.o \ + plugin/file_plugin_common.o \ + plugin/file/file.o \ + plugin/file/tail_conversion.o \ + plugin/file/symlink.o \ + plugin/file/cryptcompress.o \ + plugin/dir_plugin_common.o \ + plugin/dir/hashed_dir.o \ + plugin/dir/seekable_dir.o \ plugin/digest.o \ plugin/node/node40.o \ \ @@ -80,20 +90,11 @@ reiser4-y := \ plugin/tail_policy.o \ plugin/item/item.o \ \ - plugin/dir/hashed_dir.o \ - plugin/dir/pseudo_dir.o \ - plugin/dir/dir.o \ - \ plugin/security/perm.o \ - \ - plugin/pseudo/pseudo.o \ - \ plugin/space/bitmap.o \ \ plugin/disk_format/disk_format40.o \ plugin/disk_format/disk_format.o \ - \ - plugin/file/pseudo.o \ - plugin/file/file.o \ - plugin/file/regular.o \ - plugin/file/tail_conversion.o + \ + plugin/regular.o + diff -puN fs/reiser4/oid.c~reiser4-big-update fs/reiser4/oid.c --- devel/fs/reiser4/oid.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/oid.c 2005-09-15 19:51:08.000000000 -0700 @@ -14,8 +14,7 @@ * are provided by disk format plugin that reads them from the disk during * mount. */ -reiser4_internal int -oid_init_allocator(struct super_block *super, oid_t nr_files, oid_t next) +int oid_init_allocator(struct super_block *super, oid_t nr_files, oid_t next) { reiser4_super_info_data *sbinfo; @@ -30,8 +29,7 @@ oid_init_allocator(struct super_block *s * allocate oid and return it. ABSOLUTE_MAX_OID is returned when allocator * runs out of oids. */ -reiser4_internal oid_t -oid_allocate(struct super_block *super) +oid_t oid_allocate(struct super_block * super) { reiser4_super_info_data *sbinfo; oid_t oid; @@ -40,8 +38,8 @@ oid_allocate(struct super_block *super) reiser4_spin_lock_sb(sbinfo); if (sbinfo->next_to_use != ABSOLUTE_MAX_OID) { - oid = sbinfo->next_to_use ++; - sbinfo->oids_in_use ++; + oid = sbinfo->next_to_use++; + sbinfo->oids_in_use++; } else oid = ABSOLUTE_MAX_OID; reiser4_spin_unlock_sb(sbinfo); @@ -51,15 +49,14 @@ oid_allocate(struct super_block *super) /* * Tell oid allocator that @oid is now free. */ -reiser4_internal int -oid_release(struct super_block *super, oid_t oid UNUSED_ARG) +int oid_release(struct super_block *super, oid_t oid UNUSED_ARG) { reiser4_super_info_data *sbinfo; sbinfo = get_super_private(super); reiser4_spin_lock_sb(sbinfo); - sbinfo->oids_in_use --; + sbinfo->oids_in_use--; reiser4_spin_unlock_sb(sbinfo); return 0; } @@ -69,7 +66,7 @@ oid_release(struct super_block *super, o * without actually allocating it. This is used by disk format plugin to save * oid allocator state on the disk. */ -reiser4_internal oid_t oid_next(const struct super_block *super) +oid_t oid_next(const struct super_block * super) { reiser4_super_info_data *sbinfo; oid_t oid; @@ -87,7 +84,7 @@ reiser4_internal oid_t oid_next(const st * number of "inodes" and by disk format plugin to save oid allocator state on * the disk. */ -reiser4_internal long oids_used(const struct super_block *super) +long oids_used(const struct super_block *super) { reiser4_super_info_data *sbinfo; oid_t used; @@ -97,17 +94,17 @@ reiser4_internal long oids_used(const st reiser4_spin_lock_sb(sbinfo); used = sbinfo->oids_in_use; reiser4_spin_unlock_sb(sbinfo); - if (used < (__u64) ((long) ~0) >> 1) - return (long) used; + if (used < (__u64) ((long)~0) >> 1) + return (long)used; else - return (long) -1; + return (long)-1; } /* * return number of "free" oids. This is used by statfs(2) to report "free" * inodes. */ -reiser4_internal long oids_free(const struct super_block *super) +long oids_free(const struct super_block *super) { reiser4_super_info_data *sbinfo; oid_t oids; @@ -117,10 +114,10 @@ reiser4_internal long oids_free(const st reiser4_spin_lock_sb(sbinfo); oids = ABSOLUTE_MAX_OID - OIDS_RESERVED - sbinfo->next_to_use; reiser4_spin_unlock_sb(sbinfo); - if (oids < (__u64) ((long) ~0) >> 1) - return (long) oids; + if (oids < (__u64) ((long)~0) >> 1) + return (long)oids; else - return (long) -1; + return (long)-1; } /* @@ -129,8 +126,7 @@ reiser4_internal long oids_free(const st * (i.e., when oid allocation cannot be any longer rolled back due to some * error). */ -reiser4_internal void -oid_count_allocated(void) +void oid_count_allocated(void) { txn_atom *atom; @@ -144,8 +140,7 @@ oid_count_allocated(void) * point when we are irrevocably committed to the deletion of the file (i.e., * when oid release cannot be any longer rolled back due to some error). */ -reiser4_internal void -oid_count_released(void) +void oid_count_released(void) { txn_atom *atom; diff -puN fs/reiser4/page_cache.c~reiser4-big-update fs/reiser4/page_cache.c --- devel/fs/reiser4/page_cache.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/page_cache.c 2005-09-15 19:51:08.000000000 -0700 @@ -42,7 +42,6 @@ 5. kmapping/kunmapping of unformatted pages is done by read/write methods. - DEADLOCKS RELATED TO MEMORY PRESSURE. [OUTDATED. Only interesting historically.] @@ -87,13 +86,6 @@ When there is more than one reiser4 mount in a system, condition (c) makes reclaim-ability not easily verifiable beyond trivial cases mentioned above. - - - - - - - THIS COMMENT IS VALID FOR "MANY BLOCKS ON PAGE" CASE Fake inode is used to bound formatted nodes and each node is indexed within @@ -192,7 +184,7 @@ #include #include -static struct bio *page_bio(struct page *page, jnode * node, int rw, int gfp); +static struct bio *page_bio(struct page *, jnode *, int rw, unsigned int gfp); static struct address_space_operations formatted_fake_as_ops; @@ -200,15 +192,9 @@ static const oid_t fake_ino = 0x1; static const oid_t bitmap_ino = 0x2; static const oid_t cc_ino = 0x3; -/* one-time initialization of fake inodes handling functions. */ -reiser4_internal int -init_fakes() -{ - return 0; -} - static void -init_fake_inode(struct super_block *super, struct inode *fake, struct inode **pfake) +init_fake_inode(struct super_block *super, struct inode *fake, + struct inode **pfake) { assert("nikita-2168", fake->i_state & I_NEW); fake->i_mapping->a_ops = &formatted_fake_as_ops; @@ -221,9 +207,14 @@ init_fake_inode(struct super_block *supe unlock_new_inode(fake); } -/* initialize fake inode to which formatted nodes are bound in the page cache. */ -reiser4_internal int -init_formatted_fake(struct super_block *super) +/** + * init_formatted_fake - iget inodes for formatted nodes and bitmaps + * @super: super block to init fake inode for + * + * Initializes fake inode to which formatted nodes are bound in the page cache + * and inode for bitmaps. + */ +int init_formatted_fake(struct super_block *super) { struct inode *fake; struct inode *bitmap; @@ -260,9 +251,14 @@ init_formatted_fake(struct super_block * return RETERR(-ENOMEM); } -/* release fake inode for @super */ -reiser4_internal int -done_formatted_fake(struct super_block *super) +/** + * done_formatted_fake - release inode used by formatted nodes and bitmaps + * @super: super block to init fake inode for + * + * Releases inodes which were used as address spaces of bitmap and formatted + * nodes. + */ +void done_formatted_fake(struct super_block *super) { reiser4_super_info_data *sinfo; @@ -283,12 +279,12 @@ done_formatted_fake(struct super_block * iput(sinfo->cc); sinfo->cc = NULL; } - return 0; + return; } -reiser4_internal void reiser4_wait_page_writeback (struct page * page) +void reiser4_wait_page_writeback(struct page *page) { - assert ("zam-783", PageLocked(page)); + assert("zam-783", PageLocked(page)); do { unlock_page(page); @@ -298,8 +294,7 @@ reiser4_internal void reiser4_wait_page_ } /* return tree @page is in */ -reiser4_internal reiser4_tree * -tree_by_page(const struct page *page /* page to query */ ) +reiser4_tree *tree_by_page(const struct page *page /* page to query */ ) { assert("nikita-2461", page != NULL); return &get_super_private(page->mapping->host->i_sb)->tree; @@ -311,7 +306,8 @@ tree_by_page(const struct page *page /* */ static int -end_bio_single_page_read(struct bio *bio, unsigned int bytes_done UNUSED_ARG, int err UNUSED_ARG) +end_bio_single_page_read(struct bio *bio, unsigned int bytes_done UNUSED_ARG, + int err UNUSED_ARG) { struct page *page; @@ -323,9 +319,9 @@ end_bio_single_page_read(struct bio *bio page = bio->bi_io_vec[0].bv_page; - if (test_bit(BIO_UPTODATE, &bio->bi_flags)) + if (test_bit(BIO_UPTODATE, &bio->bi_flags)) { SetPageUptodate(page); - else { + } else { ClearPageUptodate(page); SetPageError(page); } @@ -340,7 +336,8 @@ end_bio_single_page_read(struct bio *bio */ static int -end_bio_single_page_write(struct bio *bio, unsigned int bytes_done UNUSED_ARG, int err UNUSED_ARG) +end_bio_single_page_write(struct bio *bio, unsigned int bytes_done UNUSED_ARG, + int err UNUSED_ARG) { struct page *page; @@ -361,17 +358,23 @@ end_bio_single_page_write(struct bio *bi /* ->readpage() method for formatted nodes */ static int -formatted_readpage(struct file *f UNUSED_ARG, struct page *page /* page to read */ ) +formatted_readpage(struct file *f UNUSED_ARG, + struct page *page /* page to read */ ) { assert("nikita-2412", PagePrivate(page) && jprivate(page)); return page_io(page, jprivate(page), READ, GFP_KERNEL); } -/* submit single-page bio request */ -reiser4_internal int -page_io(struct page *page /* page to perform io for */ , - jnode * node /* jnode of page */ , - int rw /* read or write */ , int gfp /* GFP mask */ ) +/** + * page_io - submit single-page bio request + * @page: page to perform io for + * @node: jnode of page + * @rw: read or write + * @gfp: gfp mask for bio allocation + * + * Submits single page read or write. + */ +int page_io(struct page *page, jnode *node, int rw, int gfp) { struct bio *bio; int result; @@ -405,8 +408,8 @@ page_io(struct page *page /* page to per } /* helper function to construct bio for page */ -static struct bio * -page_bio(struct page *page, jnode * node, int rw, int gfp) +static struct bio *page_bio(struct page *page, jnode * node, int rw, + unsigned int gfp) { struct bio *bio; assert("nikita-2092", page != NULL); @@ -416,7 +419,7 @@ page_bio(struct page *page, jnode * node We only have to submit one block, but submit_bh() will allocate bio anyway, so lets use all the bells-and-whistles of bio code. - */ + */ bio = bio_alloc(gfp, 1); if (bio != NULL) { @@ -427,7 +430,7 @@ page_bio(struct page *page, jnode * node super = page->mapping->host->i_sb; assert("nikita-2029", super != NULL); blksz = super->s_blocksize; - assert("nikita-2028", blksz == (int) PAGE_CACHE_SIZE); + assert("nikita-2028", blksz == (int)PAGE_CACHE_SIZE); blocknr = *UNDER_SPIN(jnode, node, jnode_get_io_block(node)); @@ -448,16 +451,15 @@ page_bio(struct page *page, jnode * node /* bio -> bi_idx is filled by bio_init() */ bio->bi_end_io = (rw == READ) ? - end_bio_single_page_read : end_bio_single_page_write; + end_bio_single_page_read : end_bio_single_page_write; return bio; } else return ERR_PTR(RETERR(-ENOMEM)); } - /* this function is internally called by jnode_make_dirty() */ -int set_page_dirty_internal (struct page * page, int tag_as_moved) +int set_page_dirty_internal(struct page *page, int tag_as_moved) { struct address_space *mapping; @@ -468,53 +470,55 @@ int set_page_dirty_internal (struct page if (mapping_cap_account_dirty(mapping)) inc_page_state(nr_dirty); - write_lock_irq(&mapping->tree_lock); - BUG_ON(page->mapping != mapping); - if (tag_as_moved) { - /* write_page_by_ent wants to set this bit on. FIXME: - * MOVED bit must be set already */ - assert("vs-1731", REISER4_USE_ENTD); - radix_tree_tag_set( - &mapping->page_tree, page->index, - PAGECACHE_TAG_REISER4_MOVED); - } else { - radix_tree_tag_clear( - &mapping->page_tree, page->index, - PAGECACHE_TAG_REISER4_MOVED); - } - write_unlock_irq(&mapping->tree_lock); __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); } return 0; } +static int can_hit_entd(reiser4_context * ctx, struct super_block *s) +{ + if (get_super_private(s)->entd.tsk == current) + return 0; + if (ctx == NULL || ((unsigned long)ctx->magic) != context_magic) + return 1; + if (ctx->super != s) + return 1; + return 0; +} +/** + * reiser4_writepage - + * @page: page to write + * @wbc: + */ /* Common memory pressure notification. */ -reiser4_internal int -reiser4_writepage(struct page *page /* page to start writeback from */, - struct writeback_control *wbc) +int reiser4_writepage(struct page *page /* page to start writeback from */ , + struct writeback_control *wbc) { struct super_block *s; - reiser4_context ctx; + reiser4_context *ctx; reiser4_tree *tree; - txn_atom * atom; + txn_atom *atom; jnode *node; int result; - s = page->mapping->host->i_sb; - init_context(&ctx, s); - assert("vs-828", PageLocked(page)); -#if REISER4_USE_ENTD + s = page->mapping->host->i_sb; + ctx = get_current_context_check(); - /* Throttle memory allocations if we were not in reiser4 */ - if (ctx.parent == &ctx) { - write_page_by_ent(page, wbc); - result = 1; - goto out; +#if REISER4_USE_ENTD + if (can_hit_entd(ctx, s) || + (ctx && lock_stack_isclean(get_current_lock_stack()) && + ctx->trans->atom == NULL && ctx->entd == 0)) { + /* Throttle memory allocations if we were not in reiser4 or if + lock stack is clean and atom is not opened */ + return write_page_by_ent(page, wbc); } -#endif /* REISER4_USE_ENTD */ +#endif /* REISER4_USE_ENTD */ + + BUG_ON(ctx == NULL); + BUG_ON(s != ctx->super); tree = &get_super_private(s)->tree; node = jnode_of_page(page); @@ -557,20 +561,27 @@ reiser4_writepage(struct page *page /* p set_page_dirty_internal(page, 0); unlock_page(page); } - out: - reiser4_exit_context(&ctx); return result; } /* ->set_page_dirty() method of formatted address_space */ -static int -formatted_set_page_dirty(struct page *page /* page to mark - * dirty */ ) +static int formatted_set_page_dirty(struct page *page) { assert("nikita-2173", page != NULL); return __set_page_dirty_nobuffers(page); } +/* writepages method of address space operations in reiser4 is used to involve + into transactions pages which are dirtied via mmap. Only regular files can + have such pages. Fake inode is used to access formatted nodes via page + cache. As formatted nodes can never be mmaped, fake inode's writepages has + nothing to do */ +static int +writepages_fake(struct address_space *mapping, struct writeback_control *wbc) +{ + return 0; +} + /* address space operations for the fake inode */ static struct address_space_operations formatted_fake_as_ops = { /* Perform a writeback of a single page as a memory-freeing @@ -584,11 +595,11 @@ static struct address_space_operations f This is most annoyingly misnomered method. Actually it is called from wait_on_page_bit() and lock_page() and its purpose is to actually start io by jabbing device drivers. - */ - .sync_page = reiser4_start_up_io, + */ + .sync_page = block_sync_page, /* Write back some dirty pages from this mapping. Called from sync. called during sync (pdflush) */ - .writepages = reiser4_writepages, + .writepages = writepages_fake, /* Set a page dirty */ .set_page_dirty = formatted_set_page_dirty, /* used for read-ahead. Not applicable */ @@ -603,15 +614,14 @@ static struct address_space_operations f /* this is called by shrink_cache() so that file system can try to release objects (jnodes, buffers, journal heads) attached to page and, may be made page itself free-able. - */ + */ .releasepage = reiser4_releasepage, .direct_IO = NULL }; /* called just before page is released (no longer used by reiser4). Callers: jdelete() and extent2tail(). */ -reiser4_internal void -drop_page(struct page *page) +void drop_page(struct page *page) { assert("nikita-2181", PageLocked(page)); clear_page_dirty(page); @@ -627,14 +637,12 @@ drop_page(struct page *page) unlock_page(page); } - /* this is called by truncate_jnodes_range which in its turn is always called after truncate_mapping_pages_range. Therefore, here jnode can not have page. New pages can not be created because truncate_jnodes_range goes under exclusive access on file obtained, where as new page creation requires non-exclusive access obtained */ -static void -invalidate_unformatted(jnode *node) +static void invalidate_unformatted(jnode * node) { struct page *page; @@ -646,7 +654,7 @@ invalidate_unformatted(jnode *node) page_cache_get(page); UNLOCK_JNODE(node); /* FIXME: use truncate_complete_page instead */ - from = (loff_t)page->index << PAGE_CACHE_SHIFT; + from = (loff_t) page->index << PAGE_CACHE_SHIFT; to = from + PAGE_CACHE_SIZE - 1; truncate_inode_pages_range(page->mapping, from, to); page_cache_release(page); @@ -675,19 +683,21 @@ truncate_jnodes_range(struct inode *inod tree = tree_by_inode(inode); index = from; - end = from + count; + end = from + count; while (1) { jnode *gang[JNODE_GANG_SIZE]; - int taken; - int i; + int taken; + int i; jnode *node; assert("nikita-3466", index <= end); RLOCK_TREE(tree); - taken = radix_tree_gang_lookup(jnode_tree_by_reiser4_inode(info), (void **)gang, - index, JNODE_GANG_SIZE); + taken = + radix_tree_gang_lookup(jnode_tree_by_reiser4_inode(info), + (void **)gang, index, + JNODE_GANG_SIZE); for (i = 0; i < taken; ++i) { node = gang[i]; if (index_jnode(node) < end) @@ -702,7 +712,7 @@ truncate_jnodes_range(struct inode *inod if (node != NULL) { index = max(index, index_jnode(node)); invalidate_unformatted(node); - truncated_jnodes ++; + truncated_jnodes++; jput(node); } else break; @@ -713,7 +723,7 @@ truncate_jnodes_range(struct inode *inod return truncated_jnodes; } -reiser4_internal void +void reiser4_invalidate_pages(struct address_space *mapping, pgoff_t from, unsigned long count, int even_cows) { @@ -721,42 +731,39 @@ reiser4_invalidate_pages(struct address_ if (count == 0) return; - from_bytes = ((loff_t)from) << PAGE_CACHE_SHIFT; - count_bytes = ((loff_t)count) << PAGE_CACHE_SHIFT; + from_bytes = ((loff_t) from) << PAGE_CACHE_SHIFT; + count_bytes = ((loff_t) count) << PAGE_CACHE_SHIFT; unmap_mapping_range(mapping, from_bytes, count_bytes, even_cows); - truncate_inode_pages_range(mapping, from_bytes, from_bytes + count_bytes - 1); + truncate_inode_pages_range(mapping, from_bytes, + from_bytes + count_bytes - 1); truncate_jnodes_range(mapping->host, from, count); } - #if REISER4_DEBUG #define page_flag_name( page, flag ) \ ( test_bit( ( flag ), &( page ) -> flags ) ? ((#flag "|")+3) : "" ) -reiser4_internal void -print_page(const char *prefix, struct page *page) +void print_page(const char *prefix, struct page *page) { if (page == NULL) { printk("null page\n"); return; } printk("%s: page index: %lu mapping: %p count: %i private: %lx\n", - prefix, page->index, page->mapping, page_count(page), page->private); + prefix, page->index, page->mapping, page_count(page), + page->private); printk("\tflags: %s%s%s%s %s%s%s %s%s%s %s%s\n", - page_flag_name(page, PG_locked), - page_flag_name(page, PG_error), - page_flag_name(page, PG_referenced), - page_flag_name(page, PG_uptodate), - - page_flag_name(page, PG_dirty), - page_flag_name(page, PG_lru), - page_flag_name(page, PG_slab), - - page_flag_name(page, PG_checked), - page_flag_name(page, PG_reserved), - page_flag_name(page, PG_private), page_flag_name(page, PG_writeback), page_flag_name(page, PG_nosave)); + page_flag_name(page, PG_locked), page_flag_name(page, PG_error), + page_flag_name(page, PG_referenced), page_flag_name(page, + PG_uptodate), + page_flag_name(page, PG_dirty), page_flag_name(page, PG_lru), + page_flag_name(page, PG_slab), page_flag_name(page, PG_checked), + page_flag_name(page, PG_reserved), page_flag_name(page, + PG_private), + page_flag_name(page, PG_writeback), page_flag_name(page, + PG_nosave)); if (jprivate(page) != NULL) { print_jnode("\tpage jnode", jprivate(page)); printk("\n"); @@ -765,13 +772,14 @@ print_page(const char *prefix, struct pa #endif -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - scroll-step: 1 - End: -*/ + +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 120 + * scroll-step: 1 + * End: + */ diff -puN fs/reiser4/page_cache.h~reiser4-big-update fs/reiser4/page_cache.h --- devel/fs/reiser4/page_cache.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/page_cache.h 2005-09-15 19:51:08.000000000 -0700 @@ -12,32 +12,32 @@ #include /* for struct page */ #include /* for lock_page() */ -extern int init_fakes(void); -extern int init_formatted_fake(struct super_block *super); -extern int done_formatted_fake(struct super_block *super); + +extern int init_formatted_fake(struct super_block *); +extern void done_formatted_fake(struct super_block *); extern reiser4_tree *tree_by_page(const struct page *page); -extern int set_page_dirty_internal (struct page * page, int tag_as_moved); +extern int set_page_dirty_internal(struct page *page, int tag_as_moved); #define reiser4_submit_bio(rw, bio) submit_bio((rw), (bio)) -extern void reiser4_wait_page_writeback (struct page * page); -static inline void lock_and_wait_page_writeback (struct page * page) +extern void reiser4_wait_page_writeback(struct page *page); +static inline void lock_and_wait_page_writeback(struct page *page) { lock_page(page); if (unlikely(PageWriteback(page))) - reiser4_wait_page_writeback(page); + reiser4_wait_page_writeback(page); } #define jprivate(page) ((jnode *) (page)->private) extern int page_io(struct page *page, jnode * node, int rw, int gfp); -extern int reiser4_writepage(struct page *page, struct writeback_control *wbc); extern void drop_page(struct page *page); extern void reiser4_invalidate_pages(struct address_space *, pgoff_t from, unsigned long count, int even_cows); -extern void capture_reiser4_inodes (struct super_block *, struct writeback_control *); +extern void capture_reiser4_inodes(struct super_block *, + struct writeback_control *); #define PAGECACHE_TAG_REISER4_MOVED PAGECACHE_TAG_DIRTY diff -puN fs/reiser4/plugin/compress/compress.c~reiser4-big-update fs/reiser4/plugin/compress/compress.c --- devel/fs/reiser4/plugin/compress/compress.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/compress/compress.c 2005-09-15 19:51:08.000000000 -0700 @@ -4,7 +4,6 @@ #include "../../debug.h" #include "../../inode.h" #include "../plugin.h" -#include "../cryptcompress.h" #include "minilzo.h" #include @@ -12,13 +11,13 @@ #include #include -static int -change_compression(struct inode * inode, reiser4_plugin * plugin) +static int change_compression(struct inode *inode, reiser4_plugin * plugin) { assert("edward-1316", inode != NULL); assert("edward-1317", plugin != NULL); assert("edward-1318", is_reiser4_inode(inode)); - assert("edward-1319", plugin->h.type_id == REISER4_COMPRESSION_PLUGIN_TYPE); + assert("edward-1319", + plugin->h.type_id == REISER4_COMPRESSION_PLUGIN_TYPE); if (inode_file_plugin(inode)->h.id != DIRECTORY_FILE_PLUGIN_ID) if (inode_compression_plugin(inode) != @@ -29,11 +28,11 @@ change_compression(struct inode * inode, } static reiser4_plugin_ops compression_plugin_ops = { - .init = NULL, - .load = NULL, + .init = NULL, + .load = NULL, .save_len = NULL, - .save = NULL, - .change = &change_compression + .save = NULL, + .change = &change_compression }; /******************************************************************************/ @@ -44,15 +43,24 @@ static reiser4_plugin_ops compression_pl #define GZIP1_DEF_WINBITS 15 #define GZIP1_DEF_MEMLEVEL MAX_MEM_LEVEL +static int gzip1_init(void) +{ + int ret = -ENOSYS; +#if defined(REISER4_GZIP_TFM) + ret = 0; +#endif + return ret; +} + static int gzip1_overrun(unsigned src_len UNUSED_ARG) { return 0; } -static coa_t -gzip1_alloc(tfm_action act) +static coa_t gzip1_alloc(tfm_action act) { coa_t coa = NULL; +#if defined(REISER4_GZIP_TFM) int ret = 0; switch (act) { case TFM_WRITE: /* compress */ @@ -63,7 +71,7 @@ gzip1_alloc(tfm_action act) } memset(coa, 0, zlib_deflate_workspacesize()); break; - case TFM_READ: /* decompress */ + case TFM_READ: /* decompress */ coa = vmalloc(zlib_inflate_workspacesize()); if (!coa) { ret = -ENOMEM; @@ -81,18 +89,19 @@ gzip1_alloc(tfm_action act) act); return ERR_PTR(ret); } +#endif return coa; } -static coa_t -gzip1_nocompress_alloc(tfm_action act) +static coa_t gzip1_nocompress_alloc(tfm_action act) { coa_t coa = NULL; +#if defined(REISER4_GZIP_TFM) int ret = 0; switch (act) { case TFM_WRITE: /* compress */ break; - case TFM_READ: /* decompress */ + case TFM_READ: /* decompress */ coa = vmalloc(zlib_inflate_workspacesize()); if (!coa) { ret = -ENOMEM; @@ -109,6 +118,7 @@ gzip1_nocompress_alloc(tfm_action act) act); return ERR_PTR(ret); } +#endif return coa; } @@ -120,7 +130,7 @@ static void gzip1_free(coa_t coa, tfm_ac case TFM_WRITE: /* compress */ vfree(coa); break; - case TFM_READ: /* decompress */ + case TFM_READ: /* decompress */ vfree(coa); break; default: @@ -134,7 +144,7 @@ static void gzip1_nocompress_free(coa_t assert("edward-1301", coa != NULL); switch (act) { - case TFM_READ: /* decompress */ + case TFM_READ: /* decompress */ vfree(coa); case TFM_WRITE: /* compress */ impossible("edward-1302", @@ -145,8 +155,7 @@ static void gzip1_nocompress_free(coa_t return; } -static int -gzip1_min_size_deflate(void) +static int gzip1_min_size_deflate(void) { return 64; } @@ -188,7 +197,7 @@ gzip1_compress(coa_t coa, __u8 * src_fir } *dst_len = stream.total_out; return; - rollback: + rollback: *dst_len = src_len; return; } @@ -254,8 +263,7 @@ static int lzo1_overrun(unsigned in_len) #define LZO_HEAP_SIZE(size) \ sizeof(lzo_align_t) * (((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t)) -static coa_t -lzo1_alloc(tfm_action act) +static coa_t lzo1_alloc(tfm_action act) { int ret = 0; coa_t coa = NULL; @@ -268,7 +276,7 @@ lzo1_alloc(tfm_action act) break; } memset(coa, 0, LZO_HEAP_SIZE(LZO1X_1_MEM_COMPRESS)); - case TFM_READ: /* decompress */ + case TFM_READ: /* decompress */ break; default: impossible("edward-877", @@ -283,8 +291,7 @@ lzo1_alloc(tfm_action act) return coa; } -static void -lzo1_free(coa_t coa, tfm_action act) +static void lzo1_free(coa_t coa, tfm_action act) { assert("edward-879", coa != NULL); @@ -292,7 +299,7 @@ lzo1_free(coa_t coa, tfm_action act) case TFM_WRITE: /* compress */ vfree(coa); break; - case TFM_READ: /* decompress */ + case TFM_READ: /* decompress */ impossible("edward-1304", "trying to free non-allocated workspace"); default: @@ -301,8 +308,7 @@ lzo1_free(coa_t coa, tfm_action act) return; } -static int -lzo1_min_size_deflate(void) +static int lzo1_min_size_deflate(void) { return 256; } @@ -323,8 +329,7 @@ lzo1_compress(coa_t coa, __u8 * src_firs goto out; } - result = - lzo1x_1_compress(src_first, src_len, dst_first, dst_len, coa); + result = lzo1x_1_compress(src_first, src_len, dst_first, dst_len, coa); if (result != LZO_E_OK) { warning("edward-849", "lzo1x_1_compress failed\n"); goto out; @@ -334,7 +339,7 @@ lzo1_compress(coa_t coa, __u8 * src_firs goto out; } return; - out: + out: *dst_len = src_len; return; } @@ -363,104 +368,100 @@ lzo1_decompress(coa_t coa, __u8 * src_fi compression_plugin compression_plugins[LAST_COMPRESSION_ID] = { [LZO1_COMPRESSION_ID] = { - .h = { - .type_id = - REISER4_COMPRESSION_PLUGIN_TYPE, - .id = LZO1_COMPRESSION_ID, - .pops = &compression_plugin_ops, - .label = "lzo1", - .desc = "lzo1 compression transform", - .linkage = TYPE_SAFE_LIST_LINK_ZERO} - , - .dual = LZO1_NO_COMPRESSION_ID, - .init = NULL, - .overrun = lzo1_overrun, - .alloc = lzo1_alloc, - .free = lzo1_free, - .min_size_deflate = lzo1_min_size_deflate, - .checksum = reiser4_adler32, - .compress = lzo1_compress, - .decompress = lzo1_decompress} - , + .h = { + .type_id = REISER4_COMPRESSION_PLUGIN_TYPE, + .id = LZO1_COMPRESSION_ID, + .pops = &compression_plugin_ops, + .label = "lzo1", + .desc = "lzo1 compression transform", + .linkage = {NULL, NULL} + }, + .dual = LZO1_NO_COMPRESSION_ID, + .init = NULL, + .overrun = lzo1_overrun, + .alloc = lzo1_alloc, + .free = lzo1_free, + .min_size_deflate = lzo1_min_size_deflate, + .checksum = reiser4_adler32, + .compress = lzo1_compress, + .decompress = lzo1_decompress + }, [LZO1_NO_COMPRESSION_ID] = { - .h = { - .type_id = - REISER4_COMPRESSION_PLUGIN_TYPE, - .id = LZO1_NO_COMPRESSION_ID, - .pops = &compression_plugin_ops, - .label = "lzo1_no", - .desc = "lzo1 no compression transform", - .linkage = TYPE_SAFE_LIST_LINK_ZERO} - , - .dual = LZO1_COMPRESSION_ID, - .init = NULL, - .overrun = NULL, - .alloc = NULL, - .free = NULL, - .min_size_deflate = NULL, - .checksum = reiser4_adler32, - .compress = NULL, - .decompress = lzo1_decompress} - , + .h = { + .type_id = REISER4_COMPRESSION_PLUGIN_TYPE, + .id = LZO1_NO_COMPRESSION_ID, + .pops = &compression_plugin_ops, + .label = "lzo1_no", + .desc = "lzo1 no compression transform", + .linkage = {NULL, NULL} + }, + .dual = LZO1_COMPRESSION_ID, + .init = NULL, + .overrun = NULL, + .alloc = NULL, + .free = NULL, + .min_size_deflate = NULL, + .checksum = reiser4_adler32, + .compress = NULL, + .decompress = lzo1_decompress + }, [GZIP1_COMPRESSION_ID] = { - .h = { - .type_id = - REISER4_COMPRESSION_PLUGIN_TYPE, - .id = GZIP1_COMPRESSION_ID, - .pops = &compression_plugin_ops, - .label = "gzip1", - .desc = "gzip1 compression transform", - .linkage = TYPE_SAFE_LIST_LINK_ZERO} - , - .dual = GZIP1_NO_COMPRESSION_ID, - .init = NULL, - .overrun = gzip1_overrun, - .alloc = gzip1_alloc, - .free = gzip1_free, - .min_size_deflate = gzip1_min_size_deflate, - .checksum = NULL, - .compress = gzip1_compress, - .decompress = gzip1_decompress} - , + .h = { + .type_id = REISER4_COMPRESSION_PLUGIN_TYPE, + .id = GZIP1_COMPRESSION_ID, + .pops = &compression_plugin_ops, + .label = "gzip1", + .desc = "gzip1 compression transform", + .linkage = {NULL, NULL} + }, + .dual = GZIP1_NO_COMPRESSION_ID, + .init = gzip1_init, + .overrun = gzip1_overrun, + .alloc = gzip1_alloc, + .free = gzip1_free, + .min_size_deflate = gzip1_min_size_deflate, + .checksum = NULL, + .compress = gzip1_compress, + .decompress = gzip1_decompress + }, [GZIP1_NO_COMPRESSION_ID] = { - .h = { - .type_id = - REISER4_COMPRESSION_PLUGIN_TYPE, - .id = GZIP1_NO_COMPRESSION_ID, - .pops = &compression_plugin_ops, - .label = "gzip1_no", - .desc = "gzip1 no compression transform", - .linkage = TYPE_SAFE_LIST_LINK_ZERO} - , - .dual = GZIP1_COMPRESSION_ID, - .init = NULL, - .overrun = NULL, - .alloc = gzip1_nocompress_alloc, - .free = gzip1_nocompress_free, - .min_size_deflate = NULL, - .checksum = NULL, - .compress = NULL, - .decompress = gzip1_decompress} - , + .h = { + .type_id = REISER4_COMPRESSION_PLUGIN_TYPE, + .id = GZIP1_NO_COMPRESSION_ID, + .pops = &compression_plugin_ops, + .label = "gzip1_no", + .desc = "gzip1 no compression transform", + .linkage = {NULL, NULL} + }, + .dual = GZIP1_COMPRESSION_ID, + .init = gzip1_init, + .overrun = NULL, + .alloc = gzip1_nocompress_alloc, + .free = gzip1_nocompress_free, + .min_size_deflate = NULL, + .checksum = NULL, + .compress = NULL, + .decompress = gzip1_decompress + }, [NONE_COMPRESSION_ID] = { - .h = { - .type_id = - REISER4_COMPRESSION_PLUGIN_TYPE, - .id = NONE_COMPRESSION_ID, - .pops = &compression_plugin_ops, - .label = "none", - .desc = "No compression transform", - .linkage = TYPE_SAFE_LIST_LINK_ZERO} - , - .dual = NONE_COMPRESSION_ID, - .init = NULL, - .overrun = NULL, - .alloc = NULL, - .free = NULL, - .min_size_deflate = NULL, - .checksum = NULL, - .compress = NULL, - .decompress = NULL} + .h = { + .type_id = REISER4_COMPRESSION_PLUGIN_TYPE, + .id = NONE_COMPRESSION_ID, + .pops = &compression_plugin_ops, + .label = "none", + .desc = "No compression transform", + .linkage = {NULL, NULL} + }, + .dual = NONE_COMPRESSION_ID, + .init = NULL, + .overrun = NULL, + .alloc = NULL, + .free = NULL, + .min_size_deflate = NULL, + .checksum = NULL, + .compress = NULL, + .decompress = NULL + } }; /* diff -puN fs/reiser4/plugin/compress/compress.h~reiser4-big-update fs/reiser4/plugin/compress/compress.h --- devel/fs/reiser4/plugin/compress/compress.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/compress/compress.h 2005-09-15 19:51:08.000000000 -0700 @@ -21,12 +21,12 @@ typedef enum { } reiser4_compression_id; typedef unsigned long cloff_t; -typedef void * coa_t; +typedef void *coa_t; typedef coa_t coa_set[LAST_COMPRESSION_ID]; -__u32 reiser4_adler32(char * data, __u32 len); +__u32 reiser4_adler32(char *data, __u32 len); -#endif /* __FS_REISER4_COMPRESS_H__ */ +#endif /* __FS_REISER4_COMPRESS_H__ */ /* Make Linus happy. Local variables: diff -puN fs/reiser4/plugin/compress/compress_mode.c~reiser4-big-update fs/reiser4/plugin/compress/compress_mode.c --- devel/fs/reiser4/plugin/compress/compress_mode.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/compress/compress_mode.c 2005-09-15 19:51:08.000000000 -0700 @@ -4,19 +4,16 @@ #include "../../inode.h" #include "../plugin.h" -#include "../cryptcompress.h" /* plugin->should_deflate() */ -static int -should_deflate_test(cloff_t index) +static int should_deflate_test(cloff_t index) { return !test_bit(0, &index); } /* plugin->discard_deflate() */ -static int -discard_deflate_nocond(struct inode * inode, cloff_t index) +static int discard_deflate_nocond(struct inode *inode, cloff_t index) { int result; @@ -31,8 +28,7 @@ discard_deflate_nocond(struct inode * in return 0; } -static int -discard_deflate_first(struct inode * inode, cloff_t index) +static int discard_deflate_first(struct inode *inode, cloff_t index) { assert("edward-1308", inode != NULL); @@ -48,7 +44,7 @@ compression_mode_plugin compression_mode .pops = NULL, .label = "if-0-compressible", .desc = "If-first-cluster-compressible heuristic", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .should_deflate = NULL, .save_deflate = NULL, @@ -61,7 +57,7 @@ compression_mode_plugin compression_mode .pops = NULL, .label = "if-all-compressible", .desc = "If-all-compressible heuristic", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .should_deflate = NULL, .save_deflate = NULL, @@ -74,7 +70,7 @@ compression_mode_plugin compression_mode .pops = NULL, .label = "force", .desc = "Compress everything", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .should_deflate = NULL, .save_deflate = NULL, @@ -85,9 +81,9 @@ compression_mode_plugin compression_mode .type_id = REISER4_COMPRESSION_MODE_PLUGIN_TYPE, .id = TEST_COMPRESSION_MODE_ID, .pops = NULL, - .label = "test", /* This mode is only for benchmarks */ + .label = "test", /* This mode is only for benchmarks */ .desc = "Don't compress odd clusters", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .should_deflate = should_deflate_test, .save_deflate = NULL, @@ -95,7 +91,6 @@ compression_mode_plugin compression_mode } }; - /* Local variables: c-indentation-style: "K&R" diff -puN fs/reiser4/plugin/compress/lzoconf.h~reiser4-big-update fs/reiser4/plugin/compress/lzoconf.h --- devel/fs/reiser4/plugin/compress/lzoconf.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/compress/lzoconf.h 2005-09-15 19:51:08.000000000 -0700 @@ -33,7 +33,7 @@ http://www.oberhumer.com/opensource/lzo/ */ -#include /* for UINT_MAX, ULONG_MAX - edward */ +#include /* for UINT_MAX, ULONG_MAX - edward */ #ifndef __LZOCONF_H #define __LZOCONF_H @@ -50,38 +50,16 @@ extern "C" { #endif - /*********************************************************************** // LZO requires a conforming ************************************************************************/ -#define CHAR_BIT 8 /* -edward */ -#define USHRT_MAX 0xffff /* -edward */ +#define CHAR_BIT 8 +#define USHRT_MAX 0xffff -#if 0 /* -edward */ -#if !defined(CHAR_BIT) || (CHAR_BIT != 8) -# error "invalid CHAR_BIT" -#endif -#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) -# error "check your compiler installation" -#endif -#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) -# error "your limits.h macros are broken" -#endif -#endif /* -edward */ /* workaround a cpp bug under hpux 10.20 */ #define LZO_0xffffffffL 4294967295ul -#if 0 /* -edward */ -#if !defined(LZO_UINT32_C) -# if (UINT_MAX < LZO_0xffffffffL) -# define LZO_UINT32_C(c) c ## UL -# else -# define LZO_UINT32_C(c) c ## U -# endif -#endif -#endif /* -edward */ - /*********************************************************************** // architecture defines ************************************************************************/ @@ -115,8 +93,8 @@ extern "C" { # define __LZO_TOS16 # elif defined(__C166__) # else - /* porting hint: for pure 16-bit architectures try compiling - * everything with -D__LZO_STRICT_16BIT */ + /* porting hint: for pure 16-bit architectures try compiling + * everything with -D__LZO_STRICT_16BIT */ # error "16-bit target not supported - contact me for porting hints" # endif #endif @@ -148,7 +126,6 @@ extern "C" { # endif #endif - /*********************************************************************** // integral and pointer types ************************************************************************/ @@ -156,14 +133,14 @@ extern "C" { /* Integral types with 32 bits or more */ #if !defined(LZO_UINT32_MAX) # if (UINT_MAX >= LZO_0xffffffffL) - typedef unsigned int lzo_uint32; - typedef int lzo_int32; + typedef unsigned int lzo_uint32; + typedef int lzo_int32; # define LZO_UINT32_MAX UINT_MAX # define LZO_INT32_MAX INT_MAX # define LZO_INT32_MIN INT_MIN # elif (ULONG_MAX >= LZO_0xffffffffL) - typedef unsigned long lzo_uint32; - typedef long lzo_int32; + typedef unsigned long lzo_uint32; + typedef long lzo_int32; # define LZO_UINT32_MAX ULONG_MAX # define LZO_INT32_MAX LONG_MAX # define LZO_INT32_MIN LONG_MIN @@ -175,14 +152,14 @@ extern "C" { /* lzo_uint is used like size_t */ #if !defined(LZO_UINT_MAX) # if (UINT_MAX >= LZO_0xffffffffL) - typedef unsigned int lzo_uint; - typedef int lzo_int; + typedef unsigned int lzo_uint; + typedef int lzo_int; # define LZO_UINT_MAX UINT_MAX # define LZO_INT_MAX INT_MAX # define LZO_INT_MIN INT_MIN # elif (ULONG_MAX >= LZO_0xffffffffL) - typedef unsigned long lzo_uint; - typedef long lzo_int; + typedef unsigned long lzo_uint; + typedef long lzo_int; # define LZO_UINT_MAX ULONG_MAX # define LZO_INT_MAX LONG_MAX # define LZO_INT_MIN LONG_MIN @@ -191,8 +168,7 @@ extern "C" { # endif #endif -typedef int lzo_bool; - + typedef int lzo_bool; /*********************************************************************** // memory models @@ -252,7 +228,6 @@ typedef int lzo_bool; # define lzo_sizeof_dict_t sizeof(lzo_bytep) #endif - /*********************************************************************** // calling conventions and function types ************************************************************************/ @@ -290,50 +265,54 @@ typedef int lzo_bool; # define LZO_NOTHROW #endif - -typedef int -(__LZO_ENTRY *lzo_compress_t) ( const lzo_byte *src, lzo_uint src_len, - lzo_byte *dst, lzo_uintp dst_len, - lzo_voidp wrkmem ); - -typedef int -(__LZO_ENTRY *lzo_decompress_t) ( const lzo_byte *src, lzo_uint src_len, - lzo_byte *dst, lzo_uintp dst_len, - lzo_voidp wrkmem ); - -typedef int -(__LZO_ENTRY *lzo_optimize_t) ( lzo_byte *src, lzo_uint src_len, - lzo_byte *dst, lzo_uintp dst_len, - lzo_voidp wrkmem ); - -typedef int -(__LZO_ENTRY *lzo_compress_dict_t)(const lzo_byte *src, lzo_uint src_len, - lzo_byte *dst, lzo_uintp dst_len, - lzo_voidp wrkmem, - const lzo_byte *dict, lzo_uint dict_len ); - -typedef int -(__LZO_ENTRY *lzo_decompress_dict_t)(const lzo_byte *src, lzo_uint src_len, - lzo_byte *dst, lzo_uintp dst_len, - lzo_voidp wrkmem, - const lzo_byte *dict, lzo_uint dict_len ); - + typedef int + (__LZO_ENTRY * lzo_compress_t) (const lzo_byte * src, lzo_uint src_len, + lzo_byte * dst, lzo_uintp dst_len, + lzo_voidp wrkmem); + + typedef int + (__LZO_ENTRY * lzo_decompress_t) (const lzo_byte * src, + lzo_uint src_len, lzo_byte * dst, + lzo_uintp dst_len, lzo_voidp wrkmem); + + typedef int + (__LZO_ENTRY * lzo_optimize_t) (lzo_byte * src, lzo_uint src_len, + lzo_byte * dst, lzo_uintp dst_len, + lzo_voidp wrkmem); + + typedef int + (__LZO_ENTRY * lzo_compress_dict_t) (const lzo_byte * src, + lzo_uint src_len, lzo_byte * dst, + lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_byte * dict, + lzo_uint dict_len); + + typedef int + (__LZO_ENTRY * lzo_decompress_dict_t) (const lzo_byte * src, + lzo_uint src_len, + lzo_byte * dst, + lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_byte * dict, + lzo_uint dict_len); /* assembler versions always use __cdecl */ -typedef int -(__LZO_CDECL *lzo_compress_asm_t)( const lzo_byte *src, lzo_uint src_len, - lzo_byte *dst, lzo_uintp dst_len, - lzo_voidp wrkmem ); - -typedef int -(__LZO_CDECL *lzo_decompress_asm_t)( const lzo_byte *src, lzo_uint src_len, - lzo_byte *dst, lzo_uintp dst_len, - lzo_voidp wrkmem ); - + typedef int + (__LZO_CDECL * lzo_compress_asm_t) (const lzo_byte * src, + lzo_uint src_len, lzo_byte * dst, + lzo_uintp dst_len, + lzo_voidp wrkmem); + + typedef int + (__LZO_CDECL * lzo_decompress_asm_t) (const lzo_byte * src, + lzo_uint src_len, lzo_byte * dst, + lzo_uintp dst_len, + lzo_voidp wrkmem); /* a progress indicator callback function */ -typedef void (__LZO_ENTRY *lzo_progress_callback_t) (lzo_uint, lzo_uint); - + typedef void (__LZO_ENTRY * lzo_progress_callback_t) (lzo_uint, + lzo_uint); /*********************************************************************** // export information @@ -378,7 +357,6 @@ typedef void (__LZO_ENTRY *lzo_progress_ # define LZO_EXTERN_VAR(_type) extern LZO_PUBLIC_VAR(_type) #endif - /*********************************************************************** // error codes and prototypes ************************************************************************/ @@ -389,15 +367,14 @@ typedef void (__LZO_ENTRY *lzo_progress_ */ #define LZO_E_OK 0 #define LZO_E_ERROR (-1) -#define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */ -#define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */ +#define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */ +#define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */ #define LZO_E_INPUT_OVERRUN (-4) #define LZO_E_OUTPUT_OVERRUN (-5) #define LZO_E_LOOKBEHIND_OVERRUN (-6) #define LZO_E_EOF_NOT_FOUND (-7) #define LZO_E_INPUT_NOT_CONSUMED (-8) - /* lzo_init() should be the first function you call. * Check the return code ! * @@ -408,16 +385,28 @@ typedef void (__LZO_ENTRY *lzo_progress_ (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\ (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ (int)sizeof(lzo_compress_t)) -LZO_EXTERN(int) __lzo_init2(unsigned,int,int,int,int,int,int,int,int,int); + LZO_EXTERN(int) __lzo_init2(unsigned, int, int, int, int, int, int, + int, int, int); /* checksum functions */ -LZO_EXTERN(lzo_uint32) -lzo_crc32(lzo_uint32 _c, const lzo_byte *_buf, lzo_uint _len); + LZO_EXTERN(lzo_uint32) + lzo_crc32(lzo_uint32 _c, const lzo_byte * _buf, lzo_uint _len); /* misc. */ -typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u; -typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u; -typedef union { void *vp; lzo_bytep bp; lzo_uint32 u32; long l; } lzo_align_t; + typedef union { + lzo_bytep p; + lzo_uint u; + } __lzo_pu_u; + typedef union { + lzo_bytep p; + lzo_uint32 u32; + } __lzo_pu32_u; + typedef union { + void *vp; + lzo_bytep bp; + lzo_uint32 u32; + long l; + } lzo_align_t; #define LZO_PTR_ALIGN_UP(_ptr,_size) \ ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size))) @@ -425,10 +414,7 @@ typedef union { void *vp; lzo_bytep bp; /* deprecated - only for backward compatibility */ #define LZO_ALIGN(_ptr,_size) LZO_PTR_ALIGN_UP(_ptr,_size) - #ifdef __cplusplus -} /* extern "C" */ +} /* extern "C" */ #endif - -#endif /* already included */ - +#endif /* already included */ diff -puN fs/reiser4/plugin/compress/minilzo.c~reiser4-big-update fs/reiser4/plugin/compress/minilzo.c --- devel/fs/reiser4/plugin/compress/minilzo.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/compress/minilzo.c 2005-09-15 19:51:08.000000000 -0700 @@ -39,7 +39,7 @@ * http://www.oberhumer.com/opensource/lzo/ */ -#include "../../debug.h" /* for reiser4 assert macro -edward */ +#include "../../debug.h" /* for reiser4 assert macro -edward */ #define __LZO_IN_MINILZO #define LZO_BUILD @@ -59,12 +59,6 @@ # define LZO_HAVE_CONFIG_H #endif -#if 0 /* -edward */ -#if !defined(LZO_NO_SYS_TYPES_H) -# include -#endif -#include -#endif /* -edward */ #ifndef __LZO_CONF_H #define __LZO_CONF_H @@ -82,30 +76,10 @@ # define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) #endif -#if 0 /* edward */ -#if !defined(LZO_HAVE_CONFIG_H) -# include -# include -# if !defined(NO_STDLIB_H) -# include -# endif -#endif /* edward */ # define HAVE_MEMCMP # define HAVE_MEMCPY # define HAVE_MEMMOVE # define HAVE_MEMSET -#if 0 /* edward */ -#else -# include -# if defined(HAVE_STDDEF_H) -# include -# endif -# if defined(STDC_HEADERS) -# include -# include -# endif -#endif -#endif /* edward */ #if defined(__LZO_DOS16) || defined(__LZO_WIN16) # define HAVE_MALLOC_H @@ -121,9 +95,9 @@ # include # endif #endif -# if 0 /* edward */ +# if 0 /* edward */ #include -#endif /* edward */ +#endif /* edward */ #if !defined(LZO_COMPILE_TIME_ASSERT) # define LZO_COMPILE_TIME_ASSERT(expr) \ @@ -157,11 +131,7 @@ # define memset lzo_memset #endif -#if 0 -# define LZO_BYTE(x) ((unsigned char) (x)) -#else # define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) -#endif #define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) #define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) @@ -301,22 +271,6 @@ __LZO_EXTERN_C const lzo_uint32 _lzo_crc #define _LZO_ECONCAT4(a,b,c,d) _LZO_CONCAT4(a,b,c,d) #define _LZO_ECONCAT5(a,b,c,d,e) _LZO_CONCAT5(a,b,c,d,e) -#if 0 - -#define __LZO_IS_COMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) -#define __LZO_QUERY_COMPRESS(i,il,o,ol,w,n,s) \ - (*ol = (n)*(s), LZO_E_OK) - -#define __LZO_IS_DECOMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) -#define __LZO_QUERY_DECOMPRESS(i,il,o,ol,w,n,s) \ - (*ol = (n)*(s), LZO_E_OK) - -#define __LZO_IS_OPTIMIZE_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) -#define __LZO_QUERY_OPTIMIZE(i,il,o,ol,w,n,s) \ - (*ol = (n)*(s), LZO_E_OK) - -#endif - #ifndef __LZO_PTR_H #define __LZO_PTR_H @@ -328,10 +282,10 @@ extern "C" { # include # if 1 && defined(__WATCOMC__) # include - __LZO_EXTERN_C unsigned char _HShift; + __LZO_EXTERN_C unsigned char _HShift; # define __LZO_HShift _HShift # elif 1 && defined(_MSC_VER) - __LZO_EXTERN_C unsigned short __near _AHSHIFT; + __LZO_EXTERN_C unsigned short __near _AHSHIFT; # define __LZO_HShift ((unsigned) &_AHSHIFT) # elif defined(__LZO_WIN16) # define __LZO_HShift 3 @@ -348,9 +302,9 @@ extern "C" { #if !defined(lzo_ptrdiff_t) # if (UINT_MAX >= LZO_0xffffffffL) - typedef ptrdiff_t lzo_ptrdiff_t; + typedef ptrdiff_t lzo_ptrdiff_t; # else - typedef long lzo_ptrdiff_t; + typedef long lzo_ptrdiff_t; # endif #endif @@ -362,8 +316,8 @@ extern "C" { #if !defined(__LZO_HAVE_PTR_T) # if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_LONG) # if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_LONG) - typedef unsigned long lzo_ptr_t; - typedef long lzo_sptr_t; + typedef unsigned long lzo_ptr_t; + typedef long lzo_sptr_t; # define __LZO_HAVE_PTR_T # endif # endif @@ -371,8 +325,8 @@ extern "C" { #if !defined(__LZO_HAVE_PTR_T) # if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED) # if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED) - typedef unsigned int lzo_ptr_t; - typedef int lzo_sptr_t; + typedef unsigned int lzo_ptr_t; + typedef int lzo_sptr_t; # define __LZO_HAVE_PTR_T # endif # endif @@ -380,8 +334,8 @@ extern "C" { #if !defined(__LZO_HAVE_PTR_T) # if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_SHORT) # if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_SHORT) - typedef unsigned short lzo_ptr_t; - typedef short lzo_sptr_t; + typedef unsigned short lzo_ptr_t; + typedef short lzo_sptr_t; # define __LZO_HAVE_PTR_T # endif # endif @@ -390,8 +344,8 @@ extern "C" { # if defined(LZO_HAVE_CONFIG_H) || defined(SIZEOF_CHAR_P) # error "no suitable type for lzo_ptr_t" # else - typedef unsigned long lzo_ptr_t; - typedef long lzo_sptr_t; + typedef unsigned long lzo_ptr_t; + typedef long lzo_sptr_t; # define __LZO_HAVE_PTR_T # endif #endif @@ -414,49 +368,43 @@ extern "C" { #define PTR_DIFF(a,b) ((lzo_ptrdiff_t) (PTR(a) - PTR(b))) #define pd(a,b) ((lzo_uint) ((a)-(b))) -typedef union -{ - char a_char; - unsigned char a_uchar; - short a_short; - unsigned short a_ushort; - int a_int; - unsigned int a_uint; - long a_long; - unsigned long a_ulong; - lzo_int a_lzo_int; - lzo_uint a_lzo_uint; - lzo_int32 a_lzo_int32; - lzo_uint32 a_lzo_uint32; - ptrdiff_t a_ptrdiff_t; - lzo_ptrdiff_t a_lzo_ptrdiff_t; - lzo_ptr_t a_lzo_ptr_t; - lzo_voidp a_lzo_voidp; - void * a_void_p; - lzo_bytep a_lzo_bytep; - lzo_bytepp a_lzo_bytepp; - lzo_uintp a_lzo_uintp; - lzo_uint * a_lzo_uint_p; - lzo_uint32p a_lzo_uint32p; - lzo_uint32 * a_lzo_uint32_p; - unsigned char * a_uchar_p; - char * a_char_p; -} -lzo_full_align_t; + typedef union { + char a_char; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long a_long; + unsigned long a_ulong; + lzo_int a_lzo_int; + lzo_uint a_lzo_uint; + lzo_int32 a_lzo_int32; + lzo_uint32 a_lzo_uint32; + ptrdiff_t a_ptrdiff_t; + lzo_ptrdiff_t a_lzo_ptrdiff_t; + lzo_ptr_t a_lzo_ptr_t; + lzo_voidp a_lzo_voidp; + void *a_void_p; + lzo_bytep a_lzo_bytep; + lzo_bytepp a_lzo_bytepp; + lzo_uintp a_lzo_uintp; + lzo_uint *a_lzo_uint_p; + lzo_uint32p a_lzo_uint32p; + lzo_uint32 *a_lzo_uint32_p; + unsigned char *a_uchar_p; + char *a_char_p; + } lzo_full_align_t; #ifdef __cplusplus } #endif - #endif - #define LZO_DETERMINISTIC - #define LZO_DICT_USE_PTR #if defined(__LZO_DOS16) || defined(__LZO_WIN16) || defined(__LZO_STRICT_16BIT) # undef LZO_DICT_USE_PTR #endif - #if defined(LZO_DICT_USE_PTR) # define lzo_dict_t const lzo_bytep # define lzo_dict_p lzo_dict_t __LZO_MMODEL * @@ -464,47 +412,38 @@ lzo_full_align_t; # define lzo_dict_t lzo_uint # define lzo_dict_p lzo_dict_t __LZO_MMODEL * #endif - #if !defined(lzo_moff_t) #define lzo_moff_t lzo_uint #endif - #endif - -static lzo_ptr_t -__lzo_ptr_linear(const lzo_voidp ptr) +static lzo_ptr_t __lzo_ptr_linear(const lzo_voidp ptr) { - lzo_ptr_t p; + lzo_ptr_t p; #if defined(__LZO_DOS16) || defined(__LZO_WIN16) - p = (((lzo_ptr_t)(_FP_SEG(ptr))) << (16 - __LZO_HShift)) + (_FP_OFF(ptr)); + p = (((lzo_ptr_t) (_FP_SEG(ptr))) << (16 - __LZO_HShift)) + + (_FP_OFF(ptr)); #else - p = PTR_LINEAR(ptr); + p = PTR_LINEAR(ptr); #endif - return p; + return p; } -static unsigned -__lzo_align_gap(const lzo_voidp ptr, lzo_uint size) +static unsigned __lzo_align_gap(const lzo_voidp ptr, lzo_uint size) { - lzo_ptr_t p, s, n; + lzo_ptr_t p, s, n; - assert("lzo-01", size > 0); + assert("lzo-01", size > 0); - p = __lzo_ptr_linear(ptr); - s = (lzo_ptr_t) (size - 1); -#if 0 - assert((size & (size - 1)) == 0); - n = ((p + s) & ~s) - p; -#else - n = (((p + s) / size) * size) - p; -#endif + p = __lzo_ptr_linear(ptr); + s = (lzo_ptr_t) (size - 1); + n = (((p + s) / size) * size) - p; - assert("lzo-02", (long)n >= 0); - assert("lzo-03", n <= s); + assert("lzo-02", (long)n >= 0); + assert("lzo-03", n <= s); - return (unsigned)n; + return (unsigned)n; } #ifndef __LZO_UTIL_H @@ -528,23 +467,6 @@ extern "C" { #endif #endif -#if 0 && !defined(MEMCPY8_DS) - -#define MEMCPY8_DS(dest,src,len) \ - { do { \ - *dest++ = *src++; \ - *dest++ = *src++; \ - *dest++ = *src++; \ - *dest++ = *src++; \ - *dest++ = *src++; \ - *dest++ = *src++; \ - *dest++ = *src++; \ - *dest++ = *src++; \ - len -= 8; \ - } while (len > 0); } - -#endif - #if !defined(MEMCPY8_DS) #define MEMCPY8_DS(dest,src,len) \ @@ -570,28 +492,10 @@ extern "C" { do *dest++ = *src++; \ while (--len > 0) -#if 0 && defined(LZO_OPTIMIZE_GNUC_i386) - -#define BZERO8_PTR(s,l,n) \ -__asm__ __volatile__( \ - "movl %0,%%eax \n" \ - "movl %1,%%edi \n" \ - "movl %2,%%ecx \n" \ - "cld \n" \ - "rep \n" \ - "stosl %%eax,(%%edi) \n" \ - : \ - :"g" (0),"g" (s),"g" (n) \ - :"eax","edi","ecx", "memory", "cc" \ -) -#elif (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) -#if 1 #define BZERO8_PTR(s,l,n) memset((s),0,(lzo_uint)(l)*(n)) -#else -#define BZERO8_PTR(s,l,n) memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) -#endif #else @@ -600,32 +504,6 @@ __asm__ __volatile__( \ #endif -#if 0 -#if defined(__GNUC__) && defined(__i386__) - -unsigned char lzo_rotr8(unsigned char value, int shift); -extern __inline__ unsigned char lzo_rotr8(unsigned char value, int shift) -{ - unsigned char result; - - __asm__ __volatile__ ("movb %b1, %b0; rorb %b2, %b0" - : "=a"(result) : "g"(value), "c"(shift)); - return result; -} - -unsigned short lzo_rotr16(unsigned short value, int shift); -extern __inline__ unsigned short lzo_rotr16(unsigned short value, int shift) -{ - unsigned short result; - - __asm__ __volatile__ ("movw %b1, %b0; rorw %b2, %b0" - : "=a"(result) : "g"(value), "c"(shift)); - return result; -} - -#endif -#endif - #ifdef __cplusplus } #endif @@ -636,7 +514,7 @@ extern __inline__ unsigned short lzo_rot * copyright string in the executable of your product. */ -const lzo_byte __lzo_copyright[] = +static const lzo_byte __lzo_copyright[] = #if !defined(__LZO_IN_MINLZO) LZO_VERSION_STRING; #else @@ -693,8 +571,7 @@ const lzo_byte __lzo_copyright[] = #if defined(__LZO_IN_MINILZO) " __LZO_IN_MINILZO\n" #endif - "\n\n" - "$Id: LZO " LZO_VERSION_STRING " built " __DATE__ " " __TIME__ + "\n\n" "$Id: LZO " LZO_VERSION_STRING " built " __DATE__ " " __TIME__ #if defined(__GNUC__) && defined(__VERSION__) " by gcc " __VERSION__ #elif defined(__BORLANDC__) @@ -714,7 +591,6 @@ const lzo_byte __lzo_copyright[] = "$Copyright: LZO (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer $\n"; #endif - #define LZO_BASE 65521u #define LZO_NMAX 5552 @@ -724,475 +600,421 @@ const lzo_byte __lzo_copyright[] = #define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4); #define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8); -static lzo_voidp -lzo_memset(lzo_voidp s, int c, lzo_uint len) -{ -#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) - return memset(s,c,len); -#else - lzo_byte *p = (lzo_byte *) s; - - if (len > 0) do - *p++ = LZO_BYTE(c); - while (--len > 0); - return s; -#endif -} - -#if 0 -# define IS_SIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) < 0) -# define IS_UNSIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) > 0) -#else # define IS_SIGNED(type) (((type) (-1)) < ((type) 0)) # define IS_UNSIGNED(type) (((type) (-1)) > ((type) 0)) -#endif #define IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0) static lzo_bool schedule_insns_bug(void); static lzo_bool strength_reduce_bug(int *); -#if 0 || defined(LZO_DEBUG) -#include -static lzo_bool __lzo_assert_fail(const char *s, unsigned line) -{ -#if defined(__palmos__) - printf("LZO assertion failed in line %u: '%s'\n",line,s); -#else - fprintf(stderr,"LZO assertion failed in line %u: '%s'\n",line,s); -#endif - return 0; -} -# define __lzo_assert(x) ((x) ? 1 : __lzo_assert_fail(#x,__LINE__)) -#else # define __lzo_assert(x) ((x) ? 1 : 0) -#endif #undef COMPILE_TIME_ASSERT -#if 0 -# define COMPILE_TIME_ASSERT(expr) r &= __lzo_assert(expr) -#else + # define COMPILE_TIME_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) -#endif static lzo_bool basic_integral_check(void) { - lzo_bool r = 1; + lzo_bool r = 1; - COMPILE_TIME_ASSERT(CHAR_BIT == 8); - COMPILE_TIME_ASSERT(sizeof(char) == 1); - COMPILE_TIME_ASSERT(sizeof(short) >= 2); - COMPILE_TIME_ASSERT(sizeof(long) >= 4); - COMPILE_TIME_ASSERT(sizeof(int) >= sizeof(short)); - COMPILE_TIME_ASSERT(sizeof(long) >= sizeof(int)); + COMPILE_TIME_ASSERT(CHAR_BIT == 8); + COMPILE_TIME_ASSERT(sizeof(char) == 1); + COMPILE_TIME_ASSERT(sizeof(short) >= 2); + COMPILE_TIME_ASSERT(sizeof(long) >= 4); + COMPILE_TIME_ASSERT(sizeof(int) >= sizeof(short)); + COMPILE_TIME_ASSERT(sizeof(long) >= sizeof(int)); - COMPILE_TIME_ASSERT(sizeof(lzo_uint) == sizeof(lzo_int)); - COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == sizeof(lzo_int32)); + COMPILE_TIME_ASSERT(sizeof(lzo_uint) == sizeof(lzo_int)); + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == sizeof(lzo_int32)); - COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= 4); - COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= sizeof(unsigned)); + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= sizeof(unsigned)); #if defined(__LZO_STRICT_16BIT) - COMPILE_TIME_ASSERT(sizeof(lzo_uint) == 2); + COMPILE_TIME_ASSERT(sizeof(lzo_uint) == 2); #else - COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= 4); - COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= sizeof(unsigned)); + COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= sizeof(unsigned)); #endif #if (USHRT_MAX == 65535u) - COMPILE_TIME_ASSERT(sizeof(short) == 2); + COMPILE_TIME_ASSERT(sizeof(short) == 2); #elif (USHRT_MAX == LZO_0xffffffffL) - COMPILE_TIME_ASSERT(sizeof(short) == 4); + COMPILE_TIME_ASSERT(sizeof(short) == 4); #elif (USHRT_MAX >= LZO_0xffffffffL) - COMPILE_TIME_ASSERT(sizeof(short) > 4); + COMPILE_TIME_ASSERT(sizeof(short) > 4); #endif -#if 0 /* to make gcc happy -edward */ +#if 0 /* to make gcc happy -edward */ #if (UINT_MAX == 65535u) - COMPILE_TIME_ASSERT(sizeof(int) == 2); + COMPILE_TIME_ASSERT(sizeof(int) == 2); #elif (UINT_MAX == LZO_0xffffffffL) - COMPILE_TIME_ASSERT(sizeof(int) == 4); + COMPILE_TIME_ASSERT(sizeof(int) == 4); #elif (UINT_MAX >= LZO_0xffffffffL) - COMPILE_TIME_ASSERT(sizeof(int) > 4); + COMPILE_TIME_ASSERT(sizeof(int) > 4); #endif #if (ULONG_MAX == 65535ul) - COMPILE_TIME_ASSERT(sizeof(long) == 2); + COMPILE_TIME_ASSERT(sizeof(long) == 2); #elif (ULONG_MAX == LZO_0xffffffffL) - COMPILE_TIME_ASSERT(sizeof(long) == 4); + COMPILE_TIME_ASSERT(sizeof(long) == 4); #elif (ULONG_MAX >= LZO_0xffffffffL) - COMPILE_TIME_ASSERT(sizeof(long) > 4); + COMPILE_TIME_ASSERT(sizeof(long) > 4); #endif #if defined(SIZEOF_UNSIGNED) - COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED == sizeof(unsigned)); + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED == sizeof(unsigned)); #endif #if defined(SIZEOF_UNSIGNED_LONG) - COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_LONG == sizeof(unsigned long)); + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_LONG == sizeof(unsigned long)); #endif #if defined(SIZEOF_UNSIGNED_SHORT) - COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_SHORT == sizeof(unsigned short)); + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_SHORT == sizeof(unsigned short)); #endif #if !defined(__LZO_IN_MINILZO) #if defined(SIZEOF_SIZE_T) - COMPILE_TIME_ASSERT(SIZEOF_SIZE_T == sizeof(size_t)); + COMPILE_TIME_ASSERT(SIZEOF_SIZE_T == sizeof(size_t)); #endif #endif -#endif /* -edward */ +#endif /* -edward */ - COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned char)); - COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned short)); - COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned)); - COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned long)); - COMPILE_TIME_ASSERT(IS_SIGNED(short)); - COMPILE_TIME_ASSERT(IS_SIGNED(int)); - COMPILE_TIME_ASSERT(IS_SIGNED(long)); - - COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint32)); - COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint)); - COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int32)); - COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int)); - - COMPILE_TIME_ASSERT(INT_MAX == LZO_STYPE_MAX(sizeof(int))); - COMPILE_TIME_ASSERT(UINT_MAX == LZO_UTYPE_MAX(sizeof(unsigned))); - COMPILE_TIME_ASSERT(LONG_MAX == LZO_STYPE_MAX(sizeof(long))); - COMPILE_TIME_ASSERT(ULONG_MAX == LZO_UTYPE_MAX(sizeof(unsigned long))); - // COMPILE_TIME_ASSERT(SHRT_MAX == LZO_STYPE_MAX(sizeof(short))); /* edward */ - COMPILE_TIME_ASSERT(USHRT_MAX == LZO_UTYPE_MAX(sizeof(unsigned short))); - COMPILE_TIME_ASSERT(LZO_UINT32_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint32))); - COMPILE_TIME_ASSERT(LZO_UINT_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint))); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned char)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned short)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned long)); + COMPILE_TIME_ASSERT(IS_SIGNED(short)); + COMPILE_TIME_ASSERT(IS_SIGNED(int)); + COMPILE_TIME_ASSERT(IS_SIGNED(long)); + + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint32)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int32)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int)); + + COMPILE_TIME_ASSERT(INT_MAX == LZO_STYPE_MAX(sizeof(int))); + COMPILE_TIME_ASSERT(UINT_MAX == LZO_UTYPE_MAX(sizeof(unsigned))); + COMPILE_TIME_ASSERT(LONG_MAX == LZO_STYPE_MAX(sizeof(long))); + COMPILE_TIME_ASSERT(ULONG_MAX == LZO_UTYPE_MAX(sizeof(unsigned long))); + // COMPILE_TIME_ASSERT(SHRT_MAX == LZO_STYPE_MAX(sizeof(short))); /* edward */ + COMPILE_TIME_ASSERT(USHRT_MAX == LZO_UTYPE_MAX(sizeof(unsigned short))); + COMPILE_TIME_ASSERT(LZO_UINT32_MAX == + LZO_UTYPE_MAX(sizeof(lzo_uint32))); + COMPILE_TIME_ASSERT(LZO_UINT_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint))); #if !defined(__LZO_IN_MINILZO) - COMPILE_TIME_ASSERT(SIZE_T_MAX == LZO_UTYPE_MAX(sizeof(size_t))); + COMPILE_TIME_ASSERT(SIZE_T_MAX == LZO_UTYPE_MAX(sizeof(size_t))); #endif - r &= __lzo_assert(LZO_BYTE(257) == 1); + r &= __lzo_assert(LZO_BYTE(257) == 1); - return r; + return r; } static lzo_bool basic_ptr_check(void) { - lzo_bool r = 1; + lzo_bool r = 1; - COMPILE_TIME_ASSERT(sizeof(char *) >= sizeof(int)); - COMPILE_TIME_ASSERT(sizeof(lzo_byte *) >= sizeof(char *)); + COMPILE_TIME_ASSERT(sizeof(char *) >= sizeof(int)); + COMPILE_TIME_ASSERT(sizeof(lzo_byte *) >= sizeof(char *)); - COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_byte *)); - COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_voidpp)); - COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_bytepp)); - COMPILE_TIME_ASSERT(sizeof(lzo_voidp) >= sizeof(lzo_uint)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_byte *)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_voidpp)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_bytepp)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) >= sizeof(lzo_uint)); - COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_voidp)); - COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_sptr_t)); - COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) >= sizeof(lzo_uint)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_voidp)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_sptr_t)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) >= sizeof(lzo_uint)); - COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= 4); - COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(ptrdiff_t)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(ptrdiff_t)); - COMPILE_TIME_ASSERT(sizeof(ptrdiff_t) >= sizeof(size_t)); - COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(lzo_uint)); + COMPILE_TIME_ASSERT(sizeof(ptrdiff_t) >= sizeof(size_t)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(lzo_uint)); #if defined(SIZEOF_CHAR_P) - COMPILE_TIME_ASSERT(SIZEOF_CHAR_P == sizeof(char *)); + COMPILE_TIME_ASSERT(SIZEOF_CHAR_P == sizeof(char *)); #endif #if defined(SIZEOF_PTRDIFF_T) - COMPILE_TIME_ASSERT(SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)); + COMPILE_TIME_ASSERT(SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)); #endif - COMPILE_TIME_ASSERT(IS_SIGNED(ptrdiff_t)); - COMPILE_TIME_ASSERT(IS_UNSIGNED(size_t)); - COMPILE_TIME_ASSERT(IS_SIGNED(lzo_ptrdiff_t)); - COMPILE_TIME_ASSERT(IS_SIGNED(lzo_sptr_t)); - COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_ptr_t)); - COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_moff_t)); + COMPILE_TIME_ASSERT(IS_SIGNED(ptrdiff_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(size_t)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_ptrdiff_t)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_sptr_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_ptr_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_moff_t)); - return r; + return r; } static lzo_bool ptr_check(void) { - lzo_bool r = 1; - int i; - char _wrkmem[10 * sizeof(lzo_byte *) + sizeof(lzo_full_align_t)]; - lzo_bytep wrkmem; - lzo_bytepp dict; - unsigned char x[4 * sizeof(lzo_full_align_t)]; - long d; - lzo_full_align_t a; - lzo_full_align_t u; - - for (i = 0; i < (int) sizeof(x); i++) - x[i] = LZO_BYTE(i); - - wrkmem = LZO_PTR_ALIGN_UP((lzo_byte *)_wrkmem,sizeof(lzo_full_align_t)); - -#if 0 - dict = (lzo_bytepp) wrkmem; -#else - - u.a_lzo_bytep = wrkmem; dict = u.a_lzo_bytepp; -#endif - - d = (long) ((const lzo_bytep) dict - (const lzo_bytep) _wrkmem); - r &= __lzo_assert(d >= 0); - r &= __lzo_assert(d < (long) sizeof(lzo_full_align_t)); - - memset(&a,0,sizeof(a)); - r &= __lzo_assert(a.a_lzo_voidp == NULL); - - memset(&a,0xff,sizeof(a)); - r &= __lzo_assert(a.a_ushort == USHRT_MAX); - r &= __lzo_assert(a.a_uint == UINT_MAX); - r &= __lzo_assert(a.a_ulong == ULONG_MAX); - r &= __lzo_assert(a.a_lzo_uint == LZO_UINT_MAX); - r &= __lzo_assert(a.a_lzo_uint32 == LZO_UINT32_MAX); - - if (r == 1) - { - for (i = 0; i < 8; i++) - r &= __lzo_assert((const lzo_voidp) (&dict[i]) == (const lzo_voidp) (&wrkmem[i * sizeof(lzo_byte *)])); - } - - memset(&a,0,sizeof(a)); - r &= __lzo_assert(a.a_char_p == NULL); - r &= __lzo_assert(a.a_lzo_bytep == NULL); - r &= __lzo_assert(NULL == (void *)0); - if (r == 1) - { - for (i = 0; i < 10; i++) - dict[i] = wrkmem; - BZERO8_PTR(dict+1,sizeof(dict[0]),8); - r &= __lzo_assert(dict[0] == wrkmem); - for (i = 1; i < 9; i++) - r &= __lzo_assert(dict[i] == NULL); - r &= __lzo_assert(dict[9] == wrkmem); - } - - if (r == 1) - { - unsigned k = 1; - const unsigned n = (unsigned) sizeof(lzo_uint32); - lzo_byte *p0; - lzo_byte *p1; + lzo_bool r = 1; + int i; + char _wrkmem[10 * sizeof(lzo_byte *) + sizeof(lzo_full_align_t)]; + lzo_bytep wrkmem; + lzo_bytepp dict; + unsigned char x[4 * sizeof(lzo_full_align_t)]; + long d; + lzo_full_align_t a; + lzo_full_align_t u; + + for (i = 0; i < (int)sizeof(x); i++) + x[i] = LZO_BYTE(i); + + wrkmem = + LZO_PTR_ALIGN_UP((lzo_byte *) _wrkmem, sizeof(lzo_full_align_t)); + + u.a_lzo_bytep = wrkmem; + dict = u.a_lzo_bytepp; + + d = (long)((const lzo_bytep)dict - (const lzo_bytep)_wrkmem); + r &= __lzo_assert(d >= 0); + r &= __lzo_assert(d < (long)sizeof(lzo_full_align_t)); + + memset(&a, 0, sizeof(a)); + r &= __lzo_assert(a.a_lzo_voidp == NULL); + + memset(&a, 0xff, sizeof(a)); + r &= __lzo_assert(a.a_ushort == USHRT_MAX); + r &= __lzo_assert(a.a_uint == UINT_MAX); + r &= __lzo_assert(a.a_ulong == ULONG_MAX); + r &= __lzo_assert(a.a_lzo_uint == LZO_UINT_MAX); + r &= __lzo_assert(a.a_lzo_uint32 == LZO_UINT32_MAX); + + if (r == 1) { + for (i = 0; i < 8; i++) + r &= __lzo_assert((const lzo_voidp)(&dict[i]) == + (const + lzo_voidp)(&wrkmem[i * + sizeof(lzo_byte + *)])); + } + + memset(&a, 0, sizeof(a)); + r &= __lzo_assert(a.a_char_p == NULL); + r &= __lzo_assert(a.a_lzo_bytep == NULL); + r &= __lzo_assert(NULL == (void *)0); + if (r == 1) { + for (i = 0; i < 10; i++) + dict[i] = wrkmem; + BZERO8_PTR(dict + 1, sizeof(dict[0]), 8); + r &= __lzo_assert(dict[0] == wrkmem); + for (i = 1; i < 9; i++) + r &= __lzo_assert(dict[i] == NULL); + r &= __lzo_assert(dict[9] == wrkmem); + } + + if (r == 1) { + unsigned k = 1; + const unsigned n = (unsigned)sizeof(lzo_uint32); + lzo_byte *p0; + lzo_byte *p1; - k += __lzo_align_gap(&x[k],n); - p0 = (lzo_bytep) &x[k]; + k += __lzo_align_gap(&x[k], n); + p0 = (lzo_bytep) & x[k]; #if defined(PTR_LINEAR) - r &= __lzo_assert((PTR_LINEAR(p0) & (n-1)) == 0); + r &= __lzo_assert((PTR_LINEAR(p0) & (n - 1)) == 0); #else - r &= __lzo_assert(n == 4); - r &= __lzo_assert(PTR_ALIGNED_4(p0)); + r &= __lzo_assert(n == 4); + r &= __lzo_assert(PTR_ALIGNED_4(p0)); #endif - r &= __lzo_assert(k >= 1); - p1 = (lzo_bytep) &x[1]; - r &= __lzo_assert(PTR_GE(p0,p1)); + r &= __lzo_assert(k >= 1); + p1 = (lzo_bytep) & x[1]; + r &= __lzo_assert(PTR_GE(p0, p1)); - r &= __lzo_assert(k < 1+n); - p1 = (lzo_bytep) &x[1+n]; - r &= __lzo_assert(PTR_LT(p0,p1)); + r &= __lzo_assert(k < 1 + n); + p1 = (lzo_bytep) & x[1 + n]; + r &= __lzo_assert(PTR_LT(p0, p1)); - if (r == 1) - { - lzo_uint32 v0, v1; -#if 0 - v0 = * (lzo_uint32 *) &x[k]; - v1 = * (lzo_uint32 *) &x[k+n]; -#else + if (r == 1) { + lzo_uint32 v0, v1; - u.a_uchar_p = &x[k]; - v0 = *u.a_lzo_uint32_p; - u.a_uchar_p = &x[k+n]; - v1 = *u.a_lzo_uint32_p; -#endif - r &= __lzo_assert(v0 > 0); - r &= __lzo_assert(v1 > 0); + u.a_uchar_p = &x[k]; + v0 = *u.a_lzo_uint32_p; + u.a_uchar_p = &x[k + n]; + v1 = *u.a_lzo_uint32_p; + + r &= __lzo_assert(v0 > 0); + r &= __lzo_assert(v1 > 0); + } } - } - return r; + return r; } -static int -_lzo_config_check(void) +static int _lzo_config_check(void) { - lzo_bool r = 1; - int i; - union { - lzo_uint32 a; - unsigned short b; - lzo_uint32 aa[4]; - unsigned char x[4*sizeof(lzo_full_align_t)]; - } u; - - COMPILE_TIME_ASSERT( (int) ((unsigned char) ((signed char) -1)) == 255); - COMPILE_TIME_ASSERT( (((unsigned char)128) << (int)(8*sizeof(int)-8)) < 0); - -#if 0 - r &= __lzo_assert((const void *)&u == (const void *)&u.a); - r &= __lzo_assert((const void *)&u == (const void *)&u.b); - r &= __lzo_assert((const void *)&u == (const void *)&u.x[0]); - r &= __lzo_assert((const void *)&u == (const void *)&u.aa[0]); -#endif - - r &= basic_integral_check(); - r &= basic_ptr_check(); - if (r != 1) - return LZO_E_ERROR; - - u.a = 0; u.b = 0; - for (i = 0; i < (int) sizeof(u.x); i++) - u.x[i] = LZO_BYTE(i); + lzo_bool r = 1; + int i; + union { + lzo_uint32 a; + unsigned short b; + lzo_uint32 aa[4]; + unsigned char x[4 * sizeof(lzo_full_align_t)]; + } + u; + + COMPILE_TIME_ASSERT((int)((unsigned char)((signed char)-1)) == 255); + COMPILE_TIME_ASSERT((((unsigned char)128) << (int)(8 * sizeof(int) - 8)) + < 0); + + r &= basic_integral_check(); + r &= basic_ptr_check(); + if (r != 1) + return LZO_E_ERROR; + + u.a = 0; + u.b = 0; + for (i = 0; i < (int)sizeof(u.x); i++) + u.x[i] = LZO_BYTE(i); #if defined(LZO_BYTE_ORDER) - if (r == 1) - { + if (r == 1) { # if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) - lzo_uint32 a = (lzo_uint32) (u.a & LZO_0xffffffffL); - unsigned short b = (unsigned short) (u.b & 0xffff); - r &= __lzo_assert(a == 0x03020100L); - r &= __lzo_assert(b == 0x0100); + lzo_uint32 a = (lzo_uint32) (u.a & LZO_0xffffffffL); + unsigned short b = (unsigned short)(u.b & 0xffff); + r &= __lzo_assert(a == 0x03020100L); + r &= __lzo_assert(b == 0x0100); # elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) - lzo_uint32 a = u.a >> (8 * sizeof(u.a) - 32); - unsigned short b = u.b >> (8 * sizeof(u.b) - 16); - r &= __lzo_assert(a == 0x00010203L); - r &= __lzo_assert(b == 0x0001); + lzo_uint32 a = u.a >> (8 * sizeof(u.a) - 32); + unsigned short b = u.b >> (8 * sizeof(u.b) - 16); + r &= __lzo_assert(a == 0x00010203L); + r &= __lzo_assert(b == 0x0001); # else # error "invalid LZO_BYTE_ORDER" # endif - } + } #endif #if defined(LZO_UNALIGNED_OK_2) - COMPILE_TIME_ASSERT(sizeof(short) == 2); - if (r == 1) - { - unsigned short b[4]; + COMPILE_TIME_ASSERT(sizeof(short) == 2); + if (r == 1) { + unsigned short b[4]; - for (i = 0; i < 4; i++) - b[i] = * (const unsigned short *) &u.x[i]; + for (i = 0; i < 4; i++) + b[i] = *(const unsigned short *)&u.x[i]; # if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) - r &= __lzo_assert(b[0] == 0x0100); - r &= __lzo_assert(b[1] == 0x0201); - r &= __lzo_assert(b[2] == 0x0302); - r &= __lzo_assert(b[3] == 0x0403); + r &= __lzo_assert(b[0] == 0x0100); + r &= __lzo_assert(b[1] == 0x0201); + r &= __lzo_assert(b[2] == 0x0302); + r &= __lzo_assert(b[3] == 0x0403); # elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) - r &= __lzo_assert(b[0] == 0x0001); - r &= __lzo_assert(b[1] == 0x0102); - r &= __lzo_assert(b[2] == 0x0203); - r &= __lzo_assert(b[3] == 0x0304); + r &= __lzo_assert(b[0] == 0x0001); + r &= __lzo_assert(b[1] == 0x0102); + r &= __lzo_assert(b[2] == 0x0203); + r &= __lzo_assert(b[3] == 0x0304); # endif - } + } #endif #if defined(LZO_UNALIGNED_OK_4) - COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4); - if (r == 1) - { - lzo_uint32 a[4]; + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4); + if (r == 1) { + lzo_uint32 a[4]; - for (i = 0; i < 4; i++) - a[i] = * (const lzo_uint32 *) &u.x[i]; + for (i = 0; i < 4; i++) + a[i] = *(const lzo_uint32 *)&u.x[i]; # if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) - r &= __lzo_assert(a[0] == 0x03020100L); - r &= __lzo_assert(a[1] == 0x04030201L); - r &= __lzo_assert(a[2] == 0x05040302L); - r &= __lzo_assert(a[3] == 0x06050403L); + r &= __lzo_assert(a[0] == 0x03020100L); + r &= __lzo_assert(a[1] == 0x04030201L); + r &= __lzo_assert(a[2] == 0x05040302L); + r &= __lzo_assert(a[3] == 0x06050403L); # elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) - r &= __lzo_assert(a[0] == 0x00010203L); - r &= __lzo_assert(a[1] == 0x01020304L); - r &= __lzo_assert(a[2] == 0x02030405L); - r &= __lzo_assert(a[3] == 0x03040506L); + r &= __lzo_assert(a[0] == 0x00010203L); + r &= __lzo_assert(a[1] == 0x01020304L); + r &= __lzo_assert(a[2] == 0x02030405L); + r &= __lzo_assert(a[3] == 0x03040506L); # endif - } + } #endif #if defined(LZO_ALIGNED_OK_4) - COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4); + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4); #endif - COMPILE_TIME_ASSERT(lzo_sizeof_dict_t == sizeof(lzo_dict_t)); - - if (r == 1) - { - r &= __lzo_assert(!schedule_insns_bug()); - } + COMPILE_TIME_ASSERT(lzo_sizeof_dict_t == sizeof(lzo_dict_t)); - if (r == 1) - { - static int x[3]; - static unsigned xn = 3; - register unsigned j; + if (r == 1) { + r &= __lzo_assert(!schedule_insns_bug()); + } - for (j = 0; j < xn; j++) - x[j] = (int)j - 3; - r &= __lzo_assert(!strength_reduce_bug(x)); - } + if (r == 1) { + static int x[3]; + static unsigned xn = 3; + register unsigned j; + + for (j = 0; j < xn; j++) + x[j] = (int)j - 3; + r &= __lzo_assert(!strength_reduce_bug(x)); + } - if (r == 1) - { - r &= ptr_check(); - } + if (r == 1) { + r &= ptr_check(); + } - return r == 1 ? LZO_E_OK : LZO_E_ERROR; + return r == 1 ? LZO_E_OK : LZO_E_ERROR; } static lzo_bool schedule_insns_bug(void) { #if defined(__LZO_CHECKER) - return 0; + return 0; #else - const int clone[] = {1, 2, 0}; - const int *q; - q = clone; - return (*q) ? 0 : 1; + const int clone[] = { 1, 2, 0 }; + const int *q; + q = clone; + return (*q) ? 0 : 1; #endif } static lzo_bool strength_reduce_bug(int *x) { - return x[0] != -3 || x[1] != -2 || x[2] != -1; + return x[0] != -3 || x[1] != -2 || x[2] != -1; } #undef COMPILE_TIME_ASSERT LZO_PUBLIC(int) -__lzo_init2(unsigned v, int s1, int s2, int s3, int s4, int s5, - int s6, int s7, int s8, int s9) + __lzo_init2(unsigned v, int s1, int s2, int s3, int s4, int s5, + int s6, int s7, int s8, int s9) { - int r; + int r; - if (v == 0) - return LZO_E_ERROR; + if (v == 0) + return LZO_E_ERROR; - r = (s1 == -1 || s1 == (int) sizeof(short)) && - (s2 == -1 || s2 == (int) sizeof(int)) && - (s3 == -1 || s3 == (int) sizeof(long)) && - (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) && - (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && - (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && - (s7 == -1 || s7 == (int) sizeof(char *)) && - (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && - (s9 == -1 || s9 == (int) sizeof(lzo_compress_t)); - if (!r) - return LZO_E_ERROR; + r = (s1 == -1 || s1 == (int)sizeof(short)) && + (s2 == -1 || s2 == (int)sizeof(int)) && + (s3 == -1 || s3 == (int)sizeof(long)) && + (s4 == -1 || s4 == (int)sizeof(lzo_uint32)) && + (s5 == -1 || s5 == (int)sizeof(lzo_uint)) && + (s6 == -1 || s6 == (int)lzo_sizeof_dict_t) && + (s7 == -1 || s7 == (int)sizeof(char *)) && + (s8 == -1 || s8 == (int)sizeof(lzo_voidp)) && + (s9 == -1 || s9 == (int)sizeof(lzo_compress_t)); + if (!r) + return LZO_E_ERROR; + + r = _lzo_config_check(); + if (r != LZO_E_OK) + return r; - r = _lzo_config_check(); - if (r != LZO_E_OK) return r; - - return r; } #if !defined(__LZO_IN_MINILZO) LZO_EXTERN(int) -__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7); + __lzo_init(unsigned v, int s1, int s2, int s3, int s4, int s5, int s6, int s7); LZO_PUBLIC(int) -__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7) +__lzo_init(unsigned v, int s1, int s2, int s3, int s4, int s5, int s6, int s7) { - if (v == 0 || v > 0x1010) - return LZO_E_ERROR; - return __lzo_init2(v,s1,s2,s3,s4,s5,-1,-1,s6,s7); + if (v == 0 || v > 0x1010) + return LZO_E_ERROR; + return __lzo_init2(v, s1, s2, s3, s4, s5, -1, -1, s6, s7); } #endif @@ -1399,12 +1221,11 @@ extern "C" { #if !defined(DVAL_ASSERT) #if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) -static void DVAL_ASSERT(lzo_uint32 dv, const lzo_byte *p) -{ - lzo_uint32 df; - DVAL_FIRST(df,(p)); - assert(DINDEX(dv,p) == DINDEX(df,p)); -} + static void DVAL_ASSERT(lzo_uint32 dv, const lzo_byte * p) { + lzo_uint32 df; + DVAL_FIRST(df, (p)); + assert(DINDEX(dv, p) == DINDEX(df, p)); + } #else # define DVAL_ASSERT(dv,p) ((void) 0) #endif @@ -1469,313 +1290,255 @@ static void DVAL_ASSERT(lzo_uint32 dv, c #ifdef __cplusplus } #endif - #endif - #endif - #endif - #define DO_COMPRESS lzo1x_1_compress - static -lzo_uint do_compress ( const lzo_byte *in , lzo_uint in_len, - lzo_byte *out, lzo_uintp out_len, - lzo_voidp wrkmem ) +lzo_uint do_compress(const lzo_byte * in, lzo_uint in_len, + lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem) { -#if 0 && defined(__GNUC__) && defined(__i386__) - register const lzo_byte *ip __asm__("%esi"); -#else - register const lzo_byte *ip; -#endif - lzo_byte *op; - const lzo_byte * const in_end = in + in_len; - const lzo_byte * const ip_end = in + in_len - M2_MAX_LEN - 5; - const lzo_byte *ii; - lzo_dict_p const dict = (lzo_dict_p) wrkmem; - - op = out; - ip = in; - ii = ip; - - ip += 4; - for (;;) - { -#if 0 && defined(__GNUC__) && defined(__i386__) - register const lzo_byte *m_pos __asm__("%edi"); -#else - register const lzo_byte *m_pos; -#endif - lzo_moff_t m_off; - lzo_uint m_len; - lzo_uint dindex; - - DINDEX1(dindex,ip); - GINDEX(m_pos,m_off,dict,dindex,in); - if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) - goto literal; + register const lzo_byte *ip; + lzo_byte *op; + const lzo_byte *const in_end = in + in_len; + const lzo_byte *const ip_end = in + in_len - M2_MAX_LEN - 5; + const lzo_byte *ii; + lzo_dict_p const dict = (lzo_dict_p) wrkmem; + + op = out; + ip = in; + ii = ip; + + ip += 4; + for (;;) { + register const lzo_byte *m_pos; + + lzo_moff_t m_off; + lzo_uint m_len; + lzo_uint dindex; + + DINDEX1(dindex, ip); + GINDEX(m_pos, m_off, dict, dindex, in); + if (LZO_CHECK_MPOS_NON_DET(m_pos, m_off, in, ip, M4_MAX_OFFSET)) + goto literal; #if 1 - if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) - goto try_match; - DINDEX2(dindex,ip); -#endif - GINDEX(m_pos,m_off,dict,dindex,in); - if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) - goto literal; - if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) - goto try_match; - goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + DINDEX2(dindex, ip); +#endif + GINDEX(m_pos, m_off, dict, dindex, in); + if (LZO_CHECK_MPOS_NON_DET(m_pos, m_off, in, ip, M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + goto literal; -try_match: + try_match: #if 1 && defined(LZO_UNALIGNED_OK_2) - if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip) + if (*(const lzo_ushortp)m_pos != *(const lzo_ushortp)ip) { #else - if (m_pos[0] != ip[0] || m_pos[1] != ip[1]) + if (m_pos[0] != ip[0] || m_pos[1] != ip[1]) { #endif - { - } - else - { - if (m_pos[2] == ip[2]) - { -#if 0 - if (m_off <= M2_MAX_OFFSET) - goto match; - if (lit <= 3) - goto match; - if (lit == 3) - { - assert(op - 2 > out); op[-2] |= LZO_BYTE(3); - *op++ = *ii++; *op++ = *ii++; *op++ = *ii++; - goto code_match; + ; + } else { + if (m_pos[2] == ip[2]) { + goto match; + } else { + ; + } } - if (m_pos[3] == ip[3]) -#endif - goto match; - } - else - { -#if 0 -#if 0 - if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3) -#else - if (m_off <= M1_MAX_OFFSET && lit == 3) -#endif - { - register lzo_uint t; - t = lit; - assert(op - 2 > out); op[-2] |= LZO_BYTE(t); - do *op++ = *ii++; while (--t > 0); - assert(ii == ip); - m_off -= 1; - *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2)); - *op++ = LZO_BYTE(m_off >> 2); - ip += 2; - goto match_done; + literal: + UPDATE_I(dict, 0, dindex, ip, in); + ++ip; + if (ip >= ip_end) + break; + continue; + + match: + UPDATE_I(dict, 0, dindex, ip, in); + if (pd(ip, ii) > 0) { + register lzo_uint t = pd(ip, ii); + + if (t <= 3) { + assert("lzo-04", op - 2 > out); + op[-2] |= LZO_BYTE(t); + } else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else { + register lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) { + tt -= 255; + *op++ = 0; + } + assert("lzo-05", tt > 0); + *op++ = LZO_BYTE(tt); + } + do + *op++ = *ii++; + while (--t > 0); } -#endif - } - } - -literal: - UPDATE_I(dict,0,dindex,ip,in); - ++ip; - if (ip >= ip_end) - break; - continue; - -match: - UPDATE_I(dict,0,dindex,ip,in); - if (pd(ip,ii) > 0) - { - register lzo_uint t = pd(ip,ii); - - if (t <= 3) - { - assert("lzo-04", op - 2 > out); - op[-2] |= LZO_BYTE(t); - } - else if (t <= 18) - *op++ = LZO_BYTE(t - 3); - else - { - register lzo_uint tt = t - 18; - *op++ = 0; - while (tt > 255) - { - tt -= 255; - *op++ = 0; - } - assert("lzo-05", tt > 0); - *op++ = LZO_BYTE(tt); - } - do *op++ = *ii++; while (--t > 0); - } - - assert("lzo-06", ii == ip); - ip += 3; - if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ || - m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++ + assert("lzo-06", ii == ip); + ip += 3; + if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ + || m_pos[6] != *ip++ || m_pos[7] != *ip++ + || m_pos[8] != *ip++ #ifdef LZO1Y - || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++ - || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++ -#endif - ) - { - --ip; - m_len = ip - ii; - assert("lzo-07", m_len >= 3); assert("lzo-08", m_len <= M2_MAX_LEN); - - if (m_off <= M2_MAX_OFFSET) - { - m_off -= 1; + || m_pos[9] != *ip++ || m_pos[10] != *ip++ + || m_pos[11] != *ip++ || m_pos[12] != *ip++ + || m_pos[13] != *ip++ || m_pos[14] != *ip++ +#endif + ) { + --ip; + m_len = ip - ii; + assert("lzo-07", m_len >= 3); + assert("lzo-08", m_len <= M2_MAX_LEN); + + if (m_off <= M2_MAX_OFFSET) { + m_off -= 1; #if defined(LZO1X) - *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); - *op++ = LZO_BYTE(m_off >> 3); + *op++ = + LZO_BYTE(((m_len - + 1) << 5) | ((m_off & 7) << 2)); + *op++ = LZO_BYTE(m_off >> 3); #elif defined(LZO1Y) - *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); - *op++ = LZO_BYTE(m_off >> 2); -#endif - } - else if (m_off <= M3_MAX_OFFSET) - { - m_off -= 1; - *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); - goto m3_m4_offset; - } - else + *op++ = + LZO_BYTE(((m_len + + 1) << 4) | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); +#endif + } else if (m_off <= M3_MAX_OFFSET) { + m_off -= 1; + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + goto m3_m4_offset; + } else #if defined(LZO1X) - { - m_off -= 0x4000; - assert("lzo-09", m_off > 0); assert("lzo-10", m_off <= 0x7fff); - *op++ = LZO_BYTE(M4_MARKER | - ((m_off & 0x4000) >> 11) | (m_len - 2)); - goto m3_m4_offset; - } + { + m_off -= 0x4000; + assert("lzo-09", m_off > 0); + assert("lzo-10", m_off <= 0x7fff); + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | + (m_len - 2)); + goto m3_m4_offset; + } #elif defined(LZO1Y) - goto m4_match; + goto m4_match; #endif - } - else - { - { - const lzo_byte *end = in_end; - const lzo_byte *m = m_pos + M2_MAX_LEN + 1; - while (ip < end && *m == *ip) - m++, ip++; - m_len = (ip - ii); - } - assert("lzo-11", m_len > M2_MAX_LEN); - - if (m_off <= M3_MAX_OFFSET) - { - m_off -= 1; - if (m_len <= 33) - *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); - else - { - m_len -= 33; - *op++ = M3_MARKER | 0; - goto m3_m4_len; - } - } - else - { + } else { + { + const lzo_byte *end = in_end; + const lzo_byte *m = m_pos + M2_MAX_LEN + 1; + while (ip < end && *m == *ip) + m++, ip++; + m_len = (ip - ii); + } + assert("lzo-11", m_len > M2_MAX_LEN); + + if (m_off <= M3_MAX_OFFSET) { + m_off -= 1; + if (m_len <= 33) + *op++ = + LZO_BYTE(M3_MARKER | (m_len - 2)); + else { + m_len -= 33; + *op++ = M3_MARKER | 0; + goto m3_m4_len; + } + } else { #if defined(LZO1Y) -m4_match: + m4_match: #endif - m_off -= 0x4000; - assert("lzo-12", m_off > 0); assert("lzo-13", m_off <= 0x7fff); - if (m_len <= M4_MAX_LEN) - *op++ = LZO_BYTE(M4_MARKER | - ((m_off & 0x4000) >> 11) | (m_len - 2)); - else - { - m_len -= M4_MAX_LEN; - *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11)); -m3_m4_len: - while (m_len > 255) - { - m_len -= 255; - *op++ = 0; - } - assert("lzo-14", m_len > 0); - *op++ = LZO_BYTE(m_len); + m_off -= 0x4000; + assert("lzo-12", m_off > 0); + assert("lzo-13", m_off <= 0x7fff); + if (m_len <= M4_MAX_LEN) + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> + 11) | (m_len - 2)); + else { + m_len -= M4_MAX_LEN; + *op++ = + LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11)); + m3_m4_len: + while (m_len > 255) { + m_len -= 255; + *op++ = 0; + } + assert("lzo-14", m_len > 0); + *op++ = LZO_BYTE(m_len); + } + } + + m3_m4_offset: + *op++ = LZO_BYTE((m_off & 63) << 2); + *op++ = LZO_BYTE(m_off >> 6); } - } -m3_m4_offset: - *op++ = LZO_BYTE((m_off & 63) << 2); - *op++ = LZO_BYTE(m_off >> 6); + ii = ip; + if (ip >= ip_end) + break; } -#if 0 -match_done: -#endif - ii = ip; - if (ip >= ip_end) - break; - } - - *out_len = op - out; - return pd(in_end,ii); + *out_len = op - out; + return pd(in_end, ii); } LZO_PUBLIC(int) -DO_COMPRESS ( const lzo_byte *in , lzo_uint in_len, - lzo_byte *out, lzo_uintp out_len, - lzo_voidp wrkmem ) + DO_COMPRESS(const lzo_byte * in, lzo_uint in_len, + lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem) { - lzo_byte *op = out; - lzo_uint t; + lzo_byte *op = out; + lzo_uint t; #if defined(__LZO_QUERY_COMPRESS) - if (__LZO_IS_COMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) - return __LZO_QUERY_COMPRESS(in,in_len,out,out_len,wrkmem,D_SIZE,lzo_sizeof(lzo_dict_t)); + if (__LZO_IS_COMPRESS_QUERY(in, in_len, out, out_len, wrkmem)) + return __LZO_QUERY_COMPRESS(in, in_len, out, out_len, wrkmem, + D_SIZE, lzo_sizeof(lzo_dict_t)); #endif - if (in_len <= M2_MAX_LEN + 5) - t = in_len; - else - { - t = do_compress(in,in_len,op,out_len,wrkmem); - op += *out_len; - } - - if (t > 0) - { - const lzo_byte *ii = in + in_len - t; - - if (op == out && t <= 238) - *op++ = LZO_BYTE(17 + t); - else if (t <= 3) - op[-2] |= LZO_BYTE(t); - else if (t <= 18) - *op++ = LZO_BYTE(t - 3); - else - { - lzo_uint tt = t - 18; - - *op++ = 0; - while (tt > 255) - { - tt -= 255; - *op++ = 0; - } - assert("lzo-15", tt > 0); - *op++ = LZO_BYTE(tt); + if (in_len <= M2_MAX_LEN + 5) + t = in_len; + else { + t = do_compress(in, in_len, op, out_len, wrkmem); + op += *out_len; } - do *op++ = *ii++; while (--t > 0); - } - *op++ = M4_MARKER | 1; - *op++ = 0; - *op++ = 0; + if (t > 0) { + const lzo_byte *ii = in + in_len - t; - *out_len = op - out; - return LZO_E_OK; + if (op == out && t <= 238) + *op++ = LZO_BYTE(17 + t); + else if (t <= 3) + op[-2] |= LZO_BYTE(t); + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else { + lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) { + tt -= 255; + *op++ = 0; + } + assert("lzo-15", tt > 0); + *op++ = LZO_BYTE(tt); + } + do + *op++ = *ii++; + while (--t > 0); + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = op - out; + return LZO_E_OK; } #undef do_compress @@ -1885,395 +1648,409 @@ DO_COMPRESS ( const lzo_byte *in , #if defined(DO_DECOMPRESS) LZO_PUBLIC(int) -DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, - lzo_byte *out, lzo_uintp out_len, - lzo_voidp wrkmem ) + DO_DECOMPRESS(const lzo_byte * in, lzo_uint in_len, + lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem) #endif { - register lzo_byte *op; - register const lzo_byte *ip; - register lzo_uint t; + register lzo_byte *op; + register const lzo_byte *ip; + register lzo_uint t; #if defined(COPY_DICT) - lzo_uint m_off; - const lzo_byte *dict_end; + lzo_uint m_off; + const lzo_byte *dict_end; #else - register const lzo_byte *m_pos; + register const lzo_byte *m_pos; #endif - const lzo_byte * const ip_end = in + in_len; + const lzo_byte *const ip_end = in + in_len; #if defined(HAVE_ANY_OP) - lzo_byte * const op_end = out + *out_len; + lzo_byte *const op_end = out + *out_len; #endif #if defined(LZO1Z) - lzo_uint last_m_off = 0; + lzo_uint last_m_off = 0; #endif - LZO_UNUSED(wrkmem); + LZO_UNUSED(wrkmem); #if defined(__LZO_QUERY_DECOMPRESS) - if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) - return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0); + if (__LZO_IS_DECOMPRESS_QUERY(in, in_len, out, out_len, wrkmem)) + return __LZO_QUERY_DECOMPRESS(in, in_len, out, out_len, wrkmem, + 0, 0); #endif #if defined(COPY_DICT) - if (dict) - { - if (dict_len > M4_MAX_OFFSET) - { - dict += dict_len - M4_MAX_OFFSET; - dict_len = M4_MAX_OFFSET; + if (dict) { + if (dict_len > M4_MAX_OFFSET) { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } else { + dict_len = 0; + dict_end = NULL; } - dict_end = dict + dict_len; - } - else - { - dict_len = 0; - dict_end = NULL; - } -#endif - - *out_len = 0; - - op = out; - ip = in; - - if (*ip > 17) - { - t = *ip++ - 17; - if (t < 4) - goto match_next; - assert("lzo-16", t > 0); NEED_OP(t); NEED_IP(t+1); - do *op++ = *ip++; while (--t > 0); - goto first_literal_run; - } - - while (TEST_IP && TEST_OP) - { - t = *ip++; - if (t >= 16) - goto match; - if (t == 0) - { - NEED_IP(1); - while (*ip == 0) - { - t += 255; - ip++; - NEED_IP(1); - } - t += 15 + *ip++; +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert("lzo-16", t > 0); + NEED_OP(t); + NEED_IP(t + 1); + do + *op++ = *ip++; + while (--t > 0); + goto first_literal_run; } - assert("lzo-17", t > 0); NEED_OP(t+3); NEED_IP(t+4); + + while (TEST_IP && TEST_OP) { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) { + NEED_IP(1); + while (*ip == 0) { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert("lzo-17", t > 0); + NEED_OP(t + 3); + NEED_IP(t + 4); #if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) #if !defined(LZO_UNALIGNED_OK_4) - if (PTR_ALIGNED2_4(op,ip)) - { + if (PTR_ALIGNED2_4(op, ip)) { #endif - COPY4(op,ip); - op += 4; ip += 4; - if (--t > 0) - { - if (t >= 4) - { - do { - COPY4(op,ip); - op += 4; ip += 4; t -= 4; - } while (t >= 4); - if (t > 0) do *op++ = *ip++; while (--t > 0); - } - else - do *op++ = *ip++; while (--t > 0); - } + COPY4(op, ip); + op += 4; + ip += 4; + if (--t > 0) { + if (t >= 4) { + do { + COPY4(op, ip); + op += 4; + ip += 4; + t -= 4; + } while (t >= 4); + if (t > 0) + do + *op++ = *ip++; + while (--t > 0); + } else + do + *op++ = *ip++; + while (--t > 0); + } #if !defined(LZO_UNALIGNED_OK_4) - } - else + } else #endif #endif #if !defined(LZO_UNALIGNED_OK_4) - { - *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; - do *op++ = *ip++; while (--t > 0); - } + { + *op++ = *ip++; + *op++ = *ip++; + *op++ = *ip++; + do + *op++ = *ip++; + while (--t > 0); + } #endif -first_literal_run: + first_literal_run: - t = *ip++; - if (t >= 16) - goto match; + t = *ip++; + if (t >= 16) + goto match; #if defined(COPY_DICT) #if defined(LZO1Z) - m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); - last_m_off = m_off; + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; #else - m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); #endif - NEED_OP(3); - t = 3; COPY_DICT(t,m_off) + NEED_OP(3); + t = 3; + COPY_DICT(t, m_off) #else #if defined(LZO1Z) - t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); - m_pos = op - t; - last_m_off = t; -#else - m_pos = op - (1 + M2_MAX_OFFSET); - m_pos -= t >> 2; - m_pos -= *ip++ << 2; -#endif - TEST_LOOKBEHIND(m_pos,out); NEED_OP(3); - *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; -#endif - goto match_done; - - while (TEST_IP && TEST_OP) - { -match: - if (t >= 64) - { + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos, out); + NEED_OP(3); + *op++ = *m_pos++; + *op++ = *m_pos++; + *op++ = *m_pos; +#endif + goto match_done; + + while (TEST_IP && TEST_OP) { + match: + if (t >= 64) { #if defined(COPY_DICT) #if defined(LZO1X) - m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); - t = (t >> 5) - 1; + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; #elif defined(LZO1Y) - m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); - t = (t >> 4) - 3; + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; #elif defined(LZO1Z) - m_off = t & 0x1f; - if (m_off >= 0x1c) - m_off = last_m_off; - else - { - m_off = 1 + (m_off << 6) + (*ip++ >> 2); - last_m_off = m_off; - } - t = (t >> 5) - 1; + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; #endif #else #if defined(LZO1X) - m_pos = op - 1; - m_pos -= (t >> 2) & 7; - m_pos -= *ip++ << 3; - t = (t >> 5) - 1; + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; #elif defined(LZO1Y) - m_pos = op - 1; - m_pos -= (t >> 2) & 3; - m_pos -= *ip++ << 2; - t = (t >> 4) - 3; + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; #elif defined(LZO1Z) - { - lzo_uint off = t & 0x1f; - m_pos = op; - if (off >= 0x1c) - { - assert(last_m_off > 0); - m_pos -= last_m_off; - } - else - { - off = 1 + (off << 6) + (*ip++ >> 2); - m_pos -= off; - last_m_off = off; - } - } - t = (t >> 5) - 1; -#endif - TEST_LOOKBEHIND(m_pos,out); assert("lzo-18", t > 0); NEED_OP(t+3-1); - goto copy_match; -#endif - } - else if (t >= 32) - { - t &= 31; - if (t == 0) - { - NEED_IP(1); - while (*ip == 0) - { - t += 255; - ip++; - NEED_IP(1); - } - t += 31 + *ip++; - } + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) { + assert(last_m_off > 0); + m_pos -= last_m_off; + } else { + off = + 1 + (off << 6) + + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LOOKBEHIND(m_pos, out); + assert("lzo-18", t > 0); + NEED_OP(t + 3 - 1); + goto copy_match; +#endif + } else if (t >= 32) { + t &= 31; + if (t == 0) { + NEED_IP(1); + while (*ip == 0) { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } #if defined(COPY_DICT) #if defined(LZO1Z) - m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); - last_m_off = m_off; + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; #else - m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); #endif #else #if defined(LZO1Z) - { - lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); - m_pos = op - off; - last_m_off = off; - } + { + lzo_uint off = + 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } #elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) - m_pos = op - 1; - m_pos -= (* (const lzo_ushortp) ip) >> 2; + m_pos = op - 1; + m_pos -= (*(const lzo_ushortp)ip) >> 2; #else - m_pos = op - 1; - m_pos -= (ip[0] >> 2) + (ip[1] << 6); + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif #endif - ip += 2; - } - else if (t >= 16) - { + ip += 2; + } else if (t >= 16) { #if defined(COPY_DICT) - m_off = (t & 8) << 11; + m_off = (t & 8) << 11; #else - m_pos = op; - m_pos -= (t & 8) << 11; + m_pos = op; + m_pos -= (t & 8) << 11; #endif - t &= 7; - if (t == 0) - { - NEED_IP(1); - while (*ip == 0) - { - t += 255; - ip++; - NEED_IP(1); - } - t += 7 + *ip++; - } + t &= 7; + if (t == 0) { + NEED_IP(1); + while (*ip == 0) { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } #if defined(COPY_DICT) #if defined(LZO1Z) - m_off += (ip[0] << 6) + (ip[1] >> 2); + m_off += (ip[0] << 6) + (ip[1] >> 2); #else - m_off += (ip[0] >> 2) + (ip[1] << 6); + m_off += (ip[0] >> 2) + (ip[1] << 6); #endif - ip += 2; - if (m_off == 0) - goto eof_found; - m_off += 0x4000; + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; #if defined(LZO1Z) - last_m_off = m_off; + last_m_off = m_off; #endif #else #if defined(LZO1Z) - m_pos -= (ip[0] << 6) + (ip[1] >> 2); + m_pos -= (ip[0] << 6) + (ip[1] >> 2); #elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) - m_pos -= (* (const lzo_ushortp) ip) >> 2; + m_pos -= (*(const lzo_ushortp)ip) >> 2; #else - m_pos -= (ip[0] >> 2) + (ip[1] << 6); + m_pos -= (ip[0] >> 2) + (ip[1] << 6); #endif - ip += 2; - if (m_pos == op) - goto eof_found; - m_pos -= 0x4000; + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; #if defined(LZO1Z) - last_m_off = op - m_pos; + last_m_off = op - m_pos; #endif #endif - } - else - { + } else { #if defined(COPY_DICT) #if defined(LZO1Z) - m_off = 1 + (t << 6) + (*ip++ >> 2); - last_m_off = m_off; + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; #else - m_off = 1 + (t >> 2) + (*ip++ << 2); + m_off = 1 + (t >> 2) + (*ip++ << 2); #endif - NEED_OP(2); - t = 2; COPY_DICT(t,m_off) + NEED_OP(2); + t = 2; + COPY_DICT(t, m_off) #else #if defined(LZO1Z) - t = 1 + (t << 6) + (*ip++ >> 2); - m_pos = op - t; - last_m_off = t; -#else - m_pos = op - 1; - m_pos -= t >> 2; - m_pos -= *ip++ << 2; -#endif - TEST_LOOKBEHIND(m_pos,out); NEED_OP(2); - *op++ = *m_pos++; *op++ = *m_pos; + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos, out); + NEED_OP(2); + *op++ = *m_pos++; + *op++ = *m_pos; #endif - goto match_done; - } + goto match_done; + } #if defined(COPY_DICT) - NEED_OP(t+3-1); - t += 3-1; COPY_DICT(t,m_off) - + NEED_OP(t + 3 - 1); + t += 3 - 1; + COPY_DICT(t, m_off) #else - TEST_LOOKBEHIND(m_pos,out); assert("lzo-19", t > 0); NEED_OP(t+3-1); + TEST_LOOKBEHIND(m_pos, out); + assert("lzo-19", t > 0); + NEED_OP(t + 3 - 1); #if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) #if !defined(LZO_UNALIGNED_OK_4) - if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) - { - assert((op - m_pos) >= 4); -#else - if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) - { -#endif - COPY4(op,m_pos); - op += 4; m_pos += 4; t -= 4 - (3 - 1); - do { - COPY4(op,m_pos); - op += 4; m_pos += 4; t -= 4; - } while (t >= 4); - if (t > 0) do *op++ = *m_pos++; while (--t > 0); - } - else -#endif - { -copy_match: - *op++ = *m_pos++; *op++ = *m_pos++; - do *op++ = *m_pos++; while (--t > 0); - } + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op, m_pos)) { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) { +#endif + COPY4(op, m_pos); + op += 4; + m_pos += 4; + t -= 4 - (3 - 1); + do { + COPY4(op, m_pos); + op += 4; + m_pos += 4; + t -= 4; + } while (t >= 4); + if (t > 0) + do + *op++ = *m_pos++; + while (--t > 0); + } else +#endif + { + copy_match: + *op++ = *m_pos++; + *op++ = *m_pos++; + do + *op++ = *m_pos++; + while (--t > 0); + } #endif -match_done: + match_done: #if defined(LZO1Z) - t = ip[-1] & 3; + t = ip[-1] & 3; #else - t = ip[-2] & 3; + t = ip[-2] & 3; #endif - if (t == 0) - break; + if (t == 0) + break; -match_next: - assert("lzo-20", t > 0); NEED_OP(t); NEED_IP(t+1); - do *op++ = *ip++; while (--t > 0); - t = *ip++; + match_next: + assert("lzo-20", t > 0); + NEED_OP(t); + NEED_IP(t + 1); + do + *op++ = *ip++; + while (--t > 0); + t = *ip++; + } } - } #if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) - *out_len = op - out; - return LZO_E_EOF_NOT_FOUND; + *out_len = op - out; + return LZO_E_EOF_NOT_FOUND; #endif -eof_found: - assert("lzo-21", t == 1); - *out_len = op - out; - return (ip == ip_end ? LZO_E_OK : - (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + eof_found: + assert("lzo-21", t == 1); + *out_len = op - out; + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); #if defined(HAVE_NEED_IP) -input_overrun: - *out_len = op - out; - return LZO_E_INPUT_OVERRUN; + input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; #endif #if defined(HAVE_NEED_OP) -output_overrun: - *out_len = op - out; - return LZO_E_OUTPUT_OVERRUN; + output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; #endif #if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) -lookbehind_overrun: - *out_len = op - out; - return LZO_E_LOOKBEHIND_OVERRUN; + lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; #endif } @@ -2376,4 +2153,3 @@ lookbehind_overrun: #endif /***** End of minilzo.c *****/ - diff -puN fs/reiser4/plugin/compress/minilzo.h~reiser4-big-update fs/reiser4/plugin/compress/minilzo.h --- devel/fs/reiser4/plugin/compress/minilzo.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/compress/minilzo.h 2005-09-15 19:51:08.000000000 -0700 @@ -39,7 +39,6 @@ * http://www.oberhumer.com/opensource/lzo/ */ - #ifndef __MINILZO_H #define __MINILZO_H @@ -56,12 +55,10 @@ # error "version mismatch in header files" #endif - #ifdef __cplusplus extern "C" { #endif - /*********************************************************************** // ************************************************************************/ @@ -74,29 +71,24 @@ extern "C" { #define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) #define LZO1X_MEM_DECOMPRESS (0) - /* compression */ -LZO_EXTERN(int) -lzo1x_1_compress ( const lzo_byte *src, lzo_uint src_len, - lzo_byte *dst, lzo_uintp dst_len, - lzo_voidp wrkmem ); + LZO_EXTERN(int) + lzo1x_1_compress(const lzo_byte * src, lzo_uint src_len, + lzo_byte * dst, lzo_uintp dst_len, lzo_voidp wrkmem); /* decompression */ -LZO_EXTERN(int) -lzo1x_decompress ( const lzo_byte *src, lzo_uint src_len, - lzo_byte *dst, lzo_uintp dst_len, - lzo_voidp wrkmem /* NOT USED */ ); + LZO_EXTERN(int) + lzo1x_decompress(const lzo_byte * src, lzo_uint src_len, + lzo_byte * dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); /* safe decompression with overrun testing */ -LZO_EXTERN(int) -lzo1x_decompress_safe ( const lzo_byte *src, lzo_uint src_len, - lzo_byte *dst, lzo_uintp dst_len, - lzo_voidp wrkmem /* NOT USED */ ); - + LZO_EXTERN(int) + lzo1x_decompress_safe(const lzo_byte * src, lzo_uint src_len, + lzo_byte * dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); #ifdef __cplusplus -} /* extern "C" */ +} /* extern "C" */ #endif - -#endif /* already included */ - +#endif /* already included */ diff -L fs/reiser4/plugin/cryptcompress.c -puN fs/reiser4/plugin/cryptcompress.c~reiser4-big-update /dev/null --- devel/fs/reiser4/plugin/cryptcompress.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,3507 +0,0 @@ -/* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by reiser4/README - -This file contains all cluster operations and methods of the reiser4 -cryptcompress object plugin (see http://www.namesys.com/cryptcompress_design.html -for details). - -Cryptcompress specific fields of reiser4 inode/stat-data: - - Incore inode Disk stat-data -******************************************************************************************** -* data structure * field * data structure * field * -******************************************************************************************** -* plugin_set *file plugin id * reiser4_plugin_stat *file plugin id * -* *crypto plugin id * *crypto plugin id * -* *digest plugin id * *digest plugin id * -* *compression plugin id * *compression plugin id* -******************************************************************************************** -* crypto_stat_t * keysize * reiser4_crypto_stat * keysize * -* * keyid * * keyid * -******************************************************************************************** -* cluster_stat_t * cluster_shift * reiser4_cluster_stat * cluster_shift * -******************************************************************************************** -* cryptcompress_info_t * crypto_tfm * * * -******************************************************************************************** -*/ -#include "../debug.h" -#include "../inode.h" -#include "../jnode.h" -#include "../tree.h" -#include "../page_cache.h" -#include "../readahead.h" -#include "../forward.h" -#include "../super.h" -#include "../context.h" -#include "../cluster.h" -#include "../seal.h" -#include "../vfs_ops.h" -#include "plugin.h" -#include "object.h" -#include "../tree_walk.h" -#include "file/funcs.h" - -#include -#include -#include -#include -#include -#include -#include - -int do_readpage_ctail(reiser4_cluster_t *, struct page * page); -int ctail_read_cluster (reiser4_cluster_t *, struct inode *, int); -reiser4_key * append_cluster_key_ctail(const coord_t *, reiser4_key *); -int setattr_reserve(reiser4_tree *); -int writepage_ctail(struct page *); -int update_file_size(struct inode * inode, reiser4_key * key, int update_sd); -int cut_file_items(struct inode *inode, loff_t new_size, int update_sd, loff_t cur_size, - int (*update_actor)(struct inode *, reiser4_key *, int)); -int delete_object(struct inode *inode, int mode); -int ctail_insert_unprepped_cluster(reiser4_cluster_t * clust, struct inode * inode); -int hint_is_set(const hint_t *hint); -reiser4_plugin * get_default_plugin(pset_member memb); -void inode_check_scale_nolock(struct inode * inode, __u64 old, __u64 new); - -/* get cryptcompress specific portion of inode */ -reiser4_internal cryptcompress_info_t * -cryptcompress_inode_data(const struct inode * inode) -{ - return &reiser4_inode_data(inode)->file_plugin_data.cryptcompress_info; -} - -/* plugin->u.file.init_inode_data */ -reiser4_internal void -init_inode_data_cryptcompress(struct inode *inode, - reiser4_object_create_data *crd, int create) -{ - cryptcompress_info_t * data; - - data = cryptcompress_inode_data(inode); - assert("edward-685", data != NULL); - - memset(data, 0, sizeof (*data)); - - init_rwsem(&data->lock); - init_inode_ordering(inode, crd, create); -} - -#if REISER4_DEBUG -static int -crc_generic_check_ok(void) -{ - return MIN_CRYPTO_BLOCKSIZE == DC_CHECKSUM_SIZE << 1; -} - -reiser4_internal int -crc_inode_ok(struct inode * inode) -{ - cryptcompress_info_t * data = cryptcompress_inode_data(inode); - - if (cluster_shift_ok(inode_cluster_shift(inode)) && - (data->tfm[CRYPTO_TFM] == NULL) && - (data->tfm[DIGEST_TFM] == NULL)) - return 1; - assert("edward-686", 0); - return 0; -} -#endif - -static int -check_cryptcompress(struct inode * inode) -{ - int result = 0; - - assert("edward-1307", inode_compression_plugin(inode) != NULL); - - if (inode_cluster_size(inode) < PAGE_CACHE_SIZE) { - warning("edward-1331", - "%s clusters are unsupported", - inode_cluster_plugin(inode)->h.label); - return RETERR(-EINVAL); - } - if (inode_compression_plugin(inode)->init) - result = inode_compression_plugin(inode)->init(); - return result; -} - -static crypto_stat_t * inode_crypto_stat (struct inode * inode) -{ - assert("edward-90", inode != NULL); - assert("edward-91", reiser4_inode_data(inode) != NULL); - - return (cryptcompress_inode_data(inode)->crypt); -} - -/* NOTE-EDWARD: Do not use crypto without digest */ -static int -alloc_crypto_tfm(struct inode * inode, struct inode * parent) -{ - int result; - crypto_plugin * cplug = inode_crypto_plugin(parent); - digest_plugin * dplug = inode_digest_plugin(parent); - - assert("edward-414", dplug != NULL); - assert("edward-415", cplug != NULL); - - result = dplug->alloc(inode); - if (result) - return result; - result = cplug->alloc(inode); - if (result) { - dplug->free(inode); - return result; - } - return 0; -} - -static void -free_crypto_tfm(struct inode * inode) -{ - reiser4_inode * info; - - assert("edward-410", inode != NULL); - - info = reiser4_inode_data(inode); - - if (!inode_get_crypto(inode)) - return; - - assert("edward-411", inode_crypto_plugin(inode)); - assert("edward-763", inode_digest_plugin(inode)); - - inode_crypto_plugin(inode)->free(inode); - inode_digest_plugin(inode)->free(inode); -} - -static int -attach_crypto_stat(struct inode * inode, crypto_data_t * data) -{ - __u8 * txt; - - crypto_stat_t * stat; - struct scatterlist sg; - struct crypto_tfm * dtfm; - - assert("edward-690", inode_get_crypto(inode)); - assert("edward-766", inode_get_digest(inode)); - - dtfm = inode_get_digest(inode); - - stat = reiser4_kmalloc(sizeof(*stat), GFP_KERNEL); - if (!stat) - return -ENOMEM; - - stat->keyid = reiser4_kmalloc((size_t)crypto_tfm_alg_digestsize(dtfm), GFP_KERNEL); - if (!stat->keyid) { - reiser4_kfree(stat); - return -ENOMEM; - } - txt = reiser4_kmalloc(data->keyid_size, GFP_KERNEL); - if (!txt) { - reiser4_kfree(stat->keyid); - reiser4_kfree(stat); - return -ENOMEM; - } - memcpy(txt, data->keyid, data->keyid_size); - sg.page = virt_to_page (txt); - sg.offset = offset_in_page (txt); - sg.length = data->keyid_size; - - crypto_digest_init (dtfm); - crypto_digest_update (dtfm, &sg, 1); - crypto_digest_final (dtfm, stat->keyid); - - cryptcompress_inode_data(inode)->crypt = stat; - reiser4_kfree(txt); - - return 0; -} - -static void -detach_crypto_stat(struct inode * object) -{ - crypto_stat_t * stat; - - stat = inode_crypto_stat(object); - - assert("edward-691", crc_inode_ok(object)); - - if (!inode_get_crypto(object)) - return; - - assert("edward-412", stat != NULL); - - reiser4_kfree(stat->keyid); - reiser4_kfree(stat); -} - -/* 1) fill crypto specific part of inode - 2) set inode crypto stat which is supposed to be saved in stat-data */ -static int -inode_set_crypto(struct inode * object, struct inode * parent, - crypto_data_t * data) -{ - int result; - struct crypto_tfm * tfm; - crypto_plugin * cplug; - digest_plugin * dplug; - reiser4_inode * info = reiser4_inode_data(object); - - cplug = inode_crypto_plugin(parent); - dplug = inode_digest_plugin(parent); - - plugin_set_crypto(&info->pset, cplug); - plugin_set_digest(&info->pset, dplug); - - result = alloc_crypto_tfm(object, parent); - if (!result) - return result; - - if (!inode_get_crypto(object)) - /* nothing to do anymore */ - return 0; - - assert("edward-414", dplug != NULL); - assert("edward-415", cplug != NULL); - assert("edward-417", data->key!= NULL); - assert("edward-88", data->keyid != NULL); - assert("edward-83", data->keyid_size != 0); - assert("edward-89", data->keysize != 0); - - tfm = inode_get_tfm(object, CRYPTO_TFM); - assert("edward-695", tfm != NULL); - - result = cplug->setkey(tfm, data->key, data->keysize); - if (result) { - free_crypto_tfm(object); - return result; - } - assert ("edward-34", !inode_get_flag(object, REISER4_SECRET_KEY_INSTALLED)); - inode_set_flag(object, REISER4_SECRET_KEY_INSTALLED); - - info->extmask |= (1 << CRYPTO_STAT); - - result = attach_crypto_stat(object, data); - if (result) - goto error; - - info->plugin_mask |= (1 << PSET_CRYPTO) | (1 << PSET_DIGEST); - - return 0; - error: - free_crypto_tfm(object); - inode_clr_flag(object, REISER4_SECRET_KEY_INSTALLED); - return result; -} - -static int -inode_set_compression(struct inode * object, struct inode * parent) -{ - int result = 0; - compression_plugin * cplug; - reiser4_inode * info = reiser4_inode_data(object); - - cplug = inode_compression_plugin(parent); - - if (cplug->init != NULL) { - result = cplug->init(); - if (result) - return result; - } - plugin_set_compression(&info->pset, cplug); - info->plugin_mask |= (1 << PSET_COMPRESSION); - - return 0; -} - -static void -inode_set_compression_mode(struct inode * object, struct inode * parent) -{ - compression_mode_plugin * mplug; - reiser4_inode * info = reiser4_inode_data(object); - - mplug = inode_compression_mode_plugin(parent); - - plugin_set_compression_mode(&info->pset, mplug); - info->plugin_mask |= (1 << PSET_COMPRESSION_MODE); - return; -} - -static int -inode_set_cluster(struct inode * object, struct inode * parent) -{ - reiser4_inode * info; - cluster_plugin * cplug; - - assert("edward-696", object != NULL); - - info = reiser4_inode_data(object); - cplug = inode_cluster_plugin(parent); - - if (cplug->shift < PAGE_CACHE_SHIFT) { - warning("edward-1320", - "Can not support cluster size %p", - cplug->h.label); - return RETERR(-EINVAL); - } - plugin_set_cluster(&info->pset, cplug); - - info->plugin_mask |= (1 << PSET_CLUSTER); - return 0; -} - -/* plugin->create() method for crypto-compressed files - -. install plugins -. attach crypto info if specified -. attach compression info if specified -. attach cluster info -*/ -reiser4_internal int -create_cryptcompress(struct inode *object, struct inode *parent, - reiser4_object_create_data * data) -{ - int result; - reiser4_inode * info; - - assert("edward-23", object != NULL); - assert("edward-24", parent != NULL); - assert("edward-30", data != NULL); - assert("edward-26", inode_get_flag(object, REISER4_NO_SD)); - assert("edward-27", data->id == CRC_FILE_PLUGIN_ID); - assert("edward-1170", crc_generic_check_ok()); - - info = reiser4_inode_data(object); - - assert("edward-29", info != NULL); - - /* set file bit */ - info->plugin_mask |= (1 << PSET_FILE); - - /* set crypto */ - result = inode_set_crypto(object, parent, data->crypto); - if (result) - goto error; - /* set compression */ - result = inode_set_compression(object, parent); - if (result) - goto error; - inode_set_compression_mode(object, parent); - - /* set cluster info */ - result = inode_set_cluster(object, parent); - if (result) - goto error; - /* set plugin mask */ - info->extmask |= (1 << PLUGIN_STAT); - - /* save everything in disk stat-data */ - result = write_sd_by_inode_common(object); - if (!result) - return 0; - /* save() method failed, release attached crypto info */ - inode_clr_flag(object, REISER4_CRYPTO_STAT_LOADED); - error: - free_crypto_tfm(object); - detach_crypto_stat(object); - inode_clr_flag(object, REISER4_SECRET_KEY_INSTALLED); - return result; -} - -reiser4_internal int open_cryptcompress(struct inode * inode, struct file * file) -{ - /* FIXME-EDWARD: should be powered by key management */ - assert("edward-698", inode_file_plugin(inode) == file_plugin_by_id(CRC_FILE_PLUGIN_ID)); - return 0; -} - -/* plugin->destroy_inode() */ -reiser4_internal void -destroy_inode_cryptcompress(struct inode * inode) -{ - assert("edward-802", inode_file_plugin(inode) == file_plugin_by_id(CRC_FILE_PLUGIN_ID)); - assert("edward-803", !is_bad_inode(inode) && is_inode_loaded(inode)); - - free_crypto_tfm(inode); - if (inode_get_flag(inode, REISER4_CRYPTO_STAT_LOADED)) - detach_crypto_stat(inode); - - inode_clr_flag(inode, REISER4_CRYPTO_STAT_LOADED); - inode_clr_flag(inode, REISER4_SECRET_KEY_INSTALLED); -} - -/* returns translated offset */ -static loff_t inode_scaled_offset (struct inode * inode, - const loff_t src_off /* input offset */) -{ - assert("edward-97", inode != NULL); - - if (!inode_get_crypto(inode) || src_off == get_key_offset(max_key())) - return src_off; - - return inode_crypto_plugin(inode)->scale(inode, crypto_blocksize(inode), src_off); -} - -/* returns disk cluster size */ -reiser4_internal size_t -inode_scaled_cluster_size (struct inode * inode) -{ - assert("edward-110", inode != NULL); - - return inode_scaled_offset(inode, inode_cluster_size(inode)); -} - -static int -new_cluster(reiser4_cluster_t * clust, struct inode * inode) -{ - return (clust_to_off(clust->index, inode) >= inode->i_size); -} - -/* set number of cluster pages */ -static void -set_cluster_nrpages(reiser4_cluster_t * clust, struct inode * inode) -{ - reiser4_slide_t * win; - - assert("edward-180", clust != NULL); - assert("edward-1040", inode != NULL); - - win = clust->win; - if (!win) { - /* FIXME-EDWARD: i_size should be protected */ - clust->nr_pages = count_to_nrpages(fsize_to_count(clust, inode)); - return; - } - assert("edward-1176", clust->op != PCL_UNKNOWN); - assert("edward-1064", win->off + win->count + win->delta != 0); - - if (win->stat == HOLE_WINDOW && - win->off == 0 && - win->count == inode_cluster_size(inode)) { - /* special case: we start write hole from fake cluster */ - clust->nr_pages = 0; - return; - } - clust->nr_pages = - count_to_nrpages(max_count(win->off + win->count + win->delta, - fsize_to_count(clust, inode))); - return; -} - -/* plugin->key_by_inode() */ -/* see plugin/plugin.h for details */ -reiser4_internal int -key_by_inode_cryptcompress(struct inode *inode, loff_t off, reiser4_key * key) -{ - loff_t clust_off; - - assert("edward-64", inode != 0); - // assert("edward-112", ergo(off != get_key_offset(max_key()), !off_to_cloff(off, inode))); - /* don't come here with other offsets */ - - clust_off = (off == get_key_offset(max_key()) ? get_key_offset(max_key()) : off_to_clust_to_off(off, inode)); - - key_by_inode_and_offset_common(inode, 0, key); - set_key_offset(key, (__u64) (!inode_crypto_stat(inode) ? clust_off : inode_scaled_offset(inode, clust_off))); - return 0; -} - -/* plugin->flow_by_inode */ -reiser4_internal int -flow_by_inode_cryptcompress(struct inode *inode /* file to build flow for */ , - char *buf /* user level buffer */ , - int user /* 1 if @buf is of user space, 0 - if it is - kernel space */ , - loff_t size /* buffer size */ , - loff_t off /* offset to start io from */ , - rw_op op /* READ or WRITE */ , - flow_t * f /* resulting flow */) -{ - assert("edward-436", f != NULL); - assert("edward-149", inode != NULL); - assert("edward-150", inode_file_plugin(inode) != NULL); - assert("edward-151", inode_file_plugin(inode)->key_by_inode == key_by_inode_cryptcompress); - - - f->length = size; - f->data = buf; - f->user = user; - f->op = op; - - if (op == WRITE_OP && user == 1) - return 0; - return key_by_inode_cryptcompress(inode, off, &f->key); -} - -static int -crc_hint_validate(hint_t *hint, const reiser4_key *key, znode_lock_mode lock_mode) -{ - coord_t * coord; - - assert("edward-704", hint != NULL); - assert("edward-1089", !hint->ext_coord.valid); - assert("edward-706", hint->ext_coord.lh->owner == NULL); - - coord = &hint->ext_coord.coord; - - if (!hint || !hint_is_set(hint) || hint->mode != lock_mode) - /* hint either not set or set by different operation */ - return RETERR(-E_REPEAT); - - if (get_key_offset(key) != hint->offset) - /* hint is set for different key */ - return RETERR(-E_REPEAT); - - assert("edward-707", schedulable()); - - return seal_validate(&hint->seal, &hint->ext_coord.coord, - key, hint->ext_coord.lh, - lock_mode, - ZNODE_LOCK_LOPRI); -} - -static int -__reserve4cluster(struct inode * inode, reiser4_cluster_t * clust) -{ - int result = 0; - - assert("edward-965", schedulable()); - assert("edward-439", inode != NULL); - assert("edward-440", clust != NULL); - assert("edward-441", clust->pages != NULL); - assert("edward-1261", get_current_context()->grabbed_blocks == 0); - - if (clust->nr_pages == 0) { - assert("edward-1152", clust->win != NULL); - assert("edward-1153", clust->win->stat == HOLE_WINDOW); - /* don't reserve space for fake disk clusteer */ - return 0; - } - assert("edward-442", jprivate(clust->pages[0]) != NULL); - - result = reiser4_grab_space_force(/* for prepped disk cluster */ - estimate_insert_cluster(inode, 0) + - /* for unprepped disk cluster */ - estimate_insert_cluster(inode, 1), - BA_CAN_COMMIT); - if (result) - return result; - clust->reserved = 1; - grabbed2cluster_reserved(estimate_insert_cluster(inode, 0) + - estimate_insert_cluster(inode, 1)); -#if REISER4_DEBUG - clust->reserved_prepped = estimate_insert_cluster(inode, 0); - clust->reserved_unprepped = estimate_insert_cluster(inode, 1); -#endif - assert("edward-1262", get_current_context()->grabbed_blocks == 0); - return 0; -} - -#ifdef REISER4_TRACE -#define reserve4cluster(inode, clust, msg) __reserve4cluster(inode, clust) -#else -#define reserve4cluster(inode, clust, msg) __reserve4cluster(inode, clust) -#endif - -static void -free_reserved4cluster(struct inode * inode, reiser4_cluster_t * clust, int count) -{ - assert("edward-967", clust->reserved == 1); - - cluster_reserved2free(count); - clust->reserved = 0; -} -#if REISER4_DEBUG -static int -eq_to_ldk(znode *node, const reiser4_key *key) -{ - return UNDER_RW(dk, current_tree, read, keyeq(key, znode_get_ld_key(node))); -} -#endif - -/* The core search procedure. - If returned value is not cbk_errored, current znode is locked */ -static int -find_cluster_item(hint_t * hint, - const reiser4_key *key, /* key of the item we are - looking for */ - znode_lock_mode lock_mode /* which lock */, - ra_info_t *ra_info, - lookup_bias bias, - __u32 flags) -{ - int result; - reiser4_key ikey; - coord_t * coord = &hint->ext_coord.coord; - coord_t orig = *coord; - - assert("edward-152", hint != NULL); - - if (hint->ext_coord.valid == 0) { - result = crc_hint_validate(hint, key, lock_mode); - if (result == -E_REPEAT) - goto traverse_tree; - else if (result) { - assert("edward-1216", 0); - return result; - } - hint->ext_coord.valid = 1; - } - assert("edward-709", znode_is_any_locked(coord->node)); - - /* In-place lookup is going here, it means we just need to - check if next item of the @coord match to the @keyhint) */ - - if (equal_to_rdk(coord->node, key)) { - result = goto_right_neighbor(coord, hint->ext_coord.lh); - if (result == -E_NO_NEIGHBOR) { - assert("edward-1217", 0); - return RETERR(-EIO); - } - if (result) - return result; - assert("edward-1218", eq_to_ldk(coord->node, key)); - } - else { - coord->item_pos++; - coord->unit_pos = 0; - coord->between = AT_UNIT; - } - result = zload(coord->node); - if (result) - return result; - assert("edward-1219", !node_is_empty(coord->node)); - - if (!coord_is_existing_item(coord)) { - zrelse(coord->node); - goto not_found; - } - item_key_by_coord(coord, &ikey); - zrelse(coord->node); - if (!keyeq(key, &ikey)) - goto not_found; - return CBK_COORD_FOUND; - - not_found: - assert("edward-1220", coord->item_pos > 0); - //coord->item_pos--; - /* roll back */ - *coord = orig; - ON_DEBUG(coord_update_v(coord)); - return CBK_COORD_NOTFOUND; - - traverse_tree: - assert("edward-713", hint->ext_coord.lh->owner == NULL); - assert("edward-714", schedulable()); - - unset_hint(hint); - coord_init_zero(coord); - result = coord_by_key(current_tree, key, coord, hint->ext_coord.lh, - lock_mode, bias, LEAF_LEVEL, LEAF_LEVEL, - CBK_UNIQUE | flags, ra_info); - if (cbk_errored(result)) - return result; - hint->ext_coord.valid = 1; - return result; -} - -/* FIXME-EDWARD */ -#if 0 -/* This represent reiser4 crypto alignment policy. - Returns the size > 0 of aligning overhead, if we should align/cut, - returns 0, if we shouldn't (alignment assumes appending an overhead of the size > 0) */ -static int -crypto_overhead(size_t len /* advised length */, - reiser4_cluster_t * clust, - struct inode * inode, rw_op rw) -{ - size_t size = 0; - int result = 0; - int oh; - - assert("edward-486", clust != 0); - - if (!inode_get_crypto(inode) || !inode_crypto_plugin(inode)->align_stream) - return 0; - if (!len) - size = clust->len; - - assert("edward-615", size != 0); - assert("edward-489", crypto_blocksize(inode) != 0); - - switch (rw) { - case WRITE_OP: /* align */ - assert("edward-488", size <= inode_cluster_size(inode)); - - oh = size % crypto_blocksize(inode); - - if (!oh && size == fsize_to_count(clust, inode)) - /* cluster don't need alignment and didn't get compressed */ - return 0; - result = (crypto_blocksize(inode) - oh); - break; - case READ_OP: /* cut */ - assert("edward-490", size <= inode_scaled_cluster_size(inode)); - if (size >= inode_scaled_offset(inode, fsize_to_count(clust, inode))) - /* cluster didn't get aligned */ - return 0; - assert("edward-491", tfm_stream_data(clust, OUTPUT_STREAM) != NULL); - assert("edward-900", 0); - /* FIXME-EDWARD: the stuff above */ - result = *(tfm_stream_data(clust, OUTPUT_STREAM) + size - 1); - break; - default: - impossible("edward-493", "bad option for getting alignment"); - } - return result; -} -#endif - -/* the following two functions are to evaluate results - of compression transform */ -static unsigned -max_crypto_overhead(struct inode * inode) -{ - if (!inode_get_crypto(inode) || !inode_crypto_plugin(inode)->align_stream) - return 0; - return crypto_blocksize(inode); -} - -static int -deflate_overhead(struct inode * inode) -{ - return (inode_compression_plugin(inode)->checksum ? DC_CHECKSUM_SIZE : 0); -} - -/* to estimate size of allocating transform stream */ -static unsigned -deflate_overrun(struct inode * inode, int in_len) -{ - return (inode_compression_plugin(inode)->overrun != NULL ? - inode_compression_plugin(inode)->overrun(in_len) : - 0); -} - -/* The following two functions represent reiser4 compression policy */ -static int -try_compress(tfm_cluster_t * tc, cloff_t index, struct inode * inode) -{ - compression_plugin * cplug = inode_compression_plugin(inode); - compression_mode_plugin * mplug = inode_compression_mode_plugin(inode); - - assert("edward-1321", tc->len != 0); - assert("edward-1322", cplug != NULL); - assert("edward-1323", mplug != NULL); - - return (cplug->compress != NULL) && - (mplug->should_deflate != NULL ? mplug->should_deflate(index) : 1) && - (cplug->min_size_deflate != NULL ? tc->len >= cplug->min_size_deflate() : 1); -} - -static int -try_encrypt(struct inode * inode) -{ - return inode_get_crypto(inode) != NULL; -} - -/* Evaluation results of compression transform. */ -static int -save_compressed(int old_size, int new_size, struct inode * inode) -{ - return (new_size + deflate_overhead(inode) + max_crypto_overhead(inode) < old_size); -} - -/* Guess result of the evaluation above */ -static int -need_inflate(reiser4_cluster_t * clust, struct inode * inode, - int encrypted /* is cluster encrypted */) -{ - tfm_cluster_t * tc = &clust->tc; - - assert("edward-142", tc != 0); - assert("edward-143", inode != NULL); - - return tc->len < - (encrypted ? - inode_scaled_offset(inode, fsize_to_count(clust, inode)) : - fsize_to_count(clust, inode)); -} - -/* append checksum at the end of input transform stream - and increase its length */ -static void -dc_set_checksum(compression_plugin * cplug, tfm_cluster_t * tc) -{ - __u32 checksum; - - assert("edward-1309", tc != NULL); - assert("edward-1310", tc->len > 0); - assert("edward-1311", cplug->checksum != NULL); - - checksum = cplug->checksum(tfm_stream_data(tc, OUTPUT_STREAM), tc->len); - cputod32(checksum, (d32 *)(tfm_stream_data(tc, OUTPUT_STREAM) + tc->len)); - tc->len += (int)DC_CHECKSUM_SIZE; -} - -/* returns 0 if checksums coincide, otherwise returns 1, - increase the length of input transform stream */ -static int -dc_check_checksum(compression_plugin * cplug, tfm_cluster_t * tc) -{ - assert("edward-1312", tc != NULL); - assert("edward-1313", tc->len > (int)DC_CHECKSUM_SIZE); - assert("edward-1314", cplug->checksum != NULL); - - if (cplug->checksum(tfm_stream_data(tc, INPUT_STREAM), tc->len - (int)DC_CHECKSUM_SIZE) != - d32tocpu((d32 *)(tfm_stream_data(tc, INPUT_STREAM) + tc->len - (int)DC_CHECKSUM_SIZE))) { - warning("edward-156", "bad disk cluster checksum %d, (should be %d)\n", - (int)d32tocpu((d32 *)(tfm_stream_data(tc, INPUT_STREAM) + tc->len - (int)DC_CHECKSUM_SIZE)), - (int)cplug->checksum(tfm_stream_data(tc, INPUT_STREAM), tc->len - (int)DC_CHECKSUM_SIZE)); - return 1; - } - tc->len -= (int)DC_CHECKSUM_SIZE; - return 0; -} - -reiser4_internal int -grab_tfm_stream(struct inode * inode, tfm_cluster_t * tc, - tfm_action act, tfm_stream_id id) -{ - size_t size = inode_scaled_cluster_size(inode); - - assert("edward-901", tc != NULL); - assert("edward-1027", inode_compression_plugin(inode) != NULL); - - if (act == TFM_WRITE) - size += deflate_overrun(inode, inode_cluster_size(inode)); - - if (!tfm_stream(tc, id) && id == INPUT_STREAM) - alternate_streams(tc); - if (!tfm_stream(tc, id)) - return alloc_tfm_stream(tc, size, id); - - assert("edward-902", tfm_stream_is_set(tc, id)); - - if (tfm_stream_size(tc, id) < size) - return realloc_tfm_stream(tc, size, id); - return 0; -} - -/* Common deflate cluster manager */ -reiser4_internal int -deflate_cluster(reiser4_cluster_t * clust, struct inode * inode) -{ - int result = 0; - int transformed = 0; - tfm_cluster_t * tc = &clust->tc; - - assert("edward-401", inode != NULL); - assert("edward-903", tfm_stream_is_set(tc, INPUT_STREAM)); - assert("edward-498", !tfm_cluster_is_uptodate(tc)); - - if (try_compress(tc, clust->index, inode)) { - /* try to compress, discard bad results */ - __u32 dst_len; - compression_plugin * cplug = inode_compression_plugin(inode); - compression_mode_plugin * mplug = - inode_compression_mode_plugin(inode); - assert("edward-602", cplug != NULL); - - result = grab_tfm_stream(inode, tc, TFM_WRITE, OUTPUT_STREAM); - if (result) - return result; - dst_len = tfm_stream_size(tc, OUTPUT_STREAM); - cplug->compress(get_coa(tc, cplug->h.id), - tfm_stream_data(tc, INPUT_STREAM), tc->len, - tfm_stream_data(tc, OUTPUT_STREAM), &dst_len); - - /* make sure we didn't overwrite extra bytes */ - assert("edward-603", dst_len <= tfm_stream_size(tc, OUTPUT_STREAM)); - - /* evaluate results of compression transform */ - if (save_compressed(tc->len, dst_len, inode)) { - /* good result, accept */ - tc->len = dst_len; - if (cplug->checksum != NULL) - dc_set_checksum(cplug, tc); - transformed = 1; - if (mplug->save_deflate != NULL) - mplug->save_deflate(inode); - } - else { - /* bad result, discard */ -#if REISER4_DEBUG - warning("edward-1309", - "incompressible data: inode %llu, cluster %lu", - (unsigned long long)get_inode_oid(inode), clust->index); -#endif - if (mplug->discard_deflate != NULL) { - result = mplug->discard_deflate(inode, clust->index); - if (result) - return result; - } - } - } - if (try_encrypt(inode)) { - crypto_plugin * cplug; - /* FIXME-EDWARD */ - assert("edward-904", 0); - - cplug = inode_crypto_plugin(inode); - if (transformed) - alternate_streams(tc); - result = grab_tfm_stream(inode, tc, TFM_WRITE, OUTPUT_STREAM); - if (result) - return result; - /* FIXME: set src_len, dst_len, encrypt */ - transformed = 1; - } - if (!transformed) - alternate_streams(tc); - return result; -} - -/* Common inflate cluster manager. - Is used in readpage() or readpages() methods of - cryptcompress object plugins. */ -reiser4_internal int -inflate_cluster(reiser4_cluster_t * clust, struct inode * inode) -{ - int result = 0; - int transformed = 0; - - tfm_cluster_t * tc = &clust->tc; - - assert("edward-905", inode != NULL); - assert("edward-1178", clust->dstat == PREP_DISK_CLUSTER); - assert("edward-906", tfm_stream_is_set(&clust->tc, INPUT_STREAM)); - assert("edward-907", !tfm_cluster_is_uptodate(tc)); - - if (inode_get_crypto(inode) != NULL) { - crypto_plugin * cplug; - - /* FIXME-EDWARD: isn't supported yet */ - assert("edward-908", 0); - cplug = inode_crypto_plugin(inode); - assert("edward-617", cplug != NULL); - - result = grab_tfm_stream(inode, tc, TFM_READ, OUTPUT_STREAM); - if (result) - return result; - assert("edward-909", tfm_cluster_is_set(tc)); - - /* set src_len, dst_len and decrypt */ - /* tc->len = dst_len */ - - transformed = 1; - } - if (need_inflate(clust, inode, 0)) { - unsigned dst_len = inode_cluster_size(inode); - compression_plugin * cplug = inode_compression_plugin(inode); - - if(transformed) - alternate_streams(tc); - - result = grab_tfm_stream(inode, tc, TFM_READ, OUTPUT_STREAM); - if (result) - return result; - assert("edward-1305", cplug->decompress != NULL); - assert("edward-910", tfm_cluster_is_set(tc)); - - /* Check compression checksum for possible IO errors. - - End-of-cluster format created before encryption: - - data - checksum (4) Indicates presence of compression - infrastructure, should be private. - Can be absent. - crypto_overhead Created by ->align() method of crypto-plugin, - Can be absent. - - Crypto overhead format: - - data - tail_size (1) size of aligning tail, - 1 <= tail_size <= blksize - */ - if (cplug->checksum != NULL) { - result = dc_check_checksum(cplug, tc); - if (result) - return RETERR(-EIO); - } - /* decompress cluster */ - cplug->decompress(get_coa(tc, cplug->h.id), - tfm_stream_data(tc, INPUT_STREAM), tc->len, - tfm_stream_data(tc, OUTPUT_STREAM), &dst_len); - - /* check length */ - tc->len = dst_len; - assert("edward-157", dst_len == fsize_to_count(clust, inode)); - transformed = 1; - } - if (!transformed) - alternate_streams(tc); - return result; -} - -/* plugin->read() : - * generic_file_read() - * All key offsets don't make sense in traditional unix semantics unless they - * represent the beginning of clusters, so the only thing we can do is start - * right from mapping to the address space (this is precisely what filemap - * generic method does) */ -/* plugin->readpage() */ -reiser4_internal int -readpage_cryptcompress(void *vp, struct page *page) -{ - reiser4_cluster_t clust; - struct file * file; - item_plugin * iplug; - int result; - - assert("edward-88", PageLocked(page)); - assert("edward-89", page->mapping && page->mapping->host); - - result = check_cryptcompress(page->mapping->host); - if (result) - return result; - file = vp; - if (file) - assert("edward-113", page->mapping == file->f_dentry->d_inode->i_mapping); - - if (PageUptodate(page)) { - printk("readpage_cryptcompress: page became already uptodate\n"); - unlock_page(page); - return 0; - } - reiser4_cluster_init(&clust, 0); - clust.file = file; - iplug = item_plugin_by_id(CTAIL_ID); - if (!iplug->s.file.readpage) { - put_cluster_handle(&clust, TFM_READ); - return -EINVAL; - } - result = iplug->s.file.readpage(&clust, page); - - assert("edward-64", ergo(result == 0, (PageLocked(page) || PageUptodate(page)))); - /* if page has jnode - that jnode is mapped - assert("edward-65", ergo(result == 0 && PagePrivate(page), - jnode_mapped(jprivate(page)))); - */ - put_cluster_handle(&clust, TFM_READ); - return result; -} - -/* plugin->readpages() */ -reiser4_internal void -readpages_cryptcompress(struct file *file, struct address_space *mapping, - struct list_head *pages) -{ - file_plugin *fplug; - item_plugin *iplug; - - assert("edward-1112", mapping != NULL); - assert("edward-1113", mapping->host != NULL); - - if (check_cryptcompress(mapping->host)) - return; - fplug = inode_file_plugin(mapping->host); - - assert("edward-1114", fplug == file_plugin_by_id(CRC_FILE_PLUGIN_ID)); - - iplug = item_plugin_by_id(CTAIL_ID); - - iplug->s.file.readpages(file, mapping, pages); - - return; -} - -/* how much pages will be captured */ -static int -cluster_nrpages_to_capture(reiser4_cluster_t * clust) -{ - switch (clust->op) { - case PCL_APPEND: - return clust->nr_pages; - case PCL_TRUNCATE: - assert("edward-1179", clust->win != NULL); - return count_to_nrpages(clust->win->off + clust->win->count); - default: - impossible("edward-1180","bad page cluster option"); - return 0; - } -} - -static void -set_cluster_pages_dirty(reiser4_cluster_t * clust) -{ - int i; - struct page * pg; - int nrpages = cluster_nrpages_to_capture(clust); - - for (i=0; i < nrpages; i++) { - - pg = clust->pages[i]; - - assert("edward-968", pg != NULL); - - lock_page(pg); - - assert("edward-1065", PageUptodate(pg)); - - set_page_dirty_internal(pg, 0); - - if (!PageReferenced(pg)) - SetPageReferenced(pg); - mark_page_accessed(pg); - - unlock_page(pg); - } -} - -static void -clear_cluster_pages_dirty(reiser4_cluster_t * clust) -{ - int i; - assert("edward-1275", clust != NULL); - - for (i = 0; i < clust->nr_pages; i++) { - assert("edward-1276", clust->pages[i] != NULL); - - lock_page(clust->pages[i]); - if (!PageDirty(clust->pages[i])) { - warning("edward-985", "Page of index %lu (inode %llu)" - " is not dirty\n", clust->pages[i]->index, - (unsigned long long)get_inode_oid(clust->pages[i]->mapping->host)); - } - else { - assert("edward-1277", PageUptodate(clust->pages[i])); - reiser4_clear_page_dirty(clust->pages[i]); - } - unlock_page(clust->pages[i]); - } -} - -/* update i_size by window */ -static void -inode_set_new_size(reiser4_cluster_t * clust, struct inode * inode) -{ - loff_t size; - reiser4_slide_t * win; - - assert("edward-1181", clust != NULL); - assert("edward-1182", inode != NULL); - - win = clust->win; - assert("edward-1183", win != NULL); - - size = clust_to_off(clust->index, inode) + win->off; - - switch (clust->op) { - case PCL_APPEND: - if (size + win->count <= inode->i_size) - /* overwrite only */ - return; - size += win->count; - break; - case PCL_TRUNCATE: - break; - default: - impossible("edward-1184", "bad page cluster option"); - break; - } - inode_check_scale_nolock(inode, inode->i_size, size); - inode->i_size = size; - return; -} - -/* . reserve space for a disk cluster if its jnode is not dirty; - . update set of pages referenced by this jnode - . update jnode's counter of referenced pages (excluding first one) -*/ -static void -make_cluster_jnode_dirty_locked(reiser4_cluster_t * clust, jnode * node, - loff_t * old_isize, struct inode * inode) -{ - int i; - int old_refcnt; - int new_refcnt; - - assert("edward-221", node != NULL); - assert("edward-971", clust->reserved == 1); - assert("edward-1028", spin_jnode_is_locked(node)); - assert("edward-972", node->page_count < cluster_nrpages(inode)); - assert("edward-1263", clust->reserved_prepped == estimate_insert_cluster(inode, 0)); - assert("edward-1264", clust->reserved_unprepped == 0); - - - if (jnode_is_dirty(node)) { - /* there are >= 1 pages already referenced by this jnode */ - assert("edward-973", count_to_nrpages(off_to_count(*old_isize, clust->index, inode))); - old_refcnt = count_to_nrpages(off_to_count(*old_isize, clust->index, inode)) - 1; - /* space for the disk cluster is already reserved */ - - free_reserved4cluster(inode, clust, estimate_insert_cluster(inode, 0)); - } - else { - /* there is only one page referenced by this jnode */ - assert("edward-1043", node->page_count == 0); - old_refcnt = 0; - jnode_make_dirty_locked(node); - clust->reserved = 0; - } -#if REISER4_DEBUG - clust->reserved_prepped -= estimate_insert_cluster(inode, 0); -#endif - new_refcnt = cluster_nrpages_to_capture(clust) - 1; - - /* get rid of duplicated references */ - for (i = 0; i <= old_refcnt; i++) { - assert("edward-975", clust->pages[i]); - assert("edward-976", old_refcnt < inode_cluster_size(inode)); - assert("edward-1185", PageUptodate(clust->pages[i])); - - page_cache_release(clust->pages[i]); - } - /* truncate old references */ - if (new_refcnt < old_refcnt) { - assert("edward-1186", clust->op == PCL_TRUNCATE); - for (i = new_refcnt + 1; i <= old_refcnt; i++) { - assert("edward-1187", clust->pages[i]); - assert("edward-1188", PageUptodate(clust->pages[i])); - - page_cache_release(clust->pages[i]); - } - } -#if REISER4_DEBUG - node->page_count = new_refcnt; -#endif - return; -} - -/* This is the interface to capture page cluster. - All the cluster pages contain dependent modifications - and should be committed at the same time */ -static int -try_capture_cluster(reiser4_cluster_t * clust, struct inode * inode) -{ - int result = 0; - loff_t old_size = inode->i_size; - jnode * node; - - assert("edward-1029", clust != NULL); - assert("edward-1030", clust->reserved == 1); - assert("edward-1031", clust->nr_pages != 0); - assert("edward-1032", clust->pages != NULL); - assert("edward-1033", clust->pages[0] != NULL); - - node = jprivate(clust->pages[0]); - - assert("edward-1035", node != NULL); - - LOCK_JNODE(node); - if (clust->win) - inode_set_new_size(clust, inode); - - result = try_capture(node, ZNODE_WRITE_LOCK, 0, 0); - if (result) - goto exit; - make_cluster_jnode_dirty_locked(clust, node, &old_size, inode); - exit: - assert("edward-1034", !result); - UNLOCK_JNODE(node); - jput(node); - return result; -} - -/* Collect unlocked cluster pages and jnode */ -static int -grab_cluster_pages_jnode(struct inode * inode, reiser4_cluster_t * clust) -{ - int i; - int result = 0; - jnode * node = NULL; - - assert("edward-182", clust != NULL); - assert("edward-183", clust->pages != NULL); - assert("edward-184", clust->nr_pages <= cluster_nrpages(inode)); - - if (clust->nr_pages == 0) - return 0; - - for (i = 0; i < clust->nr_pages; i++) { - - assert("edward-1044", clust->pages[i] == NULL); - - clust->pages[i] = grab_cache_page(inode->i_mapping, clust_to_pg(clust->index, inode) + i); - if (!clust->pages[i]) { - result = RETERR(-ENOMEM); - break; - } - if (i == 0) { - node = jnode_of_page(clust->pages[i]); - unlock_page(clust->pages[i]); - if (IS_ERR(node)) { - result = PTR_ERR(node); - break; - } - assert("edward-919", node); - continue; - } - unlock_page(clust->pages[i]); - } - if (result) { - while(i) - page_cache_release(clust->pages[--i]); - if (node && !IS_ERR(node)) - jput(node); - return result; - } - assert("edward-920", jprivate(clust->pages[0])); - LOCK_JNODE(node); - JF_SET(node, JNODE_CLUSTER_PAGE); - UNLOCK_JNODE(node); - return 0; -} - -/* collect unlocked cluster pages */ -static int -grab_cluster_pages(struct inode * inode, reiser4_cluster_t * clust) -{ - int i; - int result = 0; - - assert("edward-787", clust != NULL); - assert("edward-788", clust->pages != NULL); - assert("edward-789", clust->nr_pages != 0); - assert("edward-790", clust->nr_pages <= cluster_nrpages(inode)); - - for (i = 0; i < clust->nr_pages; i++) { - clust->pages[i] = grab_cache_page(inode->i_mapping, clust_to_pg(clust->index, inode) + i); - if (!clust->pages[i]) { - result = RETERR(-ENOMEM); - break; - } - unlock_page(clust->pages[i]); - } - if (result) - while(i) - page_cache_release(clust->pages[--i]); - return result; -} - -/* put cluster pages */ -static void -release_cluster_pages(reiser4_cluster_t * clust, int from) -{ - int i; - - assert("edward-447", clust != NULL); - assert("edward-448", from <= clust->nr_pages); - - for (i = from; i < clust->nr_pages; i++) { - - assert("edward-449", clust->pages[i] != NULL); - - page_cache_release(clust->pages[i]); - } -} - -static void -release_cluster_pages_capture(reiser4_cluster_t * clust) -{ - assert("edward-1278", clust != NULL); - assert("edward-1279", clust->nr_pages != 0); - - return release_cluster_pages(clust, 1); -} - -reiser4_internal void -release_cluster_pages_nocapture(reiser4_cluster_t * clust) -{ - return release_cluster_pages(clust, 0); -} - -static void -release_cluster_pages_and_jnode(reiser4_cluster_t * clust) -{ - jnode * node; - - assert("edward-445", clust != NULL); - assert("edward-922", clust->pages != NULL); - assert("edward-446", clust->pages[0] != NULL); - - node = jprivate(clust->pages[0]); - - assert("edward-447", node != NULL); - - release_cluster_pages(clust, 0); - - jput(node); -} - -#if REISER4_DEBUG -static int -window_ok(reiser4_slide_t * win, struct inode * inode) -{ - assert ("edward-1115", win != NULL); - assert ("edward-1116", ergo(win->delta, win->stat == HOLE_WINDOW)); - - return (win->off != inode_cluster_size(inode)) && - (win->off + win->count + win->delta <= inode_cluster_size(inode)); -} - -static int -cluster_ok(reiser4_cluster_t * clust, struct inode * inode) -{ - assert("edward-279", clust != NULL); - - if (!clust->pages) - return 0; - return (clust->win ? window_ok(clust->win, inode) : 1); -} -#endif - -/* guess next window stat */ -static inline window_stat -next_window_stat(reiser4_slide_t * win) -{ - assert ("edward-1130", win != NULL); - return ((win->stat == HOLE_WINDOW && win->delta == 0) ? - HOLE_WINDOW : DATA_WINDOW); -} - -/* guess next cluster index and window params */ -static void -update_cluster(struct inode * inode, reiser4_cluster_t * clust, loff_t file_off, loff_t to_file) -{ - reiser4_slide_t * win; - - assert ("edward-185", clust != NULL); - assert ("edward-438", clust->pages != NULL); - assert ("edward-281", cluster_ok(clust, inode)); - - win = clust->win; - if (!win) - return; - - switch (win->stat) { - case DATA_WINDOW: - /* increment window position */ - clust->index++; - win->stat = DATA_WINDOW; - win->off = 0; - win->count = min_count(inode_cluster_size(inode), to_file); - break; - case HOLE_WINDOW: - switch(next_window_stat(win)) { - case HOLE_WINDOW: - /* set window to fit the offset we start write from */ - clust->index = off_to_clust(file_off, inode); - win->stat = HOLE_WINDOW; - win->off = 0; - win->count = off_to_cloff(file_off, inode); - win->delta = min_count(inode_cluster_size(inode) - win->count, to_file); - break; - case DATA_WINDOW: - /* do not move the window, just change its state, - off+count+delta=inv */ - win->stat = DATA_WINDOW; - win->off = win->off + win->count; - win->count = win->delta; - win->delta = 0; - break; - default: - impossible ("edward-282", "wrong next window state"); - } - break; - default: - impossible ("edward-283", "wrong current window state"); - } - assert ("edward-1068", cluster_ok(clust, inode)); -} - -static int -update_sd_cryptcompress(struct inode *inode) -{ - int result = 0; - - assert("edward-978", schedulable()); - assert("edward-1265", get_current_context()->grabbed_blocks == 0); - - result = reiser4_grab_space_force(/* one for stat data update */ - estimate_update_common(inode), - BA_CAN_COMMIT); - assert("edward-979", !result); - if (result) - return result; - inode->i_ctime = inode->i_mtime = CURRENT_TIME; - result = reiser4_update_sd(inode); - - all_grabbed2free(); - return result; -} - -static void -uncapture_cluster_jnode(jnode *node) -{ - txn_atom *atom; - - assert("edward-1023", spin_jnode_is_locked(node)); - - /*jnode_make_clean(node);*/ - atom = jnode_get_atom(node); - if (atom == NULL) { - assert("jmacd-7111", !jnode_is_dirty(node)); - UNLOCK_JNODE (node); - return; - } - - uncapture_block(node); - UNLOCK_ATOM(atom); - jput(node); -} - -reiser4_internal void -forget_cluster_pages(struct page ** pages, int nr) -{ - int i; - for (i = 0; i < nr; i++) { - - assert("edward-1045", pages[i] != NULL); - page_cache_release(pages[i]); - } -} - -/* Prepare input stream for transform operations. - Try to do it in one step. Return -E_REPEAT when it is - impossible because of races with concurrent processes. -*/ -reiser4_internal int -flush_cluster_pages(reiser4_cluster_t * clust, jnode * node, - struct inode * inode) -{ - int result = 0; - int i; - int nr_pages = 0; - tfm_cluster_t * tc = &clust->tc; - - assert("edward-980", node != NULL); - assert("edward-236", inode != NULL); - assert("edward-237", clust != NULL); - assert("edward-240", !clust->win); - assert("edward-241", schedulable()); - assert("edward-718", crc_inode_ok(inode)); - - LOCK_JNODE(node); - - if (!jnode_is_dirty(node)) { - - assert("edward-981", node->page_count == 0); - warning("edward-982", "flush_cluster_pages: jnode is not dirty " - "clust %lu, inode %llu\n", - clust->index, (unsigned long long)get_inode_oid(inode)); - - /* race with another flush */ - UNLOCK_JNODE(node); - return RETERR(-E_REPEAT); - } - tc->len = fsize_to_count(clust, inode); - clust->nr_pages = count_to_nrpages(tc->len); - - assert("edward-983", clust->nr_pages == node->page_count + 1); -#if REISER4_DEBUG - node->page_count = 0; -#endif - cluster_reserved2grabbed(estimate_insert_cluster(inode, 0)); - uncapture_cluster_jnode(node); - - /* Try to create input stream for the found size (tc->len). - Starting from this point the page cluster can be modified - (truncated, appended) by concurrent processes, so we need - to worry if the constructed stream is valid */ - - assert("edward-1224", schedulable()); - - result = grab_tfm_stream(inode, tc, TFM_WRITE, INPUT_STREAM); - if (result) - return result; - - nr_pages = find_get_pages(inode->i_mapping, clust_to_pg(clust->index, inode), - clust->nr_pages, clust->pages); - - if (nr_pages != clust->nr_pages) { - /* the page cluster get truncated, try again */ - assert("edward-1280", nr_pages < clust->nr_pages); - warning("edward-1281", "Page cluster of index %lu (inode %llu)" - " get truncated from %u to %u pages\n", - clust->index, - (unsigned long long)get_inode_oid(inode), - clust->nr_pages, - nr_pages); - forget_cluster_pages(clust->pages, nr_pages); - return RETERR(-E_REPEAT); - } - for (i = 0; i < clust->nr_pages; i++){ - char * data; - - assert("edward-242", clust->pages[i] != NULL); - - if (clust->pages[i]->index != clust_to_pg(clust->index, inode) + i) { - /* holes in the indices of found group of pages: - page cluster get truncated, transform impossible */ - warning("edward-1282", - "Hole in the indices: " - "Page %d in the cluster of index %lu " - "(inode %llu) has index %lu\n", - i, clust->index, - (unsigned long long)get_inode_oid(inode), - clust->pages[i]->index); - - forget_cluster_pages(clust->pages, nr_pages); - result = RETERR(-E_REPEAT); - goto finish; - } - if (!PageUptodate(clust->pages[i])) { - /* page cluster get truncated, transform impossible */ - assert("edward-1283", !PageDirty(clust->pages[i])); - warning("edward-1284", - "Page of index %lu (inode %llu) " - "is not uptodate\n", clust->pages[i]->index, - (unsigned long long)get_inode_oid(inode)); - - forget_cluster_pages(clust->pages, nr_pages); - result = RETERR(-E_REPEAT); - goto finish; - } - /* ok with this page, flush it to the input stream */ - lock_page(clust->pages[i]); - data = kmap(clust->pages[i]); - - assert("edward-986", off_to_pgcount(tc->len, i) != 0); - - memcpy(tfm_stream_data(tc, INPUT_STREAM) + pg_to_off(i), - data, off_to_pgcount(tc->len, i)); - kunmap(clust->pages[i]); - unlock_page(clust->pages[i]); - } - /* input stream is ready for transform */ - - clear_cluster_pages_dirty(clust); - finish: - release_cluster_pages_capture(clust); - return result; -} - -/* set hint for the cluster of the index @index */ -reiser4_internal void -set_hint_cluster(struct inode * inode, hint_t * hint, - cloff_t index, znode_lock_mode mode) -{ - reiser4_key key; - assert("edward-722", crc_inode_ok(inode)); - assert("edward-723", inode_file_plugin(inode) == file_plugin_by_id(CRC_FILE_PLUGIN_ID)); - - inode_file_plugin(inode)->key_by_inode(inode, clust_to_off(index, inode), &key); - - seal_init(&hint->seal, &hint->ext_coord.coord, &key); - hint->offset = get_key_offset(&key); - hint->mode = mode; -} - -reiser4_internal void -invalidate_hint_cluster(reiser4_cluster_t * clust) -{ - assert("edward-1291", clust != NULL); - assert("edward-1292", clust->hint != NULL); - - done_lh(clust->hint->ext_coord.lh); - clust->hint->ext_coord.valid = 0; -} - -static void -put_hint_cluster(reiser4_cluster_t * clust, struct inode * inode, - znode_lock_mode mode) -{ - assert("edward-1286", clust != NULL); - assert("edward-1287", clust->hint != NULL); - - set_hint_cluster(inode, clust->hint, clust->index + 1, mode); - invalidate_hint_cluster(clust); -} - -static int -balance_dirty_page_cluster(reiser4_cluster_t * clust, struct inode * inode, - loff_t off, loff_t to_file) -{ - int result; - - assert("edward-724", inode != NULL); - assert("edward-725", crc_inode_ok(inode)); - assert("edward-1272", get_current_context()->grabbed_blocks == 0); - - /* set next window params */ - update_cluster(inode, clust, off, to_file); - - result = update_sd_cryptcompress(inode); - assert("edward-988", !result); - if (result) - return result; - assert("edward-726", clust->hint->ext_coord.lh->owner == NULL); - - reiser4_throttle_write(inode); - all_grabbed2free(); - return 0; -} - -/* set zeroes to the cluster, update it, and maybe, try to capture its pages */ -static int -write_hole(struct inode *inode, reiser4_cluster_t * clust, loff_t file_off, loff_t to_file) -{ - char * data; - int result = 0; - unsigned cl_off, cl_count = 0; - unsigned to_pg, pg_off; - reiser4_slide_t * win; - - assert ("edward-190", clust != NULL); - assert ("edward-1069", clust->win != NULL); - assert ("edward-191", inode != NULL); - assert ("edward-727", crc_inode_ok(inode)); - assert ("edward-1171", clust->dstat != INVAL_DISK_CLUSTER); - assert ("edward-1154", - ergo(clust->dstat != FAKE_DISK_CLUSTER, clust->reserved == 1)); - - win = clust->win; - - assert ("edward-1070", win != NULL); - assert ("edward-201", win->stat == HOLE_WINDOW); - assert ("edward-192", cluster_ok(clust, inode)); - - if (win->off == 0 && win->count == inode_cluster_size(inode)) { - /* the hole will be represented by fake disk cluster */ - update_cluster(inode, clust, file_off, to_file); - return 0; - } - cl_count = win->count; /* number of zeroes to write */ - cl_off = win->off; - pg_off = off_to_pgoff(win->off); - - while (cl_count) { - struct page * page; - page = clust->pages[off_to_pg(cl_off)]; - - assert ("edward-284", page != NULL); - - to_pg = min_count(PAGE_CACHE_SIZE - pg_off, cl_count); - lock_page(page); - data = kmap_atomic(page, KM_USER0); - memset(data + pg_off, 0, to_pg); - flush_dcache_page(page); - kunmap_atomic(data, KM_USER0); - SetPageUptodate(page); - unlock_page(page); - - cl_off += to_pg; - cl_count -= to_pg; - pg_off = 0; - } - if (!win->delta) { - /* only zeroes, try to capture */ - - set_cluster_pages_dirty(clust); - result = try_capture_cluster(clust, inode); - if (result) - return result; - put_hint_cluster(clust, inode, ZNODE_WRITE_LOCK); - result = balance_dirty_page_cluster(clust, inode, file_off, to_file); - } - else - update_cluster(inode, clust, file_off, to_file); - return result; -} - -/* - The main disk search procedure for cryptcompress plugins, which - . scans all items of disk cluster - . maybe reads each one (if @read != 0) - . maybe makes its znode dirty (if @write != 0) - - NOTE-EDWARD: Callers should handle the case when disk cluster - is incomplete (-EIO) -*/ -reiser4_internal int -find_cluster(reiser4_cluster_t * clust, - struct inode * inode, - int read, - int write) -{ - flow_t f; - hint_t * hint; - int result; - unsigned long cl_idx; - ra_info_t ra_info; - file_plugin * fplug; - item_plugin * iplug; - tfm_cluster_t * tc; - -#if REISER4_DEBUG - reiser4_context *ctx; - ctx = get_current_context(); -#endif - assert("edward-138", clust != NULL); - assert("edward-728", clust->hint != NULL); - assert("edward-225", read || write); - assert("edward-226", schedulable()); - assert("edward-137", inode != NULL); - assert("edward-729", crc_inode_ok(inode)); - assert("edward-474", get_current_context()->grabbed_blocks == 0); - - hint = clust->hint; - cl_idx = clust->index; - fplug = inode_file_plugin(inode); - - tc = &clust->tc; - - assert("edward-462", !tfm_cluster_is_uptodate(tc)); - assert("edward-461", ergo(read, tfm_stream_is_set(tc, INPUT_STREAM))); - - /* set key of the first disk cluster item */ - fplug->flow_by_inode(inode, - (read ? tfm_stream_data(tc, INPUT_STREAM) : 0), - 0 /* kernel space */, - inode_scaled_cluster_size(inode), - clust_to_off(cl_idx, inode), READ_OP, &f); - if (write) { - /* reserve for flush to make dirty all the leaf nodes - which contain disk cluster */ - result = reiser4_grab_space_force(estimate_disk_cluster(inode), BA_CAN_COMMIT); - assert("edward-990", !result); - if (result) - goto out2; - } - - ra_info.key_to_stop = f.key; - set_key_offset(&ra_info.key_to_stop, get_key_offset(max_key())); - - while (f.length) { - result = find_cluster_item(hint, - &f.key, - (write ? ZNODE_WRITE_LOCK : ZNODE_READ_LOCK), - NULL, - FIND_EXACT, - (write ? CBK_FOR_INSERT : 0)); - switch (result) { - case CBK_COORD_NOTFOUND: - if (inode_scaled_offset(inode, clust_to_off(cl_idx, inode)) == get_key_offset(&f.key)) { - /* first item not found, this is treated - as disk cluster is absent */ - clust->dstat = FAKE_DISK_CLUSTER; - result = 0; - goto out2; - } - /* we are outside the cluster, stop search here */ - assert("edward-146", f.length != inode_scaled_cluster_size(inode)); - goto ok; - case CBK_COORD_FOUND: - assert("edward-148", hint->ext_coord.coord.between == AT_UNIT); - assert("edward-460", hint->ext_coord.coord.unit_pos == 0); - - coord_clear_iplug(&hint->ext_coord.coord); - result = zload_ra(hint->ext_coord.coord.node, &ra_info); - if (unlikely(result)) - goto out2; - iplug = item_plugin_by_coord(&hint->ext_coord.coord); - assert("edward-147", - item_id_by_coord(&hint->ext_coord.coord) == CTAIL_ID); - - result = iplug->s.file.read(NULL, &f, hint); - if (result) - goto out; - if (write) { - znode_make_dirty(hint->ext_coord.coord.node); - znode_set_convertible(hint->ext_coord.coord.node); - } - zrelse(hint->ext_coord.coord.node); - break; - default: - goto out2; - } - } - ok: - /* at least one item was found */ - /* NOTE-EDWARD: Callers should handle the case when disk cluster is incomplete (-EIO) */ - tc->len = inode_scaled_cluster_size(inode) - f.length; - assert("edward-1196", tc->len > 0); - - if (hint_is_unprepped_dclust(clust->hint)) - clust->dstat = UNPR_DISK_CLUSTER; - else - clust->dstat = PREP_DISK_CLUSTER; - all_grabbed2free(); - return 0; - out: - zrelse(hint->ext_coord.coord.node); - out2: - all_grabbed2free(); - return result; -} - -reiser4_internal int -get_disk_cluster_locked(reiser4_cluster_t * clust, struct inode * inode, - znode_lock_mode lock_mode) -{ - reiser4_key key; - ra_info_t ra_info; - - assert("edward-730", schedulable()); - assert("edward-731", clust != NULL); - assert("edward-732", inode != NULL); - - if (clust->hint->ext_coord.valid) { - assert("edward-1293", clust->dstat != INVAL_DISK_CLUSTER); - assert("edward-1294", znode_is_write_locked(clust->hint->ext_coord.lh->node)); - /* already have a valid locked position */ - return (clust->dstat == FAKE_DISK_CLUSTER ? CBK_COORD_NOTFOUND : CBK_COORD_FOUND); - } - key_by_inode_cryptcompress(inode, clust_to_off(clust->index, inode), &key); - ra_info.key_to_stop = key; - set_key_offset(&ra_info.key_to_stop, get_key_offset(max_key())); - - return find_cluster_item(clust->hint, &key, lock_mode, NULL, FIND_EXACT, CBK_FOR_INSERT); -} - -/* Read needed cluster pages before modifying. - If success, @clust->hint contains locked position in the tree. - Also: - . find and set disk cluster state - . make disk cluster dirty if its state is not FAKE_DISK_CLUSTER. -*/ -static int -read_some_cluster_pages(struct inode * inode, reiser4_cluster_t * clust) -{ - int i; - int result = 0; - item_plugin * iplug; - reiser4_slide_t * win = clust->win; - - iplug = item_plugin_by_id(CTAIL_ID); - - assert("edward-733", get_current_context()->grabbed_blocks == 0); - assert("edward-924", !tfm_cluster_is_uptodate(&clust->tc)); - -#if REISER4_DEBUG - if (clust->nr_pages == 0) { - /* start write hole from fake disk cluster */ - assert("edward-1117", win != NULL); - assert("edward-1118", win->stat == HOLE_WINDOW); - assert("edward-1119", new_cluster(clust, inode)); - } -#endif - if (new_cluster(clust, inode)) { - /* - new page cluster is about to be written, nothing to read, - */ - assert("edward-734", schedulable()); - assert("edward-735", clust->hint->ext_coord.lh->owner == NULL); - - clust->dstat = FAKE_DISK_CLUSTER; - return 0; - } - /* - Here we should search for disk cluster to figure out its real state. - Also there is one more important reason to do disk search: we need - to make disk cluster _dirty_ if it exists - */ - - /* if windows is specified, read the only pages - that will be modified partially */ - - for (i = 0; i < clust->nr_pages; i++) { - struct page * pg = clust->pages[i]; - - lock_page(pg); - if (PageUptodate(pg)) { - unlock_page(pg); - continue; - } - unlock_page(pg); - - if (win && - i >= count_to_nrpages(win->off) && - i < off_to_pg(win->off + win->count + win->delta)) - /* page will be completely overwritten */ - continue; - if (win && (i == clust->nr_pages - 1) && - /* the last page is - partially modified, - not uptodate .. */ - (count_to_nrpages(inode->i_size) <= pg->index)) { - /* .. and appended, - so set zeroes to the rest */ - char * data; - int offset; - lock_page(pg); - data = kmap_atomic(pg, KM_USER0); - - assert("edward-1260", - count_to_nrpages(win->off + win->count + win->delta) - 1 == i); - - offset = off_to_pgoff(win->off + win->count + win->delta); - memset(data + offset, 0, PAGE_CACHE_SIZE - offset); - flush_dcache_page(pg); - kunmap_atomic(data, KM_USER0); - unlock_page(pg); - /* still not uptodate */ - break; - } - if (!tfm_cluster_is_uptodate(&clust->tc)) { - result = ctail_read_cluster(clust, inode, 1 /* write */); - assert("edward-992", !result); - if (result) - goto out; - assert("edward-925", tfm_cluster_is_uptodate(&clust->tc)); - } - lock_page(pg); - result = do_readpage_ctail(clust, pg); - unlock_page(pg); - assert("edward-993", !result); - if (result) { - impossible("edward-219", "do_readpage_ctail returned crap"); - goto out; - } - } - if (!tfm_cluster_is_uptodate(&clust->tc)) { - /* disk cluster unclaimed, but we need to make its znodes dirty - to make flush update convert its content */ - result = find_cluster(clust, inode, 0 /* do not read */, 1 /*write */); - assert("edward-994", !cbk_errored(result)); - if (!cbk_errored(result)) - result = 0; - } - out: - tfm_cluster_clr_uptodate(&clust->tc); - return result; -} - -static int -should_create_unprepped_cluster(reiser4_cluster_t * clust, struct inode * inode) -{ - assert("edward-737", clust != NULL); - - switch (clust->dstat) { - case PREP_DISK_CLUSTER: - case UNPR_DISK_CLUSTER: - return 0; - case FAKE_DISK_CLUSTER: - if (clust->win && - clust->win->stat == HOLE_WINDOW && - clust->nr_pages == 0) { - assert("edward-1172", new_cluster(clust, inode)); - return 0; - } - return 1; - default: - impossible("edward-1173", "bad disk cluster state"); - return 0; - } -} - -static int -crc_make_unprepped_cluster (reiser4_cluster_t * clust, struct inode * inode) -{ - int result; - - assert("edward-1123", schedulable()); - assert("edward-737", clust != NULL); - assert("edward-738", inode != NULL); - assert("edward-739", crc_inode_ok(inode)); - assert("edward-1053", clust->hint != NULL); - assert("edward-1266", get_current_context()->grabbed_blocks == 0); - - if (clust->reserved){ - cluster_reserved2grabbed(estimate_insert_cluster(inode, 1)); -#if REISER4_DEBUG - assert("edward-1267", clust->reserved_unprepped == estimate_insert_cluster(inode, 1)); - clust->reserved_unprepped -= estimate_insert_cluster(inode, 1); -#endif - } - if (!should_create_unprepped_cluster(clust, inode)) { - all_grabbed2free(); - return 0; - } else { - assert("edward-1268", clust->reserved == 1); - } - result = ctail_insert_unprepped_cluster(clust, inode); - all_grabbed2free(); - if (result) - return result; - - assert("edward-743", crc_inode_ok(inode)); - assert("edward-1269", get_current_context()->grabbed_blocks == 0); - assert("edward-744", znode_is_write_locked(clust->hint->ext_coord.lh->node)); - - clust->dstat = UNPR_DISK_CLUSTER; - return 0; -} - -#if REISER4_DEBUG -static int -jnode_truncate_ok(struct inode *inode, cloff_t index) -{ - jnode * node; - node = jlookup(current_tree, get_inode_oid(inode), clust_to_pg(index, inode)); - if (node) { - warning("edward-1315", "jnode %p is untruncated\n", node); - jput(node); - } - return (node == NULL); -} - -static int -jnodes_truncate_ok(struct inode * inode, cloff_t start) -{ - int result; - jnode * node; - reiser4_inode *info = reiser4_inode_data(inode); - reiser4_tree * tree = tree_by_inode(inode); - - RLOCK_TREE(tree); - - result = radix_tree_gang_lookup(jnode_tree_by_reiser4_inode(info), (void **)&node, - clust_to_pg(start, inode), 1); - RUNLOCK_TREE(tree); - if (result) - warning("edward-1332", "Untruncated jnode %p\n", node); - return !result; -} - -#endif - -/* Collect unlocked cluster pages and jnode (the last is in the - case when the page cluster will be modified and captured) */ -reiser4_internal int -prepare_page_cluster(struct inode *inode, reiser4_cluster_t *clust, int capture) -{ - assert("edward-177", inode != NULL); - assert("edward-741", crc_inode_ok(inode)); - assert("edward-740", clust->pages != NULL); - - set_cluster_nrpages(clust, inode); - reset_cluster_pgset(clust, cluster_nrpages(inode)); - return (capture ? - grab_cluster_pages_jnode(inode, clust) : - grab_cluster_pages (inode, clust)); -} - -/* Truncate all the pages and jnode bound with the cluster of index @index */ -reiser4_internal void -truncate_page_cluster(struct inode *inode, cloff_t index) -{ - int i; - int found = 0; - int nr_pages; - jnode * node; - struct page * pages[MAX_CLUSTER_NRPAGES]; - - node = jlookup(current_tree, get_inode_oid(inode), clust_to_pg(index, inode)); - /* jnode is absent, just drop pages which can not - acquire jnode because of exclusive access */ - if (!node) { - truncate_inode_pages_range(inode->i_mapping, - clust_to_off(index, inode), - clust_to_off(index, inode) + inode_cluster_size(inode) - 1); - return; - } - /* jnode is present and may be dirty, if so, put - all the cluster pages except the first one */ - nr_pages = count_to_nrpages(off_to_count(inode->i_size, index, inode)); - - found = find_get_pages(inode->i_mapping, clust_to_pg(index, inode), - nr_pages, pages); - - LOCK_JNODE(node); - if (jnode_is_dirty(node)) { - /* jnode is dirty => space for disk cluster - conversion grabbed */ - cluster_reserved2grabbed(estimate_insert_cluster(inode, 0)); - grabbed2free(get_current_context(), - get_current_super_private(), - estimate_insert_cluster(inode, 0)); - - assert("edward-1198", found == nr_pages); - /* This will clear dirty bit so concurrent flush - won't start to convert the disk cluster */ - assert("edward-1199", PageUptodate(pages[0])); - uncapture_cluster_jnode(node); - - for (i = 1; i < nr_pages ; i++) { - assert("edward-1200", PageUptodate(pages[i])); - - page_cache_release(pages[i]); - } - } - else - UNLOCK_JNODE(node); - /* now drop pages and jnode */ - /* FIXME-EDWARD: Use truncate_complete_page in the loop above instead */ - - jput(node); - forget_cluster_pages(pages, found); - truncate_inode_pages_range(inode->i_mapping, - clust_to_off(index, inode), - clust_to_off(index, inode) + inode_cluster_size(inode) - 1); - assert("edward-1201", jnode_truncate_ok(inode, index)); - return; -} - -/* Prepare cluster handle before write and(or) capture. This function - is called by all the clients which modify page cluster and(or) put - it into a transaction (file_write, truncate, writepages, etc..) - - . grab cluster pages; - . reserve disk space; - . maybe read pages from disk and set the disk cluster dirty; - . maybe write hole; - . maybe create 'unprepped' disk cluster if the last one is fake - (isn't represenred by any items on disk) -*/ - -static int -prepare_cluster(struct inode *inode, - loff_t file_off /* write position in the file */, - loff_t to_file, /* bytes of users data to write to the file */ - reiser4_cluster_t *clust, - page_cluster_op op) - -{ - int result = 0; - reiser4_slide_t * win = clust->win; - - assert("edward-1273", get_current_context()->grabbed_blocks == 0); - reset_cluster_params(clust); -#if REISER4_DEBUG - clust->ctx = get_current_context(); -#endif - assert("edward-1190", op != PCL_UNKNOWN); - - clust->op = op; - - result = prepare_page_cluster(inode, clust, 1); - if (result) - return result; - result = reserve4cluster(inode, clust, msg); - if (result) - goto err1; - result = read_some_cluster_pages(inode, clust); - if (result) { - free_reserved4cluster(inode, - clust, - estimate_insert_cluster(inode, 0) + - estimate_insert_cluster(inode, 1)); - goto err1; - } - assert("edward-1124", clust->dstat != INVAL_DISK_CLUSTER); - - result = crc_make_unprepped_cluster(clust, inode); - if (result) - goto err2; - if (win && win->stat == HOLE_WINDOW) { - result = write_hole(inode, clust, file_off, to_file); - if (result) - goto err2; - } - return 0; - err2: - free_reserved4cluster(inode, - clust, - estimate_insert_cluster(inode, 0)); - err1: - page_cache_release(clust->pages[0]); - release_cluster_pages_and_jnode(clust); - assert("edward-1125", 0); - return result; -} - -/* set window by two offsets */ -static void -set_window(reiser4_cluster_t * clust, reiser4_slide_t * win, - struct inode * inode, loff_t o1, loff_t o2) -{ - assert("edward-295", clust != NULL); - assert("edward-296", inode != NULL); - assert("edward-1071", win != NULL); - assert("edward-297", o1 <= o2); - - clust->index = off_to_clust(o1, inode); - - win->off = off_to_cloff(o1, inode); - win->count = min_count(inode_cluster_size(inode) - win->off, o2 - o1); - win->delta = 0; - - clust->win = win; -} - -static int -set_cluster_params(struct inode * inode, reiser4_cluster_t * clust, - reiser4_slide_t * win, flow_t * f, loff_t file_off) -{ - int result; - - assert("edward-197", clust != NULL); - assert("edward-1072", win != NULL); - assert("edward-198", inode != NULL); - - result = alloc_cluster_pgset(clust, cluster_nrpages(inode)); - if (result) - return result; - - if (file_off > inode->i_size) { - /* Uhmm, hole in crypto-file... */ - loff_t hole_size; - hole_size = file_off - inode->i_size; - - set_window(clust, win, inode, inode->i_size, file_off); - win->stat = HOLE_WINDOW; - if (win->off + hole_size < inode_cluster_size(inode)) - /* there is also user's data to append to the hole */ - win->delta = min_count(inode_cluster_size(inode) - (win->off + win->count), f->length); - return 0; - } - set_window(clust, win, inode, file_off, file_off + f->length); - win->stat = DATA_WINDOW; - return 0; -} - -/* reset all the params that not get updated */ -reiser4_internal void -reset_cluster_params(reiser4_cluster_t * clust) -{ - assert("edward-197", clust != NULL); - - clust->dstat = INVAL_DISK_CLUSTER; - clust->tc.uptodate = 0; - clust->tc.len = 0; -} - -/* Main write procedure for cryptcompress objects, - this slices user's data into clusters and copies to page cache. - If @buf != NULL, returns number of bytes in successfully written clusters, - otherwise returns error */ -/* FIXME_EDWARD replace flow by something lightweigth */ - -static loff_t -write_cryptcompress_flow(struct file * file , struct inode * inode, const char *buf, size_t count, loff_t pos) -{ - int i; - flow_t f; - hint_t hint; - lock_handle lh; - int result = 0; - size_t to_write = 0; - loff_t file_off; - reiser4_slide_t win; - reiser4_cluster_t clust; - - assert("edward-161", schedulable()); - assert("edward-748", crc_inode_ok(inode)); - assert("edward-159", current_blocksize == PAGE_CACHE_SIZE); - assert("edward-1274", get_current_context()->grabbed_blocks == 0); - - result = check_cryptcompress(inode); - if (result) - return result; - result = load_file_hint(file, &hint); - if (result) - return result; - init_lh(&lh); - hint.ext_coord.lh = &lh; - - result = flow_by_inode_cryptcompress(inode, (char *)buf, 1 /* user space */, count, pos, WRITE_OP, &f); - if (result) - goto out; - to_write = f.length; - - /* current write position in file */ - file_off = pos; - reiser4_slide_init(&win); - reiser4_cluster_init(&clust, &win); - clust.hint = &hint; - - result = set_cluster_params(inode, &clust, &win, &f, file_off); - if (result) - goto out; - - if (next_window_stat(&win) == HOLE_WINDOW) { - result = prepare_cluster(inode, file_off, f.length, &clust, PCL_APPEND); - if (result) - goto out; - } - do { - char *src; - unsigned page_off, page_count; - - assert("edward-750", schedulable()); - - result = prepare_cluster(inode, file_off, f.length, &clust, PCL_APPEND); - if (result) - goto out; - - assert("edward-751", crc_inode_ok(inode)); - assert("edward-204", win.stat == DATA_WINDOW); - assert("edward-1288", clust.hint->ext_coord.valid); - assert("edward-752", znode_is_write_locked(hint.ext_coord.coord.node)); - - put_hint_cluster(&clust, inode, ZNODE_WRITE_LOCK); - - /* set write position in page */ - page_off = off_to_pgoff(win.off); - - /* copy user's data to cluster pages */ - for (i = off_to_pg(win.off), src = f.data; i < count_to_nrpages(win.off + win.count); i++, src += page_count) { - page_count = off_to_pgcount(win.off + win.count, i) - page_off; - - assert("edward-1039", page_off + page_count <= PAGE_CACHE_SIZE); - assert("edward-287", clust.pages[i] != NULL); - - lock_page(clust.pages[i]); - result = __copy_from_user((char *)kmap(clust.pages[i]) + page_off, src, page_count); - kunmap(clust.pages[i]); - if (unlikely(result)) { - unlock_page(clust.pages[i]); - result = -EFAULT; - goto err3; - } - SetPageUptodate(clust.pages[i]); - unlock_page(clust.pages[i]); - page_off = 0; - } - assert("edward-753", crc_inode_ok(inode)); - - set_cluster_pages_dirty(&clust); - - result = try_capture_cluster(&clust, inode); - if (result) - goto err2; - - assert("edward-998", f.user == 1); - - move_flow_forward(&f, win.count); - - /* disk cluster may be already clean at this point */ - - /* . update cluster - . set hint for new offset - . unlock znode - . update inode - . balance dirty pages - */ - result = balance_dirty_page_cluster(&clust, inode, 0, f.length); - if(result) - goto err1; - assert("edward-755", hint.ext_coord.lh->owner == NULL); - reset_cluster_params(&clust); - continue; - err3: - page_cache_release(clust.pages[0]); - err2: - release_cluster_pages_and_jnode(&clust); - err1: - if (clust.reserved) - free_reserved4cluster(inode, - &clust, - estimate_insert_cluster(inode, 0)); - break; - } while (f.length); - out: - done_lh(&lh); - if (result == -EEXIST) - printk("write returns EEXIST!\n"); - - put_cluster_handle(&clust, TFM_READ); - save_file_hint(file, &hint); - if (buf) { - /* if nothing were written - there must be an error */ - assert("edward-195", ergo((to_write == f.length), result < 0)); - return (to_write - f.length) ? (to_write - f.length) : result; - } - return result; -} - -static ssize_t -write_crc_file(struct file * file, /* file to write to */ - struct inode *inode, /* inode */ - const char *buf, /* address of user-space buffer */ - size_t count, /* number of bytes to write */ - loff_t * off /* position to write which */) -{ - - int result; - loff_t pos; - ssize_t written; - cryptcompress_info_t * info = cryptcompress_inode_data(inode); - - assert("edward-196", crc_inode_ok(inode)); - - result = generic_write_checks(file, off, &count, 0); - if (unlikely(result != 0)) - return result; - - if (unlikely(count == 0)) - return 0; - - /* FIXME-EDWARD: other UNIX features */ - - down_write(&info->lock); - LOCK_CNT_INC(inode_sem_w); - - pos = *off; - written = write_cryptcompress_flow(file, inode, (char *)buf, count, pos); - if (written < 0) { - if (written == -EEXIST) - printk("write_crc_file returns EEXIST!\n"); - return written; - } - - /* update position in a file */ - *off = pos + written; - - up_write(&info->lock); - LOCK_CNT_DEC(inode_sem_w); - - /* return number of written bytes */ - return written; -} - -/* plugin->u.file.write */ -reiser4_internal ssize_t -write_cryptcompress(struct file * file, /* file to write to */ - const char *buf, /* address of user-space buffer */ - size_t count, /* number of bytes to write */ - loff_t * off /* position to write which */) -{ - ssize_t result; - struct inode *inode; - - inode = file->f_dentry->d_inode; - - down(&inode->i_sem); - - result = write_crc_file(file, inode, buf, count, off); - - up(&inode->i_sem); - return result; -} - -static void -readpages_crc(struct address_space *mapping, struct list_head *pages, void *data) -{ - file_plugin *fplug; - item_plugin *iplug; - - assert("edward-1112", mapping != NULL); - assert("edward-1113", mapping->host != NULL); - - fplug = inode_file_plugin(mapping->host); - assert("edward-1114", fplug == file_plugin_by_id(CRC_FILE_PLUGIN_ID)); - iplug = item_plugin_by_id(CTAIL_ID); - - iplug->s.file.readpages(data, mapping, pages); - - return; -} - -static reiser4_block_nr -cryptcompress_estimate_read(struct inode *inode) -{ - /* reserve one block to update stat data item */ - assert("edward-1193", - inode_file_plugin(inode)->estimate.update == estimate_update_common); - return estimate_update_common(inode); -} - -/* plugin->u.file.read */ -ssize_t read_cryptcompress(struct file * file, char *buf, size_t size, loff_t * off) -{ - ssize_t result; - struct inode *inode; - reiser4_file_fsdata * fsdata; - cryptcompress_info_t * info; - reiser4_block_nr needed; - - inode = file->f_dentry->d_inode; - assert("edward-1194", !inode_get_flag(inode, REISER4_NO_SD)); - - info = cryptcompress_inode_data(inode); - needed = cryptcompress_estimate_read(inode); - /* FIXME-EDWARD: - Grab space for sd_update so find_cluster will be happy */ -#if 0 - result = reiser4_grab_space(needed, BA_CAN_COMMIT); - if (result != 0) - return result; -#endif - fsdata = reiser4_get_file_fsdata(file); - fsdata->ra2.data = file; - fsdata->ra2.readpages = readpages_crc; - - down_read(&info->lock); - LOCK_CNT_INC(inode_sem_r); - - result = generic_file_read(file, buf, size, off); - - up_read(&info->lock); - LOCK_CNT_DEC(inode_sem_r); - - return result; -} - -static void -set_append_cluster_key(const coord_t *coord, reiser4_key *key, struct inode *inode) -{ - item_key_by_coord(coord, key); - set_key_offset(key, clust_to_off(clust_by_coord(coord, inode) + 1, inode)); -} - -/* If @index > 0, find real disk cluster of the index (@index - 1), - If @index == 0 find the real disk cluster of the object of maximal index. - Keep incremented index of the result in @found. - It succes was returned: - (@index == 0 && @found == 0) means that the object doesn't have real disk - clusters. - (@index != 0 && @found == 0) means that disk cluster of (@index -1 ) doesn't - exist. -*/ -static int -find_real_disk_cluster(struct inode * inode, cloff_t * found, cloff_t index) -{ - int result; - reiser4_key key; - loff_t offset; - hint_t hint; - lookup_bias bias; - coord_t *coord; - lock_handle lh; - item_plugin *iplug; - file_plugin *fplug = inode_file_plugin(inode); - - assert("edward-1131", fplug == file_plugin_by_id(CRC_FILE_PLUGIN_ID)); - assert("edward-95", crc_inode_ok(inode)); - - init_lh(&lh); - hint_init_zero(&hint); - hint.ext_coord.lh = &lh; - - bias = (index ? FIND_EXACT : FIND_MAX_NOT_MORE_THAN); - offset = (index ? clust_to_off(index, inode) - 1 : get_key_offset(max_key())); - - fplug->key_by_inode(inode, offset, &key); - - /* find the last item of this object */ - result = find_cluster_item(&hint, &key, ZNODE_READ_LOCK, 0/* ra_info */, bias, 0); - if (cbk_errored(result)) { - done_lh(&lh); - return result; - } - if (result == CBK_COORD_NOTFOUND) { - /* no real disk clusters */ - done_lh(&lh); - *found = 0; - return 0; - } - /* disk cluster is found */ - coord = &hint.ext_coord.coord; - coord_clear_iplug(coord); - result = zload(coord->node); - if (unlikely(result)) { - done_lh(&lh); - return result; - } - iplug = item_plugin_by_coord(coord); - assert("edward-277", iplug == item_plugin_by_id(CTAIL_ID)); - assert("edward-1202", ctail_ok(coord)); - - set_append_cluster_key(coord, &key, inode); - - *found = off_to_clust(get_key_offset(&key), inode); - - assert("edward-1132", ergo(index, index == *found)); - - zrelse(coord->node); - done_lh(&lh); - - return 0; -} - -static int -find_fake_appended(struct inode *inode, cloff_t *index) -{ - return find_real_disk_cluster(inode, index, 0 /* find last real one */); -} - -/* Set left coord when unit is not found after node_lookup() - This takes into account that there can be holes in a sequence - of disk clusters */ - -static void -adjust_left_coord(coord_t * left_coord) -{ - switch(left_coord->between) { - case AFTER_UNIT: - left_coord->between = AFTER_ITEM; - case AFTER_ITEM: - case BEFORE_UNIT: - break; - default: - impossible("edward-1204", "bad left coord to cut"); - } - return; -} - -#define CRC_CUT_TREE_MIN_ITERATIONS 64 -reiser4_internal int -cut_tree_worker_cryptcompress(tap_t * tap, const reiser4_key * from_key, - const reiser4_key * to_key, reiser4_key * smallest_removed, - struct inode * object, int truncate, int *progress) -{ - lock_handle next_node_lock; - coord_t left_coord; - int result; - - assert("edward-1158", tap->coord->node != NULL); - assert("edward-1159", znode_is_write_locked(tap->coord->node)); - assert("edward-1160", znode_get_level(tap->coord->node) == LEAF_LEVEL); - - *progress = 0; - init_lh(&next_node_lock); - - while (1) { - znode *node; /* node from which items are cut */ - node_plugin *nplug; /* node plugin for @node */ - - node = tap->coord->node; - - /* Move next_node_lock to the next node on the left. */ - result = reiser4_get_left_neighbor( - &next_node_lock, node, ZNODE_WRITE_LOCK, GN_CAN_USE_UPPER_LEVELS); - if (result != 0 && result != -E_NO_NEIGHBOR) - break; - /* FIXME-EDWARD: Check can we delete the node as a whole. */ - result = tap_load(tap); - if (result) - return result; - - /* Prepare the second (right) point for cut_node() */ - if (*progress) - coord_init_last_unit(tap->coord, node); - - else if (item_plugin_by_coord(tap->coord)->b.lookup == NULL) - /* set rightmost unit for the items without lookup method */ - tap->coord->unit_pos = coord_last_unit_pos(tap->coord); - - nplug = node->nplug; - - assert("edward-1161", nplug); - assert("edward-1162", nplug->lookup); - - /* left_coord is leftmost unit cut from @node */ - result = nplug->lookup(node, from_key, - FIND_EXACT, &left_coord); - - if (IS_CBKERR(result)) - break; - - if (result == CBK_COORD_NOTFOUND) - adjust_left_coord(&left_coord); - - /* adjust coordinates so that they are set to existing units */ - if (coord_set_to_right(&left_coord) || coord_set_to_left(tap->coord)) { - result = 0; - break; - } - - if (coord_compare(&left_coord, tap->coord) == COORD_CMP_ON_RIGHT) { - /* keys from @from_key to @to_key are not in the tree */ - result = 0; - break; - } - - /* cut data from one node */ - *smallest_removed = *min_key(); - result = kill_node_content(&left_coord, - tap->coord, - from_key, - to_key, - smallest_removed, - next_node_lock.node, - object, truncate); -#if REISER4_DEBUG - /*node_check(node, ~0U);*/ -#endif - tap_relse(tap); - - if (result) - break; - - ++ (*progress); - - /* Check whether all items with keys >= from_key were removed - * from the tree. */ - if (keyle(smallest_removed, from_key)) - /* result = 0;*/ - break; - - if (next_node_lock.node == NULL) - break; - - result = tap_move(tap, &next_node_lock); - done_lh(&next_node_lock); - if (result) - break; - - /* Break long cut_tree operation (deletion of a large file) if - * atom requires commit. */ - if (*progress > CRC_CUT_TREE_MIN_ITERATIONS - && current_atom_should_commit()) - { - result = -E_REPEAT; - break; - } - } - done_lh(&next_node_lock); - return result; -} - -/* Append or expand hole in two steps (exclusive access should be aquired!) - 1) write zeroes to the current real cluster, - 2) expand hole via fake clusters (just increase i_size) */ -static int -cryptcompress_append_hole(struct inode * inode /*contains old i_size */, - loff_t new_size) -{ - int result = 0; - hint_t hint; - loff_t hole_size; - int nr_zeroes; - lock_handle lh; - reiser4_slide_t win; - reiser4_cluster_t clust; - - assert("edward-1133", inode->i_size < new_size); - assert("edward-1134", schedulable()); - assert("edward-1135", crc_inode_ok(inode)); - assert("edward-1136", current_blocksize == PAGE_CACHE_SIZE); - assert("edward-1333", off_to_cloff(inode->i_size, inode) != 0); - - init_lh(&lh); - hint_init_zero(&hint); - hint.ext_coord.lh = &lh; - - reiser4_slide_init(&win); - reiser4_cluster_init(&clust, &win); - clust.hint = &hint; - - /* set cluster handle */ - result = alloc_cluster_pgset(&clust, cluster_nrpages(inode)); - if (result) - goto out; - hole_size = new_size - inode->i_size; - nr_zeroes = min_count(inode_cluster_size(inode) - off_to_cloff(inode->i_size, inode), hole_size); - - set_window(&clust, &win, inode, inode->i_size, inode->i_size + nr_zeroes); - win.stat = HOLE_WINDOW; - - assert("edward-1137", clust.index == off_to_clust(inode->i_size, inode)); - - result = prepare_cluster(inode, 0, 0, &clust, PCL_APPEND); - - assert("edward-1271", !result); - if (result) - goto out; - assert("edward-1139", - clust.dstat == PREP_DISK_CLUSTER || - clust.dstat == UNPR_DISK_CLUSTER); - - hole_size -= nr_zeroes; - if (!hole_size) - /* nothing to append anymore */ - goto out; - - /* fake_append: */ - INODE_SET_FIELD(inode, i_size, new_size); - out: - done_lh(&lh); - put_cluster_handle(&clust, TFM_READ); - return result; -} - -#if REISER4_DEBUG -static int -pages_truncate_ok(struct inode * inode, loff_t old_size, pgoff_t start) -{ - struct pagevec pvec; - int i; - int count; - int rest; - - rest = count_to_nrpages(old_size) - start; - - pagevec_init(&pvec, 0); - count = min_count(pagevec_space(&pvec), rest); - - while (rest) { - count = min_count(pagevec_space(&pvec), rest); - pvec.nr = find_get_pages(inode->i_mapping, start, - count, pvec.pages); - for (i = 0; i < pagevec_count(&pvec); i++) { - if (PageUptodate(pvec.pages[i])) { - warning("edward-1205", - "truncated page of index %lu is uptodate", - pvec.pages[i]->index); - return 0; - } - } - start += count; - rest -= count; - pagevec_release(&pvec); - } - return 1; -} - -static int -body_truncate_ok(struct inode * inode, cloff_t aidx) -{ - int result; - cloff_t raidx; - - result = find_fake_appended(inode, &raidx); - return !result && (aidx == raidx); -} -#endif - -static int -update_cryptcompress_size(struct inode * inode, reiser4_key * key, int update_sd) -{ - return (get_key_offset(key) & ((loff_t)(inode_cluster_size(inode)) - 1) ? - 0 : - update_file_size(inode, key, update_sd)); -} - -/* prune cryptcompress file in two steps (exclusive access should be acquired!) - 1) cut all disk clusters but the last one partially truncated, - 2) set zeroes and capture last partially truncated page cluster if the last - one exists, otherwise truncate via prune fake cluster (just decrease i_size) -*/ -static int -prune_cryptcompress(struct inode * inode, loff_t new_size, int update_sd, - cloff_t aidx) -{ - int result = 0; - unsigned nr_zeroes; - loff_t to_prune; - loff_t old_size; - cloff_t ridx; - - hint_t hint; - lock_handle lh; - reiser4_slide_t win; - reiser4_cluster_t clust; - - assert("edward-1140", inode->i_size >= new_size); - assert("edward-1141", schedulable()); - assert("edward-1142", crc_inode_ok(inode)); - assert("edward-1143", current_blocksize == PAGE_CACHE_SIZE); - - init_lh(&lh); - hint_init_zero(&hint); - hint.ext_coord.lh = &lh; - - reiser4_slide_init(&win); - reiser4_cluster_init(&clust, &win); - clust.hint = &hint; - - /* rightmost completely truncated cluster */ - ridx = count_to_nrclust(new_size, inode); - - assert("edward-1174", ridx <= aidx); - old_size = inode->i_size; - if (ridx != aidx) { - result = cut_file_items(inode, - clust_to_off(ridx, inode), - update_sd, - clust_to_off(aidx, inode), - update_cryptcompress_size); - if (result) - goto out; - } - if (!off_to_cloff(new_size, inode)) { - /* no partially truncated clusters */ - assert("edward-1145", inode->i_size == new_size); - goto finish; - } - assert("edward-1146", new_size < inode->i_size); - - to_prune = inode->i_size - new_size; - - /* check if partially truncated cluster is fake */ - result = find_real_disk_cluster(inode, &aidx, ridx); - if (result) - goto out; - if (!aidx) - /* yup, this is fake one */ - goto finish; - - assert("edward-1148", aidx == ridx); - - /* try to capture partially truncated page cluster */ - result = alloc_cluster_pgset(&clust, cluster_nrpages(inode)); - if (result) - goto out; - nr_zeroes = (off_to_pgoff(new_size) ? - PAGE_CACHE_SIZE - off_to_pgoff(new_size) : - 0); - set_window(&clust, &win, inode, new_size, new_size + nr_zeroes); - win.stat = HOLE_WINDOW; - - assert("edward-1149", clust.index == ridx - 1); - - result = prepare_cluster(inode, 0, 0, &clust, PCL_TRUNCATE); - if (result) - goto out; - assert("edward-1151", - clust.dstat == PREP_DISK_CLUSTER || - clust.dstat == UNPR_DISK_CLUSTER); - - assert("edward-1191", inode->i_size == new_size); - assert("edward-1206", body_truncate_ok(inode, ridx)); - finish: - /* drop all the pages that don't have jnodes (i.e. pages - which can not be truncated by cut_file_items() because - of holes represented by fake disk clusters) including - the pages of partially truncated cluster which was - released by prepare_cluster() */ - truncate_inode_pages(inode->i_mapping, new_size); - INODE_SET_FIELD(inode, i_size, new_size); - out: - assert("edward-1334", !result); - assert("edward-1209", - pages_truncate_ok(inode, old_size, count_to_nrpages(new_size))); - assert("edward-1335", - jnodes_truncate_ok(inode, count_to_nrclust(new_size, inode))); - done_lh(&lh); - put_cluster_handle(&clust, TFM_READ); - return result; -} - -static int -start_truncate_fake(struct inode *inode, cloff_t aidx, loff_t new_size, int update_sd) -{ - int result = 0; - int bytes; - - if (new_size > inode->i_size) { - /* append */ - if (inode->i_size < clust_to_off(aidx, inode)) - /* no fake bytes */ - return 0; - bytes = new_size - inode->i_size; - INODE_SET_FIELD(inode, i_size, inode->i_size + bytes); - } - else { - /* prune */ - if (inode->i_size <= clust_to_off(aidx, inode)) - /* no fake bytes */ - return 0; - bytes = inode->i_size - max_count(new_size, clust_to_off(aidx, inode)); - if (!bytes) - return 0; - INODE_SET_FIELD(inode, i_size, inode->i_size - bytes); - /* In the case of fake prune we need to drop page cluster. - There are only 2 cases for partially truncated page: - 1. If is is dirty, therefore it is anonymous - (was dirtied via mmap), and will be captured - later via ->capture(). - 2. If is clean, therefore it is filled by zeroes. - In both cases we don't need to make it dirty and - capture here. - */ - truncate_inode_pages(inode->i_mapping, inode->i_size); - assert("edward-1336", - jnodes_truncate_ok(inode, count_to_nrclust(inode->i_size, inode))); - } - if (update_sd) - result = update_sd_cryptcompress(inode); - return result; -} - -/* This is called in setattr_cryptcompress when it is used to truncate, - and in delete_cryptcompress */ -static int -cryptcompress_truncate(struct inode *inode, /* old size */ - loff_t new_size, /* new size */ - int update_sd) -{ - int result; - cloff_t aidx; - - result = find_fake_appended(inode, &aidx); - if (result) - return result; - assert("edward-1208", - ergo(aidx > 0, inode->i_size > clust_to_off(aidx - 1, inode))); - - result = start_truncate_fake(inode, aidx, new_size, update_sd); - if (result) - return result; - if (inode->i_size == new_size) - /* nothing to truncate anymore */ - return 0; - return (inode->i_size < new_size ? - cryptcompress_append_hole(inode, new_size) : - prune_cryptcompress(inode, new_size, update_sd, aidx)); -} - -/* plugin->u.file.truncate */ -reiser4_internal int -truncate_cryptcompress(struct inode *inode, loff_t new_size) -{ - return 0; -} - -/* page cluser is anonymous if it contains at least one anonymous page */ -static int -capture_anonymous_cluster(reiser4_cluster_t * clust, struct inode * inode) -{ - int result; - - assert("edward-1073", clust != NULL); - assert("edward-1074", inode != NULL); - assert("edward-1075", clust->dstat == INVAL_DISK_CLUSTER); - - result = prepare_cluster(inode, 0, 0, clust, PCL_APPEND); - if (result) - return result; - set_cluster_pages_dirty(clust); - - result = try_capture_cluster(clust, inode); - put_hint_cluster(clust, inode, ZNODE_WRITE_LOCK); - if (result) - release_cluster_pages_and_jnode(clust); - return result; -} - -#define MAX_CLUSTERS_TO_CAPTURE(inode) (1024 >> inode_cluster_shift(inode)) - -/* read lock should be acquired */ -static int -capture_anonymous_clusters(struct address_space * mapping, pgoff_t * index, int to_capture) -{ - int result = 0; - int found; - int progress = 0; - struct page * page = NULL; - hint_t hint; - lock_handle lh; - reiser4_cluster_t clust; - - assert("edward-1127", mapping != NULL); - assert("edward-1128", mapping->host != NULL); - - init_lh(&lh); - hint_init_zero(&hint); - hint.ext_coord.lh = &lh; - reiser4_cluster_init(&clust, 0); - clust.hint = &hint; - - result = alloc_cluster_pgset(&clust, cluster_nrpages(mapping->host)); - if (result) - goto out; - - while (to_capture > 0) { - found = find_get_pages_tag(mapping, index, PAGECACHE_TAG_REISER4_MOVED, 1, &page); - if (!found) { - *index = (pgoff_t) - 1; - break; - } - assert("edward-1109", page != NULL); - - move_cluster_forward(&clust, mapping->host, page->index, &progress); - result = capture_anonymous_cluster(&clust, mapping->host); - page_cache_release(page); - if (result) - break; - to_capture --; - } - if (result) { - warning("edward-1077", "Cannot capture anon pages: result=%i (captured=%d)\n", - result, - ((__u32)MAX_CLUSTERS_TO_CAPTURE(mapping->host)) - to_capture); - } else { - /* something had to be found */ - assert("edward-1078", to_capture <= MAX_CLUSTERS_TO_CAPTURE(mapping->host)); - if (to_capture <= 0) - /* there may be left more pages */ - __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); - } - out: - done_lh(&lh); - put_cluster_handle(&clust, TFM_READ); - return result; -} - -/* Check mapping for existence of not captured dirty pages. - This returns !0 if either page tree contains pages tagged - PAGECACHE_TAG_REISER4_MOVED */ -static int -crc_inode_has_anon_pages(struct inode *inode) -{ - return mapping_tagged(inode->i_mapping, PAGECACHE_TAG_REISER4_MOVED); -} - -/* plugin->u.file.capture */ -reiser4_internal int -capture_cryptcompress(struct inode *inode, struct writeback_control *wbc) -{ - int result; - int to_capture; - pgoff_t nrpages; - pgoff_t index = 0; - cryptcompress_info_t * info; - - if (!crc_inode_has_anon_pages(inode)) - return 0; - - info = cryptcompress_inode_data(inode); - nrpages = count_to_nrpages(i_size_read(inode)); - - if (wbc->sync_mode != WB_SYNC_ALL) - to_capture = min_count(wbc->nr_to_write, MAX_CLUSTERS_TO_CAPTURE(inode)); - else - to_capture = MAX_CLUSTERS_TO_CAPTURE(inode); - do { - reiser4_context ctx; - - if (is_in_reiser4_context()) { - /* FIXME-EDWARD: REMOVEME */ - all_grabbed2free(); - - /* It can be in the context of write system call from - balance_dirty_pages() */ - if (down_read_trylock(&info->lock) == 0) { - result = RETERR(-EBUSY); - break; - } - } else - down_read(&info->lock); - - init_context(&ctx, inode->i_sb); - ctx.nobalance = 1; - - assert("edward-1079", lock_stack_isclean(get_current_lock_stack())); - - LOCK_CNT_INC(inode_sem_r); - - result = capture_anonymous_clusters(inode->i_mapping, &index, to_capture); - - up_read(&info->lock); - - LOCK_CNT_DEC(inode_sem_r); - - if (result != 0 || wbc->sync_mode != WB_SYNC_ALL) { - reiser4_exit_context(&ctx); - break; - } - result = txnmgr_force_commit_all(inode->i_sb, 0); - reiser4_exit_context(&ctx); - } while (result == 0 && index < nrpages); - - return result; -} - -/* plugin->u.file.mmap */ -reiser4_internal int -mmap_cryptcompress(struct file * file, struct vm_area_struct * vma) -{ - return -ENOSYS; - //return generic_file_mmap(file, vma); -} - - -/* plugin->u.file.release */ -/* plugin->u.file.get_block */ -/* This function is used for ->bmap() VFS method in reiser4 address_space_operations */ -reiser4_internal int -get_block_cryptcompress(struct inode *inode, sector_t block, struct buffer_head *bh_result, int create UNUSED_ARG) -{ - if (current_blocksize != inode_cluster_size(inode)) - return RETERR(-EINVAL); - else { - int result; - reiser4_key key; - hint_t hint; - lock_handle lh; - item_plugin *iplug; - - assert("edward-1166", 0); - assert("edward-420", create == 0); - key_by_inode_cryptcompress(inode, (loff_t)block * current_blocksize, &key); - init_lh(&lh); - hint_init_zero(&hint); - hint.ext_coord.lh = &lh; - result = find_cluster_item(&hint, &key, ZNODE_READ_LOCK, 0, FIND_EXACT, 0); - if (result != CBK_COORD_FOUND) { - done_lh(&lh); - return result; - } - result = zload(hint.ext_coord.coord.node); - if (unlikely(result)) { - done_lh(&lh); - return result; - } - iplug = item_plugin_by_coord(&hint.ext_coord.coord); - - assert("edward-421", iplug == item_plugin_by_id(CTAIL_ID)); - - if (iplug->s.file.get_block) - result = iplug->s.file.get_block(&hint.ext_coord.coord, block, bh_result); - else - result = RETERR(-EINVAL); - - zrelse(hint.ext_coord.coord.node); - done_lh(&lh); - return result; - } -} - -/* plugin->u.file.delete method - see plugin.h for description */ -reiser4_internal int -delete_cryptcompress(struct inode *inode) -{ - int result; - - assert("edward-429", inode->i_nlink == 0); - - if (inode->i_size) { - result = cryptcompress_truncate(inode, 0, 0); - if (result) { - warning("edward-430", "cannot truncate cryptcompress file %lli: %i", - (unsigned long long)get_inode_oid(inode), result); - return result; - } - } - return delete_object(inode, 0); -} - -/* plugin->u.file.pre_delete method - see plugin.h for description */ -reiser4_internal int -pre_delete_cryptcompress(struct inode *inode) -{ - return cryptcompress_truncate(inode, 0, 0); -} - -/* plugin->u.file.setattr method - see plugin.h for description */ -reiser4_internal int -setattr_cryptcompress(struct inode *inode, /* Object to change attributes */ - struct iattr *attr /* change description */ ) -{ - int result; - - result = check_cryptcompress(inode); - if (result) - return result; - if (attr->ia_valid & ATTR_SIZE) { - /* EDWARD-FIXME-HANS: VS-FIXME-HANS: - Q: this case occurs when? truncate? - A: yes - - Q: If so, why isn't this code in truncate itself instead of here? - - A: because vfs calls fs's truncate after it has called truncate_inode_pages to get rid of pages - corresponding to part of file being truncated. In reiser4 it may cause existence of unallocated - extents which do not have jnodes. Flush code does not expect that. Solution of this problem is - straightforward. As vfs's truncate is implemented using setattr operation (common implementaion of - which calls truncate_inode_pages and fs's truncate in case when size of file changes) - it seems - reasonable to have reiser4_setattr which will take care of removing pages, jnodes and extents - simultaneously in case of truncate. - Q: do you think implementing truncate using setattr is ugly, - and vfs needs improving, or is there some sense in which this is a good design? - - A: VS-FIXME-HANS: - */ - - /* truncate does reservation itself and requires exclusive access obtained */ - if (inode->i_size != attr->ia_size) { - loff_t old_size; - cryptcompress_info_t * info = cryptcompress_inode_data(inode); - - down_write(&info->lock); - LOCK_CNT_INC(inode_sem_w); - - inode_check_scale(inode, inode->i_size, attr->ia_size); - - old_size = inode->i_size; - - result = cryptcompress_truncate(inode, attr->ia_size, 1/* update stat data */); - if (result) { - warning("edward-1192", "truncate_cryptcompress failed: oid %lli, " - "old size %lld, new size %lld, retval %d", - (unsigned long long)get_inode_oid(inode), - old_size, attr->ia_size, result); - } - up_write(&info->lock); - LOCK_CNT_DEC(inode_sem_w); - } else - result = 0; - } else - result = setattr_common(inode, attr); - return result; -} - -static int -save_len_cryptcompress_plugin(struct inode * inode, reiser4_plugin * plugin) -{ - assert("edward-457", inode != NULL); - assert("edward-458", plugin != NULL); - assert("edward-459", plugin->h.id == CRC_FILE_PLUGIN_ID); - return 0; -} - -static int -load_cryptcompress_plugin(struct inode * inode, reiser4_plugin * plugin, char **area, int *len) -{ - assert("edward-455", inode != NULL); - assert("edward-456", (reiser4_inode_data(inode)->pset != NULL)); - - plugin_set_file(&reiser4_inode_data(inode)->pset, file_plugin_by_id(CRC_FILE_PLUGIN_ID)); - return 0; -} - -static int -change_crypto_file(struct inode * inode, reiser4_plugin * plugin) -{ - /* cannot change object plugin of already existing object */ - return RETERR(-EINVAL); -} - -struct reiser4_plugin_ops cryptcompress_plugin_ops = { - .load = load_cryptcompress_plugin, - .save_len = save_len_cryptcompress_plugin, - .save = NULL, - .alignment = 8, - .change = change_crypto_file -}; - -/* - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - scroll-step: 1 - End: -*/ diff -L fs/reiser4/plugin/cryptcompress.h -puN fs/reiser4/plugin/cryptcompress.h~reiser4-big-update /dev/null --- devel/fs/reiser4/plugin/cryptcompress.h +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,532 +0,0 @@ -/* Copyright 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */ -/* See http://www.namesys.com/cryptcompress_design.html */ - -#if !defined( __FS_REISER4_CRYPTCOMPRESS_H__ ) -#define __FS_REISER4_CRYPTCOMPRESS_H__ - -#include "compress/compress.h" - -#include -#include -#include - -#define MIN_CLUSTER_SIZE PAGE_CACHE_SIZE -#define MIN_CLUSTER_SHIFT PAGE_CACHE_SHIFT -#define MAX_CLUSTER_SHIFT 16 -#define MAX_CLUSTER_NRPAGES (1U << MAX_CLUSTER_SHIFT >> PAGE_CACHE_SHIFT) -#define DEFAULT_CLUSTER_SHIFT 0 -#define DC_CHECKSUM_SIZE 4 -#define MIN_CRYPTO_BLOCKSIZE 8 - -#if REISER4_DEBUG -static inline int -cluster_shift_ok (int shift) -{ - return (shift >= MIN_CLUSTER_SHIFT) && (shift <= MAX_CLUSTER_SHIFT); -} -#endif - -/* Set of transform id's supported by reiser4, - each transform is implemented by appropriate transform plugin: */ -typedef enum { - CRYPTO_TFM, /* crypto plugin */ - DIGEST_TFM, /* digest plugin */ - COMPRESS_TFM, /* compression plugin */ - LAST_TFM -} reiser4_tfm; - -typedef struct tfm_stream { - __u8 * data; - size_t size; -} tfm_stream_t; - -typedef enum { - INPUT_STREAM, - OUTPUT_STREAM, - LAST_STREAM -} tfm_stream_id; - -typedef tfm_stream_t * tfm_unit[LAST_STREAM]; - -static inline __u8 * -ts_data(tfm_stream_t * stm) -{ - assert("edward-928", stm != NULL); - return stm->data; -} - -static inline size_t -ts_size(tfm_stream_t * stm) -{ - assert("edward-929", stm != NULL); - return stm->size; -} - -static inline void -set_ts_size(tfm_stream_t * stm, size_t size) -{ - assert("edward-930", stm != NULL); - - stm->size = size; -} - -static inline int -alloc_ts(tfm_stream_t ** stm) -{ - assert("edward-931", stm); - assert("edward-932", *stm == NULL); - - *stm = reiser4_kmalloc(sizeof ** stm, GFP_KERNEL); - if (*stm == NULL) - return -ENOMEM; - memset(*stm, 0, sizeof ** stm); - return 0; -} - -static inline void -free_ts(tfm_stream_t * stm) -{ - assert("edward-933", !ts_data(stm)); - assert("edward-934", !ts_size(stm)); - - reiser4_kfree(stm); -} - -static inline int -alloc_ts_data(tfm_stream_t * stm, size_t size) -{ - assert("edward-935", !ts_data(stm)); - assert("edward-936", !ts_size(stm)); - assert("edward-937", size != 0); - - stm->data = vmalloc(size); - if (!stm->data) - return -ENOMEM; - set_ts_size(stm, size); - return 0; -} - -static inline void -free_ts_data(tfm_stream_t * stm) -{ - assert("edward-938", equi(ts_data(stm), ts_size(stm))); - - if (ts_data(stm)) - vfree(ts_data(stm)); - memset(stm, 0, sizeof *stm); -} - -/* Write modes for item conversion in flush convert phase */ -typedef enum { - CRC_APPEND_ITEM = 1, - CRC_OVERWRITE_ITEM = 2, - CRC_CUT_ITEM = 3 -} crc_write_mode_t; - -typedef enum { - PCL_UNKNOWN = 0, /* invalid option */ - PCL_APPEND = 1, /* append and/or overwrite */ - PCL_TRUNCATE = 2 /* truncate */ -} page_cluster_op; - -/* Reiser4 file write/read transforms page cluster into disk cluster (and back) - using crypto/compression transforms implemented by reiser4 transform plugins. - Before each transform we allocate a pair of streams (tfm_unit) and assemble - page cluster into the input one. After transform we split output stream into - a set of items (disk cluster). -*/ -typedef struct tfm_cluster{ - coa_set coa; - tfm_unit tun; - int uptodate; - int len; -} tfm_cluster_t; - -static inline coa_t -get_coa(tfm_cluster_t * tc, reiser4_compression_id id) -{ - return tc->coa[id]; -} - -static inline void -set_coa(tfm_cluster_t * tc, reiser4_compression_id id, coa_t coa) -{ - tc->coa[id] = coa; -} - -static inline int -alloc_coa(tfm_cluster_t * tc, compression_plugin * cplug, tfm_action act) -{ - coa_t coa; - - coa = cplug->alloc(act); - if (IS_ERR(coa)) - return PTR_ERR(coa); - set_coa(tc, cplug->h.id, coa); - return 0; -} - -static inline void -free_coa_set(tfm_cluster_t * tc, tfm_action act) -{ - reiser4_compression_id i; - compression_plugin * cplug; - - assert("edward-810", tc != NULL); - - for(i = 0; i < LAST_COMPRESSION_ID; i++) { - if (!get_coa(tc, i)) - continue; - cplug = compression_plugin_by_id(i); - assert("edward-812", cplug->free != NULL); - cplug->free(get_coa(tc, i), act); - set_coa(tc, i, 0); - } - return; -} - -static inline tfm_stream_t * -tfm_stream (tfm_cluster_t * tc, tfm_stream_id id) -{ - return tc->tun[id]; -} - -static inline void -set_tfm_stream (tfm_cluster_t * tc, tfm_stream_id id, tfm_stream_t * ts) -{ - tc->tun[id] = ts; -} - -static inline __u8 * -tfm_stream_data (tfm_cluster_t * tc, tfm_stream_id id) -{ - return ts_data(tfm_stream(tc, id)); -} - -static inline void -set_tfm_stream_data(tfm_cluster_t * tc, tfm_stream_id id, __u8 * data) -{ - tfm_stream(tc, id)->data = data; -} - -static inline size_t -tfm_stream_size (tfm_cluster_t * tc, tfm_stream_id id) -{ - return ts_size(tfm_stream(tc, id)); -} - -static inline void -set_tfm_stream_size(tfm_cluster_t * tc, tfm_stream_id id, size_t size) -{ - tfm_stream(tc, id)->size = size; -} - -static inline int -alloc_tfm_stream(tfm_cluster_t * tc, size_t size, tfm_stream_id id) -{ - assert("edward-939", tc != NULL); - assert("edward-940", !tfm_stream(tc, id)); - - tc->tun[id] = reiser4_kmalloc(sizeof(tfm_stream_t), GFP_KERNEL); - if (!tc->tun[id]) - return -ENOMEM; - memset(tfm_stream(tc, id), 0, sizeof(tfm_stream_t)); - return alloc_ts_data(tfm_stream(tc, id), size); -} - -static inline int -realloc_tfm_stream(tfm_cluster_t * tc, size_t size, tfm_stream_id id) -{ - assert("edward-941", tfm_stream_size(tc, id) < size); - free_ts_data(tfm_stream(tc, id)); - return alloc_ts_data(tfm_stream(tc, id), size); -} - -static inline void -free_tfm_stream(tfm_cluster_t * tc, tfm_stream_id id) -{ - free_ts_data(tfm_stream(tc, id)); - free_ts(tfm_stream(tc, id)); - set_tfm_stream(tc, id, 0); -} - -static inline void -free_tfm_unit(tfm_cluster_t * tc) -{ - tfm_stream_id id; - for (id = 0; id < LAST_STREAM; id++) { - if (!tfm_stream(tc, id)) - continue; - free_tfm_stream(tc, id); - } -} - -static inline void -put_tfm_cluster(tfm_cluster_t * tc, tfm_action act) -{ - assert("edward-942", tc != NULL); - free_coa_set(tc, act); - free_tfm_unit(tc); -} - -static inline int -tfm_cluster_is_uptodate (tfm_cluster_t * tc) -{ - assert("edward-943", tc != NULL); - assert("edward-944", tc->uptodate == 0 || tc->uptodate == 1); - return (tc->uptodate == 1); -} - -static inline void -tfm_cluster_set_uptodate (tfm_cluster_t * tc) -{ - assert("edward-945", tc != NULL); - assert("edward-946", tc->uptodate == 0 || tc->uptodate == 1); - tc->uptodate = 1; - return; -} - -static inline void -tfm_cluster_clr_uptodate (tfm_cluster_t * tc) -{ - assert("edward-947", tc != NULL); - assert("edward-948", tc->uptodate == 0 || tc->uptodate == 1); - tc->uptodate = 0; - return; -} - -static inline int -tfm_stream_is_set(tfm_cluster_t * tc, tfm_stream_id id) -{ - return (tfm_stream(tc, id) && - tfm_stream_data(tc, id) && - tfm_stream_size(tc, id)); -} - -static inline int -tfm_cluster_is_set(tfm_cluster_t * tc) -{ - int i; - for (i = 0; i < LAST_STREAM; i++) - if (!tfm_stream_is_set(tc, i)) - return 0; - return 1; -} - -static inline void -alternate_streams(tfm_cluster_t * tc) -{ - tfm_stream_t * tmp = tfm_stream(tc, INPUT_STREAM); - - set_tfm_stream(tc, INPUT_STREAM, tfm_stream(tc, OUTPUT_STREAM)); - set_tfm_stream(tc, OUTPUT_STREAM, tmp); -} - -/* a kind of data that we can write to the window */ -typedef enum { - DATA_WINDOW, /* the data we copy form user space */ - HOLE_WINDOW /* zeroes if we write hole */ -} window_stat; - -/* Sliding window of cluster size which should be set to the approprite position - (defined by cluster index) in a file before page cluster modification by - file_write. Then we translate file size, offset to write from, number of - bytes to write, etc.. to the following configuration needed to estimate - number of pages to read before write, etc... -*/ -typedef struct reiser4_slide { - unsigned off; /* offset we start to write/truncate from */ - unsigned count; /* number of bytes (zeroes) to write/truncate */ - unsigned delta; /* number of bytes to append to the hole */ - window_stat stat; /* a kind of data to write to the window */ -} reiser4_slide_t; - -/* The following is a set of possible disk cluster states */ -typedef enum { - INVAL_DISK_CLUSTER,/* unknown state */ - PREP_DISK_CLUSTER, /* disk cluster got converted by flush - at least 1 time */ - UNPR_DISK_CLUSTER, /* disk cluster just created and should be - converted by flush */ - FAKE_DISK_CLUSTER /* disk cluster doesn't exist neither in memory - nor on disk */ -} disk_cluster_stat; - -/* - While implementing all transforms (from page to disk cluster, and back) - reiser4 cluster manager fills the following structure incapsulating pointers - to all the clusters for the same index including the sliding window above -*/ -typedef struct reiser4_cluster{ - tfm_cluster_t tc; /* transform cluster */ - int nr_pages; /* number of pages */ - struct page ** pages; /* page cluster */ - page_cluster_op op; /* page cluster operation */ - struct file * file; - hint_t * hint; /* disk cluster item for traversal */ - disk_cluster_stat dstat; /* state of the current disk cluster */ - cloff_t index; /* offset in the units of cluster size */ - reiser4_slide_t * win; /* sliding window of cluster size */ - int reserved; /* this indicates that space for disk - cluster modification is reserved */ -#if REISER4_DEBUG - reiser4_context * ctx; - int reserved_prepped; - int reserved_unprepped; -#endif -} reiser4_cluster_t; - -static inline void -reset_cluster_pgset(reiser4_cluster_t * clust, int nrpages) -{ - assert("edward-1057", clust->pages != NULL); - memset(clust->pages, 0, sizeof(*clust->pages) * nrpages); -} - -static inline int -alloc_cluster_pgset(reiser4_cluster_t * clust, int nrpages) -{ - assert("edward-949", clust != NULL); - assert("edward-950", nrpages != 0 && nrpages <= MAX_CLUSTER_NRPAGES); - - clust->pages = reiser4_kmalloc(sizeof(*clust->pages) * nrpages, GFP_KERNEL); - if (!clust->pages) - return RETERR(-ENOMEM); - reset_cluster_pgset(clust, nrpages); - return 0; -} - -static inline void -free_cluster_pgset(reiser4_cluster_t * clust) -{ - assert("edward-951", clust->pages != NULL); - reiser4_kfree(clust->pages); -} - -static inline void -put_cluster_handle(reiser4_cluster_t * clust, tfm_action act) -{ - assert("edward-435", clust != NULL); - - put_tfm_cluster(&clust->tc, act); - if (clust->pages) - free_cluster_pgset(clust); - memset(clust, 0, sizeof *clust); -} - -/* security attributes supposed to be stored on disk - are loaded by stat-data methods (see plugin/item/static_stat.c */ -typedef struct crypto_stat { - __u8 * keyid; /* pointer to a fingerprint */ - __u16 keysize; /* key size, bits */ - __u32 * expkey; -} crypto_stat_t; - -/* cryptcompress specific part of reiser4_inode */ -typedef struct cryptcompress_info { - struct rw_semaphore lock; - struct crypto_tfm *tfm[LAST_TFM]; - crypto_stat_t * crypt; -} cryptcompress_info_t; - -cryptcompress_info_t *cryptcompress_inode_data(const struct inode * inode); -int equal_to_rdk(znode *, const reiser4_key *); -int goto_right_neighbor(coord_t *, lock_handle *); -int load_file_hint(struct file *, hint_t *); -void save_file_hint(struct file *, const hint_t *); - -/* declarations of functions implementing methods of cryptcompress object plugin */ -void init_inode_data_cryptcompress(struct inode *inode, reiser4_object_create_data *crd, int create); -int create_cryptcompress(struct inode *, struct inode *, reiser4_object_create_data *); -int open_cryptcompress(struct inode * inode, struct file * file); -int truncate_cryptcompress(struct inode *, loff_t size); -int readpage_cryptcompress(void *, struct page *); -int capture_cryptcompress(struct inode *inode, struct writeback_control *wbc); -ssize_t read_cryptcompress(struct file * file, char *buf, size_t size, loff_t * off); -ssize_t write_cryptcompress(struct file *, const char *buf, size_t size, loff_t *off); -int release_cryptcompress(struct inode *inode, struct file *); -int mmap_cryptcompress(struct file *, struct vm_area_struct *vma); -int get_block_cryptcompress(struct inode *, sector_t block, struct buffer_head *bh_result, int create); -int flow_by_inode_cryptcompress(struct inode *, char *buf, int user, loff_t, loff_t, rw_op, flow_t *); -int key_by_inode_cryptcompress(struct inode *, loff_t off, reiser4_key *); -int delete_cryptcompress(struct inode *); -int owns_item_cryptcompress(const struct inode *, const coord_t *); -int setattr_cryptcompress(struct inode *, struct iattr *); -void readpages_cryptcompress(struct file *, struct address_space *, struct list_head *pages); -void init_inode_data_cryptcompress(struct inode *, reiser4_object_create_data *, int create); -int pre_delete_cryptcompress(struct inode *); -int cut_tree_worker_cryptcompress(tap_t * tap, const reiser4_key * from_key, - const reiser4_key * to_key, reiser4_key * smallest_removed, - struct inode * object, int, int*); -void hint_init_zero(hint_t *); -void destroy_inode_cryptcompress(struct inode * inode); -int crc_inode_ok(struct inode * inode); - -static inline struct crypto_tfm * -inode_get_tfm (struct inode * inode, reiser4_tfm tfm) -{ - return cryptcompress_inode_data(inode)->tfm[tfm]; -} - -static inline struct crypto_tfm * -inode_get_crypto (struct inode * inode) -{ - return (inode_get_tfm(inode, CRYPTO_TFM)); -} - -static inline struct crypto_tfm * -inode_get_digest (struct inode * inode) -{ - return (inode_get_tfm(inode, DIGEST_TFM)); -} - -static inline unsigned int -crypto_blocksize(struct inode * inode) -{ - assert("edward-758", inode_get_tfm(inode, CRYPTO_TFM) != NULL); - return crypto_tfm_alg_blocksize(inode_get_tfm(inode, CRYPTO_TFM)); -} - -static inline compression_plugin * -dual_compression_plugin(compression_plugin * cplug) -{ - return compression_plugin_by_id(cplug->dual); -} - -#define REGISTER_NONE_ALG(ALG, TFM) \ -static int alloc_none_ ## ALG (struct inode * inode) \ -{ \ - cryptcompress_info_t * info; \ - assert("edward-760", inode != NULL); \ - \ - info = cryptcompress_inode_data(inode); \ - \ - \ - cryptcompress_inode_data(inode)->tfm[TFM ## _TFM] = NULL; \ - return 0; \ - \ -} \ -static void free_none_ ## ALG (struct inode * inode) \ -{ \ - cryptcompress_info_t * info; \ - assert("edward-761", inode != NULL); \ - \ - info = cryptcompress_inode_data(inode); \ - \ - assert("edward-762", info != NULL); \ - \ - info->tfm[TFM ## _TFM] = NULL; \ -} - -#endif /* __FS_REISER4_CRYPTCOMPRESS_H__ */ - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - scroll-step: 1 - End: -*/ diff -puN fs/reiser4/plugin/digest.c~reiser4-big-update fs/reiser4/plugin/digest.c --- devel/fs/reiser4/plugin/digest.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/digest.c 2005-09-15 19:51:08.000000000 -0700 @@ -5,7 +5,7 @@ #include "../debug.h" #include "plugin_header.h" #include "plugin.h" -#include "cryptcompress.h" +#include "file/cryptcompress.h" #include @@ -22,7 +22,7 @@ digest_plugin digest_plugins[LAST_DIGEST .pops = NULL, .label = "none", .desc = "trivial digest", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .dsize = NONE_DIGEST_SIZE, .alloc = alloc_none_digest, diff -L fs/reiser4/plugin/dir/dir.c -puN fs/reiser4/plugin/dir/dir.c~reiser4-big-update /dev/null --- devel/fs/reiser4/plugin/dir/dir.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,1886 +0,0 @@ -/* Copyright 2001, 2002, 2003, 2004 by Hans Reiser, licensing governed by - * reiser4/README */ - -/* Methods of directory plugin. */ - -#include "../../forward.h" -#include "../../debug.h" -#include "../../spin_macros.h" -#include "../plugin_header.h" -#include "../../key.h" -#include "../../kassign.h" -#include "../../coord.h" -#include "../../type_safe_list.h" -#include "../plugin.h" -#include "dir.h" -#include "../item/item.h" -#include "../security/perm.h" -#include "../../jnode.h" -#include "../../znode.h" -#include "../../tap.h" -#include "../../vfs_ops.h" -#include "../../inode.h" -#include "../../super.h" -#include "../../safe_link.h" -#include "../object.h" - -#include "hashed_dir.h" -#include "pseudo_dir.h" - -#include /* for __u?? */ -#include /* for struct file */ -#include -#include /* for struct dentry */ - -/* helper function. Standards require that for many file-system operations - on success ctime and mtime of parent directory is to be updated. */ -reiser4_internal int -reiser4_update_dir(struct inode *dir) -{ - assert("nikita-2525", dir != NULL); - - dir->i_ctime = dir->i_mtime = CURRENT_TIME; - return reiser4_mark_inode_dirty(dir); -} - -/* estimate disk space necessary to add a link from @parent to @object. */ -static reiser4_block_nr common_estimate_link( - struct inode *parent /* parent directory */, - struct inode *object /* object to which new link is being cerated */) -{ - reiser4_block_nr res = 0; - file_plugin *fplug; - dir_plugin *dplug; - - assert("vpf-317", object != NULL); - assert("vpf-318", parent != NULL ); - - fplug = inode_file_plugin(object); - dplug = inode_dir_plugin(parent); - /* VS-FIXME-HANS: why do we do fplug->estimate.update(object) twice instead of multiplying by 2? */ - /* reiser4_add_nlink(object) */ - res += fplug->estimate.update(object); - /* add_entry(parent) */ - res += dplug->estimate.add_entry(parent); - /* reiser4_del_nlink(object) */ - res += fplug->estimate.update(object); - /* update_dir(parent) */ - res += inode_file_plugin(parent)->estimate.update(parent); - /* safe-link */ - res += estimate_one_item_removal(tree_by_inode(object)); - - return res; -} - -/* add link from @parent directory to @existing object. - - . get plugins - . check permissions - . check that "existing" can hold yet another link - . start transaction - . add link to "existing" - . add entry to "parent" - . if last step fails, remove link from "existing" - -*/ -static int -link_common(struct inode *parent /* parent directory */ , - struct dentry *existing /* dentry of object to which - * new link is being - * cerated */ , - struct dentry *newname /* new name */ ) -{ - int result; - struct inode *object; - dir_plugin *parent_dplug; - reiser4_dir_entry_desc entry; - reiser4_object_create_data data; - reiser4_block_nr reserve; - - assert("nikita-1431", existing != NULL); - assert("nikita-1432", parent != NULL); - assert("nikita-1433", newname != NULL); - - object = existing->d_inode; - assert("nikita-1434", object != NULL); - - /* check for race with create_object() */ - if (inode_get_flag(object, REISER4_IMMUTABLE)) - return RETERR(-E_REPEAT); - - /* links to directories are not allowed if file-system - logical name-space should be ADG */ - if (S_ISDIR(object->i_mode) && reiser4_is_set(parent->i_sb, REISER4_ADG)) - return RETERR(-EISDIR); - - /* check permissions */ - result = perm_chk(parent, link, existing, parent, newname); - if (result != 0) - return result; - - parent_dplug = inode_dir_plugin(parent); - - memset(&entry, 0, sizeof entry); - entry.obj = object; - - data.mode = object->i_mode; - data.id = inode_file_plugin(object)->h.id; - - reserve = common_estimate_link(parent, existing->d_inode); - if ((__s64)reserve < 0) - return reserve; - - if (reiser4_grab_space(reserve, BA_CAN_COMMIT)) - return RETERR(-ENOSPC); - - /* - * Subtle race handling: sys_link() doesn't take i_sem on @parent. It - * means that link(2) can race against unlink(2) or rename(2), and - * inode is dead (->i_nlink == 0) when reiser4_link() is entered. - * - * For such inode we have to undo special processing done in - * reiser4_unlink() viz. creation of safe-link. - */ - if (unlikely(object->i_nlink == 0)) { - result = safe_link_del(tree_by_inode(object), - get_inode_oid(object), SAFE_UNLINK); - if (result != 0) - return result; - } - - result = reiser4_add_nlink(object, parent, 1); - if (result == 0) { - /* add entry to the parent */ - result = parent_dplug->add_entry(parent, newname, &data, &entry); - if (result != 0) { - /* failure to add entry to the parent, remove - link from "existing" */ - reiser4_del_nlink(object, parent, 1); - /* now, if this fails, we have a file with too - big nlink---space leak, much better than - directory entry pointing to nowhere */ - /* may be it should be recorded somewhere, but - if addition of link to parent and update of - object's stat data both failed, chances are - that something is going really wrong */ - } - } - if (result == 0) { - atomic_inc(&object->i_count); - /* Upon successful completion, link() shall mark for update - the st_ctime field of the file. Also, the st_ctime and - st_mtime fields of the directory that contains the new - entry shall be marked for update. --SUS - */ - result = reiser4_update_dir(parent); - } - return result; -} - -/* estimate disk space necessary to remove a link between @parent and - * @object. */ -static reiser4_block_nr common_estimate_unlink ( - struct inode *parent /* parent directory */, - struct inode *object /* object to which new link is being cerated */) -{ - reiser4_block_nr res = 0; - file_plugin *fplug; - dir_plugin *dplug; - - assert("vpf-317", object != NULL); - assert("vpf-318", parent != NULL ); - - fplug = inode_file_plugin(object); - dplug = inode_dir_plugin(parent); - - /* rem_entry(parent) */ - res += dplug->estimate.rem_entry(parent); - /* reiser4_del_nlink(object) */ - res += fplug->estimate.update(object); - /* update_dir(parent) */ - res += inode_file_plugin(parent)->estimate.update(parent); - /* fplug->unlink */ - res += fplug->estimate.unlink(object, parent); - /* safe-link */ - res += estimate_one_insert_item(tree_by_inode(object)); - - return res; -} - -/* grab space for unlink. */ -static int -unlink_check_and_grab(struct inode *parent, struct dentry *victim) -{ - file_plugin *fplug; - struct inode *child; - int result; - - result = 0; - child = victim->d_inode; - fplug = inode_file_plugin(child); - - /* check for race with create_object() */ - if (inode_get_flag(child, REISER4_IMMUTABLE)) - return RETERR(-E_REPEAT); - /* object being deleted should have stat data */ - assert("vs-949", !inode_get_flag(child, REISER4_NO_SD)); - - /* check permissions */ - result = perm_chk(parent, unlink, parent, victim); - if (result != 0) - return result; - - /* ask object plugin */ - if (fplug->can_rem_link != NULL && !fplug->can_rem_link(child)) - return RETERR(-ENOTEMPTY); - - result = (int)common_estimate_unlink(parent, child); - if (result < 0) - return result; - - return reiser4_grab_reserved(child->i_sb, result, BA_CAN_COMMIT); -} - -/* remove link from @parent directory to @victim object. - - . get plugins - . find entry in @parent - . check permissions - . decrement nlink on @victim - . if nlink drops to 0, delete object -*/ -static int -unlink_common(struct inode *parent /* parent object */ , - struct dentry *victim /* name being removed from @parent */) -{ - int result; - struct inode *object; - file_plugin *fplug; - - object = victim->d_inode; - fplug = inode_file_plugin(object); - assert("nikita-2882", fplug->detach != NULL); - - result = unlink_check_and_grab(parent, victim); - if (result != 0) - return result; - - result = fplug->detach(object, parent); - if (result == 0) { - dir_plugin *parent_dplug; - reiser4_dir_entry_desc entry; - - parent_dplug = inode_dir_plugin(parent); - memset(&entry, 0, sizeof entry); - - /* first, delete directory entry */ - result = parent_dplug->rem_entry(parent, victim, &entry); - if (result == 0) { - /* - * if name was removed successfully, we _have_ to - * return 0 from this function, because upper level - * caller (vfs_{rmdir,unlink}) expect this. - */ - /* now that directory entry is removed, update - * stat-data */ - reiser4_del_nlink(object, parent, 1); - /* Upon successful completion, unlink() shall mark for - update the st_ctime and st_mtime fields of the - parent directory. Also, if the file's link count is - not 0, the st_ctime field of the file shall be - marked for update. --SUS */ - reiser4_update_dir(parent); - /* add safe-link for this file */ - if (object->i_nlink == 0) - safe_link_add(object, SAFE_UNLINK); - } - } - - if (unlikely(result != 0)) { - if (result != -ENOMEM) - warning("nikita-3398", "Cannot unlink %llu (%i)", - (unsigned long long)get_inode_oid(object), - result); - /* if operation failed commit pending inode modifications to - * the stat-data */ - reiser4_update_sd(object); - reiser4_update_sd(parent); - } - - reiser4_release_reserved(object->i_sb); - - /* @object's i_ctime was updated by ->rem_link() method(). */ - - return result; -} - -/* Estimate the maximum amount of nodes will be allocated or changed for: - - insert an in the parent entry - - update the SD of parent - - estimate child creation -*/ -static reiser4_block_nr common_estimate_create_child( - struct inode *parent, /* parent object */ - struct inode *object /* object */) -{ - assert("vpf-309", parent != NULL); - assert("vpf-307", object != NULL); - - return - /* object creation estimation */ - inode_file_plugin(object)->estimate.create(object) + - /* stat data of parent directory estimation */ - inode_file_plugin(parent)->estimate.update(parent) + - /* adding entry estimation */ - inode_dir_plugin(parent)->estimate.add_entry(parent) + - /* to undo in the case of failure */ - inode_dir_plugin(parent)->estimate.rem_entry(parent); -} - -/* Create child in directory. - - . get object's plugin - . get fresh inode - . initialize inode - . add object's stat-data - . initialize object's directory - . add entry to the parent - . instantiate dentry - -*/ -/* ->create_child method of directory plugin */ -static int -create_child_common(reiser4_object_create_data * data /* parameters - * of new - * object */, - struct inode ** retobj) -{ - int result; - - struct dentry *dentry; /* parent object */ - struct inode *parent; /* new name */ - - dir_plugin *par_dir; /* directory plugin on the parent */ - dir_plugin *obj_dir; /* directory plugin on the new object */ - file_plugin *obj_plug; /* object plugin on the new object */ - struct inode *object; /* new object */ - reiser4_block_nr reserve; - - reiser4_dir_entry_desc entry; /* new directory entry */ - - assert("nikita-1420", data != NULL); - parent = data->parent; - dentry = data->dentry; - - assert("nikita-1418", parent != NULL); - assert("nikita-1419", dentry != NULL); - par_dir = inode_dir_plugin(parent); - /* check permissions */ - result = perm_chk(parent, create, parent, dentry, data); - if (result != 0) - return result; - - /* check, that name is acceptable for parent */ - if (par_dir->is_name_acceptable && - !par_dir->is_name_acceptable(parent, - dentry->d_name.name, - (int) dentry->d_name.len)) - return RETERR(-ENAMETOOLONG); - - result = 0; - obj_plug = file_plugin_by_id((int) data->id); - if (obj_plug == NULL) { - warning("nikita-430", "Cannot find plugin %i", data->id); - return RETERR(-ENOENT); - } - object = new_inode(parent->i_sb); - if (object == NULL) - return RETERR(-ENOMEM); - /* we'll update i_nlink below */ - object->i_nlink = 0; - /* new_inode() initializes i_ino to "arbitrary" value. Reset it to 0, - * to simplify error handling: if some error occurs before i_ino is - * initialized with oid, i_ino should already be set to some - * distinguished value. */ - object->i_ino = 0; - - /* So that on error iput will be called. */ - *retobj = object; - - if (DQUOT_ALLOC_INODE(object)) { - DQUOT_DROP(object); - object->i_flags |= S_NOQUOTA; - return RETERR(-EDQUOT); - } - - memset(&entry, 0, sizeof entry); - entry.obj = object; - - plugin_set_file(&reiser4_inode_data(object)->pset, obj_plug); - result = obj_plug->set_plug_in_inode(object, parent, data); - if (result) { - warning("nikita-431", "Cannot install plugin %i on %llx", - data->id, (unsigned long long)get_inode_oid(object)); - DQUOT_FREE_INODE(object); - object->i_flags |= S_NOQUOTA; - return result; - } - - /* reget plugin after installation */ - obj_plug = inode_file_plugin(object); - - if (obj_plug->create == NULL) { - DQUOT_FREE_INODE(object); - object->i_flags |= S_NOQUOTA; - return RETERR(-EPERM); - } - - /* if any of hash, tail, sd or permission plugins for newly created - object are not set yet set them here inheriting them from parent - directory - */ - assert("nikita-2070", obj_plug->adjust_to_parent != NULL); - result = obj_plug->adjust_to_parent(object, - parent, - object->i_sb->s_root->d_inode); - if (result != 0) { - warning("nikita-432", "Cannot inherit from %llx to %llx", - (unsigned long long)get_inode_oid(parent), - (unsigned long long)get_inode_oid(object)); - DQUOT_FREE_INODE(object); - object->i_flags |= S_NOQUOTA; - return result; - } - - /* call file plugin's method to initialize plugin specific part of - * inode */ - if (obj_plug->init_inode_data) - obj_plug->init_inode_data(object, data, 1/*create*/); - - /* obtain directory plugin (if any) for new object. */ - obj_dir = inode_dir_plugin(object); - if (obj_dir != NULL && obj_dir->init == NULL) { - DQUOT_FREE_INODE(object); - object->i_flags |= S_NOQUOTA; - return RETERR(-EPERM); - } - - reiser4_inode_data(object)->locality_id = get_inode_oid(parent); - - reserve = common_estimate_create_child(parent, object); - if (reiser4_grab_space(reserve, BA_CAN_COMMIT)) { - DQUOT_FREE_INODE(object); - object->i_flags |= S_NOQUOTA; - return RETERR(-ENOSPC); - } - - /* mark inode `immutable'. We disable changes to the file being - created until valid directory entry for it is inserted. Otherwise, - if file were expanded and insertion of directory entry fails, we - have to remove file, but we only alloted enough space in - transaction to remove _empty_ file. 3.x code used to remove stat - data in different transaction thus possibly leaking disk space on - crash. This all only matters if it's possible to access file - without name, for example, by inode number - */ - inode_set_flag(object, REISER4_IMMUTABLE); - - /* create empty object, this includes allocation of new objectid. For - directories this implies creation of dot and dotdot */ - assert("nikita-2265", inode_get_flag(object, REISER4_NO_SD)); - - /* mark inode as `loaded'. From this point onward - reiser4_delete_inode() will try to remove its stat-data. */ - inode_set_flag(object, REISER4_LOADED); - - result = obj_plug->create(object, parent, data); - if (result != 0) { - inode_clr_flag(object, REISER4_IMMUTABLE); - if (result != -ENAMETOOLONG && result != -ENOMEM) - warning("nikita-2219", - "Failed to create sd for %llu", - (unsigned long long)get_inode_oid(object)); - DQUOT_FREE_INODE(object); - object->i_flags |= S_NOQUOTA; - return result; - } - - if (obj_dir != NULL) - result = obj_dir->init(object, parent, data); - if (result == 0) { - assert("nikita-434", !inode_get_flag(object, REISER4_NO_SD)); - /* insert inode into VFS hash table */ - insert_inode_hash(object); - /* create entry */ - result = par_dir->add_entry(parent, dentry, data, &entry); - if (result == 0) { - result = reiser4_add_nlink(object, parent, 0); - /* If O_CREAT is set and the file did not previously - exist, upon successful completion, open() shall - mark for update the st_atime, st_ctime, and - st_mtime fields of the file and the st_ctime and - st_mtime fields of the parent directory. --SUS - */ - /* @object times are already updated by - reiser4_add_nlink() */ - if (result == 0) - reiser4_update_dir(parent); - if (result != 0) - /* cleanup failure to add nlink */ - par_dir->rem_entry(parent, dentry, &entry); - } - if (result != 0) - /* cleanup failure to add entry */ - obj_plug->detach(object, parent); - } else if (result != -ENOMEM) - warning("nikita-2219", "Failed to initialize dir for %llu: %i", - (unsigned long long)get_inode_oid(object), result); - - /* - * update stat-data, committing all pending modifications to the inode - * fields. - */ - reiser4_update_sd(object); - if (result != 0) { - DQUOT_FREE_INODE(object); - object->i_flags |= S_NOQUOTA; - /* if everything was ok (result == 0), parent stat-data is - * already updated above (update_parent_dir()) */ - reiser4_update_sd(parent); - /* failure to create entry, remove object */ - obj_plug->delete(object); - } - - /* file has name now, clear immutable flag */ - inode_clr_flag(object, REISER4_IMMUTABLE); - - /* on error, iput() will call ->delete_inode(). We should keep track - of the existence of stat-data for this inode and avoid attempt to - remove it in reiser4_delete_inode(). This is accomplished through - REISER4_NO_SD bit in inode.u.reiser4_i.plugin.flags - */ - return result; -} - -/* ->is_name_acceptable() method of directory plugin */ -/* Audited by: green(2002.06.15) */ -reiser4_internal int -is_name_acceptable(const struct inode *inode /* directory to check */ , - const char *name UNUSED_ARG /* name to check */ , - int len /* @name's length */ ) -{ - assert("nikita-733", inode != NULL); - assert("nikita-734", name != NULL); - assert("nikita-735", len > 0); - - return len <= reiser4_max_filename_len(inode); -} - -/* return true, iff @coord points to the valid directory item that is part of - * @inode directory. */ -static int -is_valid_dir_coord(struct inode * inode, coord_t * coord) -{ - return - item_type_by_coord(coord) == DIR_ENTRY_ITEM_TYPE && - inode_file_plugin(inode)->owns_item(inode, coord); -} - -/* true if directory is empty (only contains dot and dotdot) */ -reiser4_internal int -is_dir_empty(const struct inode *dir) -{ - assert("nikita-1976", dir != NULL); - - /* rely on our method to maintain directory i_size being equal to the - number of entries. */ - return dir->i_size <= 2 ? 0 : RETERR(-ENOTEMPTY); -} - -/* compare two logical positions within the same directory */ -static cmp_t dir_pos_cmp(const dir_pos * p1, const dir_pos * p2) -{ - cmp_t result; - - assert("nikita-2534", p1 != NULL); - assert("nikita-2535", p2 != NULL); - - result = de_id_cmp(&p1->dir_entry_key, &p2->dir_entry_key); - if (result == EQUAL_TO) { - int diff; - - diff = p1->pos - p2->pos; - result = (diff < 0) ? LESS_THAN : (diff ? GREATER_THAN : EQUAL_TO); - } - return result; -} - -/* true, if file descriptor @f is created by NFS server by "demand" to serve - * one file system operation. This means that there may be "detached state" - * for underlying inode. */ -static inline int -file_is_stateless(struct file *f) -{ - return reiser4_get_dentry_fsdata(f->f_dentry)->stateless; -} - -#define CID_SHIFT (20) -#define CID_MASK (0xfffffull) - -/* calculate ->fpos from user-supplied cookie. Normally it is dir->f_pos, but - * in the case of stateless directory operation (readdir-over-nfs), client id - * was encoded in the high bits of cookie and should me masked off. */ -static loff_t -get_dir_fpos(struct file * dir) -{ - if (file_is_stateless(dir)) - return dir->f_pos & CID_MASK; - else - return dir->f_pos; -} - -/* see comment before readdir_common() for overview of why "adjustment" is - * necessary. */ -static void -adjust_dir_pos(struct file * dir, - readdir_pos * readdir_spot, - const dir_pos * mod_point, - int adj) -{ - dir_pos *pos; - - /* - * new directory entry was added (adj == +1) or removed (adj == -1) at - * the @mod_point. Directory file descriptor @dir is doing readdir and - * is currently positioned at @readdir_spot. Latter has to be updated - * to maintain stable readdir. - */ - /* directory is positioned to the beginning. */ - if (readdir_spot->entry_no == 0) - return; - - pos = &readdir_spot->position; - switch (dir_pos_cmp(mod_point, pos)) { - case LESS_THAN: - /* @mod_pos is _before_ @readdir_spot, that is, entry was - * added/removed on the left (in key order) of current - * position. */ - /* logical number of directory entry readdir is "looking" at - * changes */ - readdir_spot->entry_no += adj; - assert("nikita-2577", - ergo(dir != NULL, get_dir_fpos(dir) + adj >= 0)); - if (de_id_cmp(&pos->dir_entry_key, - &mod_point->dir_entry_key) == EQUAL_TO) { - assert("nikita-2575", mod_point->pos < pos->pos); - /* - * if entry added/removed has the same key as current - * for readdir, update counter of duplicate keys in - * @readdir_spot. - */ - pos->pos += adj; - } - break; - case GREATER_THAN: - /* directory is modified after @pos: nothing to do. */ - break; - case EQUAL_TO: - /* cannot insert an entry readdir is looking at, because it - already exists. */ - assert("nikita-2576", adj < 0); - /* directory entry to which @pos points to is being - removed. - - NOTE-NIKITA: Right thing to do is to update @pos to point - to the next entry. This is complex (we are under spin-lock - for one thing). Just rewind it to the beginning. Next - readdir will have to scan the beginning of - directory. Proper solution is to use semaphore in - spin lock's stead and use rewind_right() here. - - NOTE-NIKITA: now, semaphore is used, so... - */ - memset(readdir_spot, 0, sizeof *readdir_spot); - } -} - -/* scan all file-descriptors for this directory and adjust their positions - respectively. */ -reiser4_internal void -adjust_dir_file(struct inode *dir, const struct dentry * de, int offset, int adj) -{ - reiser4_file_fsdata *scan; - dir_pos mod_point; - - assert("nikita-2536", dir != NULL); - assert("nikita-2538", de != NULL); - assert("nikita-2539", adj != 0); - - build_de_id(dir, &de->d_name, &mod_point.dir_entry_key); - mod_point.pos = offset; - - spin_lock_inode(dir); - - /* - * new entry was added/removed in directory @dir. Scan all file - * descriptors for @dir that are currently involved into @readdir and - * update them. - */ - - for_all_type_safe_list(readdir, get_readdir_list(dir), scan) - adjust_dir_pos(scan->back, &scan->dir.readdir, &mod_point, adj); - - spin_unlock_inode(dir); -} - -/* - * traverse tree to start/continue readdir from the readdir position @pos. - */ -static int -dir_go_to(struct file *dir, readdir_pos * pos, tap_t * tap) -{ - reiser4_key key; - int result; - struct inode *inode; - - assert("nikita-2554", pos != NULL); - - inode = dir->f_dentry->d_inode; - result = inode_dir_plugin(inode)->build_readdir_key(dir, &key); - if (result != 0) - return result; - result = object_lookup(inode, - &key, - tap->coord, - tap->lh, - tap->mode, - FIND_EXACT, - LEAF_LEVEL, - LEAF_LEVEL, - 0, - &tap->ra_info); - if (result == CBK_COORD_FOUND) - result = rewind_right(tap, (int) pos->position.pos); - else { - tap->coord->node = NULL; - done_lh(tap->lh); - result = RETERR(-EIO); - } - return result; -} - -/* - * handling of non-unique keys: calculate at what ordinal position within - * sequence of directory items with identical keys @pos is. - */ -static int -set_pos(struct inode * inode, readdir_pos * pos, tap_t * tap) -{ - int result; - coord_t coord; - lock_handle lh; - tap_t scan; - de_id *did; - reiser4_key de_key; - - coord_init_zero(&coord); - init_lh(&lh); - tap_init(&scan, &coord, &lh, ZNODE_READ_LOCK); - tap_copy(&scan, tap); - tap_load(&scan); - pos->position.pos = 0; - - did = &pos->position.dir_entry_key; - - if (is_valid_dir_coord(inode, scan.coord)) { - - build_de_id_by_key(unit_key_by_coord(scan.coord, &de_key), did); - - while (1) { - - result = go_prev_unit(&scan); - if (result != 0) - break; - - if (!is_valid_dir_coord(inode, scan.coord)) { - result = -EINVAL; - break; - } - - /* get key of directory entry */ - unit_key_by_coord(scan.coord, &de_key); - if (de_id_key_cmp(did, &de_key) != EQUAL_TO) { - /* duplicate-sequence is over */ - break; - } - pos->position.pos ++; - } - } else - result = RETERR(-ENOENT); - tap_relse(&scan); - tap_done(&scan); - return result; -} - - -/* - * "rewind" directory to @offset, i.e., set @pos and @tap correspondingly. - */ -static int -dir_rewind(struct file *dir, readdir_pos * pos, tap_t * tap) -{ - __u64 destination; - __s64 shift; - int result; - struct inode *inode; - loff_t dirpos; - - assert("nikita-2553", dir != NULL); - assert("nikita-2548", pos != NULL); - assert("nikita-2551", tap->coord != NULL); - assert("nikita-2552", tap->lh != NULL); - - dirpos = get_dir_fpos(dir); - shift = dirpos - pos->fpos; - /* this is logical directory entry within @dir which we are rewinding - * to */ - destination = pos->entry_no + shift; - - inode = dir->f_dentry->d_inode; - if (dirpos < 0) - return RETERR(-EINVAL); - else if (destination == 0ll || dirpos == 0) { - /* rewind to the beginning of directory */ - memset(pos, 0, sizeof *pos); - return dir_go_to(dir, pos, tap); - } else if (destination >= inode->i_size) - return RETERR(-ENOENT); - - if (shift < 0) { - /* I am afraid of negative numbers */ - shift = -shift; - /* rewinding to the left */ - if (shift <= (int) pos->position.pos) { - /* destination is within sequence of entries with - duplicate keys. */ - result = dir_go_to(dir, pos, tap); - } else { - shift -= pos->position.pos; - while (1) { - /* repetitions: deadlock is possible when - going to the left. */ - result = dir_go_to(dir, pos, tap); - if (result == 0) { - result = rewind_left(tap, shift); - if (result == -E_DEADLOCK) { - tap_done(tap); - continue; - } - } - break; - } - } - } else { - /* rewinding to the right */ - result = dir_go_to(dir, pos, tap); - if (result == 0) - result = rewind_right(tap, shift); - } - if (result == 0) { - result = set_pos(inode, pos, tap); - if (result == 0) { - /* update pos->position.pos */ - pos->entry_no = destination; - pos->fpos = dirpos; - } - } - return result; -} - -/* - * Function that is called by common_readdir() on each directory entry while - * doing readdir. ->filldir callback may block, so we had to release long term - * lock while calling it. To avoid repeating tree traversal, seal is used. If - * seal is broken, we return -E_REPEAT. Node is unlocked in this case. - * - * Whether node is unlocked in case of any other error is undefined. It is - * guaranteed to be still locked if success (0) is returned. - * - * When ->filldir() wants no more, feed_entry() returns 1, and node is - * unlocked. - */ -static int -feed_entry(struct file *f, - readdir_pos * pos, tap_t *tap, filldir_t filldir, void *dirent) -{ - item_plugin *iplug; - char *name; - reiser4_key sd_key; - int result; - char buf[DE_NAME_BUF_LEN]; - char name_buf[32]; - char *local_name; - unsigned file_type; - seal_t seal; - coord_t *coord; - reiser4_key entry_key; - - coord = tap->coord; - iplug = item_plugin_by_coord(coord); - - /* pointer to name within the node */ - name = iplug->s.dir.extract_name(coord, buf); - assert("nikita-1371", name != NULL); - - /* key of object the entry points to */ - if (iplug->s.dir.extract_key(coord, &sd_key) != 0) - return RETERR(-EIO); - - /* we must release longterm znode lock before calling filldir to avoid - deadlock which may happen if filldir causes page fault. So, copy - name to intermediate buffer */ - if (strlen(name) + 1 > sizeof(name_buf)) { - local_name = kmalloc(strlen(name) + 1, GFP_KERNEL); - if (local_name == NULL) - return RETERR(-ENOMEM); - } else - local_name = name_buf; - - strcpy(local_name, name); - file_type = iplug->s.dir.extract_file_type(coord); - - unit_key_by_coord(coord, &entry_key); - seal_init(&seal, coord, &entry_key); - - longterm_unlock_znode(tap->lh); - - /* - * send information about directory entry to the ->filldir() filler - * supplied to us by caller (VFS). - * - * ->filldir is entitled to do weird things. For example, ->filldir - * supplied by knfsd re-enters file system. Make sure no locks are - * held. - */ - assert("nikita-3436", lock_stack_isclean(get_current_lock_stack())); - - result = filldir(dirent, name, (int) strlen(name), - /* offset of this entry */ - f->f_pos, - /* inode number of object bounden by this entry */ - oid_to_uino(get_key_objectid(&sd_key)), - file_type); - if (local_name != name_buf) - kfree(local_name); - if (result < 0) - /* ->filldir() is satisfied. (no space in buffer, IOW) */ - result = 1; - else - result = seal_validate(&seal, coord, &entry_key, - tap->lh, tap->mode, ZNODE_LOCK_HIPRI); - return result; -} - -static void -move_entry(readdir_pos * pos, coord_t * coord) -{ - reiser4_key de_key; - de_id *did; - - /* update @pos */ - ++pos->entry_no; - did = &pos->position.dir_entry_key; - - /* get key of directory entry */ - unit_key_by_coord(coord, &de_key); - - if (de_id_key_cmp(did, &de_key) == EQUAL_TO) - /* we are within sequence of directory entries - with duplicate keys. */ - ++pos->position.pos; - else { - pos->position.pos = 0; - build_de_id_by_key(&de_key, did); - } - ++pos->fpos; -} - -/* - * STATELESS READDIR - * - * readdir support in reiser4 relies on ability to update readdir_pos embedded - * into reiser4_file_fsdata on each directory modification (name insertion and - * removal), see readdir_common() function below. This obviously doesn't work - * when reiser4 is accessed over NFS, because NFS doesn't keep any state - * across client READDIR requests for the same directory. - * - * To address this we maintain a "pool" of detached reiser4_file_fsdata - * (d_cursor). Whenever NFS readdir request comes, we detect this, and try to - * find detached reiser4_file_fsdata corresponding to previous readdir - * request. In other words, additional state is maintained on the - * server. (This is somewhat contrary to the design goals of NFS protocol.) - * - * To efficiently detect when our ->readdir() method is called by NFS server, - * dentry is marked as "stateless" in reiser4_decode_fh() (this is checked by - * file_is_stateless() function). - * - * To find out d_cursor in the pool, we encode client id (cid) in the highest - * bits of NFS readdir cookie: when first readdir request comes to the given - * directory from the given client, cookie is set to 0. This situation is - * detected, global cid_counter is incremented, and stored in highest bits of - * all direntry offsets returned to the client, including last one. As the - * only valid readdir cookie is one obtained as direntry->offset, we are - * guaranteed that next readdir request (continuing current one) will have - * current cid in the highest bits of starting readdir cookie. All d_cursors - * are hashed into per-super-block hash table by (oid, cid) key. - * - * In addition d_cursors are placed into per-super-block radix tree where they - * are keyed by oid alone. This is necessary to efficiently remove them during - * rmdir. - * - * At last, currently unused d_cursors are linked into special list. This list - * is used d_cursor_shrink to reclaim d_cursors on memory pressure. - * - */ - -TYPE_SAFE_LIST_DECLARE(d_cursor); -TYPE_SAFE_LIST_DECLARE(a_cursor); - -typedef struct { - __u16 cid; - __u64 oid; -} d_cursor_key; - -struct dir_cursor { - int ref; - reiser4_file_fsdata *fsdata; - d_cursor_hash_link hash; - d_cursor_list_link list; - d_cursor_key key; - d_cursor_info *info; - a_cursor_list_link alist; -}; - -static kmem_cache_t *d_cursor_slab; -static struct shrinker *d_cursor_shrinker; -static unsigned long d_cursor_unused = 0; -static spinlock_t d_lock = SPIN_LOCK_UNLOCKED; -static a_cursor_list_head cursor_cache = TYPE_SAFE_LIST_HEAD_INIT(cursor_cache); - -#define D_CURSOR_TABLE_SIZE (256) - -static inline unsigned long -d_cursor_hash(d_cursor_hash_table *table, const d_cursor_key * key) -{ - assert("nikita-3555", IS_POW(D_CURSOR_TABLE_SIZE)); - return (key->oid + key->cid) & (D_CURSOR_TABLE_SIZE - 1); -} - -static inline int -d_cursor_eq(const d_cursor_key * k1, const d_cursor_key * k2) -{ - return k1->cid == k2->cid && k1->oid == k2->oid; -} - -#define KMALLOC(size) kmalloc((size), GFP_KERNEL) -#define KFREE(ptr, size) kfree(ptr) -TYPE_SAFE_HASH_DEFINE(d_cursor, - dir_cursor, - d_cursor_key, - key, - hash, - d_cursor_hash, - d_cursor_eq); -#undef KFREE -#undef KMALLOC - -TYPE_SAFE_LIST_DEFINE(d_cursor, dir_cursor, list); -TYPE_SAFE_LIST_DEFINE(a_cursor, dir_cursor, alist); - -static void kill_cursor(dir_cursor *cursor); - -/* - * shrink d_cursors cache. Scan LRU list of unused cursors, freeing requested - * number. Return number of still freeable cursors. - */ -static int d_cursor_shrink(int nr, unsigned int gfp_mask) -{ - if (nr != 0) { - dir_cursor *scan; - int killed; - - killed = 0; - spin_lock(&d_lock); - while (!a_cursor_list_empty(&cursor_cache)) { - scan = a_cursor_list_front(&cursor_cache); - assert("nikita-3567", scan->ref == 0); - kill_cursor(scan); - ++ killed; - -- nr; - if (nr == 0) - break; - } - spin_unlock(&d_lock); - } - return d_cursor_unused; -} - -/* - * perform global initializations for the d_cursor sub-system. - */ -reiser4_internal int -d_cursor_init(void) -{ - d_cursor_slab = kmem_cache_create("d_cursor", sizeof (dir_cursor), 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); - if (d_cursor_slab == NULL) - return RETERR(-ENOMEM); - else { - /* actually, d_cursors are "priceless", because there is no - * way to recover information stored in them. On the other - * hand, we don't want to consume all kernel memory by - * them. As a compromise, just assign higher "seeks" value to - * d_cursor cache, so that it will be shrunk only if system is - * really tight on memory. */ - d_cursor_shrinker = set_shrinker(DEFAULT_SEEKS << 3, - d_cursor_shrink); - if (d_cursor_shrinker == NULL) - return RETERR(-ENOMEM); - else - return 0; - } -} - -/* - * Dual to d_cursor_init(): release global d_cursor resources. - */ -reiser4_internal void -d_cursor_done(void) -{ - if (d_cursor_shrinker != NULL) { - remove_shrinker(d_cursor_shrinker); - d_cursor_shrinker = NULL; - } - if (d_cursor_slab != NULL) { - kmem_cache_destroy(d_cursor_slab); - d_cursor_slab = NULL; - } -} - -/* - * initialize per-super-block d_cursor resources - */ -reiser4_internal int -d_cursor_init_at(struct super_block *s) -{ - d_cursor_info *p; - - p = &get_super_private(s)->d_info; - - INIT_RADIX_TREE(&p->tree, GFP_KERNEL); - return d_cursor_hash_init(&p->table, D_CURSOR_TABLE_SIZE); -} - -/* - * Dual to d_cursor_init_at: release per-super-block d_cursor resources - */ -reiser4_internal void -d_cursor_done_at(struct super_block *s) -{ - d_cursor_hash_done(&get_super_private(s)->d_info.table); -} - -/* - * return d_cursor data for the file system @inode is in. - */ -static inline d_cursor_info * d_info(struct inode *inode) -{ - return &get_super_private(inode->i_sb)->d_info; -} - -/* - * lookup d_cursor in the per-super-block radix tree. - */ -static inline dir_cursor *lookup(d_cursor_info *info, unsigned long index) -{ - return (dir_cursor *)radix_tree_lookup(&info->tree, index); -} - -/* - * attach @cursor to the radix tree. There may be multiple cursors for the - * same oid, they are chained into circular list. - */ -static void bind_cursor(dir_cursor *cursor, unsigned long index) -{ - dir_cursor *head; - - head = lookup(cursor->info, index); - if (head == NULL) { - /* this is the first cursor for this index */ - d_cursor_list_clean(cursor); - radix_tree_insert(&cursor->info->tree, index, cursor); - } else { - /* some cursor already exists. Chain ours */ - d_cursor_list_insert_after(head, cursor); - } -} - -/* - * remove @cursor from indices and free it - */ -static void -kill_cursor(dir_cursor *cursor) -{ - unsigned long index; - - assert("nikita-3566", cursor->ref == 0); - assert("nikita-3572", cursor->fsdata != NULL); - - index = (unsigned long)cursor->key.oid; - readdir_list_remove_clean(cursor->fsdata); - reiser4_free_fsdata(cursor->fsdata); - cursor->fsdata = NULL; - - if (d_cursor_list_is_clean(cursor)) - /* this is last cursor for a file. Kill radix-tree entry */ - radix_tree_delete(&cursor->info->tree, index); - else { - void **slot; - - /* - * there are other cursors for the same oid. - */ - - /* - * if radix tree point to the cursor being removed, re-target - * radix tree slot to the next cursor in the (non-empty as was - * checked above) element of the circular list of all cursors - * for this oid. - */ - slot = radix_tree_lookup_slot(&cursor->info->tree, index); - assert("nikita-3571", *slot != NULL); - if (*slot == cursor) - *slot = d_cursor_list_next(cursor); - /* remove cursor from circular list */ - d_cursor_list_remove_clean(cursor); - } - /* remove cursor from the list of unused cursors */ - a_cursor_list_remove_clean(cursor); - /* remove cursor from the hash table */ - d_cursor_hash_remove(&cursor->info->table, cursor); - /* and free it */ - kmem_cache_free(d_cursor_slab, cursor); - -- d_cursor_unused; -} - -/* possible actions that can be performed on all cursors for the given file */ -enum cursor_action { - /* load all detached state: this is called when stat-data is loaded - * from the disk to recover information about all pending readdirs */ - CURSOR_LOAD, - /* detach all state from inode, leaving it in the cache. This is - * called when inode is removed form the memory by memory pressure */ - CURSOR_DISPOSE, - /* detach cursors from the inode, and free them. This is called when - * inode is destroyed. */ - CURSOR_KILL -}; - -static void -process_cursors(struct inode *inode, enum cursor_action act) -{ - oid_t oid; - dir_cursor *start; - readdir_list_head *head; - reiser4_context ctx; - d_cursor_info *info; - - /* this can be called by - * - * kswapd->...->prune_icache->..reiser4_destroy_inode - * - * without reiser4_context - */ - init_context(&ctx, inode->i_sb); - - assert("nikita-3558", inode != NULL); - - info = d_info(inode); - oid = get_inode_oid(inode); - spin_lock_inode(inode); - head = get_readdir_list(inode); - spin_lock(&d_lock); - /* find any cursor for this oid: reference to it is hanging of radix - * tree */ - start = lookup(info, (unsigned long)oid); - if (start != NULL) { - dir_cursor *scan; - reiser4_file_fsdata *fsdata; - - /* process circular list of cursors for this oid */ - scan = start; - do { - dir_cursor *next; - - next = d_cursor_list_next(scan); - fsdata = scan->fsdata; - assert("nikita-3557", fsdata != NULL); - if (scan->key.oid == oid) { - switch (act) { - case CURSOR_DISPOSE: - readdir_list_remove_clean(fsdata); - break; - case CURSOR_LOAD: - readdir_list_push_front(head, fsdata); - break; - case CURSOR_KILL: - kill_cursor(scan); - break; - } - } - if (scan == next) - /* last cursor was just killed */ - break; - scan = next; - } while (scan != start); - } - spin_unlock(&d_lock); - /* check that we killed 'em all */ - assert("nikita-3568", ergo(act == CURSOR_KILL, - readdir_list_empty(get_readdir_list(inode)))); - assert("nikita-3569", ergo(act == CURSOR_KILL, - lookup(info, oid) == NULL)); - spin_unlock_inode(inode); - reiser4_exit_context(&ctx); -} - -/* detach all cursors from inode. This is called when inode is removed from - * the memory by memory pressure */ -reiser4_internal void dispose_cursors(struct inode *inode) -{ - process_cursors(inode, CURSOR_DISPOSE); -} - -/* attach all detached cursors to the inode. This is done when inode is loaded - * into memory */ -reiser4_internal void load_cursors(struct inode *inode) -{ - process_cursors(inode, CURSOR_LOAD); -} - -/* free all cursors for this inode. This is called when inode is destroyed. */ -reiser4_internal void kill_cursors(struct inode *inode) -{ - process_cursors(inode, CURSOR_KILL); -} - -/* global counter used to generate "client ids". These ids are encoded into - * high bits of fpos. */ -static __u32 cid_counter = 0; - -/* - * detach fsdata (if detachable) from file descriptor, and put cursor on the - * "unused" list. Called when file descriptor is not longer in active use. - */ -static void -clean_fsdata(struct file *f) -{ - dir_cursor *cursor; - reiser4_file_fsdata *fsdata; - - assert("nikita-3570", file_is_stateless(f)); - - fsdata = (reiser4_file_fsdata *)f->private_data; - if (fsdata != NULL) { - cursor = fsdata->cursor; - if (cursor != NULL) { - spin_lock(&d_lock); - -- cursor->ref; - if (cursor->ref == 0) { - a_cursor_list_push_back(&cursor_cache, cursor); - ++ d_cursor_unused; - } - spin_unlock(&d_lock); - f->private_data = NULL; - } - } -} - -/* add detachable readdir state to the @f */ -static int -insert_cursor(dir_cursor *cursor, struct file *f, struct inode *inode) -{ - int result; - reiser4_file_fsdata *fsdata; - - memset(cursor, 0, sizeof *cursor); - - /* this is either first call to readdir, or rewind. Anyway, create new - * cursor. */ - fsdata = create_fsdata(NULL, GFP_KERNEL); - if (fsdata != NULL) { - result = radix_tree_preload(GFP_KERNEL); - if (result == 0) { - d_cursor_info *info; - oid_t oid; - - info = d_info(inode); - oid = get_inode_oid(inode); - /* cid occupies higher 12 bits of f->f_pos. Don't - * allow it to become negative: this confuses - * nfsd_readdir() */ - cursor->key.cid = (++ cid_counter) & 0x7ff; - cursor->key.oid = oid; - cursor->fsdata = fsdata; - cursor->info = info; - cursor->ref = 1; - spin_lock_inode(inode); - /* install cursor as @f's private_data, discarding old - * one if necessary */ - clean_fsdata(f); - reiser4_free_file_fsdata(f); - f->private_data = fsdata; - fsdata->cursor = cursor; - spin_unlock_inode(inode); - spin_lock(&d_lock); - /* insert cursor into hash table */ - d_cursor_hash_insert(&info->table, cursor); - /* and chain it into radix-tree */ - bind_cursor(cursor, (unsigned long)oid); - spin_unlock(&d_lock); - radix_tree_preload_end(); - f->f_pos = ((__u64)cursor->key.cid) << CID_SHIFT; - } - } else - result = RETERR(-ENOMEM); - return result; -} - -/* find or create cursor for readdir-over-nfs */ -static int -try_to_attach_fsdata(struct file *f, struct inode *inode) -{ - loff_t pos; - int result; - dir_cursor *cursor; - - /* - * we are serialized by inode->i_sem - */ - - if (!file_is_stateless(f)) - return 0; - - pos = f->f_pos; - result = 0; - if (pos == 0) { - /* - * first call to readdir (or rewind to the beginning of - * directory) - */ - cursor = kmem_cache_alloc(d_cursor_slab, GFP_KERNEL); - if (cursor != NULL) - result = insert_cursor(cursor, f, inode); - else - result = RETERR(-ENOMEM); - } else { - /* try to find existing cursor */ - d_cursor_key key; - - key.cid = pos >> CID_SHIFT; - key.oid = get_inode_oid(inode); - spin_lock(&d_lock); - cursor = d_cursor_hash_find(&d_info(inode)->table, &key); - if (cursor != NULL) { - /* cursor was found */ - if (cursor->ref == 0) { - /* move it from unused list */ - a_cursor_list_remove_clean(cursor); - -- d_cursor_unused; - } - ++ cursor->ref; - } - spin_unlock(&d_lock); - if (cursor != NULL) { - spin_lock_inode(inode); - assert("nikita-3556", cursor->fsdata->back == NULL); - clean_fsdata(f); - reiser4_free_file_fsdata(f); - f->private_data = cursor->fsdata; - spin_unlock_inode(inode); - } - } - return result; -} - -/* detach fsdata, if necessary */ -static void -detach_fsdata(struct file *f) -{ - struct inode *inode; - - if (!file_is_stateless(f)) - return; - - inode = f->f_dentry->d_inode; - spin_lock_inode(inode); - clean_fsdata(f); - spin_unlock_inode(inode); -} - -/* - * prepare for readdir. - */ -static int -dir_readdir_init(struct file *f, tap_t * tap, readdir_pos ** pos) -{ - struct inode *inode; - reiser4_file_fsdata *fsdata; - int result; - - assert("nikita-1359", f != NULL); - inode = f->f_dentry->d_inode; - assert("nikita-1360", inode != NULL); - - if (!S_ISDIR(inode->i_mode)) - return RETERR(-ENOTDIR); - - /* try to find detached readdir state */ - result = try_to_attach_fsdata(f, inode); - if (result != 0) - return result; - - fsdata = reiser4_get_file_fsdata(f); - assert("nikita-2571", fsdata != NULL); - if (IS_ERR(fsdata)) - return PTR_ERR(fsdata); - - /* add file descriptor to the readdir list hanging of directory - * inode. This list is used to scan "readdirs-in-progress" while - * inserting or removing names in the directory. */ - spin_lock_inode(inode); - if (readdir_list_is_clean(fsdata)) - readdir_list_push_front(get_readdir_list(inode), fsdata); - *pos = &fsdata->dir.readdir; - spin_unlock_inode(inode); - - /* move @tap to the current position */ - return dir_rewind(f, *pos, tap); -} - -/* - * ->readdir method of directory plugin - * - * readdir problems: - * - * Traditional UNIX API for scanning through directory - * (readdir/seekdir/telldir/opendir/closedir/rewindir/getdents) is based - * on the assumption that directory is structured very much like regular - * file, in particular, it is implied that each name within given - * directory (directory entry) can be uniquely identified by scalar offset - * and that such offset is stable across the life-time of the name is - * identifies. - * - * This is manifestly not so for reiser4. In reiser4 the only stable - * unique identifies for the directory entry is its key that doesn't fit - * into seekdir/telldir API. - * - * solution: - * - * Within each file descriptor participating in readdir-ing of directory - * plugin/dir/dir.h:readdir_pos is maintained. This structure keeps track - * of the "current" directory entry that file descriptor looks at. It - * contains a key of directory entry (plus some additional info to deal - * with non-unique keys that we wouldn't dwell onto here) and a logical - * position of this directory entry starting from the beginning of the - * directory, that is ordinal number of this entry in the readdir order. - * - * Obviously this logical position is not stable in the face of directory - * modifications. To work around this, on each addition or removal of - * directory entry all file descriptors for directory inode are scanned - * and their readdir_pos are updated accordingly (adjust_dir_pos()). - * - */ -static int -readdir_common(struct file *f /* directory file being read */ , - void *dirent /* opaque data passed to us by VFS */ , - filldir_t filld /* filler function passed to us - * by VFS */ ) -{ - int result; - struct inode *inode; - coord_t coord; - lock_handle lh; - tap_t tap; - readdir_pos *pos; - - assert("nikita-1359", f != NULL); - inode = f->f_dentry->d_inode; - assert("nikita-1360", inode != NULL); - - if (!S_ISDIR(inode->i_mode)) - return RETERR(-ENOTDIR); - - coord_init_zero(&coord); - init_lh(&lh); - tap_init(&tap, &coord, &lh, ZNODE_READ_LOCK); - - reiser4_readdir_readahead_init(inode, &tap); - - repeat: - result = dir_readdir_init(f, &tap, &pos); - if (result == 0) { - result = tap_load(&tap); - /* scan entries one by one feeding them to @filld */ - while (result == 0) { - coord_t *coord; - - coord = tap.coord; - assert("nikita-2572", coord_is_existing_unit(coord)); - assert("nikita-3227", is_valid_dir_coord(inode, coord)); - - result = feed_entry(f, pos, &tap, filld, dirent); - if (result > 0) { - break; - } else if (result == 0) { - ++ f->f_pos; - result = go_next_unit(&tap); - if (result == -E_NO_NEIGHBOR || - result == -ENOENT) { - result = 0; - break; - } else if (result == 0) { - if (is_valid_dir_coord(inode, coord)) - move_entry(pos, coord); - else - break; - } - } else if (result == -E_REPEAT) { - /* feed_entry() had to restart. */ - ++ f->f_pos; - tap_relse(&tap); - goto repeat; - } else - warning("vs-1617", - "readdir_common: unexpected error %d", - result); - } - tap_relse(&tap); - - if (result >= 0) - f->f_version = inode->i_version; - } else if (result == -E_NO_NEIGHBOR || result == -ENOENT) - result = 0; - tap_done(&tap); - detach_fsdata(f); - return (result <= 0) ? result : 0; -} - -/* - * seek method for directory. See comment before readdir_common() for - * explanation. - */ -loff_t -seek_dir(struct file *file, loff_t off, int origin) -{ - loff_t result; - struct inode *inode; - - inode = file->f_dentry->d_inode; - down(&inode->i_sem); - - /* update ->f_pos */ - result = default_llseek(file, off, origin); - if (result >= 0) { - int ff; - coord_t coord; - lock_handle lh; - tap_t tap; - readdir_pos *pos; - - coord_init_zero(&coord); - init_lh(&lh); - tap_init(&tap, &coord, &lh, ZNODE_READ_LOCK); - - ff = dir_readdir_init(file, &tap, &pos); - detach_fsdata(file); - if (ff != 0) - result = (loff_t) ff; - tap_done(&tap); - } - detach_fsdata(file); - up(&inode->i_sem); - return result; -} - -/* ->attach method of directory plugin */ -static int -attach_common(struct inode *child UNUSED_ARG, struct inode *parent UNUSED_ARG) -{ - assert("nikita-2647", child != NULL); - assert("nikita-2648", parent != NULL); - - return 0; -} - -/* ->estimate.add_entry method of directory plugin - estimation of adding entry which supposes that entry is inserting a unit into item -*/ -static reiser4_block_nr -estimate_add_entry_common(struct inode *inode) -{ - return estimate_one_insert_into_item(tree_by_inode(inode)); -} - -/* ->estimate.rem_entry method of directory plugin */ -static reiser4_block_nr -estimate_rem_entry_common(struct inode *inode) -{ - return estimate_one_item_removal(tree_by_inode(inode)); -} - -/* placeholder for VFS methods not-applicable to the object */ -static ssize_t -noperm(void) -{ - return RETERR(-EPERM); -} - -#define dir_eperm ((void *)noperm) - -static int -_noop(void) -{ - return 0; -} - -#define enoop ((void *)_noop) - -static int -change_dir(struct inode * inode, reiser4_plugin * plugin) -{ - /* cannot change dir plugin of already existing object */ - return RETERR(-EINVAL); -} - -static reiser4_plugin_ops dir_plugin_ops = { - .init = NULL, - .load = NULL, - .save_len = NULL, - .save = NULL, - .change = change_dir -}; - -/* - * definition of directory plugins - */ - -dir_plugin dir_plugins[LAST_DIR_ID] = { - /* standard hashed directory plugin */ - [HASHED_DIR_PLUGIN_ID] = { - .h = { - .type_id = REISER4_DIR_PLUGIN_TYPE, - .id = HASHED_DIR_PLUGIN_ID, - .pops = &dir_plugin_ops, - .label = "dir", - .desc = "hashed directory", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .get_parent = get_parent_hashed, - .lookup = lookup_hashed, - .unlink = unlink_common, - .link = link_common, - .is_name_acceptable = is_name_acceptable, - .build_entry_key = build_entry_key_common, - .build_readdir_key = build_readdir_key_common, - .add_entry = add_entry_hashed, - .rem_entry = rem_entry_hashed, - .create_child = create_child_common, - .rename = rename_hashed, - .readdir = readdir_common, - .init = init_hashed, - .done = done_hashed, - .attach = attach_common, - .detach = detach_hashed, - .estimate = { - .add_entry = estimate_add_entry_common, - .rem_entry = estimate_rem_entry_common, - .unlink = estimate_unlink_hashed - } - }, - /* hashed directory for which seekdir/telldir are guaranteed to - * work. Brain-damage. */ - [SEEKABLE_HASHED_DIR_PLUGIN_ID] = { - .h = { - .type_id = REISER4_DIR_PLUGIN_TYPE, - .id = SEEKABLE_HASHED_DIR_PLUGIN_ID, - .pops = &dir_plugin_ops, - .label = "dir32", - .desc = "directory hashed with 31 bit hash", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .get_parent = get_parent_hashed, - .lookup = lookup_hashed, - .unlink = unlink_common, - .link = link_common, - .is_name_acceptable = is_name_acceptable, - .build_entry_key = build_entry_key_stable_entry, - .build_readdir_key = build_readdir_key_common, - .add_entry = add_entry_hashed, - .rem_entry = rem_entry_hashed, - .create_child = create_child_common, - .rename = rename_hashed, - .readdir = readdir_common, - .init = init_hashed, - .done = done_hashed, - .attach = attach_common, - .detach = detach_hashed, - .estimate = { - .add_entry = estimate_add_entry_common, - .rem_entry = estimate_rem_entry_common, - .unlink = estimate_unlink_hashed - } - }, - /* pseudo directory. */ - [PSEUDO_DIR_PLUGIN_ID] = { - .h = { - .type_id = REISER4_DIR_PLUGIN_TYPE, - .id = PSEUDO_DIR_PLUGIN_ID, - .pops = &dir_plugin_ops, - .label = "pseudo", - .desc = "pseudo directory", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .get_parent = get_parent_pseudo, - .lookup = lookup_pseudo, - .unlink = dir_eperm, - .link = dir_eperm, - .is_name_acceptable = NULL, - .build_entry_key = NULL, - .build_readdir_key = NULL, - .add_entry = dir_eperm, - .rem_entry = dir_eperm, - .create_child = NULL, - .rename = dir_eperm, - .readdir = readdir_pseudo, - .init = enoop, - .done = enoop, - .attach = enoop, - .detach = enoop, - .estimate = { - .add_entry = NULL, - .rem_entry = NULL, - .unlink = NULL - } - } -}; - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - End: -*/ diff -puN fs/reiser4/plugin/dir/dir.h~reiser4-big-update fs/reiser4/plugin/dir/dir.h --- devel/fs/reiser4/plugin/dir/dir.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/dir/dir.h 2005-09-15 19:51:08.000000000 -0700 @@ -1,96 +1,26 @@ /* Copyright 2001, 2002, 2003, 2004 by Hans Reiser, licensing governed by * reiser4/README */ -/* Directory plugin's methods. See dir.c for more details. */ +/* this file contains declarations of methods implementing directory plugins */ #if !defined( __REISER4_DIR_H__ ) #define __REISER4_DIR_H__ -#include "../../forward.h" -#include "../../kassign.h" -#include "../../type_safe_hash.h" - -#include /* for __u?? */ -#include /* for struct file */ -#include - -/* locking: fields of per file descriptor readdir_pos and ->f_pos are - * protected by ->i_sem on inode. Under this lock following invariant - * holds: - * - * file descriptor is "looking" at the entry_no-th directory entry from - * the beginning of directory. This entry has key dir_entry_key and is - * pos-th entry with duplicate-key sequence. - * - */ - -/* logical position within directory */ -typedef struct { - /* key of directory entry (actually, part of a key sufficient to - identify directory entry) */ - de_id dir_entry_key; - /* ordinal number of directory entry among all entries with the same - key. (Starting from 0.) */ - unsigned pos; -} dir_pos; - -typedef struct { - /* f_pos corresponding to this readdir position */ - __u64 fpos; - /* logical position within directory */ - dir_pos position; - /* logical number of directory entry within - directory */ - __u64 entry_no; -} readdir_pos; - -extern void adjust_dir_file(struct inode *dir, const struct dentry *de, - int offset, int adj); -extern loff_t seek_dir(struct file *file, loff_t off, int origin); - -/* description of directory entry being created/destroyed/sought for - - It is passed down to the directory plugin and farther to the - directory item plugin methods. Creation of new directory is done in - several stages: first we search for an entry with the same name, then - create new one. reiser4_dir_entry_desc is used to store some information - collected at some stage of this process and required later: key of - item that we want to insert/delete and pointer to an object that will - be bound by the new directory entry. Probably some more fields will - be added there. +/*#include "../../key.h" -*/ -struct reiser4_dir_entry_desc { - /* key of directory entry */ - reiser4_key key; - /* object bound by this entry. */ - struct inode *obj; -}; - -int is_name_acceptable(const struct inode *inode, const char *name UNUSED_ARG, int len); -int is_dir_empty(const struct inode *dir); -int reiser4_update_dir(struct inode *dir); - -void dispose_cursors(struct inode *inode); -void load_cursors(struct inode *inode); -void kill_cursors(struct inode *inode); +#include */ -typedef struct dir_cursor dir_cursor; +/* declarations of functions implementing HASHED_DIR_PLUGIN_ID dir plugin */ -TYPE_SAFE_HASH_DECLARE(d_cursor, dir_cursor); +/* "hashed" directory methods of dir plugin */ +void build_entry_key_hashed(const struct inode *, const struct qstr *, + reiser4_key *); -int d_cursor_init_at(struct super_block *s); -void d_cursor_done_at(struct super_block *s); +/* declarations of functions implementing SEEKABLE_HASHED_DIR_PLUGIN_ID dir plugin */ -/* - * information about d_cursors (detached readdir state) maintained in reiser4 - * specific portion of reiser4 super-block. See dir.c for more information on - * d_cursors. - */ -typedef struct d_cursor_info { - d_cursor_hash_table table; - struct radix_tree_root tree; -} d_cursor_info; +/* "seekable" directory methods of dir plugin */ +void build_entry_key_seekable(const struct inode *, const struct qstr *, + reiser4_key *); /* __REISER4_DIR_H__ */ #endif diff -puN fs/reiser4/plugin/dir/hashed_dir.c~reiser4-big-update fs/reiser4/plugin/dir/hashed_dir.c --- devel/fs/reiser4/plugin/dir/hashed_dir.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/dir/hashed_dir.c 2005-09-15 19:51:08.000000000 -0700 @@ -4,8 +4,6 @@ /* Directory plugin using hashes (see fs/reiser4/plugin/hash.c) to map file names to the files. */ -/* See fs/reiser4/doc/directory-service for initial design note. */ - /* * Hashed directory logically consists of persistent directory * entries. Directory entry is a pair of a file name and a key of stat-data of @@ -28,1428 +26,52 @@ * */ -#include "../../forward.h" -#include "../../debug.h" -#include "../../spin_macros.h" -#include "../../key.h" -#include "../../kassign.h" -#include "../../coord.h" -#include "../../seal.h" -#include "dir.h" -#include "../item/item.h" -#include "../security/perm.h" -#include "../pseudo/pseudo.h" -#include "../plugin.h" -#include "../object.h" -#include "../../jnode.h" -#include "../../znode.h" -#include "../../tree.h" -#include "../../vfs_ops.h" #include "../../inode.h" -#include "../../reiser4.h" -#include "../../safe_link.h" - -#include /* for struct inode */ -#include /* for struct dentry */ - -static int create_dot_dotdot(struct inode *object, struct inode *parent); -static int find_entry(struct inode *dir, struct dentry *name, - lock_handle * lh, znode_lock_mode mode, - reiser4_dir_entry_desc * entry); -static int check_item(const struct inode *dir, - const coord_t * coord, const char *name); - -static reiser4_block_nr -hashed_estimate_init(struct inode *parent, struct inode *object) -{ - reiser4_block_nr res = 0; - - assert("vpf-321", parent != NULL); - assert("vpf-322", object != NULL); - - /* hashed_add_entry(object) */ - res += inode_dir_plugin(object)->estimate.add_entry(object); - /* reiser4_add_nlink(object) */ - res += inode_file_plugin(object)->estimate.update(object); - /* hashed_add_entry(object) */ - res += inode_dir_plugin(object)->estimate.add_entry(object); - /* reiser4_add_nlink(parent) */ - res += inode_file_plugin(parent)->estimate.update(parent); - - return 0; -} - -/* plugin->u.dir.init - create sd for directory file. Create stat-data, dot, and dotdot. */ -reiser4_internal int -init_hashed(struct inode *object /* new directory */ , - struct inode *parent /* parent directory */ , - reiser4_object_create_data * data UNUSED_ARG /* info passed - * to us, this - * is filled by - * reiser4() - * syscall in - * particular */ ) -{ - reiser4_block_nr reserve; - - assert("nikita-680", object != NULL); - assert("nikita-681", S_ISDIR(object->i_mode)); - assert("nikita-682", parent != NULL); - assert("nikita-684", data != NULL); - assert("nikita-686", data->id == DIRECTORY_FILE_PLUGIN_ID); - assert("nikita-687", object->i_mode & S_IFDIR); - - reserve = hashed_estimate_init(parent, object); - if (reiser4_grab_space(reserve, BA_CAN_COMMIT)) - return RETERR(-ENOSPC); - - return create_dot_dotdot(object, parent); -} - -static reiser4_block_nr -hashed_estimate_done(struct inode *object) -{ - reiser4_block_nr res = 0; - - /* hashed_rem_entry(object) */ - res += inode_dir_plugin(object)->estimate.rem_entry(object); - return res; -} - -/* plugin->u.dir.estimate.unlink */ -reiser4_internal reiser4_block_nr -estimate_unlink_hashed(struct inode *parent, struct inode *object) -{ - reiser4_block_nr res = 0; - - /* hashed_rem_entry(object) */ - res += inode_dir_plugin(object)->estimate.rem_entry(object); - /* del_nlink(parent) */ - res += 2 * inode_file_plugin(parent)->estimate.update(parent); - - return res; -} - -/* ->delete() method of directory plugin - plugin->u.dir.done - Delete dot, and call common_file_delete() to delete stat data. -*/ -reiser4_internal int -done_hashed(struct inode *object /* object being deleted */) -{ - int result; - reiser4_block_nr reserve; - struct dentry goodby_dots; - reiser4_dir_entry_desc entry; - - assert("nikita-1449", object != NULL); - - if (inode_get_flag(object, REISER4_NO_SD)) - return 0; - - /* of course, this can be rewritten to sweep everything in one - cut_tree(). */ - memset(&entry, 0, sizeof entry); - - /* FIXME: this done method is called from delete_directory_common which - * reserved space already */ - reserve = hashed_estimate_done(object); - if (reiser4_grab_space(reserve, BA_CAN_COMMIT | BA_RESERVED)) - return RETERR(-ENOSPC); - - memset(&goodby_dots, 0, sizeof goodby_dots); - entry.obj = goodby_dots.d_inode = object; - goodby_dots.d_name.name = "."; - goodby_dots.d_name.len = 1; - result = rem_entry_hashed(object, &goodby_dots, &entry); - reiser4_free_dentry_fsdata(&goodby_dots); - if (unlikely(result != 0 && result != -ENOMEM && result != -ENOENT)) - /* only worth a warning - - "values of B will give rise to dom!\n" - -- v6src/s2/mv.c:89 - */ - warning("nikita-2252", "Cannot remove dot of %lli: %i", - (unsigned long long)get_inode_oid(object), result); - return 0; -} - -/* ->detach() method of directory plugin - plugin->u.dir.done - Delete dotdot, decrease nlink on parent -*/ -reiser4_internal int -detach_hashed(struct inode *object, struct inode *parent) -{ - int result; - struct dentry goodby_dots; - reiser4_dir_entry_desc entry; - - assert("nikita-2885", object != NULL); - assert("nikita-2886", !inode_get_flag(object, REISER4_NO_SD)); - - memset(&entry, 0, sizeof entry); - - /* NOTE-NIKITA this only works if @parent is -the- parent of - @object, viz. object whose key is stored in dotdot - entry. Wouldn't work with hard-links on directories. */ - memset(&goodby_dots, 0, sizeof goodby_dots); - entry.obj = goodby_dots.d_inode = parent; - goodby_dots.d_name.name = ".."; - goodby_dots.d_name.len = 2; - result = rem_entry_hashed(object, &goodby_dots, &entry); - reiser4_free_dentry_fsdata(&goodby_dots); - if (result == 0) { - /* the dot should be the only entry remaining at this time... */ - assert("nikita-3400", object->i_size == 1); - /* and, together with the only name directory can have, they - * provides for the last 2 remaining references. If we get - * here as part of error handling during mkdir, @object - * possibly has no name yet, so its nlink == 1. If we get here - * from rename (targeting empty directory), it has no name - * already, so its nlink == 1. */ - assert("nikita-3401", - object->i_nlink == 2 || object->i_nlink == 1); - - reiser4_del_nlink(parent, object, 0); - } - return result; -} - - -/* ->owns_item() for hashed directory object plugin. */ -reiser4_internal int -owns_item_hashed(const struct inode *inode /* object to check against */ , - const coord_t * coord /* coord of item to check */ ) -{ - reiser4_key item_key; - - assert("nikita-1335", inode != NULL); - assert("nikita-1334", coord != NULL); - - if (item_type_by_coord(coord) == DIR_ENTRY_ITEM_TYPE) - return get_key_locality(item_key_by_coord(coord, &item_key)) == get_inode_oid(inode); - else - return owns_item_common(inode, coord); -} - -/* helper function for directory_file_create(). Create "." and ".." */ -static int -create_dot_dotdot(struct inode *object /* object to create dot and - * dotdot for */ , - struct inode *parent /* parent of @object */ ) -{ - int result; - struct dentry dots_entry; - reiser4_dir_entry_desc entry; - - assert("nikita-688", object != NULL); - assert("nikita-689", S_ISDIR(object->i_mode)); - assert("nikita-691", parent != NULL); - - /* We store dot and dotdot as normal directory entries. This is - not necessary, because almost all information stored in them - is already in the stat-data of directory, the only thing - being missed is objectid of grand-parent directory that can - easily be added there as extension. - - But it is done the way it is done, because not storing dot - and dotdot will lead to the following complications: - - . special case handling in ->lookup(). - . addition of another extension to the sd. - . dependency on key allocation policy for stat data. - - */ - - memset(&entry, 0, sizeof entry); - memset(&dots_entry, 0, sizeof dots_entry); - entry.obj = dots_entry.d_inode = object; - dots_entry.d_name.name = "."; - dots_entry.d_name.len = 1; - result = add_entry_hashed(object, &dots_entry, NULL, &entry); - reiser4_free_dentry_fsdata(&dots_entry); - - if (result == 0) { - result = reiser4_add_nlink(object, object, 0); - if (result == 0) { - entry.obj = dots_entry.d_inode = parent; - dots_entry.d_name.name = ".."; - dots_entry.d_name.len = 2; - result = add_entry_hashed(object, - &dots_entry, NULL, &entry); - reiser4_free_dentry_fsdata(&dots_entry); - /* if creation of ".." failed, iput() will delete - object with ".". */ - if (result == 0) { - result = reiser4_add_nlink(parent, object, 0); - if (result != 0) - /* - * if we failed to bump i_nlink, try - * to remove ".." - */ - detach_hashed(object, parent); - } - } - } - - if (result != 0) { - /* - * in the case of error, at least update stat-data so that, - * ->i_nlink updates are not lingering. - */ - reiser4_update_sd(object); - reiser4_update_sd(parent); - } - - return result; -} - -/* looks for name specified in @dentry in directory @parent and if name is - found - key of object found entry points to is stored in @entry->key */ -static int -lookup_name_hashed(struct inode *parent /* inode of directory to lookup for - * name in */, - struct dentry *dentry /* name to look for */, - reiser4_key *key /* place to store key */) -{ - int result; - coord_t *coord; - lock_handle lh; - const char *name; - int len; - reiser4_dir_entry_desc entry; - reiser4_dentry_fsdata *fsdata; - - assert("nikita-1247", parent != NULL); - assert("nikita-1248", dentry != NULL); - assert("nikita-1123", dentry->d_name.name != NULL); - assert("vs-1486", - dentry->d_op == &get_super_private(parent->i_sb)->ops.dentry); - - result = perm_chk(parent, lookup, parent, dentry); - if (result != 0) - return 0; - - name = dentry->d_name.name; - len = dentry->d_name.len; - - if (!is_name_acceptable(parent, name, len)) - /* some arbitrary error code to return */ - return RETERR(-ENAMETOOLONG); - - fsdata = reiser4_get_dentry_fsdata(dentry); - if (IS_ERR(fsdata)) - return PTR_ERR(fsdata); - - coord = &fsdata->dec.entry_coord; - coord_clear_iplug(coord); - init_lh(&lh); - - /* find entry in a directory. This is plugin method. */ - result = find_entry(parent, dentry, &lh, ZNODE_READ_LOCK, &entry); - if (result == 0) { - /* entry was found, extract object key from it. */ - result = WITH_COORD(coord, item_plugin_by_coord(coord)->s.dir.extract_key(coord, key)); - } - done_lh(&lh); - return result; - -} - -/* - * helper for ->lookup() and ->get_parent() methods: if @inode is a - * light-weight file, setup its credentials that are not stored in the - * stat-data in this case - */ -static void -check_light_weight(struct inode *inode, struct inode *parent) -{ - if (inode_get_flag(inode, REISER4_LIGHT_WEIGHT)) { - inode->i_uid = parent->i_uid; - inode->i_gid = parent->i_gid; - /* clear light-weight flag. If inode would be read by any - other name, [ug]id wouldn't change. */ - inode_clr_flag(inode, REISER4_LIGHT_WEIGHT); - } -} - -/* implementation of ->lookup() method for hashed directories. */ -reiser4_internal int -lookup_hashed(struct inode * parent /* inode of directory to - * lookup into */ , - struct dentry **dentryloc /* name to look for */ ) -{ - int result; - struct inode *inode; - struct dentry *dentry; - reiser4_dir_entry_desc entry; - - dentry = *dentryloc; - /* set up operations on dentry. */ - dentry->d_op = &get_super_private(parent->i_sb)->ops.dentry; - - result = lookup_name_hashed(parent, dentry, &entry.key); - if (result == 0) { - inode = reiser4_iget(parent->i_sb, &entry.key, 0); - if (!IS_ERR(inode)) { - check_light_weight(inode, parent); - /* success */ - *dentryloc = d_splice_alias(inode, dentry); - reiser4_iget_complete(inode); - } else - result = PTR_ERR(inode); - } else if (result == -ENOENT) - result = lookup_pseudo_file(parent, dentryloc); - - return result; -} - -/* - * ->get_parent() method of hashed directory. This is used by NFS kernel - * server to "climb" up directory tree to check permissions. - */ -reiser4_internal struct dentry * -get_parent_hashed(struct inode *child) -{ - struct super_block *s; - struct inode *parent; - struct dentry dotdot; - struct dentry *dentry; - reiser4_key key; - int result; - - /* - * lookup dotdot entry. - */ - - s = child->i_sb; - memset(&dotdot, 0, sizeof(dotdot)); - dotdot.d_name.name = ".."; - dotdot.d_name.len = 2; - dotdot.d_op = &get_super_private(s)->ops.dentry; - - result = lookup_name_hashed(child, &dotdot, &key); - if (result != 0) - return ERR_PTR(result); - - parent = reiser4_iget(s, &key, 1); - if (!IS_ERR(parent)) { - /* - * FIXME-NIKITA dubious: attributes are inherited from @child - * to @parent. But: - * - * (*) this is the only this we can do - * - * (*) attributes of light-weight object are inherited - * from a parent through which object was looked up first, - * so it is ambiguous anyway. - * - */ - check_light_weight(parent, child); - reiser4_iget_complete(parent); - dentry = d_alloc_anon(parent); - if (dentry == NULL) { - iput(parent); - dentry = ERR_PTR(RETERR(-ENOMEM)); - } else - dentry->d_op = &get_super_private(s)->ops.dentry; - } else if (PTR_ERR(parent) == -ENOENT) - dentry = ERR_PTR(RETERR(-ESTALE)); - else - dentry = (void *)parent; - return dentry; -} - -static const char *possible_leak = "Possible disk space leak."; - -/* re-bind existing name at @from_coord in @from_dir to point to @to_inode. - - Helper function called from hashed_rename() */ -static int -replace_name(struct inode *to_inode /* inode where @from_coord is - * to be re-targeted at */ , - struct inode *from_dir /* directory where @from_coord - * lives */ , - struct inode *from_inode /* inode @from_coord - * originally point to */ , - coord_t * from_coord /* where directory entry is in - * the tree */ , - lock_handle * from_lh /* lock handle on @from_coord */ ) -{ - item_plugin *from_item; - int result; - znode *node; - - coord_clear_iplug(from_coord); - node = from_coord->node; - result = zload(node); - if (result != 0) - return result; - from_item = item_plugin_by_coord(from_coord); - if (item_type_by_coord(from_coord) == DIR_ENTRY_ITEM_TYPE) { - reiser4_key to_key; - - build_sd_key(to_inode, &to_key); - - /* everything is found and prepared to change directory entry - at @from_coord to point to @to_inode. - - @to_inode is just about to get new name, so bump its link - counter. - - */ - result = reiser4_add_nlink(to_inode, from_dir, 0); - if (result != 0) { - /* Don't issue warning: this may be plain -EMLINK */ - zrelse(node); - return result; - } - - result = from_item->s.dir.update_key(from_coord, &to_key, from_lh); - if (result != 0) { - reiser4_del_nlink(to_inode, from_dir, 0); - zrelse(node); - return result; - } - - /* @from_inode just lost its name, he-he. - - If @from_inode was directory, it contained dotdot pointing - to @from_dir. @from_dir i_nlink will be decreased when - iput() will be called on @from_inode. - - If file-system is not ADG (hard-links are - supported on directories), iput(from_inode) will not remove - @from_inode, and thus above is incorrect, but hard-links on - directories are problematic in many other respects. - */ - result = reiser4_del_nlink(from_inode, from_dir, 0); - if (result != 0) { - warning("nikita-2330", - "Cannot remove link from source: %i. %s", - result, possible_leak); - } - /* Has to return success, because entry is already - * modified. */ - result = 0; - - /* NOTE-NIKITA consider calling plugin method in stead of - accessing inode fields directly. */ - from_dir->i_mtime = CURRENT_TIME; - } else { - warning("nikita-2326", "Unexpected item type"); - result = RETERR(-EIO); - } - zrelse(node); - return result; -} - -/* add new entry pointing to @inode into @dir at @coord, locked by @lh - - Helper function used by hashed_rename(). */ -static int -add_name(struct inode *inode /* inode where @coord is to be - * re-targeted at */ , - struct inode *dir /* directory where @coord lives */ , - struct dentry *name /* new name */ , - coord_t * coord /* where directory entry is in the tree */ , - lock_handle * lh /* lock handle on @coord */ , - int is_dir /* true, if @inode is directory */ ) -{ - int result; - reiser4_dir_entry_desc entry; - - assert("nikita-2333", lh->node == coord->node); - assert("nikita-2334", is_dir == S_ISDIR(inode->i_mode)); - - memset(&entry, 0, sizeof entry); - entry.obj = inode; - /* build key of directory entry description */ - inode_dir_plugin(dir)->build_entry_key(dir, &name->d_name, &entry.key); - - /* ext2 does this in different order: first inserts new entry, - then increases directory nlink. We don't want do this, - because reiser4_add_nlink() calls ->add_link() plugin - method that can fail for whatever reason, leaving as with - cleanup problems. - */ - /* @inode is getting new name */ - reiser4_add_nlink(inode, dir, 0); - /* create @new_name in @new_dir pointing to - @old_inode */ - result = WITH_COORD(coord, - inode_dir_item_plugin(dir)->s.dir.add_entry(dir, - coord, - lh, - name, - &entry)); - if (result != 0) { - int result2; - result2 = reiser4_del_nlink(inode, dir, 0); - if (result2 != 0) { - warning("nikita-2327", "Cannot drop link on %lli %i. %s", - (unsigned long long)get_inode_oid(inode), - result2, possible_leak); - } - } else - INODE_INC_FIELD(dir, i_size); - return result; -} - -static reiser4_block_nr -hashed_estimate_rename( - struct inode *old_dir /* directory where @old is located */, - struct dentry *old_name /* old name */, - struct inode *new_dir /* directory where @new is located */, - struct dentry *new_name /* new name */) -{ - reiser4_block_nr res1, res2; - dir_plugin *p_parent_old, *p_parent_new; - file_plugin *p_child_old, *p_child_new; - - assert("vpf-311", old_dir != NULL); - assert("vpf-312", new_dir != NULL); - assert("vpf-313", old_name != NULL); - assert("vpf-314", new_name != NULL); - - p_parent_old = inode_dir_plugin(old_dir); - p_parent_new = inode_dir_plugin(new_dir); - p_child_old = inode_file_plugin(old_name->d_inode); - if (new_name->d_inode) - p_child_new = inode_file_plugin(new_name->d_inode); - else - p_child_new = 0; - - /* find_entry - can insert one leaf. */ - res1 = res2 = 1; - - /* replace_name */ - { - /* reiser4_add_nlink(p_child_old) and reiser4_del_nlink(p_child_old) */ - res1 += 2 * p_child_old->estimate.update(old_name->d_inode); - /* update key */ - res1 += 1; - /* reiser4_del_nlink(p_child_new) */ - if (p_child_new) - res1 += p_child_new->estimate.update(new_name->d_inode); - } - - /* else add_name */ - { - /* reiser4_add_nlink(p_parent_new) and reiser4_del_nlink(p_parent_new) */ - res2 += 2 * inode_file_plugin(new_dir)->estimate.update(new_dir); - /* reiser4_add_nlink(p_parent_old) */ - res2 += p_child_old->estimate.update(old_name->d_inode); - /* add_entry(p_parent_new) */ - res2 += p_parent_new->estimate.add_entry(new_dir); - /* reiser4_del_nlink(p_parent_old) */ - res2 += p_child_old->estimate.update(old_name->d_inode); - } - - res1 = res1 < res2 ? res2 : res1; - - - /* reiser4_write_sd(p_parent_new) */ - res1 += inode_file_plugin(new_dir)->estimate.update(new_dir); - - /* reiser4_write_sd(p_child_new) */ - if (p_child_new) - res1 += p_child_new->estimate.update(new_name->d_inode); - - /* hashed_rem_entry(p_parent_old) */ - res1 += p_parent_old->estimate.rem_entry(old_dir); - - /* reiser4_del_nlink(p_child_old) */ - res1 += p_child_old->estimate.update(old_name->d_inode); - - /* replace_name */ - { - /* reiser4_add_nlink(p_parent_dir_new) */ - res1 += inode_file_plugin(new_dir)->estimate.update(new_dir); - /* update_key */ - res1 += 1; - /* reiser4_del_nlink(p_parent_new) */ - res1 += inode_file_plugin(new_dir)->estimate.update(new_dir); - /* reiser4_del_nlink(p_parent_old) */ - res1 += inode_file_plugin(old_dir)->estimate.update(old_dir); - } - - /* reiser4_write_sd(p_parent_old) */ - res1 += inode_file_plugin(old_dir)->estimate.update(old_dir); - - /* reiser4_write_sd(p_child_old) */ - res1 += p_child_old->estimate.update(old_name->d_inode); - - return res1; -} - -static int -hashed_rename_estimate_and_grab( - struct inode *old_dir /* directory where @old is located */ , - struct dentry *old_name /* old name */ , - struct inode *new_dir /* directory where @new is located */ , - struct dentry *new_name /* new name */ ) -{ - reiser4_block_nr reserve; - - reserve = hashed_estimate_rename(old_dir, old_name, new_dir, new_name); - - if (reiser4_grab_space(reserve, BA_CAN_COMMIT)) - return RETERR(-ENOSPC); - return 0; -} - -/* check whether @old_inode and @new_inode can be moved within file system - * tree. This singles out attempts to rename pseudo-files, for example. */ -static int -can_rename(struct inode *old_dir, struct inode *old_inode, - struct inode *new_dir, struct inode *new_inode) -{ - file_plugin *fplug; - dir_plugin *dplug; - - assert("nikita-3370", old_inode != NULL); - - dplug = inode_dir_plugin(new_dir); - fplug = inode_file_plugin(old_inode); - - if (dplug == NULL) - return RETERR(-ENOTDIR); - else if (dplug->create_child == NULL) - return RETERR(-EPERM); - else if (!fplug->can_add_link(old_inode)) - return RETERR(-EMLINK); - else if (new_inode != NULL) { - fplug = inode_file_plugin(new_inode); - if (fplug->can_rem_link != NULL && - !fplug->can_rem_link(new_inode)) - return RETERR(-EBUSY); - } - return 0; -} - -/* ->rename directory plugin method implementation for hashed directories. - plugin->u.dir.rename - See comments in the body. - - It is arguable that this function can be made generic so, that it will be - applicable to any kind of directory plugin that deals with directories - composed out of directory entries. The only obstacle here is that we don't - have any data-type to represent directory entry. This should be - re-considered when more than one different directory plugin will be - implemented. -*/ -reiser4_internal int -rename_hashed(struct inode *old_dir /* directory where @old is located */ , - struct dentry *old_name /* old name */ , - struct inode *new_dir /* directory where @new is located */ , - struct dentry *new_name /* new name */ ) -{ - /* From `The Open Group Base Specifications Issue 6' - - - If either the old or new argument names a symbolic link, rename() - shall operate on the symbolic link itself, and shall not resolve - the last component of the argument. If the old argument and the new - argument resolve to the same existing file, rename() shall return - successfully and perform no other action. - - [this is done by VFS: vfs_rename()] - - - If the old argument points to the pathname of a file that is not a - directory, the new argument shall not point to the pathname of a - directory. - - [checked by VFS: vfs_rename->may_delete()] - - If the link named by the new argument exists, it shall - be removed and old renamed to new. In this case, a link named new - shall remain visible to other processes throughout the renaming - operation and refer either to the file referred to by new or old - before the operation began. - - [we should assure this] - - Write access permission is required for - both the directory containing old and the directory containing new. - - [checked by VFS: vfs_rename->may_delete(), may_create()] - - If the old argument points to the pathname of a directory, the new - argument shall not point to the pathname of a file that is not a - directory. - - [checked by VFS: vfs_rename->may_delete()] - - If the directory named by the new argument exists, it - shall be removed and old renamed to new. In this case, a link named - new shall exist throughout the renaming operation and shall refer - either to the directory referred to by new or old before the - operation began. - - [we should assure this] - - If new names an existing directory, it shall be - required to be an empty directory. - - [we should check this] - - If the old argument points to a pathname of a symbolic link, the - symbolic link shall be renamed. If the new argument points to a - pathname of a symbolic link, the symbolic link shall be removed. - - The new pathname shall not contain a path prefix that names - old. Write access permission is required for the directory - containing old and the directory containing new. If the old - argument points to the pathname of a directory, write access - permission may be required for the directory named by old, and, if - it exists, the directory named by new. - - [checked by VFS: vfs_rename(), vfs_rename_dir()] - - If the link named by the new argument exists and the file's link - count becomes 0 when it is removed and no process has the file - open, the space occupied by the file shall be freed and the file - shall no longer be accessible. If one or more processes have the - file open when the last link is removed, the link shall be removed - before rename() returns, but the removal of the file contents shall - be postponed until all references to the file are closed. - - [iput() handles this, but we can do this manually, a la - reiser4_unlink()] - - Upon successful completion, rename() shall mark for update the - st_ctime and st_mtime fields of the parent directory of each file. - - [N/A] - - */ - - int result; - int is_dir; /* is @old_name directory */ - - struct inode *old_inode; - struct inode *new_inode; - - reiser4_dir_entry_desc old_entry; - reiser4_dir_entry_desc new_entry; - - coord_t *new_coord; - - reiser4_dentry_fsdata *new_fsdata; - - lock_handle new_lh; - - dir_plugin *dplug; - file_plugin *fplug; - - assert("nikita-2318", old_dir != NULL); - assert("nikita-2319", new_dir != NULL); - assert("nikita-2320", old_name != NULL); - assert("nikita-2321", new_name != NULL); - - old_inode = old_name->d_inode; - new_inode = new_name->d_inode; - - dplug = inode_dir_plugin(old_dir); - fplug = NULL; - - new_fsdata = reiser4_get_dentry_fsdata(new_name); - if (IS_ERR(new_fsdata)) - return PTR_ERR(new_fsdata); - - new_coord = &new_fsdata->dec.entry_coord; - coord_clear_iplug(new_coord); - - is_dir = S_ISDIR(old_inode->i_mode); - - assert("nikita-3461", old_inode->i_nlink >= 1 + !!is_dir); - - /* if target is existing directory and it's not empty---return error. - - This check is done specifically, because is_dir_empty() requires - tree traversal and have to be done before locks are taken. - */ - if (is_dir && new_inode != NULL && is_dir_empty(new_inode) != 0) - return RETERR(-ENOTEMPTY); - - result = can_rename(old_dir, old_inode, new_dir, new_inode); - if (result != 0) - return result; - - result = hashed_rename_estimate_and_grab(old_dir, old_name, - new_dir, new_name); - if (result != 0) - return result; - - init_lh(&new_lh); - - /* find entry for @new_name */ - result = find_entry(new_dir, - new_name, &new_lh, ZNODE_WRITE_LOCK, &new_entry); - - if (IS_CBKERR(result)) { - done_lh(&new_lh); - return result; - } - - seal_done(&new_fsdata->dec.entry_seal); - - /* add or replace name for @old_inode as @new_name */ - if (new_inode != NULL) { - /* target (@new_name) exists. */ - /* Not clear what to do with objects that are - both directories and files at the same time. */ - if (result == CBK_COORD_FOUND) { - result = replace_name(old_inode, - new_dir, - new_inode, - new_coord, - &new_lh); - if (result == 0) - fplug = inode_file_plugin(new_inode); - } else if (result == CBK_COORD_NOTFOUND) { - /* VFS told us that @new_name is bound to existing - inode, but we failed to find directory entry. */ - warning("nikita-2324", "Target not found"); - result = RETERR(-ENOENT); - } - } else { - /* target (@new_name) doesn't exists. */ - if (result == CBK_COORD_NOTFOUND) - result = add_name(old_inode, - new_dir, - new_name, - new_coord, - &new_lh, is_dir); - else if (result == CBK_COORD_FOUND) { - /* VFS told us that @new_name is "negative" dentry, - but we found directory entry. */ - warning("nikita-2331", "Target found unexpectedly"); - result = RETERR(-EIO); - } - } - - assert("nikita-3462", ergo(result == 0, - old_inode->i_nlink >= 2 + !!is_dir)); - - /* We are done with all modifications to the @new_dir, release lock on - node. */ - done_lh(&new_lh); - - if (fplug != NULL) { - /* detach @new_inode from name-space */ - result = fplug->detach(new_inode, new_dir); - if (result != 0) - warning("nikita-2330", "Cannot detach %lli: %i. %s", - (unsigned long long)get_inode_oid(new_inode), - result, possible_leak); - } - - if (new_inode != NULL) - reiser4_mark_inode_dirty(new_inode); - - if (result == 0) { - memset(&old_entry, 0, sizeof old_entry); - old_entry.obj = old_inode; - - dplug->build_entry_key(old_dir, - &old_name->d_name, &old_entry.key); - - /* At this stage new name was introduced for - @old_inode. @old_inode, @new_dir, and @new_inode i_nlink - counters were updated. - - We want to remove @old_name now. If @old_inode wasn't - directory this is simple. - */ - result = rem_entry_hashed(old_dir, old_name, &old_entry); - if (result != 0 && result != -ENOMEM) { - warning("nikita-2335", - "Cannot remove old name: %i", result); - } else { - result = reiser4_del_nlink(old_inode, old_dir, 0); - if (result != 0 && result != -ENOMEM) { - warning("nikita-2337", - "Cannot drop link on old: %i", result); - } - } - - if (result == 0 && is_dir) { - /* @old_inode is directory. We also have to update - dotdot entry. */ - coord_t *dotdot_coord; - lock_handle dotdot_lh; - struct dentry dotdot_name; - reiser4_dir_entry_desc dotdot_entry; - reiser4_dentry_fsdata dataonstack; - reiser4_dentry_fsdata *fsdata; - - memset(&dataonstack, 0, sizeof dataonstack); - memset(&dotdot_entry, 0, sizeof dotdot_entry); - dotdot_entry.obj = old_dir; - memset(&dotdot_name, 0, sizeof dotdot_name); - dotdot_name.d_name.name = ".."; - dotdot_name.d_name.len = 2; - /* - * allocate ->d_fsdata on the stack to avoid using - * reiser4_get_dentry_fsdata(). Locking is not needed, - * because dentry is private to the current thread. - */ - dotdot_name.d_fsdata = &dataonstack; - init_lh(&dotdot_lh); - - fsdata = &dataonstack; - dotdot_coord = &fsdata->dec.entry_coord; - coord_clear_iplug(dotdot_coord); +void complete_entry_key(const struct inode *, const char *name, + int len, reiser4_key * result); - result = find_entry(old_inode, &dotdot_name, &dotdot_lh, - ZNODE_WRITE_LOCK, &dotdot_entry); - if (result == 0) { - /* replace_name() decreases i_nlink on - * @old_dir */ - result = replace_name(new_dir, - old_inode, - old_dir, - dotdot_coord, - &dotdot_lh); - } else - result = RETERR(-EIO); - done_lh(&dotdot_lh); - } - } - reiser4_update_dir(new_dir); - reiser4_update_dir(old_dir); - reiser4_mark_inode_dirty(old_inode); - if (result == 0) { - file_plugin *fplug; - - if (new_inode != NULL) { - /* add safe-link for target file (in case we removed - * last reference to the poor fellow */ - fplug = inode_file_plugin(new_inode); - if (new_inode->i_nlink == 0) - result = safe_link_add(new_inode, SAFE_UNLINK); - } - } - return result; -} - -/* ->add_entry() method for hashed directory object plugin. - plugin->u.dir.add_entry -*/ -reiser4_internal int -add_entry_hashed(struct inode *object /* directory to add new name - * in */ , - struct dentry *where /* new name */ , - reiser4_object_create_data * data UNUSED_ARG /* parameters - * of new - * object */ , - reiser4_dir_entry_desc * entry /* parameters of new - * directory entry */ ) -{ - int result; - coord_t *coord; - lock_handle lh; - reiser4_dentry_fsdata *fsdata; - reiser4_block_nr reserve; - - assert("nikita-1114", object != NULL); - assert("nikita-1250", where != NULL); - - fsdata = reiser4_get_dentry_fsdata(where); - if (unlikely(IS_ERR(fsdata))) - return PTR_ERR(fsdata); - - reserve = inode_dir_plugin(object)->estimate.add_entry(object); - if (reiser4_grab_space(reserve, BA_CAN_COMMIT)) - return RETERR(-ENOSPC); - - init_lh(&lh); - coord = &fsdata->dec.entry_coord; - coord_clear_iplug(coord); - - /* check for this entry in a directory. This is plugin method. */ - result = find_entry(object, where, &lh, ZNODE_WRITE_LOCK, entry); - if (likely(result == -ENOENT)) { - /* add new entry. Just pass control to the directory - item plugin. */ - assert("nikita-1709", inode_dir_item_plugin(object)); - assert("nikita-2230", coord->node == lh.node); - seal_done(&fsdata->dec.entry_seal); - result = inode_dir_item_plugin(object)->s.dir.add_entry(object, coord, &lh, where, entry); - if (result == 0) { - adjust_dir_file(object, where, fsdata->dec.pos + 1, +1); - INODE_INC_FIELD(object, i_size); - } - } else if (result == 0) { - assert("nikita-2232", coord->node == lh.node); - result = RETERR(-EEXIST); - } - done_lh(&lh); - - return result; -} - -/* ->rem_entry() method for hashed directory object plugin. - plugin->u.dir.rem_entry +/* this is implementation of build_entry_key method of dir + plugin for HASHED_DIR_PLUGIN_ID */ -reiser4_internal int -rem_entry_hashed(struct inode *object /* directory from which entry - * is begin removed */ , - struct dentry *where /* name that is being - * removed */ , - reiser4_dir_entry_desc * entry /* description of entry being - * removed */ ) +void build_entry_key_hashed(const struct inode *dir, /* directory where entry is + * (or will be) in.*/ + const struct qstr *qname, /* name of file referenced + * by this entry */ + reiser4_key * result /* resulting key of directory + * entry */ ) { - int result; - coord_t *coord; - lock_handle lh; - reiser4_dentry_fsdata *fsdata; - __u64 tograb; - - /* yes, nested function, so what? Sue me. */ - int rem_entry(void) { - item_plugin *iplug; - struct inode *child; - - iplug = inode_dir_item_plugin(object); - child = where->d_inode; - assert("nikita-3399", child != NULL); - - /* check that we are really destroying an entry for @child */ - if (REISER4_DEBUG) { - int result; - reiser4_key key; - - result = iplug->s.dir.extract_key(coord, &key); - if (result != 0) - return result; - if (get_key_objectid(&key) != get_inode_oid(child)) { - warning("nikita-3397", - "rem_entry: %#llx != %#llx\n", - get_key_objectid(&key), - (unsigned long long)get_inode_oid(child)); - return RETERR(-EIO); - } - } - return iplug->s.dir.rem_entry(object, - &where->d_name, coord, &lh, entry); - } - - assert("nikita-1124", object != NULL); - assert("nikita-1125", where != NULL); - - tograb = inode_dir_plugin(object)->estimate.rem_entry(object); - result = reiser4_grab_space(tograb, BA_CAN_COMMIT | BA_RESERVED); - if (result != 0) - return RETERR(-ENOSPC); - - init_lh(&lh); - - /* check for this entry in a directory. This is plugin method. */ - result = find_entry(object, where, &lh, ZNODE_WRITE_LOCK, entry); - fsdata = reiser4_get_dentry_fsdata(where); - if (IS_ERR(fsdata)) - return PTR_ERR(fsdata); - - coord = &fsdata->dec.entry_coord; - - assert("nikita-3404", - get_inode_oid(where->d_inode) != get_inode_oid(object) || - object->i_size <= 1); - - coord_clear_iplug(coord); - if (result == 0) { - /* remove entry. Just pass control to the directory item - plugin. */ - assert("vs-542", inode_dir_item_plugin(object)); - seal_done(&fsdata->dec.entry_seal); - adjust_dir_file(object, where, fsdata->dec.pos, -1); - result = WITH_COORD(coord, rem_entry()); - if (result == 0) { - if (object->i_size >= 1) - INODE_DEC_FIELD(object, i_size); - else { - warning("nikita-2509", "Dir %llu is runt", - (unsigned long long)get_inode_oid(object)); - result = RETERR(-EIO); - } - - assert("nikita-3405", where->d_inode->i_nlink != 1 || - where->d_inode->i_size != 2 || - inode_dir_plugin(where->d_inode) == NULL); - } - } - done_lh(&lh); - - return result; -} - -static int entry_actor(reiser4_tree * tree /* tree being scanned */ , - coord_t * coord /* current coord */ , - lock_handle * lh /* current lock handle */ , - void *args /* argument to scan */ ); - -/* - * argument package used by entry_actor to scan entries with identical keys. - */ -typedef struct entry_actor_args { - /* name we are looking for */ const char *name; - /* key of directory entry. entry_actor() scans through sequence of - * items/units having the same key */ - reiser4_key *key; - /* how many entries with duplicate key was scanned so far. */ - int non_uniq; -#if defined(REISER4_USE_COLLISION_LIMIT) || defined(REISER4_STATS) - /* scan limit */ - int max_non_uniq; -#endif - /* return parameter: set to true, if ->name wasn't found */ - int not_found; - /* what type of lock to take when moving to the next node during - * scan */ - znode_lock_mode mode; - - /* last coord that was visited during scan */ - coord_t last_coord; - /* last node locked during scan */ - lock_handle last_lh; - /* inode of directory */ - const struct inode *inode; -} entry_actor_args; - -static int -check_entry(const struct inode *dir, coord_t *coord, const struct qstr *name) -{ - return WITH_COORD(coord, check_item(dir, coord, name->name)); -} - -/* Look for given @name within directory @dir. - - This is called during lookup, creation and removal of directory - entries. - - First calculate key that directory entry for @name would have. Search - for this key in the tree. If such key is found, scan all items with - the same key, checking name in each directory entry along the way. -*/ -static int -find_entry(struct inode *dir /* directory to scan */, - struct dentry *de /* name to search for */, - lock_handle * lh /* resulting lock handle */, - znode_lock_mode mode /* required lock mode */, - reiser4_dir_entry_desc * entry /* parameters of found directory - * entry */) -{ - const struct qstr *name; - seal_t *seal; - coord_t *coord; - int result; - __u32 flags; - de_location *dec; - reiser4_dentry_fsdata *fsdata; - - assert("nikita-1130", lh != NULL); - assert("nikita-1128", dir != NULL); - - name = &de->d_name; - assert("nikita-1129", name != NULL); - - /* dentry private data don't require lock, because dentry - manipulations are protected by i_sem on parent. - - This is not so for inodes, because there is no -the- parent in - inode case. - */ - fsdata = reiser4_get_dentry_fsdata(de); - if (IS_ERR(fsdata)) - return PTR_ERR(fsdata); - dec = &fsdata->dec; - - coord = &dec->entry_coord; - coord_clear_iplug(coord); - seal = &dec->entry_seal; - /* compose key of directory entry for @name */ - inode_dir_plugin(dir)->build_entry_key(dir, name, &entry->key); - - if (seal_is_set(seal)) { - /* check seal */ - result = seal_validate(seal, coord, &entry->key, - lh, mode, ZNODE_LOCK_LOPRI); - if (result == 0) { - /* key was found. Check that it is really item we are - looking for. */ - result = check_entry(dir, coord, name); - if (result == 0) - return 0; - } - } - flags = (mode == ZNODE_WRITE_LOCK) ? CBK_FOR_INSERT : 0; - /* - * find place in the tree where directory item should be located. - */ - result = object_lookup(dir, - &entry->key, - coord, - lh, - mode, - FIND_EXACT, - LEAF_LEVEL, - LEAF_LEVEL, - flags, - 0/*ra_info*/); - - if (result == CBK_COORD_FOUND) { - entry_actor_args arg; - - /* fast path: no hash collisions */ - result = check_entry(dir, coord, name); - if (result == 0) { - seal_init(seal, coord, &entry->key); - dec->pos = 0; - } else if (result > 0) { - /* Iterate through all units with the same keys. */ - arg.name = name->name; - arg.key = &entry->key; - arg.not_found = 0; - arg.non_uniq = 0; -#if REISER4_USE_COLLISION_LIMIT - arg.max_non_uniq = max_hash_collisions(dir); - assert("nikita-2851", arg.max_non_uniq > 1); -#endif - arg.mode = mode; - arg.inode = dir; - coord_init_zero(&arg.last_coord); - init_lh(&arg.last_lh); - - result = iterate_tree(tree_by_inode(dir), coord, lh, - entry_actor, &arg, mode, 1); - /* if end of the tree or extent was reached during - scanning. */ - if (arg.not_found || (result == -E_NO_NEIGHBOR)) { - /* step back */ - done_lh(lh); - - result = zload(arg.last_coord.node); - if (result == 0) { - coord_clear_iplug(&arg.last_coord); - coord_dup(coord, &arg.last_coord); - move_lh(lh, &arg.last_lh); - result = RETERR(-ENOENT); - zrelse(arg.last_coord.node); - --arg.non_uniq; - } - } - - done_lh(&arg.last_lh); - if (result == 0) - seal_init(seal, coord, &entry->key); - - if (result == 0 || result == -ENOENT) { - assert("nikita-2580", arg.non_uniq > 0); - dec->pos = arg.non_uniq - 1; - } - } - } else - dec->pos = -1; - return result; -} - -/* Function called by find_entry() to look for given name in the directory. */ -static int -entry_actor(reiser4_tree * tree UNUSED_ARG /* tree being scanned */ , - coord_t * coord /* current coord */ , - lock_handle * lh /* current lock handle */ , - void *entry_actor_arg /* argument to scan */ ) -{ - reiser4_key unit_key; - entry_actor_args *args; - - assert("nikita-1131", tree != NULL); - assert("nikita-1132", coord != NULL); - assert("nikita-1133", entry_actor_arg != NULL); - - args = entry_actor_arg; - ++args->non_uniq; -#if REISER4_USE_COLLISION_LIMIT - if (args->non_uniq > args->max_non_uniq) { - args->not_found = 1; - /* hash collision overflow. */ - return RETERR(-EBUSY); - } -#endif - - /* - * did we just reach the end of the sequence of items/units with - * identical keys? - */ - if (!keyeq(args->key, unit_key_by_coord(coord, &unit_key))) { - assert("nikita-1791", keylt(args->key, unit_key_by_coord(coord, &unit_key))); - args->not_found = 1; - args->last_coord.between = AFTER_UNIT; - return 0; - } + int len; - coord_dup(&args->last_coord, coord); - /* - * did scan just moved to the next node? + assert("nikita-1139", dir != NULL); + assert("nikita-1140", qname != NULL); + assert("nikita-1141", qname->name != NULL); + assert("nikita-1142", result != NULL); + + name = qname->name; + len = qname->len; + + assert("nikita-2867", strlen(name) == len); + + reiser4_key_init(result); + /* locality of directory entry's key is objectid of parent + directory */ + set_key_locality(result, get_inode_oid(dir)); + /* minor packing locality is constant */ + set_key_type(result, KEY_FILE_NAME_MINOR); + /* dot is special case---we always want it to be first entry in + a directory. Actually, we just want to have smallest + directory entry. */ - if (args->last_lh.node != lh->node) { - int lock_result; - - /* - * if so, lock new node with the mode requested by the caller - */ - done_lh(&args->last_lh); - assert("nikita-1896", znode_is_any_locked(lh->node)); - lock_result = longterm_lock_znode(&args->last_lh, lh->node, - args->mode, ZNODE_LOCK_HIPRI); - if (lock_result != 0) - return lock_result; - } - return check_item(args->inode, coord, args->name); -} - -/* - * return 0 iff @coord contains a directory entry for the file with the name - * @name. - */ -static int -check_item(const struct inode *dir, const coord_t * coord, const char *name) -{ - item_plugin *iplug; - char buf[DE_NAME_BUF_LEN]; - - iplug = item_plugin_by_coord(coord); - if (iplug == NULL) { - warning("nikita-1135", "Cannot get item plugin"); - print_coord("coord", coord, 1); - return RETERR(-EIO); - } else if (item_id_by_coord(coord) != item_id_by_plugin(inode_dir_item_plugin(dir))) { - /* item id of current item does not match to id of items a - directory is built of */ - warning("nikita-1136", "Wrong item plugin"); - print_coord("coord", coord, 1); - return RETERR(-EIO); - } - assert("nikita-1137", iplug->s.dir.extract_name); - - /* Compare name stored in this entry with name we are looking for. + if (len == 1 && name[0] == '.') + return; - NOTE-NIKITA Here should go code for support of something like - unicode, code tables, etc. - */ - return !!strcmp(name, iplug->s.dir.extract_name(coord, buf)); + /* initialize part of entry key which depends on file name */ + complete_entry_key(dir, name, len, result); } -/* Make Linus happy. - Local variables: +/* Local variables: c-indentation-style: "K&R" mode-name: "LC" c-basic-offset: 8 diff -L fs/reiser4/plugin/dir/hashed_dir.h -puN fs/reiser4/plugin/dir/hashed_dir.h~reiser4-big-update /dev/null --- devel/fs/reiser4/plugin/dir/hashed_dir.h +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,46 +0,0 @@ -/* Copyright 2001, 2002, 2003, 2004 by Hans Reiser, licensing governed by - * reiser4/README */ - -/* Directory plugin using hashes (see fs/reiser4/plugin/hash.c) to map - file names to to files. See hashed_dir.c */ - -#if !defined( __HASHED_DIR_H__ ) -#define __HASHED_DIR_H__ - -#include "../../forward.h" - -#include /* for struct inode */ -#include /* for struct dentry */ - -/* create sd for directory file. Create stat-data, dot, and dotdot. */ -extern int init_hashed(struct inode *object, struct inode *parent, reiser4_object_create_data *); -extern int done_hashed(struct inode *object); -extern int detach_hashed(struct inode *object, struct inode *parent); -extern int owns_item_hashed(const struct inode *inode, const coord_t * coord); -extern int lookup_hashed(struct inode *inode, struct dentry **dentry); -extern int rename_hashed(struct inode *old_dir, - struct dentry *old_name, struct inode *new_dir, struct dentry *new_name); -extern int add_entry_hashed(struct inode *object, - struct dentry *where, reiser4_object_create_data *, reiser4_dir_entry_desc * entry); -extern int rem_entry_hashed(struct inode *object, struct dentry *where, reiser4_dir_entry_desc * entry); -extern reiser4_block_nr estimate_rename_hashed(struct inode *old_dir, - struct dentry *old_name, - struct inode *new_dir, - struct dentry *new_name); -extern reiser4_block_nr estimate_unlink_hashed(struct inode *parent, - struct inode *object); - -extern struct dentry *get_parent_hashed(struct inode *child); - -/* __HASHED_DIR_H__ */ -#endif - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - End: -*/ diff -puN /dev/null fs/reiser4/plugin/dir_plugin_common.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/dir_plugin_common.c 2005-09-15 19:51:08.000000000 -0700 @@ -0,0 +1,868 @@ +/* Copyright 2005 by Hans Reiser, licensing governed by + reiser4/README */ + +/* this file contains typical implementations for most of methods of + directory plugin +*/ + +#include "../inode.h" + +int find_entry(struct inode *dir, struct dentry *name, + lock_handle *, znode_lock_mode, reiser4_dir_entry_desc *); +int lookup_name(struct inode *parent, struct dentry *dentry, reiser4_key * key); +void check_light_weight(struct inode *inode, struct inode *parent); + +/* this is common implementation of get_parent method of dir plugin + this is used by NFS kernel server to "climb" up directory tree to + check permissions + */ +struct dentry *get_parent_common(struct inode *child) +{ + struct super_block *s; + struct inode *parent; + struct dentry dotdot; + struct dentry *dentry; + reiser4_key key; + int result; + + /* + * lookup dotdot entry. + */ + + s = child->i_sb; + memset(&dotdot, 0, sizeof(dotdot)); + dotdot.d_name.name = ".."; + dotdot.d_name.len = 2; + dotdot.d_op = &get_super_private(s)->ops.dentry; + + result = lookup_name(child, &dotdot, &key); + if (result != 0) + return ERR_PTR(result); + + parent = reiser4_iget(s, &key, 1); + if (!IS_ERR(parent)) { + /* + * FIXME-NIKITA dubious: attributes are inherited from @child + * to @parent. But: + * + * (*) this is the only this we can do + * + * (*) attributes of light-weight object are inherited + * from a parent through which object was looked up first, + * so it is ambiguous anyway. + * + */ + check_light_weight(parent, child); + reiser4_iget_complete(parent); + dentry = d_alloc_anon(parent); + if (dentry == NULL) { + iput(parent); + dentry = ERR_PTR(RETERR(-ENOMEM)); + } else + dentry->d_op = &get_super_private(s)->ops.dentry; + } else if (PTR_ERR(parent) == -ENOENT) + dentry = ERR_PTR(RETERR(-ESTALE)); + else + dentry = (void *)parent; + return dentry; +} + +/* this is common implementation of is_name_acceptable method of dir + plugin + */ +int is_name_acceptable_common(const struct inode *inode, /* directory to check */ + const char *name UNUSED_ARG, /* name to check */ + int len /* @name's length */ ) +{ + assert("nikita-733", inode != NULL); + assert("nikita-734", name != NULL); + assert("nikita-735", len > 0); + + return len <= reiser4_max_filename_len(inode); +} + +/* there is no common implementation of build_entry_key method of dir + plugin. See plugin/dir/hashed_dir.c:build_entry_key_hashed() or + plugin/dir/seekable.c:build_entry_key_seekable() for example +*/ + +/* this is common implementation of build_readdir_key method of dir + plugin + see readdir_common for more details +*/ +int build_readdir_key_common(struct file *dir /* directory being read */ , + reiser4_key * result /* where to store key */ ) +{ + reiser4_file_fsdata *fdata; + struct inode *inode; + + assert("nikita-1361", dir != NULL); + assert("nikita-1362", result != NULL); + assert("nikita-1363", dir->f_dentry != NULL); + inode = dir->f_dentry->d_inode; + assert("nikita-1373", inode != NULL); + + fdata = reiser4_get_file_fsdata(dir); + if (IS_ERR(fdata)) + return PTR_ERR(fdata); + assert("nikita-1364", fdata != NULL); + return extract_key_from_de_id(get_inode_oid(inode), + &fdata->dir.readdir.position. + dir_entry_key, result); + +} + +void adjust_dir_file(struct inode *, const struct dentry *, int offset, + int adj); + +/* this is common implementation of add_entry method of dir plugin +*/ +int add_entry_common(struct inode *object, /* directory to add new name + * in */ + struct dentry *where, /* new name */ + reiser4_object_create_data * data UNUSED_ARG, /* parameters + * of new + * object */ + reiser4_dir_entry_desc * entry /* parameters of new + * directory entry */ ) +{ + int result; + coord_t *coord; + lock_handle lh; + reiser4_dentry_fsdata *fsdata; + reiser4_block_nr reserve; + + assert("nikita-1114", object != NULL); + assert("nikita-1250", where != NULL); + + fsdata = reiser4_get_dentry_fsdata(where); + if (unlikely(IS_ERR(fsdata))) + return PTR_ERR(fsdata); + + reserve = inode_dir_plugin(object)->estimate.add_entry(object); + if (reiser4_grab_space(reserve, BA_CAN_COMMIT)) + return RETERR(-ENOSPC); + + init_lh(&lh); + coord = &fsdata->dec.entry_coord; + coord_clear_iplug(coord); + + /* check for this entry in a directory. This is plugin method. */ + result = find_entry(object, where, &lh, ZNODE_WRITE_LOCK, entry); + if (likely(result == -ENOENT)) { + /* add new entry. Just pass control to the directory + item plugin. */ + assert("nikita-1709", inode_dir_item_plugin(object)); + assert("nikita-2230", coord->node == lh.node); + seal_done(&fsdata->dec.entry_seal); + result = + inode_dir_item_plugin(object)->s.dir.add_entry(object, + coord, &lh, + where, + entry); + if (result == 0) { + adjust_dir_file(object, where, fsdata->dec.pos + 1, +1); + INODE_INC_FIELD(object, i_size); + } + } else if (result == 0) { + assert("nikita-2232", coord->node == lh.node); + result = RETERR(-EEXIST); + } + done_lh(&lh); + + return result; +} + +/** + * rem_entry - remove entry from directory item + * @dir: + * @dentry: + * @entry: + * @coord: + * @lh: + * + * Checks that coordinate @coord is set properly and calls item plugin + * method to cut entry. + */ +static int +rem_entry(struct inode *dir, struct dentry *dentry, + reiser4_dir_entry_desc * entry, coord_t * coord, lock_handle * lh) +{ + item_plugin *iplug; + struct inode *child; + + iplug = inode_dir_item_plugin(dir); + child = dentry->d_inode; + assert("nikita-3399", child != NULL); + + /* check that we are really destroying an entry for @child */ + if (REISER4_DEBUG) { + int result; + reiser4_key key; + + result = iplug->s.dir.extract_key(coord, &key); + if (result != 0) + return result; + if (get_key_objectid(&key) != get_inode_oid(child)) { + warning("nikita-3397", + "rem_entry: %#llx != %#llx\n", + get_key_objectid(&key), + (unsigned long long)get_inode_oid(child)); + return RETERR(-EIO); + } + } + return iplug->s.dir.rem_entry(dir, &dentry->d_name, coord, lh, entry); +} + +/** + * rem_entry_common - remove entry from a directory + * @dir: directory to remove entry from + * @where: name that is being removed + * @entry: description of entry being removed + * + * This is common implementation of rem_entry method of dir plugin. + */ +int rem_entry_common(struct inode *dir, + struct dentry *dentry, + reiser4_dir_entry_desc *entry) +{ + int result; + coord_t *coord; + lock_handle lh; + reiser4_dentry_fsdata *fsdata; + __u64 tograb; + + assert("nikita-1124", dir != NULL); + assert("nikita-1125", dentry != NULL); + + tograb = inode_dir_plugin(dir)->estimate.rem_entry(dir); + result = reiser4_grab_space(tograb, BA_CAN_COMMIT | BA_RESERVED); + if (result != 0) + return RETERR(-ENOSPC); + + init_lh(&lh); + + /* check for this entry in a directory. This is plugin method. */ + result = find_entry(dir, dentry, &lh, ZNODE_WRITE_LOCK, entry); + fsdata = reiser4_get_dentry_fsdata(dentry); + if (IS_ERR(fsdata)) { + done_lh(&lh); + return PTR_ERR(fsdata); + } + + coord = &fsdata->dec.entry_coord; + + assert("nikita-3404", + get_inode_oid(dentry->d_inode) != get_inode_oid(dir) || + dir->i_size <= 1); + + coord_clear_iplug(coord); + if (result == 0) { + /* remove entry. Just pass control to the directory item + plugin. */ + assert("vs-542", inode_dir_item_plugin(dir)); + seal_done(&fsdata->dec.entry_seal); + adjust_dir_file(dir, dentry, fsdata->dec.pos, -1); + result = + WITH_COORD(coord, + rem_entry(dir, dentry, entry, coord, &lh)); + if (result == 0) { + if (dir->i_size >= 1) + INODE_DEC_FIELD(dir, i_size); + else { + warning("nikita-2509", "Dir %llu is runt", + (unsigned long long) + get_inode_oid(dir)); + result = RETERR(-EIO); + } + + assert("nikita-3405", dentry->d_inode->i_nlink != 1 || + dentry->d_inode->i_size != 2 || + inode_dir_plugin(dentry->d_inode) == NULL); + } + } + done_lh(&lh); + + return result; +} + +static reiser4_block_nr estimate_init(struct inode *parent, + struct inode *object); +static int create_dot_dotdot(struct inode *object, struct inode *parent); + +/* this is common implementation of init method of dir plugin + create "." and ".." entries +*/ +int init_common(struct inode *object, /* new directory */ + struct inode *parent, /* parent directory */ + reiser4_object_create_data * data UNUSED_ARG /* info passed + * to us, this + * is filled by + * reiser4() + * syscall in + * particular */ ) +{ + reiser4_block_nr reserve; + + assert("nikita-680", object != NULL); + assert("nikita-681", S_ISDIR(object->i_mode)); + assert("nikita-682", parent != NULL); + assert("nikita-684", data != NULL); + assert("nikita-686", data->id == DIRECTORY_FILE_PLUGIN_ID); + assert("nikita-687", object->i_mode & S_IFDIR); + + reserve = estimate_init(parent, object); + if (reiser4_grab_space(reserve, BA_CAN_COMMIT)) + return RETERR(-ENOSPC); + + return create_dot_dotdot(object, parent); +} + +/* this is common implementation of done method of dir plugin + remove "." entry +*/ +int done_common(struct inode *object /* object being deleted */ ) +{ + int result; + reiser4_block_nr reserve; + struct dentry goodby_dots; + reiser4_dir_entry_desc entry; + + assert("nikita-1449", object != NULL); + + if (inode_get_flag(object, REISER4_NO_SD)) + return 0; + + /* of course, this can be rewritten to sweep everything in one + cut_tree(). */ + memset(&entry, 0, sizeof entry); + + /* FIXME: this done method is called from delete_directory_common which + * reserved space already */ + reserve = inode_dir_plugin(object)->estimate.rem_entry(object); + if (reiser4_grab_space(reserve, BA_CAN_COMMIT | BA_RESERVED)) + return RETERR(-ENOSPC); + + memset(&goodby_dots, 0, sizeof goodby_dots); + entry.obj = goodby_dots.d_inode = object; + goodby_dots.d_name.name = "."; + goodby_dots.d_name.len = 1; + result = rem_entry_common(object, &goodby_dots, &entry); + reiser4_free_dentry_fsdata(&goodby_dots); + if (unlikely(result != 0 && result != -ENOMEM && result != -ENOENT)) + /* only worth a warning + + "values of B will give rise to dom!\n" + -- v6src/s2/mv.c:89 + */ + warning("nikita-2252", "Cannot remove dot of %lli: %i", + (unsigned long long)get_inode_oid(object), result); + return 0; +} + +/* this is common implementation of attach method of dir plugin +*/ +int +attach_common(struct inode *child UNUSED_ARG, struct inode *parent UNUSED_ARG) +{ + assert("nikita-2647", child != NULL); + assert("nikita-2648", parent != NULL); + + return 0; +} + +/* this is common implementation of detach method of dir plugin + remove "..", decrease nlink on parent +*/ +int detach_common(struct inode *object, struct inode *parent) +{ + int result; + struct dentry goodby_dots; + reiser4_dir_entry_desc entry; + + assert("nikita-2885", object != NULL); + assert("nikita-2886", !inode_get_flag(object, REISER4_NO_SD)); + + memset(&entry, 0, sizeof entry); + + /* NOTE-NIKITA this only works if @parent is -the- parent of + @object, viz. object whose key is stored in dotdot + entry. Wouldn't work with hard-links on directories. */ + memset(&goodby_dots, 0, sizeof goodby_dots); + entry.obj = goodby_dots.d_inode = parent; + goodby_dots.d_name.name = ".."; + goodby_dots.d_name.len = 2; + result = rem_entry_common(object, &goodby_dots, &entry); + reiser4_free_dentry_fsdata(&goodby_dots); + if (result == 0) { + /* the dot should be the only entry remaining at this time... */ + assert("nikita-3400", object->i_size == 1 && + (object->i_nlink >= 0 && object->i_nlink <= 2)); +#if 0 + /* and, together with the only name directory can have, they + * provides for the last 2 remaining references. If we get + * here as part of error handling during mkdir, @object + * possibly has no name yet, so its nlink == 1. If we get here + * from rename (targeting empty directory), it has no name + * already, so its nlink == 1. */ + assert("nikita-3401", + object->i_nlink == 2 || object->i_nlink == 1); +#endif + + /* decrement nlink of directory removed ".." pointed + to */ + reiser4_del_nlink(parent, NULL, 0); + } + return result; +} + +/* this is common implementation of estimate.add_entry method of + dir plugin + estimation of adding entry which supposes that entry is inserting a + unit into item +*/ +reiser4_block_nr estimate_add_entry_common(const struct inode * inode) +{ + return estimate_one_insert_into_item(tree_by_inode(inode)); +} + +/* this is common implementation of estimate.rem_entry method of dir + plugin +*/ +reiser4_block_nr estimate_rem_entry_common(const struct inode * inode) +{ + return estimate_one_item_removal(tree_by_inode(inode)); +} + +/* this is common implementation of estimate.unlink method of dir + plugin +*/ +reiser4_block_nr +dir_estimate_unlink_common(const struct inode * parent, + const struct inode * object) +{ + reiser4_block_nr res; + + /* hashed_rem_entry(object) */ + res = inode_dir_plugin(object)->estimate.rem_entry(object); + /* del_nlink(parent) */ + res += 2 * inode_file_plugin(parent)->estimate.update(parent); + + return res; +} + +/* + * helper for inode_ops ->lookup() and dir plugin's ->get_parent() + * methods: if @inode is a light-weight file, setup its credentials + * that are not stored in the stat-data in this case + */ +void check_light_weight(struct inode *inode, struct inode *parent) +{ + if (inode_get_flag(inode, REISER4_LIGHT_WEIGHT)) { + inode->i_uid = parent->i_uid; + inode->i_gid = parent->i_gid; + /* clear light-weight flag. If inode would be read by any + other name, [ug]id wouldn't change. */ + inode_clr_flag(inode, REISER4_LIGHT_WEIGHT); + } +} + +/* looks for name specified in @dentry in directory @parent and if name is + found - key of object found entry points to is stored in @entry->key */ +int lookup_name(struct inode *parent, /* inode of directory to lookup for + * name in */ + struct dentry *dentry, /* name to look for */ + reiser4_key * key /* place to store key */ ) +{ + int result; + coord_t *coord; + lock_handle lh; + const char *name; + int len; + reiser4_dir_entry_desc entry; + reiser4_dentry_fsdata *fsdata; + + assert("nikita-1247", parent != NULL); + assert("nikita-1248", dentry != NULL); + assert("nikita-1123", dentry->d_name.name != NULL); + assert("vs-1486", + dentry->d_op == &get_super_private(parent->i_sb)->ops.dentry); + + result = perm_chk(parent, lookup, parent, dentry); + if (result != 0) + return 0; + + name = dentry->d_name.name; + len = dentry->d_name.len; + + if (!inode_dir_plugin(parent)->is_name_acceptable(parent, name, len)) + /* some arbitrary error code to return */ + return RETERR(-ENAMETOOLONG); + + fsdata = reiser4_get_dentry_fsdata(dentry); + if (IS_ERR(fsdata)) + return PTR_ERR(fsdata); + + coord = &fsdata->dec.entry_coord; + coord_clear_iplug(coord); + init_lh(&lh); + + /* find entry in a directory. This is plugin method. */ + result = find_entry(parent, dentry, &lh, ZNODE_READ_LOCK, &entry); + if (result == 0) { + /* entry was found, extract object key from it. */ + result = + WITH_COORD(coord, + item_plugin_by_coord(coord)->s.dir. + extract_key(coord, key)); + } + done_lh(&lh); + return result; + +} + +/* helper for init_common(): estimate number of blocks to reserve */ +static reiser4_block_nr +estimate_init(struct inode *parent, struct inode *object) +{ + reiser4_block_nr res = 0; + + assert("vpf-321", parent != NULL); + assert("vpf-322", object != NULL); + + /* hashed_add_entry(object) */ + res += inode_dir_plugin(object)->estimate.add_entry(object); + /* reiser4_add_nlink(object) */ + res += inode_file_plugin(object)->estimate.update(object); + /* hashed_add_entry(object) */ + res += inode_dir_plugin(object)->estimate.add_entry(object); + /* reiser4_add_nlink(parent) */ + res += inode_file_plugin(parent)->estimate.update(parent); + + return 0; +} + +/* helper function for init_common(). Create "." and ".." */ +static int create_dot_dotdot(struct inode *object /* object to create dot and + * dotdot for */ , + struct inode *parent /* parent of @object */ ) +{ + int result; + struct dentry dots_entry; + reiser4_dir_entry_desc entry; + + assert("nikita-688", object != NULL); + assert("nikita-689", S_ISDIR(object->i_mode)); + assert("nikita-691", parent != NULL); + + /* We store dot and dotdot as normal directory entries. This is + not necessary, because almost all information stored in them + is already in the stat-data of directory, the only thing + being missed is objectid of grand-parent directory that can + easily be added there as extension. + + But it is done the way it is done, because not storing dot + and dotdot will lead to the following complications: + + . special case handling in ->lookup(). + . addition of another extension to the sd. + . dependency on key allocation policy for stat data. + + */ + + memset(&entry, 0, sizeof entry); + memset(&dots_entry, 0, sizeof dots_entry); + entry.obj = dots_entry.d_inode = object; + dots_entry.d_name.name = "."; + dots_entry.d_name.len = 1; + result = add_entry_common(object, &dots_entry, NULL, &entry); + reiser4_free_dentry_fsdata(&dots_entry); + + if (result == 0) { + result = reiser4_add_nlink(object, object, 0); + if (result == 0) { + entry.obj = dots_entry.d_inode = parent; + dots_entry.d_name.name = ".."; + dots_entry.d_name.len = 2; + result = add_entry_common(object, + &dots_entry, NULL, &entry); + reiser4_free_dentry_fsdata(&dots_entry); + /* if creation of ".." failed, iput() will delete + object with ".". */ + if (result == 0) { + result = reiser4_add_nlink(parent, object, 0); + if (result != 0) + /* + * if we failed to bump i_nlink, try + * to remove ".." + */ + detach_common(object, parent); + } + } + } + + if (result != 0) { + /* + * in the case of error, at least update stat-data so that, + * ->i_nlink updates are not lingering. + */ + reiser4_update_sd(object); + reiser4_update_sd(parent); + } + + return result; +} + +/* + * return 0 iff @coord contains a directory entry for the file with the name + * @name. + */ +static int +check_item(const struct inode *dir, const coord_t * coord, const char *name) +{ + item_plugin *iplug; + char buf[DE_NAME_BUF_LEN]; + + iplug = item_plugin_by_coord(coord); + if (iplug == NULL) { + warning("nikita-1135", "Cannot get item plugin"); + print_coord("coord", coord, 1); + return RETERR(-EIO); + } else if (item_id_by_coord(coord) != + item_id_by_plugin(inode_dir_item_plugin(dir))) { + /* item id of current item does not match to id of items a + directory is built of */ + warning("nikita-1136", "Wrong item plugin"); + print_coord("coord", coord, 1); + return RETERR(-EIO); + } + assert("nikita-1137", iplug->s.dir.extract_name); + + /* Compare name stored in this entry with name we are looking for. + + NOTE-NIKITA Here should go code for support of something like + unicode, code tables, etc. + */ + return !!strcmp(name, iplug->s.dir.extract_name(coord, buf)); +} + +static int +check_entry(const struct inode *dir, coord_t * coord, const struct qstr *name) +{ + return WITH_COORD(coord, check_item(dir, coord, name->name)); +} + +/* + * argument package used by entry_actor to scan entries with identical keys. + */ +typedef struct entry_actor_args { + /* name we are looking for */ + const char *name; + /* key of directory entry. entry_actor() scans through sequence of + * items/units having the same key */ + reiser4_key *key; + /* how many entries with duplicate key was scanned so far. */ + int non_uniq; +#if REISER4_USE_COLLISION_LIMIT + /* scan limit */ + int max_non_uniq; +#endif + /* return parameter: set to true, if ->name wasn't found */ + int not_found; + /* what type of lock to take when moving to the next node during + * scan */ + znode_lock_mode mode; + + /* last coord that was visited during scan */ + coord_t last_coord; + /* last node locked during scan */ + lock_handle last_lh; + /* inode of directory */ + const struct inode *inode; +} entry_actor_args; + +/* Function called by find_entry() to look for given name in the directory. */ +static int entry_actor(reiser4_tree * tree UNUSED_ARG /* tree being scanned */ , + coord_t * coord /* current coord */ , + lock_handle * lh /* current lock handle */ , + void *entry_actor_arg /* argument to scan */ ) +{ + reiser4_key unit_key; + entry_actor_args *args; + + assert("nikita-1131", tree != NULL); + assert("nikita-1132", coord != NULL); + assert("nikita-1133", entry_actor_arg != NULL); + + args = entry_actor_arg; + ++args->non_uniq; +#if REISER4_USE_COLLISION_LIMIT + if (args->non_uniq > args->max_non_uniq) { + args->not_found = 1; + /* hash collision overflow. */ + return RETERR(-EBUSY); + } +#endif + + /* + * did we just reach the end of the sequence of items/units with + * identical keys? + */ + if (!keyeq(args->key, unit_key_by_coord(coord, &unit_key))) { + assert("nikita-1791", + keylt(args->key, unit_key_by_coord(coord, &unit_key))); + args->not_found = 1; + args->last_coord.between = AFTER_UNIT; + return 0; + } + + coord_dup(&args->last_coord, coord); + /* + * did scan just moved to the next node? + */ + if (args->last_lh.node != lh->node) { + int lock_result; + + /* + * if so, lock new node with the mode requested by the caller + */ + done_lh(&args->last_lh); + assert("nikita-1896", znode_is_any_locked(lh->node)); + lock_result = longterm_lock_znode(&args->last_lh, lh->node, + args->mode, ZNODE_LOCK_HIPRI); + if (lock_result != 0) + return lock_result; + } + return check_item(args->inode, coord, args->name); +} + +/* Look for given @name within directory @dir. + + This is called during lookup, creation and removal of directory + entries and on rename_common + + First calculate key that directory entry for @name would have. Search + for this key in the tree. If such key is found, scan all items with + the same key, checking name in each directory entry along the way. +*/ +int find_entry(struct inode *dir, /* directory to scan */ + struct dentry *de, /* name to search for */ + lock_handle * lh, /* resulting lock handle */ + znode_lock_mode mode, /* required lock mode */ + reiser4_dir_entry_desc * entry /* parameters of found directory + * entry */ ) +{ + const struct qstr *name; + seal_t *seal; + coord_t *coord; + int result; + __u32 flags; + de_location *dec; + reiser4_dentry_fsdata *fsdata; + + assert("nikita-1130", lh != NULL); + assert("nikita-1128", dir != NULL); + + name = &de->d_name; + assert("nikita-1129", name != NULL); + + /* dentry private data don't require lock, because dentry + manipulations are protected by i_sem on parent. + + This is not so for inodes, because there is no -the- parent in + inode case. + */ + fsdata = reiser4_get_dentry_fsdata(de); + if (IS_ERR(fsdata)) + return PTR_ERR(fsdata); + dec = &fsdata->dec; + + coord = &dec->entry_coord; + coord_clear_iplug(coord); + seal = &dec->entry_seal; + /* compose key of directory entry for @name */ + inode_dir_plugin(dir)->build_entry_key(dir, name, &entry->key); + + if (seal_is_set(seal)) { + /* check seal */ + result = seal_validate(seal, coord, &entry->key, + lh, mode, ZNODE_LOCK_LOPRI); + if (result == 0) { + /* key was found. Check that it is really item we are + looking for. */ + result = check_entry(dir, coord, name); + if (result == 0) + return 0; + } + } + flags = (mode == ZNODE_WRITE_LOCK) ? CBK_FOR_INSERT : 0; + /* + * find place in the tree where directory item should be located. + */ + result = object_lookup(dir, &entry->key, coord, lh, mode, + FIND_EXACT, LEAF_LEVEL, LEAF_LEVEL, flags, + NULL /*ra_info */ ); + if (result == CBK_COORD_FOUND) { + entry_actor_args arg; + + /* fast path: no hash collisions */ + result = check_entry(dir, coord, name); + if (result == 0) { + seal_init(seal, coord, &entry->key); + dec->pos = 0; + } else if (result > 0) { + /* Iterate through all units with the same keys. */ + arg.name = name->name; + arg.key = &entry->key; + arg.not_found = 0; + arg.non_uniq = 0; +#if REISER4_USE_COLLISION_LIMIT + arg.max_non_uniq = max_hash_collisions(dir); + assert("nikita-2851", arg.max_non_uniq > 1); +#endif + arg.mode = mode; + arg.inode = dir; + coord_init_zero(&arg.last_coord); + init_lh(&arg.last_lh); + + result = iterate_tree(tree_by_inode(dir), coord, lh, + entry_actor, &arg, mode, 1); + /* if end of the tree or extent was reached during + scanning. */ + if (arg.not_found || (result == -E_NO_NEIGHBOR)) { + /* step back */ + done_lh(lh); + + result = zload(arg.last_coord.node); + if (result == 0) { + coord_clear_iplug(&arg.last_coord); + coord_dup(coord, &arg.last_coord); + move_lh(lh, &arg.last_lh); + result = RETERR(-ENOENT); + zrelse(arg.last_coord.node); + --arg.non_uniq; + } + } + + done_lh(&arg.last_lh); + if (result == 0) + seal_init(seal, coord, &entry->key); + + if (result == 0 || result == -ENOENT) { + assert("nikita-2580", arg.non_uniq > 0); + dec->pos = arg.non_uniq - 1; + } + } + } else + dec->pos = -1; + return result; +} + +/* Local variables: + c-indentation-style: "K&R" + mode-name: "LC" + c-basic-offset: 8 + tab-width: 8 + fill-column: 120 + End: +*/ diff -L fs/reiser4/plugin/dir/pseudo_dir.c -puN fs/reiser4/plugin/dir/pseudo_dir.c~reiser4-big-update /dev/null --- devel/fs/reiser4/plugin/dir/pseudo_dir.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,97 +0,0 @@ -/* Copyright 2003 by Hans Reiser, licensing governed by reiser4/README */ - -/* Directory plugin for pseudo files that operate like a directory. */ - -#include "../../debug.h" -#include "../../inode.h" -#include "../pseudo/pseudo.h" -#include "dir.h" - -#include /* for struct inode */ -#include /* for struct dentry */ - -/* implementation of ->lookup() method for pseudo files. */ -reiser4_internal int lookup_pseudo(struct inode * parent, struct dentry **dentry) -{ - pseudo_plugin *pplug; - int result; - - /* - * call ->lookup method of pseudo plugin - */ - - pplug = reiser4_inode_data(parent)->file_plugin_data.pseudo_info.plugin; - assert("nikita-3222", pplug->lookup != NULL); - result = pplug->lookup(parent, dentry); - if (result == -ENOENT) - result = lookup_pseudo_file(parent, dentry); - return result; -} - - -/* ->readdir() method for pseudo file acting like a directory */ -reiser4_internal int -readdir_pseudo(struct file *f, void *dirent, filldir_t filld) -{ - pseudo_plugin *pplug; - struct inode *inode; - struct dentry *dentry; - int result = 0; - - dentry = f->f_dentry; - inode = dentry->d_inode; - pplug = reiser4_inode_data(inode)->file_plugin_data.pseudo_info.plugin; - if (pplug->readdir != NULL) - /* - * if pseudo plugin defines ->readdir() method---call it to do - * actual work. - */ - result = pplug->readdir(f, dirent, filld); - else { - ino_t ino; - int i; - - /* - * if there is no ->readdir() method in the pseudo plugin, - * make sure that at least dot and dotdot are returned to keep - * user-level happy. - */ - - i = f->f_pos; - switch (i) { - case 0: - ino = get_inode_oid(dentry->d_inode); - if (filld(dirent, ".", 1, i, ino, DT_DIR) < 0) - break; - f->f_pos++; - i++; - /* fallthrough */ - case 1: - ino = parent_ino(dentry); - if (filld(dirent, "..", 2, i, ino, DT_DIR) < 0) - break; - f->f_pos++; - i++; - /* fallthrough */ - } - } - return result; -} - -/* pseudo files are not serializable (currently). So, this should just return an - * error. */ -reiser4_internal struct dentry * -get_parent_pseudo(struct inode *child) -{ - return ERR_PTR(RETERR(-ENOTSUPP)); -} - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - End: -*/ diff -L fs/reiser4/plugin/dir/pseudo_dir.h -puN fs/reiser4/plugin/dir/pseudo_dir.h~reiser4-big-update /dev/null --- devel/fs/reiser4/plugin/dir/pseudo_dir.h +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,29 +0,0 @@ -/* Copyright 2003, 2004 by Hans Reiser, licensing governed by - * reiser4/README */ - -/* Directory plugin for pseudo files. See pseudo_dir.c for details. */ - -#if !defined( __PSEUDO_DIR_H__ ) -#define __PSEUDO_DIR_H__ - -#include "../../forward.h" - -#include /* for struct inode */ -#include /* for struct dentry */ - -extern int lookup_pseudo(struct inode * parent, struct dentry **dentry); -extern int readdir_pseudo(struct file *f, void *dirent, filldir_t filld); -extern struct dentry *get_parent_pseudo(struct inode *child); - -/* __PSEUDO_DIR_H__ */ -#endif - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - End: -*/ diff -puN /dev/null fs/reiser4/plugin/dir/seekable_dir.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/dir/seekable_dir.c 2005-09-15 19:51:08.000000000 -0700 @@ -0,0 +1,46 @@ +/* Copyright 2005 by Hans Reiser, licensing governed by + * reiser4/README */ + +#include "../../inode.h" + +/* this is implementation of build_entry_key method of dir + plugin for SEEKABLE_HASHED_DIR_PLUGIN_ID + This is for directories where we want repeatable and restartable readdir() + even in case 32bit user level struct dirent (readdir(3)). +*/ +void +build_entry_key_seekable(const struct inode *dir, const struct qstr *name, + reiser4_key * result) +{ + oid_t objectid; + + assert("nikita-2283", dir != NULL); + assert("nikita-2284", name != NULL); + assert("nikita-2285", name->name != NULL); + assert("nikita-2286", result != NULL); + + reiser4_key_init(result); + /* locality of directory entry's key is objectid of parent + directory */ + set_key_locality(result, get_inode_oid(dir)); + /* minor packing locality is constant */ + set_key_type(result, KEY_FILE_NAME_MINOR); + /* dot is special case---we always want it to be first entry in + a directory. Actually, we just want to have smallest + directory entry. + */ + if ((name->len == 1) && (name->name[0] == '.')) + return; + + /* objectid of key is 31 lowest bits of hash. */ + objectid = + inode_hash_plugin(dir)->hash(name->name, + (int)name->len) & 0x7fffffff; + + assert("nikita-2303", !(objectid & ~KEY_OBJECTID_MASK)); + set_key_objectid(result, objectid); + + /* offset is always 0. */ + set_key_offset(result, (__u64) 0); + return; +} diff -puN fs/reiser4/plugin/disk_format/disk_format40.c~reiser4-big-update fs/reiser4/plugin/disk_format/disk_format40.c --- devel/fs/reiser4/plugin/disk_format/disk_format40.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/disk_format/disk_format40.c 2005-09-15 19:51:08.000000000 -0700 @@ -28,65 +28,55 @@ #define RELEASE_RESERVED 4 /* functions to access fields of format40_disk_super_block */ -static __u64 -get_format40_block_count(const format40_disk_super_block * sb) +static __u64 get_format40_block_count(const format40_disk_super_block * sb) { return d64tocpu(&sb->block_count); } -static __u64 -get_format40_free_blocks(const format40_disk_super_block * sb) +static __u64 get_format40_free_blocks(const format40_disk_super_block * sb) { return d64tocpu(&sb->free_blocks); } -static __u64 -get_format40_root_block(const format40_disk_super_block * sb) +static __u64 get_format40_root_block(const format40_disk_super_block * sb) { return d64tocpu(&sb->root_block); } -static __u16 -get_format40_tree_height(const format40_disk_super_block * sb) +static __u16 get_format40_tree_height(const format40_disk_super_block * sb) { return d16tocpu(&sb->tree_height); } -static __u64 -get_format40_file_count(const format40_disk_super_block * sb) +static __u64 get_format40_file_count(const format40_disk_super_block * sb) { return d64tocpu(&sb->file_count); } -static __u64 -get_format40_oid(const format40_disk_super_block * sb) +static __u64 get_format40_oid(const format40_disk_super_block * sb) { return d64tocpu(&sb->oid); } -static __u32 -get_format40_mkfs_id(const format40_disk_super_block * sb) +static __u32 get_format40_mkfs_id(const format40_disk_super_block * sb) { return d32tocpu(&sb->mkfs_id); } -static __u64 -get_format40_flags(const format40_disk_super_block * sb) +static __u64 get_format40_flags(const format40_disk_super_block * sb) { return d64tocpu(&sb->flags); } -static format40_super_info * -get_sb_info(struct super_block *super) +static format40_super_info *get_sb_info(struct super_block *super) { return &get_super_private(super)->u.format40; } -static int -consult_diskmap(struct super_block *s) +static int consult_diskmap(struct super_block *s) { format40_super_info *info; - journal_location *jloc; + journal_location *jloc; info = get_sb_info(s); jloc = &get_super_private(s)->jloc; @@ -96,11 +86,11 @@ consult_diskmap(struct super_block *s) jloc->header = FORMAT40_JOURNAL_HEADER_BLOCKNR; info->loc.super = FORMAT40_OFFSET / s->s_blocksize; #ifdef CONFIG_REISER4_BADBLOCKS - reiser4_get_diskmap_value(FORMAT40_PLUGIN_DISKMAP_ID, FORMAT40_JF, + reiser4_get_diskmap_value(FORMAT40_PLUGIN_DISKMAP_ID, FORMAT40_JF, &jloc->footer); - reiser4_get_diskmap_value(FORMAT40_PLUGIN_DISKMAP_ID, FORMAT40_JH, + reiser4_get_diskmap_value(FORMAT40_PLUGIN_DISKMAP_ID, FORMAT40_JH, &jloc->header); - reiser4_get_diskmap_value(FORMAT40_PLUGIN_DISKMAP_ID, FORMAT40_SUPER, + reiser4_get_diskmap_value(FORMAT40_PLUGIN_DISKMAP_ID, FORMAT40_SUPER, &info->loc.super); #endif return 0; @@ -109,8 +99,8 @@ consult_diskmap(struct super_block *s) /* find any valid super block of disk_format40 (even if the first super block is destroyed), will change block numbers of actual journal header/footer (jf/jh) if needed */ -static struct buffer_head * -find_a_disk_format40_super_block(struct super_block *s) +static struct buffer_head *find_a_disk_format40_super_block(struct super_block + *s) { struct buffer_head *super_bh; format40_disk_super_block *disk_sb; @@ -140,8 +130,7 @@ find_a_disk_format40_super_block(struct /* find the most recent version of super block. This is called after journal is replayed */ -static struct buffer_head * -read_super_block(struct super_block *s UNUSED_ARG) +static struct buffer_head *read_super_block(struct super_block *s UNUSED_ARG) { /* Here the most recent superblock copy has to be read. However, as journal replay isn't complete, we are using @@ -149,8 +138,7 @@ read_super_block(struct super_block *s U return find_a_disk_format40_super_block(s); } -static int -get_super_jnode(struct super_block *s) +static int get_super_jnode(struct super_block *s) { reiser4_super_info_data *sbinfo = get_super_private(s); jnode *sb_jnode; @@ -173,8 +161,7 @@ get_super_jnode(struct super_block *s) return 0; } -static void -done_super_jnode(struct super_block *s) +static void done_super_jnode(struct super_block *s) { jnode *sb_jnode = get_super_private(s)->u.format40.sb_jnode; @@ -202,47 +189,71 @@ typedef enum format40_init_stage { ALL_DONE } format40_init_stage; -static int -try_init_format40(struct super_block *s, format40_init_stage *stage) +static format40_disk_super_block *copy_sb(const struct buffer_head *super_bh) +{ + format40_disk_super_block *sb_copy; + + sb_copy = kmalloc(sizeof(format40_disk_super_block), GFP_KERNEL); + if (sb_copy == NULL) + return ERR_PTR(RETERR(-ENOMEM)); + memcpy(sb_copy, ((format40_disk_super_block *) super_bh->b_data), + sizeof(format40_disk_super_block)); + return sb_copy; +} + +static int check_key_format(const format40_disk_super_block *sb_copy) +{ + if (!equi(REISER4_LARGE_KEY, + get_format40_flags(sb_copy) & (1 << FORMAT40_LARGE_KEYS))) { + warning("nikita-3228", "Key format mismatch. " + "Only %s keys are supported.", + REISER4_LARGE_KEY ? "large" : "small"); + return RETERR(-EINVAL); + } + return 0; +} + +/** + * try_init_format40 + * @super: + * @stage: + * + */ +static int try_init_format40(struct super_block *super, + format40_init_stage *stage) { int result; struct buffer_head *super_bh; reiser4_super_info_data *sbinfo; - format40_disk_super_block sb; - /* FIXME-NIKITA ugly work-around: keep copy of on-disk super-block */ - format40_disk_super_block *sb_copy = &sb; + format40_disk_super_block *sb_copy; tree_level height; reiser4_block_nr root_block; node_plugin *nplug; - cassert(sizeof sb == 512); - - assert("vs-475", s != NULL); - assert("vs-474", get_super_private(s)); - - /* initialize reiser4_super_info_data */ - sbinfo = get_super_private(s); + assert("vs-475", super != NULL); + assert("vs-474", get_super_private(super)); *stage = NONE_DONE; - result = consult_diskmap(s); + result = consult_diskmap(super); if (result) return result; *stage = CONSULT_DISKMAP; - super_bh = find_a_disk_format40_super_block(s); + super_bh = find_a_disk_format40_super_block(super); if (IS_ERR(super_bh)) return PTR_ERR(super_bh); brelse(super_bh); *stage = FIND_A_SUPER; /* map jnodes for journal control blocks (header, footer) to disk */ - result = init_journal_info(s); + result = init_journal_info(super); if (result) return result; *stage = INIT_JOURNAL_INFO; - result = eflush_init_at(s); + /* FIXME: this has to be in fill_super */ + result = eflush_init_at(super); if (result) return result; *stage = INIT_EFLUSH; @@ -260,36 +271,42 @@ try_init_format40(struct super_block *s, if (result == REISER4_STATUS_MOUNT_WARN) printk("Warning, mounting filesystem with errors\n"); if (result == REISER4_STATUS_MOUNT_RO) { - printk("Warning, mounting filesystem with fatal errors, forcing read-only mount\n"); + printk + ("Warning, mounting filesystem with fatal errors, forcing read-only mount\n"); /* FIXME: here we should actually enforce read-only mount, * only it is unsupported yet. */ } - result = reiser4_journal_replay(s); + result = reiser4_journal_replay(super); if (result) return result; *stage = JOURNAL_REPLAY; - super_bh = read_super_block(s); + super_bh = read_super_block(super); if (IS_ERR(super_bh)) return PTR_ERR(super_bh); *stage = READ_SUPER; - memcpy(sb_copy, ((format40_disk_super_block *) super_bh->b_data), sizeof (*sb_copy)); + /* allocate and make a copy of format40_disk_super_block */ + sb_copy = copy_sb(super_bh); brelse(super_bh); + if (IS_ERR(sb_copy)) + return PTR_ERR(sb_copy); - if (!equi(REISER4_LARGE_KEY, - get_format40_flags(sb_copy) & (1 << FORMAT40_LARGE_KEYS))) { - warning("nikita-3228", "Key format mismatch. " - "Only %s keys are supported.", - REISER4_LARGE_KEY ? "large" : "small"); - return RETERR(-EINVAL); + /* make sure that key format of kernel and filesyste match */ + result = check_key_format(sb_copy); + if (result) { + kfree(sb_copy); + return result; } *stage = KEY_CHECK; - result = oid_init_allocator(s, get_format40_file_count(sb_copy), get_format40_oid(sb_copy)); - if (result) + result = oid_init_allocator(super, get_format40_file_count(sb_copy), + get_format40_oid(sb_copy)); + if (result) { + kfree(sb_copy); return result; + } *stage = INIT_OID; /* get things necessary to init reiser4_tree */ @@ -297,24 +314,33 @@ try_init_format40(struct super_block *s, height = get_format40_tree_height(sb_copy); nplug = node_plugin_by_id(NODE40_ID); - sbinfo->tree.super = s; + + /* initialize reiser4_super_info_data */ + sbinfo = get_super_private(super); + assert("", sbinfo->tree.super == super); /* init reiser4_tree for the filesystem */ result = init_tree(&sbinfo->tree, &root_block, height, nplug); - if (result) + if (result) { + kfree(sb_copy); return result; + } *stage = INIT_TREE; - /* initialize reiser4_super_info_data */ + /* + * initialize reiser4_super_info_data with data from format40 super + * block + */ sbinfo->default_uid = 0; sbinfo->default_gid = 0; - - reiser4_set_mkfs_id(s, get_format40_mkfs_id(sb_copy)); - reiser4_set_block_count(s, get_format40_block_count(sb_copy)); - reiser4_set_free_blocks(s, get_format40_free_blocks(sb_copy)); + sbinfo->mkfs_id = get_format40_mkfs_id(sb_copy); + /* number of blocks in filesystem and reserved space */ + reiser4_set_block_count(super, get_format40_block_count(sb_copy)); + sbinfo->blocks_free = get_format40_free_blocks(sb_copy); + kfree(sb_copy); sbinfo->fsuid = 0; sbinfo->fs_flags |= (1 << REISER4_ADG); /* hard links for directories - * are not supported */ + * are not supported */ sbinfo->fs_flags |= (1 << REISER4_ONE_NODE_PLUGIN); /* all nodes in * layout 40 are * of one @@ -326,41 +352,42 @@ try_init_format40(struct super_block *s, /* NOTE-NIKITA: reiser4_journal_recover_sb_data() calls * oid_init_allocator() and reiser4_set_free_blocks() with new * data. What's the reason to call them above? */ - result = reiser4_journal_recover_sb_data(s); + result = reiser4_journal_recover_sb_data(super); if (result != 0) return result; *stage = JOURNAL_RECOVER; - /* Set number of used blocks. The number of used blocks is not stored - neither in on-disk super block nor in the journal footer blocks. At - this moment actual values of total blocks and free block counters are - set in the reiser4 super block (in-memory structure) and we can - calculate number of used blocks from them. */ - reiser4_set_data_blocks(s, - reiser4_block_count(s) - reiser4_free_blocks(s)); + /* + * Set number of used blocks. The number of used blocks is not stored + * neither in on-disk super block nor in the journal footer blocks. At + * this moment actual values of total blocks and free block counters + * are set in the reiser4 super block (in-memory structure) and we can + * calculate number of used blocks from them. + */ + reiser4_set_data_blocks(super, + reiser4_block_count(super) - + reiser4_free_blocks(super)); #if REISER4_DEBUG - sbinfo->min_blocks_used = - 16 /* reserved area */ + - 2 /* super blocks */ + - 2 /* journal footer and header */; + sbinfo->min_blocks_used = 16 /* reserved area */ + + 2 /* super blocks */ + + 2 /* journal footer and header */ ; #endif /* init disk space allocator */ - result = sa_init_allocator(get_space_allocator(s), s, 0); + result = sa_init_allocator(get_space_allocator(super), super, NULL); if (result) return result; *stage = INIT_SA; - result = get_super_jnode(s); + result = get_super_jnode(super); if (result == 0) *stage = ALL_DONE; return result; } /* plugin->u.format.get_ready */ -reiser4_internal int -get_ready_format40(struct super_block *s, void *data UNUSED_ARG) +int init_format_format40(struct super_block *s, void *data UNUSED_ARG) { int result; format40_init_stage stage; @@ -401,10 +428,10 @@ get_ready_format40(struct super_block *s return result; } -static void -pack_format40_super(const struct super_block *s, char *data) +static void pack_format40_super(const struct super_block *s, char *data) { - format40_disk_super_block *super_data = (format40_disk_super_block *) data; + format40_disk_super_block *super_data = + (format40_disk_super_block *) data; reiser4_super_info_data *sbinfo = get_super_private(s); assert("zam-591", data != NULL); @@ -421,8 +448,7 @@ pack_format40_super(const struct super_b /* plugin->u.format.log_super return a jnode which should be added to transaction when the super block gets logged */ -reiser4_internal jnode * -log_super_format40(struct super_block *s) +jnode *log_super_format40(struct super_block *s) { jnode *sb_jnode; @@ -438,8 +464,7 @@ log_super_format40(struct super_block *s } /* plugin->u.format.release */ -reiser4_internal int -release_format40(struct super_block *s) +int release_format40(struct super_block *s) { int ret; reiser4_super_info_data *sbinfo; @@ -450,7 +475,8 @@ release_format40(struct super_block *s) if (!rofs_super(s)) { ret = capture_super_block(s); if (ret != 0) - warning("vs-898", "capture_super_block failed: %d", ret); + warning("vs-898", "capture_super_block failed: %d", + ret); ret = txnmgr_force_commit_all(s, 1); if (ret != 0) @@ -464,6 +490,12 @@ release_format40(struct super_block *s) eflush_done_at(s); done_super_jnode(s); + rcu_barrier(); + done_tree(&sbinfo->tree); + /* call finish_rcu(), because some znode were "released" in + * done_tree(). */ + rcu_barrier(); + return 0; } @@ -471,8 +503,8 @@ release_format40(struct super_block *s) #define FORMAT40_ROOT_OBJECTID 42 /* plugin->u.format.root_dir_key */ -reiser4_internal const reiser4_key * -root_dir_key_format40(const struct super_block *super UNUSED_ARG) +const reiser4_key *root_dir_key_format40(const struct super_block *super + UNUSED_ARG) { static const reiser4_key FORMAT40_ROOT_DIR_KEY = { .el = {{(FORMAT40_ROOT_LOCALITY << 4) | KEY_SD_MINOR}, @@ -485,36 +517,12 @@ root_dir_key_format40(const struct super return &FORMAT40_ROOT_DIR_KEY; } -/* plugin->u.format.print_info */ -reiser4_internal void -print_info_format40(const struct super_block *s) -{ -#if 0 - format40_disk_super_block *sb_copy; - - sb_copy = &get_super_private(s)->u.format40.actual_sb; - - printk("\tblock count %llu\n" - "\tfree blocks %llu\n" - "\troot_block %llu\n" - "\ttail policy %s\n" - "\tmin free oid %llu\n" - "\tfile count %llu\n" - "\ttree height %d\n", - get_format40_block_count(sb_copy), - get_format40_free_blocks(sb_copy), - get_format40_root_block(sb_copy), - formatting_plugin_by_id(get_format40_formatting_policy(sb_copy))->h.label, - get_format40_oid(sb_copy), get_format40_file_count(sb_copy), get_format40_tree_height(sb_copy)); -#endif -} - /* plugin->u.format.check_open. Check the opened object for validness. For now it checks for the valid oid & locality only, can be improved later and it its work may depend on the mount options. */ -reiser4_internal int -check_open_format40(const struct inode *object) { +int check_open_format40(const struct inode *object) +{ oid_t max, oid; max = oid_next(object->i_sb) - 1; @@ -524,8 +532,7 @@ check_open_format40(const struct inode * if (oid > max) { warning("vpf-1360", "The object with the oid %llu " "greater then the max used oid %llu found.", - (unsigned long long)oid, - (unsigned long long)max); + (unsigned long long)oid, (unsigned long long)max); return RETERR(-EIO); } @@ -535,8 +542,7 @@ check_open_format40(const struct inode * if (oid > max) { warning("vpf-1360", "The object with the locality %llu " "greater then the max used oid %llu found.", - (unsigned long long)oid, - (unsigned long long)max); + (unsigned long long)oid, (unsigned long long)max); return RETERR(-EIO); } diff -puN fs/reiser4/plugin/disk_format/disk_format40.h~reiser4-big-update fs/reiser4/plugin/disk_format/disk_format40.h --- devel/fs/reiser4/plugin/disk_format/disk_format40.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/disk_format/disk_format40.h 2005-09-15 19:51:08.000000000 -0700 @@ -78,11 +78,10 @@ typedef struct format40_super_info { /* declarations of functions implementing methods of layout plugin for format 40. The functions theirself are in disk_format40.c */ -int get_ready_format40(struct super_block *, void *data); +int init_format_format40(struct super_block *, void *data); const reiser4_key *root_dir_key_format40(const struct super_block *); int release_format40(struct super_block *s); jnode *log_super_format40(struct super_block *s); -void print_info_format40(const struct super_block *s); int check_open_format40(const struct inode *object); /* __DISK_FORMAT40_H__ */ diff -puN fs/reiser4/plugin/disk_format/disk_format.c~reiser4-big-update fs/reiser4/plugin/disk_format/disk_format.c --- devel/fs/reiser4/plugin/disk_format/disk_format.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/disk_format/disk_format.c 2005-09-15 19:51:08.000000000 -0700 @@ -15,13 +15,12 @@ disk_format_plugin format_plugins[LAST_F .pops = NULL, .label = "reiser40", .desc = "standard disk layout for reiser40", - .linkage = TYPE_SAFE_LIST_LINK_ZERO, + .linkage = {NULL, NULL} }, - .get_ready = get_ready_format40, + .init_format = init_format_format40, .root_dir_key = root_dir_key_format40, .release = release_format40, .log_super = log_super_format40, - .print_info = print_info_format40, .check_open = check_open_format40 } }; diff -puN fs/reiser4/plugin/disk_format/disk_format.h~reiser4-big-update fs/reiser4/plugin/disk_format/disk_format.h --- devel/fs/reiser4/plugin/disk_format/disk_format.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/disk_format/disk_format.h 2005-09-15 19:51:08.000000000 -0700 @@ -25,17 +25,3 @@ typedef enum { scroll-step: 1 End: */ - - - - - - - - - - - - - - diff -puN fs/reiser4/plugin/fibration.c~reiser4-big-update fs/reiser4/plugin/fibration.c --- devel/fs/reiser4/plugin/fibration.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/fibration.c 2005-09-15 19:51:08.000000000 -0700 @@ -81,8 +81,7 @@ static __u64 fibre_ext_3(const struct in return FIBRE_NO(0); } -static int -change_fibration(struct inode * inode, reiser4_plugin * plugin) +static int change_fibration(struct inode *inode, reiser4_plugin * plugin) { int result; @@ -91,14 +90,16 @@ change_fibration(struct inode * inode, r assert("nikita-3505", is_reiser4_inode(inode)); assert("nikita-3506", inode_dir_plugin(inode) != NULL); - assert("nikita-3507", plugin->h.type_id == REISER4_FIBRATION_PLUGIN_TYPE); + assert("nikita-3507", + plugin->h.type_id == REISER4_FIBRATION_PLUGIN_TYPE); result = 0; if (inode_fibration_plugin(inode) == NULL || inode_fibration_plugin(inode)->h.id != plugin->h.id) { if (is_dir_empty(inode) == 0) - result = plugin_set_fibration(&reiser4_inode_data(inode)->pset, - &plugin->fibration); + result = + plugin_set_fibration(&reiser4_inode_data(inode)-> + pset, &plugin->fibration); else result = RETERR(-ENOTEMPTY); @@ -107,11 +108,11 @@ change_fibration(struct inode * inode, r } static reiser4_plugin_ops fibration_plugin_ops = { - .init = NULL, - .load = NULL, + .init = NULL, + .load = NULL, .save_len = NULL, - .save = NULL, - .change = change_fibration + .save = NULL, + .change = change_fibration }; /* fibration plugins */ @@ -123,7 +124,7 @@ fibration_plugin fibration_plugins[LAST_ .pops = &fibration_plugin_ops, .label = "lexicographic", .desc = "no fibration", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .fibre = fibre_trivial }, @@ -134,7 +135,7 @@ fibration_plugin fibration_plugins[LAST_ .pops = &fibration_plugin_ops, .label = "dot-o", .desc = "fibrate .o files separately", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .fibre = fibre_dot_o }, @@ -145,7 +146,7 @@ fibration_plugin fibration_plugins[LAST_ .pops = &fibration_plugin_ops, .label = "ext-1", .desc = "fibrate file by single character extension", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .fibre = fibre_ext_1 }, @@ -156,18 +157,18 @@ fibration_plugin fibration_plugins[LAST_ .pops = &fibration_plugin_ops, .label = "ext-3", .desc = "fibrate file by three character extension", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .fibre = fibre_ext_3 } }; -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - End: -*/ +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 79 + * End: + */ diff -puN fs/reiser4/plugin/fibration.h~reiser4-big-update fs/reiser4/plugin/fibration.h --- devel/fs/reiser4/plugin/fibration.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/fibration.h 2005-09-15 19:51:08.000000000 -0700 @@ -12,7 +12,7 @@ typedef struct fibration_plugin { /* generic fields */ plugin_header h; - __u64 (*fibre)(const struct inode *dir, const char *name, int len); + __u64(*fibre) (const struct inode * dir, const char *name, int len); } fibration_plugin; typedef enum { diff -puN /dev/null fs/reiser4/plugin/file/cryptcompress.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/file/cryptcompress.c 2005-09-15 19:51:08.000000000 -0700 @@ -0,0 +1,3553 @@ +/* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by reiser4/README + +This file contains all cluster operations and methods of the reiser4 +cryptcompress object plugin (see http://www.namesys.com/cryptcompress_design.html +for details). + +Cryptcompress specific fields of reiser4 inode/stat-data: + + Incore inode Disk stat-data +******************************************************************************************** +* data structure * field * data structure * field * +******************************************************************************************** +* plugin_set *file plugin id * reiser4_plugin_stat *file plugin id * +* *crypto plugin id * *crypto plugin id * +* *digest plugin id * *digest plugin id * +* *compression plugin id * *compression plugin id* +******************************************************************************************** +* crypto_stat_t * keysize * reiser4_crypto_stat * keysize * +* * keyid * * keyid * +******************************************************************************************** +* cluster_stat_t * cluster_shift * reiser4_cluster_stat * cluster_shift * +******************************************************************************************** +* cryptcompress_info_t * crypto_tfm * * * +******************************************************************************************** +*/ + +#include "../../page_cache.h" +#include "../../inode.h" +#include "../../cluster.h" +#include "../object.h" +#include "../../tree_walk.h" +#include "funcs.h" + +#include +#include +#include +#include +#include + +/* get cryptcompress specific portion of inode */ +cryptcompress_info_t *cryptcompress_inode_data(const struct inode *inode) +{ + return &reiser4_inode_data(inode)->file_plugin_data.cryptcompress_info; +} + +/* plugin->u.file.init_inode_data */ +void +init_inode_data_cryptcompress(struct inode *inode, + reiser4_object_create_data * crd, int create) +{ + cryptcompress_info_t *data; + + data = cryptcompress_inode_data(inode); + assert("edward-685", data != NULL); + + memset(data, 0, sizeof(*data)); + + init_rwsem(&data->lock); + init_inode_ordering(inode, crd, create); +} + +#if REISER4_DEBUG +static int crc_generic_check_ok(void) +{ + return MIN_CRYPTO_BLOCKSIZE == DC_CHECKSUM_SIZE << 1; +} + +int crc_inode_ok(struct inode *inode) +{ + cryptcompress_info_t *data = cryptcompress_inode_data(inode); + + if (cluster_shift_ok(inode_cluster_shift(inode)) && + (data->tfm[CRYPTO_TFM] == NULL) && (data->tfm[DIGEST_TFM] == NULL)) + return 1; + assert("edward-686", 0); + return 0; +} +#endif + +static int check_cryptcompress(struct inode *inode) +{ + int result = 0; + + assert("edward-1307", inode_compression_plugin(inode) != NULL); + + if (inode_cluster_size(inode) < PAGE_CACHE_SIZE) { + warning("edward-1331", + "%s clusters are unsupported", + inode_cluster_plugin(inode)->h.label); + return RETERR(-EINVAL); + } + + /* FIXME-EDWARD: init? or check? */ + if (inode_compression_plugin(inode)->init) + result = inode_compression_plugin(inode)->init(); + return result; +} + +static crypto_stat_t *inode_crypto_stat(struct inode *inode) +{ + assert("edward-90", inode != NULL); + assert("edward-91", reiser4_inode_data(inode) != NULL); + + return (cryptcompress_inode_data(inode)->crypt); +} + +/* NOTE-EDWARD: Do not use crypto without digest */ +static int alloc_crypto_tfm(struct inode *inode, struct inode *parent) +{ + int result; + crypto_plugin *cplug = inode_crypto_plugin(parent); + digest_plugin *dplug = inode_digest_plugin(parent); + + assert("edward-414", dplug != NULL); + assert("edward-415", cplug != NULL); + + result = dplug->alloc(inode); + if (result) + return result; + result = cplug->alloc(inode); + if (result) { + dplug->free(inode); + return result; + } + return 0; +} + +static void free_crypto_tfm(struct inode *inode) +{ + reiser4_inode *info; + + assert("edward-410", inode != NULL); + + info = reiser4_inode_data(inode); + + if (!inode_get_crypto(inode)) + return; + + assert("edward-411", inode_crypto_plugin(inode)); + assert("edward-763", inode_digest_plugin(inode)); + + inode_crypto_plugin(inode)->free(inode); + inode_digest_plugin(inode)->free(inode); +} + +static int attach_crypto_stat(struct inode *inode, crypto_data_t * data) +{ + __u8 *txt; + + crypto_stat_t *stat; + struct scatterlist sg; + struct crypto_tfm *dtfm; + + assert("edward-690", inode_get_crypto(inode)); + assert("edward-766", inode_get_digest(inode)); + + dtfm = inode_get_digest(inode); + + stat = kmalloc(sizeof(*stat), GFP_KERNEL); + if (!stat) + return -ENOMEM; + + stat->keyid = + kmalloc((size_t) crypto_tfm_alg_digestsize(dtfm), + GFP_KERNEL); + if (!stat->keyid) { + kfree(stat); + return -ENOMEM; + } + txt = kmalloc(data->keyid_size, GFP_KERNEL); + if (!txt) { + kfree(stat->keyid); + kfree(stat); + return -ENOMEM; + } + memcpy(txt, data->keyid, data->keyid_size); + sg.page = virt_to_page(txt); + sg.offset = offset_in_page(txt); + sg.length = data->keyid_size; + + crypto_digest_init(dtfm); + crypto_digest_update(dtfm, &sg, 1); + crypto_digest_final(dtfm, stat->keyid); + + cryptcompress_inode_data(inode)->crypt = stat; + kfree(txt); + + return 0; +} + +static void detach_crypto_stat(struct inode *object) +{ + crypto_stat_t *stat; + + stat = inode_crypto_stat(object); + + assert("edward-691", crc_inode_ok(object)); + + if (!inode_get_crypto(object)) + return; + + assert("edward-412", stat != NULL); + + kfree(stat->keyid); + kfree(stat); +} + +/* 1) fill crypto specific part of inode + 2) set inode crypto stat which is supposed to be saved in stat-data */ +static int +inode_set_crypto(struct inode *object, struct inode *parent, + crypto_data_t * data) +{ + int result; + struct crypto_tfm *tfm; + crypto_plugin *cplug; + digest_plugin *dplug; + reiser4_inode *info = reiser4_inode_data(object); + + cplug = inode_crypto_plugin(parent); + dplug = inode_digest_plugin(parent); + + plugin_set_crypto(&info->pset, cplug); + plugin_set_digest(&info->pset, dplug); + + result = alloc_crypto_tfm(object, parent); + if (!result) + return result; + + if (!inode_get_crypto(object)) + /* nothing to do anymore */ + return 0; + + assert("edward-414", dplug != NULL); + assert("edward-415", cplug != NULL); + assert("edward-417", data->key != NULL); + assert("edward-88", data->keyid != NULL); + assert("edward-83", data->keyid_size != 0); + assert("edward-89", data->keysize != 0); + + tfm = inode_get_tfm(object, CRYPTO_TFM); + assert("edward-695", tfm != NULL); + + result = cplug->setkey(tfm, data->key, data->keysize); + if (result) { + free_crypto_tfm(object); + return result; + } + assert("edward-34", + !inode_get_flag(object, REISER4_SECRET_KEY_INSTALLED)); + inode_set_flag(object, REISER4_SECRET_KEY_INSTALLED); + + info->extmask |= (1 << CRYPTO_STAT); + + result = attach_crypto_stat(object, data); + if (result) + goto error; + + info->plugin_mask |= (1 << PSET_CRYPTO) | (1 << PSET_DIGEST); + + return 0; + error: + free_crypto_tfm(object); + inode_clr_flag(object, REISER4_SECRET_KEY_INSTALLED); + return result; +} + +static int inode_set_compression(struct inode *object, struct inode *parent) +{ + int result = 0; + compression_plugin *cplug; + reiser4_inode *info = reiser4_inode_data(object); + + cplug = inode_compression_plugin(parent); + + if (cplug->init != NULL) { + result = cplug->init(); + if (result) + return result; + } + plugin_set_compression(&info->pset, cplug); + info->plugin_mask |= (1 << PSET_COMPRESSION); + + return 0; +} + +static void +inode_set_compression_mode(struct inode *object, struct inode *parent) +{ + compression_mode_plugin *mplug; + reiser4_inode *info = reiser4_inode_data(object); + + mplug = inode_compression_mode_plugin(parent); + + plugin_set_compression_mode(&info->pset, mplug); + info->plugin_mask |= (1 << PSET_COMPRESSION_MODE); + return; +} + +static int inode_set_cluster(struct inode *object, struct inode *parent) +{ + reiser4_inode *info; + cluster_plugin *cplug; + + assert("edward-696", object != NULL); + + info = reiser4_inode_data(object); + cplug = inode_cluster_plugin(parent); + + if (cplug->shift < PAGE_CACHE_SHIFT) { + warning("edward-1320", + "Can not support cluster size %p", cplug->h.label); + return RETERR(-EINVAL); + } + plugin_set_cluster(&info->pset, cplug); + + info->plugin_mask |= (1 << PSET_CLUSTER); + return 0; +} + +/* plugin->create() method for crypto-compressed files + +. install plugins +. attach crypto info if specified +. attach compression info if specified +. attach cluster info +*/ +int +create_cryptcompress(struct inode *object, struct inode *parent, + reiser4_object_create_data * data) +{ + int result; + reiser4_inode *info; + + assert("edward-23", object != NULL); + assert("edward-24", parent != NULL); + assert("edward-30", data != NULL); + assert("edward-26", inode_get_flag(object, REISER4_NO_SD)); + assert("edward-27", data->id == CRC_FILE_PLUGIN_ID); + assert("edward-1170", crc_generic_check_ok()); + + info = reiser4_inode_data(object); + + assert("edward-29", info != NULL); + + /* set file bit */ + info->plugin_mask |= (1 << PSET_FILE); + + /* set crypto */ + result = inode_set_crypto(object, parent, data->crypto); + if (result) + goto error; + /* set compression */ + result = inode_set_compression(object, parent); + if (result) + goto error; + inode_set_compression_mode(object, parent); + + /* set cluster info */ + result = inode_set_cluster(object, parent); + if (result) + goto error; + /* set plugin mask */ + info->extmask |= (1 << PLUGIN_STAT); + + /* save everything in disk stat-data */ + result = write_sd_by_inode_common(object); + if (!result) + return 0; + /* save() method failed, release attached crypto info */ + inode_clr_flag(object, REISER4_CRYPTO_STAT_LOADED); + error: + free_crypto_tfm(object); + detach_crypto_stat(object); + inode_clr_flag(object, REISER4_SECRET_KEY_INSTALLED); + return result; +} + +/* plugin->destroy_inode() */ +void destroy_inode_cryptcompress(struct inode *inode) +{ + assert("edward-802", + inode_file_plugin(inode) == + file_plugin_by_id(CRC_FILE_PLUGIN_ID)); + assert("edward-803", !is_bad_inode(inode) && is_inode_loaded(inode)); + + free_crypto_tfm(inode); + if (inode_get_flag(inode, REISER4_CRYPTO_STAT_LOADED)) + detach_crypto_stat(inode); + + inode_clr_flag(inode, REISER4_CRYPTO_STAT_LOADED); + inode_clr_flag(inode, REISER4_SECRET_KEY_INSTALLED); +} + +/* returns translated offset */ +static loff_t inode_scaled_offset(struct inode *inode, + const loff_t src_off /* input offset */ ) +{ + assert("edward-97", inode != NULL); + + if (!inode_get_crypto(inode) || src_off == get_key_offset(max_key())) + return src_off; + + return inode_crypto_plugin(inode)->scale(inode, crypto_blocksize(inode), + src_off); +} + +/* returns disk cluster size */ +size_t inode_scaled_cluster_size(struct inode * inode) +{ + assert("edward-110", inode != NULL); + + return inode_scaled_offset(inode, inode_cluster_size(inode)); +} + +static int new_cluster(reiser4_cluster_t * clust, struct inode *inode) +{ + return (clust_to_off(clust->index, inode) >= inode->i_size); +} + +/* set number of cluster pages */ +static void set_cluster_nrpages(reiser4_cluster_t * clust, struct inode *inode) +{ + reiser4_slide_t *win; + + assert("edward-180", clust != NULL); + assert("edward-1040", inode != NULL); + + win = clust->win; + if (!win) { + /* FIXME-EDWARD: i_size should be protected */ + clust->nr_pages = + count_to_nrpages(fsize_to_count(clust, inode)); + return; + } + assert("edward-1176", clust->op != PCL_UNKNOWN); + assert("edward-1064", win->off + win->count + win->delta != 0); + + if (win->stat == HOLE_WINDOW && + win->off == 0 && win->count == inode_cluster_size(inode)) { + /* special case: we start write hole from fake cluster */ + clust->nr_pages = 0; + return; + } + clust->nr_pages = + count_to_nrpages(max_count(win->off + win->count + win->delta, + fsize_to_count(clust, inode))); + return; +} + +/* plugin->key_by_inode() */ +/* see plugin/plugin.h for details */ +int +key_by_inode_cryptcompress(struct inode *inode, loff_t off, reiser4_key * key) +{ + loff_t clust_off; + + assert("edward-64", inode != 0); + // assert("edward-112", ergo(off != get_key_offset(max_key()), !off_to_cloff(off, inode))); + /* don't come here with other offsets */ + + clust_off = + (off == + get_key_offset(max_key())? get_key_offset(max_key()) : + off_to_clust_to_off(off, inode)); + + key_by_inode_and_offset_common(inode, 0, key); + set_key_offset(key, + (__u64) (!inode_crypto_stat(inode) ? clust_off : + inode_scaled_offset(inode, clust_off))); + return 0; +} + +/* plugin->flow_by_inode */ +int +flow_by_inode_cryptcompress(struct inode *inode /* file to build flow for */ , + const char __user *buf /* user level buffer */ , + int user /* 1 if @buf is of user space, 0 - if it is + kernel space */ , + loff_t size /* buffer size */ , + loff_t off /* offset to start io from */ , + rw_op op /* READ or WRITE */ , + flow_t * f /* resulting flow */ ) +{ + assert("edward-436", f != NULL); + assert("edward-149", inode != NULL); + assert("edward-150", inode_file_plugin(inode) != NULL); + assert("edward-151", + inode_file_plugin(inode)->key_by_inode == + key_by_inode_cryptcompress); + + f->length = size; + memcpy(&f->data, &buf, sizeof(buf)); + f->user = user; + f->op = op; + + if (op == WRITE_OP && user == 1) + return 0; + return key_by_inode_cryptcompress(inode, off, &f->key); +} + +static int +crc_hint_validate(hint_t * hint, const reiser4_key * key, + znode_lock_mode lock_mode) +{ + coord_t *coord; + + assert("edward-704", hint != NULL); + assert("edward-1089", !hint->ext_coord.valid); + assert("edward-706", hint->lh.owner == NULL); + + coord = &hint->ext_coord.coord; + + if (!hint || !hint_is_set(hint) || hint->mode != lock_mode) + /* hint either not set or set by different operation */ + return RETERR(-E_REPEAT); + + if (get_key_offset(key) != hint->offset) + /* hint is set for different key */ + return RETERR(-E_REPEAT); + + assert("edward-707", schedulable()); + + return seal_validate(&hint->seal, &hint->ext_coord.coord, + key, &hint->lh, lock_mode, ZNODE_LOCK_LOPRI); +} + +static int reserve4cluster(struct inode *inode, reiser4_cluster_t *clust) +{ + int result = 0; + + assert("edward-965", schedulable()); + assert("edward-439", inode != NULL); + assert("edward-440", clust != NULL); + assert("edward-441", clust->pages != NULL); + assert("edward-1261", get_current_context()->grabbed_blocks == 0); + + if (clust->nr_pages == 0) { + assert("edward-1152", clust->win != NULL); + assert("edward-1153", clust->win->stat == HOLE_WINDOW); + /* don't reserve space for fake disk clusteer */ + return 0; + } + assert("edward-442", jprivate(clust->pages[0]) != NULL); + + result = reiser4_grab_space_force( /* for prepped disk cluster */ + estimate_insert_cluster(inode, + 0) + + /* for unprepped disk cluster */ + estimate_insert_cluster(inode, + 1), + BA_CAN_COMMIT); + if (result) + return result; + clust->reserved = 1; + grabbed2cluster_reserved(estimate_insert_cluster(inode, 0) + + estimate_insert_cluster(inode, 1)); +#if REISER4_DEBUG + clust->reserved_prepped = estimate_insert_cluster(inode, 0); + clust->reserved_unprepped = estimate_insert_cluster(inode, 1); +#endif + assert("edward-1262", get_current_context()->grabbed_blocks == 0); + return 0; +} + +static void +free_reserved4cluster(struct inode *inode, reiser4_cluster_t * clust, int count) +{ + assert("edward-967", clust->reserved == 1); + + cluster_reserved2free(count); + clust->reserved = 0; +} + +#if REISER4_DEBUG +static int eq_to_ldk(znode * node, const reiser4_key * key) +{ + return UNDER_RW(dk, current_tree, read, + keyeq(key, znode_get_ld_key(node))); +} +#endif + +/* The core search procedure. + If returned value is not cbk_errored, current znode is locked */ +static int find_cluster_item(hint_t * hint, const reiser4_key * key, /* key of the item we are + looking for */ + znode_lock_mode lock_mode /* which lock */ , + ra_info_t * ra_info, lookup_bias bias, __u32 flags) +{ + int result; + reiser4_key ikey; + coord_t *coord = &hint->ext_coord.coord; + coord_t orig = *coord; + + assert("edward-152", hint != NULL); + + if (hint->ext_coord.valid == 0) { + result = crc_hint_validate(hint, key, lock_mode); + if (result == -E_REPEAT) + goto traverse_tree; + else if (result) { + assert("edward-1216", 0); + return result; + } + hint->ext_coord.valid = 1; + } + assert("edward-709", znode_is_any_locked(coord->node)); + + /* In-place lookup is going here, it means we just need to + check if next item of the @coord match to the @keyhint) */ + + if (equal_to_rdk(coord->node, key)) { + result = goto_right_neighbor(coord, &hint->lh); + if (result == -E_NO_NEIGHBOR) { + assert("edward-1217", 0); + return RETERR(-EIO); + } + if (result) + return result; + assert("edward-1218", eq_to_ldk(coord->node, key)); + } else { + coord->item_pos++; + coord->unit_pos = 0; + coord->between = AT_UNIT; + } + result = zload(coord->node); + if (result) + return result; + assert("edward-1219", !node_is_empty(coord->node)); + + if (!coord_is_existing_item(coord)) { + zrelse(coord->node); + goto not_found; + } + item_key_by_coord(coord, &ikey); + zrelse(coord->node); + if (!keyeq(key, &ikey)) + goto not_found; + return CBK_COORD_FOUND; + + not_found: + assert("edward-1220", coord->item_pos > 0); + //coord->item_pos--; + /* roll back */ + *coord = orig; + ON_DEBUG(coord_update_v(coord)); + return CBK_COORD_NOTFOUND; + + traverse_tree: + assert("edward-713", hint->lh.owner == NULL); + assert("edward-714", schedulable()); + + unset_hint(hint); + coord_init_zero(coord); + result = coord_by_key(current_tree, key, coord, &hint->lh, + lock_mode, bias, LEAF_LEVEL, LEAF_LEVEL, + CBK_UNIQUE | flags, ra_info); + if (cbk_errored(result)) + return result; + hint->ext_coord.valid = 1; + return result; +} + +/* the following two functions are to evaluate results + of compression transform */ +static unsigned max_crypto_overhead(struct inode *inode) +{ + if (!inode_get_crypto(inode) + || !inode_crypto_plugin(inode)->align_stream) + return 0; + return crypto_blocksize(inode); +} + +static int deflate_overhead(struct inode *inode) +{ + return (inode_compression_plugin(inode)-> + checksum ? DC_CHECKSUM_SIZE : 0); +} + +/* to estimate size of allocating transform stream */ +static unsigned deflate_overrun(struct inode *inode, int in_len) +{ + return (inode_compression_plugin(inode)->overrun != NULL ? + inode_compression_plugin(inode)->overrun(in_len) : 0); +} + +/* The following two functions represent reiser4 compression policy */ +static int try_compress(tfm_cluster_t * tc, cloff_t index, struct inode *inode) +{ + compression_plugin *cplug = inode_compression_plugin(inode); + compression_mode_plugin *mplug = inode_compression_mode_plugin(inode); + + assert("edward-1321", tc->len != 0); + assert("edward-1322", cplug != NULL); + assert("edward-1323", mplug != NULL); + + return (cplug->compress != NULL) && + (mplug->should_deflate != NULL ? mplug->should_deflate(index) : 1) + && (cplug->min_size_deflate != NULL ? tc->len >= + cplug->min_size_deflate() : 1); +} + +static int try_encrypt(struct inode *inode) +{ + return inode_get_crypto(inode) != NULL; +} + +/* Evaluation results of compression transform. */ +static int save_compressed(int old_size, int new_size, struct inode *inode) +{ + return (new_size + deflate_overhead(inode) + + max_crypto_overhead(inode) < old_size); +} + +/* Guess result of the evaluation above */ +static int +need_inflate(reiser4_cluster_t * clust, struct inode *inode, + int encrypted /* is cluster encrypted */ ) +{ + tfm_cluster_t *tc = &clust->tc; + + assert("edward-142", tc != 0); + assert("edward-143", inode != NULL); + + return tc->len < + (encrypted ? + inode_scaled_offset(inode, fsize_to_count(clust, inode)) : + fsize_to_count(clust, inode)); +} + +/* append checksum at the end of input transform stream + and increase its length */ +static void dc_set_checksum(compression_plugin * cplug, tfm_cluster_t * tc) +{ + __u32 checksum; + + assert("edward-1309", tc != NULL); + assert("edward-1310", tc->len > 0); + assert("edward-1311", cplug->checksum != NULL); + + checksum = cplug->checksum(tfm_stream_data(tc, OUTPUT_STREAM), tc->len); + cputod32(checksum, + (d32 *) (tfm_stream_data(tc, OUTPUT_STREAM) + tc->len)); + tc->len += (int)DC_CHECKSUM_SIZE; +} + +/* returns 0 if checksums coincide, otherwise returns 1, + increase the length of input transform stream */ +static int dc_check_checksum(compression_plugin * cplug, tfm_cluster_t * tc) +{ + assert("edward-1312", tc != NULL); + assert("edward-1313", tc->len > (int)DC_CHECKSUM_SIZE); + assert("edward-1314", cplug->checksum != NULL); + + if (cplug-> + checksum(tfm_stream_data(tc, INPUT_STREAM), + tc->len - (int)DC_CHECKSUM_SIZE) != + d32tocpu((d32 *) (tfm_stream_data(tc, INPUT_STREAM) + tc->len - + (int)DC_CHECKSUM_SIZE))) { + warning("edward-156", + "bad disk cluster checksum %d, (should be %d)\n", + (int) + d32tocpu((d32 *) (tfm_stream_data(tc, INPUT_STREAM) + + tc->len - (int)DC_CHECKSUM_SIZE)), + (int)cplug->checksum(tfm_stream_data(tc, INPUT_STREAM), + tc->len - (int)DC_CHECKSUM_SIZE)); + return 1; + } + tc->len -= (int)DC_CHECKSUM_SIZE; + return 0; +} + +int +grab_tfm_stream(struct inode *inode, tfm_cluster_t * tc, + tfm_action act, tfm_stream_id id) +{ + size_t size = inode_scaled_cluster_size(inode); + + assert("edward-901", tc != NULL); + assert("edward-1027", inode_compression_plugin(inode) != NULL); + + if (act == TFM_WRITE) + size += deflate_overrun(inode, inode_cluster_size(inode)); + + if (!tfm_stream(tc, id) && id == INPUT_STREAM) + alternate_streams(tc); + if (!tfm_stream(tc, id)) + return alloc_tfm_stream(tc, size, id); + + assert("edward-902", tfm_stream_is_set(tc, id)); + + if (tfm_stream_size(tc, id) < size) + return realloc_tfm_stream(tc, size, id); + return 0; +} + +/* Common deflate cluster manager */ +int deflate_cluster(reiser4_cluster_t * clust, struct inode *inode) +{ + int result = 0; + int transformed = 0; + tfm_cluster_t *tc = &clust->tc; + + assert("edward-401", inode != NULL); + assert("edward-903", tfm_stream_is_set(tc, INPUT_STREAM)); + assert("edward-498", !tfm_cluster_is_uptodate(tc)); + + if (try_compress(tc, clust->index, inode)) { + /* try to compress, discard bad results */ + __u32 dst_len; + compression_plugin *cplug = inode_compression_plugin(inode); + compression_mode_plugin *mplug = + inode_compression_mode_plugin(inode); + assert("edward-602", cplug != NULL); + + result = grab_tfm_stream(inode, tc, TFM_WRITE, OUTPUT_STREAM); + if (result) + return result; + dst_len = tfm_stream_size(tc, OUTPUT_STREAM); + cplug->compress(get_coa(tc, cplug->h.id), + tfm_stream_data(tc, INPUT_STREAM), tc->len, + tfm_stream_data(tc, OUTPUT_STREAM), &dst_len); + + /* make sure we didn't overwrite extra bytes */ + assert("edward-603", + dst_len <= tfm_stream_size(tc, OUTPUT_STREAM)); + + /* evaluate results of compression transform */ + if (save_compressed(tc->len, dst_len, inode)) { + /* good result, accept */ + tc->len = dst_len; + if (cplug->checksum != NULL) + dc_set_checksum(cplug, tc); + transformed = 1; + if (mplug->save_deflate != NULL) + mplug->save_deflate(inode); + } else { + /* bad result, discard */ +#if REISER4_DEBUG + warning("edward-1309", + "incompressible data: inode %llu, cluster %lu", + (unsigned long long)get_inode_oid(inode), + clust->index); +#endif + if (mplug->discard_deflate != NULL) { + result = + mplug->discard_deflate(inode, clust->index); + if (result) + return result; + } + } + } + if (try_encrypt(inode)) { + crypto_plugin *cplug; + /* FIXME-EDWARD */ + assert("edward-904", 0); + + cplug = inode_crypto_plugin(inode); + if (transformed) + alternate_streams(tc); + result = grab_tfm_stream(inode, tc, TFM_WRITE, OUTPUT_STREAM); + if (result) + return result; + /* FIXME: set src_len, dst_len, encrypt */ + transformed = 1; + } + if (!transformed) + alternate_streams(tc); + return result; +} + +/* Common inflate cluster manager. + Is used in readpage() or readpages() methods of + cryptcompress object plugins. */ +int inflate_cluster(reiser4_cluster_t * clust, struct inode *inode) +{ + int result = 0; + int transformed = 0; + + tfm_cluster_t *tc = &clust->tc; + + assert("edward-905", inode != NULL); + assert("edward-1178", clust->dstat == PREP_DISK_CLUSTER); + assert("edward-906", tfm_stream_is_set(&clust->tc, INPUT_STREAM)); + assert("edward-907", !tfm_cluster_is_uptodate(tc)); + + if (inode_get_crypto(inode) != NULL) { + crypto_plugin *cplug; + + /* FIXME-EDWARD: isn't supported yet */ + assert("edward-908", 0); + cplug = inode_crypto_plugin(inode); + assert("edward-617", cplug != NULL); + + result = grab_tfm_stream(inode, tc, TFM_READ, OUTPUT_STREAM); + if (result) + return result; + assert("edward-909", tfm_cluster_is_set(tc)); + + /* set src_len, dst_len and decrypt */ + /* tc->len = dst_len */ + + transformed = 1; + } + if (need_inflate(clust, inode, 0)) { + unsigned dst_len = inode_cluster_size(inode); + compression_plugin *cplug = inode_compression_plugin(inode); + + if (transformed) + alternate_streams(tc); + + result = grab_tfm_stream(inode, tc, TFM_READ, OUTPUT_STREAM); + if (result) + return result; + assert("edward-1305", cplug->decompress != NULL); + assert("edward-910", tfm_cluster_is_set(tc)); + + /* Check compression checksum for possible IO errors. + + End-of-cluster format created before encryption: + + data + checksum (4) Indicates presence of compression + infrastructure, should be private. + Can be absent. + crypto_overhead Created by ->align() method of crypto-plugin, + Can be absent. + + Crypto overhead format: + + data + tail_size (1) size of aligning tail, + 1 <= tail_size <= blksize + */ + if (cplug->checksum != NULL) { + result = dc_check_checksum(cplug, tc); + if (result) + return RETERR(-EIO); + } + /* decompress cluster */ + cplug->decompress(get_coa(tc, cplug->h.id), + tfm_stream_data(tc, INPUT_STREAM), tc->len, + tfm_stream_data(tc, OUTPUT_STREAM), &dst_len); + + /* check length */ + tc->len = dst_len; + assert("edward-157", dst_len == fsize_to_count(clust, inode)); + transformed = 1; + } + if (!transformed) + alternate_streams(tc); + return result; +} + +/* plugin->read() : + * generic_file_read() + * All key offsets don't make sense in traditional unix semantics unless they + * represent the beginning of clusters, so the only thing we can do is start + * right from mapping to the address space (this is precisely what filemap + * generic method does) */ +/* plugin->readpage() */ +int readpage_cryptcompress(struct file *file, struct page *page) +{ + reiser4_context *ctx; + reiser4_cluster_t clust; + item_plugin *iplug; + int result; + + assert("edward-88", PageLocked(page)); + assert("vs-976", !PageUptodate(page)); + assert("edward-89", page->mapping && page->mapping->host); + + ctx = init_context(page->mapping->host->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + result = check_cryptcompress(page->mapping->host); + if (result) { + reiser4_exit_context(ctx); + return result; + } + if (file) + assert("edward-113", + page->mapping == file->f_dentry->d_inode->i_mapping); + + if (PageUptodate(page)) { + printk + ("readpage_cryptcompress: page became already uptodate\n"); + unlock_page(page); + reiser4_exit_context(ctx); + return 0; + } + reiser4_cluster_init(&clust, NULL); + clust.file = file; + iplug = item_plugin_by_id(CTAIL_ID); + if (!iplug->s.file.readpage) { + put_cluster_handle(&clust, TFM_READ); + reiser4_exit_context(ctx); + return -EINVAL; + } + result = iplug->s.file.readpage(&clust, page); + + assert("edward-64", + ergo(result == 0, (PageLocked(page) || PageUptodate(page)))); + /* if page has jnode - that jnode is mapped + assert("edward-65", ergo(result == 0 && PagePrivate(page), + jnode_mapped(jprivate(page)))); + */ + put_cluster_handle(&clust, TFM_READ); + reiser4_exit_context(ctx); + return result; +} + +/* plugin->readpages() */ +void +readpages_cryptcompress(struct file *file, struct address_space *mapping, + struct list_head *pages) +{ + file_plugin *fplug; + item_plugin *iplug; + + assert("edward-1112", mapping != NULL); + assert("edward-1113", mapping->host != NULL); + + if (check_cryptcompress(mapping->host)) + return; + fplug = inode_file_plugin(mapping->host); + + assert("edward-1114", fplug == file_plugin_by_id(CRC_FILE_PLUGIN_ID)); + + iplug = item_plugin_by_id(CTAIL_ID); + + iplug->s.file.readpages(file, mapping, pages); + + return; +} + +/* how much pages will be captured */ +static int cluster_nrpages_to_capture(reiser4_cluster_t * clust) +{ + switch (clust->op) { + case PCL_APPEND: + return clust->nr_pages; + case PCL_TRUNCATE: + assert("edward-1179", clust->win != NULL); + return count_to_nrpages(clust->win->off + clust->win->count); + default: + impossible("edward-1180", "bad page cluster option"); + return 0; + } +} + +static void set_cluster_pages_dirty(reiser4_cluster_t * clust) +{ + int i; + struct page *pg; + int nrpages = cluster_nrpages_to_capture(clust); + + for (i = 0; i < nrpages; i++) { + + pg = clust->pages[i]; + + assert("edward-968", pg != NULL); + + lock_page(pg); + + assert("edward-1065", PageUptodate(pg)); + + set_page_dirty_internal(pg, 0); + + if (!PageReferenced(pg)) + SetPageReferenced(pg); + mark_page_accessed(pg); + + unlock_page(pg); + } +} + +static void clear_cluster_pages_dirty(reiser4_cluster_t * clust) +{ + int i; + assert("edward-1275", clust != NULL); + + for (i = 0; i < clust->nr_pages; i++) { + assert("edward-1276", clust->pages[i] != NULL); + + lock_page(clust->pages[i]); + if (!PageDirty(clust->pages[i])) { + warning("edward-985", "Page of index %lu (inode %llu)" + " is not dirty\n", clust->pages[i]->index, + (unsigned long long)get_inode_oid(clust-> + pages[i]-> + mapping-> + host)); + } else { + assert("edward-1277", PageUptodate(clust->pages[i])); + reiser4_clear_page_dirty(clust->pages[i]); + } + unlock_page(clust->pages[i]); + } +} + +/* update i_size by window */ +static void inode_set_new_size(reiser4_cluster_t * clust, struct inode *inode) +{ + loff_t size; + reiser4_slide_t *win; + + assert("edward-1181", clust != NULL); + assert("edward-1182", inode != NULL); + + win = clust->win; + assert("edward-1183", win != NULL); + + size = clust_to_off(clust->index, inode) + win->off; + + switch (clust->op) { + case PCL_APPEND: + if (size + win->count <= inode->i_size) + /* overwrite only */ + return; + size += win->count; + break; + case PCL_TRUNCATE: + break; + default: + impossible("edward-1184", "bad page cluster option"); + break; + } + inode_check_scale_nolock(inode, inode->i_size, size); + inode->i_size = size; + return; +} + +/* . reserve space for a disk cluster if its jnode is not dirty; + . update set of pages referenced by this jnode + . update jnode's counter of referenced pages (excluding first one) +*/ +static void +make_cluster_jnode_dirty_locked(reiser4_cluster_t * clust, jnode * node, + loff_t * old_isize, struct inode *inode) +{ + int i; + int old_refcnt; + int new_refcnt; + + assert("edward-221", node != NULL); + assert("edward-971", clust->reserved == 1); + assert("edward-1028", spin_jnode_is_locked(node)); + assert("edward-972", node->page_count < cluster_nrpages(inode)); + assert("edward-1263", + clust->reserved_prepped == estimate_insert_cluster(inode, 0)); + assert("edward-1264", clust->reserved_unprepped == 0); + + if (jnode_is_dirty(node)) { + /* there are >= 1 pages already referenced by this jnode */ + assert("edward-973", + count_to_nrpages(off_to_count + (*old_isize, clust->index, inode))); + old_refcnt = + count_to_nrpages(off_to_count + (*old_isize, clust->index, inode)) - 1; + /* space for the disk cluster is already reserved */ + + free_reserved4cluster(inode, clust, + estimate_insert_cluster(inode, 0)); + } else { + /* there is only one page referenced by this jnode */ + assert("edward-1043", node->page_count == 0); + old_refcnt = 0; + jnode_make_dirty_locked(node); + clust->reserved = 0; + } +#if REISER4_DEBUG + clust->reserved_prepped -= estimate_insert_cluster(inode, 0); +#endif + new_refcnt = cluster_nrpages_to_capture(clust) - 1; + + /* get rid of duplicated references */ + for (i = 0; i <= old_refcnt; i++) { + assert("edward-975", clust->pages[i]); + assert("edward-976", old_refcnt < inode_cluster_size(inode)); + assert("edward-1185", PageUptodate(clust->pages[i])); + + page_cache_release(clust->pages[i]); + } + /* truncate old references */ + if (new_refcnt < old_refcnt) { + assert("edward-1186", clust->op == PCL_TRUNCATE); + for (i = new_refcnt + 1; i <= old_refcnt; i++) { + assert("edward-1187", clust->pages[i]); + assert("edward-1188", PageUptodate(clust->pages[i])); + + page_cache_release(clust->pages[i]); + } + } +#if REISER4_DEBUG + node->page_count = new_refcnt; +#endif + return; +} + +/* This is the interface to capture page cluster. + All the cluster pages contain dependent modifications + and should be committed at the same time */ +static int try_capture_cluster(reiser4_cluster_t * clust, struct inode *inode) +{ + int result = 0; + loff_t old_size = inode->i_size; + jnode *node; + + assert("edward-1029", clust != NULL); + assert("edward-1030", clust->reserved == 1); + assert("edward-1031", clust->nr_pages != 0); + assert("edward-1032", clust->pages != NULL); + assert("edward-1033", clust->pages[0] != NULL); + + node = jprivate(clust->pages[0]); + + assert("edward-1035", node != NULL); + + LOCK_JNODE(node); + if (clust->win) + inode_set_new_size(clust, inode); + + result = try_capture(node, ZNODE_WRITE_LOCK, 0, 0); + if (result) + goto exit; + make_cluster_jnode_dirty_locked(clust, node, &old_size, inode); + exit: + assert("edward-1034", !result); + UNLOCK_JNODE(node); + jput(node); + return result; +} + +/* Collect unlocked cluster pages and jnode */ +static int +grab_cluster_pages_jnode(struct inode *inode, reiser4_cluster_t * clust) +{ + int i; + int result = 0; + jnode *node = NULL; + + assert("edward-182", clust != NULL); + assert("edward-183", clust->pages != NULL); + assert("edward-184", clust->nr_pages <= cluster_nrpages(inode)); + + if (clust->nr_pages == 0) + return 0; + + for (i = 0; i < clust->nr_pages; i++) { + + assert("edward-1044", clust->pages[i] == NULL); + + clust->pages[i] = + grab_cache_page(inode->i_mapping, + clust_to_pg(clust->index, inode) + i); + if (!clust->pages[i]) { + result = RETERR(-ENOMEM); + break; + } + if (i == 0) { + node = jnode_of_page(clust->pages[i]); + unlock_page(clust->pages[i]); + if (IS_ERR(node)) { + result = PTR_ERR(node); + break; + } + assert("edward-919", node); + continue; + } + unlock_page(clust->pages[i]); + } + if (result) { + while (i) + page_cache_release(clust->pages[--i]); + if (node && !IS_ERR(node)) + jput(node); + return result; + } + assert("edward-920", jprivate(clust->pages[0])); + LOCK_JNODE(node); + JF_SET(node, JNODE_CLUSTER_PAGE); + UNLOCK_JNODE(node); + return 0; +} + +/* collect unlocked cluster pages */ +static int grab_cluster_pages(struct inode *inode, reiser4_cluster_t * clust) +{ + int i; + int result = 0; + + assert("edward-787", clust != NULL); + assert("edward-788", clust->pages != NULL); + assert("edward-789", clust->nr_pages != 0); + assert("edward-790", clust->nr_pages <= cluster_nrpages(inode)); + + for (i = 0; i < clust->nr_pages; i++) { + clust->pages[i] = + grab_cache_page(inode->i_mapping, + clust_to_pg(clust->index, inode) + i); + if (!clust->pages[i]) { + result = RETERR(-ENOMEM); + break; + } + unlock_page(clust->pages[i]); + } + if (result) + while (i) + page_cache_release(clust->pages[--i]); + return result; +} + +/* put cluster pages */ +static void release_cluster_pages(reiser4_cluster_t * clust, int from) +{ + int i; + + assert("edward-447", clust != NULL); + assert("edward-448", from <= clust->nr_pages); + + for (i = from; i < clust->nr_pages; i++) { + + assert("edward-449", clust->pages[i] != NULL); + + page_cache_release(clust->pages[i]); + } +} + +static void release_cluster_pages_capture(reiser4_cluster_t * clust) +{ + assert("edward-1278", clust != NULL); + assert("edward-1279", clust->nr_pages != 0); + + return release_cluster_pages(clust, 1); +} + +void release_cluster_pages_nocapture(reiser4_cluster_t * clust) +{ + return release_cluster_pages(clust, 0); +} + +static void release_cluster_pages_and_jnode(reiser4_cluster_t * clust) +{ + jnode *node; + + assert("edward-445", clust != NULL); + assert("edward-922", clust->pages != NULL); + assert("edward-446", clust->pages[0] != NULL); + + node = jprivate(clust->pages[0]); + + assert("edward-447", node != NULL); + + release_cluster_pages(clust, 0); + + jput(node); +} + +#if REISER4_DEBUG +static int window_ok(reiser4_slide_t * win, struct inode *inode) +{ + assert("edward-1115", win != NULL); + assert("edward-1116", ergo(win->delta, win->stat == HOLE_WINDOW)); + + return (win->off != inode_cluster_size(inode)) && + (win->off + win->count + win->delta <= inode_cluster_size(inode)); +} + +static int cluster_ok(reiser4_cluster_t * clust, struct inode *inode) +{ + assert("edward-279", clust != NULL); + + if (!clust->pages) + return 0; + return (clust->win ? window_ok(clust->win, inode) : 1); +} +#endif + +/* guess next window stat */ +static inline window_stat next_window_stat(reiser4_slide_t * win) +{ + assert("edward-1130", win != NULL); + return ((win->stat == HOLE_WINDOW && win->delta == 0) ? + HOLE_WINDOW : DATA_WINDOW); +} + +/* guess next cluster index and window params */ +static void +update_cluster(struct inode *inode, reiser4_cluster_t * clust, loff_t file_off, + loff_t to_file) +{ + reiser4_slide_t *win; + + assert("edward-185", clust != NULL); + assert("edward-438", clust->pages != NULL); + assert("edward-281", cluster_ok(clust, inode)); + + win = clust->win; + if (!win) + return; + + switch (win->stat) { + case DATA_WINDOW: + /* increment window position */ + clust->index++; + win->stat = DATA_WINDOW; + win->off = 0; + win->count = min_count(inode_cluster_size(inode), to_file); + break; + case HOLE_WINDOW: + switch (next_window_stat(win)) { + case HOLE_WINDOW: + /* set window to fit the offset we start write from */ + clust->index = off_to_clust(file_off, inode); + win->stat = HOLE_WINDOW; + win->off = 0; + win->count = off_to_cloff(file_off, inode); + win->delta = + min_count(inode_cluster_size(inode) - win->count, + to_file); + break; + case DATA_WINDOW: + /* do not move the window, just change its state, + off+count+delta=inv */ + win->stat = DATA_WINDOW; + win->off = win->off + win->count; + win->count = win->delta; + win->delta = 0; + break; + default: + impossible("edward-282", "wrong next window state"); + } + break; + default: + impossible("edward-283", "wrong current window state"); + } + assert("edward-1068", cluster_ok(clust, inode)); +} + +static int update_sd_cryptcompress(struct inode *inode) +{ + int result = 0; + + assert("edward-978", schedulable()); + assert("edward-1265", get_current_context()->grabbed_blocks == 0); + + result = reiser4_grab_space_force( /* one for stat data update */ + estimate_update_common(inode), + BA_CAN_COMMIT); + assert("edward-979", !result); + if (result) + return result; + inode->i_ctime = inode->i_mtime = CURRENT_TIME; + result = reiser4_update_sd(inode); + + all_grabbed2free(); + return result; +} + +static void uncapture_cluster_jnode(jnode * node) +{ + txn_atom *atom; + + assert("edward-1023", spin_jnode_is_locked(node)); + + /*jnode_make_clean(node); */ + atom = jnode_get_atom(node); + if (atom == NULL) { + assert("jmacd-7111", !jnode_is_dirty(node)); + UNLOCK_JNODE(node); + return; + } + + uncapture_block(node); + UNLOCK_ATOM(atom); + jput(node); +} + +void forget_cluster_pages(struct page **pages, int nr) +{ + int i; + for (i = 0; i < nr; i++) { + + assert("edward-1045", pages[i] != NULL); + page_cache_release(pages[i]); + } +} + +/* Prepare input stream for transform operations. + Try to do it in one step. Return -E_REPEAT when it is + impossible because of races with concurrent processes. +*/ +int +flush_cluster_pages(reiser4_cluster_t * clust, jnode * node, + struct inode *inode) +{ + int result = 0; + int i; + int nr_pages = 0; + tfm_cluster_t *tc = &clust->tc; + + assert("edward-980", node != NULL); + assert("edward-236", inode != NULL); + assert("edward-237", clust != NULL); + assert("edward-240", !clust->win); + assert("edward-241", schedulable()); + assert("edward-718", crc_inode_ok(inode)); + + LOCK_JNODE(node); + + if (!jnode_is_dirty(node)) { + + assert("edward-981", node->page_count == 0); + warning("edward-982", "flush_cluster_pages: jnode is not dirty " + "clust %lu, inode %llu\n", + clust->index, (unsigned long long)get_inode_oid(inode)); + + /* race with another flush */ + UNLOCK_JNODE(node); + return RETERR(-E_REPEAT); + } + tc->len = fsize_to_count(clust, inode); + clust->nr_pages = count_to_nrpages(tc->len); + + assert("edward-983", clust->nr_pages == node->page_count + 1); +#if REISER4_DEBUG + node->page_count = 0; +#endif + cluster_reserved2grabbed(estimate_insert_cluster(inode, 0)); + uncapture_cluster_jnode(node); + + /* Try to create input stream for the found size (tc->len). + Starting from this point the page cluster can be modified + (truncated, appended) by concurrent processes, so we need + to worry if the constructed stream is valid */ + + assert("edward-1224", schedulable()); + + result = grab_tfm_stream(inode, tc, TFM_WRITE, INPUT_STREAM); + if (result) + return result; + + nr_pages = + find_get_pages(inode->i_mapping, clust_to_pg(clust->index, inode), + clust->nr_pages, clust->pages); + + if (nr_pages != clust->nr_pages) { + /* the page cluster get truncated, try again */ + assert("edward-1280", nr_pages < clust->nr_pages); + warning("edward-1281", "Page cluster of index %lu (inode %llu)" + " get truncated from %u to %u pages\n", + clust->index, + (unsigned long long)get_inode_oid(inode), + clust->nr_pages, nr_pages); + forget_cluster_pages(clust->pages, nr_pages); + return RETERR(-E_REPEAT); + } + for (i = 0; i < clust->nr_pages; i++) { + char *data; + + assert("edward-242", clust->pages[i] != NULL); + + if (clust->pages[i]->index != + clust_to_pg(clust->index, inode) + i) { + /* holes in the indices of found group of pages: + page cluster get truncated, transform impossible */ + warning("edward-1282", + "Hole in the indices: " + "Page %d in the cluster of index %lu " + "(inode %llu) has index %lu\n", + i, clust->index, + (unsigned long long)get_inode_oid(inode), + clust->pages[i]->index); + + forget_cluster_pages(clust->pages, nr_pages); + result = RETERR(-E_REPEAT); + goto finish; + } + if (!PageUptodate(clust->pages[i])) { + /* page cluster get truncated, transform impossible */ + assert("edward-1283", !PageDirty(clust->pages[i])); + warning("edward-1284", + "Page of index %lu (inode %llu) " + "is not uptodate\n", clust->pages[i]->index, + (unsigned long long)get_inode_oid(inode)); + + forget_cluster_pages(clust->pages, nr_pages); + result = RETERR(-E_REPEAT); + goto finish; + } + /* ok with this page, flush it to the input stream */ + lock_page(clust->pages[i]); + data = kmap(clust->pages[i]); + + assert("edward-986", off_to_pgcount(tc->len, i) != 0); + + memcpy(tfm_stream_data(tc, INPUT_STREAM) + pg_to_off(i), + data, off_to_pgcount(tc->len, i)); + kunmap(clust->pages[i]); + unlock_page(clust->pages[i]); + } + /* input stream is ready for transform */ + + clear_cluster_pages_dirty(clust); + finish: + release_cluster_pages_capture(clust); + return result; +} + +/* set hint for the cluster of the index @index */ +void +set_hint_cluster(struct inode *inode, hint_t * hint, + cloff_t index, znode_lock_mode mode) +{ + reiser4_key key; + assert("edward-722", crc_inode_ok(inode)); + assert("edward-723", + inode_file_plugin(inode) == + file_plugin_by_id(CRC_FILE_PLUGIN_ID)); + + inode_file_plugin(inode)->key_by_inode(inode, + clust_to_off(index, inode), + &key); + + seal_init(&hint->seal, &hint->ext_coord.coord, &key); + hint->offset = get_key_offset(&key); + hint->mode = mode; +} + +void invalidate_hint_cluster(reiser4_cluster_t * clust) +{ + assert("edward-1291", clust != NULL); + assert("edward-1292", clust->hint != NULL); + + done_lh(&clust->hint->lh); + clust->hint->ext_coord.valid = 0; +} + +static void +put_hint_cluster(reiser4_cluster_t * clust, struct inode *inode, + znode_lock_mode mode) +{ + assert("edward-1286", clust != NULL); + assert("edward-1287", clust->hint != NULL); + + set_hint_cluster(inode, clust->hint, clust->index + 1, mode); + invalidate_hint_cluster(clust); +} + +static int +balance_dirty_page_cluster(reiser4_cluster_t * clust, struct inode *inode, + loff_t off, loff_t to_file) +{ + int result; + + assert("edward-724", inode != NULL); + assert("edward-725", crc_inode_ok(inode)); + assert("edward-1272", get_current_context()->grabbed_blocks == 0); + + /* set next window params */ + update_cluster(inode, clust, off, to_file); + + result = update_sd_cryptcompress(inode); + assert("edward-988", !result); + if (result) + return result; + assert("edward-726", clust->hint->lh.owner == NULL); + + reiser4_throttle_write(inode); + all_grabbed2free(); + return 0; +} + +/* set zeroes to the cluster, update it, and maybe, try to capture its pages */ +static int +write_hole(struct inode *inode, reiser4_cluster_t * clust, loff_t file_off, + loff_t to_file) +{ + char *data; + int result = 0; + unsigned cl_off, cl_count = 0; + unsigned to_pg, pg_off; + reiser4_slide_t *win; + + assert("edward-190", clust != NULL); + assert("edward-1069", clust->win != NULL); + assert("edward-191", inode != NULL); + assert("edward-727", crc_inode_ok(inode)); + assert("edward-1171", clust->dstat != INVAL_DISK_CLUSTER); + assert("edward-1154", + ergo(clust->dstat != FAKE_DISK_CLUSTER, clust->reserved == 1)); + + win = clust->win; + + assert("edward-1070", win != NULL); + assert("edward-201", win->stat == HOLE_WINDOW); + assert("edward-192", cluster_ok(clust, inode)); + + if (win->off == 0 && win->count == inode_cluster_size(inode)) { + /* the hole will be represented by fake disk cluster */ + update_cluster(inode, clust, file_off, to_file); + return 0; + } + cl_count = win->count; /* number of zeroes to write */ + cl_off = win->off; + pg_off = off_to_pgoff(win->off); + + while (cl_count) { + struct page *page; + page = clust->pages[off_to_pg(cl_off)]; + + assert("edward-284", page != NULL); + + to_pg = min_count(PAGE_CACHE_SIZE - pg_off, cl_count); + lock_page(page); + data = kmap_atomic(page, KM_USER0); + memset(data + pg_off, 0, to_pg); + flush_dcache_page(page); + kunmap_atomic(data, KM_USER0); + SetPageUptodate(page); + unlock_page(page); + + cl_off += to_pg; + cl_count -= to_pg; + pg_off = 0; + } + if (!win->delta) { + /* only zeroes, try to capture */ + + set_cluster_pages_dirty(clust); + result = try_capture_cluster(clust, inode); + if (result) + return result; + put_hint_cluster(clust, inode, ZNODE_WRITE_LOCK); + result = + balance_dirty_page_cluster(clust, inode, file_off, to_file); + } else + update_cluster(inode, clust, file_off, to_file); + return result; +} + +/* + The main disk search procedure for cryptcompress plugins, which + . scans all items of disk cluster + . maybe reads each one (if @read != 0) + . maybe makes its znode dirty (if @write != 0) + + NOTE-EDWARD: Callers should handle the case when disk cluster + is incomplete (-EIO) +*/ +int +find_cluster(reiser4_cluster_t * clust, + struct inode *inode, int read, int write) +{ + flow_t f; + hint_t *hint; + int result; + unsigned long cl_idx; + ra_info_t ra_info; + file_plugin *fplug; + item_plugin *iplug; + tfm_cluster_t *tc; + +#if REISER4_DEBUG + reiser4_context *ctx; + ctx = get_current_context(); +#endif + assert("edward-138", clust != NULL); + assert("edward-728", clust->hint != NULL); + assert("edward-225", read || write); + assert("edward-226", schedulable()); + assert("edward-137", inode != NULL); + assert("edward-729", crc_inode_ok(inode)); + assert("edward-474", get_current_context()->grabbed_blocks == 0); + + hint = clust->hint; + cl_idx = clust->index; + fplug = inode_file_plugin(inode); + + tc = &clust->tc; + + assert("edward-462", !tfm_cluster_is_uptodate(tc)); + assert("edward-461", ergo(read, tfm_stream_is_set(tc, INPUT_STREAM))); + + /* set key of the first disk cluster item */ + fplug->flow_by_inode(inode, + (read ? (char __user *)tfm_stream_data(tc, INPUT_STREAM) : NULL), + 0 /* kernel space */ , + inode_scaled_cluster_size(inode), + clust_to_off(cl_idx, inode), READ_OP, &f); + if (write) { + /* reserve for flush to make dirty all the leaf nodes + which contain disk cluster */ + result = + reiser4_grab_space_force(estimate_disk_cluster(inode), + BA_CAN_COMMIT); + assert("edward-990", !result); + if (result) + goto out2; + } + + ra_info.key_to_stop = f.key; + set_key_offset(&ra_info.key_to_stop, get_key_offset(max_key())); + + while (f.length) { + result = find_cluster_item(hint, + &f.key, + (write ? ZNODE_WRITE_LOCK : + ZNODE_READ_LOCK), NULL, FIND_EXACT, + (write ? CBK_FOR_INSERT : 0)); + switch (result) { + case CBK_COORD_NOTFOUND: + if (inode_scaled_offset + (inode, + clust_to_off(cl_idx, + inode)) == get_key_offset(&f.key)) { + /* first item not found, this is treated + as disk cluster is absent */ + clust->dstat = FAKE_DISK_CLUSTER; + result = 0; + goto out2; + } + /* we are outside the cluster, stop search here */ + assert("edward-146", + f.length != inode_scaled_cluster_size(inode)); + goto ok; + case CBK_COORD_FOUND: + assert("edward-148", + hint->ext_coord.coord.between == AT_UNIT); + assert("edward-460", + hint->ext_coord.coord.unit_pos == 0); + + coord_clear_iplug(&hint->ext_coord.coord); + result = zload_ra(hint->ext_coord.coord.node, &ra_info); + if (unlikely(result)) + goto out2; + iplug = item_plugin_by_coord(&hint->ext_coord.coord); + assert("edward-147", + item_id_by_coord(&hint->ext_coord.coord) == + CTAIL_ID); + + result = iplug->s.file.read(NULL, &f, hint); + if (result) + goto out; + if (write) { + znode_make_dirty(hint->ext_coord.coord.node); + znode_set_convertible(hint->ext_coord.coord. + node); + } + zrelse(hint->ext_coord.coord.node); + break; + default: + goto out2; + } + } + ok: + /* at least one item was found */ + /* NOTE-EDWARD: Callers should handle the case when disk cluster is incomplete (-EIO) */ + tc->len = inode_scaled_cluster_size(inode) - f.length; + assert("edward-1196", tc->len > 0); + + if (hint_is_unprepped_dclust(clust->hint)) + clust->dstat = UNPR_DISK_CLUSTER; + else + clust->dstat = PREP_DISK_CLUSTER; + all_grabbed2free(); + return 0; + out: + zrelse(hint->ext_coord.coord.node); + out2: + all_grabbed2free(); + return result; +} + +int +get_disk_cluster_locked(reiser4_cluster_t * clust, struct inode *inode, + znode_lock_mode lock_mode) +{ + reiser4_key key; + ra_info_t ra_info; + + assert("edward-730", schedulable()); + assert("edward-731", clust != NULL); + assert("edward-732", inode != NULL); + + if (clust->hint->ext_coord.valid) { + assert("edward-1293", clust->dstat != INVAL_DISK_CLUSTER); + assert("edward-1294", + znode_is_write_locked(clust->hint->lh.node)); + /* already have a valid locked position */ + return (clust->dstat == + FAKE_DISK_CLUSTER ? CBK_COORD_NOTFOUND : + CBK_COORD_FOUND); + } + key_by_inode_cryptcompress(inode, clust_to_off(clust->index, inode), + &key); + ra_info.key_to_stop = key; + set_key_offset(&ra_info.key_to_stop, get_key_offset(max_key())); + + return find_cluster_item(clust->hint, &key, lock_mode, NULL, FIND_EXACT, + CBK_FOR_INSERT); +} + +/* Read needed cluster pages before modifying. + If success, @clust->hint contains locked position in the tree. + Also: + . find and set disk cluster state + . make disk cluster dirty if its state is not FAKE_DISK_CLUSTER. +*/ +static int +read_some_cluster_pages(struct inode *inode, reiser4_cluster_t * clust) +{ + int i; + int result = 0; + item_plugin *iplug; + reiser4_slide_t *win = clust->win; + + iplug = item_plugin_by_id(CTAIL_ID); + + assert("edward-733", get_current_context()->grabbed_blocks == 0); + assert("edward-924", !tfm_cluster_is_uptodate(&clust->tc)); + +#if REISER4_DEBUG + if (clust->nr_pages == 0) { + /* start write hole from fake disk cluster */ + assert("edward-1117", win != NULL); + assert("edward-1118", win->stat == HOLE_WINDOW); + assert("edward-1119", new_cluster(clust, inode)); + } +#endif + if (new_cluster(clust, inode)) { + /* + new page cluster is about to be written, nothing to read, + */ + assert("edward-734", schedulable()); + assert("edward-735", clust->hint->lh.owner == NULL); + + clust->dstat = FAKE_DISK_CLUSTER; + return 0; + } + /* + Here we should search for disk cluster to figure out its real state. + Also there is one more important reason to do disk search: we need + to make disk cluster _dirty_ if it exists + */ + + /* if windows is specified, read the only pages + that will be modified partially */ + + for (i = 0; i < clust->nr_pages; i++) { + struct page *pg = clust->pages[i]; + + lock_page(pg); + if (PageUptodate(pg)) { + unlock_page(pg); + continue; + } + unlock_page(pg); + + if (win && + i >= count_to_nrpages(win->off) && + i < off_to_pg(win->off + win->count + win->delta)) + /* page will be completely overwritten */ + continue; + if (win && (i == clust->nr_pages - 1) && + /* the last page is + partially modified, + not uptodate .. */ + (count_to_nrpages(inode->i_size) <= pg->index)) { + /* .. and appended, + so set zeroes to the rest */ + char *data; + int offset; + lock_page(pg); + data = kmap_atomic(pg, KM_USER0); + + assert("edward-1260", + count_to_nrpages(win->off + win->count + + win->delta) - 1 == i); + + offset = + off_to_pgoff(win->off + win->count + win->delta); + memset(data + offset, 0, PAGE_CACHE_SIZE - offset); + flush_dcache_page(pg); + kunmap_atomic(data, KM_USER0); + unlock_page(pg); + /* still not uptodate */ + break; + } + if (!tfm_cluster_is_uptodate(&clust->tc)) { + result = + ctail_read_cluster(clust, inode, 1 /* write */ ); + assert("edward-992", !result); + if (result) + goto out; + assert("edward-925", + tfm_cluster_is_uptodate(&clust->tc)); + } + lock_page(pg); + result = do_readpage_ctail(clust, pg); + unlock_page(pg); + assert("edward-993", !result); + if (result) { + impossible("edward-219", + "do_readpage_ctail returned crap"); + goto out; + } + } + if (!tfm_cluster_is_uptodate(&clust->tc)) { + /* disk cluster unclaimed, but we need to make its znodes dirty + to make flush update convert its content */ + result = + find_cluster(clust, inode, 0 /* do not read */ , + 1 /*write */ ); + assert("edward-994", !cbk_errored(result)); + if (!cbk_errored(result)) + result = 0; + } + out: + tfm_cluster_clr_uptodate(&clust->tc); + return result; +} + +static int +should_create_unprepped_cluster(reiser4_cluster_t * clust, struct inode *inode) +{ + assert("edward-737", clust != NULL); + + switch (clust->dstat) { + case PREP_DISK_CLUSTER: + case UNPR_DISK_CLUSTER: + return 0; + case FAKE_DISK_CLUSTER: + if (clust->win && + clust->win->stat == HOLE_WINDOW && clust->nr_pages == 0) { + assert("edward-1172", new_cluster(clust, inode)); + return 0; + } + return 1; + default: + impossible("edward-1173", "bad disk cluster state"); + return 0; + } +} + +static int +crc_make_unprepped_cluster(reiser4_cluster_t * clust, struct inode *inode) +{ + int result; + + assert("edward-1123", schedulable()); + assert("edward-737", clust != NULL); + assert("edward-738", inode != NULL); + assert("edward-739", crc_inode_ok(inode)); + assert("edward-1053", clust->hint != NULL); + assert("edward-1266", get_current_context()->grabbed_blocks == 0); + + if (clust->reserved) { + cluster_reserved2grabbed(estimate_insert_cluster(inode, 1)); +#if REISER4_DEBUG + assert("edward-1267", + clust->reserved_unprepped == + estimate_insert_cluster(inode, 1)); + clust->reserved_unprepped -= estimate_insert_cluster(inode, 1); +#endif + } + if (!should_create_unprepped_cluster(clust, inode)) { + all_grabbed2free(); + return 0; + } else { + assert("edward-1268", clust->reserved == 1); + } + result = ctail_insert_unprepped_cluster(clust, inode); + all_grabbed2free(); + if (result) + return result; + + assert("edward-743", crc_inode_ok(inode)); + assert("edward-1269", get_current_context()->grabbed_blocks == 0); + assert("edward-744", znode_is_write_locked(clust->hint->lh.node)); + + clust->dstat = UNPR_DISK_CLUSTER; + return 0; +} + +#if REISER4_DEBUG +static int jnode_truncate_ok(struct inode *inode, cloff_t index) +{ + jnode *node; + node = + jlookup(current_tree, get_inode_oid(inode), + clust_to_pg(index, inode)); + if (node) { + warning("edward-1315", "jnode %p is untruncated\n", node); + jput(node); + } + return (node == NULL); +} + +static int jnodes_truncate_ok(struct inode *inode, cloff_t start) +{ + int result; + jnode *node; + reiser4_inode *info = reiser4_inode_data(inode); + reiser4_tree *tree = tree_by_inode(inode); + + RLOCK_TREE(tree); + + result = + radix_tree_gang_lookup(jnode_tree_by_reiser4_inode(info), + (void **)&node, clust_to_pg(start, inode), + 1); + RUNLOCK_TREE(tree); + if (result) + warning("edward-1332", "Untruncated jnode %p\n", node); + return !result; +} + +#endif + +/* Collect unlocked cluster pages and jnode (the last is in the + case when the page cluster will be modified and captured) */ +int +prepare_page_cluster(struct inode *inode, reiser4_cluster_t * clust, + int capture) +{ + assert("edward-177", inode != NULL); + assert("edward-741", crc_inode_ok(inode)); + assert("edward-740", clust->pages != NULL); + + set_cluster_nrpages(clust, inode); + reset_cluster_pgset(clust, cluster_nrpages(inode)); + return (capture ? + grab_cluster_pages_jnode(inode, clust) : + grab_cluster_pages(inode, clust)); +} + +/* Truncate all the pages and jnode bound with the cluster of index @index */ +void truncate_page_cluster(struct inode *inode, cloff_t index) +{ + int i; + int found = 0; + int nr_pages; + jnode *node; + struct page *pages[MAX_CLUSTER_NRPAGES]; + + node = + jlookup(current_tree, get_inode_oid(inode), + clust_to_pg(index, inode)); + /* jnode is absent, just drop pages which can not + acquire jnode because of exclusive access */ + if (!node) { + truncate_inode_pages_range(inode->i_mapping, + clust_to_off(index, inode), + clust_to_off(index, + inode) + + inode_cluster_size(inode) - 1); + return; + } + /* jnode is present and may be dirty, if so, put + all the cluster pages except the first one */ + nr_pages = count_to_nrpages(off_to_count(inode->i_size, index, inode)); + + found = find_get_pages(inode->i_mapping, clust_to_pg(index, inode), + nr_pages, pages); + + LOCK_JNODE(node); + if (jnode_is_dirty(node)) { + /* jnode is dirty => space for disk cluster + conversion grabbed */ + cluster_reserved2grabbed(estimate_insert_cluster(inode, 0)); + grabbed2free(get_current_context(), + get_current_super_private(), + estimate_insert_cluster(inode, 0)); + + assert("edward-1198", found == nr_pages); + /* This will clear dirty bit so concurrent flush + won't start to convert the disk cluster */ + assert("edward-1199", PageUptodate(pages[0])); + uncapture_cluster_jnode(node); + + for (i = 1; i < nr_pages; i++) { + assert("edward-1200", PageUptodate(pages[i])); + + page_cache_release(pages[i]); + } + } else + UNLOCK_JNODE(node); + /* now drop pages and jnode */ + /* FIXME-EDWARD: Use truncate_complete_page in the loop above instead */ + + jput(node); + forget_cluster_pages(pages, found); + truncate_inode_pages_range(inode->i_mapping, + clust_to_off(index, inode), + clust_to_off(index, + inode) + + inode_cluster_size(inode) - 1); + assert("edward-1201", jnode_truncate_ok(inode, index)); + return; +} + +/* Prepare cluster handle before write and(or) capture. This function + is called by all the clients which modify page cluster and(or) put + it into a transaction (file_write, truncate, writepages, etc..) + + . grab cluster pages; + . reserve disk space; + . maybe read pages from disk and set the disk cluster dirty; + . maybe write hole; + . maybe create 'unprepped' disk cluster if the last one is fake + (isn't represenred by any items on disk) +*/ + +static int +prepare_cluster(struct inode *inode, + loff_t file_off /* write position in the file */ , + loff_t to_file, /* bytes of users data to write to the file */ + reiser4_cluster_t * clust, page_cluster_op op) +{ + int result = 0; + reiser4_slide_t *win = clust->win; + + assert("edward-1273", get_current_context()->grabbed_blocks == 0); + reset_cluster_params(clust); +#if REISER4_DEBUG + clust->ctx = get_current_context(); +#endif + assert("edward-1190", op != PCL_UNKNOWN); + + clust->op = op; + + result = prepare_page_cluster(inode, clust, 1); + if (result) + return result; + result = reserve4cluster(inode, clust); + if (result) + goto err1; + result = read_some_cluster_pages(inode, clust); + if (result) { + free_reserved4cluster(inode, + clust, + estimate_insert_cluster(inode, 0) + + estimate_insert_cluster(inode, 1)); + goto err1; + } + assert("edward-1124", clust->dstat != INVAL_DISK_CLUSTER); + + result = crc_make_unprepped_cluster(clust, inode); + if (result) + goto err2; + if (win && win->stat == HOLE_WINDOW) { + result = write_hole(inode, clust, file_off, to_file); + if (result) + goto err2; + } + return 0; + err2: + free_reserved4cluster(inode, clust, estimate_insert_cluster(inode, 0)); + err1: + page_cache_release(clust->pages[0]); + release_cluster_pages_and_jnode(clust); + assert("edward-1125", 0); + return result; +} + +/* set window by two offsets */ +static void +set_window(reiser4_cluster_t * clust, reiser4_slide_t * win, + struct inode *inode, loff_t o1, loff_t o2) +{ + assert("edward-295", clust != NULL); + assert("edward-296", inode != NULL); + assert("edward-1071", win != NULL); + assert("edward-297", o1 <= o2); + + clust->index = off_to_clust(o1, inode); + + win->off = off_to_cloff(o1, inode); + win->count = min_count(inode_cluster_size(inode) - win->off, o2 - o1); + win->delta = 0; + + clust->win = win; +} + +static int +set_cluster_params(struct inode *inode, reiser4_cluster_t * clust, + reiser4_slide_t * win, flow_t * f, loff_t file_off) +{ + int result; + + assert("edward-197", clust != NULL); + assert("edward-1072", win != NULL); + assert("edward-198", inode != NULL); + + result = alloc_cluster_pgset(clust, cluster_nrpages(inode)); + if (result) + return result; + + if (file_off > inode->i_size) { + /* Uhmm, hole in crypto-file... */ + loff_t hole_size; + hole_size = file_off - inode->i_size; + + set_window(clust, win, inode, inode->i_size, file_off); + win->stat = HOLE_WINDOW; + if (win->off + hole_size < inode_cluster_size(inode)) + /* there is also user's data to append to the hole */ + win->delta = + min_count(inode_cluster_size(inode) - + (win->off + win->count), f->length); + return 0; + } + set_window(clust, win, inode, file_off, file_off + f->length); + win->stat = DATA_WINDOW; + return 0; +} + +/* reset all the params that not get updated */ +void reset_cluster_params(reiser4_cluster_t * clust) +{ + assert("edward-197", clust != NULL); + + clust->dstat = INVAL_DISK_CLUSTER; + clust->tc.uptodate = 0; + clust->tc.len = 0; +} + +/* Main write procedure for cryptcompress objects, + this slices user's data into clusters and copies to page cache. + If @buf != NULL, returns number of bytes in successfully written clusters, + otherwise returns error */ +/* FIXME_EDWARD replace flow by something lightweigth */ + +static loff_t +write_cryptcompress_flow(struct file *file, struct inode *inode, + const char __user *buf, size_t count, loff_t pos) +{ + int i; + flow_t f; + hint_t *hint; + int result = 0; + size_t to_write = 0; + loff_t file_off; + reiser4_slide_t win; + reiser4_cluster_t clust; + + assert("edward-161", schedulable()); + assert("edward-748", crc_inode_ok(inode)); + assert("edward-159", current_blocksize == PAGE_CACHE_SIZE); + assert("edward-1274", get_current_context()->grabbed_blocks == 0); + + result = check_cryptcompress(inode); + if (result) + return result; + hint = kmalloc(sizeof(*hint), GFP_KERNEL); + if (hint == NULL) + return RETERR(-ENOMEM); + + result = load_file_hint(file, hint); + if (result) { + kfree(hint); + return result; + } + + result = + flow_by_inode_cryptcompress(inode, buf, 1 /* user space */ , + count, pos, WRITE_OP, &f); + if (result) + goto out; + to_write = f.length; + + /* current write position in file */ + file_off = pos; + reiser4_slide_init(&win); + reiser4_cluster_init(&clust, &win); + clust.hint = hint; + + result = set_cluster_params(inode, &clust, &win, &f, file_off); + if (result) + goto out; + + if (next_window_stat(&win) == HOLE_WINDOW) { + result = + prepare_cluster(inode, file_off, f.length, &clust, + PCL_APPEND); + if (result) + goto out; + } + do { + char *src; + unsigned page_off, page_count; + + assert("edward-750", schedulable()); + + result = + prepare_cluster(inode, file_off, f.length, &clust, + PCL_APPEND); + if (result) + goto out; + + assert("edward-751", crc_inode_ok(inode)); + assert("edward-204", win.stat == DATA_WINDOW); + assert("edward-1288", clust.hint->ext_coord.valid); + assert("edward-752", + znode_is_write_locked(hint->ext_coord.coord.node)); + + put_hint_cluster(&clust, inode, ZNODE_WRITE_LOCK); + + /* set write position in page */ + page_off = off_to_pgoff(win.off); + + /* copy user's data to cluster pages */ + for (i = off_to_pg(win.off), src = f.data; + i < count_to_nrpages(win.off + win.count); + i++, src += page_count) { + page_count = + off_to_pgcount(win.off + win.count, i) - page_off; + + assert("edward-1039", + page_off + page_count <= PAGE_CACHE_SIZE); + assert("edward-287", clust.pages[i] != NULL); + + lock_page(clust.pages[i]); + result = + __copy_from_user((char *)kmap(clust.pages[i]) + + page_off, (char __user *)src, page_count); + kunmap(clust.pages[i]); + if (unlikely(result)) { + unlock_page(clust.pages[i]); + result = -EFAULT; + goto err3; + } + SetPageUptodate(clust.pages[i]); + unlock_page(clust.pages[i]); + page_off = 0; + } + assert("edward-753", crc_inode_ok(inode)); + + set_cluster_pages_dirty(&clust); + + result = try_capture_cluster(&clust, inode); + if (result) + goto err2; + + assert("edward-998", f.user == 1); + + move_flow_forward(&f, win.count); + + /* disk cluster may be already clean at this point */ + + /* . update cluster + . set hint for new offset + . unlock znode + . update inode + . balance dirty pages + */ + result = balance_dirty_page_cluster(&clust, inode, 0, f.length); + if (result) + goto err1; + assert("edward-755", hint->lh.owner == NULL); + reset_cluster_params(&clust); + continue; + err3: + page_cache_release(clust.pages[0]); + err2: + release_cluster_pages_and_jnode(&clust); + err1: + if (clust.reserved) + free_reserved4cluster(inode, + &clust, + estimate_insert_cluster(inode, + 0)); + break; + } while (f.length); + out: + done_lh(&hint->lh); + if (result == -EEXIST) + printk("write returns EEXIST!\n"); + + put_cluster_handle(&clust, TFM_READ); + save_file_hint(file, hint); + kfree(hint); + if (buf) { + /* if nothing were written - there must be an error */ + assert("edward-195", ergo((to_write == f.length), result < 0)); + return (to_write - f.length) ? (to_write - f.length) : result; + } + return result; +} + +static ssize_t write_crc_file(struct file *file, /* file to write to */ + struct inode *inode, /* inode */ + const char __user *buf, /* address of user-space buffer */ + size_t count, /* number of bytes to write */ + loff_t * off /* position to write which */ ) +{ + + int result; + loff_t pos; + ssize_t written; + cryptcompress_info_t *info = cryptcompress_inode_data(inode); + + assert("edward-196", crc_inode_ok(inode)); + + result = generic_write_checks(file, off, &count, 0); + if (unlikely(result != 0)) + return result; + + if (unlikely(count == 0)) + return 0; + + /* FIXME-EDWARD: other UNIX features */ + + down_write(&info->lock); + LOCK_CNT_INC(inode_sem_w); + + pos = *off; + written = + write_cryptcompress_flow(file, inode, buf, count, pos); + if (written < 0) { + if (written == -EEXIST) + printk("write_crc_file returns EEXIST!\n"); + return written; + } + + /* update position in a file */ + *off = pos + written; + + up_write(&info->lock); + LOCK_CNT_DEC(inode_sem_w); + + /* return number of written bytes */ + return written; +} + +/** + * write_cryptcompress - write of struct file_operations + * @file: file to write to + * @buf: address of user-space buffer + * @read_amount: number of bytes to write + * @off: position in file to write to + * + * This is implementation of vfs's write method of struct file_operations for + * cryptcompress plugin. + */ +ssize_t write_cryptcompress(struct file *file, const char __user *buf, + size_t count, loff_t *off) +{ + ssize_t result; + struct inode *inode; + + inode = file->f_dentry->d_inode; + + down(&inode->i_sem); + + result = write_crc_file(file, inode, buf, count, off); + + up(&inode->i_sem); + return result; +} + +static void +readpages_crc(struct address_space *mapping, struct list_head *pages, + void *data) +{ + file_plugin *fplug; + item_plugin *iplug; + + assert("edward-1112", mapping != NULL); + assert("edward-1113", mapping->host != NULL); + + fplug = inode_file_plugin(mapping->host); + assert("edward-1114", fplug == file_plugin_by_id(CRC_FILE_PLUGIN_ID)); + iplug = item_plugin_by_id(CTAIL_ID); + + iplug->s.file.readpages(data, mapping, pages); + + return; +} + +static reiser4_block_nr cryptcompress_estimate_read(struct inode *inode) +{ + /* reserve one block to update stat data item */ + assert("edward-1193", + inode_file_plugin(inode)->estimate.update == + estimate_update_common); + return estimate_update_common(inode); +} + +/** + * read_cryptcompress - read of struct file_operations + * @file: file to read from + * @buf: address of user-space buffer + * @read_amount: number of bytes to read + * @off: position in file to read from + * + * This is implementation of vfs's read method of struct file_operations for + * cryptcompress plugin. + */ +ssize_t read_cryptcompress(struct file * file, char __user *buf, size_t size, + loff_t * off) +{ + ssize_t result; + struct inode *inode; + reiser4_file_fsdata *fsdata; + cryptcompress_info_t *info; + reiser4_block_nr needed; + + inode = file->f_dentry->d_inode; + assert("edward-1194", !inode_get_flag(inode, REISER4_NO_SD)); + + info = cryptcompress_inode_data(inode); + needed = cryptcompress_estimate_read(inode); + /* FIXME-EDWARD: + Grab space for sd_update so find_cluster will be happy */ +#if 0 + result = reiser4_grab_space(needed, BA_CAN_COMMIT); + if (result != 0) + return result; +#endif + fsdata = reiser4_get_file_fsdata(file); + fsdata->ra2.data = file; + fsdata->ra2.readpages = readpages_crc; + + down_read(&info->lock); + LOCK_CNT_INC(inode_sem_r); + + result = generic_file_read(file, buf, size, off); + + up_read(&info->lock); + LOCK_CNT_DEC(inode_sem_r); + + return result; +} + +static void +set_append_cluster_key(const coord_t * coord, reiser4_key * key, + struct inode *inode) +{ + item_key_by_coord(coord, key); + set_key_offset(key, + clust_to_off(clust_by_coord(coord, inode) + 1, inode)); +} + +/* If @index > 0, find real disk cluster of the index (@index - 1), + If @index == 0 find the real disk cluster of the object of maximal index. + Keep incremented index of the result in @found. + It succes was returned: + (@index == 0 && @found == 0) means that the object doesn't have real disk + clusters. + (@index != 0 && @found == 0) means that disk cluster of (@index -1) doesn't + exist. +*/ +static int +find_real_disk_cluster(struct inode *inode, cloff_t * found, cloff_t index) +{ + int result; + reiser4_key key; + loff_t offset; + hint_t *hint; + lock_handle *lh; + lookup_bias bias; + coord_t *coord; + item_plugin *iplug; + file_plugin *fplug = inode_file_plugin(inode); + + assert("edward-1131", fplug == file_plugin_by_id(CRC_FILE_PLUGIN_ID)); + assert("edward-95", crc_inode_ok(inode)); + + hint = kmalloc(sizeof(*hint), GFP_KERNEL); + if (hint == NULL) + return RETERR(-ENOMEM); + hint_init_zero(hint); + lh = &hint->lh; + + bias = (index ? FIND_EXACT : FIND_MAX_NOT_MORE_THAN); + offset = + (index ? clust_to_off(index, inode) - + 1 : get_key_offset(max_key())); + + fplug->key_by_inode(inode, offset, &key); + + /* find the last item of this object */ + result = + find_cluster_item(hint, &key, ZNODE_READ_LOCK, NULL /* ra_info */, + bias, 0); + if (cbk_errored(result)) { + done_lh(lh); + kfree(hint); + return result; + } + if (result == CBK_COORD_NOTFOUND) { + /* no real disk clusters */ + done_lh(lh); + kfree(hint); + *found = 0; + return 0; + } + /* disk cluster is found */ + coord = &hint->ext_coord.coord; + coord_clear_iplug(coord); + result = zload(coord->node); + if (unlikely(result)) { + done_lh(lh); + kfree(hint); + return result; + } + iplug = item_plugin_by_coord(coord); + assert("edward-277", iplug == item_plugin_by_id(CTAIL_ID)); + assert("edward-1202", ctail_ok(coord)); + + set_append_cluster_key(coord, &key, inode); + + *found = off_to_clust(get_key_offset(&key), inode); + + assert("edward-1132", ergo(index, index == *found)); + + zrelse(coord->node); + done_lh(lh); + kfree(hint); + return 0; +} + +static int find_fake_appended(struct inode *inode, cloff_t * index) +{ + return find_real_disk_cluster(inode, index, + 0 /* find last real one */ ); +} + +/* Set left coord when unit is not found after node_lookup() + This takes into account that there can be holes in a sequence + of disk clusters */ + +static void adjust_left_coord(coord_t * left_coord) +{ + switch (left_coord->between) { + case AFTER_UNIT: + left_coord->between = AFTER_ITEM; + case AFTER_ITEM: + case BEFORE_UNIT: + break; + default: + impossible("edward-1204", "bad left coord to cut"); + } + return; +} + +#define CRC_CUT_TREE_MIN_ITERATIONS 64 +int +cut_tree_worker_cryptcompress(tap_t * tap, const reiser4_key * from_key, + const reiser4_key * to_key, + reiser4_key * smallest_removed, + struct inode *object, int truncate, int *progress) +{ + lock_handle next_node_lock; + coord_t left_coord; + int result; + + assert("edward-1158", tap->coord->node != NULL); + assert("edward-1159", znode_is_write_locked(tap->coord->node)); + assert("edward-1160", znode_get_level(tap->coord->node) == LEAF_LEVEL); + + *progress = 0; + init_lh(&next_node_lock); + + while (1) { + znode *node; /* node from which items are cut */ + node_plugin *nplug; /* node plugin for @node */ + + node = tap->coord->node; + + /* Move next_node_lock to the next node on the left. */ + result = + reiser4_get_left_neighbor(&next_node_lock, node, + ZNODE_WRITE_LOCK, + GN_CAN_USE_UPPER_LEVELS); + if (result != 0 && result != -E_NO_NEIGHBOR) + break; + /* FIXME-EDWARD: Check can we delete the node as a whole. */ + result = tap_load(tap); + if (result) + return result; + + /* Prepare the second (right) point for cut_node() */ + if (*progress) + coord_init_last_unit(tap->coord, node); + + else if (item_plugin_by_coord(tap->coord)->b.lookup == NULL) + /* set rightmost unit for the items without lookup method */ + tap->coord->unit_pos = coord_last_unit_pos(tap->coord); + + nplug = node->nplug; + + assert("edward-1161", nplug); + assert("edward-1162", nplug->lookup); + + /* left_coord is leftmost unit cut from @node */ + result = nplug->lookup(node, from_key, FIND_EXACT, &left_coord); + + if (IS_CBKERR(result)) + break; + + if (result == CBK_COORD_NOTFOUND) + adjust_left_coord(&left_coord); + + /* adjust coordinates so that they are set to existing units */ + if (coord_set_to_right(&left_coord) + || coord_set_to_left(tap->coord)) { + result = 0; + break; + } + + if (coord_compare(&left_coord, tap->coord) == + COORD_CMP_ON_RIGHT) { + /* keys from @from_key to @to_key are not in the tree */ + result = 0; + break; + } + + /* cut data from one node */ + *smallest_removed = *min_key(); + result = kill_node_content(&left_coord, + tap->coord, + from_key, + to_key, + smallest_removed, + next_node_lock.node, + object, truncate); +#if REISER4_DEBUG + /*node_check(node, ~0U); */ +#endif + tap_relse(tap); + + if (result) + break; + + ++(*progress); + + /* Check whether all items with keys >= from_key were removed + * from the tree. */ + if (keyle(smallest_removed, from_key)) + /* result = 0; */ + break; + + if (next_node_lock.node == NULL) + break; + + result = tap_move(tap, &next_node_lock); + done_lh(&next_node_lock); + if (result) + break; + + /* Break long cut_tree operation (deletion of a large file) if + * atom requires commit. */ + if (*progress > CRC_CUT_TREE_MIN_ITERATIONS + && current_atom_should_commit()) { + result = -E_REPEAT; + break; + } + } + done_lh(&next_node_lock); + return result; +} + +/* Append or expand hole in two steps (exclusive access should be aquired!) + 1) write zeroes to the current real cluster, + 2) expand hole via fake clusters (just increase i_size) */ +static int +cryptcompress_append_hole(struct inode *inode /*contains old i_size */ , + loff_t new_size) +{ + int result = 0; + hint_t *hint; + lock_handle *lh; + loff_t hole_size; + int nr_zeroes; + reiser4_slide_t win; + reiser4_cluster_t clust; + + assert("edward-1133", inode->i_size < new_size); + assert("edward-1134", schedulable()); + assert("edward-1135", crc_inode_ok(inode)); + assert("edward-1136", current_blocksize == PAGE_CACHE_SIZE); + assert("edward-1333", off_to_cloff(inode->i_size, inode) != 0); + + hint = kmalloc(sizeof(*hint), GFP_KERNEL); + if (hint == NULL) + return RETERR(-ENOMEM); + hint_init_zero(hint); + lh = &hint->lh; + + reiser4_slide_init(&win); + reiser4_cluster_init(&clust, &win); + clust.hint = hint; + + /* set cluster handle */ + result = alloc_cluster_pgset(&clust, cluster_nrpages(inode)); + if (result) + goto out; + hole_size = new_size - inode->i_size; + nr_zeroes = + min_count(inode_cluster_size(inode) - + off_to_cloff(inode->i_size, inode), hole_size); + + set_window(&clust, &win, inode, inode->i_size, + inode->i_size + nr_zeroes); + win.stat = HOLE_WINDOW; + + assert("edward-1137", + clust.index == off_to_clust(inode->i_size, inode)); + + result = prepare_cluster(inode, 0, 0, &clust, PCL_APPEND); + + assert("edward-1271", !result); + if (result) + goto out; + assert("edward-1139", + clust.dstat == PREP_DISK_CLUSTER || + clust.dstat == UNPR_DISK_CLUSTER); + + hole_size -= nr_zeroes; + if (!hole_size) + /* nothing to append anymore */ + goto out; + + /* fake_append: */ + INODE_SET_FIELD(inode, i_size, new_size); + out: + done_lh(lh); + kfree(hint); + put_cluster_handle(&clust, TFM_READ); + return result; +} + +#if REISER4_DEBUG +static int +pages_truncate_ok(struct inode *inode, loff_t old_size, pgoff_t start) +{ + struct pagevec pvec; + int i; + int count; + int rest; + + rest = count_to_nrpages(old_size) - start; + + pagevec_init(&pvec, 0); + count = min_count(pagevec_space(&pvec), rest); + + while (rest) { + count = min_count(pagevec_space(&pvec), rest); + pvec.nr = find_get_pages(inode->i_mapping, start, + count, pvec.pages); + for (i = 0; i < pagevec_count(&pvec); i++) { + if (PageUptodate(pvec.pages[i])) { + warning("edward-1205", + "truncated page of index %lu is uptodate", + pvec.pages[i]->index); + return 0; + } + } + start += count; + rest -= count; + pagevec_release(&pvec); + } + return 1; +} + +static int body_truncate_ok(struct inode *inode, cloff_t aidx) +{ + int result; + cloff_t raidx; + + result = find_fake_appended(inode, &raidx); + return !result && (aidx == raidx); +} +#endif + +static int +update_cryptcompress_size(struct inode *inode, reiser4_key * key, int update_sd) +{ + return (get_key_offset(key) & ((loff_t) (inode_cluster_size(inode)) - 1) + ? 0 : update_file_size(inode, key, update_sd)); +} + +/* prune cryptcompress file in two steps (exclusive access should be acquired!) + 1) cut all disk clusters but the last one partially truncated, + 2) set zeroes and capture last partially truncated page cluster if the last + one exists, otherwise truncate via prune fake cluster (just decrease i_size) +*/ +static int +prune_cryptcompress(struct inode *inode, loff_t new_size, int update_sd, + cloff_t aidx) +{ + int result = 0; + unsigned nr_zeroes; + loff_t to_prune; + loff_t old_size; + cloff_t ridx; + + hint_t *hint; + lock_handle *lh; + reiser4_slide_t win; + reiser4_cluster_t clust; + + assert("edward-1140", inode->i_size >= new_size); + assert("edward-1141", schedulable()); + assert("edward-1142", crc_inode_ok(inode)); + assert("edward-1143", current_blocksize == PAGE_CACHE_SIZE); + + hint = kmalloc(sizeof(*hint), GFP_KERNEL); + if (hint == NULL) + return RETERR(-ENOMEM); + hint_init_zero(hint); + lh = &hint->lh; + + reiser4_slide_init(&win); + reiser4_cluster_init(&clust, &win); + clust.hint = hint; + + /* rightmost completely truncated cluster */ + ridx = count_to_nrclust(new_size, inode); + + assert("edward-1174", ridx <= aidx); + old_size = inode->i_size; + if (ridx != aidx) { + result = cut_file_items(inode, + clust_to_off(ridx, inode), + update_sd, + clust_to_off(aidx, inode), + update_cryptcompress_size); + if (result) + goto out; + } + if (!off_to_cloff(new_size, inode)) { + /* no partially truncated clusters */ + assert("edward-1145", inode->i_size == new_size); + goto finish; + } + assert("edward-1146", new_size < inode->i_size); + + to_prune = inode->i_size - new_size; + + /* check if partially truncated cluster is fake */ + result = find_real_disk_cluster(inode, &aidx, ridx); + if (result) + goto out; + if (!aidx) + /* yup, this is fake one */ + goto finish; + + assert("edward-1148", aidx == ridx); + + /* try to capture partially truncated page cluster */ + result = alloc_cluster_pgset(&clust, cluster_nrpages(inode)); + if (result) + goto out; + nr_zeroes = (off_to_pgoff(new_size) ? + PAGE_CACHE_SIZE - off_to_pgoff(new_size) : 0); + set_window(&clust, &win, inode, new_size, new_size + nr_zeroes); + win.stat = HOLE_WINDOW; + + assert("edward-1149", clust.index == ridx - 1); + + result = prepare_cluster(inode, 0, 0, &clust, PCL_TRUNCATE); + if (result) + goto out; + assert("edward-1151", + clust.dstat == PREP_DISK_CLUSTER || + clust.dstat == UNPR_DISK_CLUSTER); + + assert("edward-1191", inode->i_size == new_size); + assert("edward-1206", body_truncate_ok(inode, ridx)); + finish: + /* drop all the pages that don't have jnodes (i.e. pages + which can not be truncated by cut_file_items() because + of holes represented by fake disk clusters) including + the pages of partially truncated cluster which was + released by prepare_cluster() */ + truncate_inode_pages(inode->i_mapping, new_size); + INODE_SET_FIELD(inode, i_size, new_size); + out: + assert("edward-1334", !result); + assert("edward-1209", + pages_truncate_ok(inode, old_size, count_to_nrpages(new_size))); + assert("edward-1335", + jnodes_truncate_ok(inode, count_to_nrclust(new_size, inode))); + done_lh(lh); + kfree(lh); + put_cluster_handle(&clust, TFM_READ); + return result; +} + +static int +start_truncate_fake(struct inode *inode, cloff_t aidx, loff_t new_size, + int update_sd) +{ + int result = 0; + int bytes; + + if (new_size > inode->i_size) { + /* append */ + if (inode->i_size < clust_to_off(aidx, inode)) + /* no fake bytes */ + return 0; + bytes = new_size - inode->i_size; + INODE_SET_FIELD(inode, i_size, inode->i_size + bytes); + } else { + /* prune */ + if (inode->i_size <= clust_to_off(aidx, inode)) + /* no fake bytes */ + return 0; + bytes = + inode->i_size - max_count(new_size, + clust_to_off(aidx, inode)); + if (!bytes) + return 0; + INODE_SET_FIELD(inode, i_size, inode->i_size - bytes); + /* In the case of fake prune we need to drop page cluster. + There are only 2 cases for partially truncated page: + 1. If is is dirty, therefore it is anonymous + (was dirtied via mmap), and will be captured + later via ->capture(). + 2. If is clean, therefore it is filled by zeroes. + In both cases we don't need to make it dirty and + capture here. + */ + truncate_inode_pages(inode->i_mapping, inode->i_size); + assert("edward-1336", + jnodes_truncate_ok(inode, + count_to_nrclust(inode->i_size, + inode))); + } + if (update_sd) + result = update_sd_cryptcompress(inode); + return result; +} + +/* This is called in setattr_cryptcompress when it is used to truncate, + and in delete_cryptcompress */ +static int cryptcompress_truncate(struct inode *inode, /* old size */ + loff_t new_size, /* new size */ + int update_sd) +{ + int result; + cloff_t aidx; + + result = find_fake_appended(inode, &aidx); + if (result) + return result; + assert("edward-1208", + ergo(aidx > 0, inode->i_size > clust_to_off(aidx - 1, inode))); + + result = start_truncate_fake(inode, aidx, new_size, update_sd); + if (result) + return result; + if (inode->i_size == new_size) + /* nothing to truncate anymore */ + return 0; + return (inode->i_size < new_size ? + cryptcompress_append_hole(inode, new_size) : + prune_cryptcompress(inode, new_size, update_sd, aidx)); +} + +/* page cluser is anonymous if it contains at least one anonymous page */ +static int +capture_anonymous_cluster(reiser4_cluster_t * clust, struct inode *inode) +{ + int result; + + assert("edward-1073", clust != NULL); + assert("edward-1074", inode != NULL); + assert("edward-1075", clust->dstat == INVAL_DISK_CLUSTER); + + result = prepare_cluster(inode, 0, 0, clust, PCL_APPEND); + if (result) + return result; + set_cluster_pages_dirty(clust); + + result = try_capture_cluster(clust, inode); + put_hint_cluster(clust, inode, ZNODE_WRITE_LOCK); + if (result) + release_cluster_pages_and_jnode(clust); + return result; +} + +#define MAX_CLUSTERS_TO_CAPTURE(inode) (1024 >> inode_cluster_shift(inode)) + +/* read lock should be acquired */ +static int +capture_anonymous_clusters(struct address_space *mapping, pgoff_t * index, + int to_capture) +{ + int result = 0; + int found; + int progress = 0; + struct page *page = NULL; + hint_t *hint; + lock_handle *lh; + reiser4_cluster_t clust; + + assert("edward-1127", mapping != NULL); + assert("edward-1128", mapping->host != NULL); + + hint = kmalloc(sizeof(*hint), GFP_KERNEL); + if (hint == NULL) + return RETERR(-ENOMEM); + hint_init_zero(hint); + lh = &hint->lh; + + reiser4_cluster_init(&clust, NULL); + clust.hint = hint; + + result = alloc_cluster_pgset(&clust, cluster_nrpages(mapping->host)); + if (result) + goto out; + + while (to_capture > 0) { + found = + find_get_pages_tag(mapping, index, + PAGECACHE_TAG_REISER4_MOVED, 1, &page); + if (!found) { + *index = (pgoff_t) - 1; + break; + } + assert("edward-1109", page != NULL); + + move_cluster_forward(&clust, mapping->host, page->index, + &progress); + result = capture_anonymous_cluster(&clust, mapping->host); + page_cache_release(page); + if (result) + break; + to_capture--; + } + if (result) { + warning("edward-1077", + "Cannot capture anon pages: result=%i (captured=%d)\n", + result, + ((__u32) MAX_CLUSTERS_TO_CAPTURE(mapping->host)) - + to_capture); + } else { + /* something had to be found */ + assert("edward-1078", + to_capture <= MAX_CLUSTERS_TO_CAPTURE(mapping->host)); + if (to_capture <= 0) + /* there may be left more pages */ + __mark_inode_dirty(mapping->host, I_DIRTY_PAGES); + } + out: + done_lh(lh); + kfree(hint); + put_cluster_handle(&clust, TFM_READ); + return result; +} + +/* Check mapping for existence of not captured dirty pages. + This returns !0 if either page tree contains pages tagged + PAGECACHE_TAG_REISER4_MOVED */ +static int crc_inode_has_anon_pages(struct inode *inode) +{ + return mapping_tagged(inode->i_mapping, PAGECACHE_TAG_REISER4_MOVED); +} + +/* this is implementation of vfs's writepages method of struct + address_space_operations */ +int +writepages_cryptcompress(struct address_space *mapping, + struct writeback_control *wbc) +{ + int result; + int to_capture; + pgoff_t nrpages; + pgoff_t index = 0; + cryptcompress_info_t *info; + struct inode *inode; + + inode = mapping->host; + if (!crc_inode_has_anon_pages(inode)) { + result = 0; + goto end; + } + + info = cryptcompress_inode_data(inode); + nrpages = count_to_nrpages(i_size_read(inode)); + + if (wbc->sync_mode != WB_SYNC_ALL) + to_capture = + min_count(wbc->nr_to_write, MAX_CLUSTERS_TO_CAPTURE(inode)); + else + to_capture = MAX_CLUSTERS_TO_CAPTURE(inode); + do { + reiser4_context *ctx; + + if (is_in_reiser4_context()) { + /* FIXME-EDWARD: REMOVEME */ + all_grabbed2free(); + + /* It can be in the context of write system call from + balance_dirty_pages() */ + if (down_read_trylock(&info->lock) == 0) { + result = RETERR(-EBUSY); + break; + } + } else + down_read(&info->lock); + + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) { + result = PTR_ERR(ctx); + break; + } + ctx->nobalance = 1; + + assert("edward-1079", + lock_stack_isclean(get_current_lock_stack())); + + LOCK_CNT_INC(inode_sem_r); + + result = + capture_anonymous_clusters(inode->i_mapping, &index, + to_capture); + + up_read(&info->lock); + + LOCK_CNT_DEC(inode_sem_r); + + if (result != 0 || wbc->sync_mode != WB_SYNC_ALL) { + reiser4_exit_context(ctx); + break; + } + result = txnmgr_force_commit_all(inode->i_sb, 0); + reiser4_exit_context(ctx); + } while (result == 0 && index < nrpages); + + end: + if (is_in_reiser4_context()) { + if (get_current_context()->nr_captured >= CAPTURE_APAGE_BURST) { + /* there are already pages to flush, flush them out, do + not delay until end of reiser4_sync_inodes */ + writeout(inode->i_sb, wbc); + get_current_context()->nr_captured = 0; + } + } + return result; +} + +/* plugin->u.file.mmap */ +int mmap_cryptcompress(struct file *file, struct vm_area_struct *vma) +{ + return -ENOSYS; + //return generic_file_mmap(file, vma); +} + +/* plugin->u.file.release */ +/* plugin->u.file.get_block */ + +/* implentation of vfs' bmap method of struct address_space_operations for + cryptcompress plugin +*/ +sector_t bmap_cryptcompress(struct address_space * mapping, sector_t lblock) +{ + struct inode *inode; + sector_t block; + + inode = mapping->host; + if (current_blocksize != inode_cluster_size(inode)) + return RETERR(-EINVAL); + else { + int result; + reiser4_key key; + hint_t *hint; + lock_handle *lh; + item_plugin *iplug; + + assert("edward-1166", 0); + key_by_inode_cryptcompress(inode, + (loff_t) block * current_blocksize, + &key); + + hint = kmalloc(sizeof(*hint), GFP_KERNEL); + if (IS_ERR(hint)) + return RETERR(-ENOMEM); + hint_init_zero(hint); + lh = &hint->lh; + result = + find_cluster_item(hint, &key, ZNODE_READ_LOCK, NULL, + FIND_EXACT, 0); + if (result != CBK_COORD_FOUND) { + done_lh(lh); + kfree(hint); + return result; + } + result = zload(hint->ext_coord.coord.node); + if (unlikely(result)) { + done_lh(lh); + kfree(hint); + return result; + } + iplug = item_plugin_by_coord(&hint->ext_coord.coord); + + assert("edward-421", iplug == item_plugin_by_id(CTAIL_ID)); + + if (iplug->s.file.get_block) { + result = + iplug->s.file.get_block(&hint->ext_coord.coord, + lblock, &block); + if (result == 0) + result = block; + } else + result = RETERR(-EINVAL); + + zrelse(hint->ext_coord.coord.node); + done_lh(lh); + kfree(hint); + return result; + } +} + +/* this is implementation of delete method of file plugin for cryptcompress + */ +int delete_cryptcompress(struct inode *inode) +{ + int result; + + assert("edward-429", inode->i_nlink == 0); + + if (inode->i_size) { + result = cryptcompress_truncate(inode, 0, 0); + if (result) { + warning("edward-430", + "cannot truncate cryptcompress file %lli: %i", + (unsigned long long)get_inode_oid(inode), + result); + return result; + } + } + /* and remove stat data */ + return delete_object_common(inode); +} + +/* plugin->u.file.setattr method + see plugin.h for description */ +int setattr_cryptcompress(struct dentry *dentry, /* Object to change attributes */ + struct iattr *attr /* change description */ ) +{ + int result; + struct inode *inode; + + inode = dentry->d_inode; + result = check_cryptcompress(inode); + if (result) + return result; + if (attr->ia_valid & ATTR_SIZE) { + /* EDWARD-FIXME-HANS: VS-FIXME-HANS: + Q: this case occurs when? truncate? + A: yes + + Q: If so, why isn't this code in truncate itself instead of here? + + A: because vfs calls fs's truncate after it has called truncate_inode_pages to get rid of pages + corresponding to part of file being truncated. In reiser4 it may cause existence of unallocated + extents which do not have jnodes. Flush code does not expect that. Solution of this problem is + straightforward. As vfs's truncate is implemented using setattr operation (common implementaion of + which calls truncate_inode_pages and fs's truncate in case when size of file changes) - it seems + reasonable to have reiser4_setattr which will take care of removing pages, jnodes and extents + simultaneously in case of truncate. + Q: do you think implementing truncate using setattr is ugly, + and vfs needs improving, or is there some sense in which this is a good design? + + A: VS-FIXME-HANS: + */ + + /* truncate does reservation itself and requires exclusive access obtained */ + if (inode->i_size != attr->ia_size) { + loff_t old_size; + cryptcompress_info_t *info = + cryptcompress_inode_data(inode); + + down_write(&info->lock); + LOCK_CNT_INC(inode_sem_w); + + inode_check_scale(inode, inode->i_size, attr->ia_size); + + old_size = inode->i_size; + + result = + cryptcompress_truncate(inode, attr->ia_size, + 1 /* update stat data */ ); + if (result) { + warning("edward-1192", + "truncate_cryptcompress failed: oid %lli, " + "old size %lld, new size %lld, retval %d", + (unsigned long long) + get_inode_oid(inode), old_size, + attr->ia_size, result); + } + up_write(&info->lock); + LOCK_CNT_DEC(inode_sem_w); + } else + result = 0; + } else + result = setattr_common(dentry, attr); + return result; +} + +static int +save_len_cryptcompress_plugin(struct inode *inode, reiser4_plugin * plugin) +{ + assert("edward-457", inode != NULL); + assert("edward-458", plugin != NULL); + assert("edward-459", plugin->h.id == CRC_FILE_PLUGIN_ID); + return 0; +} + +static int +load_cryptcompress_plugin(struct inode *inode, reiser4_plugin * plugin, + char **area, int *len) +{ + assert("edward-455", inode != NULL); + assert("edward-456", (reiser4_inode_data(inode)->pset != NULL)); + + plugin_set_file(&reiser4_inode_data(inode)->pset, + file_plugin_by_id(CRC_FILE_PLUGIN_ID)); + return 0; +} + +static int change_crypto_file(struct inode *inode, reiser4_plugin * plugin) +{ + /* cannot change object plugin of already existing object */ + return RETERR(-EINVAL); +} + +struct reiser4_plugin_ops cryptcompress_plugin_ops = { + .load = load_cryptcompress_plugin, + .save_len = save_len_cryptcompress_plugin, + .save = NULL, + .alignment = 8, + .change = change_crypto_file +}; + +/* + Local variables: + c-indentation-style: "K&R" + mode-name: "LC" + c-basic-offset: 8 + tab-width: 8 + fill-column: 120 + scroll-step: 1 + End: +*/ diff -puN /dev/null fs/reiser4/plugin/file/cryptcompress.h --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/file/cryptcompress.h 2005-09-15 19:51:08.000000000 -0700 @@ -0,0 +1,481 @@ +/* Copyright 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */ +/* See http://www.namesys.com/cryptcompress_design.html */ + +#if !defined( __FS_REISER4_CRYPTCOMPRESS_H__ ) +#define __FS_REISER4_CRYPTCOMPRESS_H__ + +#include "../compress/compress.h" + +#include +#include +#include + +#define MIN_CLUSTER_SIZE PAGE_CACHE_SIZE +#define MIN_CLUSTER_SHIFT PAGE_CACHE_SHIFT +#define MAX_CLUSTER_SHIFT 16 +#define MAX_CLUSTER_NRPAGES (1U << MAX_CLUSTER_SHIFT >> PAGE_CACHE_SHIFT) +#define DEFAULT_CLUSTER_SHIFT 0 +#define DC_CHECKSUM_SIZE 4 +#define MIN_CRYPTO_BLOCKSIZE 8 + +#if REISER4_DEBUG +static inline int cluster_shift_ok(int shift) +{ + return (shift >= MIN_CLUSTER_SHIFT) && (shift <= MAX_CLUSTER_SHIFT); +} +#endif + +/* Set of transform id's supported by reiser4, + each transform is implemented by appropriate transform plugin: */ +typedef enum { + CRYPTO_TFM, /* crypto plugin */ + DIGEST_TFM, /* digest plugin */ + COMPRESS_TFM, /* compression plugin */ + LAST_TFM +} reiser4_tfm; + +typedef struct tfm_stream { + __u8 *data; + size_t size; +} tfm_stream_t; + +typedef enum { + INPUT_STREAM, + OUTPUT_STREAM, + LAST_STREAM +} tfm_stream_id; + +typedef tfm_stream_t *tfm_unit[LAST_STREAM]; + +static inline __u8 *ts_data(tfm_stream_t * stm) +{ + assert("edward-928", stm != NULL); + return stm->data; +} + +static inline size_t ts_size(tfm_stream_t * stm) +{ + assert("edward-929", stm != NULL); + return stm->size; +} + +static inline void set_ts_size(tfm_stream_t * stm, size_t size) +{ + assert("edward-930", stm != NULL); + + stm->size = size; +} + +static inline int alloc_ts(tfm_stream_t ** stm) +{ + assert("edward-931", stm); + assert("edward-932", *stm == NULL); + + *stm = kmalloc(sizeof **stm, GFP_KERNEL); + if (*stm == NULL) + return -ENOMEM; + memset(*stm, 0, sizeof **stm); + return 0; +} + +static inline void free_ts(tfm_stream_t * stm) +{ + assert("edward-933", !ts_data(stm)); + assert("edward-934", !ts_size(stm)); + + kfree(stm); +} + +static inline int alloc_ts_data(tfm_stream_t * stm, size_t size) +{ + assert("edward-935", !ts_data(stm)); + assert("edward-936", !ts_size(stm)); + assert("edward-937", size != 0); + + stm->data = vmalloc(size); + if (!stm->data) + return -ENOMEM; + set_ts_size(stm, size); + return 0; +} + +static inline void free_ts_data(tfm_stream_t * stm) +{ + assert("edward-938", equi(ts_data(stm), ts_size(stm))); + + if (ts_data(stm)) + vfree(ts_data(stm)); + memset(stm, 0, sizeof *stm); +} + +/* Write modes for item conversion in flush convert phase */ +typedef enum { + CRC_APPEND_ITEM = 1, + CRC_OVERWRITE_ITEM = 2, + CRC_CUT_ITEM = 3 +} crc_write_mode_t; + +typedef enum { + PCL_UNKNOWN = 0, /* invalid option */ + PCL_APPEND = 1, /* append and/or overwrite */ + PCL_TRUNCATE = 2 /* truncate */ +} page_cluster_op; + +/* Reiser4 file write/read transforms page cluster into disk cluster (and back) + using crypto/compression transforms implemented by reiser4 transform plugins. + Before each transform we allocate a pair of streams (tfm_unit) and assemble + page cluster into the input one. After transform we split output stream into + a set of items (disk cluster). +*/ +typedef struct tfm_cluster { + coa_set coa; + tfm_unit tun; + int uptodate; + int len; +} tfm_cluster_t; + +static inline coa_t get_coa(tfm_cluster_t * tc, reiser4_compression_id id) +{ + return tc->coa[id]; +} + +static inline void +set_coa(tfm_cluster_t * tc, reiser4_compression_id id, coa_t coa) +{ + tc->coa[id] = coa; +} + +static inline int +alloc_coa(tfm_cluster_t * tc, compression_plugin * cplug, tfm_action act) +{ + coa_t coa; + + coa = cplug->alloc(act); + if (IS_ERR(coa)) + return PTR_ERR(coa); + set_coa(tc, cplug->h.id, coa); + return 0; +} + +static inline void free_coa_set(tfm_cluster_t * tc, tfm_action act) +{ + reiser4_compression_id i; + compression_plugin *cplug; + + assert("edward-810", tc != NULL); + + for (i = 0; i < LAST_COMPRESSION_ID; i++) { + if (!get_coa(tc, i)) + continue; + cplug = compression_plugin_by_id(i); + assert("edward-812", cplug->free != NULL); + cplug->free(get_coa(tc, i), act); + set_coa(tc, i, 0); + } + return; +} + +static inline tfm_stream_t *tfm_stream(tfm_cluster_t * tc, tfm_stream_id id) +{ + return tc->tun[id]; +} + +static inline void +set_tfm_stream(tfm_cluster_t * tc, tfm_stream_id id, tfm_stream_t * ts) +{ + tc->tun[id] = ts; +} + +static inline __u8 *tfm_stream_data(tfm_cluster_t * tc, tfm_stream_id id) +{ + return ts_data(tfm_stream(tc, id)); +} + +static inline void +set_tfm_stream_data(tfm_cluster_t * tc, tfm_stream_id id, __u8 * data) +{ + tfm_stream(tc, id)->data = data; +} + +static inline size_t tfm_stream_size(tfm_cluster_t * tc, tfm_stream_id id) +{ + return ts_size(tfm_stream(tc, id)); +} + +static inline void +set_tfm_stream_size(tfm_cluster_t * tc, tfm_stream_id id, size_t size) +{ + tfm_stream(tc, id)->size = size; +} + +static inline int +alloc_tfm_stream(tfm_cluster_t * tc, size_t size, tfm_stream_id id) +{ + assert("edward-939", tc != NULL); + assert("edward-940", !tfm_stream(tc, id)); + + tc->tun[id] = kmalloc(sizeof(tfm_stream_t), GFP_KERNEL); + if (!tc->tun[id]) + return -ENOMEM; + memset(tfm_stream(tc, id), 0, sizeof(tfm_stream_t)); + return alloc_ts_data(tfm_stream(tc, id), size); +} + +static inline int +realloc_tfm_stream(tfm_cluster_t * tc, size_t size, tfm_stream_id id) +{ + assert("edward-941", tfm_stream_size(tc, id) < size); + free_ts_data(tfm_stream(tc, id)); + return alloc_ts_data(tfm_stream(tc, id), size); +} + +static inline void free_tfm_stream(tfm_cluster_t * tc, tfm_stream_id id) +{ + free_ts_data(tfm_stream(tc, id)); + free_ts(tfm_stream(tc, id)); + set_tfm_stream(tc, id, 0); +} + +static inline void free_tfm_unit(tfm_cluster_t * tc) +{ + tfm_stream_id id; + for (id = 0; id < LAST_STREAM; id++) { + if (!tfm_stream(tc, id)) + continue; + free_tfm_stream(tc, id); + } +} + +static inline void put_tfm_cluster(tfm_cluster_t * tc, tfm_action act) +{ + assert("edward-942", tc != NULL); + free_coa_set(tc, act); + free_tfm_unit(tc); +} + +static inline int tfm_cluster_is_uptodate(tfm_cluster_t * tc) +{ + assert("edward-943", tc != NULL); + assert("edward-944", tc->uptodate == 0 || tc->uptodate == 1); + return (tc->uptodate == 1); +} + +static inline void tfm_cluster_set_uptodate(tfm_cluster_t * tc) +{ + assert("edward-945", tc != NULL); + assert("edward-946", tc->uptodate == 0 || tc->uptodate == 1); + tc->uptodate = 1; + return; +} + +static inline void tfm_cluster_clr_uptodate(tfm_cluster_t * tc) +{ + assert("edward-947", tc != NULL); + assert("edward-948", tc->uptodate == 0 || tc->uptodate == 1); + tc->uptodate = 0; + return; +} + +static inline int tfm_stream_is_set(tfm_cluster_t * tc, tfm_stream_id id) +{ + return (tfm_stream(tc, id) && + tfm_stream_data(tc, id) && tfm_stream_size(tc, id)); +} + +static inline int tfm_cluster_is_set(tfm_cluster_t * tc) +{ + int i; + for (i = 0; i < LAST_STREAM; i++) + if (!tfm_stream_is_set(tc, i)) + return 0; + return 1; +} + +static inline void alternate_streams(tfm_cluster_t * tc) +{ + tfm_stream_t *tmp = tfm_stream(tc, INPUT_STREAM); + + set_tfm_stream(tc, INPUT_STREAM, tfm_stream(tc, OUTPUT_STREAM)); + set_tfm_stream(tc, OUTPUT_STREAM, tmp); +} + +/* a kind of data that we can write to the window */ +typedef enum { + DATA_WINDOW, /* the data we copy form user space */ + HOLE_WINDOW /* zeroes if we write hole */ +} window_stat; + +/* Sliding window of cluster size which should be set to the approprite position + (defined by cluster index) in a file before page cluster modification by + file_write. Then we translate file size, offset to write from, number of + bytes to write, etc.. to the following configuration needed to estimate + number of pages to read before write, etc... +*/ +typedef struct reiser4_slide { + unsigned off; /* offset we start to write/truncate from */ + unsigned count; /* number of bytes (zeroes) to write/truncate */ + unsigned delta; /* number of bytes to append to the hole */ + window_stat stat; /* a kind of data to write to the window */ +} reiser4_slide_t; + +/* The following is a set of possible disk cluster states */ +typedef enum { + INVAL_DISK_CLUSTER, /* unknown state */ + PREP_DISK_CLUSTER, /* disk cluster got converted by flush + at least 1 time */ + UNPR_DISK_CLUSTER, /* disk cluster just created and should be + converted by flush */ + FAKE_DISK_CLUSTER /* disk cluster doesn't exist neither in memory + nor on disk */ +} disk_cluster_stat; + +/* + While implementing all transforms (from page to disk cluster, and back) + reiser4 cluster manager fills the following structure incapsulating pointers + to all the clusters for the same index including the sliding window above +*/ +typedef struct reiser4_cluster { + tfm_cluster_t tc; /* transform cluster */ + int nr_pages; /* number of pages */ + struct page **pages; /* page cluster */ + page_cluster_op op; /* page cluster operation */ + struct file *file; + hint_t *hint; /* disk cluster item for traversal */ + disk_cluster_stat dstat; /* state of the current disk cluster */ + cloff_t index; /* offset in the units of cluster size */ + reiser4_slide_t *win; /* sliding window of cluster size */ + int reserved; /* this indicates that space for disk + cluster modification is reserved */ +#if REISER4_DEBUG + reiser4_context *ctx; + int reserved_prepped; + int reserved_unprepped; +#endif +} reiser4_cluster_t; + +static inline void reset_cluster_pgset(reiser4_cluster_t * clust, int nrpages) +{ + assert("edward-1057", clust->pages != NULL); + memset(clust->pages, 0, sizeof(*clust->pages) * nrpages); +} + +static inline int alloc_cluster_pgset(reiser4_cluster_t * clust, int nrpages) +{ + assert("edward-949", clust != NULL); + assert("edward-950", nrpages != 0 && nrpages <= MAX_CLUSTER_NRPAGES); + + clust->pages = + kmalloc(sizeof(*clust->pages) * nrpages, GFP_KERNEL); + if (!clust->pages) + return RETERR(-ENOMEM); + reset_cluster_pgset(clust, nrpages); + return 0; +} + +static inline void free_cluster_pgset(reiser4_cluster_t * clust) +{ + assert("edward-951", clust->pages != NULL); + kfree(clust->pages); +} + +static inline void put_cluster_handle(reiser4_cluster_t * clust, tfm_action act) +{ + assert("edward-435", clust != NULL); + + put_tfm_cluster(&clust->tc, act); + if (clust->pages) + free_cluster_pgset(clust); + memset(clust, 0, sizeof *clust); +} + +/* security attributes supposed to be stored on disk + are loaded by stat-data methods (see plugin/item/static_stat.c */ +typedef struct crypto_stat { + __u8 *keyid; /* pointer to a fingerprint */ + __u16 keysize; /* key size, bits */ + __u32 *expkey; +} crypto_stat_t; + +/* cryptcompress specific part of reiser4_inode */ +typedef struct cryptcompress_info { + struct rw_semaphore lock; + struct crypto_tfm *tfm[LAST_TFM]; + crypto_stat_t *crypt; +} cryptcompress_info_t; + +cryptcompress_info_t *cryptcompress_inode_data(const struct inode *inode); +int equal_to_rdk(znode *, const reiser4_key *); +int goto_right_neighbor(coord_t *, lock_handle *); +int load_file_hint(struct file *, hint_t *); +void save_file_hint(struct file *, const hint_t *); +void hint_init_zero(hint_t *); +int crc_inode_ok(struct inode *inode); +extern int ctail_read_cluster (reiser4_cluster_t *, struct inode *, int); +extern int do_readpage_ctail(reiser4_cluster_t *, struct page * page); +extern int ctail_insert_unprepped_cluster(reiser4_cluster_t * clust, struct inode * inode); + +static inline struct crypto_tfm *inode_get_tfm(struct inode *inode, + reiser4_tfm tfm) +{ + return cryptcompress_inode_data(inode)->tfm[tfm]; +} + +static inline struct crypto_tfm *inode_get_crypto(struct inode *inode) +{ + return (inode_get_tfm(inode, CRYPTO_TFM)); +} + +static inline struct crypto_tfm *inode_get_digest(struct inode *inode) +{ + return (inode_get_tfm(inode, DIGEST_TFM)); +} + +static inline unsigned int crypto_blocksize(struct inode *inode) +{ + assert("edward-758", inode_get_tfm(inode, CRYPTO_TFM) != NULL); + return crypto_tfm_alg_blocksize(inode_get_tfm(inode, CRYPTO_TFM)); +} + +static inline compression_plugin *dual_compression_plugin(compression_plugin * + cplug) +{ + return compression_plugin_by_id(cplug->dual); +} + +#define REGISTER_NONE_ALG(ALG, TFM) \ +static int alloc_none_ ## ALG (struct inode * inode) \ +{ \ + cryptcompress_info_t * info; \ + assert("edward-760", inode != NULL); \ + \ + info = cryptcompress_inode_data(inode); \ + \ + \ + cryptcompress_inode_data(inode)->tfm[TFM ## _TFM] = NULL; \ + return 0; \ + \ +} \ +static void free_none_ ## ALG (struct inode * inode) \ +{ \ + cryptcompress_info_t * info; \ + assert("edward-761", inode != NULL); \ + \ + info = cryptcompress_inode_data(inode); \ + \ + assert("edward-762", info != NULL); \ + \ + info->tfm[TFM ## _TFM] = NULL; \ +} + +#endif /* __FS_REISER4_CRYPTCOMPRESS_H__ */ + +/* Make Linus happy. + Local variables: + c-indentation-style: "K&R" + mode-name: "LC" + c-basic-offset: 8 + tab-width: 8 + fill-column: 120 + scroll-step: 1 + End: +*/ diff -puN fs/reiser4/plugin/file/file.c~reiser4-big-update fs/reiser4/plugin/file/file.c --- devel/fs/reiser4/plugin/file/file.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/file/file.c 2005-09-15 19:51:08.000000000 -0700 @@ -1,6 +1,11 @@ /* Copyright 2001, 2002, 2003, 2004 by Hans Reiser, licensing governed by * reiser4/README */ +/* this file contains implementations of inode/file/address_space/file plugin + operations specific for "unix file plugin" (plugin id is + UNIX_FILE_PLUGIN_ID) +*/ + #include "../../inode.h" #include "../../super.h" #include "../../tree_walk.h" @@ -15,101 +20,77 @@ #include #include -/* this file contains file plugin methods of reiser4 unix files. - - Those files are either built of tail items only (FORMATTING_ID) or of extent - items only (EXTENT_POINTER_ID) or empty (have no items but stat data) */ +/* "Unix file" are built either of tail items only (FORMATTING_ID) or of extent + items only (EXTENT_POINTER_ID) or empty (have no items but stat data) +*/ static int unpack(struct inode *inode, int forever); /* get unix file plugin specific portion of inode */ -reiser4_internal unix_file_info_t * -unix_file_inode_data(const struct inode * inode) +unix_file_info_t *unix_file_inode_data(const struct inode *inode) { return &reiser4_inode_data(inode)->file_plugin_data.unix_file_info; } -static int -file_is_built_of_tails(const struct inode *inode) +static int file_is_built_of_tails(const struct inode *inode) { return unix_file_inode_data(inode)->container == UF_CONTAINER_TAILS; } -#if REISER4_DEBUG - -static int -file_is_built_of_extents(const struct inode *inode) -{ - return unix_file_inode_data(inode)->container == UF_CONTAINER_EXTENTS; -} - -static int -file_is_empty(const struct inode *inode) -{ - return unix_file_inode_data(inode)->container == UF_CONTAINER_EMPTY; -} - -#endif - -static int -file_state_is_unknown(const struct inode *inode) +static int file_state_is_unknown(const struct inode *inode) { return unix_file_inode_data(inode)->container == UF_CONTAINER_UNKNOWN; } -static void -set_file_state_extents(struct inode *inode) +static void set_file_state_extents(struct inode *inode) { unix_file_inode_data(inode)->container = UF_CONTAINER_EXTENTS; } -static void -set_file_state_tails(struct inode *inode) +static void set_file_state_tails(struct inode *inode) { unix_file_inode_data(inode)->container = UF_CONTAINER_TAILS; } -static void -set_file_state_empty(struct inode *inode) +static void set_file_state_empty(struct inode *inode) { unix_file_inode_data(inode)->container = UF_CONTAINER_EMPTY; } -static void -set_file_state_unknown(struct inode *inode) +static void set_file_state_unknown(struct inode *inode) { unix_file_inode_data(inode)->container = UF_CONTAINER_UNKNOWN; } -static int -less_than_ldk(znode *node, const reiser4_key *key) +static int less_than_ldk(znode * node, const reiser4_key * key) { - return UNDER_RW(dk, current_tree, read, keylt(key, znode_get_ld_key(node))); + return UNDER_RW(dk, current_tree, read, + keylt(key, znode_get_ld_key(node))); } -reiser4_internal int -equal_to_rdk(znode *node, const reiser4_key *key) +int equal_to_rdk(znode * node, const reiser4_key * key) { - return UNDER_RW(dk, current_tree, read, keyeq(key, znode_get_rd_key(node))); + return UNDER_RW(dk, current_tree, read, + keyeq(key, znode_get_rd_key(node))); } #if REISER4_DEBUG -static int -less_than_rdk(znode *node, const reiser4_key *key) +static int less_than_rdk(znode * node, const reiser4_key * key) { - return UNDER_RW(dk, current_tree, read, keylt(key, znode_get_rd_key(node))); + return UNDER_RW(dk, current_tree, read, + keylt(key, znode_get_rd_key(node))); } -static int -equal_to_ldk(znode *node, const reiser4_key *key) +static int equal_to_ldk(znode * node, const reiser4_key * key) { - return UNDER_RW(dk, current_tree, read, keyeq(key, znode_get_ld_key(node))); + return UNDER_RW(dk, current_tree, read, + keyeq(key, znode_get_ld_key(node))); } /* get key of item next to one @coord is set to */ -static reiser4_key * -get_next_item_key(const coord_t *coord, reiser4_key *next_key) +static reiser4_key *get_next_item_key(const coord_t * coord, + reiser4_key * next_key) { if (coord->item_pos == node_num_items(coord->node) - 1) { /* get key of next item if it is in right neighbor */ @@ -127,8 +108,14 @@ get_next_item_key(const coord_t *coord, return next_key; } -static int -item_of_that_file(const coord_t *coord, const reiser4_key *key) +/** + * item_of_that_file + * @coord: + * @key: + * + * Returns true if @key is a key of position if @coord is set to item of fileif item of file + */ +static int item_of_that_file(const coord_t *coord, const reiser4_key *key) { reiser4_key max_possible; item_plugin *iplug; @@ -138,42 +125,52 @@ item_of_that_file(const coord_t *coord, return keylt(key, iplug->b.max_key_inside(coord, &max_possible)); } -static int -check_coord(const coord_t *coord, const reiser4_key *key) +static int check_coord(const coord_t * coord, const reiser4_key * key) { coord_t twin; if (!REISER4_DEBUG) return 1; - node_plugin_by_node(coord->node)->lookup(coord->node, key, FIND_MAX_NOT_MORE_THAN, &twin); + node_plugin_by_node(coord->node)->lookup(coord->node, key, + FIND_MAX_NOT_MORE_THAN, &twin); return coords_equal(coord, &twin); } -#endif /* REISER4_DEBUG */ +static int file_is_built_of_extents(const struct inode *inode) +{ + return unix_file_inode_data(inode)->container == UF_CONTAINER_EXTENTS; +} -static void -init_uf_coord(uf_coord_t *uf_coord, lock_handle *lh) +static int file_is_empty(const struct inode *inode) +{ + return unix_file_inode_data(inode)->container == UF_CONTAINER_EMPTY; +} + +#endif /* REISER4_DEBUG */ + +static void init_uf_coord(uf_coord_t * uf_coord, lock_handle * lh) { coord_init_zero(&uf_coord->coord); - coord_clear_iplug(&uf_coord->coord); + coord_clear_iplug(&uf_coord->coord); uf_coord->lh = lh; init_lh(lh); memset(&uf_coord->extension, 0, sizeof(uf_coord->extension)); uf_coord->valid = 0; } -static inline void -validate_extended_coord(uf_coord_t *uf_coord, loff_t offset) +static inline void validate_extended_coord(uf_coord_t * uf_coord, loff_t offset) { assert("vs-1333", uf_coord->valid == 0); - assert("vs-1348", item_plugin_by_coord(&uf_coord->coord)->s.file.init_coord_extension); + assert("vs-1348", + item_plugin_by_coord(&uf_coord->coord)->s.file. + init_coord_extension); item_body_by_coord(&uf_coord->coord); - item_plugin_by_coord(&uf_coord->coord)->s.file.init_coord_extension(uf_coord, offset); + item_plugin_by_coord(&uf_coord->coord)->s.file. + init_coord_extension(uf_coord, offset); } -reiser4_internal write_mode_t -how_to_write(uf_coord_t *uf_coord, const reiser4_key *key) +write_mode_t how_to_write(uf_coord_t * uf_coord, const reiser4_key * key) { write_mode_t result; coord_t *coord; @@ -186,7 +183,8 @@ how_to_write(uf_coord_t *uf_coord, const if (uf_coord->valid == 1) { assert("vs-1332", check_coord(coord, key)); - return (coord->between == AFTER_UNIT) ? APPEND_ITEM : OVERWRITE_ITEM; + return (coord->between == + AFTER_UNIT) ? APPEND_ITEM : OVERWRITE_ITEM; } if (less_than_ldk(coord->node, key)) { @@ -213,7 +211,9 @@ how_to_write(uf_coord_t *uf_coord, const * lingering. Nothing prevents us from reusing it. */ assert("vs-1000", UNDER_RW(dk, current_tree, read, - keylt(key, znode_get_rd_key(coord->node)))); + keylt(key, + znode_get_rd_key(coord-> + node)))); assert("vs-1002", coord->between == EMPTY_NODE); result = FIRST_ITEM; uf_coord->valid = 1; @@ -221,23 +221,34 @@ how_to_write(uf_coord_t *uf_coord, const } assert("vs-1336", coord->item_pos < node_num_items(coord->node)); - assert("vs-1007", ergo(coord->between == AFTER_UNIT || coord->between == AT_UNIT, keyle(item_key_by_coord(coord, &check), key))); - assert("vs-1008", ergo(coord->between == AFTER_UNIT || coord->between == AT_UNIT, keylt(key, get_next_item_key(coord, &check)))); + assert("vs-1007", + ergo(coord->between == AFTER_UNIT + || coord->between == AT_UNIT, + keyle(item_key_by_coord(coord, &check), key))); + assert("vs-1008", + ergo(coord->between == AFTER_UNIT + || coord->between == AT_UNIT, keylt(key, + get_next_item_key(coord, + &check)))); - switch(coord->between) { + switch (coord->between) { case AFTER_ITEM: uf_coord->valid = 1; result = FIRST_ITEM; break; case AFTER_UNIT: - assert("vs-1323", (item_is_tail(coord) || item_is_extent(coord)) && item_of_that_file(coord, key)); - assert("vs-1208", keyeq(item_plugin_by_coord(coord)->s.file.append_key(coord, &check), key)); + assert("vs-1323", (item_is_tail(coord) || item_is_extent(coord)) + && item_of_that_file(coord, key)); + assert("vs-1208", + keyeq(item_plugin_by_coord(coord)->s.file. + append_key(coord, &check), key)); result = APPEND_ITEM; validate_extended_coord(uf_coord, get_key_offset(key)); break; case AT_UNIT: /* FIXME: it would be nice to check that coord matches to key */ - assert("vs-1324", (item_is_tail(coord) || item_is_extent(coord)) && item_of_that_file(coord, key)); + assert("vs-1324", (item_is_tail(coord) || item_is_extent(coord)) + && item_of_that_file(coord, key)); validate_extended_coord(uf_coord, get_key_offset(key)); result = OVERWRITE_ITEM; break; @@ -247,15 +258,14 @@ how_to_write(uf_coord_t *uf_coord, const break; } -ok: + ok: assert("vs-1349", uf_coord->valid == 1); assert("vs-1332", check_coord(coord, key)); return result; } /* obtain lock on right neighbor and drop lock on current node */ -reiser4_internal int -goto_right_neighbor(coord_t * coord, lock_handle * lh) +int goto_right_neighbor(coord_t * coord, lock_handle * lh) { int result; lock_handle lh_right; @@ -263,10 +273,11 @@ goto_right_neighbor(coord_t * coord, loc assert("vs-1100", znode_is_locked(coord->node)); init_lh(&lh_right); - result = reiser4_get_right_neighbor( - &lh_right, coord->node, - znode_is_wlocked(coord->node) ? ZNODE_WRITE_LOCK : ZNODE_READ_LOCK, - GN_CAN_USE_UPPER_LEVELS); + result = reiser4_get_right_neighbor(&lh_right, coord->node, + znode_is_wlocked(coord-> + node) ? + ZNODE_WRITE_LOCK : ZNODE_READ_LOCK, + GN_CAN_USE_UPPER_LEVELS); if (result) { done_lh(&lh_right); return result; @@ -281,7 +292,8 @@ goto_right_neighbor(coord_t * coord, loc } -/* this is to be used after find_file_item and in find_file_item_nohint to determine real state of file */ +/* this is to be used after find_file_item and in find_file_item_nohint to + * determine real state of file */ static void set_file_state(struct inode *inode, int cbk_result, tree_level level) { @@ -309,75 +321,70 @@ set_file_state(struct inode *inode, int /* file state is known, check that it is set correctly */ assert("vs-1161", ergo(cbk_result == CBK_COORD_NOTFOUND, file_is_empty(inode))); - assert("vs-1162", ergo(level == LEAF_LEVEL && cbk_result == CBK_COORD_FOUND, - file_is_built_of_tails(inode))); - assert("vs-1165", ergo(level == TWIG_LEVEL && cbk_result == CBK_COORD_FOUND, - file_is_built_of_extents(inode))); + assert("vs-1162", + ergo(level == LEAF_LEVEL + && cbk_result == CBK_COORD_FOUND, + file_is_built_of_tails(inode))); + assert("vs-1165", + ergo(level == TWIG_LEVEL + && cbk_result == CBK_COORD_FOUND, + file_is_built_of_extents(inode))); } } -static int -find_file_item(hint_t *hint, /* coord, lock handle and seal are here */ - const reiser4_key *key, /* key of position in a file of next read/write */ - znode_lock_mode lock_mode, /* which lock (read/write) to put on returned node */ - ra_info_t *ra_info, - struct inode *inode) +/** + * find_file_item - look for file item in the tree + * @hint: provides coordinate, lock handle, seal + * @key: key for search + * @mode: mode of lock to put on returned node + * @ra_info: + * @inode: + * + * This finds position in the tree corresponding to @key. It first tries to use + * @hint's seal if it is set. + */ +static int find_file_item(hint_t *hint, const reiser4_key *key, + znode_lock_mode lock_mode, + struct inode *inode) { int result; coord_t *coord; lock_handle *lh; - __u32 cbk_flags; assert("nikita-3030", schedulable()); assert("vs-1707", hint != NULL); + assert("vs-47", inode != NULL); coord = &hint->ext_coord.coord; lh = hint->ext_coord.lh; init_lh(lh); - result = hint_validate(hint, key, 1/*check key*/, lock_mode); + result = hint_validate(hint, key, 1 /* check key */ , lock_mode); if (!result) { - if (coord->between == AFTER_UNIT && equal_to_rdk(coord->node, key)) { + if (coord->between == AFTER_UNIT + && equal_to_rdk(coord->node, key)) { result = goto_right_neighbor(coord, lh); if (result == -E_NO_NEIGHBOR) return RETERR(-EIO); if (result) return result; assert("vs-1152", equal_to_ldk(coord->node, key)); - /* we moved to different node. Invalidate coord extension, zload is necessary to init it - again */ + /* we moved to different node. Invalidate coord + extension, zload is necessary to init it again */ hint->ext_coord.valid = 0; } - set_file_state(inode, CBK_COORD_FOUND, znode_get_level(coord->node)); + set_file_state(inode, CBK_COORD_FOUND, + znode_get_level(coord->node)); return CBK_COORD_FOUND; } coord_init_zero(coord); - cbk_flags = (lock_mode == ZNODE_READ_LOCK) ? CBK_UNIQUE : (CBK_UNIQUE | CBK_FOR_INSERT); - if (inode != NULL) { - result = object_lookup(inode, - key, - coord, - lh, - lock_mode, - FIND_MAX_NOT_MORE_THAN, - TWIG_LEVEL, - LEAF_LEVEL, - cbk_flags, - ra_info); - } else { - result = coord_by_key(current_tree, - key, - coord, - lh, - lock_mode, - FIND_MAX_NOT_MORE_THAN, - TWIG_LEVEL, - LEAF_LEVEL, - cbk_flags, - ra_info); - } + result = object_lookup(inode, key, coord, lh, lock_mode, + FIND_MAX_NOT_MORE_THAN, + TWIG_LEVEL, LEAF_LEVEL, + (lock_mode == ZNODE_READ_LOCK) ? CBK_UNIQUE : + (CBK_UNIQUE | CBK_FOR_INSERT), NULL); set_file_state(inode, result, znode_get_level(coord->node)); @@ -386,17 +393,20 @@ find_file_item(hint_t *hint, /* coord, l return result; } -reiser4_internal int -find_file_item_nohint(coord_t *coord, lock_handle *lh, const reiser4_key *key, - znode_lock_mode lock_mode, struct inode *inode) +int +find_file_item_nohint(coord_t * coord, lock_handle * lh, + const reiser4_key * key, znode_lock_mode lock_mode, + struct inode *inode) { int result; result = object_lookup(inode, key, coord, lh, lock_mode, FIND_MAX_NOT_MORE_THAN, TWIG_LEVEL, LEAF_LEVEL, - (lock_mode == ZNODE_READ_LOCK) ? CBK_UNIQUE : (CBK_UNIQUE | CBK_FOR_INSERT), - NULL /* ra_info */); + (lock_mode == + ZNODE_READ_LOCK) ? CBK_UNIQUE : (CBK_UNIQUE | + CBK_FOR_INSERT), + NULL /* ra_info */ ); set_file_state(inode, result, znode_get_level(coord->node)); return result; } @@ -404,16 +414,16 @@ find_file_item_nohint(coord_t *coord, lo /* plugin->u.file.write_flowom = NULL plugin->u.file.read_flow = NULL */ -reiser4_internal void -hint_init_zero(hint_t *hint) +void hint_init_zero(hint_t * hint) { - memset(hint, 0, sizeof (*hint)); + memset(hint, 0, sizeof(*hint)); + init_lh(&hint->lh); + hint->ext_coord.lh = &hint->lh; } /* find position of last byte of last item of the file plus 1. This is used by truncate and mmap to find real file size */ -static int -find_file_size(struct inode *inode, loff_t *file_size) +static int find_file_size(struct inode *inode, loff_t * file_size) { int result; reiser4_key key; @@ -421,11 +431,14 @@ find_file_size(struct inode *inode, loff lock_handle lh; item_plugin *iplug; - assert("vs-1247", inode_file_plugin(inode)->key_by_inode == key_by_inode_unix_file); - key_by_inode_unix_file(inode, get_key_offset(max_key()), &key); + assert("vs-1247", + inode_file_plugin(inode)->key_by_inode == + key_by_inode_and_offset_common); + key_by_inode_and_offset_common(inode, get_key_offset(max_key()), &key); init_lh(&lh); - result = find_file_item_nohint(&coord, &lh, &key, ZNODE_READ_LOCK, inode); + result = + find_file_item_nohint(&coord, &lh, &key, ZNODE_READ_LOCK, inode); if (cbk_errored(result)) { /* error happened */ done_lh(&lh); @@ -440,7 +453,7 @@ find_file_size(struct inode *inode, loff } /* there are items of this file (at least one) */ - /*coord_clear_iplug(&coord);*/ + /*coord_clear_iplug(&coord); */ result = zload(coord.node); if (unlikely(result)) { done_lh(&lh); @@ -459,8 +472,7 @@ find_file_size(struct inode *inode, loff return 0; } -static int -find_file_state(unix_file_info_t *uf_info) +static int find_file_state(unix_file_info_t * uf_info) { int result; @@ -470,16 +482,19 @@ find_file_state(unix_file_info_t *uf_inf if (uf_info->container == UF_CONTAINER_UNKNOWN) { loff_t file_size; - result = find_file_size(unix_file_info_to_inode(uf_info), &file_size); + result = + find_file_size(unix_file_info_to_inode(uf_info), + &file_size); } - assert("vs-1074", ergo(result == 0, uf_info->container != UF_CONTAINER_UNKNOWN)); + assert("vs-1074", + ergo(result == 0, uf_info->container != UF_CONTAINER_UNKNOWN)); return result; } /* estimate and reserve space needed to truncate page which gets partially truncated: one block for page itself, stat data update (estimate_one_insert_into_item) and one item insertion (estimate_one_insert_into_item) which may happen if page corresponds to hole extent and unallocated one will have to be created */ -static int reserve_partial_page(reiser4_tree *tree) +static int reserve_partial_page(reiser4_tree * tree) { grab_space_enable(); return reiser4_grab_reserved(reiser4_get_current_sb(), @@ -489,25 +504,24 @@ static int reserve_partial_page(reiser4_ } /* estimate and reserve space needed to cut one item and update one stat data */ -static int -reserve_cut_iteration(reiser4_tree *tree) +static int reserve_cut_iteration(reiser4_tree * tree) { __u64 estimate = estimate_one_item_removal(tree) - + estimate_one_insert_into_item(tree); + + estimate_one_insert_into_item(tree); assert("nikita-3172", lock_stack_isclean(get_current_lock_stack())); grab_space_enable(); /* We need to double our estimate now that we can delete more than one node. */ - return reiser4_grab_reserved(reiser4_get_current_sb(), estimate*2, + return reiser4_grab_reserved(reiser4_get_current_sb(), estimate * 2, BA_CAN_COMMIT); } -reiser4_internal int -update_file_size(struct inode *inode, reiser4_key * key, int update_sd) +int update_file_size(struct inode *inode, reiser4_key * key, int update_sd) { int result = 0; + INODE_SET_FIELD(inode, i_size, get_key_offset(key)); if (update_sd) { inode->i_ctime = inode->i_mtime = CURRENT_TIME; @@ -518,13 +532,14 @@ update_file_size(struct inode *inode, re /* cut file items one by one starting from the last one until new file size (inode->i_size) is reached. Reserve space and update file stat data on every single cut from the tree */ -reiser4_internal int -cut_file_items(struct inode *inode, loff_t new_size, int update_sd, loff_t cur_size, - int (*update_actor)(struct inode *, reiser4_key *, int)) +int +cut_file_items(struct inode *inode, loff_t new_size, int update_sd, + loff_t cur_size, int (*update_actor) (struct inode *, + reiser4_key *, int)) { reiser4_key from_key, to_key; reiser4_key smallest_removed; - file_plugin * fplug = inode_file_plugin(inode); + file_plugin *fplug = inode_file_plugin(inode); int result; int progress = 0; @@ -534,7 +549,7 @@ cut_file_items(struct inode *inode, loff fplug->key_by_inode(inode, new_size, &from_key); to_key = from_key; - set_key_offset(&to_key, cur_size - 1/*get_key_offset(max_key())*/); + set_key_offset(&to_key, cur_size - 1 /*get_key_offset(max_key()) */ ); /* this loop normally runs just once */ while (1) { result = reserve_cut_iteration(tree_by_inode(inode)); @@ -542,11 +557,14 @@ cut_file_items(struct inode *inode, loff break; result = cut_tree_object(current_tree, &from_key, &to_key, - &smallest_removed, inode, 1, &progress); + &smallest_removed, inode, 1, + &progress); if (result == -E_REPEAT) { /* -E_REPEAT is a signal to interrupt a long file truncation process */ if (progress) { - result = update_actor(inode, &smallest_removed, update_sd); + result = + update_actor(inode, &smallest_removed, + update_sd); if (result) break; } @@ -559,7 +577,9 @@ cut_file_items(struct inode *inode, loff txn_restart_current(); continue; } - if (result && !(result == CBK_COORD_NOTFOUND && new_size == 0 && inode->i_size == 0)) + if (result + && !(result == CBK_COORD_NOTFOUND && new_size == 0 + && inode->i_size == 0)) break; set_key_offset(&smallest_removed, new_size); @@ -575,9 +595,14 @@ cut_file_items(struct inode *inode, loff int find_or_create_extent(struct page *page); -/* part of unix_file_truncate: it is called when truncate is used to make file shorter */ -static int -shorten_file(struct inode *inode, loff_t new_size) +static int filler(void *vp, struct page *page) +{ + return readpage_unix_file(vp, page); +} + +/* part of truncate_file_body: it is called when truncate is used to make file + shorter */ +static int shorten_file(struct inode *inode, loff_t new_size) { int result; struct page *page; @@ -587,7 +612,9 @@ shorten_file(struct inode *inode, loff_t /* all items of ordinary reiser4 file are grouped together. That is why we can use cut_tree. Plan B files (for instance) can not be truncated that simply */ - result = cut_file_items(inode, new_size, 1/*update_sd*/, get_key_offset(max_key()), update_file_size); + result = + cut_file_items(inode, new_size, 1 /*update_sd */ , + get_key_offset(max_key()), update_file_size); if (result) return result; @@ -618,7 +645,7 @@ shorten_file(struct inode *inode, loff_t /* last page is partially truncated - zero its content */ index = (inode->i_size >> PAGE_CACHE_SHIFT); - page = read_cache_page(inode->i_mapping, index, readpage_unix_file/*filler*/, 0); + page = read_cache_page(inode->i_mapping, index, filler, NULL); if (IS_ERR(page)) { all_grabbed2free(); reiser4_release_reserved(inode->i_sb); @@ -636,11 +663,12 @@ shorten_file(struct inode *inode, loff_t return RETERR(-EIO); } - /* if page correspons to hole extent unit - unallocated one will be created here. This is not necessary */ + /* if page correspons to hole extent unit - unallocated one will be + created here. This is not necessary */ result = find_or_create_extent(page); - /* FIXME: cut_file_items has already updated inode. Probably it would be better to update it here when file is - really truncated */ + /* FIXME: cut_file_items has already updated inode. Probably it would + be better to update it here when file is really truncated */ all_grabbed2free(); if (result) { page_cache_release(page); @@ -661,13 +689,15 @@ shorten_file(struct inode *inode, loff_t } static loff_t -write_flow(hint_t *, struct file *, struct inode *, const char *buf, loff_t count, loff_t pos, int exclusive); +write_flow(hint_t *, struct file *, struct inode *, const char __user *buf, + loff_t count, loff_t pos, int exclusive); -/* it is called when truncate is used to make file longer and when write position is set past real end of file. It - appends file which has size @cur_size with hole of certain size (@hole_size). It returns 0 on success, error code - otherwise */ +/* it is called when truncate is used to make file longer and when write + position is set past real end of file. It appends file which has size + @cur_size with hole of certain size (@hole_size). It returns 0 on success, + error code otherwise */ static int -append_hole(hint_t *hint, struct inode *inode, loff_t new_size, int exclusive) +append_hole(hint_t * hint, struct inode *inode, loff_t new_size, int exclusive) { int result; loff_t written; @@ -677,7 +707,7 @@ append_hole(hint_t *hint, struct inode * result = 0; hole_size = new_size - inode->i_size; - written = write_flow(hint, NULL, inode, NULL/*buf*/, hole_size, + written = write_flow(hint, NULL, inode, NULL /*buf */ , hole_size, inode->i_size, exclusive); if (written != hole_size) { /* return error because file is not expanded as required */ @@ -691,40 +721,39 @@ append_hole(hint_t *hint, struct inode * return result; } -/* this either cuts or add items of/to the file so that items match new_size. It is used in unix_file_setattr when it is - used to truncate -VS-FIXME-HANS: explain that -and in unix_file_delete */ -static int -truncate_file_body(struct inode *inode, loff_t new_size) +/** + * truncate_file_body - change length of file + * @inode: inode of file + * @new_size: new file length + * + * Adjusts items file @inode is built of to match @new_size. It may either cut + * items or add them to represent a hole at the end of file. The caller has to + * obtain exclusive access to the file. + */ +static int truncate_file_body(struct inode *inode, loff_t new_size) { int result; - hint_t hint; - hint_init_zero(&hint); - if (inode->i_size < new_size) - result = append_hole(&hint, inode, new_size, 1/* exclusive access is obtained */); - else - result = shorten_file(inode, new_size); + if (inode->i_size < new_size) { + hint_t *hint; + hint = kmalloc(sizeof(*hint), GFP_KERNEL); + if (hint == NULL) + return RETERR(-ENOMEM); + hint_init_zero(hint); + result = append_hole(hint, inode, new_size, + 1 /* exclusive access is obtained */ ); + kfree(hint); + } else + result = shorten_file(inode, new_size); return result; } -/* plugin->u.file.truncate - all the work is done on reiser4_setattr->unix_file_setattr->truncate_file_body -*/ -reiser4_internal int -truncate_unix_file(struct inode *inode, loff_t new_size) -{ - return 0; -} - /* plugin->u.write_sd_by_inode = write_sd_by_inode_common */ /* get access hint (seal, coord, key, level) stored in reiser4 private part of struct file if it was stored in a previous access to the file */ -reiser4_internal int -load_file_hint(struct file *file, hint_t *hint) +int load_file_hint(struct file *file, hint_t * hint) { reiser4_file_fsdata *fsdata; @@ -736,12 +765,15 @@ load_file_hint(struct file *file, hint_t spin_lock_inode(file->f_dentry->d_inode); if (seal_is_set(&fsdata->reg.hint.seal)) { *hint = fsdata->reg.hint; + init_lh(&hint->lh); + hint->ext_coord.lh = &hint->lh; spin_unlock_inode(file->f_dentry->d_inode); /* force re-validation of the coord on the first * iteration of the read/write loop. */ hint->ext_coord.valid = 0; assert("nikita-19892", coords_equal(&hint->seal.coord1, - &hint->ext_coord.coord)); + &hint->ext_coord. + coord)); return 0; } memset(&fsdata->reg.hint, 0, sizeof(hint_t)); @@ -753,8 +785,7 @@ load_file_hint(struct file *file, hint_t /* this copies hint for future tree accesses back to reiser4 private part of struct file */ -reiser4_internal void -save_file_hint(struct file *file, const hint_t *hint) +void save_file_hint(struct file *file, const hint_t * hint) { reiser4_file_fsdata *fsdata; @@ -765,41 +796,40 @@ save_file_hint(struct file *file, const assert("vs-965", !IS_ERR(fsdata)); assert("nikita-19891", coords_equal(&hint->seal.coord1, &hint->ext_coord.coord)); - + assert("vs-30", hint->lh.owner == NULL); spin_lock_inode(file->f_dentry->d_inode); fsdata->reg.hint = *hint; spin_unlock_inode(file->f_dentry->d_inode); return; } -reiser4_internal void -unset_hint(hint_t *hint) +void unset_hint(hint_t * hint) { assert("vs-1315", hint); hint->ext_coord.valid = 0; seal_done(&hint->seal); + done_lh(&hint->lh); } /* coord must be set properly. So, that set_hint has nothing to do */ -reiser4_internal void -set_hint(hint_t *hint, const reiser4_key *key, znode_lock_mode mode) +void set_hint(hint_t * hint, const reiser4_key * key, znode_lock_mode mode) { - ON_DEBUG(coord_t *coord = &hint->ext_coord.coord); + ON_DEBUG(coord_t * coord = &hint->ext_coord.coord); assert("vs-1207", WITH_DATA(coord->node, check_coord(coord, key))); seal_init(&hint->seal, &hint->ext_coord.coord, key); hint->offset = get_key_offset(key); hint->mode = mode; + done_lh(&hint->lh); } -reiser4_internal int -hint_is_set(const hint_t *hint) +int hint_is_set(const hint_t * hint) { return seal_is_set(&hint->seal); } #if REISER4_DEBUG -static int all_but_offset_key_eq(const reiser4_key *k1, const reiser4_key *k2) +static int all_but_offset_key_eq(const reiser4_key * k1, const reiser4_key * k2) { return (get_key_locality(k1) == get_key_locality(k2) && get_key_type(k1) == get_key_type(k2) && @@ -809,8 +839,9 @@ static int all_but_offset_key_eq(const r } #endif -reiser4_internal int -hint_validate(hint_t *hint, const reiser4_key *key, int check_key, znode_lock_mode lock_mode) +int +hint_validate(hint_t * hint, const reiser4_key * key, int check_key, + znode_lock_mode lock_mode) { if (!hint || !hint_is_set(hint) || hint->mode != lock_mode) /* hint either not set or set by different operation */ @@ -822,15 +853,14 @@ hint_validate(hint_t *hint, const reiser /* hint is set for different key */ return RETERR(-E_REPEAT); + assert("vs-31", hint->ext_coord.lh == &hint->lh); return seal_validate(&hint->seal, &hint->ext_coord.coord, key, - hint->ext_coord.lh, - lock_mode, ZNODE_LOCK_LOPRI); + hint->ext_coord.lh, lock_mode, ZNODE_LOCK_LOPRI); } /* look for place at twig level for extent corresponding to page, call extent's writepage method to create unallocated extent if it does not exist yet, initialize jnode, capture page */ -reiser4_internal int -find_or_create_extent(struct page *page) +int find_or_create_extent(struct page *page) { int result; uf_coord_t uf_coord; @@ -845,18 +875,21 @@ find_or_create_extent(struct page *page) inode = page->mapping->host; /* get key of first byte of the page */ - key_by_inode_unix_file(inode, (loff_t) page->index << PAGE_CACHE_SHIFT, &key); + key_by_inode_and_offset_common(inode, + (loff_t) page->index << PAGE_CACHE_SHIFT, + &key); init_uf_coord(&uf_coord, &lh); coord = &uf_coord.coord; - result = find_file_item_nohint(coord, &lh, &key, ZNODE_WRITE_LOCK, inode); + result = + find_file_item_nohint(coord, &lh, &key, ZNODE_WRITE_LOCK, inode); if (IS_CBKERR(result)) { done_lh(&lh); return result; } - /*coord_clear_iplug(coord);*/ + /*coord_clear_iplug(coord); */ result = zload(coord->node); if (result) { done_lh(&lh); @@ -866,39 +899,46 @@ find_or_create_extent(struct page *page) /* get plugin of extent item */ iplug = item_plugin_by_id(EXTENT_POINTER_ID); - result = iplug->s.file.capture(&key, &uf_coord, page, how_to_write(&uf_coord, &key)); + result = + iplug->s.file.capture(&key, &uf_coord, page, + how_to_write(&uf_coord, &key)); assert("vs-429378", result != -E_REPEAT); zrelse(loaded); done_lh(&lh); return result; } -#if REISER4_USE_EFLUSH -static int inode_has_eflushed_jnodes(struct inode * inode) +/** + * has_anonymous_pages - check whether inode has pages dirtied via mmap + * @inode: inode to check + * + * Returns true if inode's mapping has dirty pages which do not belong to any + * atom. Those are either tagged PAGECACHE_TAG_REISER4_MOVED in mapping's page + * tree or were eflushed and can be found via jnodes tagged + * EFLUSH_TAG_ANONYMOUS in radix tree of jnodes. + */ +static int has_anonymous_pages(struct inode *inode) { - reiser4_tree * tree = &get_super_private(inode->i_sb)->tree; - int ret; + int result; - RLOCK_TREE(tree); - ret = radix_tree_tagged(jnode_tree_by_inode(inode), EFLUSH_TAG_ANONYMOUS); - RUNLOCK_TREE(tree); - return ret; -} -# else -#define inode_has_eflushed_jnodes(inode) (0) + read_lock_irq(&inode->i_mapping->tree_lock); + result = radix_tree_tagged(&inode->i_mapping->page_tree, PAGECACHE_TAG_REISER4_MOVED) +#if REISER4_USE_EFLUSH + | radix_tree_tagged(jnode_tree_by_inode(inode), EFLUSH_TAG_ANONYMOUS) #endif - -/* Check mapping for existence of not captured dirty pages. This returns !0 if either page tree contains pages tagged - PAGECACHE_TAG_REISER4_MOVED or if eflushed jnode tree is not empty */ -static int -inode_has_anonymous_pages(struct inode *inode) -{ - return (mapping_tagged(inode->i_mapping, PAGECACHE_TAG_REISER4_MOVED) || - inode_has_eflushed_jnodes(inode)); + ; + read_unlock_irq(&inode->i_mapping->tree_lock); + return result; } -static int -capture_page_and_create_extent(struct page *page) +/** + * capture_page_and_create_extent - + * @page: page to be captured + * + * Grabs space for extent creation and stat data update and calls function to + * do actual work. + */ +static int capture_page_and_create_extent(struct page *page) { int result; struct inode *inode; @@ -907,12 +947,18 @@ capture_page_and_create_extent(struct pa inode = page->mapping->host; assert("vs-1139", file_is_built_of_extents(inode)); /* page belongs to file */ - assert("vs-1393", inode->i_size > ((loff_t) page->index << PAGE_CACHE_SHIFT)); + assert("vs-1393", + inode->i_size > ((loff_t) page->index << PAGE_CACHE_SHIFT)); - /* page capture may require extent creation (if it does not exist yet) and stat data's update (number of blocks - changes on extent creation) */ - grab_space_enable (); - result = reiser4_grab_space(2 * estimate_one_insert_into_item(tree_by_inode(inode)), BA_CAN_COMMIT); + /* page capture may require extent creation (if it does not exist yet) + and stat data's update (number of blocks changes on extent + creation) */ + grab_space_enable(); + result = + reiser4_grab_space(2 * + estimate_one_insert_into_item(tree_by_inode + (inode)), + BA_CAN_COMMIT); if (likely(!result)) result = find_or_create_extent(page); @@ -922,16 +968,35 @@ capture_page_and_create_extent(struct pa return result; } -/* plugin->u.file.capturepage handler */ -reiser4_internal int -capturepage_unix_file(struct page * page) { +/* this is implementation of method commit_write of struct + address_space_operations for unix file plugin */ +int +commit_write_unix_file(struct file *file, struct page *page, + unsigned from, unsigned to) +{ + reiser4_context *ctx; + struct inode *inode; int result; + assert("umka-3101", file != NULL); + assert("umka-3102", page != NULL); + assert("umka-3093", PageLocked(page)); + + SetPageUptodate(page); + + inode = page->mapping->host; + ctx = init_context(page->mapping->host->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); page_cache_get(page); unlock_page(page); result = capture_page_and_create_extent(page); lock_page(page); page_cache_release(page); + + /* don't commit transaction under inode semaphore */ + context_set_commit_async(ctx); + reiser4_exit_context(ctx); return result; } @@ -952,49 +1017,52 @@ capturepage_unix_file(struct page * page * jnode. Such page is called "anonymous" in reiser4. Certain work-loads * (iozone) generate huge number of anonymous pages. Emergency flush handles * this situation by creating jnode for anonymous page, starting IO on the - * page, and marking jnode with JNODE_KEEPME bit so that it's not throw out of + * page, and marking jnode with JNODE_KEEPME bit so that it's not thrown out of * memory. Such jnode is also called anonymous. * * reiser4_sync_sb() method tries to insert anonymous pages and jnodes into * tree. This is done by capture_anonymous_*() functions below. - * */ -/* this returns 1 if it captured page */ -static int -capture_anonymous_page(struct page *pg, int keepme) +/** + * capture_anonymous_page - involve page into transaction + * @pg: page to deal with + * + * Takes care that @page has corresponding metadata in the tree, creates jnode + * for @page and captures it. On success 1 is returned. + */ +static int capture_anonymous_page(struct page *page) { struct address_space *mapping; jnode *node; int result; - if (PageWriteback(pg)) + if (PageWriteback(page)) /* FIXME: do nothing? */ return 0; - mapping = pg->mapping; + mapping = page->mapping; - lock_page(pg); - /* page is guaranteed to be in the mapping, because we are operating under rw-semaphore. */ - assert("nikita-3336", pg->mapping == mapping); - node = jnode_of_page(pg); - unlock_page(pg); + lock_page(page); + /* page is guaranteed to be in the mapping, because we are operating + under rw-semaphore. */ + assert("nikita-3336", page->mapping == mapping); + node = jnode_of_page(page); + unlock_page(page); if (!IS_ERR(node)) { result = jload(node); assert("nikita-3334", result == 0); - assert("nikita-3335", jnode_page(node) == pg); - result = capture_page_and_create_extent(pg); + assert("nikita-3335", jnode_page(node) == page); + result = capture_page_and_create_extent(page); if (result == 0) { /* - * node will be captured into atom by - * capture_page_and_create_extent(). Atom - * cannot commit (because we have open - * transaction handle), and node cannot be - * truncated, because we have non-exclusive + * node has beed captured into atom by + * capture_page_and_create_extent(). Atom cannot commit + * (because we have open transaction handle), and node + * cannot be truncated, because we have non-exclusive * access to the file. */ assert("nikita-3327", node->atom != NULL); - JF_CLR(node, JNODE_KEEPME); result = 1; } else warning("nikita-3329", @@ -1007,55 +1075,116 @@ capture_anonymous_page(struct page *pg, return result; } -/* look for pages tagged REISER4_MOVED starting from the index-th page, return - number of captured pages, update index to next page after the last found - one */ +/** + * capture_anonymous_pages - find and capture pages dirtied via mmap + * @mapping: address space where to look for pages + * @index: start index + * @to_capture: maximum number of pages to capture + * + * Looks for pages tagged REISER4_MOVED starting from the *@index-th page, + * captures (involves into atom) them, returns number of captured pages, + * updates @index to next page after the last captured one. + */ static int capture_anonymous_pages(struct address_space *mapping, pgoff_t *index, - int to_capture) + unsigned int to_capture) { int result; struct pagevec pvec; - unsigned found_pages; - int count; - int i; + unsigned int i, count; int nr; pagevec_init(&pvec, 0); - count = min(pagevec_space(&pvec), (unsigned)to_capture); + count = min(pagevec_space(&pvec), to_capture); nr = 0; - found_pages = pagevec_lookup_tag(&pvec, mapping, index, PAGECACHE_TAG_REISER4_MOVED, count); - if (found_pages != 0) { - for (i = 0; i < pagevec_count(&pvec); i ++) { - /* tag PAGECACHE_TAG_REISER4_MOVED will be cleared by - set_page_dirty_internal which is called when jnode - is captured */ - result = capture_anonymous_page(pvec.pages[i], 0); - if (result == 1) - nr ++; - else if (result < 0) { - warning("vs-1454", "failed for moved page: result=%d, captured=%d)\n", + /* find pages tagged MOVED */ + write_lock_irq(&mapping->tree_lock); + pvec.nr = radix_tree_gang_lookup_tag(&mapping->page_tree, + (void **)pvec.pages, *index, count, + PAGECACHE_TAG_REISER4_MOVED); + if (pagevec_count(&pvec) == 0) { + /* there are no pages tagged MOVED in mapping->page_tree + starting from *index */ + write_unlock_irq(&mapping->tree_lock); + *index = (pgoff_t)-1; + return 0; + } + + /* clear tag for all found pages */ + for (i = 0; i < pagevec_count(&pvec); i++) { + void *p; + + page_cache_get(pvec.pages[i]); + p = radix_tree_tag_clear(&mapping->page_tree, pvec.pages[i]->index, + PAGECACHE_TAG_REISER4_MOVED); + assert("vs-49", p == pvec.pages[i]); + } + write_unlock_irq(&mapping->tree_lock); + + + *index = pvec.pages[i - 1]->index + 1; + + for (i = 0; i < pagevec_count(&pvec); i++) { + /* tag PAGECACHE_TAG_REISER4_MOVED will be cleared by + set_page_dirty_internal which is called when jnode is + captured */ + result = capture_anonymous_page(pvec.pages[i]); + if (result == 1) + nr++; + else { + if (result < 0) { + warning("vs-1454", + "failed to capture page: " + "result=%d, captured=%d)\n", result, i); + + /* set MOVED tag to all pages which + left not captured */ + write_lock_irq(&mapping->tree_lock); + for (; i < pagevec_count(&pvec); i ++) { + radix_tree_tag_set(&mapping->page_tree, + pvec.pages[i]->index, + PAGECACHE_TAG_REISER4_MOVED); + } + write_unlock_irq(&mapping->tree_lock); + pagevec_release(&pvec); return result; } else { - /* result == 0. capture_anonymous_page returns 0 for Writeback-ed page */ - ; + /* result == 0. capture_anonymous_page returns + 0 for Writeback-ed page. Set MOVED tag on + that page */ + write_lock_irq(&mapping->tree_lock); + radix_tree_tag_set(&mapping->page_tree, + pvec.pages[i]->index, + PAGECACHE_TAG_REISER4_MOVED); + write_unlock_irq(&mapping->tree_lock); + if (i == 0) + *index = pvec.pages[0]->index; + else + *index = pvec.pages[i - 1]->index + 1; } } - pagevec_release(&pvec); - } else - /* there are no starting from *index */ - *index = (pgoff_t)-1; - + } + pagevec_release(&pvec); return nr; } +/** + * capture_anonymous_jnodes - find and capture anonymous jnodes + * @mapping: address space where to look for jnodes + * @from: start index + * @to: end index + * @to_capture: maximum number of jnodes to capture + * + * Looks for jnodes tagged EFLUSH_TAG_ANONYMOUS in inode's tree of jnodes in + * the range of indexes @from-@to and captures them, returns number of captured + * jnodes, updates @from to next jnode after the last captured one. + */ static int capture_anonymous_jnodes(struct address_space *mapping, - pgoff_t *from, pgoff_t to, - int to_capture) + pgoff_t *from, pgoff_t to, int to_capture) { #if REISER4_USE_EFLUSH int found_jnodes; @@ -1065,36 +1194,50 @@ capture_anonymous_jnodes(struct address_ int result; jnode *jvec[PAGEVEC_SIZE]; reiser4_tree *tree; + struct radix_tree_root *root; count = min(PAGEVEC_SIZE, to_capture); nr = 0; result = 0; tree = &get_super_private(mapping->host->i_sb)->tree; - RLOCK_TREE(tree); - found_jnodes = radix_tree_gang_lookup_tag(jnode_tree_by_inode(mapping->host), - (void **)&jvec, *from, count, - EFLUSH_TAG_ANONYMOUS); + root = jnode_tree_by_inode(mapping->host); + + write_lock_irq(&mapping->tree_lock); + + found_jnodes = + radix_tree_gang_lookup_tag(root, (void **)&jvec, *from, count, + EFLUSH_TAG_ANONYMOUS); if (found_jnodes == 0) { - /* there are no anonymous jnodes from index from down to the + /* there are no anonymous jnodes from index @from down to the end of file */ - RUNLOCK_TREE(tree); + write_unlock_irq(&mapping->tree_lock); *from = to; return 0; } - for (i = 0; i < found_jnodes; i ++) { - if (index_jnode(jvec[i]) < to) + for (i = 0; i < found_jnodes; i++) { + if (index_jnode(jvec[i]) < to) { + void *p; + jref(jvec[i]); - else { + p = radix_tree_tag_clear(root, index_jnode(jvec[i]), + EFLUSH_TAG_ANONYMOUS); + assert("", p == jvec[i]); + + /* if page is tagged PAGECACHE_TAG_REISER4_MOVED it has + to be untagged because we are about to capture it */ + radix_tree_tag_clear(&mapping->page_tree, index_jnode(jvec[i]), + PAGECACHE_TAG_REISER4_MOVED); + } else { found_jnodes = i; break; } } + write_unlock_irq(&mapping->tree_lock); - RUNLOCK_TREE(tree); if (found_jnodes == 0) { - /* there are no anonymous jnodes in the gived range of + /* there are no anonymous jnodes in the given range of indexes */ *from = to; return 0; @@ -1103,40 +1246,67 @@ capture_anonymous_jnodes(struct address_ /* there are anonymous jnodes from given range */ /* start i/o for eflushed nodes */ - for (i = 0; i < found_jnodes; i ++) + for (i = 0; i < found_jnodes; i++) jstartio(jvec[i]); - for (i = 0; i < found_jnodes; i ++) { + *from = index_jnode(jvec[found_jnodes - 1]) + 1; + + for (i = 0; i < found_jnodes; i++) { result = jload(jvec[i]); if (result == 0) { - result = capture_anonymous_page(jnode_page(jvec[i]), 0); + result = capture_anonymous_page(jnode_page(jvec[i])); if (result == 1) - nr ++; + nr++; else if (result < 0) { jrelse(jvec[i]); warning("nikita-3328", "failed for anonymous jnode: result=%i, captured %d\n", result, i); + /* set ANONYMOUS tag to all jnodes which left + not captured */ + write_lock_irq(&mapping->tree_lock); + for (; i < found_jnodes; i ++) + /* page should be in the mapping. Do + * not tag jnode back as anonymous + * because it is not now (after + * jload) */ + radix_tree_tag_set(&mapping->page_tree, + index_jnode(jvec[i]), + PAGECACHE_TAG_REISER4_MOVED); + write_unlock_irq(&mapping->tree_lock); break; } else { - /* result == 0. capture_anonymous_page returns 0 for Writeback-ed page */ - ; + /* result == 0. capture_anonymous_page returns + 0 for Writeback-ed page. Set ANONYMOUS tag + on that jnode */ + warning("nikita-33281", + "anonymous jnode in writeback: (%lu %lu)\n", + mapping->host->i_ino, index_jnode(jvec[i])); + write_lock_irq(&mapping->tree_lock); + radix_tree_tag_set(&mapping->page_tree, + index_jnode(jvec[i]), + PAGECACHE_TAG_REISER4_MOVED); + write_unlock_irq(&mapping->tree_lock); + if (i == 0) + *from = index_jnode(jvec[0]); + else + *from = index_jnode(jvec[i - 1]) + 1; } jrelse(jvec[i]); } else { - warning("vs-1454", "jload for anonymous jnode failed: result=%i, captured %d\n", + warning("vs-1454", + "jload for anonymous jnode failed: result=%i, captured %d\n", result, i); break; } } - *from = index_jnode(jvec[found_jnodes - 1]) + 1; - for (i = 0; i < found_jnodes; i ++) + for (i = 0; i < found_jnodes; i++) jput(jvec[i]); if (result) return result; return nr; -#else /* REISER4_USE_EFLUSH */ +#else /* REISER4_USE_EFLUSH */ return 0; #endif } @@ -1144,8 +1314,7 @@ capture_anonymous_jnodes(struct address_ /* * Commit atom of the jnode of a page. */ -static int -sync_page(struct page *page) +static int sync_page(struct page *page) { int result; do { @@ -1171,13 +1340,12 @@ sync_page(struct page *page) * Commit atoms of pages on @pages list. * call sync_page for each page from mapping's page tree */ -static int -sync_page_list(struct inode *inode) +static int sync_page_list(struct inode *inode) { int result; struct address_space *mapping; - unsigned long from; /* start index for radix_tree_gang_lookup */ - unsigned int found; /* return value for radix_tree_gang_lookup */ + unsigned long from; /* start index for radix_tree_gang_lookup */ + unsigned int found; /* return value for radix_tree_gang_lookup */ mapping = inode->i_mapping; from = 0; @@ -1186,7 +1354,9 @@ sync_page_list(struct inode *inode) while (result == 0) { struct page *page; - found = radix_tree_gang_lookup(&mapping->page_tree, (void **)&page, from, 1); + found = + radix_tree_gang_lookup(&mapping->page_tree, (void **)&page, + from, 1); assert("", found < 2); if (found == 0) break; @@ -1208,26 +1378,19 @@ sync_page_list(struct inode *inode) return result; } -static int -commit_file_atoms(struct inode *inode) +static int commit_file_atoms(struct inode *inode) { - int result; + int result; unix_file_info_t *uf_info; - reiser4_context *ctx; - /* - * close current transaction - */ - - ctx = get_current_context(); - txn_restart(ctx); + /* close current transaction */ + txn_restart_current(); uf_info = unix_file_inode_data(inode); /* * finish extent<->tail conversion if necessary */ - get_exclusive_access(uf_info); if (inode_get_flag(inode, REISER4_PART_CONV)) { result = finish_conversion(inode); @@ -1240,7 +1403,6 @@ commit_file_atoms(struct inode *inode) /* * find what items file is made from */ - result = find_file_state(uf_info); drop_exclusive_access(uf_info); if (result != 0) @@ -1249,27 +1411,28 @@ commit_file_atoms(struct inode *inode) /* * file state cannot change because we are under ->i_sem */ - - switch(uf_info->container) { + switch (uf_info->container) { case UF_CONTAINER_EXTENTS: + /* find_file_state might open join an atom */ + txn_restart_current(); result = - /* - * when we are called by - * filemap_fdatawrite-> - * do_writepages()-> - * reiser4_writepages() - * - * inode->i_mapping->dirty_pages are spices into - * ->io_pages, leaving ->dirty_pages dirty. - * - * When we are called from - * reiser4_fsync()->sync_unix_file(), we have to - * commit atoms of all pages on the ->dirty_list. - * - * So for simplicity we just commit ->io_pages and - * ->dirty_pages. - */ - sync_page_list(inode); + /* + * when we are called by + * filemap_fdatawrite-> + * do_writepages()-> + * reiser4_writepages() + * + * inode->i_mapping->dirty_pages are spices into + * ->io_pages, leaving ->dirty_pages dirty. + * + * When we are called from + * reiser4_fsync()->sync_unix_file(), we have to + * commit atoms of all pages on the ->dirty_list. + * + * So for simplicity we just commit ->io_pages and + * ->dirty_pages. + */ + sync_page_list(inode); break; case UF_CONTAINER_TAILS: /* @@ -1291,38 +1454,49 @@ commit_file_atoms(struct inode *inode) * commit current transaction: there can be captured nodes from * find_file_state() and finish_conversion(). */ - txn_restart(ctx); + txn_restart_current(); return result; } -reiser4_internal int -capture_unix_file(struct inode *inode, struct writeback_control *wbc) +/* reiser4 writepages() address space operation this captures anonymous pages + and anonymous jnodes. Anonymous pages are pages which are dirtied via + mmapping. Anonymous jnodes are ones which were created by reiser4_writepage + */ +int +writepages_unix_file(struct address_space *mapping, + struct writeback_control *wbc) { - int result; + int result; unix_file_info_t *uf_info; pgoff_t pindex, jindex, nr_pages; long to_capture; + struct inode *inode; - if (!inode_has_anonymous_pages(inode)) - return 0; - - uf_info = unix_file_inode_data(inode); - + inode = mapping->host; + if (!has_anonymous_pages(inode)) { + result = 0; + goto end; + } + jindex = pindex = wbc->start >> PAGE_CACHE_SHIFT; result = 0; - pindex = 0; - jindex = 0; - nr_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + nr_pages = + (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + uf_info = unix_file_inode_data(inode); do { - reiser4_context ctx; + reiser4_context *ctx; if (wbc->sync_mode != WB_SYNC_ALL) to_capture = min(wbc->nr_to_write, CAPTURE_APAGE_BURST); else to_capture = CAPTURE_APAGE_BURST; - init_context(&ctx, inode->i_sb); + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) { + result = PTR_ERR(ctx); + break; + } /* avoid recursive calls to ->sync_inodes */ - ctx.nobalance = 1; + ctx->nobalance = 1; assert("zam-760", lock_stack_isclean(get_current_lock_stack())); /* * locking: creation of extent requires read-semaphore on @@ -1347,7 +1521,10 @@ capture_unix_file(struct inode *inode, s assert("vs-1727", jindex <= pindex); if (pindex == jindex) { start = pindex; - result = capture_anonymous_pages(inode->i_mapping, &pindex, to_capture); + result = + capture_anonymous_pages(inode->i_mapping, + &pindex, + to_capture); if (result < 0) break; to_capture -= result; @@ -1356,18 +1533,20 @@ capture_unix_file(struct inode *inode, s jindex = pindex; continue; } - if (to_capture <= 0) + if (to_capture <= 0) break; } /* deal with anonymous jnodes between jindex and pindex */ - result = capture_anonymous_jnodes(inode->i_mapping, &jindex, pindex, to_capture); + result = + capture_anonymous_jnodes(inode->i_mapping, &jindex, + pindex, to_capture); if (result < 0) break; to_capture -= result; - get_current_context()->nr_captured -= result; + get_current_context()->nr_captured += result; - if (jindex == (pgoff_t)-1) { - assert("vs-1728", pindex == (pgoff_t)-1); + if (jindex == (pgoff_t) - 1) { + assert("vs-1728", pindex == (pgoff_t) - 1); break; } } @@ -1378,19 +1557,28 @@ capture_unix_file(struct inode *inode, s drop_nonexclusive_access(uf_info); if (result < 0) { /* error happened */ - reiser4_exit_context(&ctx); + reiser4_exit_context(ctx); return result; } if (wbc->sync_mode != WB_SYNC_ALL) { - reiser4_exit_context(&ctx); + reiser4_exit_context(ctx); return 0; } result = commit_file_atoms(inode); - reiser4_exit_context(&ctx); + reiser4_exit_context(ctx); if (pindex >= nr_pages && jindex == pindex) break; } while (1); + end: + if (is_in_reiser4_context()) { + if (get_current_context()->nr_captured >= CAPTURE_APAGE_BURST) { + /* there are already pages to flush, flush them out, do + not delay until end of reiser4_sync_inodes */ + writeout(inode->i_sb, wbc); + get_current_context()->nr_captured = 0; + } + } return result; } @@ -1406,15 +1594,17 @@ capture_unix_file(struct inode *inode, s * filemap_fdatawrite() that will ultimately call reiser4_writepages(), insert * all missing extents and capture anonymous pages. */ -reiser4_internal int -sync_unix_file(struct inode *inode, int datasync) +int sync_unix_file(struct file *file, struct dentry *dentry, int datasync) { int result; reiser4_context *ctx; - ctx = get_current_context(); + ctx = init_context(dentry->d_inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + assert("nikita-3486", ctx->trans->atom == NULL); - result = commit_file_atoms(inode); + result = commit_file_atoms(dentry->d_inode); assert("nikita-3484", ergo(result == 0, ctx->trans->atom == NULL)); if (result == 0 && !datasync) { do { @@ -1427,14 +1617,15 @@ sync_unix_file(struct inode *inode, int init_lh(&lh); /* locate stat-data in a tree and return with znode * locked */ - result = locate_inode_sd(inode, &key, &coord, &lh); + result = + locate_inode_sd(dentry->d_inode, &key, &coord, &lh); if (result == 0) { - jnode *node; + jnode *node; txn_atom *atom; node = jref(ZJNODE(coord.node)); done_lh(&lh); - txn_restart(ctx); + txn_restart_current(); LOCK_JNODE(node); atom = jnode_get_atom(node); UNLOCK_JNODE(node); @@ -1444,6 +1635,7 @@ sync_unix_file(struct inode *inode, int done_lh(&lh); } while (result == -E_REPEAT); } + reiser4_exit_context(ctx); return result; } @@ -1452,60 +1644,83 @@ sync_unix_file(struct inode *inode, int that case vp is struct file *file, or on truncate when last page of a file is to be read to perform its partial truncate and in that case vp is 0 */ -reiser4_internal int -readpage_unix_file(void *vp, struct page *page) +int readpage_unix_file(struct file *file, struct page *page) { + reiser4_context *ctx; int result; struct inode *inode; - lock_handle lh; reiser4_key key; item_plugin *iplug; - hint_t hint; + hint_t *hint; + lock_handle *lh; coord_t *coord; - struct file *file; assert("vs-1062", PageLocked(page)); + assert("vs-976", !PageUptodate(page)); assert("vs-1061", page->mapping && page->mapping->host); - assert("vs-1078", (page->mapping->host->i_size > ((loff_t) page->index << PAGE_CACHE_SHIFT))); + assert("vs-1078", + (page->mapping->host->i_size > + ((loff_t) page->index << PAGE_CACHE_SHIFT))); inode = page->mapping->host; - file = vp; - result = load_file_hint(file, &hint); - if (result) + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + hint = kmalloc(sizeof(*hint), GFP_KERNEL); + if (hint == NULL) { + reiser4_exit_context(ctx); + return RETERR(-ENOMEM); + } + + result = load_file_hint(file, hint); + if (result) { + kfree(hint); + reiser4_exit_context(ctx); return result; - init_lh(&lh); - hint.ext_coord.lh = &lh; + } + lh = &hint->lh; /* get key of first byte of the page */ - key_by_inode_unix_file(inode, (loff_t) page->index << PAGE_CACHE_SHIFT, &key); + key_by_inode_and_offset_common(inode, + (loff_t) page->index << PAGE_CACHE_SHIFT, + &key); /* look for file metadata corresponding to first byte of page */ unlock_page(page); - result = find_file_item(&hint, &key, ZNODE_READ_LOCK, 0/* ra_info */, inode); + result = find_file_item(hint, &key, ZNODE_READ_LOCK, inode); lock_page(page); if (result != CBK_COORD_FOUND) { /* this indicates file corruption */ - done_lh(&lh); - unlock_page(page); + done_lh(lh); + unlock_page(page); + kfree(hint); + reiser4_exit_context(ctx); return result; } if (PageUptodate(page)) { - done_lh(&lh); - unlock_page(page); + done_lh(lh); + unlock_page(page); + kfree(hint); + reiser4_exit_context(ctx); return 0; } - coord = &hint.ext_coord.coord; + coord = &hint->ext_coord.coord; result = zload(coord->node); if (result) { - done_lh(&lh); - unlock_page(page); + done_lh(lh); + unlock_page(page); + kfree(hint); + reiser4_exit_context(ctx); return result; } - if (hint.ext_coord.valid == 0) - validate_extended_coord(&hint.ext_coord, (loff_t) page->index << PAGE_CACHE_SHIFT); + if (hint->ext_coord.valid == 0) + validate_extended_coord(&hint->ext_coord, + (loff_t) page-> + index << PAGE_CACHE_SHIFT); if (!coord_is_existing_unit(coord)) { /* this indicates corruption */ @@ -1516,8 +1731,10 @@ readpage_unix_file(void *vp, struct page inode->i_size, result); zrelse(coord->node); - done_lh(&lh); - unlock_page(page); + done_lh(lh); + unlock_page(page); + kfree(hint); + reiser4_exit_context(ctx); return RETERR(-EIO); } @@ -1530,29 +1747,32 @@ readpage_unix_file(void *vp, struct page result = RETERR(-EINVAL); if (!result) { - set_key_offset(&key, (loff_t) (page->index + 1) << PAGE_CACHE_SHIFT); + set_key_offset(&key, + (loff_t) (page->index + 1) << PAGE_CACHE_SHIFT); /* FIXME should call set_hint() */ - unset_hint(&hint); + unset_hint(hint); } else { - unlock_page(page); - unset_hint(&hint); + unlock_page(page); + unset_hint(hint); } zrelse(coord->node); - done_lh(&lh); + done_lh(lh); - save_file_hint(file, &hint); + save_file_hint(file, hint); + kfree(hint); - assert("vs-979", ergo(result == 0, (PageLocked(page) || PageUptodate(page)))); - assert("vs-9791", ergo(result != 0, !PageLocked(page))); + assert("vs-979", + ergo(result == 0, (PageLocked(page) || PageUptodate(page)))); + assert("vs-9791", ergo(result != 0, !PageLocked(page))); + reiser4_exit_context(ctx); return result; } /* returns 1 if file of that size (@new_size) has to be stored in unformatted nodes */ /* Audited by: green(2002.06.15) */ -static int -should_have_notail(const unix_file_info_t *uf_info, loff_t new_size) +static int should_have_notail(const unix_file_info_t * uf_info, loff_t new_size) { if (!uf_info->tplug) return 1; @@ -1564,9 +1784,11 @@ should_have_notail(const unix_file_info_ static reiser4_block_nr unix_file_estimate_read(struct inode *inode, loff_t count UNUSED_ARG) { - /* We should reserve one block, because of updating of the stat data + /* We should reserve one block, because of updating of the stat data item */ - assert("vs-1249", inode_file_plugin(inode)->estimate.update == estimate_update_common); + assert("vs-1249", + inode_file_plugin(inode)->estimate.update == + estimate_update_common); return estimate_update_common(inode); } @@ -1580,21 +1802,23 @@ get_nr_pages_nr_bytes(unsigned long addr /* number of pages through which count bytes starting of address addr are spread */ *nr_pages = ((addr + count + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) - - (addr >> PAGE_CACHE_SHIFT); + (addr >> PAGE_CACHE_SHIFT); if (*nr_pages > NR_PAGES_TO_PIN) { *nr_pages = NR_PAGES_TO_PIN; - nr_bytes = (*nr_pages * PAGE_CACHE_SIZE) - (addr & (PAGE_CACHE_SIZE - 1)); + nr_bytes = + (*nr_pages * PAGE_CACHE_SIZE) - + (addr & (PAGE_CACHE_SIZE - 1)); } else nr_bytes = count; return nr_bytes; } -static size_t -adjust_nr_bytes(unsigned long addr, size_t count, int nr_pages) +static size_t adjust_nr_bytes(unsigned long addr, size_t count, int nr_pages) { if (count > nr_pages * PAGE_CACHE_SIZE) - return (nr_pages * PAGE_CACHE_SIZE) - (addr & (PAGE_CACHE_SIZE - 1)); + return (nr_pages * PAGE_CACHE_SIZE) - + (addr & (PAGE_CACHE_SIZE - 1)); return count; } @@ -1604,28 +1828,24 @@ reiser4_get_user_pages(struct page **pag { down_read(¤t->mm->mmap_sem); nr_pages = get_user_pages(current, current->mm, addr, - nr_pages, (rw == READ), 0, - pages, NULL); + nr_pages, (rw == READ), 0, pages, NULL); up_read(¤t->mm->mmap_sem); return nr_pages; } -static void -reiser4_put_user_pages(struct page **pages, int nr_pages) +static void reiser4_put_user_pages(struct page **pages, int nr_pages) { int i; - for (i = 0; i < nr_pages; i ++) + for (i = 0; i < nr_pages; i++) page_cache_release(pages[i]); } /* this is called with nonexclusive access obtained, file's container can not change */ -static size_t -read_file(hint_t *hint, - struct file *file, /* file to write to */ - char *buf, /* address of user-space buffer */ - size_t count, /* number of bytes to write */ - loff_t *off) +static size_t read_file(hint_t * hint, struct file *file, /* file to read from to */ + char __user *buf, /* address of user-space buffer */ + size_t count, /* number of bytes to read */ + loff_t * off) { int result; struct inode *inode; @@ -1636,10 +1856,13 @@ read_file(hint_t *hint, inode = file->f_dentry->d_inode; - /* build flow */ - assert("vs-1250", inode_file_plugin(inode)->flow_by_inode == flow_by_inode_unix_file); - result = flow_by_inode_unix_file(inode, buf, 1 /* user space */ , count, *off, READ_OP, &flow); + assert("vs-1250", + inode_file_plugin(inode)->flow_by_inode == + flow_by_inode_unix_file); + result = + flow_by_inode_unix_file(inode, buf, 1 /* user space */ , count, + *off, READ_OP, &flow); if (unlikely(result)) return result; @@ -1647,10 +1870,11 @@ read_file(hint_t *hint, of struct file. The coord will tell us where our last read of this file finished, and the seal will help to determine if that location is still valid. - */ + */ coord = &hint->ext_coord.coord; while (flow.length && result == 0) { - result = find_file_item(hint, &flow.key, ZNODE_READ_LOCK, NULL, inode); + result = + find_file_item(hint, &flow.key, ZNODE_READ_LOCK, inode); if (cbk_errored(result)) /* error happened */ break; @@ -1665,9 +1889,11 @@ read_file(hint_t *hint, break; if (hint->ext_coord.valid == 0) - validate_extended_coord(&hint->ext_coord, get_key_offset(&flow.key)); + validate_extended_coord(&hint->ext_coord, + get_key_offset(&flow.key)); assert("vs-4", hint->ext_coord.valid == 1); + assert("vs-33", hint->ext_coord.lh == &hint->lh); /* call item's read method */ read_f = item_plugin_by_coord(coord)->s.file.read; result = read_f(file, &flow, hint); @@ -1678,23 +1904,29 @@ read_file(hint_t *hint, return (count - flow.length) ? (count - flow.length) : result; } -static int is_user_space(const char *buf) +static int is_user_space(const char __user *buf) { return (unsigned long)buf < PAGE_OFFSET; } -/* plugin->u.file.read - - the read method for the unix_file plugin - -*/ -reiser4_internal ssize_t -read_unix_file(struct file *file, char *buf, size_t read_amount, loff_t *off) +/** + * read_unix_file - read of struct file_operations + * @file: file to read from + * @buf: address of user-space buffer + * @read_amount: number of bytes to read + * @off: position in file to read from + * + * This is implementation of vfs's read method of struct file_operations for + * unix file plugin. + */ +ssize_t +read_unix_file(struct file *file, char __user *buf, size_t read_amount, + loff_t *off) { + reiser4_context *ctx; int result; struct inode *inode; - lock_handle lh; - hint_t hint; + hint_t *hint; unix_file_info_t *uf_info; struct page *pages[NR_PAGES_TO_PIN]; int nr_pages; @@ -1706,26 +1938,43 @@ read_unix_file(struct file *file, char * if (unlikely(read_amount == 0)) return 0; + assert("umka-072", file != NULL); + assert("umka-074", off != NULL); inode = file->f_dentry->d_inode; assert("vs-972", !inode_get_flag(inode, REISER4_NO_SD)); - uf_info = unix_file_inode_data(inode); + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); needed = unix_file_estimate_read(inode, read_amount); result = reiser4_grab_space(needed, BA_CAN_COMMIT); - if (result != 0) + if (result != 0) { + context_set_commit_async(ctx); + reiser4_exit_context(ctx); return result; + } - result = load_file_hint(file, &hint); - if (result) + hint = kmalloc(sizeof(*hint), GFP_KERNEL); + if (hint == NULL) { + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return RETERR(-ENOMEM); + } + + result = load_file_hint(file, hint); + if (result) { + kfree(hint); + context_set_commit_async(ctx); + reiser4_exit_context(ctx); return result; - init_lh(&lh); - hint.ext_coord.lh = &lh; + } left = read_amount; count = 0; user_space = is_user_space(buf); nr_pages = 0; + uf_info = unix_file_inode_data(inode); while (left > 0) { unsigned long addr; size_t to_read; @@ -1742,7 +1991,8 @@ read_unix_file(struct file *file, char * if (user_space) { to_read = get_nr_pages_nr_bytes(addr, left, &nr_pages); - nr_pages = reiser4_get_user_pages(pages, addr, nr_pages, READ); + nr_pages = + reiser4_get_user_pages(pages, addr, nr_pages, READ); if (nr_pages < 0) { result = nr_pages; break; @@ -1770,7 +2020,7 @@ read_unix_file(struct file *file, char * to_read = inode->i_size - *off; assert("vs-1706", to_read <= left); - read = read_file(&hint, file, buf, to_read, off); + read = read_file(hint, file, buf, to_read, off); if (user_space) reiser4_put_user_pages(pages, nr_pages); @@ -1789,28 +2039,34 @@ read_unix_file(struct file *file, char * /* total number of read bytes */ count += read; } - save_file_hint(file, &hint); + save_file_hint(file, hint); + kfree(hint); if (count) { /* something was read. Update inode's atime and stat data */ update_atime(inode); } + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + /* return number of read bytes or error code if nothing is read */ return count ? count : result; } -typedef int (*write_f_t)(struct inode *, flow_t *, hint_t *, int grabbed, write_mode_t); +typedef int (*write_f_t) (struct inode *, flow_t *, hint_t *, int grabbed, + write_mode_t); /* This searches for write position in the tree and calls write method of appropriate item to actually copy user data into filesystem. This loops until all the data from flow @f are written to a file. */ static loff_t -append_and_or_overwrite(hint_t *hint, struct file *file, struct inode *inode, flow_t *flow, - int exclusive /* if 1 - exclusive access on a file is obtained */) +append_and_or_overwrite(hint_t * hint, struct file *file, struct inode *inode, + flow_t * flow, + int exclusive + /* if 1 - exclusive access on a file is obtained */ ) { int result; - lock_handle lh; loff_t to_write; write_f_t write_f; file_container_t cur_container, new_container; @@ -1821,8 +2077,7 @@ append_and_or_overwrite(hint_t *hint, st assert("vs-1109", get_current_context()->grabbed_blocks == 0); assert("vs-1708", hint != NULL); - init_lh(&lh); - hint->ext_coord.lh = &lh; + init_lh(&hint->lh); result = 0; uf_info = unix_file_inode_data(inode); @@ -1835,45 +2090,59 @@ append_and_or_overwrite(hint_t *hint, st if (to_write == flow->length) { /* it may happend that find_file_item will have to insert empty node to the tree (empty leaf node between two extent items) */ - result = reiser4_grab_space_force(1 + estimate_one_insert_item(tree_by_inode(inode)), 0); + result = + reiser4_grab_space_force(1 + + estimate_one_insert_item + (tree_by_inode(inode)), 0); if (result) return result; } /* when hint is set - hint's coord matches seal's coord */ assert("nikita-19894", !hint_is_set(hint) || - coords_equal(&hint->seal.coord1, &hint->ext_coord.coord)); + coords_equal(&hint->seal.coord1, + &hint->ext_coord.coord)); /* look for file's metadata (extent or tail item) corresponding to position we write to */ - result = find_file_item(hint, &flow->key, ZNODE_WRITE_LOCK, NULL/* ra_info */, inode); + result = find_file_item(hint, &flow->key, ZNODE_WRITE_LOCK, + inode); all_grabbed2free(); if (IS_CBKERR(result)) { /* error occurred */ - done_lh(&lh); + done_lh(&hint->lh); return result; } - + assert("vs-32", hint->lh.node == hint->ext_coord.coord.node); cur_container = uf_info->container; switch (cur_container) { case UF_CONTAINER_EMPTY: assert("vs-1196", get_key_offset(&flow->key) == 0); - if (should_have_notail(uf_info, get_key_offset(&flow->key) + flow->length)) { + if (should_have_notail + (uf_info, + get_key_offset(&flow->key) + flow->length)) { new_container = UF_CONTAINER_EXTENTS; - write_f = item_plugin_by_id(EXTENT_POINTER_ID)->s.file.write; + write_f = + item_plugin_by_id(EXTENT_POINTER_ID)->s. + file.write; } else { new_container = UF_CONTAINER_TAILS; - write_f = item_plugin_by_id(FORMATTING_ID)->s.file.write; + write_f = + item_plugin_by_id(FORMATTING_ID)->s.file. + write; } break; case UF_CONTAINER_EXTENTS: - write_f = item_plugin_by_id(EXTENT_POINTER_ID)->s.file.write; + write_f = + item_plugin_by_id(EXTENT_POINTER_ID)->s.file.write; new_container = cur_container; break; case UF_CONTAINER_TAILS: - if (should_have_notail(uf_info, get_key_offset(&flow->key) + flow->length)) { - done_lh(&lh); + if (should_have_notail + (uf_info, + get_key_offset(&flow->key) + flow->length)) { + done_lh(&hint->lh); if (!exclusive) { drop_nonexclusive_access(uf_info); txn_restart_current(); @@ -1891,44 +2160,46 @@ append_and_or_overwrite(hint_t *hint, st unset_hint(hint); continue; } - write_f = item_plugin_by_id(FORMATTING_ID)->s.file.write; + write_f = + item_plugin_by_id(FORMATTING_ID)->s.file.write; new_container = cur_container; break; default: - done_lh(&lh); + done_lh(&hint->lh); return RETERR(-EIO); } - result = zload(lh.node); + result = zload(hint->lh.node); if (result) { - done_lh(&lh); + done_lh(&hint->lh); return result; } - loaded = lh.node; + loaded = hint->lh.node; assert("vs-11", hint->ext_coord.coord.node == loaded); - result = write_f(inode, - flow, - hint, - 0/* not grabbed */, + result = write_f(inode, flow, hint, 0 /* not grabbed */ , how_to_write(&hint->ext_coord, &flow->key)); - assert("nikita-3142", get_current_context()->grabbed_blocks == 0); + assert("nikita-3142", + get_current_context()->grabbed_blocks == 0); /* seal has either to be not set to set properly */ assert("nikita-19893", ((!hint_is_set(hint) && hint->ext_coord.valid == 0) || - (coords_equal(&hint->seal.coord1, &hint->ext_coord.coord) && - keyeq(&flow->key, &hint->seal.key)))); + (coords_equal + (&hint->seal.coord1, &hint->ext_coord.coord) + && keyeq(&flow->key, &hint->seal.key)))); - if (cur_container == UF_CONTAINER_EMPTY && to_write != flow->length) { + if (cur_container == UF_CONTAINER_EMPTY + && to_write != flow->length) { /* file was empty and we have written something and we are having exclusive access to the file - change file state */ - assert("vs-1195", (new_container == UF_CONTAINER_TAILS || - new_container == UF_CONTAINER_EXTENTS)); + assert("vs-1195", + (new_container == UF_CONTAINER_TAILS + || new_container == UF_CONTAINER_EXTENTS)); uf_info->container = new_container; } zrelse(loaded); - done_lh(&lh); + done_lh(&hint->lh); if (result && result != -E_REPEAT && result != -E_DEADLOCK) break; preempt_point(); @@ -1944,45 +2215,48 @@ append_and_or_overwrite(hint_t *hint, st /* make flow and write data (@buf) to the file. If @buf == 0 - hole of size @count will be created. This is called with uf_info->latch either read- or write-locked */ static loff_t -write_flow(hint_t *hint, struct file *file, struct inode *inode, const char *buf, loff_t count, loff_t pos, - int exclusive) +write_flow(hint_t * hint, struct file *file, struct inode *inode, + const char __user *buf, loff_t count, loff_t pos, int exclusive) { int result; flow_t flow; - assert("vs-1251", inode_file_plugin(inode)->flow_by_inode == flow_by_inode_unix_file); + assert("vs-1251", + inode_file_plugin(inode)->flow_by_inode == + flow_by_inode_unix_file); result = flow_by_inode_unix_file(inode, - (char *)buf, 1 /* user space */, count, pos, WRITE_OP, &flow); + buf, 1 /* user space */ , + count, pos, WRITE_OP, &flow); if (result) return result; return append_and_or_overwrite(hint, file, inode, &flow, exclusive); } -static struct page * -unix_file_filemap_nopage(struct vm_area_struct *area, unsigned long address, int * unused) +static struct page *unix_file_filemap_nopage(struct vm_area_struct *area, + unsigned long address, int *unused) { struct page *page; struct inode *inode; - reiser4_context ctx; + reiser4_context *ctx; inode = area->vm_file->f_dentry->d_inode; - init_context(&ctx, inode->i_sb); + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) + return (struct page *)ctx; /* block filemap_nopage if copy on capture is processing with a node of this file */ down_read(&reiser4_inode_data(inode)->coc_sem); /* second argument is to note that current atom may exist */ get_nonexclusive_access(unix_file_inode_data(inode), 1); - page = filemap_nopage(area, address, 0); + page = filemap_nopage(area, address, NULL); drop_nonexclusive_access(unix_file_inode_data(inode)); up_read(&reiser4_inode_data(inode)->coc_sem); - /*txn_restart_current();*/ - - reiser4_exit_context(&ctx); + reiser4_exit_context(ctx); return page; } @@ -2000,29 +2274,50 @@ static struct vm_operations_struct unix_ Here also tail2extent conversion is performed if it is allowed and file is going to be written or mapped for write. This functions may be called from write_unix_file() or mmap_unix_file(). */ -static int -check_pages_unix_file(struct inode *inode) +static int check_pages_unix_file(struct inode *inode) { reiser4_invalidate_pages(inode->i_mapping, 0, - (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT, 0); - return unpack(inode, 0 /* not forever */); + (inode->i_size + PAGE_CACHE_SIZE - + 1) >> PAGE_CACHE_SHIFT, 0); + return unpack(inode, 0 /* not forever */ ); } -/* plugin->u.file.mmap - make sure that file is built of extent blocks. An estimation is in tail2extent */ +/* implentation of vfs' mmap method of struct file_operations for unix file + plugin + + make sure that file is built of extent blocks. An estimation is in + tail2extent -/* This sets inode flags: file has mapping. if file is mmaped with VM_MAYWRITE - invalidate pages and convert. */ -reiser4_internal int -mmap_unix_file(struct file *file, struct vm_area_struct *vma) + This sets inode flags: file has mapping. if file is mmaped with VM_MAYWRITE + - invalidate pages and convert. +*/ +int mmap_unix_file(struct file *file, struct vm_area_struct *vma) { + reiser4_context *ctx; int result; struct inode *inode; unix_file_info_t *uf_info; + reiser4_block_nr needed; inode = file->f_dentry->d_inode; + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + /* + * generic_file_mmap will do update_atime. Grab space for stat data + * update + */ + needed = inode_file_plugin(inode)->estimate.update(inode); + result = reiser4_grab_space(needed, BA_CAN_COMMIT); + if (result) { + reiser4_exit_context(ctx); + return result; + } + uf_info = unix_file_inode_data(inode); - down(&uf_info->write); + down(&uf_info->write); get_exclusive_access(uf_info); if (!IS_RDONLY(inode) && (vma->vm_flags & (VM_MAYWRITE | VM_SHARED))) { @@ -2032,6 +2327,7 @@ mmap_unix_file(struct file *file, struct if (result) { drop_exclusive_access(uf_info); up(&uf_info->write); + reiser4_exit_context(ctx); return result; } @@ -2039,6 +2335,7 @@ mmap_unix_file(struct file *file, struct if (result != 0) { drop_exclusive_access(uf_info); up(&uf_info->write); + reiser4_exit_context(ctx); return result; } @@ -2051,6 +2348,7 @@ mmap_unix_file(struct file *file, struct if (result) { drop_exclusive_access(uf_info); up(&uf_info->write); + reiser4_exit_context(ctx); return result; } } @@ -2065,16 +2363,15 @@ mmap_unix_file(struct file *file, struct drop_exclusive_access(uf_info); up(&uf_info->write); + reiser4_exit_context(ctx); return result; } -static ssize_t -write_file(hint_t *hint, - struct file *file, /* file to write to */ - const char *buf, /* address of user-space buffer */ - size_t count, /* number of bytes to write */ - loff_t *off /* position in file to write to */, - int exclusive) +static ssize_t write_file(hint_t * hint, struct file *file, /* file to write to */ + const char __user *buf, /* address of user-space buffer */ + size_t count, /* number of bytes to write */ + loff_t * off /* position in file to write to */ , + int exclusive) { struct inode *inode; ssize_t written; /* amount actually written so far */ @@ -2103,16 +2400,23 @@ write_file(hint_t *hint, return written; } -/* plugin->u.file.write */ -reiser4_internal ssize_t -write_unix_file(struct file *file, /* file to write to */ - const char *buf, /* address of user-space buffer */ - size_t write_amount, /* number of bytes to write */ - loff_t *off /* position in file to write to */) +/** + * write_unix_file - write of struct file_operations + * @file: file to write to + * @buf: address of user-space buffer + * @write_amount: number of bytes to write + * @off: position in file to write to + * + * This is implementation of vfs's write method of struct file_operations for + * unix file plugin. + */ +ssize_t write_unix_file(struct file *file, const char __user *buf, + size_t write_amount, loff_t *off) { + reiser4_context *ctx; int result; struct inode *inode; - hint_t hint; + hint_t *hint; unix_file_info_t *uf_info; struct page *pages[NR_PAGES_TO_PIN]; int nr_pages; @@ -2124,15 +2428,21 @@ write_unix_file(struct file *file, /* fi return 0; inode = file->f_dentry->d_inode; + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + assert("vs-947", !inode_get_flag(inode, REISER4_NO_SD)); uf_info = unix_file_inode_data(inode); - down(&uf_info->write); + down(&uf_info->write); result = generic_write_checks(file, off, &write_amount, 0); if (result) { up(&uf_info->write); + context_set_commit_async(ctx); + reiser4_exit_context(ctx); return result; } @@ -2147,11 +2457,14 @@ write_unix_file(struct file *file, /* fi if (result) { current->backing_dev_info = NULL; up(&uf_info->write); + context_set_commit_async(ctx); + reiser4_exit_context(ctx); return result; } } - if (inode_get_flag(inode, REISER4_HAS_MMAP) && uf_info->container == UF_CONTAINER_TAILS) { + if (inode_get_flag(inode, REISER4_HAS_MMAP) + && uf_info->container == UF_CONTAINER_TAILS) { /* file built of tails was mmaped. So, there might be faultin-ed pages filled by tail item contents and mapped to process address space. @@ -2170,7 +2483,9 @@ write_unix_file(struct file *file, /* fi drop_exclusive_access(uf_info); if (result) { current->backing_dev_info = NULL; - up(&uf_info->write); + up(&uf_info->write); + context_set_commit_async(ctx); + reiser4_exit_context(ctx); return result; } } @@ -2183,15 +2498,32 @@ write_unix_file(struct file *file, /* fi if (result != 0) { current->backing_dev_info = NULL; up(&uf_info->write); + context_set_commit_async(ctx); + reiser4_exit_context(ctx); return result; } grab_space_enable(); + hint = kmalloc(sizeof(*hint), GFP_KERNEL); + if (hint == NULL) { + current->backing_dev_info = NULL; + up(&uf_info->write); + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return RETERR(-ENOMEM); + } + /* get seal and coord sealed with it from reiser4 private data of * struct file */ - result = load_file_hint(file, &hint); - if (result) + result = load_file_hint(file, hint); + if (result) { + current->backing_dev_info = NULL; + up(&uf_info->write); + kfree(hint); + context_set_commit_async(ctx); + reiser4_exit_context(ctx); return result; + } left = write_amount; count = 0; @@ -2212,7 +2544,9 @@ write_unix_file(struct file *file, /* fi if (user_space) { to_write = get_nr_pages_nr_bytes(addr, left, &nr_pages); - nr_pages = reiser4_get_user_pages(pages, addr, nr_pages, WRITE); + nr_pages = + reiser4_get_user_pages(pages, addr, nr_pages, + WRITE); if (nr_pages < 0) { result = nr_pages; break; @@ -2232,7 +2566,7 @@ write_unix_file(struct file *file, /* fi } all_grabbed2free(); - written = write_file(&hint, file, buf, to_write, off, excl); + written = write_file(hint, file, buf, to_write, off, excl); if (user_space) reiser4_put_user_pages(pages, nr_pages); @@ -2243,12 +2577,12 @@ write_unix_file(struct file *file, /* fi /* With no locks held we can commit atoms in attempt to recover * free space. */ - if ((ssize_t)written == -ENOSPC && try_free_space) { + if ((ssize_t) written == -ENOSPC && try_free_space) { txnmgr_force_commit_all(inode->i_sb, 0); try_free_space = 0; continue; } - if ((ssize_t)written < 0) { + if ((ssize_t) written < 0) { result = written; break; } @@ -2261,52 +2595,104 @@ write_unix_file(struct file *file, /* fi if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { txn_restart_current(); - result = sync_unix_file(inode, 0/* data and stat data */); + result = + sync_unix_file(file, file->f_dentry, + 0 /* data and stat data */ ); if (result) warning("reiser4-7", "failed to sync file %llu", (unsigned long long)get_inode_oid(inode)); } - save_file_hint(file, &hint); + save_file_hint(file, hint); + kfree(hint); up(&uf_info->write); - current->backing_dev_info = 0; + current->backing_dev_info = NULL; + + context_set_commit_async(ctx); + reiser4_exit_context(ctx); return count ? count : result; } -/* plugin->u.file.release() convert all extent items into tail items if - necessary */ -reiser4_internal int -release_unix_file(struct inode *object, struct file *file) +/* this is implementation of vfs's release method of struct + file_operations for unix file plugin + convert all extent items into tail items if necessary */ +int release_unix_file(struct inode *inode, struct file *file) { + reiser4_context *ctx; unix_file_info_t *uf_info; int result; + int in_reiser4; + + in_reiser4 = is_in_reiser4_context(); + + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); - uf_info = unix_file_inode_data(object); result = 0; + if (in_reiser4 == 0) { + uf_info = unix_file_inode_data(inode); - down(&uf_info->write); - get_exclusive_access(uf_info); - if (atomic_read(&file->f_dentry->d_count) == 1 && - uf_info->container == UF_CONTAINER_EXTENTS && - !should_have_notail(uf_info, object->i_size) && - !rofs_inode(object)) { - result = extent2tail(uf_info); - if (result != 0) { - warning("nikita-3233", "Failed to convert in %s (%llu)", - __FUNCTION__, (unsigned long long)get_inode_oid(object)); + down(&uf_info->write); + get_exclusive_access(uf_info); + if (atomic_read(&file->f_dentry->d_count) == 1 && + uf_info->container == UF_CONTAINER_EXTENTS && + !should_have_notail(uf_info, inode->i_size) && + !rofs_inode(inode)) { + result = extent2tail(uf_info); + if (result != 0) { + warning("nikita-3233", + "Failed to convert in %s (%llu)", + __FUNCTION__, + (unsigned long long) + get_inode_oid(inode)); + } } + drop_exclusive_access(uf_info); + up(&uf_info->write); + } else { + /* + we are within reiser4 context already. How latter is + possible? Simple: + + (gdb) bt + #0 get_exclusive_access () + #2 0xc01e56d3 in release_unix_file () + #3 0xc01c3643 in reiser4_release () + #4 0xc014cae0 in __fput () + #5 0xc013ffc3 in remove_vm_struct () + #6 0xc0141786 in exit_mmap () + #7 0xc0118480 in mmput () + #8 0xc0133205 in oom_kill () + #9 0xc01332d1 in out_of_memory () + #10 0xc013bc1d in try_to_free_pages () + #11 0xc013427b in __alloc_pages () + #12 0xc013f058 in do_anonymous_page () + #13 0xc013f19d in do_no_page () + #14 0xc013f60e in handle_mm_fault () + #15 0xc01131e5 in do_page_fault () + #16 0xc0104935 in error_code () + #17 0xc025c0c6 in __copy_to_user_ll () + #18 0xc01d496f in read_tail () + #19 0xc01e4def in read_unix_file () + #20 0xc01c3504 in reiser4_read () + #21 0xc014bd4f in vfs_read () + #22 0xc014bf66 in sys_read () + */ + warning("vs-44", "out of memory?"); } - drop_exclusive_access(uf_info); - up(&uf_info->write); - return 0; + + reiser4_free_file_fsdata(file); + + reiser4_exit_context(ctx); + return result; } -static void -set_file_notail(struct inode *inode) +static void set_file_notail(struct inode *inode) { reiser4_inode *state; - formatting_plugin *tplug; + formatting_plugin *tplug; state = reiser4_inode_data(inode); tplug = formatting_plugin_by_id(NEVER_TAILS_FORMATTING_ID); @@ -2316,18 +2702,17 @@ set_file_notail(struct inode *inode) } /* if file is built of tails - convert it to extents */ -static int -unpack(struct inode *inode, int forever) +static int unpack(struct inode *inode, int forever) { - int result = 0; + int result = 0; unix_file_info_t *uf_info; - uf_info = unix_file_inode_data(inode); assert("vs-1628", ea_obtained(uf_info)); result = find_file_state(uf_info); - assert("vs-1074", ergo(result == 0, uf_info->container != UF_CONTAINER_UNKNOWN)); + assert("vs-1074", + ergo(result == 0, uf_info->container != UF_CONTAINER_UNKNOWN)); if (result == 0) { if (uf_info->container == UF_CONTAINER_TAILS) result = tail2extent(uf_info); @@ -2337,7 +2722,8 @@ unpack(struct inode *inode, int forever) __u64 tograb; grab_space_enable(); - tograb = inode_file_plugin(inode)->estimate.update(inode); + tograb = + inode_file_plugin(inode)->estimate.update(inode); result = reiser4_grab_space(tograb, BA_CAN_COMMIT); if (result == 0) update_atime(inode); @@ -2347,16 +2733,24 @@ unpack(struct inode *inode, int forever) return result; } -/* plugin->u.file.ioctl */ -reiser4_internal int -ioctl_unix_file(struct inode *inode, struct file *filp UNUSED_ARG, unsigned int cmd, unsigned long arg UNUSED_ARG) +/* implentation of vfs' ioctl method of struct file_operations for unix file + plugin +*/ +int +ioctl_unix_file(struct inode *inode, struct file *filp UNUSED_ARG, + unsigned int cmd, unsigned long arg UNUSED_ARG) { + reiser4_context *ctx; int result; + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + switch (cmd) { case REISER4_IOC_UNPACK: get_exclusive_access(unix_file_inode_data(inode)); - result = unpack(inode, 1 /* forever */); + result = unpack(inode, 1 /* forever */ ); drop_exclusive_access(unix_file_inode_data(inode)); break; @@ -2364,76 +2758,92 @@ ioctl_unix_file(struct inode *inode, str result = RETERR(-ENOSYS); break; } + reiser4_exit_context(ctx); return result; } -/* plugin->u.file.get_block */ -reiser4_internal int -get_block_unix_file(struct inode *inode, - sector_t block, struct buffer_head *bh_result, int create UNUSED_ARG) +/* implentation of vfs' bmap method of struct address_space_operations for unix + file plugin +*/ +sector_t bmap_unix_file(struct address_space * mapping, sector_t lblock) { - int result; + reiser4_context *ctx; + sector_t result; reiser4_key key; coord_t coord; lock_handle lh; + struct inode *inode; item_plugin *iplug; + sector_t block; - assert("vs-1091", create == 0); + inode = mapping->host; - key_by_inode_unix_file(inode, (loff_t) block * current_blocksize, &key); + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + key_by_inode_and_offset_common(inode, + (loff_t) lblock * current_blocksize, + &key); init_lh(&lh); - result = find_file_item_nohint(&coord, &lh, &key, ZNODE_READ_LOCK, inode); + result = + find_file_item_nohint(&coord, &lh, &key, ZNODE_READ_LOCK, inode); if (cbk_errored(result)) { done_lh(&lh); + reiser4_exit_context(ctx); return result; } - /*coord_clear_iplug(&coord);*/ result = zload(coord.node); if (result) { done_lh(&lh); + reiser4_exit_context(ctx); return result; } + iplug = item_plugin_by_coord(&coord); - if (iplug->s.file.get_block) - result = iplug->s.file.get_block(&coord, block, bh_result); - else + if (iplug->s.file.get_block) { + result = iplug->s.file.get_block(&coord, lblock, &block); + if (result == 0) + result = block; + } else result = RETERR(-EINVAL); zrelse(coord.node); done_lh(&lh); + reiser4_exit_context(ctx); return result; } -/* plugin->u.file.flow_by_inode - initialize flow (key, length, buf, etc) */ -reiser4_internal int -flow_by_inode_unix_file(struct inode *inode /* file to build flow for */ , - char *buf /* user level buffer */ , - int user /* 1 if @buf is of user space, 0 - if it is kernel space */ , - loff_t size /* buffer size */ , - loff_t off /* offset to start operation(read/write) from */ , - rw_op op /* READ or WRITE */ , - flow_t *flow /* resulting flow */ ) +/** + * flow_by_inode_unix_file - initizlize structure flow + * @inode: inode of file for which read or write is abou + * @buf: buffer to perform read to or write from + * @user: flag showing whether @buf is user space or kernel space + * @size: size of buffer @buf + * @off: start offset fro read or write + * @op: READ or WRITE + * @flow: + * + * Initializes fields of @flow: key, size of data, i/o mode (read or write). + */ +int flow_by_inode_unix_file(struct inode *inode, + const char __user *buf, int user, + loff_t size, loff_t off, + rw_op op, flow_t *flow) { assert("nikita-1100", inode != NULL); flow->length = size; - flow->data = buf; + memcpy(&flow->data, &buf, sizeof(buf)); flow->user = user; flow->op = op; assert("nikita-1931", inode_file_plugin(inode) != NULL); - assert("nikita-1932", inode_file_plugin(inode)->key_by_inode == key_by_inode_unix_file); + assert("nikita-1932", + inode_file_plugin(inode)->key_by_inode == + key_by_inode_and_offset_common); /* calculate key of write position and insert it into flow->key */ - return key_by_inode_unix_file(inode, off, &flow->key); -} - -/* plugin->u.file.key_by_inode */ -reiser4_internal int -key_by_inode_unix_file(struct inode *inode, loff_t off, reiser4_key *key) -{ - return key_by_inode_and_offset_common(inode, off, key); + return key_by_inode_and_offset_common(inode, off, &flow->key); } /* plugin->u.file.set_plug_in_sd = NULL @@ -2447,9 +2857,9 @@ key_by_inode_unix_file(struct inode *ino /* plugin->u.file.owns_item this is common_file_owns_item with assertion */ /* Audited by: green(2002.06.15) */ -reiser4_internal int -owns_item_unix_file(const struct inode *inode /* object to check against */ , - const coord_t *coord /* coord to check */ ) +int +owns_item_unix_file(const struct inode *inode /* object to check against */ , + const coord_t * coord /* coord to check */ ) { int result; @@ -2464,8 +2874,7 @@ owns_item_unix_file(const struct inode * return 1; } -static int -setattr_truncate(struct inode *inode, struct iattr *attr) +static int setattr_truncate(struct inode *inode, struct iattr *attr) { int result; int s_result; @@ -2491,7 +2900,8 @@ setattr_truncate(struct inode *inode, st s_result = safe_link_grab(tree, BA_CAN_COMMIT); if (s_result == 0) - s_result = safe_link_del(tree, get_inode_oid(inode), SAFE_TRUNCATE); + s_result = + safe_link_del(tree, get_inode_oid(inode), SAFE_TRUNCATE); if (s_result != 0) { warning("nikita-3417", "Cannot kill safelink %lli: %i", (unsigned long long)get_inode_oid(inode), s_result); @@ -2504,33 +2914,39 @@ setattr_truncate(struct inode *inode, st /* plugin->u.file.setattr method */ /* This calls inode_setattr and if truncate is in effect it also takes exclusive inode access to avoid races */ -reiser4_internal int -setattr_unix_file(struct inode *inode, /* Object to change attributes */ - struct iattr *attr /* change description */ ) +int setattr_unix_file(struct dentry *dentry, /* Object to change attributes */ + struct iattr *attr /* change description */ ) { int result; if (attr->ia_valid & ATTR_SIZE) { - /* truncate does reservation itself and requires exclusive - * access obtained */ + reiser4_context *ctx; unix_file_info_t *uf_info; - uf_info = unix_file_inode_data(inode); + /* truncate does reservation itself and requires exclusive + access obtained */ + ctx = init_context(dentry->d_inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + uf_info = unix_file_inode_data(dentry->d_inode); down(&uf_info->write); get_exclusive_access(uf_info); - result = setattr_truncate(inode, attr); + result = setattr_truncate(dentry->d_inode, attr); drop_exclusive_access(uf_info); up(&uf_info->write); + context_set_commit_async(ctx); + reiser4_exit_context(ctx); } else - result = setattr_common(inode, attr); + result = setattr_common(dentry, attr); return result; } /* plugin->u.file.init_inode_data */ -reiser4_internal void +void init_inode_data_unix_file(struct inode *inode, - reiser4_object_create_data *crd, int create) + reiser4_object_create_data * crd, int create) { unix_file_info_t *data; @@ -2542,166 +2958,83 @@ init_inode_data_unix_file(struct inode * data->exclusive_use = 0; #if REISER4_DEBUG - data->ea_owner = 0; + data->ea_owner = NULL; atomic_set(&data->nr_neas, 0); #endif init_inode_ordering(inode, crd, create); } -/* plugin->u.file.pre_delete - - We need this because generic_delete_inode calls truncate_inode_pages before - filesystem's delete_inode method. As result of this, reiser4 tree may have - unallocated extents which do not have pages pointed by them (those pages are - removed by truncate_inode_pages), which may confuse flush code. The solution - for this problem is to call pre_delete method from reiser4_put_inode to - remove file items together with corresponding pages. Generic_delete_inode - will call truncate_inode_pages which will do nothing and - reiser4_delete_inode which completes file deletion by removing stat data - from the tree. - This method is to be called from reiser4_put_inode when file is already - unlinked and iput is about to drop last reference to inode. If nfsd manages - to iget the file after pre_delete started, it will either be able to access - a file content (if it will get access to file earlier than pre_delete) or it - will get file truncated to 0 size if pre_delete goes first -*/ -reiser4_internal int -pre_delete_unix_file(struct inode *inode) +/** + * delete_object_unix_file - delete_object of file_plugin + * @inode: inode to be deleted + * + * Truncates file to length 0, removes stat data and safe link. + */ +int delete_object_unix_file(struct inode *inode) { unix_file_info_t *uf_info; int result; - txn_restart_current(); + assert("", (get_current_context() && + get_current_context()->trans->atom == NULL)); + + if (inode_get_flag(inode, REISER4_NO_SD)) + return 0; - /* FIXME: put comment here */ + /* truncate file bogy first */ uf_info = unix_file_inode_data(inode); get_exclusive_access(uf_info); - result = truncate_file_body(inode, 0/* size */); + result = truncate_file_body(inode, 0 /* size */ ); drop_exclusive_access(uf_info); - return result; -} - -/* Reads @count bytes from @file and calls @actor for every page read. This is - needed for loop back devices support. */ -reiser4_internal ssize_t sendfile_common ( - struct file *file, loff_t *ppos, size_t count, read_actor_t actor, void __user *target) -{ - file_plugin *fplug; - struct inode *inode; - read_descriptor_t desc; - struct page *page = NULL; - int ret = 0; - - assert("umka-3108", file != NULL); - - inode = file->f_dentry->d_inode; - - desc.error = 0; - desc.written = 0; - desc.arg.data = target; - desc.count = count; - - fplug = inode_file_plugin(inode); - if (fplug->readpage == NULL) - return RETERR(-EINVAL); - - while (desc.count != 0) { - unsigned long read_request_size; - unsigned long index; - unsigned long offset; - loff_t file_size = i_size_read(inode); - - if (*ppos >= file_size) - break; - - index = *ppos >> PAGE_CACHE_SHIFT; - offset = *ppos & ~PAGE_CACHE_MASK; - - page_cache_readahead(inode->i_mapping, &file->f_ra, file, offset, (file_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT); - - /* determine valid read request size. */ - read_request_size = PAGE_CACHE_SIZE - offset; - if (read_request_size > desc.count) - read_request_size = desc.count; - if (*ppos + read_request_size >= file_size) { - read_request_size = file_size - *ppos; - if (read_request_size == 0) - break; - } - page = grab_cache_page(inode->i_mapping, index); - if (unlikely(page == NULL)) { - desc.error = RETERR(-ENOMEM); - break; - } - - if (PageUptodate(page)) - /* process locked, up-to-date page by read actor */ - goto actor; - - ret = fplug->readpage(file, page); - if (ret != 0) { - SetPageError(page); - ClearPageUptodate(page); - desc.error = ret; - goto fail_locked_page; - } - - lock_page(page); - if (!PageUptodate(page)) { - desc.error = RETERR(-EIO); - goto fail_locked_page; - } - - actor: - ret = actor(&desc, page, offset, read_request_size); - unlock_page(page); - page_cache_release(page); - - (*ppos) += ret; - - if (ret != read_request_size) - break; - } - if (0) { - fail_locked_page: - unlock_page(page); - page_cache_release(page); - } - - update_atime(inode); + if (result) + warning("", "failed to truncate file (%llu) on removal: %d", + get_inode_oid(inode), result); - if (desc.written) - return desc.written; - return desc.error; + /* remove stat data and safe link */ + return delete_object_common(inode); } -reiser4_internal ssize_t sendfile_unix_file(struct file *file, loff_t *ppos, size_t count, - read_actor_t actor, void __user *target) +/* Reads @count bytes from @file and calls @actor for every page read. This is + needed for loop back devices support. */ +ssize_t +sendfile_unix_file(struct file *file, loff_t *ppos, size_t count, + read_actor_t actor, void *target) { - ssize_t ret; + reiser4_context *ctx; + ssize_t result; struct inode *inode; - unix_file_info_t *ufo; + unix_file_info_t *uf_info; inode = file->f_dentry->d_inode; - ufo = unix_file_inode_data(inode); + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); down(&inode->i_sem); inode_set_flag(inode, REISER4_HAS_MMAP); up(&inode->i_sem); - get_nonexclusive_access(ufo, 0); - ret = sendfile_common(file, ppos, count, actor, target); - drop_nonexclusive_access(ufo); - return ret; + uf_info = unix_file_inode_data(inode); + get_nonexclusive_access(uf_info, 0); + result = do_sendfile(file, ppos, count, actor, target); + drop_nonexclusive_access(uf_info); + reiser4_exit_context(ctx); + return result; } -reiser4_internal int prepare_write_unix_file(struct file *file, struct page *page, - unsigned from, unsigned to) +int +prepare_write_unix_file(struct file *file, struct page *page, + unsigned from, unsigned to) { + reiser4_context *ctx; unix_file_info_t *uf_info; int ret; + ctx = init_context(file->f_dentry->d_inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + uf_info = unix_file_inode_data(file->f_dentry->d_inode); get_exclusive_access(uf_info); ret = find_file_state(uf_info); @@ -2709,9 +3042,13 @@ reiser4_internal int prepare_write_unix_ if (uf_info->container == UF_CONTAINER_TAILS) ret = -EINVAL; else - ret = prepare_write_common(file, page, from, to); + ret = do_prepare_write(file, page, from, to); } drop_exclusive_access(uf_info); + + /* don't commit transaction under inode semaphore */ + context_set_commit_async(ctx); + reiser4_exit_context(ctx); return ret; } diff -puN fs/reiser4/plugin/file/file.h~reiser4-big-update fs/reiser4/plugin/file/file.h --- devel/fs/reiser4/plugin/file/file.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/file/file.h 2005-09-15 19:51:08.000000000 -0700 @@ -1,45 +1,56 @@ /* Copyright 2001, 2002, 2003, 2004 by Hans Reiser, licensing governed by * reiser4/README */ +/* this file contains declarations of methods implementing file plugins + (UNIX_FILE_PLUGIN_ID, SYMLINK_FILE_PLUGIN_ID and CRC_FILE_PLUGIN_ID) */ + #if !defined( __REISER4_FILE_H__ ) #define __REISER4_FILE_H__ -/* declarations of functions implementing file plugin for unix file plugin */ -int truncate_unix_file(struct inode *, loff_t size); -int readpage_unix_file(void *, struct page *); -int capturepage_unix_file(struct page *); -int capture_unix_file(struct inode *, struct writeback_control *); -ssize_t read_unix_file(struct file *, char *buf, size_t size, loff_t *off); -ssize_t write_unix_file(struct file *, const char *buf, size_t size, loff_t *off); -int release_unix_file(struct inode *inode, struct file *); -int ioctl_unix_file(struct inode *, struct file *, unsigned int cmd, unsigned long arg); -int mmap_unix_file(struct file *, struct vm_area_struct *vma); -int get_block_unix_file(struct inode *, sector_t block, struct buffer_head *bh_result, int create); -int flow_by_inode_unix_file(struct inode *, char *buf, int user, loff_t, loff_t, rw_op, flow_t *); -int key_by_inode_unix_file(struct inode *, loff_t off, reiser4_key *); -int owns_item_unix_file(const struct inode *, const coord_t *); -int setattr_unix_file(struct inode *, struct iattr *); -void init_inode_data_unix_file(struct inode *, reiser4_object_create_data *, int create); -int pre_delete_unix_file(struct inode *); - -extern ssize_t sendfile_common ( - struct file *file, loff_t *ppos, size_t count, read_actor_t actor, void __user *target); -extern ssize_t sendfile_unix_file ( - struct file *file, loff_t *ppos, size_t count, read_actor_t actor, void __user *target); -extern int prepare_write_unix_file (struct file *, struct page *, unsigned, unsigned); +/* declarations of functions implementing UNIX_FILE_PLUGIN_ID file plugin */ -int sync_unix_file(struct inode *, int datasync); +/* inode operations */ +int setattr_unix_file(struct dentry *, struct iattr *); - -/* all the write into unix file is performed by item write method. Write method of unix file plugin only decides which - item plugin (extent or tail) and in which mode (one from the enum below) to call */ +/* file operations */ +ssize_t read_unix_file(struct file *, char __user *buf, size_t read_amount, + loff_t *off); +ssize_t write_unix_file(struct file *, const char __user *buf, size_t write_amount, + loff_t * off); +int ioctl_unix_file(struct inode *, struct file *, unsigned int cmd, + unsigned long arg); +int mmap_unix_file(struct file *, struct vm_area_struct *); +int release_unix_file(struct inode *, struct file *); +int sync_unix_file(struct file *, struct dentry *, int datasync); +ssize_t sendfile_unix_file(struct file *, loff_t *ppos, size_t count, + read_actor_t, void *target); + +/* address space operations */ +int readpage_unix_file(struct file *, struct page *); +int writepages_unix_file(struct address_space *, struct writeback_control *); +int prepare_write_unix_file(struct file *, struct page *, unsigned from, + unsigned to); +int commit_write_unix_file(struct file *, struct page *, unsigned from, + unsigned to); +sector_t bmap_unix_file(struct address_space *, sector_t lblock); + +/* file plugin operations */ +int flow_by_inode_unix_file(struct inode *, const char __user *buf, + int user, loff_t, loff_t, rw_op, flow_t *); +int owns_item_unix_file(const struct inode *, const coord_t *); +void init_inode_data_unix_file(struct inode *, reiser4_object_create_data *, + int create); +int delete_object_unix_file(struct inode *); + +/* all the write into unix file is performed by item write method. Write method + of unix file plugin only decides which item plugin (extent or tail) and in + which mode (one from the enum below) to call */ typedef enum { FIRST_ITEM = 1, APPEND_ITEM = 2, OVERWRITE_ITEM = 3 } write_mode_t; - /* unix file may be in one the following states */ typedef enum { UF_CONTAINER_UNKNOWN = 0, @@ -78,13 +89,10 @@ typedef struct unix_file_info { void *ea_owner; atomic_t nr_neas; void *last_reader; -#ifdef CONFIG_FRAME_POINTER - void *where[5]; -#endif #endif } unix_file_info_t; -struct unix_file_info *unix_file_inode_data(const struct inode * inode); +struct unix_file_info *unix_file_inode_data(const struct inode *inode); void get_exclusive_access(unix_file_info_t *); void drop_exclusive_access(unix_file_info_t *); void get_nonexclusive_access(unix_file_info_t *, int); @@ -105,7 +113,9 @@ struct uf_coord { } extension; }; +#include "../../forward.h" #include "../../seal.h" +#include "../../lock.h" /* structure used to speed up file operations (reads and writes). It contains * a seal over last file item accessed. */ @@ -114,21 +124,24 @@ struct hint { uf_coord_t ext_coord; loff_t offset; znode_lock_mode mode; -#if REISER4_DEBUG && defined(CONFIG_FRAME_POINTER) - void *bt[5]; -#endif + lock_handle lh; }; void set_hint(hint_t *, const reiser4_key *, znode_lock_mode); int hint_is_set(const hint_t *); void unset_hint(hint_t *); -int hint_validate(hint_t *, const reiser4_key *, int check_key, znode_lock_mode); +int hint_validate(hint_t *, const reiser4_key *, int check_key, + znode_lock_mode); +int update_file_size(struct inode *, reiser4_key *, int update_sd); +int cut_file_items(struct inode *, loff_t new_size, int update_sd, + loff_t cur_size, int (*update_actor) (struct inode *, + reiser4_key *, int)); #if REISER4_DEBUG /* return 1 is exclusive access is obtained, 0 - otherwise */ -static inline int ea_obtained(unix_file_info_t *uf_info) +static inline int ea_obtained(unix_file_info_t * uf_info) { int ret; @@ -140,6 +153,49 @@ static inline int ea_obtained(unix_file_ #endif +/* declarations of functions implementing SYMLINK_FILE_PLUGIN_ID file plugin */ +int create_symlink(struct inode *symlink, struct inode *dir, + reiser4_object_create_data *); +void destroy_inode_symlink(struct inode *); + +/* declarations of functions implementing CRC_FILE_PLUGIN_ID file plugin */ + +/* inode operations */ +int setattr_cryptcompress(struct dentry *, struct iattr *); + +/* file operations */ +ssize_t read_cryptcompress(struct file *, char __user *buf, size_t read_amount, + loff_t * off); +ssize_t write_cryptcompress(struct file *, const char __user *buf, size_t write_amount, + loff_t * off); +int mmap_cryptcompress(struct file *, struct vm_area_struct *); + +/* address space operations */ +extern int readpage_cryptcompress(struct file *, struct page *); +extern int writepages_cryptcompress(struct address_space *, + struct writeback_control *); +extern void readpages_cryptcompress(struct file *, struct address_space *, + struct list_head *pages); +extern sector_t bmap_cryptcompress(struct address_space *, sector_t lblock); + + +/* file plugin operations */ +int flow_by_inode_cryptcompress(struct inode *, const char __user *buf, + int user, loff_t, loff_t, rw_op, flow_t *); +int key_by_inode_cryptcompress(struct inode *, loff_t off, reiser4_key *); +int create_cryptcompress(struct inode *, struct inode *, + reiser4_object_create_data *); +int delete_cryptcompress(struct inode *); +void init_inode_data_cryptcompress(struct inode *, reiser4_object_create_data *, + int create); +int cut_tree_worker_cryptcompress(tap_t *, const reiser4_key * from_key, + const reiser4_key * to_key, + reiser4_key * smallest_removed, + struct inode *object, int truncate, + int *progress); +void destroy_inode_cryptcompress(struct inode *); + +extern reiser4_plugin_ops cryptcompress_plugin_ops; /* __REISER4_FILE_H__ */ #endif diff -puN fs/reiser4/plugin/file/funcs.h~reiser4-big-update fs/reiser4/plugin/file/funcs.h --- devel/fs/reiser4/plugin/file/funcs.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/file/funcs.h 2005-09-15 19:51:08.000000000 -0700 @@ -18,8 +18,8 @@ int goto_right_neighbor(coord_t *, lock_ int find_or_create_extent(struct page *); write_mode_t how_to_write(uf_coord_t *, const reiser4_key *); -extern inline int -cbk_errored(int cbk_result) +extern inline int cbk_errored(int cbk_result) { - return (cbk_result != CBK_COORD_NOTFOUND && cbk_result != CBK_COORD_FOUND); + return (cbk_result != CBK_COORD_NOTFOUND + && cbk_result != CBK_COORD_FOUND); } diff -puN fs/reiser4/plugin/file/invert.c~reiser4-big-update fs/reiser4/plugin/file/invert.c --- devel/fs/reiser4/plugin/file/invert.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/file/invert.c 2005-09-15 19:51:08.000000000 -0700 @@ -155,7 +155,6 @@ Then a read will return: The other parsing results give malformed signature that aborts READ method and releases all resources. - Format of subfile (entry) signature: "START_MAGIC"<>(TYPE="...",LOOKUP_ARG="...")SUBFILE_BODY"END_MAGIC" @@ -251,69 +250,57 @@ typedef struct subfile_header { /* functions to get/set fields of flow header */ -static void -fl_set_magic(flow_header * fh, __u32 value) +static void fl_set_magic(flow_header * fh, __u32 value) { cputod32(value, &fh->fh_magic); } -static __u32 -fl_get_magic(flow_header * fh) +static __u32 fl_get_magic(flow_header * fh) { return d32tocpu(&fh->fh_magic); } -static void -fl_set_number(flow_header * fh, __u16 value) +static void fl_set_number(flow_header * fh, __u16 value) { cputod16(value, &fh->fh_nr); } -static unsigned -fl_get_number(flow_header * fh) +static unsigned fl_get_number(flow_header * fh) { return d16tocpu(&fh->fh_nr); } /* functions to get/set fields of subfile header */ -static void -sh_set_magic(subfile_header * sh, __u32 value) +static void sh_set_magic(subfile_header * sh, __u32 value) { cputod32(value, &sh->sh_magic); } -static __u32 -sh_get_magic(subfile_header * sh) +static __u32 sh_get_magic(subfile_header * sh) { return d32tocpu(&sh->sh_magic); } -static void -sh_set_type(subfile_header * sh, __u16 value) +static void sh_set_type(subfile_header * sh, __u16 value) { cputod16(value, &sh->sh_magic); } -static unsigned -sh_get_type(subfile_header * sh) +static unsigned sh_get_type(subfile_header * sh) { return d16tocpu(&sh->sh_magic); } -static void -sh_set_arg_len(subfile_header * sh, __u16 value) +static void sh_set_arg_len(subfile_header * sh, __u16 value) { cputod16(value, &sh->sh_arg_len); } -static unsigned -sh_get_arg_len(subfile_header * sh) +static unsigned sh_get_arg_len(subfile_header * sh) { return d16tocpu(&sh->sh_arg_len); } -static void -sh_set_body_len(subfile_header * sh, __u32 value) +static void sh_set_body_len(subfile_header * sh, __u32 value) { cputod32(value, &sh->sh_body_len); } -static __u32 -sh_get_body_len(subfile_header * sh) +static __u32 sh_get_body_len(subfile_header * sh) { return d32tocpu(&sh->sh_body_len); } @@ -339,12 +326,11 @@ struct inv_entry { /* allocate and init invert entry */ -static struct inv_entry * -allocate_inv_entry(void) +static struct inv_entry *allocate_inv_entry(void) { struct inv_entry *inv_entry; - inv_entry = reiser4_kmalloc(sizeof (struct inv_entry), GFP_KERNEL); + inv_entry = reiser4_kmalloc(sizeof(struct inv_entry), GFP_KERNEL); if (!inv_entry) return ERR_PTR(RETERR(-ENOMEM)); inv_entry->ie_file = NULL; @@ -353,8 +339,7 @@ allocate_inv_entry(void) return inv_entry; } -static int -put_inv_entry(struct inv_entry *ientry) +static int put_inv_entry(struct inv_entry *ientry) { int result = 0; @@ -371,14 +356,13 @@ put_inv_entry(struct inv_entry *ientry) return result; } -static int -allocate_incore_sd_base(struct inv_entry *inv_entry) +static int allocate_incore_sd_base(struct inv_entry *inv_entry) { struct incore_sd_base *isd_base assert("edward-98", inv_entry != NULL); assert("edward-99", inv_entry->ie_inode = NULL); assert("edward-100", inv_entry->ie_sd = NULL); - isd_base = reiser4_kmalloc(sizeof (struct incore_sd_base), GFP_KERNEL); + isd_base = reiser4_kmalloc(sizeof(struct incore_sd_base), GFP_KERNEL); if (!isd_base) return RETERR(-ENOMEM); inv_entry->ie_sd = isd_base; @@ -390,8 +374,7 @@ allocate_incore_sd_base(struct inv_entry Copies data from on-disk stat-data format into light-weight analog of inode . Doesn't hanlde stat-data extensions. */ -static void -sd_base_load(struct inv_entry *inv_entry, char *sd) +static void sd_base_load(struct inv_entry *inv_entry, char *sd) { reiser4_stat_data_base *sd_base; @@ -408,8 +391,7 @@ sd_base_load(struct inv_entry *inv_entry /* initialise incore stat-data */ -static void -init_incore_sd_base(struct inv_entry *inv_entry, coord_t * coord) +static void init_incore_sd_base(struct inv_entry *inv_entry, coord_t * coord) { reiser4_plugin *plugin = item_plugin_by_coord(coord); void *body = item_body_by_coord(coord); @@ -425,12 +407,11 @@ init_incore_sd_base(struct inv_entry *in init and adds it into the list, we use lookup_sd_by_key() for light-weight files and VFS lookup by filename */ -int -get_inv_entry(struct inode *invert_inode, /* inode of invert's body */ - inv_entry_type type, /* LIGHT-WEIGHT or ORDINARY */ - const reiser4_key * key, /* key of invert entry stat-data */ - char *filename, /* filename of the file to be opened */ - int flags, int mode) +int get_inv_entry(struct inode *invert_inode, /* inode of invert's body */ + inv_entry_type type, /* LIGHT-WEIGHT or ORDINARY */ + const reiser4_key * key, /* key of invert entry stat-data */ + char *filename, /* filename of the file to be opened */ + int flags, int mode) { int result; struct inv_entry *ientry; @@ -449,7 +430,9 @@ get_inv_entry(struct inode *invert_inode init_coord(&coord); init_lh(&lh); - result = lookup_sd_by_key(tree_by_inode(invert_inode), ZNODE_READ_LOCK, &coord, &lh, key); + result = + lookup_sd_by_key(tree_by_inode(invert_inode), + ZNODE_READ_LOCK, &coord, &lh, key); if (result == 0) init_incore_sd_base(ientry, coord); @@ -473,8 +456,7 @@ get_inv_entry(struct inode *invert_inode /* takes inode of invert, reads the body of this invert, parses it, opens all invert entries and return pointer on the first inv_entry */ -struct inv_entry * -open_invert(struct file *invert_file) +struct inv_entry *open_invert(struct file *invert_file) { } diff -puN /dev/null fs/reiser4/plugin/file_ops.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/file_ops.c 2005-09-15 19:51:08.000000000 -0700 @@ -0,0 +1,251 @@ +/* Copyright 2005 by Hans Reiser, licensing governed by + reiser4/README */ + +/* this file contains typical implementations for some of methods of + struct file_operations and of struct address_space_operations +*/ + +#include "../inode.h" +#include "object.h" + +/* file operations */ + +/* implementation of vfs's llseek method of struct file_operations for + typical directory can be found in readdir_common.c +*/ +loff_t llseek_common_dir(struct file *, loff_t, int origin); + +/* implementation of vfs's readdir method of struct file_operations for + typical directory can be found in readdir_common.c +*/ +int readdir_common(struct file *, void *dirent, filldir_t); + +/* this is implementation of vfs's release method of struct file_operations for + typical directory +*/ +int release_dir_common(struct inode *inode, struct file *file) +{ + reiser4_free_file_fsdata(file); + return 0; +} + +/* this is common implementation of vfs's fsync method of struct + file_operations +*/ +int sync_common(struct file *file, struct dentry *dentry, int datasync) +{ + reiser4_context *ctx; + int result; + + ctx = init_context(dentry->d_inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + result = txnmgr_force_commit_all(dentry->d_inode->i_sb, 0); + + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return result; +} + +/* this is common implementation of vfs's sendfile method of struct + file_operations + + Reads @count bytes from @file and calls @actor for every page read. This is + needed for loop back devices support. +*/ +ssize_t +sendfile_common(struct file *file, loff_t *ppos, size_t count, + read_actor_t actor, void *target) +{ + reiser4_context *ctx; + ssize_t result; + + ctx = init_context(file->f_dentry->d_inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + result = do_sendfile(file, ppos, count, actor, target); + reiser4_exit_context(ctx); + return result; +} + +/* this is helper for sendfile_common and sendfile_unix_file + */ +ssize_t +do_sendfile(struct file *file, loff_t *ppos, size_t count, + read_actor_t actor, void *target) +{ + struct inode *inode; + read_descriptor_t desc; + struct page *page = NULL; + int ret = 0; + + assert("umka-3108", file != NULL); + + inode = file->f_dentry->d_inode; + + desc.error = 0; + desc.written = 0; + desc.arg.data = target; + desc.count = count; + + if (inode->i_mapping->a_ops->readpage) + return RETERR(-EINVAL); + + while (desc.count != 0) { + unsigned long read_request_size; + unsigned long index; + unsigned long offset; + loff_t file_size = i_size_read(inode); + + if (*ppos >= file_size) + break; + + index = *ppos >> PAGE_CACHE_SHIFT; + offset = *ppos & ~PAGE_CACHE_MASK; + + page_cache_readahead(inode->i_mapping, &file->f_ra, file, + offset, + (file_size + PAGE_CACHE_SIZE - + 1) >> PAGE_CACHE_SHIFT); + + /* determine valid read request size. */ + read_request_size = PAGE_CACHE_SIZE - offset; + if (read_request_size > desc.count) + read_request_size = desc.count; + if (*ppos + read_request_size >= file_size) { + read_request_size = file_size - *ppos; + if (read_request_size == 0) + break; + } + page = grab_cache_page(inode->i_mapping, index); + if (unlikely(page == NULL)) { + desc.error = RETERR(-ENOMEM); + break; + } + + if (PageUptodate(page)) + /* process locked, up-to-date page by read actor */ + goto actor; + + ret = inode->i_mapping->a_ops->readpage(file, page); + if (ret != 0) { + SetPageError(page); + ClearPageUptodate(page); + desc.error = ret; + goto fail_locked_page; + } + + lock_page(page); + if (!PageUptodate(page)) { + desc.error = RETERR(-EIO); + goto fail_locked_page; + } + + actor: + ret = actor(&desc, page, offset, read_request_size); + unlock_page(page); + page_cache_release(page); + + (*ppos) += ret; + + if (ret != read_request_size) + break; + } + + if (0) { + fail_locked_page: + unlock_page(page); + page_cache_release(page); + } + + update_atime(inode); + + if (desc.written) + return desc.written; + return desc.error; +} + +/* address space operations */ + +/* this is common implementation of vfs's prepare_write method of struct + address_space_operations +*/ +int +prepare_write_common(struct file *file, struct page *page, unsigned from, + unsigned to) +{ + reiser4_context *ctx; + int result; + + ctx = init_context(page->mapping->host->i_sb); + result = do_prepare_write(file, page, from, to); + + /* don't commit transaction under inode semaphore */ + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + + return result; +} + +/* this is helper for prepare_write_common and prepare_write_unix_file + */ +int +do_prepare_write(struct file *file, struct page *page, unsigned from, + unsigned to) +{ + int result; + file_plugin *fplug; + struct inode *inode; + + assert("umka-3099", file != NULL); + assert("umka-3100", page != NULL); + assert("umka-3095", PageLocked(page)); + + if (to - from == PAGE_CACHE_SIZE || PageUptodate(page)) + return 0; + + inode = page->mapping->host; + fplug = inode_file_plugin(inode); + + if (page->mapping->a_ops->readpage == NULL) + return RETERR(-EINVAL); + + result = page->mapping->a_ops->readpage(file, page); + if (result != 0) { + SetPageError(page); + ClearPageUptodate(page); + /* All reiser4 readpage() implementations should return the + * page locked in case of error. */ + assert("nikita-3472", PageLocked(page)); + } else { + /* + * ->readpage() either: + * + * 1. starts IO against @page. @page is locked for IO in + * this case. + * + * 2. doesn't start IO. @page is unlocked. + * + * In either case, page should be locked. + */ + lock_page(page); + /* + * IO (if any) is completed at this point. Check for IO + * errors. + */ + if (!PageUptodate(page)) + result = RETERR(-EIO); + } + assert("umka-3098", PageLocked(page)); + return result; +} + +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 79 + * End: + */ diff -puN /dev/null fs/reiser4/plugin/file_ops_readdir.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/file_ops_readdir.c 2005-09-15 19:51:08.000000000 -0700 @@ -0,0 +1,657 @@ +/* Copyright 2005 by Hans Reiser, licensing governed by + * reiser4/README */ + +#include "../inode.h" + +/* return true, iff @coord points to the valid directory item that is part of + * @inode directory. */ +static int is_valid_dir_coord(struct inode *inode, coord_t * coord) +{ + return + item_type_by_coord(coord) == DIR_ENTRY_ITEM_TYPE && + inode_file_plugin(inode)->owns_item(inode, coord); +} + +/* compare two logical positions within the same directory */ +static cmp_t dir_pos_cmp(const dir_pos * p1, const dir_pos * p2) +{ + cmp_t result; + + assert("nikita-2534", p1 != NULL); + assert("nikita-2535", p2 != NULL); + + result = de_id_cmp(&p1->dir_entry_key, &p2->dir_entry_key); + if (result == EQUAL_TO) { + int diff; + + diff = p1->pos - p2->pos; + result = + (diff < 0) ? LESS_THAN : (diff ? GREATER_THAN : EQUAL_TO); + } + return result; +} + + +/* see comment before readdir_common() for overview of why "adjustment" is + * necessary. */ +static void +adjust_dir_pos(struct file *dir, + readdir_pos * readdir_spot, const dir_pos * mod_point, int adj) +{ + dir_pos *pos; + + /* + * new directory entry was added (adj == +1) or removed (adj == -1) at + * the @mod_point. Directory file descriptor @dir is doing readdir and + * is currently positioned at @readdir_spot. Latter has to be updated + * to maintain stable readdir. + */ + /* directory is positioned to the beginning. */ + if (readdir_spot->entry_no == 0) + return; + + pos = &readdir_spot->position; + switch (dir_pos_cmp(mod_point, pos)) { + case LESS_THAN: + /* @mod_pos is _before_ @readdir_spot, that is, entry was + * added/removed on the left (in key order) of current + * position. */ + /* logical number of directory entry readdir is "looking" at + * changes */ + readdir_spot->entry_no += adj; + assert("nikita-2577", + ergo(dir != NULL, get_dir_fpos(dir) + adj >= 0)); + if (de_id_cmp(&pos->dir_entry_key, + &mod_point->dir_entry_key) == EQUAL_TO) { + assert("nikita-2575", mod_point->pos < pos->pos); + /* + * if entry added/removed has the same key as current + * for readdir, update counter of duplicate keys in + * @readdir_spot. + */ + pos->pos += adj; + } + break; + case GREATER_THAN: + /* directory is modified after @pos: nothing to do. */ + break; + case EQUAL_TO: + /* cannot insert an entry readdir is looking at, because it + already exists. */ + assert("nikita-2576", adj < 0); + /* directory entry to which @pos points to is being + removed. + + NOTE-NIKITA: Right thing to do is to update @pos to point + to the next entry. This is complex (we are under spin-lock + for one thing). Just rewind it to the beginning. Next + readdir will have to scan the beginning of + directory. Proper solution is to use semaphore in + spin lock's stead and use rewind_right() here. + + NOTE-NIKITA: now, semaphore is used, so... + */ + memset(readdir_spot, 0, sizeof *readdir_spot); + } +} + +/* scan all file-descriptors for this directory and adjust their + positions respectively. Should be used by implementations of + add_entry and rem_entry of dir plugin */ +void +adjust_dir_file(struct inode *dir, const struct dentry *de, int offset, int adj) +{ + reiser4_file_fsdata *scan; + dir_pos mod_point; + struct list_head *pos; + + assert("nikita-2536", dir != NULL); + assert("nikita-2538", de != NULL); + assert("nikita-2539", adj != 0); + + build_de_id(dir, &de->d_name, &mod_point.dir_entry_key); + mod_point.pos = offset; + + spin_lock_inode(dir); + + /* + * new entry was added/removed in directory @dir. Scan all file + * descriptors for @dir that are currently involved into @readdir and + * update them. + */ + + list_for_each(pos, get_readdir_list(dir)) { + scan = list_entry(pos, reiser4_file_fsdata, dir.linkage); + adjust_dir_pos(scan->back, &scan->dir.readdir, &mod_point, adj); + } + + spin_unlock_inode(dir); +} + +/* + * traverse tree to start/continue readdir from the readdir position @pos. + */ +static int dir_go_to(struct file *dir, readdir_pos * pos, tap_t * tap) +{ + reiser4_key key; + int result; + struct inode *inode; + + assert("nikita-2554", pos != NULL); + + inode = dir->f_dentry->d_inode; + result = inode_dir_plugin(inode)->build_readdir_key(dir, &key); + if (result != 0) + return result; + result = object_lookup(inode, + &key, + tap->coord, + tap->lh, + tap->mode, + FIND_EXACT, + LEAF_LEVEL, LEAF_LEVEL, 0, &tap->ra_info); + if (result == CBK_COORD_FOUND) + result = rewind_right(tap, (int)pos->position.pos); + else { + tap->coord->node = NULL; + done_lh(tap->lh); + result = RETERR(-EIO); + } + return result; +} + +/* + * handling of non-unique keys: calculate at what ordinal position within + * sequence of directory items with identical keys @pos is. + */ +static int set_pos(struct inode *inode, readdir_pos * pos, tap_t * tap) +{ + int result; + coord_t coord; + lock_handle lh; + tap_t scan; + de_id *did; + reiser4_key de_key; + + coord_init_zero(&coord); + init_lh(&lh); + tap_init(&scan, &coord, &lh, ZNODE_READ_LOCK); + tap_copy(&scan, tap); + tap_load(&scan); + pos->position.pos = 0; + + did = &pos->position.dir_entry_key; + + if (is_valid_dir_coord(inode, scan.coord)) { + + build_de_id_by_key(unit_key_by_coord(scan.coord, &de_key), did); + + while (1) { + + result = go_prev_unit(&scan); + if (result != 0) + break; + + if (!is_valid_dir_coord(inode, scan.coord)) { + result = -EINVAL; + break; + } + + /* get key of directory entry */ + unit_key_by_coord(scan.coord, &de_key); + if (de_id_key_cmp(did, &de_key) != EQUAL_TO) { + /* duplicate-sequence is over */ + break; + } + pos->position.pos++; + } + } else + result = RETERR(-ENOENT); + tap_relse(&scan); + tap_done(&scan); + return result; +} + +/* + * "rewind" directory to @offset, i.e., set @pos and @tap correspondingly. + */ +static int dir_rewind(struct file *dir, readdir_pos * pos, tap_t * tap) +{ + __u64 destination; + __s64 shift; + int result; + struct inode *inode; + loff_t dirpos; + + assert("nikita-2553", dir != NULL); + assert("nikita-2548", pos != NULL); + assert("nikita-2551", tap->coord != NULL); + assert("nikita-2552", tap->lh != NULL); + + dirpos = get_dir_fpos(dir); + shift = dirpos - pos->fpos; + /* this is logical directory entry within @dir which we are rewinding + * to */ + destination = pos->entry_no + shift; + + inode = dir->f_dentry->d_inode; + if (dirpos < 0) + return RETERR(-EINVAL); + else if (destination == 0ll || dirpos == 0) { + /* rewind to the beginning of directory */ + memset(pos, 0, sizeof *pos); + return dir_go_to(dir, pos, tap); + } else if (destination >= inode->i_size) + return RETERR(-ENOENT); + + if (shift < 0) { + /* I am afraid of negative numbers */ + shift = -shift; + /* rewinding to the left */ + if (shift <= (int)pos->position.pos) { + /* destination is within sequence of entries with + duplicate keys. */ + result = dir_go_to(dir, pos, tap); + } else { + shift -= pos->position.pos; + while (1) { + /* repetitions: deadlock is possible when + going to the left. */ + result = dir_go_to(dir, pos, tap); + if (result == 0) { + result = rewind_left(tap, shift); + if (result == -E_DEADLOCK) { + tap_done(tap); + continue; + } + } + break; + } + } + } else { + /* rewinding to the right */ + result = dir_go_to(dir, pos, tap); + if (result == 0) + result = rewind_right(tap, shift); + } + if (result == 0) { + result = set_pos(inode, pos, tap); + if (result == 0) { + /* update pos->position.pos */ + pos->entry_no = destination; + pos->fpos = dirpos; + } + } + return result; +} + +/* + * Function that is called by common_readdir() on each directory entry while + * doing readdir. ->filldir callback may block, so we had to release long term + * lock while calling it. To avoid repeating tree traversal, seal is used. If + * seal is broken, we return -E_REPEAT. Node is unlocked in this case. + * + * Whether node is unlocked in case of any other error is undefined. It is + * guaranteed to be still locked if success (0) is returned. + * + * When ->filldir() wants no more, feed_entry() returns 1, and node is + * unlocked. + */ +static int +feed_entry(struct file *f, + readdir_pos * pos, tap_t * tap, filldir_t filldir, void *dirent) +{ + item_plugin *iplug; + char *name; + reiser4_key sd_key; + int result; + char buf[DE_NAME_BUF_LEN]; + char name_buf[32]; + char *local_name; + unsigned file_type; + seal_t seal; + coord_t *coord; + reiser4_key entry_key; + + coord = tap->coord; + iplug = item_plugin_by_coord(coord); + + /* pointer to name within the node */ + name = iplug->s.dir.extract_name(coord, buf); + assert("nikita-1371", name != NULL); + + /* key of object the entry points to */ + if (iplug->s.dir.extract_key(coord, &sd_key) != 0) + return RETERR(-EIO); + + /* we must release longterm znode lock before calling filldir to avoid + deadlock which may happen if filldir causes page fault. So, copy + name to intermediate buffer */ + if (strlen(name) + 1 > sizeof(name_buf)) { + local_name = kmalloc(strlen(name) + 1, GFP_KERNEL); + if (local_name == NULL) + return RETERR(-ENOMEM); + } else + local_name = name_buf; + + strcpy(local_name, name); + file_type = iplug->s.dir.extract_file_type(coord); + + unit_key_by_coord(coord, &entry_key); + seal_init(&seal, coord, &entry_key); + + longterm_unlock_znode(tap->lh); + + /* + * send information about directory entry to the ->filldir() filler + * supplied to us by caller (VFS). + * + * ->filldir is entitled to do weird things. For example, ->filldir + * supplied by knfsd re-enters file system. Make sure no locks are + * held. + */ + assert("nikita-3436", lock_stack_isclean(get_current_lock_stack())); + + result = filldir(dirent, name, (int)strlen(name), + /* offset of this entry */ + f->f_pos, + /* inode number of object bounden by this entry */ + oid_to_uino(get_key_objectid(&sd_key)), file_type); + if (local_name != name_buf) + kfree(local_name); + if (result < 0) + /* ->filldir() is satisfied. (no space in buffer, IOW) */ + result = 1; + else + result = seal_validate(&seal, coord, &entry_key, + tap->lh, tap->mode, ZNODE_LOCK_HIPRI); + return result; +} + +static void move_entry(readdir_pos * pos, coord_t * coord) +{ + reiser4_key de_key; + de_id *did; + + /* update @pos */ + ++pos->entry_no; + did = &pos->position.dir_entry_key; + + /* get key of directory entry */ + unit_key_by_coord(coord, &de_key); + + if (de_id_key_cmp(did, &de_key) == EQUAL_TO) + /* we are within sequence of directory entries + with duplicate keys. */ + ++pos->position.pos; + else { + pos->position.pos = 0; + build_de_id_by_key(&de_key, did); + } + ++pos->fpos; +} + +/* + * STATELESS READDIR + * + * readdir support in reiser4 relies on ability to update readdir_pos embedded + * into reiser4_file_fsdata on each directory modification (name insertion and + * removal), see readdir_common() function below. This obviously doesn't work + * when reiser4 is accessed over NFS, because NFS doesn't keep any state + * across client READDIR requests for the same directory. + * + * To address this we maintain a "pool" of detached reiser4_file_fsdata + * (d_cursor). Whenever NFS readdir request comes, we detect this, and try to + * find detached reiser4_file_fsdata corresponding to previous readdir + * request. In other words, additional state is maintained on the + * server. (This is somewhat contrary to the design goals of NFS protocol.) + * + * To efficiently detect when our ->readdir() method is called by NFS server, + * dentry is marked as "stateless" in reiser4_decode_fh() (this is checked by + * file_is_stateless() function). + * + * To find out d_cursor in the pool, we encode client id (cid) in the highest + * bits of NFS readdir cookie: when first readdir request comes to the given + * directory from the given client, cookie is set to 0. This situation is + * detected, global cid_counter is incremented, and stored in highest bits of + * all direntry offsets returned to the client, including last one. As the + * only valid readdir cookie is one obtained as direntry->offset, we are + * guaranteed that next readdir request (continuing current one) will have + * current cid in the highest bits of starting readdir cookie. All d_cursors + * are hashed into per-super-block hash table by (oid, cid) key. + * + * In addition d_cursors are placed into per-super-block radix tree where they + * are keyed by oid alone. This is necessary to efficiently remove them during + * rmdir. + * + * At last, currently unused d_cursors are linked into special list. This list + * is used d_cursor_shrink to reclaim d_cursors on memory pressure. + * + */ + + +/* + * prepare for readdir. + */ +static int dir_readdir_init(struct file *f, tap_t * tap, readdir_pos ** pos) +{ + struct inode *inode; + reiser4_file_fsdata *fsdata; + int result; + + assert("nikita-1359", f != NULL); + inode = f->f_dentry->d_inode; + assert("nikita-1360", inode != NULL); + + if (!S_ISDIR(inode->i_mode)) + return RETERR(-ENOTDIR); + + /* try to find detached readdir state */ + result = try_to_attach_fsdata(f, inode); + if (result != 0) + return result; + + fsdata = reiser4_get_file_fsdata(f); + assert("nikita-2571", fsdata != NULL); + if (IS_ERR(fsdata)) + return PTR_ERR(fsdata); + + /* add file descriptor to the readdir list hanging of directory + * inode. This list is used to scan "readdirs-in-progress" while + * inserting or removing names in the directory. */ + spin_lock_inode(inode); + if (list_empty_careful(&fsdata->dir.linkage)) + list_add(&fsdata->dir.linkage, get_readdir_list(inode)); + *pos = &fsdata->dir.readdir; + spin_unlock_inode(inode); + + /* move @tap to the current position */ + return dir_rewind(f, *pos, tap); +} + +/* this is implementation of vfs's llseek method of struct file_operations for + typical directory + See comment before readdir_common() for explanation. +*/ +loff_t llseek_common_dir(struct file * file, loff_t off, int origin) +{ + reiser4_context *ctx; + loff_t result; + struct inode *inode; + + inode = file->f_dentry->d_inode; + + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + down(&inode->i_sem); + + /* update ->f_pos */ + result = default_llseek(file, off, origin); + if (result >= 0) { + int ff; + coord_t coord; + lock_handle lh; + tap_t tap; + readdir_pos *pos; + + coord_init_zero(&coord); + init_lh(&lh); + tap_init(&tap, &coord, &lh, ZNODE_READ_LOCK); + + ff = dir_readdir_init(file, &tap, &pos); + detach_fsdata(file); + if (ff != 0) + result = (loff_t) ff; + tap_done(&tap); + } + detach_fsdata(file); + up(&inode->i_sem); + + reiser4_exit_context(ctx); + return result; +} + +/* this is common implementation of vfs's readdir method of struct + file_operations + + readdir problems: + + readdir(2)/getdents(2) interface is based on implicit assumption that + readdir can be restarted from any particular point by supplying file system + with off_t-full of data. That is, file system fills ->d_off field in struct + dirent and later user passes ->d_off to the seekdir(3), which is, actually, + implemented by glibc as lseek(2) on directory. + + Reiser4 cannot restart readdir from 64 bits of data, because two last + components of the key of directory entry are unknown, which given 128 bits: + locality and type fields in the key of directory entry are always known, to + start readdir() from given point objectid and offset fields have to be + filled. + + Traditional UNIX API for scanning through directory + (readdir/seekdir/telldir/opendir/closedir/rewindir/getdents) is based on the + assumption that directory is structured very much like regular file, in + particular, it is implied that each name within given directory (directory + entry) can be uniquely identified by scalar offset and that such offset is + stable across the life-time of the name is identifies. + + This is manifestly not so for reiser4. In reiser4 the only stable unique + identifies for the directory entry is its key that doesn't fit into + seekdir/telldir API. + + solution: + + Within each file descriptor participating in readdir-ing of directory + plugin/dir/dir.h:readdir_pos is maintained. This structure keeps track of + the "current" directory entry that file descriptor looks at. It contains a + key of directory entry (plus some additional info to deal with non-unique + keys that we wouldn't dwell onto here) and a logical position of this + directory entry starting from the beginning of the directory, that is + ordinal number of this entry in the readdir order. + + Obviously this logical position is not stable in the face of directory + modifications. To work around this, on each addition or removal of directory + entry all file descriptors for directory inode are scanned and their + readdir_pos are updated accordingly (adjust_dir_pos()). +*/ +int readdir_common(struct file *f /* directory file being read */ , + void *dirent /* opaque data passed to us by VFS */ , + filldir_t filld /* filler function passed to us by VFS */ ) +{ + reiser4_context *ctx; + int result; + struct inode *inode; + coord_t coord; + lock_handle lh; + tap_t tap; + readdir_pos *pos; + + assert("nikita-1359", f != NULL); + inode = f->f_dentry->d_inode; + assert("nikita-1360", inode != NULL); + + if (!S_ISDIR(inode->i_mode)) + return RETERR(-ENOTDIR); + + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + coord_init_zero(&coord); + init_lh(&lh); + tap_init(&tap, &coord, &lh, ZNODE_READ_LOCK); + + reiser4_readdir_readahead_init(inode, &tap); + + repeat: + result = dir_readdir_init(f, &tap, &pos); + if (result == 0) { + result = tap_load(&tap); + /* scan entries one by one feeding them to @filld */ + while (result == 0) { + coord_t *coord; + + coord = tap.coord; + assert("nikita-2572", coord_is_existing_unit(coord)); + assert("nikita-3227", is_valid_dir_coord(inode, coord)); + + result = feed_entry(f, pos, &tap, filld, dirent); + if (result > 0) { + break; + } else if (result == 0) { + ++f->f_pos; + result = go_next_unit(&tap); + if (result == -E_NO_NEIGHBOR || + result == -ENOENT) { + result = 0; + break; + } else if (result == 0) { + if (is_valid_dir_coord(inode, coord)) + move_entry(pos, coord); + else + break; + } + } else if (result == -E_REPEAT) { + /* feed_entry() had to restart. */ + ++f->f_pos; + tap_relse(&tap); + goto repeat; + } else + warning("vs-1617", + "readdir_common: unexpected error %d", + result); + } + tap_relse(&tap); + + if (result >= 0) + f->f_version = inode->i_version; + } else if (result == -E_NO_NEIGHBOR || result == -ENOENT) + result = 0; + tap_done(&tap); + detach_fsdata(f); + + /* try to update directory's atime */ + if (reiser4_grab_space(inode_file_plugin(inode)->estimate.update(inode), + BA_CAN_COMMIT) != 0) + warning("", "failed to update atime on readdir: %llu", + get_inode_oid(inode)); + else + update_atime(inode); + + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + + return (result <= 0) ? result : 0; +} + +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 79 + * End: + */ diff -puN /dev/null fs/reiser4/plugin/file_plugin_common.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/file_plugin_common.c 2005-09-15 19:51:08.000000000 -0700 @@ -0,0 +1,911 @@ +/* Copyright 2005 by Hans Reiser, licensing governed by + reiser4/README */ + +/* this file contains typical implementations for most of methods of + file plugin +*/ + +#include "../inode.h" +#include "object.h" +#include "../safe_link.h" + +#include + +static int insert_new_sd(struct inode *inode); +static int update_sd(struct inode *inode); + +/* this is common implementation of write_sd_by_inode method of file plugin + either insert stat data or update it + */ +int write_sd_by_inode_common(struct inode *inode /* object to save */ ) +{ + int result; + + assert("nikita-730", inode != NULL); + + if (inode_get_flag(inode, REISER4_NO_SD)) + /* object doesn't have stat-data yet */ + result = insert_new_sd(inode); + else + result = update_sd(inode); + if (result != 0 && result != -ENAMETOOLONG && result != -ENOMEM) + /* Don't issue warnings about "name is too long" */ + warning("nikita-2221", "Failed to save sd for %llu: %i", + (unsigned long long)get_inode_oid(inode), result); + return result; +} + +/* this is common implementation of key_by_inode method of file plugin + */ +int +key_by_inode_and_offset_common(struct inode *inode, loff_t off, + reiser4_key * key) +{ + reiser4_key_init(key); + set_key_locality(key, reiser4_inode_data(inode)->locality_id); + set_key_ordering(key, get_inode_ordering(inode)); + set_key_objectid(key, get_inode_oid(inode)); /*FIXME: inode->i_ino */ + set_key_type(key, KEY_BODY_MINOR); + set_key_offset(key, (__u64) off); + return 0; +} + +/* this is common implementation of set_plug_in_inode method of file plugin + */ +int set_plug_in_inode_common(struct inode *object /* inode to set plugin on */ , + struct inode *parent /* parent object */ , + reiser4_object_create_data * data /* creational + * data */ ) +{ + __u64 mask; + + object->i_mode = data->mode; + /* this should be plugin decision */ + object->i_uid = current->fsuid; + object->i_mtime = object->i_atime = object->i_ctime = CURRENT_TIME; + + /* support for BSD style group-id assignment. See mount's manual page + description of bsdgroups ext2 mount options for more details */ + if (reiser4_is_set(object->i_sb, REISER4_BSD_GID)) + object->i_gid = parent->i_gid; + else if (parent->i_mode & S_ISGID) { + /* parent directory has sguid bit */ + object->i_gid = parent->i_gid; + if (S_ISDIR(object->i_mode)) + /* sguid is inherited by sub-directories */ + object->i_mode |= S_ISGID; + } else + object->i_gid = current->fsgid; + + /* this object doesn't have stat-data yet */ + inode_set_flag(object, REISER4_NO_SD); +#if 0 + /* this is now called after all inode plugins are initialized: + do_create_vfs_child after adjust_to_parent */ + /* setup inode and file-operations for this inode */ + setup_inode_ops(object, data); +#endif + object->i_nlink = 0; + seal_init(&reiser4_inode_data(object)->sd_seal, NULL, NULL); + mask = (1 << UNIX_STAT) | (1 << LIGHT_WEIGHT_STAT); + if (!reiser4_is_set(object->i_sb, REISER4_32_BIT_TIMES)) + mask |= (1 << LARGE_TIMES_STAT); + + reiser4_inode_data(object)->extmask = mask; + return 0; +} + +/* this is common implementation of adjust_to_parent method of file plugin for + regular files + */ +int adjust_to_parent_common(struct inode *object /* new object */ , + struct inode *parent /* parent directory */ , + struct inode *root /* root directory */ ) +{ + assert("nikita-2165", object != NULL); + if (parent == NULL) + parent = root; + assert("nikita-2069", parent != NULL); + + /* + * inherit missing plugins from parent + */ + + grab_plugin(object, parent, PSET_FILE); + grab_plugin(object, parent, PSET_SD); + grab_plugin(object, parent, PSET_FORMATTING); + grab_plugin(object, parent, PSET_PERM); + return 0; +} + +/* this is common implementation of adjust_to_parent method of file plugin for + typical directories + */ +int adjust_to_parent_common_dir(struct inode *object /* new object */ , + struct inode *parent /* parent directory */ , + struct inode *root /* root directory */ ) +{ + int result = 0; + pset_member memb; + + assert("nikita-2166", object != NULL); + if (parent == NULL) + parent = root; + assert("nikita-2167", parent != NULL); + + /* + * inherit missing plugins from parent + */ + for (memb = 0; memb < PSET_LAST; ++memb) { + result = grab_plugin(object, parent, memb); + if (result != 0) + break; + } + return result; +} + +/* this is common implementation of create_object method of file plugin + */ +int +create_object_common(struct inode *object, struct inode *parent UNUSED_ARG, + reiser4_object_create_data * data UNUSED_ARG) +{ + reiser4_block_nr reserve; + assert("nikita-744", object != NULL); + assert("nikita-745", parent != NULL); + assert("nikita-747", data != NULL); + assert("nikita-748", inode_get_flag(object, REISER4_NO_SD)); + + reserve = estimate_create_common(object); + if (reiser4_grab_space(reserve, BA_CAN_COMMIT)) + return RETERR(-ENOSPC); + return write_sd_by_inode_common(object); +} + +static int common_object_delete_no_reserve(struct inode *inode); + +/** + * delete_object_common - delete_object of file_plugin + * @inode: inode to be deleted + * + * This is common implementation of delete_object method of file_plugin. It + * applies to object its deletion consists of removing two items - stat data + * and safe-link. + */ +int delete_object_common(struct inode *inode) +{ + int result; + + assert("nikita-1477", inode != NULL); + /* FIXME: if file body deletion failed (i/o error, for instance), + inode->i_size can be != 0 here */ + assert("nikita-3420", inode->i_size == 0 || S_ISLNK(inode->i_mode)); + assert("nikita-3421", inode->i_nlink == 0); + + + if (!inode_get_flag(inode, REISER4_NO_SD)) { + reiser4_block_nr reserve; + + /* grab space which is needed to remove 2 items from the tree: + stat data and safe-link */ + reserve = 2 * estimate_one_item_removal(tree_by_inode(inode)); + if (reiser4_grab_space_force(reserve, + BA_RESERVED | BA_CAN_COMMIT)) + return RETERR(-ENOSPC); + result = common_object_delete_no_reserve(inode); + } else + result = 0; + return result; +} + +/** + * delete_directory_common - delete_object of file_plugin + * @inode: inode to be deleted + * + * This is common implementation of delete_object method of file_plugin for + * typical directory. It calls done method of dir_plugin to remove "." and + * removes stat data and safe-link. + */ +int delete_directory_common(struct inode *inode) +{ + int result; + dir_plugin *dplug; + + assert("", (get_current_context() && + get_current_context()->trans->atom == NULL)); + + dplug = inode_dir_plugin(inode); + assert("vs-1101", dplug && dplug->done); + + /* kill cursors which might be attached to inode */ + kill_cursors(inode); + + /* grab space enough for removing two items */ + if (reiser4_grab_space + (2 * estimate_one_item_removal(tree_by_inode(inode)), + BA_RESERVED | BA_CAN_COMMIT)) + return RETERR(-ENOSPC); + + result = dplug->done(inode); + if (!result) + result = common_object_delete_no_reserve(inode); + all_grabbed2free(); + return result; +} + +/* this is common implementation of add_link method of file plugin + */ +int add_link_common(struct inode *object, struct inode *parent UNUSED_ARG) +{ + /* + * increment ->i_nlink and update ->i_ctime + */ + + INODE_INC_FIELD(object, i_nlink); + object->i_ctime = CURRENT_TIME; + return 0; +} + +/* this is common implementation of rem_link method of file plugin + */ +int rem_link_common(struct inode *object, struct inode *parent UNUSED_ARG) +{ + assert("nikita-2021", object != NULL); + assert("nikita-2163", object->i_nlink > 0); + + /* + * decrement ->i_nlink and update ->i_ctime + */ + + INODE_DEC_FIELD(object, i_nlink); + object->i_ctime = CURRENT_TIME; + return 0; +} + +/* this is common implementation of rem_link method of file plugin for typical + directory +*/ +int rem_link_common_dir(struct inode *object, struct inode *parent UNUSED_ARG) +{ + assert("nikita-20211", object != NULL); + assert("nikita-21631", object->i_nlink > 0); + + /* + * decrement ->i_nlink and update ->i_ctime + */ + INODE_DEC_FIELD(object, i_nlink); + if (object->i_nlink == 1) + INODE_DEC_FIELD(object, i_nlink); + object->i_ctime = CURRENT_TIME; + return 0; +} + +/* this is common implementation of owns_item method of file plugin + compare objectids of keys in inode and coord */ +int owns_item_common(const struct inode *inode, /* object to check + * against */ + const coord_t * coord /* coord to check */ ) +{ + reiser4_key item_key; + reiser4_key file_key; + + assert("nikita-760", inode != NULL); + assert("nikita-761", coord != NULL); + + return coord_is_existing_item(coord) && + (get_key_objectid(build_sd_key(inode, &file_key)) == + get_key_objectid(item_key_by_coord(coord, &item_key))); +} + +/* this is common implementation of owns_item method of file plugin + for typical directory +*/ +int owns_item_common_dir(const struct inode *inode, /* object to check against */ + const coord_t * coord /* coord of item to check */ ) +{ + reiser4_key item_key; + + assert("nikita-1335", inode != NULL); + assert("nikita-1334", coord != NULL); + + if (item_type_by_coord(coord) == DIR_ENTRY_ITEM_TYPE) + return get_key_locality(item_key_by_coord(coord, &item_key)) == + get_inode_oid(inode); + else + return owns_item_common(inode, coord); +} + +/* this is common implementation of can_add_link method of file plugin + checks whether yet another hard links to this object can be added +*/ +int can_add_link_common(const struct inode *object /* object to check */ ) +{ + assert("nikita-732", object != NULL); + + /* inode->i_nlink is unsigned int, so just check for integer + overflow */ + return object->i_nlink + 1 != 0; +} + +/* this is common implementation of can_rem_link method of file plugin for + typical directory +*/ +int can_rem_link_common_dir(const struct inode *inode) +{ + /* is_dir_empty() returns 0 is dir is empty */ + return !is_dir_empty(inode); +} + +/* this is common implementation of detach method of file plugin for typical + directory +*/ +int detach_common_dir(struct inode *child, struct inode *parent) +{ + dir_plugin *dplug; + + dplug = inode_dir_plugin(child); + assert("nikita-2883", dplug != NULL); + assert("nikita-2884", dplug->detach != NULL); + return dplug->detach(child, parent); +} + +/* this is common implementation of bind method of file plugin for typical + directory +*/ +int bind_common_dir(struct inode *child, struct inode *parent) +{ + dir_plugin *dplug; + + dplug = inode_dir_plugin(child); + assert("nikita-2646", dplug != NULL); + return dplug->attach(child, parent); +} + +static int process_truncate(struct inode *, __u64 size); + +/* this is common implementation of safelink method of file plugin + */ +int safelink_common(struct inode *object, reiser4_safe_link_t link, __u64 value) +{ + int result; + + assert("vs-1705", get_current_context()->trans->atom == NULL); + if (link == SAFE_UNLINK) + /* nothing to do. iput() in the caller (process_safelink) will + * finish with file */ + result = 0; + else if (link == SAFE_TRUNCATE) + result = process_truncate(object, value); + else { + warning("nikita-3438", "Unrecognized safe-link type: %i", link); + result = RETERR(-EIO); + } + return result; +} + +/* this is common implementation of estimate.create method of file plugin + can be used when object creation involves insertion of one item (usually stat + data) into tree +*/ +reiser4_block_nr estimate_create_common(const struct inode * object) +{ + return estimate_one_insert_item(tree_by_inode(object)); +} + +/* this is common implementation of estimate.create method of file plugin for + typical directory + can be used when directory creation involves insertion of two items (usually + stat data and item containing "." and "..") into tree +*/ +reiser4_block_nr estimate_create_common_dir(const struct inode * object) +{ + return 2 * estimate_one_insert_item(tree_by_inode(object)); +} + +/* this is common implementation of estimate.update method of file plugin + can be used when stat data update does not do more than inserting a unit + into a stat data item which is probably true for most cases +*/ +reiser4_block_nr estimate_update_common(const struct inode * inode) +{ + return estimate_one_insert_into_item(tree_by_inode(inode)); +} + +/* this is common implementation of estimate.unlink method of file plugin + */ +reiser4_block_nr +estimate_unlink_common(const struct inode * object UNUSED_ARG, + const struct inode * parent UNUSED_ARG) +{ + return 0; +} + +/* this is common implementation of estimate.unlink method of file plugin for + typical directory +*/ +reiser4_block_nr +estimate_unlink_common_dir(const struct inode * object, + const struct inode * parent) +{ + dir_plugin *dplug; + + dplug = inode_dir_plugin(object); + assert("nikita-2888", dplug != NULL); + assert("nikita-2887", dplug->estimate.unlink != NULL); + return dplug->estimate.unlink(object, parent); +} + +char *wire_write_common(struct inode *inode, char *start) +{ + return build_inode_onwire(inode, start); +} + +char *wire_read_common(char *addr, reiser4_object_on_wire * obj) +{ + return extract_obj_key_id_from_onwire(addr, &obj->u.std.key_id); +} + +struct dentry *wire_get_common(struct super_block *sb, + reiser4_object_on_wire * obj) +{ + struct inode *inode; + struct dentry *dentry; + reiser4_key key; + + extract_key_from_id(&obj->u.std.key_id, &key); + inode = reiser4_iget(sb, &key, 1); + if (!IS_ERR(inode)) { + reiser4_iget_complete(inode); + dentry = d_alloc_anon(inode); + if (dentry == NULL) { + iput(inode); + dentry = ERR_PTR(-ENOMEM); + } else + dentry->d_op = &get_super_private(sb)->ops.dentry; + } else if (PTR_ERR(inode) == -ENOENT) + /* + * inode wasn't found at the key encoded in the file + * handle. Hence, file handle is stale. + */ + dentry = ERR_PTR(RETERR(-ESTALE)); + else + dentry = (void *)inode; + return dentry; +} + +int wire_size_common(struct inode *inode) +{ + return inode_onwire_size(inode); +} + +void wire_done_common(reiser4_object_on_wire * obj) +{ + /* nothing to do */ +} + +/* helper function to print errors */ +static void key_warning(const reiser4_key * key /* key to print */ , + const struct inode *inode, + int code /* error code to print */ ) +{ + assert("nikita-716", key != NULL); + + if (code != -ENOMEM) { + warning("nikita-717", "Error for inode %llu (%i)", + (unsigned long long)get_key_objectid(key), code); + print_key("for key", key); + } +} + +/* NIKITA-FIXME-HANS: perhaps this function belongs in another file? */ +#if REISER4_DEBUG +static void +check_inode_seal(const struct inode *inode, + const coord_t * coord, const reiser4_key * key) +{ + reiser4_key unit_key; + + unit_key_by_coord(coord, &unit_key); + assert("nikita-2752", + WITH_DATA_RET(coord->node, 1, keyeq(key, &unit_key))); + assert("nikita-2753", get_inode_oid(inode) == get_key_objectid(key)); +} + +static void check_sd_coord(coord_t * coord, const reiser4_key * key) +{ + reiser4_key ukey; + + coord_clear_iplug(coord); + if (zload(coord->node)) + return; + + if (!coord_is_existing_unit(coord) || + !item_plugin_by_coord(coord) || + !keyeq(unit_key_by_coord(coord, &ukey), key) || + (znode_get_level(coord->node) != LEAF_LEVEL) || + !item_is_statdata(coord)) { + warning("nikita-1901", "Conspicuous seal"); + print_key("key", key); + print_coord("coord", coord, 1); + impossible("nikita-2877", "no way"); + } + zrelse(coord->node); +} + +#else +#define check_inode_seal(inode, coord, key) noop +#define check_sd_coord(coord, key) noop +#endif + +/* insert new stat-data into tree. Called with inode state + locked. Return inode state locked. */ +static int insert_new_sd(struct inode *inode /* inode to create sd for */ ) +{ + int result; + reiser4_key key; + coord_t coord; + reiser4_item_data data; + char *area; + reiser4_inode *ref; + lock_handle lh; + oid_t oid; + + assert("nikita-723", inode != NULL); + assert("nikita-3406", inode_get_flag(inode, REISER4_NO_SD)); + + ref = reiser4_inode_data(inode); + spin_lock_inode(inode); + + if (ref->plugin_mask != 0) + /* inode has non-standard plugins */ + inode_set_extension(inode, PLUGIN_STAT); + /* + * prepare specification of new item to be inserted + */ + + data.iplug = inode_sd_plugin(inode); + data.length = data.iplug->s.sd.save_len(inode); + spin_unlock_inode(inode); + + data.data = NULL; + data.user = 0; +/* could be optimized for case where there is only one node format in + * use in the filesystem, probably there are lots of such + * places we could optimize for only one node layout.... -Hans */ + if (data.length > tree_by_inode(inode)->nplug->max_item_size()) { + /* This is silly check, but we don't know actual node where + insertion will go into. */ + return RETERR(-ENAMETOOLONG); + } + oid = oid_allocate(inode->i_sb); +/* NIKITA-FIXME-HANS: what is your opinion on whether this error check should be encapsulated into oid_allocate? */ + if (oid == ABSOLUTE_MAX_OID) + return RETERR(-EOVERFLOW); + + set_inode_oid(inode, oid); + + coord_init_zero(&coord); + init_lh(&lh); + + result = insert_by_key(tree_by_inode(inode), + build_sd_key(inode, &key), &data, &coord, &lh, + /* stat data lives on a leaf level */ + LEAF_LEVEL, CBK_UNIQUE); + + /* we don't want to re-check that somebody didn't insert + stat-data while we were doing io, because if it did, + insert_by_key() returned error. */ + /* but what _is_ possible is that plugin for inode's stat-data, + list of non-standard plugins or their state would change + during io, so that stat-data wouldn't fit into sd. To avoid + this race we keep inode_state lock. This lock has to be + taken each time you access inode in a way that would cause + changes in sd size: changing plugins etc. + */ + + if (result == IBK_INSERT_OK) { + coord_clear_iplug(&coord); + result = zload(coord.node); + if (result == 0) { + /* have we really inserted stat data? */ + assert("nikita-725", item_is_statdata(&coord)); + + /* inode was just created. It is inserted into hash + table, but no directory entry was yet inserted into + parent. So, inode is inaccessible through + ->lookup(). All places that directly grab inode + from hash-table (like old knfsd), should check + IMMUTABLE flag that is set by common_create_child. + */ + assert("nikita-3240", data.iplug != NULL); + assert("nikita-3241", data.iplug->s.sd.save != NULL); + area = item_body_by_coord(&coord); + result = data.iplug->s.sd.save(inode, &area); + znode_make_dirty(coord.node); + if (result == 0) { + /* object has stat-data now */ + inode_clr_flag(inode, REISER4_NO_SD); + inode_set_flag(inode, REISER4_SDLEN_KNOWN); + /* initialise stat-data seal */ + seal_init(&ref->sd_seal, &coord, &key); + ref->sd_coord = coord; + check_inode_seal(inode, &coord, &key); + } else if (result != -ENOMEM) + /* + * convert any other error code to -EIO to + * avoid confusing user level with unexpected + * errors. + */ + result = RETERR(-EIO); + zrelse(coord.node); + } + } + done_lh(&lh); + + if (result != 0) + key_warning(&key, inode, result); + else + oid_count_allocated(); + + return result; +} + +/* find sd of inode in a tree, deal with errors */ +int lookup_sd(struct inode *inode /* inode to look sd for */ , + znode_lock_mode lock_mode /* lock mode */ , + coord_t * coord /* resulting coord */ , + lock_handle * lh /* resulting lock handle */ , + const reiser4_key * key /* resulting key */ , + int silent) +{ + int result; + __u32 flags; + + assert("nikita-1692", inode != NULL); + assert("nikita-1693", coord != NULL); + assert("nikita-1694", key != NULL); + + /* look for the object's stat data in a tree. + This returns in "node" pointer to a locked znode and in "pos" + position of an item found in node. Both are only valid if + coord_found is returned. */ + flags = (lock_mode == ZNODE_WRITE_LOCK) ? CBK_FOR_INSERT : 0; + flags |= CBK_UNIQUE; + /* + * traverse tree to find stat data. We cannot use vroot here, because + * it only covers _body_ of the file, and stat data don't belong + * there. + */ + result = coord_by_key(tree_by_inode(inode), + key, + coord, + lh, + lock_mode, + FIND_EXACT, LEAF_LEVEL, LEAF_LEVEL, flags, NULL); + if (REISER4_DEBUG && result == 0) + check_sd_coord(coord, key); + + if (result != 0 && !silent) + key_warning(key, inode, result); + return result; +} + +int +locate_inode_sd(struct inode *inode, + reiser4_key * key, coord_t * coord, lock_handle * lh) +{ + reiser4_inode *state; + seal_t seal; + int result; + + assert("nikita-3483", inode != NULL); + + state = reiser4_inode_data(inode); + spin_lock_inode(inode); + *coord = state->sd_coord; + coord_clear_iplug(coord); + seal = state->sd_seal; + spin_unlock_inode(inode); + + build_sd_key(inode, key); + if (seal_is_set(&seal)) { + /* first, try to use seal */ + result = seal_validate(&seal, + coord, + key, + lh, ZNODE_WRITE_LOCK, ZNODE_LOCK_LOPRI); + if (result == 0) + check_sd_coord(coord, key); + } else + result = -E_REPEAT; + + if (result != 0) { + coord_init_zero(coord); + result = lookup_sd(inode, ZNODE_WRITE_LOCK, coord, lh, key, 0); + } + return result; +} + +/* update stat-data at @coord */ +static int +update_sd_at(struct inode *inode, coord_t * coord, reiser4_key * key, + lock_handle * lh) +{ + int result; + reiser4_item_data data; + char *area; + reiser4_inode *state; + znode *loaded; + + state = reiser4_inode_data(inode); + + coord_clear_iplug(coord); + result = zload(coord->node); + if (result != 0) + return result; + loaded = coord->node; + + spin_lock_inode(inode); + assert("nikita-728", inode_sd_plugin(inode) != NULL); + data.iplug = inode_sd_plugin(inode); + + /* if inode has non-standard plugins, add appropriate stat data + * extension */ + if (state->plugin_mask != 0) + inode_set_extension(inode, PLUGIN_STAT); + + /* data.length is how much space to add to (or remove + from if negative) sd */ + if (!inode_get_flag(inode, REISER4_SDLEN_KNOWN)) { + /* recalculate stat-data length */ + data.length = + data.iplug->s.sd.save_len(inode) - + item_length_by_coord(coord); + inode_set_flag(inode, REISER4_SDLEN_KNOWN); + } else + data.length = 0; + spin_unlock_inode(inode); + + /* if on-disk stat data is of different length than required + for this inode, resize it */ + if (data.length != 0) { + data.data = NULL; + data.user = 0; + + /* insertion code requires that insertion point (coord) was + * between units. */ + coord->between = AFTER_UNIT; + result = resize_item(coord, + &data, key, lh, COPI_DONT_SHIFT_LEFT); + if (result != 0) { + key_warning(key, inode, result); + zrelse(loaded); + return result; + } + if (loaded != coord->node) { + /* resize_item moved coord to another node. Zload it */ + zrelse(loaded); + coord_clear_iplug(coord); + result = zload(coord->node); + if (result != 0) + return result; + loaded = coord->node; + } + } + + area = item_body_by_coord(coord); + spin_lock_inode(inode); + result = data.iplug->s.sd.save(inode, &area); + znode_make_dirty(coord->node); + + /* re-initialise stat-data seal */ + + /* + * coord.between was possibly skewed from AT_UNIT when stat-data size + * was changed and new extensions were pasted into item. + */ + coord->between = AT_UNIT; + seal_init(&state->sd_seal, coord, key); + state->sd_coord = *coord; + spin_unlock_inode(inode); + check_inode_seal(inode, coord, key); + zrelse(loaded); + return result; +} + +/* Update existing stat-data in a tree. Called with inode state locked. Return + inode state locked. */ +static int update_sd(struct inode *inode /* inode to update sd for */ ) +{ + int result; + reiser4_key key; + coord_t coord; + lock_handle lh; + + assert("nikita-726", inode != NULL); + + /* no stat-data, nothing to update?! */ + assert("nikita-3482", !inode_get_flag(inode, REISER4_NO_SD)); + + init_lh(&lh); + + result = locate_inode_sd(inode, &key, &coord, &lh); + if (result == 0) + result = update_sd_at(inode, &coord, &key, &lh); + done_lh(&lh); + + return result; +} + +/* helper for delete_object_common and delete_directory_common. Remove object + stat data. Space for that must be reserved by caller before +*/ +static int +common_object_delete_no_reserve(struct inode *inode /* object to remove */ ) +{ + int result; + + assert("nikita-1477", inode != NULL); + + if (!inode_get_flag(inode, REISER4_NO_SD)) { + reiser4_key sd_key; + + DQUOT_FREE_INODE(inode); + DQUOT_DROP(inode); + + build_sd_key(inode, &sd_key); + result = + cut_tree(tree_by_inode(inode), &sd_key, &sd_key, NULL, 0); + if (result == 0) { + inode_set_flag(inode, REISER4_NO_SD); + result = oid_release(inode->i_sb, get_inode_oid(inode)); + if (result == 0) { + oid_count_released(); + + result = safe_link_del(tree_by_inode(inode), + get_inode_oid(inode), + SAFE_UNLINK); + } + } + } else + result = 0; + return result; +} + +/* helper for safelink_common */ +static int process_truncate(struct inode *inode, __u64 size) +{ + int result; + struct iattr attr; + file_plugin *fplug; + reiser4_context *ctx; + struct dentry dentry; + + assert("vs-21", is_in_reiser4_context()); + ctx = init_context(inode->i_sb); + assert("vs-22", !IS_ERR(ctx)); + + attr.ia_size = size; + attr.ia_valid = ATTR_SIZE | ATTR_CTIME; + fplug = inode_file_plugin(inode); + + down(&inode->i_sem); + assert("vs-1704", get_current_context()->trans->atom == NULL); + dentry.d_inode = inode; + result = inode->i_op->setattr(&dentry, &attr); + up(&inode->i_sem); + + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + + return result; +} + +/* Local variables: + c-indentation-style: "K&R" + mode-name: "LC" + c-basic-offset: 8 + tab-width: 8 + fill-column: 120 + End: +*/ diff -L fs/reiser4/plugin/file/pseudo.c -puN fs/reiser4/plugin/file/pseudo.c~reiser4-big-update /dev/null --- devel/fs/reiser4/plugin/file/pseudo.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,180 +0,0 @@ -/* Copyright 2003 by Hans Reiser, licensing governed by reiser4/README */ - -/* - * Pseudo file plugin. This contains helper functions used by pseudo files. - */ - -#include "pseudo.h" -#include "../plugin.h" - -#include "../../inode.h" - -#include -#include - -/* extract pseudo file plugin, stored in @file */ -static pseudo_plugin * -get_pplug(struct file * file) -{ - struct inode *inode; - - inode = file->f_dentry->d_inode; - return reiser4_inode_data(inode)->file_plugin_data.pseudo_info.plugin; -} - -/* common routine to open pseudo file. */ -reiser4_internal int open_pseudo(struct inode * inode, struct file * file) -{ - int result; - pseudo_plugin *pplug; - - pplug = get_pplug(file); - - /* for pseudo files based on seq_file interface */ - if (pplug->read_type == PSEUDO_READ_SEQ) { - result = seq_open(file, &pplug->read.ops); - if (result == 0) { - struct seq_file *m; - - m = file->private_data; - m->private = file; - } - } else if (pplug->read_type == PSEUDO_READ_SINGLE) - /* for pseudo files containing one record */ - result = single_open(file, pplug->read.single_show, file); - else - result = 0; - - return result; -} - -/* common read method for pseudo files */ -reiser4_internal ssize_t read_pseudo(struct file *file, - char __user *buf, size_t size, loff_t *ppos) -{ - switch (get_pplug(file)->read_type) { - case PSEUDO_READ_SEQ: - case PSEUDO_READ_SINGLE: - /* seq_file behaves like pipe, requiring @ppos to always be - * address of file->f_pos */ - return seq_read(file, buf, size, &file->f_pos); - case PSEUDO_READ_FORWARD: - return get_pplug(file)->read.read(file, buf, size, ppos); - default: - return 0; - } -} - -/* common seek method for pseudo files */ -reiser4_internal loff_t seek_pseudo(struct file *file, loff_t offset, int origin) -{ - switch (get_pplug(file)->read_type) { - case PSEUDO_READ_SEQ: - case PSEUDO_READ_SINGLE: - return seq_lseek(file, offset, origin); - default: - return 0; - } -} - -/* common release method for pseudo files */ -reiser4_internal int release_pseudo(struct inode *inode, struct file *file) -{ - int result; - - switch (get_pplug(file)->read_type) { - case PSEUDO_READ_SEQ: - case PSEUDO_READ_SINGLE: - result = seq_release(inode, file); - file->private_data = NULL; - break; - default: - result = 0; - } - return result; -} - -/* pseudo files need special ->drop() method, because they don't have nlink - * and only exist while host object does. */ -reiser4_internal void drop_pseudo(struct inode * object) -{ - /* pseudo files are not protected from deletion by their ->i_nlink */ - generic_delete_inode(object); -} - -/* common write method for pseudo files */ -reiser4_internal ssize_t -write_pseudo(struct file *file, - const char __user *buf, size_t size, loff_t *ppos) -{ - ssize_t result; - - switch (get_pplug(file)->write_type) { - case PSEUDO_WRITE_STRING: { - char * inkernel; - - inkernel = getname(buf); - if (!IS_ERR(inkernel)) { - result = get_pplug(file)->write.gets(file, inkernel); - putname(inkernel); - if (result == 0) - result = size; - } else - result = PTR_ERR(inkernel); - break; - } - case PSEUDO_WRITE_FORWARD: - result = get_pplug(file)->write.write(file, buf, size, ppos); - break; - default: - result = size; - } - return result; -} - -/* on-wire serialization of pseudo files. */ - -/* this is not implemented so far (and, hence, pseudo files are not accessible - * over NFS, closing remote exploits a fortiori */ - -reiser4_internal int -wire_size_pseudo(struct inode *inode) -{ - return RETERR(-ENOTSUPP); -} - -reiser4_internal char * -wire_write_pseudo(struct inode *inode, char *start) -{ - return ERR_PTR(RETERR(-ENOTSUPP)); -} - -reiser4_internal char * -wire_read_pseudo(char *addr, reiser4_object_on_wire *obj) -{ - return ERR_PTR(RETERR(-ENOTSUPP)); -} - -reiser4_internal void -wire_done_pseudo(reiser4_object_on_wire *obj) -{ - /* nothing to do */ -} - -reiser4_internal struct dentry * -wire_get_pseudo(struct super_block *sb, reiser4_object_on_wire *obj) -{ - return ERR_PTR(RETERR(-ENOTSUPP)); -} - - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - scroll-step: 1 - End: -*/ diff -L fs/reiser4/plugin/file/pseudo.h -puN fs/reiser4/plugin/file/pseudo.h~reiser4-big-update /dev/null --- devel/fs/reiser4/plugin/file/pseudo.h +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,39 +0,0 @@ -/* Copyright 2003 by Hans Reiser, licensing governed by reiser4/README */ - -#if !defined(__REISER4_PSEUDO_FILE_H__) -#define __REISER4_PSEUDO_FILE_H__ - -#include "../plugin.h" - -#include - -extern int open_pseudo(struct inode * inode, struct file * file); -extern ssize_t read_pseudo(struct file *file, - char __user *buf, size_t size, loff_t *ppos); -extern ssize_t write_pseudo(struct file *file, - const char __user *buf, size_t size, loff_t *ppos); -extern loff_t seek_pseudo(struct file *file, loff_t offset, int origin); -extern int release_pseudo(struct inode *inode, struct file *file); -extern void drop_pseudo(struct inode * object); - -extern int wire_size_pseudo(struct inode *inode); -extern char *wire_write_pseudo(struct inode *inode, char *start); -extern char *wire_read_pseudo(char *addr, reiser4_object_on_wire *obj); -extern void wire_done_pseudo(reiser4_object_on_wire *obj); -extern struct dentry *wire_get_pseudo(struct super_block *sb, - reiser4_object_on_wire *obj); - -/* __REISER4_PSEUDO_FILE_H__ */ -#endif - -/* - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - scroll-step: 1 - End: -*/ - diff -L fs/reiser4/plugin/file/regular.c -puN fs/reiser4/plugin/file/regular.c~reiser4-big-update /dev/null --- devel/fs/reiser4/plugin/file/regular.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,44 +0,0 @@ -/* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */ - -/* Contains Reiser4 regular plugins which: - . specify a set of reiser4 regular object plugins, - . used by directory plugin to create entries powered by specified - regular plugins */ - -#include "../plugin.h" - -regular_plugin regular_plugins[LAST_REGULAR_ID] = { - [UF_REGULAR_ID] = { - .h = { - .type_id = REISER4_REGULAR_PLUGIN_TYPE, - .id = UF_REGULAR_ID, - .pops = NULL, - .label = "unixfile", - .desc = "Unix file regular plugin", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .id = UNIX_FILE_PLUGIN_ID - }, - [CRC_REGULAR_ID] = { - .h = { - .type_id = REISER4_REGULAR_PLUGIN_TYPE, - .id = CRC_REGULAR_ID, - .pops = NULL, - .label = "cryptcompress", - .desc = "Cryptcompress regular plugin", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .id = CRC_FILE_PLUGIN_ID - } -}; - -/* - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - scroll-step: 1 - End: -*/ diff -puN fs/reiser4/plugin/file/symfile.c~reiser4-big-update fs/reiser4/plugin/file/symfile.c --- devel/fs/reiser4/plugin/file/symfile.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/file/symfile.c 2005-09-15 19:51:08.000000000 -0700 @@ -85,14 +85,3 @@ sophisticated symfile syntax that we are not planning to write for version 4.0. */ - - - - - - - - - - - diff -puN /dev/null fs/reiser4/plugin/file/symlink.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/file/symlink.c 2005-09-15 19:51:08.000000000 -0700 @@ -0,0 +1,92 @@ +/* Copyright 2002, 2003, 2005 by Hans Reiser, licensing governed by reiser4/README */ + +#include "../../inode.h" + +#include +#include + +/* file plugin methods specific for symlink files + (SYMLINK_FILE_PLUGIN_ID) */ + +/* this is implementation of create_object method of file plugin for + SYMLINK_FILE_PLUGIN_ID + */ + +/** + * create_symlink - create_object of file plugin for SYMLINK_FILE_PLUGIN_ID + * @symlink: inode of symlink object + * @dir: inode of parent directory + * @info: parameters of new object + * + * Inserts stat data with symlink extension where into the tree. + */ +int create_symlink(struct inode *symlink, + struct inode *dir UNUSED_ARG, + reiser4_object_create_data *data /* info passed to us, + * this is filled by + * reiser4() syscall + * in particular */ ) +{ + int result; + + assert("nikita-680", symlink != NULL); + assert("nikita-681", S_ISLNK(symlink->i_mode)); + assert("nikita-685", inode_get_flag(symlink, REISER4_NO_SD)); + assert("nikita-682", dir != NULL); + assert("nikita-684", data != NULL); + assert("nikita-686", data->id == SYMLINK_FILE_PLUGIN_ID); + + /* + * stat data of symlink has symlink extension in which we store + * symlink content, that is, path symlink is pointing to. + */ + reiser4_inode_data(symlink)->extmask |= (1 << SYMLINK_STAT); + + assert("vs-838", symlink->u.generic_ip == NULL); + symlink->u.generic_ip = (void *)data->name; + + assert("vs-843", symlink->i_size == 0); + INODE_SET_FIELD(symlink, i_size, strlen(data->name)); + + /* insert stat data appended with data->name */ + result = inode_file_plugin(symlink)->write_sd_by_inode(symlink); + if (result) { + /* FIXME-VS: Make sure that symlink->u.generic_ip is not attached + to kmalloced data */ + INODE_SET_FIELD(symlink, i_size, 0); + } else { + assert("vs-849", symlink->u.generic_ip + && inode_get_flag(symlink, REISER4_GENERIC_PTR_USED)); + assert("vs-850", + !memcmp((char *)symlink->u.generic_ip, data->name, + (size_t) symlink->i_size + 1)); + } + return result; +} + +/* this is implementation of destroy_inode method of file plugin for + SYMLINK_FILE_PLUGIN_ID + */ +void destroy_inode_symlink(struct inode *inode) +{ + assert("edward-799", + inode_file_plugin(inode) == + file_plugin_by_id(SYMLINK_FILE_PLUGIN_ID)); + assert("edward-800", !is_bad_inode(inode) && is_inode_loaded(inode)); + assert("edward-801", inode_get_flag(inode, REISER4_GENERIC_PTR_USED)); + assert("vs-839", S_ISLNK(inode->i_mode)); + + kfree(inode->u.generic_ip); + inode->u.generic_ip = NULL; + inode_clr_flag(inode, REISER4_GENERIC_PTR_USED); +} + +/* Local variables: + c-indentation-style: "K&R" + mode-name: "LC" + c-basic-offset: 8 + tab-width: 8 + fill-column: 120 + scroll-step: 1 + End: +*/ diff -puN fs/reiser4/plugin/file/tail_conversion.c~reiser4-big-update fs/reiser4/plugin/file/tail_conversion.c --- devel/fs/reiser4/plugin/file/tail_conversion.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/file/tail_conversion.c 2005-09-15 19:51:08.000000000 -0700 @@ -4,7 +4,6 @@ #include "../../super.h" #include "../../page_cache.h" #include "../../carry.h" -#include "../../lib.h" #include "../../safe_link.h" #include "../../vfs_ops.h" #include "funcs.h" @@ -14,10 +13,8 @@ /* this file contains: tail2extent and extent2tail */ - /* exclusive access to a file is acquired when file state changes: tail2extent, empty2tail, extent2tail, etc */ -reiser4_internal void -get_exclusive_access(unix_file_info_t *uf_info) +void get_exclusive_access(unix_file_info_t * uf_info) { assert("nikita-3028", schedulable()); assert("nikita-3047", LOCK_CNT_NIL(inode_sem_w)); @@ -38,8 +35,7 @@ get_exclusive_access(unix_file_info_t *u ON_DEBUG(uf_info->ea_owner = current); } -reiser4_internal void -drop_exclusive_access(unix_file_info_t *uf_info) +void drop_exclusive_access(unix_file_info_t * uf_info) { assert("vs-1714", uf_info->ea_owner == current); assert("vs-1715", atomic_read(&uf_info->nr_neas) == 0); @@ -52,31 +48,25 @@ drop_exclusive_access(unix_file_info_t * } /* nonexclusive access to a file is acquired for read, write, readpage */ -reiser4_internal void -get_nonexclusive_access(unix_file_info_t *uf_info, int atom_may_exist) +void get_nonexclusive_access(unix_file_info_t * uf_info, int atom_may_exist) { assert("nikita-3029", schedulable()); /* unix_file_filemap_nopage may call this when current atom exist already */ - assert("nikita-3361", ergo(atom_may_exist == 0, get_current_context()->trans->atom == NULL)); - BUG_ON(atom_may_exist == 0 && get_current_context()->trans->atom != NULL); + assert("nikita-3361", + ergo(atom_may_exist == 0, + get_current_context()->trans->atom == NULL)); + BUG_ON(atom_may_exist == 0 + && get_current_context()->trans->atom != NULL); down_read(&uf_info->latch); LOCK_CNT_INC(inode_sem_r); assert("vs-1716", uf_info->ea_owner == NULL); ON_DEBUG(atomic_inc(&uf_info->nr_neas)); #if REISER4_DEBUG uf_info->last_reader = current; -#ifdef CONFIG_FRAME_POINTER - uf_info->where[0] = __builtin_return_address(0); - uf_info->where[1] = __builtin_return_address(1); - uf_info->where[2] = __builtin_return_address(2); - uf_info->where[3] = __builtin_return_address(3); - uf_info->where[4] = __builtin_return_address(4); -#endif #endif } -reiser4_internal void -drop_nonexclusive_access(unix_file_info_t *uf_info) +void drop_nonexclusive_access(unix_file_info_t * uf_info) { assert("vs-1718", uf_info->ea_owner == NULL); assert("vs-1719", atomic_read(&uf_info->nr_neas) > 0); @@ -88,15 +78,14 @@ drop_nonexclusive_access(unix_file_info_ /* part of tail2extent. Cut all items covering @count bytes starting from @offset */ /* Audited by: green(2002.06.15) */ -static int -cut_formatting_items(struct inode *inode, loff_t offset, int count) +static int cut_formatting_items(struct inode *inode, loff_t offset, int count) { reiser4_key from, to; /* AUDIT: How about putting an assertion here, what would check all provided range is covered by tail items only? */ /* key of first byte in the range to be cut */ - key_by_inode_unix_file(inode, offset, &from); + inode_file_plugin(inode)->key_by_inode(inode, offset, &from); /* key of last byte in that range */ to = from; @@ -106,15 +95,14 @@ cut_formatting_items(struct inode *inode return cut_tree(tree_by_inode(inode), &from, &to, inode, 0); } -static void -release_all_pages(struct page **pages, unsigned nr_pages) +static void release_all_pages(struct page **pages, unsigned nr_pages) { unsigned i; for (i = 0; i < nr_pages; i++) { if (pages[i] == NULL) { unsigned j; - for (j = i + 1; j < nr_pages; j ++) + for (j = i + 1; j < nr_pages; j++) assert("vs-1620", pages[j] == NULL); break; } @@ -140,7 +128,10 @@ replace(struct inode *inode, struct page assert("vs-596", pages[0]); /* cut copied items */ - result = cut_formatting_items(inode, (loff_t) pages[0]->index << PAGE_CACHE_SHIFT, count); + result = + cut_formatting_items(inode, + (loff_t) pages[0]->index << PAGE_CACHE_SHIFT, + count); if (result) return result; @@ -149,7 +140,9 @@ replace(struct inode *inode, struct page /* put into tree replacement for just removed items: extent item, namely */ for (i = 0; i < nr_pages; i++) { result = add_to_page_cache_lru(pages[i], inode->i_mapping, - pages[i]->index, mapping_gfp_mask(inode->i_mapping)); + pages[i]->index, + mapping_gfp_mask(inode-> + i_mapping)); if (result) break; unlock_page(pages[i]); @@ -164,8 +157,7 @@ replace(struct inode *inode, struct page #define TAIL2EXTENT_PAGE_NUM 3 /* number of pages to fill before cutting tail * items */ -static int -reserve_tail2extent_iteration(struct inode *inode) +static int reserve_tail2extent_iteration(struct inode *inode) { reiser4_block_nr unformatted_nodes; reiser4_tree *tree; @@ -192,30 +184,29 @@ reserve_tail2extent_iteration(struct ino */ grab_space_enable(); return reiser4_grab_space - (2 * tree->height + - TAIL2EXTENT_PAGE_NUM + - TAIL2EXTENT_PAGE_NUM * estimate_one_insert_into_item(tree) + - 1 + estimate_one_insert_item(tree) + - inode_file_plugin(inode)->estimate.update(inode), - BA_CAN_COMMIT); + (2 * tree->height + + TAIL2EXTENT_PAGE_NUM + + TAIL2EXTENT_PAGE_NUM * estimate_one_insert_into_item(tree) + + 1 + estimate_one_insert_item(tree) + + inode_file_plugin(inode)->estimate.update(inode), BA_CAN_COMMIT); } /* this is used by tail2extent and extent2tail to detect where previous uncompleted conversion stopped */ static int -find_start(struct inode *object, reiser4_plugin_id id, __u64 *offset) +find_start(struct inode *object, reiser4_plugin_id id, __u64 * offset) { - int result; - lock_handle lh; - coord_t coord; + int result; + lock_handle lh; + coord_t coord; unix_file_info_t *ufo; - int found; - reiser4_key key; + int found; + reiser4_key key; ufo = unix_file_inode_data(object); init_lh(&lh); result = 0; found = 0; - key_by_inode_unix_file(object, *offset, &key); + inode_file_plugin(object)->key_by_inode(object, *offset, &key); do { init_lh(&lh); result = find_file_item_nohint(&coord, &lh, &key, @@ -223,13 +214,15 @@ find_start(struct inode *object, reiser4 if (result == CBK_COORD_FOUND) { if (coord.between == AT_UNIT) { - /*coord_clear_iplug(&coord);*/ + /*coord_clear_iplug(&coord); */ result = zload(coord.node); if (result == 0) { if (item_id_by_coord(&coord) == id) found = 1; else - item_plugin_by_coord(&coord)->s.file.append_key(&coord, &key); + item_plugin_by_coord(&coord)->s. + file.append_key(&coord, + &key); zrelse(coord.node); } } else @@ -242,15 +235,15 @@ find_start(struct inode *object, reiser4 } /* clear stat data's flag indicating that conversion is being converted */ -static int -complete_conversion(struct inode *inode) +static int complete_conversion(struct inode *inode) { int result; all_grabbed2free(); grab_space_enable(); - result = reiser4_grab_space(inode_file_plugin(inode)->estimate.update(inode), - BA_CAN_COMMIT); + result = + reiser4_grab_space(inode_file_plugin(inode)->estimate.update(inode), + BA_CAN_COMMIT); if (result == 0) { inode_clr_flag(inode, REISER4_PART_CONV); result = reiser4_update_sd(inode); @@ -261,15 +254,15 @@ complete_conversion(struct inode *inode) return 0; } -reiser4_internal int -tail2extent(unix_file_info_t *uf_info) +int tail2extent(unix_file_info_t * uf_info) { int result; reiser4_key key; /* key of next byte to be moved to page */ - ON_DEBUG(reiser4_key tmp;) + ON_DEBUG(reiser4_key tmp; + ) char *p_data; /* data of page */ unsigned page_off = 0, /* offset within the page where to copy data */ - count; /* number of bytes of item which can be + count; /* number of bytes of item which can be * copied to page */ struct page *pages[TAIL2EXTENT_PAGE_NUM]; struct page *page; @@ -301,13 +294,13 @@ tail2extent(unix_file_info_t *uf_info) } /* get key of first byte of a file */ - key_by_inode_unix_file(inode, offset, &key); + inode_file_plugin(inode)->key_by_inode(inode, offset, &key); done = 0; result = 0; first_iteration = 1; while (done == 0) { - memset(pages, 0, sizeof (pages)); + memset(pages, 0, sizeof(pages)); all_grabbed2free(); result = reserve_tail2extent_iteration(inode); if (result != 0) @@ -319,14 +312,17 @@ tail2extent(unix_file_info_t *uf_info) } bytes = 0; for (i = 0; i < sizeof_array(pages) && done == 0; i++) { - assert("vs-598", (get_key_offset(&key) & ~PAGE_CACHE_MASK) == 0); + assert("vs-598", + (get_key_offset(&key) & ~PAGE_CACHE_MASK) == 0); page = alloc_page(mapping_gfp_mask(inode->i_mapping)); if (!page) { result = RETERR(-ENOMEM); goto error; } - page->index = (unsigned long) (get_key_offset(&key) >> PAGE_CACHE_SHIFT); + page->index = + (unsigned long)(get_key_offset(&key) >> + PAGE_CACHE_SHIFT); /* usually when one is going to longterm lock znode (as find_file_item does, for instance) he must not hold locked pages. However, there is an exception for @@ -334,9 +330,10 @@ tail2extent(unix_file_info_t *uf_info) reachable to everyone else, they are clean, they do not have jnodes attached so keeping them locked do not risk deadlock appearance - */ + */ assert("vs-983", !PagePrivate(page)); - reiser4_invalidate_pages(inode->i_mapping, page->index, 1, 0); + reiser4_invalidate_pages(inode->i_mapping, page->index, + 1, 0); for (page_off = 0; page_off < PAGE_CACHE_SIZE;) { coord_t coord; lock_handle lh; @@ -344,8 +341,12 @@ tail2extent(unix_file_info_t *uf_info) /* get next item */ /* FIXME: we might want to readahead here */ init_lh(&lh); - result = find_file_item_nohint(&coord, &lh, &key, ZNODE_READ_LOCK, inode); - if (cbk_errored(result) || result == CBK_COORD_NOTFOUND) { + result = + find_file_item_nohint(&coord, &lh, &key, + ZNODE_READ_LOCK, + inode); + if (cbk_errored(result) + || result == CBK_COORD_NOTFOUND) { /* error happened of not items of file were found */ done_lh(&lh); page_cache_release(page); @@ -357,7 +358,8 @@ tail2extent(unix_file_info_t *uf_info) done_lh(&lh); done = 1; p_data = kmap_atomic(page, KM_USER0); - memset(p_data + page_off, 0, PAGE_CACHE_SIZE - page_off); + memset(p_data + page_off, 0, + PAGE_CACHE_SIZE - page_off); kunmap_atomic(p_data, KM_USER0); break; } @@ -368,13 +370,20 @@ tail2extent(unix_file_info_t *uf_info) done_lh(&lh); goto error; } - assert("vs-562", owns_item_unix_file(inode, &coord)); + assert("vs-562", + owns_item_unix_file(inode, &coord)); assert("vs-856", coord.between == AT_UNIT); - assert("green-11", keyeq(&key, unit_key_by_coord(&coord, &tmp))); - item = ((char *)item_body_by_coord(&coord)) + coord.unit_pos; + assert("green-11", + keyeq(&key, + unit_key_by_coord(&coord, &tmp))); + item = + ((char *)item_body_by_coord(&coord)) + + coord.unit_pos; /* how many bytes to copy */ - count = item_length_by_coord(&coord) - coord.unit_pos; + count = + item_length_by_coord(&coord) - + coord.unit_pos; /* limit length of copy to end of page */ if (count > PAGE_CACHE_SIZE - page_off) count = PAGE_CACHE_SIZE - page_off; @@ -384,16 +393,18 @@ tail2extent(unix_file_info_t *uf_info) p_data = kmap_atomic(page, KM_USER0); /* copy item (as much as will fit starting from the beginning of the item) into the page */ - memcpy(p_data + page_off, item, (unsigned) count); + memcpy(p_data + page_off, item, + (unsigned)count); kunmap_atomic(p_data, KM_USER0); page_off += count; bytes += count; - set_key_offset(&key, get_key_offset(&key) + count); + set_key_offset(&key, + get_key_offset(&key) + count); zrelse(coord.node); done_lh(&lh); - } /* end of loop which fills one page by content of formatting items */ + } /* end of loop which fills one page by content of formatting items */ if (page_off) { /* something was copied into page */ @@ -403,7 +414,7 @@ tail2extent(unix_file_info_t *uf_info) assert("vs-1648", done == 1); break; } - } /* end of loop through pages of one conversion iteration */ + } /* end of loop through pages of one conversion iteration */ if (i > 0) { result = replace(inode, pages, i, bytes); @@ -436,18 +447,17 @@ tail2extent(unix_file_info_t *uf_info) /* conversion is not complete. Inode was already marked as * REISER4_PART_CONV and stat-data were updated at the first * iteration of the loop above. */ - error: + error: release_all_pages(pages, sizeof_array(pages)); warning("nikita-2282", "Partial conversion of %llu: %i", (unsigned long long)get_inode_oid(inode), result); } - out: + out: all_grabbed2free(); return result; } - /* part of extent2tail. Page contains data which are to be put into tree by tail items. Use tail_write for this. flow is composed like in unix_file_write. The only difference is that data for writing are in @@ -457,9 +467,9 @@ static int write_page_by_tail(struct inode *inode, struct page *page, unsigned count) { flow_t f; - hint_t hint; + hint_t *hint; + lock_handle *lh; coord_t *coord; - lock_handle lh; znode *loaded; item_plugin *iplug; int result; @@ -467,34 +477,49 @@ write_page_by_tail(struct inode *inode, result = 0; assert("vs-1089", count); - assert("vs-1647", inode_file_plugin(inode)->flow_by_inode == flow_by_inode_unix_file); + assert("vs-1647", + inode_file_plugin(inode)->flow_by_inode == + flow_by_inode_unix_file); + + hint = kmalloc(sizeof(*hint), GFP_KERNEL); + if (hint == NULL) + return RETERR(-ENOMEM); + hint_init_zero(hint); + lh = &hint->lh; /* build flow */ /* FIXME: do not kmap here */ - flow_by_inode_unix_file(inode, kmap(page), 0 /* not user space */ , - count, (loff_t) (page->index << PAGE_CACHE_SHIFT), WRITE_OP, &f); + flow_by_inode_unix_file(inode, (char __user *)kmap(page), 0 /* not user space */ , + count, + (loff_t) (page->index << PAGE_CACHE_SHIFT), + WRITE_OP, &f); iplug = item_plugin_by_id(FORMATTING_ID); - hint_init_zero(&hint); - init_lh(&lh); - hint.ext_coord.lh = &lh; - coord = &hint.ext_coord.coord; + + coord = &hint->ext_coord.coord; while (f.length) { - result = find_file_item_nohint(coord, &lh, &f.key, ZNODE_WRITE_LOCK, inode); + result = + find_file_item_nohint(coord, lh, &f.key, ZNODE_WRITE_LOCK, + inode); if (IS_CBKERR(result)) break; - assert("vs-957", ergo(result == CBK_COORD_NOTFOUND, get_key_offset(&f.key) == 0)); - assert("vs-958", ergo(result == CBK_COORD_FOUND, get_key_offset(&f.key) != 0)); + assert("vs-957", + ergo(result == CBK_COORD_NOTFOUND, + get_key_offset(&f.key) == 0)); + assert("vs-958", + ergo(result == CBK_COORD_FOUND, + get_key_offset(&f.key) != 0)); - /*coord_clear_iplug(coord);*/ result = zload(coord->node); if (result) break; loaded = coord->node; - result = iplug->s.file.write(inode, &f, &hint, 1/*grabbed*/, how_to_write(&hint.ext_coord, &f.key)); + result = + iplug->s.file.write(inode, &f, hint, 1 /*grabbed */ , + how_to_write(&hint->ext_coord, &f.key)); zrelse(loaded); - done_lh(&lh); + done_lh(lh); if (result == -E_REPEAT) result = 0; @@ -502,7 +527,8 @@ write_page_by_tail(struct inode *inode, break; } - done_lh(&lh); + done_lh(lh); + kfree(hint); kunmap(page); /* result of write is 0 or error */ @@ -512,8 +538,7 @@ write_page_by_tail(struct inode *inode, return result; } -static int -reserve_extent2tail_iteration(struct inode *inode) +static int reserve_extent2tail_iteration(struct inode *inode) { reiser4_tree *tree; @@ -531,17 +556,20 @@ reserve_extent2tail_iteration(struct ino */ grab_space_enable(); return reiser4_grab_space - (estimate_one_item_removal(tree) + - estimate_insert_flow(tree->height) + - 1 + estimate_one_insert_item(tree) + - inode_file_plugin(inode)->estimate.update(inode), - BA_CAN_COMMIT); + (estimate_one_item_removal(tree) + + estimate_insert_flow(tree->height) + + 1 + estimate_one_insert_item(tree) + + inode_file_plugin(inode)->estimate.update(inode), BA_CAN_COMMIT); +} + +static int filler(void *vp, struct page *page) +{ + return readpage_unix_file(vp, page); } /* for every page of file: read page, cut part of extent pointing to this page, put data of page tree by tail item */ -reiser4_internal int -extent2tail(unix_file_info_t *uf_info) +int extent2tail(unix_file_info_t * uf_info) { int result; struct inode *inode; @@ -574,10 +602,10 @@ extent2tail(unix_file_info_t *uf_info) /* number of pages in the file */ num_pages = - (inode->i_size - offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + (inode->i_size - offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; start_page = offset >> PAGE_CACHE_SHIFT; - key_by_inode_unix_file(inode, offset, &from); + inode_file_plugin(inode)->key_by_inode(inode, offset, &from); to = from; result = 0; @@ -594,8 +622,7 @@ extent2tail(unix_file_info_t *uf_info) } page = read_cache_page(inode->i_mapping, - (unsigned) (i + start_page), - readpage_unix_file/*filler*/, 0); + (unsigned)(i + start_page), filler, NULL); if (IS_ERR(page)) { result = PTR_ERR(page); break; @@ -629,7 +656,9 @@ extent2tail(unix_file_info_t *uf_info) /* put page data into tree via tail_write */ count = PAGE_CACHE_SIZE; if (i == num_pages - 1) - count = (inode->i_size & ~PAGE_CACHE_MASK) ? : PAGE_CACHE_SIZE; + count = + (inode-> + i_size & ~PAGE_CACHE_MASK) ? : PAGE_CACHE_SIZE; result = write_page_by_tail(inode, page, count); if (result) { page_cache_release(page); @@ -640,7 +669,8 @@ extent2tail(unix_file_info_t *uf_info) lock_page(page); /* page is already detached from jnode and mapping. */ assert("vs-1086", page->mapping == NULL); - assert("nikita-2690", (!PagePrivate(page) && page->private == 0)); + assert("nikita-2690", + (!PagePrivate(page) && page->private == 0)); /* waiting for writeback completion with page lock held is * perfectly valid. */ wait_on_page_writeback(page); @@ -652,7 +682,8 @@ extent2tail(unix_file_info_t *uf_info) if (i == num_pages) { /* file is converted to formatted items */ assert("vs-1698", inode_get_flag(inode, REISER4_PART_CONV)); - assert("vs-1260", inode_has_no_jnodes(reiser4_inode_data(inode))); + assert("vs-1260", + inode_has_no_jnodes(reiser4_inode_data(inode))); uf_info->container = UF_CONTAINER_TAILS; complete_conversion(inode); @@ -670,8 +701,7 @@ extent2tail(unix_file_info_t *uf_info) } /* this is used to find which conversion did not complete */ -static int -find_first_item(struct inode *inode) +static int find_first_item(struct inode *inode) { coord_t coord; lock_handle lh; @@ -680,16 +710,18 @@ find_first_item(struct inode *inode) coord_init_zero(&coord); init_lh(&lh); - key_by_inode_unix_file(inode, 0, &key); - result = find_file_item_nohint(&coord, &lh, &key, ZNODE_READ_LOCK, inode); + inode_file_plugin(inode)->key_by_inode(inode, 0, &key); + result = + find_file_item_nohint(&coord, &lh, &key, ZNODE_READ_LOCK, inode); if (result == CBK_COORD_FOUND) { if (coord.between == AT_UNIT) { - /*coord_clear_iplug(&coord);*/ + /*coord_clear_iplug(&coord); */ result = zload(coord.node); if (result == 0) { result = item_id_by_coord(&coord); zrelse(coord.node); - if (result != EXTENT_POINTER_ID && result != FORMATTING_ID) + if (result != EXTENT_POINTER_ID + && result != FORMATTING_ID) result = RETERR(-EIO); } } else @@ -701,8 +733,7 @@ find_first_item(struct inode *inode) /* exclusive access is obtained. File may be "partially converted" - that is file body may have both formatting and extent items. Find which conversion did not completed and complete */ -reiser4_internal int -finish_conversion(struct inode *inode) +int finish_conversion(struct inode *inode) { int result; @@ -717,7 +748,8 @@ finish_conversion(struct inode *inode) result = extent2tail(unix_file_inode_data(inode)); } else result = 0; - assert("vs-1712", ergo(result == 0, !inode_get_flag(inode, REISER4_PART_CONV))); + assert("vs-1712", + ergo(result == 0, !inode_get_flag(inode, REISER4_PART_CONV))); return result; } diff -puN fs/reiser4/plugin/hash.c~reiser4-big-update fs/reiser4/plugin/hash.c --- devel/fs/reiser4/plugin/hash.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/hash.c 2005-09-15 19:51:08.000000000 -0700 @@ -8,14 +8,12 @@ #include "plugin.h" #include "../super.h" #include "../inode.h" -#include "../plugin/dir/dir.h" #include /* old rupasov (yura) hash */ -static __u64 -hash_rupasov(const unsigned char *name /* name to hash */ , - int len /* @name's length */ ) +static __u64 hash_rupasov(const unsigned char *name /* name to hash */ , + int len /* @name's length */ ) { int i; int j; @@ -59,9 +57,8 @@ hash_rupasov(const unsigned char *name / } /* r5 hash */ -static __u64 -hash_r5(const unsigned char *name /* name to hash */ , - int len UNUSED_ARG /* @name's length */ ) +static __u64 hash_r5(const unsigned char *name /* name to hash */ , + int len UNUSED_ARG /* @name's length */ ) { __u64 a = 0; @@ -89,9 +86,8 @@ hash_r5(const unsigned char *name /* nam This code was blindly upgraded to __u64 by s/__u32/__u64/g. */ -static __u64 -hash_tea(const unsigned char *name /* name to hash */ , - int len /* @name's length */ ) +static __u64 hash_tea(const unsigned char *name /* name to hash */ , + int len /* @name's length */ ) { __u64 k[] = { 0x9464a485u, 0x542e1a94u, 0x3e846bffu, 0xb75bcfc3u }; @@ -132,10 +128,14 @@ hash_tea(const unsigned char *name /* na pad |= pad << 16; while (len >= 16) { - a = (__u64) name[0] | (__u64) name[1] << 8 | (__u64) name[2] << 16 | (__u64) name[3] << 24; - b = (__u64) name[4] | (__u64) name[5] << 8 | (__u64) name[6] << 16 | (__u64) name[7] << 24; - c = (__u64) name[8] | (__u64) name[9] << 8 | (__u64) name[10] << 16 | (__u64) name[11] << 24; - d = (__u64) name[12] | (__u64) name[13] << 8 | (__u64) name[14] << 16 | (__u64) name[15] << 24; + a = (__u64) name[0] | (__u64) name[1] << 8 | (__u64) name[2] << + 16 | (__u64) name[3] << 24; + b = (__u64) name[4] | (__u64) name[5] << 8 | (__u64) name[6] << + 16 | (__u64) name[7] << 24; + c = (__u64) name[8] | (__u64) name[9] << 8 | (__u64) name[10] << + 16 | (__u64) name[11] << 24; + d = (__u64) name[12] | (__u64) name[13] << 8 | (__u64) name[14] + << 16 | (__u64) name[15] << 24; TEACORE(PARTROUNDS); @@ -146,11 +146,14 @@ hash_tea(const unsigned char *name /* na if (len >= 12) { //assert(len < 16); if (len >= 16) - *(int *) 0 = 0; + *(int *)0 = 0; - a = (__u64) name[0] | (__u64) name[1] << 8 | (__u64) name[2] << 16 | (__u64) name[3] << 24; - b = (__u64) name[4] | (__u64) name[5] << 8 | (__u64) name[6] << 16 | (__u64) name[7] << 24; - c = (__u64) name[8] | (__u64) name[9] << 8 | (__u64) name[10] << 16 | (__u64) name[11] << 24; + a = (__u64) name[0] | (__u64) name[1] << 8 | (__u64) name[2] << + 16 | (__u64) name[3] << 24; + b = (__u64) name[4] | (__u64) name[5] << 8 | (__u64) name[6] << + 16 | (__u64) name[7] << 24; + c = (__u64) name[8] | (__u64) name[9] << 8 | (__u64) name[10] << + 16 | (__u64) name[11] << 24; d = pad; for (i = 12; i < len; i++) { @@ -160,9 +163,11 @@ hash_tea(const unsigned char *name /* na } else if (len >= 8) { //assert(len < 12); if (len >= 12) - *(int *) 0 = 0; - a = (__u64) name[0] | (__u64) name[1] << 8 | (__u64) name[2] << 16 | (__u64) name[3] << 24; - b = (__u64) name[4] | (__u64) name[5] << 8 | (__u64) name[6] << 16 | (__u64) name[7] << 24; + *(int *)0 = 0; + a = (__u64) name[0] | (__u64) name[1] << 8 | (__u64) name[2] << + 16 | (__u64) name[3] << 24; + b = (__u64) name[4] | (__u64) name[5] << 8 | (__u64) name[6] << + 16 | (__u64) name[7] << 24; c = d = pad; for (i = 8; i < len; i++) { @@ -172,8 +177,9 @@ hash_tea(const unsigned char *name /* na } else if (len >= 4) { //assert(len < 8); if (len >= 8) - *(int *) 0 = 0; - a = (__u64) name[0] | (__u64) name[1] << 8 | (__u64) name[2] << 16 | (__u64) name[3] << 24; + *(int *)0 = 0; + a = (__u64) name[0] | (__u64) name[1] << 8 | (__u64) name[2] << + 16 | (__u64) name[3] << 24; b = c = d = pad; for (i = 4; i < len; i++) { @@ -183,7 +189,7 @@ hash_tea(const unsigned char *name /* na } else { //assert(len < 4); if (len >= 4) - *(int *) 0 = 0; + *(int *)0 = 0; a = b = c = d = pad; for (i = 0; i < len; i++) { a <<= 8; @@ -213,9 +219,8 @@ hash_tea(const unsigned char *name /* na domain. */ -static __u64 -hash_fnv1(const unsigned char *name /* name to hash */ , - int len UNUSED_ARG /* @name's length */ ) +static __u64 hash_fnv1(const unsigned char *name /* name to hash */ , + int len UNUSED_ARG /* @name's length */ ) { unsigned long long a = 0xcbf29ce484222325ull; const unsigned long long fnv_64_prime = 0x100000001b3ull; @@ -228,7 +233,7 @@ hash_fnv1(const unsigned char *name /* n /* multiply by the 32 bit FNV magic prime mod 2^64 */ a *= fnv_64_prime; /* xor the bottom with the current octet */ - a ^= (unsigned long long) (*name); + a ^= (unsigned long long)(*name); } /* return our new hash value */ return a; @@ -236,15 +241,13 @@ hash_fnv1(const unsigned char *name /* n /* degenerate hash function used to simplify testing of non-unique key handling */ -static __u64 -hash_deg(const unsigned char *name UNUSED_ARG /* name to hash */ , - int len UNUSED_ARG /* @name's length */ ) +static __u64 hash_deg(const unsigned char *name UNUSED_ARG /* name to hash */ , + int len UNUSED_ARG /* @name's length */ ) { return 0xc0c0c0c010101010ull; } -static int -change_hash(struct inode * inode, reiser4_plugin * plugin) +static int change_hash(struct inode *inode, reiser4_plugin * plugin) { int result; @@ -259,8 +262,9 @@ change_hash(struct inode * inode, reiser if (inode_hash_plugin(inode) == NULL || inode_hash_plugin(inode)->h.id != plugin->h.id) { if (is_dir_empty(inode) == 0) - result = plugin_set_hash(&reiser4_inode_data(inode)->pset, - &plugin->hash); + result = + plugin_set_hash(&reiser4_inode_data(inode)->pset, + &plugin->hash); else result = RETERR(-ENOTEMPTY); @@ -269,11 +273,11 @@ change_hash(struct inode * inode, reiser } static reiser4_plugin_ops hash_plugin_ops = { - .init = NULL, - .load = NULL, + .init = NULL, + .load = NULL, .save_len = NULL, - .save = NULL, - .change = change_hash + .save = NULL, + .change = change_hash }; /* hash plugins */ @@ -285,8 +289,8 @@ hash_plugin hash_plugins[LAST_HASH_ID] = .pops = &hash_plugin_ops, .label = "rupasov", .desc = "Original Yura's hash", - .linkage = TYPE_SAFE_LIST_LINK_ZERO} - , + .linkage = {NULL, NULL} + }, .hash = hash_rupasov }, [R5_HASH_ID] = { @@ -296,8 +300,8 @@ hash_plugin hash_plugins[LAST_HASH_ID] = .pops = &hash_plugin_ops, .label = "r5", .desc = "r5 hash", - .linkage = TYPE_SAFE_LIST_LINK_ZERO} - , + .linkage = {NULL, NULL} + }, .hash = hash_r5 }, [TEA_HASH_ID] = { @@ -307,8 +311,8 @@ hash_plugin hash_plugins[LAST_HASH_ID] = .pops = &hash_plugin_ops, .label = "tea", .desc = "tea hash", - .linkage = TYPE_SAFE_LIST_LINK_ZERO} - , + .linkage = {NULL, NULL} + }, .hash = hash_tea }, [FNV1_HASH_ID] = { @@ -318,8 +322,8 @@ hash_plugin hash_plugins[LAST_HASH_ID] = .pops = &hash_plugin_ops, .label = "fnv1", .desc = "fnv1 hash", - .linkage = TYPE_SAFE_LIST_LINK_ZERO} - , + .linkage = {NULL, NULL} + }, .hash = hash_fnv1 }, [DEGENERATE_HASH_ID] = { @@ -329,8 +333,8 @@ hash_plugin hash_plugins[LAST_HASH_ID] = .pops = &hash_plugin_ops, .label = "degenerate hash", .desc = "Degenerate hash: only for testing", - .linkage = TYPE_SAFE_LIST_LINK_ZERO} - , + .linkage = {NULL, NULL} + }, .hash = hash_deg } }; diff -puN /dev/null fs/reiser4/plugin/inode_ops.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/inode_ops.c 2005-09-15 19:51:08.000000000 -0700 @@ -0,0 +1,936 @@ +/* + * Copyright 2005 by Hans Reiser, licensing governed by reiser4/README + */ + +/* + * this file contains typical implementations for most of methods of struct + * inode_operations + */ + +#include "../inode.h" +#include "../safe_link.h" + +#include +#include + + +static int create_vfs_object(struct inode *parent, struct dentry *dentry, + reiser4_object_create_data *data); + +/** + * create_common - create of inode operations + * @parent: inode of parent directory + * @dentry: dentry of new object to create + * @mode: the permissions to use + * @nameidata: + * + * This is common implementation of vfs's create method of struct + * inode_operations. + * Creates regular file using file plugin from parent directory plugin set. + */ +int create_common(struct inode *parent, struct dentry *dentry, + int mode, struct nameidata *nameidata) +{ + reiser4_object_create_data data; + + memset(&data, 0, sizeof data); + data.mode = S_IFREG | mode; + data.id = inode_regular_plugin(parent)->id; + return create_vfs_object(parent, dentry, &data); +} + +int lookup_name(struct inode *dir, struct dentry *, reiser4_key *); +void check_light_weight(struct inode *inode, struct inode *parent); + +/** + * lookup_common - lookup of inode operations + * @parent: inode of directory to lookup into + * @dentry: name to look for + * @nameidata: + * + * This is common implementation of vfs's lookup method of struct + * inode_operations. + */ +struct dentry *lookup_common(struct inode *parent, struct dentry *dentry, + struct nameidata *nameidata) +{ + reiser4_context *ctx; + int result; + struct dentry *new; + struct inode *inode; + reiser4_dir_entry_desc entry; + + ctx = init_context(parent->i_sb); + if (IS_ERR(ctx)) + return (struct dentry *)ctx; + + /* set up operations on dentry. */ + dentry->d_op = &get_super_private(parent->i_sb)->ops.dentry; + + result = lookup_name(parent, dentry, &entry.key); + if (result) { + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + if (result == -ENOENT) { + /* object not found */ + if (!IS_DEADDIR(parent)) + d_add(dentry, NULL); + return NULL; + } + return ERR_PTR(result); + } + + inode = reiser4_iget(parent->i_sb, &entry.key, 0); + if (IS_ERR(inode)) { + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return ERR_PTR(PTR_ERR(inode)); + } + + /* success */ + check_light_weight(inode, parent); + new = d_splice_alias(inode, dentry); + reiser4_iget_complete(inode); + + /* prevent balance_dirty_pages() from being called: we don't want to + * do this under directory i_sem. */ + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return new; +} + +static reiser4_block_nr common_estimate_link(struct inode *parent, + struct inode *object); +int reiser4_update_dir(struct inode *); + +/** + * link_common - link of inode operations + * @existing: dentry of object which is to get new name + * @parent: directory where new name is to be created + * @newname: new name + * + * This is common implementation of vfs's link method of struct + * inode_operations. + */ +int link_common(struct dentry *existing, struct inode *parent, + struct dentry *newname) +{ + reiser4_context *ctx; + int result; + struct inode *object; + dir_plugin *parent_dplug; + reiser4_dir_entry_desc entry; + reiser4_object_create_data data; + reiser4_block_nr reserve; + + ctx = init_context(parent->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + assert("nikita-1431", existing != NULL); + assert("nikita-1432", parent != NULL); + assert("nikita-1433", newname != NULL); + + object = existing->d_inode; + assert("nikita-1434", object != NULL); + + /* check for race with create_object() */ + if (inode_get_flag(object, REISER4_IMMUTABLE)) { + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return RETERR(-E_REPEAT); + } + + /* links to directories are not allowed if file-system logical + name-space should be ADG */ + if (S_ISDIR(object->i_mode) + && reiser4_is_set(parent->i_sb, REISER4_ADG)) { + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return RETERR(-EISDIR); + } + + /* check permissions */ + result = perm_chk(parent, link, existing, parent, newname); + if (result != 0) { + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return result; + } + + parent_dplug = inode_dir_plugin(parent); + + memset(&entry, 0, sizeof entry); + entry.obj = object; + + data.mode = object->i_mode; + data.id = inode_file_plugin(object)->h.id; + + reserve = common_estimate_link(parent, existing->d_inode); + if ((__s64) reserve < 0) { + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return reserve; + } + + if (reiser4_grab_space(reserve, BA_CAN_COMMIT)) { + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return RETERR(-ENOSPC); + } + + /* + * Subtle race handling: sys_link() doesn't take i_sem on @parent. It + * means that link(2) can race against unlink(2) or rename(2), and + * inode is dead (->i_nlink == 0) when reiser4_link() is entered. + * + * For such inode we have to undo special processing done in + * reiser4_unlink() viz. creation of safe-link. + */ + if (unlikely(object->i_nlink == 0)) { + result = safe_link_del(tree_by_inode(object), + get_inode_oid(object), SAFE_UNLINK); + if (result != 0) { + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return result; + } + } + + /* increment nlink of @existing and update its stat data */ + result = reiser4_add_nlink(object, parent, 1); + if (result == 0) { + /* add entry to the parent */ + result = + parent_dplug->add_entry(parent, newname, &data, &entry); + if (result != 0) { + /* failed to add entry to the parent, decrement nlink + of @existing */ + reiser4_del_nlink(object, parent, 1); + /* + * now, if that failed, we have a file with too big + * nlink---space leak, much better than directory + * entry pointing to nowhere + */ + } + } + if (result == 0) { + atomic_inc(&object->i_count); + /* + * Upon successful completion, link() shall mark for update + * the st_ctime field of the file. Also, the st_ctime and + * st_mtime fields of the directory that contains the new + * entry shall be marked for update. --SUS + */ + result = reiser4_update_dir(parent); + } + if (result == 0) + d_instantiate(newname, existing->d_inode); + + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return result; +} + +static int unlink_check_and_grab(struct inode *parent, struct dentry *victim); + +/** + * unlink_common - unlink of inode operations + * @parent: inode of directory to remove name from + * @victim: name to be removed + * + * This is common implementation of vfs's unlink method of struct + * inode_operations. + */ +int unlink_common(struct inode *parent, struct dentry *victim) +{ + reiser4_context *ctx; + int result; + struct inode *object; + file_plugin *fplug; + + ctx = init_context(parent->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + object = victim->d_inode; + fplug = inode_file_plugin(object); + assert("nikita-2882", fplug->detach != NULL); + + result = unlink_check_and_grab(parent, victim); + if (result != 0) { + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return result; + } + + result = fplug->detach(object, parent); + if (result == 0) { + dir_plugin *parent_dplug; + reiser4_dir_entry_desc entry; + + parent_dplug = inode_dir_plugin(parent); + memset(&entry, 0, sizeof entry); + + /* first, delete directory entry */ + result = parent_dplug->rem_entry(parent, victim, &entry); + if (result == 0) { + /* + * if name was removed successfully, we _have_ to + * return 0 from this function, because upper level + * caller (vfs_{rmdir,unlink}) expect this. + * + * now that directory entry is removed, update + * stat-data + */ + reiser4_del_nlink(object, parent, 1); + /* + * Upon successful completion, unlink() shall mark for + * update the st_ctime and st_mtime fields of the + * parent directory. Also, if the file's link count is + * not 0, the st_ctime field of the file shall be + * marked for update. --SUS + */ + reiser4_update_dir(parent); + /* add safe-link for this file */ + if (object->i_nlink == 0) + safe_link_add(object, SAFE_UNLINK); + } + } + + if (unlikely(result != 0)) { + if (result != -ENOMEM) + warning("nikita-3398", "Cannot unlink %llu (%i)", + (unsigned long long)get_inode_oid(object), + result); + /* if operation failed commit pending inode modifications to + * the stat-data */ + reiser4_update_sd(object); + reiser4_update_sd(parent); + } + + reiser4_release_reserved(object->i_sb); + + /* @object's i_ctime was updated by ->rem_link() method(). */ + + /* @victim can be already removed from the disk by this time. Inode is + then marked so that iput() wouldn't try to remove stat data. But + inode itself is still there. + */ + + /* + * we cannot release directory semaphore here, because name has + * already been deleted, but dentry (@victim) still exists. Prevent + * balance_dirty_pages() from being called on exiting this context: we + * don't want to do this under directory i_sem. + */ + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return result; +} + +/** + * symlink_common - symlink of inode operations + * @parent: inode of parent directory + * @dentry: dentry of object to be created + * @linkname: string symlink is to contain + * + * This is common implementation of vfs's symlink method of struct + * inode_operations. + * Creates object using file plugin SYMLINK_FILE_PLUGIN_ID. + */ +int symlink_common(struct inode *parent, struct dentry *dentry, + const char *linkname) +{ + reiser4_object_create_data data; + + memset(&data, 0, sizeof data); + data.name = linkname; + data.id = SYMLINK_FILE_PLUGIN_ID; + data.mode = S_IFLNK | S_IRWXUGO; + return create_vfs_object(parent, dentry, &data); +} + +/** + * mkdir_common - mkdir of inode operations + * @parent: inode of parent directory + * @dentry: dentry of object to be created + * @mode: the permissions to use + * + * This is common implementation of vfs's mkdir method of struct + * inode_operations. + * Creates object using file plugin DIRECTORY_FILE_PLUGIN_ID. + */ +int mkdir_common(struct inode *parent, struct dentry *dentry, int mode) +{ + reiser4_object_create_data data; + + memset(&data, 0, sizeof data); + data.mode = S_IFDIR | mode; + data.id = DIRECTORY_FILE_PLUGIN_ID; + return create_vfs_object(parent, dentry, &data); +} + +/** + * mknod_common - mknod of inode operations + * @parent: inode of parent directory + * @dentry: dentry of object to be created + * @mode: the permissions to use and file type + * @rdev: minor and major of new device file + * + * This is common implementation of vfs's mknod method of struct + * inode_operations. + * Creates object using file plugin SPECIAL_FILE_PLUGIN_ID. + */ +int mknod_common(struct inode *parent, struct dentry *dentry, + int mode, dev_t rdev) +{ + reiser4_object_create_data data; + + memset(&data, 0, sizeof data); + data.mode = mode; + data.rdev = rdev; + data.id = SPECIAL_FILE_PLUGIN_ID; + return create_vfs_object(parent, dentry, &data); +} + +/* + * implementation of vfs's rename method of struct inode_operations for typical + * directory is in inode_ops_rename.c + */ + +/** + * readlink_common - readlink of inode operations + * @dentry: dentry of symlink + * @buf: user buffer to read symlink content to + * @buflen: size of user buffer + * + * This is common implementation of vfs's readlink method of struct + * inode_operations. + * Assumes that inode's generic_ip points to the content of symbolic link. + */ +int readlink_common(struct dentry *dentry, char __user *buf, int buflen) +{ + assert("vs-852", S_ISLNK(dentry->d_inode->i_mode)); + if (!dentry->d_inode->u.generic_ip + || !inode_get_flag(dentry->d_inode, REISER4_GENERIC_PTR_USED)) + return RETERR(-EINVAL); + return vfs_readlink(dentry, buf, buflen, dentry->d_inode->u.generic_ip); +} + +/** + * follow_link_common - follow_link of inode operations + * @dentry: dentry of symlink + * @data: + * + * This is common implementation of vfs's followlink method of struct + * inode_operations. + * Assumes that inode's generic_ip points to the content of symbolic link. + */ +void *follow_link_common(struct dentry *dentry, struct nameidata *nd) +{ + assert("vs-851", S_ISLNK(dentry->d_inode->i_mode)); + + if (!dentry->d_inode->u.generic_ip + || !inode_get_flag(dentry->d_inode, REISER4_GENERIC_PTR_USED)) + return ERR_PTR(RETERR(-EINVAL)); + nd_set_link(nd, dentry->d_inode->u.generic_ip); + return NULL; +} + +/* this is common implementation of vfs's permission method of struct + inode_operations +*/ +int permission_common(struct inode *inode /* object */ , + int mask, /* mode bits to check permissions for */ + struct nameidata *nameidata) +{ + /* reiser4_context creation/destruction removed from here, + because permission checks currently don't require this. + + Permission plugin have to create context itself if necessary. */ + assert("nikita-1687", inode != NULL); + + return perm_chk(inode, mask, inode, mask); +} + +static int setattr_reserve(reiser4_tree *); + +/* this is common implementation of vfs's setattr method of struct + inode_operations +*/ +int setattr_common(struct dentry *dentry, struct iattr *attr) +{ + reiser4_context *ctx; + struct inode *inode; + int result; + + inode = dentry->d_inode; + result = inode_change_ok(inode, attr); + if (result) + return result; + + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + assert("nikita-3119", !(attr->ia_valid & ATTR_SIZE)); + + /* + * grab disk space and call standard inode_setattr(). + */ + result = setattr_reserve(tree_by_inode(inode)); + if (!result) { + if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) + || (attr->ia_valid & ATTR_GID + && attr->ia_gid != inode->i_gid)) { + result = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; + if (result) { + all_grabbed2free(); + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return result; + } + } + result = inode_setattr(inode, attr); + if (!result) + reiser4_update_sd(inode); + } + + all_grabbed2free(); + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return result; +} + +/* this is common implementation of vfs's getattr method of struct + inode_operations +*/ +int +getattr_common(struct vfsmount *mnt UNUSED_ARG, struct dentry *dentry, + struct kstat *stat) +{ + struct inode *obj; + + assert("nikita-2298", dentry != NULL); + assert("nikita-2299", stat != NULL); + assert("nikita-2300", dentry->d_inode != NULL); + + obj = dentry->d_inode; + + stat->dev = obj->i_sb->s_dev; + stat->ino = oid_to_uino(get_inode_oid(obj)); + stat->mode = obj->i_mode; + /* don't confuse userland with huge nlink. This is not entirely + * correct, because nlink_t is not necessary 16 bit signed. */ + stat->nlink = min(obj->i_nlink, (typeof(obj->i_nlink)) 0x7fff); + stat->uid = obj->i_uid; + stat->gid = obj->i_gid; + stat->rdev = obj->i_rdev; + stat->atime = obj->i_atime; + stat->mtime = obj->i_mtime; + stat->ctime = obj->i_ctime; + stat->size = obj->i_size; + stat->blocks = + (inode_get_bytes(obj) + VFS_BLKSIZE - 1) >> VFS_BLKSIZE_BITS; + /* "preferred" blocksize for efficient file system I/O */ + stat->blksize = get_super_private(obj->i_sb)->optimal_io_size; + + return 0; +} + +/* Estimate the maximum amount of nodes which might be allocated or changed on + typical new object creation. Typical creation consists of calling create + method of file plugin, adding directory entry to parent and update parent + directory's stat data. +*/ +static reiser4_block_nr estimate_create_vfs_object(struct inode *parent, /* parent object */ + struct inode *object + /* object */ ) +{ + assert("vpf-309", parent != NULL); + assert("vpf-307", object != NULL); + + return + /* object creation estimation */ + inode_file_plugin(object)->estimate.create(object) + + /* stat data of parent directory estimation */ + inode_file_plugin(parent)->estimate.update(parent) + + /* adding entry estimation */ + inode_dir_plugin(parent)->estimate.add_entry(parent) + + /* to undo in the case of failure */ + inode_dir_plugin(parent)->estimate.rem_entry(parent); +} + +/* Create child in directory. + + . get object's plugin + . get fresh inode + . initialize inode + . add object's stat-data + . initialize object's directory + . add entry to the parent + . instantiate dentry + +*/ +static int do_create_vfs_child(reiser4_object_create_data * data, /* parameters of new + object */ + struct inode **retobj) +{ + int result; + + struct dentry *dentry; /* parent object */ + struct inode *parent; /* new name */ + + dir_plugin *par_dir; /* directory plugin on the parent */ + dir_plugin *obj_dir; /* directory plugin on the new object */ + file_plugin *obj_plug; /* object plugin on the new object */ + struct inode *object; /* new object */ + reiser4_block_nr reserve; + + reiser4_dir_entry_desc entry; /* new directory entry */ + + assert("nikita-1420", data != NULL); + parent = data->parent; + dentry = data->dentry; + + assert("nikita-1418", parent != NULL); + assert("nikita-1419", dentry != NULL); + + /* check permissions */ + result = perm_chk(parent, create, parent, dentry, data); + if (result != 0) + return result; + + /* check, that name is acceptable for parent */ + par_dir = inode_dir_plugin(parent); + if (par_dir->is_name_acceptable && + !par_dir->is_name_acceptable(parent, + dentry->d_name.name, + (int)dentry->d_name.len)) + return RETERR(-ENAMETOOLONG); + + result = 0; + obj_plug = file_plugin_by_id((int)data->id); + if (obj_plug == NULL) { + warning("nikita-430", "Cannot find plugin %i", data->id); + return RETERR(-ENOENT); + } + object = new_inode(parent->i_sb); + if (object == NULL) + return RETERR(-ENOMEM); + /* we'll update i_nlink below */ + object->i_nlink = 0; + /* new_inode() initializes i_ino to "arbitrary" value. Reset it to 0, + * to simplify error handling: if some error occurs before i_ino is + * initialized with oid, i_ino should already be set to some + * distinguished value. */ + object->i_ino = 0; + + /* So that on error iput will be called. */ + *retobj = object; + + if (DQUOT_ALLOC_INODE(object)) { + DQUOT_DROP(object); + object->i_flags |= S_NOQUOTA; + return RETERR(-EDQUOT); + } + + memset(&entry, 0, sizeof entry); + entry.obj = object; + + plugin_set_file(&reiser4_inode_data(object)->pset, obj_plug); + result = obj_plug->set_plug_in_inode(object, parent, data); + if (result) { + warning("nikita-431", "Cannot install plugin %i on %llx", + data->id, (unsigned long long)get_inode_oid(object)); + DQUOT_FREE_INODE(object); + object->i_flags |= S_NOQUOTA; + return result; + } + + /* reget plugin after installation */ + obj_plug = inode_file_plugin(object); + + if (obj_plug->create_object == NULL) { + DQUOT_FREE_INODE(object); + object->i_flags |= S_NOQUOTA; + return RETERR(-EPERM); + } + + /* if any of hash, tail, sd or permission plugins for newly created + object are not set yet set them here inheriting them from parent + directory + */ + assert("nikita-2070", obj_plug->adjust_to_parent != NULL); + result = obj_plug->adjust_to_parent(object, + parent, + object->i_sb->s_root->d_inode); + if (result != 0) { + warning("nikita-432", "Cannot inherit from %llx to %llx", + (unsigned long long)get_inode_oid(parent), + (unsigned long long)get_inode_oid(object)); + DQUOT_FREE_INODE(object); + object->i_flags |= S_NOQUOTA; + return result; + } + + /* setup inode and file-operations for this inode */ + setup_inode_ops(object, data); + + /* call file plugin's method to initialize plugin specific part of + * inode */ + if (obj_plug->init_inode_data) + obj_plug->init_inode_data(object, data, 1 /*create */ ); + + /* obtain directory plugin (if any) for new object. */ + obj_dir = inode_dir_plugin(object); + if (obj_dir != NULL && obj_dir->init == NULL) { + DQUOT_FREE_INODE(object); + object->i_flags |= S_NOQUOTA; + return RETERR(-EPERM); + } + + reiser4_inode_data(object)->locality_id = get_inode_oid(parent); + + reserve = estimate_create_vfs_object(parent, object); + if (reiser4_grab_space(reserve, BA_CAN_COMMIT)) { + DQUOT_FREE_INODE(object); + object->i_flags |= S_NOQUOTA; + return RETERR(-ENOSPC); + } + + /* mark inode `immutable'. We disable changes to the file being + created until valid directory entry for it is inserted. Otherwise, + if file were expanded and insertion of directory entry fails, we + have to remove file, but we only alloted enough space in + transaction to remove _empty_ file. 3.x code used to remove stat + data in different transaction thus possibly leaking disk space on + crash. This all only matters if it's possible to access file + without name, for example, by inode number + */ + inode_set_flag(object, REISER4_IMMUTABLE); + + /* create empty object, this includes allocation of new objectid. For + directories this implies creation of dot and dotdot */ + assert("nikita-2265", inode_get_flag(object, REISER4_NO_SD)); + + /* mark inode as `loaded'. From this point onward + reiser4_delete_inode() will try to remove its stat-data. */ + inode_set_flag(object, REISER4_LOADED); + + result = obj_plug->create_object(object, parent, data); + if (result != 0) { + inode_clr_flag(object, REISER4_IMMUTABLE); + if (result != -ENAMETOOLONG && result != -ENOMEM) + warning("nikita-2219", + "Failed to create sd for %llu", + (unsigned long long)get_inode_oid(object)); + DQUOT_FREE_INODE(object); + object->i_flags |= S_NOQUOTA; + return result; + } + + if (obj_dir != NULL) + result = obj_dir->init(object, parent, data); + if (result == 0) { + assert("nikita-434", !inode_get_flag(object, REISER4_NO_SD)); + /* insert inode into VFS hash table */ + insert_inode_hash(object); + /* create entry */ + result = par_dir->add_entry(parent, dentry, data, &entry); + if (result == 0) { + result = reiser4_add_nlink(object, parent, 0); + /* If O_CREAT is set and the file did not previously + exist, upon successful completion, open() shall + mark for update the st_atime, st_ctime, and + st_mtime fields of the file and the st_ctime and + st_mtime fields of the parent directory. --SUS + */ + /* @object times are already updated by + reiser4_add_nlink() */ + if (result == 0) + reiser4_update_dir(parent); + if (result != 0) + /* cleanup failure to add nlink */ + par_dir->rem_entry(parent, dentry, &entry); + } + if (result != 0) + /* cleanup failure to add entry */ + obj_plug->detach(object, parent); + } else if (result != -ENOMEM) + warning("nikita-2219", "Failed to initialize dir for %llu: %i", + (unsigned long long)get_inode_oid(object), result); + + /* + * update stat-data, committing all pending modifications to the inode + * fields. + */ + reiser4_update_sd(object); + if (result != 0) { + DQUOT_FREE_INODE(object); + object->i_flags |= S_NOQUOTA; + /* if everything was ok (result == 0), parent stat-data is + * already updated above (update_parent_dir()) */ + reiser4_update_sd(parent); + /* failure to create entry, remove object */ + obj_plug->delete_object(object); + } + + /* file has name now, clear immutable flag */ + inode_clr_flag(object, REISER4_IMMUTABLE); + + /* on error, iput() will call ->delete_inode(). We should keep track + of the existence of stat-data for this inode and avoid attempt to + remove it in reiser4_delete_inode(). This is accomplished through + REISER4_NO_SD bit in inode.u.reiser4_i.plugin.flags + */ + return result; +} + +/* this is helper for common implementations of reiser4_mkdir, reiser4_create, + reiser4_mknod and reiser4_symlink +*/ +static int +create_vfs_object(struct inode *parent, + struct dentry *dentry, reiser4_object_create_data * data) +{ + reiser4_context *ctx; + int result; + struct inode *child; + + ctx = init_context(parent->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + context_set_commit_async(ctx); + + data->parent = parent; + data->dentry = dentry; + child = NULL; + result = do_create_vfs_child(data, &child); + if (unlikely(result != 0)) { + if (child != NULL) { + reiser4_make_bad_inode(child); + iput(child); + } + } else + d_instantiate(dentry, child); + + reiser4_exit_context(ctx); + return result; +} + +/* helper for link_common. Estimate disk space necessary to add a link + from @parent to @object +*/ +static reiser4_block_nr common_estimate_link(struct inode *parent, /* parent directory */ + struct inode *object + /* object to which new link is being cerated */ + ) +{ + reiser4_block_nr res = 0; + file_plugin *fplug; + dir_plugin *dplug; + + assert("vpf-317", object != NULL); + assert("vpf-318", parent != NULL); + + fplug = inode_file_plugin(object); + dplug = inode_dir_plugin(parent); + /* VS-FIXME-HANS: why do we do fplug->estimate.update(object) twice instead of multiplying by 2? */ + /* reiser4_add_nlink(object) */ + res += fplug->estimate.update(object); + /* add_entry(parent) */ + res += dplug->estimate.add_entry(parent); + /* reiser4_del_nlink(object) */ + res += fplug->estimate.update(object); + /* update_dir(parent) */ + res += inode_file_plugin(parent)->estimate.update(parent); + /* safe-link */ + res += estimate_one_item_removal(tree_by_inode(object)); + + return res; +} + +/* Estimate disk space necessary to remove a link between @parent and + @object. +*/ +static reiser4_block_nr estimate_unlink(struct inode *parent, /* parent directory */ + struct inode *object + /* object to which new link is being cerated */ + ) +{ + reiser4_block_nr res = 0; + file_plugin *fplug; + dir_plugin *dplug; + + assert("vpf-317", object != NULL); + assert("vpf-318", parent != NULL); + + fplug = inode_file_plugin(object); + dplug = inode_dir_plugin(parent); + + /* rem_entry(parent) */ + res += dplug->estimate.rem_entry(parent); + /* reiser4_del_nlink(object) */ + res += fplug->estimate.update(object); + /* update_dir(parent) */ + res += inode_file_plugin(parent)->estimate.update(parent); + /* fplug->unlink */ + res += fplug->estimate.unlink(object, parent); + /* safe-link */ + res += estimate_one_insert_item(tree_by_inode(object)); + + return res; +} + +/* helper for unlink_common. Estimate and grab space for unlink. */ +static int unlink_check_and_grab(struct inode *parent, struct dentry *victim) +{ + file_plugin *fplug; + struct inode *child; + int result; + + result = 0; + child = victim->d_inode; + fplug = inode_file_plugin(child); + + /* check for race with create_object() */ + if (inode_get_flag(child, REISER4_IMMUTABLE)) + return RETERR(-E_REPEAT); + /* object being deleted should have stat data */ + assert("vs-949", !inode_get_flag(child, REISER4_NO_SD)); + + /* check permissions */ + result = perm_chk(parent, unlink, parent, victim); + if (result != 0) + return result; + + /* ask object plugin */ + if (fplug->can_rem_link != NULL && !fplug->can_rem_link(child)) + return RETERR(-ENOTEMPTY); + + result = (int)estimate_unlink(parent, child); + if (result < 0) + return result; + + return reiser4_grab_reserved(child->i_sb, result, BA_CAN_COMMIT); +} + +/* helper for setattr_common */ +static int setattr_reserve(reiser4_tree * tree) +{ + assert("vs-1096", is_grab_enabled(get_current_context())); + return reiser4_grab_space(estimate_one_insert_into_item(tree), + BA_CAN_COMMIT); +} + +/* helper function. Standards require that for many file-system operations + on success ctime and mtime of parent directory is to be updated. */ +int reiser4_update_dir(struct inode *dir) +{ + assert("nikita-2525", dir != NULL); + + dir->i_ctime = dir->i_mtime = CURRENT_TIME; + return reiser4_update_sd(dir); +} diff -puN /dev/null fs/reiser4/plugin/inode_ops_rename.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/inode_ops_rename.c 2005-09-15 19:51:08.000000000 -0700 @@ -0,0 +1,904 @@ +/* Copyright 2001, 2002, 2003, 2004 by Hans Reiser, licensing governed by + * reiser4/README */ + +#include "../inode.h" +#include "../safe_link.h" + +static const char *possible_leak = "Possible disk space leak."; + +/* re-bind existing name at @from_coord in @from_dir to point to @to_inode. + + Helper function called from hashed_rename() */ +static int replace_name(struct inode *to_inode, /* inode where @from_coord is + * to be re-targeted at */ + struct inode *from_dir, /* directory where @from_coord + * lives */ + struct inode *from_inode, /* inode @from_coord + * originally point to */ + coord_t * from_coord, /* where directory entry is in + * the tree */ + lock_handle * from_lh /* lock handle on @from_coord */ ) +{ + item_plugin *from_item; + int result; + znode *node; + + coord_clear_iplug(from_coord); + node = from_coord->node; + result = zload(node); + if (result != 0) + return result; + from_item = item_plugin_by_coord(from_coord); + if (item_type_by_coord(from_coord) == DIR_ENTRY_ITEM_TYPE) { + reiser4_key to_key; + + build_sd_key(to_inode, &to_key); + + /* everything is found and prepared to change directory entry + at @from_coord to point to @to_inode. + + @to_inode is just about to get new name, so bump its link + counter. + + */ + result = reiser4_add_nlink(to_inode, from_dir, 0); + if (result != 0) { + /* Don't issue warning: this may be plain -EMLINK */ + zrelse(node); + return result; + } + + result = + from_item->s.dir.update_key(from_coord, &to_key, from_lh); + if (result != 0) { + reiser4_del_nlink(to_inode, from_dir, 0); + zrelse(node); + return result; + } + + /* @from_inode just lost its name, he-he. + + If @from_inode was directory, it contained dotdot pointing + to @from_dir. @from_dir i_nlink will be decreased when + iput() will be called on @from_inode. + + If file-system is not ADG (hard-links are + supported on directories), iput(from_inode) will not remove + @from_inode, and thus above is incorrect, but hard-links on + directories are problematic in many other respects. + */ + result = reiser4_del_nlink(from_inode, from_dir, 0); + if (result != 0) { + warning("nikita-2330", + "Cannot remove link from source: %i. %s", + result, possible_leak); + } + /* Has to return success, because entry is already + * modified. */ + result = 0; + + /* NOTE-NIKITA consider calling plugin method in stead of + accessing inode fields directly. */ + from_dir->i_mtime = CURRENT_TIME; + } else { + warning("nikita-2326", "Unexpected item type"); + result = RETERR(-EIO); + } + zrelse(node); + return result; +} + +/* add new entry pointing to @inode into @dir at @coord, locked by @lh + + Helper function used by hashed_rename(). */ +static int add_name(struct inode *inode, /* inode where @coord is to be + * re-targeted at */ + struct inode *dir, /* directory where @coord lives */ + struct dentry *name, /* new name */ + coord_t * coord, /* where directory entry is in the tree */ + lock_handle * lh, /* lock handle on @coord */ + int is_dir /* true, if @inode is directory */ ) +{ + int result; + reiser4_dir_entry_desc entry; + + assert("nikita-2333", lh->node == coord->node); + assert("nikita-2334", is_dir == S_ISDIR(inode->i_mode)); + + memset(&entry, 0, sizeof entry); + entry.obj = inode; + /* build key of directory entry description */ + inode_dir_plugin(dir)->build_entry_key(dir, &name->d_name, &entry.key); + + /* ext2 does this in different order: first inserts new entry, + then increases directory nlink. We don't want do this, + because reiser4_add_nlink() calls ->add_link() plugin + method that can fail for whatever reason, leaving as with + cleanup problems. + */ + /* @inode is getting new name */ + reiser4_add_nlink(inode, dir, 0); + /* create @new_name in @new_dir pointing to + @old_inode */ + result = WITH_COORD(coord, + inode_dir_item_plugin(dir)->s.dir.add_entry(dir, + coord, + lh, + name, + &entry)); + if (result != 0) { + int result2; + result2 = reiser4_del_nlink(inode, dir, 0); + if (result2 != 0) { + warning("nikita-2327", + "Cannot drop link on %lli %i. %s", + (unsigned long long)get_inode_oid(inode), + result2, possible_leak); + } + } else + INODE_INC_FIELD(dir, i_size); + return result; +} + +static reiser4_block_nr estimate_rename(struct inode *old_dir, /* directory where @old is located */ + struct dentry *old_name, /* old name */ + struct inode *new_dir, /* directory where @new is located */ + struct dentry *new_name /* new name */ ) +{ + reiser4_block_nr res1, res2; + dir_plugin *p_parent_old, *p_parent_new; + file_plugin *p_child_old, *p_child_new; + + assert("vpf-311", old_dir != NULL); + assert("vpf-312", new_dir != NULL); + assert("vpf-313", old_name != NULL); + assert("vpf-314", new_name != NULL); + + p_parent_old = inode_dir_plugin(old_dir); + p_parent_new = inode_dir_plugin(new_dir); + p_child_old = inode_file_plugin(old_name->d_inode); + if (new_name->d_inode) + p_child_new = inode_file_plugin(new_name->d_inode); + else + p_child_new = NULL; + + /* find_entry - can insert one leaf. */ + res1 = res2 = 1; + + /* replace_name */ + { + /* reiser4_add_nlink(p_child_old) and reiser4_del_nlink(p_child_old) */ + res1 += 2 * p_child_old->estimate.update(old_name->d_inode); + /* update key */ + res1 += 1; + /* reiser4_del_nlink(p_child_new) */ + if (p_child_new) + res1 += p_child_new->estimate.update(new_name->d_inode); + } + + /* else add_name */ + { + /* reiser4_add_nlink(p_parent_new) and reiser4_del_nlink(p_parent_new) */ + res2 += + 2 * inode_file_plugin(new_dir)->estimate.update(new_dir); + /* reiser4_add_nlink(p_parent_old) */ + res2 += p_child_old->estimate.update(old_name->d_inode); + /* add_entry(p_parent_new) */ + res2 += p_parent_new->estimate.add_entry(new_dir); + /* reiser4_del_nlink(p_parent_old) */ + res2 += p_child_old->estimate.update(old_name->d_inode); + } + + res1 = res1 < res2 ? res2 : res1; + + /* reiser4_write_sd(p_parent_new) */ + res1 += inode_file_plugin(new_dir)->estimate.update(new_dir); + + /* reiser4_write_sd(p_child_new) */ + if (p_child_new) + res1 += p_child_new->estimate.update(new_name->d_inode); + + /* hashed_rem_entry(p_parent_old) */ + res1 += p_parent_old->estimate.rem_entry(old_dir); + + /* reiser4_del_nlink(p_child_old) */ + res1 += p_child_old->estimate.update(old_name->d_inode); + + /* replace_name */ + { + /* reiser4_add_nlink(p_parent_dir_new) */ + res1 += inode_file_plugin(new_dir)->estimate.update(new_dir); + /* update_key */ + res1 += 1; + /* reiser4_del_nlink(p_parent_new) */ + res1 += inode_file_plugin(new_dir)->estimate.update(new_dir); + /* reiser4_del_nlink(p_parent_old) */ + res1 += inode_file_plugin(old_dir)->estimate.update(old_dir); + } + + /* reiser4_write_sd(p_parent_old) */ + res1 += inode_file_plugin(old_dir)->estimate.update(old_dir); + + /* reiser4_write_sd(p_child_old) */ + res1 += p_child_old->estimate.update(old_name->d_inode); + + return res1; +} + +static int hashed_rename_estimate_and_grab(struct inode *old_dir, /* directory where @old is located */ + struct dentry *old_name, /* old name */ + struct inode *new_dir, /* directory where @new is located */ + struct dentry *new_name + /* new name */ ) +{ + reiser4_block_nr reserve; + + reserve = estimate_rename(old_dir, old_name, new_dir, new_name); + + if (reiser4_grab_space(reserve, BA_CAN_COMMIT)) + return RETERR(-ENOSPC); + + return 0; +} + +/* check whether @old_inode and @new_inode can be moved within file system + * tree. This singles out attempts to rename pseudo-files, for example. */ +static int can_rename(struct inode *old_dir, struct inode *old_inode, + struct inode *new_dir, struct inode *new_inode) +{ + file_plugin *fplug; + dir_plugin *dplug; + + assert("nikita-3370", old_inode != NULL); + + dplug = inode_dir_plugin(new_dir); + fplug = inode_file_plugin(old_inode); + + if (dplug == NULL) + return RETERR(-ENOTDIR); + else if (new_dir->i_op->create == NULL) + return RETERR(-EPERM); + else if (!fplug->can_add_link(old_inode)) + return RETERR(-EMLINK); + else if (new_inode != NULL) { + fplug = inode_file_plugin(new_inode); + if (fplug->can_rem_link != NULL && + !fplug->can_rem_link(new_inode)) + return RETERR(-EBUSY); + } + return 0; +} + +int find_entry(struct inode *, struct dentry *, lock_handle *, + znode_lock_mode, reiser4_dir_entry_desc *); +int reiser4_update_dir(struct inode *); + +/* this is common implementation of vfs's rename method of struct + inode_operations + See comments in the body. + + It is arguable that this function can be made generic so, that it + will be applicable to any kind of directory plugin that deals with + directories composed out of directory entries. The only obstacle + here is that we don't have any data-type to represent directory + entry. This should be re-considered when more than one different + directory plugin will be implemented. +*/ +int rename_common(struct inode *old_dir /* directory where @old is located */ , + struct dentry *old_name /* old name */ , + struct inode *new_dir /* directory where @new is located */ , + struct dentry *new_name /* new name */ ) +{ + /* From `The Open Group Base Specifications Issue 6' + + If either the old or new argument names a symbolic link, rename() + shall operate on the symbolic link itself, and shall not resolve + the last component of the argument. If the old argument and the new + argument resolve to the same existing file, rename() shall return + successfully and perform no other action. + + [this is done by VFS: vfs_rename()] + + If the old argument points to the pathname of a file that is not a + directory, the new argument shall not point to the pathname of a + directory. + + [checked by VFS: vfs_rename->may_delete()] + + If the link named by the new argument exists, it shall + be removed and old renamed to new. In this case, a link named new + shall remain visible to other processes throughout the renaming + operation and refer either to the file referred to by new or old + before the operation began. + + [we should assure this] + + Write access permission is required for + both the directory containing old and the directory containing new. + + [checked by VFS: vfs_rename->may_delete(), may_create()] + + If the old argument points to the pathname of a directory, the new + argument shall not point to the pathname of a file that is not a + directory. + + [checked by VFS: vfs_rename->may_delete()] + + If the directory named by the new argument exists, it + shall be removed and old renamed to new. In this case, a link named + new shall exist throughout the renaming operation and shall refer + either to the directory referred to by new or old before the + operation began. + + [we should assure this] + + If new names an existing directory, it shall be + required to be an empty directory. + + [we should check this] + + If the old argument points to a pathname of a symbolic link, the + symbolic link shall be renamed. If the new argument points to a + pathname of a symbolic link, the symbolic link shall be removed. + + The new pathname shall not contain a path prefix that names + old. Write access permission is required for the directory + containing old and the directory containing new. If the old + argument points to the pathname of a directory, write access + permission may be required for the directory named by old, and, if + it exists, the directory named by new. + + [checked by VFS: vfs_rename(), vfs_rename_dir()] + + If the link named by the new argument exists and the file's link + count becomes 0 when it is removed and no process has the file + open, the space occupied by the file shall be freed and the file + shall no longer be accessible. If one or more processes have the + file open when the last link is removed, the link shall be removed + before rename() returns, but the removal of the file contents shall + be postponed until all references to the file are closed. + + [iput() handles this, but we can do this manually, a la + reiser4_unlink()] + + Upon successful completion, rename() shall mark for update the + st_ctime and st_mtime fields of the parent directory of each file. + + [N/A] + + */ + reiser4_context *ctx; + int result; + int is_dir; /* is @old_name directory */ + + struct inode *old_inode; + struct inode *new_inode; + coord_t *new_coord; + + reiser4_dentry_fsdata *new_fsdata; + dir_plugin *dplug; + file_plugin *fplug; + + reiser4_dir_entry_desc *old_entry, *new_entry, *dotdot_entry; + lock_handle *new_lh, *dotdot_lh; + struct dentry *dotdot_name; + reiser4_dentry_fsdata *dataonstack; + + ctx = init_context(old_dir->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + old_entry = kmalloc(3 * sizeof(*old_entry) + 2 * sizeof(*new_lh) + + sizeof(*dotdot_name) + sizeof(*dataonstack), + GFP_KERNEL); + if (old_entry == NULL) { + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return RETERR(-ENOMEM); + } + memset(old_entry, 0, 3 * sizeof(*old_entry) + 2 * sizeof(*new_lh) + + sizeof(*dotdot_name) + sizeof(*dataonstack)); + + new_entry = old_entry + 1; + dotdot_entry = old_entry + 2; + new_lh = (lock_handle *)(old_entry + 3); + dotdot_lh = new_lh + 1; + dotdot_name = (struct dentry *)(new_lh + 2); + dataonstack = (reiser4_dentry_fsdata *)(dotdot_name + 1); + + assert("nikita-2318", old_dir != NULL); + assert("nikita-2319", new_dir != NULL); + assert("nikita-2320", old_name != NULL); + assert("nikita-2321", new_name != NULL); + + old_inode = old_name->d_inode; + new_inode = new_name->d_inode; + + dplug = inode_dir_plugin(old_dir); + fplug = NULL; + + new_fsdata = reiser4_get_dentry_fsdata(new_name); + if (IS_ERR(new_fsdata)) { + kfree(old_entry); + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return PTR_ERR(new_fsdata); + } + + new_coord = &new_fsdata->dec.entry_coord; + coord_clear_iplug(new_coord); + + is_dir = S_ISDIR(old_inode->i_mode); + + assert("nikita-3461", old_inode->i_nlink >= 1 + !!is_dir); + + /* if target is existing directory and it's not empty---return error. + + This check is done specifically, because is_dir_empty() requires + tree traversal and have to be done before locks are taken. + */ + if (is_dir && new_inode != NULL && is_dir_empty(new_inode) != 0) { + kfree(old_entry); + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return RETERR(-ENOTEMPTY); + } + + result = can_rename(old_dir, old_inode, new_dir, new_inode); + if (result != 0) { + kfree(old_entry); + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return result; + } + + result = hashed_rename_estimate_and_grab(old_dir, old_name, + new_dir, new_name); + if (result != 0) { + kfree(old_entry); + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return result; + } + + init_lh(new_lh); + + /* find entry for @new_name */ + result = find_entry(new_dir, + new_name, new_lh, ZNODE_WRITE_LOCK, new_entry); + + if (IS_CBKERR(result)) { + done_lh(new_lh); + kfree(old_entry); + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return result; + } + + seal_done(&new_fsdata->dec.entry_seal); + + /* add or replace name for @old_inode as @new_name */ + if (new_inode != NULL) { + /* target (@new_name) exists. */ + /* Not clear what to do with objects that are + both directories and files at the same time. */ + if (result == CBK_COORD_FOUND) { + result = replace_name(old_inode, + new_dir, + new_inode, new_coord, new_lh); + if (result == 0) + fplug = inode_file_plugin(new_inode); + } else if (result == CBK_COORD_NOTFOUND) { + /* VFS told us that @new_name is bound to existing + inode, but we failed to find directory entry. */ + warning("nikita-2324", "Target not found"); + result = RETERR(-ENOENT); + } + } else { + /* target (@new_name) doesn't exists. */ + if (result == CBK_COORD_NOTFOUND) + result = add_name(old_inode, + new_dir, + new_name, new_coord, new_lh, is_dir); + else if (result == CBK_COORD_FOUND) { + /* VFS told us that @new_name is "negative" dentry, + but we found directory entry. */ + warning("nikita-2331", "Target found unexpectedly"); + result = RETERR(-EIO); + } + } + + assert("nikita-3462", ergo(result == 0, + old_inode->i_nlink >= 2 + !!is_dir)); + + /* We are done with all modifications to the @new_dir, release lock on + node. */ + done_lh(new_lh); + + if (fplug != NULL) { + /* detach @new_inode from name-space */ + result = fplug->detach(new_inode, new_dir); + if (result != 0) + warning("nikita-2330", "Cannot detach %lli: %i. %s", + (unsigned long long)get_inode_oid(new_inode), + result, possible_leak); + } + + if (new_inode != NULL) + reiser4_update_sd(new_inode); + + if (result == 0) { + old_entry->obj = old_inode; + + dplug->build_entry_key(old_dir, + &old_name->d_name, &old_entry->key); + + /* At this stage new name was introduced for + @old_inode. @old_inode, @new_dir, and @new_inode i_nlink + counters were updated. + + We want to remove @old_name now. If @old_inode wasn't + directory this is simple. + */ + result = dplug->rem_entry(old_dir, old_name, old_entry); + if (result != 0 && result != -ENOMEM) { + warning("nikita-2335", + "Cannot remove old name: %i", result); + } else { + result = reiser4_del_nlink(old_inode, old_dir, 0); + if (result != 0 && result != -ENOMEM) { + warning("nikita-2337", + "Cannot drop link on old: %i", result); + } + } + + if (result == 0 && is_dir) { + /* @old_inode is directory. We also have to update + dotdot entry. */ + coord_t *dotdot_coord; + + memset(dataonstack, 0, sizeof dataonstack); + memset(dotdot_entry, 0, sizeof dotdot_entry); + dotdot_entry->obj = old_dir; + memset(dotdot_name, 0, sizeof dotdot_name); + dotdot_name->d_name.name = ".."; + dotdot_name->d_name.len = 2; + /* + * allocate ->d_fsdata on the stack to avoid using + * reiser4_get_dentry_fsdata(). Locking is not needed, + * because dentry is private to the current thread. + */ + dotdot_name->d_fsdata = dataonstack; + init_lh(dotdot_lh); + + dotdot_coord = &dataonstack->dec.entry_coord; + coord_clear_iplug(dotdot_coord); + + result = find_entry(old_inode, dotdot_name, dotdot_lh, + ZNODE_WRITE_LOCK, dotdot_entry); + if (result == 0) { + /* replace_name() decreases i_nlink on + * @old_dir */ + result = replace_name(new_dir, + old_inode, + old_dir, + dotdot_coord, dotdot_lh); + } else + result = RETERR(-EIO); + done_lh(dotdot_lh); + } + } + reiser4_update_dir(new_dir); + reiser4_update_dir(old_dir); + reiser4_update_sd(old_inode); + if (result == 0) { + file_plugin *fplug; + + if (new_inode != NULL) { + /* add safe-link for target file (in case we removed + * last reference to the poor fellow */ + fplug = inode_file_plugin(new_inode); + if (new_inode->i_nlink == 0) + result = safe_link_add(new_inode, SAFE_UNLINK); + } + } + kfree(old_entry); + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return result; +} + +#if 0 +int rename_common(struct inode *old_dir /* directory where @old is located */ , + struct dentry *old_name /* old name */ , + struct inode *new_dir /* directory where @new is located */ , + struct dentry *new_name /* new name */ ) +{ + /* From `The Open Group Base Specifications Issue 6' + + If either the old or new argument names a symbolic link, rename() + shall operate on the symbolic link itself, and shall not resolve + the last component of the argument. If the old argument and the new + argument resolve to the same existing file, rename() shall return + successfully and perform no other action. + + [this is done by VFS: vfs_rename()] + + If the old argument points to the pathname of a file that is not a + directory, the new argument shall not point to the pathname of a + directory. + + [checked by VFS: vfs_rename->may_delete()] + + If the link named by the new argument exists, it shall + be removed and old renamed to new. In this case, a link named new + shall remain visible to other processes throughout the renaming + operation and refer either to the file referred to by new or old + before the operation began. + + [we should assure this] + + Write access permission is required for + both the directory containing old and the directory containing new. + + [checked by VFS: vfs_rename->may_delete(), may_create()] + + If the old argument points to the pathname of a directory, the new + argument shall not point to the pathname of a file that is not a + directory. + + [checked by VFS: vfs_rename->may_delete()] + + If the directory named by the new argument exists, it + shall be removed and old renamed to new. In this case, a link named + new shall exist throughout the renaming operation and shall refer + either to the directory referred to by new or old before the + operation began. + + [we should assure this] + + If new names an existing directory, it shall be + required to be an empty directory. + + [we should check this] + + If the old argument points to a pathname of a symbolic link, the + symbolic link shall be renamed. If the new argument points to a + pathname of a symbolic link, the symbolic link shall be removed. + + The new pathname shall not contain a path prefix that names + old. Write access permission is required for the directory + containing old and the directory containing new. If the old + argument points to the pathname of a directory, write access + permission may be required for the directory named by old, and, if + it exists, the directory named by new. + + [checked by VFS: vfs_rename(), vfs_rename_dir()] + + If the link named by the new argument exists and the file's link + count becomes 0 when it is removed and no process has the file + open, the space occupied by the file shall be freed and the file + shall no longer be accessible. If one or more processes have the + file open when the last link is removed, the link shall be removed + before rename() returns, but the removal of the file contents shall + be postponed until all references to the file are closed. + + [iput() handles this, but we can do this manually, a la + reiser4_unlink()] + + Upon successful completion, rename() shall mark for update the + st_ctime and st_mtime fields of the parent directory of each file. + + [N/A] + + */ + reiser4_context *ctx; + int result; + int is_dir; /* is @old_name directory */ + struct inode *old_inode; + struct inode *new_inode; + reiser4_dir_entry_desc old_entry; + reiser4_dir_entry_desc new_entry; + coord_t *new_coord; + reiser4_dentry_fsdata *new_fsdata; + lock_handle new_lh; + dir_plugin *dplug; + file_plugin *fplug; + + ctx = init_context(old_dir->i_sb); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + assert("nikita-2318", old_dir != NULL); + assert("nikita-2319", new_dir != NULL); + assert("nikita-2320", old_name != NULL); + assert("nikita-2321", new_name != NULL); + + old_inode = old_name->d_inode; + new_inode = new_name->d_inode; + + dplug = inode_dir_plugin(old_dir); + fplug = NULL; + + new_fsdata = reiser4_get_dentry_fsdata(new_name); + if (IS_ERR(new_fsdata)) { + result = PTR_ERR(new_fsdata); + goto exit; + } + + new_coord = &new_fsdata->dec.entry_coord; + coord_clear_iplug(new_coord); + + is_dir = S_ISDIR(old_inode->i_mode); + + assert("nikita-3461", old_inode->i_nlink >= 1 + !!is_dir); + + /* if target is existing directory and it's not empty---return error. + + This check is done specifically, because is_dir_empty() requires + tree traversal and have to be done before locks are taken. + */ + if (is_dir && new_inode != NULL && is_dir_empty(new_inode) != 0) + return RETERR(-ENOTEMPTY); + + result = can_rename(old_dir, old_inode, new_dir, new_inode); + if (result != 0) + goto exit; + + result = hashed_rename_estimate_and_grab(old_dir, old_name, + new_dir, new_name); + if (result != 0) + goto exit; + + init_lh(&new_lh); + + /* find entry for @new_name */ + result = find_entry(new_dir, + new_name, &new_lh, ZNODE_WRITE_LOCK, &new_entry); + + if (IS_CBKERR(result)) { + done_lh(&new_lh); + goto exit; + } + + seal_done(&new_fsdata->dec.entry_seal); + + /* add or replace name for @old_inode as @new_name */ + if (new_inode != NULL) { + /* target (@new_name) exists. */ + /* Not clear what to do with objects that are + both directories and files at the same time. */ + if (result == CBK_COORD_FOUND) { + result = replace_name(old_inode, + new_dir, + new_inode, new_coord, &new_lh); + if (result == 0) + fplug = inode_file_plugin(new_inode); + } else if (result == CBK_COORD_NOTFOUND) { + /* VFS told us that @new_name is bound to existing + inode, but we failed to find directory entry. */ + warning("nikita-2324", "Target not found"); + result = RETERR(-ENOENT); + } + } else { + /* target (@new_name) doesn't exists. */ + if (result == CBK_COORD_NOTFOUND) + result = add_name(old_inode, + new_dir, + new_name, new_coord, &new_lh, is_dir); + else if (result == CBK_COORD_FOUND) { + /* VFS told us that @new_name is "negative" dentry, + but we found directory entry. */ + warning("nikita-2331", "Target found unexpectedly"); + result = RETERR(-EIO); + } + } + + assert("nikita-3462", ergo(result == 0, + old_inode->i_nlink >= 2 + !!is_dir)); + + /* We are done with all modifications to the @new_dir, release lock on + node. */ + done_lh(&new_lh); + + if (fplug != NULL) { + /* detach @new_inode from name-space */ + result = fplug->detach(new_inode, new_dir); + if (result != 0) + warning("nikita-2330", "Cannot detach %lli: %i. %s", + (unsigned long long)get_inode_oid(new_inode), + result, possible_leak); + } + + if (new_inode != NULL) + reiser4_update_sd(new_inode); + + if (result == 0) { + memset(&old_entry, 0, sizeof old_entry); + old_entry.obj = old_inode; + + dplug->build_entry_key(old_dir, + &old_name->d_name, &old_entry.key); + + /* At this stage new name was introduced for + @old_inode. @old_inode, @new_dir, and @new_inode i_nlink + counters were updated. + + We want to remove @old_name now. If @old_inode wasn't + directory this is simple. + */ + result = dplug->rem_entry(old_dir, old_name, &old_entry); + /*result = rem_entry_hashed(old_dir, old_name, &old_entry); */ + if (result != 0 && result != -ENOMEM) { + warning("nikita-2335", + "Cannot remove old name: %i", result); + } else { + result = reiser4_del_nlink(old_inode, old_dir, 0); + if (result != 0 && result != -ENOMEM) { + warning("nikita-2337", + "Cannot drop link on old: %i", result); + } + } + + if (result == 0 && is_dir) { + /* @old_inode is directory. We also have to update + dotdot entry. */ + coord_t *dotdot_coord; + lock_handle dotdot_lh; + struct dentry dotdot_name; + reiser4_dir_entry_desc dotdot_entry; + reiser4_dentry_fsdata dataonstack; + reiser4_dentry_fsdata *fsdata; + + memset(&dataonstack, 0, sizeof dataonstack); + memset(&dotdot_entry, 0, sizeof dotdot_entry); + dotdot_entry.obj = old_dir; + memset(&dotdot_name, 0, sizeof dotdot_name); + dotdot_name.d_name.name = ".."; + dotdot_name.d_name.len = 2; + /* + * allocate ->d_fsdata on the stack to avoid using + * reiser4_get_dentry_fsdata(). Locking is not needed, + * because dentry is private to the current thread. + */ + dotdot_name.d_fsdata = &dataonstack; + init_lh(&dotdot_lh); + + fsdata = &dataonstack; + dotdot_coord = &fsdata->dec.entry_coord; + coord_clear_iplug(dotdot_coord); + + result = find_entry(old_inode, &dotdot_name, &dotdot_lh, + ZNODE_WRITE_LOCK, &dotdot_entry); + if (result == 0) { + /* replace_name() decreases i_nlink on + * @old_dir */ + result = replace_name(new_dir, + old_inode, + old_dir, + dotdot_coord, &dotdot_lh); + } else + result = RETERR(-EIO); + done_lh(&dotdot_lh); + } + } + reiser4_update_dir(new_dir); + reiser4_update_dir(old_dir); + reiser4_update_sd(old_inode); + if (result == 0) { + file_plugin *fplug; + + if (new_inode != NULL) { + /* add safe-link for target file (in case we removed + * last reference to the poor fellow */ + fplug = inode_file_plugin(new_inode); + if (new_inode->i_nlink == 0) + result = safe_link_add(new_inode, SAFE_UNLINK); + } + } + exit: + context_set_commit_async(ctx); + reiser4_exit_context(ctx); + return result; +} +#endif diff -puN fs/reiser4/plugin/item/acl.h~reiser4-big-update fs/reiser4/plugin/item/acl.h --- devel/fs/reiser4/plugin/item/acl.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/acl.h 2005-09-15 19:51:08.000000000 -0700 @@ -22,7 +22,7 @@ typedef struct directory_entry_format { We store key as array of bytes, because we don't want 8-byte alignment of dir entries. - */ + */ obj_key_id id; /* file name. Null terminated string. */ d8 name[0]; @@ -30,19 +30,21 @@ typedef struct directory_entry_format { void print_de(const char *prefix, coord_t * coord); int extract_key_de(const coord_t * coord, reiser4_key * key); -int update_key_de(const coord_t * coord, const reiser4_key * key, lock_handle * lh); +int update_key_de(const coord_t * coord, const reiser4_key * key, + lock_handle * lh); char *extract_name_de(const coord_t * coord, char *buf); unsigned extract_file_type_de(const coord_t * coord); int add_entry_de(struct inode *dir, coord_t * coord, - lock_handle * lh, const struct dentry *name, reiser4_dir_entry_desc * entry); -int rem_entry_de(struct inode *dir, const struct qstr * name, coord_t * coord, lock_handle * lh, reiser4_dir_entry_desc * entry); + lock_handle * lh, const struct dentry *name, + reiser4_dir_entry_desc * entry); +int rem_entry_de(struct inode *dir, const struct qstr *name, coord_t * coord, + lock_handle * lh, reiser4_dir_entry_desc * entry); int max_name_len_de(const struct inode *dir); - int de_rem_and_shrink(struct inode *dir, coord_t * coord, int length); char *extract_dent_name(const coord_t * coord, - directory_entry_format *dent, char *buf); + directory_entry_format * dent, char *buf); #if REISER4_LARGE_KEY #define DE_NAME_BUF_LEN (24) diff -puN fs/reiser4/plugin/item/blackbox.c~reiser4-big-update fs/reiser4/plugin/item/blackbox.c --- devel/fs/reiser4/plugin/item/blackbox.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/blackbox.c 2005-09-15 19:51:08.000000000 -0700 @@ -15,10 +15,9 @@ #include "item.h" #include "../plugin.h" - -reiser4_internal int -store_black_box(reiser4_tree *tree, - const reiser4_key *key, void *data, int length) +int +store_black_box(reiser4_tree * tree, + const reiser4_key * key, void *data, int length) { int result; reiser4_item_data idata; @@ -38,15 +37,16 @@ store_black_box(reiser4_tree *tree, assert("nikita-3413", ergo(result == 0, - WITH_COORD(&coord, item_length_by_coord(&coord) == length))); + WITH_COORD(&coord, + item_length_by_coord(&coord) == length))); done_lh(&lh); return result; } -reiser4_internal int -load_black_box(reiser4_tree *tree, - reiser4_key *key, void *data, int length, int exact) +int +load_black_box(reiser4_tree * tree, + reiser4_key * key, void *data, int length, int exact) { int result; coord_t coord; @@ -89,9 +89,9 @@ load_black_box(reiser4_tree *tree, } -reiser4_internal int -update_black_box(reiser4_tree *tree, - const reiser4_key *key, void *data, int length) +int +update_black_box(reiser4_tree * tree, + const reiser4_key * key, void *data, int length) { int result; coord_t coord; @@ -109,7 +109,8 @@ update_black_box(reiser4_tree *tree, if (result == 0) { ilen = item_length_by_coord(&coord); if (length <= ilen) { - memcpy(item_body_by_coord(&coord), data, length); + memcpy(item_body_by_coord(&coord), data, + length); } else { warning("nikita-3437", "Wrong black box length: %i < %i", @@ -125,12 +126,11 @@ update_black_box(reiser4_tree *tree, } -reiser4_internal int kill_black_box(reiser4_tree *tree, const reiser4_key *key) +int kill_black_box(reiser4_tree * tree, const reiser4_key * key) { return cut_tree(tree, key, key, NULL, 1); } - /* Make Linus happy. Local variables: c-indentation-style: "K&R" diff -puN fs/reiser4/plugin/item/blackbox.h~reiser4-big-update fs/reiser4/plugin/item/blackbox.h --- devel/fs/reiser4/plugin/item/blackbox.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/blackbox.h 2005-09-15 19:51:08.000000000 -0700 @@ -11,13 +11,13 @@ #include "../../kassign.h" #include "../../key.h" -extern int store_black_box(reiser4_tree *tree, - const reiser4_key *key, void *data, int length); -extern int load_black_box(reiser4_tree *tree, - reiser4_key *key, void *data, int length, int exact); -extern int kill_black_box(reiser4_tree *tree, const reiser4_key *key); -extern int update_black_box(reiser4_tree *tree, - const reiser4_key *key, void *data, int length); +extern int store_black_box(reiser4_tree * tree, + const reiser4_key * key, void *data, int length); +extern int load_black_box(reiser4_tree * tree, + reiser4_key * key, void *data, int length, int exact); +extern int kill_black_box(reiser4_tree * tree, const reiser4_key * key); +extern int update_black_box(reiser4_tree * tree, + const reiser4_key * key, void *data, int length); /* __FS_REISER4_BLACK_BOX_H__ */ #endif diff -puN fs/reiser4/plugin/item/cde.c~reiser4-big-update fs/reiser4/plugin/item/cde.c --- devel/fs/reiser4/plugin/item/cde.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/cde.c 2005-09-15 19:51:08.000000000 -0700 @@ -86,35 +86,31 @@ #define CHECKME(coord) noop #endif - /* return body of compound directory item at @coord */ -static inline cde_item_format * -formatted_at(const coord_t * coord) +static inline cde_item_format *formatted_at(const coord_t * coord) { assert("nikita-1282", coord != NULL); return item_body_by_coord(coord); } /* return entry header at @coord */ -static inline cde_unit_header * -header_at(const coord_t * coord /* coord of item */ , - int idx /* index of unit */ ) +static inline cde_unit_header *header_at(const coord_t * + coord /* coord of item */ , + int idx /* index of unit */ ) { assert("nikita-1283", coord != NULL); return &formatted_at(coord)->entry[idx]; } /* return number of units in compound directory item at @coord */ -static int -units(const coord_t * coord /* coord of item */ ) +static int units(const coord_t * coord /* coord of item */ ) { return d16tocpu(&formatted_at(coord)->num_of_entries); } /* return offset of the body of @idx-th entry in @coord */ -static unsigned int -offset_of(const coord_t * coord /* coord of item */ , - int idx /* index of unit */ ) +static unsigned int offset_of(const coord_t * coord /* coord of item */ , + int idx /* index of unit */ ) { if (idx < units(coord)) return d16tocpu(&header_at(coord, idx)->offset); @@ -126,20 +122,18 @@ offset_of(const coord_t * coord /* coord } /* set offset of the body of @idx-th entry in @coord */ -static void -set_offset(const coord_t * coord /* coord of item */ , - int idx /* index of unit */ , - unsigned int offset /* new offset */ ) +static void set_offset(const coord_t * coord /* coord of item */ , + int idx /* index of unit */ , + unsigned int offset /* new offset */ ) { cputod16((__u16) offset, &header_at(coord, idx)->offset); } -static void -adj_offset(const coord_t * coord /* coord of item */ , - int idx /* index of unit */ , - int delta /* offset change */ ) +static void adj_offset(const coord_t * coord /* coord of item */ , + int idx /* index of unit */ , + int delta /* offset change */ ) { - d16 *doffset; + d16 *doffset; __u16 offset; doffset = &header_at(coord, idx)->offset; @@ -149,35 +143,32 @@ adj_offset(const coord_t * coord /* coor } /* return pointer to @offset-th byte from the beginning of @coord */ -static char * -address(const coord_t * coord /* coord of item */ , - int offset) +static char *address(const coord_t * coord /* coord of item */ , + int offset) { - return ((char *) item_body_by_coord(coord)) + offset; + return ((char *)item_body_by_coord(coord)) + offset; } /* return pointer to the body of @idx-th entry in @coord */ -static directory_entry_format * -entry_at(const coord_t * coord /* coord of - * item */ , - int idx /* index of unit */ ) +static directory_entry_format *entry_at(const coord_t * coord /* coord of + * item */ , + int idx /* index of unit */ ) { - return (directory_entry_format *) address(coord, (int) offset_of(coord, idx)); + return (directory_entry_format *) address(coord, + (int)offset_of(coord, idx)); } /* return number of unit referenced by @coord */ -static int -idx_of(const coord_t * coord /* coord of item */ ) +static int idx_of(const coord_t * coord /* coord of item */ ) { assert("nikita-1285", coord != NULL); return coord->unit_pos; } /* find position where entry with @entry_key would be inserted into @coord */ -static int -find(const coord_t * coord /* coord of item */ , - const reiser4_key * entry_key /* key to look for */ , - cmp_t * last /* result of last comparison */ ) +static int find(const coord_t * coord /* coord of item */ , + const reiser4_key * entry_key /* key to look for */ , + cmp_t * last /* result of last comparison */ ) { int entries; @@ -207,19 +198,19 @@ find(const coord_t * coord /* coord of i case GREATER_THAN: right = median; break; - case EQUAL_TO: { - do { - median --; - header --; - } while (median >= 0 && - de_id_key_cmp(&header->hash, - entry_key) == EQUAL_TO); - return median + 1; - } + case EQUAL_TO:{ + do { + median--; + header--; + } while (median >= 0 && + de_id_key_cmp(&header->hash, + entry_key) == EQUAL_TO); + return median + 1; + } } } header = header_at(coord, left); - for (; left < entries; ++ left, ++ header) { + for (; left < entries; ++left, ++header) { prefetch(header + 1); *last = de_id_key_cmp(&header->hash, entry_key); if (*last != LESS_THAN) @@ -234,13 +225,12 @@ find(const coord_t * coord /* coord of i /* expand @coord as to accommodate for insertion of @no new entries starting from @pos, with total bodies size @size. */ -static int -expand_item(const coord_t * coord /* coord of item */ , - int pos /* unit position */ , int no /* number of new - * units*/ , - int size /* total size of new units' data */ , - unsigned int data_size /* free space already reserved - * in the item for insertion */ ) +static int expand_item(const coord_t * coord /* coord of item */ , + int pos /* unit position */ , int no /* number of new + * units*/ , + int size /* total size of new units' data */ , + unsigned int data_size /* free space already reserved + * in the item for insertion */ ) { int entries; cde_unit_header *header; @@ -250,29 +240,33 @@ expand_item(const coord_t * coord /* coo assert("nikita-1310", coord != NULL); assert("nikita-1311", pos >= 0); assert("nikita-1312", no > 0); - assert("nikita-1313", data_size >= no * sizeof (directory_entry_format)); - assert("nikita-1343", item_length_by_coord(coord) >= (int) (size + data_size + no * sizeof *header)); + assert("nikita-1313", data_size >= no * sizeof(directory_entry_format)); + assert("nikita-1343", + item_length_by_coord(coord) >= + (int)(size + data_size + no * sizeof *header)); entries = units(coord); if (pos == entries) dent = address(coord, size); else - dent = (char *) entry_at(coord, pos); + dent = (char *)entry_at(coord, pos); /* place where new header will be in */ header = header_at(coord, pos); /* free space for new entry headers */ - memmove(header + no, header, (unsigned) (address(coord, size) - (char *) header)); + memmove(header + no, header, + (unsigned)(address(coord, size) - (char *)header)); /* if adding to the end initialise first new header */ if (pos == entries) { - set_offset(coord, pos, (unsigned) size); + set_offset(coord, pos, (unsigned)size); } /* adjust entry pointer and size */ dent = dent + no * sizeof *header; size += no * sizeof *header; /* free space for new entries */ - memmove(dent + data_size, dent, (unsigned) (address(coord, size) - dent)); + memmove(dent + data_size, dent, + (unsigned)(address(coord, size) - dent)); /* increase counter */ entries += no; @@ -290,41 +284,40 @@ expand_item(const coord_t * coord /* coo } /* insert new @entry into item */ -static int -expand(const coord_t * coord /* coord of item */ , - cde_entry * entry /* entry to insert */ , - int len /* length of @entry data */ , - int *pos /* position to insert */ , - reiser4_dir_entry_desc * dir_entry /* parameters for new - * entry */ ) +static int expand(const coord_t * coord /* coord of item */ , + cde_entry * entry /* entry to insert */ , + int len /* length of @entry data */ , + int *pos /* position to insert */ , + reiser4_dir_entry_desc * dir_entry /* parameters for new + * entry */ ) { cmp_t cmp_res; - int datasize; + int datasize; *pos = find(coord, &dir_entry->key, &cmp_res); if (*pos < 0) *pos = units(coord); - datasize = sizeof (directory_entry_format); + datasize = sizeof(directory_entry_format); if (is_longname(entry->name->name, entry->name->len)) datasize += entry->name->len + 1; - expand_item(coord, *pos, 1, item_length_by_coord(coord) - len, datasize); + expand_item(coord, *pos, 1, item_length_by_coord(coord) - len, + datasize); return 0; } /* paste body of @entry into item */ -static int -paste_entry(const coord_t * coord /* coord of item */ , - cde_entry * entry /* new entry */ , - int pos /* position to insert */ , - reiser4_dir_entry_desc * dir_entry /* parameters for - * new entry */ ) +static int paste_entry(const coord_t * coord /* coord of item */ , + cde_entry * entry /* new entry */ , + int pos /* position to insert */ , + reiser4_dir_entry_desc * dir_entry /* parameters for + * new entry */ ) { cde_unit_header *header; directory_entry_format *dent; const char *name; - int len; + int len; header = header_at(coord, pos); dent = entry_at(coord, pos); @@ -339,9 +332,9 @@ paste_entry(const coord_t * coord /* coo amount of space in dent -> name and be able to check that we are not going to overwrite more than we supposed to */ name = entry->name->name; - len = entry->name->len; + len = entry->name->len; if (is_longname(name, len)) { - strcpy((unsigned char *) dent->name, name); + strcpy((unsigned char *)dent->name, name); cputod8(0, &dent->name[len]); } return 0; @@ -349,9 +342,8 @@ paste_entry(const coord_t * coord /* coo /* estimate how much space is necessary in item to insert/paste set of entries described in @data. */ -reiser4_internal int -estimate_cde(const coord_t * coord /* coord of item */ , - const reiser4_item_data * data /* parameters for new item */ ) +int estimate_cde(const coord_t * coord /* coord of item */ , + const reiser4_item_data * data /* parameters for new item */ ) { cde_entry_data *e; int result; @@ -364,19 +356,19 @@ estimate_cde(const coord_t * coord /* co if (coord == NULL) /* insert */ - result = sizeof (cde_item_format); + result = sizeof(cde_item_format); else /* paste */ result = 0; result += e->num_of_entries * - (sizeof (cde_unit_header) + sizeof (directory_entry_format)); + (sizeof(cde_unit_header) + sizeof(directory_entry_format)); for (i = 0; i < e->num_of_entries; ++i) { const char *name; - int len; + int len; name = e->entry[i].name->name; - len = e->entry[i].name->len; + len = e->entry[i].name->len; assert("nikita-2054", strlen(name) == len); if (is_longname(name, len)) result += len + 1; @@ -386,23 +378,22 @@ estimate_cde(const coord_t * coord /* co } /* ->nr_units() method for this item plugin. */ -reiser4_internal pos_in_node_t -nr_units_cde(const coord_t * coord /* coord of item */ ) +pos_in_node_t nr_units_cde(const coord_t * coord /* coord of item */ ) { return units(coord); } /* ->unit_key() method for this item plugin. */ -reiser4_internal reiser4_key * -unit_key_cde(const coord_t * coord /* coord of item */ , - reiser4_key * key /* resulting key */ ) +reiser4_key *unit_key_cde(const coord_t * coord /* coord of item */ , + reiser4_key * key /* resulting key */ ) { assert("nikita-1452", coord != NULL); assert("nikita-1345", idx_of(coord) < units(coord)); assert("nikita-1346", key != NULL); item_key_by_coord(coord, key); - extract_key_from_de_id(extract_dir_id_from_key(key), &header_at(coord, idx_of(coord))->hash, key); + extract_key_from_de_id(extract_dir_id_from_key(key), + &header_at(coord, idx_of(coord))->hash, key); return key; } @@ -412,9 +403,8 @@ unit_key_cde(const coord_t * coord /* co directory. That simple. */ -reiser4_internal int -mergeable_cde(const coord_t * p1 /* coord of first item */ , - const coord_t * p2 /* coord of second item */ ) +int mergeable_cde(const coord_t * p1 /* coord of first item */ , + const coord_t * p2 /* coord of second item */ ) { reiser4_key k1; reiser4_key k2; @@ -430,9 +420,8 @@ mergeable_cde(const coord_t * p1 /* coor } /* ->max_key_inside() method for this item plugin. */ -reiser4_internal reiser4_key * -max_key_inside_cde(const coord_t * coord /* coord of item */ , - reiser4_key * result /* resulting key */) +reiser4_key *max_key_inside_cde(const coord_t * coord /* coord of item */ , + reiser4_key * result /* resulting key */ ) { assert("nikita-1342", coord != NULL); @@ -444,10 +433,9 @@ max_key_inside_cde(const coord_t * coord } /* @data contains data which are to be put into tree */ -reiser4_internal int -can_contain_key_cde(const coord_t * coord /* coord of item */ , - const reiser4_key * key /* key to check */ , - const reiser4_item_data * data /* parameters of new +int can_contain_key_cde(const coord_t * coord /* coord of item */ , + const reiser4_key * key /* key to check */ , + const reiser4_item_data * data /* parameters of new * item/unit being * created */ ) { @@ -460,68 +448,9 @@ can_contain_key_cde(const coord_t * coor item_key_by_coord(coord, &item_key); return (item_plugin_by_coord(coord) == data->iplug) && - (extract_dir_id_from_key(&item_key) == extract_dir_id_from_key(key)); -} - -#ifdef REISER4_DEBUG_OUTPUT -/* ->print() method for this item plugin. */ -reiser4_internal void -print_cde(const char *prefix /* prefix to print */ , - coord_t * coord /* coord of item to print */ ) -{ - assert("nikita-1077", prefix != NULL); - assert("nikita-1078", coord != NULL); - - if (item_length_by_coord(coord) < (int) sizeof (cde_item_format)) { - printk("%s: wrong size: %i < %i\n", prefix, item_length_by_coord(coord), sizeof (cde_item_format)); - } else { - char *name; - char *end; - char *start; - int i; - oid_t dirid; - reiser4_key key; - - start = address(coord, 0); - end = address(coord, item_length_by_coord(coord)); - item_key_by_coord(coord, &key); - dirid = extract_dir_id_from_key(&key); - - printk("%s: units: %i\n", prefix, nr_units_cde(coord)); - for (i = 0; i < units(coord); ++i) { - cde_unit_header *header; - - header = header_at(coord, i); - indent_znode(coord->node); - printk("\theader %i: ", i); - if ((char *) (header + 1) > end) { - printk("out of bounds: %p [%p, %p]\n", header, start, end); - } else { - extract_key_from_de_id(dirid, &header->hash, &key); - printk("%i: at %i, offset: %i, ", i, i * sizeof (*header), d16tocpu(&header->offset)); - print_key("key", &key); - } - } - for (i = 0; i < units(coord); ++i) { - directory_entry_format *entry; - char buf[DE_NAME_BUF_LEN]; - - entry = entry_at(coord, i); - indent_znode(coord->node); - printk("\tentry: %i: ", i); - if (((char *) (entry + 1) > end) || ((char *) entry < start)) { - printk("out of bounds: %p [%p, %p]\n", entry, start, end); - } else { - coord->unit_pos = i; - extract_key_cde(coord, &key); - name = extract_name_cde(coord, buf); - printk("at %i, name: %s, ", (char *) entry - start, name); - print_key("sdkey", &key); - } - } - } + (extract_dir_id_from_key(&item_key) == + extract_dir_id_from_key(key)); } -#endif #if REISER4_DEBUG /* cde_check ->check() method for compressed directory items @@ -530,9 +459,8 @@ print_cde(const char *prefix /* prefix t possible check of the consistency of the item that the inventor can construct */ -reiser4_internal int -check_cde(const coord_t * coord /* coord of item to check */ , - const char **error /* where to store error message */ ) +int check_cde(const coord_t * coord /* coord of item to check */ , + const char **error /* where to store error message */ ) { int i; int result; @@ -558,18 +486,19 @@ check_cde(const coord_t * coord /* coord for (i = 0; i < units(coord); ++i) { directory_entry_format *entry; - if ((char *) (header_at(coord, i) + 1) > item_end - units(coord) * sizeof *entry) { + if ((char *)(header_at(coord, i) + 1) > + item_end - units(coord) * sizeof *entry) { *error = "CDE header is out of bounds"; result = -1; break; } entry = entry_at(coord, i); - if ((char *) entry < item_start + sizeof (cde_item_format)) { + if ((char *)entry < item_start + sizeof(cde_item_format)) { *error = "CDE header is too low"; result = -1; break; } - if ((char *) (entry + 1) > item_end) { + if ((char *)(entry + 1) > item_end) { *error = "CDE header is too high"; result = -1; break; @@ -581,21 +510,18 @@ check_cde(const coord_t * coord /* coord #endif /* ->init() method for this item plugin. */ -reiser4_internal int -init_cde(coord_t * coord /* coord of item */ , - coord_t * from UNUSED_ARG, - reiser4_item_data * data /* structure used for insertion */ - UNUSED_ARG) +int init_cde(coord_t * coord /* coord of item */ , + coord_t * from UNUSED_ARG, reiser4_item_data * data /* structure used for insertion */ + UNUSED_ARG) { cputod16(0u, &formatted_at(coord)->num_of_entries); return 0; } /* ->lookup() method for this item plugin. */ -reiser4_internal lookup_result -lookup_cde(const reiser4_key * key /* key to search for */ , - lookup_bias bias /* search bias */ , - coord_t * coord /* coord of item to lookup in */ ) +lookup_result lookup_cde(const reiser4_key * key /* key to search for */ , + lookup_bias bias /* search bias */ , + coord_t * coord /* coord of item to lookup in */ ) { cmp_t last_comp; int pos; @@ -614,7 +540,7 @@ lookup_cde(const reiser4_key * key /* ke } pos = find(coord, key, &last_comp); if (pos >= 0) { - coord->unit_pos = (int) pos; + coord->unit_pos = (int)pos; switch (last_comp) { case EQUAL_TO: coord->between = AT_UNIT; @@ -630,16 +556,17 @@ lookup_cde(const reiser4_key * key /* ke } else { coord->unit_pos = units(coord) - 1; coord->between = AFTER_UNIT; - return (bias == FIND_MAX_NOT_MORE_THAN) ? CBK_COORD_FOUND : CBK_COORD_NOTFOUND; + return (bias == + FIND_MAX_NOT_MORE_THAN) ? CBK_COORD_FOUND : + CBK_COORD_NOTFOUND; } } /* ->paste() method for this item plugin. */ -reiser4_internal int -paste_cde(coord_t * coord /* coord of item */ , - reiser4_item_data * data /* parameters of new unit being +int paste_cde(coord_t * coord /* coord of item */ , + reiser4_item_data * data /* parameters of new unit being * inserted */ , - carry_plugin_info * info UNUSED_ARG /* todo carry queue */ ) + carry_plugin_info * info UNUSED_ARG /* todo carry queue */ ) { cde_entry_data *e; int result; @@ -655,9 +582,10 @@ paste_cde(coord_t * coord /* coord of it phantom_size = data->length; if (units(coord) == 0) - phantom_size -= sizeof (cde_item_format); + phantom_size -= sizeof(cde_item_format); - result = expand(coord, e->entry + i, phantom_size, &pos, data->arg); + result = + expand(coord, e->entry + i, phantom_size, &pos, data->arg); if (result != 0) break; result = paste_entry(coord, e->entry + i, pos, data->arg); @@ -670,15 +598,16 @@ paste_cde(coord_t * coord /* coord of it /* amount of space occupied by all entries starting from @idx both headers and bodies. */ -static unsigned int -part_size(const coord_t * coord /* coord of item */ , - int idx /* index of unit */ ) +static unsigned int part_size(const coord_t * coord /* coord of item */ , + int idx /* index of unit */ ) { assert("nikita-1299", coord != NULL); - assert("nikita-1300", idx < (int) units(coord)); + assert("nikita-1300", idx < (int)units(coord)); - return sizeof (cde_item_format) + - (idx + 1) * sizeof (cde_unit_header) + offset_of(coord, idx + 1) - offset_of(coord, 0); + return sizeof(cde_item_format) + + (idx + 1) * sizeof(cde_unit_header) + offset_of(coord, + idx + 1) - + offset_of(coord, 0); } /* how many but not more than @want units of @source can be merged with @@ -687,13 +616,12 @@ part_size(const coord_t * coord /* coord "prepend" first item in @target by last units of @source. @target node has @free_space bytes of free space. Total size of those units are returned via @size */ -reiser4_internal int -can_shift_cde(unsigned free_space /* free space in item */ , - coord_t * coord /* coord of source item */ , - znode * target /* target node */ , - shift_direction pend /* shift direction */ , - unsigned *size /* resulting number of shifted bytes */ , - unsigned want /* maximal number of bytes to shift */ ) +int can_shift_cde(unsigned free_space /* free space in item */ , + coord_t * coord /* coord of source item */ , + znode * target /* target node */ , + shift_direction pend /* shift direction */ , + unsigned *size /* resulting number of shifted bytes */ , + unsigned want /* maximal number of bytes to shift */ ) { int shift; @@ -705,10 +633,11 @@ can_shift_cde(unsigned free_space /* fre /* pend == SHIFT_LEFT <==> shifting to the left */ if (pend == SHIFT_LEFT) { - for (shift = min((int) want - 1, units(coord)); shift >= 0; --shift) { + for (shift = min((int)want - 1, units(coord)); shift >= 0; + --shift) { *size = part_size(coord, shift); if (target != NULL) - *size -= sizeof (cde_item_format); + *size -= sizeof(cde_item_format); if (*size <= free_space) break; } @@ -719,10 +648,11 @@ can_shift_cde(unsigned free_space /* fre assert("nikita-1301", pend == SHIFT_RIGHT); total_size = item_length_by_coord(coord); - for (shift = units(coord) - want - 1; shift < units(coord) - 1; ++shift) { + for (shift = units(coord) - want - 1; shift < units(coord) - 1; + ++shift) { *size = total_size - part_size(coord, shift); if (target == NULL) - *size += sizeof (cde_item_format); + *size += sizeof(cde_item_format); if (*size <= free_space) break; } @@ -735,13 +665,12 @@ can_shift_cde(unsigned free_space /* fre } /* ->copy_units() method for this item plugin. */ -reiser4_internal void -copy_units_cde(coord_t * target /* coord of target item */ , - coord_t * source /* coord of source item */ , - unsigned from /* starting unit */ , - unsigned count /* how many units to copy */ , - shift_direction where_is_free_space /* shift direction */ , - unsigned free_space /* free space in item */ ) +void copy_units_cde(coord_t * target /* coord of target item */ , + coord_t * source /* coord of source item */ , + unsigned from /* starting unit */ , + unsigned count /* how many units to copy */ , + shift_direction where_is_free_space /* shift direction */ , + unsigned free_space /* free space in item */ ) { char *header_from; char *header_to; @@ -756,58 +685,64 @@ copy_units_cde(coord_t * target /* coord assert("nikita-1303", target != NULL); assert("nikita-1304", source != NULL); - assert("nikita-1305", (int) from < units(source)); - assert("nikita-1307", (int) (from + count) <= units(source)); + assert("nikita-1305", (int)from < units(source)); + assert("nikita-1307", (int)(from + count) <= units(source)); if (where_is_free_space == SHIFT_LEFT) { assert("nikita-1453", from == 0); pos_in_target = units(target); } else { - assert("nikita-1309", (int) (from + count) == units(source)); + assert("nikita-1309", (int)(from + count) == units(source)); pos_in_target = 0; memmove(item_body_by_coord(target), - (char *) item_body_by_coord(target) + free_space, item_length_by_coord(target) - free_space); + (char *)item_body_by_coord(target) + free_space, + item_length_by_coord(target) - free_space); } CHECKME(target); CHECKME(source); /* expand @target */ - data_size = offset_of(source, (int) (from + count)) - offset_of(source, (int) from); + data_size = + offset_of(source, (int)(from + count)) - offset_of(source, + (int)from); if (units(target) == 0) - free_space -= sizeof (cde_item_format); + free_space -= sizeof(cde_item_format); - expand_item(target, pos_in_target, (int) count, - (int) (item_length_by_coord(target) - free_space), (unsigned) data_size); + expand_item(target, pos_in_target, (int)count, + (int)(item_length_by_coord(target) - free_space), + (unsigned)data_size); /* copy first @count units of @source into @target */ - data_delta = offset_of(target, pos_in_target) - offset_of(source, (int) from); + data_delta = + offset_of(target, pos_in_target) - offset_of(source, (int)from); /* copy entries */ - entry_from = (char *) entry_at(source, (int) from); - entry_to = (char *) entry_at(source, (int) (from + count)); - memmove(entry_at(target, pos_in_target), entry_from, (unsigned) (entry_to - entry_from)); + entry_from = (char *)entry_at(source, (int)from); + entry_to = (char *)entry_at(source, (int)(from + count)); + memmove(entry_at(target, pos_in_target), entry_from, + (unsigned)(entry_to - entry_from)); /* copy headers */ - header_from = (char *) header_at(source, (int) from); - header_to = (char *) header_at(source, (int) (from + count)); - memmove(header_at(target, pos_in_target), header_from, (unsigned) (header_to - header_from)); + header_from = (char *)header_at(source, (int)from); + header_to = (char *)header_at(source, (int)(from + count)); + memmove(header_at(target, pos_in_target), header_from, + (unsigned)(header_to - header_from)); /* update offsets */ - for (i = pos_in_target; i < (int) (pos_in_target + count); ++i) + for (i = pos_in_target; i < (int)(pos_in_target + count); ++i) adj_offset(target, i, data_delta); CHECKME(target); CHECKME(source); } /* ->cut_units() method for this item plugin. */ -reiser4_internal int -cut_units_cde(coord_t * coord /* coord of item */ , - pos_in_node_t from /* start unit pos */ , - pos_in_node_t to /* stop unit pos */ , - struct carry_cut_data *cdata UNUSED_ARG, reiser4_key *smallest_removed, - reiser4_key *new_first) +int cut_units_cde(coord_t * coord /* coord of item */ , + pos_in_node_t from /* start unit pos */ , + pos_in_node_t to /* stop unit pos */ , + struct carry_cut_data *cdata UNUSED_ARG, + reiser4_key * smallest_removed, reiser4_key * new_first) { char *header_from; char *header_to; @@ -827,7 +762,7 @@ cut_units_cde(coord_t * coord /* coord o count = to - from + 1; assert("nikita-1454", coord != NULL); - assert("nikita-1455", (int) (from + count) <= units(coord)); + assert("nikita-1455", (int)(from + count) <= units(coord)); if (smallest_removed) unit_key_by_coord(coord, smallest_removed); @@ -840,23 +775,24 @@ cut_units_cde(coord_t * coord /* coord o assert("vs-1528", to < units(coord) - 1); coord_dup(&next, coord); - next.unit_pos ++; + next.unit_pos++; unit_key_by_coord(&next, new_first); } size = item_length_by_coord(coord); - if (count == (unsigned) units(coord)) { + if (count == (unsigned)units(coord)) { return size; } - header_from = (char *) header_at(coord, (int) from); - header_to = (char *) header_at(coord, (int) (from + count)); + header_from = (char *)header_at(coord, (int)from); + header_to = (char *)header_at(coord, (int)(from + count)); - entry_from = (char *) entry_at(coord, (int) from); - entry_to = (char *) entry_at(coord, (int) (from + count)); + entry_from = (char *)entry_at(coord, (int)from); + entry_to = (char *)entry_at(coord, (int)(from + count)); /* move headers */ - memmove(header_from, header_to, (unsigned) (address(coord, size) - header_to)); + memmove(header_from, header_to, + (unsigned)(address(coord, size) - header_to)); header_delta = header_to - header_from; @@ -865,50 +801,53 @@ cut_units_cde(coord_t * coord /* coord o size -= header_delta; /* copy entries */ - memmove(entry_from, entry_to, (unsigned) (address(coord, size) - entry_to)); + memmove(entry_from, entry_to, + (unsigned)(address(coord, size) - entry_to)); entry_delta = entry_to - entry_from; size -= entry_delta; /* update offsets */ - for (i = 0; i < (int) from; ++i) - adj_offset(coord, i, - header_delta); + for (i = 0; i < (int)from; ++i) + adj_offset(coord, i, -header_delta); - for (i = from; i < units(coord) - (int) count; ++i) - adj_offset(coord, i, - header_delta - entry_delta); + for (i = from; i < units(coord) - (int)count; ++i) + adj_offset(coord, i, -header_delta - entry_delta); - cputod16((__u16) units(coord) - count, &formatted_at(coord)->num_of_entries); + cputod16((__u16) units(coord) - count, + &formatted_at(coord)->num_of_entries); if (from == 0) { /* entries from head was removed - move remaining to right */ - memmove((char *) item_body_by_coord(coord) + - header_delta + entry_delta, item_body_by_coord(coord), (unsigned) size); + memmove((char *)item_body_by_coord(coord) + + header_delta + entry_delta, item_body_by_coord(coord), + (unsigned)size); if (REISER4_DEBUG) - memset(item_body_by_coord(coord), 0, (unsigned) header_delta + entry_delta); + memset(item_body_by_coord(coord), 0, + (unsigned)header_delta + entry_delta); } else { /* freed space is already at the end of item */ if (REISER4_DEBUG) - memset((char *) item_body_by_coord(coord) + size, 0, (unsigned) header_delta + entry_delta); + memset((char *)item_body_by_coord(coord) + size, 0, + (unsigned)header_delta + entry_delta); } return header_delta + entry_delta; } -reiser4_internal int -kill_units_cde(coord_t * coord /* coord of item */ , - pos_in_node_t from /* start unit pos */ , - pos_in_node_t to /* stop unit pos */ , - struct carry_kill_data *kdata UNUSED_ARG, reiser4_key *smallest_removed, - reiser4_key *new_first) +int kill_units_cde(coord_t * coord /* coord of item */ , + pos_in_node_t from /* start unit pos */ , + pos_in_node_t to /* stop unit pos */ , + struct carry_kill_data *kdata UNUSED_ARG, + reiser4_key * smallest_removed, reiser4_key * new_first) { - return cut_units_cde(coord, from, to, 0, smallest_removed, new_first); + return cut_units_cde(coord, from, to, NULL, smallest_removed, new_first); } /* ->s.dir.extract_key() method for this item plugin. */ -reiser4_internal int -extract_key_cde(const coord_t * coord /* coord of item */ , - reiser4_key * key /* resulting key */ ) +int extract_key_cde(const coord_t * coord /* coord of item */ , + reiser4_key * key /* resulting key */ ) { directory_entry_format *dent; @@ -919,8 +858,9 @@ extract_key_cde(const coord_t * coord /* return extract_key_from_id(&dent->id, key); } -reiser4_internal int -update_key_cde(const coord_t * coord, const reiser4_key * key, lock_handle * lh UNUSED_ARG) +int +update_key_cde(const coord_t * coord, const reiser4_key * key, + lock_handle * lh UNUSED_ARG) { directory_entry_format *dent; obj_key_id obj_id; @@ -939,8 +879,7 @@ update_key_cde(const coord_t * coord, co } /* ->s.dir.extract_name() method for this item plugin. */ -reiser4_internal char * -extract_name_cde(const coord_t * coord /* coord of item */, char *buf) +char *extract_name_cde(const coord_t * coord /* coord of item */ , char *buf) { directory_entry_format *dent; @@ -950,24 +889,22 @@ extract_name_cde(const coord_t * coord / return extract_dent_name(coord, dent, buf); } -static int -cde_bytes(int pasting, const reiser4_item_data * data) +static int cde_bytes(int pasting, const reiser4_item_data * data) { int result; result = data->length; if (!pasting) - result -= sizeof (cde_item_format); + result -= sizeof(cde_item_format); return result; } /* ->s.dir.add_entry() method for this item plugin */ -reiser4_internal int -add_entry_cde(struct inode *dir /* directory object */ , - coord_t * coord /* coord of item */ , - lock_handle * lh /* lock handle for insertion */ , - const struct dentry *name /* name to insert */ , - reiser4_dir_entry_desc * dir_entry /* parameters of new +int add_entry_cde(struct inode *dir /* directory object */ , + coord_t * coord /* coord of item */ , + lock_handle * lh /* lock handle for insertion */ , + const struct dentry *name /* name to insert */ , + reiser4_dir_entry_desc * dir_entry /* parameters of new * directory entry */ ) { reiser4_item_data data; @@ -985,7 +922,7 @@ add_entry_cde(struct inode *dir /* direc entry.obj = dir_entry->obj; entry.name = &name->d_name; - data.data = (char *) &edata; + data.data = (char *)&edata; data.user = 0; /* &edata is not user space */ data.iplug = item_plugin_by_id(COMPOUND_DIR_ID); data.arg = dir_entry; @@ -1006,15 +943,13 @@ add_entry_cde(struct inode *dir /* direc } /* ->s.dir.rem_entry() */ -reiser4_internal int -rem_entry_cde(struct inode *dir /* directory of item */ , - const struct qstr * name, - coord_t * coord /* coord of item */ , - lock_handle * lh UNUSED_ARG /* lock handle for +int rem_entry_cde(struct inode *dir /* directory of item */ , + const struct qstr *name, coord_t * coord /* coord of item */ , + lock_handle * lh UNUSED_ARG /* lock handle for * removal */ , - reiser4_dir_entry_desc * entry UNUSED_ARG /* parameters of - * directory entry - * being removed */ ) + reiser4_dir_entry_desc * entry UNUSED_ARG /* parameters of + * directory entry + * being removed */ ) { coord_t shadow; int result; @@ -1022,9 +957,10 @@ rem_entry_cde(struct inode *dir /* direc ON_DEBUG(char buf[DE_NAME_BUF_LEN]); assert("nikita-2870", strlen(name->name) == name->len); - assert("nikita-2869", !strcmp(name->name, extract_name_cde(coord, buf))); + assert("nikita-2869", + !strcmp(name->name, extract_name_cde(coord, buf))); - length = sizeof (directory_entry_format) + sizeof (cde_unit_header); + length = sizeof(directory_entry_format) + sizeof(cde_unit_header); if (is_longname(name->name, name->len)) length += name->len + 1; @@ -1040,9 +976,10 @@ rem_entry_cde(struct inode *dir /* direc coords, because it will modify them without respect to possible aliasing. To work around this, create temporary copy of @coord. - */ + */ coord_dup(&shadow, coord); - result = kill_node_content(coord, &shadow, NULL, NULL, NULL, NULL, NULL, 0); + result = + kill_node_content(coord, &shadow, NULL, NULL, NULL, NULL, NULL, 0); if (result == 0) { /* NOTE-NIKITA quota plugin? */ DQUOT_FREE_SPACE_NODIRTY(dir, length); @@ -1051,12 +988,12 @@ rem_entry_cde(struct inode *dir /* direc } /* ->s.dir.max_name_len() method for this item plugin */ -reiser4_internal int -max_name_len_cde(const struct inode *dir /* directory */ ) +int max_name_len_cde(const struct inode *dir /* directory */ ) { return tree_by_inode(dir)->nplug->max_item_size() - - sizeof (directory_entry_format) - sizeof (cde_item_format) - sizeof (cde_unit_header) - 2; + sizeof(directory_entry_format) - sizeof(cde_item_format) - + sizeof(cde_unit_header) - 2; } /* Make Linus happy. diff -puN fs/reiser4/plugin/item/cde.h~reiser4-big-update fs/reiser4/plugin/item/cde.h --- devel/fs/reiser4/plugin/item/cde.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/cde.h 2005-09-15 19:51:08.000000000 -0700 @@ -35,33 +35,42 @@ typedef struct cde_entry_data { /* plugin->item.b.* */ reiser4_key *max_key_inside_cde(const coord_t * coord, reiser4_key * result); -int can_contain_key_cde(const coord_t * coord, const reiser4_key * key, const reiser4_item_data *); +int can_contain_key_cde(const coord_t * coord, const reiser4_key * key, + const reiser4_item_data *); int mergeable_cde(const coord_t * p1, const coord_t * p2); pos_in_node_t nr_units_cde(const coord_t * coord); reiser4_key *unit_key_cde(const coord_t * coord, reiser4_key * key); int estimate_cde(const coord_t * coord, const reiser4_item_data * data); void print_cde(const char *prefix, coord_t * coord); int init_cde(coord_t * coord, coord_t * from, reiser4_item_data * data); -lookup_result lookup_cde(const reiser4_key * key, lookup_bias bias, coord_t * coord); -int paste_cde(coord_t * coord, reiser4_item_data * data, carry_plugin_info * info UNUSED_ARG); -int can_shift_cde(unsigned free_space, coord_t * coord, - znode * target, shift_direction pend, unsigned *size, unsigned want); -void copy_units_cde(coord_t * target, coord_t * source, - unsigned from, unsigned count, shift_direction where_is_free_space, unsigned free_space); +lookup_result lookup_cde(const reiser4_key * key, lookup_bias bias, + coord_t * coord); +int paste_cde(coord_t * coord, reiser4_item_data * data, + carry_plugin_info * info UNUSED_ARG); +int can_shift_cde(unsigned free_space, coord_t * coord, znode * target, + shift_direction pend, unsigned *size, unsigned want); +void copy_units_cde(coord_t * target, coord_t * source, unsigned from, + unsigned count, shift_direction where_is_free_space, + unsigned free_space); int cut_units_cde(coord_t * coord, pos_in_node_t from, pos_in_node_t to, - struct carry_cut_data *, reiser4_key * smallest_removed, reiser4_key *new_first); + struct carry_cut_data *, reiser4_key * smallest_removed, + reiser4_key * new_first); int kill_units_cde(coord_t * coord, pos_in_node_t from, pos_in_node_t to, - struct carry_kill_data *, reiser4_key * smallest_removed, reiser4_key *new_first); + struct carry_kill_data *, reiser4_key * smallest_removed, + reiser4_key * new_first); void print_cde(const char *prefix, coord_t * coord); int check_cde(const coord_t * coord, const char **error); /* plugin->u.item.s.dir.* */ int extract_key_cde(const coord_t * coord, reiser4_key * key); -int update_key_cde(const coord_t * coord, const reiser4_key * key, lock_handle * lh); +int update_key_cde(const coord_t * coord, const reiser4_key * key, + lock_handle * lh); char *extract_name_cde(const coord_t * coord, char *buf); int add_entry_cde(struct inode *dir, coord_t * coord, - lock_handle * lh, const struct dentry *name, reiser4_dir_entry_desc * entry); -int rem_entry_cde(struct inode *dir, const struct qstr * name, coord_t * coord, lock_handle * lh, reiser4_dir_entry_desc * entry); + lock_handle * lh, const struct dentry *name, + reiser4_dir_entry_desc * entry); +int rem_entry_cde(struct inode *dir, const struct qstr *name, coord_t * coord, + lock_handle * lh, reiser4_dir_entry_desc * entry); int max_name_len_cde(const struct inode *dir); /* __FS_REISER4_PLUGIN_COMPRESSED_DE_H__ */ diff -puN fs/reiser4/plugin/item/ctail.c~reiser4-big-update fs/reiser4/plugin/item/ctail.c --- devel/fs/reiser4/plugin/item/ctail.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/ctail.c 2005-09-15 19:51:08.000000000 -0700 @@ -40,40 +40,35 @@ Internal on-disk structure: #include /* return body of ctail item at @coord */ -static ctail_item_format * -ctail_formatted_at(const coord_t * coord) +static ctail_item_format *ctail_formatted_at(const coord_t * coord) { assert("edward-60", coord != NULL); return item_body_by_coord(coord); } -reiser4_internal int -cluster_shift_by_coord(const coord_t * coord) +int cluster_shift_by_coord(const coord_t * coord) { return d8tocpu(&ctail_formatted_at(coord)->cluster_shift); } -static unsigned long -off_by_coord(const coord_t * coord) +static unsigned long off_by_coord(const coord_t * coord) { - reiser4_key key; + reiser4_key key; return get_key_offset(item_key_by_coord(coord, &key)); } -static int -coord_is_unprepped_ctail(const coord_t * coord) +static int coord_is_unprepped_ctail(const coord_t * coord) { assert("edward-1233", coord != NULL); assert("edward-1234", item_id_by_coord(coord) == CTAIL_ID); assert("edward-1235", ergo((int)cluster_shift_by_coord(coord) == (int)UCTAIL_SHIFT, - nr_units_ctail(coord) == (pos_in_node_t)UCTAIL_NR_UNITS)); + nr_units_ctail(coord) == (pos_in_node_t) UCTAIL_NR_UNITS)); return (int)cluster_shift_by_coord(coord) == (int)UCTAIL_SHIFT; } -reiser4_internal unsigned long -clust_by_coord(const coord_t * coord, struct inode * inode) +unsigned long clust_by_coord(const coord_t * coord, struct inode *inode) { int shift; @@ -82,16 +77,14 @@ clust_by_coord(const coord_t * coord, st assert("edward-1236", ergo(!coord_is_unprepped_ctail(coord), shift == cluster_shift_by_coord(coord))); - } - else { + } else { assert("edward-1237", !coord_is_unprepped_ctail(coord)); shift = cluster_shift_by_coord(coord); } return off_by_coord(coord) >> shift; } -static int unsigned long -disk_cluster_size (const coord_t * coord) +static int unsigned long disk_cluster_size(const coord_t * coord) { assert("edward-1156", item_plugin_by_coord(coord) == item_plugin_by_id(CTAIL_ID)); @@ -103,28 +96,28 @@ disk_cluster_size (const coord_t * coord } /* true if the key is of first disk cluster item */ -static int -is_disk_cluster_key(const reiser4_key * key, const coord_t * coord) +static int is_disk_cluster_key(const reiser4_key * key, const coord_t * coord) { assert("edward-1239", item_id_by_coord(coord) == CTAIL_ID); return coord_is_unprepped_ctail(coord) || - ((get_key_offset(key) & ((loff_t)disk_cluster_size(coord) - 1)) == 0); + ((get_key_offset(key) & ((loff_t) disk_cluster_size(coord) - 1)) == + 0); } -static char * -first_unit(coord_t * coord) +static char *first_unit(coord_t * coord) { /* FIXME: warning: pointer of type `void *' used in arithmetic */ - return (char *)item_body_by_coord(coord) + sizeof (ctail_item_format); + return (char *)item_body_by_coord(coord) + sizeof(ctail_item_format); } /* plugin->u.item.b.max_key_inside : tail_max_key_inside */ /* plugin->u.item.b.can_contain_key */ -reiser4_internal int -can_contain_key_ctail(const coord_t *coord, const reiser4_key *key, const reiser4_item_data *data) +int +can_contain_key_ctail(const coord_t * coord, const reiser4_key * key, + const reiser4_item_data * data) { reiser4_key item_key; @@ -135,7 +128,8 @@ can_contain_key_ctail(const coord_t *coo if (get_key_locality(key) != get_key_locality(&item_key) || get_key_objectid(key) != get_key_objectid(&item_key)) return 0; - if (get_key_offset(&item_key) + nr_units_ctail(coord) != get_key_offset(key)) + if (get_key_offset(&item_key) + nr_units_ctail(coord) != + get_key_offset(key)) return 0; if (is_disk_cluster_key(key, coord)) return 0; @@ -144,13 +138,13 @@ can_contain_key_ctail(const coord_t *coo /* plugin->u.item.b.mergeable c-tails of different clusters are not mergeable */ -reiser4_internal int -mergeable_ctail(const coord_t * p1, const coord_t * p2) +int mergeable_ctail(const coord_t * p1, const coord_t * p2) { reiser4_key key1, key2; assert("edward-62", item_id_by_coord(p1) == CTAIL_ID); - assert("edward-61", item_type_by_coord(p1) == UNIX_FILE_METADATA_ITEM_TYPE); + assert("edward-61", + item_type_by_coord(p1) == UNIX_FILE_METADATA_ITEM_TYPE); if (item_id_by_coord(p2) != CTAIL_ID) { /* second item is of another type */ @@ -164,7 +158,7 @@ mergeable_ctail(const coord_t * p1, cons get_key_type(&key1) != get_key_type(&key2)) { /* items of different objects */ return 0; - } + } if (get_key_offset(&key1) + nr_units_ctail(p1) != get_key_offset(&key2)) /* not adjacent items */ return 0; @@ -174,18 +168,18 @@ mergeable_ctail(const coord_t * p1, cons } /* plugin->u.item.b.nr_units */ -reiser4_internal pos_in_node_t -nr_units_ctail(const coord_t * coord) +pos_in_node_t nr_units_ctail(const coord_t * coord) { - return (item_length_by_coord(coord) - sizeof(ctail_formatted_at(coord)->cluster_shift)); + return (item_length_by_coord(coord) - + sizeof(ctail_formatted_at(coord)->cluster_shift)); } /* plugin->u.item.b.estimate: estimate how much space is needed to insert/paste @data->length bytes into ctail at @coord */ -reiser4_internal int -estimate_ctail(const coord_t * coord /* coord of item */, - const reiser4_item_data * data /* parameters for new item */) +int estimate_ctail(const coord_t * coord /* coord of item */ , + const reiser4_item_data * + data /* parameters for new item */ ) { if (coord == NULL) /* insert */ @@ -195,36 +189,18 @@ estimate_ctail(const coord_t * coord /* return data->length; } -#ifdef REISER4_DEBUG_OUTPUT -/* ->print() method for this item plugin. */ -reiser4_internal void -print_ctail(const char *prefix /* prefix to print */ , - coord_t * coord /* coord of item to print */ ) -{ - assert("edward-63", prefix != NULL); - assert("edward-64", coord != NULL); - - if (item_length_by_coord(coord) < (int) sizeof (ctail_item_format)) - printk("%s: wrong size: %i < %i\n", prefix, item_length_by_coord(coord), sizeof (ctail_item_format)); - else - printk("%s: disk cluster shift: %d\n", prefix, cluster_shift_by_coord(coord)); -} -#endif - /* ->init() method for this item plugin. */ -reiser4_internal int -init_ctail(coord_t * to /* coord of item */, - coord_t * from /* old_item */, - reiser4_item_data * data /* structure used for insertion */) +int init_ctail(coord_t * to /* coord of item */ , + coord_t * from /* old_item */ , + reiser4_item_data * data /* structure used for insertion */ ) { - int cluster_shift; /* cpu value to convert */ + int cluster_shift; /* cpu value to convert */ if (data) { assert("edward-463", data->length > sizeof(ctail_item_format)); cluster_shift = *((int *)(data->arg)); data->length -= sizeof(ctail_item_format); - } - else { + } else { assert("edward-464", from != NULL); assert("edward-855", ctail_ok(from)); cluster_shift = (int)(cluster_shift_by_coord(from)); @@ -238,16 +214,14 @@ init_ctail(coord_t * to /* coord of item NULL: We are looking for item keys only */ #if REISER4_DEBUG -reiser4_internal int -ctail_ok (const coord_t *coord) +int ctail_ok(const coord_t * coord) { return coord_is_unprepped_ctail(coord) || - cluster_shift_ok(cluster_shift_by_coord(coord)); + cluster_shift_ok(cluster_shift_by_coord(coord)); } /* plugin->u.item.b.check */ -reiser4_internal int -check_ctail (const coord_t * coord, const char **error) +int check_ctail(const coord_t * coord, const char **error) { if (!ctail_ok(coord)) { if (error) @@ -259,8 +233,9 @@ check_ctail (const coord_t * coord, cons #endif /* plugin->u.item.b.paste */ -reiser4_internal int -paste_ctail(coord_t * coord, reiser4_item_data * data, carry_plugin_info * info UNUSED_ARG) +int +paste_ctail(coord_t * coord, reiser4_item_data * data, + carry_plugin_info * info UNUSED_ARG) { unsigned old_nr_units; @@ -268,22 +243,25 @@ paste_ctail(coord_t * coord, reiser4_ite /* copy only from kernel space */ assert("edward-66", data->user == 0); - old_nr_units = item_length_by_coord(coord) - sizeof(ctail_item_format) - data->length; + old_nr_units = + item_length_by_coord(coord) - sizeof(ctail_item_format) - + data->length; /* ctail items never get pasted in the middle */ if (coord->unit_pos == 0 && coord->between == AT_UNIT) { - /* paste at the beginning when create new item */ - assert("edward-450", item_length_by_coord(coord) == data->length + sizeof(ctail_item_format)); + /* paste at the beginning when create new item */ + assert("edward-450", + item_length_by_coord(coord) == + data->length + sizeof(ctail_item_format)); assert("edward-451", old_nr_units == 0); - } - else if (coord->unit_pos == old_nr_units - 1 && coord->between == AFTER_UNIT) { + } else if (coord->unit_pos == old_nr_units - 1 + && coord->between == AFTER_UNIT) { - /* paste at the end */ + /* paste at the end */ coord->unit_pos++; - } - else + } else impossible("edward-453", "bad paste position"); memcpy(first_unit(coord) + coord->unit_pos, data->data, data->length); @@ -298,7 +276,7 @@ paste_ctail(coord_t * coord, reiser4_ite /* plugin->u.item.b.can_shift number of units is returned via return value, number of bytes via @size. For ctail items they coincide */ -reiser4_internal int +int can_shift_ctail(unsigned free_space, coord_t * source, znode * target, shift_direction direction UNUSED_ARG, unsigned *size /* number of bytes */ , unsigned want) @@ -321,14 +299,14 @@ can_shift_ctail(unsigned free_space, coo /* plugin->u.item.b.copy_units cooperates with ->can_shift() */ -reiser4_internal void +void copy_units_ctail(coord_t * target, coord_t * source, - unsigned from, unsigned count /* units */, + unsigned from, unsigned count /* units */ , shift_direction where_is_free_space, - unsigned free_space /* bytes */) + unsigned free_space /* bytes */ ) { /* make sure that item @target is expanded already */ - assert("edward-69", (unsigned) item_length_by_coord(target) >= count); + assert("edward-69", (unsigned)item_length_by_coord(target) >= count); assert("edward-70", free_space == count || free_space == count + 1); assert("edward-858", ctail_ok(source)); @@ -339,7 +317,8 @@ copy_units_ctail(coord_t * target, coord assert("edward-71", from == 0); assert("edward-860", ctail_ok(target)); - memcpy(first_unit(target) + nr_units_ctail(target) - count, first_unit(source), count); + memcpy(first_unit(target) + nr_units_ctail(target) - count, + first_unit(source), count); } else { /* target item is moved to right already */ reiser4_key key; @@ -349,8 +328,7 @@ copy_units_ctail(coord_t * target, coord if (free_space == count) { init_ctail(target, source, NULL); //assert("edward-861", cluster_shift_by_coord(target) == d8tocpu(&ctail_formatted_at(target)->body[count])); - } - else { + } else { /* new item has been created */ assert("edward-862", ctail_ok(target)); } @@ -363,13 +341,13 @@ copy_units_ctail(coord_t * target, coord item_key_by_coord(source, &key); set_key_offset(&key, get_key_offset(&key) + from); - node_plugin_by_node(target->node)->update_item_key(target, &key, 0 /*info */); + node_plugin_by_node(target->node)->update_item_key(target, &key, + NULL /*info */); } } /* plugin->u.item.b.create_hook */ -reiser4_internal int -create_hook_ctail (const coord_t * coord, void * arg) +int create_hook_ctail(const coord_t * coord, void *arg) { assert("edward-864", znode_is_loaded(coord->node)); @@ -378,8 +356,9 @@ create_hook_ctail (const coord_t * coord } /* plugin->u.item.b.kill_hook */ -reiser4_internal int -kill_hook_ctail(const coord_t *coord, pos_in_node_t from, pos_in_node_t count, carry_kill_data *kdata) +int +kill_hook_ctail(const coord_t * coord, pos_in_node_t from, pos_in_node_t count, + carry_kill_data * kdata) { struct inode *inode; @@ -392,7 +371,8 @@ kill_hook_ctail(const coord_t *coord, po item_key_by_coord(coord, &key); if (from == 0 && is_disk_cluster_key(&key, coord)) { - cloff_t start = off_to_clust(get_key_offset(&key), inode); + cloff_t start = + off_to_clust(get_key_offset(&key), inode); truncate_page_cluster(inode, start); } } @@ -402,12 +382,11 @@ kill_hook_ctail(const coord_t *coord, po /* for shift_hook_ctail(), return true if the first disk cluster item has dirty child */ -static int -ctail_convertible (const coord_t *coord) +static int ctail_convertible(const coord_t * coord) { int result; - reiser4_key key; - jnode * child = NULL; + reiser4_key key; + jnode *child = NULL; assert("edward-477", coord != NULL); assert("edward-478", item_id_by_coord(coord) == CTAIL_ID); @@ -417,9 +396,10 @@ ctail_convertible (const coord_t *coord) return 1; item_key_by_coord(coord, &key); - child = jlookup(current_tree, - get_key_objectid(&key), - clust_by_coord(coord, NULL) << cluster_shift_by_coord(coord)); + child = jlookup(current_tree, + get_key_objectid(&key), + clust_by_coord(coord, + NULL) << cluster_shift_by_coord(coord)); if (!child) return 0; LOCK_JNODE(child); @@ -433,11 +413,10 @@ ctail_convertible (const coord_t *coord) } /* plugin->u.item.b.shift_hook */ -reiser4_internal int -shift_hook_ctail(const coord_t * item /* coord of item */ , - unsigned from UNUSED_ARG /* start unit */ , - unsigned count UNUSED_ARG /* stop unit */ , - znode * old_node /* old parent */ ) +int shift_hook_ctail(const coord_t * item /* coord of item */ , + unsigned from UNUSED_ARG /* start unit */ , + unsigned count UNUSED_ARG /* stop unit */ , + znode * old_node /* old parent */ ) { assert("edward-479", item != NULL); assert("edward-480", item->node != old_node); @@ -450,13 +429,14 @@ shift_hook_ctail(const coord_t * item /* } static int -cut_or_kill_ctail_units(coord_t * coord, pos_in_node_t from, pos_in_node_t to, int cut, - void *p, reiser4_key * smallest_removed, reiser4_key *new_first) +cut_or_kill_ctail_units(coord_t * coord, pos_in_node_t from, pos_in_node_t to, + int cut, void *p, reiser4_key * smallest_removed, + reiser4_key * new_first) { - pos_in_node_t count; /* number of units to cut */ + pos_in_node_t count; /* number of units to cut */ char *item; - count = to - from + 1; + count = to - from + 1; item = item_body_by_coord(coord); assert("edward-74", ergo(from != 0, to == coord_last_unit_pos(coord))); @@ -464,14 +444,16 @@ cut_or_kill_ctail_units(coord_t * coord, if (smallest_removed) { /* store smallest key removed */ item_key_by_coord(coord, smallest_removed); - set_key_offset(smallest_removed, get_key_offset(smallest_removed) + from); + set_key_offset(smallest_removed, + get_key_offset(smallest_removed) + from); } if (new_first) { assert("vs-1531", from == 0); item_key_by_coord(coord, new_first); - set_key_offset(new_first, get_key_offset(new_first) + from + count); + set_key_offset(new_first, + get_key_offset(new_first) + from + count); } if (!cut) @@ -485,9 +467,10 @@ cut_or_kill_ctail_units(coord_t * coord, memcpy(item + to + 1, item, sizeof(ctail_item_format)); item_key_by_coord(coord, &key); set_key_offset(&key, get_key_offset(&key) + count); - node_plugin_by_node(coord->node)->update_item_key(coord, &key, 0 /*info */ ); - } - else { + node_plugin_by_node(coord->node)->update_item_key(coord, + &key, + NULL); + } else { /* cut_units should not be called to cut evrything */ assert("vs-1532", ergo(cut, 0)); /* whole item is cut, so more then amount of space occupied @@ -496,31 +479,33 @@ cut_or_kill_ctail_units(coord_t * coord, } if (REISER4_DEBUG) memset(item, 0, count); - } - else if (REISER4_DEBUG) + } else if (REISER4_DEBUG) memset(item + sizeof(ctail_item_format) + from, 0, count); return count; } /* plugin->u.item.b.cut_units */ -reiser4_internal int -cut_units_ctail(coord_t *item, pos_in_node_t from, pos_in_node_t to, - carry_cut_data *cdata, reiser4_key *smallest_removed, reiser4_key *new_first) +int +cut_units_ctail(coord_t * item, pos_in_node_t from, pos_in_node_t to, + carry_cut_data * cdata, reiser4_key * smallest_removed, + reiser4_key * new_first) { - return cut_or_kill_ctail_units(item, from, to, 1, NULL, smallest_removed, new_first); + return cut_or_kill_ctail_units(item, from, to, 1, NULL, + smallest_removed, new_first); } /* plugin->u.item.b.kill_units */ -reiser4_internal int -kill_units_ctail(coord_t *item, pos_in_node_t from, pos_in_node_t to, - struct carry_kill_data *kdata, reiser4_key *smallest_removed, reiser4_key *new_first) +int +kill_units_ctail(coord_t * item, pos_in_node_t from, pos_in_node_t to, + struct carry_kill_data *kdata, reiser4_key * smallest_removed, + reiser4_key * new_first) { - return cut_or_kill_ctail_units(item, from, to, 0, kdata, smallest_removed, new_first); + return cut_or_kill_ctail_units(item, from, to, 0, kdata, + smallest_removed, new_first); } /* plugin->u.item.s.file.read */ -reiser4_internal int -read_ctail(struct file *file UNUSED_ARG, flow_t *f, hint_t *hint) +int read_ctail(struct file *file UNUSED_ARG, flow_t * f, hint_t * hint) { uf_coord_t *uf_coord; coord_t *coord; @@ -541,7 +526,8 @@ read_ctail(struct file *file UNUSED_ARG, assert("edward-886", ctail_ok(coord)); if (f->data) - memcpy(f->data, (char *)first_unit(coord), (size_t)nr_units_ctail(coord)); + memcpy(f->data, (char *)first_unit(coord), + (size_t) nr_units_ctail(coord)); dclust_set_extension(hint); mark_page_accessed(znode_page(coord->node)); @@ -552,13 +538,13 @@ read_ctail(struct file *file UNUSED_ARG, /* Reads a disk cluster consists of ctail items, attaches a transform stream with plain text */ -reiser4_internal int -ctail_read_cluster (reiser4_cluster_t * clust, struct inode * inode, int write) +int +ctail_read_cluster(reiser4_cluster_t * clust, struct inode *inode, int write) { int result; - compression_plugin * cplug; + compression_plugin *cplug; #if REISER4_DEBUG - reiser4_inode * info; + reiser4_inode *info; info = reiser4_inode_data(inode); #endif assert("edward-671", clust->hint != NULL); @@ -570,7 +556,7 @@ ctail_read_cluster (reiser4_cluster_t * if (result) return result; - result = find_cluster(clust, inode, 1 /* read */, write); + result = find_cluster(clust, inode, 1 /* read */ , write); if (cbk_errored(result)) return result; @@ -578,40 +564,39 @@ ctail_read_cluster (reiser4_cluster_t * set_hint_cluster(inode, clust->hint, clust->index + 1, ZNODE_READ_LOCK); - assert("edward-673", znode_is_any_locked(clust->hint->ext_coord.lh->node)); + assert("edward-673", znode_is_any_locked(clust->hint->lh.node)); if (clust->dstat == FAKE_DISK_CLUSTER || clust->dstat == UNPR_DISK_CLUSTER) { tfm_cluster_set_uptodate(&clust->tc); return 0; } - cplug = inode_compression_plugin(inode); + cplug = inode_compression_plugin(inode); if (cplug->alloc && !get_coa(&clust->tc, cplug->h.id)) { result = alloc_coa(&clust->tc, cplug, TFM_READ); if (result) return result; } result = inflate_cluster(clust, inode); - if(result) + if (result) return result; tfm_cluster_set_uptodate(&clust->tc); return 0; } /* read one locked page */ -reiser4_internal int -do_readpage_ctail(reiser4_cluster_t * clust, struct page *page) +int do_readpage_ctail(reiser4_cluster_t * clust, struct page *page) { int ret; unsigned cloff; - struct inode * inode; - char * data; + struct inode *inode; + char *data; size_t pgcnt; - tfm_cluster_t * tc = &clust->tc; + tfm_cluster_t *tc = &clust->tc; assert("edward-212", PageLocked(page)); - if(PageUptodate(page)) + if (PageUptodate(page)) goto exit; inode = page->mapping->host; @@ -619,12 +604,12 @@ do_readpage_ctail(reiser4_cluster_t * cl if (!tfm_cluster_is_uptodate(&clust->tc)) { clust->index = pg_to_clust(page->index, inode); unlock_page(page); - ret = ctail_read_cluster(clust, inode, 0 /* read only */); + ret = ctail_read_cluster(clust, inode, 0 /* read only */ ); lock_page(page); if (ret) return ret; } - if(PageUptodate(page)) + if (PageUptodate(page)) /* races with another read/write */ goto exit; @@ -644,7 +629,8 @@ do_readpage_ctail(reiser4_cluster_t * cl #if REISER4_DEBUG warning("edward-1168", "page %lu is not uptodate and disk cluster %lu (inode %llu) is unprepped\n", - page->index, clust->index, (unsigned long long)get_inode_oid(inode)); + page->index, clust->index, + (unsigned long long)get_inode_oid(inode)); #endif case FAKE_DISK_CLUSTER: /* fill the page by zeroes */ @@ -665,7 +651,7 @@ do_readpage_ctail(reiser4_cluster_t * cl data = kmap(page); memcpy(data, tfm_stream_data(tc, OUTPUT_STREAM) + cloff, pgcnt); - memset(data + pgcnt, 0, (size_t)PAGE_CACHE_SIZE - pgcnt); + memset(data + pgcnt, 0, (size_t) PAGE_CACHE_SIZE - pgcnt); flush_dcache_page(page); kunmap(page); SetPageUptodate(page); @@ -673,17 +659,16 @@ do_readpage_ctail(reiser4_cluster_t * cl default: impossible("edward-1169", "bad disk cluster state"); } - exit: + exit: return 0; } /* plugin->u.item.s.file.readpage */ -reiser4_internal int readpage_ctail(void * vp, struct page * page) +int readpage_ctail(void *vp, struct page *page) { int result; - hint_t hint; - lock_handle lh; - reiser4_cluster_t * clust = vp; + hint_t *hint; + reiser4_cluster_t *clust = vp; assert("edward-114", clust != NULL); assert("edward-115", PageLocked(page)); @@ -692,24 +677,29 @@ reiser4_internal int readpage_ctail(void assert("edward-118", page->mapping && page->mapping->host); assert("edward-867", !tfm_cluster_is_uptodate(&clust->tc)); - clust->hint = &hint; - result = load_file_hint(clust->file, &hint); - if (result) + hint = kmalloc(sizeof(*hint), GFP_KERNEL); + if (hint == NULL) + return RETERR(-ENOMEM); + clust->hint = hint; + result = load_file_hint(clust->file, hint); + if (result) { + kfree(hint); return result; - init_lh(&lh); - hint.ext_coord.lh = &lh; - + } + assert("vs-25", hint->ext_coord.lh == &hint->lh); result = do_readpage_ctail(clust, page); assert("edward-213", PageLocked(page)); - assert("edward-1163", ergo (!result, PageUptodate(page))); - assert("edward-868", ergo (!result, tfm_cluster_is_uptodate(&clust->tc))); + assert("edward-1163", ergo(!result, PageUptodate(page))); + assert("edward-868", + ergo(!result, tfm_cluster_is_uptodate(&clust->tc))); unlock_page(page); - hint.ext_coord.valid = 0; - save_file_hint(clust->file, &hint); - done_lh(&lh); + hint->ext_coord.valid = 0; + save_file_hint(clust->file, hint); + done_lh(&hint->lh); + kfree(hint); tfm_cluster_clr_uptodate(&clust->tc); return result; @@ -718,7 +708,7 @@ reiser4_internal int readpage_ctail(void /* Unconditionally reads a disk cluster. This is used by ->readpages() */ static int -ctail_read_page_cluster(reiser4_cluster_t * clust, struct inode * inode) +ctail_read_page_cluster(reiser4_cluster_t * clust, struct inode *inode) { int i; int result; @@ -726,17 +716,17 @@ ctail_read_page_cluster(reiser4_cluster_ assert("edward-1059", clust->win == NULL); assert("edward-780", inode != NULL); - result = prepare_page_cluster(inode, clust, 0 /* do not capture */); + result = prepare_page_cluster(inode, clust, 0 /* do not capture */ ); if (result) return result; - result = ctail_read_cluster(clust, inode, 0 /* read */); + result = ctail_read_cluster(clust, inode, 0 /* read */ ); if (result) goto out; /* stream is attached at this point */ assert("edward-781", tfm_cluster_is_uptodate(&clust->tc)); - for (i=0; i < clust->nr_pages; i++) { - struct page * page = clust->pages[i]; + for (i = 0; i < clust->nr_pages; i++) { + struct page *page = clust->pages[i]; lock_page(page); result = do_readpage_ctail(clust, page); unlock_page(page); @@ -744,7 +734,7 @@ ctail_read_page_cluster(reiser4_cluster_ break; } tfm_cluster_clr_uptodate(&clust->tc); - out: + out: release_cluster_pages_nocapture(clust); assert("edward-1060", !result); @@ -766,35 +756,39 @@ assert("edward-214", ergo(!list_empty(pa populate an address space with page clusters, and start reads against them. FIXME_EDWARD: this function should return errors */ -reiser4_internal void -readpages_ctail(void *vp, struct address_space *mapping, struct list_head *pages) +void +readpages_ctail(void *vp, struct address_space *mapping, + struct list_head *pages) { int ret = 0; - hint_t hint; - lock_handle lh; + hint_t *hint; reiser4_cluster_t clust; struct page *page; struct pagevec lru_pvec; - struct inode * inode = mapping->host; + struct inode *inode = mapping->host; int progress = 0; assert("edward-214", ergo(!list_empty(pages) && pages->next != pages->prev, - list_to_page(pages)->index < list_to_next_page(pages)->index)); + list_to_page(pages)->index < + list_to_next_page(pages)->index)); pagevec_init(&lru_pvec, 0); - reiser4_cluster_init(&clust, 0); + reiser4_cluster_init(&clust, NULL); clust.file = vp; - clust.hint = &hint; - - init_lh(&lh); + hint = kmalloc(sizeof(*hint), GFP_KERNEL); + if (hint == NULL) { + warning("vs-28", "failed to allocate hint"); + return; + } + clust.hint = hint; ret = alloc_cluster_pgset(&clust, cluster_nrpages(inode)); if (ret) goto out; - ret = load_file_hint(clust.file, &hint); + ret = load_file_hint(clust.file, hint); if (ret) goto out; - hint.ext_coord.lh = &lh; + assert("vs-26", hint->ext_coord.lh == &hint->lh); /* address_space-level file readahead doesn't know about reiser4 page clustering, so we work around this fact */ @@ -827,7 +821,7 @@ readpages_ctail(void *vp, struct address if (ret) { warning("edward-215", "do_readpage_ctail failed"); unlock_page(page); - exit: + exit: while (!list_empty(pages)) { struct page *victim; @@ -842,10 +836,11 @@ readpages_ctail(void *vp, struct address unlock_page(page); } assert("edward-870", !tfm_cluster_is_uptodate(&clust.tc)); - save_file_hint(clust.file, &hint); - out: - done_lh(&lh); - hint.ext_coord.valid = 0; + save_file_hint(clust.file, hint); + out: + done_lh(&hint->lh); + hint->ext_coord.valid = 0; + kfree(hint); put_cluster_handle(&clust, TFM_READ); pagevec_lru_add(&lru_pvec); return; @@ -855,19 +850,21 @@ readpages_ctail(void *vp, struct address plugin->u.item.s.file.append_key key of the first item of the next disk cluster */ -reiser4_internal reiser4_key * -append_key_ctail(const coord_t *coord, reiser4_key *key) +reiser4_key *append_key_ctail(const coord_t * coord, reiser4_key * key) { assert("edward-1241", item_id_by_coord(coord) == CTAIL_ID); assert("edward-1242", cluster_shift_ok(cluster_shift_by_coord(coord))); item_key_by_coord(coord, key); - set_key_offset(key, ((__u64)(clust_by_coord(coord, NULL)) + 1) << cluster_shift_by_coord(coord) << PAGE_CACHE_SHIFT); + set_key_offset(key, + ((__u64) (clust_by_coord(coord, NULL)) + + 1) << cluster_shift_by_coord(coord) << + PAGE_CACHE_SHIFT); return key; } - static int -insert_unprepped_ctail(reiser4_cluster_t * clust, struct inode * inode) +static int +insert_unprepped_ctail(reiser4_cluster_t * clust, struct inode *inode) { int result; char buf[UCTAIL_NR_UNITS]; @@ -875,7 +872,7 @@ insert_unprepped_ctail(reiser4_cluster_t reiser4_key key; int shift = (int)UCTAIL_SHIFT; - memset(buf, 0, (size_t)UCTAIL_NR_UNITS); + memset(buf, 0, (size_t) UCTAIL_NR_UNITS); result = key_by_inode_cryptcompress(inode, clust_to_off(clust->index, inode), &key); @@ -884,61 +881,66 @@ insert_unprepped_ctail(reiser4_cluster_t data.user = 0; data.iplug = item_plugin_by_id(CTAIL_ID); data.arg = &shift; - data.length = sizeof(ctail_item_format) + (size_t)UCTAIL_NR_UNITS; + data.length = sizeof(ctail_item_format) + (size_t) UCTAIL_NR_UNITS; data.data = buf; result = insert_by_coord(&clust->hint->ext_coord.coord, - &data, - &key, - clust->hint->ext_coord.lh, 0); + &data, &key, clust->hint->ext_coord.lh, 0); return result; } static int -insert_crc_flow(coord_t * coord, lock_handle * lh, flow_t * f, struct inode * inode) +insert_crc_flow(coord_t * coord, lock_handle * lh, flow_t * f, + struct inode *inode) { int result; carry_pool *pool; - carry_level lowest_level; + carry_level *lowest_level; + reiser4_item_data *data; carry_op *op; - reiser4_item_data data; int cluster_shift = inode_cluster_shift(inode); - pool = init_carry_pool(); + pool = + init_carry_pool(sizeof(*pool) + 3 * sizeof(*lowest_level) + + sizeof(*data)); if (IS_ERR(pool)) return PTR_ERR(pool); - init_carry_level(&lowest_level, pool); - - assert("edward-466", coord->between == AFTER_ITEM || coord->between == AFTER_UNIT || - coord->between == BEFORE_ITEM || coord->between == EMPTY_NODE + lowest_level = (carry_level *) (pool + 1); + init_carry_level(lowest_level, pool); + data = (reiser4_item_data *) (lowest_level + 3); + + assert("edward-466", coord->between == AFTER_ITEM + || coord->between == AFTER_UNIT || coord->between == BEFORE_ITEM + || coord->between == EMPTY_NODE || coord->between == BEFORE_UNIT); if (coord->between == AFTER_UNIT) { coord->unit_pos = 0; coord->between = AFTER_ITEM; } - op = post_carry(&lowest_level, COP_INSERT_FLOW, coord->node, 0 /* operate directly on coord -> node */ ); + op = post_carry(lowest_level, COP_INSERT_FLOW, coord->node, + 0 /* operate directly on coord -> node */ ); if (IS_ERR(op) || (op == NULL)) { done_carry_pool(pool); return RETERR(op ? PTR_ERR(op) : -EIO); } - data.user = 0; - data.iplug = item_plugin_by_id(CTAIL_ID); - data.arg = &cluster_shift; + data->user = 0; + data->iplug = item_plugin_by_id(CTAIL_ID); + data->arg = &cluster_shift; - data.length = 0; - data.data = 0; + data->length = 0; + data->data = NULL; op->u.insert_flow.flags = COPI_DONT_SHIFT_LEFT | COPI_DONT_SHIFT_RIGHT; op->u.insert_flow.insert_point = coord; op->u.insert_flow.flow = f; - op->u.insert_flow.data = &data; + op->u.insert_flow.data = data; op->u.insert_flow.new_nodes = 0; - lowest_level.track_type = CARRY_TRACK_CHANGE; - lowest_level.tracked = lh; + lowest_level->track_type = CARRY_TRACK_CHANGE; + lowest_level->tracked = lh; - result = carry(&lowest_level, 0); + result = carry(lowest_level, NULL); done_carry_pool(pool); return result; @@ -946,21 +948,23 @@ insert_crc_flow(coord_t * coord, lock_ha /* Implementation of CRC_APPEND_ITEM mode of ctail conversion */ static int -insert_crc_flow_in_place(coord_t * coord, lock_handle * lh, flow_t * f, struct inode * inode) +insert_crc_flow_in_place(coord_t * coord, lock_handle * lh, flow_t * f, + struct inode *inode) { int ret; coord_t pos; lock_handle lock; assert("edward-674", f->length <= inode_scaled_cluster_size(inode)); - assert("edward-484", coord->between == AT_UNIT || coord->between == AFTER_ITEM); + assert("edward-484", coord->between == AT_UNIT + || coord->between == AFTER_ITEM); assert("edward-485", item_id_by_coord(coord) == CTAIL_ID); - coord_dup (&pos, coord); + coord_dup(&pos, coord); pos.unit_pos = 0; pos.between = AFTER_ITEM; - init_lh (&lock); + init_lh(&lock); copy_lh(&lock, lh); ret = insert_crc_flow(&pos, &lock, f, inode); @@ -971,8 +975,7 @@ insert_crc_flow_in_place(coord_t * coord } /* Implementation of CRC_OVERWRITE_ITEM mode of ctail conversion */ -static int -overwrite_ctail(coord_t * coord, flow_t * f) +static int overwrite_ctail(coord_t * coord, flow_t * f) { unsigned count; @@ -998,8 +1001,7 @@ overwrite_ctail(coord_t * coord, flow_t /* Implementation of CRC_CUT_ITEM mode of ctail conversion: cut ctail (part or whole) starting from next unit position */ -static int -cut_ctail(coord_t * coord) +static int cut_ctail(coord_t * coord) { coord_t stop; @@ -1007,7 +1009,7 @@ cut_ctail(coord_t * coord) coord->item_pos < coord_num_items(coord) && coord->unit_pos <= coord_num_units(coord)); - if(coord->unit_pos == coord_num_units(coord)) + if (coord->unit_pos == coord_num_units(coord)) /* nothing to cut */ return 0; coord_dup(&stop, coord); @@ -1016,7 +1018,8 @@ cut_ctail(coord_t * coord) return cut_node_content(coord, &stop, NULL, NULL, NULL); } -int ctail_insert_unprepped_cluster(reiser4_cluster_t * clust, struct inode * inode) +int +ctail_insert_unprepped_cluster(reiser4_cluster_t * clust, struct inode *inode) { int result; @@ -1024,37 +1027,39 @@ int ctail_insert_unprepped_cluster(reise assert("edward-1245", clust->hint != NULL); assert("edward-1246", clust->dstat == FAKE_DISK_CLUSTER); assert("edward-1247", clust->reserved == 1); - assert("edward-1248", get_current_context()->grabbed_blocks == + assert("edward-1248", get_current_context()->grabbed_blocks == estimate_insert_cluster(inode, 1)); result = get_disk_cluster_locked(clust, inode, ZNODE_WRITE_LOCK); if (cbk_errored(result)) return result; assert("edward-1249", result == CBK_COORD_NOTFOUND); - assert("edward-1250", znode_is_write_locked(clust->hint->ext_coord.lh->node)); + assert("edward-1250", znode_is_write_locked(clust->hint->lh.node)); - assert("edward-1295", - clust->hint->ext_coord.lh->node == clust->hint->ext_coord.coord.node); + assert("edward-1295", + clust->hint->ext_coord.lh->node == + clust->hint->ext_coord.coord.node); - coord_set_between_clusters(&clust->hint->ext_coord.coord); + coord_set_between_clusters(&clust->hint->ext_coord.coord); result = insert_unprepped_ctail(clust, inode); all_grabbed2free(); assert("edward-1251", !result); assert("edward-1252", crc_inode_ok(inode)); - assert("edward-1253", znode_is_write_locked(clust->hint->ext_coord.lh->node)); - assert("edward-1254", reiser4_clustered_blocks(reiser4_get_current_sb())); - assert("edward-1255", znode_convertible(clust->hint->ext_coord.coord.node)); + assert("edward-1253", znode_is_write_locked(clust->hint->lh.node)); + assert("edward-1254", + reiser4_clustered_blocks(reiser4_get_current_sb())); + assert("edward-1255", + znode_convertible(clust->hint->ext_coord.coord.node)); return result; } -static int -do_convert_ctail(flush_pos_t * pos, crc_write_mode_t mode) +static int do_convert_ctail(flush_pos_t * pos, crc_write_mode_t mode) { int result = 0; - convert_item_info_t * info; + convert_item_info_t *info; assert("edward-468", pos != NULL); assert("edward-469", pos->sq != NULL); @@ -1066,8 +1071,11 @@ do_convert_ctail(flush_pos_t * pos, crc_ switch (mode) { case CRC_APPEND_ITEM: assert("edward-1229", info->flow.length != 0); - assert("edward-1256", cluster_shift_ok(cluster_shift_by_coord(&pos->coord))); - result = insert_crc_flow_in_place(&pos->coord, &pos->lock, &info->flow, info->inode); + assert("edward-1256", + cluster_shift_ok(cluster_shift_by_coord(&pos->coord))); + result = + insert_crc_flow_in_place(&pos->coord, &pos->lock, + &info->flow, info->inode); break; case CRC_OVERWRITE_ITEM: assert("edward-1230", info->flow.length != 0); @@ -1086,12 +1094,12 @@ do_convert_ctail(flush_pos_t * pos, crc_ } /* plugin->u.item.f.scan */ -reiser4_internal int scan_ctail(flush_scan * scan) +int scan_ctail(flush_scan * scan) { int result = 0; - struct page * page; - struct inode * inode; - jnode * node = scan->node; + struct page *page; + struct inode *inode; + jnode *node = scan->node; assert("edward-227", scan->node != NULL); assert("edward-228", jnode_is_cluster_page(scan->node)); @@ -1108,10 +1116,12 @@ reiser4_internal int scan_ctail(flush_sc if (!znode_convertible(scan->parent_lock.node)) { LOCK_JNODE(scan->node); if (jnode_is_dirty(scan->node)) { - warning("edward-873", "child is dirty but parent not squeezable"); + warning("edward-873", + "child is dirty but parent not squeezable"); znode_set_convertible(scan->parent_lock.node); } else { - warning("edward-681", "cluster page is already processed"); + warning("edward-681", + "cluster page is already processed"); UNLOCK_JNODE(scan->node); return -EAGAIN; } @@ -1121,14 +1131,15 @@ reiser4_internal int scan_ctail(flush_sc } /* If true, this function attaches children */ -static int -should_attach_convert_idata(flush_pos_t * pos) +static int should_attach_convert_idata(flush_pos_t * pos) { int result; assert("edward-431", pos != NULL); assert("edward-432", pos->child == NULL); assert("edward-619", znode_is_write_locked(pos->coord.node)); - assert("edward-470", item_plugin_by_coord(&pos->coord) == item_plugin_by_id(CTAIL_ID)); + assert("edward-470", + item_plugin_by_coord(&pos->coord) == + item_plugin_by_id(CTAIL_ID)); /* check for leftmost child */ utmost_child_ctail(&pos->coord, LEFT_SIDE, &pos->child); @@ -1137,7 +1148,7 @@ should_attach_convert_idata(flush_pos_t return 0; LOCK_JNODE(pos->child); result = jnode_is_dirty(pos->child) && - pos->child->atom == ZJNODE(pos->coord.node)->atom; + pos->child->atom == ZJNODE(pos->coord.node)->atom; UNLOCK_JNODE(pos->child); if (!result && pos->child) { /* existing child isn't to attach, clear up this one */ @@ -1149,7 +1160,7 @@ should_attach_convert_idata(flush_pos_t /* plugin->init_convert_data() */ static int -init_convert_data_ctail(convert_item_info_t * idata, struct inode * inode) +init_convert_data_ctail(convert_item_info_t * idata, struct inode *inode) { assert("edward-813", idata != NULL); assert("edward-814", inode != NULL); @@ -1161,47 +1172,43 @@ init_convert_data_ctail(convert_item_inf return 0; } -static int -alloc_item_convert_data(convert_info_t * sq) +static int alloc_item_convert_data(convert_info_t * sq) { assert("edward-816", sq != NULL); assert("edward-817", sq->itm == NULL); - sq->itm = reiser4_kmalloc(sizeof(*sq->itm), GFP_KERNEL); + sq->itm = kmalloc(sizeof(*sq->itm), GFP_KERNEL); if (sq->itm == NULL) return RETERR(-ENOMEM); return 0; } -static void -free_item_convert_data(convert_info_t * sq) +static void free_item_convert_data(convert_info_t * sq) { assert("edward-818", sq != NULL); assert("edward-819", sq->itm != NULL); assert("edward-820", sq->iplug != NULL); - reiser4_kfree(sq->itm); + kfree(sq->itm); sq->itm = NULL; return; } -static int -alloc_convert_data(flush_pos_t * pos) +static int alloc_convert_data(flush_pos_t * pos) { assert("edward-821", pos != NULL); assert("edward-822", pos->sq == NULL); - pos->sq = reiser4_kmalloc(sizeof(*pos->sq), GFP_KERNEL); + pos->sq = kmalloc(sizeof(*pos->sq), GFP_KERNEL); if (!pos->sq) return RETERR(-ENOMEM); memset(pos->sq, 0, sizeof(*pos->sq)); return 0; } -reiser4_internal void -free_convert_data(flush_pos_t * pos) +void free_convert_data(flush_pos_t * pos) { - convert_info_t * sq; + convert_info_t *sq; assert("edward-823", pos != NULL); assert("edward-824", pos->sq != NULL); @@ -1210,15 +1217,14 @@ free_convert_data(flush_pos_t * pos) if (sq->itm) free_item_convert_data(sq); put_cluster_handle(&sq->clust, TFM_WRITE); - reiser4_kfree(pos->sq); + kfree(pos->sq); pos->sq = NULL; return; } -static int -init_item_convert_data(flush_pos_t * pos, struct inode * inode) +static int init_item_convert_data(flush_pos_t * pos, struct inode *inode) { - convert_info_t * sq; + convert_info_t *sq; assert("edward-825", pos != NULL); assert("edward-826", pos->sq != NULL); @@ -1235,21 +1241,22 @@ init_item_convert_data(flush_pos_t * pos /* create and attach disk cluster info used by 'convert' phase of the flush squalloc() */ -static int -attach_convert_idata(flush_pos_t * pos, struct inode * inode) +static int attach_convert_idata(flush_pos_t * pos, struct inode *inode) { int ret = 0; - convert_item_info_t * info; + convert_item_info_t *info; reiser4_cluster_t *clust; - file_plugin * fplug = inode_file_plugin(inode); - compression_plugin * cplug = inode_compression_plugin(inode); + file_plugin *fplug = inode_file_plugin(inode); + compression_plugin *cplug = inode_compression_plugin(inode); assert("edward-248", pos != NULL); assert("edward-249", pos->child != NULL); assert("edward-251", inode != NULL); assert("edward-682", crc_inode_ok(inode)); assert("edward-252", fplug == file_plugin_by_id(CRC_FILE_PLUGIN_ID)); - assert("edward-473", item_plugin_by_coord(&pos->coord) == item_plugin_by_id(CTAIL_ID)); + assert("edward-473", + item_plugin_by_coord(&pos->coord) == + item_plugin_by_id(CTAIL_ID)); if (!pos->sq) { ret = alloc_convert_data(pos); @@ -1269,8 +1276,7 @@ attach_convert_idata(flush_pos_t * pos, if (ret) goto err; } - reset_cluster_pgset(&convert_data(pos)->clust, - MAX_CLUSTER_NRPAGES); + reset_cluster_pgset(&convert_data(pos)->clust, MAX_CLUSTER_NRPAGES); assert("edward-829", pos->sq != NULL); assert("edward-250", item_convert_data(pos) == NULL); @@ -1291,7 +1297,8 @@ attach_convert_idata(flush_pos_t * pos, if (ret) goto err; - assert("edward-830", equi(get_coa(&clust->tc, cplug->h.id), cplug->alloc)); + assert("edward-830", + equi(get_coa(&clust->tc, cplug->h.id), cplug->alloc)); ret = deflate_cluster(clust, inode); if (ret) @@ -1301,27 +1308,25 @@ attach_convert_idata(flush_pos_t * pos, /* make flow by transformed stream */ fplug->flow_by_inode(info->inode, - tfm_stream_data(&clust->tc, OUTPUT_STREAM), - 0/* kernel space */, + (const char __user *)tfm_stream_data(&clust->tc, OUTPUT_STREAM), + 0 /* kernel space */ , clust->tc.len, clust_to_off(clust->index, inode), - WRITE_OP, - &info->flow); + WRITE_OP, &info->flow); jput(pos->child); assert("edward-683", crc_inode_ok(inode)); return 0; - err: + err: jput(pos->child); free_convert_data(pos); return ret; } /* clear up disk cluster info */ -static void -detach_convert_idata(convert_info_t * sq) +static void detach_convert_idata(convert_info_t * sq) { - convert_item_info_t * info; + convert_item_info_t *info; assert("edward-253", sq != NULL); assert("edward-840", sq->itm != NULL); @@ -1342,8 +1347,7 @@ detach_convert_idata(convert_info_t * sq if the child exists, and NULL in other cases. NOTE-EDWARD: Do not call this for RIGHT_SIDE */ -reiser4_internal int -utmost_child_ctail(const coord_t * coord, sideof side, jnode ** child) +int utmost_child_ctail(const coord_t * coord, sideof side, jnode ** child) { reiser4_key key; @@ -1352,13 +1356,15 @@ utmost_child_ctail(const coord_t * coord assert("edward-257", coord != NULL); assert("edward-258", child != NULL); assert("edward-259", side == LEFT_SIDE); - assert("edward-260", item_plugin_by_coord(coord) == item_plugin_by_id(CTAIL_ID)); + assert("edward-260", + item_plugin_by_coord(coord) == item_plugin_by_id(CTAIL_ID)); if (!is_disk_cluster_key(&key, coord)) *child = NULL; else *child = jlookup(current_tree, - get_key_objectid(item_key_by_coord(coord, &key)), + get_key_objectid(item_key_by_coord + (coord, &key)), off_to_pg(get_key_offset(&key))); return 0; } @@ -1368,8 +1374,7 @@ utmost_child_ctail(const coord_t * coord Disk cluster is a set of items. If ->clustered() != NULL, with each item the whole disk cluster should be read/modified */ -static int -clustered_ctail (const coord_t * p1, const coord_t * p2) +static int clustered_ctail(const coord_t * p1, const coord_t * p2) { return mergeable_ctail(p1, p2); } @@ -1381,20 +1386,21 @@ clustered_ctail (const coord_t * p1, con the slum because of races. If so, make it dirty and convertible. */ -static int -next_item_dc_stat(flush_pos_t * pos) +static int next_item_dc_stat(flush_pos_t * pos) { int ret = 0; int stop = 0; - znode * cur; + znode *cur; coord_t coord; lock_handle lh; lock_handle right_lock; assert("edward-1232", !node_is_empty(pos->coord.node)); - assert("edward-1014", pos->coord.item_pos < coord_num_items(&pos->coord)); + assert("edward-1014", + pos->coord.item_pos < coord_num_items(&pos->coord)); assert("edward-1015", chaining_data_present(pos)); - assert("edward-1017", item_convert_data(pos)->d_next == DC_INVALID_STATE); + assert("edward-1017", + item_convert_data(pos)->d_next == DC_INVALID_STATE); item_convert_data(pos)->d_next = DC_AFTER_CLUSTER; @@ -1432,20 +1438,20 @@ next_item_dc_stat(flush_pos_t * pos) if (!znode_is_dirty(lh.node)) { /* - warning("edward-1024", - "next slum item mergeable, " - "but znode %p isn't dirty\n", - lh.node); - */ + warning("edward-1024", + "next slum item mergeable, " + "but znode %p isn't dirty\n", + lh.node); + */ znode_make_dirty(lh.node); } if (!znode_convertible(lh.node)) { /* - warning("edward-1272", - "next slum item mergeable, " - "but znode %p isn't convertible\n", - lh.node); - */ + warning("edward-1272", + "next slum item mergeable, " + "but znode %p isn't convertible\n", + lh.node); + */ znode_set_convertible(lh.node); } stop = 1; @@ -1465,8 +1471,7 @@ next_item_dc_stat(flush_pos_t * pos) } static int -assign_convert_mode(convert_item_info_t * idata, - crc_write_mode_t * mode) +assign_convert_mode(convert_item_info_t * idata, crc_write_mode_t * mode) { int result = 0; @@ -1474,7 +1479,7 @@ assign_convert_mode(convert_item_info_t if (idata->flow.length) { /* append or overwrite */ - switch(idata->d_cur) { + switch (idata->d_cur) { case DC_FIRST_ITEM: case DC_CHAINED_ITEM: *mode = CRC_OVERWRITE_ITEM; @@ -1483,12 +1488,11 @@ assign_convert_mode(convert_item_info_t *mode = CRC_APPEND_ITEM; break; default: - impossible("edward-1018", - "wrong current item state"); + impossible("edward-1018", "wrong current item state"); } } else { /* cut or invalidate */ - switch(idata->d_cur) { + switch (idata->d_cur) { case DC_FIRST_ITEM: case DC_CHAINED_ITEM: *mode = CRC_CUT_ITEM; @@ -1497,8 +1501,7 @@ assign_convert_mode(convert_item_info_t result = 1; break; default: - impossible("edward-1019", - "wrong current item state"); + impossible("edward-1019", "wrong current item state"); } } return result; @@ -1506,8 +1509,7 @@ assign_convert_mode(convert_item_info_t /* plugin->u.item.f.convert */ /* write ctail in guessed mode */ -reiser4_internal int -convert_ctail(flush_pos_t * pos) +int convert_ctail(flush_pos_t * pos) { int result; int nr_items; @@ -1523,11 +1525,12 @@ convert_ctail(flush_pos_t * pos) if (!chaining_data_present(pos)) { if (should_attach_convert_idata(pos)) { /* attach convert item info */ - struct inode * inode; + struct inode *inode; assert("edward-264", pos->child != NULL); assert("edward-265", jnode_page(pos->child) != NULL); - assert("edward-266", jnode_page(pos->child)->mapping != NULL); + assert("edward-266", + jnode_page(pos->child)->mapping != NULL); inode = jnode_page(pos->child)->mapping->host; @@ -1545,15 +1548,13 @@ convert_ctail(flush_pos_t * pos) } if (result != 0) return result; - } - else + } else /* unconvertible */ return 0; - } - else { + } else { /* use old convert info */ - convert_item_info_t * idata; + convert_item_info_t *idata; idata = item_convert_data(pos); @@ -1567,7 +1568,8 @@ convert_ctail(flush_pos_t * pos) } assert("edward-433", chaining_data_present(pos)); - assert("edward-1022", pos->coord.item_pos < coord_num_items(&pos->coord)); + assert("edward-1022", + pos->coord.item_pos < coord_num_items(&pos->coord)); result = next_item_dc_stat(pos); if (result) { @@ -1603,9 +1605,12 @@ convert_ctail(flush_pos_t * pos) if (coord_is_unprepped_ctail(&pos->coord)) { /* convert unpprepped ctail to prepped one */ int shift; - shift = inode_cluster_shift(item_convert_data(pos)->inode); + shift = + inode_cluster_shift(item_convert_data(pos)->inode); assert("edward-1259", cluster_shift_ok(shift)); - cputod8(shift, &ctail_formatted_at(&pos->coord)->cluster_shift); + cputod8(shift, + &ctail_formatted_at(&pos->coord)-> + cluster_shift); } break; } diff -puN fs/reiser4/plugin/item/ctail.h~reiser4-big-update fs/reiser4/plugin/item/ctail.h --- devel/fs/reiser4/plugin/item/ctail.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/ctail.h 2005-09-15 19:51:08.000000000 -0700 @@ -13,7 +13,7 @@ typedef struct ctail_item_format { d8 cluster_shift; /* ctail body */ d8 body[0]; -} __attribute__((packed)) ctail_item_format; +} __attribute__ ((packed)) ctail_item_format; /* The following is a set of various item states in a disk cluster. Disk cluster is a set of items whose keys belong to the interval @@ -26,30 +26,36 @@ typedef enum { } dc_item_stat; typedef struct { - int shift; /* we keep here a cpu value of cluster_shift field - of ctail_item_format (see above) */ + int shift; /* we keep here a cpu value of cluster_shift field + of ctail_item_format (see above) */ } ctail_coord_extension_t; struct cut_list; /* plugin->item.b.* */ -int can_contain_key_ctail(const coord_t *, const reiser4_key *, const reiser4_item_data *); +int can_contain_key_ctail(const coord_t *, const reiser4_key *, + const reiser4_item_data *); int mergeable_ctail(const coord_t * p1, const coord_t * p2); pos_in_node_t nr_units_ctail(const coord_t * coord); int estimate_ctail(const coord_t * coord, const reiser4_item_data * data); void print_ctail(const char *prefix, coord_t * coord); lookup_result lookup_ctail(const reiser4_key *, lookup_bias, coord_t *); -int paste_ctail(coord_t * coord, reiser4_item_data * data, carry_plugin_info * info UNUSED_ARG); +int paste_ctail(coord_t * coord, reiser4_item_data * data, + carry_plugin_info * info UNUSED_ARG); int init_ctail(coord_t *, coord_t *, reiser4_item_data *); int can_shift_ctail(unsigned free_space, coord_t * coord, - znode * target, shift_direction pend, unsigned *size, unsigned want); -void copy_units_ctail(coord_t * target, coord_t * source, - unsigned from, unsigned count, shift_direction where_is_free_space, unsigned free_space); -int cut_units_ctail(coord_t *coord, pos_in_node_t from, pos_in_node_t to, - carry_cut_data *, reiser4_key * smallest_removed, reiser4_key *new_first); + znode * target, shift_direction pend, unsigned *size, + unsigned want); +void copy_units_ctail(coord_t * target, coord_t * source, unsigned from, + unsigned count, shift_direction where_is_free_space, + unsigned free_space); +int cut_units_ctail(coord_t * coord, pos_in_node_t from, pos_in_node_t to, + carry_cut_data *, reiser4_key * smallest_removed, + reiser4_key * new_first); int kill_units_ctail(coord_t * coord, pos_in_node_t from, pos_in_node_t to, - carry_kill_data *, reiser4_key * smallest_removed, reiser4_key *new_first); + carry_kill_data *, reiser4_key * smallest_removed, + reiser4_key * new_first); int ctail_ok(const coord_t * coord); int check_ctail(const coord_t * coord, const char **error); @@ -58,8 +64,9 @@ int read_ctail(struct file *, flow_t *, int readpage_ctail(void *, struct page *); void readpages_ctail(void *, struct address_space *, struct list_head *); reiser4_key *append_key_ctail(const coord_t *, reiser4_key *); -int create_hook_ctail (const coord_t * coord, void * arg); -int kill_hook_ctail(const coord_t *, pos_in_node_t, pos_in_node_t, carry_kill_data *); +int create_hook_ctail(const coord_t * coord, void *arg); +int kill_hook_ctail(const coord_t *, pos_in_node_t, pos_in_node_t, + carry_kill_data *); int shift_hook_ctail(const coord_t *, unsigned, unsigned, znode *); /* plugin->u.item.f */ @@ -69,7 +76,7 @@ int convert_ctail(flush_pos_t *); size_t inode_scaled_cluster_size(struct inode *); int cluster_shift_by_coord(const coord_t * coord); -#endif /* __FS_REISER4_CTAIL_H__ */ +#endif /* __FS_REISER4_CTAIL_H__ */ /* Make Linus happy. Local variables: diff -puN fs/reiser4/plugin/item/extent.c~reiser4-big-update fs/reiser4/plugin/item/extent.c --- devel/fs/reiser4/plugin/item/extent.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/extent.c 2005-09-15 19:51:08.000000000 -0700 @@ -10,24 +10,22 @@ #include "../../flush.h" #include "../object.h" - /* prepare structure reiser4_item_data. It is used to put one extent unit into tree */ /* Audited by: green(2002.06.13) */ -reiser4_internal reiser4_item_data * -init_new_extent(reiser4_item_data *data, void *ext_unit, int nr_extents) +reiser4_item_data *init_new_extent(reiser4_item_data * data, void *ext_unit, + int nr_extents) { data->data = ext_unit; /* data->data is kernel space */ data->user = 0; data->length = sizeof(reiser4_extent) * nr_extents; - data->arg = 0; + data->arg = NULL; data->iplug = item_plugin_by_id(EXTENT_POINTER_ID); return data; } /* how many bytes are addressed by @nr first extents of the extent item */ -reiser4_internal reiser4_block_nr -extent_size(const coord_t *coord, pos_in_node_t nr) +reiser4_block_nr extent_size(const coord_t * coord, pos_in_node_t nr) { pos_in_node_t i; reiser4_block_nr blocks; @@ -44,10 +42,9 @@ extent_size(const coord_t *coord, pos_in return blocks * current_blocksize; } -reiser4_internal extent_state -state_of_extent(reiser4_extent *ext) +extent_state state_of_extent(reiser4_extent * ext) { - switch ((int) extent_get_start(ext)) { + switch ((int)extent_get_start(ext)) { case 0: return HOLE_EXTENT; case 1: @@ -58,8 +55,7 @@ state_of_extent(reiser4_extent *ext) return ALLOCATED_EXTENT; } -reiser4_internal int -extent_is_unallocated(const coord_t *item) +int extent_is_unallocated(const coord_t * item) { assert("jmacd-5133", item_is_extent(item)); @@ -67,115 +63,136 @@ extent_is_unallocated(const coord_t *ite } /* set extent's start and width */ -reiser4_internal void -set_extent(reiser4_extent *ext, reiser4_block_nr start, reiser4_block_nr width) +void +set_extent(reiser4_extent * ext, reiser4_block_nr start, reiser4_block_nr width) { extent_set_start(ext, start); extent_set_width(ext, width); } -/* used in split_allocated_extent, conv_extent, plug_hole to insert 1 or 2 extent units (@exts_to_add) after the one - @un_extent is set to. @un_extent itself is changed to @replace */ -reiser4_internal int -replace_extent(coord_t *un_extent, lock_handle *lh, - reiser4_key *key, reiser4_item_data *exts_to_add, const reiser4_extent *replace, unsigned flags UNUSED_ARG, - int return_inserted_position /* if it is 1 - un_extent and lh are returned set to first of newly inserted - units, if it is 0 - un_extent and lh are returned set to unit which was - replaced */) + +/** + * replace_extent - replace extent and paste 1 or 2 after it + * @un_extent: coordinate of extent to be overwritten + * @lh: need better comment + * @key: need better comment + * @exts_to_add: data prepared for insertion into tree + * @replace: need better comment + * @flags: need better comment + * @return_insert_position: need better comment + * + * Overwrites one extent, pastes 1 or 2 more ones after overwritten one. If + * @return_inserted_position is 1 - @un_extent and @lh are returned set to + * first of newly inserted units, if it is 0 - @un_extent and @lh are returned + * set to extent which was overwritten. + */ +int replace_extent(struct replace_handle *h, int return_inserted_position) { int result; - coord_t coord_after; - lock_handle lh_after; - tap_t watch; znode *orig_znode; - ON_DEBUG(reiser4_extent orig_ext); /* this is for debugging */ + /*ON_DEBUG(reiser4_extent orig_ext);*/ /* this is for debugging */ - assert("vs-990", coord_is_existing_unit(un_extent)); - assert("vs-1375", znode_is_write_locked(un_extent->node)); - assert("vs-1426", extent_get_width(replace) != 0); - assert("vs-1427", extent_get_width((reiser4_extent *)exts_to_add->data) != 0); - - coord_dup(&coord_after, un_extent); - init_lh(&lh_after); - copy_lh(&lh_after, lh); - tap_init(&watch, &coord_after, &lh_after, ZNODE_WRITE_LOCK); - tap_monitor(&watch); + assert("vs-990", coord_is_existing_unit(h->coord)); + assert("vs-1375", znode_is_write_locked(h->coord->node)); + assert("vs-1426", extent_get_width(&h->overwrite) != 0); + assert("vs-1427", extent_get_width(&h->new_extents[0]) != 0); + assert("vs-1427", ergo(h->nr_new_extents == 2, + extent_get_width(&h->new_extents[1]) != 0)); + + /* compose structure for paste */ + init_new_extent(&h->item, &h->new_extents[0], h->nr_new_extents); + + coord_dup(&h->coord_after, h->coord); + init_lh(&h->lh_after); + copy_lh(&h->lh_after, h->lh); + tap_init(&h->watch, &h->coord_after, &h->lh_after, ZNODE_WRITE_LOCK); + tap_monitor(&h->watch); - ON_DEBUG(orig_ext = *extent_by_coord(un_extent)); - orig_znode = un_extent->node; + ON_DEBUG(h->orig_ext = *extent_by_coord(h->coord)); + orig_znode = h->coord->node; +#if REISER4_DEBUG /* make sure that key is set properly */ - if (REISER4_DEBUG) { - reiser4_key tmp; - - unit_key_by_coord(un_extent, &tmp); - set_key_offset(&tmp, get_key_offset(&tmp) + extent_get_width(replace) * current_blocksize); - assert("vs-1080", keyeq(&tmp, key)); - } + unit_key_by_coord(h->coord, &h->tmp); + set_key_offset(&h->tmp, + get_key_offset(&h->tmp) + + extent_get_width(&h->overwrite) * current_blocksize); + assert("vs-1080", keyeq(&h->tmp, &h->paste_key)); +#endif /* set insert point after unit to be replaced */ - un_extent->between = AFTER_UNIT; + h->coord->between = AFTER_UNIT; - result = insert_into_item(un_extent, - return_inserted_position ? lh : 0, - /*(flags == COPI_DONT_SHIFT_LEFT) ? 0 : lh,*/ key, exts_to_add, flags); + result = insert_into_item(h->coord, return_inserted_position ? h->lh : NULL, + &h->paste_key, &h->item, h->flags); if (!result) { - /* now we have to replace the unit after which new units were inserted. Its position is tracked by - @watch */ + /* now we have to replace the unit after which new units were + inserted. Its position is tracked by @watch */ reiser4_extent *ext; + znode *node; - if (coord_after.node != orig_znode) { - coord_clear_iplug(&coord_after); - result = zload(coord_after.node); + node = h->coord_after.node; + if (node != orig_znode) { + coord_clear_iplug(&h->coord_after); + result = zload(node); } if (likely(!result)) { - ext = extent_by_coord(&coord_after); + ext = extent_by_coord(&h->coord_after); - assert("vs-987", znode_is_loaded(coord_after.node)); - assert("vs-988", !memcmp(ext, &orig_ext, sizeof (*ext))); + assert("vs-987", znode_is_loaded(node)); + assert("vs-988", !memcmp(ext, &h->orig_ext, sizeof(*ext))); - memcpy(ext, replace, sizeof(*ext)); - znode_make_dirty(coord_after.node); + /* overwrite extent unit */ + memcpy(ext, &h->overwrite, sizeof(reiser4_extent)); + znode_make_dirty(node); - if (coord_after.node != orig_znode) - zrelse(coord_after.node); + if (node != orig_znode) + zrelse(node); if (return_inserted_position == 0) { - /* return un_extent and lh set to the same */ - assert("vs-1662", WITH_DATA(coord_after.node, !memcmp(replace, extent_by_coord(&coord_after), sizeof(reiser4_extent)))); - - *un_extent = coord_after; - done_lh(lh); - copy_lh(lh, &lh_after); + /* coord and lh are to be set to overwritten + extent */ + assert("vs-1662", + WITH_DATA(node, !memcmp(&h->overwrite, + extent_by_coord( + &h->coord_after), + sizeof(reiser4_extent)))); + + *h->coord = h->coord_after; + done_lh(h->lh); + copy_lh(h->lh, &h->lh_after); } else { - /* return un_extent and lh set to first of inserted units */ - assert("vs-1663", WITH_DATA(un_extent->node, !memcmp(exts_to_add->data, extent_by_coord(un_extent), sizeof(reiser4_extent)))); - assert("vs-1664", lh->node == un_extent->node); + /* h->coord and h->lh are to be set to first of + inserted units */ + assert("vs-1663", + WITH_DATA(h->coord->node, + !memcmp(&h->new_extents[0], + extent_by_coord(h->coord), + sizeof(reiser4_extent)))); + assert("vs-1664", h->lh->node == h->coord->node); } } } - tap_done(&watch); + tap_done(&h->watch); return result; } -reiser4_internal lock_handle * -znode_lh(znode *node) +lock_handle *znode_lh(znode *node) { assert("vs-1371", znode_is_write_locked(node)); assert("vs-1372", znode_is_wlocked_once(node)); - return owners_list_front(&node->lock.owners); + return list_entry(node->lock.owners.next, lock_handle, owners_link); } - /* - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - scroll-step: 1 - End: -*/ + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 79 + * scroll-step: 1 + * End: + */ diff -puN fs/reiser4/plugin/item/extent_file_ops.c~reiser4-big-update fs/reiser4/plugin/item/extent_file_ops.c --- devel/fs/reiser4/plugin/item/extent_file_ops.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/extent_file_ops.c 2005-09-15 19:51:08.000000000 -0700 @@ -3,35 +3,38 @@ #include "item.h" #include "../../inode.h" #include "../../page_cache.h" -#include "../../flush.h" /* just for jnode_tostring */ +#include "../../flush.h" /* just for jnode_tostring */ #include "../object.h" #include #include -static inline reiser4_extent * -ext_by_offset(const znode *node, int offset) +static inline reiser4_extent *ext_by_offset(const znode * node, int offset) { reiser4_extent *ext; - ext = (reiser4_extent *)(zdata(node) + offset); + ext = (reiser4_extent *) (zdata(node) + offset); return ext; } -static inline reiser4_extent * -ext_by_ext_coord(const uf_coord_t *uf_coord) +static inline reiser4_extent *ext_by_ext_coord(const uf_coord_t * uf_coord) { reiser4_extent *ext; - ext = ext_by_offset(uf_coord->coord.node, uf_coord->extension.extent.ext_offset); - assert("vs-1650", extent_get_start(ext) == extent_get_start(&uf_coord->extension.extent.extent)); - assert("vs-1651", extent_get_width(ext) == extent_get_width(&uf_coord->extension.extent.extent)); + ext = + ext_by_offset(uf_coord->coord.node, + uf_coord->extension.extent.ext_offset); + assert("vs-1650", + extent_get_start(ext) == + extent_get_start(&uf_coord->extension.extent.extent)); + assert("vs-1651", + extent_get_width(ext) == + extent_get_width(&uf_coord->extension.extent.extent)); return ext; } #if REISER4_DEBUG -static int -coord_extension_is_ok(const uf_coord_t *uf_coord) +static int coord_extension_is_ok(const uf_coord_t * uf_coord) { const coord_t *coord; const extent_coord_extension_t *ext_coord; @@ -44,19 +47,23 @@ coord_extension_is_ok(const uf_coord_t * return WITH_DATA(coord->node, (uf_coord->valid == 1 && coord_is_iplug_set(coord) && item_is_extent(coord) && - ext_coord->nr_units == nr_units_extent(coord) && - ext == extent_by_coord(coord) && - ext_coord->width == extent_get_width(ext) && - coord->unit_pos < ext_coord->nr_units && - ext_coord->pos_in_unit < ext_coord->width && - extent_get_start(ext) == extent_get_start(&ext_coord->extent) && - extent_get_width(ext) == extent_get_width(&ext_coord->extent))); + ext_coord->nr_units == + nr_units_extent(coord) + && ext == extent_by_coord(coord) + && ext_coord->width == + extent_get_width(ext) + && coord->unit_pos < ext_coord->nr_units + && ext_coord->pos_in_unit < + ext_coord->width + && extent_get_start(ext) == + extent_get_start(&ext_coord->extent) + && extent_get_width(ext) == + extent_get_width(&ext_coord->extent))); } /* return 1 if offset @off is inside of extent unit pointed to by @coord. Set pos_in_unit inside of unit correspondingly */ -static int -offset_is_in_unit(const coord_t *coord, loff_t off) +static int offset_is_in_unit(const coord_t * coord, loff_t off) { reiser4_key unit_key; __u64 unit_off; @@ -74,7 +81,7 @@ offset_is_in_unit(const coord_t *coord, } static int -coord_matches_key_extent(const coord_t *coord, const reiser4_key *key) +coord_matches_key_extent(const coord_t * coord, const reiser4_key * key) { reiser4_key item_key; @@ -86,14 +93,15 @@ coord_matches_key_extent(const coord_t * } static int -coord_extension_is_ok2(const uf_coord_t *uf_coord, const reiser4_key *key) +coord_extension_is_ok2(const uf_coord_t * uf_coord, const reiser4_key * key) { reiser4_key coord_key; unit_key_by_coord(&uf_coord->coord, &coord_key); set_key_offset(&coord_key, get_key_offset(&coord_key) + - (uf_coord->extension.extent.pos_in_unit << PAGE_CACHE_SHIFT)); + (uf_coord->extension.extent. + pos_in_unit << PAGE_CACHE_SHIFT)); return keyeq(key, &coord_key); } @@ -105,7 +113,8 @@ coord_extension_is_ok2(const uf_coord_t node). Calculate size of hole to be inserted. If that hole is too big - only part of it is inserted */ static int -add_hole(coord_t *coord, lock_handle *lh, const reiser4_key *key /* key of position in a file for write */) +add_hole(coord_t * coord, lock_handle * lh, + const reiser4_key * key /* key of position in a file for write */ ) { int result; znode *loaded; @@ -114,7 +123,6 @@ add_hole(coord_t *coord, lock_handle *lh reiser4_item_data item; reiser4_key hole_key; - /*coord_clear_iplug(coord);*/ result = zload(coord->node); if (result) return result; @@ -137,7 +145,10 @@ add_hole(coord_t *coord, lock_handle *lh /* compose body of hole extent */ set_extent(&new_ext, HOLE_EXTENT_START, hole_width); - result = insert_extent_by_coord(coord, init_new_extent(&item, &new_ext, 1), &hole_key, lh); + result = + insert_extent_by_coord(coord, + init_new_extent(&item, &new_ext, 1), + &hole_key, lh); zrelse(loaded); return result; } @@ -174,27 +185,35 @@ add_hole(coord_t *coord, lock_handle *lh /* last extent of a file is hole extent. Widen that extent by @hole_width blocks. Note that we do not worry about overflowing - extent width is 64 bits */ - set_extent(ext, HOLE_EXTENT_START, extent_get_width(ext) + hole_width); + set_extent(ext, HOLE_EXTENT_START, + extent_get_width(ext) + hole_width); znode_make_dirty(coord->node); zrelse(loaded); return 0; } /* append item with hole extent unit */ - assert("vs-713", (state_of_extent(ext) == ALLOCATED_EXTENT || state_of_extent(ext) == UNALLOCATED_EXTENT)); + assert("vs-713", + (state_of_extent(ext) == ALLOCATED_EXTENT + || state_of_extent(ext) == UNALLOCATED_EXTENT)); /* compose body of hole extent */ set_extent(&new_ext, HOLE_EXTENT_START, hole_width); - result = insert_into_item(coord, lh, &hole_key, init_new_extent(&item, &new_ext, 1), 0 /*flags */ ); + result = + insert_into_item(coord, lh, &hole_key, + init_new_extent(&item, &new_ext, 1), + 0 /*flags */ ); zrelse(loaded); return result; } + /* insert extent item (containing one unallocated extent of width 1) to place set by @coord */ static int -insert_first_block(uf_coord_t *uf_coord, const reiser4_key *key, reiser4_block_nr *block) +insert_first_block(uf_coord_t * uf_coord, const reiser4_key * key, + reiser4_block_nr * block) { int result; reiser4_extent ext; @@ -207,7 +226,10 @@ insert_first_block(uf_coord_t *uf_coord, assert("vs-719", znode_get_level(uf_coord->coord.node) == LEAF_LEVEL); set_extent(&ext, UNALLOCATED_EXTENT_START, 1); - result = insert_extent_by_coord(&uf_coord->coord, init_new_extent(&unit, &ext, 1), key, uf_coord->lh); + result = + insert_extent_by_coord(&uf_coord->coord, + init_new_extent(&unit, &ext, 1), key, + uf_coord->lh); if (result) { /* FIXME-VITALY: this is grabbed at file_write time. */ /* grabbed2free ((__u64)1); */ @@ -221,10 +243,17 @@ insert_first_block(uf_coord_t *uf_coord, return 0; } +/** + * append_one_block - append one unallocated extent to th eend of file + * @uf_coord: + * @key: + * @block: + */ /* @coord is set to the end of extent item. Append it with pointer to one block - either by expanding last unallocated extent or by appending a new one of width 1 */ static int -append_one_block(uf_coord_t *uf_coord, reiser4_key *key, reiser4_block_nr *block) +append_one_block(uf_coord_t * uf_coord, reiser4_key * key, + reiser4_block_nr * block) { int result; reiser4_extent new_ext; @@ -241,27 +270,31 @@ append_one_block(uf_coord_t *uf_coord, r assert("vs-228", coord->unit_pos == coord_last_unit_pos(coord)); assert("vs-1311", coord->between == AFTER_UNIT); assert("vs-1302", ext_coord->pos_in_unit == ext_coord->width - 1); - assert("vs-883", - ( { - reiser4_key next; - keyeq(key, append_key_extent(coord, &next)); - })); + assert("vs-883", ( { + reiser4_key next; + keyeq(key, append_key_extent(coord, &next));})); switch (state_of_extent(ext)) { case UNALLOCATED_EXTENT: - set_extent(ext, UNALLOCATED_EXTENT_START, extent_get_width(ext) + 1); + set_extent(ext, UNALLOCATED_EXTENT_START, + extent_get_width(ext) + 1); znode_make_dirty(coord->node); /* update coord extension */ - ext_coord->width ++; - ON_DEBUG(extent_set_width(&uf_coord->extension.extent.extent, ext_coord->width)); + ext_coord->width++; + ON_DEBUG(extent_set_width + (&uf_coord->extension.extent.extent, + ext_coord->width)); break; case HOLE_EXTENT: case ALLOCATED_EXTENT: /* append one unallocated extent of width 1 */ set_extent(&new_ext, UNALLOCATED_EXTENT_START, 1); - result = insert_into_item(coord, uf_coord->lh, key, init_new_extent(&unit, &new_ext, 1), 0 /* flags */ ); + result = + insert_into_item(coord, uf_coord->lh, key, + init_new_extent(&unit, &new_ext, 1), + 0 /* flags */ ); /* FIXME: for now */ uf_coord->valid = 0; if (result) @@ -275,27 +308,30 @@ append_one_block(uf_coord_t *uf_coord, r return 0; } -/* @coord is set to hole unit inside of extent item, replace hole unit with an - unit for unallocated extent of the width 1, and perhaps a hole unit before - the unallocated unit and perhaps a hole unit after the unallocated unit. */ -static int -plug_hole(uf_coord_t *uf_coord, reiser4_key *key) +/** + * plug_hole - replace hole extent with unallocated and holes + * @h: structure containing coordinate, lock handle, key, etc + * + * Creates an unallocated extent of width 1 within a hole. In worst case two + * additional extents can be created. + */ +static int plug_hole(struct make_extent_handle *h) { - reiser4_extent *ext, new_exts[2], /* extents which will be added after original - * hole one */ - replace; /* extent original hole extent will be replaced - * with */ + struct replace_handle *rh; + reiser4_extent *ext; reiser4_block_nr width, pos_in_unit; - reiser4_item_data item; - int count; coord_t *coord; extent_coord_extension_t *ext_coord; - reiser4_key tmp_key; int return_inserted_position; - coord = &uf_coord->coord; - ext_coord = &uf_coord->extension.extent; - ext = ext_by_ext_coord(uf_coord); + rh = &h->u.replace; + rh->coord = coord_by_uf_coord(h->uf_coord); + rh->lh = h->uf_coord->lh; + rh->flags = 0; + + coord = coord_by_uf_coord(h->uf_coord); + ext_coord = ext_coord_by_uf_coord(h->uf_coord); + ext = ext_by_ext_coord(h->uf_coord); width = ext_coord->width; pos_in_unit = ext_coord->pos_in_unit; @@ -311,115 +347,121 @@ plug_hole(uf_coord_t *uf_coord, reiser4_ if (coord->unit_pos) { /* there is an extent to the left */ if (state_of_extent(ext - 1) == UNALLOCATED_EXTENT) { - /* unit to the left is an unallocated extent. Increase its width and decrease width of - * hole */ - extent_set_width(ext - 1, extent_get_width(ext - 1) + 1); + /* unit to the left is an unallocated + extent. Increase its width and decrease + width of hole */ + extent_set_width(ext - 1, + extent_get_width(ext - 1) + 1); extent_set_width(ext, width - 1); znode_make_dirty(coord->node); /* update coord extension */ - coord->unit_pos --; + coord->unit_pos--; ext_coord->width = extent_get_width(ext - 1); ext_coord->pos_in_unit = ext_coord->width - 1; ext_coord->ext_offset -= sizeof(reiser4_extent); - ON_DEBUG(ext_coord->extent = *extent_by_coord(coord)); + ON_DEBUG(ext_coord->extent = + *extent_by_coord(coord)); return 0; } } /* extent for replace */ - set_extent(&replace, UNALLOCATED_EXTENT_START, 1); + set_extent(&rh->overwrite, UNALLOCATED_EXTENT_START, 1); /* extent to be inserted */ - set_extent(&new_exts[0], HOLE_EXTENT_START, width - 1); + set_extent(&rh->new_extents[0], HOLE_EXTENT_START, width - 1); + rh->nr_new_extents = 1; - /* have replace_extent to return with @coord and @uf_coord->lh set to unit which was replaced */ + /* have replace_extent to return with @coord and @uf_coord->lh + set to unit which was replaced */ return_inserted_position = 0; - count = 1; } else if (pos_in_unit == width - 1) { /* we deal with last element of extent */ if (coord->unit_pos < nr_units_extent(coord) - 1) { /* there is an extent unit to the right */ if (state_of_extent(ext + 1) == UNALLOCATED_EXTENT) { - /* unit to the right is an unallocated extent. Increase its width and decrease width of - * hole */ - extent_set_width(ext + 1, extent_get_width(ext + 1) + 1); + /* unit to the right is an unallocated + extent. Increase its width and decrease + width of hole */ + extent_set_width(ext + 1, + extent_get_width(ext + 1) + 1); extent_set_width(ext, width - 1); znode_make_dirty(coord->node); /* update coord extension */ - coord->unit_pos ++; + coord->unit_pos++; ext_coord->width = extent_get_width(ext + 1); ext_coord->pos_in_unit = 0; ext_coord->ext_offset += sizeof(reiser4_extent); - ON_DEBUG(ext_coord->extent = *extent_by_coord(coord)); + ON_DEBUG(ext_coord->extent = + *extent_by_coord(coord)); return 0; } } /* extent for replace */ - set_extent(&replace, HOLE_EXTENT_START, width - 1); + set_extent(&rh->overwrite, HOLE_EXTENT_START, width - 1); /* extent to be inserted */ - set_extent(&new_exts[0], UNALLOCATED_EXTENT_START, 1); + set_extent(&rh->new_extents[0], UNALLOCATED_EXTENT_START, 1); + rh->nr_new_extents = 1; - /* have replace_extent to return with @coord and @uf_coord->lh set to unit which was inserted */ + /* have replace_extent to return with @coord and @uf_coord->lh + set to unit which was inserted */ return_inserted_position = 1; - count = 1; } else { /* extent for replace */ - set_extent(&replace, HOLE_EXTENT_START, pos_in_unit); + set_extent(&rh->overwrite, HOLE_EXTENT_START, pos_in_unit); /* extents to be inserted */ - set_extent(&new_exts[0], UNALLOCATED_EXTENT_START, 1); - set_extent(&new_exts[1], HOLE_EXTENT_START, width - pos_in_unit - 1); + set_extent(&rh->new_extents[0], UNALLOCATED_EXTENT_START, 1); + set_extent(&rh->new_extents[1], HOLE_EXTENT_START, + width - pos_in_unit - 1); + rh->nr_new_extents = 2; - /* have replace_extent to return with @coord and @uf_coord->lh set to first of units which were - inserted */ + /* have replace_extent to return with @coord and @uf_coord->lh + set to first of units which were inserted */ return_inserted_position = 1; - count = 2; } - - /* insert_into_item will insert new units after the one @coord is set - to. So, update key correspondingly */ - unit_key_by_coord(coord, &tmp_key); - set_key_offset(&tmp_key, (get_key_offset(&tmp_key) + extent_get_width(&replace) * current_blocksize)); - - uf_coord->valid = 0; - return replace_extent(coord, uf_coord->lh, &tmp_key, init_new_extent(&item, new_exts, count), &replace, 0 /* flags */, return_inserted_position); -} - -/* make unallocated node pointer in the position @uf_coord is set to */ + unit_key_by_coord(coord, &rh->paste_key); + set_key_offset(&rh->paste_key, get_key_offset(&rh->paste_key) + + extent_get_width(&rh->overwrite) * current_blocksize); + + h->uf_coord->valid = 0; + return replace_extent(rh, return_inserted_position); +} + +/** + * overwrite_one_block - + * @h: + * + * make unallocated node pointer in the position @uf_coord is set to + */ static int -overwrite_one_block(uf_coord_t *uf_coord, reiser4_key *key, reiser4_block_nr *block, int *created, - struct inode *inode) +overwrite_one_block(struct make_extent_handle *h) { int result; extent_coord_extension_t *ext_coord; reiser4_extent *ext; - oid_t oid; - pgoff_t index; - - oid = get_key_objectid(key); - index = get_key_offset(key) >> current_blocksize_bits; - assert("vs-1312", uf_coord->coord.between == AT_UNIT); + assert("vs-1312", h->uf_coord->coord.between == AT_UNIT); result = 0; - *created = 0; - ext_coord = &uf_coord->extension.extent; - ext = ext_by_ext_coord(uf_coord); + h->created = 0; + ext_coord = ext_coord_by_uf_coord(h->uf_coord); + ext = ext_by_ext_coord(h->uf_coord); switch (state_of_extent(ext)) { case ALLOCATED_EXTENT: - *block = extent_get_start(ext) + ext_coord->pos_in_unit; + h->blocknr = extent_get_start(ext) + ext_coord->pos_in_unit; break; case HOLE_EXTENT: - if (inode != NULL && DQUOT_ALLOC_BLOCK(inode, 1)) + if (h->inode != NULL && DQUOT_ALLOC_BLOCK_NODIRTY(h->inode, 1)) return RETERR(-EDQUOT); - result = plug_hole(uf_coord, key); + result = plug_hole(h); if (!result) { - *block = fake_blocknr_unformatted(); - *created = 1; + h->blocknr = fake_blocknr_unformatted(); + h->created = 1; } else { - if (inode != NULL) - DQUOT_FREE_BLOCK(inode, 1); + if (h->inode != NULL) + DQUOT_FREE_BLOCK_NODIRTY(h->inode, 1); } break; @@ -437,10 +479,11 @@ overwrite_one_block(uf_coord_t *uf_coord #if REISER4_DEBUG -/* after make extent uf_coord's lock handle must be set to node containing unit which was inserted/found */ +/* after make extent uf_coord's lock handle must be set to node containing unit + * which was inserted/found */ static void -check_make_extent_result(int result, write_mode_t mode, const reiser4_key *key, - const lock_handle *lh, reiser4_block_nr block) +check_make_extent_result(int result, write_mode_t mode, const reiser4_key * key, + const lock_handle * lh, reiser4_block_nr block) { coord_t coord; @@ -456,72 +499,79 @@ check_make_extent_result(int result, wri assert("vs-1656", coord_is_existing_unit(&coord)); if (blocknr_is_fake(&block)) { - assert("vs-1657", state_of_extent(extent_by_coord(&coord)) == UNALLOCATED_EXTENT); + assert("vs-1657", + state_of_extent(extent_by_coord(&coord)) == + UNALLOCATED_EXTENT); } else if (block == 0) { assert("vs-1660", mode == OVERWRITE_ITEM); - assert("vs-1657", state_of_extent(extent_by_coord(&coord)) == UNALLOCATED_EXTENT); + assert("vs-1657", + state_of_extent(extent_by_coord(&coord)) == + UNALLOCATED_EXTENT); } else { reiser4_key tmp; reiser4_block_nr pos_in_unit; - assert("vs-1658", state_of_extent(extent_by_coord(&coord)) == ALLOCATED_EXTENT); + assert("vs-1658", + state_of_extent(extent_by_coord(&coord)) == + ALLOCATED_EXTENT); unit_key_by_coord(&coord, &tmp); - pos_in_unit = (get_key_offset(key) - get_key_offset(&tmp)) >> current_blocksize_bits; - assert("vs-1659", block == extent_get_start(extent_by_coord(&coord)) + pos_in_unit); + pos_in_unit = + (get_key_offset(key) - + get_key_offset(&tmp)) >> current_blocksize_bits; + assert("vs-1659", + block == + extent_get_start(extent_by_coord(&coord)) + pos_in_unit); } zrelse(lh->node); } #endif -/* when @inode is not NULL, alloc quota before updating extent item */ +/** + * make_extent - make sure that non hole extent corresponding h->pkey exists + * @h: structure containing coordinate, lock handle, key, etc + * @mode: preliminary hint obtained via search + * + * when @inode is not NULL, alloc quota before updating extent item + */ static int -make_extent(reiser4_key *key, uf_coord_t *uf_coord, write_mode_t mode, - reiser4_block_nr *block, int *created, struct inode *inode) +make_extent(struct make_extent_handle *h, write_mode_t mode) { int result; - oid_t oid; - pgoff_t index; - - oid = get_key_objectid(key); - index = get_key_offset(key) >> current_blocksize_bits; - assert("vs-960", znode_is_write_locked(uf_coord->coord.node)); - assert("vs-1334", znode_is_loaded(uf_coord->coord.node)); + assert("vs-960", znode_is_write_locked(h->uf_coord->coord.node)); + assert("vs-1334", znode_is_loaded(h->uf_coord->coord.node)); - *block = 0; + h->blocknr = 0; switch (mode) { case FIRST_ITEM: /* new block will be inserted into file. Check quota */ - if (inode != NULL && DQUOT_ALLOC_BLOCK(inode, 1)) + if (h->inode != NULL && DQUOT_ALLOC_BLOCK_NODIRTY(h->inode, 1)) return RETERR(-EDQUOT); /* create first item of the file */ - result = insert_first_block(uf_coord, key, block); - if (result && inode != NULL) - DQUOT_FREE_BLOCK(inode, 1); - *created = 1; + result = insert_first_block(h->uf_coord, h->u.replace.pkey, &h->blocknr); + if (result && h->inode != NULL) + DQUOT_FREE_BLOCK_NODIRTY(h->inode, 1); + h->created = 1; break; case APPEND_ITEM: /* new block will be inserted into file. Check quota */ - if (inode != NULL && DQUOT_ALLOC_BLOCK(inode, 1)) + if (h->inode != NULL && DQUOT_ALLOC_BLOCK_NODIRTY(h->inode, 1)) return RETERR(-EDQUOT); - /* FIXME: item plugin should be initialized - item_plugin_by_coord(&uf_coord->base_coord);*/ - assert("vs-1316", coord_extension_is_ok(uf_coord)); - result = append_one_block(uf_coord, key, block); - if (result && inode != NULL) - DQUOT_FREE_BLOCK(inode, 1); - *created = 1; + /* append one block to the file */ + assert("vs-1316", coord_extension_is_ok(h->uf_coord)); + result = append_one_block(h->uf_coord, h->u.replace.pkey, &h->blocknr); + if (result && h->inode != NULL) + DQUOT_FREE_BLOCK_NODIRTY(h->inode, 1); + h->created = 1; break; case OVERWRITE_ITEM: - /* FIXME: item plugin should be initialized - item_plugin_by_coord(&uf_coord->base_coord);*/ - assert("vs-1316", coord_extension_is_ok(uf_coord)); - result = overwrite_one_block(uf_coord, key, block, created, inode); + assert("vs-1316", coord_extension_is_ok(h->uf_coord)); + result = overwrite_one_block(h); break; default: @@ -530,34 +580,37 @@ make_extent(reiser4_key *key, uf_coord_t break; } - ON_DEBUG(check_make_extent_result(result, mode, key, uf_coord->lh, *block)); + ON_DEBUG(check_make_extent_result + (result, mode, h->u.replace.pkey, h->uf_coord->lh, h->blocknr)); return result; } /* estimate and reserve space which may be required for writing one page of file */ static int -reserve_extent_write_iteration(struct inode *inode, reiser4_tree *tree) +reserve_extent_write_iteration(struct inode *inode, reiser4_tree * tree) { int result; grab_space_enable(); /* one unformatted node and one insertion into tree and one stat data update may be involved */ - result = reiser4_grab_space(1 + /* Hans removed reservation for balancing here. */ + result = reiser4_grab_space(1 + /* Hans removed reservation for balancing here. */ /* if extent items will be ever used by plugins other than unix file plugin - estimate update should instead be taken by inode_file_plugin(inode)->estimate.update(inode) - */ + */ estimate_update_common(inode), - 0/* flags */); + 0 /* flags */ ); return result; } static void -write_move_coord(coord_t *coord, uf_coord_t *uf_coord, write_mode_t mode, int full_page) +write_move_coord(coord_t * coord, uf_coord_t * uf_coord, write_mode_t mode, + int full_page) { extent_coord_extension_t *ext_coord; - assert("vs-1339", ergo(mode == OVERWRITE_ITEM, coord->between == AT_UNIT)); + assert("vs-1339", + ergo(mode == OVERWRITE_ITEM, coord->between == AT_UNIT)); assert("vs-1341", ergo(mode == FIRST_ITEM, uf_coord->valid == 0)); if (uf_coord->valid == 0) @@ -568,10 +621,13 @@ write_move_coord(coord_t *coord, uf_coor if (mode == APPEND_ITEM) { assert("vs-1340", coord->between == AFTER_UNIT); assert("vs-1342", coord->unit_pos == ext_coord->nr_units - 1); - assert("vs-1343", ext_coord->pos_in_unit == ext_coord->width - 2); - assert("vs-1344", state_of_extent(ext_by_ext_coord(uf_coord)) == UNALLOCATED_EXTENT); + assert("vs-1343", + ext_coord->pos_in_unit == ext_coord->width - 2); + assert("vs-1344", + state_of_extent(ext_by_ext_coord(uf_coord)) == + UNALLOCATED_EXTENT); ON_DEBUG(ext_coord->extent = *ext_by_ext_coord(uf_coord)); - ext_coord->pos_in_unit ++; + ext_coord->pos_in_unit++; if (!full_page) coord->between = AT_UNIT; return; @@ -588,18 +644,24 @@ write_move_coord(coord_t *coord, uf_coor uf_coord->valid = 0; } else { /* move to the next unit */ - coord->unit_pos ++; + coord->unit_pos++; ext_coord->ext_offset += sizeof(reiser4_extent); - ON_DEBUG(ext_coord->extent = *ext_by_offset(coord->node, ext_coord->ext_offset)); - ext_coord->width = extent_get_width(ext_by_offset(coord->node, ext_coord->ext_offset)); + ON_DEBUG(ext_coord->extent = + *ext_by_offset(coord->node, + ext_coord->ext_offset)); + ext_coord->width = + extent_get_width(ext_by_offset + (coord->node, + ext_coord->ext_offset)); ext_coord->pos_in_unit = 0; } } else - ext_coord->pos_in_unit ++; + ext_coord->pos_in_unit++; } static int -write_is_partial(struct inode *inode, loff_t file_off, unsigned page_off, unsigned count) +write_is_partial(struct inode *inode, loff_t file_off, unsigned page_off, + unsigned count) { if (count == inode->i_sb->s_blocksize) return 0; @@ -609,8 +671,7 @@ write_is_partial(struct inode *inode, lo } /* this initialize content of page not covered by write */ -static void -zero_around(struct page *page, int from, int count) +static void zero_around(struct page *page, int from, int count) { char *data; @@ -621,7 +682,8 @@ zero_around(struct page *page, int from, kunmap_atomic(data, KM_USER0); } -static void assign_jnode_blocknr(jnode *j, reiser4_block_nr blocknr, int created) +static void assign_jnode_blocknr(jnode * j, reiser4_block_nr blocknr, + int created) { assert("vs-1737", !JF_ISSET(j, JNODE_EFLUSH)); if (created) { @@ -630,20 +692,20 @@ static void assign_jnode_blocknr(jnode * JF_SET(j, JNODE_CREATED); /* new block is added to file. Update inode->i_blocks and inode->i_bytes. FIXME: inode_set/get/add/sub_bytes is used to be called by quota macros */ - /*inode_add_bytes(inode, PAGE_CACHE_SIZE);*/ + /*inode_add_bytes(inode, PAGE_CACHE_SIZE); */ } if (*jnode_get_block(j) == 0) { jnode_set_block(j, &blocknr); } else { assert("vs-1508", !blocknr_is_fake(&blocknr)); - assert("vs-1507", ergo(blocknr, *jnode_get_block(j) == blocknr)); + assert("vs-1507", + ergo(blocknr, *jnode_get_block(j) == blocknr)); } } static int -extent_balance_dirty_pages(struct inode *inode, const flow_t *f, - hint_t *hint) +extent_balance_dirty_pages(struct inode *inode, const flow_t * f, hint_t * hint) { int result; int excl; @@ -653,7 +715,7 @@ extent_balance_dirty_pages(struct inode set_hint(hint, &f->key, ZNODE_WRITE_LOCK); else unset_hint(hint); - longterm_unlock_znode(hint->ext_coord.lh); + /* &hint->lh is done-ed */ /* file was appended, update its size */ if (get_key_offset(&f->key) > inode->i_size) { @@ -673,9 +735,14 @@ extent_balance_dirty_pages(struct inode if (!reiser4_is_set(inode->i_sb, REISER4_ATOMIC_WRITE)) { uf_info = unix_file_inode_data(inode); excl = unix_file_inode_data(inode)->exclusive_use; - if (excl) + if (excl) { + /* we are about to drop exclusive access. Set file + container to UF_CONTAINER_EXTENTS if file is not + under tail conversion */ + if (!inode_get_flag(inode, REISER4_PART_CONV)) + uf_info->container = UF_CONTAINER_EXTENTS; drop_exclusive_access(uf_info); - else + } else drop_nonexclusive_access(uf_info); reiser4_throttle_write(inode); if (excl) @@ -686,11 +753,18 @@ extent_balance_dirty_pages(struct inode return 0; } -/* write flow's data into file by pages */ -static int -extent_write_flow(struct inode *inode, flow_t *flow, hint_t *hint, - int grabbed, /* 0 if space for operation is not reserved yet, 1 - otherwise */ - write_mode_t mode) +/** + * extent_write_flow - core of extent item's write + * @inode: + * @flow: + * @hint: + * @grabbed: if it is 1 - space for operation is reserved already + * @mode: + * + * Write flow's data into file by pages. + */ +static int extent_write_flow(struct inode *inode, flow_t * flow, hint_t * hint, + int grabbed, write_mode_t mode) { int result; loff_t file_off; @@ -698,23 +772,16 @@ extent_write_flow(struct inode *inode, f unsigned long page_off, count; struct page *page; jnode *j; - uf_coord_t *uf_coord; coord_t *coord; oid_t oid; reiser4_tree *tree; - reiser4_key page_key; - reiser4_block_nr blocknr; - int created; + struct make_extent_handle *h; assert("nikita-3139", !inode_get_flag(inode, REISER4_NO_SD)); assert("vs-885", current_blocksize == PAGE_CACHE_SIZE); assert("vs-700", flow->user == 1); assert("vs-1352", flow->length > 0); - tree = tree_by_inode(inode); - oid = get_inode_oid(inode); - uf_coord = &hint->ext_coord; - coord = &uf_coord->coord; /* position in a file to start write from */ file_off = get_key_offset(&flow->key); @@ -723,9 +790,20 @@ extent_write_flow(struct inode *inode, f /* offset within the page */ page_off = (unsigned long)(file_off & (PAGE_CACHE_SIZE - 1)); + h = kmalloc(sizeof(*h), GFP_KERNEL); + if (h == NULL) + return RETERR(-ENOMEM); + h->uf_coord = &hint->ext_coord; + h->inode = inode; + h->u.replace.pkey = &h->u.replace.key; + /* key of first byte of page */ - page_key = flow->key; - set_key_offset(&page_key, (loff_t)page_nr << PAGE_CACHE_SHIFT); + h->u.replace.key = flow->key; + set_key_offset(h->u.replace.pkey, file_off & ~((loff_t)(PAGE_CACHE_SIZE - 1))); + + tree = tree_by_inode(inode); + oid = get_inode_oid(inode); + coord = coord_by_uf_coord(h->uf_coord); do { if (!grabbed) { result = reserve_extent_write_iteration(inode, tree); @@ -737,7 +815,7 @@ extent_write_flow(struct inode *inode, f if (count > flow->length) count = flow->length; - result = make_extent(&page_key, uf_coord, mode, &blocknr, &created, inode/* check quota */); + result = make_extent(h, mode); if (result) goto exit1; @@ -768,8 +846,10 @@ extent_write_flow(struct inode *inode, f block (in which case created == 0). In either case we have to read this page if it is being overwritten partially */ - if (write_is_partial(inode, file_off, page_off, count) && - (created == 0 || JF_ISSET(j, JNODE_EFLUSH))) { + if (write_is_partial + (inode, file_off, page_off, count) + && (h->created == 0 + || JF_ISSET(j, JNODE_EFLUSH))) { if (!JF_ISSET(j, JNODE_EFLUSH)) { /* eflush bit can be neither set nor cleared by other @@ -777,11 +857,13 @@ extent_write_flow(struct inode *inode, f attached to jnode is locked */ LOCK_JNODE(j); - assign_jnode_blocknr(j, blocknr, created); + assign_jnode_blocknr(j, h->blocknr, + h->created); blocknr_set = 1; UNLOCK_JNODE(j); } - result = page_io(page, j, READ, GFP_KERNEL); + result = + page_io(page, j, READ, GFP_KERNEL); if (result) goto exit3; @@ -796,7 +878,8 @@ extent_write_flow(struct inode *inode, f LOCK_JNODE(j); eflush_del(j, 1); if (blocknr_set == 0) - assign_jnode_blocknr(j, blocknr, created); + assign_jnode_blocknr(j, h->blocknr, + h->created); UNLOCK_JNODE(j); } else { /* new page added to the file. No need to carry @@ -808,21 +891,27 @@ extent_write_flow(struct inode *inode, f /* assign blocknr to jnode if it is not assigned yet */ LOCK_JNODE(j); - assign_jnode_blocknr(j, blocknr, created); + assign_jnode_blocknr(j, h->blocknr, h->created); UNLOCK_JNODE(j); } } else { LOCK_JNODE(j); eflush_del(j, 1); - assign_jnode_blocknr(j, blocknr, created); + assign_jnode_blocknr(j, h->blocknr, h->created); UNLOCK_JNODE(j); } - assert("vs-1503", UNDER_SPIN(jnode, j, (!JF_ISSET(j, JNODE_EFLUSH) && jnode_page(j) == page))); + assert("vs-1503", + UNDER_SPIN(jnode, j, + (!JF_ISSET(j, JNODE_EFLUSH) + && jnode_page(j) == page))); assert("nikita-3033", schedulable()); /* copy user data into page */ - result = __copy_from_user((char *)kmap(page) + page_off, flow->data, count); + result = + __copy_from_user((char *)kmap(page) + page_off, + (const char __user *)flow->data, + count); kunmap(page); if (unlikely(result)) { /* FIXME: write(fd, 0, 10); to empty file will write no @@ -842,20 +931,22 @@ extent_write_flow(struct inode *inode, f jnode_mark_dirty gets moved to dirty list. So, it would be more optimal to put jnode directly to dirty list */ LOCK_JNODE(j); - result = try_capture(j, ZNODE_WRITE_LOCK, 0, 1/* can_coc */); + result = try_capture(j, ZNODE_WRITE_LOCK, 0, 1 /* can_coc */ ); if (result) { UNLOCK_JNODE(j); page_cache_release(page); goto exit2; } jnode_make_dirty_locked(j); + JF_CLR(j, JNODE_KEEPME); UNLOCK_JNODE(j); page_cache_release(page); jput(j); move_flow_forward(flow, count); - write_move_coord(coord, uf_coord, mode, page_off + count == PAGE_CACHE_SIZE); + write_move_coord(coord, h->uf_coord, mode, + page_off + count == PAGE_CACHE_SIZE); /* set seal, drop long term lock, throttle the writer */ result = extent_balance_dirty_pages(inode, flow, hint); @@ -865,51 +956,55 @@ extent_write_flow(struct inode *inode, f break; page_off = 0; - page_nr ++; + page_nr++; file_off += count; - set_key_offset(&page_key, (loff_t)page_nr << PAGE_CACHE_SHIFT); + set_key_offset(h->u.replace.pkey, (loff_t) page_nr << PAGE_CACHE_SHIFT); - if (flow->length && uf_coord->valid == 1) { + if (flow->length && h->uf_coord->valid == 1) { /* loop continues - try to obtain lock validating a - seal set in extent_balance_dirty_pages*/ - result = hint_validate(hint, &flow->key, 0/* do not check key */, ZNODE_WRITE_LOCK); + seal set in extent_balance_dirty_pages */ + result = + hint_validate(hint, &flow->key, + 0 /* do not check key */ , + ZNODE_WRITE_LOCK); if (result == 0) continue; } break; /* handling various error code pathes */ - exit3: + exit3: unlock_page(page); page_cache_release(page); - exit2: - if (created) + exit2: + if (h->created) inode_sub_bytes(inode, PAGE_CACHE_SIZE); jput(j); - exit1: + exit1: if (!grabbed) all_grabbed2free(); - exit0: + exit0: unset_hint(hint); - longterm_unlock_znode(hint->ext_coord.lh); break; } while (1); + kfree(h); + if (result && result != -E_REPEAT) assert("vs-18", !hint_is_set(hint)); else assert("vs-19", ergo(hint_is_set(hint), - coords_equal(&hint->ext_coord.coord, &hint->seal.coord1) && - keyeq(&flow->key, &hint->seal.key))); + coords_equal(&hint->ext_coord.coord, + &hint->seal.coord1) + && keyeq(&flow->key, &hint->seal.key))); assert("vs-20", lock_stack_isclean(get_current_lock_stack())); return result; } /* estimate and reserve space which may be required for appending file with hole stored in extent */ -static int -extent_hole_reserve(reiser4_tree *tree) +static int extent_hole_reserve(reiser4_tree * tree) { /* adding hole may require adding a hole unit into extent item and stat data update */ grab_space_enable(); @@ -917,7 +1012,8 @@ extent_hole_reserve(reiser4_tree *tree) } static int -extent_write_hole(struct inode *inode, flow_t *flow, hint_t *hint, int grabbed) +extent_write_hole(struct inode *inode, flow_t * flow, hint_t * hint, + int grabbed) { int result; loff_t new_size; @@ -958,14 +1054,12 @@ extent_write_hole(struct inode *inode, f 1. real write - to write data from flow to a file (@flow->data != 0) 2. expanding truncate (@f->data == 0) */ -reiser4_internal int -write_extent(struct inode *inode, flow_t *flow, hint_t *hint, - int grabbed, /* extent's write may be called from plain unix file write and from tail conversion. In first - case (grabbed == 0) space is not reserved forehand, so, it must be done here. When it is - being called from tail conversion - space is reserved already for whole operation which may - involve several calls to item write. In this case space reservation will not be done - here */ - write_mode_t mode) +int write_extent(struct inode *inode, flow_t * flow, hint_t * hint, int grabbed, /* extent's write may be called from plain unix file write and from tail conversion. In first + case (grabbed == 0) space is not reserved forehand, so, it must be done here. When it is + being called from tail conversion - space is reserved already for whole operation which may + involve several calls to item write. In this case space reservation will not be done + here */ + write_mode_t mode) { if (flow->data) /* real write */ @@ -975,8 +1069,7 @@ write_extent(struct inode *inode, flow_t return extent_write_hole(inode, flow, hint, grabbed); } -static inline void -zero_page(struct page *page) +static inline void zero_page(struct page *page) { char *kaddr = kmap_atomic(page, KM_USER0); @@ -988,7 +1081,8 @@ zero_page(struct page *page) } static int -do_readpage_extent(reiser4_extent *ext, reiser4_block_nr pos, struct page *page) +do_readpage_extent(reiser4_extent * ext, reiser4_block_nr pos, + struct page *page) { jnode *j; struct address_space *mapping; @@ -1031,7 +1125,8 @@ do_readpage_extent(reiser4_extent *ext, blocknr = extent_get_start(ext) + pos; jnode_set_block(j, &blocknr); } else - assert("vs-1403", j->blocknr == extent_get_start(ext) + pos); + assert("vs-1403", + j->blocknr == extent_get_start(ext) + pos); break; case UNALLOCATED_EXTENT: @@ -1057,7 +1152,8 @@ do_readpage_extent(reiser4_extent *ext, } static int -move_coord_pages(coord_t *coord, extent_coord_extension_t *ext_coord, unsigned count) +move_coord_pages(coord_t * coord, extent_coord_extension_t * ext_coord, + unsigned count) { reiser4_extent *ext; @@ -1078,10 +1174,10 @@ move_coord_pages(coord_t *coord, extent_ /* shift to next unit */ count -= (ext_coord->width - ext_coord->pos_in_unit); - coord->unit_pos ++; + coord->unit_pos++; ext_coord->pos_in_unit = 0; ext_coord->ext_offset += sizeof(reiser4_extent); - ext ++; + ext++; ON_DEBUG(ext_coord->extent = *ext); ext_coord->width = extent_get_width(ext); } while (1); @@ -1089,8 +1185,7 @@ move_coord_pages(coord_t *coord, extent_ return 0; } -static int -readahead_readpage_extent(void *vp, struct page *page) +static int readahead_readpage_extent(void *vp, struct page *page) { int result; uf_coord_t *uf_coord; @@ -1109,26 +1204,30 @@ readahead_readpage_extent(void *vp, stru if (ext_coord->expected_page != page->index) { /* read_cache_pages skipped few pages. Try to adjust coord to page */ assert("vs-1269", page->index > ext_coord->expected_page); - if (move_coord_pages(coord, ext_coord, page->index - ext_coord->expected_page)) { + if (move_coord_pages + (coord, ext_coord, + page->index - ext_coord->expected_page)) { /* extent pointing to this page is not here */ unlock_page(page); return RETERR(-EINVAL); } assert("vs-1274", offset_is_in_unit(coord, - (loff_t)page->index << PAGE_CACHE_SHIFT)); + (loff_t) page-> + index << PAGE_CACHE_SHIFT)); ext_coord->expected_page = page->index; } assert("vs-1281", page->index == ext_coord->expected_page); - result = do_readpage_extent(ext_by_ext_coord(uf_coord), ext_coord->pos_in_unit, page); + result = + do_readpage_extent(ext_by_ext_coord(uf_coord), + ext_coord->pos_in_unit, page); if (!result) move_coord_pages(coord, ext_coord, 1); return result; } -static int -move_coord_forward(uf_coord_t *ext_coord) +static int move_coord_forward(uf_coord_t * ext_coord) { coord_t *coord; extent_coord_extension_t *extension; @@ -1136,7 +1235,7 @@ move_coord_forward(uf_coord_t *ext_coord assert("", coord_extension_is_ok(ext_coord)); extension = &ext_coord->extension.extent; - extension->pos_in_unit ++; + extension->pos_in_unit++; if (extension->pos_in_unit < extension->width) /* stay within the same extent unit */ return 0; @@ -1144,7 +1243,7 @@ move_coord_forward(uf_coord_t *ext_coord coord = &ext_coord->coord; /* try to move to the next extent unit */ - coord->unit_pos ++; + coord->unit_pos++; if (coord->unit_pos < extension->nr_units) { /* went to the next extent unit */ reiser4_extent *ext; @@ -1162,8 +1261,7 @@ move_coord_forward(uf_coord_t *ext_coord } /* this is called by read_cache_pages for each of readahead pages */ -static int -extent_readpage_filler(void *data, struct page *page) +static int extent_readpage_filler(void *data, struct page *page) { hint_t *hint; loff_t offset; @@ -1171,16 +1269,16 @@ extent_readpage_filler(void *data, struc uf_coord_t *ext_coord; int result; - offset = (loff_t)page->index << PAGE_CACHE_SHIFT; - key_by_inode_unix_file(page->mapping->host, offset, &key); + offset = (loff_t) page->index << PAGE_CACHE_SHIFT; + key_by_inode_and_offset_common(page->mapping->host, offset, &key); - hint = (hint_t *)data; + hint = (hint_t *) data; ext_coord = &hint->ext_coord; BUG_ON(PageUptodate(page)); unlock_page(page); - if (hint_validate(hint, &key, 1/* check key */, ZNODE_READ_LOCK) != 0) { + if (hint_validate(hint, &key, 1 /* check key */ , ZNODE_READ_LOCK) != 0) { result = coord_by_key(current_tree, &key, &ext_coord->coord, ext_coord->lh, ZNODE_READ_LOCK, FIND_EXACT, TWIG_LEVEL, @@ -1194,27 +1292,26 @@ extent_readpage_filler(void *data, struc if (zload(ext_coord->coord.node)) { unset_hint(hint); - done_lh(ext_coord->lh); return RETERR(-EIO); } if (!item_is_extent(&ext_coord->coord)) { /* tail conversion is running in parallel */ zrelse(ext_coord->coord.node); unset_hint(hint); - done_lh(ext_coord->lh); return RETERR(-EIO); } if (ext_coord->valid == 0) init_coord_extension_extent(ext_coord, offset); - assert("", (coord_extension_is_ok(ext_coord) && - coord_extension_is_ok2(ext_coord, &key))); + assert("vs-48", (coord_extension_is_ok(ext_coord) && + coord_extension_is_ok2(ext_coord, &key))); lock_page(page); if (!PageUptodate(page)) { result = do_readpage_extent(ext_by_ext_coord(ext_coord), - ext_coord->extension.extent.pos_in_unit, page); + ext_coord->extension.extent. + pos_in_unit, page); if (result) unlock_page(page); } else { @@ -1227,13 +1324,13 @@ extent_readpage_filler(void *data, struc } else unset_hint(hint); zrelse(ext_coord->coord.node); - done_lh(ext_coord->lh); return result; } /* this is called by reiser4_readpages */ static void -extent_readpages_hook(struct address_space *mapping, struct list_head *pages, void *data) +extent_readpages_hook(struct address_space *mapping, struct list_head *pages, + void *data) { /* FIXME: try whether having reiser4_read_cache_pages improves anything */ read_cache_pages(mapping, pages, extent_readpage_filler, data); @@ -1241,10 +1338,9 @@ extent_readpages_hook(struct address_spa static int call_page_cache_readahead(struct address_space *mapping, struct file *file, - hint_t *hint, + hint_t * hint, unsigned long page_nr, - unsigned long ra_pages, - struct file_ra_state *ra) + unsigned long ra_pages, struct file_ra_state *ra) { reiser4_file_fsdata *fsdata; int result; @@ -1260,10 +1356,8 @@ call_page_cache_readahead(struct address return result; } - /* this is called when readahead did not */ -static int -call_readpage(struct file *file, struct page *page) +static int call_readpage(struct file *file, struct page *page) { int result; @@ -1282,9 +1376,13 @@ call_readpage(struct file *file, struct return 0; } +static int filler(void *vp, struct page *page) +{ + return readpage_unix_file(vp, page); +} + /* Implements plugin->u.item.s.file.read operation for extent items. */ -reiser4_internal int -read_extent(struct file *file, flow_t *flow, hint_t *hint) +int read_extent(struct file *file, flow_t * flow, hint_t * hint) { int result; struct page *page; @@ -1304,6 +1402,7 @@ read_extent(struct file *file, flow_t *f uf_coord = &hint->ext_coord; assert("vs-1318", coord_extension_is_ok(uf_coord)); + assert("vs-33", uf_coord->lh == &hint->lh); coord = &uf_coord->coord; assert("vs-1119", znode_is_rlocked(coord->node)); @@ -1324,24 +1423,28 @@ read_extent(struct file *file, flow_t *f cur_page = (unsigned long)(file_off >> PAGE_CACHE_SHIFT); next_page = cur_page; /* number of pages flow spans over */ - nr_pages = ((file_off + flow->length + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) - cur_page; + nr_pages = + ((file_off + flow->length + PAGE_CACHE_SIZE - + 1) >> PAGE_CACHE_SHIFT) - cur_page; /* we start having twig node read locked. However, we do not want to keep that lock all the time readahead works. So, set a sel and release twig node. */ set_hint(hint, &flow->key, ZNODE_READ_LOCK); - longterm_unlock_znode(hint->ext_coord.lh); + /* &hint->lh is done-ed */ ra = file->f_ra; prev_page = ra.prev_page; do { if (next_page == cur_page) - next_page = call_page_cache_readahead(mapping, file, hint, cur_page, nr_pages, &ra); + next_page = + call_page_cache_readahead(mapping, file, hint, + cur_page, nr_pages, &ra); page = find_get_page(mapping, cur_page); if (unlikely(page == NULL)) { handle_ra_miss(mapping, &ra, cur_page); - page = read_cache_page(mapping, cur_page, readpage_unix_file, file); + page = read_cache_page(mapping, cur_page, filler, file); if (IS_ERR(page)) return PTR_ERR(page); lock_page(page); @@ -1349,7 +1452,8 @@ read_extent(struct file *file, flow_t *f unlock_page(page); page_detach_jnode(page, mapping, cur_page); page_cache_release(page); - warning("jmacd-97178", "extent_read: page is not up to date"); + warning("jmacd-97178", + "extent_read: page is not up to date"); return RETERR(-EIO); } unlock_page(page); @@ -1376,7 +1480,7 @@ read_extent(struct file *file, flow_t *f /* If users can be writing to this page using arbitrary virtual addresses, take care about potential aliasing before reading the page on the kernel side. - */ + */ if (mapping_writably_mapped(mapping)) flush_dcache_page(page); @@ -1387,7 +1491,10 @@ read_extent(struct file *file, flow_t *f count = flow->length; /* user area is already get_user_pages-ed in read_unix_file, which makes major page faults impossible */ - result = __copy_to_user(flow->data, (char *)kmap(page) + page_off, count); + result = + __copy_to_user((char __user *)flow->data, + (char *)kmap(page) + page_off, + count); kunmap(page); page_cache_release(page); @@ -1398,9 +1505,9 @@ read_extent(struct file *file, flow_t *f move_flow_forward(flow, count); page_off = 0; - cur_page ++; + cur_page++; count = PAGE_CACHE_SIZE; - nr_pages --; + nr_pages--; } while (flow->length); file->f_ra = ra; @@ -1410,8 +1517,9 @@ read_extent(struct file *file, flow_t *f /* plugin->u.item.s.file.readpages */ -reiser4_internal void -readpages_extent(void *vp, struct address_space *mapping, struct list_head *pages) +void +readpages_extent(void *vp, struct address_space *mapping, + struct list_head *pages) { assert("vs-1739", 0); if (vp) @@ -1427,11 +1535,10 @@ readpages_extent(void *vp, struct addres At the beginning: coord->node is read locked, zloaded, page is locked, coord is set to existing unit inside of extent item (it is not necessary that coord matches to page->index) */ -reiser4_internal int -readpage_extent(void *vp, struct page *page) +int readpage_extent(void *vp, struct page *page) { uf_coord_t *uf_coord = vp; - ON_DEBUG(coord_t *coord = &uf_coord->coord); + ON_DEBUG(coord_t * coord = &uf_coord->coord); ON_DEBUG(reiser4_key key); assert("vs-1040", PageLocked(page)); @@ -1443,36 +1550,54 @@ readpage_extent(void *vp, struct page *p assert("vs-758", item_is_extent(coord)); assert("vs-1046", coord_is_existing_unit(coord)); assert("vs-1045", znode_is_rlocked(coord->node)); - assert("vs-1047", page->mapping->host->i_ino == get_key_objectid(item_key_by_coord(coord, &key))); + assert("vs-1047", + page->mapping->host->i_ino == + get_key_objectid(item_key_by_coord(coord, &key))); assert("vs-1320", coord_extension_is_ok(uf_coord)); - return do_readpage_extent(ext_by_ext_coord(uf_coord), uf_coord->extension.extent.pos_in_unit, page); + return do_readpage_extent(ext_by_ext_coord(uf_coord), + uf_coord->extension.extent.pos_in_unit, page); } -/* - plugin->s.file.capture - - At the beginning: coord.node is write locked, zloaded, page is not locked, coord is set to existing unit inside of - extent item -*/ -reiser4_internal int -capture_extent(reiser4_key *key, uf_coord_t *uf_coord, struct page *page, write_mode_t mode) +/** + * capture_extent - capture page, make sure there is non hole extent for it + * @key: key of first byte in @page + * @uf_coord: coordinate and lock handle of position in the tree + * @page: page to create + * @mode: preliminary hint obtained via search + * + * This implements capture method of item plugin for extent items. At the + * beginning uf_coord->coord.node is write locked, zloaded, @page is not + * locked, @uf_coord is set to in accordance to @key. Extent and jnode + * corresponding to @page are created if they do not exist yet. Jnode is + * captured and marked dirty. Tag of @page->mapping->page_tree specifying that + * page may have no corresponding extent item is cleared. + */ +int +capture_extent(reiser4_key *key, uf_coord_t *uf_coord, struct page *page, + write_mode_t mode) { jnode *j; int result; - reiser4_block_nr blocknr; - int created; - int check_quota; + struct make_extent_handle *h; assert("vs-1051", page->mapping && page->mapping->host); - assert("nikita-3139", !inode_get_flag(page->mapping->host, REISER4_NO_SD)); + assert("nikita-3139", + !inode_get_flag(page->mapping->host, REISER4_NO_SD)); assert("vs-864", znode_is_wlocked(uf_coord->coord.node)); - assert("vs-1398", get_key_objectid(key) == get_inode_oid(page->mapping->host)); + assert("vs-1398", + get_key_objectid(key) == get_inode_oid(page->mapping->host)); - /* FIXME: assume for now that quota is only checked on write */ - check_quota = 0; - result = make_extent(key, uf_coord, mode, &blocknr, &created, check_quota ? page->mapping->host : NULL); + h = kmalloc(sizeof(*h), GFP_KERNEL); + if (h == NULL) + return RETERR(-ENOMEM); + h->uf_coord = uf_coord; + h->inode = NULL; + h->u.replace.pkey = key; + h->inode = NULL; /* do not check quota */ + result = make_extent(h, mode); if (result) { + kfree(h); done_lh(uf_coord->lh); return result; } @@ -1480,17 +1605,19 @@ capture_extent(reiser4_key *key, uf_coor lock_page(page); j = jnode_of_page(page); if (IS_ERR(j)) { + kfree(h); unlock_page(page); done_lh(uf_coord->lh); return PTR_ERR(j); } UNDER_SPIN_VOID(jnode, j, eflush_del(j, 1)); - set_page_dirty_internal(page, 0); + unlock_page(page); LOCK_JNODE(j); + BUG_ON(JF_ISSET(j, JNODE_EFLUSH)); - if (created) { + if (h->created) { /* extent corresponding to this jnode was just created */ assert("vs-1504", *jnode_get_block(j) == 0); JF_SET(j, JNODE_CREATED); @@ -1500,35 +1627,40 @@ capture_extent(reiser4_key *key, uf_coor } if (*jnode_get_block(j) == 0) - jnode_set_block(j, &blocknr); + jnode_set_block(j, &h->blocknr); else { - assert("vs-1508", !blocknr_is_fake(&blocknr)); - assert("vs-1507", ergo(blocknr, *jnode_get_block(j) == blocknr)); + assert("vs-1508", !blocknr_is_fake(&h->blocknr)); + assert("vs-1507", + ergo(h->blocknr, *jnode_get_block(j) == h->blocknr)); } UNLOCK_JNODE(j); - done_lh(uf_coord->lh); + done_lh(h->uf_coord->lh); LOCK_JNODE(j); - result = try_capture(j, ZNODE_WRITE_LOCK, 0, 1/* can_coc */); + result = try_capture(j, ZNODE_WRITE_LOCK, 0, 1 /* can_coc */ ); if (result != 0) - reiser4_panic("nikita-3324", "Cannot capture jnode: %i", result); + reiser4_panic("nikita-3324", "Cannot capture jnode: %i", + result); jnode_make_dirty_locked(j); + JF_CLR(j, JNODE_KEEPME); UNLOCK_JNODE(j); jput(j); - if (created) + if (h->created) reiser4_update_sd(page->mapping->host); - /* warning about failure of this is issued already */ + /* warning about failure of this is issued already */ + kfree(h); return 0; } /* plugin->u.item.s.file.get_block */ -reiser4_internal int -get_block_address_extent(const coord_t *coord, sector_t block, struct buffer_head *bh) +int +get_block_address_extent(const coord_t * coord, sector_t block, + sector_t * result) { reiser4_extent *ext; @@ -1539,14 +1671,21 @@ get_block_address_extent(const coord_t * if (state_of_extent(ext) != ALLOCATED_EXTENT) /* FIXME: bad things may happen if it is unallocated extent */ - bh->b_blocknr = 0; + *result = 0; else { reiser4_key key; unit_key_by_coord(coord, &key); - assert("vs-1645", block >= get_key_offset(&key) >> current_blocksize_bits); - assert("vs-1646", block < (get_key_offset(&key) >> current_blocksize_bits) + extent_get_width(ext)); - bh->b_blocknr = extent_get_start(ext) + (block - (get_key_offset(&key) >> current_blocksize_bits)); + assert("vs-1645", + block >= get_key_offset(&key) >> current_blocksize_bits); + assert("vs-1646", + block < + (get_key_offset(&key) >> current_blocksize_bits) + + extent_get_width(ext)); + *result = + extent_get_start(ext) + (block - + (get_key_offset(&key) >> + current_blocksize_bits)); } return 0; } @@ -1555,19 +1694,21 @@ get_block_address_extent(const coord_t * plugin->u.item.s.file.append_key key of first byte which is the next to last byte by addressed by this extent */ -reiser4_internal reiser4_key * -append_key_extent(const coord_t *coord, reiser4_key *key) +reiser4_key *append_key_extent(const coord_t * coord, reiser4_key * key) { item_key_by_coord(coord, key); - set_key_offset(key, get_key_offset(key) + extent_size(coord, nr_units_extent(coord))); + set_key_offset(key, + get_key_offset(key) + extent_size(coord, + nr_units_extent + (coord))); - assert("vs-610", get_key_offset(key) && (get_key_offset(key) & (current_blocksize - 1)) == 0); + assert("vs-610", get_key_offset(key) + && (get_key_offset(key) & (current_blocksize - 1)) == 0); return key; } /* plugin->u.item.s.file.init_coord_extension */ -reiser4_internal void -init_coord_extension_extent(uf_coord_t *uf_coord, loff_t lookuped) +void init_coord_extension_extent(uf_coord_t * uf_coord, loff_t lookuped) { coord_t *coord; extent_coord_extension_t *ext_coord; @@ -1585,14 +1726,16 @@ init_coord_extension_extent(uf_coord_t * ext_coord = &uf_coord->extension.extent; ext_coord->nr_units = nr_units_extent(coord); - ext_coord->ext_offset = (char *)extent_by_coord(coord) - zdata(coord->node); + ext_coord->ext_offset = + (char *)extent_by_coord(coord) - zdata(coord->node); ext_coord->width = extent_get_width(extent_by_coord(coord)); ON_DEBUG(ext_coord->extent = *extent_by_coord(coord)); uf_coord->valid = 1; /* pos_in_unit is the only uninitialized field in extended coord */ if (coord->between == AFTER_UNIT) { - assert("vs-1330", coord->unit_pos == nr_units_extent(coord) - 1); + assert("vs-1330", + coord->unit_pos == nr_units_extent(coord) - 1); ext_coord->pos_in_unit = ext_coord->width - 1; } else { @@ -1601,8 +1744,11 @@ init_coord_extension_extent(uf_coord_t * offset = get_key_offset(&key); assert("vs-1328", offset <= lookuped); - assert("vs-1329", lookuped < offset + ext_coord->width * current_blocksize); - ext_coord->pos_in_unit = ((lookuped - offset) >> current_blocksize_bits); + assert("vs-1329", + lookuped < + offset + ext_coord->width * current_blocksize); + ext_coord->pos_in_unit = + ((lookuped - offset) >> current_blocksize_bits); } } diff -puN fs/reiser4/plugin/item/extent_flush_ops.c~reiser4-big-update fs/reiser4/plugin/item/extent_flush_ops.c --- devel/fs/reiser4/plugin/item/extent_flush_ops.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/extent_flush_ops.c 2005-09-15 19:51:08.000000000 -0700 @@ -10,13 +10,13 @@ #include -static reiser4_block_nr extent_unit_start(const coord_t *item); +static reiser4_block_nr extent_unit_start(const coord_t * item); /* Return either first or last extent (depending on @side) of the item @coord is set to. Set @pos_in_unit either to first or to last block of extent. */ -static reiser4_extent * -extent_utmost_ext(const coord_t *coord, sideof side, reiser4_block_nr *pos_in_unit) +static reiser4_extent *extent_utmost_ext(const coord_t * coord, sideof side, + reiser4_block_nr * pos_in_unit) { reiser4_extent *ext; @@ -37,8 +37,7 @@ extent_utmost_ext(const coord_t *coord, /* item_plugin->f.utmost_child */ /* Return the child. Coord is set to extent item. Find jnode corresponding either to first or to last unformatted node pointed by the item */ -reiser4_internal int -utmost_child_extent(const coord_t *coord, sideof side, jnode **childp) +int utmost_child_extent(const coord_t * coord, sideof side, jnode ** childp) { reiser4_extent *ext; reiser4_block_nr pos_in_unit; @@ -70,12 +69,14 @@ utmost_child_extent(const coord_t *coord append_key_extent(coord, &key); } - assert("vs-544", (get_key_offset(&key) >> PAGE_CACHE_SHIFT) < ~0ul); + assert("vs-544", + (get_key_offset(&key) >> PAGE_CACHE_SHIFT) < ~0ul); /* index of first or last (depending on @side) page addressed by the extent */ - index = (unsigned long) (get_key_offset(&key) >> PAGE_CACHE_SHIFT); + index = + (unsigned long)(get_key_offset(&key) >> PAGE_CACHE_SHIFT); if (side == RIGHT_SIDE) - index --; + index--; tree = coord->node->zjnode.tree; *childp = jlookup(tree, get_key_objectid(&key), index); @@ -86,8 +87,9 @@ utmost_child_extent(const coord_t *coord /* item_plugin->f.utmost_child_real_block */ /* Return the child's block, if allocated. */ -reiser4_internal int -utmost_child_real_block_extent(const coord_t *coord, sideof side, reiser4_block_nr *block) +int +utmost_child_real_block_extent(const coord_t * coord, sideof side, + reiser4_block_nr * block) { reiser4_extent *ext; @@ -125,7 +127,7 @@ utmost_child_real_block_extent(const coo It returns control to scan_extent, handles these terminating conditions, e.g., by loading the next twig. */ -reiser4_internal int scan_extent(flush_scan * scan) +int scan_extent(flush_scan * scan) { coord_t coord; jnode *neighbor; @@ -138,8 +140,8 @@ reiser4_internal int scan_extent(flush_s if (!jnode_check_dirty(scan->node)) { scan->stop = 1; - return 0; /* Race with truncate, this node is already - * truncated. */ + return 0; /* Race with truncate, this node is already + * truncated. */ } coord_dup(&coord, &scan->parent_coord); @@ -154,7 +156,7 @@ reiser4_internal int scan_extent(flush_s assert("jmacd-7889", item_is_extent(&coord)); -repeat: + repeat: /* objectid of file */ oid = get_key_objectid(item_key_by_coord(&coord, &key)); @@ -192,7 +194,8 @@ repeat: if (neighbor == NULL) goto stop_same_parent; - if (scan->node != neighbor && !scan_goto(scan, neighbor)) { + if (scan->node != neighbor + && !scan_goto(scan, neighbor)) { /* @neighbor was jput() by scan_goto(). */ goto stop_same_parent; } @@ -210,7 +213,7 @@ repeat: } else { /* Optimized case for unallocated extents, skip to the end. */ - neighbor = jlookup(tree, oid, scan_max/*index*/); + neighbor = jlookup(tree, oid, scan_max /*index */ ); if (neighbor == NULL) { /* Race with truncate */ scan->stop = 1; @@ -218,12 +221,7 @@ repeat: goto exit; } - assert ("zam-1043", blocknr_is_fake(jnode_get_block(neighbor))); - - /* XXX commented assertion out, because it is inherently - * racy */ - /* assert("jmacd-3551", !jnode_check_flushprepped(neighbor) - && same_slum_check(neighbor, scan->node, 0, 0)); */ + assert("zam-1043", blocknr_is_fake(jnode_get_block(neighbor))); ret = scan_set_current(scan, neighbor, scan_dist, &coord); if (ret != 0) { @@ -231,16 +229,18 @@ repeat: } } - if (coord_sideof_unit(&coord, scan->direction) == 0 && item_is_extent(&coord)) { + if (coord_sideof_unit(&coord, scan->direction) == 0 + && item_is_extent(&coord)) { /* Continue as long as there are more extent units. */ scan_index = - extent_unit_index(&coord) + (scanning_left(scan) ? extent_unit_width(&coord) - 1 : 0); + extent_unit_index(&coord) + + (scanning_left(scan) ? extent_unit_width(&coord) - 1 : 0); goto repeat; } if (0) { -stop_same_parent: + stop_same_parent: /* If we are scanning left and we stop in the middle of an allocated extent, we know the preceder immediately.. */ @@ -252,10 +252,11 @@ stop_same_parent: unit. Flush stopped at the @scan_index block from the beginning of the file, which is (scan_index - unit_index) block within extent. - */ + */ if (unit_start) { /* skip preceder update when we are at hole */ - scan->preceder_blk = unit_start + scan_index - unit_index; + scan->preceder_blk = + unit_start + scan_index - unit_index; check_preceder(scan->preceder_blk); } } @@ -267,21 +268,22 @@ stop_same_parent: /* In this case, we are still scanning, coord is set to the next item which is either off-the-end of the node or not an extent. */ assert("jmacd-8912", scan->stop == 0); - assert("jmacd-7812", (coord_is_after_sideof_unit(&coord, scan->direction) - || !item_is_extent(&coord))); + assert("jmacd-7812", + (coord_is_after_sideof_unit(&coord, scan->direction) + || !item_is_extent(&coord))); } ret = 0; -exit: + exit: return ret; } /* ask block allocator for some blocks */ static void -extent_allocate_blocks(reiser4_blocknr_hint *preceder, +extent_allocate_blocks(reiser4_blocknr_hint * preceder, reiser4_block_nr wanted_count, - reiser4_block_nr *first_allocated, reiser4_block_nr *allocated, - block_stage_t block_stage) + reiser4_block_nr * first_allocated, + reiser4_block_nr * allocated, block_stage_t block_stage) { *allocated = wanted_count; preceder->max_dist = 0; /* scan whole disk, if needed */ @@ -290,7 +292,9 @@ extent_allocate_blocks(reiser4_blocknr_h preceder->block_stage = block_stage; /* FIXME: we do not handle errors here now */ - check_me("vs-420", reiser4_alloc_blocks(preceder, first_allocated, allocated, BA_PERMANENT) == 0); + check_me("vs-420", + reiser4_alloc_blocks(preceder, first_allocated, allocated, + BA_PERMANENT) == 0); /* update flush_pos's preceder to last allocated block number */ preceder->blk = *first_allocated + *allocated - 1; } @@ -298,8 +302,7 @@ extent_allocate_blocks(reiser4_blocknr_h /* when on flush time unallocated extent is to be replaced with allocated one it may happen that one unallocated extent will have to be replaced with set of allocated extents. In this case insert_into_item will be called which may have to add new nodes into tree. Space for that is taken from inviolable reserve (5%). */ -static reiser4_block_nr -reserve_replace(void) +static reiser4_block_nr reserve_replace(void) { reiser4_block_nr grabbed, needed; @@ -309,8 +312,7 @@ reserve_replace(void) return grabbed; } -static void -free_replace_reserved(reiser4_block_nr grabbed) +static void free_replace_reserved(reiser4_block_nr grabbed) { reiser4_context *ctx; @@ -320,8 +322,7 @@ free_replace_reserved(reiser4_block_nr g } /* Block offset of first block addressed by unit */ -reiser4_internal __u64 -extent_unit_index(const coord_t *item) +__u64 extent_unit_index(const coord_t * item) { reiser4_key key; @@ -332,53 +333,65 @@ extent_unit_index(const coord_t *item) /* AUDIT shouldn't return value be of reiser4_block_nr type? Josh's answer: who knows? Is a "number of blocks" the same type as "block offset"? */ -reiser4_internal __u64 -extent_unit_width(const coord_t *item) +__u64 extent_unit_width(const coord_t * item) { assert("vs-649", coord_is_existing_unit(item)); return width_by_coord(item); } /* Starting block location of this unit */ -static reiser4_block_nr -extent_unit_start(const coord_t *item) +static reiser4_block_nr extent_unit_start(const coord_t * item) { return extent_get_start(extent_by_coord(item)); } -/* replace allocated extent with two allocated extents */ -static int -split_allocated_extent(coord_t *coord, reiser4_block_nr pos_in_unit) +/** + * split_allocated_extent - + * @coord: + * @pos_in_unit: + * + * replace allocated extent with two allocated extents + */ +static int split_allocated_extent(coord_t *coord, reiser4_block_nr pos_in_unit) { int result; + struct replace_handle *h; reiser4_extent *ext; - reiser4_extent replace_ext; - reiser4_extent append_ext; - reiser4_key key; - reiser4_item_data item; reiser4_block_nr grabbed; ext = extent_by_coord(coord); assert("vs-1410", state_of_extent(ext) == ALLOCATED_EXTENT); assert("vs-1411", extent_get_width(ext) > pos_in_unit); - set_extent(&replace_ext, extent_get_start(ext), pos_in_unit); - set_extent(&append_ext, extent_get_start(ext) + pos_in_unit, extent_get_width(ext) - pos_in_unit); - - /* insert_into_item will insert new unit after the one @coord is set to. So, update key correspondingly */ - unit_key_by_coord(coord, &key); - set_key_offset(&key, (get_key_offset(&key) + pos_in_unit * current_blocksize)); + h = kmalloc(sizeof(*h), GFP_KERNEL); + if (h == NULL) + return RETERR(-ENOMEM); + h->coord = coord; + h->lh = znode_lh(coord->node); + h->pkey = &h->key; + unit_key_by_coord(coord, h->pkey); + set_key_offset(h->pkey, + (get_key_offset(h->pkey) + + pos_in_unit * current_blocksize)); + set_extent(&h->overwrite, extent_get_start(ext), pos_in_unit); + set_extent(&h->new_extents[0], extent_get_start(ext) + pos_in_unit, + extent_get_width(ext) - pos_in_unit); + h->nr_new_extents = 1; + h->flags = COPI_DONT_SHIFT_LEFT; + h->paste_key = h->key; + /* reserve space for extent unit paste, @grabbed is reserved before */ grabbed = reserve_replace(); - result = replace_extent(coord, znode_lh(coord->node), &key, init_new_extent(&item, &append_ext, 1), - &replace_ext, COPI_DONT_SHIFT_LEFT, 0/* return replaced position */); + result = replace_extent(h, 0 /* leave @coord set to overwritten + extent */); + /* restore reserved */ free_replace_reserved(grabbed); + kfree(h); return result; } /* clear bit preventing node from being written bypassing extent allocation procedure */ -static inline void -junprotect (jnode * node) +static inline void junprotect(jnode * node) { assert("zam-837", !JF_ISSET(node, JNODE_EFLUSH)); assert("zam-838", JF_ISSET(node, JNODE_EPROTECTED)); @@ -386,42 +399,61 @@ junprotect (jnode * node) JF_CLR(node, JNODE_EPROTECTED); } -/* this is used to unprotect nodes which were protected before allocating but which will not be allocated either because - space allocator allocates less blocks than were protected and/or if allocation of those nodes failed */ static void -unprotect_extent_nodes(flush_pos_t *flush_pos, __u64 count, capture_list_head *protected_nodes) +protected_list_split(struct list_head *head_split, + struct list_head *head_new, + jnode *node) +{ + assert("vs-1471", list_empty_careful(head_new)); + + /* attach to new list */ + head_new->next = &node->capture_link; + head_new->prev = head_split->prev; + + /* cut from old list */ + node->capture_link.prev->next = head_split; + head_split->prev = node->capture_link.prev; + + /* link new list */ + head_new->next->prev = head_new; + head_new->prev->next = head_new; +} + +/* this is used to unprotect nodes which were protected before allocating but + which will not be allocated either because space allocator allocates less + blocks than were protected and/or if allocation of those nodes failed */ +static void +unprotect_extent_nodes(flush_pos_t *flush_pos, __u64 count, + struct list_head *protected_nodes) { jnode *node, *tmp; - capture_list_head unprotected_nodes; + LIST_HEAD(unprotected_nodes); txn_atom *atom; - capture_list_init(&unprotected_nodes); - atom = atom_locked_by_fq(pos_fq(flush_pos)); assert("vs-1468", atom); - assert("vs-1469", !capture_list_empty(protected_nodes)); + assert("vs-1469", !list_empty_careful(protected_nodes)); assert("vs-1474", count > 0); - node = capture_list_back(protected_nodes); + node = list_entry(protected_nodes->prev, jnode, capture_link); do { - count --; + count--; junprotect(node); - ON_DEBUG( - LOCK_JNODE(node); - count_jnode(atom, node, PROTECT_LIST, DIRTY_LIST, 0); - UNLOCK_JNODE(node); - ); + ON_DEBUG(LOCK_JNODE(node); + count_jnode(atom, node, PROTECT_LIST, DIRTY_LIST, 0); + UNLOCK_JNODE(node);); if (count == 0) { break; } - tmp = capture_list_prev(node); + tmp = list_entry(node->capture_link.prev, jnode, capture_link); node = tmp; - assert("vs-1470", !capture_list_end(protected_nodes, node)); + assert("vs-1470", protected_nodes != &node->capture_link); } while (1); /* move back to dirty list */ - capture_list_split(protected_nodes, &unprotected_nodes, node); - capture_list_splice(ATOM_DIRTY_LIST(atom, LEAF_LEVEL), &unprotected_nodes); + protected_list_split(protected_nodes, &unprotected_nodes, node); + list_splice(&unprotected_nodes, ATOM_DIRTY_LIST(atom, LEAF_LEVEL)); + INIT_LIST_HEAD(&unprotected_nodes); UNLOCK_ATOM(atom); } @@ -429,8 +461,7 @@ unprotect_extent_nodes(flush_pos_t *flus extern int getjevent(void); /* remove node from atom's list and put to the end of list @jnodes */ -static void -protect_reloc_node(capture_list_head *jnodes, jnode *node) +static void protect_reloc_node(struct list_head *jnodes, jnode *node) { assert("zam-836", !JF_ISSET(node, JNODE_EPROTECTED)); assert("vs-1216", jnode_is_unformatted(node)); @@ -438,42 +469,45 @@ protect_reloc_node(capture_list_head *jn assert("nikita-3390", spin_jnode_is_locked(node)); JF_SET(node, JNODE_EPROTECTED); - capture_list_remove_clean(node); - capture_list_push_back(jnodes, node); + list_del_init(&node->capture_link); + list_add_tail(&node->capture_link, jnodes); ON_DEBUG(count_jnode(node->atom, node, DIRTY_LIST, PROTECT_LIST, 0)); } #define JNODES_TO_UNFLUSH (16) -/* @count nodes of file (objectid @oid) starting from @index are going to be allocated. Protect those nodes from - e-flushing. Nodes which are eflushed already will be un-eflushed. There will be not more than JNODES_TO_UNFLUSH - un-eflushed nodes. If a node is not found or flushprepped - stop protecting */ -/* FIXME: it is likely that not flushprepped jnodes are on dirty capture list in sequential order.. */ +/* @count nodes of file (objectid @oid) starting from @index are going to be + allocated. Protect those nodes from e-flushing. Nodes which are eflushed + already will be un-eflushed. There will be not more than JNODES_TO_UNFLUSH + un-eflushed nodes. If a node is not found or flushprepped - stop + protecting */ +/* FIXME: it is likely that not flushprepped jnodes are on dirty capture list + * in sequential order.. */ static int -protect_extent_nodes(flush_pos_t *flush_pos, oid_t oid, unsigned long index, reiser4_block_nr count, - reiser4_block_nr *protected, reiser4_extent *ext, - capture_list_head *protected_nodes) -{ - __u64 i; - __u64 j; - int result; - reiser4_tree *tree; - int eflushed; - jnode *buf[JNODES_TO_UNFLUSH]; - txn_atom *atom; +protect_extent_nodes(flush_pos_t *flush_pos, oid_t oid, unsigned long index, + reiser4_block_nr count, reiser4_block_nr *protected, + reiser4_extent *ext, struct list_head *protected_nodes) +{ + __u64 i; + __u64 j; + int result; + reiser4_tree *tree; + int eflushed; + jnode *buf[JNODES_TO_UNFLUSH]; + txn_atom *atom; - assert("nikita-3394", capture_list_empty(protected_nodes)); + assert("nikita-3394", list_empty_careful(protected_nodes)); tree = current_tree; atom = atom_locked_by_fq(pos_fq(flush_pos)); assert("vs-1468", atom); - assert("vs-1470", extent_get_width(ext) == count); + assert("vs-1470", extent_get_width(ext) >= count); eflushed = 0; *protected = 0; for (i = 0; i < count; ++i, ++index) { - jnode *node; + jnode *node; node = jlookup(tree, oid, index); if (!node) @@ -491,11 +525,11 @@ protect_extent_nodes(flush_pos_t *flush_ if (JF_ISSET(node, JNODE_EFLUSH)) { if (eflushed == JNODES_TO_UNFLUSH) { UNLOCK_JNODE(node); - atomic_dec(&node->x_count); + atomic_dec(&node->x_count); break; } buf[eflushed] = node; - eflushed ++; + eflushed++; protect_reloc_node(protected_nodes, node); UNLOCK_JNODE(node); } else { @@ -506,16 +540,16 @@ protect_extent_nodes(flush_pos_t *flush_ atomic_dec(&node->x_count); } - (*protected) ++; + (*protected)++; } UNLOCK_ATOM(atom); /* start io for eflushed nodes */ - for (j = 0; j < eflushed; ++ j) + for (j = 0; j < eflushed; ++j) jstartio(buf[j]); result = 0; - for (j = 0; j < eflushed; ++ j) { + for (j = 0; j < eflushed; ++j) { if (result == 0) { result = emergency_unflush(buf[j]); if (result != 0) { @@ -536,24 +570,32 @@ protect_extent_nodes(flush_pos_t *flush_ /* replace extent @ext by extent @replace. Try to merge @replace with previous extent of the item (if there is one). Return 1 if it succeeded, 0 - otherwise */ static int -try_to_merge_with_left(coord_t *coord, reiser4_extent *ext, reiser4_extent *replace) +try_to_merge_with_left(coord_t * coord, reiser4_extent * ext, + reiser4_extent * replace) { assert("vs-1415", extent_by_coord(coord) == ext); - if (coord->unit_pos == 0 || state_of_extent(ext - 1) != ALLOCATED_EXTENT) + if (coord->unit_pos == 0 + || state_of_extent(ext - 1) != ALLOCATED_EXTENT) /* @ext either does not exist or is not allocated extent */ return 0; - if (extent_get_start(ext - 1) + extent_get_width(ext - 1) != extent_get_start(replace)) + if (extent_get_start(ext - 1) + extent_get_width(ext - 1) != + extent_get_start(replace)) return 0; /* we can glue, widen previous unit */ - extent_set_width(ext - 1, extent_get_width(ext - 1) + extent_get_width(replace)); + extent_set_width(ext - 1, + extent_get_width(ext - 1) + extent_get_width(replace)); if (extent_get_width(ext) != extent_get_width(replace)) { /* make current extent narrower */ if (state_of_extent(ext) == ALLOCATED_EXTENT) - extent_set_start(ext, extent_get_start(ext) + extent_get_width(replace)); - extent_set_width(ext, extent_get_width(ext) - extent_get_width(replace)); + extent_set_start(ext, + extent_get_start(ext) + + extent_get_width(replace)); + extent_set_width(ext, + extent_get_width(ext) - + extent_get_width(replace)); } else { /* current extent completely glued with its left neighbor, remove it */ coord_t from, to; @@ -564,28 +606,33 @@ try_to_merge_with_left(coord_t *coord, r /* currently cut from extent can cut either from the beginning or from the end. Move place which got freed after unit removal to end of item */ - memmove(ext, ext + 1, (from.unit_pos - coord->unit_pos) * sizeof(reiser4_extent)); + memmove(ext, ext + 1, + (from.unit_pos - + coord->unit_pos) * sizeof(reiser4_extent)); /* wipe part of item which is going to be cut, so that node_check will not be confused */ cut_node_content(&from, &to, NULL, NULL, NULL); } znode_make_dirty(coord->node); /* move coord back */ - coord->unit_pos --; + coord->unit_pos--; return 1; } -/* replace extent (unallocated or allocated) pointed by @coord with extent @replace (allocated). If @replace is shorter - than @coord - add padding extent */ -static int -conv_extent(coord_t *coord, reiser4_extent *replace) +/** + * conv_extent - replace extent with 2 ones + * @coord: coordinate of extent to be replaced + * @replace: extent to overwrite the one @coord is set to + * + * Overwrites extent @coord is set to and paste one extent unit after + * overwritten one if @replace is shorter than initial extent + */ +static int conv_extent(coord_t *coord, reiser4_extent *replace) { int result; + struct replace_handle *h; reiser4_extent *ext; - reiser4_extent padd_ext; reiser4_block_nr start, width, new_width; reiser4_block_nr grabbed; - reiser4_item_data item; - reiser4_key key; extent_state state; ext = extent_by_coord(coord); @@ -594,11 +641,13 @@ conv_extent(coord_t *coord, reiser4_exte width = extent_get_width(ext); new_width = extent_get_width(replace); - assert("vs-1458", state == UNALLOCATED_EXTENT || state == ALLOCATED_EXTENT); + assert("vs-1458", (state == UNALLOCATED_EXTENT || + state == ALLOCATED_EXTENT)); assert("vs-1459", width >= new_width); if (try_to_merge_with_left(coord, ext, replace)) { - /* merged @replace with left neighbor. Current unit is either removed or narrowed */ + /* merged @replace with left neighbor. Current unit is either + removed or narrowed */ return 0; } @@ -609,31 +658,48 @@ conv_extent(coord_t *coord, reiser4_exte return 0; } + h = kmalloc(sizeof(*h), GFP_KERNEL); + if (h == NULL) + return RETERR(-ENOMEM); + h->coord = coord; + h->lh = znode_lh(coord->node); + h->pkey = &h->key; + unit_key_by_coord(coord, h->pkey); + set_key_offset(h->pkey, + (get_key_offset(h->pkey) + new_width * current_blocksize)); + h->overwrite = *replace; + /* replace @ext with @replace and padding extent */ - set_extent(&padd_ext, state == ALLOCATED_EXTENT ? (start + new_width) : UNALLOCATED_EXTENT_START, + set_extent(&h->new_extents[0], + (state == ALLOCATED_EXTENT) ? (start + new_width) : UNALLOCATED_EXTENT_START, width - new_width); + h->nr_new_extents = 1; + h->flags = COPI_DONT_SHIFT_LEFT; + h->paste_key = h->key; - /* insert_into_item will insert new units after the one @coord is set to. So, update key correspondingly */ - unit_key_by_coord(coord, &key); - set_key_offset(&key, (get_key_offset(&key) + new_width * current_blocksize)); - + /* reserve space for extent unit paste, @grabbed is reserved before */ grabbed = reserve_replace(); - result = replace_extent(coord, znode_lh(coord->node), &key, init_new_extent(&item, &padd_ext, 1), - replace, COPI_DONT_SHIFT_LEFT, 0/* return replaced position */); + result = replace_extent(h, 0 /* leave @coord set to overwritten + extent */); + /* restore reserved */ free_replace_reserved(grabbed); + kfree(h); return result; } -/* for every jnode from @protected_nodes list assign block number and mark it RELOC and FLUSH_QUEUED. Attach whole - @protected_nodes list to flush queue's prepped list */ +/* for every jnode from @protected_nodes list assign block number and mark it + RELOC and FLUSH_QUEUED. Attach whole @protected_nodes list to flush queue's + prepped list */ static void -assign_real_blocknrs(flush_pos_t *flush_pos, reiser4_block_nr first, reiser4_block_nr count, - extent_state state, capture_list_head *protected_nodes) +assign_real_blocknrs(flush_pos_t *flush_pos, reiser4_block_nr first, + reiser4_block_nr count, extent_state state, + struct list_head *protected_nodes) { jnode *node; txn_atom *atom; flush_queue_t *fq; + struct list_head *pos; int i; fq = pos_fq(flush_pos); @@ -641,66 +707,87 @@ assign_real_blocknrs(flush_pos_t *flush_ assert("vs-1468", atom); i = 0; - for_all_type_safe_list(capture, protected_nodes, node) { + list_for_each(pos, protected_nodes) { + node = list_entry(pos, jnode, capture_link); LOCK_JNODE(node); - assert("vs-1132", ergo(state == UNALLOCATED_EXTENT, blocknr_is_fake(jnode_get_block(node)))); + assert("vs-1132", + ergo(state == UNALLOCATED_EXTENT, + blocknr_is_fake(jnode_get_block(node)))); assert("vs-1475", node->atom == atom); assert("vs-1476", atomic_read(&node->x_count) > 0); JF_CLR(node, JNODE_FLUSH_RESERVED); jnode_set_block(node, &first); + unformatted_make_reloc(node, fq); - /*XXXX*/ON_DEBUG(count_jnode(node->atom, node, PROTECT_LIST, FQ_LIST, 0)); + ON_DEBUG(count_jnode(node->atom, node, PROTECT_LIST, + FQ_LIST, 0)); junprotect(node); assert("", NODE_LIST(node) == FQ_LIST); UNLOCK_JNODE(node); - first ++; - i ++; + first++; + i++; } - capture_list_splice(ATOM_FQ_LIST(fq), protected_nodes); - /*XXX*/ + list_splice(protected_nodes, ATOM_FQ_LIST(fq)); + INIT_LIST_HEAD(protected_nodes); + assert("vs-1687", count == i); if (state == UNALLOCATED_EXTENT) dec_unalloc_unfm_ptrs(count); UNLOCK_ATOM(atom); } -static void -make_node_ovrwr(capture_list_head *jnodes, jnode *node) +/** + * make_node_ovrwr - assign node to overwrite set + * @jnodes: overwrite set list head + * @node: jnode to belong to overwrite set + * + * Sets OVRWR jnode state bit and puts @node to the end of list head @jnodes + * which is an accumulator for nodes before they get to overwrite set list of + * atom. + */ +static void make_node_ovrwr(struct list_head *jnodes, jnode *node) { LOCK_JNODE(node); - assert ("zam-917", !JF_ISSET(node, JNODE_RELOC)); - assert ("zam-918", !JF_ISSET(node, JNODE_OVRWR)); + assert("zam-917", !JF_ISSET(node, JNODE_RELOC)); + assert("zam-918", !JF_ISSET(node, JNODE_OVRWR)); JF_SET(node, JNODE_OVRWR); - capture_list_remove_clean(node); - capture_list_push_back(jnodes, node); + list_del_init(&node->capture_link); + list_add_tail(&node->capture_link, jnodes); ON_DEBUG(count_jnode(node->atom, node, DIRTY_LIST, OVRWR_LIST, 0)); UNLOCK_JNODE(node); } -/* put nodes of one extent (file objectid @oid, extent width @width) to overwrite set. Starting from the one with index - @index. If end of slum is detected (node is not found or flushprepped) - stop iterating and set flush position's - state to POS_INVALID */ -static void -mark_jnodes_overwrite(flush_pos_t *flush_pos, oid_t oid, unsigned long index, reiser4_block_nr width) +/** + * mark_jnodes_overwrite - put bunch of jnodes to overwrite set + * @flush_pos: flush position + * @oid: objectid of file jnodes belong to + * @index: starting index + * @width: extent width + * + * Puts nodes of one extent (file objectid @oid, extent width @width) to atom's + * overwrite set. Starting from the one with index @index. If end of slum is + * detected (node is not found or flushprepped) - stop iterating and set flush + * position's state to POS_INVALID. + */ +static void mark_jnodes_overwrite(flush_pos_t *flush_pos, oid_t oid, + unsigned long index, reiser4_block_nr width) { unsigned long i; reiser4_tree *tree; jnode *node; txn_atom *atom; - capture_list_head jnodes; - - capture_list_init(&jnodes); + LIST_HEAD(jnodes); tree = current_tree; atom = atom_locked_by_fq(pos_fq(flush_pos)); assert("vs-1478", atom); - for (i = flush_pos->pos_in_unit; i < width; i ++, index ++) { + for (i = flush_pos->pos_in_unit; i < width; i++, index++) { node = jlookup(tree, oid, index); if (!node) { flush_pos->state = POS_INVALID; @@ -715,15 +802,15 @@ mark_jnodes_overwrite(flush_pos_t *flush atomic_dec(&node->x_count); } - capture_list_splice(ATOM_OVRWR_LIST(atom), &jnodes); + list_splice(&jnodes, ATOM_OVRWR_LIST(atom)); + INIT_LIST_HEAD(&jnodes); UNLOCK_ATOM(atom); } /* this is called by handle_pos_on_twig to proceed extent unit flush_pos->coord is set to. It is to prepare for flushing sequence of not flushprepped nodes (slum). It supposes that slum starts at flush_pos->pos_in_unit position within the extent. Slum gets to relocate set if flush_pos->leaf_relocate is set to 1 and to overwrite set otherwise */ -reiser4_internal int -alloc_extent(flush_pos_t *flush_pos) +int alloc_extent(flush_pos_t * flush_pos) { coord_t *coord; reiser4_extent *ext; @@ -741,7 +828,8 @@ alloc_extent(flush_pos_t *flush_pos) block_stage_t block_stage; assert("vs-1468", flush_pos->state == POS_ON_EPOINT); - assert("vs-1469", coord_is_existing_unit(&flush_pos->coord) && item_is_extent(&flush_pos->coord)); + assert("vs-1469", coord_is_existing_unit(&flush_pos->coord) + && item_is_extent(&flush_pos->coord)); coord = &flush_pos->coord; @@ -766,7 +854,9 @@ alloc_extent(flush_pos_t *flush_pos) /* relocate */ if (flush_pos->pos_in_unit) { /* split extent unit into two */ - result = split_allocated_extent(coord, flush_pos->pos_in_unit); + result = + split_allocated_extent(coord, + flush_pos->pos_in_unit); flush_pos->pos_in_unit = 0; return result; } @@ -777,9 +867,17 @@ alloc_extent(flush_pos_t *flush_pos) protected_jnodes_init(&jnodes); - result = protect_extent_nodes(flush_pos, oid, index, width, &protected, ext, &jnodes.nodes); + /* limit number of nodes to allocate */ + /*warning("", "nr_to_write = %ld, extent width %llu\n", flush_pos->nr_to_write, width); */ + if (flush_pos->nr_to_write < width) + width = flush_pos->nr_to_write; + + result = + protect_extent_nodes(flush_pos, oid, index, width, + &protected, ext, &jnodes.nodes); if (result) { - warning("vs-1469", "Failed to protect extent. Should not happen\n"); + warning("vs-1469", + "Failed to protect extent. Should not happen\n"); protected_jnodes_done(&jnodes); return result; } @@ -798,11 +896,16 @@ alloc_extent(flush_pos_t *flush_pos) block_stage = BLOCK_UNALLOCATED; /* look at previous unit if possible. If it is allocated, make preceder more precise */ - if (coord->unit_pos && (state_of_extent(ext - 1) == ALLOCATED_EXTENT)) - pos_hint(flush_pos)->blk = extent_get_start(ext - 1) + extent_get_width(ext - 1); + if (coord->unit_pos + && (state_of_extent(ext - 1) == ALLOCATED_EXTENT)) + pos_hint(flush_pos)->blk = + extent_get_start(ext - 1) + extent_get_width(ext - + 1); /* allocate new block numbers for protected nodes */ - extent_allocate_blocks(pos_hint(flush_pos), protected, &first_allocated, &allocated, block_stage); + extent_allocate_blocks(pos_hint(flush_pos), protected, + &first_allocated, &allocated, + block_stage); if (allocated != protected) /* unprotect nodes which will not be @@ -812,11 +915,13 @@ alloc_extent(flush_pos_t *flush_pos) if (state == ALLOCATED_EXTENT) { /* on relocating - free nodes which are going to be * relocated */ - reiser4_dealloc_blocks(&start, &allocated, BLOCK_ALLOCATED, BA_DEFER); + reiser4_dealloc_blocks(&start, &allocated, + BLOCK_ALLOCATED, BA_DEFER); } /* assign new block numbers to protected nodes */ - assign_real_blocknrs(flush_pos, first_allocated, allocated, state, &jnodes.nodes); + assign_real_blocknrs(flush_pos, first_allocated, allocated, + state, &jnodes.nodes); protected_jnodes_done(&jnodes); @@ -826,9 +931,15 @@ alloc_extent(flush_pos_t *flush_pos) /* adjust extent item */ result = conv_extent(coord, &replace_ext); if (result != 0 && result != -ENOMEM) { - warning("vs-1461", "Failed to allocate extent. Should not happen\n"); + warning("vs-1461", + "Failed to allocate extent. Should not happen\n"); return result; } + + /* break flush we prepared for flushing as many blocks as we + were asked for */ + if (flush_pos->nr_to_write == allocated) + flush_pos->state = POS_INVALID; } else { /* overwrite */ mark_jnodes_overwrite(flush_pos, oid, index, width); @@ -838,20 +949,21 @@ alloc_extent(flush_pos_t *flush_pos) } /* if @key is glueable to the item @coord is set to */ -static int -must_insert(const coord_t *coord, const reiser4_key *key) +static int must_insert(const coord_t * coord, const reiser4_key * key) { reiser4_key last; - if (item_id_by_coord(coord) == EXTENT_POINTER_ID && keyeq(append_key_extent(coord, &last), key)) + if (item_id_by_coord(coord) == EXTENT_POINTER_ID + && keyeq(append_key_extent(coord, &last), key)) return 0; return 1; } /* copy extent @copy to the end of @node. It may have to either insert new item after the last one, or append last item, - or modify last unit of last item to have greater width */ + or modify last unit of last item to have greater width */ static int -put_unit_to_end(znode *node, const reiser4_key *key, reiser4_extent *copy_ext) +put_unit_to_end(znode * node, const reiser4_key * key, + reiser4_extent * copy_ext) { int result; coord_t coord; @@ -863,23 +975,32 @@ put_unit_to_end(znode *node, const reise coord_init_last_unit(&coord, node); coord.between = AFTER_UNIT; - flags = COPI_DONT_SHIFT_LEFT | COPI_DONT_SHIFT_RIGHT | COPI_DONT_ALLOCATE; + flags = + COPI_DONT_SHIFT_LEFT | COPI_DONT_SHIFT_RIGHT | COPI_DONT_ALLOCATE; if (must_insert(&coord, key)) { - result = insert_by_coord(&coord, init_new_extent(&data, copy_ext, 1), key, 0 /*lh */ , flags); + result = + insert_by_coord(&coord, init_new_extent(&data, copy_ext, 1), + key, NULL /*lh */ , flags); } else { /* try to glue with last unit */ last_ext = extent_by_coord(&coord); if (state_of_extent(last_ext) && - extent_get_start(last_ext) + extent_get_width(last_ext) == extent_get_start(copy_ext)) { + extent_get_start(last_ext) + extent_get_width(last_ext) == + extent_get_start(copy_ext)) { /* widen last unit of node */ - extent_set_width(last_ext, extent_get_width(last_ext) + extent_get_width(copy_ext)); + extent_set_width(last_ext, + extent_get_width(last_ext) + + extent_get_width(copy_ext)); znode_make_dirty(node); return 0; } /* FIXME: put an assertion here that we can not merge last unit in @node and new unit */ - result = insert_into_item(&coord, 0 /*lh */ , key, init_new_extent(&data, copy_ext, 1), flags); + result = + insert_into_item(&coord, NULL /*lh */ , key, + init_new_extent(&data, copy_ext, 1), + flags); } assert("vs-438", result == 0 || result == -E_NODE_FULL); @@ -887,8 +1008,9 @@ put_unit_to_end(znode *node, const reise } /* @coord is set to extent unit */ -reiser4_internal squeeze_result -squalloc_extent(znode *left, const coord_t *coord, flush_pos_t *flush_pos, reiser4_key *stop_key) +squeeze_result +squalloc_extent(znode * left, const coord_t * coord, flush_pos_t * flush_pos, + reiser4_key * stop_key) { reiser4_extent *ext; __u64 index; @@ -921,9 +1043,12 @@ squalloc_extent(znode *left, const coord /* relocate */ protected_jnodes_init(&jnodes); - result = protect_extent_nodes(flush_pos, oid, index, width, &protected, ext, &jnodes.nodes); + result = + protect_extent_nodes(flush_pos, oid, index, width, + &protected, ext, &jnodes.nodes); if (result) { - warning("vs-1469", "Failed to protect extent. Should not happen\n"); + warning("vs-1469", + "Failed to protect extent. Should not happen\n"); protected_jnodes_done(&jnodes); return result; } @@ -941,11 +1066,16 @@ squalloc_extent(znode *left, const coord block_stage = BLOCK_UNALLOCATED; /* look at previous unit if possible. If it is allocated, make preceder more precise */ - if (coord->unit_pos && (state_of_extent(ext - 1) == ALLOCATED_EXTENT)) - pos_hint(flush_pos)->blk = extent_get_start(ext - 1) + extent_get_width(ext - 1); + if (coord->unit_pos + && (state_of_extent(ext - 1) == ALLOCATED_EXTENT)) + pos_hint(flush_pos)->blk = + extent_get_start(ext - 1) + extent_get_width(ext - + 1); /* allocate new block numbers for protected nodes */ - extent_allocate_blocks(pos_hint(flush_pos), protected, &first_allocated, &allocated, block_stage); + extent_allocate_blocks(pos_hint(flush_pos), protected, + &first_allocated, &allocated, + block_stage); if (allocated != protected) unprotect_extent_nodes(flush_pos, protected - allocated, &jnodes.nodes); @@ -958,9 +1088,15 @@ squalloc_extent(znode *left, const coord int target_block_stage; /* free blocks which were just allocated */ - target_block_stage = (state == ALLOCATED_EXTENT) ? BLOCK_FLUSH_RESERVED : BLOCK_UNALLOCATED; - reiser4_dealloc_blocks(&first_allocated, &allocated, target_block_stage, BA_PERMANENT); - unprotect_extent_nodes(flush_pos, allocated, &jnodes.nodes); + target_block_stage = + (state == + ALLOCATED_EXTENT) ? BLOCK_FLUSH_RESERVED : + BLOCK_UNALLOCATED; + reiser4_dealloc_blocks(&first_allocated, &allocated, + target_block_stage, + BA_PERMANENT); + unprotect_extent_nodes(flush_pos, allocated, + &jnodes.nodes); /* rewind the preceder. */ flush_pos->preceder.blk = first_allocated; @@ -972,14 +1108,18 @@ squalloc_extent(znode *left, const coord if (state == ALLOCATED_EXTENT) { /* free nodes which were relocated */ - reiser4_dealloc_blocks(&start, &allocated, BLOCK_ALLOCATED, BA_DEFER); + reiser4_dealloc_blocks(&start, &allocated, + BLOCK_ALLOCATED, BA_DEFER); } /* assign new block numbers to protected nodes */ - assign_real_blocknrs(flush_pos, first_allocated, allocated, state, &jnodes.nodes); + assign_real_blocknrs(flush_pos, first_allocated, allocated, + state, &jnodes.nodes); protected_jnodes_done(&jnodes); - set_key_offset(&key, get_key_offset(&key) + (allocated << current_blocksize_bits)); + set_key_offset(&key, + get_key_offset(&key) + + (allocated << current_blocksize_bits)); } else { /* overwrite: try to copy unit as it is to left neighbor and make all first not flushprepped nodes overwrite nodes */ @@ -989,14 +1129,15 @@ squalloc_extent(znode *left, const coord return SQUEEZE_TARGET_FULL; } mark_jnodes_overwrite(flush_pos, oid, index, width); - set_key_offset(&key, get_key_offset(&key) + (width << current_blocksize_bits)); + set_key_offset(&key, + get_key_offset(&key) + + (width << current_blocksize_bits)); } *stop_key = key; return SQUEEZE_CONTINUE; } -reiser4_internal int -key_by_offset_extent(struct inode *inode, loff_t off, reiser4_key *key) +int key_by_offset_extent(struct inode *inode, loff_t off, reiser4_key * key) { return key_by_inode_and_offset_common(inode, off, key); } diff -puN fs/reiser4/plugin/item/extent.h~reiser4-big-update fs/reiser4/plugin/item/extent.h --- devel/fs/reiser4/plugin/item/extent.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/extent.h 2005-09-15 19:51:08.000000000 -0700 @@ -32,9 +32,9 @@ typedef enum { typedef struct { reiser4_block_nr pos_in_unit; - reiser4_block_nr width; /* width of current unit */ - pos_in_node_t nr_units; /* number of units */ - int ext_offset; /* offset from the beginning of zdata() */ + reiser4_block_nr width; /* width of current unit */ + pos_in_node_t nr_units; /* number of units */ + int ext_offset; /* offset from the beginning of zdata() */ unsigned long expected_page; #if REISER4_DEBUG reiser4_extent extent; @@ -42,14 +42,12 @@ typedef struct { } extent_coord_extension_t; /* macros to set/get fields of on-disk extent */ -static inline reiser4_block_nr -extent_get_start(const reiser4_extent * ext) +static inline reiser4_block_nr extent_get_start(const reiser4_extent * ext) { return dblock_to_cpu(&ext->start); } -static inline reiser4_block_nr -extent_get_width(const reiser4_extent * ext) +static inline reiser4_block_nr extent_get_width(const reiser4_extent * ext) { return dblock_to_cpu(&ext->width); } @@ -59,19 +57,21 @@ extern __u64 reiser4_current_block_count static inline void extent_set_start(reiser4_extent * ext, reiser4_block_nr start) { - cassert(sizeof (ext->start) == 8); - assert("nikita-2510", ergo(start > 1, start < reiser4_current_block_count())); + cassert(sizeof(ext->start) == 8); + assert("nikita-2510", + ergo(start > 1, start < reiser4_current_block_count())); cpu_to_dblock(start, &ext->start); } static inline void -extent_set_width(reiser4_extent *ext, reiser4_block_nr width) +extent_set_width(reiser4_extent * ext, reiser4_block_nr width) { - cassert(sizeof (ext->width) == 8); + cassert(sizeof(ext->width) == 8); cpu_to_dblock(width, &ext->width); assert("nikita-2511", ergo(extent_get_start(ext) > 1, - extent_get_start(ext) + width <= reiser4_current_block_count())); + extent_get_start(ext) + width <= + reiser4_current_block_count())); } #define extent_item(coord) \ @@ -97,7 +97,8 @@ struct carry_kill_data; /* plugin->u.item.b.* */ reiser4_key *max_key_inside_extent(const coord_t *, reiser4_key *); -int can_contain_key_extent(const coord_t * coord, const reiser4_key * key, const reiser4_item_data *); +int can_contain_key_extent(const coord_t * coord, const reiser4_key * key, + const reiser4_item_data *); int mergeable_extent(const coord_t * p1, const coord_t * p2); pos_in_node_t nr_units_extent(const coord_t *); lookup_result lookup_extent(const reiser4_key *, lookup_bias, coord_t *); @@ -105,21 +106,26 @@ void init_coord_extent(coord_t *); int init_extent(coord_t *, reiser4_item_data *); int paste_extent(coord_t *, reiser4_item_data *, carry_plugin_info *); int can_shift_extent(unsigned free_space, - coord_t * source, znode * target, shift_direction, unsigned *size, unsigned want); -void copy_units_extent(coord_t * target, - coord_t * source, - unsigned from, unsigned count, shift_direction where_is_free_space, unsigned free_space); -int kill_hook_extent(const coord_t *, pos_in_node_t from, pos_in_node_t count, struct carry_kill_data *); + coord_t * source, znode * target, shift_direction, + unsigned *size, unsigned want); +void copy_units_extent(coord_t * target, coord_t * source, unsigned from, + unsigned count, shift_direction where_is_free_space, + unsigned free_space); +int kill_hook_extent(const coord_t *, pos_in_node_t from, pos_in_node_t count, + struct carry_kill_data *); int create_hook_extent(const coord_t * coord, void *arg); -int cut_units_extent(coord_t *coord, pos_in_node_t from, pos_in_node_t to, - struct carry_cut_data *, reiser4_key *smallest_removed, reiser4_key *new_first); -int kill_units_extent(coord_t *coord, pos_in_node_t from, pos_in_node_t to, - struct carry_kill_data *, reiser4_key *smallest_removed, reiser4_key *new_first); +int cut_units_extent(coord_t * coord, pos_in_node_t from, pos_in_node_t to, + struct carry_cut_data *, reiser4_key * smallest_removed, + reiser4_key * new_first); +int kill_units_extent(coord_t * coord, pos_in_node_t from, pos_in_node_t to, + struct carry_kill_data *, reiser4_key * smallest_removed, + reiser4_key * new_first); reiser4_key *unit_key_extent(const coord_t *, reiser4_key *); reiser4_key *max_unit_key_extent(const coord_t *, reiser4_key *); void print_extent(const char *, coord_t *); int utmost_child_extent(const coord_t * coord, sideof side, jnode ** child); -int utmost_child_real_block_extent(const coord_t * coord, sideof side, reiser4_block_nr * block); +int utmost_child_real_block_extent(const coord_t * coord, sideof side, + reiser4_block_nr * block); void item_stat_extent(const coord_t * coord, void *vp); int check_extent(const coord_t * coord, const char **error); @@ -131,34 +137,82 @@ void readpages_extent(void *, struct add int capture_extent(reiser4_key *, uf_coord_t *, struct page *, write_mode_t); reiser4_key *append_key_extent(const coord_t *, reiser4_key *); void init_coord_extension_extent(uf_coord_t *, loff_t offset); -int get_block_address_extent(const coord_t *, sector_t block, struct buffer_head *); - +int get_block_address_extent(const coord_t *, sector_t block, + sector_t * result); /* these are used in flush.c FIXME-VS: should they be somewhere in item_plugin? */ int allocate_extent_item_in_place(coord_t *, lock_handle *, flush_pos_t * pos); -int allocate_and_copy_extent(znode * left, coord_t * right, flush_pos_t * pos, reiser4_key * stop_key); +int allocate_and_copy_extent(znode * left, coord_t * right, flush_pos_t * pos, + reiser4_key * stop_key); int extent_is_unallocated(const coord_t * item); /* True if this extent is unallocated (i.e., not a hole, not allocated). */ __u64 extent_unit_index(const coord_t * item); /* Block offset of this unit. */ __u64 extent_unit_width(const coord_t * item); /* Number of blocks in this unit. */ /* plugin->u.item.f. */ -int scan_extent (flush_scan * scan); +int scan_extent(flush_scan * scan); extern int key_by_offset_extent(struct inode *, loff_t, reiser4_key *); -reiser4_item_data *init_new_extent(reiser4_item_data *data, void *ext_unit, int nr_extents); -reiser4_block_nr extent_size(const coord_t *coord, pos_in_node_t nr); -extent_state state_of_extent(reiser4_extent *ext); -void set_extent(reiser4_extent *ext, reiser4_block_nr start, reiser4_block_nr width); -int replace_extent(coord_t *un_extent, lock_handle *lh, - reiser4_key *key, reiser4_item_data *data, const reiser4_extent *new_ext, unsigned flags, int); +reiser4_item_data *init_new_extent(reiser4_item_data * data, void *ext_unit, + int nr_extents); +reiser4_block_nr extent_size(const coord_t * coord, pos_in_node_t nr); +extent_state state_of_extent(reiser4_extent * ext); +void set_extent(reiser4_extent * ext, reiser4_block_nr start, + reiser4_block_nr width); + +#include "../../coord.h" +#include "../../lock.h" +#include "../../tap.h" + +struct replace_handle { + /* these are to be set before calling replace_extent */ + coord_t *coord; + lock_handle *lh; + reiser4_key key; + reiser4_key *pkey; + reiser4_extent overwrite; + reiser4_extent new_extents[2]; + int nr_new_extents; + unsigned flags; + + /* these are used by replace_extent */ + reiser4_item_data item; + coord_t coord_after; + lock_handle lh_after; + tap_t watch; + reiser4_key paste_key; +#if REISER4_DEBUG + reiser4_extent orig_ext; + reiser4_key tmp; +#endif +}; + +/* this structure is kmalloced before calling make_extent to avoid excessive + stack consumption on plug_hole->replace_extent */ +struct make_extent_handle { + uf_coord_t *uf_coord; + reiser4_block_nr blocknr; + int created; + struct inode *inode; + union { + struct { + } append; + struct replace_handle replace; + } u; +}; + +int replace_extent(struct replace_handle *, int return_inserted_position); lock_handle *znode_lh(znode *); /* the reiser4 repacker support */ struct repacker_cursor; -extern int process_extent_backward_for_repacking (tap_t *, struct repacker_cursor *); -extern int mark_extent_for_repacking (tap_t *, int); +extern int process_extent_backward_for_repacking(tap_t *, + struct repacker_cursor *); +extern int mark_extent_for_repacking(tap_t *, int); + +#define coord_by_uf_coord(uf_coord) (&((uf_coord)->coord)) +#define ext_coord_by_uf_coord(uf_coord) (&((uf_coord)->extension.extent)) /* __REISER4_EXTENT_H__ */ #endif diff -puN fs/reiser4/plugin/item/extent_item_ops.c~reiser4-big-update fs/reiser4/plugin/item/extent_item_ops.c --- devel/fs/reiser4/plugin/item/extent_item_ops.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/extent_item_ops.c 2005-09-15 19:51:08.000000000 -0700 @@ -2,15 +2,14 @@ #include "item.h" #include "../../inode.h" -#include "../../tree_walk.h" /* check_sibling_list() */ +#include "../../tree_walk.h" /* check_sibling_list() */ #include "../../page_cache.h" #include "../../carry.h" #include /* item_plugin->b.max_key_inside */ -reiser4_internal reiser4_key * -max_key_inside_extent(const coord_t *coord, reiser4_key *key) +reiser4_key *max_key_inside_extent(const coord_t * coord, reiser4_key * key) { item_key_by_coord(coord, key); set_key_offset(key, get_key_offset(max_key())); @@ -19,8 +18,9 @@ max_key_inside_extent(const coord_t *coo /* item_plugin->b.can_contain_key this checks whether @key of @data is matching to position set by @coord */ -reiser4_internal int -can_contain_key_extent(const coord_t *coord, const reiser4_key *key, const reiser4_item_data *data) +int +can_contain_key_extent(const coord_t * coord, const reiser4_key * key, + const reiser4_item_data * data) { reiser4_key item_key; @@ -30,7 +30,8 @@ can_contain_key_extent(const coord_t *co item_key_by_coord(coord, &item_key); if (get_key_locality(key) != get_key_locality(&item_key) || get_key_objectid(key) != get_key_objectid(&item_key) || - get_key_ordering(key) != get_key_ordering(&item_key)) return 0; + get_key_ordering(key) != get_key_ordering(&item_key)) + return 0; return 1; } @@ -38,8 +39,7 @@ can_contain_key_extent(const coord_t *co /* item_plugin->b.mergeable first item is of extent type */ /* Audited by: green(2002.06.13) */ -reiser4_internal int -mergeable_extent(const coord_t *p1, const coord_t *p2) +int mergeable_extent(const coord_t * p1, const coord_t * p2) { reiser4_key key1, key2; @@ -56,23 +56,25 @@ mergeable_extent(const coord_t *p1, cons get_key_ordering(&key1) != get_key_ordering(&key2) || get_key_type(&key1) != get_key_type(&key2)) return 0; - if (get_key_offset(&key1) + extent_size(p1, nr_units_extent(p1)) != get_key_offset(&key2)) + if (get_key_offset(&key1) + extent_size(p1, nr_units_extent(p1)) != + get_key_offset(&key2)) return 0; return 1; } /* item_plugin->b.nr_units */ -reiser4_internal pos_in_node_t -nr_units_extent(const coord_t *coord) +pos_in_node_t nr_units_extent(const coord_t * coord) { /* length of extent item has to be multiple of extent size */ - assert("vs-1424", (item_length_by_coord(coord) % sizeof (reiser4_extent)) == 0); - return item_length_by_coord(coord) / sizeof (reiser4_extent); + assert("vs-1424", + (item_length_by_coord(coord) % sizeof(reiser4_extent)) == 0); + return item_length_by_coord(coord) / sizeof(reiser4_extent); } /* item_plugin->b.lookup */ -reiser4_internal lookup_result -lookup_extent(const reiser4_key *key, lookup_bias bias UNUSED_ARG, coord_t *coord) +lookup_result +lookup_extent(const reiser4_key * key, lookup_bias bias UNUSED_ARG, + coord_t * coord) { /* znode and item_pos are set to an extent item to look through */ @@ -90,7 +92,7 @@ lookup_extent(const reiser4_key *key, lo assert("vs-414", keygt(key, &item_key)); assert("umka-99945", - !keygt(key, max_key_inside_extent(coord, &item_key))); + !keygt(key, max_key_inside_extent(coord, &item_key))); ext = extent_item(coord); assert("vs-1350", (char *)ext == (zdata(coord->node) + coord->offset)); @@ -125,8 +127,9 @@ lookup_extent(const reiser4_key *key, lo @coord->in_item.unit_pos. It must fit into that free space. @coord must be set between units. */ -reiser4_internal int -paste_extent(coord_t *coord, reiser4_item_data *data, carry_plugin_info *info UNUSED_ARG) +int +paste_extent(coord_t * coord, reiser4_item_data * data, + carry_plugin_info * info UNUSED_ARG) { unsigned old_nr_units; reiser4_extent *ext; @@ -134,14 +137,16 @@ paste_extent(coord_t *coord, reiser4_ite ext = extent_item(coord); item_length = item_length_by_coord(coord); - old_nr_units = (item_length - data->length) / sizeof (reiser4_extent); + old_nr_units = (item_length - data->length) / sizeof(reiser4_extent); /* this is also used to copy extent into newly created item, so old_nr_units could be 0 */ assert("vs-260", item_length >= data->length); /* make sure that coord is set properly */ - assert("vs-35", ((!coord_is_existing_unit(coord)) || (!old_nr_units && !coord->unit_pos))); + assert("vs-35", + ((!coord_is_existing_unit(coord)) + || (!old_nr_units && !coord->unit_pos))); /* first unit to be moved */ switch (coord->between) { @@ -158,47 +163,53 @@ paste_extent(coord_t *coord, reiser4_ite } /* prepare space for new units */ - memmove(ext + coord->unit_pos + data->length / sizeof (reiser4_extent), - ext + coord->unit_pos, (old_nr_units - coord->unit_pos) * sizeof (reiser4_extent)); + memmove(ext + coord->unit_pos + data->length / sizeof(reiser4_extent), + ext + coord->unit_pos, + (old_nr_units - coord->unit_pos) * sizeof(reiser4_extent)); /* copy new data from kernel space */ assert("vs-556", data->user == 0); - memcpy(ext + coord->unit_pos, data->data, (unsigned) data->length); + memcpy(ext + coord->unit_pos, data->data, (unsigned)data->length); /* after paste @coord is set to first of pasted units */ assert("vs-332", coord_is_existing_unit(coord)); - assert("vs-333", !memcmp(data->data, extent_by_coord(coord), (unsigned) data->length)); + assert("vs-333", + !memcmp(data->data, extent_by_coord(coord), + (unsigned)data->length)); return 0; } /* item_plugin->b.can_shift */ -reiser4_internal int -can_shift_extent(unsigned free_space, coord_t *source, - znode *target UNUSED_ARG, shift_direction pend UNUSED_ARG, unsigned *size, unsigned want) +int +can_shift_extent(unsigned free_space, coord_t * source, + znode * target UNUSED_ARG, shift_direction pend UNUSED_ARG, + unsigned *size, unsigned want) { *size = item_length_by_coord(source); if (*size > free_space) /* never split a unit of extent item */ - *size = free_space - free_space % sizeof (reiser4_extent); + *size = free_space - free_space % sizeof(reiser4_extent); /* we can shift *size bytes, calculate how many do we want to shift */ - if (*size > want * sizeof (reiser4_extent)) - *size = want * sizeof (reiser4_extent); + if (*size > want * sizeof(reiser4_extent)) + *size = want * sizeof(reiser4_extent); - if (*size % sizeof (reiser4_extent) != 0) - impossible("vs-119", "Wrong extent size: %i %zd", *size, sizeof (reiser4_extent)); - return *size / sizeof (reiser4_extent); + if (*size % sizeof(reiser4_extent) != 0) + impossible("vs-119", "Wrong extent size: %i %zd", *size, + sizeof(reiser4_extent)); + return *size / sizeof(reiser4_extent); } /* item_plugin->b.copy_units */ -reiser4_internal void -copy_units_extent(coord_t *target, coord_t *source, - unsigned from, unsigned count, shift_direction where_is_free_space, unsigned free_space) +void +copy_units_extent(coord_t * target, coord_t * source, + unsigned from, unsigned count, + shift_direction where_is_free_space, unsigned free_space) { char *from_ext, *to_ext; - assert("vs-217", free_space == count * sizeof (reiser4_extent)); + assert("vs-217", free_space == count * sizeof(reiser4_extent)); from_ext = item_body_by_coord(source); to_ext = item_body_by_coord(target); @@ -210,13 +221,15 @@ copy_units_extent(coord_t *target, coord header by shifting code, hence nr_units_extent() will return "new" number of units---one we obtain after copying units. - */ - to_ext += (nr_units_extent(target) - count) * sizeof (reiser4_extent); + */ + to_ext += + (nr_units_extent(target) - count) * sizeof(reiser4_extent); } else { reiser4_key key; coord_t coord; - assert("vs-216", from + count == coord_last_unit_pos(source) + 1); + assert("vs-216", + from + count == coord_last_unit_pos(source) + 1); from_ext += item_length_by_coord(source) - free_space; @@ -226,7 +239,8 @@ copy_units_extent(coord_t *target, coord coord.unit_pos = from; unit_key_extent(&coord, &key); - node_plugin_by_node(target->node)->update_item_key(target, &key, 0/*info */); + node_plugin_by_node(target->node)->update_item_key(target, &key, + NULL /*info */); } memcpy(to_ext, from_ext, free_space); @@ -234,8 +248,7 @@ copy_units_extent(coord_t *target, coord /* item_plugin->b.create_hook @arg is znode of leaf node for which we need to update right delimiting key */ -reiser4_internal int -create_hook_extent(const coord_t *coord, void *arg) +int create_hook_extent(const coord_t * coord, void *arg) { coord_t *child_coord; znode *node; @@ -269,10 +282,10 @@ create_hook_extent(const coord_t *coord, assert("nikita-3282", check_sibling_list(node)); /* break sibling links */ if (ZF_ISSET(node, JNODE_RIGHT_CONNECTED) && node->right) { - ON_DEBUG( - node->right->left_version = atomic_inc_return(&delim_key_version); - node->right_version = atomic_inc_return(&delim_key_version); - ); + ON_DEBUG(node->right->left_version = + atomic_inc_return(&delim_key_version); + node->right_version = + atomic_inc_return(&delim_key_version);); node->right->left = NULL; node->right = NULL; @@ -283,7 +296,6 @@ create_hook_extent(const coord_t *coord, return 0; } - #define ITEM_TAIL_KILLED 0 #define ITEM_HEAD_KILLED 1 #define ITEM_KILLED 2 @@ -291,47 +303,59 @@ create_hook_extent(const coord_t *coord, /* item_plugin->b.kill_hook this is called when @count units starting from @from-th one are going to be removed */ -reiser4_internal int -kill_hook_extent(const coord_t *coord, pos_in_node_t from, pos_in_node_t count, struct carry_kill_data *kdata) +int +kill_hook_extent(const coord_t * coord, pos_in_node_t from, pos_in_node_t count, + struct carry_kill_data *kdata) { reiser4_extent *ext; reiser4_block_nr start, length; - reiser4_key min_item_key, max_item_key; - reiser4_key from_key, to_key; const reiser4_key *pfrom_key, *pto_key; struct inode *inode; reiser4_tree *tree; pgoff_t from_off, to_off, offset, skip; int retval; - assert ("zam-811", znode_is_write_locked(coord->node)); + /* these are located in memory kmalloc-ed by kill_node_content */ + reiser4_key *min_item_key, *max_item_key, *from_key, *to_key, *key; + coord_t *dup, *next; + + assert("zam-811", znode_is_write_locked(coord->node)); assert("nikita-3315", kdata != NULL); + assert("vs-34", kdata->buf != NULL); - item_key_by_coord(coord, &min_item_key); - max_item_key_by_coord(coord, &max_item_key); + /* map structures to kdata->buf */ + min_item_key = (reiser4_key *) (kdata->buf); + max_item_key = min_item_key + 1; + from_key = max_item_key + 1; + to_key = from_key + 1; + key = to_key + 1; + dup = (coord_t *) (key + 1); + next = dup + 1; + + item_key_by_coord(coord, min_item_key); + max_item_key_by_coord(coord, max_item_key); if (kdata->params.from_key) { pfrom_key = kdata->params.from_key; pto_key = kdata->params.to_key; } else { - coord_t dup; - assert("vs-1549", from == coord->unit_pos); - unit_key_by_coord(coord, &from_key); - pfrom_key = &from_key; + unit_key_by_coord(coord, from_key); + pfrom_key = from_key; - coord_dup(&dup, coord); - dup.unit_pos = from + count - 1; - max_unit_key_by_coord(&dup, &to_key); - pto_key = &to_key; + coord_dup(dup, coord); + dup->unit_pos = from + count - 1; + max_unit_key_by_coord(dup, to_key); + pto_key = to_key; } - if (!keylt(pto_key, &max_item_key)) { - if (!keygt(pfrom_key, &min_item_key)) { + if (!keylt(pto_key, max_item_key)) { + if (!keygt(pfrom_key, min_item_key)) { znode *left, *right; /* item is to be removed completely */ - assert("nikita-3316", kdata->left != NULL && kdata->right != NULL); + assert("nikita-3316", kdata->left != NULL + && kdata->right != NULL); left = kdata->left->node; right = kdata->right->node; @@ -355,43 +379,55 @@ kill_hook_extent(const coord_t *coord, p if (left) { /* update right delimiting key of left * neighbor of extent item */ - coord_t next; - reiser4_key key; + /*coord_t next; + reiser4_key key; */ - coord_dup(&next, coord); + coord_dup(next, coord); - if (coord_next_item(&next)) - key = *znode_get_rd_key(coord->node); + if (coord_next_item(next)) + *key = *znode_get_rd_key(coord->node); else - item_key_by_coord(&next, &key); - znode_set_rd_key(left, &key); + item_key_by_coord(next, key); + znode_set_rd_key(left, key); } - WUNLOCK_DK(tree); + WUNLOCK_DK(tree); WUNLOCK_TREE(tree); - from_off = get_key_offset(&min_item_key) >> PAGE_CACHE_SHIFT; - to_off = (get_key_offset(&max_item_key) + 1) >> PAGE_CACHE_SHIFT; + from_off = + get_key_offset(min_item_key) >> PAGE_CACHE_SHIFT; + to_off = + (get_key_offset(max_item_key) + + 1) >> PAGE_CACHE_SHIFT; retval = ITEM_KILLED; } else { /* tail of item is to be removed */ - from_off = (get_key_offset(pfrom_key) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - to_off = (get_key_offset(&max_item_key) + 1) >> PAGE_CACHE_SHIFT; + from_off = + (get_key_offset(pfrom_key) + PAGE_CACHE_SIZE - + 1) >> PAGE_CACHE_SHIFT; + to_off = + (get_key_offset(max_item_key) + + 1) >> PAGE_CACHE_SHIFT; retval = ITEM_TAIL_KILLED; } } else { /* head of item is to be removed */ - assert("vs-1571", keyeq(pfrom_key, &min_item_key)); - assert("vs-1572", (get_key_offset(pfrom_key) & (PAGE_CACHE_SIZE - 1)) == 0); - assert("vs-1573", ((get_key_offset(pto_key) + 1) & (PAGE_CACHE_SIZE - 1)) == 0); + assert("vs-1571", keyeq(pfrom_key, min_item_key)); + assert("vs-1572", + (get_key_offset(pfrom_key) & (PAGE_CACHE_SIZE - 1)) == + 0); + assert("vs-1573", + ((get_key_offset(pto_key) + 1) & (PAGE_CACHE_SIZE - + 1)) == 0); if (kdata->left->node) { /* update right delimiting key of left neighbor of extent item */ - reiser4_key key; + /*reiser4_key key; */ - key = *pto_key; - set_key_offset(&key, get_key_offset(pto_key) + 1); + *key = *pto_key; + set_key_offset(key, get_key_offset(pto_key) + 1); - UNDER_RW_VOID(dk, current_tree, write, znode_set_rd_key(kdata->left->node, &key)); + UNDER_RW_VOID(dk, current_tree, write, + znode_set_rd_key(kdata->left->node, key)); } from_off = get_key_offset(pfrom_key) >> PAGE_CACHE_SHIFT; @@ -403,12 +439,14 @@ kill_hook_extent(const coord_t *coord, p assert("vs-1545", inode != NULL); if (inode != NULL) /* take care of pages and jnodes corresponding to part of item being killed */ - reiser4_invalidate_pages( - inode->i_mapping, from_off, to_off - from_off, - kdata->params.truncate); + reiser4_invalidate_pages(inode->i_mapping, from_off, + to_off - from_off, + kdata->params.truncate); ext = extent_item(coord) + from; - offset = (get_key_offset(&min_item_key) + extent_size(coord, from)) >> PAGE_CACHE_SHIFT; + offset = + (get_key_offset(min_item_key) + + extent_size(coord, from)) >> PAGE_CACHE_SHIFT; assert("vs-1551", from_off >= offset); assert("vs-1552", from_off - offset <= extent_get_width(ext)); @@ -420,7 +458,7 @@ kill_hook_extent(const coord_t *coord, p if (state_of_extent(ext) == HOLE_EXTENT) { skip = 0; offset += length; - ext ++; + ext++; continue; } @@ -428,16 +466,15 @@ kill_hook_extent(const coord_t *coord, p length = to_off - offset; } - DQUOT_FREE_BLOCK(inode, length); + DQUOT_FREE_BLOCK_NODIRTY(inode, length); if (state_of_extent(ext) == UNALLOCATED_EXTENT) { /* some jnodes corresponding to this unallocated extent */ - fake_allocated2free(length, - 0 /* unformatted */); + fake_allocated2free(length, 0 /* unformatted */ ); skip = 0; offset += length; - ext ++; + ext++; continue; } @@ -448,31 +485,36 @@ kill_hook_extent(const coord_t *coord, p /* BA_DEFER bit parameter is turned on because blocks which get freed are not safe to be freed immediately */ - reiser4_dealloc_blocks(&start, &length, 0 /* not used */, - BA_DEFER/* unformatted with defer */); + reiser4_dealloc_blocks(&start, &length, + 0 /* not used */ , + BA_DEFER + /* unformatted with defer */ ); } skip = 0; offset += length; - ext ++; + ext++; } return retval; } /* item_plugin->b.kill_units */ -reiser4_internal int -kill_units_extent(coord_t *coord, pos_in_node_t from, pos_in_node_t to, struct carry_kill_data *kdata, - reiser4_key *smallest_removed, reiser4_key *new_first) +int +kill_units_extent(coord_t * coord, pos_in_node_t from, pos_in_node_t to, + struct carry_kill_data *kdata, reiser4_key * smallest_removed, + reiser4_key * new_first) { reiser4_extent *ext; reiser4_key item_key; - pos_in_node_t count; + pos_in_node_t count; reiser4_key from_key, to_key; const reiser4_key *pfrom_key, *pto_key; loff_t off; int result; - assert("vs-1541", ((kdata->params.from_key == NULL && kdata->params.to_key == NULL) || - (kdata->params.from_key != NULL && kdata->params.to_key != NULL))); + assert("vs-1541", + ((kdata->params.from_key == NULL && kdata->params.to_key == NULL) + || (kdata->params.from_key != NULL + && kdata->params.to_key != NULL))); if (kdata->params.from_key) { pfrom_key = kdata->params.from_key; @@ -516,21 +558,29 @@ kill_units_extent(coord_t *coord, pos_in if (new_first) { /* item head is cut. Item key will change. This new key is calculated here */ - assert("vs-1556", (get_key_offset(pto_key) & (PAGE_CACHE_SIZE - 1)) == (PAGE_CACHE_SIZE - 1)); + assert("vs-1556", + (get_key_offset(pto_key) & (PAGE_CACHE_SIZE - 1)) == + (PAGE_CACHE_SIZE - 1)); *new_first = *pto_key; set_key_offset(new_first, get_key_offset(new_first) + 1); } count = to - from + 1; - result = kill_hook_extent(coord, from, count, kdata); + result = kill_hook_extent(coord, from, count, kdata); if (result == ITEM_TAIL_KILLED) { - assert("vs-1553", get_key_offset(pfrom_key) >= get_key_offset(&item_key) + extent_size(coord, from)); - off = get_key_offset(pfrom_key) - (get_key_offset(&item_key) + extent_size(coord, from)); + assert("vs-1553", + get_key_offset(pfrom_key) >= + get_key_offset(&item_key) + extent_size(coord, from)); + off = + get_key_offset(pfrom_key) - (get_key_offset(&item_key) + + extent_size(coord, from)); if (off) { /* unit @from is to be cut partially. Its width decreases */ ext = extent_item(coord) + from; - extent_set_width(ext, (off + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT); - count --; + extent_set_width(ext, + (off + PAGE_CACHE_SIZE - + 1) >> PAGE_CACHE_SHIFT); + count--; } } else { __u64 max_to_offset; @@ -538,12 +588,19 @@ kill_units_extent(coord_t *coord, pos_in assert("vs-1575", result == ITEM_HEAD_KILLED); assert("", from == 0); - assert("", ((get_key_offset(pto_key) + 1) & (PAGE_CACHE_SIZE - 1)) == 0); - assert("", get_key_offset(pto_key) + 1 > get_key_offset(&item_key) + extent_size(coord, to)); - max_to_offset = get_key_offset(&item_key) + extent_size(coord, to + 1) - 1; + assert("", + ((get_key_offset(pto_key) + 1) & (PAGE_CACHE_SIZE - + 1)) == 0); + assert("", + get_key_offset(pto_key) + 1 > + get_key_offset(&item_key) + extent_size(coord, to)); + max_to_offset = + get_key_offset(&item_key) + extent_size(coord, to + 1) - 1; assert("", get_key_offset(pto_key) <= max_to_offset); - rest = (max_to_offset - get_key_offset(pto_key)) >> PAGE_CACHE_SHIFT; + rest = + (max_to_offset - + get_key_offset(pto_key)) >> PAGE_CACHE_SHIFT; if (rest) { /* unit @to is to be cut partially */ ext = extent_item(coord) + to; @@ -551,10 +608,13 @@ kill_units_extent(coord_t *coord, pos_in assert("", extent_get_width(ext) > rest); if (state_of_extent(ext) == ALLOCATED_EXTENT) - extent_set_start(ext, extent_get_start(ext) + (extent_get_width(ext) - rest)); + extent_set_start(ext, + extent_get_start(ext) + + (extent_get_width(ext) - + rest)); extent_set_width(ext, rest); - count --; + count--; } } return count * sizeof(reiser4_extent); @@ -562,19 +622,22 @@ kill_units_extent(coord_t *coord, pos_in /* item_plugin->b.cut_units this is too similar to kill_units_extent */ -reiser4_internal int -cut_units_extent(coord_t *coord, pos_in_node_t from, pos_in_node_t to, struct carry_cut_data *cdata, - reiser4_key *smallest_removed, reiser4_key *new_first) +int +cut_units_extent(coord_t * coord, pos_in_node_t from, pos_in_node_t to, + struct carry_cut_data *cdata, reiser4_key * smallest_removed, + reiser4_key * new_first) { reiser4_extent *ext; reiser4_key item_key; - pos_in_node_t count; + pos_in_node_t count; reiser4_key from_key, to_key; const reiser4_key *pfrom_key, *pto_key; loff_t off; - assert("vs-1541", ((cdata->params.from_key == NULL && cdata->params.to_key == NULL) || - (cdata->params.from_key != NULL && cdata->params.to_key != NULL))); + assert("vs-1541", + ((cdata->params.from_key == NULL && cdata->params.to_key == NULL) + || (cdata->params.from_key != NULL + && cdata->params.to_key != NULL))); if (cdata->params.from_key) { pfrom_key = cdata->params.from_key; @@ -594,8 +657,11 @@ cut_units_extent(coord_t *coord, pos_in_ pto_key = &to_key; } - assert("vs-1555", (get_key_offset(pfrom_key) & (PAGE_CACHE_SIZE - 1)) == 0); - assert("vs-1556", (get_key_offset(pto_key) & (PAGE_CACHE_SIZE - 1)) == (PAGE_CACHE_SIZE - 1)); + assert("vs-1555", + (get_key_offset(pfrom_key) & (PAGE_CACHE_SIZE - 1)) == 0); + assert("vs-1556", + (get_key_offset(pto_key) & (PAGE_CACHE_SIZE - 1)) == + (PAGE_CACHE_SIZE - 1)); item_key_by_coord(coord, &item_key); @@ -603,10 +669,17 @@ cut_units_extent(coord_t *coord, pos_in_ { reiser4_key max_item_key; - assert("vs-1584", get_key_locality(pfrom_key) == get_key_locality(&item_key)); - assert("vs-1585", get_key_type(pfrom_key) == get_key_type(&item_key)); - assert("vs-1586", get_key_objectid(pfrom_key) == get_key_objectid(&item_key)); - assert("vs-1587", get_key_ordering(pfrom_key) == get_key_ordering(&item_key)); + assert("vs-1584", + get_key_locality(pfrom_key) == + get_key_locality(&item_key)); + assert("vs-1585", + get_key_type(pfrom_key) == get_key_type(&item_key)); + assert("vs-1586", + get_key_objectid(pfrom_key) == + get_key_objectid(&item_key)); + assert("vs-1587", + get_key_ordering(pfrom_key) == + get_key_ordering(&item_key)); max_item_key_by_coord(coord, &max_item_key); @@ -633,52 +706,65 @@ cut_units_extent(coord_t *coord, pos_in_ count = to - from + 1; - assert("vs-1553", get_key_offset(pfrom_key) >= get_key_offset(&item_key) + extent_size(coord, from)); - off = get_key_offset(pfrom_key) - (get_key_offset(&item_key) + extent_size(coord, from)); + assert("vs-1553", + get_key_offset(pfrom_key) >= + get_key_offset(&item_key) + extent_size(coord, from)); + off = + get_key_offset(pfrom_key) - (get_key_offset(&item_key) + + extent_size(coord, from)); if (off) { /* tail of unit @from is to be cut partially. Its width decreases */ assert("vs-1582", new_first == NULL); ext = extent_item(coord) + from; extent_set_width(ext, off >> PAGE_CACHE_SHIFT); - count --; + count--; } - assert("vs-1554", get_key_offset(pto_key) <= get_key_offset(&item_key) + extent_size(coord, to + 1) - 1); - off = (get_key_offset(&item_key) + extent_size(coord, to + 1) - 1) - get_key_offset(pto_key); + assert("vs-1554", + get_key_offset(pto_key) <= + get_key_offset(&item_key) + extent_size(coord, to + 1) - 1); + off = + (get_key_offset(&item_key) + extent_size(coord, to + 1) - 1) - + get_key_offset(pto_key); if (off) { /* @to_key is smaller than max key of unit @to. Unit @to will not be removed. It gets start increased and width decreased. */ assert("vs-1583", (off & (PAGE_CACHE_SIZE - 1)) == 0); ext = extent_item(coord) + to; if (state_of_extent(ext) == ALLOCATED_EXTENT) - extent_set_start(ext, extent_get_start(ext) + (extent_get_width(ext) - (off >> PAGE_CACHE_SHIFT))); + extent_set_start(ext, + extent_get_start(ext) + + (extent_get_width(ext) - + (off >> PAGE_CACHE_SHIFT))); extent_set_width(ext, (off >> PAGE_CACHE_SHIFT)); - count --; + count--; } return count * sizeof(reiser4_extent); } /* item_plugin->b.unit_key */ -reiser4_internal reiser4_key * -unit_key_extent(const coord_t *coord, reiser4_key *key) +reiser4_key *unit_key_extent(const coord_t * coord, reiser4_key * key) { assert("vs-300", coord_is_existing_unit(coord)); item_key_by_coord(coord, key); - set_key_offset(key, (get_key_offset(key) + extent_size(coord, coord->unit_pos))); + set_key_offset(key, + (get_key_offset(key) + + extent_size(coord, coord->unit_pos))); return key; } /* item_plugin->b.max_unit_key */ -reiser4_internal reiser4_key * -max_unit_key_extent(const coord_t *coord, reiser4_key *key) +reiser4_key *max_unit_key_extent(const coord_t * coord, reiser4_key * key) { assert("vs-300", coord_is_existing_unit(coord)); item_key_by_coord(coord, key); - set_key_offset(key, (get_key_offset(key) + extent_size(coord, coord->unit_pos + 1) - 1)); + set_key_offset(key, + (get_key_offset(key) + + extent_size(coord, coord->unit_pos + 1) - 1)); return key; } @@ -692,9 +778,8 @@ max_unit_key_extent(const coord_t *coord possible check of the consistency of the item that the inventor can construct */ -int -check_extent(const coord_t *coord /* coord of item to check */ , - const char **error /* where to store error message */ ) +int check_extent(const coord_t * coord /* coord of item to check */ , + const char **error /* where to store error message */ ) { reiser4_extent *ext, *first; unsigned i, j; @@ -711,7 +796,7 @@ check_extent(const coord_t *coord /* coo *error = "Extent on the wrong level"; return -1; } - if (item_length_by_coord(coord) % sizeof (reiser4_extent) != 0) { + if (item_length_by_coord(coord) % sizeof(reiser4_extent) != 0) { *error = "Wrong item size"; return -1; } @@ -733,7 +818,7 @@ check_extent(const coord_t *coord /* coo /* check that all jnodes are present for the unallocated * extent */ if (state_of_extent(ext) == UNALLOCATED_EXTENT) { - for (j = 0; j < extent_get_width(ext); j ++) { + for (j = 0; j < extent_get_width(ext); j++) { jnode *node; node = jlookup(tree, oid, index + j); @@ -765,8 +850,13 @@ check_extent(const coord_t *coord /* coo for (j = 0; j < i; j++) { if (state_of_extent(first + j) != ALLOCATED_EXTENT) continue; - if (!((extent_get_start(ext) >= extent_get_start(first + j) + extent_get_width(first + j)) - || (extent_get_start(ext) + extent_get_width(ext) <= extent_get_start(first + j)))) { + if (! + ((extent_get_start(ext) >= + extent_get_start(first + j) + + extent_get_width(first + j)) + || (extent_get_start(ext) + + extent_get_width(ext) <= + extent_get_start(first + j)))) { *error = "Extent overlaps with others"; return -1; } @@ -777,7 +867,7 @@ check_extent(const coord_t *coord /* coo return 0; } -#endif /* REISER4_DEBUG */ +#endif /* REISER4_DEBUG */ /* Local variables: diff -puN fs/reiser4/plugin/item/internal.c~reiser4-big-update fs/reiser4/plugin/item/internal.c --- devel/fs/reiser4/plugin/item/internal.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/internal.c 2005-09-15 19:51:08.000000000 -0700 @@ -22,19 +22,17 @@ /* see internal.h for explanation */ /* plugin->u.item.b.mergeable */ -reiser4_internal int -mergeable_internal(const coord_t * p1 UNUSED_ARG /* first item */ , - const coord_t * p2 UNUSED_ARG /* second item */ ) +int mergeable_internal(const coord_t * p1 UNUSED_ARG /* first item */ , + const coord_t * p2 UNUSED_ARG /* second item */ ) { /* internal items are not mergeable */ return 0; } /* ->lookup() method for internal items */ -reiser4_internal lookup_result -lookup_internal(const reiser4_key * key /* key to look up */ , - lookup_bias bias UNUSED_ARG /* lookup bias */ , - coord_t * coord /* coord of item */ ) +lookup_result lookup_internal(const reiser4_key * key /* key to look up */ , + lookup_bias bias UNUSED_ARG /* lookup bias */ , + coord_t * coord /* coord of item */ ) { reiser4_key ukey; @@ -54,17 +52,17 @@ lookup_internal(const reiser4_key * key } /* return body of internal item at @coord */ -static internal_item_layout * -internal_at(const coord_t * coord /* coord of - * item */ ) +static internal_item_layout *internal_at(const coord_t * coord /* coord of + * item */ ) { assert("nikita-607", coord != NULL); - assert("nikita-1650", item_plugin_by_coord(coord) == item_plugin_by_id(NODE_POINTER_ID)); + assert("nikita-1650", + item_plugin_by_coord(coord) == + item_plugin_by_id(NODE_POINTER_ID)); return (internal_item_layout *) item_body_by_coord(coord); } -reiser4_internal void -update_internal(const coord_t * coord, const reiser4_block_nr * blocknr) +void update_internal(const coord_t * coord, const reiser4_block_nr * blocknr) { internal_item_layout *item = internal_at(coord); assert("nikita-2959", reiser4_blocknr_is_sane(blocknr)); @@ -73,28 +71,25 @@ update_internal(const coord_t * coord, c } /* return child block number stored in the internal item at @coord */ -static reiser4_block_nr -pointer_at(const coord_t * coord /* coord of item */ ) +static reiser4_block_nr pointer_at(const coord_t * coord /* coord of item */ ) { assert("nikita-608", coord != NULL); return dblock_to_cpu(&internal_at(coord)->pointer); } /* get znode pointed to by internal @item */ -static znode * -znode_at(const coord_t * item /* coord of item */ , - znode * parent /* parent node */) +static znode *znode_at(const coord_t * item /* coord of item */ , + znode * parent /* parent node */ ) { return child_znode(item, parent, 1, 0); } /* store pointer from internal item into "block". Implementation of ->down_link() method */ -reiser4_internal void -down_link_internal(const coord_t * coord /* coord of item */ , - const reiser4_key * key UNUSED_ARG /* key to get - * pointer for */ , - reiser4_block_nr * block /* resulting block number */ ) +void down_link_internal(const coord_t * coord /* coord of item */ , + const reiser4_key * key UNUSED_ARG /* key to get + * pointer for */ , + reiser4_block_nr * block /* resulting block number */ ) { ON_DEBUG(reiser4_key item_key); @@ -102,15 +97,17 @@ down_link_internal(const coord_t * coord assert("nikita-611", block != NULL); assert("nikita-612", (key == NULL) || /* twig horrors */ - (znode_get_level(coord->node) == TWIG_LEVEL) || keyle(item_key_by_coord(coord, &item_key), key)); + (znode_get_level(coord->node) == TWIG_LEVEL) + || keyle(item_key_by_coord(coord, &item_key), key)); *block = pointer_at(coord); assert("nikita-2960", reiser4_blocknr_is_sane(block)); } /* Get the child's block number, or 0 if the block is unallocated. */ -reiser4_internal int -utmost_child_real_block_internal(const coord_t * coord, sideof side UNUSED_ARG, reiser4_block_nr * block) +int +utmost_child_real_block_internal(const coord_t * coord, sideof side UNUSED_ARG, + reiser4_block_nr * block) { assert("jmacd-2059", coord != NULL); @@ -125,8 +122,9 @@ utmost_child_real_block_internal(const c } /* Return the child. */ -reiser4_internal int -utmost_child_internal(const coord_t * coord, sideof side UNUSED_ARG, jnode ** childp) +int +utmost_child_internal(const coord_t * coord, sideof side UNUSED_ARG, + jnode ** childp) { reiser4_block_nr block = pointer_at(coord); znode *child; @@ -145,7 +143,7 @@ utmost_child_internal(const coord_t * co return 0; } -static void check_link(znode *left, znode *right) +static void check_link(znode * left, znode * right) { znode *scan; @@ -166,7 +164,7 @@ static void check_link(znode *left, znod } } -reiser4_internal int check__internal(const coord_t * coord, const char **error) +int check__internal(const coord_t * coord, const char **error) { reiser4_block_nr blk; znode *child; @@ -210,27 +208,11 @@ reiser4_internal int check__internal(con return 0; } -#ifdef REISER4_DEBUG_OUTPUT -/* debugging aid: print human readable information about internal item at - @coord */ -reiser4_internal void -print_internal(const char *prefix /* prefix to print */ , - coord_t * coord /* coord of item to print */ ) -{ - reiser4_block_nr blk; - - blk = pointer_at(coord); - assert("nikita-2963", reiser4_blocknr_is_sane(&blk)); - printk("%s: internal: %s\n", prefix, sprint_address(&blk)); -} -#endif - /* return true only if this item really points to "block" */ /* Audited by: green(2002.06.14) */ -reiser4_internal int -has_pointer_to_internal(const coord_t * coord /* coord of item */ , - const reiser4_block_nr * block /* block number to - * check */ ) +int has_pointer_to_internal(const coord_t * coord /* coord of item */ , + const reiser4_block_nr * block /* block number to + * check */ ) { assert("nikita-613", coord != NULL); assert("nikita-614", block != NULL); @@ -245,9 +227,8 @@ has_pointer_to_internal(const coord_t * parent pointer in child znode, insert child into sibling list and slum. */ -reiser4_internal int -create_hook_internal(const coord_t * item /* coord of item */ , - void *arg /* child's left neighbor, if any */ ) +int create_hook_internal(const coord_t * item /* coord of item */ , + void *arg /* child's left neighbor, if any */ ) { znode *child; @@ -266,8 +247,9 @@ create_hook_internal(const coord_t * ite tree = znode_get_tree(item->node); WLOCK_TREE(tree); WLOCK_DK(tree); - assert("nikita-1400", (child->in_parent.node == NULL) || (znode_above_root(child->in_parent.node))); - ++ item->node->c_count; + assert("nikita-1400", (child->in_parent.node == NULL) + || (znode_above_root(child->in_parent.node))); + ++item->node->c_count; coord_to_parent_coord(item, &child->in_parent); sibling_list_insert_nolock(child, left); @@ -302,11 +284,10 @@ create_hook_internal(const coord_t * ite */ -reiser4_internal int -kill_hook_internal(const coord_t * item /* coord of item */ , - pos_in_node_t from UNUSED_ARG /* start unit */ , - pos_in_node_t count UNUSED_ARG /* stop unit */, - struct carry_kill_data *p UNUSED_ARG) +int kill_hook_internal(const coord_t * item /* coord of item */ , + pos_in_node_t from UNUSED_ARG /* start unit */ , + pos_in_node_t count UNUSED_ARG /* stop unit */ , + struct carry_kill_data *p UNUSED_ARG) { znode *child; @@ -327,12 +308,13 @@ kill_hook_internal(const coord_t * item tree = znode_get_tree(item->node); WLOCK_TREE(tree); init_parent_coord(&child->in_parent, NULL); - -- item->node->c_count; + --item->node->c_count; WUNLOCK_TREE(tree); zput(child); return 0; } else { - warning("nikita-1223", "Cowardly refuse to remove link to non-empty node"); + warning("nikita-1223", + "Cowardly refuse to remove link to non-empty node"); print_znode("parent", item->node); print_znode("child", child); zput(child); @@ -346,11 +328,10 @@ kill_hook_internal(const coord_t * item Update parent pointer in child and c_counts in old and new parent */ -reiser4_internal int -shift_hook_internal(const coord_t * item /* coord of item */ , - unsigned from UNUSED_ARG /* start unit */ , - unsigned count UNUSED_ARG /* stop unit */ , - znode * old_node /* old parent */ ) +int shift_hook_internal(const coord_t * item /* coord of item */ , + unsigned from UNUSED_ARG /* start unit */ , + unsigned count UNUSED_ARG /* stop unit */ , + znode * old_node /* old parent */ ) { znode *child; znode *new_node; @@ -369,13 +350,14 @@ shift_hook_internal(const coord_t * item return 0; if (!IS_ERR(child)) { WLOCK_TREE(tree); - ++ new_node->c_count; + ++new_node->c_count; assert("nikita-1395", znode_parent(child) == old_node); assert("nikita-1396", old_node->c_count > 0); coord_to_parent_coord(item, &child->in_parent); assert("nikita-1781", znode_parent(child) == new_node); - assert("nikita-1782", check_tree_pointer(item, child) == NS_FOUND); - -- old_node->c_count; + assert("nikita-1782", + check_tree_pointer(item, child) == NS_FOUND); + --old_node->c_count; WUNLOCK_TREE(tree); zput(child); return 0; diff -puN fs/reiser4/plugin/item/internal.h~reiser4-big-update fs/reiser4/plugin/item/internal.h --- devel/fs/reiser4/plugin/item/internal.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/internal.h 2005-09-15 19:51:08.000000000 -0700 @@ -18,19 +18,25 @@ typedef struct internal_item_layout { struct cut_list; int mergeable_internal(const coord_t * p1, const coord_t * p2); -lookup_result lookup_internal(const reiser4_key * key, lookup_bias bias, coord_t * coord); +lookup_result lookup_internal(const reiser4_key * key, lookup_bias bias, + coord_t * coord); /* store pointer from internal item into "block". Implementation of ->down_link() method */ -extern void down_link_internal(const coord_t * coord, const reiser4_key * key, reiser4_block_nr * block); -extern int has_pointer_to_internal(const coord_t * coord, const reiser4_block_nr * block); +extern void down_link_internal(const coord_t * coord, const reiser4_key * key, + reiser4_block_nr * block); +extern int has_pointer_to_internal(const coord_t * coord, + const reiser4_block_nr * block); extern int create_hook_internal(const coord_t * item, void *arg); -extern int kill_hook_internal(const coord_t * item, pos_in_node_t from, pos_in_node_t count, - struct carry_kill_data *); -extern int shift_hook_internal(const coord_t * item, unsigned from, unsigned count, znode * old_node); +extern int kill_hook_internal(const coord_t * item, pos_in_node_t from, + pos_in_node_t count, struct carry_kill_data *); +extern int shift_hook_internal(const coord_t * item, unsigned from, + unsigned count, znode * old_node); extern void print_internal(const char *prefix, coord_t * coord); -extern int utmost_child_internal(const coord_t * coord, sideof side, jnode ** child); -int utmost_child_real_block_internal(const coord_t * coord, sideof side, reiser4_block_nr * block); +extern int utmost_child_internal(const coord_t * coord, sideof side, + jnode ** child); +int utmost_child_real_block_internal(const coord_t * coord, sideof side, + reiser4_block_nr * block); extern void update_internal(const coord_t * coord, const reiser4_block_nr * blocknr); diff -puN fs/reiser4/plugin/item/item.c~reiser4-big-update fs/reiser4/plugin/item/item.c --- devel/fs/reiser4/plugin/item/item.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/item.c 2005-09-15 19:51:08.000000000 -0700 @@ -12,46 +12,44 @@ #include "item.h" #include "static_stat.h" #include "../plugin.h" -#include "../cryptcompress.h" #include "../../znode.h" #include "../../tree.h" #include "../../context.h" #include "ctail.h" /* return pointer to item body */ -reiser4_internal void -item_body_by_coord_hard(coord_t * coord /* coord to query */ ) +void item_body_by_coord_hard(coord_t * coord /* coord to query */ ) { assert("nikita-324", coord != NULL); assert("nikita-325", coord->node != NULL); assert("nikita-326", znode_is_loaded(coord->node)); assert("nikita-3200", coord->offset == INVALID_OFFSET); - coord->offset = node_plugin_by_node(coord->node)->item_by_coord(coord) - zdata(coord->node); + coord->offset = + node_plugin_by_node(coord->node)->item_by_coord(coord) - + zdata(coord->node); ON_DEBUG(coord->body_v = coord->node->times_locked); } -reiser4_internal void * -item_body_by_coord_easy(const coord_t * coord /* coord to query */ ) +void *item_body_by_coord_easy(const coord_t * coord /* coord to query */ ) { return zdata(coord->node) + coord->offset; } #if REISER4_DEBUG -reiser4_internal int -item_body_is_valid(const coord_t * coord) +int item_body_is_valid(const coord_t * coord) { return - coord->offset == - node_plugin_by_node(coord->node)->item_by_coord(coord) - zdata(coord->node); + coord->offset == + node_plugin_by_node(coord->node)->item_by_coord(coord) - + zdata(coord->node); } #endif /* return length of item at @coord */ -reiser4_internal pos_in_node_t -item_length_by_coord(const coord_t * coord /* coord to query */ ) +pos_in_node_t item_length_by_coord(const coord_t * coord /* coord to query */ ) { int len; @@ -63,22 +61,22 @@ item_length_by_coord(const coord_t * coo return len; } -reiser4_internal void -obtain_item_plugin(const coord_t * coord) +void obtain_item_plugin(const coord_t * coord) { assert("nikita-330", coord != NULL); assert("nikita-331", coord->node != NULL); assert("nikita-332", znode_is_loaded(coord->node)); coord_set_iplug((coord_t *) coord, - node_plugin_by_node(coord->node)->plugin_by_coord(coord)); + node_plugin_by_node(coord->node)-> + plugin_by_coord(coord)); assert("nikita-2479", - coord_iplug(coord) == node_plugin_by_node(coord->node)->plugin_by_coord(coord)); + coord_iplug(coord) == + node_plugin_by_node(coord->node)->plugin_by_coord(coord)); } /* return type of item at @coord */ -reiser4_internal item_type_id -item_type_by_coord(const coord_t * coord /* coord to query */ ) +item_type_id item_type_by_coord(const coord_t * coord /* coord to query */ ) { assert("nikita-333", coord != NULL); assert("nikita-334", coord->node != NULL); @@ -90,23 +88,22 @@ item_type_by_coord(const coord_t * coord /* return id of item */ /* Audited by: green(2002.06.15) */ -reiser4_internal item_id -item_id_by_coord(const coord_t * coord /* coord to query */ ) +item_id item_id_by_coord(const coord_t * coord /* coord to query */ ) { assert("vs-539", coord != NULL); assert("vs-538", coord->node != NULL); assert("vs-537", znode_is_loaded(coord->node)); assert("vs-536", item_plugin_by_coord(coord) != NULL); - assert("vs-540", item_id_by_plugin(item_plugin_by_coord(coord)) < LAST_ITEM_ID); + assert("vs-540", + item_id_by_plugin(item_plugin_by_coord(coord)) < LAST_ITEM_ID); return item_id_by_plugin(item_plugin_by_coord(coord)); } /* return key of item at @coord */ /* Audited by: green(2002.06.15) */ -reiser4_internal reiser4_key * -item_key_by_coord(const coord_t * coord /* coord to query */ , - reiser4_key * key /* result */ ) +reiser4_key *item_key_by_coord(const coord_t * coord /* coord to query */ , + reiser4_key * key /* result */ ) { assert("nikita-338", coord != NULL); assert("nikita-339", coord->node != NULL); @@ -116,9 +113,8 @@ item_key_by_coord(const coord_t * coord } /* this returns max key in the item */ -reiser4_internal reiser4_key * -max_item_key_by_coord(const coord_t *coord /* coord to query */ , - reiser4_key *key /* result */ ) +reiser4_key *max_item_key_by_coord(const coord_t * coord /* coord to query */ , + reiser4_key * key /* result */ ) { coord_t last; @@ -136,9 +132,8 @@ max_item_key_by_coord(const coord_t *coo } /* return key of unit at @coord */ -reiser4_internal reiser4_key * -unit_key_by_coord(const coord_t * coord /* coord to query */ , - reiser4_key * key /* result */ ) +reiser4_key *unit_key_by_coord(const coord_t * coord /* coord to query */ , + reiser4_key * key /* result */ ) { assert("nikita-772", coord != NULL); assert("nikita-774", coord->node != NULL); @@ -151,9 +146,8 @@ unit_key_by_coord(const coord_t * coord } /* return the biggest key contained the unit @coord */ -reiser4_internal reiser4_key * -max_unit_key_by_coord(const coord_t * coord /* coord to query */ , - reiser4_key * key /* result */ ) +reiser4_key *max_unit_key_by_coord(const coord_t * coord /* coord to query */ , + reiser4_key * key /* result */ ) { assert("nikita-772", coord != NULL); assert("nikita-774", coord->node != NULL); @@ -165,12 +159,12 @@ max_unit_key_by_coord(const coord_t * co return unit_key_by_coord(coord, key); } - /* ->max_key_inside() method for items consisting of exactly one key (like stat-data) */ -static reiser4_key * -max_key_inside_single_key(const coord_t * coord /* coord of item */ , - reiser4_key * result /* resulting key */) +static reiser4_key *max_key_inside_single_key(const coord_t * + coord /* coord of item */ , + reiser4_key * + result /* resulting key */ ) { assert("nikita-604", coord != NULL); @@ -181,7 +175,7 @@ max_key_inside_single_key(const coord_t /* ->nr_units() method for items consisting of exactly one unit always */ static pos_in_node_t -nr_units_single_unit(const coord_t * coord UNUSED_ARG /* coord of item */ ) +nr_units_single_unit(const coord_t * coord UNUSED_ARG /* coord of item */ ) { return 1; } @@ -201,10 +195,9 @@ agree_to_fast_op(const coord_t * coord U return 1; } -reiser4_internal int -item_can_contain_key(const coord_t * item /* coord of item */ , - const reiser4_key * key /* key to check */ , - const reiser4_item_data * data /* parameters of item +int item_can_contain_key(const coord_t * item /* coord of item */ , + const reiser4_key * key /* key to check */ , + const reiser4_item_data * data /* parameters of item * being created */ ) { item_plugin *iplug; @@ -223,25 +216,24 @@ item_can_contain_key(const coord_t * ite iplug->b.max_key_inside(item, &max_key_in_item); /* can contain key if - min_key_in_item <= key && - key <= max_key_in_item - */ - return keyle(&min_key_in_item, key) && keyle(key, &max_key_in_item); + min_key_in_item <= key && + key <= max_key_in_item + */ + return keyle(&min_key_in_item, key) + && keyle(key, &max_key_in_item); } } /* mergeable method for non mergeable items */ static int -not_mergeable(const coord_t * i1 UNUSED_ARG, - const coord_t * i2 UNUSED_ARG) +not_mergeable(const coord_t * i1 UNUSED_ARG, const coord_t * i2 UNUSED_ARG) { return 0; } /* return 0 if @item1 and @item2 are not mergeable, !0 - otherwise */ -reiser4_internal int -are_items_mergeable(const coord_t * i1 /* coord of first item */ , - const coord_t * i2 /* coord of second item */ ) +int are_items_mergeable(const coord_t * i1 /* coord of first item */ , + const coord_t * i2 /* coord of second item */ ) { item_plugin *iplug; reiser4_key k1; @@ -255,7 +247,8 @@ are_items_mergeable(const coord_t * i1 / /* NOTE-NIKITA are_items_mergeable() is also called by assertions in shifting code when nodes are in "suspended" state. */ - assert("nikita-1663", keyle(item_key_by_coord(i1, &k1), item_key_by_coord(i2, &k2))); + assert("nikita-1663", + keyle(item_key_by_coord(i1, &k1), item_key_by_coord(i2, &k2))); if (iplug->b.mergeable != NULL) { return iplug->b.mergeable(i1, i2); @@ -264,277 +257,258 @@ are_items_mergeable(const coord_t * i1 / item_key_by_coord(i2, &k2); /* mergeable if ->max_key_inside() >= key of i2; */ - return keyge(iplug->b.max_key_inside(i1, &k1), item_key_by_coord(i2, &k2)); + return keyge(iplug->b.max_key_inside(i1, &k1), + item_key_by_coord(i2, &k2)); } else { item_key_by_coord(i1, &k1); item_key_by_coord(i2, &k2); return (get_key_locality(&k1) == get_key_locality(&k2)) && - (get_key_objectid(&k1) == get_key_objectid(&k2)) && (iplug == item_plugin_by_coord(i2)); + (get_key_objectid(&k1) == get_key_objectid(&k2)) + && (iplug == item_plugin_by_coord(i2)); } } -reiser4_internal int -item_is_extent(const coord_t * item) +int item_is_extent(const coord_t * item) { assert("vs-482", coord_is_existing_item(item)); return item_id_by_coord(item) == EXTENT_POINTER_ID; } -reiser4_internal int -item_is_tail(const coord_t * item) +int item_is_tail(const coord_t * item) { assert("vs-482", coord_is_existing_item(item)); return item_id_by_coord(item) == FORMATTING_ID; } -reiser4_internal int -item_is_statdata(const coord_t * item) +int item_is_statdata(const coord_t * item) { assert("vs-516", coord_is_existing_item(item)); return item_type_by_coord(item) == STAT_DATA_ITEM_TYPE; } -reiser4_internal int -item_is_ctail(const coord_t * item) +int item_is_ctail(const coord_t * item) { assert("edward-xx", coord_is_existing_item(item)); return item_id_by_coord(item) == CTAIL_ID; } -static int -change_item(struct inode * inode, reiser4_plugin * plugin) +static int change_item(struct inode *inode, reiser4_plugin * plugin) { /* cannot change constituent item (sd, or dir_item) */ return RETERR(-EINVAL); } static reiser4_plugin_ops item_plugin_ops = { - .init = NULL, - .load = NULL, + .init = NULL, + .load = NULL, .save_len = NULL, - .save = NULL, - .change = change_item + .save = NULL, + .change = change_item }; - item_plugin item_plugins[LAST_ITEM_ID] = { [STATIC_STAT_DATA_ID] = { .h = { .type_id = REISER4_ITEM_PLUGIN_TYPE, - .id = STATIC_STAT_DATA_ID, - .pops = &item_plugin_ops, - .label = "sd", - .desc = "stat-data", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .id = STATIC_STAT_DATA_ID, + .pops = &item_plugin_ops, + .label = "sd", + .desc = "stat-data", + .linkage = {NULL, NULL} }, .b = { - .item_type = STAT_DATA_ITEM_TYPE, - .max_key_inside = max_key_inside_single_key, - .can_contain_key = NULL, - .mergeable = not_mergeable, - .nr_units = nr_units_single_unit, - .lookup = NULL, - .init = NULL, - .paste = paste_no_paste, - .fast_paste = NULL, - .can_shift = NULL, - .copy_units = NULL, - .create_hook = NULL, - .kill_hook = NULL, - .shift_hook = NULL, - .cut_units = NULL, - .kill_units = NULL, - .unit_key = NULL, - .max_unit_key = NULL, - .estimate = NULL, + .item_type = STAT_DATA_ITEM_TYPE, + .max_key_inside = max_key_inside_single_key, + .can_contain_key = NULL, + .mergeable = not_mergeable, + .nr_units = nr_units_single_unit, + .lookup = NULL, + .init = NULL, + .paste = paste_no_paste, + .fast_paste = NULL, + .can_shift = NULL, + .copy_units = NULL, + .create_hook = NULL, + .kill_hook = NULL, + .shift_hook = NULL, + .cut_units = NULL, + .kill_units = NULL, + .unit_key = NULL, + .max_unit_key = NULL, + .estimate = NULL, .item_data_by_flow = NULL, -#ifdef REISER4_DEBUG_OUTPUT - .print = print_sd, - .item_stat = item_stat_static_sd, -#endif #if REISER4_DEBUG - .check = NULL + .check = NULL #endif }, .f = { - .utmost_child = NULL, + .utmost_child = NULL, .utmost_child_real_block = NULL, - .update = NULL, - .scan = NULL, - .convert = NULL + .update = NULL, + .scan = NULL, + .convert = NULL }, .s = { .sd = { .init_inode = init_inode_static_sd, - .save_len = save_len_static_sd, - .save = save_static_sd + .save_len = save_len_static_sd, + .save = save_static_sd } } }, [SIMPLE_DIR_ENTRY_ID] = { .h = { .type_id = REISER4_ITEM_PLUGIN_TYPE, - .id = SIMPLE_DIR_ENTRY_ID, - .pops = &item_plugin_ops, - .label = "de", - .desc = "directory entry", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .id = SIMPLE_DIR_ENTRY_ID, + .pops = &item_plugin_ops, + .label = "de", + .desc = "directory entry", + .linkage = {NULL, NULL} }, .b = { - .item_type = DIR_ENTRY_ITEM_TYPE, - .max_key_inside = max_key_inside_single_key, - .can_contain_key = NULL, - .mergeable = NULL, - .nr_units = nr_units_single_unit, - .lookup = NULL, - .init = NULL, - .paste = NULL, - .fast_paste = NULL, - .can_shift = NULL, - .copy_units = NULL, - .create_hook = NULL, - .kill_hook = NULL, - .shift_hook = NULL, - .cut_units = NULL, - .kill_units = NULL, - .unit_key = NULL, - .max_unit_key = NULL, - .estimate = NULL, + .item_type = DIR_ENTRY_ITEM_TYPE, + .max_key_inside = max_key_inside_single_key, + .can_contain_key = NULL, + .mergeable = NULL, + .nr_units = nr_units_single_unit, + .lookup = NULL, + .init = NULL, + .paste = NULL, + .fast_paste = NULL, + .can_shift = NULL, + .copy_units = NULL, + .create_hook = NULL, + .kill_hook = NULL, + .shift_hook = NULL, + .cut_units = NULL, + .kill_units = NULL, + .unit_key = NULL, + .max_unit_key = NULL, + .estimate = NULL, .item_data_by_flow = NULL, -#ifdef REISER4_DEBUG_OUTPUT - .print = print_de, - .item_stat = NULL, -#endif #if REISER4_DEBUG - .check = NULL + .check = NULL #endif }, .f = { - .utmost_child = NULL, + .utmost_child = NULL, .utmost_child_real_block = NULL, - .update = NULL, - .scan = NULL, - .convert = NULL + .update = NULL, + .scan = NULL, + .convert = NULL }, .s = { .dir = { - .extract_key = extract_key_de, - .update_key = update_key_de, - .extract_name = extract_name_de, + .extract_key = extract_key_de, + .update_key = update_key_de, + .extract_name = extract_name_de, .extract_file_type = extract_file_type_de, - .add_entry = add_entry_de, - .rem_entry = rem_entry_de, - .max_name_len = max_name_len_de + .add_entry = add_entry_de, + .rem_entry = rem_entry_de, + .max_name_len = max_name_len_de } } }, [COMPOUND_DIR_ID] = { .h = { .type_id = REISER4_ITEM_PLUGIN_TYPE, - .id = COMPOUND_DIR_ID, - .pops = &item_plugin_ops, - .label = "cde", - .desc = "compressed directory entry", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .id = COMPOUND_DIR_ID, + .pops = &item_plugin_ops, + .label = "cde", + .desc = "compressed directory entry", + .linkage = {NULL, NULL} }, .b = { - .item_type = DIR_ENTRY_ITEM_TYPE, - .max_key_inside = max_key_inside_cde, - .can_contain_key = can_contain_key_cde, - .mergeable = mergeable_cde, - .nr_units = nr_units_cde, - .lookup = lookup_cde, - .init = init_cde, - .paste = paste_cde, - .fast_paste = agree_to_fast_op, - .can_shift = can_shift_cde, - .copy_units = copy_units_cde, - .create_hook = NULL, - .kill_hook = NULL, - .shift_hook = NULL, - .cut_units = cut_units_cde, - .kill_units = kill_units_cde, - .unit_key = unit_key_cde, - .max_unit_key = unit_key_cde, - .estimate = estimate_cde, - .item_data_by_flow = NULL -#ifdef REISER4_DEBUG_OUTPUT - , .print = print_cde, - .item_stat = NULL -#endif + .item_type = DIR_ENTRY_ITEM_TYPE, + .max_key_inside = max_key_inside_cde, + .can_contain_key = can_contain_key_cde, + .mergeable = mergeable_cde, + .nr_units = nr_units_cde, + .lookup = lookup_cde, + .init = init_cde, + .paste = paste_cde, + .fast_paste = agree_to_fast_op, + .can_shift = can_shift_cde, + .copy_units = copy_units_cde, + .create_hook = NULL, + .kill_hook = NULL, + .shift_hook = NULL, + .cut_units = cut_units_cde, + .kill_units = kill_units_cde, + .unit_key = unit_key_cde, + .max_unit_key = unit_key_cde, + .estimate = estimate_cde, + .item_data_by_flow = NULL, #if REISER4_DEBUG - , .check = check_cde + .check = check_cde #endif }, .f = { - .utmost_child = NULL, + .utmost_child = NULL, .utmost_child_real_block = NULL, - .update = NULL, - .scan = NULL, - .convert = NULL + .update = NULL, + .scan = NULL, + .convert = NULL }, .s = { .dir = { - .extract_key = extract_key_cde, - .update_key = update_key_cde, - .extract_name = extract_name_cde, + .extract_key = extract_key_cde, + .update_key = update_key_cde, + .extract_name = extract_name_cde, .extract_file_type = extract_file_type_de, - .add_entry = add_entry_cde, - .rem_entry = rem_entry_cde, - .max_name_len = max_name_len_cde + .add_entry = add_entry_cde, + .rem_entry = rem_entry_cde, + .max_name_len = max_name_len_cde } } }, [NODE_POINTER_ID] = { .h = { .type_id = REISER4_ITEM_PLUGIN_TYPE, - .id = NODE_POINTER_ID, - .pops = NULL, - .label = "internal", - .desc = "internal item", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .id = NODE_POINTER_ID, + .pops = NULL, + .label = "internal", + .desc = "internal item", + .linkage = {NULL, NULL} }, .b = { - .item_type = INTERNAL_ITEM_TYPE, - .max_key_inside = NULL, - .can_contain_key = NULL, - .mergeable = mergeable_internal, - .nr_units = nr_units_single_unit, - .lookup = lookup_internal, - .init = NULL, - .paste = NULL, - .fast_paste = NULL, - .can_shift = NULL, - .copy_units = NULL, - .create_hook = create_hook_internal, - .kill_hook = kill_hook_internal, - .shift_hook = shift_hook_internal, - .cut_units = NULL, - .kill_units = NULL, - .unit_key = NULL, - .max_unit_key = NULL, - .estimate = NULL, - .item_data_by_flow = NULL -#ifdef REISER4_DEBUG_OUTPUT - , .print = print_internal, - .item_stat = NULL -#endif + .item_type = INTERNAL_ITEM_TYPE, + .max_key_inside = NULL, + .can_contain_key = NULL, + .mergeable = mergeable_internal, + .nr_units = nr_units_single_unit, + .lookup = lookup_internal, + .init = NULL, + .paste = NULL, + .fast_paste = NULL, + .can_shift = NULL, + .copy_units = NULL, + .create_hook = create_hook_internal, + .kill_hook = kill_hook_internal, + .shift_hook = shift_hook_internal, + .cut_units = NULL, + .kill_units = NULL, + .unit_key = NULL, + .max_unit_key = NULL, + .estimate = NULL, + .item_data_by_flow = NULL, #if REISER4_DEBUG - , .check = check__internal + .check = check__internal #endif }, .f = { - .utmost_child = utmost_child_internal, - .utmost_child_real_block = utmost_child_real_block_internal, - .update = update_internal, - .scan = NULL, - .convert = NULL + .utmost_child = utmost_child_internal, + .utmost_child_real_block = + utmost_child_real_block_internal, + .update = update_internal, + .scan = NULL, + .convert = NULL }, .s = { .internal = { - .down_link = down_link_internal, + .down_link = down_link_internal, .has_pointer_to = has_pointer_to_internal } } @@ -542,208 +516,204 @@ item_plugin item_plugins[LAST_ITEM_ID] = [EXTENT_POINTER_ID] = { .h = { .type_id = REISER4_ITEM_PLUGIN_TYPE, - .id = EXTENT_POINTER_ID, - .pops = NULL, - .label = "extent", - .desc = "extent item", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .id = EXTENT_POINTER_ID, + .pops = NULL, + .label = "extent", + .desc = "extent item", + .linkage = {NULL, NULL} }, .b = { - .item_type = UNIX_FILE_METADATA_ITEM_TYPE, - .max_key_inside = max_key_inside_extent, - .can_contain_key = can_contain_key_extent, - .mergeable = mergeable_extent, - .nr_units = nr_units_extent, - .lookup = lookup_extent, - .init = NULL, - .paste = paste_extent, - .fast_paste = agree_to_fast_op, - .can_shift = can_shift_extent, - .create_hook = create_hook_extent, - .copy_units = copy_units_extent, - .kill_hook = kill_hook_extent, - .shift_hook = NULL, - .cut_units = cut_units_extent, - .kill_units = kill_units_extent, - .unit_key = unit_key_extent, - .max_unit_key = max_unit_key_extent, - .estimate = NULL, + .item_type = UNIX_FILE_METADATA_ITEM_TYPE, + .max_key_inside = max_key_inside_extent, + .can_contain_key = can_contain_key_extent, + .mergeable = mergeable_extent, + .nr_units = nr_units_extent, + .lookup = lookup_extent, + .init = NULL, + .paste = paste_extent, + .fast_paste = agree_to_fast_op, + .can_shift = can_shift_extent, + .create_hook = create_hook_extent, + .copy_units = copy_units_extent, + .kill_hook = kill_hook_extent, + .shift_hook = NULL, + .cut_units = cut_units_extent, + .kill_units = kill_units_extent, + .unit_key = unit_key_extent, + .max_unit_key = max_unit_key_extent, + .estimate = NULL, .item_data_by_flow = NULL, #if REISER4_DEBUG .check = check_extent #endif }, .f = { - .utmost_child = utmost_child_extent, - .utmost_child_real_block = utmost_child_real_block_extent, - .update = NULL, - .scan = scan_extent, - .convert = NULL, - .key_by_offset = key_by_offset_extent + .utmost_child = utmost_child_extent, + .utmost_child_real_block = + utmost_child_real_block_extent, + .update = NULL, + .scan = scan_extent, + .convert = NULL, + .key_by_offset = key_by_offset_extent }, .s = { .file = { - .write = write_extent, - .read = read_extent, - .readpage = readpage_extent, - .capture = capture_extent, - .get_block = get_block_address_extent, - .readpages = readpages_extent, - .append_key = append_key_extent, - .init_coord_extension = init_coord_extension_extent + .write = write_extent, + .read = read_extent, + .readpage = readpage_extent, + .capture = capture_extent, + .get_block = get_block_address_extent, + .readpages = readpages_extent, + .append_key = append_key_extent, + .init_coord_extension = + init_coord_extension_extent } } }, [FORMATTING_ID] = { .h = { .type_id = REISER4_ITEM_PLUGIN_TYPE, - .id = FORMATTING_ID, - .pops = NULL, - .label = "body", - .desc = "body (or tail?) item", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .id = FORMATTING_ID, + .pops = NULL, + .label = "body", + .desc = "body (or tail?) item", + .linkage = {NULL, NULL} }, .b = { - .item_type = UNIX_FILE_METADATA_ITEM_TYPE, - .max_key_inside = max_key_inside_tail, - .can_contain_key = can_contain_key_tail, - .mergeable = mergeable_tail, - .nr_units = nr_units_tail, - .lookup = lookup_tail, - .init = NULL, - .paste = paste_tail, - .fast_paste = agree_to_fast_op, - .can_shift = can_shift_tail, - .create_hook = NULL, - .copy_units = copy_units_tail, - .kill_hook = kill_hook_tail, - .shift_hook = NULL, - .cut_units = cut_units_tail, - .kill_units = kill_units_tail, - .unit_key = unit_key_tail, - .max_unit_key = unit_key_tail, - .estimate = NULL, + .item_type = UNIX_FILE_METADATA_ITEM_TYPE, + .max_key_inside = max_key_inside_tail, + .can_contain_key = can_contain_key_tail, + .mergeable = mergeable_tail, + .nr_units = nr_units_tail, + .lookup = lookup_tail, + .init = NULL, + .paste = paste_tail, + .fast_paste = agree_to_fast_op, + .can_shift = can_shift_tail, + .create_hook = NULL, + .copy_units = copy_units_tail, + .kill_hook = kill_hook_tail, + .shift_hook = NULL, + .cut_units = cut_units_tail, + .kill_units = kill_units_tail, + .unit_key = unit_key_tail, + .max_unit_key = unit_key_tail, + .estimate = NULL, .item_data_by_flow = NULL, #if REISER4_DEBUG - .check = NULL + .check = NULL #endif }, .f = { - .utmost_child = NULL, + .utmost_child = NULL, .utmost_child_real_block = NULL, - .update = NULL, - .scan = NULL, - .convert = NULL + .update = NULL, + .scan = NULL, + .convert = NULL }, .s = { .file = { - .write = write_tail, - .read = read_tail, - .readpage = readpage_tail, - .capture = NULL, - .get_block = NULL, - .readpages = NULL, - .append_key = append_key_tail, - .init_coord_extension = init_coord_extension_tail + .write = write_tail, + .read = read_tail, + .readpage = readpage_tail, + .capture = NULL, + .get_block = NULL, + .readpages = NULL, + .append_key = append_key_tail, + .init_coord_extension = + init_coord_extension_tail } } }, [CTAIL_ID] = { .h = { .type_id = REISER4_ITEM_PLUGIN_TYPE, - .id = CTAIL_ID, - .pops = NULL, - .label = "ctail", - .desc = "cryptcompress tail item", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .id = CTAIL_ID, + .pops = NULL, + .label = "ctail", + .desc = "cryptcompress tail item", + .linkage = {NULL, NULL} }, .b = { - .item_type = UNIX_FILE_METADATA_ITEM_TYPE, - .max_key_inside = max_key_inside_tail, - .can_contain_key = can_contain_key_ctail, - .mergeable = mergeable_ctail, - .nr_units = nr_units_ctail, - .lookup = NULL, - .init = init_ctail, - .paste = paste_ctail, - .fast_paste = agree_to_fast_op, - .can_shift = can_shift_ctail, - .create_hook = create_hook_ctail, - .copy_units = copy_units_ctail, - .kill_hook = kill_hook_ctail, - .shift_hook = shift_hook_ctail, - .cut_units = cut_units_ctail, - .kill_units = kill_units_ctail, - .unit_key = unit_key_tail, - .max_unit_key = unit_key_tail, - .estimate = estimate_ctail, - .item_data_by_flow = NULL -#ifdef REISER4_DEBUG_OUTPUT - , .print = print_ctail, - .item_stat = NULL -#endif + .item_type = UNIX_FILE_METADATA_ITEM_TYPE, + .max_key_inside = max_key_inside_tail, + .can_contain_key = can_contain_key_ctail, + .mergeable = mergeable_ctail, + .nr_units = nr_units_ctail, + .lookup = NULL, + .init = init_ctail, + .paste = paste_ctail, + .fast_paste = agree_to_fast_op, + .can_shift = can_shift_ctail, + .create_hook = create_hook_ctail, + .copy_units = copy_units_ctail, + .kill_hook = kill_hook_ctail, + .shift_hook = shift_hook_ctail, + .cut_units = cut_units_ctail, + .kill_units = kill_units_ctail, + .unit_key = unit_key_tail, + .max_unit_key = unit_key_tail, + .estimate = estimate_ctail, + .item_data_by_flow = NULL, #if REISER4_DEBUG - , .check = check_ctail + .check = check_ctail #endif }, .f = { - .utmost_child = utmost_child_ctail, + .utmost_child = utmost_child_ctail, /* FIXME-EDWARD: write this */ .utmost_child_real_block = NULL, - .update = NULL, - .scan = scan_ctail, - .convert = convert_ctail + .update = NULL, + .scan = scan_ctail, + .convert = convert_ctail }, .s = { .file = { - .write = NULL, - .read = read_ctail, - .readpage = readpage_ctail, - .capture = NULL, - .get_block = get_block_address_tail, - .readpages = readpages_ctail, - .append_key = append_key_ctail, - .init_coord_extension = init_coord_extension_tail + .write = NULL, + .read = read_ctail, + .readpage = readpage_ctail, + .capture = NULL, + .get_block = get_block_address_tail, + .readpages = readpages_ctail, + .append_key = append_key_ctail, + .init_coord_extension = + init_coord_extension_tail } } }, [BLACK_BOX_ID] = { .h = { .type_id = REISER4_ITEM_PLUGIN_TYPE, - .id = BLACK_BOX_ID, - .pops = NULL, - .label = "blackbox", - .desc = "black box item", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .id = BLACK_BOX_ID, + .pops = NULL, + .label = "blackbox", + .desc = "black box item", + .linkage = {NULL, NULL} }, .b = { - .item_type = OTHER_ITEM_TYPE, - .max_key_inside = NULL, - .can_contain_key = NULL, - .mergeable = not_mergeable, - .nr_units = nr_units_single_unit, + .item_type = OTHER_ITEM_TYPE, + .max_key_inside = NULL, + .can_contain_key = NULL, + .mergeable = not_mergeable, + .nr_units = nr_units_single_unit, /* to need for ->lookup method */ - .lookup = NULL, - .init = NULL, - .paste = NULL, - .fast_paste = NULL, - .can_shift = NULL, - .copy_units = NULL, - .create_hook = NULL, - .kill_hook = NULL, - .shift_hook = NULL, - .cut_units = NULL, - .kill_units = NULL, - .unit_key = NULL, - .max_unit_key = NULL, - .estimate = NULL, + .lookup = NULL, + .init = NULL, + .paste = NULL, + .fast_paste = NULL, + .can_shift = NULL, + .copy_units = NULL, + .create_hook = NULL, + .kill_hook = NULL, + .shift_hook = NULL, + .cut_units = NULL, + .kill_units = NULL, + .unit_key = NULL, + .max_unit_key = NULL, + .estimate = NULL, .item_data_by_flow = NULL, -#ifdef REISER4_DEBUG_OUTPUT - .print = NULL, - .item_stat = NULL, -#endif #if REISER4_DEBUG - .check = NULL + .check = NULL #endif } } diff -puN fs/reiser4/plugin/item/item.h~reiser4-big-update fs/reiser4/plugin/item/item.h --- devel/fs/reiser4/plugin/item/item.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/item.h 2005-09-15 19:51:08.000000000 -0700 @@ -31,7 +31,6 @@ typedef enum { OTHER_ITEM_TYPE } item_type_id; - /* this is the part of each item plugin that all items are expected to support or at least explicitly fail to support by setting the pointer to null. */ @@ -40,44 +39,45 @@ typedef struct { /* operations called by balancing - It is interesting to consider that some of these item - operations could be given sources or targets that are not - really items in nodes. This could be ok/useful. + It is interesting to consider that some of these item + operations could be given sources or targets that are not + really items in nodes. This could be ok/useful. - */ + */ /* maximal key that can _possibly_ be occupied by this item - When inserting, and node ->lookup() method (called by - coord_by_key()) reaches an item after binary search, - the ->max_key_inside() item plugin method is used to determine - whether new item should pasted into existing item - (new_key<=max_key_inside()) or new item has to be created - (new_key>max_key_inside()). - - For items that occupy exactly one key (like stat-data) - this method should return this key. For items that can - grow indefinitely (extent, directory item) this should - return max_key(). + When inserting, and node ->lookup() method (called by + coord_by_key()) reaches an item after binary search, + the ->max_key_inside() item plugin method is used to determine + whether new item should pasted into existing item + (new_key<=max_key_inside()) or new item has to be created + (new_key>max_key_inside()). + + For items that occupy exactly one key (like stat-data) + this method should return this key. For items that can + grow indefinitely (extent, directory item) this should + return max_key(). For example extent with the key (LOCALITY,4,OBJID,STARTING-OFFSET), and length BLK blocks, ->max_key_inside is (LOCALITY,4,OBJID,0xffffffffffffffff), and - */ + */ reiser4_key *(*max_key_inside) (const coord_t *, reiser4_key *); /* true if item @coord can merge data at @key. */ - int (*can_contain_key) (const coord_t *, const reiser4_key *, const reiser4_item_data *); + int (*can_contain_key) (const coord_t *, const reiser4_key *, + const reiser4_item_data *); /* mergeable() - check items for mergeability Optional method. Returns true if two items can be merged. - */ + */ int (*mergeable) (const coord_t *, const coord_t *); /* number of atomic things in an item */ - pos_in_node_t (*nr_units) (const coord_t *); + pos_in_node_t(*nr_units) (const coord_t *); /* search within item for a unit within the item, and return a pointer to it. This can be used to calculate how many @@ -86,17 +86,18 @@ typedef struct { are continuous in the node, if the item's data are not continuous in the node, all sorts of other things are maybe going to break as well. */ - lookup_result(*lookup) (const reiser4_key *, lookup_bias, coord_t *); + lookup_result(*lookup) (const reiser4_key *, lookup_bias, coord_t *); /* method called by ode_plugin->create_item() to initialise new item */ - int (*init) (coord_t * target, coord_t * from, reiser4_item_data * data); + int (*init) (coord_t * target, coord_t * from, + reiser4_item_data * data); /* method called (e.g., by resize_item()) to place new data into - item when it grows*/ + item when it grows */ int (*paste) (coord_t *, reiser4_item_data *, carry_plugin_info *); /* return true if paste into @coord is allowed to skip carry. That is, if such paste would require any changes at the parent level - */ + */ int (*fast_paste) (const coord_t *); /* how many but not more than @want units of @source can be shifted into @target node. If pend == append - we try to @@ -108,9 +109,10 @@ typedef struct { @target is not NULL if shifting to the mergeable item and NULL is new item will be created during shifting. - */ + */ int (*can_shift) (unsigned free_space, coord_t *, - znode *, shift_direction, unsigned *size, unsigned want); + znode *, shift_direction, unsigned *size, + unsigned want); /* starting off @from-th unit of item @source append or prepend @count units to @target. @target has been already @@ -119,7 +121,9 @@ typedef struct { == SHIFT_LEFT - free space is at the end of @target item, othersize - it is in the beginning of it. */ void (*copy_units) (coord_t *, coord_t *, - unsigned from, unsigned count, shift_direction where_is_free_space, unsigned free_space); + unsigned from, unsigned count, + shift_direction where_is_free_space, + unsigned free_space); int (*create_hook) (const coord_t *, void *); /* do whatever is necessary to do when @count units starting @@ -135,23 +139,29 @@ typedef struct { undo changes made. OTOH, if space allocator involves balancing to perform dealloc_block - this will probably break balancing due to deadlock issues - */ - int (*kill_hook) (const coord_t *, pos_in_node_t from, pos_in_node_t count, struct carry_kill_data *); - int (*shift_hook) (const coord_t *, unsigned from, unsigned count, znode *_node); + */ + int (*kill_hook) (const coord_t *, pos_in_node_t from, + pos_in_node_t count, struct carry_kill_data *); + int (*shift_hook) (const coord_t *, unsigned from, unsigned count, + znode * _node); /* unit @*from contains @from_key. unit @*to contains @to_key. Cut all keys between @from_key and @to_key including boundaries. When units are cut from item beginning - move space which gets freed to head of item. When units are cut from item end - move freed space to item end. When units are cut from the middle of item - move freed space to item head. Return amount of space which got freed. Save smallest removed key in @smallest_removed if it is not 0. Save new first item key in @new_first_key if it is not 0 - */ - int (*cut_units) (coord_t *, pos_in_node_t from, pos_in_node_t to, struct carry_cut_data *, - reiser4_key *smallest_removed, reiser4_key *new_first_key); + */ + int (*cut_units) (coord_t *, pos_in_node_t from, pos_in_node_t to, + struct carry_cut_data *, + reiser4_key * smallest_removed, + reiser4_key * new_first_key); /* like cut_units, except that these units are removed from the tree, not only from a node */ - int (*kill_units) (coord_t *, pos_in_node_t from, pos_in_node_t to, struct carry_kill_data *, - reiser4_key *smallest_removed, reiser4_key *new_first); + int (*kill_units) (coord_t *, pos_in_node_t from, pos_in_node_t to, + struct carry_kill_data *, + reiser4_key * smallest_removed, + reiser4_key * new_first); /* if @key_of_coord == 1 - returned key of coord, otherwise - key of unit is returned. If @coord is not set to certain @@ -161,13 +171,14 @@ typedef struct { /* estimate how much space is needed for paste @data into item at @coord. if @coord==0 - estimate insertion, otherwise - estimate pasting - */ + */ int (*estimate) (const coord_t *, const reiser4_item_data *); /* converts flow @f to item data. @coord == 0 on insert */ - int (*item_data_by_flow) (const coord_t *, const flow_t *, reiser4_item_data *); + int (*item_data_by_flow) (const coord_t *, const flow_t *, + reiser4_item_data *); - /*void (*show) (struct seq_file *, coord_t *);*/ + /*void (*show) (struct seq_file *, coord_t *); */ #if REISER4_DEBUG /* used for debugging, every item should have here the most @@ -184,7 +195,8 @@ typedef struct { /* return whether the right or left child of @coord has a non-fake block number. */ - int (*utmost_child_real_block) (const coord_t *, sideof side, reiser4_block_nr *); + int (*utmost_child_real_block) (const coord_t *, sideof side, + reiser4_block_nr *); /* relocate child at @coord to the @block */ void (*update) (const coord_t *, const reiser4_block_nr *); /* count unformatted nodes per item for leave relocation policy, etc.. */ @@ -207,23 +219,27 @@ typedef struct { /* extract file type (DT_* stuff) from directory entry at @coord and return it */ unsigned (*extract_file_type) (const coord_t *); - int (*add_entry) (struct inode *dir, + int (*add_entry) (struct inode * dir, coord_t *, lock_handle *, - const struct dentry *name, reiser4_dir_entry_desc *entry); - int (*rem_entry) (struct inode *dir, const struct qstr *name, + const struct dentry * name, + reiser4_dir_entry_desc * entry); + int (*rem_entry) (struct inode * dir, const struct qstr * name, coord_t *, lock_handle *, - reiser4_dir_entry_desc *entry); - int (*max_name_len) (const struct inode *dir); + reiser4_dir_entry_desc * entry); + int (*max_name_len) (const struct inode * dir); } dir_entry_ops; /* operations specific to items regular (unix) file metadata are built of */ typedef struct { - int (*write)(struct inode *, flow_t *, hint_t *, int grabbed, write_mode_t); - int (*read)(struct file *, flow_t *, hint_t *); + int (*write) (struct inode *, flow_t *, hint_t *, int grabbed, + write_mode_t); + int (*read) (struct file *, flow_t *, hint_t *); int (*readpage) (void *, struct page *); - int (*capture) (reiser4_key *, uf_coord_t *, struct page *, write_mode_t); - int (*get_block) (const coord_t *, sector_t, struct buffer_head *); - void (*readpages) (void *, struct address_space *, struct list_head *pages); + int (*capture) (reiser4_key *, uf_coord_t *, struct page *, + write_mode_t); + int (*get_block) (const coord_t *, sector_t, sector_t *); + void (*readpages) (void *, struct address_space *, + struct list_head * pages); /* key of first byte which is not addressed by the item @coord is set to For example extent with the key @@ -235,7 +251,7 @@ typedef struct { /* FIXME: could be uf_coord also */ reiser4_key *(*append_key) (const coord_t *, reiser4_key *); - void (*init_coord_extension)(uf_coord_t *, loff_t); + void (*init_coord_extension) (uf_coord_t *, loff_t); } file_ops; /* operations specific to items of stat data type */ @@ -248,7 +264,7 @@ typedef struct { /* operations specific to internal item */ typedef struct { /* all tree traversal want to know from internal item is where - to go next. */ + to go next. */ void (*down_link) (const coord_t * coord, const reiser4_key * key, reiser4_block_nr * block); /* check that given internal item contains given pointer. */ @@ -275,24 +291,21 @@ struct item_plugin { }; -static inline item_id -item_id_by_plugin(item_plugin * plugin) +static inline item_id item_id_by_plugin(item_plugin * plugin) { return plugin->h.id; } -static inline char -get_iplugid(item_plugin *iplug) +static inline char get_iplugid(item_plugin * iplug) { assert("nikita-2838", iplug != NULL); assert("nikita-2839", 0 <= iplug->h.id && iplug->h.id < 0xff); return (char)item_id_by_plugin(iplug); } -extern unsigned long znode_times_locked(const znode *z); +extern unsigned long znode_times_locked(const znode * z); -static inline void -coord_set_iplug(coord_t * coord, item_plugin *iplug) +static inline void coord_set_iplug(coord_t * coord, item_plugin * iplug) { assert("nikita-2837", coord != NULL); assert("nikita-2838", iplug != NULL); @@ -300,17 +313,17 @@ coord_set_iplug(coord_t * coord, item_pl ON_DEBUG(coord->plug_v = znode_times_locked(coord->node)); } -static inline item_plugin * -coord_iplug(const coord_t * coord) +static inline item_plugin *coord_iplug(const coord_t * coord) { assert("nikita-2833", coord != NULL); assert("nikita-2834", coord->iplugid != INVALID_PLUGID); assert("nikita-3549", coord->plug_v == znode_times_locked(coord->node)); - return (item_plugin *)plugin_by_id(REISER4_ITEM_PLUGIN_TYPE, - coord->iplugid); + return (item_plugin *) plugin_by_id(REISER4_ITEM_PLUGIN_TYPE, + coord->iplugid); } -extern int item_can_contain_key(const coord_t * item, const reiser4_key * key, const reiser4_item_data *); +extern int item_can_contain_key(const coord_t * item, const reiser4_key * key, + const reiser4_item_data *); extern int are_items_mergeable(const coord_t * i1, const coord_t * i2); extern int item_is_extent(const coord_t *); extern int item_is_tail(const coord_t *); @@ -323,17 +336,18 @@ extern item_id item_id_by_coord(const co extern reiser4_key *item_key_by_coord(const coord_t * coord, reiser4_key * key); extern reiser4_key *max_item_key_by_coord(const coord_t *, reiser4_key *); extern reiser4_key *unit_key_by_coord(const coord_t * coord, reiser4_key * key); -extern reiser4_key *max_unit_key_by_coord(const coord_t * coord, reiser4_key * key); +extern reiser4_key *max_unit_key_by_coord(const coord_t * coord, + reiser4_key * key); extern void obtain_item_plugin(const coord_t * coord); -#if defined(REISER4_DEBUG) || defined(REISER4_DEBUG_MODIFY) || defined(REISER4_DEBUG_OUTPUT) +#if defined(REISER4_DEBUG) extern int znode_is_loaded(const znode * node); #endif /* return plugin of item at @coord */ -static inline item_plugin * -item_plugin_by_coord(const coord_t * coord /* coord to query */ ) +static inline item_plugin *item_plugin_by_coord(const coord_t * + coord /* coord to query */ ) { assert("nikita-330", coord != NULL); assert("nikita-331", coord->node != NULL); @@ -345,8 +359,7 @@ item_plugin_by_coord(const coord_t * coo } /* this returns true if item is of internal type */ -static inline int -item_is_internal(const coord_t * item) +static inline int item_is_internal(const coord_t * item) { assert("vs-483", coord_is_existing_item(item)); return item_type_by_coord(item) == INTERNAL_ITEM_TYPE; @@ -359,15 +372,15 @@ extern int item_body_is_valid(const coor #endif /* return pointer to item body */ -static inline void * -item_body_by_coord(const coord_t * coord /* coord to query */ ) +static inline void *item_body_by_coord(const coord_t * + coord /* coord to query */ ) { assert("nikita-324", coord != NULL); assert("nikita-325", coord->node != NULL); assert("nikita-326", znode_is_loaded(coord->node)); if (coord->offset == INVALID_OFFSET) - item_body_by_coord_hard((coord_t *)coord); + item_body_by_coord_hard((coord_t *) coord); assert("nikita-3201", item_body_is_valid(coord)); assert("nikita-3550", coord->body_v == znode_times_locked(coord->node)); return item_body_by_coord_easy(coord); diff -puN fs/reiser4/plugin/item/sde.c~reiser4-big-update fs/reiser4/plugin/item/sde.c --- devel/fs/reiser4/plugin/item/sde.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/sde.c 2005-09-15 19:51:08.000000000 -0700 @@ -18,33 +18,9 @@ #include /* for struct dentry */ #include -#ifdef REISER4_DEBUG_OUTPUT -reiser4_internal void -print_de(const char *prefix /* prefix to print */ , - coord_t * coord /* item to print */ ) -{ - assert("nikita-1456", prefix != NULL); - assert("nikita-1457", coord != NULL); - - if (item_length_by_coord(coord) < (int) sizeof (directory_entry_format)) { - printk("%s: wrong size: %i < %i\n", prefix, item_length_by_coord(coord), sizeof (directory_entry_format)); - } else { - reiser4_key sdkey; - char *name; - char buf[DE_NAME_BUF_LEN]; - - extract_key_de(coord, &sdkey); - name = extract_name_de(coord, buf); - printk("%s: name: %s\n", prefix, name); - print_key("\tsdkey", &sdkey); - } -} -#endif - /* ->extract_key() method of simple directory item plugin. */ -reiser4_internal int -extract_key_de(const coord_t * coord /* coord of item */ , - reiser4_key * key /* resulting key */ ) +int extract_key_de(const coord_t * coord /* coord of item */ , + reiser4_key * key /* resulting key */ ) { directory_entry_format *dent; @@ -52,12 +28,13 @@ extract_key_de(const coord_t * coord /* assert("nikita-1459", key != NULL); dent = (directory_entry_format *) item_body_by_coord(coord); - assert("nikita-1158", item_length_by_coord(coord) >= (int) sizeof *dent); + assert("nikita-1158", item_length_by_coord(coord) >= (int)sizeof *dent); return extract_key_from_id(&dent->id, key); } -reiser4_internal int -update_key_de(const coord_t * coord, const reiser4_key * key, lock_handle * lh UNUSED_ARG) +int +update_key_de(const coord_t * coord, const reiser4_key * key, + lock_handle * lh UNUSED_ARG) { directory_entry_format *dent; obj_key_id obj_id; @@ -75,8 +52,8 @@ update_key_de(const coord_t * coord, con return 0; } -reiser4_internal char * -extract_dent_name(const coord_t * coord, directory_entry_format *dent, char *buf) +char *extract_dent_name(const coord_t * coord, directory_entry_format * dent, + char *buf) { reiser4_key key; @@ -85,16 +62,15 @@ extract_dent_name(const coord_t * coord, print_address("oops", znode_get_block(coord->node)); if (!is_longname_key(&key)) { if (is_dot_key(&key)) - return (char *) "."; + return (char *)"."; else return extract_name_from_key(&key, buf); } else - return (char *) dent->name; + return (char *)dent->name; } /* ->extract_name() method of simple directory item plugin. */ -reiser4_internal char * -extract_name_de(const coord_t * coord /* coord of item */, char *buf) +char *extract_name_de(const coord_t * coord /* coord of item */ , char *buf) { directory_entry_format *dent; @@ -105,24 +81,22 @@ extract_name_de(const coord_t * coord /* } /* ->extract_file_type() method of simple directory item plugin. */ -reiser4_internal unsigned -extract_file_type_de(const coord_t * coord UNUSED_ARG /* coord of - * item */ ) +unsigned extract_file_type_de(const coord_t * coord UNUSED_ARG /* coord of + * item */ ) { assert("nikita-1764", coord != NULL); /* we don't store file type in the directory entry yet. But see comments at kassign.h:obj_key_id - */ + */ return DT_UNKNOWN; } -reiser4_internal int -add_entry_de(struct inode *dir /* directory of item */ , - coord_t * coord /* coord of item */ , - lock_handle * lh /* insertion lock handle */ , - const struct dentry *de /* name to add */ , - reiser4_dir_entry_desc * entry /* parameters of new directory +int add_entry_de(struct inode *dir /* directory of item */ , + coord_t * coord /* coord of item */ , + lock_handle * lh /* insertion lock handle */ , + const struct dentry *de /* name to add */ , + reiser4_dir_entry_desc * entry /* parameters of new directory * entry */ ) { reiser4_item_data data; @@ -133,7 +107,7 @@ add_entry_de(struct inode *dir /* direct int longname; name = de->d_name.name; - len = de->d_name.len; + len = de->d_name.len; assert("nikita-1163", strlen(name) == len); longname = is_longname(name, len); @@ -162,15 +136,14 @@ add_entry_de(struct inode *dir /* direct return 0; } -reiser4_internal int -rem_entry_de(struct inode *dir /* directory of item */ , - const struct qstr * name UNUSED_ARG, - coord_t * coord /* coord of item */ , - lock_handle * lh UNUSED_ARG /* lock handle for - * removal */ , - reiser4_dir_entry_desc * entry UNUSED_ARG /* parameters of - * directory entry - * being removed */ ) +int rem_entry_de(struct inode *dir /* directory of item */ , + const struct qstr *name UNUSED_ARG, + coord_t * coord /* coord of item */ , + lock_handle * lh UNUSED_ARG /* lock handle for + * removal */ , + reiser4_dir_entry_desc * entry UNUSED_ARG /* parameters of + * directory entry + * being removed */ ) { coord_t shadow; int result; @@ -189,9 +162,10 @@ rem_entry_de(struct inode *dir /* direct coords, because it will modify them without respect to possible aliasing. To work around this, create temporary copy of @coord. - */ + */ coord_dup(&shadow, coord); - result = kill_node_content(coord, &shadow, NULL, NULL, NULL, NULL, NULL, 0); + result = + kill_node_content(coord, &shadow, NULL, NULL, NULL, NULL, NULL, 0); if (result == 0) { /* NOTE-NIKITA quota plugin */ DQUOT_FREE_SPACE_NODIRTY(dir, length); @@ -199,10 +173,10 @@ rem_entry_de(struct inode *dir /* direct return result; } -reiser4_internal int -max_name_len_de(const struct inode *dir) +int max_name_len_de(const struct inode *dir) { - return tree_by_inode(dir)->nplug->max_item_size() - sizeof (directory_entry_format) - 2; + return tree_by_inode(dir)->nplug->max_item_size() - + sizeof(directory_entry_format) - 2; } /* Make Linus happy. diff -puN fs/reiser4/plugin/item/sde.h~reiser4-big-update fs/reiser4/plugin/item/sde.h --- devel/fs/reiser4/plugin/item/sde.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/sde.h 2005-09-15 19:51:08.000000000 -0700 @@ -22,7 +22,7 @@ typedef struct directory_entry_format { We store key as array of bytes, because we don't want 8-byte alignment of dir entries. - */ + */ obj_key_id id; /* file name. Null terminated string. */ d8 name[0]; @@ -30,19 +30,21 @@ typedef struct directory_entry_format { void print_de(const char *prefix, coord_t * coord); int extract_key_de(const coord_t * coord, reiser4_key * key); -int update_key_de(const coord_t * coord, const reiser4_key * key, lock_handle * lh); +int update_key_de(const coord_t * coord, const reiser4_key * key, + lock_handle * lh); char *extract_name_de(const coord_t * coord, char *buf); unsigned extract_file_type_de(const coord_t * coord); int add_entry_de(struct inode *dir, coord_t * coord, - lock_handle * lh, const struct dentry *name, reiser4_dir_entry_desc * entry); -int rem_entry_de(struct inode *dir, const struct qstr * name, coord_t * coord, lock_handle * lh, reiser4_dir_entry_desc * entry); + lock_handle * lh, const struct dentry *name, + reiser4_dir_entry_desc * entry); +int rem_entry_de(struct inode *dir, const struct qstr *name, coord_t * coord, + lock_handle * lh, reiser4_dir_entry_desc * entry); int max_name_len_de(const struct inode *dir); - int de_rem_and_shrink(struct inode *dir, coord_t * coord, int length); char *extract_dent_name(const coord_t * coord, - directory_entry_format *dent, char *buf); + directory_entry_format * dent, char *buf); #if REISER4_LARGE_KEY #define DE_NAME_BUF_LEN (24) diff -puN fs/reiser4/plugin/item/static_stat.c~reiser4-big-update fs/reiser4/plugin/item/static_stat.c --- devel/fs/reiser4/plugin/item/static_stat.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/static_stat.c 2005-09-15 19:51:08.000000000 -0700 @@ -22,10 +22,9 @@ /* helper function used while we are dumping/loading inode/plugin state to/from the stat-data. */ -static void -move_on(int *length /* space remaining in stat-data */ , - char **area /* current coord in stat data */ , - int size_of /* how many bytes to move forward */ ) +static void move_on(int *length /* space remaining in stat-data */ , + char **area /* current coord in stat data */ , + int size_of /* how many bytes to move forward */ ) { assert("nikita-615", length != NULL); assert("nikita-616", area != NULL); @@ -36,106 +35,11 @@ move_on(int *length /* space remaining i assert("nikita-617", *length >= 0); } -#ifdef REISER4_DEBUG_OUTPUT -/* ->print() method of static sd item. Prints human readable information about - sd at @coord */ -reiser4_internal void -print_sd(const char *prefix /* prefix to print */ , - coord_t * coord /* coord of item */ ) -{ - char *sd; - int len; - int bit; - int chunk; - __u16 mask; - reiser4_stat_data_base *sd_base; - - assert("nikita-1254", prefix != NULL); - assert("nikita-1255", coord != NULL); - - sd = item_body_by_coord(coord); - len = item_length_by_coord(coord); - - sd_base = (reiser4_stat_data_base *) sd; - if (len < (int) sizeof *sd_base) { - printk("%s: wrong size: %i < %i\n", prefix, item_length_by_coord(coord), sizeof *sd_base); - return; - } - - mask = d16tocpu(&sd_base->extmask); - printk("%s: extmask: %x\n", prefix, mask); - - move_on(&len, &sd, sizeof *sd_base); - - for (bit = 0, chunk = 0; mask != 0; ++bit, mask >>= 1) { - if (((bit + 1) % 16) != 0) { - /* handle extension */ - sd_ext_plugin *sdplug; - - sdplug = sd_ext_plugin_by_id(bit); - if (sdplug == NULL) { - continue; - } - if ((mask & 1) && sdplug->print != NULL) { - /* alignment is not supported in node layout - plugin yet. - result = align( inode, &len, &sd, - sdplug -> alignment ); - if( result != 0 ) - return result; */ - sdplug->print(prefix, &sd, &len); - } - } else if (mask & 1) { - /* next portion of bitmask */ - if (len < (int) sizeof (d16)) { - warning("nikita-2708", "No space for bitmap"); - break; - } - mask = d16tocpu((d16 *) sd); - move_on(&len, &sd, sizeof (d16)); - ++chunk; - if (chunk == 3) { - if (!(mask & 0x8000)) { - /* clear last bit */ - mask &= ~0x8000; - continue; - } - /* too much */ - warning("nikita-2709", "Too many extensions"); - break; - } - } else - /* bitmask exhausted */ - break; - } -} -#endif - -reiser4_internal void -item_stat_static_sd(const coord_t * coord, void *vp) -{ - reiser4_stat_data_base *sd; - mode_t mode; - sd_stat *stat; - - stat = (sd_stat *) vp; - sd = (reiser4_stat_data_base *) item_body_by_coord(coord); - mode = 0; // d16tocpu( &sd -> mode ); - - if (S_ISREG(mode)) - stat->files++; - else if (S_ISDIR(mode)) - stat->dirs++; - else - stat->others++; -} - /* helper function used while loading inode/plugin state from stat-data. Complain if there is less space in stat-data than was expected. Can only happen on disk corruption. */ -static int -not_enough_space(struct inode *inode /* object being processed */ , - const char *where /* error message */ ) +static int not_enough_space(struct inode *inode /* object being processed */ , + const char *where /* error message */ ) { assert("nikita-618", inode != NULL); @@ -147,9 +51,8 @@ not_enough_space(struct inode *inode /* /* helper function used while loading inode/plugin state from stat-data. Call it if invalid plugin id was found. */ -static int -unknown_plugin(reiser4_plugin_id id /* invalid id */ , - struct inode *inode /* object being processed */ ) +static int unknown_plugin(reiser4_plugin_id id /* invalid id */ , + struct inode *inode /* object being processed */ ) { warning("nikita-620", "Unknown plugin %i in %llu", id, (unsigned long long)get_inode_oid(inode)); @@ -157,43 +60,14 @@ unknown_plugin(reiser4_plugin_id id /* i return RETERR(-EINVAL); } -#if 0 /* Item alignment is not yet supported */ - -/* helper function used while storing/loading inode/plugin data to/from - stat-data. Move current coord in stat-data ("area") to position - aligned up to "alignment" bytes. */ -static int -align(struct inode *inode /* object being processed */ , - int *length /* space remaining in stat-data */ , - char **area /* current coord in stat data */ , - int alignment /* required alignment */ ) -{ - int delta; - - assert("nikita-621", inode != NULL); - assert("nikita-622", length != NULL); - assert("nikita-623", area != NULL); - assert("nikita-624", alignment > 0); - - delta = round_up(*area, alignment) - *area; - if (delta > *length) - return not_enough_space(inode, "padding"); - if (delta > 0) - move_on(length, area, delta); - return 0; -} - -#endif /* 0 */ - /* this is installed as ->init_inode() method of item_plugins[ STATIC_STAT_DATA_IT ] (fs/reiser4/plugin/item/item.c). Copies data from on-disk stat-data format into inode. Handles stat-data extensions. */ /* was sd_load */ -reiser4_internal int -init_inode_static_sd(struct inode *inode /* object being processed */ , - char *sd /* stat-data body */ , - int len /* length of stat-data */ ) +int init_inode_static_sd(struct inode *inode /* object being processed */ , + char *sd /* stat-data body */ , + int len /* length of stat-data */ ) { int result; int bit; @@ -214,15 +88,20 @@ init_inode_static_sd(struct inode *inode inode_set_flag(inode, REISER4_SDLEN_KNOWN); move_on(&len, &sd, sizeof *sd_base); - for (bit = 0, chunk = 0; mask != 0 || bit <= LAST_IMPORTANT_SD_EXTENSION; ++bit, mask >>= 1) { + for (bit = 0, chunk = 0; + mask != 0 || bit <= LAST_IMPORTANT_SD_EXTENSION; + ++bit, mask >>= 1) { if (((bit + 1) % 16) != 0) { /* handle extension */ sd_ext_plugin *sdplug; sdplug = sd_ext_plugin_by_id(bit); if (sdplug == NULL) { - warning("nikita-627", "No such extension %i in inode %llu", - bit, (unsigned long long)get_inode_oid(inode)); + warning("nikita-627", + "No such extension %i in inode %llu", + bit, + (unsigned long long) + get_inode_oid(inode)); result = RETERR(-EINVAL); break; @@ -231,10 +110,10 @@ init_inode_static_sd(struct inode *inode assert("nikita-628", sdplug->present); /* alignment is not supported in node layout plugin yet. - result = align( inode, &len, &sd, - sdplug -> alignment ); - if( result != 0 ) - return result; */ + result = align( inode, &len, &sd, + sdplug -> alignment ); + if( result != 0 ) + return result; */ result = sdplug->present(inode, &sd, &len); } else if (sdplug->absent != NULL) result = sdplug->absent(inode); @@ -244,9 +123,11 @@ init_inode_static_sd(struct inode *inode portion of bitmask */ } else if (mask & 1) { /* next portion of bitmask */ - if (len < (int) sizeof (d16)) { - warning("nikita-629", "No space for bitmap in inode %llu", - (unsigned long long)get_inode_oid(inode)); + if (len < (int)sizeof(d16)) { + warning("nikita-629", + "No space for bitmap in inode %llu", + (unsigned long long) + get_inode_oid(inode)); result = RETERR(-EINVAL); break; @@ -254,7 +135,7 @@ init_inode_static_sd(struct inode *inode mask = d16tocpu((d16 *) sd); bigmask <<= 16; bigmask |= mask; - move_on(&len, &sd, sizeof (d16)); + move_on(&len, &sd, sizeof(d16)); ++chunk; if (chunk == 3) { if (!(mask & 0x8000)) { @@ -263,8 +144,10 @@ init_inode_static_sd(struct inode *inode continue; } /* too much */ - warning("nikita-630", "Too many extensions in %llu", - (unsigned long long)get_inode_oid(inode)); + warning("nikita-630", + "Too many extensions in %llu", + (unsigned long long) + get_inode_oid(inode)); result = RETERR(-EINVAL); break; @@ -276,7 +159,7 @@ init_inode_static_sd(struct inode *inode state->extmask = bigmask; /* common initialisations */ inode->i_blksize = get_super_private(inode->i_sb)->optimal_io_size; - if (len - (sizeof (d16) * bit / 16) > 0) { + if (len - (sizeof(d16) * bit / 16) > 0) { /* alignment in save_len_static_sd() is taken into account -edward */ warning("nikita-631", "unused space in inode %llu", @@ -290,8 +173,7 @@ init_inode_static_sd(struct inode *inode Installed as ->save_len() method of item_plugins[ STATIC_STAT_DATA_IT ] (fs/reiser4/plugin/item/item.c). */ /* was sd_len */ -reiser4_internal int -save_len_static_sd(struct inode *inode /* object being processed */ ) +int save_len_static_sd(struct inode *inode /* object being processed */ ) { unsigned int result; __u64 mask; @@ -299,7 +181,7 @@ save_len_static_sd(struct inode *inode / assert("nikita-632", inode != NULL); - result = sizeof (reiser4_stat_data_base); + result = sizeof(reiser4_stat_data_base); mask = reiser4_inode_data(inode)->extmask; for (bit = 0; mask != 0; ++bit, mask >>= 1) { if (mask & 1) { @@ -313,7 +195,7 @@ save_len_static_sd(struct inode *inode / result += sdplug->save_len(inode); } } - result += sizeof (d16) * bit / 16; + result += sizeof(d16) * bit / 16; return result; } @@ -321,9 +203,8 @@ save_len_static_sd(struct inode *inode / Installed as ->save() method of item_plugins[ STATIC_STAT_DATA_IT ] (fs/reiser4/plugin/item/item.c). */ /* was sd_save */ -reiser4_internal int -save_static_sd(struct inode *inode /* object being processed */ , - char **area /* where to save stat-data */ ) +int save_static_sd(struct inode *inode /* object being processed */ , + char **area /* where to save stat-data */ ) { int result; __u64 emask; @@ -337,7 +218,7 @@ save_static_sd(struct inode *inode /* ob result = 0; emask = reiser4_inode_data(inode)->extmask; sd_base = (reiser4_stat_data_base *) * area; - cputod16((unsigned) (emask & 0xffff), &sd_base->extmask); + cputod16((unsigned)(emask & 0xffff), &sd_base->extmask); *area += sizeof *sd_base; len = 0xffffffffu; @@ -354,8 +235,9 @@ save_static_sd(struct inode *inode /* ob if (result) break; } else { - cputod16((unsigned) (emask & 0xffff), (d16 *) * area); - *area += sizeof (d16); + cputod16((unsigned)(emask & 0xffff), + (d16 *) * area); + *area += sizeof(d16); } } } @@ -364,12 +246,11 @@ save_static_sd(struct inode *inode /* ob /* stat-data extension handling functions. */ -static int -present_lw_sd(struct inode *inode /* object being processed */ , - char **area /* position in stat-data */ , - int *len /* remaining length */ ) +static int present_lw_sd(struct inode *inode /* object being processed */ , + char **area /* position in stat-data */ , + int *len /* remaining length */ ) { - if (*len >= (int) sizeof (reiser4_light_weight_stat)) { + if (*len >= (int)sizeof(reiser4_light_weight_stat)) { reiser4_light_weight_stat *sd_lw; sd_lw = (reiser4_light_weight_stat *) * area; @@ -387,16 +268,14 @@ present_lw_sd(struct inode *inode /* obj return not_enough_space(inode, "lw sd"); } -static int -save_len_lw_sd(struct inode *inode UNUSED_ARG /* object being - * processed */ ) +static int save_len_lw_sd(struct inode *inode UNUSED_ARG /* object being + * processed */ ) { - return sizeof (reiser4_light_weight_stat); + return sizeof(reiser4_light_weight_stat); } -static int -save_lw_sd(struct inode *inode /* object being processed */ , - char **area /* position in stat-data */ ) +static int save_lw_sd(struct inode *inode /* object being processed */ , + char **area /* position in stat-data */ ) { reiser4_light_weight_stat *sd; mode_t delta; @@ -415,24 +294,9 @@ save_lw_sd(struct inode *inode /* object return 0; } -#ifdef REISER4_DEBUG_OUTPUT -static void -print_lw_sd(const char *prefix, char **area /* position in stat-data */ , - int *len /* remaining length */ ) -{ - reiser4_light_weight_stat *sd; - - sd = (reiser4_light_weight_stat *) * area; - printk("%s: mode: %o, nlink: %i, size: %llu\n", prefix, - d16tocpu(&sd->mode), d32tocpu(&sd->nlink), d64tocpu(&sd->size)); - move_on(len, area, sizeof *sd); -} -#endif - -static int -present_unix_sd(struct inode *inode /* object being processed */ , - char **area /* position in stat-data */ , - int *len /* remaining length */ ) +static int present_unix_sd(struct inode *inode /* object being processed */ , + char **area /* position in stat-data */ , + int *len /* remaining length */ ) { assert("nikita-637", inode != NULL); assert("nikita-638", area != NULL); @@ -440,7 +304,7 @@ present_unix_sd(struct inode *inode /* o assert("nikita-640", len != NULL); assert("nikita-641", *len > 0); - if (*len >= (int) sizeof (reiser4_unix_stat)) { + if (*len >= (int)sizeof(reiser4_unix_stat)) { reiser4_unix_stat *sd; sd = (reiser4_unix_stat *) * area; @@ -460,8 +324,7 @@ present_unix_sd(struct inode *inode /* o return not_enough_space(inode, "unix sd"); } -static int -absent_unix_sd(struct inode *inode /* object being processed */ ) +static int absent_unix_sd(struct inode *inode /* object being processed */ ) { inode->i_uid = get_super_private(inode->i_sb)->default_uid; inode->i_gid = get_super_private(inode->i_sb)->default_gid; @@ -474,16 +337,14 @@ absent_unix_sd(struct inode *inode /* ob } /* Audited by: green(2002.06.14) */ -static int -save_len_unix_sd(struct inode *inode UNUSED_ARG /* object being - * processed */ ) +static int save_len_unix_sd(struct inode *inode UNUSED_ARG /* object being + * processed */ ) { - return sizeof (reiser4_unix_stat); + return sizeof(reiser4_unix_stat); } -static int -save_unix_sd(struct inode *inode /* object being processed */ , - char **area /* position in stat-data */ ) +static int save_unix_sd(struct inode *inode /* object being processed */ , + char **area /* position in stat-data */ ) { reiser4_unix_stat *sd; @@ -505,30 +366,12 @@ save_unix_sd(struct inode *inode /* obje return 0; } -#ifdef REISER4_DEBUG_OUTPUT -static void -print_unix_sd(const char *prefix, char **area /* position in stat-data */ , - int *len /* remaining length */ ) -{ - reiser4_unix_stat *sd; - - sd = (reiser4_unix_stat *) * area; - printk("%s: uid: %i, gid: %i, atime: %i, mtime: %i, ctime: %i, " - "rdev: %llo, bytes: %llu\n", prefix, - d32tocpu(&sd->uid), - d32tocpu(&sd->gid), - d32tocpu(&sd->atime), - d32tocpu(&sd->mtime), d32tocpu(&sd->ctime), d64tocpu(&sd->u.rdev), d64tocpu(&sd->u.bytes)); - move_on(len, area, sizeof *sd); -} -#endif - static int -present_large_times_sd(struct inode *inode /* object being processed */, - char **area /* position in stat-data */, - int *len /* remaining length */) +present_large_times_sd(struct inode *inode /* object being processed */ , + char **area /* position in stat-data */ , + int *len /* remaining length */ ) { - if (*len >= (int) sizeof (reiser4_large_times_stat)) { + if (*len >= (int)sizeof(reiser4_large_times_stat)) { reiser4_large_times_stat *sd_lt; sd_lt = (reiser4_large_times_stat *) * area; @@ -544,9 +387,10 @@ present_large_times_sd(struct inode *ino } static int -save_len_large_times_sd(struct inode *inode UNUSED_ARG /* object being processed */ ) +save_len_large_times_sd(struct inode *inode UNUSED_ARG + /* object being processed */ ) { - return sizeof (reiser4_large_times_stat); + return sizeof(reiser4_large_times_stat); } static int @@ -569,51 +413,36 @@ save_large_times_sd(struct inode *inode return 0; } -#ifdef REISER4_DEBUG_OUTPUT -static void -print_large_times_sd(const char *prefix, char **area /* position in stat-data */, - int *len /* remaining length */ ) -{ - reiser4_large_times_stat *sd; - - sd = (reiser4_large_times_stat *) * area; - printk("%s: nanotimes: a: %i, m: %i, c: %i\n", prefix, - d32tocpu(&sd->atime), d32tocpu(&sd->mtime), d32tocpu(&sd->ctime)); - move_on(len, area, sizeof *sd); -} -#endif - /* symlink stat data extension */ /* allocate memory for symlink target and attach it to inode->u.generic_ip */ static int symlink_target_to_inode(struct inode *inode, const char *target, int len) { - assert("vs-845", inode->u.generic_ip == 0); + assert("vs-845", inode->u.generic_ip == NULL); assert("vs-846", !inode_get_flag(inode, REISER4_GENERIC_PTR_USED)); /* FIXME-VS: this is prone to deadlock. Not more than other similar places, though */ - inode->u.generic_ip = reiser4_kmalloc((size_t) len + 1, GFP_KERNEL); + inode->u.generic_ip = kmalloc((size_t) len + 1, GFP_KERNEL); if (!inode->u.generic_ip) return RETERR(-ENOMEM); - memcpy((char *) (inode->u.generic_ip), target, (size_t) len); - ((char *) (inode->u.generic_ip))[len] = 0; + memcpy((char *)(inode->u.generic_ip), target, (size_t) len); + ((char *)(inode->u.generic_ip))[len] = 0; inode_set_flag(inode, REISER4_GENERIC_PTR_USED); return 0; } /* this is called on read_inode. There is nothing to do actually, but some sanity checks */ -static int -present_symlink_sd(struct inode *inode, char **area, int *len) +static int present_symlink_sd(struct inode *inode, char **area, int *len) { int result; int length; reiser4_symlink_stat *sd; - length = (int) inode->i_size; + length = (int)inode->i_size; /* * *len is number of bytes in stat data item from *area to the end of * item. It must be not less than size of symlink + 1 for ending 0 @@ -633,22 +462,20 @@ present_symlink_sd(struct inode *inode, return result; } -static int -save_len_symlink_sd(struct inode *inode) +static int save_len_symlink_sd(struct inode *inode) { return inode->i_size + 1; } /* this is called on create and update stat data. Do nothing on update but update @area */ -static int -save_symlink_sd(struct inode *inode, char **area) +static int save_symlink_sd(struct inode *inode, char **area) { int result; int length; reiser4_symlink_stat *sd; - length = (int) inode->i_size; + length = (int)inode->i_size; /* inode->i_size must be set already */ assert("vs-841", length); @@ -657,8 +484,8 @@ save_symlink_sd(struct inode *inode, cha if (!inode_get_flag(inode, REISER4_GENERIC_PTR_USED)) { const char *target; - target = (const char *) (inode->u.generic_ip); - inode->u.generic_ip = 0; + target = (const char *)(inode->u.generic_ip); + inode->u.generic_ip = NULL; result = symlink_target_to_inode(inode, target, length); @@ -667,32 +494,18 @@ save_symlink_sd(struct inode *inode, cha (*area)[length] = 0; } else { /* there is nothing to do in update but move area */ - assert("vs-844", !memcmp(inode->u.generic_ip, sd->body, (size_t) length + 1)); + assert("vs-844", + !memcmp(inode->u.generic_ip, sd->body, + (size_t) length + 1)); } *area += (length + 1); return result; } -#ifdef REISER4_DEBUG_OUTPUT -static void -print_symlink_sd(const char *prefix, char **area /* position in stat-data */ , - int *len /* remaining length */ ) -{ - reiser4_symlink_stat *sd; - int length; - - sd = (reiser4_symlink_stat *) * area; - length = strlen(sd->body); - printk("%s: \"%s\"\n", prefix, sd->body); - move_on(len, area, length + 1); -} -#endif - -static int -present_flags_sd(struct inode *inode /* object being processed */ , - char **area /* position in stat-data */ , - int *len /* remaining length */ ) +static int present_flags_sd(struct inode *inode /* object being processed */ , + char **area /* position in stat-data */ , + int *len /* remaining length */ ) { assert("nikita-645", inode != NULL); assert("nikita-646", area != NULL); @@ -700,7 +513,7 @@ present_flags_sd(struct inode *inode /* assert("nikita-648", len != NULL); assert("nikita-649", *len > 0); - if (*len >= (int) sizeof (reiser4_flags_stat)) { + if (*len >= (int)sizeof(reiser4_flags_stat)) { reiser4_flags_stat *sd; sd = (reiser4_flags_stat *) * area; @@ -712,16 +525,14 @@ present_flags_sd(struct inode *inode /* } /* Audited by: green(2002.06.14) */ -static int -save_len_flags_sd(struct inode *inode UNUSED_ARG /* object being - * processed */ ) +static int save_len_flags_sd(struct inode *inode UNUSED_ARG /* object being + * processed */ ) { - return sizeof (reiser4_flags_stat); + return sizeof(reiser4_flags_stat); } -static int -save_flags_sd(struct inode *inode /* object being processed */ , - char **area /* position in stat-data */ ) +static int save_flags_sd(struct inode *inode /* object being processed */ , + char **area /* position in stat-data */ ) { reiser4_flags_stat *sd; @@ -736,10 +547,9 @@ save_flags_sd(struct inode *inode /* obj } static int absent_plugin_sd(struct inode *inode); -static int -present_plugin_sd(struct inode *inode /* object being processed */ , - char **area /* position in stat-data */ , - int *len /* remaining length */ ) +static int present_plugin_sd(struct inode *inode /* object being processed */ , + char **area /* position in stat-data */ , + int *len /* remaining length */ ) { reiser4_plugin_stat *sd; reiser4_plugin *plugin; @@ -754,7 +564,7 @@ present_plugin_sd(struct inode *inode /* assert("nikita-656", len != NULL); assert("nikita-657", *len > 0); - if (*len < (int) sizeof (reiser4_plugin_stat)) + if (*len < (int)sizeof(reiser4_plugin_stat)) return not_enough_space(inode, "plugin"); sd = (reiser4_plugin_stat *) * area; @@ -765,18 +575,19 @@ present_plugin_sd(struct inode *inode /* result = 0; for (i = 0; i < num_of_plugins; ++i) { reiser4_plugin_slot *slot; - reiser4_plugin_type type; - pset_member memb; + reiser4_plugin_type type; + pset_member memb; slot = (reiser4_plugin_slot *) * area; - if (*len < (int) sizeof *slot) + if (*len < (int)sizeof *slot) return not_enough_space(inode, "additional plugin"); memb = d16tocpu(&slot->pset_memb); type = pset_member_to_type_unsafe(memb); if (type == REISER4_PLUGIN_TYPES) { - warning("nikita-3502", "wrong pset member (%i) for %llu", - memb, (unsigned long long)get_inode_oid(inode)); + warning("nikita-3502", + "wrong pset member (%i) for %llu", memb, + (unsigned long long)get_inode_oid(inode)); return RETERR(-EINVAL); } plugin = plugin_by_disk_id(tree_by_inode(inode), @@ -812,9 +623,57 @@ present_plugin_sd(struct inode *inode /* return result; } -/* Audited by: green(2002.06.14) */ +/* Determine object plugin for @inode based on i_mode. + + Many objects in reiser4 file system are controlled by standard object + plugins that emulate traditional unix objects: unix file, directory, symlink, fifo, and so on. + + For such files we don't explicitly store plugin id in object stat + data. Rather required plugin is guessed from mode bits, where file "type" + is encoded (see stat(2)). +*/ static int -absent_plugin_sd(struct inode *inode /* object being processed */ ) +guess_plugin_by_mode(struct inode *inode /* object to guess plugins for */ ) +{ + int fplug_id; + int dplug_id; + reiser4_inode *info; + + assert("nikita-736", inode != NULL); + + dplug_id = fplug_id = -1; + + switch (inode->i_mode & S_IFMT) { + case S_IFSOCK: + case S_IFBLK: + case S_IFCHR: + case S_IFIFO: + fplug_id = SPECIAL_FILE_PLUGIN_ID; + break; + case S_IFLNK: + fplug_id = SYMLINK_FILE_PLUGIN_ID; + break; + case S_IFDIR: + fplug_id = DIRECTORY_FILE_PLUGIN_ID; + dplug_id = HASHED_DIR_PLUGIN_ID; + break; + default: + warning("nikita-737", "wrong file mode: %o", inode->i_mode); + return RETERR(-EIO); + case S_IFREG: + fplug_id = UNIX_FILE_PLUGIN_ID; + break; + } + info = reiser4_inode_data(inode); + plugin_set_file(&info->pset, + (fplug_id >= 0) ? file_plugin_by_id(fplug_id) : NULL); + plugin_set_dir(&info->pset, + (dplug_id >= 0) ? dir_plugin_by_id(dplug_id) : NULL); + return 0; +} + +/* Audited by: green(2002.06.14) */ +static int absent_plugin_sd(struct inode *inode /* object being processed */ ) { int result; @@ -832,17 +691,16 @@ absent_plugin_sd(struct inode *inode /* /* helper function for plugin_sd_save_len(): calculate how much space required to save state of given plugin */ /* Audited by: green(2002.06.14) */ -static int -len_for(reiser4_plugin * plugin /* plugin to save */ , - struct inode *inode /* object being processed */ , - pset_member memb, int len) +static int len_for(reiser4_plugin * plugin /* plugin to save */ , + struct inode *inode /* object being processed */ , + pset_member memb, int len) { reiser4_inode *info; assert("nikita-661", inode != NULL); info = reiser4_inode_data(inode); if (plugin != NULL && (info->plugin_mask & (1 << memb))) { - len += sizeof (reiser4_plugin_slot); + len += sizeof(reiser4_plugin_slot); if (plugin->h.pops && plugin->h.pops->save_len != NULL) { /* non-standard plugin, call method */ /* commented as it is incompatible with alignment @@ -856,8 +714,7 @@ len_for(reiser4_plugin * plugin /* plugi /* calculate how much space is required to save state of all plugins, associated with inode */ -static int -save_len_plugin_sd(struct inode *inode /* object being processed */ ) +static int save_len_plugin_sd(struct inode *inode /* object being processed */ ) { int len; reiser4_inode *state; @@ -869,21 +726,20 @@ save_len_plugin_sd(struct inode *inode / /* common case: no non-standard plugins */ if (state->plugin_mask == 0) return 0; - len = sizeof (reiser4_plugin_stat); - for (memb = 0; memb < PSET_LAST; ++ memb) + len = sizeof(reiser4_plugin_stat); + for (memb = 0; memb < PSET_LAST; ++memb) len = len_for(pset_get(state->pset, memb), inode, memb, len); - assert("nikita-664", len > (int) sizeof (reiser4_plugin_stat)); + assert("nikita-664", len > (int)sizeof(reiser4_plugin_stat)); return len; } /* helper function for plugin_sd_save(): save plugin, associated with inode. */ -static int -save_plug(reiser4_plugin * plugin /* plugin to save */ , - struct inode *inode /* object being processed */ , - pset_member memb /* what element of pset is saved*/, - char **area /* position in stat-data */ , - int *count /* incremented if plugin were actually +static int save_plug(reiser4_plugin * plugin /* plugin to save */ , + struct inode *inode /* object being processed */ , + pset_member memb /* what element of pset is saved */ , + char **area /* position in stat-data */ , + int *count /* incremented if plugin were actually * saved. */ ) { reiser4_plugin_slot *slot; @@ -900,8 +756,8 @@ save_plug(reiser4_plugin * plugin /* plu return 0; slot = (reiser4_plugin_slot *) * area; cputod16(memb, &slot->pset_memb); - cputod16((unsigned) plugin->h.id, &slot->id); - fake_len = (int) 0xffff; + cputod16((unsigned)plugin->h.id, &slot->id); + fake_len = (int)0xffff; move_on(&fake_len, area, sizeof *slot); ++*count; result = 0; @@ -913,9 +769,8 @@ save_plug(reiser4_plugin * plugin /* plu } /* save state of all non-standard plugins associated with inode */ -static int -save_plugin_sd(struct inode *inode /* object being processed */ , - char **area /* position in stat-data */ ) +static int save_plugin_sd(struct inode *inode /* object being processed */ , + char **area /* position in stat-data */ ) { int result = 0; int num_of_plugins; @@ -932,46 +787,45 @@ save_plugin_sd(struct inode *inode /* ob if (state->plugin_mask == 0) return 0; sd = (reiser4_plugin_stat *) * area; - fake_len = (int) 0xffff; + fake_len = (int)0xffff; move_on(&fake_len, area, sizeof *sd); num_of_plugins = 0; - for (memb = 0; memb < PSET_LAST; ++ memb) { + for (memb = 0; memb < PSET_LAST; ++memb) { result = save_plug(pset_get(state->pset, memb), inode, memb, area, &num_of_plugins); if (result != 0) break; } - cputod16((unsigned) num_of_plugins, &sd->plugins_no); + cputod16((unsigned)num_of_plugins, &sd->plugins_no); return result; } - /* helper function for crypto_sd_present(), crypto_sd_save. Allocates memory for crypto stat, keyid and attaches it to the inode */ -static int crypto_stat_to_inode (struct inode *inode, - reiser4_crypto_stat * sd, - unsigned int size /* fingerprint size */) +static int crypto_stat_to_inode(struct inode *inode, + reiser4_crypto_stat * sd, + unsigned int size /* fingerprint size */ ) { - crypto_stat_t * stat; + crypto_stat_t *stat; - assert ("edward-11", (cryptcompress_inode_data(inode))->crypt == NULL); - assert ("edward-33", !inode_get_flag(inode, REISER4_CRYPTO_STAT_LOADED)); + assert("edward-11", (cryptcompress_inode_data(inode))->crypt == NULL); + assert("edward-33", !inode_get_flag(inode, REISER4_CRYPTO_STAT_LOADED)); - stat = reiser4_kmalloc(sizeof(*stat), GFP_KERNEL); + stat = kmalloc(sizeof(*stat), GFP_KERNEL); if (!stat) return RETERR(-ENOMEM); memset(stat, 0, sizeof *stat); - stat->keyid = reiser4_kmalloc((size_t)size, GFP_KERNEL); + stat->keyid = kmalloc((size_t) size, GFP_KERNEL); if (!stat->keyid) { - reiser4_kfree(stat); + kfree(stat); return RETERR(-ENOMEM); } /* load inode crypto-stat */ stat->keysize = d16tocpu(&sd->keysize); - memcpy(stat->keyid, sd->keyid, (size_t)size); + memcpy(stat->keyid, sd->keyid, (size_t) size); cryptcompress_inode_data(inode)->crypt = stat; inode_set_flag(inode, REISER4_CRYPTO_STAT_LOADED); @@ -984,7 +838,7 @@ static int present_crypto_sd(struct inod { int result; reiser4_crypto_stat *sd; - digest_plugin * dplug = inode_digest_plugin(inode); + digest_plugin *dplug = inode_digest_plugin(inode); unsigned int keyid_size; assert("edward-06", dplug != NULL); @@ -994,7 +848,7 @@ static int present_crypto_sd(struct inod assert("edward-09", len != NULL); assert("edward-10", *len > 0); - if (*len < (int) sizeof (reiser4_crypto_stat)) { + if (*len < (int)sizeof(reiser4_crypto_stat)) { return not_enough_space(inode, "crypto-sd"); } keyid_size = dplug->dsize; @@ -1009,38 +863,39 @@ static int present_crypto_sd(struct inod return result; } -static int absent_crypto_sd(struct inode * inode) +static int absent_crypto_sd(struct inode *inode) { return -EIO; } static int save_len_crypto_sd(struct inode *inode) { - return (sizeof(reiser4_crypto_stat) + inode_digest_plugin(inode)->dsize); + return (sizeof(reiser4_crypto_stat) + + inode_digest_plugin(inode)->dsize); } static int save_crypto_sd(struct inode *inode, char **area) { int result = 0; reiser4_crypto_stat *sd; - digest_plugin * dplug = inode_digest_plugin(inode); + digest_plugin *dplug = inode_digest_plugin(inode); assert("edward-12", dplug != NULL); assert("edward-13", area != NULL); assert("edward-14", *area != NULL); assert("edward-76", reiser4_inode_data(inode) != NULL); - sd = (reiser4_crypto_stat *) *area; + sd = (reiser4_crypto_stat *) * area; if (!inode_get_flag(inode, REISER4_CRYPTO_STAT_LOADED)) { /* file is just created */ - crypto_stat_t * stat; + crypto_stat_t *stat; stat = cryptcompress_inode_data(inode)->crypt; assert("edward-15", stat != NULL); /* copy everything but private key to the disk stat-data */ cputod16(stat->keysize, &sd->keysize); - memcpy(sd->keyid, stat->keyid, (size_t)dplug->dsize); + memcpy(sd->keyid, stat->keyid, (size_t) dplug->dsize); inode_set_flag(inode, REISER4_CRYPTO_STAT_LOADED); } else { /* do nothing */ @@ -1049,20 +904,6 @@ static int save_crypto_sd(struct inode * return result; } -#ifdef REISER4_DEBUG_OUTPUT -static void -print_crypto_sd(const char *prefix, char **area /* position in stat-data */ , - int *len /* remaining length */ ) -{ - /* FIXME-EDWARD Make sure we debug only with none digest plugin */ - digest_plugin * dplug = digest_plugin_by_id(NONE_DIGEST_ID); - reiser4_crypto_stat *sd = (reiser4_crypto_stat *) * area; - - printk("%s: keysize: %u keyid: \"%llx\"\n", prefix, d16tocpu(&sd->keysize), *(__u64 *)(sd->keyid)); - move_on(len, area, sizeof(*sd) + dplug->dsize); -} -#endif - static int eio(struct inode *inode, char **area, int *len) { return RETERR(-EIO); @@ -1070,150 +911,127 @@ static int eio(struct inode *inode, char sd_ext_plugin sd_ext_plugins[LAST_SD_EXTENSION] = { [LIGHT_WEIGHT_STAT] = { - .h = { - .type_id = REISER4_SD_EXT_PLUGIN_TYPE, - .id = LIGHT_WEIGHT_STAT, - .pops = NULL, - .label = "light-weight sd", - .desc = "sd for light-weight files", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .present = present_lw_sd, - .absent = NULL, - .save_len = save_len_lw_sd, - .save = save_lw_sd, -#ifdef REISER4_DEBUG_OUTPUT - .print = print_lw_sd, -#endif - .alignment = 8 + .h = { + .type_id = REISER4_SD_EXT_PLUGIN_TYPE, + .id = LIGHT_WEIGHT_STAT, + .pops = NULL, + .label = "light-weight sd", + .desc = "sd for light-weight files", + .linkage = {NULL,NULL} + }, + .present = present_lw_sd, + .absent = NULL, + .save_len = save_len_lw_sd, + .save = save_lw_sd, + .alignment = 8 }, [UNIX_STAT] = { - .h = { - .type_id = REISER4_SD_EXT_PLUGIN_TYPE, - .id = UNIX_STAT, - .pops = NULL, - .label = "unix-sd", - .desc = "unix stat-data fields", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .present = present_unix_sd, - .absent = absent_unix_sd, - .save_len = save_len_unix_sd, - .save = save_unix_sd, -#ifdef REISER4_DEBUG_OUTPUT - .print = print_unix_sd, -#endif - .alignment = 8 + .h = { + .type_id = REISER4_SD_EXT_PLUGIN_TYPE, + .id = UNIX_STAT, + .pops = NULL, + .label = "unix-sd", + .desc = "unix stat-data fields", + .linkage = {NULL,NULL} + }, + .present = present_unix_sd, + .absent = absent_unix_sd, + .save_len = save_len_unix_sd, + .save = save_unix_sd, + .alignment = 8 }, [LARGE_TIMES_STAT] = { - .h = { - .type_id = REISER4_SD_EXT_PLUGIN_TYPE, - .id = LARGE_TIMES_STAT, - .pops = NULL, - .label = "64time-sd", - .desc = "nanosecond resolution for times", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .present = present_large_times_sd, - .absent = NULL, - .save_len = save_len_large_times_sd, - .save = save_large_times_sd, -#ifdef REISER4_DEBUG_OUTPUT - .print = print_large_times_sd, -#endif - .alignment = 8 + .h = { + .type_id = REISER4_SD_EXT_PLUGIN_TYPE, + .id = LARGE_TIMES_STAT, + .pops = NULL, + .label = "64time-sd", + .desc = "nanosecond resolution for times", + .linkage = {NULL,NULL} + }, + .present = present_large_times_sd, + .absent = NULL, + .save_len = save_len_large_times_sd, + .save = save_large_times_sd, + .alignment = 8 }, [SYMLINK_STAT] = { - /* stat data of symlink has this extension */ - .h = { - .type_id = REISER4_SD_EXT_PLUGIN_TYPE, - .id = SYMLINK_STAT, - .pops = NULL, - .label = "symlink-sd", - .desc = "stat data is appended with symlink name", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .present = present_symlink_sd, - .absent = NULL, - .save_len = save_len_symlink_sd, - .save = save_symlink_sd, -#ifdef REISER4_DEBUG_OUTPUT - .print = print_symlink_sd, -#endif - .alignment = 8 + /* stat data of symlink has this extension */ + .h = { + .type_id = REISER4_SD_EXT_PLUGIN_TYPE, + .id = SYMLINK_STAT, + .pops = NULL, + .label = "symlink-sd", + .desc = + "stat data is appended with symlink name", + .linkage = {NULL,NULL} + }, + .present = present_symlink_sd, + .absent = NULL, + .save_len = save_len_symlink_sd, + .save = save_symlink_sd, + .alignment = 8 }, [PLUGIN_STAT] = { - .h = { - .type_id = REISER4_SD_EXT_PLUGIN_TYPE, - .id = PLUGIN_STAT, - .pops = NULL, - .label = "plugin-sd", - .desc = "plugin stat-data fields", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .present = present_plugin_sd, - .absent = absent_plugin_sd, - .save_len = save_len_plugin_sd, - .save = save_plugin_sd, -#ifdef REISER4_DEBUG_OUTPUT - .print = NULL, -#endif - .alignment = 8 + .h = { + .type_id = REISER4_SD_EXT_PLUGIN_TYPE, + .id = PLUGIN_STAT, + .pops = NULL, + .label = "plugin-sd", + .desc = "plugin stat-data fields", + .linkage = {NULL,NULL} + }, + .present = present_plugin_sd, + .absent = absent_plugin_sd, + .save_len = save_len_plugin_sd, + .save = save_plugin_sd, + .alignment = 8 }, [FLAGS_STAT] = { - .h = { - .type_id = REISER4_SD_EXT_PLUGIN_TYPE, - .id = FLAGS_STAT, - .pops = NULL, - .label = "flags-sd", - .desc = "inode bit flags", - .linkage = TYPE_SAFE_LIST_LINK_ZERO} - , - .present = present_flags_sd, - .absent = NULL, - .save_len = save_len_flags_sd, - .save = save_flags_sd, -#ifdef REISER4_DEBUG_OUTPUT - .print = NULL, -#endif - .alignment = 8 + .h = { + .type_id = REISER4_SD_EXT_PLUGIN_TYPE, + .id = FLAGS_STAT, + .pops = NULL, + .label = "flags-sd", + .desc = "inode bit flags", + .linkage = {NULL, NULL} + }, + .present = present_flags_sd, + .absent = NULL, + .save_len = save_len_flags_sd, + .save = save_flags_sd, + .alignment = 8 }, [CAPABILITIES_STAT] = { - .h = { - .type_id = REISER4_SD_EXT_PLUGIN_TYPE, - .id = CAPABILITIES_STAT, - .pops = NULL, - .label = "capabilities-sd", - .desc = "capabilities", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .present = eio, - .absent = NULL, - .save_len = save_len_flags_sd, - .save = save_flags_sd, -#ifdef REISER4_DEBUG_OUTPUT - .print = NULL, -#endif - .alignment = 8 + .h = { + .type_id = REISER4_SD_EXT_PLUGIN_TYPE, + .id = CAPABILITIES_STAT, + .pops = NULL, + .label = "capabilities-sd", + .desc = "capabilities", + .linkage = {NULL, NULL} + }, + .present = eio, + .absent = NULL, + .save_len = save_len_flags_sd, + .save = save_flags_sd, + .alignment = 8 }, [CRYPTO_STAT] = { - .h = { - .type_id = REISER4_SD_EXT_PLUGIN_TYPE, - .id = CRYPTO_STAT, - .pops = NULL, - .label = "crypto-sd", - .desc = "secret key size and id", - .linkage = TYPE_SAFE_LIST_LINK_ZERO} - , - .present = present_crypto_sd, - .absent = absent_crypto_sd, - /* return IO_ERROR if smthng is wrong */ - .save_len = save_len_crypto_sd, - .save = save_crypto_sd, -#ifdef REISER4_DEBUG_OUTPUT - .print = print_crypto_sd, -#endif - .alignment = 8 + .h = { + .type_id = REISER4_SD_EXT_PLUGIN_TYPE, + .id = CRYPTO_STAT, + .pops = NULL, + .label = "crypto-sd", + .desc = "secret key size and id", + .linkage = {NULL, NULL} + }, + .present = present_crypto_sd, + .absent = absent_crypto_sd, + /* return IO_ERROR if smthng is wrong */ + .save_len = save_len_crypto_sd, + .save = save_crypto_sd, + .alignment = 8 } }; diff -puN fs/reiser4/plugin/item/static_stat.h~reiser4-big-update fs/reiser4/plugin/item/static_stat.h --- devel/fs/reiser4/plugin/item/static_stat.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/static_stat.h 2005-09-15 19:51:08.000000000 -0700 @@ -23,23 +23,25 @@ reiser4 is working, then fix it...:-) /* Stat data layout: goals and implementation. -We want to be able to have lightweight files which have complete flexibility in what semantic metadata is attached to -them, including not having semantic metadata attached to them. + We want to be able to have lightweight files which have complete flexibility in what semantic metadata is attached to + them, including not having semantic metadata attached to them. -There is one problem with doing that, which is that if in fact you have exactly the same metadata for most files you want to store, then it takes more space to store that metadata in a dynamically sized structure than in a statically sized structure because the statically sized structure knows without recording it what the names and lengths of the attributes are. + There is one problem with doing that, which is that if in fact you have exactly the same metadata for most files you + want to store, then it takes more space to store that metadata in a dynamically sized structure than in a statically + sized structure because the statically sized structure knows without recording it what the names and lengths of the + attributes are. -This leads to a natural compromise, which is to special case those files which have simply the standard unix file -attributes, and only employ the full dynamic stat data mechanism for those files that differ from the standard unix file -in their use of file attributes. + This leads to a natural compromise, which is to special case those files which have simply the standard unix file + attributes, and only employ the full dynamic stat data mechanism for those files that differ from the standard unix + file in their use of file attributes. -Yet this compromise deserves to be compromised a little. + Yet this compromise deserves to be compromised a little. -We accommodate the case where you have no more than the standard unix file attributes by using an "extension bitmask": -each bit in it indicates presence or absence of or particular stat data extension (see sd_ext_bits enum). + We accommodate the case where you have no more than the standard unix file attributes by using an "extension + bitmask": each bit in it indicates presence or absence of or particular stat data extension (see sd_ext_bits enum). - If the first -bit of the extension bitmask bit is 0, we have light-weight file whose attributes are either inherited from parent -directory (as uid, gid) or initialised to some sane values. + If the first bit of the extension bitmask bit is 0, we have light-weight file whose attributes are either inherited + from parent directory (as uid, gid) or initialised to some sane values. To capitalize on existing code infrastructure, extensions are implemented as plugins of type REISER4_SD_EXT_PLUGIN_TYPE. @@ -58,7 +60,7 @@ typedef enum { /* support for light-weight files */ LIGHT_WEIGHT_STAT, /* data required to implement unix stat(2) call. Layout is in - reiser4_unix_stat. If this is not present, file is light-weight */ + reiser4_unix_stat. If this is not present, file is light-weight */ UNIX_STAT, /* this contains additional set of 32bit [anc]time fields to implement nanosecond resolution. Layout is in reiser4_large_times_stat. Usage @@ -67,15 +69,15 @@ typedef enum { /* stat data has link name included */ SYMLINK_STAT, /* if this is present, file is controlled by non-standard - plugin (that is, plugin that cannot be deduced from file - mode bits), for example, aggregation, interpolation etc. */ + plugin (that is, plugin that cannot be deduced from file + mode bits), for example, aggregation, interpolation etc. */ PLUGIN_STAT, /* this extension contains persistent inode flags. These flags are single bits: immutable, append, only, etc. Layout is in reiser4_flags_stat. */ FLAGS_STAT, /* this extension contains capabilities sets, associated with this - file. Layout is in reiser4_capabilities_stat */ + file. Layout is in reiser4_capabilities_stat */ CAPABILITIES_STAT, /* this extension contains size and public id of the secret key. Layout is in reiser4_crypto_stat */ @@ -122,10 +124,10 @@ typedef struct reiser4_unix_stat { /* change time */ /* 16 */ d32 ctime; union { - /* minor:major for device files */ - /* 20 */ d64 rdev; - /* bytes used by file */ - /* 20 */ d64 bytes; + /* minor:major for device files */ + /* 20 */ d64 rdev; + /* bytes used by file */ + /* 20 */ d64 bytes; } u; /* 28 */ } PACKED reiser4_unix_stat; @@ -138,7 +140,7 @@ typedef struct reiser4_symlink_stat { typedef struct reiser4_plugin_slot { /* 0 */ d16 pset_memb; /* 2 */ d16 id; -/* 4 *//* here plugin stores its persistent state */ + /* 4 *//* here plugin stores its persistent state */ } PACKED reiser4_plugin_slot; /* stat-data extension for files with non-standard plugin. */ diff -puN fs/reiser4/plugin/item/tail.c~reiser4-big-update fs/reiser4/plugin/item/tail.c --- devel/fs/reiser4/plugin/item/tail.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/tail.c 2005-09-15 19:51:08.000000000 -0700 @@ -12,8 +12,7 @@ #include /* plugin->u.item.b.max_key_inside */ -reiser4_internal reiser4_key * -max_key_inside_tail(const coord_t *coord, reiser4_key *key) +reiser4_key *max_key_inside_tail(const coord_t * coord, reiser4_key * key) { item_key_by_coord(coord, key); set_key_offset(key, get_key_offset(max_key())); @@ -21,8 +20,9 @@ max_key_inside_tail(const coord_t *coord } /* plugin->u.item.b.can_contain_key */ -reiser4_internal int -can_contain_key_tail(const coord_t *coord, const reiser4_key *key, const reiser4_item_data *data) +int +can_contain_key_tail(const coord_t * coord, const reiser4_key * key, + const reiser4_item_data * data) { reiser4_key item_key; @@ -31,7 +31,8 @@ can_contain_key_tail(const coord_t *coor item_key_by_coord(coord, &item_key); if (get_key_locality(key) != get_key_locality(&item_key) || - get_key_objectid(key) != get_key_objectid(&item_key)) return 0; + get_key_objectid(key) != get_key_objectid(&item_key)) + return 0; return 1; } @@ -39,12 +40,12 @@ can_contain_key_tail(const coord_t *coor /* plugin->u.item.b.mergeable first item is of tail type */ /* Audited by: green(2002.06.14) */ -reiser4_internal int -mergeable_tail(const coord_t *p1, const coord_t *p2) +int mergeable_tail(const coord_t * p1, const coord_t * p2) { reiser4_key key1, key2; - assert("vs-535", item_type_by_coord(p1) == UNIX_FILE_METADATA_ITEM_TYPE); + assert("vs-535", + item_type_by_coord(p1) == UNIX_FILE_METADATA_ITEM_TYPE); assert("vs-365", item_id_by_coord(p1) == FORMATTING_ID); if (item_id_by_coord(p2) != FORMATTING_ID) { @@ -55,7 +56,8 @@ mergeable_tail(const coord_t *p1, const item_key_by_coord(p1, &key1); item_key_by_coord(p2, &key2); if (get_key_locality(&key1) != get_key_locality(&key2) || - get_key_objectid(&key1) != get_key_objectid(&key2) || get_key_type(&key1) != get_key_type(&key2)) { + get_key_objectid(&key1) != get_key_objectid(&key2) + || get_key_type(&key1) != get_key_type(&key2)) { /* items of different objects */ return 0; } @@ -70,15 +72,14 @@ mergeable_tail(const coord_t *p1, const plugin->u.item.b.check */ /* plugin->u.item.b.nr_units */ -reiser4_internal pos_in_node_t -nr_units_tail(const coord_t *coord) +pos_in_node_t nr_units_tail(const coord_t * coord) { return item_length_by_coord(coord); } /* plugin->u.item.b.lookup */ -reiser4_internal lookup_result -lookup_tail(const reiser4_key *key, lookup_bias bias, coord_t *coord) +lookup_result +lookup_tail(const reiser4_key * key, lookup_bias bias, coord_t * coord) { reiser4_key item_key; __u64 lookuped, offset; @@ -104,12 +105,14 @@ lookup_tail(const reiser4_key *key, look /* set coord after last unit */ coord->unit_pos = nr_units - 1; coord->between = AFTER_UNIT; - return bias == FIND_MAX_NOT_MORE_THAN ? CBK_COORD_FOUND : CBK_COORD_NOTFOUND; + return bias == + FIND_MAX_NOT_MORE_THAN ? CBK_COORD_FOUND : CBK_COORD_NOTFOUND; } /* plugin->u.item.b.paste */ -reiser4_internal int -paste_tail(coord_t *coord, reiser4_item_data *data, carry_plugin_info *info UNUSED_ARG) +int +paste_tail(coord_t *coord, reiser4_item_data *data, + carry_plugin_info *info UNUSED_ARG) { unsigned old_item_length; char *item; @@ -122,7 +125,8 @@ paste_tail(coord_t *coord, reiser4_item_ (coord->unit_pos == 0 && coord->between == BEFORE_UNIT) || (coord->unit_pos == old_item_length - 1 && coord->between == AFTER_UNIT) || - (coord->unit_pos == 0 && old_item_length == 0 && coord->between == AT_UNIT)); + (coord->unit_pos == 0 && old_item_length == 0 + && coord->between == AT_UNIT)); item = item_body_by_coord(coord); if (coord->unit_pos == 0) @@ -137,14 +141,17 @@ paste_tail(coord_t *coord, reiser4_item_ assert("vs-554", data->user == 0 || data->user == 1); if (data->user) { assert("nikita-3035", schedulable()); - /* AUDIT: return result is not checked! */ /* copy from user space */ - __copy_from_user(item + coord->unit_pos, data->data, (unsigned) data->length); + if (__copy_from_user(item + coord->unit_pos, + (const char __user *)data->data, + (unsigned)data->length)) + return RETERR(-EFAULT); } else /* copy from kernel space */ - memcpy(item + coord->unit_pos, data->data, (unsigned) data->length); + memcpy(item + coord->unit_pos, data->data, + (unsigned)data->length); } else { - memset(item + coord->unit_pos, 0, (unsigned) data->length); + memset(item + coord->unit_pos, 0, (unsigned)data->length); } return 0; } @@ -154,57 +161,64 @@ paste_tail(coord_t *coord, reiser4_item_ /* plugin->u.item.b.can_shift number of units is returned via return value, number of bytes via @size. For tail items they coincide */ -reiser4_internal int -can_shift_tail(unsigned free_space, coord_t *source UNUSED_ARG, - znode *target UNUSED_ARG, shift_direction direction UNUSED_ARG, unsigned *size, unsigned want) +int +can_shift_tail(unsigned free_space, coord_t * source UNUSED_ARG, + znode * target UNUSED_ARG, shift_direction direction UNUSED_ARG, + unsigned *size, unsigned want) { /* make sure that that we do not want to shift more than we have */ - assert("vs-364", want > 0 && want <= (unsigned) item_length_by_coord(source)); + assert("vs-364", want > 0 + && want <= (unsigned)item_length_by_coord(source)); *size = min(want, free_space); return *size; } /* plugin->u.item.b.copy_units */ -reiser4_internal void -copy_units_tail(coord_t *target, coord_t *source, - unsigned from, unsigned count, shift_direction where_is_free_space, unsigned free_space UNUSED_ARG) +void +copy_units_tail(coord_t * target, coord_t * source, + unsigned from, unsigned count, + shift_direction where_is_free_space, + unsigned free_space UNUSED_ARG) { /* make sure that item @target is expanded already */ - assert("vs-366", (unsigned) item_length_by_coord(target) >= count); + assert("vs-366", (unsigned)item_length_by_coord(target) >= count); assert("vs-370", free_space >= count); if (where_is_free_space == SHIFT_LEFT) { /* append item @target with @count first bytes of @source */ assert("vs-365", from == 0); - memcpy((char *) item_body_by_coord(target) + - item_length_by_coord(target) - count, (char *) item_body_by_coord(source), count); + memcpy((char *)item_body_by_coord(target) + + item_length_by_coord(target) - count, + (char *)item_body_by_coord(source), count); } else { /* target item is moved to right already */ reiser4_key key; - assert("vs-367", (unsigned) item_length_by_coord(source) == from + count); + assert("vs-367", + (unsigned)item_length_by_coord(source) == from + count); - memcpy((char *) item_body_by_coord(target), (char *) item_body_by_coord(source) + from, count); + memcpy((char *)item_body_by_coord(target), + (char *)item_body_by_coord(source) + from, count); /* new units are inserted before first unit in an item, therefore, we have to update item key */ item_key_by_coord(source, &key); set_key_offset(&key, get_key_offset(&key) + from); - node_plugin_by_node(target->node)->update_item_key(target, &key, 0 /*info */); + node_plugin_by_node(target->node)->update_item_key(target, &key, + NULL /*info */); } } /* plugin->u.item.b.create_hook */ - /* item_plugin->b.kill_hook this is called when @count units starting from @from-th one are going to be removed */ -reiser4_internal int -kill_hook_tail(const coord_t *coord, pos_in_node_t from, +int +kill_hook_tail(const coord_t * coord, pos_in_node_t from, pos_in_node_t count, struct carry_kill_data *kdata) { reiser4_key key; @@ -224,8 +238,8 @@ kill_hook_tail(const coord_t *coord, pos /* helper for kill_units_tail and cut_units_tail */ static int -do_cut_or_kill(coord_t *coord, pos_in_node_t from, pos_in_node_t to, - reiser4_key *smallest_removed, reiser4_key *new_first) +do_cut_or_kill(coord_t * coord, pos_in_node_t from, pos_in_node_t to, + reiser4_key * smallest_removed, reiser4_key * new_first) { pos_in_node_t count; @@ -240,41 +254,44 @@ do_cut_or_kill(coord_t *coord, pos_in_no if (smallest_removed) { /* store smallest key removed */ item_key_by_coord(coord, smallest_removed); - set_key_offset(smallest_removed, get_key_offset(smallest_removed) + from); + set_key_offset(smallest_removed, + get_key_offset(smallest_removed) + from); } if (new_first) { /* head of item is cut */ assert("vs-1529", from == 0); item_key_by_coord(coord, new_first); - set_key_offset(new_first, get_key_offset(new_first) + from + count); + set_key_offset(new_first, + get_key_offset(new_first) + from + count); } if (REISER4_DEBUG) - memset((char *) item_body_by_coord(coord) + from, 0, count); + memset((char *)item_body_by_coord(coord) + from, 0, count); return count; } /* plugin->u.item.b.cut_units */ -reiser4_internal int -cut_units_tail(coord_t *coord, pos_in_node_t from, pos_in_node_t to, - struct carry_cut_data *cdata UNUSED_ARG, reiser4_key *smallest_removed, reiser4_key *new_first) +int +cut_units_tail(coord_t * coord, pos_in_node_t from, pos_in_node_t to, + struct carry_cut_data *cdata UNUSED_ARG, + reiser4_key * smallest_removed, reiser4_key * new_first) { return do_cut_or_kill(coord, from, to, smallest_removed, new_first); } /* plugin->u.item.b.kill_units */ -reiser4_internal int -kill_units_tail(coord_t *coord, pos_in_node_t from, pos_in_node_t to, - struct carry_kill_data *kdata, reiser4_key *smallest_removed, reiser4_key *new_first) +int +kill_units_tail(coord_t * coord, pos_in_node_t from, pos_in_node_t to, + struct carry_kill_data *kdata, reiser4_key * smallest_removed, + reiser4_key * new_first) { kill_hook_tail(coord, from, to - from + 1, kdata); return do_cut_or_kill(coord, from, to, smallest_removed, new_first); } /* plugin->u.item.b.unit_key */ -reiser4_internal reiser4_key * -unit_key_tail(const coord_t *coord, reiser4_key *key) +reiser4_key *unit_key_tail(const coord_t * coord, reiser4_key * key) { assert("vs-375", coord_is_existing_unit(coord)); @@ -288,8 +305,7 @@ unit_key_tail(const coord_t *coord, reis plugin->u.item.b.item_data_by_flow */ /* overwrite tail item or its part by use data */ -static int -overwrite_tail(coord_t *coord, flow_t *f) +static int overwrite_tail(coord_t *coord, flow_t *f) { unsigned count; @@ -303,7 +319,8 @@ overwrite_tail(coord_t *coord, flow_t *f if (count > f->length) count = f->length; - if (__copy_from_user((char *) item_body_by_coord(coord) + coord->unit_pos, f->data, count)) + if (__copy_from_user((char *)item_body_by_coord(coord) + coord->unit_pos, + (const char __user *)f->data, count)) return RETERR(-EFAULT); znode_make_dirty(coord->node); @@ -313,8 +330,7 @@ overwrite_tail(coord_t *coord, flow_t *f } /* tail redpage function. It is called from readpage_tail(). */ -static int -do_readpage_tail(uf_coord_t *uf_coord, struct page *page) +static int do_readpage_tail(uf_coord_t * uf_coord, struct page *page) { tap_t tap; int result; @@ -350,7 +366,8 @@ do_readpage_tail(uf_coord_t *uf_coord, s /* copying tail body to page. */ memcpy(pagedata + mapped, - ((char *)item_body_by_coord(&coord) + coord.unit_pos), count); + ((char *)item_body_by_coord(&coord) + coord.unit_pos), + count); flush_dcache_page(page); @@ -387,7 +404,8 @@ do_readpage_tail(uf_coord_t *uf_coord, s } } else { /* check if found coord is not owned by file. */ - if (!inode_file_plugin(inode)->owns_item(inode, &coord)) { + if (!inode_file_plugin(inode)-> + owns_item(inode, &coord)) { result = 0; goto out_update_page; } @@ -405,13 +423,13 @@ do_readpage_tail(uf_coord_t *uf_coord, s return 0; - out_update_page: + out_update_page: SetPageUptodate(page); - out_unlock_page: + out_unlock_page: unlock_page(page); - out_tap_relse: + out_tap_relse: tap_relse(&tap); - out_tap_done: + out_tap_done: tap_done(&tap); return result; } @@ -424,11 +442,10 @@ do_readpage_tail(uf_coord_t *uf_coord, s At the beginning: coord->node is read locked, zloaded, page is locked, coord is set to existing unit inside of tail item. */ -reiser4_internal int -readpage_tail(void *vp, struct page *page) +int readpage_tail(void *vp, struct page *page) { uf_coord_t *uf_coord = vp; - ON_DEBUG(coord_t *coord = &uf_coord->coord); + ON_DEBUG(coord_t * coord = &uf_coord->coord); ON_DEBUG(reiser4_key key); assert("umka-2515", PageLocked(page)); @@ -440,7 +457,9 @@ readpage_tail(void *vp, struct page *pag assert("umka-2520", item_is_tail(coord)); assert("umka-2521", coord_is_existing_unit(coord)); assert("umka-2522", znode_is_rlocked(coord->node)); - assert("umka-2523", page->mapping->host->i_ino == get_key_objectid(item_key_by_coord(coord, &key))); + assert("umka-2523", + page->mapping->host->i_ino == + get_key_objectid(item_key_by_coord(coord, &key))); return do_readpage_tail(uf_coord, page); } @@ -449,8 +468,8 @@ readpage_tail(void *vp, struct page *pag balance_dirty_pages. balance_dirty_pages may cause transaction to close, therefore we have to update stat data if necessary */ static int -tail_balance_dirty_pages(struct address_space *mapping, const flow_t *f, - hint_t *hint) +tail_balance_dirty_pages(struct address_space *mapping, const flow_t * f, + hint_t * hint) { int result; struct inode *inode; @@ -461,7 +480,6 @@ tail_balance_dirty_pages(struct address_ set_hint(hint, &f->key, ZNODE_WRITE_LOCK); else unset_hint(hint); - longterm_unlock_znode(hint->ext_coord.lh); inode = mapping->host; if (get_key_offset(&f->key) > inode->i_size) { @@ -480,9 +498,14 @@ tail_balance_dirty_pages(struct address_ if (!reiser4_is_set(inode->i_sb, REISER4_ATOMIC_WRITE)) { uf_info = unix_file_inode_data(inode); excl = unix_file_inode_data(inode)->exclusive_use; - if (excl) + if (excl) { + /* we are about to drop exclusive access. Set file + container to UF_CONTAINER_TAILS if file is not under + tail conversion */ + if (!inode_get_flag(inode, REISER4_PART_CONV)) + uf_info->container = UF_CONTAINER_TAILS; drop_exclusive_access(uf_info); - else + } else drop_nonexclusive_access(uf_info); reiser4_throttle_write(inode); if (excl) @@ -493,19 +516,20 @@ tail_balance_dirty_pages(struct address_ return 0; } -/* calculate number of blocks which can be dirtied/added when flow is inserted and stat data gets updated and grab them. - FIXME-VS: we may want to call grab_space with BA_CAN_COMMIT flag but that would require all that complexity with - sealing coord, releasing long term lock and validating seal later */ -static int -insert_flow_reserve(reiser4_tree *tree) +/* calculate number of blocks which can be dirtied/added when flow is inserted + and stat data gets updated and grab them. FIXME-VS: we may want to call + grab_space with BA_CAN_COMMIT flag but that would require all that + complexity with sealing coord, releasing long term lock and validating seal + later */ +static int insert_flow_reserve(reiser4_tree * tree) { grab_space_enable(); - return reiser4_grab_space(estimate_insert_flow(tree->height) + estimate_one_insert_into_item(tree), 0); + return reiser4_grab_space(estimate_insert_flow(tree->height) + + estimate_one_insert_into_item(tree), 0); } /* one block gets overwritten and stat data may get updated */ -static int -overwrite_reserve(reiser4_tree *tree) +static int overwrite_reserve(reiser4_tree * tree) { grab_space_enable(); return reiser4_grab_space(1 + estimate_one_insert_into_item(tree), 0); @@ -513,13 +537,11 @@ overwrite_reserve(reiser4_tree *tree) /* plugin->u.item.s.file.write access to data stored in tails goes directly through formatted nodes */ -reiser4_internal int -write_tail(struct inode *inode, flow_t *f, hint_t *hint, - int grabbed, /* tail's write may be called from plain unix file write and from tail conversion. In first - case (grabbed == 0) space is not reserved forehand, so, it must be done here. When it is - being called from tail conversion - space is reserved already for whole operation which may - involve several calls to item write. In this case space reservation will not be done here */ - write_mode_t mode) +int write_tail(struct inode *inode, flow_t * f, hint_t * hint, int grabbed, /* tail's write may be called from plain unix file write and from tail conversion. In first + case (grabbed == 0) space is not reserved forehand, so, it must be done here. When it is + being called from tail conversion - space is reserved already for whole operation which may + involve several calls to item write. In this case space reservation will not be done here */ + write_mode_t mode) { int result; coord_t *coord; @@ -539,16 +561,21 @@ write_tail(struct inode *inode, flow_t * } if (!grabbed) - result = insert_flow_reserve(znode_get_tree(coord->node)); + result = + insert_flow_reserve(znode_get_tree + (coord->node)); if (!result) - result = insert_flow(coord, hint->ext_coord.lh, f); + result = + insert_flow(coord, hint->ext_coord.lh, f); if (f->length) DQUOT_FREE_SPACE_NODIRTY(inode, f->length); break; case OVERWRITE_ITEM: if (!grabbed) - result = overwrite_reserve(znode_get_tree(coord->node)); + result = + overwrite_reserve(znode_get_tree + (coord->node)); if (!result) result = overwrite_tail(coord, f); break; @@ -564,7 +591,6 @@ write_tail(struct inode *inode, flow_t * if (!grabbed) all_grabbed2free(); unset_hint(hint); - longterm_unlock_znode(hint->ext_coord.lh); break; } @@ -575,10 +601,8 @@ write_tail(struct inode *inode, flow_t * result = tail_balance_dirty_pages(inode->i_mapping, f, hint); if (!grabbed) all_grabbed2free(); - if (result) { - // reiser4_stat_tail_add(bdp_caused_repeats); + if (result) break; - } } return result; @@ -587,22 +611,22 @@ write_tail(struct inode *inode, flow_t * #if REISER4_DEBUG static int -coord_matches_key_tail(const coord_t *coord, const reiser4_key *key) +coord_matches_key_tail(const coord_t * coord, const reiser4_key * key) { reiser4_key item_key; assert("vs-1356", coord_is_existing_unit(coord)); assert("vs-1354", keylt(key, append_key_tail(coord, &item_key))); assert("vs-1355", keyge(key, item_key_by_coord(coord, &item_key))); - return get_key_offset(key) == get_key_offset(&item_key) + coord->unit_pos; + return get_key_offset(key) == + get_key_offset(&item_key) + coord->unit_pos; } #endif /* plugin->u.item.s.file.read */ -reiser4_internal int -read_tail(struct file *file UNUSED_ARG, flow_t *f, hint_t *hint) +int read_tail(struct file *file UNUSED_ARG, flow_t *f, hint_t *hint) { unsigned count; int item_length; @@ -627,10 +651,11 @@ read_tail(struct file *file UNUSED_ARG, if (count > f->length) count = f->length; - - /* FIXME: unlock long term lock ! */ - - if (__copy_to_user(f->data, ((char *) item_body_by_coord(coord) + coord->unit_pos), count)) + /* user page has to be brought in so that major page fault does not + * occur here when longtem lock is held */ + if (__copy_to_user((char __user *)f->data, + ((char *)item_body_by_coord(coord) + coord->unit_pos), + count)) return RETERR(-EFAULT); /* probably mark_page_accessed() should only be called if @@ -640,7 +665,7 @@ read_tail(struct file *file UNUSED_ARG, coord->unit_pos += count; if (item_length == coord->unit_pos) { - coord->unit_pos --; + coord->unit_pos--; coord->between = AFTER_UNIT; } @@ -651,8 +676,7 @@ read_tail(struct file *file UNUSED_ARG, plugin->u.item.s.file.append_key key of first byte which is the next to last byte by addressed by this item */ -reiser4_internal reiser4_key * -append_key_tail(const coord_t *coord, reiser4_key *key) +reiser4_key *append_key_tail(const coord_t * coord, reiser4_key * key) { item_key_by_coord(coord, key); set_key_offset(key, get_key_offset(key) + item_length_by_coord(coord)); @@ -660,8 +684,7 @@ append_key_tail(const coord_t *coord, re } /* plugin->u.item.s.file.init_coord_extension */ -reiser4_internal void -init_coord_extension_tail(uf_coord_t *uf_coord, loff_t lookuped) +void init_coord_extension_tail(uf_coord_t * uf_coord, loff_t lookuped) { uf_coord->valid = 1; } @@ -669,13 +692,12 @@ init_coord_extension_tail(uf_coord_t *uf /* plugin->u.item.s.file.get_block */ -reiser4_internal int -get_block_address_tail(const coord_t *coord, sector_t block, struct buffer_head *bh) +int +get_block_address_tail(const coord_t * coord, sector_t lblock, sector_t * block) { - assert("nikita-3252", - znode_get_level(coord->node) == LEAF_LEVEL); + assert("nikita-3252", znode_get_level(coord->node) == LEAF_LEVEL); - bh->b_blocknr = *znode_get_block(coord->node); + *block = *znode_get_block(coord->node); return 0; } diff -puN fs/reiser4/plugin/item/tail.h~reiser4-big-update fs/reiser4/plugin/item/tail.h --- devel/fs/reiser4/plugin/item/tail.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/item/tail.h 2005-09-15 19:51:08.000000000 -0700 @@ -9,23 +9,27 @@ typedef struct { struct cut_list; - /* plugin->u.item.b.* */ reiser4_key *max_key_inside_tail(const coord_t *, reiser4_key *); -int can_contain_key_tail(const coord_t * coord, const reiser4_key * key, const reiser4_item_data *); +int can_contain_key_tail(const coord_t * coord, const reiser4_key * key, + const reiser4_item_data *); int mergeable_tail(const coord_t * p1, const coord_t * p2); pos_in_node_t nr_units_tail(const coord_t *); lookup_result lookup_tail(const reiser4_key *, lookup_bias, coord_t *); int paste_tail(coord_t *, reiser4_item_data *, carry_plugin_info *); int can_shift_tail(unsigned free_space, coord_t * source, - znode * target, shift_direction, unsigned *size, unsigned want); -void copy_units_tail(coord_t * target, coord_t * source, - unsigned from, unsigned count, shift_direction, unsigned free_space); -int kill_hook_tail(const coord_t *, pos_in_node_t from, pos_in_node_t count, struct carry_kill_data *); + znode * target, shift_direction, unsigned *size, + unsigned want); +void copy_units_tail(coord_t * target, coord_t * source, unsigned from, + unsigned count, shift_direction, unsigned free_space); +int kill_hook_tail(const coord_t *, pos_in_node_t from, pos_in_node_t count, + struct carry_kill_data *); int cut_units_tail(coord_t *, pos_in_node_t from, pos_in_node_t to, - struct carry_cut_data *, reiser4_key *smallest_removed, reiser4_key *new_first); + struct carry_cut_data *, reiser4_key * smallest_removed, + reiser4_key * new_first); int kill_units_tail(coord_t *, pos_in_node_t from, pos_in_node_t to, - struct carry_kill_data *, reiser4_key *smallest_removed, reiser4_key *new_first); + struct carry_kill_data *, reiser4_key * smallest_removed, + reiser4_key * new_first); reiser4_key *unit_key_tail(const coord_t *, reiser4_key *); /* plugin->u.item.s.* */ @@ -34,10 +38,9 @@ int read_tail(struct file *, flow_t *, h int readpage_tail(void *vp, struct page *page); reiser4_key *append_key_tail(const coord_t *, reiser4_key *); void init_coord_extension_tail(uf_coord_t *, loff_t offset); -int get_block_address_tail(const coord_t *coord, - sector_t block, struct buffer_head *bh); -int item_balance_dirty_pages(struct address_space *mapping, const flow_t *f, - hint_t *hint, int back_to_dirty, int set_hint); +int get_block_address_tail(const coord_t *, sector_t, sector_t *); +int item_balance_dirty_pages(struct address_space *, const flow_t *, + hint_t *, int back_to_dirty, int set_hint); /* __REISER4_TAIL_H__ */ #endif diff -puN fs/reiser4/plugin/node/node40.c~reiser4-big-update fs/reiser4/plugin/node/node40.c --- devel/fs/reiser4/plugin/node/node40.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/node/node40.c 2005-09-15 19:51:08.000000000 -0700 @@ -36,12 +36,12 @@ /* magic number that is stored in ->magic field of node header */ static const __u32 REISER4_NODE_MAGIC = 0x52344653; /* (*(__u32 *)"R4FS"); */ -static int prepare_for_update(znode * left, znode * right, carry_plugin_info * info); +static int prepare_for_update(znode * left, znode * right, + carry_plugin_info * info); /* header of node of reiser40 format is at the beginning of node */ -static inline node40_header * -node40_node_header(const znode * node /* node to - * query */ ) +static inline node40_header *node40_node_header(const znode * node /* node to + * query */ ) { assert("nikita-567", node != NULL); assert("nikita-568", znode_page(node) != NULL); @@ -51,75 +51,63 @@ node40_node_header(const znode * node /* /* functions to get/set fields of node40_header */ -static __u32 -nh40_get_magic(node40_header * nh) +static __u32 nh40_get_magic(node40_header * nh) { return d32tocpu(&nh->magic); } -static void -nh40_set_magic(node40_header * nh, __u32 magic) +static void nh40_set_magic(node40_header * nh, __u32 magic) { cputod32(magic, &nh->magic); } -static void -nh40_set_free_space(node40_header * nh, unsigned value) +static void nh40_set_free_space(node40_header * nh, unsigned value) { cputod16(value, &nh->free_space); /*node->free_space = value; */ } -static inline unsigned -nh40_get_free_space(node40_header * nh) +static inline unsigned nh40_get_free_space(node40_header * nh) { return d16tocpu(&nh->free_space); } -static void -nh40_set_free_space_start(node40_header * nh, unsigned value) +static void nh40_set_free_space_start(node40_header * nh, unsigned value) { cputod16(value, &nh->free_space_start); } -static inline unsigned -nh40_get_free_space_start(node40_header * nh) +static inline unsigned nh40_get_free_space_start(node40_header * nh) { return d16tocpu(&nh->free_space_start); } -static inline void -nh40_set_level(node40_header * nh, unsigned value) +static inline void nh40_set_level(node40_header * nh, unsigned value) { cputod8(value, &nh->level); } -static unsigned -nh40_get_level(node40_header * nh) +static unsigned nh40_get_level(node40_header * nh) { return d8tocpu(&nh->level); } -static void -nh40_set_num_items(node40_header * nh, unsigned value) +static void nh40_set_num_items(node40_header * nh, unsigned value) { cputod16(value, &nh->nr_items); } -static inline unsigned -nh40_get_num_items(node40_header * nh) +static inline unsigned nh40_get_num_items(node40_header * nh) { return d16tocpu(&nh->nr_items); } -static void -nh40_set_mkfs_id(node40_header * nh, __u32 id) +static void nh40_set_mkfs_id(node40_header * nh, __u32 id) { cputod32(id, &nh->mkfs_id); } -static inline __u64 -nh40_get_flush_id(node40_header * nh) +static inline __u64 nh40_get_flush_id(node40_header * nh) { return d64tocpu(&nh->flush_id); } @@ -128,29 +116,27 @@ nh40_get_flush_id(node40_header * nh) plugin_by_disk_id/save_disk_plugin */ /* array of item headers is at the end of node */ -static inline item_header40 * -node40_ih_at(const znode * node, unsigned pos) +static inline item_header40 *node40_ih_at(const znode * node, unsigned pos) { return (item_header40 *) (zdata(node) + znode_size(node)) - pos - 1; } /* ( page_address( node -> pg ) + PAGE_CACHE_SIZE ) - pos - 1 */ -static inline item_header40 * -node40_ih_at_coord(const coord_t * coord) +static inline item_header40 *node40_ih_at_coord(const coord_t * coord) { - return (item_header40 *) (zdata(coord->node) + znode_size(coord->node)) - (coord->item_pos) - 1; + return (item_header40 *) (zdata(coord->node) + + znode_size(coord->node)) - (coord->item_pos) - + 1; } /* functions to get/set fields of item_header40 */ -static void -ih40_set_offset(item_header40 * ih, unsigned offset) +static void ih40_set_offset(item_header40 * ih, unsigned offset) { cputod16(offset, &ih->offset); } -static inline unsigned -ih40_get_offset(item_header40 * ih) +static inline unsigned ih40_get_offset(item_header40 * ih) { return d16tocpu(&ih->offset); } @@ -162,15 +148,15 @@ ih40_get_offset(item_header40 * ih) /* plugin->u.node.item_overhead look for description of this method in plugin/node/node.h */ -reiser4_internal size_t +size_t item_overhead_node40(const znode * node UNUSED_ARG, flow_t * f UNUSED_ARG) { - return sizeof (item_header40); + return sizeof(item_header40); } /* plugin->u.node.free_space look for description of this method in plugin/node/node.h */ -reiser4_internal size_t free_space_node40(znode * node) +size_t free_space_node40(znode * node) { assert("nikita-577", node != NULL); assert("nikita-578", znode_is_loaded(node)); @@ -182,14 +168,13 @@ reiser4_internal size_t free_space_node4 /* private inline version of node40_num_of_items() for use in this file. This is necessary, because address of node40_num_of_items() is taken and it is never inlined as a result. */ -static inline short -node40_num_of_items_internal(const znode * node) +static inline short node40_num_of_items_internal(const znode * node) { return nh40_get_num_items(node40_node_header(node)); } #if REISER4_DEBUG -static inline void check_num_items(const znode *node) +static inline void check_num_items(const znode * node) { assert("nikita-2749", node40_num_of_items_internal(node) == node->nr_items); @@ -201,8 +186,7 @@ static inline void check_num_items(const /* plugin->u.node.num_of_items look for description of this method in plugin/node/node.h */ -reiser4_internal int -num_of_items_node40(const znode * node) +int num_of_items_node40(const znode * node) { return node40_num_of_items_internal(node); } @@ -221,8 +205,7 @@ node40_set_num_items(znode * node, node4 /* plugin->u.node.item_by_coord look for description of this method in plugin/node/node.h */ -reiser4_internal char * -item_by_coord_node40(const coord_t * coord) +char *item_by_coord_node40(const coord_t * coord) { item_header40 *ih; char *p; @@ -238,8 +221,7 @@ item_by_coord_node40(const coord_t * coo /* plugin->u.node.length_by_coord look for description of this method in plugin/node/node.h */ -reiser4_internal int -length_by_coord_node40(const coord_t * coord) +int length_by_coord_node40(const coord_t * coord) { item_header40 *ih; int result; @@ -249,8 +231,11 @@ length_by_coord_node40(const coord_t * c assert("vs-257", coord_is_existing_item(coord)); ih = node40_ih_at_coord(coord); - if ((int) coord->item_pos == node40_num_of_items_internal(coord->node) - 1) - result = nh40_get_free_space_start(node40_node_header(coord->node)) - ih40_get_offset(ih); + if ((int)coord->item_pos == + node40_num_of_items_internal(coord->node) - 1) + result = + nh40_get_free_space_start(node40_node_header(coord->node)) - + ih40_get_offset(ih); else result = ih40_get_offset(ih - 1) - ih40_get_offset(ih); @@ -258,7 +243,7 @@ length_by_coord_node40(const coord_t * c } static pos_in_node_t -node40_item_length(const znode *node, pos_in_node_t item_pos) +node40_item_length(const znode * node, pos_in_node_t item_pos) { item_header40 *ih; pos_in_node_t result; @@ -269,7 +254,9 @@ node40_item_length(const znode *node, po ih = node40_ih_at(node, item_pos); if (item_pos == node40_num_of_items_internal(node) - 1) - result = nh40_get_free_space_start(node40_node_header(node)) - ih40_get_offset(ih); + result = + nh40_get_free_space_start(node40_node_header(node)) - + ih40_get_offset(ih); else result = ih40_get_offset(ih - 1) - ih40_get_offset(ih); @@ -278,11 +265,10 @@ node40_item_length(const znode *node, po /* plugin->u.node.plugin_by_coord look for description of this method in plugin/node/node.h */ -reiser4_internal item_plugin * -plugin_by_coord_node40(const coord_t * coord) +item_plugin *plugin_by_coord_node40(const coord_t * coord) { item_header40 *ih; - item_plugin *result; + item_plugin *result; /* @coord is set to existing item */ assert("vs-258", coord != NULL); @@ -296,8 +282,7 @@ plugin_by_coord_node40(const coord_t * c /* plugin->u.node.key_at look for description of this method in plugin/node/node.h */ -reiser4_internal reiser4_key * -key_at_node40(const coord_t * coord, reiser4_key * key) +reiser4_key *key_at_node40(const coord_t * coord, reiser4_key * key) { item_header40 *ih; @@ -305,7 +290,7 @@ key_at_node40(const coord_t * coord, rei /* @coord is set to existing item */ ih = node40_ih_at_coord(coord); - memcpy(key, &ih->key, sizeof (reiser4_key)); + memcpy(key, &ih->key, sizeof(reiser4_key)); return key; } @@ -319,11 +304,10 @@ key_at_node40(const coord_t * coord, rei /* plugin->u.node.lookup look for description of this method in plugin/node/node.h */ -reiser4_internal node_search_result -lookup_node40(znode * node /* node to query */ , - const reiser4_key * key /* key to look for */ , - lookup_bias bias /* search bias */ , - coord_t * coord /* resulting coord */ ) +node_search_result lookup_node40(znode * node /* node to query */ , + const reiser4_key * key /* key to look for */ , + lookup_bias bias /* search bias */ , + coord_t * coord /* resulting coord */ ) { int left; int right; @@ -377,7 +361,7 @@ lookup_node40(znode * node /* node to qu right to left in attempt to use more efficient loop termination condition (comparison with 0). This doesn't work. - */ + */ while (right - left >= REISER4_SEQ_SEARCH_BREAK) { int median; @@ -401,9 +385,9 @@ lookup_node40(znode * node /* node to qu break; case EQUAL_TO: do { - -- median; + --median; /* headers are ordered from right to left */ - ++ medianh; + ++medianh; } while (median >= 0 && keyeq(key, &medianh->key)); right = left = median + 1; ih = lefth = righth = medianh - 1; @@ -415,9 +399,9 @@ lookup_node40(znode * node /* node to qu the rightmost part of a node from right to left. We are trying to access memory from left to right, and hence, scan in _descending_ order of item numbers. - */ + */ if (!found) { - for (left = right, ih = righth; left >= 0; ++ ih, -- left) { + for (left = right, ih = righth; left >= 0; ++ih, --left) { cmp_t comparison; prefetchkey(&(ih + 1)->key); @@ -427,11 +411,11 @@ lookup_node40(znode * node /* node to qu if (comparison == EQUAL_TO) { found = 1; do { - -- left; - ++ ih; + --left; + ++ih; } while (left >= 0 && keyeq(&ih->key, key)); - ++ left; - -- ih; + ++left; + --ih; } else { assert("nikita-1256", comparison == LESS_THAN); } @@ -445,32 +429,19 @@ lookup_node40(znode * node /* node to qu assert("nikita-3214", equi(found, keyeq(&node40_ih_at(node, left)->key, key))); -#ifdef REISER4_STATS - NODE_ADDSTAT(node, found, !!found); - NODE_ADDSTAT(node, pos, left); - if (items > 1) - NODE_ADDSTAT(node, posrelative, (left << 10) / (items - 1)); - else - NODE_ADDSTAT(node, posrelative, 1 << 10); - if (left == node->last_lookup_pos) - NODE_INCSTAT(node, samepos); - if (left == node->last_lookup_pos + 1) - NODE_INCSTAT(node, nextpos); - node->last_lookup_pos = left; -#endif - coord_set_item_pos(coord, left); coord->unit_pos = 0; coord->between = AT_UNIT; /* key < leftmost key in a mode or node is corrupted and keys are not sorted */ - bstop = node40_ih_at(node, (unsigned) left); + bstop = node40_ih_at(node, (unsigned)left); order = keycmp(&bstop->key, key); if (unlikely(order == GREATER_THAN)) { if (unlikely(left != 0)) { /* screw up */ - warning("nikita-587", "Key less than %i key in a node", left); + warning("nikita-587", "Key less than %i key in a node", + left); print_key("key", key); print_key("min", &bstop->key); print_znode("node", node); @@ -485,7 +456,8 @@ lookup_node40(znode * node /* node to qu iplug = item_plugin_by_disk_id(znode_get_tree(node), &bstop->plugin_id); if (unlikely(iplug == NULL)) { - warning("nikita-588", "Unknown plugin %i", d16tocpu(&bstop->plugin_id)); + warning("nikita-588", "Unknown plugin %i", + d16tocpu(&bstop->plugin_id)); print_key("key", key); print_znode("node", node); print_coord_content("coord", coord); @@ -514,7 +486,7 @@ lookup_node40(znode * node /* node to qu created. When writing to position 0 in that file - traverse_tree will stop here on twig level. When we want it to go down to leaf level - */ + */ return NS_NOT_FOUND; } } @@ -533,7 +505,7 @@ lookup_node40(znode * node /* node to qu /* plugin->u.node.estimate look for description of this method in plugin/node/node.h */ -reiser4_internal size_t estimate_node40(znode * node) +size_t estimate_node40(znode * node) { size_t result; @@ -546,10 +518,9 @@ reiser4_internal size_t estimate_node40( /* plugin->u.node.check look for description of this method in plugin/node/node.h */ -reiser4_internal int -check_node40(const znode * node /* node to check */ , - __u32 flags /* check flags */ , - const char **error /* where to store error message */ ) +int check_node40(const znode * node /* node to check */ , + __u32 flags /* check flags */ , + const char **error /* where to store error message */ ) { int nr_items; int i; @@ -574,7 +545,7 @@ check_node40(const znode * node /* node } if (flags & REISER4_NODE_DKEYS) - prev = *znode_get_ld_key((znode *)node); + prev = *znode_get_ld_key((znode *) node); else prev = *min_key(); @@ -589,11 +560,11 @@ check_node40(const znode * node /* node reiser4_key unit_key; unsigned j; - ih = node40_ih_at(node, (unsigned) i); + ih = node40_ih_at(node, (unsigned)i); coord_set_item_pos(&coord, i); if ((ih40_get_offset(ih) >= - znode_size(node) - nr_items * sizeof (item_header40)) || - (ih40_get_offset(ih) < sizeof (node40_header))) { + znode_size(node) - nr_items * sizeof(item_header40)) || + (ih40_get_offset(ih) < sizeof(node40_header))) { *error = "Offset is out of bounds"; return -1; } @@ -626,13 +597,11 @@ check_node40(const znode * node /* node prev = unit_key; } coord.unit_pos = 0; - if (level != TWIG_LEVEL && - item_is_extent(&coord)) { + if (level != TWIG_LEVEL && item_is_extent(&coord)) { *error = "extent on the wrong level"; return -1; } - if (level == LEAF_LEVEL && - item_is_internal(&coord)) { + if (level == LEAF_LEVEL && item_is_internal(&coord)) { *error = "internal item on the wrong level"; return -1; } @@ -641,13 +610,13 @@ check_node40(const znode * node /* node *error = "wrong item on the internal level"; return -1; } - if (level > TWIG_LEVEL && - !item_is_internal(&coord)) { + if (level > TWIG_LEVEL && !item_is_internal(&coord)) { *error = "non-internal item on the internal level"; return -1; } #if REISER4_DEBUG - if (item_plugin_by_coord(&coord)->b.check && item_plugin_by_coord(&coord)->b.check(&coord, error)) + if (item_plugin_by_coord(&coord)->b.check + && item_plugin_by_coord(&coord)->b.check(&coord, error)) return -1; #endif if (i) { @@ -675,7 +644,9 @@ check_node40(const znode * node /* node iplug->s.file.append_key(&coord, &mkey); set_key_offset(&mkey, get_key_offset(&mkey) - 1); - if (UNDER_RW(dk, current_tree, read, keygt(&mkey, znode_get_rd_key((znode *) node)))) { + if (UNDER_RW + (dk, current_tree, read, + keygt(&mkey, znode_get_rd_key((znode *) node)))) { *error = "key of rightmost item is too large"; return -1; } @@ -687,7 +658,7 @@ check_node40(const znode * node /* node flags |= REISER4_NODE_TREE_STABLE; - if (keygt(&prev, znode_get_rd_key((znode *)node))) { + if (keygt(&prev, znode_get_rd_key((znode *) node))) { if (flags & REISER4_NODE_TREE_STABLE) { *error = "Last key is greater than rdkey"; RUNLOCK_DK(current_tree); @@ -695,7 +666,9 @@ check_node40(const znode * node /* node return -1; } } - if (keygt(znode_get_ld_key((znode *)node), znode_get_rd_key((znode *)node))) { + if (keygt + (znode_get_ld_key((znode *) node), + znode_get_rd_key((znode *) node))) { *error = "ldkey is greater than rdkey"; RUNLOCK_DK(current_tree); RUNLOCK_TREE(current_tree); @@ -705,8 +678,11 @@ check_node40(const znode * node /* node (node->left != NULL) && !ZF_ISSET(node->left, JNODE_HEARD_BANSHEE) && ergo(flags & REISER4_NODE_TREE_STABLE, - !keyeq(znode_get_rd_key(node->left), znode_get_ld_key((znode *)node))) && - ergo(!(flags & REISER4_NODE_TREE_STABLE), keygt(znode_get_rd_key(node->left), znode_get_ld_key((znode *)node)))) { + !keyeq(znode_get_rd_key(node->left), + znode_get_ld_key((znode *) node))) + && ergo(!(flags & REISER4_NODE_TREE_STABLE), + keygt(znode_get_rd_key(node->left), + znode_get_ld_key((znode *) node)))) { *error = "left rdkey or ldkey is wrong"; RUNLOCK_DK(current_tree); RUNLOCK_TREE(current_tree); @@ -716,8 +692,11 @@ check_node40(const znode * node /* node (node->right != NULL) && !ZF_ISSET(node->right, JNODE_HEARD_BANSHEE) && ergo(flags & REISER4_NODE_TREE_STABLE, - !keyeq(znode_get_rd_key((znode *)node), znode_get_ld_key(node->right))) && - ergo(!(flags & REISER4_NODE_TREE_STABLE), keygt(znode_get_rd_key((znode *)node), znode_get_ld_key(node->right)))) { + !keyeq(znode_get_rd_key((znode *) node), + znode_get_ld_key(node->right))) + && ergo(!(flags & REISER4_NODE_TREE_STABLE), + keygt(znode_get_rd_key((znode *) node), + znode_get_ld_key(node->right)))) { *error = "rdkey or right ldkey is wrong"; RUNLOCK_DK(current_tree); RUNLOCK_TREE(current_tree); @@ -733,8 +712,7 @@ check_node40(const znode * node /* node /* plugin->u.node.parse look for description of this method in plugin/node/node.h */ -reiser4_internal int -parse_node40(znode * node /* node to parse */ ) +int parse_node40(znode * node /* node to parse */ ) { node40_header *header; int result; @@ -753,14 +731,13 @@ parse_node40(znode * node /* node to par result = 0; } if (unlikely(result != 0)) - /* print_znode("node", node)*/; + /* print_znode("node", node) */ ; return RETERR(result); } /* plugin->u.node.init look for description of this method in plugin/node/node.h */ -reiser4_internal int -init_node40(znode * node /* node to initialise */ ) +int init_node40(znode * node /* node to initialise */ ) { node40_header *header; @@ -768,12 +745,13 @@ init_node40(znode * node /* node to init assert("nikita-572", zdata(node) != NULL); header = node40_node_header(node); - memset(header, 0, sizeof (node40_header)); - nh40_set_free_space(header, znode_size(node) - sizeof (node40_header)); - nh40_set_free_space_start(header, sizeof (node40_header)); + memset(header, 0, sizeof(node40_header)); + nh40_set_free_space(header, znode_size(node) - sizeof(node40_header)); + nh40_set_free_space_start(header, sizeof(node40_header)); /* sane hypothesis: 0 in CPU format is 0 in disk format */ /* items: 0 */ - save_plugin_id(node_plugin_to_plugin(node->nplug), &header->common_header.plugin_id); + save_plugin_id(node_plugin_to_plugin(node->nplug), + &header->common_header.plugin_id); nh40_set_level(header, znode_get_level(node)); nh40_set_magic(header, REISER4_NODE_MAGIC); node->nr_items = 0; @@ -784,8 +762,7 @@ init_node40(znode * node /* node to init } #ifdef GUESS_EXISTS -reiser4_internal int -guess_node40(const znode * node /* node to guess plugin of */ ) +int guess_node40(const znode * node /* node to guess plugin of */ ) { node40_header *nethack; @@ -794,14 +771,15 @@ guess_node40(const znode * node /* node return (nh40_get_magic(nethack) == REISER4_NODE_MAGIC) && (plugin_by_disk_id(znode_get_tree(node), - REISER4_NODE_PLUGIN_TYPE, &nethack->common_header.plugin_id)->h.id == NODE40_ID); + REISER4_NODE_PLUGIN_TYPE, + &nethack->common_header.plugin_id)->h.id == + NODE40_ID); } #endif /* plugin->u.node.chage_item_size look for description of this method in plugin/node/node.h */ -reiser4_internal void -change_item_size_node40(coord_t * coord, int by) +void change_item_size_node40(coord_t * coord, int by) { node40_header *nh; item_header40 *ih; @@ -820,7 +798,8 @@ change_item_size_node40(coord_t * coord, /* move item bodies */ ih = node40_ih_at_coord(coord); memmove(item_data + item_length + by, item_data + item_length, - nh40_get_free_space_start(node40_node_header(coord->node)) - (ih40_get_offset(ih) + item_length)); + nh40_get_free_space_start(node40_node_header(coord->node)) - + (ih40_get_offset(ih) + item_length)); /* update offsets of moved items */ for (i = coord->item_pos + 1; i < nh40_get_num_items(nh); i++) { @@ -833,17 +812,18 @@ change_item_size_node40(coord_t * coord, nh40_set_free_space_start(nh, nh40_get_free_space_start(nh) + by); } -static int -should_notify_parent(const znode * node) +static int should_notify_parent(const znode * node) { /* FIXME_JMACD This looks equivalent to znode_is_root(), right? -josh */ - return !disk_addr_eq(znode_get_block(node), &znode_get_tree(node)->root_block); + return !disk_addr_eq(znode_get_block(node), + &znode_get_tree(node)->root_block); } /* plugin->u.node.create_item look for description of this method in plugin/node/node.h */ -reiser4_internal int -create_item_node40(coord_t * target, const reiser4_key * key, reiser4_item_data * data, carry_plugin_info * info) +int +create_item_node40(coord_t *target, const reiser4_key *key, + reiser4_item_data *data, carry_plugin_info *info) { node40_header *nh; item_header40 *ih; @@ -854,7 +834,9 @@ create_item_node40(coord_t * target, con assert("vs-212", coord_is_between_items(target)); /* node must have enough free space */ - assert("vs-254", free_space_node40(target->node) >= data->length + sizeof(item_header40)); + assert("vs-254", + free_space_node40(target->node) >= + data->length + sizeof(item_header40)); assert("vs-1410", data->length >= 0); if (coord_set_to_right(target)) @@ -870,7 +852,8 @@ create_item_node40(coord_t * target, con offset = ih40_get_offset(ih); memmove(zdata(target->node) + offset + data->length, - zdata(target->node) + offset, nh40_get_free_space_start(nh) - offset); + zdata(target->node) + offset, + nh40_get_free_space_start(nh) - offset); /* update headers of moved items */ for (i = target->item_pos; i < nh40_get_num_items(nh); i++) { ih = node40_ih_at(target->node, i); @@ -878,7 +861,9 @@ create_item_node40(coord_t * target, con } /* @ih is set to item header of the last item, move item headers */ - memmove(ih - 1, ih, sizeof (item_header40) * (nh40_get_num_items(nh) - target->item_pos)); + memmove(ih - 1, ih, + sizeof(item_header40) * (nh40_get_num_items(nh) - + target->item_pos)); } else { /* new item will start at this offset */ offset = nh40_get_free_space_start(nh); @@ -886,13 +871,16 @@ create_item_node40(coord_t * target, con /* make item header for the new item */ ih = node40_ih_at_coord(target); - memcpy(&ih->key, key, sizeof (reiser4_key)); + memcpy(&ih->key, key, sizeof(reiser4_key)); ih40_set_offset(ih, offset); save_plugin_id(item_plugin_to_plugin(data->iplug), &ih->plugin_id); /* update node header */ - nh40_set_free_space(nh, nh40_get_free_space(nh) - data->length - sizeof (item_header40)); - nh40_set_free_space_start(nh, nh40_get_free_space_start(nh) + data->length); + nh40_set_free_space(nh, + nh40_get_free_space(nh) - data->length - + sizeof(item_header40)); + nh40_set_free_space_start(nh, + nh40_get_free_space_start(nh) + data->length); node40_set_num_items(target->node, nh, nh40_get_num_items(nh) + 1); /* FIXME: check how does create_item work when between is set to BEFORE_UNIT */ @@ -900,7 +888,7 @@ create_item_node40(coord_t * target, con target->between = AT_UNIT; coord_clear_iplug(target); - /* initialise item */ + /* initialize item */ if (data->iplug->b.init != NULL) { data->iplug->b.init(target, NULL, data); } @@ -915,10 +903,13 @@ create_item_node40(coord_t * target, con without this check? */ assert("nikita-3038", schedulable()); /* copy data from user space */ - __copy_from_user(zdata(target->node) + offset, data->data, (unsigned) data->length); + __copy_from_user(zdata(target->node) + offset, + (const char __user *)data->data, + (unsigned)data->length); } else /* copy from kernel space */ - memcpy(zdata(target->node) + offset, data->data, (unsigned) data->length); + memcpy(zdata(target->node) + offset, data->data, + (unsigned)data->length); } if (target->item_pos == 0) { @@ -935,13 +926,14 @@ create_item_node40(coord_t * target, con /* plugin->u.node.update_item_key look for description of this method in plugin/node/node.h */ -reiser4_internal void -update_item_key_node40(coord_t * target, const reiser4_key * key, carry_plugin_info * info) +void +update_item_key_node40(coord_t * target, const reiser4_key * key, + carry_plugin_info * info) { item_header40 *ih; ih = node40_ih_at_coord(target); - memcpy(&ih->key, key, sizeof (reiser4_key)); + memcpy(&ih->key, key, sizeof(reiser4_key)); if (target->item_pos == 0) { prepare_for_update(NULL, target->node, info); @@ -955,10 +947,10 @@ update_item_key_node40(coord_t * target, struct cut40_info { int mode; - pos_in_node_t tail_removed; /* position of item which gets tail removed */ - pos_in_node_t first_removed; /* position of first the leftmost item among items removed completely */ - pos_in_node_t removed_count; /* number of items removed completely */ - pos_in_node_t head_removed; /* position of item which gets head removed */ + pos_in_node_t tail_removed; /* position of item which gets tail removed */ + pos_in_node_t first_removed; /* position of first the leftmost item among items removed completely */ + pos_in_node_t removed_count; /* number of items removed completely */ + pos_in_node_t head_removed; /* position of item which gets head removed */ pos_in_node_t freed_space_start; pos_in_node_t freed_space_end; @@ -966,8 +958,7 @@ struct cut40_info { pos_in_node_t head_removed_location; }; -static void -init_cinfo(struct cut40_info *cinfo) +static void init_cinfo(struct cut40_info *cinfo) { cinfo->mode = 0; cinfo->tail_removed = MAX_POS_IN_NODE; @@ -981,8 +972,7 @@ init_cinfo(struct cut40_info *cinfo) } /* complete cut_node40/kill_node40 content by removing the gap created by */ -static void -compact(znode *node, struct cut40_info *cinfo) +static void compact(znode * node, struct cut40_info *cinfo) { node40_header *nh; item_header40 *ih; @@ -998,7 +988,8 @@ compact(znode *node, struct cut40_info * nr_items = nh40_get_num_items(nh); /* remove gap made up by removal */ - memmove(zdata(node) + cinfo->freed_space_start, zdata(node) + cinfo->freed_space_end, + memmove(zdata(node) + cinfo->freed_space_start, + zdata(node) + cinfo->freed_space_end, nh40_get_free_space_start(nh) - cinfo->freed_space_end); /* update item headers of moved items - change their locations */ @@ -1007,12 +998,12 @@ compact(znode *node, struct cut40_info * if (cinfo->head_removed_location != MAX_POS_IN_NODE) { assert("vs-1580", pos == cinfo->head_removed); ih40_set_offset(ih, cinfo->head_removed_location); - pos ++; - ih --; + pos++; + ih--; } freed = cinfo->freed_space_end - cinfo->freed_space_start; - for (; pos < nr_items; pos ++, ih --) { + for (; pos < nr_items; pos++, ih--) { assert("vs-1581", ih == node40_ih_at(node, pos)); ih40_set_offset(ih, ih40_get_offset(ih) - freed); } @@ -1024,8 +1015,10 @@ compact(znode *node, struct cut40_info * /* number of items changed. Remove item headers of those items */ ih = node40_ih_at(node, nr_items - 1); memmove(ih + cinfo->removed_count, ih, - sizeof (item_header40) * (nr_items - cinfo->removed_count - cinfo->first_removed)); - freed += sizeof (item_header40) * cinfo->removed_count; + sizeof(item_header40) * (nr_items - + cinfo->removed_count - + cinfo->first_removed)); + freed += sizeof(item_header40) * cinfo->removed_count; node40_set_num_items(node, nh, nr_items - cinfo->removed_count); } @@ -1033,14 +1026,13 @@ compact(znode *node, struct cut40_info * nh40_set_free_space(nh, nh40_get_free_space(nh) + freed); } -reiser4_internal int -shrink_item_node40(coord_t *coord, int delta) +int shrink_item_node40(coord_t * coord, int delta) { node40_header *nh; item_header40 *ih; pos_in_node_t pos; pos_in_node_t nr_items; - char *end; + char *end; znode *node; assert("nikita-3487", coord != NULL); @@ -1060,7 +1052,7 @@ shrink_item_node40(coord_t *coord, int d /* update item headers of moved items - change their locations */ pos = coord->item_pos + 1; ih = node40_ih_at(node, pos); - for (; pos < nr_items; pos ++, ih --) { + for (; pos < nr_items; pos++, ih--) { assert("nikita-3490", ih == node40_ih_at(node, pos)); ih40_set_offset(ih, ih40_get_offset(ih) - delta); } @@ -1077,7 +1069,6 @@ shrink_item_node40(coord_t *coord, int d return 0; } - /* this is used by cut_node40 and kill_node40. It analyses input parameters and calculates cut mode. There are 2 types of cut. First is when a unit is removed from the middle of an item. In this case this function returns 1. All the rest fits into second case: 0 or 1 of items getting tail cut, 0 or more items removed completely and 0 or 1 item @@ -1109,7 +1100,8 @@ parse_cut(struct cut40_info *cinfo, cons } if (params->from->item_pos == params->to->item_pos) { - if (keylt(&min_from_key, from_key) && keylt(to_key, &max_to_key)) + if (keylt(&min_from_key, from_key) + && keylt(to_key, &max_to_key)) return 1; if (keygt(from_key, &min_from_key)) { @@ -1128,22 +1120,23 @@ parse_cut(struct cut40_info *cinfo, cons } } else { cinfo->first_removed = params->from->item_pos + 1; - cinfo->removed_count = params->to->item_pos - params->from->item_pos - 1; + cinfo->removed_count = + params->to->item_pos - params->from->item_pos - 1; if (keygt(from_key, &min_from_key)) { /* first item is not cut completely */ cinfo->tail_removed = params->from->item_pos; cinfo->mode |= CMODE_TAIL; } else { - cinfo->first_removed --; - cinfo->removed_count ++; + cinfo->first_removed--; + cinfo->removed_count++; } if (keylt(to_key, &max_to_key)) { /* last item is not cut completely */ cinfo->head_removed = params->to->item_pos; cinfo->mode |= CMODE_HEAD; } else { - cinfo->removed_count ++; + cinfo->removed_count++; } if (cinfo->removed_count) cinfo->mode |= CMODE_WHOLE; @@ -1153,7 +1146,8 @@ parse_cut(struct cut40_info *cinfo, cons } static void -call_kill_hooks(znode *node, pos_in_node_t from, pos_in_node_t count, carry_kill_data *kdata) +call_kill_hooks(znode * node, pos_in_node_t from, pos_in_node_t count, + carry_kill_data * kdata) { coord_t coord; item_plugin *iplug; @@ -1162,21 +1156,22 @@ call_kill_hooks(znode *node, pos_in_node coord.node = node; coord.unit_pos = 0; coord.between = AT_UNIT; - for (pos = 0; pos < count; pos ++) { + for (pos = 0; pos < count; pos++) { coord_set_item_pos(&coord, from + pos); coord.unit_pos = 0; coord.between = AT_UNIT; iplug = item_plugin_by_coord(&coord); if (iplug->b.kill_hook) { - iplug->b.kill_hook(&coord, 0, coord_num_units(&coord), kdata); + iplug->b.kill_hook(&coord, 0, coord_num_units(&coord), + kdata); } } } /* this is used to kill item partially */ static pos_in_node_t -kill_units(coord_t *coord, pos_in_node_t from, pos_in_node_t to, void *data, reiser4_key *smallest_removed, - reiser4_key *new_first_key) +kill_units(coord_t * coord, pos_in_node_t from, pos_in_node_t to, void *data, + reiser4_key * smallest_removed, reiser4_key * new_first_key) { struct carry_kill_data *kdata; item_plugin *iplug; @@ -1185,32 +1180,36 @@ kill_units(coord_t *coord, pos_in_node_t iplug = item_plugin_by_coord(coord); assert("vs-1524", iplug->b.kill_units); - return iplug->b.kill_units(coord, from, to, kdata, smallest_removed, new_first_key); + return iplug->b.kill_units(coord, from, to, kdata, smallest_removed, + new_first_key); } /* call item plugin to cut tail of file */ static pos_in_node_t -kill_tail(coord_t *coord, void *data, reiser4_key *smallest_removed) +kill_tail(coord_t * coord, void *data, reiser4_key * smallest_removed) { struct carry_kill_data *kdata; pos_in_node_t to; kdata = data; to = coord_last_unit_pos(coord); - return kill_units(coord, coord->unit_pos, to, kdata, smallest_removed, 0); + return kill_units(coord, coord->unit_pos, to, kdata, smallest_removed, + NULL); } /* call item plugin to cut head of item */ static pos_in_node_t -kill_head(coord_t *coord, void *data, reiser4_key *smallest_removed, reiser4_key *new_first_key) +kill_head(coord_t * coord, void *data, reiser4_key * smallest_removed, + reiser4_key * new_first_key) { - return kill_units(coord, 0, coord->unit_pos, data, smallest_removed, new_first_key); + return kill_units(coord, 0, coord->unit_pos, data, smallest_removed, + new_first_key); } /* this is used to cut item partially */ static pos_in_node_t -cut_units(coord_t *coord, pos_in_node_t from, pos_in_node_t to, void *data, - reiser4_key *smallest_removed, reiser4_key *new_first_key) +cut_units(coord_t * coord, pos_in_node_t from, pos_in_node_t to, void *data, + reiser4_key * smallest_removed, reiser4_key * new_first_key) { carry_cut_data *cdata; item_plugin *iplug; @@ -1218,32 +1217,36 @@ cut_units(coord_t *coord, pos_in_node_t cdata = data; iplug = item_plugin_by_coord(coord); assert("vs-302", iplug->b.cut_units); - return iplug->b.cut_units(coord, from, to, cdata, smallest_removed, new_first_key); + return iplug->b.cut_units(coord, from, to, cdata, smallest_removed, + new_first_key); } /* call item plugin to cut tail of file */ static pos_in_node_t -cut_tail(coord_t *coord, void *data, reiser4_key *smallest_removed) +cut_tail(coord_t * coord, void *data, reiser4_key * smallest_removed) { carry_cut_data *cdata; pos_in_node_t to; cdata = data; to = coord_last_unit_pos(cdata->params.from); - return cut_units(coord, coord->unit_pos, to, data, smallest_removed, 0); + return cut_units(coord, coord->unit_pos, to, data, smallest_removed, NULL); } /* call item plugin to cut head of item */ static pos_in_node_t -cut_head(coord_t *coord, void *data, reiser4_key *smallest_removed, reiser4_key *new_first_key) +cut_head(coord_t * coord, void *data, reiser4_key * smallest_removed, + reiser4_key * new_first_key) { - return cut_units(coord, 0, coord->unit_pos, data, smallest_removed, new_first_key); + return cut_units(coord, 0, coord->unit_pos, data, smallest_removed, + new_first_key); } /* this returns 1 of key of first item changed, 0 - if it did not */ static int -prepare_for_compact(struct cut40_info *cinfo, const struct cut_kill_params *params, int is_cut, - void *data, carry_plugin_info *info) +prepare_for_compact(struct cut40_info *cinfo, + const struct cut_kill_params *params, int is_cut, + void *data, carry_plugin_info * info) { znode *node; item_header40 *ih; @@ -1251,9 +1254,11 @@ prepare_for_compact(struct cut40_info *c pos_in_node_t item_pos; coord_t coord; reiser4_key new_first_key; - pos_in_node_t (*kill_units_f)(coord_t *, pos_in_node_t, pos_in_node_t, void *, reiser4_key *, reiser4_key *); - pos_in_node_t (*kill_tail_f)(coord_t *, void *, reiser4_key *); - pos_in_node_t (*kill_head_f)(coord_t *, void *, reiser4_key *, reiser4_key *); + pos_in_node_t(*kill_units_f) (coord_t *, pos_in_node_t, pos_in_node_t, + void *, reiser4_key *, reiser4_key *); + pos_in_node_t(*kill_tail_f) (coord_t *, void *, reiser4_key *); + pos_in_node_t(*kill_head_f) (coord_t *, void *, reiser4_key *, + reiser4_key *); int retval; retval = 0; @@ -1262,7 +1267,8 @@ prepare_for_compact(struct cut40_info *c assert("vs-184", node == params->to->node); assert("vs-312", !node_is_empty(node)); - assert("vs-297", coord_compare(params->from, params->to) != COORD_CMP_ON_RIGHT); + assert("vs-297", + coord_compare(params->from, params->to) != COORD_CMP_ON_RIGHT); if (is_cut) { kill_units_f = cut_units; @@ -1276,11 +1282,16 @@ prepare_for_compact(struct cut40_info *c if (parse_cut(cinfo, params) == 1) { /* cut from the middle of item */ - freed = kill_units_f(params->from, params->from->unit_pos, params->to->unit_pos, data, params->smallest_removed, NULL); + freed = + kill_units_f(params->from, params->from->unit_pos, + params->to->unit_pos, data, + params->smallest_removed, NULL); item_pos = params->from->item_pos; ih = node40_ih_at(node, item_pos); - cinfo->freed_space_start = ih40_get_offset(ih) + node40_item_length(node, item_pos) - freed; + cinfo->freed_space_start = + ih40_get_offset(ih) + node40_item_length(node, + item_pos) - freed; cinfo->freed_space_end = cinfo->freed_space_start + freed; cinfo->first_moved = item_pos + 1; } else { @@ -1291,37 +1302,50 @@ prepare_for_compact(struct cut40_info *c switch (cinfo->mode) { case CMODE_TAIL: /* one item gets cut partially from its end */ - assert("vs-1562", cinfo->tail_removed == params->from->item_pos); + assert("vs-1562", + cinfo->tail_removed == params->from->item_pos); - freed = kill_tail_f(params->from, data, params->smallest_removed); + freed = + kill_tail_f(params->from, data, + params->smallest_removed); item_pos = cinfo->tail_removed; ih = node40_ih_at(node, item_pos); - cinfo->freed_space_start = ih40_get_offset(ih) + node40_item_length(node, item_pos) - freed; - cinfo->freed_space_end = cinfo->freed_space_start + freed; + cinfo->freed_space_start = + ih40_get_offset(ih) + node40_item_length(node, + item_pos) - + freed; + cinfo->freed_space_end = + cinfo->freed_space_start + freed; cinfo->first_moved = cinfo->tail_removed + 1; break; case CMODE_WHOLE: /* one or more items get removed completely */ - assert("vs-1563", cinfo->first_removed == params->from->item_pos); - assert("vs-1564", cinfo->removed_count > 0 && cinfo->removed_count != MAX_POS_IN_NODE); + assert("vs-1563", + cinfo->first_removed == params->from->item_pos); + assert("vs-1564", cinfo->removed_count > 0 + && cinfo->removed_count != MAX_POS_IN_NODE); /* call kill hook for all items removed completely */ if (is_cut == 0) - call_kill_hooks(node, cinfo->first_removed, cinfo->removed_count, data); + call_kill_hooks(node, cinfo->first_removed, + cinfo->removed_count, data); item_pos = cinfo->first_removed; ih = node40_ih_at(node, item_pos); if (params->smallest_removed) - memcpy(params->smallest_removed, &ih->key, sizeof (reiser4_key)); + memcpy(params->smallest_removed, &ih->key, + sizeof(reiser4_key)); cinfo->freed_space_start = ih40_get_offset(ih); item_pos += (cinfo->removed_count - 1); ih -= (cinfo->removed_count - 1); - cinfo->freed_space_end = ih40_get_offset(ih) + node40_item_length(node, item_pos); + cinfo->freed_space_end = + ih40_get_offset(ih) + node40_item_length(node, + item_pos); cinfo->first_moved = item_pos + 1; if (cinfo->first_removed == 0) /* key of first item of the node changes */ @@ -1330,9 +1354,13 @@ prepare_for_compact(struct cut40_info *c case CMODE_HEAD: /* one item gets cut partially from its head */ - assert("vs-1565", cinfo->head_removed == params->from->item_pos); + assert("vs-1565", + cinfo->head_removed == params->from->item_pos); - freed = kill_head_f(params->to, data, params->smallest_removed, &new_first_key); + freed = + kill_head_f(params->to, data, + params->smallest_removed, + &new_first_key); item_pos = cinfo->head_removed; ih = node40_ih_at(node, item_pos); @@ -1345,7 +1373,7 @@ prepare_for_compact(struct cut40_info *c coord_set_item_pos(&coord, item_pos); coord.unit_pos = 0; coord.between = AT_UNIT; - update_item_key_node40(&coord, &new_first_key, 0); + update_item_key_node40(&coord, &new_first_key, NULL); if (item_pos == 0) /* key of first item of the node changes */ retval = 1; @@ -1353,43 +1381,61 @@ prepare_for_compact(struct cut40_info *c case CMODE_TAIL | CMODE_WHOLE: /* one item gets cut from its end and one or more items get removed completely */ - assert("vs-1566", cinfo->tail_removed == params->from->item_pos); - assert("vs-1567", cinfo->first_removed == cinfo->tail_removed + 1); - assert("vs-1564", cinfo->removed_count > 0 && cinfo->removed_count != MAX_POS_IN_NODE); - - freed = kill_tail_f(params->from, data, params->smallest_removed); + assert("vs-1566", + cinfo->tail_removed == params->from->item_pos); + assert("vs-1567", + cinfo->first_removed == cinfo->tail_removed + 1); + assert("vs-1564", cinfo->removed_count > 0 + && cinfo->removed_count != MAX_POS_IN_NODE); + + freed = + kill_tail_f(params->from, data, + params->smallest_removed); item_pos = cinfo->tail_removed; ih = node40_ih_at(node, item_pos); - cinfo->freed_space_start = ih40_get_offset(ih) + node40_item_length(node, item_pos) - freed; + cinfo->freed_space_start = + ih40_get_offset(ih) + node40_item_length(node, + item_pos) - + freed; /* call kill hook for all items removed completely */ if (is_cut == 0) - call_kill_hooks(node, cinfo->first_removed, cinfo->removed_count, data); + call_kill_hooks(node, cinfo->first_removed, + cinfo->removed_count, data); item_pos += cinfo->removed_count; ih -= cinfo->removed_count; - cinfo->freed_space_end = ih40_get_offset(ih) + node40_item_length(node, item_pos); + cinfo->freed_space_end = + ih40_get_offset(ih) + node40_item_length(node, + item_pos); cinfo->first_moved = item_pos + 1; break; case CMODE_WHOLE | CMODE_HEAD: /* one or more items get removed completely and one item gets cut partially from its head */ - assert("vs-1568", cinfo->first_removed == params->from->item_pos); - assert("vs-1564", cinfo->removed_count > 0 && cinfo->removed_count != MAX_POS_IN_NODE); - assert("vs-1569", cinfo->head_removed == cinfo->first_removed + cinfo->removed_count); + assert("vs-1568", + cinfo->first_removed == params->from->item_pos); + assert("vs-1564", cinfo->removed_count > 0 + && cinfo->removed_count != MAX_POS_IN_NODE); + assert("vs-1569", + cinfo->head_removed == + cinfo->first_removed + cinfo->removed_count); /* call kill hook for all items removed completely */ if (is_cut == 0) - call_kill_hooks(node, cinfo->first_removed, cinfo->removed_count, data); + call_kill_hooks(node, cinfo->first_removed, + cinfo->removed_count, data); item_pos = cinfo->first_removed; ih = node40_ih_at(node, item_pos); if (params->smallest_removed) - memcpy(params->smallest_removed, &ih->key, sizeof (reiser4_key)); + memcpy(params->smallest_removed, &ih->key, + sizeof(reiser4_key)); - freed = kill_head_f(params->to, data, 0, &new_first_key); + freed = + kill_head_f(params->to, data, NULL, &new_first_key); cinfo->freed_space_start = ih40_get_offset(ih); @@ -1405,7 +1451,7 @@ prepare_for_compact(struct cut40_info *c coord_set_item_pos(&coord, cinfo->head_removed); coord.unit_pos = 0; coord.between = AT_UNIT; - update_item_key_node40(&coord, &new_first_key, 0); + update_item_key_node40(&coord, &new_first_key, NULL); assert("vs-1579", cinfo->first_removed == 0); /* key of first item of the node changes */ @@ -1428,11 +1474,9 @@ prepare_for_compact(struct cut40_info *c return retval; } - /* plugin->u.node.kill return value is number of items removed completely */ -int -kill_node40(struct carry_kill_data *kdata, carry_plugin_info *info) +int kill_node40(struct carry_kill_data *kdata, carry_plugin_info * info) { znode *node; struct cut40_info cinfo; @@ -1440,13 +1484,16 @@ kill_node40(struct carry_kill_data *kdat node = kdata->params.from->node; - first_key_changed = prepare_for_compact(&cinfo, &kdata->params, 0/* not cut */, kdata, info); + first_key_changed = + prepare_for_compact(&cinfo, &kdata->params, 0 /* not cut */ , kdata, + info); compact(node, &cinfo); if (info) { /* it is not called by node40_shift, so we have to take care of changes on upper levels */ - if (node_is_empty(node) && !(kdata->flags & DELETE_RETAIN_EMPTY)) + if (node_is_empty(node) + && !(kdata->flags & DELETE_RETAIN_EMPTY)) /* all contents of node is deleted */ prepare_removal_node40(node, info); else if (first_key_changed) { @@ -1463,8 +1510,7 @@ kill_node40(struct carry_kill_data *kdat /* plugin->u.node.cut return value is number of items removed completely */ -int -cut_node40(struct carry_cut_data *cdata, carry_plugin_info *info) +int cut_node40(struct carry_cut_data *cdata, carry_plugin_info * info) { znode *node; struct cut40_info cinfo; @@ -1472,7 +1518,9 @@ cut_node40(struct carry_cut_data *cdata, node = cdata->params.from->node; - first_key_changed = prepare_for_compact(&cinfo, &cdata->params, 1/* not cut */, cdata, info); + first_key_changed = + prepare_for_compact(&cinfo, &cdata->params, 1 /* not cut */ , cdata, + info); compact(node, &cinfo); if (info) { @@ -1490,10 +1538,9 @@ cut_node40(struct carry_cut_data *cdata, coord_clear_iplug(cdata->params.to); znode_make_dirty(node); - return cinfo.removed_count == MAX_POS_IN_NODE ? 0 : cinfo.removed_count ; + return cinfo.removed_count == MAX_POS_IN_NODE ? 0 : cinfo.removed_count; } - /* this structure is used by shift method of node40 plugin */ struct shift_params { shift_direction pend; /* when @pend == append - we are shifting to @@ -1534,21 +1581,21 @@ struct shift_params { }; -static int -item_creation_overhead(coord_t * item) +static int item_creation_overhead(coord_t *item) { - return node_plugin_by_coord(item)->item_overhead(item->node, 0); + return node_plugin_by_coord(item)->item_overhead(item->node, NULL); } /* how many units are there in @source starting from source->unit_pos but not further than @stop_coord */ static int -wanted_units(coord_t * source, coord_t * stop_coord, shift_direction pend) +wanted_units(coord_t *source, coord_t *stop_coord, shift_direction pend) { if (pend == SHIFT_LEFT) { assert("vs-181", source->unit_pos == 0); } else { - assert("vs-182", source->unit_pos == coord_last_unit_pos(source)); + assert("vs-182", + source->unit_pos == coord_last_unit_pos(source)); } if (source->item_pos != stop_coord->item_pos) { @@ -1566,7 +1613,7 @@ wanted_units(coord_t * source, coord_t * /* this calculates what can be copied from @shift->wish_stop.node to @shift->target */ static void -estimate_shift(struct shift_params *shift, const reiser4_context *ctx) +estimate_shift(struct shift_params *shift, const reiser4_context * ctx) { unsigned target_free_space, size; pos_in_node_t stop_item; /* item which estimating should not consider */ @@ -1599,10 +1646,14 @@ estimate_shift(struct shift_params *shif coord_init_first_unit(&to, shift->target); } - if ((shift->pend == SHIFT_LEFT) ? are_items_mergeable(&to, &source) : are_items_mergeable(&source, &to)) { + if ((shift->pend == SHIFT_LEFT) ? are_items_mergeable(&to, + &source) : + are_items_mergeable(&source, &to)) { /* how many units of @source do we want to merge to item @to */ - want = wanted_units(&source, &shift->wish_stop, shift->pend); + want = + wanted_units(&source, &shift->wish_stop, + shift->pend); /* how many units of @source we can merge to item @to */ @@ -1610,7 +1661,9 @@ estimate_shift(struct shift_params *shif if (iplug->b.can_shift != NULL) shift->merging_units = iplug->b.can_shift(target_free_space, - &source, shift->target, shift->pend, &size, want); + &source, shift->target, + shift->pend, &size, + want); else { shift->merging_units = 0; size = 0; @@ -1621,13 +1674,20 @@ estimate_shift(struct shift_params *shif we can merge to @target */ if (shift->merging_units) /* at least one unit can be shifted */ - shift->real_stop.unit_pos = (shift->merging_units - source.unit_pos - 1) * shift->pend; + shift->real_stop.unit_pos = + (shift->merging_units - source.unit_pos - + 1) * shift->pend; else { /* nothing can be shifted */ if (shift->pend == SHIFT_LEFT) - coord_init_before_first_item(&shift->real_stop, source.node); + coord_init_before_first_item(&shift-> + real_stop, + source. + node); else - coord_init_after_last_item(&shift->real_stop, source.node); + coord_init_after_last_item(&shift-> + real_stop, + source.node); } assert("nikita-2081", shift->real_stop.unit_pos + 1); @@ -1648,7 +1708,8 @@ estimate_shift(struct shift_params *shif /* calculate how many items can be copied into given free space as whole */ - for (; source.item_pos != stop_item; coord_add_item_pos(&source, shift->pend)) { + for (; source.item_pos != stop_item; + coord_add_item_pos(&source, shift->pend)) { if (shift->pend == SHIFT_RIGHT) source.unit_pos = coord_last_unit_pos(&source); @@ -1657,12 +1718,16 @@ estimate_shift(struct shift_params *shif if (want == coord_last_unit_pos(&source) + 1) { /* we want this item to be copied entirely */ - size = item_length_by_coord(&source) + item_creation_overhead(&source); + size = + item_length_by_coord(&source) + + item_creation_overhead(&source); if (size <= target_free_space) { /* item fits into target node as whole */ target_free_space -= size; - shift->shift_bytes += size - item_creation_overhead(&source); - shift->entire_bytes += size - item_creation_overhead(&source); + shift->shift_bytes += + size - item_creation_overhead(&source); + shift->entire_bytes += + size - item_creation_overhead(&source); shift->entire++; /* update shift->real_stop coord to be set to @@ -1670,7 +1735,9 @@ estimate_shift(struct shift_params *shif @target */ shift->real_stop = source; if (shift->pend == SHIFT_LEFT) - shift->real_stop.unit_pos = coord_last_unit_pos(&shift->real_stop); + shift->real_stop.unit_pos = + coord_last_unit_pos(&shift-> + real_stop); else shift->real_stop.unit_pos = 0; continue; @@ -1683,12 +1750,17 @@ estimate_shift(struct shift_params *shif create new item in target node, so decrease amout of free space by an item creation overhead. We can reach here also if stop coord is in this item */ - if (target_free_space >= (unsigned) item_creation_overhead(&source)) { + if (target_free_space >= + (unsigned)item_creation_overhead(&source)) { target_free_space -= item_creation_overhead(&source); iplug = item_plugin_by_coord(&source); if (iplug->b.can_shift) { - shift->part_units = iplug->b.can_shift(target_free_space, &source, 0 /*target */ - , shift->pend, &size, want); + shift->part_units = iplug->b.can_shift(target_free_space, + &source, + NULL, /* target */ + shift->pend, + &size, + want); } else { target_free_space = 0; shift->part_units = 0; @@ -1706,7 +1778,9 @@ estimate_shift(struct shift_params *shif to @shift->target */ if (shift->part_units) { shift->real_stop = source; - shift->real_stop.unit_pos = (shift->part_units - source.unit_pos - 1) * shift->pend; + shift->real_stop.unit_pos = + (shift->part_units - source.unit_pos - + 1) * shift->pend; assert("nikita-2082", shift->real_stop.unit_pos + 1); } @@ -1720,7 +1794,8 @@ estimate_shift(struct shift_params *shif } static void -copy_units(coord_t * target, coord_t * source, unsigned from, unsigned count, shift_direction dir, unsigned free_space) +copy_units(coord_t * target, coord_t * source, unsigned from, unsigned count, + shift_direction dir, unsigned free_space) { item_plugin *iplug; @@ -1740,15 +1815,15 @@ copy_units(coord_t * target, coord_t * s assert("nikita-1469", target->unit_pos == 0); unit_key_by_coord(target, &split_key); - node_plugin_by_coord(target)->update_item_key(target, &split_key, 0); + node_plugin_by_coord(target)->update_item_key(target, + &split_key, NULL); } } /* copy part of @shift->real_stop.node starting either from its beginning or from its end and ending at @shift->real_stop to either the end or the beginning of @shift->target */ -static void -copy(struct shift_params *shift) +static void copy(struct shift_params *shift) { node40_header *nh; coord_t from; @@ -1764,7 +1839,9 @@ copy(struct shift_params *shift) free_space_start = nh40_get_free_space_start(nh); old_items = nh40_get_num_items(nh); new_items = shift->entire + (shift->part_units ? 1 : 0); - assert("vs-185", shift->shift_bytes == shift->merging_bytes + shift->entire_bytes + shift->part_bytes); + assert("vs-185", + shift->shift_bytes == + shift->merging_bytes + shift->entire_bytes + shift->part_bytes); from = shift->wish_stop; @@ -1776,7 +1853,7 @@ copy(struct shift_params *shift) Oh, wonders of ->betweeness... - */ + */ to.between = AT_UNIT; if (shift->pend == SHIFT_LEFT) { @@ -1785,17 +1862,22 @@ copy(struct shift_params *shift) coord_set_item_pos(&from, 0); from_ih = node40_ih_at(from.node, 0); - coord_set_item_pos(&to, node40_num_of_items_internal(to.node) - 1); + coord_set_item_pos(&to, + node40_num_of_items_internal(to.node) - 1); if (shift->merging_units) { /* expand last item, so that plugin methods will see correct data */ free_space_start += shift->merging_bytes; - nh40_set_free_space_start(nh, (unsigned) free_space_start); - nh40_set_free_space(nh, nh40_get_free_space(nh) - shift->merging_bytes); + nh40_set_free_space_start(nh, + (unsigned)free_space_start); + nh40_set_free_space(nh, + nh40_get_free_space(nh) - + shift->merging_bytes); /* appending last item of @target */ - copy_units(&to, &from, 0, /* starting from 0-th unit */ - shift->merging_units, SHIFT_LEFT, shift->merging_bytes); + copy_units(&to, &from, 0, /* starting from 0-th unit */ + shift->merging_units, SHIFT_LEFT, + shift->merging_bytes); coord_inc_item_pos(&from); from_ih--; coord_inc_item_pos(&to); @@ -1807,78 +1889,104 @@ copy(struct shift_params *shift) /* copy item headers */ memcpy(to_ih - shift->entire + 1, - from_ih - shift->entire + 1, shift->entire * sizeof (item_header40)); + from_ih - shift->entire + 1, + shift->entire * sizeof(item_header40)); /* update item header offset */ old_offset = ih40_get_offset(from_ih); /* AUDIT: Looks like if we calculate old_offset + free_space_start here instead of just old_offset, we can perform one "add" operation less per each iteration */ for (i = 0; i < shift->entire; i++, to_ih--, from_ih--) - ih40_set_offset(to_ih, ih40_get_offset(from_ih) - old_offset + free_space_start); + ih40_set_offset(to_ih, + ih40_get_offset(from_ih) - + old_offset + free_space_start); /* copy item bodies */ memcpy(zdata(shift->target) + free_space_start, zdata(from.node) + old_offset, /*ih40_get_offset (from_ih), */ shift->entire_bytes); - coord_add_item_pos(&from, (int) shift->entire); - coord_add_item_pos(&to, (int) shift->entire); + coord_add_item_pos(&from, (int)shift->entire); + coord_add_item_pos(&to, (int)shift->entire); } - nh40_set_free_space_start(nh, free_space_start + shift->shift_bytes - shift->merging_bytes); + nh40_set_free_space_start(nh, + free_space_start + + shift->shift_bytes - + shift->merging_bytes); nh40_set_free_space(nh, nh40_get_free_space(nh) - - (shift->shift_bytes - shift->merging_bytes + sizeof (item_header40) * new_items)); + (shift->shift_bytes - shift->merging_bytes + + sizeof(item_header40) * new_items)); /* update node header */ node40_set_num_items(shift->target, nh, old_items + new_items); - assert("vs-170", nh40_get_free_space(nh) < znode_size(shift->target)); + assert("vs-170", + nh40_get_free_space(nh) < znode_size(shift->target)); if (shift->part_units) { /* copy heading part (@part units) of @source item as a new item into @target->node */ /* copy item header of partially copied item */ - coord_set_item_pos(&to, node40_num_of_items_internal(to.node) + coord_set_item_pos(&to, + node40_num_of_items_internal(to.node) - 1); - memcpy(to_ih, from_ih, sizeof (item_header40)); - ih40_set_offset(to_ih, nh40_get_free_space_start(nh) - shift->part_bytes); + memcpy(to_ih, from_ih, sizeof(item_header40)); + ih40_set_offset(to_ih, + nh40_get_free_space_start(nh) - + shift->part_bytes); if (item_plugin_by_coord(&to)->b.init) - item_plugin_by_coord(&to)->b.init(&to, &from, 0); - copy_units(&to, &from, 0, shift->part_units, SHIFT_LEFT, shift->part_bytes); + item_plugin_by_coord(&to)->b.init(&to, &from, + NULL); + copy_units(&to, &from, 0, shift->part_units, SHIFT_LEFT, + shift->part_bytes); } } else { /* copying to right */ - coord_set_item_pos(&from, node40_num_of_items_internal(from.node) - 1); + coord_set_item_pos(&from, + node40_num_of_items_internal(from.node) - 1); from_ih = node40_ih_at_coord(&from); coord_set_item_pos(&to, 0); /* prepare space for new items */ - memmove(zdata(to.node) + sizeof (node40_header) + + memmove(zdata(to.node) + sizeof(node40_header) + shift->shift_bytes, - zdata(to.node) + sizeof (node40_header), free_space_start - sizeof (node40_header)); + zdata(to.node) + sizeof(node40_header), + free_space_start - sizeof(node40_header)); /* update item headers of moved items */ to_ih = node40_ih_at(to.node, 0); /* first item gets @merging_bytes longer. free space appears at its beginning */ if (!node_is_empty(to.node)) - ih40_set_offset(to_ih, ih40_get_offset(to_ih) + shift->shift_bytes - shift->merging_bytes); + ih40_set_offset(to_ih, + ih40_get_offset(to_ih) + + shift->shift_bytes - + shift->merging_bytes); for (i = 1; i < old_items; i++) - ih40_set_offset(to_ih - i, ih40_get_offset(to_ih - i) + shift->shift_bytes); + ih40_set_offset(to_ih - i, + ih40_get_offset(to_ih - i) + + shift->shift_bytes); /* move item headers to make space for new items */ - memmove(to_ih - old_items + 1 - new_items, to_ih - old_items + 1, sizeof (item_header40) * old_items); + memmove(to_ih - old_items + 1 - new_items, + to_ih - old_items + 1, + sizeof(item_header40) * old_items); to_ih -= (new_items - 1); - nh40_set_free_space_start(nh, free_space_start + shift->shift_bytes); + nh40_set_free_space_start(nh, + free_space_start + + shift->shift_bytes); nh40_set_free_space(nh, nh40_get_free_space(nh) - - (shift->shift_bytes + sizeof (item_header40) * new_items)); + (shift->shift_bytes + + sizeof(item_header40) * new_items)); /* update node header */ node40_set_num_items(shift->target, nh, old_items + new_items); - assert("vs-170", nh40_get_free_space(nh) < znode_size(shift->target)); + assert("vs-170", + nh40_get_free_space(nh) < znode_size(shift->target)); if (shift->merging_units) { coord_add_item_pos(&to, new_items); @@ -1887,7 +1995,9 @@ copy(struct shift_params *shift) /* prepend first item of @to */ copy_units(&to, &from, coord_last_unit_pos(&from) - - shift->merging_units + 1, shift->merging_units, SHIFT_RIGHT, shift->merging_bytes); + shift->merging_units + 1, + shift->merging_units, SHIFT_RIGHT, + shift->merging_bytes); coord_dec_item_pos(&from); from_ih++; } @@ -1896,18 +2006,22 @@ copy(struct shift_params *shift) /* copy @entire items entirely */ /* copy item headers */ - memcpy(to_ih, from_ih, shift->entire * sizeof (item_header40)); + memcpy(to_ih, from_ih, + shift->entire * sizeof(item_header40)); /* update item header offset */ - old_offset = ih40_get_offset(from_ih + shift->entire - 1); + old_offset = + ih40_get_offset(from_ih + shift->entire - 1); /* AUDIT: old_offset + sizeof (node40_header) + shift->part_bytes calculation can be taken off the loop. */ for (i = 0; i < shift->entire; i++, to_ih++, from_ih++) ih40_set_offset(to_ih, ih40_get_offset(from_ih) - - old_offset + sizeof (node40_header) + shift->part_bytes); + old_offset + + sizeof(node40_header) + + shift->part_bytes); /* copy item bodies */ - coord_add_item_pos(&from, -(int) (shift->entire - 1)); - memcpy(zdata(to.node) + sizeof (node40_header) + + coord_add_item_pos(&from, -(int)(shift->entire - 1)); + memcpy(zdata(to.node) + sizeof(node40_header) + shift->part_bytes, item_by_coord_node40(&from), shift->entire_bytes); coord_dec_item_pos(&from); @@ -1921,21 +2035,22 @@ copy(struct shift_params *shift) a new item into @target->node */ /* copy item header of partially copied item */ - memcpy(to_ih, from_ih, sizeof (item_header40)); - ih40_set_offset(to_ih, sizeof (node40_header)); + memcpy(to_ih, from_ih, sizeof(item_header40)); + ih40_set_offset(to_ih, sizeof(node40_header)); if (item_plugin_by_coord(&to)->b.init) - item_plugin_by_coord(&to)->b.init(&to, &from, 0); + item_plugin_by_coord(&to)->b.init(&to, &from, + NULL); copy_units(&to, &from, coord_last_unit_pos(&from) - - shift->part_units + 1, shift->part_units, SHIFT_RIGHT, shift->part_bytes); + shift->part_units + 1, shift->part_units, + SHIFT_RIGHT, shift->part_bytes); } } } /* remove everything either before or after @fact_stop. Number of items removed completely is returned */ -static int -delete_copied(struct shift_params *shift) +static int delete_copied(struct shift_params *shift) { coord_t from; coord_t to; @@ -1967,10 +2082,10 @@ delete_copied(struct shift_params *shift cdata.params.from = &from; cdata.params.to = &to; - cdata.params.from_key = 0; - cdata.params.to_key = 0; - cdata.params.smallest_removed = 0; - return cut_node40(&cdata, 0); + cdata.params.from_key = NULL; + cdata.params.to_key = NULL; + cdata.params.smallest_removed = NULL; + return cut_node40(&cdata, NULL); } /* something was moved between @left and @right. Add carry operation to @info @@ -2017,8 +2132,7 @@ prepare_for_update(znode * left, znode * /* plugin->u.node.prepare_removal to delete a pointer to @empty from the tree add corresponding carry operation (delete) to @info list */ -reiser4_internal int -prepare_removal_node40(znode * empty, carry_plugin_info * info) +int prepare_removal_node40(znode * empty, carry_plugin_info * info) { carry_op *op; @@ -2031,7 +2145,7 @@ prepare_removal_node40(znode * empty, ca if (IS_ERR(op) || op == NULL) return RETERR(op ? PTR_ERR(op) : -EIO); - op->u.delete.child = 0; + op->u.delete.child = NULL; op->u.delete.flags = 0; /* fare thee well */ @@ -2051,7 +2165,8 @@ prepare_removal_node40(znode * empty, ca /* something were shifted from @insert_coord->node to @shift->target, update @insert_coord correspondingly */ static void -adjust_coord(coord_t * insert_coord, struct shift_params *shift, int removed, int including_insert_coord) +adjust_coord(coord_t * insert_coord, struct shift_params *shift, int removed, + int including_insert_coord) { /* item plugin was invalidated by shifting */ coord_clear_iplug(insert_coord); @@ -2062,16 +2177,19 @@ adjust_coord(coord_t * insert_coord, str if (shift->pend == SHIFT_RIGHT) { /* set @insert_coord before first unit of @shift->target node */ - coord_init_before_first_item(insert_coord, shift->target); + coord_init_before_first_item(insert_coord, + shift->target); } else { /* set @insert_coord after last in target node */ - coord_init_after_last_item(insert_coord, shift->target); + coord_init_after_last_item(insert_coord, + shift->target); } } else { /* set @insert_coord inside of empty node. There is only one possible coord within an empty node. init_first_unit will set that coord */ - coord_init_first_unit(insert_coord, shift->wish_stop.node); + coord_init_first_unit(insert_coord, + shift->wish_stop.node); } return; } @@ -2083,12 +2201,14 @@ adjust_coord(coord_t * insert_coord, str if (including_insert_coord) { /* @insert_coord is set before first unit of @to node */ - coord_init_before_first_item(insert_coord, shift->target); + coord_init_before_first_item(insert_coord, + shift->target); insert_coord->between = BEFORE_UNIT; } else { /* @insert_coord is set after last unit of @insert->node */ - coord_init_last_unit(insert_coord, shift->wish_stop.node); + coord_init_last_unit(insert_coord, + shift->wish_stop.node); insert_coord->between = AFTER_UNIT; } } @@ -2104,7 +2224,8 @@ adjust_coord(coord_t * insert_coord, str } else { /* @insert_coord is set before first unit in the same node */ - coord_init_before_first_item(insert_coord, shift->wish_stop.node); + coord_init_before_first_item(insert_coord, + shift->wish_stop.node); } return; } @@ -2114,29 +2235,44 @@ adjust_coord(coord_t * insert_coord, str if (!removed) { /* no items were shifted entirely */ - assert("vs-195", shift->merging_units == 0 || shift->part_units == 0); + assert("vs-195", shift->merging_units == 0 + || shift->part_units == 0); if (shift->real_stop.item_pos == insert_coord->item_pos) { if (shift->merging_units) { if (insert_coord->between == AFTER_UNIT) { - assert("nikita-1441", insert_coord->unit_pos >= shift->merging_units); - insert_coord->unit_pos -= shift->merging_units; + assert("nikita-1441", + insert_coord->unit_pos >= + shift->merging_units); + insert_coord->unit_pos -= + shift->merging_units; } else if (insert_coord->between == BEFORE_UNIT) { - assert("nikita-2090", insert_coord->unit_pos > shift->merging_units); - insert_coord->unit_pos -= shift->merging_units; + assert("nikita-2090", + insert_coord->unit_pos > + shift->merging_units); + insert_coord->unit_pos -= + shift->merging_units; } - assert("nikita-2083", insert_coord->unit_pos + 1); + assert("nikita-2083", + insert_coord->unit_pos + 1); } else { if (insert_coord->between == AFTER_UNIT) { - assert("nikita-1442", insert_coord->unit_pos >= shift->part_units); - insert_coord->unit_pos -= shift->part_units; + assert("nikita-1442", + insert_coord->unit_pos >= + shift->part_units); + insert_coord->unit_pos -= + shift->part_units; } else if (insert_coord->between == BEFORE_UNIT) { - assert("nikita-2089", insert_coord->unit_pos > shift->part_units); - insert_coord->unit_pos -= shift->part_units; + assert("nikita-2089", + insert_coord->unit_pos > + shift->part_units); + insert_coord->unit_pos -= + shift->part_units; } - assert("nikita-2084", insert_coord->unit_pos + 1); + assert("nikita-2084", + insert_coord->unit_pos + 1); } } return; @@ -2157,8 +2293,7 @@ adjust_coord(coord_t * insert_coord, str assert("nikita-2085", insert_coord->unit_pos + 1); } -static int -call_shift_hooks(struct shift_params *shift) +static int call_shift_hooks(struct shift_params *shift) { unsigned i, shifted; coord_t coord; @@ -2167,7 +2302,9 @@ call_shift_hooks(struct shift_params *sh assert("vs-275", !node_is_empty(shift->target)); /* number of items shift touches */ - shifted = shift->entire + (shift->merging_units ? 1 : 0) + (shift->part_units ? 1 : 0); + shifted = + shift->entire + (shift->merging_units ? 1 : 0) + + (shift->part_units ? 1 : 0); if (shift->pend == SHIFT_LEFT) { /* moved items are at the end */ @@ -2180,7 +2317,9 @@ call_shift_hooks(struct shift_params *sh iplug = item_plugin_by_coord(&coord); if (i == 0 && shift->part_units) { - assert("vs-277", coord_num_units(&coord) == shift->part_units); + assert("vs-277", + coord_num_units(&coord) == + shift->part_units); count = shift->part_units; from = 0; } else if (i == shifted - 1 && shift->merging_units) { @@ -2192,7 +2331,8 @@ call_shift_hooks(struct shift_params *sh } if (iplug->b.shift_hook) { - iplug->b.shift_hook(&coord, from, count, shift->wish_stop.node); + iplug->b.shift_hook(&coord, from, count, + shift->wish_stop.node); } coord_add_item_pos(&coord, -shift->pend); } @@ -2206,7 +2346,9 @@ call_shift_hooks(struct shift_params *sh iplug = item_plugin_by_coord(&coord); if (i == 0 && shift->part_units) { - assert("vs-277", coord_num_units(&coord) == shift->part_units); + assert("vs-277", + coord_num_units(&coord) == + shift->part_units); count = coord_num_units(&coord); from = 0; } else if (i == shifted - 1 && shift->merging_units) { @@ -2218,7 +2360,8 @@ call_shift_hooks(struct shift_params *sh } if (iplug->b.shift_hook) { - iplug->b.shift_hook(&coord, from, count, shift->wish_stop.node); + iplug->b.shift_hook(&coord, from, count, + shift->wish_stop.node); } coord_add_item_pos(&coord, -shift->pend); } @@ -2260,8 +2403,8 @@ unit_moved_right(const struct shift_para /* coord @old was set in node from which shift was performed. What was shifted is stored in @shift. Update @old correspondingly to performed shift */ -static coord_t * -adjust_coord2(const struct shift_params *shift, const coord_t * old, coord_t * new) +static coord_t *adjust_coord2(const struct shift_params *shift, + const coord_t * old, coord_t * new) { coord_clear_iplug(new); new->between = old->between; @@ -2302,16 +2445,20 @@ adjust_coord2(const struct shift_params if (old->item_pos == 0) { /* unit_pos only changes if item got merged */ - new->unit_pos = coord_num_units(new) - (shift->merging_units - old->unit_pos); + new->unit_pos = + coord_num_units(new) - + (shift->merging_units - + old->unit_pos); } } } else { /* unit @old did not move to left neighbor. Use _nocheck, because @old is outside of its node. - */ + */ coord_dup_nocheck(new, old); - coord_add_item_pos(new, -shift->u.future_first.item_pos); + coord_add_item_pos(new, + -shift->u.future_first.item_pos); if (new->item_pos == 0) new->unit_pos -= shift->u.future_first.unit_pos; } @@ -2341,16 +2488,17 @@ adjust_coord2(const struct shift_params /* this is called when shift is completed (something of source node is copied to target and deleted in source) to update all taps set in current context */ -static void -update_taps(const struct shift_params *shift) +static void update_taps(const struct shift_params *shift) { tap_t *tap; coord_t new; for_all_taps(tap) { /* update only taps set to nodes participating in shift */ - if (tap->coord->node == shift->wish_stop.node || tap->coord->node == shift->target) - tap_to_coord(tap, adjust_coord2(shift, tap->coord, &new)); + if (tap->coord->node == shift->wish_stop.node + || tap->coord->node == shift->target) + tap_to_coord(tap, + adjust_coord2(shift, tap->coord, &new)); } } @@ -2366,15 +2514,13 @@ struct shift_check { } u; }; -void * -shift_check_prepare(const znode *left, const znode *right) +void *shift_check_prepare(const znode * left, const znode * right) { pos_in_node_t i, nr_items; int mergeable; struct shift_check *data; item_header40 *ih; - if (node_is_empty(left) || node_is_empty(right)) mergeable = 0; else { @@ -2384,8 +2530,11 @@ shift_check_prepare(const znode *left, c coord_init_first_unit(&r, right); mergeable = are_items_mergeable(&l, &r); } - nr_items = node40_num_of_items_internal(left) + node40_num_of_items_internal(right) - (mergeable ? 1 : 0); - data = reiser4_kmalloc(sizeof(struct shift_check) * nr_items, GFP_KERNEL); + nr_items = + node40_num_of_items_internal(left) + + node40_num_of_items_internal(right) - (mergeable ? 1 : 0); + data = + kmalloc(sizeof(struct shift_check) * nr_items, GFP_KERNEL); if (data != NULL) { coord_t coord; pos_in_node_t item_pos; @@ -2393,20 +2542,24 @@ shift_check_prepare(const znode *left, c coord_init_first_unit(&coord, left); i = 0; - for (item_pos = 0; item_pos < node40_num_of_items_internal(left); item_pos ++) { + for (item_pos = 0; + item_pos < node40_num_of_items_internal(left); + item_pos++) { coord_set_item_pos(&coord, item_pos); ih = node40_ih_at_coord(&coord); data[i].key = ih->key; data[i].plugin_id = d16tocpu(&ih->plugin_id); - switch(data[i].plugin_id) { + switch (data[i].plugin_id) { case CTAIL_ID: case FORMATTING_ID: data[i].u.bytes = coord_num_units(&coord); break; case EXTENT_POINTER_ID: - data[i].u.bytes = extent_size(&coord, coord_num_units(&coord)); + data[i].u.bytes = + extent_size(&coord, + coord_num_units(&coord)); break; case COMPOUND_DIR_ID: data[i].u.entries = coord_num_units(&coord); @@ -2415,7 +2568,7 @@ shift_check_prepare(const znode *left, c data[i].u.unused = NULL; break; } - i ++; + i++; } coord_init_first_unit(&coord, right); @@ -2425,17 +2578,22 @@ shift_check_prepare(const znode *left, c ih = node40_ih_at_coord(&coord); - assert("vs-1589", data[i - 1].plugin_id == d16tocpu(&ih->plugin_id)); - switch(data[i - 1].plugin_id) { + assert("vs-1589", + data[i - 1].plugin_id == + d16tocpu(&ih->plugin_id)); + switch (data[i - 1].plugin_id) { case CTAIL_ID: case FORMATTING_ID: data[i - 1].u.bytes += coord_num_units(&coord); break; case EXTENT_POINTER_ID: - data[i - 1].u.bytes += extent_size(&coord, coord_num_units(&coord)); + data[i - 1].u.bytes += + extent_size(&coord, + coord_num_units(&coord)); break; case COMPOUND_DIR_ID: - data[i - 1].u.entries += coord_num_units(&coord); + data[i - 1].u.entries += + coord_num_units(&coord); break; default: impossible("vs-1605", "wrong mergeable item"); @@ -2444,7 +2602,8 @@ shift_check_prepare(const znode *left, c item_pos = 1; } else item_pos = 0; - for (; item_pos < node40_num_of_items_internal(right); item_pos ++) { + for (; item_pos < node40_num_of_items_internal(right); + item_pos++) { assert("vs-1604", i < nr_items); coord_set_item_pos(&coord, item_pos); @@ -2452,13 +2611,15 @@ shift_check_prepare(const znode *left, c data[i].key = ih->key; data[i].plugin_id = d16tocpu(&ih->plugin_id); - switch(data[i].plugin_id) { + switch (data[i].plugin_id) { case CTAIL_ID: case FORMATTING_ID: data[i].u.bytes = coord_num_units(&coord); break; case EXTENT_POINTER_ID: - data[i].u.bytes = extent_size(&coord, coord_num_units(&coord)); + data[i].u.bytes = + extent_size(&coord, + coord_num_units(&coord)); break; case COMPOUND_DIR_ID: data[i].u.entries = coord_num_units(&coord); @@ -2467,15 +2628,14 @@ shift_check_prepare(const znode *left, c data[i].u.unused = NULL; break; } - i ++; + i++; } assert("vs-1606", i == nr_items); } return data; } -void -shift_check(void *vp, const znode *left, const znode *right) +void shift_check(void *vp, const znode * left, const znode * right) { pos_in_node_t i, nr_items; coord_t coord; @@ -2500,45 +2660,60 @@ shift_check(void *vp, const znode *left, mergeable = are_items_mergeable(&l, &r); } - nr_items = node40_num_of_items_internal(left) + node40_num_of_items_internal(right) - (mergeable ? 1 : 0); + nr_items = + node40_num_of_items_internal(left) + + node40_num_of_items_internal(right) - (mergeable ? 1 : 0); i = 0; last_bytes = 0; coord_init_first_unit(&coord, left); - for (item_pos = 0; item_pos < node40_num_of_items_internal(left); item_pos ++) { + for (item_pos = 0; item_pos < node40_num_of_items_internal(left); + item_pos++) { coord_set_item_pos(&coord, item_pos); ih = node40_ih_at_coord(&coord); assert("vs-1611", i == item_pos); assert("vs-1590", keyeq(&ih->key, &data[i].key)); - assert("vs-1591", d16tocpu(&ih->plugin_id) == data[i].plugin_id); - if ((i < (node40_num_of_items_internal(left) - 1)) || !mergeable) { - switch(data[i].plugin_id) { + assert("vs-1591", + d16tocpu(&ih->plugin_id) == data[i].plugin_id); + if ((i < (node40_num_of_items_internal(left) - 1)) + || !mergeable) { + switch (data[i].plugin_id) { case CTAIL_ID: case FORMATTING_ID: - assert("vs-1592", data[i].u.bytes == coord_num_units(&coord)); + assert("vs-1592", + data[i].u.bytes == + coord_num_units(&coord)); break; case EXTENT_POINTER_ID: - assert("vs-1593", data[i].u.bytes == extent_size(&coord, coord_num_units(&coord))); + assert("vs-1593", + data[i].u.bytes == extent_size(&coord, + coord_num_units + (&coord))); break; case COMPOUND_DIR_ID: - assert("vs-1594", data[i].u.entries == coord_num_units(&coord)); + assert("vs-1594", + data[i].u.entries == + coord_num_units(&coord)); break; default: break; } } - if (item_pos == (node40_num_of_items_internal(left) - 1) && mergeable) { - switch(data[i].plugin_id) { + if (item_pos == (node40_num_of_items_internal(left) - 1) + && mergeable) { + switch (data[i].plugin_id) { case CTAIL_ID: case FORMATTING_ID: last_bytes = coord_num_units(&coord); break; case EXTENT_POINTER_ID: - last_bytes = extent_size(&coord, coord_num_units(&coord)); + last_bytes = + extent_size(&coord, + coord_num_units(&coord)); break; case COMPOUND_DIR_ID: last_bytes = coord_num_units(&coord); @@ -2548,27 +2723,36 @@ shift_check(void *vp, const znode *left, break; } } - i ++; + i++; } coord_init_first_unit(&coord, right); if (mergeable) { ih = node40_ih_at_coord(&coord); - assert("vs-1589", data[i - 1].plugin_id == d16tocpu(&ih->plugin_id)); + assert("vs-1589", + data[i - 1].plugin_id == d16tocpu(&ih->plugin_id)); assert("vs-1608", last_bytes != 0); - switch(data[i - 1].plugin_id) { + switch (data[i - 1].plugin_id) { case CTAIL_ID: case FORMATTING_ID: - assert("vs-1596", data[i - 1].u.bytes == last_bytes + coord_num_units(&coord)); + assert("vs-1596", + data[i - 1].u.bytes == + last_bytes + coord_num_units(&coord)); break; case EXTENT_POINTER_ID: - assert("vs-1597", data[i - 1].u.bytes == last_bytes + extent_size(&coord, coord_num_units(&coord))); + assert("vs-1597", + data[i - 1].u.bytes == + last_bytes + extent_size(&coord, + coord_num_units + (&coord))); break; case COMPOUND_DIR_ID: - assert("vs-1598", data[i - 1].u.bytes == last_bytes + coord_num_units(&coord)); + assert("vs-1598", + data[i - 1].u.bytes == + last_bytes + coord_num_units(&coord)); break; default: impossible("vs-1599", "wrong mergeable item"); @@ -2578,44 +2762,47 @@ shift_check(void *vp, const znode *left, } else item_pos = 0; - for (; item_pos < node40_num_of_items_internal(right); item_pos ++) { + for (; item_pos < node40_num_of_items_internal(right); item_pos++) { coord_set_item_pos(&coord, item_pos); ih = node40_ih_at_coord(&coord); assert("vs-1612", keyeq(&ih->key, &data[i].key)); - assert("vs-1613", d16tocpu(&ih->plugin_id) == data[i].plugin_id); - switch(data[i].plugin_id) { + assert("vs-1613", + d16tocpu(&ih->plugin_id) == data[i].plugin_id); + switch (data[i].plugin_id) { case CTAIL_ID: case FORMATTING_ID: - assert("vs-1600", data[i].u.bytes == coord_num_units(&coord)); + assert("vs-1600", + data[i].u.bytes == coord_num_units(&coord)); break; case EXTENT_POINTER_ID: - assert("vs-1601", data[i].u.bytes == extent_size(&coord, coord_num_units(&coord))); + assert("vs-1601", + data[i].u.bytes == extent_size(&coord, + coord_num_units + (&coord))); break; case COMPOUND_DIR_ID: - assert("vs-1602", data[i].u.entries == coord_num_units(&coord)); + assert("vs-1602", + data[i].u.entries == coord_num_units(&coord)); break; default: break; } - i ++; + i++; } assert("vs-1603", i == nr_items); - reiser4_kfree(data); + kfree(data); } #endif /* plugin->u.node.shift look for description of this method in plugin/node/node.h */ -reiser4_internal int -shift_node40(coord_t *from, znode *to, shift_direction pend, - int delete_child, /* if @from->node becomes empty - it will be - deleted from the tree if this is set to 1 */ - int including_stop_coord, - carry_plugin_info *info) +int shift_node40(coord_t * from, znode * to, shift_direction pend, int delete_child, /* if @from->node becomes empty - it will be + deleted from the tree if this is set to 1 */ + int including_stop_coord, carry_plugin_info * info) { struct shift_params shift; int result; @@ -2625,7 +2812,7 @@ shift_node40(coord_t *from, znode *to, s assert("nikita-2161", coord_check(from)); - memset(&shift, 0, sizeof (shift)); + memset(&shift, 0, sizeof(shift)); shift.pend = pend; shift.wish_stop = *from; shift.target = to; @@ -2661,7 +2848,8 @@ shift_node40(coord_t *from, znode *to, s } if (delete_child && node_is_empty(shift.wish_stop.node)) - result = prepare_removal_node40(shift.wish_stop.node, info); + result = + prepare_removal_node40(shift.wish_stop.node, info); else result = 0; /* there is nothing to shift */ @@ -2689,18 +2877,24 @@ shift_node40(coord_t *from, znode *to, s result = delete_copied(&shift); assert("vs-1610", result >= 0); - assert("vs-1471", ((reiser4_context *) current->journal_info)->magic == context_magic); + assert("vs-1471", + ((reiser4_context *) current->journal_info)->magic == + context_magic); /* item which has been moved from one node to another might want to do something on that event. This can be done by item's shift_hook method, which will be now called for every moved items */ call_shift_hooks(&shift); - assert("vs-1472", ((reiser4_context *) current->journal_info)->magic == context_magic); + assert("vs-1472", + ((reiser4_context *) current->journal_info)->magic == + context_magic); update_taps(&shift); - assert("vs-1473", ((reiser4_context *) current->journal_info)->magic == context_magic); + assert("vs-1473", + ((reiser4_context *) current->journal_info)->magic == + context_magic); /* adjust @from pointer in accordance with @including_stop_coord flag and amount of data which was really shifted */ @@ -2722,29 +2916,26 @@ shift_node40(coord_t *from, znode *to, s result = prepare_removal_node40(source, info); } assert("nikita-2080", coord_check(from)); - return result ? result : (int) shift.shift_bytes; + return result ? result : (int)shift.shift_bytes; } /* plugin->u.node.fast_insert() look for description of this method in plugin/node/node.h */ -reiser4_internal int -fast_insert_node40(const coord_t * coord UNUSED_ARG /* node to query */ ) +int fast_insert_node40(const coord_t * coord UNUSED_ARG /* node to query */ ) { return 1; } /* plugin->u.node.fast_paste() look for description of this method in plugin/node/node.h */ -reiser4_internal int -fast_paste_node40(const coord_t * coord UNUSED_ARG /* node to query */ ) +int fast_paste_node40(const coord_t * coord UNUSED_ARG /* node to query */ ) { return 1; } /* plugin->u.node.fast_cut() look for description of this method in plugin/node/node.h */ -reiser4_internal int -fast_cut_node40(const coord_t * coord UNUSED_ARG /* node to query */ ) +int fast_cut_node40(const coord_t * coord UNUSED_ARG /* node to query */ ) { return 1; } @@ -2752,15 +2943,14 @@ fast_cut_node40(const coord_t * coord UN /* plugin->u.node.modify - not defined */ /* plugin->u.node.max_item_size */ -reiser4_internal int -max_item_size_node40(void) +int max_item_size_node40(void) { - return reiser4_get_current_sb()->s_blocksize - sizeof (node40_header) - sizeof (item_header40); + return reiser4_get_current_sb()->s_blocksize - sizeof(node40_header) - + sizeof(item_header40); } /* plugin->u.node.set_item_plugin */ -reiser4_internal int -set_item_plugin_node40(coord_t *coord, item_id id) +int set_item_plugin_node40(coord_t * coord, item_id id) { item_header40 *ih; @@ -2770,7 +2960,6 @@ set_item_plugin_node40(coord_t *coord, i return 0; } - /* Local variables: c-indentation-style: "K&R" diff -puN fs/reiser4/plugin/node/node40.h~reiser4-big-update fs/reiser4/plugin/node/node40.h --- devel/fs/reiser4/plugin/node/node40.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/node/node40.h 2005-09-15 19:51:08.000000000 -0700 @@ -9,7 +9,6 @@ #include - /* format of node header for 40 node layouts. Keep bloat out of this struct. */ typedef struct node40_header { /* identifier of node plugin. Must be located at the very beginning @@ -18,7 +17,7 @@ typedef struct node40_header { /* number of items. Should be first element in the node header, because we haven't yet finally decided whether it shouldn't go into common_header. - */ + */ /* NIKITA-FIXME-HANS: Create a macro such that if there is only one * node format at compile time, and it is this one, accesses do not function dereference when * accessing these fields (and otherwise they do). Probably 80% of users will only have one node format at a time throughout the life of reiser4. */ @@ -28,15 +27,15 @@ typedef struct node40_header { /* offset to start of free space in node */ d16 free_space_start; /* for reiser4_fsck. When information about what is a free - block is corrupted, and we try to recover everything even - if marked as freed, then old versions of data may - duplicate newer versions, and this field allows us to - restore the newer version. Also useful for when users - who don't have the new trashcan installed on their linux distro - delete the wrong files and send us desperate emails - offering $25 for them back. */ + block is corrupted, and we try to recover everything even + if marked as freed, then old versions of data may + duplicate newer versions, and this field allows us to + restore the newer version. Also useful for when users + who don't have the new trashcan installed on their linux distro + delete the wrong files and send us desperate emails + offering $25 for them back. */ - /* magic field we need to tell formatted nodes NIKITA-FIXME-HANS: improve this comment*/ + /* magic field we need to tell formatted nodes NIKITA-FIXME-HANS: improve this comment */ d32 magic; /* flushstamp is made of mk_id and write_counter. mk_id is an id generated randomly at mkreiserfs time. So we can just @@ -70,7 +69,8 @@ typedef struct item_header40 { size_t item_overhead_node40(const znode * node, flow_t * aflow); size_t free_space_node40(znode * node); -node_search_result lookup_node40(znode * node, const reiser4_key * key, lookup_bias bias, coord_t * coord); +node_search_result lookup_node40(znode * node, const reiser4_key * key, + lookup_bias bias, coord_t * coord); int num_of_items_node40(const znode * node); char *item_by_coord_node40(const coord_t * coord); int length_by_coord_node40(const coord_t * coord); @@ -84,16 +84,19 @@ int init_node40(znode * node); int guess_node40(const znode * node); #endif void change_item_size_node40(coord_t * coord, int by); -int create_item_node40(coord_t * target, const reiser4_key * key, reiser4_item_data * data, carry_plugin_info * info); -void update_item_key_node40(coord_t * target, const reiser4_key * key, carry_plugin_info * info); +int create_item_node40(coord_t * target, const reiser4_key * key, + reiser4_item_data * data, carry_plugin_info * info); +void update_item_key_node40(coord_t * target, const reiser4_key * key, + carry_plugin_info * info); int kill_node40(struct carry_kill_data *, carry_plugin_info *); int cut_node40(struct carry_cut_data *, carry_plugin_info *); int shift_node40(coord_t * from, znode * to, shift_direction pend, /* if @from->node becomes empty - it will be deleted from the tree if this is set to 1 - */ - int delete_child, int including_stop_coord, carry_plugin_info * info); + */ + int delete_child, int including_stop_coord, + carry_plugin_info * info); int fast_insert_node40(const coord_t * coord); int fast_paste_node40(const coord_t * coord); @@ -101,7 +104,12 @@ int fast_cut_node40(const coord_t * coor int max_item_size_node40(void); int prepare_removal_node40(znode * empty, carry_plugin_info * info); int set_item_plugin_node40(coord_t * coord, item_id id); -int shrink_item_node40(coord_t *coord, int delta); +int shrink_item_node40(coord_t * coord, int delta); + +#if REISER4_DEBUG +void *shift_check_prepare(const znode *left, const znode *right); +void shift_check(void *vp, const znode *left, const znode *right); +#endif /* __REISER4_NODE40_H__ */ #endif diff -puN fs/reiser4/plugin/node/node.c~reiser4-big-update fs/reiser4/plugin/node/node.c --- devel/fs/reiser4/plugin/node/node.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/node/node.c 2005-09-15 19:51:08.000000000 -0700 @@ -56,10 +56,14 @@ #include "../../super.h" #include "../../reiser4.h" -/* return starting key of the leftmost item in the @node */ -reiser4_internal reiser4_key * -leftmost_key_in_node(const znode * node /* node to query */ , - reiser4_key * key /* resulting key */ ) +/** + * leftmost_key_in_node - get the smallest key in node + * @node: + * @key: store result here + * + * Stores the leftmost key of @node in @key. + */ +reiser4_key *leftmost_key_in_node(const znode *node, reiser4_key *key) { assert("nikita-1634", node != NULL); assert("nikita-1635", key != NULL); @@ -82,7 +86,7 @@ node_plugin node_plugins[LAST_NODE_ID] = .pops = NULL, .label = "unified", .desc = "unified node layout", - .linkage = TYPE_SAFE_LIST_LINK_ZERO, + .linkage = {NULL, NULL} }, .item_overhead = item_overhead_node40, .free_space = free_space_node40, diff -puN fs/reiser4/plugin/node/node.h~reiser4-big-update fs/reiser4/plugin/node/node.h --- devel/fs/reiser4/plugin/node/node.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/node/node.h 2005-09-15 19:51:08.000000000 -0700 @@ -104,20 +104,20 @@ typedef enum { #define REISER4_NODE_MAX_OVERHEAD ( sizeof( reiser4_key ) + 32 ) typedef enum { - REISER4_NODE_DKEYS = (1 << 0), + REISER4_NODE_DKEYS = (1 << 0), REISER4_NODE_TREE_STABLE = (1 << 1) } reiser4_node_check_flag; /* cut and cut_and_kill have too long list of parameters. This structure is just to safe some space on stack */ struct cut_list { - coord_t * from; - coord_t * to; - const reiser4_key * from_key; - const reiser4_key * to_key; - reiser4_key * smallest_removed; - carry_plugin_info * info; + coord_t *from; + coord_t *to; + const reiser4_key *from_key; + const reiser4_key *to_key; + reiser4_key *smallest_removed; + carry_plugin_info *info; __u32 flags; - struct inode *inode; /* this is to pass list of eflushed jnodes down to extent_kill_hook */ + struct inode *inode; /* this is to pass list of eflushed jnodes down to extent_kill_hook */ lock_handle *left; lock_handle *right; }; @@ -141,9 +141,10 @@ typedef struct node_plugin { znode->free_space). */ size_t(*free_space) (znode * node); /* search within the node for the one item which might - contain the key, invoking item->search_within to search within - that item to see if it is in there */ - node_search_result(*lookup) (znode * node, const reiser4_key * key, lookup_bias bias, coord_t * coord); + contain the key, invoking item->search_within to search within + that item to see if it is in there */ + node_search_result(*lookup) (znode * node, const reiser4_key * key, + lookup_bias bias, coord_t * coord); /* number of items in node */ int (*num_of_items) (const znode * node); @@ -157,9 +158,9 @@ typedef struct node_plugin { /* store item key in @key */ reiser4_key *(*key_at) (const coord_t * coord, reiser4_key * key); /* conservatively estimate whether unit of what size can fit - into node. This estimation should be performed without - actually looking into the node's content (free space is saved in - znode). */ + into node. This estimation should be performed without + actually looking into the node's content (free space is saved in + znode). */ size_t(*estimate) (znode * node); /* performs every consistency check the node plugin author could @@ -169,7 +170,7 @@ typedef struct node_plugin { /* Called when node is read into memory and node plugin is already detected. This should read some data into znode (like free space counter) and, optionally, check data consistency. - */ + */ int (*parse) (znode * node); /* This method is called on a new node to initialise plugin specific data (header, etc.) */ @@ -177,7 +178,7 @@ typedef struct node_plugin { /* Check whether @node content conforms to this plugin format. Probably only useful after support for old V3.x formats is added. Uncomment after 4.0 only. - */ + */ /* int ( *guess )( const znode *node ); */ #if REISER4_DEBUG void (*print) (const char *prefix, const znode * node, __u32 flags); @@ -193,7 +194,8 @@ typedef struct node_plugin { reiser4_item_data * data, carry_plugin_info * info); /* update key of item. */ - void (*update_item_key) (coord_t * target, const reiser4_key * key, carry_plugin_info * info); + void (*update_item_key) (coord_t * target, const reiser4_key * key, + carry_plugin_info * info); int (*cut_and_kill) (struct carry_kill_data *, carry_plugin_info *); int (*cut) (struct carry_cut_data *, carry_plugin_info *); @@ -201,7 +203,7 @@ typedef struct node_plugin { /* * shrink item pointed to by @coord by @delta bytes. */ - int (*shrink_item) (coord_t *coord, int delta); + int (*shrink_item) (coord_t * coord, int delta); /* copy as much as possible but not more than up to @stop from @stop->node to @target. If (pend == append) then data from beginning of @@ -210,7 +212,8 @@ typedef struct node_plugin { @target. Copied data are removed from @stop->node. Information about what to do on upper level is stored in @todo */ int (*shift) (coord_t * stop, znode * target, shift_direction pend, - int delete_node, int including_insert_coord, carry_plugin_info * info); + int delete_node, int including_insert_coord, + carry_plugin_info * info); /* return true if this node allows skip carry() in some situations (see fs/reiser4/tree.c:insert_by_coord()). Reiser3.x format emulation doesn't. @@ -219,7 +222,7 @@ typedef struct node_plugin { parent, by bypassing initialisation of carry() structures. It's believed that majority of insertions will fit there. - */ + */ int (*fast_insert) (const coord_t * coord); int (*fast_paste) (const coord_t * coord); int (*fast_cut) (const coord_t * coord); @@ -234,14 +237,15 @@ typedef struct node_plugin { typedef enum { /* standard unified node layout used for both leaf and internal - nodes */ + nodes */ NODE40_ID, LAST_NODE_ID } reiser4_node_id; extern reiser4_key *leftmost_key_in_node(const znode * node, reiser4_key * key); #if REISER4_DEBUG -extern void print_node_content(const char *prefix, const znode * node, __u32 flags); +extern void print_node_content(const char *prefix, const znode * node, + __u32 flags); #endif extern void indent_znode(const znode * node); diff -puN fs/reiser4/plugin/object.c~reiser4-big-update fs/reiser4/plugin/object.c --- devel/fs/reiser4/plugin/object.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/object.c 2005-09-15 19:51:08.000000000 -0700 @@ -1,1168 +1,83 @@ /* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by * reiser4/README */ -/* Examples of object plugins: file, directory, symlink, special file */ -/* Plugins associated with inode: - - Plugin of inode is plugin referenced by plugin-id field of on-disk - stat-data. How we store this plugin in in-core inode is not - important. Currently pointers are used, another variant is to store - offsets and do array lookup on each access. - - Now, each inode has one selected plugin: object plugin that - determines what type of file this object is: directory, regular etc. - - This main plugin can use other plugins that are thus subordinated to - it. Directory instance of object plugin uses hash; regular file - instance uses tail policy plugin. - - Object plugin is either taken from id in stat-data or guessed from - i_mode bits. Once it is established we ask it to install its - subordinate plugins, by looking again in stat-data or inheriting them - from parent. -*/ -/* How new inode is initialized during ->read_inode(): - 1 read stat-data and initialize inode fields: i_size, i_mode, - i_generation, capabilities etc. - 2 read plugin id from stat data or try to guess plugin id - from inode->i_mode bits if plugin id is missing. - 3 Call ->init_inode() method of stat-data plugin to initialise inode fields. - -NIKITA-FIXME-HANS: can you say a little about 1 being done before 3? What if stat data does contain i_size, etc., due to it being an unusual plugin? - 4 Call ->activate() method of object's plugin. Plugin is either read from - from stat-data or guessed from mode bits - 5 Call ->inherit() method of object plugin to inherit as yet -NIKITA-FIXME-HANS: are you missing an "un" here? -initialized - plugins from parent. - - Easy induction proves that on last step all plugins of inode would be - initialized. - - When creating new object: - 1 obtain object plugin id (see next period) -NIKITA-FIXME-HANS: period? - 2 ->install() this plugin - 3 ->inherit() the rest from the parent - -*/ -/* We need some examples of creating an object with default and - non-default plugin ids. Nikita, please create them. -*/ +/* + * Examples of object plugins: file, directory, symlink, special file. + * + * Plugins associated with inode: + * + * Plugin of inode is plugin referenced by plugin-id field of on-disk + * stat-data. How we store this plugin in in-core inode is not + * important. Currently pointers are used, another variant is to store offsets + * and do array lookup on each access. + * + * Now, each inode has one selected plugin: object plugin that + * determines what type of file this object is: directory, regular etc. + * + * This main plugin can use other plugins that are thus subordinated to + * it. Directory instance of object plugin uses hash; regular file + * instance uses tail policy plugin. + * + * Object plugin is either taken from id in stat-data or guessed from + * i_mode bits. Once it is established we ask it to install its + * subordinate plugins, by looking again in stat-data or inheriting them + * from parent. + * + * How new inode is initialized during ->read_inode(): + * 1 read stat-data and initialize inode fields: i_size, i_mode, + * i_generation, capabilities etc. + * 2 read plugin id from stat data or try to guess plugin id + * from inode->i_mode bits if plugin id is missing. + * 3 Call ->init_inode() method of stat-data plugin to initialise inode fields. + * + * NIKITA-FIXME-HANS: can you say a little about 1 being done before 3? What + * if stat data does contain i_size, etc., due to it being an unusual plugin? + * + * 4 Call ->activate() method of object's plugin. Plugin is either read from + * from stat-data or guessed from mode bits + * 5 Call ->inherit() method of object plugin to inherit as yet un initialized + * plugins from parent. + * + * Easy induction proves that on last step all plugins of inode would be + * initialized. + * + * When creating new object: + * 1 obtain object plugin id (see next period) + * NIKITA-FIXME-HANS: period? + * 2 ->install() this plugin + * 3 ->inherit() the rest from the parent + * + * We need some examples of creating an object with default and non-default + * plugin ids. Nikita, please create them. + */ -#include "../forward.h" -#include "../debug.h" -#include "../key.h" -#include "../kassign.h" -#include "../coord.h" -#include "../seal.h" -#include "plugin_header.h" -#include "item/static_stat.h" -#include "file/file.h" -#include "file/pseudo.h" -#include "symlink.h" -#include "dir/dir.h" -#include "item/item.h" -#include "plugin.h" -#include "object.h" -#include "../znode.h" -#include "../tap.h" -#include "../tree.h" -#include "../vfs_ops.h" #include "../inode.h" -#include "../super.h" -#include "../reiser4.h" -#include "../safe_link.h" - -#include -#include -#include -#include -#include /* security_inode_delete() */ -#include /* wake_up_inode() */ -#include - -/* helper function to print errors */ -static void -key_warning(const reiser4_key * key /* key to print */, - const struct inode *inode, - int code /* error code to print */) -{ - assert("nikita-716", key != NULL); - - if (code != -ENOMEM) { - warning("nikita-717", "Error for inode %llu (%i)", - (unsigned long long)get_key_objectid(key), code); - print_key("for key", key); - } -} - -/* NIKITA-FIXME-HANS: perhaps this function belongs in another file? */ -#if REISER4_DEBUG -static void -check_inode_seal(const struct inode *inode, - const coord_t *coord, const reiser4_key *key) -{ - reiser4_key unit_key; - - unit_key_by_coord(coord, &unit_key); - assert("nikita-2752", - WITH_DATA_RET(coord->node, 1, keyeq(key, &unit_key))); - assert("nikita-2753", get_inode_oid(inode) == get_key_objectid(key)); -} - -static void -check_sd_coord(coord_t *coord, const reiser4_key *key) -{ - reiser4_key ukey; - - coord_clear_iplug(coord); - if (zload(coord->node)) - return; - - if (!coord_is_existing_unit(coord) || - !item_plugin_by_coord(coord) || - !keyeq(unit_key_by_coord(coord, &ukey), key) || - (znode_get_level(coord->node) != LEAF_LEVEL) || - !item_is_statdata(coord)) { - warning("nikita-1901", "Conspicuous seal"); - print_key("key", key); - print_coord("coord", coord, 1); - impossible("nikita-2877", "no way"); - } - zrelse(coord->node); -} - -#else -#define check_inode_seal(inode, coord, key) noop -#define check_sd_coord(coord, key) noop -#endif - -/* find sd of inode in a tree, deal with errors */ -reiser4_internal int -lookup_sd(struct inode *inode /* inode to look sd for */ , - znode_lock_mode lock_mode /* lock mode */ , - coord_t * coord /* resulting coord */ , - lock_handle * lh /* resulting lock handle */ , - const reiser4_key * key /* resulting key */, - int silent) -{ - int result; - __u32 flags; - - assert("nikita-1692", inode != NULL); - assert("nikita-1693", coord != NULL); - assert("nikita-1694", key != NULL); - - /* look for the object's stat data in a tree. - This returns in "node" pointer to a locked znode and in "pos" - position of an item found in node. Both are only valid if - coord_found is returned. */ - flags = (lock_mode == ZNODE_WRITE_LOCK) ? CBK_FOR_INSERT : 0; - flags |= CBK_UNIQUE; - /* - * traverse tree to find stat data. We cannot use vroot here, because - * it only covers _body_ of the file, and stat data don't belong - * there. - */ - result = coord_by_key(tree_by_inode(inode), - key, - coord, - lh, - lock_mode, - FIND_EXACT, - LEAF_LEVEL, - LEAF_LEVEL, - flags, - 0); - if (REISER4_DEBUG && result == 0) - check_sd_coord(coord, key); - - if (result != 0 && !silent) - key_warning(key, inode, result); - return result; -} - -/* insert new stat-data into tree. Called with inode state - locked. Return inode state locked. */ -static int -insert_new_sd(struct inode *inode /* inode to create sd for */ ) -{ - int result; - reiser4_key key; - coord_t coord; - reiser4_item_data data; - char *area; - reiser4_inode *ref; - lock_handle lh; - oid_t oid; - - assert("nikita-723", inode != NULL); - assert("nikita-3406", inode_get_flag(inode, REISER4_NO_SD)); - - ref = reiser4_inode_data(inode); - spin_lock_inode(inode); - - if (ref->plugin_mask != 0) - /* inode has non-standard plugins */ - inode_set_extension(inode, PLUGIN_STAT); - /* - * prepare specification of new item to be inserted - */ - - data.iplug = inode_sd_plugin(inode); - data.length = data.iplug->s.sd.save_len(inode); - spin_unlock_inode(inode); - - data.data = NULL; - data.user = 0; -/* could be optimized for case where there is only one node format in - * use in the filesystem, probably there are lots of such - * places we could optimize for only one node layout.... -Hans */ - if (data.length > tree_by_inode(inode)->nplug->max_item_size()) { - /* This is silly check, but we don't know actual node where - insertion will go into. */ - return RETERR(-ENAMETOOLONG); - } - oid = oid_allocate(inode->i_sb); -/* NIKITA-FIXME-HANS: what is your opinion on whether this error check should be encapsulated into oid_allocate? */ - if (oid == ABSOLUTE_MAX_OID) - return RETERR(-EOVERFLOW); - - set_inode_oid(inode, oid); - - coord_init_zero(&coord); - init_lh(&lh); - - result = insert_by_key(tree_by_inode(inode), - build_sd_key(inode, &key), - &data, - &coord, - &lh, - /* stat data lives on a leaf level */ - LEAF_LEVEL, - CBK_UNIQUE); - - /* we don't want to re-check that somebody didn't insert - stat-data while we were doing io, because if it did, - insert_by_key() returned error. */ - /* but what _is_ possible is that plugin for inode's stat-data, - list of non-standard plugins or their state would change - during io, so that stat-data wouldn't fit into sd. To avoid - this race we keep inode_state lock. This lock has to be - taken each time you access inode in a way that would cause - changes in sd size: changing plugins etc. - */ - - if (result == IBK_INSERT_OK) { - coord_clear_iplug(&coord); - result = zload(coord.node); - if (result == 0) { - /* have we really inserted stat data? */ - assert("nikita-725", item_is_statdata(&coord)); - - /* inode was just created. It is inserted into hash - table, but no directory entry was yet inserted into - parent. So, inode is inaccessible through - ->lookup(). All places that directly grab inode - from hash-table (like old knfsd), should check - IMMUTABLE flag that is set by common_create_child. - */ - assert("nikita-3240", data.iplug != NULL); - assert("nikita-3241", data.iplug->s.sd.save != NULL); - area = item_body_by_coord(&coord); - result = data.iplug->s.sd.save(inode, &area); - znode_make_dirty(coord.node); - if (result == 0) { - /* object has stat-data now */ - inode_clr_flag(inode, REISER4_NO_SD); - inode_set_flag(inode, REISER4_SDLEN_KNOWN); - /* initialise stat-data seal */ - seal_init(&ref->sd_seal, &coord, &key); - ref->sd_coord = coord; - check_inode_seal(inode, &coord, &key); - } else if (result != -ENOMEM) - /* - * convert any other error code to -EIO to - * avoid confusing user level with unexpected - * errors. - */ - result = RETERR(-EIO); - zrelse(coord.node); - } - } - done_lh(&lh); - - if (result != 0) - key_warning(&key, inode, result); - else - oid_count_allocated(); - - return result; -} - - -/* update stat-data at @coord */ -static int -update_sd_at(struct inode * inode, coord_t * coord, reiser4_key * key, - lock_handle * lh) -{ - int result; - reiser4_item_data data; - char *area; - reiser4_inode *state; - znode *loaded; - - state = reiser4_inode_data(inode); - - coord_clear_iplug(coord); - result = zload(coord->node); - if (result != 0) - return result; - loaded = coord->node; - - spin_lock_inode(inode); - assert("nikita-728", inode_sd_plugin(inode) != NULL); - data.iplug = inode_sd_plugin(inode); - - /* if inode has non-standard plugins, add appropriate stat data - * extension */ - if (state->plugin_mask != 0) - inode_set_extension(inode, PLUGIN_STAT); - - /* data.length is how much space to add to (or remove - from if negative) sd */ - if (!inode_get_flag(inode, REISER4_SDLEN_KNOWN)) { - /* recalculate stat-data length */ - data.length = - data.iplug->s.sd.save_len(inode) - - item_length_by_coord(coord); - inode_set_flag(inode, REISER4_SDLEN_KNOWN); - } else - data.length = 0; - spin_unlock_inode(inode); - - /* if on-disk stat data is of different length than required - for this inode, resize it */ - if (data.length != 0) { - data.data = NULL; - data.user = 0; - - /* insertion code requires that insertion point (coord) was - * between units. */ - coord->between = AFTER_UNIT; - result = resize_item(coord, - &data, key, lh, COPI_DONT_SHIFT_LEFT); - if (result != 0) { - key_warning(key, inode, result); - zrelse(loaded); - return result; - } - if (loaded != coord->node) { - /* resize_item moved coord to another node. Zload it */ - zrelse(loaded); - coord_clear_iplug(coord); - result = zload(coord->node); - if (result != 0) - return result; - loaded = coord->node; - } - } - - area = item_body_by_coord(coord); - spin_lock_inode(inode); - result = data.iplug->s.sd.save(inode, &area); - znode_make_dirty(coord->node); - - /* re-initialise stat-data seal */ - - /* - * coord.between was possibly skewed from AT_UNIT when stat-data size - * was changed and new extensions were pasted into item. - */ - coord->between = AT_UNIT; - seal_init(&state->sd_seal, coord, key); - state->sd_coord = *coord; - spin_unlock_inode(inode); - check_inode_seal(inode, coord, key); - zrelse(loaded); - return result; -} - -reiser4_internal int -locate_inode_sd(struct inode *inode, - reiser4_key *key, - coord_t *coord, - lock_handle *lh) -{ - reiser4_inode *state; - seal_t seal; - int result; - - assert("nikita-3483", inode != NULL); - - state = reiser4_inode_data(inode); - spin_lock_inode(inode); - *coord = state->sd_coord; - coord_clear_iplug(coord); - seal = state->sd_seal; - spin_unlock_inode(inode); - - build_sd_key(inode, key); - if (seal_is_set(&seal)) { - /* first, try to use seal */ - result = seal_validate(&seal, - coord, - key, - lh, - ZNODE_WRITE_LOCK, - ZNODE_LOCK_LOPRI); - if (result == 0) - check_sd_coord(coord, key); - } else - result = -E_REPEAT; - - if (result != 0) { - coord_init_zero(coord); - result = lookup_sd(inode, ZNODE_WRITE_LOCK, coord, lh, key, 0); - } - return result; -} - -/* Update existing stat-data in a tree. Called with inode state locked. Return - inode state locked. */ -static int -update_sd(struct inode *inode /* inode to update sd for */ ) -{ - int result; - reiser4_key key; - coord_t coord; - lock_handle lh; - - assert("nikita-726", inode != NULL); - - /* no stat-data, nothing to update?! */ - assert("nikita-3482", !inode_get_flag(inode, REISER4_NO_SD)); - - init_lh(&lh); - - result = locate_inode_sd(inode, &key, &coord, &lh); - if (result == 0) - result = update_sd_at(inode, &coord, &key, &lh); - done_lh(&lh); - - return result; -} -/* NIKITA-FIXME-HANS: the distinction between writing and updating made in the function names seems muddled, please adopt a better function naming strategy */ -/* save object's stat-data to disk */ -reiser4_internal int -write_sd_by_inode_common(struct inode *inode /* object to save */) -{ - int result; - - assert("nikita-730", inode != NULL); - - mark_inode_update(inode, 1); - - if (inode_get_flag(inode, REISER4_NO_SD)) - /* object doesn't have stat-data yet */ - result = insert_new_sd(inode); - else - result = update_sd(inode); - if (result != 0 && result != -ENAMETOOLONG && result != -ENOMEM) - /* Don't issue warnings about "name is too long" */ - warning("nikita-2221", "Failed to save sd for %llu: %i", - (unsigned long long)get_inode_oid(inode), result); - return result; -} - -/* checks whether yet another hard links to this object can be added */ -static int -can_add_link_common(const struct inode *object /* object to check */ ) -{ - assert("nikita-732", object != NULL); - - /* inode->i_nlink is unsigned int, so just check for integer - * overflow */ - return object->i_nlink + 1 != 0; -} - -/* remove object stat data. Space for it must be reserved by caller before */ -static int -common_object_delete_no_reserve(struct inode *inode /* object to remove */) -{ - int result; - - assert("nikita-1477", inode != NULL); - - if (!inode_get_flag(inode, REISER4_NO_SD)) { - reiser4_key sd_key; - - DQUOT_FREE_INODE(inode); - DQUOT_DROP(inode); - - build_sd_key(inode, &sd_key); - result = cut_tree(tree_by_inode(inode), &sd_key, &sd_key, NULL, 0); - if (result == 0) { - inode_set_flag(inode, REISER4_NO_SD); - result = oid_release(inode->i_sb, get_inode_oid(inode)); - if (result == 0) { - oid_count_released(); - - result = safe_link_del(tree_by_inode(inode), - get_inode_oid(inode), - SAFE_UNLINK); - } - } - } else - result = 0; - return result; -} - -/* delete object stat-data. This is to be used when file deletion turns into stat data removal */ -reiser4_internal int -delete_object(struct inode *inode /* object to remove */) -{ - int result; - - assert("nikita-1477", inode != NULL); - /* FIXME: if file body deletion failed (i/o error, for instance), - inode->i_size can be != 0 here */ - assert("nikita-3420", inode->i_size == 0 || S_ISLNK(inode->i_mode)); - assert("nikita-3421", inode->i_nlink == 0); - if (!inode_get_flag(inode, REISER4_NO_SD)) { - reiser4_block_nr reserve; - - /* grab space which is needed to remove 2 items from the tree: - stat data and safe-link */ - reserve = 2 * estimate_one_item_removal(tree_by_inode(inode)); - if (reiser4_grab_space_force(reserve, - BA_RESERVED | BA_CAN_COMMIT)) - return RETERR(-ENOSPC); - result = common_object_delete_no_reserve(inode); - } else - result = 0; - return result; -} - -/* common directory consists of two items: stat data and one item containing "." and ".." */ -static int delete_directory_common(struct inode *inode) +static int _bugop(void) { - int result; - dir_plugin *dplug; - - dplug = inode_dir_plugin(inode); - assert("vs-1101", dplug && dplug->done); - - /* grab space enough for removing two items */ - if (reiser4_grab_space(2 * estimate_one_item_removal(tree_by_inode(inode)), BA_RESERVED | BA_CAN_COMMIT)) - return RETERR(-ENOSPC); - - result = dplug->done(inode); - if (!result) - result = common_object_delete_no_reserve(inode); - all_grabbed2free(); - return result; -} - -/* ->set_plug_in_inode() default method. */ -static int -set_plug_in_inode_common(struct inode *object /* inode to set plugin on */ , - struct inode *parent /* parent object */ , - reiser4_object_create_data * data /* creational - * data */ ) -{ - __u64 mask; - - object->i_mode = data->mode; - /* this should be plugin decision */ - object->i_uid = current->fsuid; - object->i_mtime = object->i_atime = object->i_ctime = CURRENT_TIME; -/* NIKITA-FIXME-HANS: which is defined as what where? */ - /* support for BSD style group-id assignment. */ - if (reiser4_is_set(object->i_sb, REISER4_BSD_GID)) - object->i_gid = parent->i_gid; - else if (parent->i_mode & S_ISGID) { - /* parent directory has sguid bit */ - object->i_gid = parent->i_gid; - if (S_ISDIR(object->i_mode)) - /* sguid is inherited by sub-directories */ - object->i_mode |= S_ISGID; - } else - object->i_gid = current->fsgid; - - /* this object doesn't have stat-data yet */ - inode_set_flag(object, REISER4_NO_SD); - /* setup inode and file-operations for this inode */ - setup_inode_ops(object, data); - object->i_nlink = 0; - seal_init(&reiser4_inode_data(object)->sd_seal, NULL, NULL); - mask = (1 << UNIX_STAT) | (1 << LIGHT_WEIGHT_STAT); - if (!reiser4_is_set(object->i_sb, REISER4_32_BIT_TIMES)) - mask |= (1 << LARGE_TIMES_STAT); - - reiser4_inode_data(object)->extmask = mask; + BUG_ON(1); return 0; } -/* Determine object plugin for @inode based on i_mode. - - Many objects in reiser4 file system are controlled by standard object - plugins that emulate traditional unix objects: unix file, directory, symlink, fifo, and so on. +#define bugop ((void *)_bugop) - For such files we don't explicitly store plugin id in object stat - data. Rather required plugin is guessed from mode bits, where file "type" - is encoded (see stat(2)). -*/ -reiser4_internal int -guess_plugin_by_mode(struct inode *inode /* object to guess plugins - * for */ ) +static int _dummyop(void) { - int fplug_id; - int dplug_id; - reiser4_inode *info; - - assert("nikita-736", inode != NULL); - - dplug_id = fplug_id = -1; - - switch (inode->i_mode & S_IFMT) { - case S_IFSOCK: - case S_IFBLK: - case S_IFCHR: - case S_IFIFO: - fplug_id = SPECIAL_FILE_PLUGIN_ID; - break; - case S_IFLNK: - fplug_id = SYMLINK_FILE_PLUGIN_ID; - break; - case S_IFDIR: - fplug_id = DIRECTORY_FILE_PLUGIN_ID; - dplug_id = HASHED_DIR_PLUGIN_ID; - break; - default: - warning("nikita-737", "wrong file mode: %o", inode->i_mode); - return RETERR(-EIO); - case S_IFREG: - fplug_id = UNIX_FILE_PLUGIN_ID; - break; - } - info = reiser4_inode_data(inode); - plugin_set_file(&info->pset, - (fplug_id >= 0) ? file_plugin_by_id(fplug_id) : NULL); - plugin_set_dir(&info->pset, - (dplug_id >= 0) ? dir_plugin_by_id(dplug_id) : NULL); return 0; } -/* this comon implementation of create estimation function may be used when object creation involves insertion of one item - (usualy stat data) into tree */ -static reiser4_block_nr estimate_create_file_common(struct inode *object) -{ - return estimate_one_insert_item(tree_by_inode(object)); -} +#define dummyop ((void *)_dummyop) -/* this comon implementation of create directory estimation function may be used when directory creation involves - insertion of two items (usualy stat data and item containing "." and "..") into tree */ -static reiser4_block_nr estimate_create_dir_common(struct inode *object) -{ - return 2 * estimate_one_insert_item(tree_by_inode(object)); -} - -/* ->create method of object plugin */ -static int -create_common(struct inode *object, struct inode *parent UNUSED_ARG, - reiser4_object_create_data * data UNUSED_ARG) -{ - reiser4_block_nr reserve; - assert("nikita-744", object != NULL); - assert("nikita-745", parent != NULL); - assert("nikita-747", data != NULL); - assert("nikita-748", inode_get_flag(object, REISER4_NO_SD)); - - reserve = estimate_create_file_common(object); - if (reiser4_grab_space(reserve, BA_CAN_COMMIT)) - return RETERR(-ENOSPC); - return write_sd_by_inode_common(object); -} - -/* standard implementation of ->owns_item() plugin method: compare objectids - of keys in inode and coord */ -reiser4_internal int -owns_item_common(const struct inode *inode /* object to check - * against */ , - const coord_t * coord /* coord to check */ ) -{ - reiser4_key item_key; - reiser4_key file_key; - - assert("nikita-760", inode != NULL); - assert("nikita-761", coord != NULL); - - return /*coord_is_in_node( coord ) && */ - coord_is_existing_item(coord) && - (get_key_objectid(build_sd_key(inode, &file_key)) == get_key_objectid(item_key_by_coord(coord, &item_key))); -} - -/* @count bytes of flow @f got written, update correspondingly f->length, - f->data and f->key */ -reiser4_internal void -move_flow_forward(flow_t * f, unsigned count) -{ - if (f->data) - f->data += count; - f->length -= count; - set_key_offset(&f->key, get_key_offset(&f->key) + count); -} - -/* default ->add_link() method of file plugin */ -static int -add_link_common(struct inode *object, struct inode *parent UNUSED_ARG) -{ - /* - * increment ->i_nlink and update ->i_ctime - */ - - INODE_INC_FIELD(object, i_nlink); - object->i_ctime = CURRENT_TIME; - return 0; -} - -/* default ->rem_link() method of file plugin */ -static int -rem_link_common(struct inode *object, struct inode *parent UNUSED_ARG) -{ - assert("nikita-2021", object != NULL); - assert("nikita-2163", object->i_nlink > 0); - - /* - * decrement ->i_nlink and update ->i_ctime - */ - - INODE_DEC_FIELD(object, i_nlink); - object->i_ctime = CURRENT_TIME; - return 0; -} - -/* default (for directories) ->rem_link() method of file plugin */ -static int -rem_link_common_dir(struct inode *object, struct inode *parent UNUSED_ARG) -{ - assert("nikita-20211", object != NULL); - assert("nikita-21631", object->i_nlink > 0); - - /* - * decrement ->i_nlink and update ->i_ctime - */ - INODE_DEC_FIELD(object, i_nlink); - if (object->i_nlink == 1) - INODE_DEC_FIELD(object, i_nlink); - object->i_ctime = CURRENT_TIME; - return 0; -} - -/* ->adjust_to_parent() method for regular files */ -static int -adjust_to_parent_common(struct inode *object /* new object */ , - struct inode *parent /* parent directory */ , - struct inode *root /* root directory */ ) -{ - assert("nikita-2165", object != NULL); - if (parent == NULL) - parent = root; - assert("nikita-2069", parent != NULL); - - /* - * inherit missing plugins from parent - */ - - grab_plugin(object, parent, PSET_FILE); - grab_plugin(object, parent, PSET_SD); - grab_plugin(object, parent, PSET_FORMATTING); - grab_plugin(object, parent, PSET_PERM); - return 0; -} - -/* ->adjust_to_parent() method for directory files */ -static int -adjust_to_parent_dir(struct inode *object /* new object */ , - struct inode *parent /* parent directory */ , - struct inode *root /* root directory */ ) -{ - int result = 0; - pset_member memb; - - assert("nikita-2166", object != NULL); - if (parent == NULL) - parent = root; - assert("nikita-2167", parent != NULL); - - /* - * inherit missing plugins from parent - */ - for (memb = 0; memb < PSET_LAST; ++ memb) { - result = grab_plugin(object, parent, memb); - if (result != 0) - break; - } - return result; -} - -/* simplest implementation of ->getattr() method. Completely static. */ -static int -getattr_common(struct vfsmount *mnt UNUSED_ARG, struct dentry *dentry, struct kstat *stat) -{ - struct inode *obj; - - assert("nikita-2298", dentry != NULL); - assert("nikita-2299", stat != NULL); - assert("nikita-2300", dentry->d_inode != NULL); - - obj = dentry->d_inode; - - stat->dev = obj->i_sb->s_dev; - stat->ino = oid_to_uino(get_inode_oid(obj)); - stat->mode = obj->i_mode; - /* don't confuse userland with huge nlink. This is not entirely - * correct, because nlink_t is not necessary 16 bit signed. */ - stat->nlink = min(obj->i_nlink, (typeof(obj->i_nlink))0x7fff); - stat->uid = obj->i_uid; - stat->gid = obj->i_gid; - stat->rdev = obj->i_rdev; - stat->atime = obj->i_atime; - stat->mtime = obj->i_mtime; - stat->ctime = obj->i_ctime; - stat->size = obj->i_size; - stat->blocks = (inode_get_bytes(obj) + VFS_BLKSIZE - 1) >> VFS_BLKSIZE_BITS; - /* "preferred" blocksize for efficient file system I/O */ - stat->blksize = get_super_private(obj->i_sb)->optimal_io_size; - - return 0; -} - -/* plugin->u.file.release */ -static int -release_dir(struct inode *inode, struct file *file) -{ - /* this is called when directory file descriptor is closed. */ - spin_lock_inode(inode); - /* remove directory from readddir list. See comment before - * readdir_common() for details. */ - if (file->private_data != NULL) - readdir_list_remove_clean(reiser4_get_file_fsdata(file)); - spin_unlock_inode(inode); - return 0; -} - -/* default implementation of ->bind() method of file plugin */ -static int -bind_common(struct inode *child UNUSED_ARG, struct inode *parent UNUSED_ARG) -{ - return 0; -} - -#define detach_common bind_common -#define cannot ((void *)bind_common) - -static int -detach_dir(struct inode *child, struct inode *parent) -{ - dir_plugin *dplug; - - dplug = inode_dir_plugin(child); - assert("nikita-2883", dplug != NULL); - assert("nikita-2884", dplug->detach != NULL); - return dplug->detach(child, parent); -} - - -/* this common implementation of update estimation function may be used when stat data update does not do more than - inserting a unit into a stat data item which is probably true for most cases */ -reiser4_internal reiser4_block_nr -estimate_update_common(const struct inode *inode) -{ - return estimate_one_insert_into_item(tree_by_inode(inode)); -} - -static reiser4_block_nr -estimate_unlink_common(struct inode *object UNUSED_ARG, - struct inode *parent UNUSED_ARG) -{ - return 0; -} - -static reiser4_block_nr -estimate_unlink_dir_common(struct inode *object, struct inode *parent) -{ - dir_plugin *dplug; - - dplug = inode_dir_plugin(object); - assert("nikita-2888", dplug != NULL); - assert("nikita-2887", dplug->estimate.unlink != NULL); - return dplug->estimate.unlink(object, parent); -} - -/* implementation of ->bind() method for file plugin of directory file */ -static int -bind_dir(struct inode *child, struct inode *parent) -{ - dir_plugin *dplug; - - dplug = inode_dir_plugin(child); - assert("nikita-2646", dplug != NULL); - return dplug->attach(child, parent); -} - -static int -setattr_reserve_common(reiser4_tree *tree) -{ - assert("vs-1096", is_grab_enabled(get_current_context())); - return reiser4_grab_space(estimate_one_insert_into_item(tree), - BA_CAN_COMMIT); -} - -/* ->setattr() method. This is called when inode attribute (including - * ->i_size) is modified. */ -reiser4_internal int -setattr_common(struct inode *inode /* Object to change attributes */, - struct iattr *attr /* change description */) -{ - int result; - - assert("nikita-3119", !(attr->ia_valid & ATTR_SIZE)); - - result = inode_change_ok(inode, attr); - if (result) - return result; - - /* - * grab disk space and call standard inode_setattr(). - */ - result = setattr_reserve_common(tree_by_inode(inode)); - if (!result) { - if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || - (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { - result = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; - if (result) { - all_grabbed2free(); - return result; - } - } - result = inode_setattr(inode, attr); - if (!result) - reiser4_update_sd(inode); - } - - all_grabbed2free(); - return result; -} - -static ssize_t -isdir(void) -{ - return RETERR(-EISDIR); -} - -#define eisdir ((void *)isdir) - -static ssize_t -perm(void) -{ - return RETERR(-EPERM); -} - -#define eperm ((void *)perm) - -static int -can_rem_dir(const struct inode * inode) -{ - /* is_dir_empty() returns 0 is dir is empty */ - return !is_dir_empty(inode); -} - -static int -process_truncate(struct inode *inode, __u64 size) -{ - int result; - struct iattr attr; - file_plugin *fplug; - reiser4_context ctx; - - init_context(&ctx, inode->i_sb); - - attr.ia_size = size; - attr.ia_valid = ATTR_SIZE | ATTR_CTIME; - fplug = inode_file_plugin(inode); - - down(&inode->i_sem); - assert("vs-1704", get_current_context()->trans->atom == NULL); - result = fplug->setattr(inode, &attr); - up(&inode->i_sem); - - context_set_commit_async(&ctx); - reiser4_exit_context(&ctx); - - return result; -} - -static int -safelink_common(struct inode *object, reiser4_safe_link_t link, __u64 value) -{ - int result; - - assert("vs-1705", get_current_context()->trans->atom == NULL); - if (link == SAFE_UNLINK) - /* nothing to do. iput() in the caller (process_safelink) will - * finish with file */ - result = 0; - else if (link == SAFE_TRUNCATE) - result = process_truncate(object, value); - else { - warning("nikita-3438", "Unrecognized safe-link type: %i", link); - result = RETERR(-EIO); - } - return result; -} - -reiser4_internal int prepare_write_common ( - struct file * file, struct page * page, unsigned from, unsigned to) -{ - int result; - file_plugin *fplug; - struct inode *inode; - - assert("umka-3099", file != NULL); - assert("umka-3100", page != NULL); - assert("umka-3095", PageLocked(page)); - - if (to - from == PAGE_CACHE_SIZE || PageUptodate(page)) - return 0; - - inode = page->mapping->host; - fplug = inode_file_plugin(inode); - - if (fplug->readpage == NULL) - return RETERR(-EINVAL); - - result = fplug->readpage(file, page); - if (result != 0) { - SetPageError(page); - ClearPageUptodate(page); - /* All reiser4 readpage() implementations should return the - * page locked in case of error. */ - assert("nikita-3472", PageLocked(page)); - } else { - /* - * ->readpage() either: - * - * 1. starts IO against @page. @page is locked for IO in - * this case. - * - * 2. doesn't start IO. @page is unlocked. - * - * In either case, page should be locked. - */ - lock_page(page); - /* - * IO (if any) is completed at this point. Check for IO - * errors. - */ - if (!PageUptodate(page)) - result = RETERR(-EIO); - } - assert("umka-3098", PageLocked(page)); - return result; -} - -reiser4_internal int -key_by_inode_and_offset_common(struct inode *inode, loff_t off, reiser4_key *key) -{ - reiser4_key_init(key); - set_key_locality(key, reiser4_inode_data(inode)->locality_id); - set_key_ordering(key, get_inode_ordering(inode)); - set_key_objectid(key, get_inode_oid(inode));/*FIXME: inode->i_ino */ - set_key_type(key, KEY_BODY_MINOR); - set_key_offset(key, (__u64) off); - return 0; -} - -/* default implementation of ->sync() method: commit all transactions */ -static int -sync_common(struct inode *inode, int datasync) -{ - return txnmgr_force_commit_all(inode->i_sb, 0); -} - -static int -wire_size_common(struct inode *inode) -{ - return inode_onwire_size(inode); -} - -static char * -wire_write_common(struct inode *inode, char *start) -{ - return build_inode_onwire(inode, start); -} - -static char * -wire_read_common(char *addr, reiser4_object_on_wire *obj) -{ - return extract_obj_key_id_from_onwire(addr, &obj->u.std.key_id); -} - -static void -wire_done_common(reiser4_object_on_wire *obj) -{ - /* nothing to do */ -} - -static struct dentry * -wire_get_common(struct super_block *sb, reiser4_object_on_wire *obj) -{ - struct inode *inode; - struct dentry *dentry; - reiser4_key key; - - extract_key_from_id(&obj->u.std.key_id, &key); - inode = reiser4_iget(sb, &key, 1); - if (!IS_ERR(inode)) { - reiser4_iget_complete(inode); - dentry = d_alloc_anon(inode); - if (dentry == NULL) { - iput(inode); - dentry = ERR_PTR(-ENOMEM); - } else - dentry->d_op = &get_super_private(sb)->ops.dentry; - } else if (PTR_ERR(inode) == -ENOENT) - /* - * inode wasn't found at the key encoded in the file - * handle. Hence, file handle is stale. - */ - dentry = ERR_PTR(RETERR(-ESTALE)); - else - dentry = (void *)inode; - return dentry; -} - - -static int -change_file(struct inode * inode, reiser4_plugin * plugin) +static int change_file(struct inode *inode, reiser4_plugin * plugin) { /* cannot change object plugin of already existing object */ return RETERR(-EINVAL); } static reiser4_plugin_ops file_plugin_ops = { - .init = NULL, - .load = NULL, - .save_len = NULL, - .save = NULL, - .change = change_file + .change = change_file }; - /* * Definitions of object plugins. */ @@ -1175,56 +90,64 @@ file_plugin file_plugins[LAST_FILE_PLUGI .pops = &file_plugin_ops, .label = "reg", .desc = "regular file", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL}, + }, + .inode_ops = { + .permission = permission_common, + .setattr = setattr_unix_file, + .getattr = getattr_common + }, + .file_ops = { + .llseek = generic_file_llseek, + .read = read_unix_file, + .write = write_unix_file, + .ioctl = ioctl_unix_file, + .mmap = mmap_unix_file, + .release = release_unix_file, + .fsync = sync_unix_file, + .sendfile = sendfile_unix_file + }, + .as_ops = { + .writepage = reiser4_writepage, + .readpage = readpage_unix_file, + .sync_page = block_sync_page, + .writepages = writepages_unix_file, + .set_page_dirty = reiser4_set_page_dirty, + .readpages = reiser4_readpages, + .prepare_write = prepare_write_unix_file, + .commit_write = commit_write_unix_file, + .bmap = bmap_unix_file, + .invalidatepage = reiser4_invalidatepage, + .releasepage = reiser4_releasepage }, - .open = NULL, - .truncate = truncate_unix_file, .write_sd_by_inode = write_sd_by_inode_common, - .capturepage = capturepage_unix_file, - .readpage = readpage_unix_file, - .capture = capture_unix_file, - .read = read_unix_file, - .write = write_unix_file, - .release = release_unix_file, - .ioctl = ioctl_unix_file, - .mmap = mmap_unix_file, - .get_block = get_block_unix_file, .flow_by_inode = flow_by_inode_unix_file, - .key_by_inode = key_by_inode_unix_file, + .key_by_inode = key_by_inode_and_offset_common, .set_plug_in_inode = set_plug_in_inode_common, .adjust_to_parent = adjust_to_parent_common, - .create = create_common, - .delete = delete_object, - .sync = sync_unix_file, + .create_object = create_object_common, /* this is not inode_operations's create */ + .delete_object = delete_object_unix_file, .add_link = add_link_common, .rem_link = rem_link_common, .owns_item = owns_item_unix_file, .can_add_link = can_add_link_common, - .can_rem_link = NULL, - .setattr = setattr_unix_file, - .getattr = getattr_common, - .seek = NULL, - .detach = detach_common, - .bind = bind_common, + .detach = dummyop, + .bind = dummyop, .safelink = safelink_common, .estimate = { - .create = estimate_create_file_common, + .create = estimate_create_common, .update = estimate_update_common, .unlink = estimate_unlink_common }, - .wire = { - .write = wire_write_common, - .read = wire_read_common, - .get = wire_get_common, - .size = wire_size_common, - .done = wire_done_common - }, .init_inode_data = init_inode_data_unix_file, - .pre_delete = pre_delete_unix_file, .cut_tree_worker = cut_tree_worker_common, - .destroy_inode = NULL, - .sendfile = sendfile_unix_file, - .prepare_write = prepare_write_unix_file + .wire = { + .write = wire_write_common, + .read = wire_read_common, + .get = wire_get_common, + .size = wire_size_common, + .done = wire_done_common + } }, [DIRECTORY_FILE_PLUGIN_ID] = { .h = { @@ -1233,53 +156,41 @@ file_plugin file_plugins[LAST_FILE_PLUGI .pops = &file_plugin_ops, .label = "dir", .desc = "directory", - .linkage = TYPE_SAFE_LIST_LINK_ZERO}, - .open = NULL, - .truncate = eisdir, + .linkage = {NULL, NULL} + }, + .inode_ops = {NULL,}, + .file_ops = {NULL,}, + .as_ops = {NULL,}, + .write_sd_by_inode = write_sd_by_inode_common, - .capturepage = NULL, - .readpage = eisdir, - .capture = NULL, - .read = eisdir, - .write = eisdir, - .release = release_dir, - .ioctl = eisdir, - .mmap = eisdir, - .get_block = NULL, - .flow_by_inode = NULL, - .key_by_inode = NULL, + .flow_by_inode = bugop, + .key_by_inode = bugop, .set_plug_in_inode = set_plug_in_inode_common, - .adjust_to_parent = adjust_to_parent_dir, - .create = create_common, - .delete = delete_directory_common, - .sync = sync_common, + .adjust_to_parent = adjust_to_parent_common_dir, + .create_object = create_object_common, + .delete_object = delete_directory_common, .add_link = add_link_common, .rem_link = rem_link_common_dir, - .owns_item = owns_item_hashed, + .owns_item = owns_item_common_dir, .can_add_link = can_add_link_common, - .can_rem_link = can_rem_dir, - .setattr = setattr_common, - .getattr = getattr_common, - .seek = seek_dir, - .detach = detach_dir, - .bind = bind_dir, + .can_rem_link = can_rem_link_common_dir, + .detach = detach_common_dir, + .bind = bind_common_dir, .safelink = safelink_common, .estimate = { - .create = estimate_create_dir_common, + .create = estimate_create_common_dir, .update = estimate_update_common, - .unlink = estimate_unlink_dir_common + .unlink = estimate_unlink_common_dir }, .wire = { - .write = wire_write_common, - .read = wire_read_common, - .get = wire_get_common, - .size = wire_size_common, - .done = wire_done_common - }, + .write = wire_write_common, + .read = wire_read_common, + .get = wire_get_common, + .size = wire_size_common, + .done = wire_done_common + }, .init_inode_data = init_inode_ordering, - .pre_delete = NULL, - .cut_tree_worker = cut_tree_worker_common, - .destroy_inode = NULL, + .cut_tree_worker = cut_tree_worker_common }, [SYMLINK_FILE_PLUGIN_ID] = { .h = { @@ -1288,56 +199,45 @@ file_plugin file_plugins[LAST_FILE_PLUGI .pops = &file_plugin_ops, .label = "symlink", .desc = "symbolic link", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL,NULL} + }, + .inode_ops = { + .readlink = readlink_common, + .follow_link = follow_link_common, + .permission = permission_common, + .setattr = setattr_common, + .getattr = getattr_common }, - .open = NULL, - .truncate = eperm, + /* inode->i_fop of symlink is initialized by NULL in setup_inode_ops */ + .file_ops = {NULL,}, + .as_ops = {NULL,}, + .write_sd_by_inode = write_sd_by_inode_common, - .capturepage = NULL, - .readpage = eperm, - .capture = NULL, - .read = eperm, - .write = eperm, - .release = NULL, - .ioctl = eperm, - .mmap = eperm, - .sync = sync_common, - .get_block = NULL, - .flow_by_inode = NULL, - .key_by_inode = NULL, .set_plug_in_inode = set_plug_in_inode_common, .adjust_to_parent = adjust_to_parent_common, - .create = create_symlink, - /* FIXME-VS: symlink should probably have its own destroy - * method */ - .delete = delete_object, + .create_object = create_symlink, + .delete_object = delete_object_common, .add_link = add_link_common, .rem_link = rem_link_common, - .owns_item = NULL, .can_add_link = can_add_link_common, - .can_rem_link = NULL, - .setattr = setattr_common, - .getattr = getattr_common, - .seek = NULL, - .detach = detach_common, - .bind = bind_common, + .detach = dummyop, + .bind = dummyop, .safelink = safelink_common, .estimate = { - .create = estimate_create_file_common, + .create = estimate_create_common, .update = estimate_update_common, .unlink = estimate_unlink_common }, - .wire = { - .write = wire_write_common, - .read = wire_read_common, - .get = wire_get_common, - .size = wire_size_common, - .done = wire_done_common - }, .init_inode_data = init_inode_ordering, - .pre_delete = NULL, .cut_tree_worker = cut_tree_worker_common, .destroy_inode = destroy_inode_symlink, + .wire = { + .write = wire_write_common, + .read = wire_read_common, + .get = wire_get_common, + .size = wire_size_common, + .done = wire_done_common + } }, [SPECIAL_FILE_PLUGIN_ID] = { .h = { @@ -1345,111 +245,46 @@ file_plugin file_plugins[LAST_FILE_PLUGI .id = SPECIAL_FILE_PLUGIN_ID, .pops = &file_plugin_ops, .label = "special", - .desc = "special: fifo, device or socket", - .linkage = TYPE_SAFE_LIST_LINK_ZERO} - , - .open = NULL, - .truncate = eperm, - .create = create_common, + .desc = + "special: fifo, device or socket", + .linkage = {NULL, NULL} + }, + .inode_ops = { + .permission = permission_common, + .setattr = setattr_common, + .getattr = getattr_common + }, + /* file_ops of special files (sockets, block, char, fifo) are + initialized by init_special_inode. */ + .file_ops = {NULL,}, + .as_ops = {NULL,}, + .write_sd_by_inode = write_sd_by_inode_common, - .capturepage = NULL, - .readpage = eperm, - .capture = NULL, - .read = eperm, - .write = eperm, - .release = NULL, - .ioctl = eperm, - .mmap = eperm, - .sync = sync_common, - .get_block = NULL, - .flow_by_inode = NULL, - .key_by_inode = NULL, .set_plug_in_inode = set_plug_in_inode_common, .adjust_to_parent = adjust_to_parent_common, - .delete = delete_object, + .create_object = create_object_common, + .delete_object = delete_object_common, .add_link = add_link_common, .rem_link = rem_link_common, .owns_item = owns_item_common, .can_add_link = can_add_link_common, - .can_rem_link = NULL, - .setattr = setattr_common, - .getattr = getattr_common, - .seek = NULL, - .detach = detach_common, - .bind = bind_common, + .detach = dummyop, + .bind = dummyop, .safelink = safelink_common, .estimate = { - .create = estimate_create_file_common, + .create = estimate_create_common, .update = estimate_update_common, .unlink = estimate_unlink_common }, - .wire = { - .write = wire_write_common, - .read = wire_read_common, - .get = wire_get_common, - .size = wire_size_common, - .done = wire_done_common - }, .init_inode_data = init_inode_ordering, - .pre_delete = NULL, .cut_tree_worker = cut_tree_worker_common, - .destroy_inode = NULL, - }, - [PSEUDO_FILE_PLUGIN_ID] = { - .h = { - .type_id = REISER4_FILE_PLUGIN_TYPE, - .id = PSEUDO_FILE_PLUGIN_ID, - .pops = &file_plugin_ops, - .label = "pseudo", - .desc = "pseudo file", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .open = open_pseudo, - .truncate = eperm, - .write_sd_by_inode = eperm, - .readpage = eperm, - .capturepage = NULL, - .capture = NULL, - .read = read_pseudo, - .write = write_pseudo, - .release = release_pseudo, - .ioctl = eperm, - .mmap = eperm, - .sync = sync_common, - .get_block = eperm, - .flow_by_inode = NULL, - .key_by_inode = NULL, - .set_plug_in_inode = set_plug_in_inode_common, - .adjust_to_parent = NULL, - .create = NULL, - .delete = eperm, - .add_link = NULL, - .rem_link = NULL, - .owns_item = NULL, - .can_add_link = cannot, - .can_rem_link = cannot, - .setattr = inode_setattr, - .getattr = getattr_common, - .seek = seek_pseudo, - .detach = detach_common, - .bind = bind_common, - .safelink = NULL, - .estimate = { - .create = NULL, - .update = NULL, - .unlink = NULL - }, .wire = { - .write = wire_write_pseudo, - .read = wire_read_pseudo, - .get = wire_get_pseudo, - .size = wire_size_pseudo, - .done = wire_done_pseudo - }, - .init_inode_data = NULL, - .pre_delete = NULL, - .cut_tree_worker = cut_tree_worker_common, - .destroy_inode = NULL, + .write = wire_write_common, + .read = wire_read_common, + .get = wire_get_common, + .size = wire_size_common, + .done = wire_done_common + } }, [CRC_FILE_PLUGIN_ID] = { .h = { @@ -1458,58 +293,197 @@ file_plugin file_plugins[LAST_FILE_PLUGI .pops = &cryptcompress_plugin_ops, .label = "cryptcompress", .desc = "cryptcompress file", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} + }, + .inode_ops = { + .permission = permission_common, + .setattr = setattr_cryptcompress, + .getattr = getattr_common + }, + .file_ops = { + .llseek = generic_file_llseek, + .read = read_cryptcompress, + .write = write_cryptcompress, + .mmap = mmap_cryptcompress, + .fsync = sync_common, + .sendfile = sendfile_common + }, + .as_ops = { + .writepage = reiser4_writepage, + .readpage = readpage_cryptcompress, + .sync_page = block_sync_page, + .writepages = writepages_cryptcompress, + .set_page_dirty = reiser4_set_page_dirty, + .readpages = reiser4_readpages, + .prepare_write = prepare_write_common }, - /* FIXME: check which of these are relly needed */ - .open = open_cryptcompress, - .truncate = truncate_cryptcompress, .write_sd_by_inode = write_sd_by_inode_common, - .readpage = readpage_cryptcompress, - .capturepage = NULL, - .capture = capture_cryptcompress, - .read = read_cryptcompress, - .write = write_cryptcompress, - .release = NULL, - .ioctl = NULL, - .mmap = mmap_cryptcompress, - .get_block = get_block_cryptcompress, - .sync = sync_common, .flow_by_inode = flow_by_inode_cryptcompress, .key_by_inode = key_by_inode_cryptcompress, .set_plug_in_inode = set_plug_in_inode_common, .adjust_to_parent = adjust_to_parent_common, - .create = create_cryptcompress, - .delete = delete_cryptcompress, + .create_object = create_cryptcompress, + .delete_object = delete_cryptcompress, .add_link = add_link_common, .rem_link = rem_link_common, .owns_item = owns_item_common, .can_add_link = can_add_link_common, - .can_rem_link = NULL, - .setattr = setattr_cryptcompress, - .getattr = getattr_common, - .seek = NULL, - .detach = detach_common, - .bind = bind_common, + .detach = dummyop, + .bind = dummyop, .safelink = safelink_common, .estimate = { - .create = estimate_create_file_common, + .create = estimate_create_common, .update = estimate_update_common, .unlink = estimate_unlink_common }, - .wire = { - .write = wire_write_common, - .read = wire_read_common, - .get = wire_get_common, - .size = wire_size_common, - .done = wire_done_common - }, - /*.readpages = readpages_cryptcompress,*/ .init_inode_data = init_inode_data_cryptcompress, - .pre_delete = pre_delete_cryptcompress, .cut_tree_worker = cut_tree_worker_cryptcompress, .destroy_inode = destroy_inode_cryptcompress, - .sendfile = sendfile_common, - .prepare_write = prepare_write_common + .wire = { + .write = wire_write_common, + .read = wire_read_common, + .get = wire_get_common, + .size = wire_size_common, + .done = wire_done_common + } + } +}; + +static int change_dir(struct inode *inode, reiser4_plugin * plugin) +{ + /* cannot change dir plugin of already existing object */ + return RETERR(-EINVAL); +} + +static reiser4_plugin_ops dir_plugin_ops = { + .change = change_dir +}; + +/* + * definition of directory plugins + */ + +dir_plugin dir_plugins[LAST_DIR_ID] = { + /* standard hashed directory plugin */ + [HASHED_DIR_PLUGIN_ID] = { + .h = { + .type_id = REISER4_DIR_PLUGIN_TYPE, + .id = HASHED_DIR_PLUGIN_ID, + .pops = &dir_plugin_ops, + .label = "dir", + .desc = "hashed directory", + .linkage = {NULL, NULL} + }, + .inode_ops = { + .create = create_common, + .lookup = lookup_common, + .link = link_common, + .unlink = unlink_common, + .symlink = symlink_common, + .mkdir = mkdir_common, + .rmdir = unlink_common, + .mknod = mknod_common, + .rename = rename_common, + .permission = permission_common, + .setattr = setattr_common, + .getattr = getattr_common + }, + .file_ops = { + .llseek = llseek_common_dir, + .read = generic_read_dir, + .readdir = readdir_common, + .release = release_dir_common, + .fsync = sync_common + }, + .as_ops = { + .writepage = bugop, + .readpage = bugop, + .sync_page = bugop, + .writepages = dummyop, + .set_page_dirty = bugop, + .readpages = bugop, + .prepare_write = bugop, + .commit_write = bugop, + .bmap = bugop, + .invalidatepage = bugop, + .releasepage = bugop + }, + .get_parent = get_parent_common, + .is_name_acceptable = is_name_acceptable_common, + .build_entry_key = build_entry_key_hashed, + .build_readdir_key = build_readdir_key_common, + .add_entry = add_entry_common, + .rem_entry = rem_entry_common, + .init = init_common, + .done = done_common, + .attach = attach_common, + .detach = detach_common, + .estimate = { + .add_entry = estimate_add_entry_common, + .rem_entry = estimate_rem_entry_common, + .unlink = dir_estimate_unlink_common + } + }, + /* hashed directory for which seekdir/telldir are guaranteed to + * work. Brain-damage. */ + [SEEKABLE_HASHED_DIR_PLUGIN_ID] = { + .h = { + .type_id = REISER4_DIR_PLUGIN_TYPE, + .id = SEEKABLE_HASHED_DIR_PLUGIN_ID, + .pops = &dir_plugin_ops, + .label = "dir32", + .desc = "directory hashed with 31 bit hash", + .linkage = {NULL, NULL} + }, + .inode_ops = { + .create = create_common, + .lookup = lookup_common, + .link = link_common, + .unlink = unlink_common, + .symlink = symlink_common, + .mkdir = mkdir_common, + .rmdir = unlink_common, + .mknod = mknod_common, + .rename = rename_common, + .permission = permission_common, + .setattr = setattr_common, + .getattr = getattr_common + }, + .file_ops = { + .llseek = llseek_common_dir, + .read = generic_read_dir, + .readdir = readdir_common, + .release = release_dir_common, + .fsync = sync_common + }, + .as_ops = { + .writepage = bugop, + .readpage = bugop, + .sync_page = bugop, + .writepages = dummyop, + .set_page_dirty = bugop, + .readpages = bugop, + .prepare_write = bugop, + .commit_write = bugop, + .bmap = bugop, + .invalidatepage = bugop, + .releasepage = bugop + }, + .get_parent = get_parent_common, + .is_name_acceptable = is_name_acceptable_common, + .build_entry_key = build_entry_key_seekable, + .build_readdir_key = build_readdir_key_common, + .add_entry = add_entry_common, + .rem_entry = rem_entry_common, + .init = init_common, + .done = done_common, + .attach = attach_common, + .detach = detach_common, + .estimate = { + .add_entry = estimate_add_entry_common, + .rem_entry = estimate_rem_entry_common, + .unlink = dir_estimate_unlink_common + } } }; diff -puN fs/reiser4/plugin/object.h~reiser4-big-update fs/reiser4/plugin/object.h --- devel/fs/reiser4/plugin/object.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/object.h 2005-09-15 19:51:08.000000000 -0700 @@ -6,27 +6,109 @@ #if !defined( __FS_REISER4_PLUGIN_OBJECT_H__ ) #define __FS_REISER4_PLUGIN_OBJECT_H__ -#include "../forward.h" +#include "../type_safe_hash.h" -#include /* for struct inode */ -#include +/* common implementations of inode operations */ +int create_common(struct inode *parent, struct dentry *dentry, + int mode, struct nameidata *); +struct dentry *lookup_common(struct inode *parent, struct dentry *dentry, + struct nameidata *nameidata); +int link_common(struct dentry *existing, struct inode *parent, + struct dentry *newname); +int unlink_common(struct inode *parent, struct dentry *victim); +int mkdir_common(struct inode *parent, struct dentry *dentry, int mode); +int symlink_common(struct inode *parent, struct dentry *dentry, + const char *linkname); +int mknod_common(struct inode *parent, struct dentry *dentry, + int mode, dev_t rdev); +int rename_common(struct inode *old_dir, struct dentry *old_name, + struct inode *new_dir, struct dentry *new_name); +int readlink_common(struct dentry *, char __user *buf, int buflen); +void *follow_link_common(struct dentry *, struct nameidata *data); +int permission_common(struct inode *, int mask, /* mode bits to check permissions for */ + struct nameidata *nameidata); +int setattr_common(struct dentry *, struct iattr *); +int getattr_common(struct vfsmount *mnt, struct dentry *, struct kstat *); + +/* common implementations of file operations */ +loff_t llseek_common_dir(struct file *, loff_t off, int origin); +int readdir_common(struct file *, void *dirent, filldir_t); +int release_dir_common(struct inode *, struct file *); +int sync_common(struct file *, struct dentry *, int datasync); +ssize_t sendfile_common(struct file *, loff_t *ppos, size_t count, + read_actor_t, void *target); + +/* common implementations of address space operations */ +int prepare_write_common(struct file *, struct page *, unsigned from, + unsigned to); + +/* file plugin operations: common implementations */ +int write_sd_by_inode_common(struct inode *); +int key_by_inode_and_offset_common(struct inode *, loff_t, reiser4_key *); +int set_plug_in_inode_common(struct inode *object, struct inode *parent, + reiser4_object_create_data *); +int adjust_to_parent_common(struct inode *object, struct inode *parent, + struct inode *root); +int adjust_to_parent_common_dir(struct inode *object, + struct inode *parent, struct inode *root); +int create_object_common(struct inode *object, struct inode *parent, + reiser4_object_create_data *); +int delete_object_common(struct inode *); +int delete_directory_common(struct inode *); +int add_link_common(struct inode *object, struct inode *parent); +int rem_link_common(struct inode *object, struct inode *parent); +int rem_link_common_dir(struct inode *object, struct inode *parent); +int owns_item_common(const struct inode *, const coord_t *); +int owns_item_common_dir(const struct inode *, const coord_t *); +int can_add_link_common(const struct inode *); +int can_rem_link_common_dir(const struct inode *); +int detach_common_dir(struct inode *child, struct inode *parent); +int bind_common_dir(struct inode *child, struct inode *parent); +int safelink_common(struct inode *, reiser4_safe_link_t, __u64 value); +reiser4_block_nr estimate_create_common(const struct inode *); +reiser4_block_nr estimate_create_common_dir(const struct inode *); +reiser4_block_nr estimate_update_common(const struct inode *); +reiser4_block_nr estimate_unlink_common(const struct inode *, + const struct inode *); +reiser4_block_nr estimate_unlink_common_dir(const struct inode *, + const struct inode *); +char *wire_write_common(struct inode *, char *start); +char *wire_read_common(char *addr, reiser4_object_on_wire *); +struct dentry *wire_get_common(struct super_block *, reiser4_object_on_wire *); +int wire_size_common(struct inode *); +void wire_done_common(reiser4_object_on_wire *); + +/* dir plugin operations: common implementations */ +struct dentry *get_parent_common(struct inode *child); +int is_name_acceptable_common(const struct inode *, const char *name, int len); +void build_entry_key_common(const struct inode *, + const struct qstr *qname, reiser4_key *); +int build_readdir_key_common(struct file *dir, reiser4_key *); +int add_entry_common(struct inode *object, struct dentry *where, + reiser4_object_create_data *, reiser4_dir_entry_desc *); +int rem_entry_common(struct inode *object, struct dentry *where, + reiser4_dir_entry_desc *); +int init_common(struct inode *object, struct inode *parent, + reiser4_object_create_data *); +int done_common(struct inode *); +int attach_common(struct inode *child, struct inode *parent); +int detach_common(struct inode *object, struct inode *parent); +reiser4_block_nr estimate_add_entry_common(const struct inode *); +reiser4_block_nr estimate_rem_entry_common(const struct inode *); +reiser4_block_nr dir_estimate_unlink_common(const struct inode *, + const struct inode *); + +/* these are essential parts of common implementations, they are to make + customized implementations easier */ +ssize_t do_sendfile(struct file *, loff_t *ppos, size_t count, + read_actor_t, void *target); +int do_prepare_write(struct file *, struct page *, unsigned from, unsigned to); + +/* merely useful functions */ +int locate_inode_sd(struct inode *, reiser4_key *, coord_t *, lock_handle *); +int lookup_sd(struct inode *, znode_lock_mode, coord_t *, lock_handle *, + const reiser4_key *, int silent); -extern int locate_inode_sd(struct inode *inode, - reiser4_key *key, coord_t *coord, lock_handle *lh); -extern int lookup_sd(struct inode *inode, znode_lock_mode lock_mode, - coord_t * coord, lock_handle * lh, const reiser4_key * key, - int silent); -extern int guess_plugin_by_mode(struct inode *inode); - -extern int write_sd_by_inode_common(struct inode *inode); -extern int owns_item_common(const struct inode *inode, - const coord_t * coord); -extern reiser4_block_nr estimate_update_common(const struct inode *inode); -extern int prepare_write_common (struct file *, struct page *, unsigned, unsigned); -extern int key_by_inode_and_offset_common(struct inode *, loff_t, reiser4_key *); -extern int setattr_common(struct inode *, struct iattr *); - -extern reiser4_plugin_ops cryptcompress_plugin_ops; /* __FS_REISER4_PLUGIN_OBJECT_H__ */ #endif diff -puN fs/reiser4/plugin/plugin.c~reiser4-big-update fs/reiser4/plugin/plugin.c --- devel/fs/reiser4/plugin/plugin.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/plugin.c 2005-09-15 19:51:08.000000000 -0700 @@ -192,11 +192,17 @@ int locate_plugin(struct inode *inode, p /* internal functions. */ static reiser4_plugin_type find_type(const char *label); -static reiser4_plugin *find_plugin(reiser4_plugin_type_data * ptype, const char *label); +static reiser4_plugin *find_plugin(reiser4_plugin_type_data * ptype, + const char *label); -/* initialise plugin sub-system. Just call this once on reiser4 startup. */ -reiser4_internal int -init_plugins(void) +/** + * init_plugins - initialize plugins + * + * Initializes plugin sub-system. It is part of reiser4 module + * initialization. For each plugin of each type init method is called and each + * plugin is put into list of plugins. + */ +int init_plugins(void) { reiser4_plugin_type type_id; @@ -208,7 +214,7 @@ init_plugins(void) assert("nikita-3508", ptype->label != NULL); assert("nikita-3509", ptype->type_id == type_id); - plugin_list_init(&ptype->plugins_list); + INIT_LIST_HEAD(&ptype->plugins_list); /* NIKITA-FIXME-HANS: change builtin_num to some other name lacking the term builtin. */ for (i = 0; i < ptype->builtin_num; ++i) { reiser4_plugin *plugin; @@ -228,16 +234,15 @@ init_plugins(void) if (result != 0) return result; } - plugin_list_clean(plugin); - plugin_list_push_back(&ptype->plugins_list, plugin); + INIT_LIST_HEAD(&plugin->h.linkage); + list_add_tail(&plugin->h.linkage, &ptype->plugins_list); } } return 0; } /* true if plugin type id is valid */ -reiser4_internal int -is_type_id_valid(reiser4_plugin_type type_id /* plugin type id */) +int is_type_id_valid(reiser4_plugin_type type_id /* plugin type id */ ) { /* "type_id" is unsigned, so no comparison with 0 is necessary */ @@ -245,18 +250,16 @@ is_type_id_valid(reiser4_plugin_type typ } /* true if plugin id is valid */ -reiser4_internal int -is_plugin_id_valid(reiser4_plugin_type type_id /* plugin type id */ , - reiser4_plugin_id id /* plugin id */) +int is_plugin_id_valid(reiser4_plugin_type type_id /* plugin type id */ , + reiser4_plugin_id id /* plugin id */ ) { assert("nikita-1653", is_type_id_valid(type_id)); return ((id < plugins[type_id].builtin_num) && (id >= 0)); } /* lookup plugin by scanning tables */ -reiser4_internal reiser4_plugin * -lookup_plugin(const char *type_label /* plugin type label */ , - const char *plug_label /* plugin label */ ) +reiser4_plugin *lookup_plugin(const char *type_label /* plugin type label */ , + const char *plug_label /* plugin label */ ) { reiser4_plugin *result; reiser4_plugin_type type_id; @@ -282,12 +285,11 @@ user space, and passed to the filesystem comment really confused me on the first reading.... */ -reiser4_internal reiser4_plugin * -plugin_by_unsafe_id(reiser4_plugin_type type_id /* plugin - * type id, - * unchecked */ , - reiser4_plugin_id id /* plugin id, - * unchecked */ ) +reiser4_plugin *plugin_by_unsafe_id(reiser4_plugin_type type_id /* plugin + * type id, + * unchecked */ , + reiser4_plugin_id id /* plugin id, + * unchecked */ ) { if (is_type_id_valid(type_id)) { if (is_plugin_id_valid(type_id, id)) @@ -303,9 +305,8 @@ plugin_by_unsafe_id(reiser4_plugin_type } /* convert plugin id to the disk format */ -reiser4_internal int -save_plugin_id(reiser4_plugin * plugin /* plugin to convert */ , - d16 * area /* where to store result */ ) +int save_plugin_id(reiser4_plugin * plugin /* plugin to convert */ , + d16 * area /* where to store result */ ) { assert("nikita-1261", plugin != NULL); assert("nikita-1262", area != NULL); @@ -315,39 +316,23 @@ save_plugin_id(reiser4_plugin * plugin / } /* list of all plugins of given type */ -reiser4_internal plugin_list_head * -get_plugin_list(reiser4_plugin_type type_id /* plugin type - * id */ ) +struct list_head *get_plugin_list(reiser4_plugin_type type_id /* plugin type + * id */ ) { assert("nikita-1056", is_type_id_valid(type_id)); return &plugins[type_id].plugins_list; } -#ifdef REISER4_DEBUG_OUTPUT -/* print human readable plugin information */ -reiser4_internal void -print_plugin(const char *prefix /* prefix to print */ , - reiser4_plugin * plugin /* plugin to print */ ) -{ - if (plugin != NULL) { - printk("%s: %s (%s:%i)\n", prefix, plugin->h.desc, plugin->h.label, plugin->h.id); - } else - printk("%s: (nil)\n", prefix); -} - -#endif - /* find plugin type by label */ -static reiser4_plugin_type -find_type(const char *label /* plugin type - * label */ ) +static reiser4_plugin_type find_type(const char *label /* plugin type + * label */ ) { reiser4_plugin_type type_id; assert("nikita-550", label != NULL); for (type_id = 0; type_id < REISER4_PLUGIN_TYPES && - strcmp(label, plugins[type_id].label); ++type_id) { + strcmp(label, plugins[type_id].label); ++type_id) { ; } return type_id; @@ -356,13 +341,12 @@ find_type(const char *label /* plugin ty /* given plugin label find it within given plugin type by scanning array. Used to map user-visible symbolic name to internal kernel id */ -static reiser4_plugin * -find_plugin(reiser4_plugin_type_data * ptype /* plugin - * type to - * find - * plugin - * within */ , - const char *label /* plugin label */ ) +static reiser4_plugin *find_plugin(reiser4_plugin_type_data * ptype /* plugin + * type to + * find + * plugin + * within */ , + const char *label /* plugin label */ ) { int i; reiser4_plugin *result; @@ -380,8 +364,7 @@ find_plugin(reiser4_plugin_type_data * p return NULL; } -int -grab_plugin(struct inode *self, struct inode *ancestor, pset_member memb) +int grab_plugin(struct inode *self, struct inode *ancestor, pset_member memb) { reiser4_plugin *plug; reiser4_inode *parent; @@ -391,8 +374,7 @@ grab_plugin(struct inode *self, struct i return grab_plugin_from(self, memb, plug); } -static void -update_plugin_mask(reiser4_inode *info, pset_member memb) +static void update_plugin_mask(reiser4_inode * info, pset_member memb) { struct dentry *rootdir; reiser4_inode *root; @@ -411,10 +393,10 @@ update_plugin_mask(reiser4_inode *info, } int -grab_plugin_from(struct inode *self, pset_member memb, reiser4_plugin *plug) +grab_plugin_from(struct inode *self, pset_member memb, reiser4_plugin * plug) { reiser4_inode *info; - int result = 0; + int result = 0; info = reiser4_inode_data(self); if (pset_get(info->pset, memb) == NULL) { @@ -425,11 +407,10 @@ grab_plugin_from(struct inode *self, pse return result; } -int -force_plugin(struct inode *self, pset_member memb, reiser4_plugin *plug) +int force_plugin(struct inode *self, pset_member memb, reiser4_plugin * plug) { reiser4_inode *info; - int result = 0; + int result = 0; info = reiser4_inode_data(self); if (plug->h.pops != NULL && plug->h.pops->change != NULL) @@ -441,43 +422,6 @@ force_plugin(struct inode *self, pset_me return result; } -/* defined in fs/reiser4/plugin/file.c */ -extern file_plugin file_plugins[LAST_FILE_PLUGIN_ID]; -/* defined in fs/reiser4/plugin/dir.c */ -extern dir_plugin dir_plugins[LAST_DIR_ID]; -/* defined in fs/reiser4/plugin/item/static_stat.c */ -extern sd_ext_plugin sd_ext_plugins[LAST_SD_EXTENSION]; -/* defined in fs/reiser4/plugin/hash.c */ -extern hash_plugin hash_plugins[LAST_HASH_ID]; -/* defined in fs/reiser4/plugin/fibration.c */ -extern fibration_plugin fibration_plugins[LAST_FIBRATION_ID]; -/* defined in fs/reiser4/plugin/crypt.c */ -extern crypto_plugin crypto_plugins[LAST_CRYPTO_ID]; -/* defined in fs/reiser4/plugin/digest.c */ -extern digest_plugin digest_plugins[LAST_DIGEST_ID]; -/* defined in fs/reiser4/plugin/compress/compress.c */ -extern compression_plugin compression_plugins[LAST_COMPRESSION_ID]; -/* defined in fs/reiser4/plugin/compress/compression_mode.c */ -extern compression_mode_plugin compression_mode_plugins[LAST_COMPRESSION_MODE_ID]; -/* defined in fs/reiser4/plugin/cluster.c */ -extern cluster_plugin cluster_plugins[LAST_CLUSTER_ID]; -/* defined in fs/reiser4/plugin/file/regular.c */ -extern regular_plugin regular_plugins[LAST_REGULAR_ID]; -/* defined in fs/reiser4/plugin/tail.c */ -extern formatting_plugin formatting_plugins[LAST_TAIL_FORMATTING_ID]; -/* defined in fs/reiser4/plugin/security/security.c */ -extern perm_plugin perm_plugins[LAST_PERM_ID]; -/* defined in fs/reiser4/plugin/item/item.c */ -extern item_plugin item_plugins[LAST_ITEM_ID]; -/* defined in fs/reiser4/plugin/node/node.c */ -extern node_plugin node_plugins[LAST_NODE_ID]; -/* defined in fs/reiser4/plugin/disk_format/disk_format.c */ -extern disk_format_plugin format_plugins[LAST_FORMAT_ID]; -/* defined in jnode.c */ -extern jnode_plugin jnode_plugins[LAST_JNODE_TYPE]; -/* defined in plugin/pseudo.c */ -extern pseudo_plugin pseudo_plugins[LAST_PSEUDO_ID]; - reiser4_plugin_type_data plugins[REISER4_PLUGIN_TYPES] = { /* C90 initializers */ [REISER4_FILE_PLUGIN_TYPE] = { @@ -486,8 +430,8 @@ reiser4_plugin_type_data plugins[REISER4 .desc = "Object plugins", .builtin_num = sizeof_array(file_plugins), .builtin = file_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (file_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(file_plugin) }, [REISER4_DIR_PLUGIN_TYPE] = { .type_id = REISER4_DIR_PLUGIN_TYPE, @@ -495,8 +439,8 @@ reiser4_plugin_type_data plugins[REISER4 .desc = "Directory plugins", .builtin_num = sizeof_array(dir_plugins), .builtin = dir_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (dir_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(dir_plugin) }, [REISER4_HASH_PLUGIN_TYPE] = { .type_id = REISER4_HASH_PLUGIN_TYPE, @@ -504,17 +448,18 @@ reiser4_plugin_type_data plugins[REISER4 .desc = "Directory hashes", .builtin_num = sizeof_array(hash_plugins), .builtin = hash_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (hash_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(hash_plugin) }, [REISER4_FIBRATION_PLUGIN_TYPE] = { - .type_id = REISER4_FIBRATION_PLUGIN_TYPE, + .type_id = + REISER4_FIBRATION_PLUGIN_TYPE, .label = "fibration", .desc = "Directory fibrations", .builtin_num = sizeof_array(fibration_plugins), .builtin = fibration_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (fibration_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(fibration_plugin) }, [REISER4_CRYPTO_PLUGIN_TYPE] = { .type_id = REISER4_CRYPTO_PLUGIN_TYPE, @@ -522,8 +467,8 @@ reiser4_plugin_type_data plugins[REISER4 .desc = "Crypto plugins", .builtin_num = sizeof_array(crypto_plugins), .builtin = crypto_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (crypto_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(crypto_plugin) }, [REISER4_DIGEST_PLUGIN_TYPE] = { .type_id = REISER4_DIGEST_PLUGIN_TYPE, @@ -531,8 +476,8 @@ reiser4_plugin_type_data plugins[REISER4 .desc = "Digest plugins", .builtin_num = sizeof_array(digest_plugins), .builtin = digest_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (digest_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(digest_plugin) }, [REISER4_COMPRESSION_PLUGIN_TYPE] = { .type_id = REISER4_COMPRESSION_PLUGIN_TYPE, @@ -540,18 +485,17 @@ reiser4_plugin_type_data plugins[REISER4 .desc = "Compression plugins", .builtin_num = sizeof_array(compression_plugins), .builtin = compression_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (compression_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(compression_plugin) }, - [REISER4_FORMATTING_PLUGIN_TYPE] = { .type_id = REISER4_FORMATTING_PLUGIN_TYPE, .label = "formatting", .desc = "Tail inlining policies", .builtin_num = sizeof_array(formatting_plugins), .builtin = formatting_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (formatting_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(formatting_plugin) }, [REISER4_PERM_PLUGIN_TYPE] = { .type_id = REISER4_PERM_PLUGIN_TYPE, @@ -559,8 +503,8 @@ reiser4_plugin_type_data plugins[REISER4 .desc = "Permission checks", .builtin_num = sizeof_array(perm_plugins), .builtin = perm_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (perm_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(perm_plugin) }, [REISER4_ITEM_PLUGIN_TYPE] = { .type_id = REISER4_ITEM_PLUGIN_TYPE, @@ -568,8 +512,8 @@ reiser4_plugin_type_data plugins[REISER4 .desc = "Item handlers", .builtin_num = sizeof_array(item_plugins), .builtin = item_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (item_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(item_plugin) }, [REISER4_NODE_PLUGIN_TYPE] = { .type_id = REISER4_NODE_PLUGIN_TYPE, @@ -577,8 +521,8 @@ reiser4_plugin_type_data plugins[REISER4 .desc = "node layout handlers", .builtin_num = sizeof_array(node_plugins), .builtin = node_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (node_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(node_plugin) }, [REISER4_SD_EXT_PLUGIN_TYPE] = { .type_id = REISER4_SD_EXT_PLUGIN_TYPE, @@ -586,8 +530,8 @@ reiser4_plugin_type_data plugins[REISER4 .desc = "Parts of stat-data", .builtin_num = sizeof_array(sd_ext_plugins), .builtin = sd_ext_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (sd_ext_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(sd_ext_plugin) }, [REISER4_FORMAT_PLUGIN_TYPE] = { .type_id = REISER4_FORMAT_PLUGIN_TYPE, @@ -595,8 +539,8 @@ reiser4_plugin_type_data plugins[REISER4 .desc = "defines filesystem on disk layout", .builtin_num = sizeof_array(format_plugins), .builtin = format_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (disk_format_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(disk_format_plugin) }, [REISER4_JNODE_PLUGIN_TYPE] = { .type_id = REISER4_JNODE_PLUGIN_TYPE, @@ -604,17 +548,8 @@ reiser4_plugin_type_data plugins[REISER4 .desc = "defines kind of jnode", .builtin_num = sizeof_array(jnode_plugins), .builtin = jnode_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (jnode_plugin) - }, - [REISER4_PSEUDO_PLUGIN_TYPE] = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .label = "pseudo_file", - .desc = "pseudo file", - .builtin_num = sizeof_array(pseudo_plugins), - .builtin = pseudo_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (pseudo_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(jnode_plugin) }, [REISER4_COMPRESSION_MODE_PLUGIN_TYPE] = { .type_id = REISER4_COMPRESSION_MODE_PLUGIN_TYPE, @@ -622,8 +557,8 @@ reiser4_plugin_type_data plugins[REISER4 .desc = "Defines compression mode", .builtin_num = sizeof_array(compression_mode_plugins), .builtin = compression_mode_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (compression_mode_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(compression_mode_plugin) }, [REISER4_CLUSTER_PLUGIN_TYPE] = { .type_id = REISER4_CLUSTER_PLUGIN_TYPE, @@ -631,26 +566,27 @@ reiser4_plugin_type_data plugins[REISER4 .desc = "Defines cluster size", .builtin_num = sizeof_array(cluster_plugins), .builtin = cluster_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (cluster_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(cluster_plugin) }, [REISER4_REGULAR_PLUGIN_TYPE] = { .type_id = REISER4_REGULAR_PLUGIN_TYPE, .label = "regular", .desc = "Defines kind of regular file", - .builtin_num = sizeof_array(regular_plugins), + .builtin_num = + sizeof_array(regular_plugins), .builtin = regular_plugins, - .plugins_list = TYPE_SAFE_LIST_HEAD_ZERO, - .size = sizeof (regular_plugin) + .plugins_list = {NULL, NULL}, + .size = sizeof(regular_plugin) } }; -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - End: -*/ +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 120 + * End: + */ diff -puN fs/reiser4/plugin/plugin.h~reiser4-big-update fs/reiser4/plugin/plugin.h --- devel/fs/reiser4/plugin/plugin.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/plugin.h 2005-09-15 19:51:08.000000000 -0700 @@ -10,17 +10,12 @@ #include "../debug.h" #include "../dformat.h" #include "../key.h" -#include "../type_safe_list.h" #include "compress/compress.h" #include "plugin_header.h" #include "item/static_stat.h" #include "item/internal.h" #include "item/sde.h" #include "item/cde.h" -#include "pseudo/pseudo.h" -#include "symlink.h" -#include "dir/hashed_dir.h" -#include "dir/dir.h" #include "item/item.h" #include "node/node.h" #include "node/node40.h" @@ -40,105 +35,119 @@ #include #include -/* a flow is a sequence of bytes being written to or read from the tree. The - tree will slice the flow into items while storing it into nodes, but all of - that is hidden from anything outside the tree. */ - -struct flow { - reiser4_key key; /* key of start of flow's sequence of bytes */ - loff_t length; /* length of flow's sequence of bytes */ - char *data; /* start of flow's sequence of bytes */ - int user; /* if 1 data is user space, 0 - kernel space */ - rw_op op; /* NIKITA-FIXME-HANS: comment is where? */ -}; - -typedef ssize_t(*rw_f_type) (struct file * file, flow_t * a_flow, loff_t * off); - typedef struct reiser4_object_on_wire reiser4_object_on_wire; -/* File plugin. Defines the set of methods that file plugins implement, some of which are optional. - - A file plugin offers to the caller an interface for IO ( writing to and/or reading from) to what the caller sees as one - sequence of bytes. An IO to it may affect more than one physical sequence of bytes, or no physical sequence of bytes, - it may affect sequences of bytes offered by other file plugins to the semantic layer, and the file plugin may invoke - other plugins and delegate work to them, but its interface is structured for offering the caller the ability to read - and/or write what the caller sees as being a single sequence of bytes. - - The file plugin must present a sequence of bytes to the caller, but it does not necessarily have to store a sequence of - bytes, it does not necessarily have to support efficient tree traversal to any offset in the sequence of bytes (tail - and extent items, whose keys contain offsets, do however provide efficient non-sequential lookup of any offset in the - sequence of bytes). - - Directory plugins provide methods for selecting file plugins by resolving a name for them. - - The functionality other filesystems call an attribute, and rigidly tie together, we decompose into orthogonal - selectable features of files. Using the terminology we will define next, an attribute is a perhaps constrained, - perhaps static length, file whose parent has a uni-count-intra-link to it, which might be grandparent-major-packed, and - whose parent has a deletion method that deletes it. - - File plugins can implement constraints. - - Files can be of variable length (e.g. regular unix files), or of static length (e.g. static sized attributes). - - An object may have many sequences of bytes, and many file plugins, but, it has exactly one objectid. It is usually - desirable that an object has a deletion method which deletes every item with that objectid. Items cannot in general be - found by just their objectids. This means that an object must have either a method built into its deletion plugin - method for knowing what items need to be deleted, or links stored with the object that provide the plugin with a method - for finding those items. Deleting a file within an object may or may not have the effect of deleting the entire - object, depending on the file plugin's deletion method. - - LINK TAXONOMY: - - Many objects have a reference count, and when the reference count reaches 0 the object's deletion method is invoked. - Some links embody a reference count increase ("countlinks"), and others do not ("nocountlinks"). - - Some links are bi-directional links ("bilinks"), and some are uni-directional("unilinks"). - - Some links are between parts of the same object ("intralinks"), and some are between different objects ("interlinks"). - - PACKING TAXONOMY: - - Some items of an object are stored with a major packing locality based on their object's objectid (e.g. unix directory - items in plan A), and these are called "self-major-packed". - - Some items of an object are stored with a major packing locality based on their semantic parent object's objectid - (e.g. unix file bodies in plan A), and these are called "parent-major-packed". - - Some items of an object are stored with a major packing locality based on their semantic grandparent, and these are - called "grandparent-major-packed". Now carefully notice that we run into trouble with key length if we have to store a - 8 byte major+minor grandparent based packing locality, an 8 byte parent objectid, an 8 byte attribute objectid, and an - 8 byte offset, all in a 24 byte key. One of these fields must be sacrificed if an item is to be - grandparent-major-packed, and which to sacrifice is left to the item author choosing to make the item - grandparent-major-packed. You cannot make tail items and extent items grandparent-major-packed, though you could make - them self-major-packed (usually they are parent-major-packed). - - In the case of ACLs (which are composed of fixed length ACEs which consist of {subject-type, - subject, and permission bitmask} triples), it makes sense to not have an offset field in the ACE item key, and to allow - duplicate keys for ACEs. Thus, the set of ACES for a given file is found by looking for a key consisting of the - objectid of the grandparent (thus grouping all ACLs in a directory together), the minor packing locality of ACE, the - objectid of the file, and 0. - - IO involves moving data from one location to another, which means that two locations must be specified, source and - destination. - - This source and destination can be in the filesystem, or they can be a pointer in the user process address space plus a byte count. - - If both source and destination are in the filesystem, then at least one of them must be representable as a pure stream - of bytes (which we call a flow, and define as a struct containing a key, a data pointer, and a length). This may mean - converting one of them into a flow. We provide a generic cast_into_flow() method, which will work for any plugin - supporting read_flow(), though it is inefficiently implemented in that it temporarily stores the flow in a buffer - (Question: what to do with huge flows that cannot fit into memory? Answer: we must not convert them all at once. ) - - Performing a write requires resolving the write request into a flow defining the source, and a method that performs the write, and - a key that defines where in the tree the write is to go. - - Performing a read requires resolving the read request into a flow defining the target, and a method that performs the - read, and a key that defines where in the tree the read is to come from. - - There will exist file plugins which have no pluginid stored on the disk for them, and which are only invoked by other - plugins. - -*/ +/* + * File plugin. Defines the set of methods that file plugins implement, some + * of which are optional. + * + * A file plugin offers to the caller an interface for IO ( writing to and/or + * reading from) to what the caller sees as one sequence of bytes. An IO to it + * may affect more than one physical sequence of bytes, or no physical sequence + * of bytes, it may affect sequences of bytes offered by other file plugins to + * the semantic layer, and the file plugin may invoke other plugins and + * delegate work to them, but its interface is structured for offering the + * caller the ability to read and/or write what the caller sees as being a + * single sequence of bytes. + * + * The file plugin must present a sequence of bytes to the caller, but it does + * not necessarily have to store a sequence of bytes, it does not necessarily + * have to support efficient tree traversal to any offset in the sequence of + * bytes (tail and extent items, whose keys contain offsets, do however provide + * efficient non-sequential lookup of any offset in the sequence of bytes). + * + * Directory plugins provide methods for selecting file plugins by resolving a + * name for them. + * + * The functionality other filesystems call an attribute, and rigidly tie + * together, we decompose into orthogonal selectable features of files. Using + * the terminology we will define next, an attribute is a perhaps constrained, + * perhaps static length, file whose parent has a uni-count-intra-link to it, + * which might be grandparent-major-packed, and whose parent has a deletion + * method that deletes it. + * + * File plugins can implement constraints. + * + * Files can be of variable length (e.g. regular unix files), or of static + * length (e.g. static sized attributes). + * + * An object may have many sequences of bytes, and many file plugins, but, it + * has exactly one objectid. It is usually desirable that an object has a + * deletion method which deletes every item with that objectid. Items cannot + * in general be found by just their objectids. This means that an object must + * have either a method built into its deletion plugin method for knowing what + * items need to be deleted, or links stored with the object that provide the + * plugin with a method for finding those items. Deleting a file within an + * object may or may not have the effect of deleting the entire object, + * depending on the file plugin's deletion method. + * + * LINK TAXONOMY: + * + * Many objects have a reference count, and when the reference count reaches 0 + * the object's deletion method is invoked. Some links embody a reference + * count increase ("countlinks"), and others do not ("nocountlinks"). + * + * Some links are bi-directional links ("bilinks"), and some are + * uni-directional("unilinks"). + * + * Some links are between parts of the same object ("intralinks"), and some are + * between different objects ("interlinks"). + * + * PACKING TAXONOMY: + * + * Some items of an object are stored with a major packing locality based on + * their object's objectid (e.g. unix directory items in plan A), and these are + * called "self-major-packed". + * + * Some items of an object are stored with a major packing locality based on + * their semantic parent object's objectid (e.g. unix file bodies in plan A), + * and these are called "parent-major-packed". + * + * Some items of an object are stored with a major packing locality based on + * their semantic grandparent, and these are called "grandparent-major-packed". + * Now carefully notice that we run into trouble with key length if we have to + * store a 8 byte major+minor grandparent based packing locality, an 8 byte + * parent objectid, an 8 byte attribute objectid, and an 8 byte offset, all in + * a 24 byte key. One of these fields must be sacrificed if an item is to be + * grandparent-major-packed, and which to sacrifice is left to the item author + * choosing to make the item grandparent-major-packed. You cannot make tail + * items and extent items grandparent-major-packed, though you could make them + * self-major-packed (usually they are parent-major-packed). + * + * In the case of ACLs (which are composed of fixed length ACEs which consist + * of {subject-type, subject, and permission bitmask} triples), it makes sense + * to not have an offset field in the ACE item key, and to allow duplicate keys + * for ACEs. Thus, the set of ACES for a given file is found by looking for a + * key consisting of the objectid of the grandparent (thus grouping all ACLs in + * a directory together), the minor packing locality of ACE, the objectid of + * the file, and 0. + * + * IO involves moving data from one location to another, which means that two + * locations must be specified, source and destination. + * + * This source and destination can be in the filesystem, or they can be a + * pointer in the user process address space plus a byte count. + * + * If both source and destination are in the filesystem, then at least one of + * them must be representable as a pure stream of bytes (which we call a flow, + * and define as a struct containing a key, a data pointer, and a length). + * This may mean converting one of them into a flow. We provide a generic + * cast_into_flow() method, which will work for any plugin supporting + * read_flow(), though it is inefficiently implemented in that it temporarily + * stores the flow in a buffer (Question: what to do with huge flows that + * cannot fit into memory? Answer: we must not convert them all at once. ) + * + * Performing a write requires resolving the write request into a flow defining + * the source, and a method that performs the write, and a key that defines + * where in the tree the write is to go. + * + * Performing a read requires resolving the read request into a flow defining + * the target, and a method that performs the read, and a key that defines + * where in the tree the read is to come from. + * + * There will exist file plugins which have no pluginid stored on the disk for + * them, and which are only invoked by other plugins. + */ /* builtin file-plugins */ typedef enum { @@ -153,9 +162,7 @@ typedef enum { SPECIAL_FILE_PLUGIN_ID, /* Plugin id for crypto-compression objects */ CRC_FILE_PLUGIN_ID, - /* pseudo file */ - PSEUDO_FILE_PLUGIN_ID, - /* number of file plugins. Used as size of arrays to hold + /* number of file plugins. Used as size of arrays to hold file plugins. */ LAST_FILE_PLUGIN_ID } reiser4_file_id; @@ -165,138 +172,144 @@ typedef struct file_plugin { /* generic fields */ plugin_header h; - /* file_operations->open is dispatched here */ - int (*open) (struct inode * inode, struct file * file); - /* NIKITA-FIXME-HANS: comment all fields, even the ones every non-beginner FS developer knows.... */ - int (*truncate) (struct inode * inode, loff_t size); + struct inode_operations inode_ops; + struct file_operations file_ops; + struct address_space_operations as_ops; /* save inode cached stat-data onto disk. It was called - reiserfs_update_sd() in 3.x */ - int (*write_sd_by_inode) (struct inode * inode); - int (*readpage) (void *, struct page *); - int (*prepare_write) (struct file *, struct page *, unsigned, unsigned); - - /* captures passed page to current atom and takes care about extents handling. - This is needed for loop back devices support and used from ->commit_write() - -*/ /* ZAM-FIXME-HANS: are you writing to yourself or the reader? Bigger comment please. */ - int (*capturepage) (struct page *); - /* - * add pages created through mmap into object. - */ - int (*capture) (struct inode *inode, struct writeback_control *wbc); - /* these should be implemented using body_read_flow and body_write_flow - builtins */ - ssize_t(*read) (struct file * file, char *buf, size_t size, loff_t * off); - ssize_t(*write) (struct file * file, const char *buf, size_t size, loff_t * off); - - int (*release) (struct inode *inode, struct file * file); - int (*ioctl) (struct inode *, struct file *, unsigned int cmd, unsigned long arg); - int (*mmap) (struct file * file, struct vm_area_struct * vma); - int (*get_block) (struct inode * inode, sector_t block, struct buffer_head * bh_result, int create); -/* private methods: These are optional. If used they will allow you to - minimize the amount of code needed to implement a deviation from some other - method that also uses them. */ - - /* Construct flow into @flow according to user-supplied data. - - This is used by read/write methods to construct a flow to - write/read. ->flow_by_inode() is plugin method, rather than single - global implementation, because key in a flow used by plugin may - depend on data in a @buf. - -NIKITA-FIXME-HANS: please create statistics on what functions are -dereferenced how often for the mongo benchmark. You can supervise -Elena doing this for you if that helps. Email me the list of the top 10, with their counts, and an estimate of the total number of CPU cycles spent dereferencing as a percentage of CPU cycles spent processing (non-idle processing). If the total percent is, say, less than 1%, it will make our coding discussions much easier, and keep me from questioning whether functions like the below are too frequently called to be dereferenced. If the total percent is more than 1%, perhaps private methods should be listed in a "required" comment at the top of each plugin (with stern language about how if the comment is missing it will not be accepted by the maintainer), and implemented using macros not dereferenced functions. How about replacing this whole private methods part of the struct with a thorough documentation of what the standard helper functions are for use in constructing plugins? I think users have been asking for that, though not in so many words. - */ - int (*flow_by_inode) (struct inode *, char *buf, int user, loff_t size, loff_t off, rw_op op, flow_t *); - - /* Return the key used to retrieve an offset of a file. It is used by - default implementation of ->flow_by_inode() method - (common_build_flow()) and, among other things, to get to the extent - from jnode of unformatted node. - */ - int (*key_by_inode) (struct inode * inode, loff_t off, reiser4_key * key); - -/* NIKITA-FIXME-HANS: this comment is not as clear to others as you think.... */ - /* set the plugin for a file. Called during file creation in creat() - but not reiser4() unless an inode already exists for the file. */ - int (*set_plug_in_inode) (struct inode * inode, struct inode * parent, reiser4_object_create_data * data); + reiserfs_update_sd() in 3.x */ + int (*write_sd_by_inode) (struct inode *); + + /* + * private methods: These are optional. If used they will allow you to + * minimize the amount of code needed to implement a deviation from + * some other method that also uses them. + */ + + /* + * Construct flow into @flow according to user-supplied data. + * + * This is used by read/write methods to construct a flow to + * write/read. ->flow_by_inode() is plugin method, rather than single + * global implementation, because key in a flow used by plugin may + * depend on data in a @buf. + * + * NIKITA-FIXME-HANS: please create statistics on what functions are + * dereferenced how often for the mongo benchmark. You can supervise + * Elena doing this for you if that helps. Email me the list of the + * top 10, with their counts, and an estimate of the total number of + * CPU cycles spent dereferencing as a percentage of CPU cycles spent + * processing (non-idle processing). If the total percent is, say, + * less than 1%, it will make our coding discussions much easier, and + * keep me from questioning whether functions like the below are too + * frequently called to be dereferenced. If the total percent is more + * than 1%, perhaps private methods should be listed in a "required" + * comment at the top of each plugin (with stern language about how if + * the comment is missing it will not be accepted by the maintainer), + * and implemented using macros not dereferenced functions. How about + * replacing this whole private methods part of the struct with a + * thorough documentation of what the standard helper functions are for + * use in constructing plugins? I think users have been asking for + * that, though not in so many words. + */ + int (*flow_by_inode) (struct inode *, const char __user *buf, + int user, loff_t size, + loff_t off, rw_op op, flow_t *); + + /* + * Return the key used to retrieve an offset of a file. It is used by + * default implementation of ->flow_by_inode() method + * (common_build_flow()) and, among other things, to get to the extent + * from jnode of unformatted node. + */ + int (*key_by_inode) (struct inode *, loff_t off, reiser4_key *); + + /* NIKITA-FIXME-HANS: this comment is not as clear to others as you think.... */ + /* + * set the plugin for a file. Called during file creation in creat() + * but not reiser4() unless an inode already exists for the file. + */ + int (*set_plug_in_inode) (struct inode *inode, struct inode *parent, + reiser4_object_create_data *); -/* NIKITA-FIXME-HANS: comment and name seem to say different things, are you setting up the object itself also or just adjusting the parent?.... */ + /* NIKITA-FIXME-HANS: comment and name seem to say different things, + * are you setting up the object itself also or just adjusting the + * parent?.... */ /* set up plugins for new @object created in @parent. @root is root directory. */ - int (*adjust_to_parent) (struct inode * object, struct inode * parent, struct inode * root); - /* this does whatever is necessary to do when object is created. For - instance, for unix files stat data is inserted */ - int (*create) (struct inode * object, struct inode * parent, - reiser4_object_create_data * data); - /* delete empty object. This method should check REISER4_NO_SD - and set REISER4_NO_SD on success. Deletion of empty object - at least includes removal of stat-data if any. For directories this - also includes removal of dot and dot-dot. - */ - int (*delete) (struct inode * object); + int (*adjust_to_parent) (struct inode *object, struct inode *parent, + struct inode *root); + + /* + * this does whatever is necessary to do when object is created. For + * instance, for unix files stat data is inserted. It is supposed to be + * called by create of struct inode_operations. + */ + int (*create_object) (struct inode *object, struct inode *parent, + reiser4_object_create_data *); - /* method implementing f_op->fsync() */ - int (*sync)(struct inode *, int datasync); + /* + * this method should check REISER4_NO_SD and set REISER4_NO_SD on + * success. Deletion of an object usually includes removal of items + * building file body (for directories this is removal of "." and "..") + * and removal of stat-data item. + */ + int (*delete_object) (struct inode *); /* add link from @parent to @object */ - int (*add_link) (struct inode * object, struct inode * parent); + int (*add_link) (struct inode *object, struct inode *parent); /* remove link from @parent to @object */ - int (*rem_link) (struct inode * object, struct inode * parent); + int (*rem_link) (struct inode *object, struct inode *parent); - /* return true if item addressed by @coord belongs to @inode. - This is used by read/write to properly slice flow into items - in presence of multiple key assignment policies, because - items of a file are not necessarily contiguous in a key space, - for example, in a plan-b. */ - int (*owns_item) (const struct inode * inode, const coord_t * coord); + /* + * return true if item addressed by @coord belongs to @inode. This is + * used by read/write to properly slice flow into items in presence of + * multiple key assignment policies, because items of a file are not + * necessarily contiguous in a key space, for example, in a plan-b. + */ + int (*owns_item) (const struct inode *, const coord_t *); /* checks whether yet another hard links to this object can be added */ - int (*can_add_link) (const struct inode * inode); - /* checks whether hard links to this object can be removed */ - int (*can_rem_link) (const struct inode * inode); - - /* change inode attributes. */ - int (*setattr) (struct inode * inode, struct iattr * attr); - - /* obtain inode attributes */ - int (*getattr) (struct vfsmount * mnt UNUSED_ARG, struct dentry * dentry, struct kstat * stat); - - /* seek */ - loff_t(*seek) (struct file * f, loff_t offset, int origin); + int (*can_add_link) (const struct inode *); - int (*detach)(struct inode *child, struct inode *parent); + /* checks whether hard links to this object can be removed */ + int (*can_rem_link) (const struct inode *); - /* called when @child was just looked up in the @parent */ + /* not empty for DIRECTORY_FILE_PLUGIN_ID only currently. It calls + detach of directory plugin to remove ".." */ + int (*detach) (struct inode * child, struct inode * parent); + + /* called when @child was just looked up in the @parent. It is not + empty for DIRECTORY_FILE_PLUGIN_ID only where it calls attach of + directory plugin */ int (*bind) (struct inode * child, struct inode * parent); /* process safe-link during mount */ - int (*safelink)(struct inode *object, reiser4_safe_link_t link, - __u64 value); + int (*safelink) (struct inode * object, reiser4_safe_link_t link, + __u64 value); /* The couple of estimate methods for all file operations */ struct { - reiser4_block_nr (*create) (struct inode *); - reiser4_block_nr (*update) (const struct inode *); - reiser4_block_nr (*unlink) (struct inode *, struct inode *); + reiser4_block_nr(*create) (const struct inode *); + reiser4_block_nr(*update) (const struct inode *); + reiser4_block_nr(*unlink) (const struct inode *, + const struct inode *); } estimate; -/* - void (*readpages)(struct file *file, struct address_space *mapping, - struct list_head *pages); -*/ - /* reiser4 specific part of inode has a union of structures which are - specific to a plugin. This method is called when inode is read - (read_inode) and when file is created (common_create_child) so that - file plugin could initialize its inode data */ - void (*init_inode_data)(struct inode *, reiser4_object_create_data *, int); - /** + /* + * reiser4 specific part of inode has a union of structures which are + * specific to a plugin. This method is called when inode is read + * (read_inode) and when file is created (common_create_child) so that + * file plugin could initialize its inode data + */ + void (*init_inode_data) (struct inode *, reiser4_object_create_data *, + int); + + /* * This method performs progressive deletion of items and whole nodes - from right to left. + * from right to left. * * @tap: the point deletion process begins from, * @from_key: the beginning of the deleted key range, @@ -306,35 +319,35 @@ Elena doing this for you if that helps. * @return: 0 if success, error code otherwise, -E_REPEAT means that long cut_tree * operation was interrupted for allowing atom commit . */ - int (*cut_tree_worker)(tap_t * tap, const reiser4_key * from_key, const reiser4_key * to_key, - reiser4_key * smallest_removed, struct inode * object, int, int*); - - /* truncate file to zero size. called by reiser4_drop_inode before truncate_inode_pages */ - int (*pre_delete)(struct inode *); + int (*cut_tree_worker) (tap_t *, const reiser4_key * from_key, + const reiser4_key * to_key, + reiser4_key * smallest_removed, struct inode *, + int, int *); /* called from ->destroy_inode() */ - void (*destroy_inode)(struct inode *); + void (*destroy_inode) (struct inode *); - ssize_t (*sendfile)(struct file *, loff_t *, size_t, read_actor_t, void __user *); /* * methods to serialize object identify. This is used, for example, by * reiser4_{en,de}code_fh(). */ struct { /* store object's identity at @area */ - char *(*write)(struct inode *inode, char *area); + char *(*write) (struct inode * inode, char *area); /* parse object from wire to the @obj */ - char *(*read)(char *area, reiser4_object_on_wire *obj); + char *(*read) (char *area, reiser4_object_on_wire * obj); /* given object identity in @obj, find or create its dentry */ - struct dentry *(*get)(struct super_block *s, - reiser4_object_on_wire *obj); + struct dentry *(*get) (struct super_block * s, + reiser4_object_on_wire * obj); /* how many bytes ->wire.write() consumes */ - int (*size)(struct inode *inode); + int (*size) (struct inode * inode); /* finish with object identify */ - void (*done)(reiser4_object_on_wire *obj); + void (*done) (reiser4_object_on_wire * obj); } wire; } file_plugin; +extern file_plugin file_plugins[LAST_FILE_PLUGIN_ID]; + struct reiser4_object_on_wire { file_plugin *plugin; union { @@ -345,78 +358,82 @@ struct reiser4_object_on_wire { } u; }; +/* builtin dir-plugins */ +typedef enum { + HASHED_DIR_PLUGIN_ID, + SEEKABLE_HASHED_DIR_PLUGIN_ID, + LAST_DIR_ID +} reiser4_dir_id; + typedef struct dir_plugin { /* generic fields */ plugin_header h; - /* for use by open call, based on name supplied will install - appropriate plugin and state information, into the inode such that - subsequent VFS operations that supply a pointer to that inode - operate in a manner appropriate. Note that this may require storing - some state for the plugin, and that this state might even include - the name used by open. */ - int (*lookup) (struct inode * parent_inode, struct dentry **dentry); - /* VFS required/defined operations below this line */ - int (*unlink) (struct inode * parent, struct dentry * victim); - int (*link) (struct inode * parent, struct dentry * existing, struct dentry * where); - /* rename object named by @old entry in @old_dir to be named by @new - entry in @new_dir */ - int (*rename) (struct inode * old_dir, struct dentry * old, struct inode * new_dir, struct dentry * new); - - /* create new object described by @data and add it to the @parent - directory under the name described by @dentry */ - int (*create_child) (reiser4_object_create_data * data, - struct inode ** retobj); - - /* readdir implementation */ - int (*readdir) (struct file * f, void *cookie, filldir_t filldir); - - /* private methods: These are optional. If used they will allow you to - minimize the amount of code needed to implement a deviation from - some other method that uses them. You could logically argue that - they should be a separate type of plugin. */ - - /* check whether "name" is acceptable name to be inserted into - this object. Optionally implemented by directory-like objects. - Can check for maximal length, reserved symbols etc */ - int (*is_name_acceptable) (const struct inode * inode, const char *name, int len); - - void (*build_entry_key) (const struct inode * dir /* directory where - * entry is (or will - * be) in.*/ , - const struct qstr * name /* name of file referenced - * by this entry */ , - reiser4_key * result /* resulting key of directory - * entry */ ); + + struct inode_operations inode_ops; + struct file_operations file_ops; + struct address_space_operations as_ops; + + /* + * private methods: These are optional. If used they will allow you to + * minimize the amount of code needed to implement a deviation from + * some other method that uses them. You could logically argue that + * they should be a separate type of plugin. + */ + + struct dentry *(*get_parent) (struct inode * childdir); + + /* + * check whether "name" is acceptable name to be inserted into this + * object. Optionally implemented by directory-like objects. Can check + * for maximal length, reserved symbols etc + */ + int (*is_name_acceptable) (const struct inode * inode, const char *name, + int len); + + void (*build_entry_key) (const struct inode * dir /* directory where + * entry is (or will + * be) in.*/ , + const struct qstr * name /* name of file + * referenced by this + * entry */ , + reiser4_key * result /* resulting key of + * directory entry */ ); int (*build_readdir_key) (struct file * dir, reiser4_key * result); int (*add_entry) (struct inode * object, struct dentry * where, - reiser4_object_create_data * data, reiser4_dir_entry_desc * entry); + reiser4_object_create_data * data, + reiser4_dir_entry_desc * entry); + int (*rem_entry) (struct inode * object, struct dentry * where, + reiser4_dir_entry_desc * entry); - int (*rem_entry) (struct inode * object, struct dentry * where, reiser4_dir_entry_desc * entry); + /* + * initialize directory structure for newly created object. For normal + * unix directories, insert dot and dotdot. + */ + int (*init) (struct inode * object, struct inode * parent, + reiser4_object_create_data * data); - /* initialize directory structure for newly created object. For normal - unix directories, insert dot and dotdot. */ - int (*init) (struct inode * object, struct inode * parent, reiser4_object_create_data * data); /* destroy directory */ int (*done) (struct inode * child); /* called when @subdir was just looked up in the @dir */ int (*attach) (struct inode * subdir, struct inode * dir); - int (*detach)(struct inode * subdir, struct inode * dir); - - struct dentry *(*get_parent)(struct inode *childdir); + int (*detach) (struct inode * subdir, struct inode * dir); struct { - reiser4_block_nr (*add_entry) (struct inode *node); - reiser4_block_nr (*rem_entry) (struct inode *node); - reiser4_block_nr (*unlink) (struct inode *, struct inode *); + reiser4_block_nr(*add_entry) (const struct inode *); + reiser4_block_nr(*rem_entry) (const struct inode *); + reiser4_block_nr(*unlink) (const struct inode *, + const struct inode *); } estimate; } dir_plugin; +extern dir_plugin dir_plugins[LAST_DIR_ID]; + typedef struct formatting_plugin { /* generic fields */ plugin_header h; /* returns non-zero iff file's tail has to be stored - in a direct item. */ + in a direct item. */ int (*have_tail) (const struct inode * inode, loff_t size); } formatting_plugin; @@ -439,18 +456,19 @@ typedef struct crypto_plugin { For all symmetric algorithms k == 1. For asymmetric algorithms (which inflate data) offset translation guarantees that all disk cluster's units will have keys smaller then next cluster's one. - */ - loff_t (*scale)(struct inode * inode, size_t blocksize, loff_t src); + */ + loff_t(*scale) (struct inode * inode, size_t blocksize, loff_t src); /* Crypto algorithms can accept data only by chunks of crypto block size. This method is to align any flow up to crypto block size when we pass it to crypto algorithm. To align means to append padding of special format specific to the crypto algorithm */ - int (*align_stream)(__u8 *tail, int clust_size, int blocksize); + int (*align_stream) (__u8 * tail, int clust_size, int blocksize); /* low-level key manager (check, install, etc..) */ - int (*setkey) (struct crypto_tfm *tfm, const __u8 *key, unsigned int keylen); + int (*setkey) (struct crypto_tfm * tfm, const __u8 * key, + unsigned int keylen); /* main text processing procedures */ - void (*encrypt) (__u32 *expkey, __u8 *dst, const __u8 *src); - void (*decrypt) (__u32 *expkey, __u8 *dst, const __u8 *src); + void (*encrypt) (__u32 * expkey, __u8 * dst, const __u8 * src); + void (*decrypt) (__u32 * expkey, __u8 * dst, const __u8 * src); } crypto_plugin; typedef struct digest_plugin { @@ -471,17 +489,17 @@ typedef struct compression_plugin { /* the maximum number of bytes the size of the "compressed" data can * exceed the uncompressed data. */ int (*overrun) (unsigned src_len); - coa_t (*alloc) (tfm_action act); + coa_t(*alloc) (tfm_action act); void (*free) (coa_t coa, tfm_action act); /* minimal size of the flow we still try to compress */ int (*min_size_deflate) (void); - __u32 (*checksum) (char * data, __u32 length); + __u32(*checksum) (char *data, __u32 length); /* main transform procedures */ - void (*compress) (coa_t coa, __u8 *src_first, unsigned src_len, - __u8 *dst_first, unsigned *dst_len); - void (*decompress) (coa_t coa, __u8 *src_first, unsigned src_len, - __u8 *dst_first, unsigned *dst_len); -}compression_plugin; + void (*compress) (coa_t coa, __u8 * src_first, unsigned src_len, + __u8 * dst_first, unsigned *dst_len); + void (*decompress) (coa_t coa, __u8 * src_first, unsigned src_len, + __u8 * dst_first, unsigned *dst_len); +} compression_plugin; typedef struct compression_mode_plugin { /* generic fields */ @@ -499,13 +517,13 @@ typedef struct regular_plugin { plugin_header h; /* file plugin id which implements regular file */ reiser4_file_id id; -}regular_plugin; +} regular_plugin; typedef struct cluster_plugin { /* generic fields */ plugin_header h; int shift; -}cluster_plugin; +} cluster_plugin; typedef struct sd_ext_plugin { /* generic fields */ @@ -524,7 +542,8 @@ typedef struct sd_ext_plugin { typedef struct oid_allocator_plugin { /* generic fields */ plugin_header h; - int (*init_oid_allocator) (reiser4_oid_allocator * map, __u64 nr_files, __u64 oids); + int (*init_oid_allocator) (reiser4_oid_allocator * map, __u64 nr_files, + __u64 oids); /* used to report statfs->f_files */ __u64(*oids_used) (reiser4_oid_allocator * map); /* get next oid to use */ @@ -550,15 +569,14 @@ typedef struct disk_format_plugin { /* generic fields */ plugin_header h; /* replay journal, initialize super_info_data, etc */ - int (*get_ready) (struct super_block *, void *data); + int (*init_format) (struct super_block *, void *data); /* key of root directory stat data */ const reiser4_key *(*root_dir_key) (const struct super_block *); int (*release) (struct super_block *); jnode *(*log_super) (struct super_block *); - void (*print_info) (const struct super_block *); - int (*check_open) (const struct inode *object); + int (*check_open) (const struct inode * object); } disk_format_plugin; struct jnode_plugin { @@ -617,8 +635,6 @@ union reiser4_plugin { oid_allocator_plugin oid_allocator; /* plugin for different jnode types */ jnode_plugin jnode; - /* plugin for pseudo files */ - pseudo_plugin pseudo; /* compression_mode_plugin, used by object plugin */ compression_mode_plugin compression_mode; /* cluster_plugin, used by object plugin */ @@ -639,18 +655,19 @@ struct reiser4_plugin_ops { int (*load) (struct inode * inode, reiser4_plugin * plugin, char **area, int *len); /* how many space is required to store this plugin's state - in stat-data */ + in stat-data */ int (*save_len) (struct inode * inode, reiser4_plugin * plugin); /* save persistent plugin-data to disk */ - int (*save) (struct inode * inode, reiser4_plugin * plugin, char **area); + int (*save) (struct inode * inode, reiser4_plugin * plugin, + char **area); /* alignment requirement for on-disk state of this plugin - in number of bytes */ + in number of bytes */ int alignment; /* install itself into given inode. This can return error - (e.g., you cannot change hash of non-empty directory). */ + (e.g., you cannot change hash of non-empty directory). */ int (*change) (struct inode * inode, reiser4_plugin * plugin); /* install itself into given inode. This can return error - (e.g., you cannot change hash of non-empty directory). */ + (e.g., you cannot change hash of non-empty directory). */ int (*inherit) (struct inode * inode, struct inode * parent, reiser4_plugin * plugin); }; @@ -660,22 +677,12 @@ struct reiser4_plugin_ops { /* stores plugin reference in reiser4-specific part of inode */ extern int set_object_plugin(struct inode *inode, reiser4_plugin_id id); extern int setup_plugins(struct super_block *super, reiser4_plugin ** area); -extern reiser4_plugin *lookup_plugin(const char *type_label, const char *plug_label); +extern reiser4_plugin *lookup_plugin(const char *type_label, + const char *plug_label); extern int init_plugins(void); -/* functions implemented in fs/reiser4/plugin/object.c */ -void move_flow_forward(flow_t * f, unsigned count); - /* builtin plugins */ -/* builtin dir-plugins */ -typedef enum { - HASHED_DIR_PLUGIN_ID, - SEEKABLE_HASHED_DIR_PLUGIN_ID, - PSEUDO_DIR_PLUGIN_ID, - LAST_DIR_ID -} reiser4_dir_id; - /* builtin hash-plugins */ typedef enum { @@ -738,23 +745,23 @@ typedef enum { /* Encapsulations of crypto specific data */ typedef struct crypto_data { - reiser4_crypto_id cra; /* id of the crypto algorithm */ - reiser4_digest_id dia; /* id of the digest algorithm */ - __u8 * key; /* secret key */ - __u16 keysize; /* key size, bits */ - __u8 * keyid; /* keyid */ - __u16 keyid_size; /* keyid size, bytes */ + reiser4_crypto_id cra; /* id of the crypto algorithm */ + reiser4_digest_id dia; /* id of the digest algorithm */ + __u8 *key; /* secret key */ + __u16 keysize; /* key size, bits */ + __u8 *keyid; /* keyid */ + __u16 keyid_size; /* keyid size, bytes */ } crypto_data_t; /* compression/clustering specific data */ typedef struct compression_data { - reiser4_compression_id coa; /* id of the compression algorithm */ + reiser4_compression_id coa; /* id of the compression algorithm */ } compression_data_t; -typedef __u8 cluster_data_t; /* cluster info */ +typedef __u8 cluster_data_t; /* cluster info */ -/* data type used to pack parameters that we pass to vfs - object creation function create_object() */ +/* data type used to pack parameters that we pass to vfs object creation + function create_object() */ struct reiser4_object_create_data { /* plugin to control created object */ reiser4_file_id id; @@ -767,14 +774,33 @@ struct reiser4_object_create_data { const char *name; /* add here something for non-standard objects you invent, like query for interpolation file etc. */ - crypto_data_t * crypto; - compression_data_t * compression; - cluster_data_t * cluster; + crypto_data_t *crypto; + compression_data_t *compression; + cluster_data_t *cluster; - struct inode *parent; + struct inode *parent; struct dentry *dentry; }; +/* description of directory entry being created/destroyed/sought for + + It is passed down to the directory plugin and farther to the + directory item plugin methods. Creation of new directory is done in + several stages: first we search for an entry with the same name, then + create new one. reiser4_dir_entry_desc is used to store some information + collected at some stage of this process and required later: key of + item that we want to insert/delete and pointer to an object that will + be bound by the new directory entry. Probably some more fields will + be added there. + +*/ +struct reiser4_dir_entry_desc { + /* key of directory entry */ + reiser4_key key; + /* object bound by this entry. */ + struct inode *obj; +}; + #define MAX_PLUGIN_TYPE_LABEL_LEN 32 #define MAX_PLUGIN_PLUG_LABEL_LEN 32 @@ -789,11 +815,6 @@ typedef struct plugin_locator { extern int locate_plugin(struct inode *inode, plugin_locator * loc); -static inline reiser4_plugin * -plugin_by_id(reiser4_plugin_type type_id, reiser4_plugin_id id); - -static inline reiser4_plugin * -plugin_by_disk_id(reiser4_tree * tree, reiser4_plugin_type type_id, d16 * did); #define PLUGIN_BY_ID(TYPE,ID,FIELD) \ static inline TYPE *TYPE ## _by_id( reiser4_plugin_id id ) \ @@ -835,28 +856,26 @@ PLUGIN_BY_ID(compression_plugin, REISER4 PLUGIN_BY_ID(formatting_plugin, REISER4_FORMATTING_PLUGIN_TYPE, formatting); PLUGIN_BY_ID(disk_format_plugin, REISER4_FORMAT_PLUGIN_TYPE, format); PLUGIN_BY_ID(jnode_plugin, REISER4_JNODE_PLUGIN_TYPE, jnode); -PLUGIN_BY_ID(pseudo_plugin, REISER4_PSEUDO_PLUGIN_TYPE, pseudo); -PLUGIN_BY_ID(compression_mode_plugin, REISER4_COMPRESSION_MODE_PLUGIN_TYPE, compression_mode); +PLUGIN_BY_ID(compression_mode_plugin, REISER4_COMPRESSION_MODE_PLUGIN_TYPE, + compression_mode); PLUGIN_BY_ID(cluster_plugin, REISER4_CLUSTER_PLUGIN_TYPE, clust); PLUGIN_BY_ID(regular_plugin, REISER4_REGULAR_PLUGIN_TYPE, regular); extern int save_plugin_id(reiser4_plugin * plugin, d16 * area); +extern struct list_head *get_plugin_list(reiser4_plugin_type type_id); -TYPE_SAFE_LIST_DEFINE(plugin, reiser4_plugin, h.linkage); - -extern plugin_list_head *get_plugin_list(reiser4_plugin_type type_id); +#define for_all_plugins(ptype, plugin) \ +for (plugin = list_entry(get_plugin_list(ptype)->next, reiser4_plugin, h.linkage); \ + get_plugin_list(ptype) != &plugin->h.linkage; \ + plugin = list_entry(plugin->h.linkage.next, reiser4_plugin, h.linkage)) -#define for_all_plugins( ptype, plugin ) \ -for( plugin = plugin_list_front( get_plugin_list( ptype ) ) ; \ - ! plugin_list_end( get_plugin_list( ptype ), plugin ) ; \ - plugin = plugin_list_next( plugin ) ) /* enumeration of fields within plugin_set */ typedef enum { PSET_FILE, - PSET_DIR, /* PSET_FILE and PSET_DIR should be first elements: - * inode.c:read_inode() depends on this. */ + PSET_DIR, /* PSET_FILE and PSET_DIR should be first elements: + * inode.c:read_inode() depends on this. */ PSET_PERM, PSET_FORMATTING, PSET_HASH, @@ -873,8 +892,43 @@ typedef enum { } pset_member; int grab_plugin(struct inode *self, struct inode *ancestor, pset_member memb); -int grab_plugin_from(struct inode *self, pset_member memb, reiser4_plugin *plug); -int force_plugin(struct inode *self, pset_member memb, reiser4_plugin *plug); +int grab_plugin_from(struct inode *self, pset_member memb, + reiser4_plugin * plug); +int force_plugin(struct inode *self, pset_member memb, reiser4_plugin * plug); + +/* defined in fs/reiser4/plugin/object.c */ +extern file_plugin file_plugins[LAST_FILE_PLUGIN_ID]; +/* defined in fs/reiser4/plugin/object.c */ +extern dir_plugin dir_plugins[LAST_DIR_ID]; +/* defined in fs/reiser4/plugin/item/static_stat.c */ +extern sd_ext_plugin sd_ext_plugins[LAST_SD_EXTENSION]; +/* defined in fs/reiser4/plugin/hash.c */ +extern hash_plugin hash_plugins[LAST_HASH_ID]; +/* defined in fs/reiser4/plugin/fibration.c */ +extern fibration_plugin fibration_plugins[LAST_FIBRATION_ID]; +/* defined in fs/reiser4/plugin/crypt.c */ +extern crypto_plugin crypto_plugins[LAST_CRYPTO_ID]; +/* defined in fs/reiser4/plugin/digest.c */ +extern digest_plugin digest_plugins[LAST_DIGEST_ID]; +/* defined in fs/reiser4/plugin/compress/compress.c */ +extern compression_plugin compression_plugins[LAST_COMPRESSION_ID]; +/* defined in fs/reiser4/plugin/compress/compression_mode.c */ +extern compression_mode_plugin +compression_mode_plugins[LAST_COMPRESSION_MODE_ID]; +/* defined in fs/reiser4/plugin/cluster.c */ +extern cluster_plugin cluster_plugins[LAST_CLUSTER_ID]; +/* defined in fs/reiser4/plugin/regular.c */ +extern regular_plugin regular_plugins[LAST_REGULAR_ID]; +/* defined in fs/reiser4/plugin/tail.c */ +extern formatting_plugin formatting_plugins[LAST_TAIL_FORMATTING_ID]; +/* defined in fs/reiser4/plugin/security/security.c */ +extern perm_plugin perm_plugins[LAST_PERM_ID]; +/* defined in fs/reiser4/plugin/item/item.c */ +extern item_plugin item_plugins[LAST_ITEM_ID]; +/* defined in fs/reiser4/plugin/node/node.c */ +extern node_plugin node_plugins[LAST_NODE_ID]; +/* defined in fs/reiser4/plugin/disk_format/disk_format.c */ +extern disk_format_plugin format_plugins[LAST_FORMAT_ID]; /* __FS_REISER4_PLUGIN_TYPES_H__ */ #endif diff -puN fs/reiser4/plugin/plugin_header.h~reiser4-big-update fs/reiser4/plugin/plugin_header.h --- devel/fs/reiser4/plugin/plugin_header.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/plugin_header.h 2005-09-15 19:51:08.000000000 -0700 @@ -7,7 +7,7 @@ /* plugin data-types and constants */ -#include "../type_safe_list.h" +#include "../debug.h" #include "../dformat.h" typedef enum { @@ -25,7 +25,6 @@ typedef enum { REISER4_CRYPTO_PLUGIN_TYPE, REISER4_DIGEST_PLUGIN_TYPE, REISER4_COMPRESSION_PLUGIN_TYPE, - REISER4_PSEUDO_PLUGIN_TYPE, REISER4_COMPRESSION_MODE_PLUGIN_TYPE, REISER4_CLUSTER_PLUGIN_TYPE, REISER4_REGULAR_PLUGIN_TYPE, @@ -37,8 +36,6 @@ struct reiser4_plugin_ops; plugin type. */ typedef struct reiser4_plugin_ops reiser4_plugin_ops; -TYPE_SAFE_LIST_DECLARE(plugin); - /* the common part of all plugin instances. */ typedef struct plugin_header { /* plugin type */ @@ -53,19 +50,18 @@ typedef struct plugin_header { /* descriptive string.. */ const char *desc; /* list linkage */ - plugin_list_link linkage; + struct list_head linkage; } plugin_header; - /* PRIVATE INTERFACES */ /* NIKITA-FIXME-HANS: what is this for and why does it duplicate what is in plugin_header? */ /* plugin type representation. */ typedef struct reiser4_plugin_type_data { /* internal plugin type identifier. Should coincide with - index of this item in plugins[] array. */ + index of this item in plugins[] array. */ reiser4_plugin_type type_id; /* short symbolic label of this plugin type. Should be no longer - than MAX_PLUGIN_TYPE_LABEL_LEN characters including '\0'. */ + than MAX_PLUGIN_TYPE_LABEL_LEN characters including '\0'. */ const char *label; /* plugin type description longer than .label */ const char *desc; @@ -75,7 +71,7 @@ typedef struct reiser4_plugin_type_data int builtin_num; /* array of built-in plugins */ void *builtin; - plugin_list_head plugins_list; + struct list_head plugins_list; size_t size; } reiser4_plugin_type_data; @@ -84,8 +80,7 @@ extern reiser4_plugin_type_data plugins[ int is_type_id_valid(reiser4_plugin_type type_id); int is_plugin_id_valid(reiser4_plugin_type type_id, reiser4_plugin_id id); -static inline reiser4_plugin * -plugin_at(reiser4_plugin_type_data * ptype, int i) +static inline reiser4_plugin *plugin_at(reiser4_plugin_type_data * ptype, int i) { char *builtin; @@ -93,29 +88,30 @@ plugin_at(reiser4_plugin_type_data * pty return (reiser4_plugin *) (builtin + i * ptype->size); } - /* return plugin by its @type_id and @id */ -static inline reiser4_plugin * -plugin_by_id(reiser4_plugin_type type_id /* plugin type id */ , - reiser4_plugin_id id /* plugin id */ ) +static inline reiser4_plugin *plugin_by_id(reiser4_plugin_type type_id + /* plugin type id */ , + reiser4_plugin_id id /* plugin id */ + ) { assert("nikita-1651", is_type_id_valid(type_id)); assert("nikita-1652", is_plugin_id_valid(type_id, id)); return plugin_at(&plugins[type_id], id); } -extern reiser4_plugin * -plugin_by_unsafe_id(reiser4_plugin_type type_id, reiser4_plugin_id id); +extern reiser4_plugin *plugin_by_unsafe_id(reiser4_plugin_type type_id, + reiser4_plugin_id id); /* get plugin whose id is stored in disk format */ -static inline reiser4_plugin * -plugin_by_disk_id(reiser4_tree * tree UNUSED_ARG /* tree, - * plugin - * belongs - * to */ , - reiser4_plugin_type type_id /* plugin type - * id */ , - d16 * did /* plugin id in disk format */ ) +static inline reiser4_plugin *plugin_by_disk_id(reiser4_tree * tree UNUSED_ARG /* tree, + * plugin + * belongs + * to */ , + reiser4_plugin_type type_id /* plugin type + * id */ , + d16 * + did + /* plugin id in disk format */ ) { /* what we should do properly is to maintain within each file-system a dictionary that maps on-disk plugin ids to diff -puN fs/reiser4/plugin/plugin_set.c~reiser4-big-update fs/reiser4/plugin/plugin_set.c --- devel/fs/reiser4/plugin/plugin_set.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/plugin_set.c 2005-09-15 19:51:08.000000000 -0700 @@ -22,7 +22,7 @@ */ #include "../debug.h" - +#include "../super.h" #include "plugin_set.h" #include @@ -39,24 +39,20 @@ static spinlock_t plugin_set_lock[8] __c #define PS_TABLE_SIZE (32) -static inline plugin_set * -cast_to(const unsigned long * a) +static inline plugin_set *cast_to(const unsigned long *a) { return container_of(a, plugin_set, hashval); } -static inline int -pseq(const unsigned long * a1, const unsigned long * a2) +static inline int pseq(const unsigned long *a1, const unsigned long *a2) { plugin_set *set1; plugin_set *set2; /* make sure fields are not missed in the code below */ cassert(sizeof *set1 == - sizeof set1->hashval + sizeof set1->link + - sizeof set1->file + sizeof set1->dir + sizeof set1->perm + @@ -69,28 +65,26 @@ pseq(const unsigned long * a1, const uns sizeof set1->digest + sizeof set1->compression + sizeof set1->compression_mode + - sizeof set1->cluster + - sizeof set1->regular_entry); + sizeof set1->cluster + sizeof set1->regular_entry); set1 = cast_to(a1); set2 = cast_to(a2); return - set1->hashval == set2->hashval && - - set1->file == set2->file && - set1->dir == set2->dir && - set1->perm == set2->perm && - set1->formatting == set2->formatting && - set1->hash == set2->hash && - set1->fibration == set2->fibration && - set1->sd == set2->sd && - set1->dir_item == set2->dir_item && - set1->crypto == set2->crypto && - set1->digest == set2->digest && - set1->compression == set2->compression && - set1->compression_mode == set2->compression_mode && - set1->cluster == set2->cluster && - set1->regular_entry == set2->regular_entry; + set1->hashval == set2->hashval && + set1->file == set2->file && + set1->dir == set2->dir && + set1->perm == set2->perm && + set1->formatting == set2->formatting && + set1->hash == set2->hash && + set1->fibration == set2->fibration && + set1->sd == set2->sd && + set1->dir_item == set2->dir_item && + set1->crypto == set2->crypto && + set1->digest == set2->digest && + set1->compression == set2->compression && + set1->compression_mode == set2->compression_mode && + set1->cluster == set2->cluster && + set1->regular_entry == set2->regular_entry; } #define HASH_FIELD(hash, set, field) \ @@ -98,7 +92,7 @@ pseq(const unsigned long * a1, const uns (hash) += (unsigned long)(set)->field >> 2; \ }) -static inline unsigned long calculate_hash(const plugin_set *set) +static inline unsigned long calculate_hash(const plugin_set * set) { unsigned long result; @@ -121,7 +115,7 @@ static inline unsigned long calculate_ha } static inline unsigned long -pshash(ps_hash_table *table, const unsigned long * a) +pshash(ps_hash_table * table, const unsigned long *a) { return *a; } @@ -129,50 +123,51 @@ pshash(ps_hash_table *table, const unsig /* The hash table definition */ #define KMALLOC(size) kmalloc((size), GFP_KERNEL) #define KFREE(ptr, size) kfree(ptr) -TYPE_SAFE_HASH_DEFINE(ps, plugin_set, unsigned long, hashval, link, pshash, pseq); +TYPE_SAFE_HASH_DEFINE(ps, plugin_set, unsigned long, hashval, link, pshash, + pseq); #undef KFREE #undef KMALLOC static ps_hash_table ps_table; static plugin_set empty_set = { - .hashval = 0, - .file = NULL, - .dir = NULL, - .perm = NULL, - .formatting = NULL, - .hash = NULL, - .fibration = NULL, - .sd = NULL, - .dir_item = NULL, - .crypto = NULL, - .digest = NULL, - .compression = NULL, - .compression_mode = NULL, - .cluster = NULL, - .regular_entry = NULL, - .link = { NULL } + .hashval = 0, + .file = NULL, + .dir = NULL, + .perm = NULL, + .formatting = NULL, + .hash = NULL, + .fibration = NULL, + .sd = NULL, + .dir_item = NULL, + .crypto = NULL, + .digest = NULL, + .compression = NULL, + .compression_mode = NULL, + .cluster = NULL, + .regular_entry = NULL, + .link = {NULL} }; -reiser4_internal plugin_set *plugin_set_get_empty(void) +plugin_set *plugin_set_get_empty(void) { return &empty_set; } -reiser4_internal void plugin_set_put(plugin_set *set) +void plugin_set_put(plugin_set * set) { } -static inline unsigned long * -pset_field(plugin_set *set, int offset) +static inline unsigned long *pset_field(plugin_set * set, int offset) { return (unsigned long *)(((char *)set) + offset); } -static int plugin_set_field(plugin_set **set, const unsigned long val, const int offset) +static int plugin_set_field(plugin_set ** set, const unsigned long val, + const int offset) { - unsigned long *spot; + unsigned long *spot; spinlock_t *lock; - plugin_set replica; + plugin_set replica; plugin_set *twin; plugin_set *psal; plugin_set *orig; @@ -214,78 +209,76 @@ static int plugin_set_field(plugin_set * } static struct { - int offset; + int offset; reiser4_plugin_type type; } pset_descr[PSET_LAST] = { [PSET_FILE] = { .offset = offsetof(plugin_set, file), - .type = REISER4_FILE_PLUGIN_TYPE + .type = REISER4_FILE_PLUGIN_TYPE }, [PSET_DIR] = { .offset = offsetof(plugin_set, dir), - .type = REISER4_DIR_PLUGIN_TYPE + .type = REISER4_DIR_PLUGIN_TYPE }, [PSET_PERM] = { .offset = offsetof(plugin_set, perm), - .type = REISER4_PERM_PLUGIN_TYPE + .type = REISER4_PERM_PLUGIN_TYPE }, [PSET_FORMATTING] = { .offset = offsetof(plugin_set, formatting), - .type = REISER4_FORMATTING_PLUGIN_TYPE + .type = REISER4_FORMATTING_PLUGIN_TYPE }, [PSET_HASH] = { .offset = offsetof(plugin_set, hash), - .type = REISER4_HASH_PLUGIN_TYPE + .type = REISER4_HASH_PLUGIN_TYPE }, [PSET_FIBRATION] = { .offset = offsetof(plugin_set, fibration), - .type = REISER4_FIBRATION_PLUGIN_TYPE + .type = REISER4_FIBRATION_PLUGIN_TYPE }, [PSET_SD] = { .offset = offsetof(plugin_set, sd), - .type = REISER4_ITEM_PLUGIN_TYPE + .type = REISER4_ITEM_PLUGIN_TYPE }, [PSET_DIR_ITEM] = { .offset = offsetof(plugin_set, dir_item), - .type = REISER4_ITEM_PLUGIN_TYPE + .type = REISER4_ITEM_PLUGIN_TYPE }, [PSET_CRYPTO] = { .offset = offsetof(plugin_set, crypto), - .type = REISER4_CRYPTO_PLUGIN_TYPE + .type = REISER4_CRYPTO_PLUGIN_TYPE }, [PSET_DIGEST] = { .offset = offsetof(plugin_set, digest), - .type = REISER4_DIGEST_PLUGIN_TYPE + .type = REISER4_DIGEST_PLUGIN_TYPE }, [PSET_COMPRESSION] = { .offset = offsetof(plugin_set, compression), - .type = REISER4_COMPRESSION_PLUGIN_TYPE + .type = REISER4_COMPRESSION_PLUGIN_TYPE }, [PSET_COMPRESSION_MODE] = { .offset = offsetof(plugin_set, compression_mode), - .type = REISER4_COMPRESSION_MODE_PLUGIN_TYPE + .type = REISER4_COMPRESSION_MODE_PLUGIN_TYPE }, [PSET_CLUSTER] = { .offset = offsetof(plugin_set, cluster), - .type = REISER4_CLUSTER_PLUGIN_TYPE + .type = REISER4_CLUSTER_PLUGIN_TYPE }, [PSET_REGULAR_ENTRY] = { .offset = offsetof(plugin_set, regular_entry), - .type = REISER4_REGULAR_PLUGIN_TYPE + .type = REISER4_REGULAR_PLUGIN_TYPE } }; #if REISER4_DEBUG -static reiser4_plugin_type -pset_member_to_type(pset_member memb) +static reiser4_plugin_type pset_member_to_type(pset_member memb) { assert("nikita-3501", 0 <= memb && memb < PSET_LAST); return pset_descr[memb].type; } #endif -reiser4_plugin_type -pset_member_to_type_unsafe(pset_member memb) +reiser4_plugin_type pset_member_to_type_unsafe(pset_member memb) { if (0 <= memb && memb < PSET_LAST) return pset_descr[memb].type; @@ -293,7 +286,7 @@ pset_member_to_type_unsafe(pset_member m return REISER4_PLUGIN_TYPES; } -int pset_set(plugin_set **set, pset_member memb, reiser4_plugin *plugin) +int pset_set(plugin_set ** set, pset_member memb, reiser4_plugin * plugin) { assert("nikita-3492", set != NULL); assert("nikita-3493", *set != NULL); @@ -305,16 +298,16 @@ int pset_set(plugin_set **set, pset_memb (unsigned long)plugin, pset_descr[memb].offset); } -reiser4_plugin *pset_get(plugin_set *set, pset_member memb) +reiser4_plugin *pset_get(plugin_set * set, pset_member memb) { assert("nikita-3497", set != NULL); assert("nikita-3498", 0 <= memb && memb < PSET_LAST); - return *(reiser4_plugin **)(((char *)set) + pset_descr[memb].offset); + return *(reiser4_plugin **) (((char *)set) + pset_descr[memb].offset); } #define DEFINE_PLUGIN_SET(type, field) \ -reiser4_internal int plugin_set_ ## field(plugin_set **set, type *val) \ +int plugin_set_ ## field(plugin_set **set, type *val) \ { \ cassert(sizeof val == sizeof(unsigned long)); \ return plugin_set_field(set, (unsigned long)val, \ @@ -322,26 +315,33 @@ reiser4_internal int plugin_set_ ## fiel } DEFINE_PLUGIN_SET(file_plugin, file) -DEFINE_PLUGIN_SET(dir_plugin, dir) -DEFINE_PLUGIN_SET(formatting_plugin, formatting) -DEFINE_PLUGIN_SET(hash_plugin, hash) -DEFINE_PLUGIN_SET(fibration_plugin, fibration) -DEFINE_PLUGIN_SET(item_plugin, sd) -DEFINE_PLUGIN_SET(crypto_plugin, crypto) -DEFINE_PLUGIN_SET(digest_plugin, digest) -DEFINE_PLUGIN_SET(compression_plugin, compression) -DEFINE_PLUGIN_SET(compression_mode_plugin, compression_mode) -DEFINE_PLUGIN_SET(cluster_plugin, cluster) -DEFINE_PLUGIN_SET(regular_plugin, regular_entry) - -reiser4_internal int plugin_set_init(void) + DEFINE_PLUGIN_SET(dir_plugin, dir) + DEFINE_PLUGIN_SET(formatting_plugin, formatting) + DEFINE_PLUGIN_SET(hash_plugin, hash) + DEFINE_PLUGIN_SET(fibration_plugin, fibration) + DEFINE_PLUGIN_SET(item_plugin, sd) + DEFINE_PLUGIN_SET(crypto_plugin, crypto) + DEFINE_PLUGIN_SET(digest_plugin, digest) + DEFINE_PLUGIN_SET(compression_plugin, compression) + DEFINE_PLUGIN_SET(compression_mode_plugin, compression_mode) + DEFINE_PLUGIN_SET(cluster_plugin, cluster) + DEFINE_PLUGIN_SET(regular_plugin, regular_entry) + + +/** + * init_plugin_set - create pset cache and hash table + * + * Initializes slab cache of plugin_set-s and their hash table. It is part of + * reiser4 module initialization. + */ +int init_plugin_set(void) { int result; result = ps_hash_init(&ps_table, PS_TABLE_SIZE); if (result == 0) { plugin_set_slab = kmem_cache_create("plugin_set", - sizeof (plugin_set), 0, + sizeof(plugin_set), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (plugin_set_slab == NULL) @@ -350,25 +350,29 @@ reiser4_internal int plugin_set_init(voi return result; } -reiser4_internal void plugin_set_done(void) +/** + * done_plugin_set - delete plugin_set cache and plugin_set hash table + * + * This is called on reiser4 module unloading or system shutdown. + */ +void done_plugin_set(void) { - plugin_set * cur, * next; + plugin_set *cur, *next; for_all_in_htable(&ps_table, ps, cur, next) { ps_hash_remove(&ps_table, cur); kmem_cache_free(plugin_set_slab, cur); } - kmem_cache_destroy(plugin_set_slab); + destroy_reiser4_cache(&plugin_set_slab); ps_hash_done(&ps_table); } - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - End: -*/ +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 120 + * End: + */ diff -puN fs/reiser4/plugin/plugin_set.h~reiser4-big-update fs/reiser4/plugin/plugin_set.h --- devel/fs/reiser4/plugin/plugin_set.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/plugin_set.h 2005-09-15 19:51:08.000000000 -0700 @@ -16,59 +16,61 @@ typedef struct plugin_set plugin_set; TYPE_SAFE_HASH_DECLARE(ps, plugin_set); struct plugin_set { - unsigned long hashval; + unsigned long hashval; /* plugin of file */ - file_plugin *file; + file_plugin *file; /* plugin of dir */ - dir_plugin *dir; + dir_plugin *dir; /* perm plugin for this file */ - perm_plugin *perm; + perm_plugin *perm; /* tail policy plugin. Only meaningful for regular files */ - formatting_plugin *formatting; + formatting_plugin *formatting; /* hash plugin. Only meaningful for directories. */ - hash_plugin *hash; + hash_plugin *hash; /* fibration plugin. Only meaningful for directories. */ - fibration_plugin *fibration; + fibration_plugin *fibration; /* plugin of stat-data */ - item_plugin *sd; + item_plugin *sd; /* plugin of items a directory is built of */ - item_plugin *dir_item; + item_plugin *dir_item; /* crypto plugin */ - crypto_plugin *crypto; + crypto_plugin *crypto; /* digest plugin */ - digest_plugin *digest; + digest_plugin *digest; /* compression plugin */ compression_plugin *compression; /* compression mode plugin */ - compression_mode_plugin * compression_mode; + compression_mode_plugin *compression_mode; /* cluster plugin */ - cluster_plugin *cluster; + cluster_plugin *cluster; /* plugin of regular child should be created */ - regular_plugin *regular_entry; - ps_hash_link link; + regular_plugin *regular_entry; + ps_hash_link link; }; extern plugin_set *plugin_set_get_empty(void); -extern void plugin_set_put(plugin_set *set); +extern void plugin_set_put(plugin_set * set); -extern int plugin_set_file (plugin_set **set, file_plugin *plug); -extern int plugin_set_dir (plugin_set **set, dir_plugin *plug); -extern int plugin_set_formatting (plugin_set **set, formatting_plugin *plug); -extern int plugin_set_hash (plugin_set **set, hash_plugin *plug); -extern int plugin_set_fibration (plugin_set **set, fibration_plugin *plug); -extern int plugin_set_sd (plugin_set **set, item_plugin *plug); -extern int plugin_set_crypto (plugin_set **set, crypto_plugin *plug); -extern int plugin_set_digest (plugin_set **set, digest_plugin *plug); -extern int plugin_set_compression (plugin_set **set, compression_plugin *plug); -extern int plugin_set_compression_mode(plugin_set **set, compression_mode_plugin *plug); -extern int plugin_set_cluster (plugin_set **set, cluster_plugin *plug); -extern int plugin_set_regular (plugin_set **set, regular_plugin *plug); - -extern int plugin_set_init(void); -extern void plugin_set_done(void); - -extern int pset_set(plugin_set **set, pset_member memb, reiser4_plugin *plugin); -extern reiser4_plugin *pset_get(plugin_set *set, pset_member memb); +extern int plugin_set_file(plugin_set ** set, file_plugin * plug); +extern int plugin_set_dir(plugin_set ** set, dir_plugin * plug); +extern int plugin_set_formatting(plugin_set ** set, formatting_plugin * plug); +extern int plugin_set_hash(plugin_set ** set, hash_plugin * plug); +extern int plugin_set_fibration(plugin_set ** set, fibration_plugin * plug); +extern int plugin_set_sd(plugin_set ** set, item_plugin * plug); +extern int plugin_set_crypto(plugin_set ** set, crypto_plugin * plug); +extern int plugin_set_digest(plugin_set ** set, digest_plugin * plug); +extern int plugin_set_compression(plugin_set ** set, compression_plugin * plug); +extern int plugin_set_compression_mode(plugin_set ** set, + compression_mode_plugin * plug); +extern int plugin_set_cluster(plugin_set ** set, cluster_plugin * plug); +extern int plugin_set_regular_entry(plugin_set ** set, regular_plugin * plug); + +extern int init_plugin_set(void); +extern void done_plugin_set(void); + +extern int pset_set(plugin_set ** set, pset_member memb, + reiser4_plugin * plugin); +extern reiser4_plugin *pset_get(plugin_set * set, pset_member memb); extern reiser4_plugin_type pset_member_to_type_unsafe(pset_member memb); diff -L fs/reiser4/plugin/pseudo/pseudo.c -puN fs/reiser4/plugin/pseudo/pseudo.c~reiser4-big-update /dev/null --- devel/fs/reiser4/plugin/pseudo/pseudo.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,1804 +0,0 @@ -/* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by - * reiser4/README */ - -/* Handling of "pseudo" files representing unified access to meta data in - reiser4. */ - -/* - * See http://namesys.com/v4/v4.html, and especially - * http://namesys.com/v4/pseudo.html for basic information about reiser4 - * pseudo files, access to meta-data, reiser4() system call, etc. - * - * Pseudo files should be accessible from both reiser4() system call and - * normal POSIX calls. - * - * OVERVIEW - * - * Pseudo files provide access to various functionality through file - * system name space. As such they are similar to pseudo file systems - * already existing in UNIX and Linux: procfs, sysfs, etc. But pseudo - * files are embedded into name space of Reiser4---real block device based - * file system, and are more tightly integrated with it. In particular, - * some pseudo files are "attached" to other files (either "real" or also - * pseudo), by being accessible through path names of the form - * - * "a/b/c/something" - * - * Here object accessible through "a/b/c/something" is attached to the - * object accessible through "a/b/c" , and the latter is said to be the - * "host" object of the former. - * - * Object can have multiple pseudo files attached to it, distinguished by - * the last component of their names "something", "somethingelse", - * etc. - * - * (Note however, that currently "real" files have only one single pseudo - * file attached to them, viz. pseudo directory "....". This directory in - * turn contains all other pseudo files pertaining to the real file that - * "...." is attached to. To avoid referencing "...." all the time - * "a/b/c" is called a host of "/a/b/c/..../something". This violates - * definition above, but is convenient.) - * - * Moreover, in addition to the purely pseudo files (that is, file system - * objects whose content (as available through read(2) system call) is not - * backed by any kind of persistent storage), extended file attributes - * (see attr(5) on Linux, and http://acl.bestbits.at/) including security - * attributes such as ACLs are also available through file system name - * space. - * - * As a result each file system object has a sub-name-space rooted at it, - * which is in striking contrast with traditional UNIX file system, where - * only directories has sub-objects and all other types of files (regular, - * FIFO-s, devices, and symlinks) are leaves. - * - * For the sake of objectivity it should be mentioned that this is not - * _completely_ new development in file system design, see - * http://docs.sun.com/db/doc/816-0220/6m6nkorp9?a=view - * - * In particular, as each object has sub-objects, name space tree is - * infinite in both extent (number of reachable objects) and depth. - * - * Some pseudo files are "built-in". They are present as sub-objects in - * each file system object, unless specifically disabled. - * - * Built-in pseudo files are implemented in this file and described at - * http://namesys.com/v4/pseudo.html - * - * IMPLEMENTATION - * - * Pseudo files are implemented as normal inodes, living in the same super - * block as other inodes for reiser4 file system. Their inode numbers are - * generated by fs/inode.c:new_inode() function and are not persistent (in - * the sense that they are not guaranteed to be the same after - * remount). To avoid clashes with "normal" inodes, all pseudo inodes are - * placed into otherwise unused locality (for example, 0), hence allowing - * reiser4_inode_find_actor() to tell them from normal inodes. - * - * All pseudo inodes share the same object plugin - * PSEUDO_FILE_PLUGIN_ID. In pseudo-inode specific part of reiser4_inode - * (pseudo_info), two things are stored: - * - * 1. pointer to the inode of the "host object" (for /a/b/c/..../acl, - * /a/b/c is the host object) - * - * 2. pointer to pseudo plugin, used by PSEUDO_FILE_PLUGIN_ID to - * implement VFS operations. - * - * This design has following advantages: - * - * 1. provides for ease addition of new pseudo files without going - * through writing whole new object plugin. - * - * 2. allows sys_reiser4() to be implemented by directory invoking - * pseudo plugin methods. - * - */ - -#include "../../inode.h" -#include "../../debug.h" -#include "../plugin.h" - -#include "pseudo.h" - -static int init_pseudo(struct inode *parent, struct inode *pseudo, - pseudo_plugin *pplug, const char *name); - -static struct inode *add_pseudo(struct inode *parent, - pseudo_plugin *pplug, struct dentry **d); - -/* - * helper method: set ->datum field in the pseudo file specific portion of - * reiser4 inode. - */ -static void pseudo_set_datum(struct inode *pseudo, unsigned long datum) -{ - reiser4_inode_data(pseudo)->file_plugin_data.pseudo_info.datum = datum; -} - -/* - * return id of pseudo file plugin for this inode @p - */ -static int pseudo_id(struct inode *p) -{ - return reiser4_inode_data(p)->file_plugin_data.pseudo_info.plugin->h.id; -} - -/* - * helper method used to implement ->lookup() method of pseudo files. - * - * Try to find a pseudo plugin that matches given name (stored in @dentry) and - * has ->parent field equal to @id. - * - * Convention is that ->parent field is set to the id of the pseudo plugin of - * the parent pseudo file in the hierarchy (that is, plugin for - * "a/..../foo/bar" has ->parent set to the plugin id of "a/..../foo"), with - * the exception of "a/...." that uses special reserved value TOP_LEVEL for - * ->parent. - */ -static int -lookup_of_plugin(struct inode *parent, int id, struct dentry **dentry) -{ - const char *name; - struct inode *pseudo; - reiser4_plugin *plugin; - int result; - - name = (*dentry)->d_name.name; - pseudo = ERR_PTR(-ENOENT); - - /* scan all pseudo file plugins and check each */ - for_all_plugins(REISER4_PSEUDO_PLUGIN_TYPE, plugin) { - pseudo_plugin *pplug; - - pplug = &plugin->pseudo; - if (pplug->parent == id && - pplug->try != NULL && pplug->try(pplug, parent, name)) { - pseudo = add_pseudo(parent, pplug, dentry); - break; - } - } - if (!IS_ERR(pseudo)) - result = 0; - else - result = PTR_ERR(pseudo); - return result; -} - -/* - * implement ->lookup() method using convention described in the comment for - * lookup_of_plugin() function. - */ -static int lookup_table(struct inode *parent, struct dentry ** dentry) -{ - assert("nikita-3511", parent != NULL); - assert("nikita-3512", dentry != NULL); - assert("nikita-3513", - inode_file_plugin(parent)->h.id == PSEUDO_FILE_PLUGIN_ID); - - /* - * call lookup_of_plugin() passing id of pseudo plugin for @parent as - * "id" parameter. - */ - return lookup_of_plugin(parent, pseudo_id(parent), dentry); -} - -/* - * helper to implement ->readdir() method for the pseudo files. It uses the - * same convention as lookup_of_plugin() function. - */ -static int -readdir_table(struct file *f, void *dirent, filldir_t filld) -{ - loff_t off; - ino_t ino; - int skip; - int id; - - struct inode *inode; - reiser4_plugin *plugin; - - off = f->f_pos; - if (off < 0) - return 0; - - inode = f->f_dentry->d_inode; - switch ((int)off) { - /* - * first, return dot and dotdot - */ - case 0: - ino = inode->i_ino; - if (filld(dirent, ".", 1, off, ino, DT_DIR) < 0) - break; - ++ off; - /* fallthrough */ - case 1: - ino = parent_ino(f->f_dentry); - if (filld(dirent, "..", 2, off, ino, DT_DIR) < 0) - break; - ++ off; - /* fallthrough */ - default: - skip = off - 2; - id = pseudo_id(inode); - /* then, scan all pseudo plugins, looking for the ones with - * matching ->parent */ - for_all_plugins(REISER4_PSEUDO_PLUGIN_TYPE, plugin) { - pseudo_plugin *pplug; - const char *name; - - pplug = &plugin->pseudo; - if (pplug->parent == id && pplug->readdirable) { - if (skip == 0) { - name = pplug->h.label; - /* - * if match is found---fed @filld with - * it - */ - if (filld(dirent, name, strlen(name), - off, - off + (long)f, DT_REG) < 0) - break; - ++ off; - } else - -- skip; - } - } - } - f->f_pos = off; - return 0; -} - -/* - * special value of ->parent field in pseudo file plugin used by "...." top - * level pseudo directory. - */ -#define TOP_LEVEL (-1) - -/* - * try to look up built-in pseudo file by its name. - */ -reiser4_internal int -lookup_pseudo_file(struct inode *parent, struct dentry **dentry) -{ - assert("nikita-2999", parent != NULL); - assert("nikita-3000", dentry != NULL); - -#if !ENABLE_REISER4_PSEUDO - return RETERR(-ENOENT); -#endif /* ENABLE_REISER4_PSEUDO */ - /* if pseudo files are disabled for this file system bail out */ - if (reiser4_is_set(parent->i_sb, REISER4_NO_PSEUDO)) - return RETERR(-ENOENT); - else - return lookup_of_plugin(parent, TOP_LEVEL, dentry); -} - -/* create inode for pseudo file with plugin @pplug, and add it to the @parent - * under name @d */ -static struct inode *add_pseudo(struct inode *parent, - pseudo_plugin *pplug, struct dentry **d) -{ - struct inode *pseudo; - - pseudo = new_inode(parent->i_sb); - if (pseudo != NULL) { - int result; - - result = init_pseudo(parent, pseudo, pplug, (*d)->d_name.name); - if (result != 0) - pseudo = ERR_PTR(result); - else - *d = d_splice_alias(pseudo, *d); - } else - pseudo = ERR_PTR(RETERR(-ENOMEM)); - return pseudo; -} - - -/* helper function: return host object of @inode pseudo file */ -static struct inode *get_inode_host(struct inode *inode) -{ - assert("nikita-3510", - inode_file_plugin(inode)->h.id == PSEUDO_FILE_PLUGIN_ID); - return reiser4_inode_data(inode)->file_plugin_data.pseudo_info.host; -} - -/* helper function: return parent object of @inode pseudo file */ -static struct inode *get_inode_parent(struct inode *inode) -{ - assert("nikita-3510", - inode_file_plugin(inode)->h.id == PSEUDO_FILE_PLUGIN_ID); - return reiser4_inode_data(inode)->file_plugin_data.pseudo_info.parent; -} - -/* - * initialize pseudo file @pseudo to be child of @parent, with plugin @pplug - * and name @name. - */ -static int -init_pseudo(struct inode *parent, struct inode *pseudo, - pseudo_plugin *pplug, const char *name) -{ - int result; - struct inode *host; - reiser4_inode *idata; - reiser4_object_create_data data; - static const oid_t pseudo_locality = 0x0ull; - - idata = reiser4_inode_data(pseudo); - /* all pseudo files live in special reserved locality */ - idata->locality_id = pseudo_locality; - - /* - * setup ->parent and ->host fields - */ - if (pplug->parent != TOP_LEVEL) - /* host of "a/..../b/c" is "a" */ - host = get_inode_host(parent); - else - /* host of "a/...." is "a" */ - host = parent; - - idata->file_plugin_data.pseudo_info.host = host; - idata->file_plugin_data.pseudo_info.parent = parent; - idata->file_plugin_data.pseudo_info.plugin = pplug; - - data.id = PSEUDO_FILE_PLUGIN_ID; - data.mode = pplug->lookup_mode; - - plugin_set_file(&idata->pset, file_plugin_by_id(PSEUDO_FILE_PLUGIN_ID)); - /* if plugin has a ->lookup method, it means that @pseudo should - * behave like directory. */ - if (pplug->lookup != NULL) - plugin_set_dir(&idata->pset, - dir_plugin_by_id(PSEUDO_DIR_PLUGIN_ID)); - - /* perform standard plugin initialization */ - result = inode_file_plugin(pseudo)->set_plug_in_inode(pseudo, - parent, &data); - if (result != 0) { - warning("nikita-3203", "Cannot install pseudo plugin"); - return result; - } - - /* inherit permission plugin from parent, */ - grab_plugin(pseudo, parent, PSET_PERM); - /* and credentials... */ - pseudo->i_uid = parent->i_uid; - pseudo->i_gid = parent->i_gid; - - pseudo->i_nlink = 1; - /* insert inode into VFS hash table */ - insert_inode_hash(pseudo); - return 0; -} - -/* helper function: return host object by file descriptor */ -static struct inode *get_pseudo_host(struct file *file) -{ - struct inode *inode; - - inode = file->f_dentry->d_inode; - return get_inode_host(inode); -} - -/* helper function: return host object by seq_file */ -static struct inode *get_seq_pseudo_host(struct seq_file *seq) -{ - struct file *file; - - file = seq->private; - return get_pseudo_host(file); -} - -/* - * implementation of ->try method for pseudo files with fixed names. - */ -static int try_by_label(pseudo_plugin *pplug, - const struct inode *parent, const char *name) -{ - return !strcmp(name, pplug->h.label); -} - -/* - * read method for the "..../uid" pseudo file. - */ -static int show_uid(struct seq_file *seq, void *cookie) -{ - seq_printf(seq, "%lu", (long unsigned)get_seq_pseudo_host(seq)->i_uid); - return 0; -} - -/* helper: check permissions required to modify ..../[ug]id */ -static int check_perm(struct inode *inode) -{ - if (IS_RDONLY(inode)) - return RETERR(-EROFS); - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) - return RETERR(-EPERM); - return 0; -} - -/* - * helper function to update [ug]id of @inode. Called by "..../[ug]id" write - * methods - */ -static int update_ugid(struct dentry *dentry, struct inode *inode, - uid_t uid, gid_t gid) -{ - int result; - - /* logic COPIED from fs/open.c:chown_common() */ - result = check_perm(inode); - if (result == 0) { - struct iattr newattrs; - - newattrs.ia_valid = ATTR_CTIME; - if (uid != (uid_t) -1) { - newattrs.ia_valid |= ATTR_UID; - newattrs.ia_uid = uid; - } - if (gid != (uid_t) -1) { - newattrs.ia_valid |= ATTR_GID; - newattrs.ia_gid = gid; - } - if (!S_ISDIR(inode->i_mode)) - newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID; - down(&inode->i_sem); - result = notify_change(dentry, &newattrs); - up(&inode->i_sem); - } - return result; -} - -/* - * write method for the "..../uid": extract uid from user-supplied buffer, - * and update uid - */ -static int store_uid(struct file *file, const char *buf) -{ - uid_t uid; - int result; - - if (sscanf(buf, "%i", &uid) == 1) { - struct inode *host; - - host = get_pseudo_host(file); - result = update_ugid(file->f_dentry->d_parent->d_parent, - host, uid, -1); - } else - result = RETERR(-EINVAL); - return result; -} - -/* - * read method for the "..../uid" pseudo file. - */ -static int show_gid(struct seq_file *seq, void *cookie) -{ - seq_printf(seq, "%lu", (long unsigned)get_seq_pseudo_host(seq)->i_gid); - return 0; -} - -/* - * write method for the "..../gid": extract uid from user-supplied buffer, - * and update gid - */ -static int get_gid(struct file *file, const char *buf) -{ - gid_t gid; - int result; - - if (sscanf(buf, "%i", &gid) == 1) { - struct inode *host; - - host = get_pseudo_host(file); - result = update_ugid(file->f_dentry->d_parent->d_parent, - host, -1, gid); - } else - result = RETERR(-EINVAL); - return result; -} - -/* - * read method for the "..../oid" pseudo file - */ -static int show_oid(struct seq_file *seq, void *cookie) -{ - seq_printf(seq, "%llu", (unsigned long long)get_inode_oid(get_seq_pseudo_host(seq))); - return 0; -} - -/* - * read method for the "..../key" pseudo file - */ -static int show_key(struct seq_file *seq, void *cookie) -{ - char buf[KEY_BUF_LEN]; - reiser4_key key; - - sprintf_key(buf, build_sd_key(get_seq_pseudo_host(seq), &key)); - seq_printf(seq, "%s", buf); - return 0; -} - -/* - * read method for the "..../size" pseudo file - */ -static int show_size(struct seq_file *seq, void *cookie) -{ - seq_printf(seq, "%lli", get_seq_pseudo_host(seq)->i_size); - return 0; -} - -/* - * read method for the "..../nlink" pseudo file - */ -static int show_nlink(struct seq_file *seq, void *cookie) -{ - seq_printf(seq, "%u", get_seq_pseudo_host(seq)->i_nlink); - return 0; -} - -/* - * read method for the "..../locality" pseudo file - */ -static int show_locality(struct seq_file *seq, void *cookie) -{ - seq_printf(seq, "%llu", - (unsigned long long)reiser4_inode_data(get_seq_pseudo_host(seq))->locality_id); - return 0; -} - -/* - * read method for the "..../rwx" pseudo file - */ -static int show_rwx(struct seq_file *seq, void *cookie) -{ - umode_t m; - - m = get_seq_pseudo_host(seq)->i_mode; - seq_printf(seq, "%#ho %c%c%c%c%c%c%c%c%c%c", - m, - - S_ISREG(m) ? '-' : - S_ISDIR(m) ? 'd' : - S_ISCHR(m) ? 'c' : - S_ISBLK(m) ? 'b' : - S_ISFIFO(m) ? 'p' : - S_ISLNK(m) ? 'l' : - S_ISSOCK(m) ? 's' : '?', - - m & S_IRUSR ? 'r' : '-', - m & S_IWUSR ? 'w' : '-', - m & S_IXUSR ? 'x' : '-', - - m & S_IRGRP ? 'r' : '-', - m & S_IWGRP ? 'w' : '-', - m & S_IXGRP ? 'x' : '-', - - m & S_IROTH ? 'r' : '-', - m & S_IWOTH ? 'w' : '-', - m & S_IXOTH ? 'x' : '-'); - return 0; -} - -/* - * write method for the "..../rwx" file. Extract permission bits from the - * user supplied buffer and update ->i_mode. - */ -static int get_rwx(struct file *file, const char *buf) -{ - umode_t rwx; - int result; - - if (sscanf(buf, "%hi", &rwx) == 1) { - struct inode *host; - - host = get_pseudo_host(file); - result = check_perm(host); - if (result == 0) { - struct iattr newattrs; - - down(&host->i_sem); - if (rwx == (umode_t)~0) - rwx = host->i_mode; - newattrs.ia_mode = - (rwx & S_IALLUGO) | (host->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - result = notify_change(file->f_dentry->d_parent->d_parent, - &newattrs); - up(&host->i_sem); - } - } else - result = RETERR(-EINVAL); - return result; -} - -/* - * seq-methods for "..../pseudo" - */ - -/* - * start iteration over all pseudo files - */ -static void * pseudos_start(struct seq_file *m, loff_t *pos) -{ - if (*pos >= LAST_PSEUDO_ID) - return NULL; - return pseudo_plugin_by_id(*pos); -} - -/* - * stop iteration over all pseudo files - */ -static void pseudos_stop(struct seq_file *m, void *v) -{ -} - -/* - * go to next pseudo file in the sequence - */ -static void * pseudos_next(struct seq_file *m, void *v, loff_t *pos) -{ - ++ (*pos); - return pseudos_start(m, pos); -} - -/* - * output information about particular pseudo file. - */ -static int pseudos_show(struct seq_file *m, void *v) -{ - pseudo_plugin *pplug; - - pplug = v; - if (pplug->try != NULL) - seq_printf(m, "%s\n", pplug->h.label); - return 0; -} - -/* - * seq-methods for "..../bmap" - */ - -/* - * start iteration over all blocks allocated for the host file - */ -static void * bmap_start(struct seq_file *m, loff_t *pos) -{ - struct inode *host; - - host = get_seq_pseudo_host(m); - if (*pos << host->i_blkbits >= host->i_size) - return NULL; - else - return (void *)((unsigned long)*pos + 1); -} - -/* - * stop iteration over all blocks allocated for the host file - */ -static void bmap_stop(struct seq_file *m, void *v) -{ -} - -/* - * go to the next block in the sequence of blocks allocated for the host - * file. - */ -static void * bmap_next(struct seq_file *m, void *v, loff_t *pos) -{ - ++ (*pos); - return bmap_start(m, pos); -} - -extern int reiser4_lblock_to_blocknr(struct address_space *mapping, - sector_t lblock, reiser4_block_nr *blocknr); - -/* - * output information about single block number allocated for the host file - * into user supplied buffer - */ -static int bmap_show(struct seq_file *m, void *v) -{ - sector_t lblock; - int result; - reiser4_block_nr blocknr; - - lblock = ((sector_t)(unsigned long)v) - 1; - result = reiser4_lblock_to_blocknr(get_seq_pseudo_host(m)->i_mapping, - lblock, &blocknr); - if (result == 0) { - if (blocknr_is_fake(&blocknr)) - seq_printf(m, "%#llx\n", (unsigned long long)blocknr); - else - seq_printf(m, "%llu\n", (unsigned long long)blocknr); - } - return result; -} - -/* - * seq-methods for the "..../readdir" - */ - -/* "cursor" used to iterate over all directory entries for the host file */ -typedef struct readdir_cookie { - /* position within the tree */ - tap_t tap; - /* coord used by ->tap */ - coord_t coord; - /* lock handle used by ->tap */ - lock_handle lh; -} readdir_cookie; - -/* true if @coord stores directory entries for @host */ -static int is_host_item(struct inode *host, coord_t *coord) -{ - if (item_type_by_coord(coord) != DIR_ENTRY_ITEM_TYPE) - return 0; - if (!inode_file_plugin(host)->owns_item(host, coord)) - return 0; - return 1; -} - -/* helper function to release resources allocated to iterate over directory - * entries for the host file */ -static void finish(readdir_cookie *c) -{ - if (c != NULL && !IS_ERR(c)) { - /* release c->tap->lh long term lock... */ - tap_done(&c->tap); - /* ... and free cursor itself */ - kfree(c); - } -} - -/* - * start iterating over directory entries for the host file - */ -static void * readdir_start(struct seq_file *m, loff_t *pos) -{ - struct inode *host; - readdir_cookie *c; - dir_plugin *dplug; - reiser4_key dotkey; - struct qstr dotname; - int result; - loff_t entryno; - - /* - * first, lookup item containing dot of the host - */ - - host = get_seq_pseudo_host(m); - dplug = inode_dir_plugin(host); - - dotname.name = "."; - dotname.len = 1; - - down(&host->i_sem); - if (dplug == NULL || dplug->build_entry_key == NULL) { - finish(NULL); - return NULL; - } - - /* build key of dot */ - dplug->build_entry_key(host, &dotname, &dotkey); - - /* allocate cursor */ - c = kmalloc(sizeof *c, GFP_KERNEL); - if (c == NULL) { - finish(NULL); - return ERR_PTR(RETERR(-ENOMEM)); - } - - /* tree lookup */ - result = object_lookup(host, - &dotkey, - &c->coord, - &c->lh, - ZNODE_READ_LOCK, - FIND_EXACT, - LEAF_LEVEL, - LEAF_LEVEL, - CBK_READDIR_RA, - NULL); - - tap_init(&c->tap, &c->coord, &c->lh, ZNODE_READ_LOCK); - if (result == 0) - /* - * ok, now c->tap is positioned at the dot. We are requested - * to start readdir from the offset *pos. Skip that number of - * entries. That's not very efficient for the large - * directories. - */ - result = tap_load(&c->tap); { - if (result == 0) { - for (entryno = 0; entryno != *pos; ++ entryno) { - result = go_next_unit(&c->tap); - if (result == -E_NO_NEIGHBOR) { - finish(c); - return NULL; - } - if (result != 0) - break; - if (!is_host_item(host, c->tap.coord)) { - finish(c); - return NULL; - } - } - } - } - if (result != 0) { - finish(c); - return ERR_PTR(result); - } else - return c; -} - -/* - * stop iterating over directory entries for the host file - */ -static void readdir_stop(struct seq_file *m, void *v) -{ - up(&get_seq_pseudo_host(m)->i_sem); - finish(v); -} - -/* - * go to the next entry in the host directory - */ -static void * readdir_next(struct seq_file *m, void *v, loff_t *pos) -{ - readdir_cookie *c; - struct inode *host; - int result; - - c = v; - ++ (*pos); - host = get_seq_pseudo_host(m); - /* next entry is in the next unit */ - result = go_next_unit(&c->tap); - if (result == 0) { - /* check whether end of the directory was reached. */ - if (!is_host_item(host, c->tap.coord)) { - finish(c); - return NULL; - } else - return v; - } else { - finish(c); - return ERR_PTR(result); - } -} - -/* - * output information about single directory entry in the host directory - */ -static int readdir_show(struct seq_file *m, void *v) -{ - readdir_cookie *c; - item_plugin *iplug; - char *name; - char buf[DE_NAME_BUF_LEN]; - - c = v; - iplug = item_plugin_by_coord(&c->coord); - - name = iplug->s.dir.extract_name(&c->coord, buf); - assert("nikita-3221", name != NULL); - /* entries are separated by the "/" in the user buffer, because this - * is the only symbol (besides NUL) that is not allowed in file - * names. */ - seq_printf(m, "%s/", name); - return 0; -} - -/* - * methods for "..../plugin" - */ - -/* - * entry in the table mapping plugin pseudo file name to the corresponding - * pset member. - */ -typedef struct plugin_entry { - const char *name; - pset_member memb; -} plugin_entry; - -/* initializer for plugin_entry */ -#define PLUGIN_ENTRY(field, ind) \ -{ \ - .name = #field, \ - .memb = ind \ -} - -#define PSEUDO_ARRAY_ENTRY(idx, aname) \ -[idx] = { \ - .name = aname \ -} - -/* - * initialize array defining files available under "..../plugin". - */ -static plugin_entry pentry[] = { - /* "a/..../plugin/file" corresponds to the PSET_FILE plugin of its - * host file (that is, "a"), etc. */ - PLUGIN_ENTRY(file, PSET_FILE), - PLUGIN_ENTRY(dir, PSET_DIR), - PLUGIN_ENTRY(perm, PSET_PERM), - PLUGIN_ENTRY(formatting, PSET_FORMATTING), - PLUGIN_ENTRY(hash, PSET_HASH), - PLUGIN_ENTRY(fibration, PSET_FIBRATION), - PLUGIN_ENTRY(sd, PSET_SD), - PLUGIN_ENTRY(dir_item, PSET_DIR_ITEM), - PLUGIN_ENTRY(crypto, PSET_CRYPTO), - PLUGIN_ENTRY(digest, PSET_DIGEST), - PLUGIN_ENTRY(compression, PSET_COMPRESSION), - PLUGIN_ENTRY(compression_mode, PSET_COMPRESSION_MODE), - PLUGIN_ENTRY(cluster, PSET_CLUSTER), - PLUGIN_ENTRY(regular, PSET_REGULAR_ENTRY), - { - .name = NULL, - } -}; - -/* - * enumeration of files available under "a/..../plugin/foo" - */ -typedef enum { - PFIELD_TYPEID, /* "a/..../plugin/foo/type_id" contains type id of the - * plugin foo */ - PFIELD_ID, /* "a/..../plugin/foo/id" contains id of the plugin - * foo */ - PFIELD_LABEL, /* "a/..../plugin/foo/label" contains label of the - * plugin foo */ - PFIELD_DESC /* "a/..../plugin/foo/desc" contains description of - * the plugin foo */ -} plugin_field; - -/* map pseudo files under "a/..../plugin/foo" to their names */ -static plugin_entry fentry[] = { - PSEUDO_ARRAY_ENTRY(PFIELD_TYPEID, "type_id"), - PSEUDO_ARRAY_ENTRY(PFIELD_ID, "id"), - PSEUDO_ARRAY_ENTRY(PFIELD_LABEL, "label"), - PSEUDO_ARRAY_ENTRY(PFIELD_DESC, "desc"), - { - .name = NULL - }, -}; - -/* read method for "a/..../plugin/foo" */ -static int show_plugin(struct seq_file *seq, void *cookie) -{ - struct inode *host; - struct file *file; - struct inode *inode; - reiser4_plugin *plug; - plugin_entry *entry; - int idx; - plugin_set *pset; - - file = seq->private; - inode = file->f_dentry->d_inode; - - host = get_inode_host(inode); - idx = reiser4_inode_data(inode)->file_plugin_data.pseudo_info.datum; - entry = &pentry[idx]; - pset = reiser4_inode_data(host)->pset; - plug = pset_get(pset, entry->memb); - - if (plug != NULL) - seq_printf(seq, "%i %s %s", - plug->h.id, plug->h.label, plug->h.desc); - return 0; -} - -/* - * write method for "a/..../plugin/foo": extract plugin label from the user - * supplied buffer @buf and update plugin foo, if possible. - */ -static int set_plugin(struct file *file, const char *buf) -{ - struct inode *host; - struct inode *inode; - reiser4_plugin *plug; - plugin_entry *entry; - int idx; - plugin_set *pset; - int result; - reiser4_context ctx; - - inode = file->f_dentry->d_inode; - init_context(&ctx, inode->i_sb); - - host = get_inode_host(inode); - idx = reiser4_inode_data(inode)->file_plugin_data.pseudo_info.datum; - entry = &pentry[idx]; - pset = reiser4_inode_data(host)->pset; - - plug = lookup_plugin(entry->name, buf); - if (plug != NULL) { - result = force_plugin(host, entry->memb, plug); - if (result == 0) { - __u64 tograb; - - /* - * if plugin was updated successfully, save changes in - * the stat-data - */ - tograb = inode_file_plugin(host)->estimate.update(host); - result = reiser4_grab_space(tograb, BA_CAN_COMMIT); - if (result == 0) - result = reiser4_mark_inode_dirty(host); - } - } else - result = RETERR(-ENOENT); - context_set_commit_async(&ctx); - reiser4_exit_context(&ctx); - return result; -} - -/* - * helper function to implement ->lookup() method of pseudo directory plugin - * for the file that contains multiple similar children pseudo files. - * - * For example, "a/..../plugin/" directory contains files for each plugin - * associated with the host file "a". Handling of read/write for these file is - * exactly the same, the only difference being the pset member id for the - * corresponding plugin. Similarly, "a/..../plugin/foo/" itself contains - * files that are used to provide user access to the corresponding fields of - * the "foo" plugin, and all such fields can be handled similarly (see - * show_plugin_field()) - * - * To avoid code duplication in such situation, an array is constructed that - * is used as a map from the name of "child" object to the corresponding - * "datum". All child objects are handled by the same pseudo plugin, and are - * differentiated by the datum installed into pseudo file inode. - */ -static int array_lookup_pseudo(struct inode *parent, struct dentry ** dentry, - plugin_entry *array, pseudo_plugin *pplug) -{ - int result; - int idx; - struct inode *pseudo; - - pseudo = ERR_PTR(-ENOENT); - /* search for the given name in the array */ - for (idx = 0; array[idx].name != NULL; ++ idx) { - if (!strcmp((*dentry)->d_name.name, array[idx].name)) { - pseudo = add_pseudo(parent, pplug, dentry); - break; - } - } - if (IS_ERR(pseudo)) - result = PTR_ERR(pseudo); - else { - result = 0; - /* if name was found, set datum in the inode */ - pseudo_set_datum(pseudo, idx); - } - return result; -} - -/* - * helper method to implement array for the situation when we have multiple - * child pseudo files with similar functionality. See comment for - * array_lookup_pseudo(). - */ -static int array_readdir_pseudo(struct file *f, void *dirent, filldir_t filld, - plugin_entry *array, int size) -{ - loff_t off; - ino_t ino; - - off = f->f_pos; - if (off < 0) - return 0; - - /* for god's sake, why switch(loff_t) requires __cmpdi2? */ - switch ((int)off) { - case 0: - ino = f->f_dentry->d_inode->i_ino; - if (filld(dirent, ".", 1, off, ino, DT_DIR) < 0) - break; - ++ off; - /* fallthrough */ - case 1: - ino = parent_ino(f->f_dentry); - if (filld(dirent, "..", 2, off, ino, DT_DIR) < 0) - break; - ++ off; - /* fallthrough */ - default: - /* scan array for the names */ - for (; off < size + 1; ++ off) { - const char *name; - - name = array[off - 2].name; - if (filld(dirent, name, strlen(name), - off, off + (long)f, DT_REG) < 0) - break; - } - } - f->f_pos = off; - return 0; -} - - -/* - * ->lookup() method for the "a/..../plugin/foo/" directory. It uses array - * representation of child objects, described in the comment for - * array_lookup_pseudo(). - */ -static int lookup_plugin_field(struct inode *parent, struct dentry ** dentry) -{ - return array_lookup_pseudo(parent, dentry, fentry, - pseudo_plugin_by_id(PSEUDO_PLUGIN_FIELD_ID)); -} - -/* - * read method for "a/..../plugin/foo/field" - */ -static int show_plugin_field(struct seq_file *seq, void *cookie) -{ - struct inode *parent; - struct inode *host; - struct file *file; - struct inode *inode; - reiser4_plugin *plug; - plugin_entry *entry; - int pidx; - int idx; - plugin_set *pset; - - file = seq->private; - inode = file->f_dentry->d_inode; - - parent = get_inode_parent(inode); - host = get_inode_host(inode); - pidx = reiser4_inode_data(parent)->file_plugin_data.pseudo_info.datum; - idx = reiser4_inode_data(inode)->file_plugin_data.pseudo_info.datum; - entry = &pentry[pidx]; - pset = reiser4_inode_data(host)->pset; - plug = pset_get(pset, entry->memb); - - if (plug != NULL) { - switch (idx) { - case PFIELD_TYPEID: - seq_printf(seq, "%i", plug->h.type_id); - break; - case PFIELD_ID: - seq_printf(seq, "%i", plug->h.id); - break; - case PFIELD_LABEL: - seq_printf(seq, "%s", plug->h.label); - break; - case PFIELD_DESC: - seq_printf(seq, "%s", plug->h.desc); - break; - } - } - - return 0; -} - -/* - * ->readdir() method for "a/..../plugin/foo/". It uses array representation of - * child objects, described in the comment for array_lookup_pseudo(). - */ -static int readdir_plugin_field(struct file *f, void *dirent, filldir_t filld) -{ - return array_readdir_pseudo(f, dirent, filld, - fentry, sizeof_array(fentry)); -} - -/* - * ->lookup() method for the "a/..../plugin/" directory. It uses array - * representation of child objects, described in the comment for - * array_lookup_pseudo(). - */ -static int lookup_plugins(struct inode *parent, struct dentry ** dentry) -{ - return array_lookup_pseudo(parent, dentry, pentry, - pseudo_plugin_by_id(PSEUDO_PLUGIN_ID)); -} - -/* - * ->readdir() method for "a/..../plugin/". It uses array representation of - * child objects, described in the comment for array_lookup_pseudo(). - */ -static int readdir_plugins(struct file *f, void *dirent, filldir_t filld) -{ - return array_readdir_pseudo(f, dirent, filld, - pentry, sizeof_array(pentry)); -} - -/* - * seq-methods for the "a/..../items" - */ - -/* - * start iteration over a sequence of items for the host file. This iterator - * uses the same cursor as a readdir iterator above. - */ -static void * items_start(struct seq_file *m, loff_t *pos) -{ - struct inode *host; - readdir_cookie *c; - file_plugin *fplug; - reiser4_key headkey; - int result; - loff_t entryno; - - /* - * first, find first item in the file, then, scan to the *pos-th one. - */ - - host = get_seq_pseudo_host(m); - fplug = inode_file_plugin(host); - - down(&host->i_sem); - if (fplug->key_by_inode == NULL) { - finish(NULL); - return NULL; - } - - /* construct a key of the first item */ - fplug->key_by_inode(host, 0, &headkey); - - c = kmalloc(sizeof *c, GFP_KERNEL); - if (c == NULL) { - finish(NULL); - return ERR_PTR(RETERR(-ENOMEM)); - } - - /* find first item */ - result = object_lookup(host, - &headkey, - &c->coord, - &c->lh, - ZNODE_READ_LOCK, - FIND_MAX_NOT_MORE_THAN, - TWIG_LEVEL, - LEAF_LEVEL, - 0, - NULL); - - tap_init(&c->tap, &c->coord, &c->lh, ZNODE_READ_LOCK); - if (result == 0) - result = tap_load(&c->tap); { - if (result == 0) { - /* - * skip @pos items - */ - for (entryno = 0; entryno != *pos; ++ entryno) { - result = go_next_unit(&c->tap); - if (result == -E_NO_NEIGHBOR) { - finish(c); - return NULL; - } - if (result != 0) - break; - if (!fplug->owns_item(host, c->tap.coord)) { - finish(c); - return NULL; - } - } - } - } - if (result != 0) { - finish(c); - return ERR_PTR(result); - } else - return c; -} - -/* - * stop iteration over a sequence of items for the host file - */ -static void items_stop(struct seq_file *m, void *v) -{ - up(&get_seq_pseudo_host(m)->i_sem); - finish(v); -} - -/* go to the next item in the host file */ -static void * items_next(struct seq_file *m, void *v, loff_t *pos) -{ - readdir_cookie *c; - struct inode *host; - int result; - - c = v; - ++ (*pos); - host = get_seq_pseudo_host(m); - result = go_next_unit(&c->tap); - if (result == 0) { - if (!inode_file_plugin(host)->owns_item(host, c->tap.coord)) { - finish(c); - return NULL; - } else - return v; - } else { - finish(c); - return ERR_PTR(result); - } -} - -/* output information about single item of the host file */ -static int items_show(struct seq_file *m, void *v) -{ - readdir_cookie *c; - item_plugin *iplug; - char buf[KEY_BUF_LEN]; - reiser4_key key; - - - c = v; - iplug = item_plugin_by_coord(&c->coord); - - /* output key... */ - sprintf_key(buf, unit_key_by_coord(&c->coord, &key)); - /* ... and item plugin label... */ - seq_printf(m, "%s %s\n", buf, iplug->h.label); - return 0; -} - -extern int -invoke_create_method(struct inode *, struct dentry *, - reiser4_object_create_data *); - -/* - * write method for the "a/..../new" file. Extract file name from the user - * supplied buffer @buf, and create regular file with that name within host - * file (that is better to be a directory). - */ -static int get_new(struct file *file, const char *buf) -{ - int result; - - /* check that @buf contains no slashes */ - if (strchr(buf, '/') == NULL) { - struct dentry *d; - struct qstr name; - unsigned int c; - unsigned long hash; - - reiser4_object_create_data data; - memset(&data, 0, sizeof data); - - data.mode = S_IFREG | 0 /* mode */; - data.id = UNIX_FILE_PLUGIN_ID; - - name.name = buf; - c = *(const unsigned char *)buf; - - /* build hash of the name */ - hash = init_name_hash(); - do { - buf++; - hash = partial_name_hash(c, hash); - c = *(const unsigned char *)buf; - } while (c); - name.len = buf - (const char *) name.name; - name.hash = end_name_hash(hash); - - /* allocate dentry */ - d = d_alloc(file->f_dentry->d_parent->d_parent, &name); - if (d == NULL) - result = RETERR(-ENOMEM); - else { - /* call ->create() method of the host directory */ - result = invoke_create_method(get_pseudo_host(file), - d, &data); - reiser4_free_dentry_fsdata(d); - } - } else - result = RETERR(-EINVAL); - return result; -} - -/* - * initialize pseudo plugins. - */ -pseudo_plugin pseudo_plugins[LAST_PSEUDO_ID] = { - [PSEUDO_METAS_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_METAS_ID, - .pops = NULL, - .label = "....", - .desc = "meta-files", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = TOP_LEVEL, - .try = try_by_label, - .readdirable = 0, - .lookup = lookup_table, - .lookup_mode = S_IFDIR | S_IRUGO | S_IXUGO, - .read_type = PSEUDO_READ_NONE, - .write_type = PSEUDO_WRITE_NONE, - .readdir = readdir_table - }, - [PSEUDO_UID_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_UID_ID, - .pops = NULL, - .label = "uid", - .desc = "returns owner", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = PSEUDO_METAS_ID, - .try = try_by_label, - .readdirable = 1, - .lookup = NULL, - .lookup_mode = S_IFREG | S_IRUGO | S_IWUSR, - .read_type = PSEUDO_READ_SINGLE, - .read = { - .single_show = show_uid - }, - .write_type = PSEUDO_WRITE_STRING, - .write = { - .gets = store_uid - } - }, - [PSEUDO_GID_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_GID_ID, - .pops = NULL, - .label = "gid", - .desc = "returns group", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = PSEUDO_METAS_ID, - .try = try_by_label, - .readdirable = 1, - .lookup = NULL, - .lookup_mode = S_IFREG | S_IRUGO | S_IWUSR, - .read_type = PSEUDO_READ_SINGLE, - .read = { - .single_show = show_gid - }, - .write_type = PSEUDO_WRITE_STRING, - .write = { - .gets = get_gid - } - }, - [PSEUDO_RWX_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_RWX_ID, - .pops = NULL, - .label = "rwx", - .desc = "returns rwx permissions", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = PSEUDO_METAS_ID, - .try = try_by_label, - .readdirable = 1, - .lookup = NULL, - .lookup_mode = S_IFREG | S_IRUGO | S_IWUSR, - .read_type = PSEUDO_READ_SINGLE, - .read = { - .single_show = show_rwx - }, - .write_type = PSEUDO_WRITE_STRING, - .write = { - .gets = get_rwx - } - }, - [PSEUDO_OID_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_OID_ID, - .pops = NULL, - .label = "oid", - .desc = "returns object id", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = PSEUDO_METAS_ID, - .try = try_by_label, - .readdirable = 1, - .lookup = NULL, - .lookup_mode = S_IFREG | S_IRUGO, - .read_type = PSEUDO_READ_SINGLE, - .read = { - .single_show = show_oid - }, - .write_type = PSEUDO_WRITE_NONE - }, - [PSEUDO_KEY_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_KEY_ID, - .pops = NULL, - .label = "key", - .desc = "returns object's key", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = PSEUDO_METAS_ID, - .try = try_by_label, - .readdirable = 1, - .lookup = NULL, - .lookup_mode = S_IFREG | S_IRUGO, - .read_type = PSEUDO_READ_SINGLE, - .read = { - .single_show = show_key - }, - .write_type = PSEUDO_WRITE_NONE - }, - [PSEUDO_SIZE_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_SIZE_ID, - .pops = NULL, - .label = "size", - .desc = "returns object's size", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = PSEUDO_METAS_ID, - .try = try_by_label, - .readdirable = 1, - .lookup = NULL, - .lookup_mode = S_IFREG | S_IRUGO, - .read_type = PSEUDO_READ_SINGLE, - .read = { - .single_show = show_size - }, - .write_type = PSEUDO_WRITE_NONE - }, - [PSEUDO_NLINK_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_NLINK_ID, - .pops = NULL, - .label = "nlink", - .desc = "returns nlink count", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = PSEUDO_METAS_ID, - .try = try_by_label, - .readdirable = 1, - .lookup = NULL, - .lookup_mode = S_IFREG | S_IRUGO, - .read_type = PSEUDO_READ_SINGLE, - .read = { - .single_show = show_nlink - }, - .write_type = PSEUDO_WRITE_NONE - }, - [PSEUDO_LOCALITY_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_LOCALITY_ID, - .pops = NULL, - .label = "locality", - .desc = "returns object's locality", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = PSEUDO_METAS_ID, - .try = try_by_label, - .readdirable = 1, - .lookup = NULL, - .lookup_mode = S_IFREG | S_IRUGO, - .read_type = PSEUDO_READ_SINGLE, - .read = { - .single_show = show_locality - }, - .write_type = PSEUDO_WRITE_NONE - }, - [PSEUDO_PSEUDOS_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_PSEUDOS_ID, - .pops = NULL, - .label = "pseudo", - .desc = "returns a list of pseudo files", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = PSEUDO_METAS_ID, - .try = try_by_label, - .readdirable = 1, - .lookup = NULL, - .lookup_mode = S_IFREG | S_IRUGO, - .read_type = PSEUDO_READ_SEQ, - .read = { - .ops = { - .start = pseudos_start, - .stop = pseudos_stop, - .next = pseudos_next, - .show = pseudos_show - } - }, - .write_type = PSEUDO_WRITE_NONE - }, - [PSEUDO_BMAP_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_BMAP_ID, - .pops = NULL, - .label = "bmap", - .desc = "returns a list blocks for this file", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = PSEUDO_METAS_ID, - .try = try_by_label, - .readdirable = 1, - .lookup = NULL, - .lookup_mode = S_IFREG | S_IRUGO, - .read_type = PSEUDO_READ_SEQ, - .read = { - .ops = { - .start = bmap_start, - .stop = bmap_stop, - .next = bmap_next, - .show = bmap_show - } - }, - .write_type = PSEUDO_WRITE_NONE - }, - [PSEUDO_READDIR_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_READDIR_ID, - .pops = NULL, - .label = "readdir", - .desc = "returns a list of names in the dir", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = PSEUDO_METAS_ID, - .try = try_by_label, - .readdirable = 1, - .lookup = NULL, - .lookup_mode = S_IFREG | S_IRUGO, - .read_type = PSEUDO_READ_SEQ, - .read = { - .ops = { - .start = readdir_start, - .stop = readdir_stop, - .next = readdir_next, - .show = readdir_show - } - }, - .write_type = PSEUDO_WRITE_NONE - }, - [PSEUDO_PLUGIN_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_PLUGIN_ID, - .pops = NULL, - .label = "plugin", - .desc = "plugin", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = PSEUDO_PLUGINS_ID, - .try = NULL, - .readdirable = 0, - .lookup = lookup_plugin_field, - /* - * foo/..../plugin/bar is much like a directory. So, why - * there is no S_IFDIR term in the .lookup_mode, you ask? - * - * fs/namei.c:may_open(): - * - * if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE)) - * return -EISDIR; - * - * Directory cannot be opened for write. How smart. - */ - .lookup_mode = S_IFREG | S_IRUGO | S_IWUSR | S_IXUGO, - .read_type = PSEUDO_READ_SINGLE, - .read = { - .single_show = show_plugin - }, - .write_type = PSEUDO_WRITE_STRING, - .write = { - .gets = set_plugin - }, - .readdir = readdir_plugin_field - }, - [PSEUDO_PLUGINS_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_PLUGINS_ID, - .pops = NULL, - .label = "plugin", - .desc = "list of plugins", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = PSEUDO_METAS_ID, - .try = try_by_label, - .readdirable = 1, - .lookup = lookup_plugins, - .lookup_mode = S_IFDIR | S_IRUGO | S_IXUGO, - .read_type = PSEUDO_READ_NONE, - .write_type = PSEUDO_WRITE_NONE, - .readdir = readdir_plugins - }, - [PSEUDO_PLUGIN_FIELD_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_PLUGIN_ID, - .pops = NULL, - .label = "plugin-field", - .desc = "plugin field", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = PSEUDO_PLUGIN_ID, - .try = NULL, - .readdirable = 0, - .lookup = NULL, - .lookup_mode = S_IFREG | S_IRUGO, - .read_type = PSEUDO_READ_SINGLE, - .read = { - .single_show = show_plugin_field - }, - .write_type = PSEUDO_WRITE_NONE, - .readdir = NULL - }, - [PSEUDO_ITEMS_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_ITEMS_ID, - .pops = NULL, - .label = "items", - .desc = "returns a list of items for this file", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = PSEUDO_METAS_ID, - .try = try_by_label, - .readdirable = 1, - .lookup = NULL, - .lookup_mode = S_IFREG | S_IRUGO, - .read_type = PSEUDO_READ_SEQ, - .read = { - .ops = { - .start = items_start, - .stop = items_stop, - .next = items_next, - .show = items_show - } - }, - .write_type = PSEUDO_WRITE_NONE - }, - [PSEUDO_NEW_ID] = { - .h = { - .type_id = REISER4_PSEUDO_PLUGIN_TYPE, - .id = PSEUDO_NEW_ID, - .pops = NULL, - .label = "new", - .desc = "creates new file in the host", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .parent = PSEUDO_METAS_ID, - .try = try_by_label, - .readdirable = 1, - .lookup = NULL, - .lookup_mode = S_IFREG | S_IWUSR, - .read_type = PSEUDO_READ_NONE, - .read = { - .single_show = show_rwx - }, - .write_type = PSEUDO_WRITE_STRING, - .write = { - .gets = get_new - } - }, -}; - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - scroll-step: 1 - End: -*/ diff -L fs/reiser4/plugin/pseudo/pseudo.h -puN fs/reiser4/plugin/pseudo/pseudo.h~reiser4-big-update /dev/null --- devel/fs/reiser4/plugin/pseudo/pseudo.h +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,176 +0,0 @@ -/* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by - * reiser4/README */ - -/* Handling of "pseudo" files representing unified access to meta data in - reiser4. See pseudo.c for more comments. */ - -#if !defined( __REISER4_PSEUDO_H__ ) -#define __REISER4_PSEUDO_H__ - -#include "../plugin_header.h" -#include "../../key.h" - -#include -#include - -/* - * tag used by wrappers in plugin/file/pseudo.c to perform actions for the - * particular flavor of pseudo file. - */ -typedef enum { - /* this pseudo file cannot be read */ - PSEUDO_READ_NONE, - /* this pseudo file used seq_* functions (fs/seq_file.c) to generate - * it's content */ - PSEUDO_READ_SEQ, - /* this pseudo file contains single value */ - PSEUDO_READ_SINGLE, - /* this pseudo file has some special ->read() method that should be - * called */ - PSEUDO_READ_FORWARD -} pseudo_read_type; - -typedef enum { - /* this pseudo file cannot be written into */ - PSEUDO_WRITE_NONE, - /* this pseudo file's content is generated by sprintf() */ - PSEUDO_WRITE_STRING, - /* this pseudo file has some special ->write() method that should be - * called */ - PSEUDO_WRITE_FORWARD -} pseudo_write_type; - -/* low level operations on the pseudo files. - - Methods from this interface are directly callable by reiser4 system call. - - This operation structure looks suspiciously like yet another plugin - type. Doing so would simplify some things. For example, there are already - functions to look up plugin by name, etc. - -*/ -struct pseudo_plugin; -typedef struct pseudo_plugin pseudo_plugin; -struct pseudo_plugin { - - /* common fields */ - plugin_header h; - - /* - * id of plugin of the parent pseudo file in the directory - * hierarchy. See comment for - * plugin/pseudo/pseudo.c:lookup_of_plugin(). - */ - int parent; - - /* - * check whether this pseudo file matches name @name within @parent - */ - int (*try) (pseudo_plugin *pplug, - const struct inode *parent, const char *name); - /* - * true if this pseudo file is visible in readdir. - */ - int readdirable; - /* lookup method applicable to this pseudo file by method name. - - This is for something like "foo/..acl/dup", here "../acl" is the - name of a pseudo file, and "dup" is name of an operation (method) - applicable to "../acl". Once "..acl" is resolved to ACL object, - ->lookup( "dup" ) can be called to get operation. - - */ - int (*lookup)(struct inode *parent, struct dentry ** dentry); - - /* - * rwx bits returned by stat(2) for this pseudo file - */ - umode_t lookup_mode; - - /* NOTE-NIKITA some other operations. Reiser4 syntax people should - add something here. */ - - /* - * how content of this pseudo file is generated - */ - pseudo_read_type read_type; - union { - /* for PSEUDO_READ_SEQ */ - struct seq_operations ops; - /* for PSEUDO_READ_SINGLE */ - int (*single_show) (struct seq_file *, void *); - /* for PSEUDO_READ_FORWARD */ - ssize_t (*read)(struct file *, char __user *, size_t , loff_t *); - } read; - - /* - * how this pseudo file reacts to write(2) calls - */ - pseudo_write_type write_type; - union { - /* for PSEUDO_WRITE_STRING */ - int (*gets)(struct file *, const char *); - /* for PSEUDO_WRITE_FORWARD */ - ssize_t (*write)(struct file *, - const char __user *, size_t , loff_t *); - } write; - /* - * ->readdir method - */ - int (*readdir)(struct file *f, void *dirent, filldir_t filld); -}; - -/* portion of reiser4_inode specific for pseudo files */ -typedef struct pseudo_info { - /* pseudo file plugin controlling this file */ - pseudo_plugin *plugin; - /* host object, for /etc/passwd/..oid, this is pointer to inode of - * /etc/passwd */ - struct inode *host; - /* immediate parent object. This is different from ->host for deeply - * nested pseudo files like foo/..plugin/foo */ - struct inode *parent; - /* for private use of pseudo file plugin */ - unsigned long datum; -} pseudo_info_t; - -extern int lookup_pseudo_file(struct inode *parent, struct dentry **dentry); - -/* - * ids of pseudo files. See plugin/pseudo/pseudo.c for more details on each - * particular pseudo file. - */ -typedef enum { - PSEUDO_METAS_ID, - PSEUDO_UID_ID, - PSEUDO_GID_ID, - PSEUDO_RWX_ID, - PSEUDO_OID_ID, - PSEUDO_KEY_ID, - PSEUDO_SIZE_ID, - PSEUDO_NLINK_ID, - PSEUDO_LOCALITY_ID, - PSEUDO_PSEUDOS_ID, - PSEUDO_BMAP_ID, - PSEUDO_READDIR_ID, - PSEUDO_PLUGIN_ID, - PSEUDO_PLUGINS_ID, - PSEUDO_PLUGIN_FIELD_ID, - PSEUDO_ITEMS_ID, - PSEUDO_NEW_ID, - LAST_PSEUDO_ID -} reiser4_pseudo_id; - -/* __REISER4_PSEUDO_H__ */ -#endif - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - scroll-step: 1 - End: -*/ diff -puN /dev/null fs/reiser4/plugin/regular.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/regular.c 2005-09-15 19:51:08.000000000 -0700 @@ -0,0 +1,44 @@ +/* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */ + +/* Contains Reiser4 regular plugins which: + . specify a set of reiser4 regular object plugins, + . used by directory plugin to create entries powered by specified + regular plugins */ + +#include "plugin.h" + +regular_plugin regular_plugins[LAST_REGULAR_ID] = { + [UF_REGULAR_ID] = { + .h = { + .type_id = REISER4_REGULAR_PLUGIN_TYPE, + .id = UF_REGULAR_ID, + .pops = NULL, + .label = "unixfile", + .desc = "Unix file regular plugin", + .linkage = {NULL, NULL} + }, + .id = UNIX_FILE_PLUGIN_ID + }, + [CRC_REGULAR_ID] = { + .h = { + .type_id = REISER4_REGULAR_PLUGIN_TYPE, + .id = CRC_REGULAR_ID, + .pops = NULL, + .label = "cryptcompress", + .desc = "Cryptcompress regular plugin", + .linkage = {NULL, NULL} + }, + .id = CRC_FILE_PLUGIN_ID + } +}; + +/* + Local variables: + c-indentation-style: "K&R" + mode-name: "LC" + c-basic-offset: 8 + tab-width: 8 + fill-column: 120 + scroll-step: 1 + End: +*/ diff -puN fs/reiser4/plugin/security/perm.c~reiser4-big-update fs/reiser4/plugin/security/perm.c --- devel/fs/reiser4/plugin/security/perm.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/security/perm.c 2005-09-15 19:51:08.000000000 -0700 @@ -1,6 +1,9 @@ /* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */ -/* NIKITA-FIXME-HANS: this comment describes what code? */ -/* definition of item plugins. */ + +/* + * this file contains implementation of permission plugins. Currently, only + * RWX_PERM_ID is implemented + */ #include "../plugin.h" #include "../plugin_header.h" @@ -11,14 +14,12 @@ #include #include -static int -mask_ok_common(struct inode *inode, int mask) +static int mask_ok_common(struct inode *inode, int mask) { return generic_permission(inode, mask, NULL); } -static int -setattr_ok_common(struct dentry *dentry, struct iattr *attr) +static int setattr_ok_common(struct dentry *dentry, struct iattr *attr) { int result; struct inode *inode; @@ -36,56 +37,53 @@ setattr_ok_common(struct dentry *dentry, valid = attr->ia_valid; if ((valid & ATTR_UID && attr->ia_uid != inode->i_uid) || (valid & ATTR_GID && attr->ia_gid != inode->i_gid)) - result = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; + result = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0; } return result; } static int -read_ok_common( - struct file * file, const char *buf, size_t size, loff_t *off) +read_ok_common(struct file *file, const char __user *buf, size_t size, loff_t * off) { return access_ok(VERIFY_WRITE, buf, size) ? 0 : -EFAULT; } static int -write_ok_common( - struct file * file, const char *buf, size_t size, loff_t *off) +write_ok_common(struct file *file, const char __user *buf, size_t size, loff_t * off) { return access_ok(VERIFY_READ, buf, size) ? 0 : -EFAULT; } perm_plugin perm_plugins[LAST_PERM_ID] = { -/* NIKITA-FIXME-HANS: what file contains rwx permissions methods code? */ [RWX_PERM_ID] = { - .h = { - .type_id = REISER4_PERM_PLUGIN_TYPE, - .id = RWX_PERM_ID, - .pops = NULL, - .label = "rwx", - .desc = "standard UNIX permissions", - .linkage = TYPE_SAFE_LIST_LINK_ZERO - }, - .read_ok = read_ok_common, - .write_ok = write_ok_common, - .lookup_ok = NULL, - .create_ok = NULL, - .link_ok = NULL, - .unlink_ok = NULL, - .delete_ok = NULL, - .mask_ok = mask_ok_common, - .setattr_ok = setattr_ok_common, - .getattr_ok = NULL, - .rename_ok = NULL, - }, + .h = { + .type_id = REISER4_PERM_PLUGIN_TYPE, + .id = RWX_PERM_ID, + .pops = NULL, + .label = "rwx", + .desc = "standard UNIX permissions", + .linkage = {NULL, NULL} + }, + .read_ok = read_ok_common, + .write_ok = write_ok_common, + .lookup_ok = NULL, + .create_ok = NULL, + .link_ok = NULL, + .unlink_ok = NULL, + .delete_ok = NULL, + .mask_ok = mask_ok_common, + .setattr_ok = setattr_ok_common, + .getattr_ok = NULL, + .rename_ok = NULL, + } }; -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - End: -*/ +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 79 + * End: + */ diff -puN fs/reiser4/plugin/security/perm.h~reiser4-big-update fs/reiser4/plugin/security/perm.h --- devel/fs/reiser4/plugin/security/perm.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/security/perm.h 2005-09-15 19:51:08.000000000 -0700 @@ -32,17 +32,21 @@ typedef struct perm_plugin { plugin_header h; /* check permissions for read/write */ - int (*read_ok) (struct file * file, const char *buf, size_t size, loff_t * off); - int (*write_ok) (struct file * file, const char *buf, size_t size, loff_t * off); + int (*read_ok) (struct file *file, const char __user *buf, + size_t size, loff_t *off); + int (*write_ok) (struct file *file, const char __user *buf, + size_t size, loff_t *off); /* check permissions for lookup */ int (*lookup_ok) (struct inode * parent, struct dentry * dentry); /* check permissions for create */ - int (*create_ok) (struct inode * parent, struct dentry * dentry, reiser4_object_create_data * data); + int (*create_ok) (struct inode * parent, struct dentry * dentry, + reiser4_object_create_data * data); /* check permissions for linking @where to @existing */ - int (*link_ok) (struct dentry * existing, struct inode * parent, struct dentry * where); + int (*link_ok) (struct dentry * existing, struct inode * parent, + struct dentry * where); /* check permissions for unlinking @victim from @parent */ int (*unlink_ok) (struct inode * parent, struct dentry * victim); @@ -55,7 +59,8 @@ typedef struct perm_plugin { int (*setattr_ok) (struct dentry * dentry, struct iattr * attr); /* check whether stat(2) is allowed */ - int (*getattr_ok) (struct vfsmount * mnt UNUSED_ARG, struct dentry * dentry, struct kstat * stat); + int (*getattr_ok) (struct vfsmount * mnt UNUSED_ARG, + struct dentry * dentry, struct kstat * stat); /* check whether rename(2) is allowed */ int (*rename_ok) (struct inode * old_dir, struct dentry * old, struct inode * new_dir, struct dentry * new); diff -puN fs/reiser4/plugin/space/bitmap.c~reiser4-big-update fs/reiser4/plugin/space/bitmap.c --- devel/fs/reiser4/plugin/space/bitmap.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/space/bitmap.c 2005-09-15 19:51:08.000000000 -0700 @@ -7,7 +7,6 @@ #include "../../block_alloc.h" #include "../../tree.h" #include "../../super.h" -#include "../../lib.h" #include "../plugin.h" #include "space_allocator.h" #include "bitmap.h" @@ -66,7 +65,6 @@ typedef unsigned long ulong_t; - #define bmap_size(blocksize) ((blocksize) - CHECKSUM_SIZE) #define bmap_bit_count(blocksize) (bmap_size(blocksize) << 3) @@ -84,8 +82,7 @@ struct bitmap_node { * already */ }; -static inline char * -bnode_working_data(struct bitmap_node *bnode) +static inline char *bnode_working_data(struct bitmap_node *bnode) { char *data; @@ -95,8 +92,7 @@ bnode_working_data(struct bitmap_node *b return data + CHECKSUM_SIZE; } -static inline char * -bnode_commit_data(const struct bitmap_node *bnode) +static inline char *bnode_commit_data(const struct bitmap_node *bnode) { char *data; @@ -106,8 +102,7 @@ bnode_commit_data(const struct bitmap_no return data + CHECKSUM_SIZE; } -static inline __u32 -bnode_commit_crc(const struct bitmap_node *bnode) +static inline __u32 bnode_commit_crc(const struct bitmap_node *bnode) { char *data; @@ -117,8 +112,7 @@ bnode_commit_crc(const struct bitmap_nod return d32tocpu((d32 *) data); } -static inline void -bnode_set_commit_crc(struct bitmap_node *bnode, __u32 crc) +static inline void bnode_set_commit_crc(struct bitmap_node *bnode, __u32 crc) { char *data; @@ -148,8 +142,7 @@ struct bitmap_allocator_data { #define get_bnode(super, i) (get_barray(super) + i) /* allocate and initialize jnode with JNODE_BITMAP type */ -static jnode * -bnew(void) +static jnode *bnew(void) { jnode *jal = jalloc(); @@ -164,8 +157,7 @@ bnew(void) - all the helper functions like set bit, find_first_zero_bit, etc */ /* Audited by: green(2002.06.12) */ -static int -find_next_zero_bit_in_word(ulong_t word, int start_bit) +static int find_next_zero_bit_in_word(ulong_t word, int start_bit) { ulong_t mask = 1UL << start_bit; int i = start_bit; @@ -186,25 +178,27 @@ find_next_zero_bit_in_word(ulong_t word, #define OFF(addr) (((ulong_t)(addr) & (BYTES_PER_LONG - 1)) << 3) #define BASE(addr) ((ulong_t*) ((ulong_t)(addr) & ~(BYTES_PER_LONG - 1))) -static inline void reiser4_set_bit(int nr, void * addr) +static inline void reiser4_set_bit(int nr, void *addr) { ext2_set_bit(nr + OFF(addr), BASE(addr)); } -static inline void reiser4_clear_bit(int nr, void * addr) +static inline void reiser4_clear_bit(int nr, void *addr) { ext2_clear_bit(nr + OFF(addr), BASE(addr)); } -static inline int reiser4_test_bit(int nr, void * addr) +static inline int reiser4_test_bit(int nr, void *addr) { return ext2_test_bit(nr + OFF(addr), BASE(addr)); } -static inline int reiser4_find_next_zero_bit(void * addr, int maxoffset, int offset) +static inline int reiser4_find_next_zero_bit(void *addr, int maxoffset, + int offset) { int off = OFF(addr); - return ext2_find_next_zero_bit(BASE(addr), maxoffset + off, offset + off) - off; + return ext2_find_next_zero_bit(BASE(addr), maxoffset + off, + offset + off) - off; } #else @@ -220,11 +214,11 @@ ext2_find_next_zero_bit(addr, maxoffset, /* Search for a set bit in the bit array [@start_offset, @max_offset[, offsets * are counted from @addr, return the offset of the first bit if it is found, * @maxoffset otherwise. */ -static bmap_off_t __reiser4_find_next_set_bit( - void *addr, bmap_off_t max_offset, bmap_off_t start_offset) +static bmap_off_t __reiser4_find_next_set_bit(void *addr, bmap_off_t max_offset, + bmap_off_t start_offset) { ulong_t *base = addr; - /* start_offset is in bits, convert it to byte offset within bitmap. */ + /* start_offset is in bits, convert it to byte offset within bitmap. */ int word_nr = start_offset >> LONG_INT_SHIFT; /* bit number within the byte. */ int bit_nr = start_offset & LONG_INT_MASK; @@ -259,12 +253,13 @@ static bmap_off_t __reiser4_find_next_se #if BITS_PER_LONG == 64 -static bmap_off_t reiser4_find_next_set_bit( - void *addr, bmap_off_t max_offset, bmap_off_t start_offset) +static bmap_off_t reiser4_find_next_set_bit(void *addr, bmap_off_t max_offset, + bmap_off_t start_offset) { bmap_off_t off = OFF(addr); - return __reiser4_find_next_set_bit(BASE(addr), max_offset + off, start_offset + off) - off; + return __reiser4_find_next_set_bit(BASE(addr), max_offset + off, + start_offset + off) - off; } #else @@ -273,13 +268,13 @@ static bmap_off_t reiser4_find_next_set_ #endif /* search for the first set bit in single word. */ -static int find_last_set_bit_in_word (ulong_t word, int start_bit) +static int find_last_set_bit_in_word(ulong_t word, int start_bit) { ulong_t bit_mask; int nr = start_bit; - assert ("zam-965", start_bit < BITS_PER_LONG); - assert ("zam-966", start_bit >= 0); + assert("zam-965", start_bit < BITS_PER_LONG); + assert("zam-966", start_bit >= 0); bit_mask = (1UL << nr); @@ -287,7 +282,7 @@ static int find_last_set_bit_in_word (ul if (bit_mask & word) return nr; bit_mask >>= 1; - nr --; + nr--; } return BITS_PER_LONG; } @@ -303,16 +298,17 @@ static int find_last_set_bit_in_word (ul * @return: 0 - set bit was found, -1 otherwise. */ static int -reiser4_find_last_set_bit (bmap_off_t * result, void * addr, bmap_off_t low_off, bmap_off_t high_off) +reiser4_find_last_set_bit(bmap_off_t * result, void *addr, bmap_off_t low_off, + bmap_off_t high_off) { - ulong_t * base = addr; + ulong_t *base = addr; int last_word; int first_word; int last_bit; int nr; - assert ("zam-961", high_off >= 0); - assert ("zam-962", high_off >= low_off); + assert("zam-961", high_off >= 0); + assert("zam-962", high_off >= low_off); last_word = high_off >> LONG_INT_SHIFT; last_bit = high_off & LONG_INT_MASK; @@ -324,16 +320,18 @@ reiser4_find_last_set_bit (bmap_off_t * *result = (last_word << LONG_INT_SHIFT) + nr; return 0; } - -- last_word; + --last_word; } while (last_word >= first_word) { if (base[last_word] != 0x0) { - last_bit = find_last_set_bit_in_word(base[last_word], BITS_PER_LONG - 1); - assert ("zam-972", last_bit < BITS_PER_LONG); + last_bit = + find_last_set_bit_in_word(base[last_word], + BITS_PER_LONG - 1); + assert("zam-972", last_bit < BITS_PER_LONG); *result = (last_word << LONG_INT_SHIFT) + last_bit; return 0; } - -- last_word; + --last_word; } return -1; /* set bit not found */ @@ -342,9 +340,10 @@ reiser4_find_last_set_bit (bmap_off_t * /* Search bitmap for a clear bit in backward direction from the end to the * beginning of given region */ static int -reiser4_find_last_zero_bit (bmap_off_t * result, void * addr, bmap_off_t low_off, bmap_off_t high_off) +reiser4_find_last_zero_bit(bmap_off_t * result, void *addr, bmap_off_t low_off, + bmap_off_t high_off) { - ulong_t * base = addr; + ulong_t *base = addr; int last_word; int first_word; int last_bit; @@ -357,26 +356,26 @@ reiser4_find_last_zero_bit (bmap_off_t * if (last_bit < BITS_PER_LONG) { nr = find_last_set_bit_in_word(~base[last_word], last_bit); if (nr < BITS_PER_LONG) { - *result = (last_word << LONG_INT_SHIFT) + nr; - return 0; + *result = (last_word << LONG_INT_SHIFT) + nr; + return 0; } - -- last_word; + --last_word; } while (last_word >= first_word) { - if (base[last_word] != (ulong_t)(-1)) { - *result = (last_word << LONG_INT_SHIFT) + - find_last_set_bit_in_word(~base[last_word], BITS_PER_LONG - 1); + if (base[last_word] != (ulong_t) (-1)) { + *result = (last_word << LONG_INT_SHIFT) + + find_last_set_bit_in_word(~base[last_word], + BITS_PER_LONG - 1); return 0; } - -- last_word; + --last_word; } - return -1; /* zero bit not found */ + return -1; /* zero bit not found */ } /* Audited by: green(2002.06.12) */ -static void -reiser4_clear_bits(char *addr, bmap_off_t start, bmap_off_t end) +static void reiser4_clear_bits(char *addr, bmap_off_t start, bmap_off_t end) { int first_byte; int last_byte; @@ -390,7 +389,8 @@ reiser4_clear_bits(char *addr, bmap_off_ last_byte = (end - 1) >> 3; if (last_byte > first_byte + 1) - memset(addr + first_byte + 1, 0, (size_t) (last_byte - first_byte - 1)); + memset(addr + first_byte + 1, 0, + (size_t) (last_byte - first_byte - 1)); first_byte_mask >>= 8 - (start & 0x7); last_byte_mask <<= ((end - 1) & 0x7) + 1; @@ -405,8 +405,7 @@ reiser4_clear_bits(char *addr, bmap_off_ /* Audited by: green(2002.06.12) */ /* ZAM-FIXME-HANS: comment this */ -static void -reiser4_set_bits(char *addr, bmap_off_t start, bmap_off_t end) +static void reiser4_set_bits(char *addr, bmap_off_t start, bmap_off_t end) { int first_byte; int last_byte; @@ -420,7 +419,8 @@ reiser4_set_bits(char *addr, bmap_off_t last_byte = (end - 1) >> 3; if (last_byte > first_byte + 1) - memset(addr + first_byte + 1, 0xFF, (size_t) (last_byte - first_byte - 1)); + memset(addr + first_byte + 1, 0xFF, + (size_t) (last_byte - first_byte - 1)); first_byte_mask <<= start & 0x7; last_byte_mask >>= 7 - ((end - 1) & 0x7); @@ -464,8 +464,7 @@ reiser4_set_bits(char *addr, bmap_off_t The above comment applies only to the reiser4_adler32 function. */ -reiser4_internal __u32 -reiser4_adler32(char *data, __u32 len) +__u32 reiser4_adler32(char *data, __u32 len) { unsigned char *t = data; __u32 s1 = 1; @@ -490,23 +489,22 @@ reiser4_adler32(char *data, __u32 len) #define sb_by_bnode(bnode) \ ((struct super_block *)jnode_get_tree(bnode->wjnode)->super) -static __u32 -bnode_calc_crc(const struct bitmap_node *bnode, unsigned long size) +static __u32 bnode_calc_crc(const struct bitmap_node *bnode, unsigned long size) { return reiser4_adler32(bnode_commit_data(bnode), bmap_size(size)); } - static int bnode_check_adler32(const struct bitmap_node *bnode, unsigned long size) { - if (bnode_calc_crc(bnode, size) != bnode_commit_crc (bnode)) { + if (bnode_calc_crc(bnode, size) != bnode_commit_crc(bnode)) { bmap_nr_t bmap; bmap = bnode - get_bnode(sb_by_bnode(bnode), 0); warning("vpf-263", - "Checksum for the bitmap block %llu is incorrect",bmap); + "Checksum for the bitmap block %llu is incorrect", + bmap); return RETERR(-EIO); } @@ -517,8 +515,7 @@ bnode_check_adler32(const struct bitmap_ #define REISER4_CHECK_BMAP_CRC (0) #if REISER4_CHECK_BMAP_CRC -static int -bnode_check_crc(const struct bitmap_node *bnode) +static int bnode_check_crc(const struct bitmap_node *bnode) { return bnode_check_adler32(bnode, bmap_size(sb_by_bnode(bnode)->s_blocksize)); @@ -541,7 +538,8 @@ bnode_check_crc(const struct bitmap_node */ static __u32 -adler32_recalc(__u32 adler, unsigned char old_data, unsigned char data, __u32 tail) +adler32_recalc(__u32 adler, unsigned char old_data, unsigned char data, + __u32 tail) { __u32 delta = data - old_data + 2 * ADLER_BASE; __u32 s1 = adler & 0xffff; @@ -553,33 +551,59 @@ adler32_recalc(__u32 adler, unsigned cha return (s2 << 16) | s1; } - #define LIMIT(val, boundary) ((val) > (boundary) ? (boundary) : (val)) -/* A number of bitmap blocks for given fs. This number can be stored on disk - or calculated on fly; it depends on disk format. -VS-FIXME-HANS: explain calculation, using device with block count of 8 * 4096 blocks as an example. - FIXME-VS: number of blocks in a filesystem is taken from reiser4 - super private data */ -/* Audited by: green(2002.06.12) */ -static bmap_nr_t -get_nr_bmap(const struct super_block *super) +/** + * get_nr_bitmap - calculate number of bitmap blocks + * @super: super block with initialized blocksize and block count + * + * Calculates number of bitmap blocks of a filesystem which uses bitmaps to + * maintain free disk space. It assumes that each bitmap addresses the same + * number of blocks which is calculated by bmap_block_count macro defined in + * above. Number of blocks in the filesystem has to be initialized in reiser4 + * private data of super block already so that it can be obtained via + * reiser4_block_count(). Unfortunately, number of blocks addressed by a bitmap + * is not power of 2 because 4 bytes are used for checksum. Therefore, we have + * to use special function to divide and modulo 64bits filesystem block + * counters. + * + * Example: suppose filesystem have 32768 blocks. Blocksize is 4096. Each bitmap + * block addresses (4096 - 4) * 8 = 32736 blocks. Number of bitmaps to address + * all 32768 blocks is calculated as (32768 - 1) / 32736 + 1 = 2. + */ +static bmap_nr_t get_nr_bmap(const struct super_block *super) { assert("zam-393", reiser4_block_count(super) != 0); + unsigned long long quotient; - return div64_32(reiser4_block_count(super) - 1, bmap_bit_count(super->s_blocksize), NULL) + 1; - + quotient = reiser4_block_count(super) - 1; + __div64_32("ient, bmap_bit_count(super->s_blocksize)); + return quotient + 1; } -/* calculate bitmap block number and offset within that bitmap block */ +/** + * parse_blocknr - calculate bitmap number and offset in it by block number + * @block: pointer to block number to calculate location in bitmap of + * @bmap: pointer where to store bitmap block number + * @offset: pointer where to store offset within bitmap block + * + * Calculates location of bit which is responsible for allocation/freeing of + * block @*block. That location is represented by bitmap block number and offset + * within that bitmap block. + */ static void -parse_blocknr(const reiser4_block_nr * block, bmap_nr_t * bmap, bmap_off_t * offset) +parse_blocknr(const reiser4_block_nr *block, bmap_nr_t *bmap, + bmap_off_t *offset) { struct super_block *super = get_current_context()->super; + unsigned long long quotient; - *bmap = div64_32(*block, bmap_bit_count(super->s_blocksize), offset); + quotient = *block; + *offset = __div64_32("ient, bmap_bit_count(super->s_blocksize)); + *bmap = quotient; assert("zam-433", *bmap < get_nr_bmap(super)); + assert("", *offset < bmap_bit_count(super->s_blocksize)); } #if REISER4_DEBUG @@ -602,8 +626,7 @@ check_block_range(const reiser4_block_nr } } -static void -check_bnode_loaded(const struct bitmap_node *bnode) +static void check_bnode_loaded(const struct bitmap_node *bnode) { assert("zam-485", bnode != NULL); assert("zam-483", jnode_page(bnode->wjnode) != NULL); @@ -641,7 +664,8 @@ adjust_first_zero_bit(struct bitmap_node /* Audited by: green(2002.06.12) */ static void -get_bitmap_blocknr(struct super_block *super, bmap_nr_t bmap, reiser4_block_nr * bnr) +get_bitmap_blocknr(struct super_block *super, bmap_nr_t bmap, + reiser4_block_nr * bnr) { assert("zam-390", bmap < get_nr_bmap(super)); @@ -649,8 +673,8 @@ get_bitmap_blocknr(struct super_block *s #ifdef CONFIG_REISER4_BADBLOCKS #define BITMAP_PLUGIN_DISKMAP_ID ((0xc0e1<<16) | (0xe0ff)) /* Check if the diskmap have this already, first. */ - if ( reiser4_get_diskmap_value( BITMAP_PLUGIN_DISKMAP_ID, bmap, bnr) == 0 ) - return; /* Found it in diskmap */ + if (reiser4_get_diskmap_value(BITMAP_PLUGIN_DISKMAP_ID, bmap, bnr) == 0) + return; /* Found it in diskmap */ #endif /* FIXME_ZAM: before discussing of disk layouts and disk format plugins I implement bitmap location scheme which is close to scheme @@ -664,10 +688,11 @@ get_bitmap_blocknr(struct super_block *s /* construct a fake block number for shadow bitmap (WORKING BITMAP) block */ /* Audited by: green(2002.06.12) */ -static void -get_working_bitmap_blocknr(bmap_nr_t bmap, reiser4_block_nr * bnr) +static void get_working_bitmap_blocknr(bmap_nr_t bmap, reiser4_block_nr * bnr) { - *bnr = (reiser4_block_nr) ((bmap & ~REISER4_BLOCKNR_STATUS_BIT_MASK) | REISER4_BITMAP_BLOCKS_STATUS_VALUE); + *bnr = + (reiser4_block_nr) ((bmap & ~REISER4_BLOCKNR_STATUS_BIT_MASK) | + REISER4_BITMAP_BLOCKS_STATUS_VALUE); } /* bnode structure initialization */ @@ -675,14 +700,13 @@ static void init_bnode(struct bitmap_node *bnode, struct super_block *super UNUSED_ARG, bmap_nr_t bmap UNUSED_ARG) { - memset(bnode, 0, sizeof (struct bitmap_node)); + memset(bnode, 0, sizeof(struct bitmap_node)); sema_init(&bnode->sema, 1); atomic_set(&bnode->loaded, 0); } -static void -release(jnode *node) +static void release(jnode * node) { jrelse(node); JF_SET(node, JNODE_HEARD_BANSHEE); @@ -691,8 +715,7 @@ release(jnode *node) /* This function is for internal bitmap.c use because it assumes that jnode is in under full control of this thread */ -static void -done_bnode(struct bitmap_node *bnode) +static void done_bnode(struct bitmap_node *bnode) { if (bnode) { atomic_set(&bnode->loaded, 0); @@ -706,7 +729,8 @@ done_bnode(struct bitmap_node *bnode) /* ZAM-FIXME-HANS: comment this. Called only by load_and_lock_bnode()*/ static int -prepare_bnode(struct bitmap_node *bnode, jnode **cjnode_ret, jnode **wjnode_ret) +prepare_bnode(struct bitmap_node *bnode, jnode ** cjnode_ret, + jnode ** wjnode_ret) { struct super_block *super; jnode *cjnode; @@ -750,7 +774,7 @@ prepare_bnode(struct bitmap_node *bnode, return 0; - error: + error: jput(cjnode); jput(wjnode); *wjnode_ret = *cjnode_ret = NULL; @@ -759,7 +783,8 @@ prepare_bnode(struct bitmap_node *bnode, } /* Check the bnode data on read. */ -static int check_struct_bnode(struct bitmap_node *bnode, __u32 blksize) { +static int check_struct_bnode(struct bitmap_node *bnode, __u32 blksize) +{ void *data; int ret; @@ -784,8 +809,7 @@ static int check_struct_bnode(struct bit } /* load bitmap blocks "on-demand" */ -static int -load_and_lock_bnode(struct bitmap_node *bnode) +static int load_and_lock_bnode(struct bitmap_node *bnode) { int ret; @@ -837,16 +861,19 @@ load_and_lock_bnode(struct bitmap_node * check_bnode_loaded(bnode); } - if (wjnode != NULL) + if (wjnode != NULL) { release(wjnode); - if (cjnode != NULL) + bnode->wjnode = NULL; + } + if (cjnode != NULL) { release(cjnode); + bnode->cjnode = NULL; + } return ret; } -static void -release_and_unlock_bnode(struct bitmap_node *bnode) +static void release_and_unlock_bnode(struct bitmap_node *bnode) { check_bnode_loaded(bnode); up(&bnode->sema); @@ -859,8 +886,8 @@ release_and_unlock_bnode(struct bitmap_n have it in v4.x */ /* ZAM-FIXME-HANS: do you mean search one bitmap block forward? */ static int -search_one_bitmap_forward(bmap_nr_t bmap, bmap_off_t * offset, bmap_off_t max_offset, - int min_len, int max_len) +search_one_bitmap_forward(bmap_nr_t bmap, bmap_off_t * offset, + bmap_off_t max_offset, int min_len, int max_len) { struct super_block *super = get_current_context()->super; struct bitmap_node *bnode = get_bnode(super, bmap); @@ -895,7 +922,8 @@ search_one_bitmap_forward(bmap_nr_t bmap while (start + min_len < max_offset) { - start = reiser4_find_next_zero_bit((long *) data, max_offset, start); + start = + reiser4_find_next_zero_bit((long *)data, max_offset, start); if (set_first_zero_bit) { bnode->first_zero_bit = start; set_first_zero_bit = 0; @@ -904,7 +932,8 @@ search_one_bitmap_forward(bmap_nr_t bmap break; search_end = LIMIT(start + max_len, max_offset); - end = reiser4_find_next_set_bit((long *) data, search_end, start); + end = + reiser4_find_next_set_bit((long *)data, search_end, start); if (end >= start + min_len) { /* we can't trust find_next_set_bit result if set bit was not fount, result may be bigger than @@ -932,8 +961,8 @@ search_one_bitmap_forward(bmap_nr_t bmap } static int -search_one_bitmap_backward (bmap_nr_t bmap, bmap_off_t * start_offset, bmap_off_t end_offset, - int min_len, int max_len) +search_one_bitmap_backward(bmap_nr_t bmap, bmap_off_t * start_offset, + bmap_off_t end_offset, int min_len, int max_len) { struct super_block *super = get_current_context()->super; struct bitmap_node *bnode = get_bnode(super, bmap); @@ -973,14 +1002,16 @@ search_one_bitmap_backward (bmap_nr_t bm if (reiser4_find_last_set_bit(&end, data, search_end, start)) end = search_end; else - end ++; + end++; if (end + min_len <= start + 1) { if (end < search_end) end = search_end; ret = start - end + 1; - *start_offset = end; /* `end' is lowest offset */ - assert ("zam-987", reiser4_find_next_set_bit(data, start + 1, end) >= start + 1); + *start_offset = end; /* `end' is lowest offset */ + assert("zam-987", + reiser4_find_next_set_bit(data, start + 1, + end) >= start + 1); reiser4_set_bits(data, end, start + 1); break; } @@ -996,8 +1027,9 @@ search_one_bitmap_backward (bmap_nr_t bm } /* allocate contiguous range of blocks in bitmap */ -static int bitmap_alloc_forward(reiser4_block_nr * start, const reiser4_block_nr * end, - int min_len, int max_len) +static int bitmap_alloc_forward(reiser4_block_nr * start, + const reiser4_block_nr * end, int min_len, + int max_len) { bmap_nr_t bmap, end_bmap; bmap_off_t offset, end_offset; @@ -1018,21 +1050,26 @@ static int bitmap_alloc_forward(reiser4_ assert("zam-359", ergo(end_bmap == bmap, end_offset > offset)); for (; bmap < end_bmap; bmap++, offset = 0) { - len = search_one_bitmap_forward(bmap, &offset, max_offset, min_len, max_len); + len = + search_one_bitmap_forward(bmap, &offset, max_offset, + min_len, max_len); if (len != 0) goto out; } - len = search_one_bitmap_forward(bmap, &offset, end_offset, min_len, max_len); -out: + len = + search_one_bitmap_forward(bmap, &offset, end_offset, min_len, + max_len); + out: *start = bmap * max_offset + offset; return len; } /* allocate contiguous range of blocks in bitmap (from @start to @end in * backward direction) */ -static int bitmap_alloc_backward(reiser4_block_nr * start, const reiser4_block_nr * end, - int min_len, int max_len) +static int bitmap_alloc_backward(reiser4_block_nr * start, + const reiser4_block_nr * end, int min_len, + int max_len) { bmap_nr_t bmap, end_bmap; bmap_off_t offset, end_offset; @@ -1046,14 +1083,18 @@ static int bitmap_alloc_backward(reiser4 assert("zam-961", end_bmap <= bmap); assert("zam-962", ergo(end_bmap == bmap, end_offset <= offset)); - for (; bmap > end_bmap; bmap --, offset = max_offset - 1) { - len = search_one_bitmap_backward(bmap, &offset, 0, min_len, max_len); + for (; bmap > end_bmap; bmap--, offset = max_offset - 1) { + len = + search_one_bitmap_backward(bmap, &offset, 0, min_len, + max_len); if (len != 0) goto out; } - len = search_one_bitmap_backward(bmap, &offset, end_offset, min_len, max_len); - out: + len = + search_one_bitmap_backward(bmap, &offset, end_offset, min_len, + max_len); + out: *start = bmap * max_offset + offset; return len; } @@ -1076,22 +1117,26 @@ alloc_blocks_forward(reiser4_blocknr_hin if (hint->max_dist == 0) search_end = reiser4_block_count(super); else - search_end = LIMIT(hint->blk + hint->max_dist, reiser4_block_count(super)); + search_end = + LIMIT(hint->blk + hint->max_dist, + reiser4_block_count(super)); /* We use @hint -> blk as a search start and search from it to the end of the disk or in given region if @hint -> max_dist is not zero */ search_start = hint->blk; - actual_len = bitmap_alloc_forward(&search_start, &search_end, 1, needed); + actual_len = + bitmap_alloc_forward(&search_start, &search_end, 1, needed); /* There is only one bitmap search if max_dist was specified or first pass was from the beginning of the bitmap. We also do one pass for scanning bitmap in backward direction. */ - if (!(actual_len != 0 || hint->max_dist != 0 || search_start == 0)) { + if (!(actual_len != 0 || hint->max_dist != 0 || search_start == 0)) { /* next step is a scanning from 0 to search_start */ search_end = search_start; search_start = 0; - actual_len = bitmap_alloc_forward(&search_start, &search_end, 1, needed); + actual_len = + bitmap_alloc_forward(&search_start, &search_end, 1, needed); } if (actual_len == 0) return RETERR(-ENOSPC); @@ -1102,18 +1147,19 @@ alloc_blocks_forward(reiser4_blocknr_hin return 0; } -static int alloc_blocks_backward (reiser4_blocknr_hint * hint, int needed, - reiser4_block_nr * start, reiser4_block_nr * len) +static int alloc_blocks_backward(reiser4_blocknr_hint * hint, int needed, + reiser4_block_nr * start, + reiser4_block_nr * len) { reiser4_block_nr search_start; reiser4_block_nr search_end; int actual_len; - ON_DEBUG(struct super_block * super = reiser4_get_current_sb()); + ON_DEBUG(struct super_block *super = reiser4_get_current_sb()); - assert ("zam-969", super != NULL); - assert ("zam-970", hint != NULL); - assert ("zam-971", hint->blk < reiser4_block_count(super)); + assert("zam-969", super != NULL); + assert("zam-970", hint != NULL); + assert("zam-971", hint->blk < reiser4_block_count(super)); search_start = hint->blk; if (hint->max_dist == 0 || search_start <= hint->max_dist) @@ -1121,7 +1167,8 @@ static int alloc_blocks_backward (reiser else search_end = search_start - hint->max_dist; - actual_len = bitmap_alloc_backward(&search_start, &search_end, 1, needed); + actual_len = + bitmap_alloc_backward(&search_start, &search_end, 1, needed); if (actual_len == 0) return RETERR(-ENOSPC); if (actual_len < 0) @@ -1132,10 +1179,10 @@ static int alloc_blocks_backward (reiser } /* plugin->u.space_allocator.alloc_blocks() */ -reiser4_internal int +int alloc_blocks_bitmap(reiser4_space_allocator * allocator UNUSED_ARG, - reiser4_blocknr_hint * hint, int needed, - reiser4_block_nr * start, reiser4_block_nr * len) + reiser4_blocknr_hint * hint, int needed, + reiser4_block_nr * start, reiser4_block_nr * len) { if (hint->backward) return alloc_blocks_backward(hint, needed, start, len); @@ -1147,8 +1194,9 @@ alloc_blocks_bitmap(reiser4_space_alloca nodes deletion is deferred until transaction commit. However, deallocation of temporary objects like wandered blocks and transaction commit records requires immediate node deletion from WORKING BITMAP.*/ -reiser4_internal void -dealloc_blocks_bitmap(reiser4_space_allocator * allocator UNUSED_ARG, reiser4_block_nr start, reiser4_block_nr len) +void +dealloc_blocks_bitmap(reiser4_space_allocator * allocator UNUSED_ARG, + reiser4_block_nr start, reiser4_block_nr len) { struct super_block *super = reiser4_get_current_sb(); @@ -1172,17 +1220,18 @@ dealloc_blocks_bitmap(reiser4_space_allo ret = load_and_lock_bnode(bnode); assert("zam-481", ret == 0); - reiser4_clear_bits(bnode_working_data(bnode), offset, (bmap_off_t) (offset + len)); + reiser4_clear_bits(bnode_working_data(bnode), offset, + (bmap_off_t) (offset + len)); adjust_first_zero_bit(bnode, offset); release_and_unlock_bnode(bnode); } - /* plugin->u.space_allocator.check_blocks(). */ -reiser4_internal void -check_blocks_bitmap(const reiser4_block_nr * start, const reiser4_block_nr * len, int desired) +void +check_blocks_bitmap(const reiser4_block_nr * start, + const reiser4_block_nr * len, int desired) { #if REISER4_DEBUG struct super_block *super = reiser4_get_current_sb(); @@ -1211,10 +1260,14 @@ check_blocks_bitmap(const reiser4_block_ assert("nikita-2216", jnode_is_loaded(bnode->wjnode)); if (desired) { - assert("zam-623", reiser4_find_next_zero_bit(bnode_working_data(bnode), end_offset, start_offset) + assert("zam-623", + reiser4_find_next_zero_bit(bnode_working_data(bnode), + end_offset, start_offset) >= end_offset); } else { - assert("zam-624", reiser4_find_next_set_bit(bnode_working_data(bnode), end_offset, start_offset) + assert("zam-624", + reiser4_find_next_set_bit(bnode_working_data(bnode), + end_offset, start_offset) >= end_offset); } @@ -1223,8 +1276,7 @@ check_blocks_bitmap(const reiser4_block_ } /* conditional insertion of @node into atom's overwrite set if it was not there */ -static void -cond_add_to_overwrite_set (txn_atom * atom, jnode * node) +static void cond_add_to_overwrite_set(txn_atom * atom, jnode * node) { assert("zam-546", atom != NULL); assert("zam-547", atom->stage == ASTAGE_PRE_COMMIT); @@ -1247,7 +1299,8 @@ cond_add_to_overwrite_set (txn_atom * at /* an actor which applies delete set to COMMIT bitmap pages and link modified pages in a single-linked list */ static int -apply_dset_to_commit_bmap(txn_atom * atom, const reiser4_block_nr * start, const reiser4_block_nr * len, void *data) +apply_dset_to_commit_bmap(txn_atom * atom, const reiser4_block_nr * start, + const reiser4_block_nr * len, void *data) { bmap_nr_t bmap; @@ -1272,13 +1325,13 @@ apply_dset_to_commit_bmap(txn_atom * ato assert("zam-448", bnode != NULL); /* it is safe to unlock atom with is in ASTAGE_PRE_COMMIT */ - assert ("zam-767", atom->stage == ASTAGE_PRE_COMMIT); + assert("zam-767", atom->stage == ASTAGE_PRE_COMMIT); ret = load_and_lock_bnode(bnode); if (ret) return ret; /* put bnode into atom's overwrite set */ - cond_add_to_overwrite_set (atom, bnode->cjnode); + cond_add_to_overwrite_set(atom, bnode->cjnode); data = bnode_commit_data(bnode); @@ -1288,7 +1341,8 @@ apply_dset_to_commit_bmap(txn_atom * ato if (len != NULL) { /* FIXME-ZAM: a check that all bits are set should be there */ - assert("zam-443", offset + *len <= bmap_bit_count(sb->s_blocksize)); + assert("zam-443", + offset + *len <= bmap_bit_count(sb->s_blocksize)); reiser4_clear_bits(data, offset, (bmap_off_t) (offset + *len)); (*blocks_freed_p) += *len; @@ -1316,21 +1370,18 @@ apply_dset_to_commit_bmap(txn_atom * ato extern spinlock_t scan_lock; -reiser4_internal int -pre_commit_hook_bitmap(void) +int pre_commit_hook_bitmap(void) { - struct super_block * super = reiser4_get_current_sb(); + struct super_block *super = reiser4_get_current_sb(); txn_atom *atom; long long blocks_freed = 0; - atom = get_current_atom_locked (); + atom = get_current_atom_locked(); BUG_ON(atom->stage != ASTAGE_PRE_COMMIT); - assert ("zam-876", atom->stage == ASTAGE_PRE_COMMIT); + assert("zam-876", atom->stage == ASTAGE_PRE_COMMIT); spin_unlock_atom(atom); - - { /* scan atom's captured list and find all freshly allocated nodes, * mark corresponded bits in COMMIT BITMAP as used */ /* how cpu significant is this scan, should we someday have a freshly_allocated list? -Hans */ @@ -1360,7 +1411,8 @@ pre_commit_hook_bitmap(void) __u32 crc; assert("zam-559", !JF_ISSET(node, JNODE_OVRWR)); - assert("zam-460", !blocknr_is_fake(&node->blocknr)); + assert("zam-460", + !blocknr_is_fake(&node->blocknr)); parse_blocknr(&node->blocknr, &bmap, &offset); bn = get_bnode(super, bmap); @@ -1382,8 +1434,7 @@ pre_commit_hook_bitmap(void) *(bnode_commit_data(bn) + index), size - index), - - bnode_set_commit_crc(bn, crc); + bnode_set_commit_crc(bn, crc); release_and_unlock_bnode(bn); @@ -1395,7 +1446,7 @@ pre_commit_hook_bitmap(void) new j-node into clean list, because we are scanning the same list now. It is OK, if insertion is done to the list front */ - cond_add_to_overwrite_set (atom, bn->cjnode); + cond_add_to_overwrite_set(atom, bn->cjnode); } spin_lock(&scan_lock); @@ -1405,7 +1456,8 @@ pre_commit_hook_bitmap(void) spin_unlock(&scan_lock); } - blocknr_set_iterator(atom, &atom->delete_set, apply_dset_to_commit_bmap, &blocks_freed, 0); + blocknr_set_iterator(atom, &atom->delete_set, apply_dset_to_commit_bmap, + &blocks_freed, 0); blocks_freed -= atom->nr_blocks_allocated; @@ -1422,26 +1474,25 @@ pre_commit_hook_bitmap(void) return 0; } -#else /* ! REISER4_COPY_ON_CAPTURE */ +#else /* ! REISER4_COPY_ON_CAPTURE */ -reiser4_internal int -pre_commit_hook_bitmap(void) +int pre_commit_hook_bitmap(void) { - struct super_block * super = reiser4_get_current_sb(); + struct super_block *super = reiser4_get_current_sb(); txn_atom *atom; long long blocks_freed = 0; - atom = get_current_atom_locked (); - assert ("zam-876", atom->stage == ASTAGE_PRE_COMMIT); + atom = get_current_atom_locked(); + assert("zam-876", atom->stage == ASTAGE_PRE_COMMIT); spin_unlock_atom(atom); { /* scan atom's captured list and find all freshly allocated nodes, * mark corresponded bits in COMMIT BITMAP as used */ - capture_list_head *head = ATOM_CLEAN_LIST(atom); - jnode *node = capture_list_front(head); + struct list_head *head = ATOM_CLEAN_LIST(atom); + jnode *node = list_entry(head->next, jnode, capture_link); - while (!capture_list_end(head, node)) { + while (head != &node->capture_link) { /* we detect freshly allocated jnodes */ if (JF_ISSET(node, JNODE_RELOC)) { int ret; @@ -1455,7 +1506,8 @@ pre_commit_hook_bitmap(void) char byte; assert("zam-559", !JF_ISSET(node, JNODE_OVRWR)); - assert("zam-460", !blocknr_is_fake(&node->blocknr)); + assert("zam-460", + !blocknr_is_fake(&node->blocknr)); parse_blocknr(&node->blocknr, &bmap, &offset); bn = get_bnode(super, bmap); @@ -1477,8 +1529,7 @@ pre_commit_hook_bitmap(void) *(bnode_commit_data(bn) + index), size - index), - - bnode_set_commit_crc(bn, crc); + bnode_set_commit_crc(bn, crc); release_and_unlock_bnode(bn); @@ -1490,14 +1541,15 @@ pre_commit_hook_bitmap(void) new j-node into clean list, because we are scanning the same list now. It is OK, if insertion is done to the list front */ - cond_add_to_overwrite_set (atom, bn->cjnode); + cond_add_to_overwrite_set(atom, bn->cjnode); } - node = capture_list_next(node); + node = list_entry(node->capture_link.next, jnode, capture_link); } } - blocknr_set_iterator(atom, &atom->delete_set, apply_dset_to_commit_bmap, &blocks_freed, 0); + blocknr_set_iterator(atom, &atom->delete_set, apply_dset_to_commit_bmap, + &blocks_freed, 0); blocks_freed -= atom->nr_blocks_allocated; @@ -1513,12 +1565,13 @@ pre_commit_hook_bitmap(void) return 0; } -#endif /* ! REISER4_COPY_ON_CAPTURE */ +#endif /* ! REISER4_COPY_ON_CAPTURE */ /* plugin->u.space_allocator.init_allocator constructor of reiser4_space_allocator object. It is called on fs mount */ -reiser4_internal int -init_allocator_bitmap(reiser4_space_allocator * allocator, struct super_block *super, void *arg UNUSED_ARG) +int +init_allocator_bitmap(reiser4_space_allocator * allocator, + struct super_block *super, void *arg UNUSED_ARG) { struct bitmap_allocator_data *data = NULL; bmap_nr_t bitmap_blocks_nr; @@ -1527,7 +1580,8 @@ init_allocator_bitmap(reiser4_space_allo assert("nikita-3039", schedulable()); /* getting memory for bitmap allocator private data holder */ - data = reiser4_kmalloc(sizeof (struct bitmap_allocator_data), GFP_KERNEL); + data = + kmalloc(sizeof(struct bitmap_allocator_data), GFP_KERNEL); if (data == NULL) return RETERR(-ENOMEM); @@ -1542,10 +1596,10 @@ init_allocator_bitmap(reiser4_space_allo with that storage device, much less reiser4. ;-) -Hans). Kmalloc is not possible and, probably, another dynamic data structure should replace a static array of bnodes. */ - /*data->bitmap = reiser4_kmalloc((size_t) (sizeof (struct bitmap_node) * bitmap_blocks_nr), GFP_KERNEL);*/ - data->bitmap = vmalloc(sizeof (struct bitmap_node) * bitmap_blocks_nr); + /*data->bitmap = reiser4_kmalloc((size_t) (sizeof (struct bitmap_node) * bitmap_blocks_nr), GFP_KERNEL); */ + data->bitmap = vmalloc(sizeof(struct bitmap_node) * bitmap_blocks_nr); if (data->bitmap == NULL) { - reiser4_kfree(data); + kfree(data); return RETERR(-ENOMEM); } @@ -1559,9 +1613,10 @@ init_allocator_bitmap(reiser4_space_allo #endif /* Load all bitmap blocks at mount time. */ - if (!test_bit(REISER4_DONT_LOAD_BITMAP, &get_super_private(super)->fs_flags)) { + if (!test_bit + (REISER4_DONT_LOAD_BITMAP, &get_super_private(super)->fs_flags)) { __u64 start_time, elapsed_time; - struct bitmap_node * bnode; + struct bitmap_node *bnode; int ret; if (REISER4_DEBUG) @@ -1589,8 +1644,9 @@ init_allocator_bitmap(reiser4_space_allo /* plugin->u.space_allocator.destroy_allocator destructor. It is called on fs unmount */ -reiser4_internal int -destroy_allocator_bitmap(reiser4_space_allocator * allocator, struct super_block *super) +int +destroy_allocator_bitmap(reiser4_space_allocator * allocator, + struct super_block *super) { bmap_nr_t bitmap_blocks_nr; bmap_nr_t i; @@ -1625,9 +1681,8 @@ destroy_allocator_bitmap(reiser4_space_a up(&bnode->sema); } - /*reiser4_kfree(data->bitmap);*/ vfree(data->bitmap); - reiser4_kfree(data); + kfree(data); allocator->u.generic = NULL; diff -puN fs/reiser4/plugin/space/bitmap.h~reiser4-big-update fs/reiser4/plugin/space/bitmap.h --- devel/fs/reiser4/plugin/space/bitmap.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/space/bitmap.h 2005-09-15 19:51:08.000000000 -0700 @@ -11,13 +11,19 @@ /* EDWARD-FIXME-HANS: write something as informative as the below for every .h file lacking it. */ /* declarations of functions implementing methods of space allocator plugin for bitmap based allocator. The functions themselves are in bitmap.c */ -extern int init_allocator_bitmap(reiser4_space_allocator *, struct super_block *, void *); -extern int destroy_allocator_bitmap(reiser4_space_allocator *, struct super_block *); +extern int init_allocator_bitmap(reiser4_space_allocator *, + struct super_block *, void *); +extern int destroy_allocator_bitmap(reiser4_space_allocator *, + struct super_block *); extern int alloc_blocks_bitmap(reiser4_space_allocator *, - reiser4_blocknr_hint *, int needed, reiser4_block_nr * start, reiser4_block_nr * len); -extern void check_blocks_bitmap(const reiser4_block_nr *, const reiser4_block_nr *, int); + reiser4_blocknr_hint *, int needed, + reiser4_block_nr * start, + reiser4_block_nr * len); +extern void check_blocks_bitmap(const reiser4_block_nr *, + const reiser4_block_nr *, int); -extern void dealloc_blocks_bitmap(reiser4_space_allocator *, reiser4_block_nr, reiser4_block_nr); +extern void dealloc_blocks_bitmap(reiser4_space_allocator *, reiser4_block_nr, + reiser4_block_nr); extern int pre_commit_hook_bitmap(void); #define post_commit_hook_bitmap() do{}while(0) @@ -27,6 +33,8 @@ extern int pre_commit_hook_bitmap(void); typedef __u64 bmap_nr_t; typedef __u32 bmap_off_t; +extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor); + #endif /* __REISER4_PLUGIN_SPACE_BITMAP_H__ */ /* Make Linus happy. diff -L fs/reiser4/plugin/symlink.c -puN fs/reiser4/plugin/symlink.c~reiser4-big-update /dev/null --- devel/fs/reiser4/plugin/symlink.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,85 +0,0 @@ -/* Copyright 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */ - -#include "../forward.h" -#include "../debug.h" -#include "item/static_stat.h" -#include "plugin.h" -#include "../tree.h" -#include "../vfs_ops.h" -#include "../inode.h" -#include "object.h" - -#include -#include /* for struct inode */ - -/* symlink plugin's specific functions */ - -reiser4_internal int -create_symlink(struct inode *symlink, /* inode of symlink */ - struct inode *dir UNUSED_ARG, /* parent directory */ - reiser4_object_create_data * data /* info passed - * to us, this - * is filled by - * reiser4() - * syscall in - * particular */ ) -{ - int result; - - assert("nikita-680", symlink != NULL); - assert("nikita-681", S_ISLNK(symlink->i_mode)); - assert("nikita-685", inode_get_flag(symlink, REISER4_NO_SD)); - assert("nikita-682", dir != NULL); - assert("nikita-684", data != NULL); - assert("nikita-686", data->id == SYMLINK_FILE_PLUGIN_ID); - - /* - * stat data of symlink has symlink extension in which we store - * symlink content, that is, path symlink is pointing to. - */ - reiser4_inode_data(symlink)->extmask |= (1 << SYMLINK_STAT); - - assert("vs-838", symlink->u.generic_ip == 0); - symlink->u.generic_ip = (void *) data->name; - - assert("vs-843", symlink->i_size == 0); - INODE_SET_FIELD(symlink, i_size, strlen(data->name)); - - /* insert stat data appended with data->name */ - result = write_sd_by_inode_common(symlink); - if (result) { - /* FIXME-VS: Make sure that symlink->u.generic_ip is not attached - to kmalloced data */ - INODE_SET_FIELD(symlink, i_size, 0); - } else { - assert("vs-849", symlink->u.generic_ip && inode_get_flag(symlink, REISER4_GENERIC_PTR_USED)); - assert("vs-850", !memcmp((char *) symlink->u.generic_ip, data->name, (size_t) symlink->i_size + 1)); - } - return result; -} - -/* plugin->destroy_inode() */ -reiser4_internal void -destroy_inode_symlink(struct inode * inode) -{ - assert("edward-799", inode_file_plugin(inode) == file_plugin_by_id(SYMLINK_FILE_PLUGIN_ID)); - assert("edward-800", !is_bad_inode(inode) && is_inode_loaded(inode)); - assert("edward-801", inode_get_flag(inode, REISER4_GENERIC_PTR_USED)); - assert("vs-839", S_ISLNK(inode->i_mode)); - - reiser4_kfree_in_sb(inode->u.generic_ip, inode->i_sb); - inode->u.generic_ip = 0; - inode_clr_flag(inode, REISER4_GENERIC_PTR_USED); -} - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - scroll-step: 1 - End: -*/ - diff -L fs/reiser4/plugin/symlink.h -puN fs/reiser4/plugin/symlink.h~reiser4-big-update /dev/null --- devel/fs/reiser4/plugin/symlink.h +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,24 +0,0 @@ -/* Copyright 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */ - -#if !defined( __REISER4_SYMLINK_H__ ) -#define __REISER4_SYMLINK_H__ - -#include "../forward.h" -#include /* for struct inode */ - -int create_symlink(struct inode *symlink, struct inode *dir, reiser4_object_create_data * data); -void destroy_inode_symlink(struct inode * inode); - -/* __REISER4_SYMLINK_H__ */ -#endif - -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - scroll-step: 1 - End: -*/ diff -puN fs/reiser4/plugin/tail_policy.c~reiser4-big-update fs/reiser4/plugin/tail_policy.c --- devel/fs/reiser4/plugin/tail_policy.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/plugin/tail_policy.c 2005-09-15 19:51:08.000000000 -0700 @@ -1,21 +1,17 @@ /* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by * reiser4/README */ -/* Tail policy plugins */ +/* Formatting policy plugins */ -/* Tail policy is used by object plugin (of regular file) to convert file - between two representations. TO BE CONTINUED. -NIKITA-FIXME-HANS: the "TO BE CONTINUED" means what? -GREV-FIXME-HANS: why the references to tails above? fix comments and website.... tail implies it is less than the whole file that is formatted, and it is not.... not in v4.... - - Currently following policies are implemented: - - never tail - - always tail - - only tail if file is smaller than 4 blocks (default). -*/ +/* + * Formatting policy plugin is used by object plugin (of regular file) to + * convert file between two representations. + * + * Currently following policies are implemented: + * never store file in formatted nodes + * always store file in formatted nodes + * store file in formatted nodes if file is smaller than 4 blocks (default) + */ #include "../tree.h" #include "../inode.h" @@ -24,16 +20,22 @@ GREV-FIXME-HANS: why the references to t #include "plugin.h" #include "node/node.h" #include "plugin_header.h" -#include "../lib.h" #include #include /* For struct inode */ +/** + * have_formatting_never - + * @inode: + * @size: + * + * + */ /* Never store file's tail as direct item */ /* Audited by: green(2002.06.12) */ -static int -have_formatting_never(const struct inode *inode UNUSED_ARG /* inode to operate on */ , - loff_t size UNUSED_ARG /* new object size */ ) +static int have_formatting_never(const struct inode *inode UNUSED_ARG + /* inode to operate on */ , + loff_t size UNUSED_ARG /* new object size */ ) { return 0; } @@ -41,8 +43,9 @@ have_formatting_never(const struct inode /* Always store file's tail as direct item */ /* Audited by: green(2002.06.12) */ static int -have_formatting_always(const struct inode *inode UNUSED_ARG /* inode to operate on */ , - loff_t size UNUSED_ARG /* new object size */ ) +have_formatting_always(const struct inode *inode UNUSED_ARG + /* inode to operate on */ , + loff_t size UNUSED_ARG /* new object size */ ) { return 1; } @@ -50,8 +53,9 @@ have_formatting_always(const struct inod /* This function makes test if we should store file denoted @inode as tails only or as extents only. */ static int -have_formatting_default(const struct inode *inode UNUSED_ARG /* inode to operate on */ , - loff_t size /* new object size */ ) +have_formatting_default(const struct inode *inode UNUSED_ARG + /* inode to operate on */ , + loff_t size /* new object size */ ) { assert("umka-1253", inode != NULL); @@ -70,7 +74,7 @@ formatting_plugin formatting_plugins[LAS .pops = NULL, .label = "never", .desc = "Never store file's tail", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .have_tail = have_formatting_never }, @@ -80,8 +84,8 @@ formatting_plugin formatting_plugins[LAS .id = ALWAYS_TAILS_FORMATTING_ID, .pops = NULL, .label = "always", - .desc = "Always store file's tail", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .desc = "Always store file's tail", + .linkage = {NULL, NULL} }, .have_tail = have_formatting_always }, @@ -92,18 +96,18 @@ formatting_plugin formatting_plugins[LAS .pops = NULL, .label = "4blocks", .desc = "store files shorter than 4 blocks in tail items", - .linkage = TYPE_SAFE_LIST_LINK_ZERO + .linkage = {NULL, NULL} }, .have_tail = have_formatting_default } }; -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - End: -*/ +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 79 + * End: + */ diff -puN fs/reiser4/pool.c~reiser4-big-update fs/reiser4/pool.c --- devel/fs/reiser4/pool.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/pool.c 2005-09-15 19:51:08.000000000 -0700 @@ -51,22 +51,20 @@ #include #include -/* initialise new pool object */ -static void -reiser4_init_pool_obj(reiser4_pool_header * h /* pool object to - * initialise */ ) -{ - pool_usage_list_clean(h); - pool_level_list_clean(h); - pool_extra_list_clean(h); -} - -/* initialise new pool */ -reiser4_internal void -reiser4_init_pool(reiser4_pool * pool /* pool to initialise */ , - size_t obj_size /* size of objects in @pool */ , - int num_of_objs /* number of preallocated objects */ , - char *data /* area for preallocated objects */ ) +/* initialize new pool object */ +static void reiser4_init_pool_obj(reiser4_pool_header * h /* pool object to + * initialize */ ) +{ + INIT_LIST_HEAD(&h->usage_linkage); + INIT_LIST_HEAD(&h->level_linkage); + INIT_LIST_HEAD(&h->extra_linkage); +} + +/* initialize new pool */ +void reiser4_init_pool(reiser4_pool * pool /* pool to initialize */ , + size_t obj_size /* size of objects in @pool */ , + int num_of_objs /* number of preallocated objects */ , + char *data /* area for preallocated objects */ ) { reiser4_pool_header *h; int i; @@ -79,14 +77,15 @@ reiser4_init_pool(reiser4_pool * pool /* memset(pool, 0, sizeof *pool); pool->obj_size = obj_size; pool->data = data; - pool_usage_list_init(&pool->free); - pool_usage_list_init(&pool->used); - pool_extra_list_init(&pool->extra); + INIT_LIST_HEAD(&pool->free); + INIT_LIST_HEAD(&pool->used); + INIT_LIST_HEAD(&pool->extra); memset(data, 0, obj_size * num_of_objs); for (i = 0; i < num_of_objs; ++i) { h = (reiser4_pool_header *) (data + i * obj_size); reiser4_init_pool_obj(h); - pool_usage_list_push_back(&pool->free, h); + /* add pool header to the end of pool's free list */ + list_add_tail(&h->usage_linkage, &pool->free); } } @@ -96,8 +95,7 @@ reiser4_init_pool(reiser4_pool * pool /* allocated objects. */ -reiser4_internal void -reiser4_done_pool(reiser4_pool * pool UNUSED_ARG /* pool to destroy */ ) +void reiser4_done_pool(reiser4_pool * pool UNUSED_ARG /* pool to destroy */ ) { } @@ -107,54 +105,63 @@ reiser4_done_pool(reiser4_pool * pool UN allocation. */ -static void * -reiser4_pool_alloc(reiser4_pool * pool /* pool to allocate object - * from */ ) +static void *reiser4_pool_alloc(reiser4_pool * pool /* pool to allocate object + * from */ ) { reiser4_pool_header *result; assert("nikita-959", pool != NULL); - if (!pool_usage_list_empty(&pool->free)) { - result = pool_usage_list_pop_front(&pool->free); - pool_usage_list_clean(result); - assert("nikita-965", pool_extra_list_is_clean(result)); + if (!list_empty(&pool->free)) { + struct list_head *linkage; + + linkage = pool->free.next; + list_del(linkage); + INIT_LIST_HEAD(linkage); + result = list_entry(linkage, reiser4_pool_header, usage_linkage); + BUG_ON(!list_empty(&result->level_linkage) || + !list_empty(&result->extra_linkage)); } else { /* pool is empty. Extra allocations don't deserve dedicated slab to be served from, as they are expected to be rare. */ - result = reiser4_kmalloc(pool->obj_size, GFP_KERNEL); + result = kmalloc(pool->obj_size, GFP_KERNEL); if (result != 0) { reiser4_init_pool_obj(result); - pool_extra_list_push_front(&pool->extra, result); + list_add(&result->extra_linkage, &pool->extra); } else return ERR_PTR(RETERR(-ENOMEM)); + BUG_ON(!list_empty(&result->usage_linkage) || + !list_empty(&result->level_linkage)); } ++pool->objs; - pool_level_list_clean(result); - pool_usage_list_push_front(&pool->used, result); + list_add(&result->usage_linkage, &pool->used); memset(result + 1, 0, pool->obj_size - sizeof *result); return result; } /* return object back to the pool */ -reiser4_internal void -reiser4_pool_free(reiser4_pool * pool, - reiser4_pool_header * h /* pool to return object back - * into */ ) +void reiser4_pool_free(reiser4_pool * pool, reiser4_pool_header * h /* pool to return object back + * into */ ) { assert("nikita-961", h != NULL); assert("nikita-962", pool != NULL); - -- pool->objs; + --pool->objs; assert("nikita-963", pool->objs >= 0); - pool_usage_list_remove_clean(h); - pool_level_list_remove_clean(h); - if (pool_extra_list_is_clean(h)) - pool_usage_list_push_front(&pool->free, h); + list_del_init(&h->usage_linkage); + list_del_init(&h->level_linkage); + + if (list_empty(&h->extra_linkage)) + /* + * pool header is not an extra one. Push it onto free list + * using usage_linkage + */ + list_add(&h->usage_linkage, &pool->free); else { - pool_extra_list_remove_clean(h); - reiser4_kfree(h); + /* remove pool header from pool's extra list and kfree it */ + list_del(&h->extra_linkage); + kfree(h); } } @@ -174,17 +181,16 @@ reiser4_pool_free(reiser4_pool * pool, (that is "right" node). */ -reiser4_internal reiser4_pool_header * -add_obj(reiser4_pool * pool /* pool from which to - * allocate new object */ , - pool_level_list_head * list /* list where to add - * object */ , - pool_ordering order /* where to add */ , - reiser4_pool_header * reference /* after (or - * before) which - * existing - * object to - * add */ ) +reiser4_pool_header *add_obj(reiser4_pool * pool /* pool from which to + * allocate new object */ , + struct list_head *list, /* list where to add + * object */ + pool_ordering order /* where to add */ , + reiser4_pool_header * reference /* after (or + * before) which + * existing + * object to + * add */ ) { reiser4_pool_header *result; @@ -198,16 +204,20 @@ add_obj(reiser4_pool * pool /* pool from switch (order) { case POOLO_BEFORE: - pool_level_list_insert_before(reference, result); + __list_add(&result->level_linkage, + reference->level_linkage.prev, + &reference->level_linkage); break; case POOLO_AFTER: - pool_level_list_insert_after(reference, result); + __list_add(&result->level_linkage, + &reference->level_linkage, + reference->level_linkage.next); break; case POOLO_LAST: - pool_level_list_push_back(list, result); + list_add_tail(&result->level_linkage, list); break; case POOLO_FIRST: - pool_level_list_push_front(list, result); + list_add(&result->level_linkage, list); break; default: wrong_return_value("nikita-927", "order"); diff -puN fs/reiser4/pool.h~reiser4-big-update fs/reiser4/pool.h --- devel/fs/reiser4/pool.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/pool.h 2005-09-15 19:51:08.000000000 -0700 @@ -5,32 +5,22 @@ #ifndef __REISER4_POOL_H__ #define __REISER4_POOL_H__ -#include "type_safe_list.h" #include -/* each pool object is either on a "used" or "free" list. */ -TYPE_SAFE_LIST_DECLARE(pool_usage); - -/* list of extra pool objects */ -TYPE_SAFE_LIST_DECLARE(pool_extra); - -/* list of pool objects on a given level */ -TYPE_SAFE_LIST_DECLARE(pool_level); - typedef struct reiser4_pool { size_t obj_size; int objs; char *data; - pool_usage_list_head free; - pool_usage_list_head used; - pool_extra_list_head extra; + struct list_head free; + struct list_head used; + struct list_head extra; } reiser4_pool; typedef struct reiser4_pool_header { /* object is either on free or "used" lists */ - pool_usage_list_link usage_linkage; - pool_level_list_link level_linkage; - pool_extra_list_link extra_linkage; + struct list_head usage_linkage; + struct list_head level_linkage; + struct list_head extra_linkage; } reiser4_pool_header; typedef enum { @@ -40,20 +30,15 @@ typedef enum { POOLO_FIRST } pool_ordering; -/* each pool object is either on a "used" or "free" list. */ -TYPE_SAFE_LIST_DEFINE(pool_usage, reiser4_pool_header, usage_linkage); -/* list of extra pool objects */ -TYPE_SAFE_LIST_DEFINE(pool_extra, reiser4_pool_header, extra_linkage); -/* list of pool objects on a given level */ -TYPE_SAFE_LIST_DEFINE(pool_level, reiser4_pool_header, level_linkage); - /* pool manipulation functions */ -extern void reiser4_init_pool(reiser4_pool * pool, size_t obj_size, int num_of_objs, char *data); +extern void reiser4_init_pool(reiser4_pool * pool, size_t obj_size, + int num_of_objs, char *data); extern void reiser4_done_pool(reiser4_pool * pool); extern void reiser4_pool_free(reiser4_pool * pool, reiser4_pool_header * h); -reiser4_pool_header *add_obj(reiser4_pool * pool, pool_level_list_head * list, - pool_ordering order, reiser4_pool_header * reference); +reiser4_pool_header *add_obj(reiser4_pool * pool, struct list_head * list, + pool_ordering order, + reiser4_pool_header * reference); /* __REISER4_POOL_H__ */ #endif diff -puN fs/reiser4/readahead.c~reiser4-big-update fs/reiser4/readahead.c --- devel/fs/reiser4/readahead.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/readahead.c 2005-09-15 19:51:08.000000000 -0700 @@ -9,9 +9,9 @@ #include "key.h" #include "znode.h" -#include /* for totalram_pages */ +#include /* for totalram_pages */ -reiser4_internal void init_ra_info(ra_info_t * rai) +void init_ra_info(ra_info_t * rai) { rai->key_to_stop = *min_key(); } @@ -24,8 +24,7 @@ static inline int ra_adjacent_only(int f /* this is used by formatted_readahead to decide whether read for right neighbor of node is to be issued. It returns 1 if right neighbor's first key is less or equal to readahead's stop key */ -static int -should_readahead_neighbor(znode *node, ra_info_t *info) +static int should_readahead_neighbor(znode * node, ra_info_t * info) { return (UNDER_RW(dk, ZJNODE(node)->tree, read, keyle(znode_get_rd_key(node), &info->key_to_stop))); @@ -33,8 +32,7 @@ should_readahead_neighbor(znode *node, r #define LOW_MEM_PERCENTAGE (5) -static int -low_on_memory(void) +static int low_on_memory(void) { unsigned int freepages; @@ -43,8 +41,7 @@ low_on_memory(void) } /* start read for @node and for a few of its right neighbors */ -reiser4_internal void -formatted_readahead(znode *node, ra_info_t *info) +void formatted_readahead(znode * node, ra_info_t * info) { ra_params_t *ra_params; znode *cur; @@ -82,7 +79,8 @@ formatted_readahead(znode *node, ra_info if (!should_readahead_neighbor(cur, info)) break; - if (reiser4_get_right_neighbor(&next_lh, cur, ZNODE_READ_LOCK, grn_flags)) + if (reiser4_get_right_neighbor + (&next_lh, cur, ZNODE_READ_LOCK, grn_flags)) break; if (JF_ISSET(ZJNODE(next_lh.node), JNODE_EFLUSH)) { @@ -93,7 +91,8 @@ formatted_readahead(znode *node, ra_info nextblk = znode_get_block(next_lh.node); if (blocknr_is_fake(nextblk) || - (ra_adjacent_only(ra_params->flags) && *nextblk != *znode_get_block(cur) + 1)) { + (ra_adjacent_only(ra_params->flags) + && *nextblk != *znode_get_block(cur) + 1)) { break; } @@ -107,7 +106,7 @@ formatted_readahead(znode *node, ra_info * allocated (and i/o already started). */ break; - i ++; + i++; } zput(cur); done_lh(&next_lh); @@ -125,36 +124,43 @@ static inline loff_t get_min_readahead(s return VM_MIN_READAHEAD * 1024; } - /* Start read for the given window. */ -static loff_t do_reiser4_file_readahead (struct inode * inode, loff_t offset, loff_t size) +static loff_t do_reiser4_file_readahead(struct inode *inode, loff_t offset, + loff_t size) { - reiser4_tree * tree = current_tree; - reiser4_inode * object; - reiser4_key start_key; - reiser4_key stop_key; - - lock_handle lock; - lock_handle next_lock; - - coord_t coord; - tap_t tap; - + reiser4_tree *tree = current_tree; + reiser4_inode *object; loff_t result; + reiser4_key *start_key; + reiser4_key *stop_key; + lock_handle *lock; + lock_handle *next_lock; + coord_t *coord; + tap_t *tap; assert("zam-994", lock_stack_isclean(get_current_lock_stack())); + start_key = kmalloc(2 * sizeof(reiser4_key) + 2 * sizeof(lock_handle) + + sizeof(coord_t) + sizeof(tap_t), GFP_KERNEL); + if (start_key == NULL) + return RETERR(-ENOMEM); + stop_key = start_key + 1; + lock = (lock_handle *) (stop_key + 1); + next_lock = lock + 1; + coord = (coord_t *) (next_lock + 1); + tap = (tap_t *) (coord + 1); + object = reiser4_inode_data(inode); - key_by_inode_unix_file(inode, offset, &start_key); - key_by_inode_unix_file(inode, offset + size, &stop_key); + key_by_inode_and_offset_common(inode, offset, start_key); + key_by_inode_and_offset_common(inode, offset + size, stop_key); - init_lh(&lock); - init_lh(&next_lock); + init_lh(lock); + init_lh(next_lock); /* Stop on twig level */ - result = coord_by_key( - current_tree, &start_key, &coord, &lock, ZNODE_READ_LOCK, - FIND_EXACT, TWIG_LEVEL, TWIG_LEVEL, 0, NULL); + result = + coord_by_key(current_tree, start_key, coord, lock, ZNODE_READ_LOCK, + FIND_EXACT, TWIG_LEVEL, TWIG_LEVEL, 0, NULL); if (result < 0) goto error; if (result != CBK_COORD_FOUND) { @@ -162,31 +168,30 @@ static loff_t do_reiser4_file_readahead goto error; } - tap_init(&tap, &coord, &lock, ZNODE_WRITE_LOCK); - result = tap_load(&tap); + tap_init(tap, coord, lock, ZNODE_WRITE_LOCK); + result = tap_load(tap); if (result) goto error0; /* Advance coord to right (even across node boundaries) while coord key * less than stop_key. */ while (1) { - reiser4_key key; - znode * child; + znode *child; reiser4_block_nr blk; /* Currently this read-ahead is for formatted nodes only */ - if (!item_is_internal(&coord)) + if (!item_is_internal(coord)) break; - item_key_by_coord(&coord, &key); - if (keyge(&key, &stop_key)) + item_key_by_coord(coord, start_key); + if (keyge(start_key, stop_key)) break; - result = item_utmost_child_real_block(&coord, LEFT_SIDE, &blk); + result = item_utmost_child_real_block(coord, LEFT_SIDE, &blk); if (result || blk == 0) break; - child = zget(tree, &blk, lock.node, LEAF_LEVEL, GFP_KERNEL); + child = zget(tree, &blk, lock->node, LEAF_LEVEL, GFP_KERNEL); if (IS_ERR(child)) { result = PTR_ERR(child); @@ -205,47 +210,50 @@ static loff_t do_reiser4_file_readahead zput(child); /* Advance coord by one unit ... */ - result = coord_next_unit(&coord); + result = coord_next_unit(coord); if (result == 0) continue; /* ... and continue on the right neighbor if needed. */ - result = reiser4_get_right_neighbor ( - &next_lock, lock.node, ZNODE_READ_LOCK, - GN_CAN_USE_UPPER_LEVELS); + result = + reiser4_get_right_neighbor(next_lock, lock->node, + ZNODE_READ_LOCK, + GN_CAN_USE_UPPER_LEVELS); if (result) break; - if (znode_page(next_lock.node) == NULL) { + if (znode_page(next_lock->node) == NULL) { loff_t end_offset; - result = jstartio(ZJNODE(next_lock.node)); + result = jstartio(ZJNODE(next_lock->node)); if (result) break; read_lock_dk(tree); - end_offset = get_key_offset(znode_get_ld_key(next_lock.node)); + end_offset = + get_key_offset(znode_get_ld_key(next_lock->node)); read_unlock_dk(tree); result = end_offset - offset; break; } - result = tap_move(&tap, &next_lock); + result = tap_move(tap, next_lock); if (result) break; - done_lh(&next_lock); - coord_init_first_unit(&coord, lock.node); + done_lh(next_lock); + coord_init_first_unit(coord, lock->node); } - if (! result || result == -E_NO_NEIGHBOR) + if (!result || result == -E_NO_NEIGHBOR) result = size; - error0: - tap_done(&tap); - error: - done_lh(&lock); - done_lh(&next_lock); + error0: + tap_done(tap); + error: + done_lh(lock); + done_lh(next_lock); + kfree(start_key); return result; } @@ -253,18 +261,18 @@ typedef unsigned long long int ull_t; #define PRINTK(...) noop /* This is derived from the linux original read-ahead code (mm/readahead.c), and * cannot be licensed from Namesys in its current state. */ -int reiser4_file_readahead (struct file * file, loff_t offset, size_t size) +int reiser4_file_readahead(struct file *file, loff_t offset, size_t size) { loff_t min; loff_t max; loff_t orig_next_size; loff_t actual; - struct reiser4_file_ra_state * ra; - struct inode * inode = file->f_dentry->d_inode; + struct reiser4_file_ra_state *ra; + struct inode *inode = file->f_dentry->d_inode; - assert ("zam-995", inode != NULL); + assert("zam-995", inode != NULL); - PRINTK ("R/A REQ: off=%llu, size=%llu\n", (ull_t)offset, (ull_t)size); + PRINTK("R/A REQ: off=%llu, size=%llu\n", (ull_t) offset, (ull_t) size); ra = &reiser4_get_file_fsdata(file)->ra1; max = get_max_readahead(ra); @@ -296,10 +304,10 @@ int reiser4_file_readahead (struct file * by 2 * size of read request. This makes r/a window smaller * for small unordered requests and larger for big read * requests. */ - ra->next_size += -2 * PAGE_CACHE_SIZE + 2 * size ; + ra->next_size += -2 * PAGE_CACHE_SIZE + 2 * size; if (ra->next_size < 0) ra->next_size = 0; -do_io: + do_io: ra->start = offset; ra->size = size + orig_next_size; actual = do_reiser4_file_readahead(inode, offset, ra->size); @@ -309,13 +317,15 @@ do_io: ra->ahead_start = ra->start + ra->size; ra->ahead_size = ra->next_size; - actual = do_reiser4_file_readahead(inode, ra->ahead_start, ra->ahead_size); + actual = + do_reiser4_file_readahead(inode, ra->ahead_start, + ra->ahead_size); if (actual > 0) ra->ahead_size = actual; - PRINTK ("R/A MISS: cur = [%llu, +%llu[, ahead = [%llu, +%llu[\n", - (ull_t)ra->start, (ull_t)ra->size, - (ull_t)ra->ahead_start, (ull_t)ra->ahead_size); + PRINTK("R/A MISS: cur = [%llu, +%llu[, ahead = [%llu, +%llu[\n", + (ull_t) ra->start, (ull_t) ra->size, + (ull_t) ra->ahead_start, (ull_t) ra->ahead_size); } else { /* R/A hit. */ @@ -332,25 +342,26 @@ do_io: ra->ahead_start = ra->start + ra->size; ra->ahead_size = ra->next_size; - actual = do_reiser4_file_readahead( - inode, ra->ahead_start, ra->ahead_size); + actual = + do_reiser4_file_readahead(inode, ra->ahead_start, + ra->ahead_size); if (actual > 0) { ra->ahead_size = actual; } - PRINTK ("R/A ADVANCE: cur = [%llu, +%llu[, ahead = [%llu, +%llu[\n", - (ull_t)ra->start, (ull_t)ra->size, - (ull_t)ra->ahead_start, (ull_t)ra->ahead_size); + PRINTK + ("R/A ADVANCE: cur = [%llu, +%llu[, ahead = [%llu, +%llu[\n", + (ull_t) ra->start, (ull_t) ra->size, + (ull_t) ra->ahead_start, (ull_t) ra->ahead_size); } } -out: + out: return 0; } -reiser4_internal void -reiser4_readdir_readahead_init(struct inode *dir, tap_t *tap) +void reiser4_readdir_readahead_init(struct inode *dir, tap_t * tap) { reiser4_key *stop_key; diff -puN fs/reiser4/readahead.h~reiser4-big-update fs/reiser4/readahead.h --- devel/fs/reiser4/readahead.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/readahead.h 2005-09-15 19:51:08.000000000 -0700 @@ -6,16 +6,15 @@ #include "key.h" typedef enum { - RA_ADJACENT_ONLY = 1, /* only requests nodes which are adjacent. Default is NO (not only adjacent) */ + RA_ADJACENT_ONLY = 1, /* only requests nodes which are adjacent. Default is NO (not only adjacent) */ } ra_global_flags; /* reiser4 super block has a field of this type. It controls readahead during tree traversals */ typedef struct formatted_read_ahead_params { - unsigned long max; /* request not more than this amount of nodes. Default is totalram_pages / 4 */ + unsigned long max; /* request not more than this amount of nodes. Default is totalram_pages / 4 */ int flags; } ra_params_t; - typedef struct { reiser4_key key_to_stop; } ra_info_t; @@ -24,17 +23,17 @@ void formatted_readahead(znode *, ra_inf void init_ra_info(ra_info_t * rai); struct reiser4_file_ra_state { - loff_t start; /* Current window */ - loff_t size; - loff_t next_size; /* Next window size */ - loff_t ahead_start; /* Ahead window */ - loff_t ahead_size; - loff_t max_window_size; /* Maximum readahead window */ - loff_t slow_start; /* enlarging r/a size algorithm. */ + loff_t start; /* Current window */ + loff_t size; + loff_t next_size; /* Next window size */ + loff_t ahead_start; /* Ahead window */ + loff_t ahead_size; + loff_t max_window_size; /* Maximum readahead window */ + loff_t slow_start; /* enlarging r/a size algorithm. */ }; extern int reiser4_file_readahead(struct file *, loff_t, size_t); -extern void reiser4_readdir_readahead_init(struct inode *dir, tap_t *tap); +extern void reiser4_readdir_readahead_init(struct inode *dir, tap_t * tap); /* __READAHEAD_H__ */ #endif diff -puN fs/reiser4/reiser4.h~reiser4-big-update fs/reiser4/reiser4.h --- devel/fs/reiser4/reiser4.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/reiser4.h 2005-09-15 19:51:08.000000000 -0700 @@ -25,7 +25,6 @@ #define REISER4_DEBUG (0) #endif - #if defined(CONFIG_REISER4_COPY_ON_CAPTURE) /* * Turns on copy-on-capture (COC) optimization. See @@ -57,18 +56,13 @@ #define REISER4_LARGE_KEY (1) /*#define REISER4_LARGE_KEY (0)*/ -/* - * This will be turned on automatically when viewmasks are for - * obvious reasons. - */ -#define ENABLE_REISER4_PSEUDO (0) +/*#define GUESS_EXISTS 1*/ /* * PLEASE update fs/reiser4/kattr.c:show_options() when adding new compilation * option */ - extern const char *REISER4_SUPER_MAGIC_STRING; extern const int REISER4_MAGIC_OFFSET; /* offset to magic string from the * beginning of device */ @@ -103,7 +97,7 @@ extern const int REISER4_MAGIC_OFFSET; / #define REISER4_USE_ENTD (1) /* Using of emergency flush is an option. */ -#define REISER4_USE_EFLUSH (1) +#define REISER4_USE_EFLUSH (0) /* key allocation is Plan-A */ #define REISER4_PLANA_KEY_ALLOCATION (1) @@ -235,7 +229,6 @@ extern const int REISER4_MAGIC_OFFSET; / #define sizeof_array(x) ((int) (sizeof(x) / sizeof(x[0]))) - #define NOT_YET (0) /** Reiser4 specific error codes **/ diff -puN fs/reiser4/safe_link.c~reiser4-big-update fs/reiser4/safe_link.c --- devel/fs/reiser4/safe_link.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/safe_link.c 2005-09-15 19:51:08.000000000 -0700 @@ -58,19 +58,19 @@ * On-disk format of safe-link. */ typedef struct safelink { - reiser4_key sdkey; /* key of stat-data for the file safe-link is - * for */ - d64 size; /* size to which file should be truncated */ + reiser4_key sdkey; /* key of stat-data for the file safe-link is + * for */ + d64 size; /* size to which file should be truncated */ } safelink_t; /* * locality where safe-link items are stored. Next to the objectid of root * directory. */ -static oid_t -safe_link_locality(reiser4_tree *tree) +static oid_t safe_link_locality(reiser4_tree * tree) { - return get_key_objectid(get_super_private(tree->super)->df_plug->root_dir_key(tree->super)) + 1; + return get_key_objectid(get_super_private(tree->super)->df_plug-> + root_dir_key(tree->super)) + 1; } /* @@ -90,9 +90,8 @@ safe_link_locality(reiser4_tree *tree) operations. */ -static reiser4_key * -build_link_key(reiser4_tree *tree, oid_t oid, reiser4_safe_link_t link, - reiser4_key *key) +static reiser4_key *build_link_key(reiser4_tree * tree, oid_t oid, + reiser4_safe_link_t link, reiser4_key * key) { reiser4_key_init(key); set_key_locality(key, safe_link_locality(tree)); @@ -105,38 +104,38 @@ build_link_key(reiser4_tree *tree, oid_t * how much disk space is necessary to insert and remove (in the * error-handling path) safe-link. */ -static __u64 -safe_link_tograb(reiser4_tree *tree) +static __u64 safe_link_tograb(reiser4_tree * tree) { return - /* insert safe link */ - estimate_one_insert_item(tree) + - /* remove safe link */ - estimate_one_item_removal(tree) + - /* drill to the leaf level during insertion */ - 1 + estimate_one_insert_item(tree) + - /* - * possible update of existing safe-link. Actually, if - * safe-link existed already (we failed to remove it), then no - * insertion is necessary, so this term is already "covered", - * but for simplicity let's left it. - */ - 1; + /* insert safe link */ + estimate_one_insert_item(tree) + + /* remove safe link */ + estimate_one_item_removal(tree) + + /* drill to the leaf level during insertion */ + 1 + estimate_one_insert_item(tree) + + /* + * possible update of existing safe-link. Actually, if + * safe-link existed already (we failed to remove it), then no + * insertion is necessary, so this term is already "covered", + * but for simplicity let's left it. + */ + 1; } /* * grab enough disk space to insert and remove (in the error-handling path) * safe-link. */ -reiser4_internal int safe_link_grab(reiser4_tree *tree, reiser4_ba_flags_t flags) +int safe_link_grab(reiser4_tree * tree, reiser4_ba_flags_t flags) { - int result; + int result; grab_space_enable(); /* The sbinfo->delete semaphore can be taken here. * safe_link_release() should be called before leaving reiser4 * context. */ - result = reiser4_grab_reserved(tree->super, safe_link_tograb(tree), flags); + result = + reiser4_grab_reserved(tree->super, safe_link_tograb(tree), flags); grab_space_enable(); return result; } @@ -144,7 +143,7 @@ reiser4_internal int safe_link_grab(reis /* * release unused disk space reserved by safe_link_grab(). */ -reiser4_internal void safe_link_release(reiser4_tree * tree) +void safe_link_release(reiser4_tree * tree) { reiser4_release_reserved(tree->super); } @@ -152,7 +151,7 @@ reiser4_internal void safe_link_release( /* * insert into tree safe-link for operation @link on inode @inode. */ -reiser4_internal int safe_link_add(struct inode *inode, reiser4_safe_link_t link) +int safe_link_add(struct inode *inode, reiser4_safe_link_t link) { reiser4_key key; safelink_t sl; @@ -184,13 +183,11 @@ reiser4_internal int safe_link_add(struc * remove safe-link corresponding to the operation @link on inode @inode from * the tree. */ -reiser4_internal int -safe_link_del(reiser4_tree *tree, oid_t oid, reiser4_safe_link_t link) +int safe_link_del(reiser4_tree * tree, oid_t oid, reiser4_safe_link_t link) { reiser4_key key; - return kill_black_box(tree, - build_link_key(tree, oid, link, &key)); + return kill_black_box(tree, build_link_key(tree, oid, link, &key)); } /* @@ -198,18 +195,18 @@ safe_link_del(reiser4_tree *tree, oid_t * used to iterate over all safe-links. */ typedef struct { - reiser4_tree *tree; /* internal tree */ - reiser4_key key; /* safe-link key*/ - reiser4_key sdkey; /* key of object stat-data */ - reiser4_safe_link_t link; /* safe-link type */ - oid_t oid; /* object oid */ - __u64 size; /* final size for truncate */ + reiser4_tree *tree; /* internal tree */ + reiser4_key key; /* safe-link key */ + reiser4_key sdkey; /* key of object stat-data */ + reiser4_safe_link_t link; /* safe-link type */ + oid_t oid; /* object oid */ + __u64 size; /* final size for truncate */ } safe_link_context; /* * start iterating over all safe-links. */ -static void safe_link_iter_begin(reiser4_tree *tree, safe_link_context *ctx) +static void safe_link_iter_begin(reiser4_tree * tree, safe_link_context * ctx) { ctx->tree = tree; reiser4_key_init(&ctx->key); @@ -221,13 +218,12 @@ static void safe_link_iter_begin(reiser4 /* * return next safe-link. */ -static int safe_link_iter_next(safe_link_context *ctx) +static int safe_link_iter_next(safe_link_context * ctx) { int result; safelink_t sl; - result = load_black_box(ctx->tree, - &ctx->key, &sl, sizeof sl, 0); + result = load_black_box(ctx->tree, &ctx->key, &sl, sizeof sl, 0); if (result == 0) { ctx->oid = get_key_objectid(&ctx->key); ctx->link = get_key_offset(&ctx->key); @@ -241,16 +237,15 @@ static int safe_link_iter_next(safe_link /* * check are there any more safe-links left in the tree. */ -static int safe_link_iter_finished(safe_link_context *ctx) +static int safe_link_iter_finished(safe_link_context * ctx) { return get_key_locality(&ctx->key) != safe_link_locality(ctx->tree); } - /* * finish safe-link iteration. */ -static void safe_link_iter_end(safe_link_context *ctx) +static void safe_link_iter_end(safe_link_context * ctx) { /* nothing special */ } @@ -259,7 +254,7 @@ static void safe_link_iter_end(safe_link * process single safe-link. */ static int process_safelink(struct super_block *super, reiser4_safe_link_t link, - reiser4_key *sdkey, oid_t oid, __u64 size) + reiser4_key * sdkey, oid_t oid, __u64 size) { struct inode *inode; int result; @@ -298,10 +293,10 @@ static int process_safelink(struct super reiser4_iget_complete(inode); iput(inode); if (result == 0) { - result = safe_link_grab(get_tree(super), - BA_CAN_COMMIT); + result = safe_link_grab(get_tree(super), BA_CAN_COMMIT); if (result == 0) - result = safe_link_del(get_tree(super), oid, link); + result = + safe_link_del(get_tree(super), oid, link); safe_link_release(get_tree(super)); /* * restart transaction: if there was large number of @@ -319,7 +314,7 @@ static int process_safelink(struct super /* * iterate over all safe-links in the file-system processing them one by one. */ -reiser4_internal int process_safelinks(struct super_block *super) +int process_safelinks(struct super_block *super) { safe_link_context ctx; int result; @@ -337,7 +332,8 @@ reiser4_internal int process_safelinks(s } if (result == 0) result = process_safelink(super, ctx.link, - &ctx.sdkey, ctx.oid, ctx.size); + &ctx.sdkey, ctx.oid, + ctx.size); } while (result == 0); safe_link_iter_end(&ctx); return result; diff -puN fs/reiser4/safe_link.h~reiser4-big-update fs/reiser4/safe_link.h --- devel/fs/reiser4/safe_link.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/safe_link.h 2005-09-15 19:51:08.000000000 -0700 @@ -8,8 +8,8 @@ #include "tree.h" -int safe_link_grab(reiser4_tree *tree, reiser4_ba_flags_t flags); -void safe_link_release(reiser4_tree *tree); +int safe_link_grab(reiser4_tree * tree, reiser4_ba_flags_t flags); +void safe_link_release(reiser4_tree * tree); int safe_link_add(struct inode *inode, reiser4_safe_link_t link); int safe_link_del(reiser4_tree *, oid_t oid, reiser4_safe_link_t link); diff -puN fs/reiser4/seal.c~reiser4-big-update fs/reiser4/seal.c --- devel/fs/reiser4/seal.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/seal.c 2005-09-15 19:51:08.000000000 -0700 @@ -48,11 +48,10 @@ static int seal_matches(const seal_t * s /* initialise seal. This can be called several times on the same seal. @coord and @key can be NULL. */ -reiser4_internal void -seal_init(seal_t * seal /* seal to initialise */ , - const coord_t * coord /* coord @seal will be attached to */ , - const reiser4_key * key UNUSED_ARG /* key @seal will be - * attached to */ ) +void seal_init(seal_t * seal /* seal to initialise */ , + const coord_t * coord /* coord @seal will be attached to */ , + const reiser4_key * key UNUSED_ARG /* key @seal will be + * attached to */ ) { assert("nikita-1886", seal != NULL); memset(seal, 0, sizeof *seal); @@ -69,29 +68,20 @@ seal_init(seal_t * seal /* seal to initi seal->coord1 = *coord; if (key != NULL) seal->key = *key; -#ifdef CONFIG_FRAME_POINTER - seal->bt[0] = __builtin_return_address(0); - seal->bt[1] = __builtin_return_address(1); - seal->bt[2] = __builtin_return_address(2); - seal->bt[3] = __builtin_return_address(3); - seal->bt[4] = __builtin_return_address(4); -#endif #endif spin_unlock_znode(node); } } /* finish with seal */ -reiser4_internal void -seal_done(seal_t * seal /* seal to clear */) +void seal_done(seal_t * seal /* seal to clear */ ) { assert("nikita-1887", seal != NULL); seal->version = 0; } /* true if seal was initialised */ -reiser4_internal int -seal_is_set(const seal_t * seal /* seal to query */ ) +int seal_is_set(const seal_t * seal /* seal to query */ ) { assert("nikita-1890", seal != NULL); return seal->version != 0; @@ -101,29 +91,29 @@ seal_is_set(const seal_t * seal /* seal /* helper function for seal_validate(). It checks that item at @coord has * expected key. This is to detect cases where node was modified but wasn't * marked dirty. */ -static inline int -check_seal_match(const coord_t * coord /* coord to check */, - const reiser4_key * k /* expected key */) +static inline int check_seal_match(const coord_t * coord /* coord to check */ , + const reiser4_key * k /* expected key */ ) { reiser4_key ukey; return (coord->between != AT_UNIT) || - /* FIXME-VS: we only can compare keys for items whose units - represent exactly one key */ - ((coord_is_existing_unit(coord)) && (item_is_extent(coord) || keyeq(k, unit_key_by_coord(coord, &ukey)))) || - ((coord_is_existing_unit(coord)) && (item_is_ctail(coord)) && keyge(k, unit_key_by_coord(coord, &ukey))); + /* FIXME-VS: we only can compare keys for items whose units + represent exactly one key */ + ((coord_is_existing_unit(coord)) + && (item_is_extent(coord) + || keyeq(k, unit_key_by_coord(coord, &ukey)))) + || ((coord_is_existing_unit(coord)) && (item_is_ctail(coord)) + && keyge(k, unit_key_by_coord(coord, &ukey))); } #endif - /* this is used by seal_validate. It accepts return value of * longterm_lock_znode and returns 1 if it can be interpreted as seal * validation failure. For instance, when longterm_lock_znode returns -EINVAL, * seal_validate returns -E_REPEAT and caller will call tre search. We cannot * do this in longterm_lock_znode(), because sometimes we want to distinguish * between -EINVAL and -E_REPEAT. */ -static int -should_repeat(int return_code) +static int should_repeat(int return_code) { return return_code == -EINVAL; } @@ -140,13 +130,12 @@ should_repeat(int return_code) case, but this would complicate callers logic. */ -reiser4_internal int -seal_validate(seal_t * seal /* seal to validate */ , - coord_t * coord /* coord to validate against */ , - const reiser4_key * key /* key to validate against */ , - lock_handle * lh /* resulting lock handle */ , - znode_lock_mode mode /* lock node */ , - znode_lock_request request /* locking priority */ ) +int seal_validate(seal_t * seal /* seal to validate */ , + coord_t * coord /* coord to validate against */ , + const reiser4_key * key /* key to validate against */ , + lock_handle * lh /* resulting lock handle */ , + znode_lock_mode mode /* lock node */ , + znode_lock_request request /* locking priority */ ) { znode *node; int result; @@ -170,8 +159,12 @@ seal_validate(seal_t * seal /* seal to v /* if seal version and znode version coincide */ ON_DEBUG(coord_update_v(coord)); - assert("nikita-1990", node == seal->coord1.node); - assert("nikita-1898", WITH_DATA_RET(coord->node, 1, check_seal_match(coord, key))); + assert("nikita-1990", + node == seal->coord1.node); + assert("nikita-1898", + WITH_DATA_RET(coord->node, 1, + check_seal_match(coord, + key))); } else result = RETERR(-E_REPEAT); } @@ -191,40 +184,22 @@ seal_validate(seal_t * seal /* seal to v /* helpers functions */ /* obtain reference to znode seal points to, if in cache */ -static znode * -seal_node(const seal_t * seal /* seal to query */ ) +static znode *seal_node(const seal_t * seal /* seal to query */ ) { assert("nikita-1891", seal != NULL); return zlook(current_tree, &seal->block); } /* true if @seal version and @node version coincide */ -static int -seal_matches(const seal_t * seal /* seal to check */ , - znode * node /* node to check */ ) +static int seal_matches(const seal_t * seal /* seal to check */ , + znode * node /* node to check */ ) { assert("nikita-1991", seal != NULL); assert("nikita-1993", node != NULL); - return UNDER_SPIN(jnode, ZJNODE(node), (seal->version == node->version)); -} - -#ifdef REISER4_DEBUG_OUTPUT -/* debugging function: print human readable form of @seal. */ -reiser4_internal void -print_seal(const char *prefix, const seal_t * seal) -{ - if (seal == NULL) { - printk("%s: null seal\n", prefix); - } else { - printk("%s: version: %llu, block: %llu\n", prefix, seal->version, seal->block); -#if REISER4_DEBUG - print_key("seal key", &seal->key); - print_coord("seal coord", &seal->coord1, 0); -#endif - } + return UNDER_SPIN(jnode, ZJNODE(node), + (seal->version == node->version)); } -#endif /* Make Linus happy. Local variables: diff -puN fs/reiser4/seal.h~reiser4-big-update fs/reiser4/seal.h --- devel/fs/reiser4/seal.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/seal.h 2005-09-15 19:51:08.000000000 -0700 @@ -25,7 +25,6 @@ typedef struct seal_s { coord_t coord1; /* key this seal is attached to. For debugging. */ reiser4_key key; - void *bt[5]; #endif } seal_t; @@ -36,7 +35,6 @@ extern int seal_validate(seal_t *, coord const reiser4_key *, lock_handle *, znode_lock_mode mode, znode_lock_request request); - /* __SEAL_H__ */ #endif diff -puN fs/reiser4/search.c~reiser4-big-update fs/reiser4/search.c --- devel/fs/reiser4/search.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/search.c 2005-09-15 19:51:08.000000000 -0700 @@ -21,7 +21,7 @@ #include -static const char * bias_name(lookup_bias bias); +static const char *bias_name(lookup_bias bias); /* tree searching algorithm, intranode searching algorithms are in plugin/node/ */ @@ -39,39 +39,37 @@ static const char * bias_name(lookup_bia */ /* Initialise coord cache slot */ -static void -cbk_cache_init_slot(cbk_cache_slot * slot) +static void cbk_cache_init_slot(cbk_cache_slot *slot) { assert("nikita-345", slot != NULL); - cbk_cache_list_clean(slot); + INIT_LIST_HEAD(&slot->lru); slot->node = NULL; } -/* Initialise coord cache */ -reiser4_internal int -cbk_cache_init(cbk_cache * cache /* cache to init */ ) +/* Initialize coord cache */ +int cbk_cache_init(cbk_cache *cache /* cache to init */ ) { int i; assert("nikita-346", cache != NULL); - cache->slot = kmalloc(sizeof (cbk_cache_slot) * cache->nr_slots, GFP_KERNEL); + cache->slot = + kmalloc(sizeof(cbk_cache_slot) * cache->nr_slots, GFP_KERNEL); if (cache->slot == NULL) return RETERR(-ENOMEM); - cbk_cache_list_init(&cache->lru); + INIT_LIST_HEAD(&cache->lru); for (i = 0; i < cache->nr_slots; ++i) { cbk_cache_init_slot(cache->slot + i); - cbk_cache_list_push_back(&cache->lru, cache->slot + i); + list_add_tail(&((cache->slot + i)->lru), &cache->lru); } rw_cbk_cache_init(cache); return 0; } /* free cbk cache data */ -reiser4_internal void -cbk_cache_done(cbk_cache * cache /* cache to release */ ) +void cbk_cache_done(cbk_cache * cache /* cache to release */ ) { assert("nikita-2493", cache != NULL); if (cache->slot != NULL) { @@ -80,16 +78,24 @@ cbk_cache_done(cbk_cache * cache /* cach } } +#if 0 /* macro to iterate over all cbk cache slots */ #define for_all_slots( cache, slot ) \ for( ( slot ) = cbk_cache_list_front( &( cache ) -> lru ) ; \ !cbk_cache_list_end( &( cache ) -> lru, ( slot ) ) ; \ ( slot ) = cbk_cache_list_next( slot ) ) +#endif + +/* macro to iterate over all cbk cache slots */ +#define for_all_slots(cache, slot) \ + for ((slot) = list_entry((cache)->lru.next, cbk_cache_slot, lru); \ + &(cache)->lru != &(slot)->lru; \ + (slot) = list_entry(slot->lru.next, cbk_cache_slot, lru)) + #if REISER4_DEBUG /* this function assures that [cbk-cache-invariant] invariant holds */ -static int -cbk_cache_invariant(const cbk_cache * cache) +static int cbk_cache_invariant(const cbk_cache *cache) { cbk_cache_slot *slot; int result; @@ -114,8 +120,8 @@ cbk_cache_invariant(const cbk_cache * ca /* all cached nodes are different */ scan = slot; while (result) { - scan = cbk_cache_list_next(scan); - if (cbk_cache_list_end(&cache->lru, scan)) + scan = list_entry(scan->lru.next, cbk_cache_slot, lru); + if (&cache->lru == &scan->lru) break; if (slot->node == scan->node) result = 0; @@ -131,9 +137,8 @@ cbk_cache_invariant(const cbk_cache * ca #endif /* Remove references, if any, to @node from coord cache */ -reiser4_internal void -cbk_cache_invalidate(const znode * node /* node to remove from cache */ , - reiser4_tree * tree /* tree to remove node from */ ) +void cbk_cache_invalidate(const znode * node /* node to remove from cache */ , + reiser4_tree * tree /* tree to remove node from */ ) { cbk_cache_slot *slot; cbk_cache *cache; @@ -146,10 +151,10 @@ cbk_cache_invalidate(const znode * node assert("nikita-2470", cbk_cache_invariant(cache)); write_lock_cbk_cache(cache); - for (i = 0, slot = cache->slot; i < cache->nr_slots; ++ i, ++ slot) { + for (i = 0, slot = cache->slot; i < cache->nr_slots; ++i, ++slot) { if (slot->node == node) { - cbk_cache_list_remove(slot); - cbk_cache_list_push_back(&cache->lru, slot); + list_del(&slot->lru); + list_add_tail(&slot->lru, &cache->lru); slot->node = NULL; break; } @@ -160,8 +165,7 @@ cbk_cache_invalidate(const znode * node /* add to the cbk-cache in the "tree" information about "node". This can actually be update of existing slot in a cache. */ -static void -cbk_cache_add(const znode * node /* node to add to the cache */ ) +static void cbk_cache_add(const znode *node /* node to add to the cache */ ) { cbk_cache *cache; cbk_cache_slot *slot; @@ -177,18 +181,18 @@ cbk_cache_add(const znode * node /* node write_lock_cbk_cache(cache); /* find slot to update/add */ - for (i = 0, slot = cache->slot; i < cache->nr_slots; ++ i, ++ slot) { + for (i = 0, slot = cache->slot; i < cache->nr_slots; ++i, ++slot) { /* oops, this node is already in a cache */ if (slot->node == node) break; } /* if all slots are used, reuse least recently used one */ if (i == cache->nr_slots) { - slot = cbk_cache_list_back(&cache->lru); + slot = list_entry(cache->lru.prev, cbk_cache_slot, lru); slot->node = (znode *) node; } - cbk_cache_list_remove(slot); - cbk_cache_list_push_front(&cache->lru, slot); + list_del(&slot->lru); + list_add(&slot->lru, &cache->lru); write_unlock_cbk_cache(cache); assert("nikita-2473", cbk_cache_invariant(cache)); } @@ -203,7 +207,7 @@ static level_lookup_result cbk_node_look /* helper functions */ -static void update_stale_dk(reiser4_tree *tree, znode *node); +static void update_stale_dk(reiser4_tree * tree, znode * node); /* release parent node during traversal */ static void put_parent(cbk_handle * h); @@ -216,19 +220,17 @@ static level_lookup_result search_to_lef /* pack numerous (numberous I should say) arguments of coord_by_key() into * cbk_handle */ -static cbk_handle * -cbk_pack(cbk_handle *handle, - reiser4_tree * tree, - const reiser4_key * key, - coord_t * coord, - lock_handle * active_lh, - lock_handle * parent_lh, - znode_lock_mode lock_mode, - lookup_bias bias, - tree_level lock_level, - tree_level stop_level, - __u32 flags, - ra_info_t *info) +static cbk_handle *cbk_pack(cbk_handle * handle, + reiser4_tree * tree, + const reiser4_key * key, + coord_t * coord, + lock_handle * active_lh, + lock_handle * parent_lh, + znode_lock_mode lock_mode, + lookup_bias bias, + tree_level lock_level, + tree_level stop_level, + __u32 flags, ra_info_t * info) { memset(handle, 0, sizeof *handle); @@ -259,17 +261,16 @@ cbk_pack(cbk_handle *handle, Thread cannot keep any reiser4 locks (tree, znode, dk spin-locks, or znode long term locks) while calling this. */ -reiser4_internal lookup_result -coord_by_key(reiser4_tree * tree /* tree to perform search +lookup_result coord_by_key(reiser4_tree * tree /* tree to perform search * in. Usually this tree is * part of file-system * super-block */ , const reiser4_key * key /* key to look for */ , coord_t * coord /* where to store found - * position in a tree. Fields - * in "coord" are only valid if - * coord_by_key() returned - * "CBK_COORD_FOUND" */ , + * position in a tree. Fields + * in "coord" are only valid if + * coord_by_key() returned + * "CBK_COORD_FOUND" */ , lock_handle * lh, /* resulting lock handle */ znode_lock_mode lock_mode /* type of lookup we * want on node. Pass @@ -291,8 +292,11 @@ coord_by_key(reiser4_tree * tree /* tree * for has to be between * @lock_level and * @stop_level, inclusive */ , - __u32 flags /* search flags */, - ra_info_t *info /* information about desired tree traversal readahead */) + __u32 flags /* search flags */ , + ra_info_t * + info + /* information about desired tree traversal readahead */ + ) { cbk_handle handle; lock_handle parent_lh; @@ -306,7 +310,8 @@ coord_by_key(reiser4_tree * tree /* tree assert("nikita-353", tree != NULL); assert("nikita-354", key != NULL); assert("nikita-355", coord != NULL); - assert("nikita-356", (bias == FIND_EXACT) || (bias == FIND_MAX_NOT_MORE_THAN)); + assert("nikita-356", (bias == FIND_EXACT) + || (bias == FIND_MAX_NOT_MORE_THAN)); assert("nikita-357", stop_level >= LEAF_LEVEL); /* no locks can be held during tree traversal */ assert("nikita-2104", lock_stack_isclean(get_current_lock_stack())); @@ -317,31 +322,25 @@ coord_by_key(reiser4_tree * tree /* tree coord, lh, &parent_lh, - lock_mode, - bias, - lock_level, - stop_level, - flags, - info); + lock_mode, bias, lock_level, stop_level, flags, info); result = coord_by_handle(&handle); - assert("nikita-3247", ergo(!IS_CBKERR(result), coord->node == lh->node)); + assert("nikita-3247", + ergo(!IS_CBKERR(result), coord->node == lh->node)); return result; } /* like coord_by_key(), but starts traversal from vroot of @object rather than * from tree root. */ -reiser4_internal lookup_result -object_lookup(struct inode *object, +lookup_result +object_lookup(struct inode * object, const reiser4_key * key, coord_t * coord, lock_handle * lh, znode_lock_mode lock_mode, lookup_bias bias, tree_level lock_level, - tree_level stop_level, - __u32 flags, - ra_info_t *info) + tree_level stop_level, __u32 flags, ra_info_t * info) { cbk_handle handle; lock_handle parent_lh; @@ -354,7 +353,8 @@ object_lookup(struct inode *object, assert("nikita-354", key != NULL); assert("nikita-355", coord != NULL); - assert("nikita-356", (bias == FIND_EXACT) || (bias == FIND_MAX_NOT_MORE_THAN)); + assert("nikita-356", (bias == FIND_EXACT) + || (bias == FIND_MAX_NOT_MORE_THAN)); assert("nikita-357", stop_level >= LEAF_LEVEL); /* no locks can be held during tree search by key */ assert("nikita-2104", lock_stack_isclean(get_current_lock_stack())); @@ -365,22 +365,17 @@ object_lookup(struct inode *object, coord, lh, &parent_lh, - lock_mode, - bias, - lock_level, - stop_level, - flags, - info); + lock_mode, bias, lock_level, stop_level, flags, info); handle.object = object; result = coord_by_handle(&handle); - assert("nikita-3247", ergo(!IS_CBKERR(result), coord->node == lh->node)); + assert("nikita-3247", + ergo(!IS_CBKERR(result), coord->node == lh->node)); return result; } /* lookup by cbk_handle. Common part of coord_by_key() and object_lookup(). */ -static lookup_result -coord_by_handle(cbk_handle * handle) +static lookup_result coord_by_handle(cbk_handle * handle) { /* * first check cbk_cache (which is look-aside cache for our tree) and @@ -406,16 +401,15 @@ coord_by_handle(cbk_handle * handle) This is used by plugin/dir/hashe_dir.c:find_entry() to move through sequence of entries with identical keys and alikes. */ -reiser4_internal int -iterate_tree(reiser4_tree * tree /* tree to scan */ , - coord_t * coord /* coord to start from */ , - lock_handle * lh /* lock handle to start with and to - * update along the way */ , - tree_iterate_actor_t actor /* function to call on each - * item/unit */ , - void *arg /* argument to pass to @actor */ , - znode_lock_mode mode /* lock mode on scanned nodes */ , - int through_units_p /* call @actor on each item or on each +int iterate_tree(reiser4_tree * tree /* tree to scan */ , + coord_t * coord /* coord to start from */ , + lock_handle * lh /* lock handle to start with and to + * update along the way */ , + tree_iterate_actor_t actor /* function to call on each + * item/unit */ , + void *arg /* argument to pass to @actor */ , + znode_lock_mode mode /* lock mode on scanned nodes */ , + int through_units_p /* call @actor on each item or on each * unit */ ) { int result; @@ -442,8 +436,11 @@ iterate_tree(reiser4_tree * tree /* tree /* move to the next node */ init_lh(&couple); - result = reiser4_get_right_neighbor( - &couple, coord->node, (int) mode, GN_CAN_USE_UPPER_LEVELS); + result = + reiser4_get_right_neighbor(&couple, + coord->node, + (int)mode, + GN_CAN_USE_UPPER_LEVELS); zrelse(coord->node); if (result == 0) { @@ -453,7 +450,8 @@ iterate_tree(reiser4_tree * tree /* tree return result; } - coord_init_first_unit(coord, couple.node); + coord_init_first_unit(coord, + couple.node); done_lh(lh); move_lh(lh, &couple); } else @@ -468,8 +466,8 @@ iterate_tree(reiser4_tree * tree /* tree } /* return locked uber znode for @tree */ -reiser4_internal int get_uber_znode(reiser4_tree * tree, znode_lock_mode mode, - znode_lock_request pri, lock_handle *lh) +int get_uber_znode(reiser4_tree * tree, znode_lock_mode mode, + znode_lock_request pri, lock_handle * lh) { int result; @@ -482,11 +480,11 @@ reiser4_internal int get_uber_znode(reis we are looking for possibly non-unique key and it is item is at the edge of @node. May be it is in the neighbor. */ -static int -znode_contains_key_strict(znode * node /* node to check key - * against */ , - const reiser4_key * key /* key to check */, - int isunique) +static int znode_contains_key_strict(znode * node /* node to check key + * against */ , + const reiser4_key * + key /* key to check */ , + int isunique) { int answer; @@ -550,8 +548,7 @@ znode_contains_key_strict(znode * node / /* * Check whether @node is possible vroot of @object. */ -static void -handle_vroot(struct inode *object, znode *node) +static void handle_vroot(struct inode *object, znode * node) { file_plugin *fplug; coord_t coord; @@ -583,11 +580,10 @@ handle_vroot(struct inode *object, znode * helper function used by traverse tree to start tree traversal not from the * tree root, but from @h->object's vroot, if possible. */ -static int -prepare_object_lookup(cbk_handle * h) +static int prepare_object_lookup(cbk_handle * h) { - znode *vroot; - int result; + znode *vroot; + int result; vroot = inode_get_vroot(h->object); if (vroot == NULL) { @@ -610,17 +606,17 @@ prepare_object_lookup(cbk_handle * h) isunique = h->flags & CBK_UNIQUE; /* check that key is inside vroot */ inside = - UNDER_RW(dk, h->tree, read, - znode_contains_key_strict(vroot, - h->key, - isunique)) && - !ZF_ISSET(vroot, JNODE_HEARD_BANSHEE); + UNDER_RW(dk, h->tree, read, + znode_contains_key_strict(vroot, + h->key, + isunique)) && + !ZF_ISSET(vroot, JNODE_HEARD_BANSHEE); if (inside) { h->result = zload(vroot); if (h->result == 0) { /* search for key in vroot. */ result = cbk_node_lookup(h); - zrelse(vroot);/*h->active_lh->node);*/ + zrelse(vroot); /*h->active_lh->node); */ if (h->active_lh->node != vroot) { result = LOOKUP_REST; } else if (result == LOOKUP_CONT) { @@ -642,8 +638,7 @@ prepare_object_lookup(cbk_handle * h) /* main function that handles common parts of tree traversal: starting (fake znode handling), restarts, error handling, completion */ -static lookup_result -traverse_tree(cbk_handle * h /* search handle */ ) +static lookup_result traverse_tree(cbk_handle * h /* search handle */ ) { int done; int iterations; @@ -653,7 +648,8 @@ traverse_tree(cbk_handle * h /* search h assert("nikita-366", h->tree != NULL); assert("nikita-367", h->key != NULL); assert("nikita-368", h->coord != NULL); - assert("nikita-369", (h->bias == FIND_EXACT) || (h->bias == FIND_MAX_NOT_MORE_THAN)); + assert("nikita-369", (h->bias == FIND_EXACT) + || (h->bias == FIND_MAX_NOT_MORE_THAN)); assert("nikita-370", h->stop_level >= LEAF_LEVEL); assert("nikita-2949", !(h->flags & CBK_DKSET)); assert("zam-355", lock_stack_isclean(get_current_lock_stack())); @@ -663,7 +659,7 @@ traverse_tree(cbk_handle * h /* search h vroot_used = 0; /* loop for restarts */ -restart: + restart: assert("nikita-3024", schedulable()); @@ -683,8 +679,9 @@ restart: return h->result; } if (h->parent_lh->node == NULL) { - done = get_uber_znode(h->tree, ZNODE_READ_LOCK, ZNODE_LOCK_LOPRI, - h->parent_lh); + done = + get_uber_znode(h->tree, ZNODE_READ_LOCK, ZNODE_LOCK_LOPRI, + h->parent_lh); assert("nikita-1637", done != -E_DEADLOCK); @@ -701,7 +698,8 @@ restart: if (unlikely((iterations > REISER4_CBK_ITERATIONS_LIMIT) && IS_POW(iterations))) { - warning("nikita-1481", "Too many iterations: %i", iterations); + warning("nikita-1481", "Too many iterations: %i", + iterations); print_key("key", h->key); ++iterations; } else if (unlikely(iterations > REISER4_MAX_CBK_ITERATIONS)) { @@ -750,7 +748,8 @@ restart: (h->coord->node, 1, ergo((h->result == CBK_COORD_FOUND) && (h->bias == FIND_EXACT) && - (!node_is_empty(h->coord->node)), coord_is_existing_item(h->coord)))); + (!node_is_empty(h->coord->node)), + coord_is_existing_item(h->coord)))); } return h->result; } @@ -761,17 +760,16 @@ restart: @parent_coord. */ -static void -find_child_delimiting_keys(znode * parent /* parent znode, passed - * locked */ , - const coord_t * parent_coord /* coord where - * pointer to - * child is - * stored */ , - reiser4_key * ld /* where to store left - * delimiting key */ , - reiser4_key * rd /* where to store right - * delimiting key */ ) +static void find_child_delimiting_keys(znode * parent /* parent znode, passed + * locked */ , + const coord_t * parent_coord /* coord where + * pointer to + * child is + * stored */ , + reiser4_key * ld /* where to store left + * delimiting key */ , + reiser4_key * rd /* where to store right + * delimiting key */ ) { coord_t neighbor; @@ -809,9 +807,8 @@ find_child_delimiting_keys(znode * paren * * @child child node */ -reiser4_internal int -set_child_delimiting_keys(znode * parent, - const coord_t * coord, znode * child) +int +set_child_delimiting_keys(znode * parent, const coord_t * coord, znode * child) { reiser4_tree *tree; @@ -827,10 +824,10 @@ set_child_delimiting_keys(znode * parent find_child_delimiting_keys(parent, coord, &child->ld_key, &child->rd_key); - ON_DEBUG( - child->ld_key_version = atomic_inc_return(&delim_key_version); - child->rd_key_version = atomic_inc_return(&delim_key_version); - ); + ON_DEBUG(child->ld_key_version = + atomic_inc_return(&delim_key_version); + child->rd_key_version = + atomic_inc_return(&delim_key_version);); ZF_SET(child, JNODE_DKSET); } WUNLOCK_DK(tree); @@ -845,8 +842,7 @@ set_child_delimiting_keys(znode * parent See comments in a code. */ -static level_lookup_result -cbk_level_lookup(cbk_handle * h /* search handle */ ) +static level_lookup_result cbk_level_lookup(cbk_handle * h /* search handle */ ) { int ret; int setdk; @@ -858,7 +854,8 @@ cbk_level_lookup(cbk_handle * h /* searc assert("nikita-3025", schedulable()); /* acquire reference to @active node */ - active = zget(h->tree, &h->block, h->parent_lh->node, h->level, GFP_KERNEL); + active = + zget(h->tree, &h->block, h->parent_lh->node, h->level, GFP_KERNEL); if (IS_ERR(active)) { h->result = PTR_ERR(active); @@ -873,7 +870,7 @@ cbk_level_lookup(cbk_handle * h /* searc /* longterm_lock_znode() acquires additional reference to znode (which will be later released by longterm_unlock_znode()). Release reference acquired by zget(). - */ + */ zput(active); if (unlikely(h->result != 0)) goto fail_or_restart; @@ -882,7 +879,7 @@ cbk_level_lookup(cbk_handle * h /* searc /* if @active is accessed for the first time, setup delimiting keys on it. Delimiting keys are taken from the parent node. See setup_delimiting_keys() for details. - */ + */ if (h->flags & CBK_DKSET) { setdk = setup_delimiting_keys(h); h->flags &= ~CBK_DKSET; @@ -910,7 +907,7 @@ cbk_level_lookup(cbk_handle * h /* searc /* this is ugly kludge. Reminder: this is necessary, because ->lookup() method returns coord with ->between field probably set to something different from AT_UNIT. - */ + */ h->coord->between = AT_UNIT; if (znode_just_created(active) && (h->coord->node != NULL)) { @@ -918,7 +915,7 @@ cbk_level_lookup(cbk_handle * h /* searc /* if we are going to load znode right now, setup ->in_parent: coord where pointer to this node is stored in parent. - */ + */ coord_to_parent_coord(h->coord, &active->in_parent); WUNLOCK_TREE(h->tree); } @@ -945,7 +942,8 @@ cbk_level_lookup(cbk_handle * h /* searc put_parent(h); if ((!znode_contains_key_lock(active, h->key) && - (h->flags & CBK_TRUST_DK)) || ZF_ISSET(active, JNODE_HEARD_BANSHEE)) { + (h->flags & CBK_TRUST_DK)) + || ZF_ISSET(active, JNODE_HEARD_BANSHEE)) { /* 1. key was moved out of this node while this thread was waiting for the lock. Restart. More elaborate solution is to determine where key moved (to the left, or to the right) @@ -953,7 +951,7 @@ cbk_level_lookup(cbk_handle * h /* searc 2. or, node itself is going to be removed from the tree. Release lock and restart. - */ + */ h->result = -E_REPEAT; } if (h->result == -E_REPEAT) @@ -992,7 +990,7 @@ cbk_level_lookup(cbk_handle * h /* searc return ret; -fail_or_restart: + fail_or_restart: if (h->result == -E_DEADLOCK) return LOOKUP_REST; return LOOKUP_DONE; @@ -1000,8 +998,7 @@ fail_or_restart: #if REISER4_DEBUG /* check left and right delimiting keys of a znode */ -void -check_dkeys(znode *node) +void check_dkeys(znode * node) { znode *left; znode *right; @@ -1010,24 +1007,27 @@ check_dkeys(znode *node) RLOCK_DK(current_tree); assert("vs-1710", znode_is_any_locked(node)); - assert("vs-1197", !keygt(znode_get_ld_key(node), znode_get_rd_key(node))); + assert("vs-1197", + !keygt(znode_get_ld_key(node), znode_get_rd_key(node))); left = node->left; right = node->right; - if (ZF_ISSET(node, JNODE_LEFT_CONNECTED) && ZF_ISSET(node, JNODE_DKSET) && - left != NULL && ZF_ISSET(left, JNODE_DKSET)) + if (ZF_ISSET(node, JNODE_LEFT_CONNECTED) && ZF_ISSET(node, JNODE_DKSET) + && left != NULL && ZF_ISSET(left, JNODE_DKSET)) /* check left neighbor. Note that left neighbor is not locked, so it might get wrong delimiting keys therefore */ - assert("vs-1198", (keyeq(znode_get_rd_key(left), znode_get_ld_key(node)) || - ZF_ISSET(left, JNODE_HEARD_BANSHEE))); + assert("vs-1198", + (keyeq(znode_get_rd_key(left), znode_get_ld_key(node)) + || ZF_ISSET(left, JNODE_HEARD_BANSHEE))); - if (ZF_ISSET(node, JNODE_RIGHT_CONNECTED) && ZF_ISSET(node, JNODE_DKSET) && - right != NULL && ZF_ISSET(right, JNODE_DKSET)) + if (ZF_ISSET(node, JNODE_RIGHT_CONNECTED) && ZF_ISSET(node, JNODE_DKSET) + && right != NULL && ZF_ISSET(right, JNODE_DKSET)) /* check right neighbor. Note that right neighbor is not locked, so it might get wrong delimiting keys therefore */ - assert("vs-1199", (keyeq(znode_get_rd_key(node), znode_get_ld_key(right)) || - ZF_ISSET(right, JNODE_HEARD_BANSHEE))); + assert("vs-1199", + (keyeq(znode_get_rd_key(node), znode_get_ld_key(right)) + || ZF_ISSET(right, JNODE_HEARD_BANSHEE))); RUNLOCK_DK(current_tree); RUNLOCK_TREE(current_tree); @@ -1052,8 +1052,7 @@ static int key_is_ld(znode * node, const /* Process one node during tree traversal. This is called by cbk_level_lookup(). */ -static level_lookup_result -cbk_node_lookup(cbk_handle * h /* search handle */ ) +static level_lookup_result cbk_node_lookup(cbk_handle * h /* search handle */ ) { /* node plugin of @active */ node_plugin *nplug; @@ -1092,7 +1091,8 @@ cbk_node_lookup(cbk_handle * h /* search assert("nikita-381", h->coord->node == active); if (result == NS_FOUND) { /* success of tree lookup */ - if (!(h->flags & CBK_UNIQUE) && key_is_ld(active, h->key)) { + if (!(h->flags & CBK_UNIQUE) + && key_is_ld(active, h->key)) { return search_to_left(h); } else h->result = CBK_COORD_FOUND; @@ -1113,7 +1113,8 @@ cbk_node_lookup(cbk_handle * h /* search assert("vs-361", h->level > h->stop_level); if (handle_eottl(h, &result)) { - assert("vs-1674", result == LOOKUP_DONE || result == LOOKUP_REST); + assert("vs-1674", (result == LOOKUP_DONE || + result == LOOKUP_REST)); return result; } @@ -1128,8 +1129,7 @@ cbk_node_lookup(cbk_handle * h /* search } /* scan cbk_cache slots looking for a match for @h */ -static int -cbk_cache_scan_slots(cbk_handle * h /* cbk handle */ ) +static int cbk_cache_scan_slots(cbk_handle * h /* cbk handle */ ) { level_lookup_result llr; znode *node; @@ -1176,17 +1176,19 @@ cbk_cache_scan_slots(cbk_handle * h /* c * * We acquire reference to the node without holding tree lock, and * later, check node's RIP bit. This avoids races with jput(). - * */ rcu_read_lock(); read_lock_cbk_cache(cache); - slot = cbk_cache_list_prev(cbk_cache_list_front(&cache->lru)); + + slot = list_entry(cache->lru.next, cbk_cache_slot, lru); + slot = list_entry(slot->lru.prev, cbk_cache_slot, lru); + BUG_ON(&slot->lru != &cache->lru);/*????*/ while (1) { - slot = cbk_cache_list_next(slot); + slot = list_entry(slot->lru.next, cbk_cache_slot, lru); - if (!cbk_cache_list_end(&cache->lru, slot)) + if (&cache->lru != &slot->lru) node = slot->node; else node = NULL; @@ -1223,7 +1225,9 @@ cbk_cache_scan_slots(cbk_handle * h /* c return RETERR(-ENOENT); } - result = longterm_lock_znode(h->active_lh, node, cbk_lock_mode(level, h), ZNODE_LOCK_LOPRI); + result = + longterm_lock_znode(h->active_lh, node, cbk_lock_mode(level, h), + ZNODE_LOCK_LOPRI); zput(node); if (result != 0) return result; @@ -1233,16 +1237,16 @@ cbk_cache_scan_slots(cbk_handle * h /* c /* recheck keys */ result = - UNDER_RW(dk, tree, read, - znode_contains_key_strict(node, key, isunique)) && - !ZF_ISSET(node, JNODE_HEARD_BANSHEE); + UNDER_RW(dk, tree, read, + znode_contains_key_strict(node, key, isunique)) && + !ZF_ISSET(node, JNODE_HEARD_BANSHEE); if (result) { /* do lookup inside node */ llr = cbk_node_lookup(h); /* if cbk_node_lookup() wandered to another node (due to eottl or non-unique keys), adjust @node */ - /*node = h->active_lh->node;*/ + /*node = h->active_lh->node; */ if (llr != LOOKUP_DONE) { /* restart or continue on the next level */ @@ -1255,11 +1259,11 @@ cbk_cache_scan_slots(cbk_handle * h /* c result = 0; write_lock_cbk_cache(cache); - if (slot->node == h->active_lh->node/*node*/) { + if (slot->node == h->active_lh->node /*node */ ) { /* if this node is still in cbk cache---move its slot to the head of the LRU list. */ - cbk_cache_list_remove(slot); - cbk_cache_list_push_front(&cache->lru, slot); + list_del(&slot->lru); + list_add(&slot->lru, &cache->lru); } write_unlock_cbk_cache(cache); } @@ -1274,7 +1278,7 @@ cbk_cache_scan_slots(cbk_handle * h /* c scanning from the very beginning is complex. Just return, so that cbk() will be performed. This is not that important, because such races should be rare. Are they? - */ + */ result = RETERR(-ENOENT); /* -ERAUGHT */ } zrelse(node); @@ -1295,8 +1299,7 @@ cbk_cache_scan_slots(cbk_handle * h /* c of coord_by_key. */ -static int -cbk_cache_search(cbk_handle * h /* cbk handle */ ) +static int cbk_cache_search(cbk_handle * h /* cbk handle */ ) { int result = 0; tree_level level; @@ -1322,7 +1325,7 @@ cbk_cache_search(cbk_handle * h /* cbk h /* type of lock we want to obtain during tree traversal. On stop level we want type of lock user asked for, on upper levels: read lock. */ -reiser4_internal znode_lock_mode cbk_lock_mode(tree_level level, cbk_handle * h) +znode_lock_mode cbk_lock_mode(tree_level level, cbk_handle * h) { assert("nikita-382", h != NULL); @@ -1330,7 +1333,7 @@ reiser4_internal znode_lock_mode cbk_loc } /* update outdated delimiting keys */ -static void stale_dk(reiser4_tree *tree, znode *node) +static void stale_dk(reiser4_tree * tree, znode * node) { znode *right; @@ -1349,7 +1352,7 @@ static void stale_dk(reiser4_tree *tree, /* check for possibly outdated delimiting keys, and update them if * necessary. */ -static void update_stale_dk(reiser4_tree *tree, znode *node) +static void update_stale_dk(reiser4_tree * tree, znode * node) { znode *right; reiser4_key rd; @@ -1395,8 +1398,7 @@ static void update_stale_dk(reiser4_tree * duplicate keys), it sis cheaper to scan to the left on the stop level once. * */ -static level_lookup_result -search_to_left(cbk_handle * h /* search handle */ ) +static level_lookup_result search_to_left(cbk_handle * h /* search handle */ ) { level_lookup_result result; coord_t *coord; @@ -1413,8 +1415,9 @@ search_to_left(cbk_handle * h /* search node = h->active_lh->node; assert("nikita-1763", coord_is_leftmost_unit(coord)); - h->result = reiser4_get_left_neighbor( - &lh, node, (int) h->lock_mode, GN_CAN_USE_UPPER_LEVELS); + h->result = + reiser4_get_left_neighbor(&lh, node, (int)h->lock_mode, + GN_CAN_USE_UPPER_LEVELS); neighbor = NULL; switch (h->result) { case -E_DEADLOCK: @@ -1437,7 +1440,8 @@ search_to_left(cbk_handle * h /* search coord_init_zero(&crd); bias = h->bias; h->bias = FIND_EXACT; - h->result = nplug->lookup(neighbor, h->key, h->bias, &crd); + h->result = + nplug->lookup(neighbor, h->key, h->bias, &crd); h->bias = bias; if (h->result == NS_NOT_FOUND) { @@ -1460,9 +1464,9 @@ search_to_left(cbk_handle * h /* search Parent hint was set up by reiser4_get_left_neighbor() - */ - UNDER_RW_VOID(tree, znode_get_tree(neighbor), write, - h->coord->node = NULL); + */ + UNDER_RW_VOID(tree, znode_get_tree(neighbor), + write, h->coord->node = NULL); result = LOOKUP_CONT; } else { result = LOOKUP_DONE; @@ -1476,8 +1480,7 @@ search_to_left(cbk_handle * h /* search } /* debugging aid: return symbolic name of search bias */ -static const char * -bias_name(lookup_bias bias /* bias to get name of */ ) +static const char *bias_name(lookup_bias bias /* bias to get name of */ ) { if (bias == FIND_EXACT) return "exact"; @@ -1495,9 +1498,8 @@ bias_name(lookup_bias bias /* bias to ge #if REISER4_DEBUG /* debugging aid: print human readable information about @p */ -reiser4_internal void -print_coord_content(const char *prefix /* prefix to print */ , - coord_t * p /* coord to print */ ) +void print_coord_content(const char *prefix /* prefix to print */ , + coord_t * p /* coord to print */ ) { reiser4_key key; @@ -1505,8 +1507,10 @@ print_coord_content(const char *prefix / printk("%s: null\n", prefix); return; } - if ((p->node != NULL) && znode_is_loaded(p->node) && coord_is_existing_item(p)) - printk("%s: data: %p, length: %i\n", prefix, item_body_by_coord(p), item_length_by_coord(p)); + if ((p->node != NULL) && znode_is_loaded(p->node) + && coord_is_existing_item(p)) + printk("%s: data: %p, length: %i\n", prefix, + item_body_by_coord(p), item_length_by_coord(p)); print_znode(prefix, p->node); if (znode_is_loaded(p->node)) { item_key_by_coord(p, &key); @@ -1515,17 +1519,16 @@ print_coord_content(const char *prefix / } /* debugging aid: print human readable information about @block */ -reiser4_internal void -print_address(const char *prefix /* prefix to print */ , - const reiser4_block_nr * block /* block number to print */ ) +void print_address(const char *prefix /* prefix to print */ , + const reiser4_block_nr * block /* block number to print */ ) { printk("%s: %s\n", prefix, sprint_address(block)); } #endif /* return string containing human readable representation of @block */ -reiser4_internal char * -sprint_address(const reiser4_block_nr * block /* block number to print */ ) +char *sprint_address(const reiser4_block_nr * + block /* block number to print */ ) { static char address[30]; @@ -1539,8 +1542,7 @@ sprint_address(const reiser4_block_nr * } /* release parent node during traversal */ -static void -put_parent(cbk_handle * h /* search handle */ ) +static void put_parent(cbk_handle * h /* search handle */ ) { assert("nikita-383", h != NULL); if (h->parent_lh->node != NULL) { @@ -1550,8 +1552,7 @@ put_parent(cbk_handle * h /* search hand /* helper function used by coord_by_key(): release reference to parent znode stored in handle before processing its child. */ -static void -hput(cbk_handle * h /* search handle */ ) +static void hput(cbk_handle * h /* search handle */ ) { assert("nikita-385", h != NULL); done_lh(h->parent_lh); @@ -1560,8 +1561,7 @@ hput(cbk_handle * h /* search handle */ /* Helper function used by cbk(): update delimiting keys of child node (stored in h->active_lh->node) using key taken from parent on the parent level. */ -static int -setup_delimiting_keys(cbk_handle * h /* search handle */) +static int setup_delimiting_keys(cbk_handle * h /* search handle */ ) { znode *active; reiser4_tree *tree; @@ -1589,8 +1589,8 @@ setup_delimiting_keys(cbk_handle * h /* /* true if @block makes sense for the @tree. Used to detect corrupted node * pointers */ static int -block_nr_is_correct(reiser4_block_nr * block /* block number to check */ , - reiser4_tree * tree /* tree to check against */ ) +block_nr_is_correct(reiser4_block_nr * block /* block number to check */ , + reiser4_tree * tree /* tree to check against */ ) { assert("nikita-757", block != NULL); assert("nikita-758", tree != NULL); @@ -1600,8 +1600,7 @@ block_nr_is_correct(reiser4_block_nr * b } /* check consistency of fields */ -static int -sanity_check(cbk_handle * h /* search handle */ ) +static int sanity_check(cbk_handle * h /* search handle */ ) { assert("nikita-384", h != NULL); @@ -1617,7 +1616,6 @@ sanity_check(cbk_handle * h /* search ha return 0; } - /* Make Linus happy. Local variables: c-indentation-style: "K&R" diff -puN fs/reiser4/spin_macros.h~reiser4-big-update fs/reiser4/spin_macros.h --- devel/fs/reiser4/spin_macros.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/spin_macros.h 2005-09-15 19:51:08.000000000 -0700 @@ -173,7 +173,7 @@ static inline int spin_trylock_ ## NAME static inline void spin_unlock_ ## NAME (TYPE *x) \ { \ __ODCA("nikita-1375", LOCK_CNT_GTZ(spin_locked_ ## NAME)); \ - __ODCA("nikita-1376", LOCK_CNT_GTZ(spin_locked > 0)); \ + __ODCA("nikita-1376", LOCK_CNT_GTZ(spin_locked)); \ __ODCA("nikita-2703", spin_ ## NAME ## _is_locked(x)); \ \ spin_ ## NAME ## _dec(); \ @@ -226,7 +226,6 @@ typedef struct { int foo; } NAME ## _spi spin_unlock_ ## obj_type (__obj); \ }) - /* Define several inline functions for each type of read write lock. This is * insanely long macro definition. */ #define RW_LOCK_FUNCTIONS(NAME,TYPE,FIELD) \ diff -puN fs/reiser4/status_flags.c~reiser4-big-update fs/reiser4/status_flags.c --- devel/fs/reiser4/status_flags.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/status_flags.c 2005-09-15 19:51:08.000000000 -0700 @@ -15,7 +15,8 @@ /* This is our end I/O handler that marks page uptodate if IO was successful. It also unconditionally unlocks the page, so we can see that io was done. We do not free bio, because we hope to reuse that. */ -static int reiser4_status_endio(struct bio *bio, unsigned int bytes_done, int err) +static int reiser4_status_endio(struct bio *bio, unsigned int bytes_done, + int err) { if (bio->bi_size) return 1; @@ -27,19 +28,19 @@ static int reiser4_status_endio(struct b SetPageError(bio->bi_io_vec->bv_page); } unlock_page(bio->bi_io_vec->bv_page); -// bio_put(bio); return 0; } /* Initialise status code. This is expected to be called from the disk format code. block paremeter is where status block lives. */ -reiser4_internal int reiser4_status_init(reiser4_block_nr block) +int reiser4_status_init(reiser4_block_nr block) { struct super_block *sb = reiser4_get_current_sb(); struct reiser4_status *statuspage; struct bio *bio; struct page *page; + get_super_private(sb)->status_page = NULL; get_super_private(sb)->status_bio = NULL; @@ -64,15 +65,17 @@ reiser4_internal int reiser4_status_init lock_page(page); submit_bio(READ, bio); blk_run_address_space(get_super_fake(sb)->i_mapping); - /*blk_run_queues();*/ wait_on_page_locked(page); - if ( !PageUptodate(page) ) { - warning("green-2007", "I/O error while tried to read status page\n"); + if (!PageUptodate(page)) { + warning("green-2007", + "I/O error while tried to read status page\n"); return -EIO; } statuspage = (struct reiser4_status *)kmap_atomic(page, KM_USER0); - if ( memcmp( statuspage->magic, REISER4_STATUS_MAGIC, sizeof(REISER4_STATUS_MAGIC)) ) { + if (memcmp + (statuspage->magic, REISER4_STATUS_MAGIC, + sizeof(REISER4_STATUS_MAGIC))) { /* Magic does not match. */ kunmap_atomic((char *)statuspage, KM_USER0); warning("green-2008", "Wrong magic in status block\n"); @@ -90,18 +93,18 @@ reiser4_internal int reiser4_status_init /* Query the status of fs. Returns if the FS can be safely mounted. Also if "status" and "extended" parameters are given, it will fill actual parts of status from disk there. */ -reiser4_internal int reiser4_status_query(u64 *status, u64 *extended) +int reiser4_status_query(u64 * status, u64 * extended) { struct super_block *sb = reiser4_get_current_sb(); struct reiser4_status *statuspage; int retval; - if ( !get_super_private(sb)->status_page ) { // No status page? + if (!get_super_private(sb)->status_page) { // No status page? return REISER4_STATUS_MOUNT_UNKNOWN; } statuspage = (struct reiser4_status *) - kmap_atomic(get_super_private(sb)->status_page, KM_USER0); - switch ( (long)d64tocpu(&statuspage->status) ) { // FIXME: this cast is a hack for 32 bit arches to work. + kmap_atomic(get_super_private(sb)->status_page, KM_USER0); + switch ((long)d64tocpu(&statuspage->status)) { // FIXME: this cast is a hack for 32 bit arches to work. case REISER4_STATUS_OK: retval = REISER4_STATUS_MOUNT_OK; break; @@ -118,9 +121,9 @@ reiser4_internal int reiser4_status_quer break; } - if ( status ) + if (status) *status = d64tocpu(&statuspage->status); - if ( extended ) + if (extended) *extended = d64tocpu(&statuspage->extended_status); kunmap_atomic((char *)statuspage, KM_USER0); @@ -129,18 +132,17 @@ reiser4_internal int reiser4_status_quer /* This function should be called when something bad happens (e.g. from reiser4_panic). It fills the status structure and tries to push it to disk. */ -reiser4_internal int -reiser4_status_write(u64 status, u64 extended_status, char *message) +int reiser4_status_write(u64 status, u64 extended_status, char *message) { struct super_block *sb = reiser4_get_current_sb(); struct reiser4_status *statuspage; struct bio *bio = get_super_private(sb)->status_bio; - if ( !get_super_private(sb)->status_page ) { // No status page? + if (!get_super_private(sb)->status_page) { // No status page? return -1; } statuspage = (struct reiser4_status *) - kmap_atomic(get_super_private(sb)->status_page, KM_USER0); + kmap_atomic(get_super_private(sb)->status_page, KM_USER0); cputod64(status, &statuspage->status); cputod64(extended_status, &statuspage->extended_status); @@ -172,16 +174,15 @@ reiser4_status_write(u64 status, u64 ext bio->bi_vcnt = 1; bio->bi_size = sb->s_blocksize; bio->bi_end_io = reiser4_status_endio; - lock_page(get_super_private(sb)->status_page); // Safe as nobody should touch our page. + lock_page(get_super_private(sb)->status_page); // Safe as nobody should touch our page. /* We can block now, but we have no other choice anyway */ submit_bio(WRITE, bio); blk_run_address_space(get_super_fake(sb)->i_mapping); - /*blk_run_queues();*/ // Now start the i/o. - return 0; // We do not wait for io to finish. + return 0; // We do not wait for io to finish. } /* Frees the page with status and bio structure. Should be called by disk format at umount time */ -reiser4_internal int reiser4_status_finish(void) +int reiser4_status_finish(void) { struct super_block *sb = reiser4_get_current_sb(); @@ -191,4 +192,3 @@ reiser4_internal int reiser4_status_fini get_super_private(sb)->status_bio = NULL; return 0; } - diff -puN fs/reiser4/status_flags.h~reiser4-big-update fs/reiser4/status_flags.h --- devel/fs/reiser4/status_flags.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/status_flags.h 2005-09-15 19:51:08.000000000 -0700 @@ -28,15 +28,15 @@ /* We probably need to keep its size under sector size which is 512 bytes */ struct reiser4_status { char magic[16]; - d64 status; /* Current FS state */ - d64 extended_status; /* Any additional info that might have sense in addition to "status". E.g. - last sector where io error happened if status is "io error encountered" */ - d64 stacktrace[10]; /* Last ten functional calls made (addresses)*/ - char texterror[REISER4_TEXTERROR_LEN]; /* Any error message if appropriate, otherwise filled with zeroes */ + d64 status; /* Current FS state */ + d64 extended_status; /* Any additional info that might have sense in addition to "status". E.g. + last sector where io error happened if status is "io error encountered" */ + d64 stacktrace[10]; /* Last ten functional calls made (addresses) */ + char texterror[REISER4_TEXTERROR_LEN]; /* Any error message if appropriate, otherwise filled with zeroes */ }; int reiser4_status_init(reiser4_block_nr block); -int reiser4_status_query(u64 *status, u64 *extended); +int reiser4_status_query(u64 * status, u64 * extended); int reiser4_status_write(u64 status, u64 extended_status, char *message); int reiser4_status_finish(void); diff -puN fs/reiser4/super.c~reiser4-big-update fs/reiser4/super.c --- devel/fs/reiser4/super.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/super.c 2005-09-15 19:51:08.000000000 -0700 @@ -17,37 +17,32 @@ #include /* for __u?? */ #include /* for struct super_block */ -/*const __u32 REISER4_SUPER_MAGIC = 0x52345362;*/ /* (*(__u32 *)"R4Sb"); */ static __u64 reserved_for_gid(const struct super_block *super, gid_t gid); static __u64 reserved_for_uid(const struct super_block *super, uid_t uid); static __u64 reserved_for_root(const struct super_block *super); /* Return reiser4-specific part of super block */ -reiser4_internal reiser4_super_info_data * -get_super_private_nocheck(const struct super_block *super /* super block - * queried */ ) +reiser4_super_info_data *get_super_private_nocheck(const struct super_block *super /* super block + * queried */ ) { return (reiser4_super_info_data *) super->s_fs_info; } - /* Return reiser4 fstype: value that is returned in ->f_type field by statfs() */ -reiser4_internal long -statfs_type(const struct super_block *super UNUSED_ARG /* super block - * queried */ ) +long statfs_type(const struct super_block *super UNUSED_ARG /* super block + * queried */ ) { assert("nikita-448", super != NULL); assert("nikita-449", is_reiser4_super(super)); - return (long) REISER4_SUPER_MAGIC; + return (long)REISER4_SUPER_MAGIC; } /* functions to read/modify fields of reiser4_super_info_data */ /* get number of blocks in file system */ -reiser4_internal __u64 -reiser4_block_count(const struct super_block * super /* super block - queried */ ) +__u64 reiser4_block_count(const struct super_block *super /* super block + queried */ ) { assert("vs-494", super != NULL); assert("vs-495", is_reiser4_super(super)); @@ -57,34 +52,33 @@ reiser4_block_count(const struct super_b /* * number of blocks in the current file system */ -reiser4_internal __u64 reiser4_current_block_count(void) +__u64 reiser4_current_block_count(void) { return get_current_super_private()->block_count; } - /* set number of block in filesystem */ -reiser4_internal void -reiser4_set_block_count(const struct super_block *super, __u64 nr) +void reiser4_set_block_count(const struct super_block *super, __u64 nr) { assert("vs-501", super != NULL); assert("vs-502", is_reiser4_super(super)); get_super_private(super)->block_count = nr; - /* The proper calculation of the reserved space counter (%5 of device - block counter) we need a 64 bit division which is missing in Linux on - i386 platform. Because we do not need a precise calculation here we - can replace a div64 operation by this combination of multiplication - and shift: 51. / (2^10) == .0498 .*/ - /* FIXME: this is a bug. It comes up only for very small filesystems - which probably are never user. Nevertheless, it is a bug. Number of - reserved blocks must be not less than maximal number of blocks which - get grabbed with BA_RESERVED. */ + /* + * The proper calculation of the reserved space counter (%5 of device + * block counter) we need a 64 bit division which is missing in Linux + * on i386 platform. Because we do not need a precise calculation here + * we can replace a div64 operation by this combination of + * multiplication and shift: 51. / (2^10) == .0498 . + * FIXME: this is a bug. It comes up only for very small filesystems + * which probably are never used. Nevertheless, it is a bug. Number of + * reserved blocks must be not less than maximal number of blocks which + * get grabbed with BA_RESERVED. + */ get_super_private(super)->blocks_reserved = ((nr * 51) >> 10); } /* amount of blocks used (allocated for data) in file system */ -reiser4_internal __u64 -reiser4_data_blocks(const struct super_block *super /* super block +__u64 reiser4_data_blocks(const struct super_block *super /* super block queried */ ) { assert("nikita-452", super != NULL); @@ -93,8 +87,7 @@ reiser4_data_blocks(const struct super_b } /* set number of block used in filesystem */ -reiser4_internal void -reiser4_set_data_blocks(const struct super_block *super, __u64 nr) +void reiser4_set_data_blocks(const struct super_block *super, __u64 nr) { assert("vs-503", super != NULL); assert("vs-504", is_reiser4_super(super)); @@ -102,9 +95,8 @@ reiser4_set_data_blocks(const struct sup } /* amount of free blocks in file system */ -reiser4_internal __u64 -reiser4_free_blocks(const struct super_block *super /* super block - queried */ ) +__u64 reiser4_free_blocks(const struct super_block *super /* super block + queried */ ) { assert("nikita-454", super != NULL); assert("nikita-455", is_reiser4_super(super)); @@ -112,8 +104,7 @@ reiser4_free_blocks(const struct super_b } /* set number of blocks free in filesystem */ -reiser4_internal void -reiser4_set_free_blocks(const struct super_block *super, __u64 nr) +void reiser4_set_free_blocks(const struct super_block *super, __u64 nr) { assert("vs-505", super != NULL); assert("vs-506", is_reiser4_super(super)); @@ -121,9 +112,8 @@ reiser4_set_free_blocks(const struct sup } /* get mkfs unique identifier */ -reiser4_internal __u32 -reiser4_mkfs_id(const struct super_block *super /* super block - queried */ ) +__u32 reiser4_mkfs_id(const struct super_block *super /* super block + queried */ ) { assert("vpf-221", super != NULL); assert("vpf-222", is_reiser4_super(super)); @@ -131,8 +121,7 @@ reiser4_mkfs_id(const struct super_block } /* set mkfs unique identifier */ -reiser4_internal void -reiser4_set_mkfs_id(const struct super_block *super, __u32 id) +void reiser4_set_mkfs_id(const struct super_block *super, __u32 id) { assert("vpf-223", super != NULL); assert("vpf-224", is_reiser4_super(super)); @@ -140,8 +129,7 @@ reiser4_set_mkfs_id(const struct super_b } /* amount of free blocks in file system */ -reiser4_internal __u64 -reiser4_free_committed_blocks(const struct super_block *super) +__u64 reiser4_free_committed_blocks(const struct super_block *super) { assert("vs-497", super != NULL); assert("vs-498", is_reiser4_super(super)); @@ -149,10 +137,10 @@ reiser4_free_committed_blocks(const stru } /* amount of blocks in the file system reserved for @uid and @gid */ -reiser4_internal long -reiser4_reserved_blocks(const struct super_block *super /* super block - queried */ , - uid_t uid /* user id */ , gid_t gid /* group id */ ) +long reiser4_reserved_blocks(const struct super_block *super /* super block + queried */ , + uid_t uid /* user id */ , + gid_t gid /* group id */ ) { long reserved; @@ -170,7 +158,7 @@ reiser4_reserved_blocks(const struct sup } /* get/set value of/to grabbed blocks counter */ -reiser4_internal __u64 reiser4_grabbed_blocks(const struct super_block * super) +__u64 reiser4_grabbed_blocks(const struct super_block * super) { assert("zam-512", super != NULL); assert("zam-513", is_reiser4_super(super)); @@ -178,16 +166,16 @@ reiser4_internal __u64 reiser4_grabbed_b return get_super_private(super)->blocks_grabbed; } -reiser4_internal __u64 flush_reserved (const struct super_block *super) +__u64 flush_reserved(const struct super_block * super) { - assert ("vpf-285", super != NULL); - assert ("vpf-286", is_reiser4_super (super)); + assert("vpf-285", super != NULL); + assert("vpf-286", is_reiser4_super(super)); return get_super_private(super)->blocks_flush_reserved; } /* get/set value of/to counter of fake allocated formatted blocks */ -reiser4_internal __u64 reiser4_fake_allocated(const struct super_block *super) +__u64 reiser4_fake_allocated(const struct super_block * super) { assert("zam-516", super != NULL); assert("zam-517", is_reiser4_super(super)); @@ -196,8 +184,7 @@ reiser4_internal __u64 reiser4_fake_allo } /* get/set value of/to counter of fake allocated unformatted blocks */ -reiser4_internal __u64 -reiser4_fake_allocated_unformatted(const struct super_block *super) +__u64 reiser4_fake_allocated_unformatted(const struct super_block * super) { assert("zam-516", super != NULL); assert("zam-517", is_reiser4_super(super)); @@ -206,7 +193,7 @@ reiser4_fake_allocated_unformatted(const } /* get/set value of/to counter of clustered blocks */ -reiser4_internal __u64 reiser4_clustered_blocks(const struct super_block *super) +__u64 reiser4_clustered_blocks(const struct super_block * super) { assert("edward-601", super != NULL); assert("edward-602", is_reiser4_super(super)); @@ -215,8 +202,7 @@ reiser4_internal __u64 reiser4_clustered } /* space allocator used by this file system */ -reiser4_internal reiser4_space_allocator * -get_space_allocator(const struct super_block * super) +reiser4_space_allocator *get_space_allocator(const struct super_block * super) { assert("nikita-1965", super != NULL); assert("nikita-1966", is_reiser4_super(super)); @@ -224,27 +210,31 @@ get_space_allocator(const struct super_b } /* return fake inode used to bind formatted nodes in the page cache */ -reiser4_internal struct inode * -get_super_fake(const struct super_block *super /* super block - queried */ ) +struct inode *get_super_fake(const struct super_block *super /* super block + queried */ ) { assert("nikita-1757", super != NULL); return get_super_private(super)->fake; } /* return fake inode used to bind copied on capture nodes in the page cache */ -reiser4_internal struct inode * -get_cc_fake(const struct super_block *super /* super block - queried */ ) +struct inode *get_cc_fake(const struct super_block *super /* super block + queried */ ) { assert("nikita-1757", super != NULL); return get_super_private(super)->cc; } +/* return fake inode used to bind bitmaps and journlal heads */ +struct inode *get_bitmap_fake(const struct super_block *super) +{ + assert("nikita-17571", super != NULL); + return get_super_private(super)->bitmap; +} + /* tree used by this file system */ -reiser4_internal reiser4_tree * -get_tree(const struct super_block * super /* super block - * queried */ ) +reiser4_tree *get_tree(const struct super_block * super /* super block + * queried */ ) { assert("nikita-460", super != NULL); assert("nikita-461", is_reiser4_super(super)); @@ -253,47 +243,42 @@ get_tree(const struct super_block * supe /* Check that @super is (looks like) reiser4 super block. This is mainly for use in assertions. */ -reiser4_internal int -is_reiser4_super(const struct super_block *super /* super block +int is_reiser4_super(const struct super_block *super /* super block * queried */ ) { return - super != NULL && - get_super_private(super) != NULL && - super->s_op == &get_super_private(super)->ops.super; + super != NULL && + get_super_private(super) != NULL && + super->s_op == &(get_super_private(super)->ops.super); } -reiser4_internal int -reiser4_is_set(const struct super_block *super, reiser4_fs_flag f) +int reiser4_is_set(const struct super_block *super, reiser4_fs_flag f) { - return test_bit((int) f, &get_super_private(super)->fs_flags); + return test_bit((int)f, &get_super_private(super)->fs_flags); } /* amount of blocks reserved for given group in file system */ -static __u64 -reserved_for_gid(const struct super_block *super UNUSED_ARG /* super - * block - * queried */ , - gid_t gid UNUSED_ARG /* group id */ ) +static __u64 reserved_for_gid(const struct super_block *super UNUSED_ARG /* super + * block + * queried */ , + gid_t gid UNUSED_ARG /* group id */ ) { return 0; } /* amount of blocks reserved for given user in file system */ -static __u64 -reserved_for_uid(const struct super_block *super UNUSED_ARG /* super - block - queried */ , - uid_t uid UNUSED_ARG /* user id */ ) +static __u64 reserved_for_uid(const struct super_block *super UNUSED_ARG /* super + block + queried */ , + uid_t uid UNUSED_ARG /* user id */ ) { return 0; } /* amount of blocks reserved for super user in file system */ -static __u64 -reserved_for_root(const struct super_block *super UNUSED_ARG /* super - block - queried */ ) +static __u64 reserved_for_root(const struct super_block *super UNUSED_ARG /* super + block + queried */ ) { return 0; } @@ -301,9 +286,9 @@ reserved_for_root(const struct super_blo /* * true if block number @blk makes sense for the file system at @super. */ -reiser4_internal int +int reiser4_blocknr_is_sane_for(const struct super_block *super, - const reiser4_block_nr *blk) + const reiser4_block_nr * blk) { reiser4_super_info_data *sbinfo; @@ -320,120 +305,26 @@ reiser4_blocknr_is_sane_for(const struct /* * true, if block number @blk makes sense for the current file system */ -reiser4_internal int -reiser4_blocknr_is_sane(const reiser4_block_nr *blk) +int reiser4_blocknr_is_sane(const reiser4_block_nr * blk) { return reiser4_blocknr_is_sane_for(reiser4_get_current_sb(), blk); } -/* - * construct various VFS related operation vectors that are embedded into @ops - * inside of @super. - */ -reiser4_internal void -build_object_ops(struct super_block *super, object_ops *ops) -{ - struct inode_operations iops; - - assert("nikita-3248", super != NULL); - assert("nikita-3249", ops != NULL); - - iops = reiser4_inode_operations; - - /* setup super_operations... */ - ops->super = reiser4_super_operations; - /* ...and export operations for NFS */ - ops->export = reiser4_export_operations; - - /* install pointers to the per-super-block vectors into super-block - * fields */ - super->s_op = &ops->super; - super->s_export_op = &ops->export; - - /* cleanup XATTR related fields in inode operations---we don't support - * Linux xattr API... */ - iops.setxattr = NULL; - iops.getxattr = NULL; - iops.listxattr = NULL; - iops.removexattr = NULL; - - /* ...and we don't need ->clear_inode, because its only user was - * xattrs */ - /*ops->super.clear_inode = NULL;*/ - - ops->regular = iops; - ops->dir = iops; - - ops->file = reiser4_file_operations; - ops->symlink = reiser4_symlink_inode_operations; - ops->special = reiser4_special_inode_operations; - ops->dentry = reiser4_dentry_operations; - ops->as = reiser4_as_operations; - -#if !ENABLE_REISER4_PSEUDO - /* if we don't support pseudo files, we need neither ->open, - * nor ->lookup on regular files */ - ops->regular.lookup = NULL; - ops->file.open = NULL; -#endif -} - -#ifdef REISER4_DEBUG_OUTPUT -/* - * debugging function: output human readable information about file system - * parameters - */ -reiser4_internal void -print_fs_info(const char *prefix, const struct super_block *s) -{ - reiser4_super_info_data *sbinfo; - - sbinfo = get_super_private(s); - - printk("================ fs info (%s) =================\n", prefix); - printk("root block: %lli\ntree height: %i\n", sbinfo->tree.root_block, sbinfo->tree.height); - sa_print_info("", get_space_allocator(s)); - - printk("Oids: next to use %llu, in use %llu\n", sbinfo->next_to_use, sbinfo->oids_in_use); - printk("Block counters:\n\tblock count\t%llu\n\tfree blocks\t%llu\n" - "\tused blocks\t%llu\n\tgrabbed\t%llu\n\tfake allocated formatted\t%llu\n" - "\tfake allocated unformatted\t%llu\n", - reiser4_block_count(s), reiser4_free_blocks(s), - reiser4_data_blocks(s), reiser4_grabbed_blocks(s), - reiser4_fake_allocated(s), reiser4_fake_allocated_unformatted(s)); - print_key("Root directory key", sbinfo->df_plug->root_dir_key(s)); - - if ( sbinfo->diskmap_block) - printk("Diskmap is present in %llu block\n", sbinfo->diskmap_block); - else - printk("Diskmap is not present\n"); - - if (sbinfo->df_plug->print_info) { - printk("=========== disk format info (%s) =============\n", sbinfo->df_plug->h.label); - sbinfo->df_plug->print_info(s); - } - -} -#endif - - #if REISER4_DEBUG /* this is caller when unallocated extent pointer is added */ -void -inc_unalloc_unfm_ptr(void) +void inc_unalloc_unfm_ptr(void) { reiser4_super_info_data *sbinfo; sbinfo = get_super_private(get_current_context()->super); reiser4_spin_lock_sb(sbinfo); - sbinfo->unalloc_extent_pointers ++; + sbinfo->unalloc_extent_pointers++; reiser4_spin_unlock_sb(sbinfo); } /* this is called when unallocated extent is converted to allocated */ -void -dec_unalloc_unfm_ptrs(int nr) +void dec_unalloc_unfm_ptrs(int nr) { reiser4_super_info_data *sbinfo; @@ -444,28 +335,6 @@ dec_unalloc_unfm_ptrs(int nr) reiser4_spin_unlock_sb(sbinfo); } -void -inc_unfm_ef(void) -{ - reiser4_super_info_data *sbinfo; - - sbinfo = get_super_private(get_current_context()->super); - reiser4_spin_lock_sb(sbinfo); - sbinfo->eflushed_unformatted ++; - reiser4_spin_unlock_sb(sbinfo); -} - -void -dec_unfm_ef(void) -{ - reiser4_super_info_data *sbinfo; - - sbinfo = get_super_private(get_current_context()->super); - reiser4_spin_lock_sb(sbinfo); - BUG_ON(sbinfo->eflushed_unformatted == 0); - sbinfo->eflushed_unformatted --; - reiser4_spin_unlock_sb(sbinfo); -} #endif diff -puN fs/reiser4/super.h~reiser4-big-update fs/reiser4/super.h --- devel/fs/reiser4/super.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/super.h 2005-09-15 19:51:08.000000000 -0700 @@ -6,28 +6,13 @@ #if !defined( __REISER4_SUPER_H__ ) #define __REISER4_SUPER_H__ -#include "forward.h" -#include "debug.h" #include "tree.h" -#include "context.h" #include "entd.h" -#include "plugin/plugin.h" #include "wander.h" - +#include "fsdata.h" +#include "plugin/object.h" #include "plugin/space/space_allocator.h" -#include "plugin/disk_format/disk_format40.h" -#include "plugin/security/perm.h" -#include "plugin/dir/dir.h" - -#include "emergency_flush.h" - -#include -#include /* for __u??, etc. */ -#include /* for struct super_block, etc. */ -#include /* for struct list_head */ -#include /* for kobject */ - /* * Flush algorithms parameters. */ @@ -39,19 +24,21 @@ typedef struct { } flush_params; typedef enum { - /* True if this file system doesn't support hard-links (multiple - names) for directories: this is default UNIX behavior. - - If hard-links on directoires are not allowed, file system is - Acyclic Directed Graph (modulo dot, and dotdot, of course). - - This is used by reiser4_link(). - */ + /* + * True if this file system doesn't support hard-links (multiple names) + * for directories: this is default UNIX behavior. + * + * If hard-links on directoires are not allowed, file system is Acyclic + * Directed Graph (modulo dot, and dotdot, of course). + * + * This is used by reiser4_link(). + */ REISER4_ADG = 0, - /* set if all nodes in internal tree have the same node layout plugin. - If so, znode_guess_plugin() will return tree->node_plugin in stead - of guessing plugin by plugin id stored in the node. - */ + /* + * set if all nodes in internal tree have the same node layout plugin. + * If so, znode_guess_plugin() will return tree->node_plugin in stead + * of guessing plugin by plugin id stored in the node. + */ REISER4_ONE_NODE_PLUGIN = 1, /* if set, bsd gid assignment is supported. */ REISER4_BSD_GID = 2, @@ -59,37 +46,19 @@ typedef enum { REISER4_32_BIT_TIMES = 3, /* allow concurrent flushes */ REISER4_MTFLUSH = 4, - /* disable support for pseudo files. Don't treat regular files as - * directories. */ - REISER4_NO_PSEUDO = 5, /* load all bitmap blocks at mount time */ - REISER4_DONT_LOAD_BITMAP = 6, + REISER4_DONT_LOAD_BITMAP = 5, /* enforce atomicity during write(2) */ - REISER4_ATOMIC_WRITE = 7 + REISER4_ATOMIC_WRITE = 6 } reiser4_fs_flag; /* * VFS related operation vectors. - * - * Usually file system has one instance of those, but in reiser4 we sometimes - * want to be able to modify vectors on per-mount basis. For example, reiser4 - * needs ->open method to handle pseudo files correctly, but if file system is - * mounted with "nopseudo" mount option, it's better to have ->open set to - * NULL, as this makes sys_open() a little bit more efficient. - * */ typedef struct object_ops { - struct super_operations super; - struct file_operations file; - struct dentry_operations dentry; - struct address_space_operations as; - - struct inode_operations regular; - struct inode_operations dir; - struct inode_operations symlink; - struct inode_operations special; - - struct export_operations export; + struct super_operations super; + struct dentry_operations dentry; + struct export_operations export; } object_ops; /* reiser4-specific part of super block @@ -146,15 +115,12 @@ typedef struct object_ops { [sb-fake-allocated] */ struct reiser4_super_info_data { - /* guard spinlock which protects reiser4 super - block fields (currently blocks_free, - blocks_free_committed) - */ - reiser4_spin_data guard; - /* - * object id manager + * guard spinlock which protects reiser4 super block fields (currently + * blocks_free, blocks_free_committed) */ + reiser4_spin_data guard; + /* next oid that will be returned by oid_allocate() */ oid_t next_to_use; /* total number of used oids */ @@ -166,12 +132,16 @@ struct reiser4_super_info_data { /* reiser4 internal tree */ reiser4_tree tree; - /* default user id used for light-weight files without their own - stat-data. */ + /* + * default user id used for light-weight files without their own + * stat-data. + */ uid_t default_uid; - /* default group id used for light-weight files without their own - stat-data. */ + /* + * default group id used for light-weight files without their own + * stat-data. + */ gid_t default_gid; /* mkfs identifier generated at mkfs time. */ @@ -185,15 +155,22 @@ struct reiser4_super_info_data { /* amount of blocks used by file system data and meta-data. */ __u64 blocks_used; - /* amount of free blocks. This is "working" free blocks counter. It is - like "working" bitmap, please see block_alloc.c for description. */ + /* + * amount of free blocks. This is "working" free blocks counter. It is + * like "working" bitmap, please see block_alloc.c for description. + */ __u64 blocks_free; - /* free block count for fs committed state. This is "commit" version - of free block counter. */ + /* + * free block count for fs committed state. This is "commit" version of + * free block counter. + */ __u64 blocks_free_committed; - /* number of blocks reserved for further allocation, for all threads. */ + /* + * number of blocks reserved for further allocation, for all + * threads. + */ __u64 blocks_grabbed; /* number of fake allocated unformatted blocks in tree. */ @@ -205,28 +182,12 @@ struct reiser4_super_info_data { /* number of blocks reserved for flush operations. */ __u64 blocks_flush_reserved; - /* number of blocks reserved for cluster operations. */ + /* number of blocks reserved for cluster operations. */ __u64 blocks_clustered; /* unique file-system identifier */ - /* does this conform to Andreas Dilger UUID stuff? */ __u32 fsuid; - /* per-fs tracing flags. Use reiser4_trace_flags enum to set - bits in it. */ - __u32 trace_flags; - - /* per-fs log flags. Use reiser4_log_flags enum to set - bits in it. */ - __u32 log_flags; - __u32 oid_to_log; - - /* per-fs debugging flags. This is bitmask populated from - reiser4_debug_flags enum. */ - __u32 debug_flags; - - /* super block flags */ - /* file-system wide flags. See reiser4_fs_flag enum */ unsigned long fs_flags; @@ -251,21 +212,20 @@ struct reiser4_super_info_data { format40_super_info format40; } u; - /* - * value we return in st_blksize on stat(2). - */ + /* value we return in st_blksize on stat(2) */ unsigned long optimal_io_size; /* parameters for the flush algorithm */ flush_params flush; +#if REISER4_USE_EFLUSH /* see emergency_flush.c for details */ reiser4_spin_data eflush_guard; /* number of emergency flushed nodes */ - int eflushed; -#if REISER4_USE_EFLUSH + int eflushed; /* hash table used by emergency flush. Protected by ->eflush_guard */ - ef_hash_table efhash_table; + ef_hash_table efhash_table; + __u64 eflushed_unformatted; /* number of eflushed unformatted nodes */ #endif /* pointers to jnodes for journal header and footer */ jnode *journal_header; @@ -276,8 +236,10 @@ struct reiser4_super_info_data { /* head block number of last committed transaction */ __u64 last_committed_tx; - /* we remember last written location for using as a hint for - new block allocation */ + /* + * we remember last written location for using as a hint for new block + * allocation + */ __u64 blocknr_hint_default; /* committed number of files (oid allocator state variable ) */ @@ -285,9 +247,11 @@ struct reiser4_super_info_data { ra_params_t ra_params; - /* A semaphore for serializing cut tree operation if - out-of-free-space: the only one cut_tree thread is allowed to grab - space from reserved area (it is 5% of disk space) */ + /* + * A semaphore for serializing cut tree operation if out-of-free-space: + * the only one cut_tree thread is allowed to grab space from reserved + * area (it is 5% of disk space) + */ struct semaphore delete_sema; /* task owning ->delete_sema */ struct task_struct *delete_sema_owner; @@ -304,19 +268,26 @@ struct reiser4_super_info_data { /* operations for objects on this file system */ object_ops ops; - /* dir_cursor_info see plugin/dir/dir.[ch] for more details */ + /* + * structure to maintain d_cursors. See plugin/file_ops_readdir.c for + * more details + */ d_cursor_info d_info; #ifdef CONFIG_REISER4_BADBLOCKS /* Alternative master superblock offset (in bytes) */ unsigned long altsuper; #endif + struct repacker *repacker; + struct page *status_page; + struct bio *status_bio; + #if REISER4_DEBUG - /* minimum used blocks value (includes super blocks, bitmap blocks and - * other fs reserved areas), depends on fs format and fs size. */ + /* + * minimum used blocks value (includes super blocks, bitmap blocks and + * other fs reserved areas), depends on fs format and fs size. + */ __u64 min_blocks_used; - /* number of space allocated by kmalloc. For debugging. */ - int kmallocs; /* * when debugging is on, all jnodes (including znodes, bitmaps, etc.) @@ -325,30 +296,21 @@ struct reiser4_super_info_data { * with _irq modifier, because it is also modified from interrupt * contexts (by RCU). */ - spinlock_t all_guard; /* list of all jnodes */ struct list_head all_jnodes; - - /*XXX debugging code */ - __u64 eflushed_unformatted; /* number of eflushed unformatted nodes */ - __u64 unalloc_extent_pointers; /* number of unallocated extent pointers in the tree */ + /* number of unallocated extent pointers in the tree */ + __u64 unalloc_extent_pointers; #endif - struct repacker * repacker; - struct page * status_page; - struct bio * status_bio; }; - - extern reiser4_super_info_data *get_super_private_nocheck(const struct super_block *super); -extern struct super_operations reiser4_super_operations; /* Return reiser4-specific part of super block */ -static inline reiser4_super_info_data * -get_super_private(const struct super_block * super) +static inline reiser4_super_info_data *get_super_private(const struct + super_block *super) { assert("nikita-447", super != NULL); @@ -357,8 +319,7 @@ get_super_private(const struct super_blo /* "Current" super-block: main super block used during current system call. Reference to this super block is stored in reiser4_context. */ -static inline struct super_block * -reiser4_get_current_sb(void) +static inline struct super_block *reiser4_get_current_sb(void) { return get_current_context()->super; } @@ -366,14 +327,12 @@ reiser4_get_current_sb(void) /* Reiser4-specific part of "current" super-block: main super block used during current system call. Reference to this super block is stored in reiser4_context. */ -static inline reiser4_super_info_data * -get_current_super_private(void) +static inline reiser4_super_info_data *get_current_super_private(void) { return get_super_private(reiser4_get_current_sb()); } -static inline ra_params_t * -get_current_super_ra_params(void) +static inline ra_params_t *get_current_super_ra_params(void) { return &(get_current_super_private()->ra_params); } @@ -389,7 +348,7 @@ static inline int rofs_super(struct supe /* * true, if @tree represents read-only file system */ -static inline int rofs_tree(reiser4_tree *tree) +static inline int rofs_tree(reiser4_tree * tree) { return rofs_super(tree->super); } @@ -405,27 +364,24 @@ static inline int rofs_inode(struct inod /* * true, if file system where @node lives on, is read-only */ -static inline int rofs_jnode(jnode *node) +static inline int rofs_jnode(jnode * node) { return rofs_tree(jnode_get_tree(node)); } extern __u64 reiser4_current_block_count(void); -extern void build_object_ops(struct super_block *super, object_ops *ops); +extern void build_object_ops(struct super_block *super, object_ops * ops); -#define REISER4_SUPER_MAGIC 0x52345362 /* (*(__u32 *)"R4Sb"); */ +#define REISER4_SUPER_MAGIC 0x52345362 /* (*(__u32 *)"R4Sb"); */ #define spin_ordering_pred_super(private) (1) SPIN_LOCK_FUNCTIONS(super, reiser4_super_info_data, guard); -#define spin_ordering_pred_super_eflush(private) (1) -SPIN_LOCK_FUNCTIONS(super_eflush, reiser4_super_info_data, eflush_guard); - /* * lock reiser4-specific part of super block */ -static inline void reiser4_spin_lock_sb(reiser4_super_info_data *sbinfo) +static inline void reiser4_spin_lock_sb(reiser4_super_info_data * sbinfo) { spin_lock_super(sbinfo); } @@ -433,31 +389,36 @@ static inline void reiser4_spin_lock_sb( /* * unlock reiser4-specific part of super block */ -static inline void reiser4_spin_unlock_sb(reiser4_super_info_data *sbinfo) +static inline void reiser4_spin_unlock_sb(reiser4_super_info_data * sbinfo) { spin_unlock_super(sbinfo); } +#if REISER4_USE_EFLUSH + +#define spin_ordering_pred_super_eflush(private) (1) +SPIN_LOCK_FUNCTIONS(super_eflush, reiser4_super_info_data, eflush_guard); + /* * lock emergency flush data-structures for super block @s */ -static inline void spin_lock_eflush(const struct super_block * s) +static inline void spin_lock_eflush(const struct super_block *s) { - reiser4_super_info_data * sbinfo = get_super_private (s); + reiser4_super_info_data *sbinfo = get_super_private(s); spin_lock_super_eflush(sbinfo); } /* * unlock emergency flush data-structures for super block @s */ -static inline void spin_unlock_eflush(const struct super_block * s) +static inline void spin_unlock_eflush(const struct super_block *s) { - reiser4_super_info_data * sbinfo = get_super_private (s); + reiser4_super_info_data *sbinfo = get_super_private(s); spin_unlock_super_eflush(sbinfo); } +#endif - -extern __u64 flush_reserved ( const struct super_block*); +extern __u64 flush_reserved(const struct super_block *); extern int reiser4_is_set(const struct super_block *super, reiser4_fs_flag f); extern long statfs_type(const struct super_block *super); extern __u64 reiser4_block_count(const struct super_block *super); @@ -476,7 +437,8 @@ extern __u64 reiser4_fake_allocated(cons extern __u64 reiser4_fake_allocated_unformatted(const struct super_block *); extern __u64 reiser4_clustered_blocks(const struct super_block *); -extern long reiser4_reserved_blocks(const struct super_block *super, uid_t uid, gid_t gid); +extern long reiser4_reserved_blocks(const struct super_block *super, uid_t uid, + gid_t gid); extern reiser4_space_allocator *get_space_allocator(const struct super_block *super); @@ -484,12 +446,25 @@ extern reiser4_oid_allocator *get_oid_al *super); extern struct inode *get_super_fake(const struct super_block *super); extern struct inode *get_cc_fake(const struct super_block *super); +extern struct inode *get_bitmap_fake(const struct super_block *super); extern reiser4_tree *get_tree(const struct super_block *super); extern int is_reiser4_super(const struct super_block *super); -extern int reiser4_blocknr_is_sane(const reiser4_block_nr *blk); +extern int reiser4_blocknr_is_sane(const reiser4_block_nr * blk); extern int reiser4_blocknr_is_sane_for(const struct super_block *super, - const reiser4_block_nr *blk); + const reiser4_block_nr * blk); +extern int reiser4_fill_super(struct super_block *s, void *data, int silent); +extern int reiser4_done_super(struct super_block *s); +extern reiser4_plugin * get_default_plugin(pset_member memb); + +/* step of fill super */ +extern int init_fs_info(struct super_block *); +extern void done_fs_info(struct super_block *); +extern int init_super_data(struct super_block *, char *opt_string); +extern int init_read_super(struct super_block *, int silent); +extern int init_root_inode(struct super_block *); +extern void done_root_inode(struct super_block *); + /* Maximal possible object id. */ #define ABSOLUTE_MAX_OID ((oid_t)~0) @@ -504,7 +479,6 @@ void oid_count_released(void); long oids_used(const struct super_block *); long oids_free(const struct super_block *); - #if REISER4_DEBUG void print_fs_info(const char *prefix, const struct super_block *); #endif @@ -513,28 +487,29 @@ void print_fs_info(const char *prefix, c void inc_unalloc_unfm_ptr(void); void dec_unalloc_unfm_ptrs(int nr); -void inc_unfm_ef(void); -void dec_unfm_ef(void); #else #define inc_unalloc_unfm_ptr() noop #define dec_unalloc_unfm_ptrs(nr) noop -#define inc_unfm_ef() noop -#define dec_unfm_ef() noop #endif +extern void destroy_reiser4_cache(kmem_cache_t **); + +extern struct super_operations reiser4_super_operations; +extern struct export_operations reiser4_export_operations; +extern struct dentry_operations reiser4_dentry_operations; /* __REISER4_SUPER_H__ */ #endif -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - End: -*/ +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 120 + * End: + */ diff -puN /dev/null fs/reiser4/super_ops.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ devel-akpm/fs/reiser4/super_ops.c 2005-09-15 19:51:08.000000000 -0700 @@ -0,0 +1,703 @@ +/* Copyright 2005 by Hans Reiser, licensing governed by + * reiser4/README */ + +#include "inode.h" +#include "page_cache.h" +#include "ktxnmgrd.h" +#include "flush.h" +#include "emergency_flush.h" +#include "safe_link.h" + +#include +#include +#include +#include + +/* slab cache for inodes */ +static kmem_cache_t *inode_cache; + +/** + * init_once - constructor for reiser4 inodes + * @obj: inode to be initialized + * @cache: cache @obj belongs to + * @flags: SLAB flags + * + * Initialization function to be called when new page is allocated by reiser4 + * inode cache. It is set on inode cache creation. + */ +static void init_once(void *obj, kmem_cache_t *cache, unsigned long flags) +{ + reiser4_inode_object *info; + + info = obj; + + if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) == + SLAB_CTOR_CONSTRUCTOR) { + /* initialize vfs inode */ + inode_init_once(&info->vfs_inode); + + /* + * initialize reiser4 specific part fo inode. + * NOTE-NIKITA add here initializations for locks, list heads, + * etc. that will be added to our private inode part. + */ + INIT_LIST_HEAD(get_readdir_list(&info->vfs_inode)); + init_rwsem(&info->p.coc_sem); + /* init semaphore which is used during inode loading */ + loading_init_once(&info->p); + INIT_RADIX_TREE(jnode_tree_by_reiser4_inode(&info->p), + GFP_ATOMIC); +#if REISER4_DEBUG + info->p.nr_jnodes = 0; +#endif + } +} + +/** + * init_inodes - create znode cache + * + * Initializes slab cache of inodes. It is part of reiser4 module initialization. + */ +static int init_inodes(void) +{ + inode_cache = kmem_cache_create("reiser4_inode", + sizeof(reiser4_inode_object), + 0, + SLAB_HWCACHE_ALIGN | + SLAB_RECLAIM_ACCOUNT, init_once, NULL); + if (inode_cache == NULL) + return RETERR(-ENOMEM); + return 0; +} + +/** + * done_inodes - delete inode cache + * + * This is called on reiser4 module unloading or system shutdown. + */ +static void done_inodes(void) +{ + destroy_reiser4_cache(&inode_cache); +} + +/** + * reiser4_alloc_inode - alloc_inode of super operations + * @super: super block new inode is allocated for + * + * Allocates new inode, initializes reiser4 specific part of it. + */ +static struct inode *reiser4_alloc_inode(struct super_block *super) +{ + reiser4_inode_object *obj; + + assert("nikita-1696", super != NULL); + obj = kmem_cache_alloc(inode_cache, SLAB_KERNEL); + if (obj != NULL) { + reiser4_inode *info; + + info = &obj->p; + + info->hset = info->pset = plugin_set_get_empty(); + info->extmask = 0; + info->locality_id = 0ull; + info->plugin_mask = 0; +#if !REISER4_INO_IS_OID + info->oid_hi = 0; +#endif + seal_init(&info->sd_seal, NULL, NULL); + coord_init_invalid(&info->sd_coord, NULL); + info->flags = 0; + spin_inode_object_init(info); + /* this deals with info's loading semaphore */ + loading_alloc(info); + info->vroot = UBER_TREE_ADDR; + return &obj->vfs_inode; + } else + return NULL; +} + +/** + * reiser4_destroy_inode - destroy_inode of super operations + * @inode: inode being destroyed + * + * Puts reiser4 specific portion of inode, frees memory occupied by inode. + */ +static void reiser4_destroy_inode(struct inode *inode) +{ + reiser4_inode *info; + + info = reiser4_inode_data(inode); + + assert("vs-1220", inode_has_no_jnodes(info)); + + if (!is_bad_inode(inode) && is_inode_loaded(inode)) { + file_plugin *fplug = inode_file_plugin(inode); + if (fplug->destroy_inode != NULL) + fplug->destroy_inode(inode); + } + dispose_cursors(inode); + if (info->pset) + plugin_set_put(info->pset); + + /* + * cannot add similar assertion about ->i_list as prune_icache return + * inode into slab with dangling ->list.{next,prev}. This is safe, + * because they are re-initialized in the new_inode(). + */ + assert("nikita-2895", list_empty(&inode->i_dentry)); + assert("nikita-2896", hlist_unhashed(&inode->i_hash)); + assert("nikita-2898", list_empty_careful(get_readdir_list(inode))); + + /* this deals with info's loading semaphore */ + loading_destroy(info); + + kmem_cache_free(inode_cache, + container_of(info, reiser4_inode_object, p)); +} + +/** + * reiser4_dirty_inode - dirty_inode of super operations + * @inode: inode being dirtied + * + * Updates stat data. + */ +static void reiser4_dirty_inode(struct inode *inode) +{ + int result; + + if (!is_in_reiser4_context()) + return; + assert("", !IS_RDONLY(inode)); + assert("", (inode_file_plugin(inode)->estimate.update(inode) <= + get_current_context()->grabbed_blocks)); + + result = reiser4_update_sd(inode); + if (result) + warning("", "failed to dirty inode for %llu: %d", + get_inode_oid(inode), result); +} + +/** + * reiser4_delete_inode - delete_inode of super operations + * @inode: inode to delete + * + * Calls file plugin's delete_object method to delete object items from + * filesystem tree and calls clear_inode. + */ +static void reiser4_delete_inode(struct inode *inode) +{ + reiser4_context *ctx; + file_plugin *fplug; + + ctx = init_context(inode->i_sb); + if (IS_ERR(ctx)) { + warning("vs-15", "failed to init context"); + return; + } + + if (is_inode_loaded(inode)) { + fplug = inode_file_plugin(inode); + if (fplug != NULL && fplug->delete_object != NULL) + fplug->delete_object(inode); + } + + inode->i_blocks = 0; + clear_inode(inode); + reiser4_exit_context(ctx); +} + +/** + * reiser4_put_super - put_super of super operations + * @super: super block to free + * + * Stops daemons, release resources, umounts in short. + */ +static void reiser4_put_super(struct super_block *super) +{ + reiser4_super_info_data *sbinfo; + reiser4_context *ctx; + + sbinfo = get_super_private(super); + assert("vs-1699", sbinfo); + + ctx = init_context(super); + if (IS_ERR(ctx)) { + warning("vs-17", "failed to init context"); + return; + } + + /* have disk format plugin to free its resources */ + if (get_super_private(super)->df_plug->release) + get_super_private(super)->df_plug->release(super); + + done_formatted_fake(super); + + /* stop daemons: ktxnmgr and entd */ + done_entd(super); + done_ktxnmgrd(super); + done_txnmgr(&sbinfo->tmgr); + + done_fs_info(super); + reiser4_exit_context(ctx); +} + +/** + * reiser4_write_super - write_super of super operations + * @super: super block to write + * + * Captures znode associated with super block, comit all transactions. + */ +static void reiser4_write_super(struct super_block *super) +{ + int ret; + reiser4_context *ctx; + + assert("vs-1700", !rofs_super(super)); + + ctx = init_context(super); + if (IS_ERR(ctx)) { + warning("vs-16", "failed to init context"); + return; + } + + ret = capture_super_block(super); + if (ret != 0) + warning("vs-1701", + "capture_super_block failed in write_super: %d", ret); + ret = txnmgr_force_commit_all(super, 1); + if (ret != 0) + warning("jmacd-77113", + "txn_force failed in write_super: %d", ret); + + super->s_dirt = 0; + + reiser4_exit_context(ctx); +} + +/** + * reiser4_statfs - statfs of super operations + * @super: super block of file system in queried + * @stafs: buffer to fill with statistics + * + * Returns information about filesystem. + */ +static int reiser4_statfs(struct super_block *super, struct kstatfs *statfs) +{ + sector_t total; + sector_t reserved; + sector_t free; + sector_t forroot; + sector_t deleted; + reiser4_context *ctx; + + assert("nikita-408", super != NULL); + assert("nikita-409", statfs != NULL); + + ctx = init_context(super); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + statfs->f_type = statfs_type(super); + statfs->f_bsize = super->s_blocksize; + + /* + * 5% of total block space is reserved. This is needed for flush and + * for truncates (so that we are able to perform truncate/unlink even + * on the otherwise completely full file system). If this reservation + * is hidden from statfs(2), users will mistakenly guess that they + * have enough free space to complete some operation, which is + * frustrating. + * + * Another possible solution is to subtract ->blocks_reserved from + * ->f_bfree, but changing available space seems less intrusive than + * letting user to see 5% of disk space to be used directly after + * mkfs. + */ + total = reiser4_block_count(super); + reserved = get_super_private(super)->blocks_reserved; + deleted = txnmgr_count_deleted_blocks(); + free = reiser4_free_blocks(super) + deleted; + forroot = reiser4_reserved_blocks(super, 0, 0); + + /* + * These counters may be in inconsistent state because we take the + * values without keeping any global spinlock. Here we do a sanity + * check that free block counter does not exceed the number of all + * blocks. + */ + if (free > total) + free = total; + statfs->f_blocks = total - reserved; + /* make sure statfs->f_bfree is never larger than statfs->f_blocks */ + if (free > reserved) + free -= reserved; + else + free = 0; + statfs->f_bfree = free; + + if (free > forroot) + free -= forroot; + else + free = 0; + statfs->f_bavail = free; + + statfs->f_files = 0; + statfs->f_ffree = 0; + + /* maximal acceptable name length depends on directory plugin. */ + assert("nikita-3351", super->s_root->d_inode != NULL); + statfs->f_namelen = reiser4_max_filename_len(super->s_root->d_inode); + reiser4_exit_context(ctx); + return 0; +} + +/** + * reiser4_clear_inode - clear_inode of super operation + * @inode: inode about to destroy + * + * Does sanity checks: being destroyed should have all jnodes detached. + */ +static void reiser4_clear_inode(struct inode *inode) +{ +#if REISER4_DEBUG + reiser4_inode *r4_inode; + + r4_inode = reiser4_inode_data(inode); + if (!inode_has_no_jnodes(r4_inode)) + warning("vs-1732", "reiser4 inode has %ld jnodes\n", + r4_inode->nr_jnodes); +#endif +} + +/** + * reiser4_sync_inodes - sync_inodes of super operations + * @super: + * @wbc: + * + * This method is called by background and non-backgound writeback. Reiser4's + * implementation uses generic_sync_sb_inodes to call reiser4_writepages for + * each of dirty inodes. Reiser4_writepages handles pages dirtied via shared + * mapping - dirty pages get into atoms. Writeout is called to flush some + * atoms. + */ +static void reiser4_sync_inodes(struct super_block *super, + struct writeback_control *wbc) +{ + reiser4_context *ctx; + long to_write; + + if (wbc->for_kupdate) + /* reiser4 has its own means of periodical write-out */ + return; + + to_write = wbc->nr_to_write; + assert("vs-49", wbc->older_than_this == NULL); + + ctx = init_context(super); + if (IS_ERR(ctx)) { + warning("vs-13", "failed to init context"); + return; + } + + /* + * call reiser4_writepages for each of dirty inodes to turn dirty pages + * into transactions if they were not yet. + */ + generic_sync_sb_inodes(super, wbc); + + /* flush goes here */ + wbc->nr_to_write = to_write; + writeout(super, wbc); + + /* avoid recursive calls to ->sync_inodes */ + context_set_commit_async(ctx); + reiser4_exit_context(ctx); +} + +/** + * reiser4_show_options - show_options of super operations + * @m: file where to write information + * @mnt: mount structure + * + * Makes reiser4 mount options visible in /proc/mounts. + */ +static int reiser4_show_options(struct seq_file *m, struct vfsmount *mnt) +{ + struct super_block *super; + reiser4_super_info_data *sbinfo; + + super = mnt->mnt_sb; + sbinfo = get_super_private(super); + + seq_printf(m, ",atom_max_size=0x%x", sbinfo->tmgr.atom_max_size); + seq_printf(m, ",atom_max_age=0x%x", sbinfo->tmgr.atom_max_age); + seq_printf(m, ",atom_min_size=0x%x", sbinfo->tmgr.atom_min_size); + seq_printf(m, ",atom_max_flushers=0x%x", + sbinfo->tmgr.atom_max_flushers); + seq_printf(m, ",cbk_cache_slots=0x%x", + sbinfo->tree.cbk_cache.nr_slots); + + return 0; +} + +struct super_operations reiser4_super_operations = { + .alloc_inode = reiser4_alloc_inode, + .destroy_inode = reiser4_destroy_inode, + .dirty_inode = reiser4_dirty_inode, + .delete_inode = reiser4_delete_inode, + .put_super = reiser4_put_super, + .write_super = reiser4_write_super, + .statfs = reiser4_statfs, + .clear_inode = reiser4_clear_inode, + .sync_inodes = reiser4_sync_inodes, + .show_options = reiser4_show_options +}; + +/** + * fill_super - initialize super block on mount + * @super: super block to fill + * @data: reiser4 specific mount option + * @silent: + * + * This is to be called by reiser4_get_sb. Mounts filesystem. + */ +static int fill_super(struct super_block *super, void *data, int silent) +{ + reiser4_context ctx; + int result; + reiser4_super_info_data *sbinfo; + + assert("zam-989", super != NULL); + + super->s_op = NULL; + init_stack_context(&ctx, super); + + /* allocate reiser4 specific super block */ + if ((result = init_fs_info(super)) != 0) + goto failed_init_sinfo; + + sbinfo = get_super_private(super); + /* initialize various reiser4 parameters, parse mount options */ + if ((result = init_super_data(super, data)) != 0) + goto failed_init_super_data; + + /* read reiser4 master super block, initialize disk format plugin */ + if ((result = init_read_super(super, silent)) != 0) + goto failed_init_read_super; + + /* initialize transaction manager */ + init_txnmgr(&sbinfo->tmgr); + + /* initialize ktxnmgrd context and start kernel thread ktxnmrgd */ + init_ktxnmgrd(super); + + /* initialize entd context and start kernel thread entd */ + init_entd(super); + + /* initialize address spaces for formatted nodes and bitmaps */ + if ((result = init_formatted_fake(super)) != 0) + goto failed_init_formatted_fake; + + /* initialize disk format plugin */ + if ((result = get_super_private(super)->df_plug->init_format(super, data)) != 0 ) + goto failed_init_disk_format; + + /* + * There are some 'committed' versions of reiser4 super block counters, + * which correspond to reiser4 on-disk state. These counters are + * initialized here + */ + sbinfo->blocks_free_committed = sbinfo->blocks_free; + sbinfo->nr_files_committed = oids_used(super); + + /* get inode of root directory */ + if ((result = init_root_inode(super)) != 0) + goto failed_init_root_inode; + + process_safelinks(super); + reiser4_exit_context(&ctx); + return 0; + + failed_init_root_inode: + if (sbinfo->df_plug->release) + sbinfo->df_plug->release(super); + failed_init_disk_format: + done_formatted_fake(super); + failed_init_formatted_fake: + done_entd(super); + done_ktxnmgrd(super); + done_txnmgr(&sbinfo->tmgr); + failed_init_read_super: + failed_init_super_data: + done_fs_info(super); + failed_init_sinfo: + reiser4_exit_context(&ctx); + return result; +} + +/** + * reiser4_get_sb - get_sb of file_system_type operations + * @fs_type: + * @flags: mount flags MS_RDONLY, MS_VERBOSE, etc + * @dev_name: block device file name + * @data: specific mount options + * + * Reiser4 mount entry. + */ +static struct super_block *reiser4_get_sb(struct file_system_type *fs_type, + int flags, + const char *dev_name, + void *data) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, fill_super); +} + +/* structure describing the reiser4 filesystem implementation */ +static struct file_system_type reiser4_fs_type = { + .owner = THIS_MODULE, + .name = "reiser4", + .fs_flags = FS_REQUIRES_DEV, + .get_sb = reiser4_get_sb, + .kill_sb = kill_block_super, + .next = NULL +}; + +void destroy_reiser4_cache(kmem_cache_t **cachep) +{ + int result; + + BUG_ON(*cachep == NULL); + result = kmem_cache_destroy(*cachep); + BUG_ON(result != 0); + *cachep = NULL; +} + +/** + * init_reiser4 - reiser4 initialization entry point + * + * Initializes reiser4 slabs, registers reiser4 filesystem type. It is called + * on kernel initialization or during reiser4 module load. + */ +static int __init init_reiser4(void) +{ + int result; + + printk(KERN_INFO + "Loading Reiser4. " + "See www.namesys.com for a description of Reiser4.\n"); + + /* initialize slab cache of inodes */ + if ((result = init_inodes()) != 0) + goto failed_inode_cache; + + /* initialize cache of znodes */ + if ((result = init_znodes()) != 0) + goto failed_init_znodes; + + /* initialize all plugins */ + if ((result = init_plugins()) != 0) + goto failed_init_plugins; + + /* initialize cache of plugin_set-s and plugin_set's hash table */ + if ((result = init_plugin_set()) != 0) + goto failed_init_plugin_set; + + /* initialize caches of txn_atom-s and txn_handle-s */ + if ((result = init_txnmgr_static()) != 0) + goto failed_init_txnmgr_static; + + /* initialize cache of jnodes */ + if ((result = init_jnodes()) != 0) + goto failed_init_jnodes; + + /* initialize cache of eflush nodes */ + if ((result = init_eflush()) != 0) + goto failed_init_eflush; + + /* initialize cache of flush queues */ + if ((result = init_fqs()) != 0) + goto failed_init_fqs; + + /* initialize cache of structures attached to dentry->d_fsdata */ + if ((result = init_dentry_fsdata()) != 0) + goto failed_init_dentry_fsdata; + + /* initialize cache of structures attached to file->private_data */ + if ((result = init_file_fsdata()) != 0) + goto failed_init_file_fsdata; + + /* + * initialize cache of d_cursors. See plugin/file_ops_readdir.c for + * more details + */ + if ((result = init_d_cursor()) != 0) + goto failed_init_d_cursor; + + if ((result = register_filesystem(&reiser4_fs_type)) == 0) + return 0; + + done_d_cursor(); + failed_init_d_cursor: + done_file_fsdata(); + failed_init_file_fsdata: + done_dentry_fsdata(); + failed_init_dentry_fsdata: + done_fqs(); + failed_init_fqs: + done_eflush(); + failed_init_eflush: + done_jnodes(); + failed_init_jnodes: + done_txnmgr_static(); + failed_init_txnmgr_static: + done_plugin_set(); + failed_init_plugin_set: + failed_init_plugins: + done_znodes(); + failed_init_znodes: + done_inodes(); + failed_inode_cache: + return result; +} + +/** + * done_reiser4 - reiser4 exit entry point + * + * Unregister reiser4 filesystem type, deletes caches. It is called on shutdown + * or at module unload. + */ +static void __exit done_reiser4(void) +{ + int result; + + result = unregister_filesystem(&reiser4_fs_type); + BUG_ON(result != 0); + done_d_cursor(); + done_file_fsdata(); + done_dentry_fsdata(); + done_fqs(); + done_eflush(); + done_jnodes(); + done_txnmgr_static(); + done_plugin_set(); + done_znodes(); + destroy_reiser4_cache(&inode_cache); +} + +module_init(init_reiser4); +module_exit(done_reiser4); + +MODULE_DESCRIPTION("Reiser4 filesystem"); +MODULE_AUTHOR("Hans Reiser "); + +MODULE_LICENSE("GPL"); + +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 79 + * End: + */ diff -puN fs/reiser4/tap.c~reiser4-big-update fs/reiser4/tap.c --- devel/fs/reiser4/tap.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/tap.c 2005-09-15 19:51:08.000000000 -0700 @@ -30,8 +30,7 @@ static void tap_check(const tap_t * tap) #endif /** load node tap is pointing to, if not loaded already */ -reiser4_internal int -tap_load(tap_t * tap) +int tap_load(tap_t * tap) { tap_check(tap); if (tap->loaded == 0) { @@ -48,8 +47,7 @@ tap_load(tap_t * tap) } /** release node tap is pointing to. Dual to tap_load() */ -reiser4_internal void -tap_relse(tap_t * tap) +void tap_relse(tap_t * tap) { tap_check(tap); if (tap->loaded > 0) { @@ -65,47 +63,44 @@ tap_relse(tap_t * tap) * init tap to consist of @coord and @lh. Locks on nodes will be acquired with * @mode */ -reiser4_internal void +void tap_init(tap_t * tap, coord_t * coord, lock_handle * lh, znode_lock_mode mode) { - tap->coord = coord; - tap->lh = lh; - tap->mode = mode; + tap->coord = coord; + tap->lh = lh; + tap->mode = mode; tap->loaded = 0; - tap_list_clean(tap); + INIT_LIST_HEAD(&tap->linkage); init_ra_info(&tap->ra_info); } /** add @tap to the per-thread list of all taps */ -reiser4_internal void -tap_monitor(tap_t * tap) +void tap_monitor(tap_t * tap) { assert("nikita-2623", tap != NULL); tap_check(tap); - tap_list_push_front(taps_list(), tap); + list_add(&tap->linkage, taps_list()); tap_check(tap); } /* duplicate @src into @dst. Copy lock handle. @dst is not initially * loaded. */ -reiser4_internal void -tap_copy(tap_t * dst, tap_t * src) +void tap_copy(tap_t * dst, tap_t * src) { assert("nikita-3193", src != NULL); assert("nikita-3194", dst != NULL); - *dst->coord = *src->coord; + *dst->coord = *src->coord; if (src->lh->node) copy_lh(dst->lh, src->lh); - dst->mode = src->mode; - dst->loaded = 0; - tap_list_clean(dst); + dst->mode = src->mode; + dst->loaded = 0; + INIT_LIST_HEAD(&dst->linkage); dst->ra_info = src->ra_info; } /** finish with @tap */ -reiser4_internal void -tap_done(tap_t * tap) +void tap_done(tap_t * tap) { assert("nikita-2565", tap != NULL); tap_check(tap); @@ -113,7 +108,7 @@ tap_done(tap_t * tap) zrelse(tap->coord->node); done_lh(tap->lh); tap->loaded = 0; - tap_list_remove_clean(tap); + list_del_init(&tap->linkage); tap->coord->node = NULL; } @@ -121,8 +116,7 @@ tap_done(tap_t * tap) * move @tap to the new node, locked with @target. Load @target, if @tap was * already loaded. */ -reiser4_internal int -tap_move(tap_t * tap, lock_handle * target) +int tap_move(tap_t * tap, lock_handle * target) { int result = 0; @@ -151,8 +145,7 @@ tap_move(tap_t * tap, lock_handle * targ * move @tap to @target. Acquire lock on @target, if @tap was already * loaded. */ -static int -tap_to(tap_t * tap, znode * target) +static int tap_to(tap_t * tap, znode * target) { int result; @@ -180,8 +173,7 @@ tap_to(tap_t * tap, znode * target) * move @tap to given @target, loading and locking @target->node if * necessary */ -reiser4_internal int -tap_to_coord(tap_t * tap, coord_t * target) +int tap_to_coord(tap_t * tap, coord_t * target) { int result; @@ -194,15 +186,13 @@ tap_to_coord(tap_t * tap, coord_t * targ } /** return list of all taps */ -reiser4_internal tap_list_head * -taps_list(void) +struct list_head *taps_list(void) { return &get_current_context()->taps; } /** helper function for go_{next,prev}_{item,unit,node}() */ -reiser4_internal int -go_dir_el(tap_t * tap, sideof dir, int units_p) +int go_dir_el(tap_t * tap, sideof dir, int units_p) { coord_t dup; coord_t *coord; @@ -228,7 +218,8 @@ go_dir_el(tap_t * tap, sideof dir, int u get_dir_neighbor = reiser4_get_right_neighbor; coord_init = coord_init_first_unit; } - ON_DEBUG(coord_check = units_p ? coord_is_existing_unit : coord_is_existing_item); + ON_DEBUG(coord_check = + units_p ? coord_is_existing_unit : coord_is_existing_item); assert("nikita-2560", coord_check(tap->coord)); coord = tap->coord; @@ -239,8 +230,9 @@ go_dir_el(tap_t * tap, sideof dir, int u lock_handle dup; init_lh(&dup); - result = get_dir_neighbor( - &dup, coord->node, (int) tap->mode, GN_CAN_USE_UPPER_LEVELS); + result = + get_dir_neighbor(&dup, coord->node, (int)tap->mode, + GN_CAN_USE_UPPER_LEVELS); if (result == 0) { result = tap_move(tap, &dup); if (result == 0) @@ -262,8 +254,7 @@ go_dir_el(tap_t * tap, sideof dir, int u * move @tap to the next unit, transparently crossing item and node * boundaries */ -reiser4_internal int -go_next_unit(tap_t * tap) +int go_next_unit(tap_t * tap) { return go_dir_el(tap, RIGHT_SIDE, 1); } @@ -272,8 +263,7 @@ go_next_unit(tap_t * tap) * move @tap to the previous unit, transparently crossing item and node * boundaries */ -reiser4_internal int -go_prev_unit(tap_t * tap) +int go_prev_unit(tap_t * tap) { return go_dir_el(tap, LEFT_SIDE, 1); } @@ -282,8 +272,7 @@ go_prev_unit(tap_t * tap) * @shift times apply @actor to the @tap. This is used to move @tap by * @shift units (or items, or nodes) in either direction. */ -static int -rewind_to(tap_t * tap, go_actor_t actor, int shift) +static int rewind_to(tap_t * tap, go_actor_t actor, int shift) { int result; @@ -307,30 +296,29 @@ rewind_to(tap_t * tap, go_actor_t actor, } /** move @tap @shift units rightward */ -reiser4_internal int -rewind_right(tap_t * tap, int shift) +int rewind_right(tap_t * tap, int shift) { return rewind_to(tap, go_next_unit, shift); } /** move @tap @shift units leftward */ -reiser4_internal int -rewind_left(tap_t * tap, int shift) +int rewind_left(tap_t * tap, int shift) { return rewind_to(tap, go_prev_unit, shift); } #if REISER4_DEBUG /** debugging function: print @tap content in human readable form */ -static void -print_tap(const char * prefix, const tap_t * tap) +static void print_tap(const char *prefix, const tap_t * tap) { if (tap == NULL) { printk("%s: null tap\n", prefix); return; } printk("%s: loaded: %i, in-list: %i, node: %p, mode: %s\n", prefix, - tap->loaded, tap_list_is_clean(tap), tap->lh->node, + tap->loaded, (&tap->linkage == tap->linkage.next && + &tap->linkage == tap->linkage.prev), + tap->lh->node, lock_mode_name(tap->mode)); print_coord("\tcoord", tap->coord, 0); } diff -puN fs/reiser4/tap.h~reiser4-big-update fs/reiser4/tap.h --- devel/fs/reiser4/tap.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/tap.h 2005-09-15 19:51:08.000000000 -0700 @@ -6,11 +6,8 @@ #define __REISER4_TAP_H__ #include "forward.h" -#include "type_safe_list.h" #include "readahead.h" -TYPE_SAFE_LIST_DECLARE(tap); - /** tree_access_pointer aka tap. Data structure combining coord_t and lock handle. @@ -28,18 +25,17 @@ struct tree_access_pointer { /* incremented by tap_load(). Decremented by tap_relse(). */ int loaded; /* list of taps */ - tap_list_link linkage; + struct list_head linkage; /* read-ahead hint */ ra_info_t ra_info; }; -TYPE_SAFE_LIST_DEFINE(tap, tap_t, linkage); - typedef int (*go_actor_t) (tap_t * tap); extern int tap_load(tap_t * tap); extern void tap_relse(tap_t * tap); -extern void tap_init(tap_t * tap, coord_t * coord, lock_handle * lh, znode_lock_mode mode); +extern void tap_init(tap_t * tap, coord_t * coord, lock_handle * lh, + znode_lock_mode mode); extern void tap_monitor(tap_t * tap); extern void tap_copy(tap_t * dst, tap_t * src); extern void tap_done(tap_t * tap); @@ -52,12 +48,12 @@ extern int go_prev_unit(tap_t * tap); extern int rewind_right(tap_t * tap, int shift); extern int rewind_left(tap_t * tap, int shift); -extern tap_list_head *taps_list(void); +extern struct list_head *taps_list(void); -#define for_all_taps( tap ) \ - for (tap = tap_list_front ( taps_list() ); \ - ! tap_list_end ( taps_list(), tap ); \ - tap = tap_list_next ( tap ) ) +#define for_all_taps(tap) \ + for (tap = list_entry(taps_list()->next, tap_t, linkage); \ + taps_list() != &tap->linkage; \ + tap = list_entry(tap->linkage.next, tap_t, linkage)) /* __REISER4_TAP_H__ */ #endif diff -puN fs/reiser4/tree.c~reiser4-big-update fs/reiser4/tree.c --- devel/fs/reiser4/tree.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/tree.c 2005-09-15 19:51:08.000000000 -0700 @@ -208,8 +208,7 @@ const reiser4_block_nr UBER_TREE_ADDR = static int find_child_by_addr(znode * parent, znode * child, coord_t * result); /* return node plugin of coord->node */ -reiser4_internal node_plugin * -node_plugin_by_coord(const coord_t * coord) +node_plugin *node_plugin_by_coord(const coord_t * coord) { assert("vs-1", coord != NULL); assert("vs-2", coord->node != NULL); @@ -219,15 +218,14 @@ node_plugin_by_coord(const coord_t * coo /* insert item into tree. Fields of @coord are updated so that they can be * used by consequent insert operation. */ -reiser4_internal insert_result -insert_by_key(reiser4_tree * tree /* tree to insert new item +insert_result insert_by_key(reiser4_tree * tree /* tree to insert new item * into */ , const reiser4_key * key /* key of new item */ , reiser4_item_data * data /* parameters for item * creation */ , coord_t * coord /* resulting insertion coord */ , lock_handle * lh /* resulting lock - * handle */ , + * handle */ , tree_level stop_level /** level where to insert */ , __u32 flags /* insertion flags */ ) { @@ -237,7 +235,8 @@ insert_by_key(reiser4_tree * tree /* tre assert("nikita-360", coord != NULL); result = coord_by_key(tree, key, coord, lh, ZNODE_WRITE_LOCK, - FIND_EXACT, stop_level, stop_level, flags | CBK_FOR_INSERT, 0/*ra_info*/); + FIND_EXACT, stop_level, stop_level, + flags | CBK_FOR_INSERT, NULL /*ra_info */ ); switch (result) { default: break; @@ -254,50 +253,55 @@ insert_by_key(reiser4_tree * tree /* tre /* insert item by calling carry. Helper function called if short-cut insertion failed */ -static insert_result -insert_with_carry_by_coord(coord_t * coord /* coord where to insert */ , - lock_handle * lh /* lock handle of insertion - * node */ , - reiser4_item_data * data /* parameters of new - * item */ , - const reiser4_key * key /* key of new item */ , - carry_opcode cop /* carry operation to perform */ , - cop_insert_flag flags /* carry flags */) +static insert_result insert_with_carry_by_coord(coord_t * coord, /* coord where to insert */ + lock_handle * lh, /* lock handle of insertion + * node */ + reiser4_item_data * data, /* parameters of new + * item */ + const reiser4_key * key, /* key of new item */ + carry_opcode cop, /* carry operation to perform */ + cop_insert_flag flags + /* carry flags */ ) { int result; carry_pool *pool; - carry_level lowest_level; + carry_level *lowest_level; + carry_insert_data *cdata; carry_op *op; - carry_insert_data cdata; assert("umka-314", coord != NULL); - pool = init_carry_pool(); + /* allocate carry_pool and 3 carry_level-s */ + pool = + init_carry_pool(sizeof(*pool) + 3 * sizeof(*lowest_level) + + sizeof(*cdata)); if (IS_ERR(pool)) return PTR_ERR(pool); - init_carry_level(&lowest_level, pool); + lowest_level = (carry_level *) (pool + 1); + init_carry_level(lowest_level, pool); - op = post_carry(&lowest_level, cop, coord->node, 0); + op = post_carry(lowest_level, cop, coord->node, 0); if (IS_ERR(op) || (op == NULL)) { done_carry_pool(pool); return RETERR(op ? PTR_ERR(op) : -EIO); } - cdata.coord = coord; - cdata.data = data; - cdata.key = key; - op->u.insert.d = &cdata; + cdata = (carry_insert_data *) (lowest_level + 3); + cdata->coord = coord; + cdata->data = data; + cdata->key = key; + op->u.insert.d = cdata; if (flags == 0) flags = znode_get_tree(coord->node)->carry.insert_flags; op->u.insert.flags = flags; op->u.insert.type = COPT_ITEM_DATA; - op->u.insert.child = 0; + op->u.insert.child = NULL; if (lh != NULL) { assert("nikita-3245", lh->node == coord->node); - lowest_level.track_type = CARRY_TRACK_CHANGE; - lowest_level.tracked = lh; + lowest_level->track_type = CARRY_TRACK_CHANGE; + lowest_level->tracked = lh; } - result = carry(&lowest_level, 0); + result = carry(lowest_level, NULL); done_carry_pool(pool); return result; @@ -310,49 +314,52 @@ insert_with_carry_by_coord(coord_t * coo different block. */ -static int -paste_with_carry(coord_t * coord /* coord of paste */ , - lock_handle * lh /* lock handle of node - * where item is - * pasted */ , - reiser4_item_data * data /* parameters of new - * item */ , - const reiser4_key * key /* key of new item */ , - unsigned flags /* paste flags */ ) +static int paste_with_carry(coord_t * coord, /* coord of paste */ + lock_handle * lh, /* lock handle of node + * where item is + * pasted */ + reiser4_item_data * data, /* parameters of new + * item */ + const reiser4_key * key, /* key of new item */ + unsigned flags /* paste flags */ ) { int result; carry_pool *pool; - carry_level lowest_level; + carry_level *lowest_level; + carry_insert_data *cdata; carry_op *op; - carry_insert_data cdata; assert("umka-315", coord != NULL); assert("umka-316", key != NULL); - pool = init_carry_pool(); + pool = + init_carry_pool(sizeof(*pool) + 3 * sizeof(*lowest_level) + + sizeof(*cdata)); if (IS_ERR(pool)) return PTR_ERR(pool); - init_carry_level(&lowest_level, pool); + lowest_level = (carry_level *) (pool + 1); + init_carry_level(lowest_level, pool); - op = post_carry(&lowest_level, COP_PASTE, coord->node, 0); + op = post_carry(lowest_level, COP_PASTE, coord->node, 0); if (IS_ERR(op) || (op == NULL)) { done_carry_pool(pool); return RETERR(op ? PTR_ERR(op) : -EIO); } - cdata.coord = coord; - cdata.data = data; - cdata.key = key; - op->u.paste.d = &cdata; + cdata = (carry_insert_data *) (lowest_level + 3); + cdata->coord = coord; + cdata->data = data; + cdata->key = key; + op->u.paste.d = cdata; if (flags == 0) flags = znode_get_tree(coord->node)->carry.paste_flags; op->u.paste.flags = flags; op->u.paste.type = COPT_ITEM_DATA; if (lh != NULL) { - lowest_level.track_type = CARRY_TRACK_CHANGE; - lowest_level.tracked = lh; + lowest_level->track_type = CARRY_TRACK_CHANGE; + lowest_level->tracked = lh; } - result = carry(&lowest_level, 0); + result = carry(lowest_level, NULL); done_carry_pool(pool); return result; @@ -366,16 +373,15 @@ paste_with_carry(coord_t * coord /* coor that will do full carry(). */ -reiser4_internal insert_result -insert_by_coord(coord_t * coord /* coord where to - * insert. coord->node has - * to be write locked by - * caller */ , +insert_result insert_by_coord(coord_t * coord /* coord where to + * insert. coord->node has + * to be write locked by + * caller */ , reiser4_item_data * data /* data to be * inserted */ , const reiser4_key * key /* key of new item */ , lock_handle * lh /* lock handle of write - * lock on node */ , + * lock on node */ , __u32 flags /* insertion flags */ ) { unsigned item_size; @@ -395,7 +401,8 @@ insert_by_coord(coord_t * coord /* coord item_size = space_needed(node, NULL, data, 1); if (item_size > znode_free_space(node) && - (flags & COPI_DONT_SHIFT_LEFT) && (flags & COPI_DONT_SHIFT_RIGHT) && (flags & COPI_DONT_ALLOCATE)) { + (flags & COPI_DONT_SHIFT_LEFT) && (flags & COPI_DONT_SHIFT_RIGHT) + && (flags & COPI_DONT_ALLOCATE)) { /* we are forced to use free space of coord->node and new item does not fit into it. @@ -405,11 +412,12 @@ insert_by_coord(coord_t * coord /* coord have enough free space - we do not want to attempt any shifting and allocations because we are in squeezing and everything to the left of @node is tightly packed. - */ + */ result = -E_NODE_FULL; } else if ((item_size <= znode_free_space(node)) && !coord_is_before_leftmost(coord) && - (node_plugin_by_node(node)->fast_insert != NULL) && node_plugin_by_node(node)->fast_insert(coord)) { + (node_plugin_by_node(node)->fast_insert != NULL) + && node_plugin_by_node(node)->fast_insert(coord)) { /* shortcut insertion without carry() overhead. Only possible if: @@ -417,28 +425,36 @@ insert_by_coord(coord_t * coord /* coord - there is enough free space - insertion is not into the leftmost position in a node - (otherwise it would require updating of delimiting key in a - parent) + (otherwise it would require updating of delimiting key in a + parent) - node plugin agrees with this - */ - result = node_plugin_by_node(node)->create_item(coord, key, data, NULL); + */ + result = + node_plugin_by_node(node)->create_item(coord, key, data, + NULL); znode_make_dirty(node); } else { /* otherwise do full-fledged carry(). */ - result = insert_with_carry_by_coord(coord, lh, data, key, COP_INSERT, flags); + result = + insert_with_carry_by_coord(coord, lh, data, key, COP_INSERT, + flags); } zrelse(node); return result; } /* @coord is set to leaf level and @data is to be inserted to twig level */ -reiser4_internal insert_result -insert_extent_by_coord(coord_t * coord /* coord where to insert. coord->node * has to be write * locked by caller */ , - reiser4_item_data * data /* data to be inserted */ , +insert_result +insert_extent_by_coord(coord_t * + coord + /* coord where to insert. coord->node * has to be write * locked by caller */ + , + reiser4_item_data * data /* data to be inserted */ , const reiser4_key * key /* key of new item */ , - lock_handle * lh /* lock handle of write lock on * node */) + lock_handle * + lh /* lock handle of write lock on * node */ ) { assert("vs-405", coord != NULL); assert("vs-406", data != NULL); @@ -446,7 +462,8 @@ insert_extent_by_coord(coord_t * coord / assert("vs-408", znode_is_write_locked(coord->node)); assert("vs-409", znode_get_level(coord->node) == LEAF_LEVEL); - return insert_with_carry_by_coord(coord, lh, data, key, COP_EXTENT, 0 /*flags */ ); + return insert_with_carry_by_coord(coord, lh, data, key, COP_EXTENT, + 0 /*flags */ ); } /* Insert into the item at the given coord. @@ -458,12 +475,11 @@ insert_extent_by_coord(coord_t * coord / */ /* paste_into_item */ -reiser4_internal int -insert_into_item(coord_t * coord /* coord of pasting */ , - lock_handle * lh /* lock handle on node involved */ , - const reiser4_key * key /* key of unit being pasted */ , - reiser4_item_data * data /* parameters for new unit */ , - unsigned flags /* insert/paste flags */ ) +int insert_into_item(coord_t * coord /* coord of pasting */ , + lock_handle * lh /* lock handle on node involved */ , + const reiser4_key * key /* key of unit being pasted */ , + reiser4_item_data * data /* parameters for new unit */ , + unsigned flags /* insert/paste flags */ ) { int result; int size_change; @@ -479,8 +495,9 @@ insert_into_item(coord_t * coord /* coor assert("nikita-1480", iplug == data->iplug); size_change = space_needed(coord->node, coord, data, 0); - if (size_change > (int) znode_free_space(coord->node) && - (flags & COPI_DONT_SHIFT_LEFT) && (flags & COPI_DONT_SHIFT_RIGHT) && (flags & COPI_DONT_ALLOCATE)) { + if (size_change > (int)znode_free_space(coord->node) && + (flags & COPI_DONT_SHIFT_LEFT) && (flags & COPI_DONT_SHIFT_RIGHT) + && (flags & COPI_DONT_ALLOCATE)) { /* we are forced to use free space of coord->node and new data does not fit into it. */ return -E_NODE_FULL; @@ -498,8 +515,8 @@ insert_into_item(coord_t * coord /* coor - node plugin agrees with this - item plugin agrees with us - */ - if (size_change <= (int) znode_free_space(coord->node) && + */ + if (size_change <= (int)znode_free_space(coord->node) && (coord->item_pos != 0 || coord->unit_pos != 0 || coord->between == AFTER_UNIT) && coord->unit_pos != 0 && nplug->fast_paste != NULL && @@ -519,13 +536,12 @@ insert_into_item(coord_t * coord /* coor } /* this either appends or truncates item @coord */ -reiser4_internal int -resize_item(coord_t * coord /* coord of item being resized */ , - reiser4_item_data * data /* parameters of resize */ , - reiser4_key * key /* key of new unit */ , - lock_handle * lh /* lock handle of node - * being modified */ , - cop_insert_flag flags /* carry flags */ ) +int resize_item(coord_t * coord /* coord of item being resized */ , + reiser4_item_data * data /* parameters of resize */ , + reiser4_key * key /* key of new unit */ , + lock_handle * lh /* lock handle of node + * being modified */ , + cop_insert_flag flags /* carry flags */ ) { int result; znode *node; @@ -551,66 +567,70 @@ resize_item(coord_t * coord /* coord of } /* insert flow @f */ -reiser4_internal int -insert_flow(coord_t * coord, lock_handle * lh, flow_t * f) +int insert_flow(coord_t * coord, lock_handle * lh, flow_t * f) { int result; carry_pool *pool; - carry_level lowest_level; + carry_level *lowest_level; + reiser4_item_data *data; carry_op *op; - reiser4_item_data data; - pool = init_carry_pool(); + pool = + init_carry_pool(sizeof(*pool) + 3 * sizeof(*lowest_level) + + sizeof(*data)); if (IS_ERR(pool)) return PTR_ERR(pool); - init_carry_level(&lowest_level, pool); + lowest_level = (carry_level *) (pool + 1); + init_carry_level(lowest_level, pool); - op = post_carry(&lowest_level, COP_INSERT_FLOW, coord->node, 0 /* operate directly on coord -> node */ ); + op = post_carry(lowest_level, COP_INSERT_FLOW, coord->node, + 0 /* operate directly on coord -> node */ ); if (IS_ERR(op) || (op == NULL)) { done_carry_pool(pool); return RETERR(op ? PTR_ERR(op) : -EIO); } /* these are permanent during insert_flow */ - data.user = 1; - data.iplug = item_plugin_by_id(FORMATTING_ID); - data.arg = 0; + data = (reiser4_item_data *) (lowest_level + 3); + data->user = 1; + data->iplug = item_plugin_by_id(FORMATTING_ID); + data->arg = NULL; /* data.length and data.data will be set before calling paste or insert */ - data.length = 0; - data.data = 0; + data->length = 0; + data->data = NULL; op->u.insert_flow.flags = 0; op->u.insert_flow.insert_point = coord; op->u.insert_flow.flow = f; - op->u.insert_flow.data = &data; + op->u.insert_flow.data = data; op->u.insert_flow.new_nodes = 0; - lowest_level.track_type = CARRY_TRACK_CHANGE; - lowest_level.tracked = lh; + lowest_level->track_type = CARRY_TRACK_CHANGE; + lowest_level->tracked = lh; - result = carry(&lowest_level, 0); + result = carry(lowest_level, NULL); done_carry_pool(pool); return result; } /* Given a coord in parent node, obtain a znode for the corresponding child */ -reiser4_internal znode * -child_znode(const coord_t * parent_coord /* coord of pointer to +znode *child_znode(const coord_t * parent_coord /* coord of pointer to * child */ , - znode * parent /* parent of child */ , - int incore_p /* if !0 only return child if already in + znode * parent /* parent of child */ , + int incore_p /* if !0 only return child if already in * memory */ , - int setup_dkeys_p /* if !0 update delimiting keys of - * child */ ) + int setup_dkeys_p /* if !0 update delimiting keys of + * child */ ) { znode *child; assert("nikita-1374", parent_coord != NULL); assert("nikita-1482", parent != NULL); assert("nikita-1384", ergo(setup_dkeys_p, - rw_dk_is_not_locked(znode_get_tree(parent)))); + rw_dk_is_not_locked(znode_get_tree + (parent)))); assert("nikita-2947", znode_is_any_locked(parent)); if (znode_get_level(parent) <= LEAF_LEVEL) { @@ -632,7 +652,9 @@ child_znode(const coord_t * parent_coord if (incore_p) child = zlook(tree, &addr); else - child = zget(tree, &addr, parent, znode_get_level(parent) - 1, GFP_KERNEL); + child = + zget(tree, &addr, parent, + znode_get_level(parent) - 1, GFP_KERNEL); if ((child != NULL) && !IS_ERR(child) && setup_dkeys_p) set_child_delimiting_keys(parent, parent_coord, child); } else { @@ -644,11 +666,11 @@ child_znode(const coord_t * parent_coord } /* remove znode from transaction */ -static void uncapture_znode (znode * node) +static void uncapture_znode(znode * node) { - struct page * page; + struct page *page; - assert ("zam-1001", ZF_ISSET(node, JNODE_HEARD_BANSHEE)); + assert("zam-1001", ZF_ISSET(node, JNODE_HEARD_BANSHEE)); /* Get e-flush block allocation back before deallocating node's * block number. */ @@ -661,23 +683,25 @@ static void uncapture_znode (znode * nod int ret; /* An already allocated block goes right to the atom's delete set. */ - ret = reiser4_dealloc_block( - znode_get_block(node), 0, BA_DEFER | BA_FORMATTED); + ret = + reiser4_dealloc_block(znode_get_block(node), 0, + BA_DEFER | BA_FORMATTED); if (ret) - warning("zam-942", "can\'t add a block (%llu) number to atom's delete set\n", - (unsigned long long)(*znode_get_block(node))); + warning("zam-942", + "can\'t add a block (%llu) number to atom's delete set\n", + (unsigned long long)(*znode_get_block(node))); spin_lock_znode(node); /* Here we return flush reserved block which was reserved at the * moment when this allocated node was marked dirty and still * not used by flush in node relocation procedure. */ if (ZF_ISSET(node, JNODE_FLUSH_RESERVED)) { - txn_atom * atom ; + txn_atom *atom; atom = jnode_get_atom(ZJNODE(node)); assert("zam-939", atom != NULL); spin_unlock_znode(node); - flush_reserved2grabbed(atom, (__u64)1); + flush_reserved2grabbed(atom, (__u64) 1); UNLOCK_ATOM(atom); } else spin_unlock_znode(node); @@ -709,14 +733,15 @@ static void uncapture_znode (znode * nod unlock_page(page); page_cache_release(page); } else { - txn_atom * atom; + txn_atom *atom; /* handle "flush queued" znodes */ while (1) { atom = jnode_get_atom(ZJNODE(node)); assert("zam-943", atom != NULL); - if (!ZF_ISSET(node, JNODE_FLUSH_QUEUED) || !atom->nr_running_queues) + if (!ZF_ISSET(node, JNODE_FLUSH_QUEUED) + || !atom->nr_running_queues) break; spin_unlock_znode(node); @@ -733,8 +758,7 @@ static void uncapture_znode (znode * nod /* This is called from longterm_unlock_znode() when last lock is released from the node that has been removed from the tree. At this point node is removed from sibling list and its lock is invalidated. */ -reiser4_internal void -forget_znode(lock_handle * handle) +void forget_znode(lock_handle * handle) { znode *node; reiser4_tree *tree; @@ -779,10 +803,9 @@ forget_znode(lock_handle * handle) } /* Check that internal item at @pointer really contains pointer to @child. */ -reiser4_internal int -check_tree_pointer(const coord_t * pointer /* would-be pointer to - * @child */ , - const znode * child /* child znode */ ) +int check_tree_pointer(const coord_t * pointer /* would-be pointer to + * @child */ , + const znode * child /* child znode */ ) { assert("nikita-1016", pointer != NULL); assert("nikita-1017", child != NULL); @@ -819,11 +842,11 @@ check_tree_pointer(const coord_t * point be in. */ -reiser4_internal int -find_new_child_ptr(znode * parent /* parent znode, passed locked */ , - znode * child UNUSED_ARG /* child znode, passed locked */ , - znode * left /* left brother of new node */ , - coord_t * result /* where result is stored in */ ) +int find_new_child_ptr(znode * parent /* parent znode, passed locked */ , + znode * + child UNUSED_ARG /* child znode, passed locked */ , + znode * left /* left brother of new node */ , + coord_t * result /* where result is stored in */ ) { int ret; @@ -846,10 +869,9 @@ find_new_child_ptr(znode * parent /* par Find the &coord_t in the @parent where pointer to a given @child is in. */ -reiser4_internal int -find_child_ptr(znode * parent /* parent znode, passed locked */ , - znode * child /* child znode, passed locked */ , - coord_t * result /* where result is stored in */ ) +int find_child_ptr(znode * parent /* parent znode, passed locked */ , + znode * child /* child znode, passed locked */ , + coord_t * result /* where result is stored in */ ) { int lookup_res; node_plugin *nplug; @@ -918,10 +940,9 @@ find_child_ptr(znode * parent /* parent numbers in them with that of @child. */ -static int -find_child_by_addr(znode * parent /* parent znode, passed locked */ , - znode * child /* child znode, passed locked */ , - coord_t * result /* where result is stored in */ ) +static int find_child_by_addr(znode * parent /* parent znode, passed locked */ , + znode * child /* child znode, passed locked */ , + coord_t * result /* where result is stored in */ ) { int ret; @@ -945,19 +966,20 @@ find_child_by_addr(znode * parent /* par /* true, if @addr is "unallocated block number", which is just address, with highest bit set. */ -reiser4_internal int -is_disk_addr_unallocated(const reiser4_block_nr * addr /* address to - * check */ ) +int is_disk_addr_unallocated(const reiser4_block_nr * addr /* address to + * check */ ) { assert("nikita-1766", addr != NULL); - cassert(sizeof (reiser4_block_nr) == 8); - return (*addr & REISER4_BLOCKNR_STATUS_BIT_MASK) == REISER4_UNALLOCATED_STATUS_VALUE; + cassert(sizeof(reiser4_block_nr) == 8); + return (*addr & REISER4_BLOCKNR_STATUS_BIT_MASK) == + REISER4_UNALLOCATED_STATUS_VALUE; } /* returns true if removing bytes of given range of key [from_key, to_key] causes removing of whole item @from */ static int -item_removed_completely(coord_t * from, const reiser4_key * from_key, const reiser4_key * to_key) +item_removed_completely(coord_t * from, const reiser4_key * from_key, + const reiser4_key * to_key) { item_plugin *iplug; reiser4_key key_in_item; @@ -987,7 +1009,7 @@ item_removed_completely(coord_t * from, * neighbors of extent item being completely removed. Load and lock neighbors * and store lock handles into @cdata for later use by kill_hook_extent() */ static int -prepare_children(znode *left, znode *right, carry_kill_data *kdata) +prepare_children(znode * left, znode * right, carry_kill_data * kdata) { int result; int left_loaded; @@ -1011,7 +1033,8 @@ prepare_children(znode *left, znode *rig right_loaded = 1; result = longterm_lock_znode(kdata->right, right, ZNODE_READ_LOCK, - ZNODE_LOCK_HIPRI | ZNODE_LOCK_NONBLOCK); + ZNODE_LOCK_HIPRI | + ZNODE_LOCK_NONBLOCK); } } if (result != 0) { @@ -1025,8 +1048,7 @@ prepare_children(znode *left, znode *rig return result; } -static void -done_children(carry_kill_data *kdata) +static void done_children(carry_kill_data * kdata) { if (kdata->left != NULL && kdata->left->node != NULL) { zrelse(kdata->left->node); @@ -1047,7 +1069,7 @@ done_children(carry_kill_data *kdata) */ /* Audited by: umka (2002.06.16) */ static int -prepare_twig_kill(carry_kill_data *kdata, znode * locked_left_neighbor) +prepare_twig_kill(carry_kill_data * kdata, znode * locked_left_neighbor) { int result; reiser4_key key; @@ -1066,10 +1088,11 @@ prepare_twig_kill(carry_kill_data *kdata /* for one extent item only yet */ assert("vs-591", item_is_extent(from)); - assert ("vs-592", from->item_pos == kdata->params.to->item_pos); + assert("vs-592", from->item_pos == kdata->params.to->item_pos); - if ((kdata->params.from_key && keygt(kdata->params.from_key, item_key_by_coord(from, &key))) || - from->unit_pos != 0) { + if ((kdata->params.from_key + && keygt(kdata->params.from_key, item_key_by_coord(from, &key))) + || from->unit_pos != 0) { /* head of item @from is not removed, there is nothing to worry about */ return 0; @@ -1087,7 +1110,10 @@ prepare_twig_kill(carry_kill_data *kdata if (coord_prev_unit(&left_coord)) { /* @from is leftmost item in its node */ if (!locked_left_neighbor) { - result = reiser4_get_left_neighbor(&left_lh, from->node, ZNODE_READ_LOCK, GN_CAN_USE_UPPER_LEVELS); + result = + reiser4_get_left_neighbor(&left_lh, from->node, + ZNODE_READ_LOCK, + GN_CAN_USE_UPPER_LEVELS); switch (result) { case 0: break; @@ -1095,7 +1121,8 @@ prepare_twig_kill(carry_kill_data *kdata /* there is no formatted node to the left of from->node */ warning("vs-605", - "extent item has smallest key in " "the tree and it is about to be removed"); + "extent item has smallest key in " + "the tree and it is about to be removed"); return 0; case -E_DEADLOCK: /* need to restart */ @@ -1112,7 +1139,8 @@ prepare_twig_kill(carry_kill_data *kdata } else { /* squalloc_right_twig_cut should have supplied locked * left neighbor */ - assert("vs-834", znode_is_write_locked(locked_left_neighbor)); + assert("vs-834", + znode_is_write_locked(locked_left_neighbor)); result = zload(locked_left_neighbor); if (result) return result; @@ -1143,15 +1171,21 @@ prepare_twig_kill(carry_kill_data *kdata /* left child is acquired, calculate new right delimiting key for it and get right child if it is necessary */ - if (item_removed_completely(from, kdata->params.from_key, kdata->params.to_key)) { + if (item_removed_completely + (from, kdata->params.from_key, kdata->params.to_key)) { /* try to get right child of removed item */ coord_t right_coord; - assert("vs-607", kdata->params.to->unit_pos == coord_last_unit_pos(kdata->params.to)); + assert("vs-607", + kdata->params.to->unit_pos == + coord_last_unit_pos(kdata->params.to)); coord_dup(&right_coord, kdata->params.to); if (coord_next_unit(&right_coord)) { /* @to is rightmost unit in the node */ - result = reiser4_get_right_neighbor(&right_lh, from->node, ZNODE_READ_LOCK, GN_CAN_USE_UPPER_LEVELS); + result = + reiser4_get_right_neighbor(&right_lh, from->node, + ZNODE_READ_LOCK, + GN_CAN_USE_UPPER_LEVELS); switch (result) { case 0: result = zload(right_lh.node); @@ -1159,7 +1193,8 @@ prepare_twig_kill(carry_kill_data *kdata goto done; right_zloaded_here = 1; - coord_init_first_unit(&right_coord, right_lh.node); + coord_init_first_unit(&right_coord, + right_lh.node); item_key_by_coord(&right_coord, &key); break; @@ -1167,8 +1202,9 @@ prepare_twig_kill(carry_kill_data *kdata /* there is no formatted node to the right of from->node */ UNDER_RW_VOID(dk, tree, read, - key = *znode_get_rd_key(from->node)); - right_coord.node = 0; + key = + *znode_get_rd_key(from->node)); + right_coord.node = NULL; result = 0; break; default: @@ -1200,7 +1236,7 @@ prepare_twig_kill(carry_kill_data *kdata result = prepare_children(left_child, NULL, kdata); } - done: + done: if (right_child) zput(right_child); if (right_zloaded_here) @@ -1218,42 +1254,45 @@ prepare_twig_kill(carry_kill_data *kdata /* this is used to remove part of node content between coordinates @from and @to. Units to which @from and @to are set are to be cut completely */ /* for try_to_merge_with_left, delete_copied, delete_node */ -reiser4_internal int -cut_node_content(coord_t *from, coord_t *to, - const reiser4_key * from_key /* first key to be removed */ , - const reiser4_key * to_key /* last key to be removed */ , - reiser4_key * smallest_removed /* smallest key actually removed */) +int cut_node_content(coord_t * from, coord_t * to, const reiser4_key * from_key, /* first key to be removed */ + const reiser4_key * to_key, /* last key to be removed */ + reiser4_key * + smallest_removed /* smallest key actually removed */ ) { + int result; carry_pool *pool; - carry_level lowest_level; + carry_level *lowest_level; + carry_cut_data *cut_data; carry_op *op; - carry_cut_data cut_data; - int result; assert("vs-1715", coord_compare(from, to) != COORD_CMP_ON_RIGHT); - pool = init_carry_pool(); + pool = + init_carry_pool(sizeof(*pool) + 3 * sizeof(*lowest_level) + + sizeof(*cut_data)); if (IS_ERR(pool)) return PTR_ERR(pool); - init_carry_level(&lowest_level, pool); + lowest_level = (carry_level *) (pool + 1); + init_carry_level(lowest_level, pool); - op = post_carry(&lowest_level, COP_CUT, from->node, 0); + op = post_carry(lowest_level, COP_CUT, from->node, 0); assert("vs-1509", op != 0); if (IS_ERR(op)) { done_carry_pool(pool); return PTR_ERR(op); } - cut_data.params.from = from; - cut_data.params.to = to; - cut_data.params.from_key = from_key; - cut_data.params.to_key = to_key; - cut_data.params.smallest_removed = smallest_removed; + cut_data = (carry_cut_data *) (lowest_level + 3); + cut_data->params.from = from; + cut_data->params.to = to; + cut_data->params.from_key = from_key; + cut_data->params.to_key = to_key; + cut_data->params.smallest_removed = smallest_removed; op->u.cut_or_kill.is_cut = 1; - op->u.cut_or_kill.u.cut = &cut_data; + op->u.cut_or_kill.u.cut = cut_data; - result = carry(&lowest_level, 0); + result = carry(lowest_level, NULL); done_carry_pool(pool); return result; @@ -1269,77 +1308,87 @@ cut_node_content(coord_t *from, coord_t removed key is stored in @smallest_removed */ -reiser4_internal int -kill_node_content(coord_t * from /* coord of the first unit/item that will be - * eliminated */ , - coord_t * to /* coord of the last unit/item that will be - * eliminated */ , - const reiser4_key * from_key /* first key to be removed */ , - const reiser4_key * to_key /* last key to be removed */ , - reiser4_key * smallest_removed /* smallest key actually - * removed */ , - znode * locked_left_neighbor, /* this is set when kill_node_content is called with left neighbor - * locked (in squalloc_right_twig_cut, namely) */ - struct inode *inode, /* inode of file whose item (or its part) is to be killed. This is necessary to - invalidate pages together with item pointing to them */ - int truncate) /* this call is made for file truncate) */ -{ +int kill_node_content(coord_t * from, /* coord of the first unit/item that will be eliminated */ + coord_t * to, /* coord of the last unit/item that will be eliminated */ + const reiser4_key * from_key, /* first key to be removed */ + const reiser4_key * to_key, /* last key to be removed */ + reiser4_key * smallest_removed, /* smallest key actually removed */ + znode * locked_left_neighbor, /* this is set when kill_node_content is called with left neighbor + * locked (in squalloc_right_twig_cut, namely) */ + struct inode *inode, /* inode of file whose item (or its part) is to be killed. This is necessary to + invalidate pages together with item pointing to them */ + int truncate) +{ /* this call is made for file truncate) */ int result; carry_pool *pool; - carry_level lowest_level; + carry_level *lowest_level; + carry_kill_data *kdata; + lock_handle *left_child; + lock_handle *right_child; carry_op *op; - carry_kill_data kdata; - lock_handle left_child; - lock_handle right_child; assert("umka-328", from != NULL); assert("vs-316", !node_is_empty(from->node)); - assert("nikita-1812", coord_is_existing_unit(from) && coord_is_existing_unit(to)); + assert("nikita-1812", coord_is_existing_unit(from) + && coord_is_existing_unit(to)); - init_lh(&left_child); - init_lh(&right_child); + /* allocate carry_pool, 3 carry_level-s, carry_kill_data and structures for kill_hook_extent */ + pool = init_carry_pool(sizeof(*pool) + 3 * sizeof(*lowest_level) + + sizeof(carry_kill_data) + + 2 * sizeof(lock_handle) + + 5 * sizeof(reiser4_key) + 2 * sizeof(coord_t)); + if (IS_ERR(pool)) + return PTR_ERR(pool); + + lowest_level = (carry_level *) (pool + 1); + init_carry_level(lowest_level, pool); - kdata.params.from = from; - kdata.params.to = to; - kdata.params.from_key = from_key; - kdata.params.to_key = to_key; - kdata.params.smallest_removed = smallest_removed; - kdata.params.truncate = truncate; - kdata.flags = 0; - kdata.inode = inode; - kdata.left = &left_child; - kdata.right = &right_child; + kdata = (carry_kill_data *) (lowest_level + 3); + left_child = (lock_handle *) (kdata + 1); + right_child = left_child + 1; + + init_lh(left_child); + init_lh(right_child); + + kdata->params.from = from; + kdata->params.to = to; + kdata->params.from_key = from_key; + kdata->params.to_key = to_key; + kdata->params.smallest_removed = smallest_removed; + kdata->params.truncate = truncate; + kdata->flags = 0; + kdata->inode = inode; + kdata->left = left_child; + kdata->right = right_child; + /* memory for 5 reiser4_key and 2 coord_t will be used in kill_hook_extent */ + kdata->buf = (char *)(right_child + 1); if (znode_get_level(from->node) == TWIG_LEVEL && item_is_extent(from)) { /* left child of extent item may have to get updated right delimiting key and to get linked with right child of extent @from if it will be removed completely */ - result = prepare_twig_kill(&kdata, locked_left_neighbor); + result = prepare_twig_kill(kdata, locked_left_neighbor); if (result) { - done_children(&kdata); + done_children(kdata); + done_carry_pool(pool); return result; } } - pool = init_carry_pool(); - if (IS_ERR(pool)) - return PTR_ERR(pool); - init_carry_level(&lowest_level, pool); - - op = post_carry(&lowest_level, COP_CUT, from->node, 0); + op = post_carry(lowest_level, COP_CUT, from->node, 0); if (IS_ERR(op) || (op == NULL)) { + done_children(kdata); done_carry_pool(pool); - done_children(&kdata); return RETERR(op ? PTR_ERR(op) : -EIO); } op->u.cut_or_kill.is_cut = 0; - op->u.cut_or_kill.u.kill = &kdata; + op->u.cut_or_kill.u.kill = kdata; - result = carry(&lowest_level, 0); + result = carry(lowest_level, NULL); + done_children(kdata); done_carry_pool(pool); - done_children(&kdata); return result; } @@ -1357,13 +1406,15 @@ fake_kill_hook_tail(struct inode *inode, * kill up to the page boundary. */ assert("vs-123456", start_pg == end_pg); - reiser4_invalidate_pages(inode->i_mapping, start_pg, 1, truncate); + reiser4_invalidate_pages(inode->i_mapping, start_pg, 1, + truncate); } else if (start_pg != end_pg) { /* * page boundary is within killed portion of node. */ assert("vs-654321", end_pg - start_pg == 1); - reiser4_invalidate_pages(inode->i_mapping, end_pg, end_pg - start_pg, 1); + reiser4_invalidate_pages(inode->i_mapping, end_pg, + end_pg - start_pg, 1); } } inode_sub_bytes(inode, end - start); @@ -1385,18 +1436,18 @@ fake_kill_hook_tail(struct inode *inode, * cut_worker() iteration. This is needed for proper accounting of * "i_blocks" and "i_bytes" fields of the @object. */ -reiser4_internal int delete_node (znode * node, reiser4_key * smallest_removed, - struct inode * object, int truncate) +int delete_node(znode * node, reiser4_key * smallest_removed, + struct inode *object, int truncate) { lock_handle parent_lock; coord_t cut_from; coord_t cut_to; - reiser4_tree * tree; + reiser4_tree *tree; int ret; - assert ("zam-937", node != NULL); - assert ("zam-933", znode_is_write_locked(node)); - assert ("zam-999", smallest_removed != NULL); + assert("zam-937", node != NULL); + assert("zam-933", znode_is_write_locked(node)); + assert("zam-999", smallest_removed != NULL); init_lh(&parent_lock); @@ -1423,7 +1474,7 @@ reiser4_internal int delete_node (znode tree = znode_get_tree(node); WLOCK_TREE(tree); init_parent_coord(&node->in_parent, NULL); - -- parent_lock.node->c_count; + --parent_lock.node->c_count; WUNLOCK_TREE(tree); assert("zam-989", item_is_internal(&cut_from)); @@ -1441,7 +1492,7 @@ reiser4_internal int delete_node (znode goto failed; { - reiser4_tree * tree = current_tree; + reiser4_tree *tree = current_tree; __u64 start_offset = 0, end_offset = 0; RLOCK_TREE(tree); @@ -1471,12 +1522,13 @@ reiser4_internal int delete_node (znode containing item we remove and can not call item's kill hook. Instead we call function which does exactly the same things as tail kill hook in assumption that node we avoid reading contains only one item and that item is a tail one. */ - fake_kill_hook_tail(object, start_offset, end_offset, truncate); + fake_kill_hook_tail(object, start_offset, end_offset, + truncate); } } - failed: + failed: zrelse(parent_lock.node); - failed_nozrelse: + failed_nozrelse: done_lh(&parent_lock); return ret; @@ -1497,10 +1549,11 @@ reiser4_internal int delete_node (znode * @return: 0 if success, error code otherwise, -E_REPEAT means that long cut_tree * operation was interrupted for allowing atom commit . */ -reiser4_internal int -cut_tree_worker_common (tap_t * tap, const reiser4_key * from_key, - const reiser4_key * to_key, reiser4_key * smallest_removed, - struct inode * object, int truncate, int *progress) +int +cut_tree_worker_common(tap_t * tap, const reiser4_key * from_key, + const reiser4_key * to_key, + reiser4_key * smallest_removed, struct inode *object, + int truncate, int *progress) { lock_handle next_node_lock; coord_t left_coord; @@ -1513,21 +1566,25 @@ cut_tree_worker_common (tap_t * tap, con init_lh(&next_node_lock); while (1) { - znode *node; /* node from which items are cut */ - node_plugin *nplug; /* node plugin for @node */ + znode *node; /* node from which items are cut */ + node_plugin *nplug; /* node plugin for @node */ node = tap->coord->node; /* Move next_node_lock to the next node on the left. */ - result = reiser4_get_left_neighbor( - &next_node_lock, node, ZNODE_WRITE_LOCK, GN_CAN_USE_UPPER_LEVELS); + result = + reiser4_get_left_neighbor(&next_node_lock, node, + ZNODE_WRITE_LOCK, + GN_CAN_USE_UPPER_LEVELS); if (result != 0 && result != -E_NO_NEIGHBOR) break; /* Check can we delete the node as a whole. */ if (*progress && znode_get_level(node) == LEAF_LEVEL && - UNDER_RW(dk, current_tree, read, keyle(from_key, znode_get_ld_key(node)))) - { - result = delete_node(node, smallest_removed, object, truncate); + UNDER_RW(dk, current_tree, read, + keyle(from_key, znode_get_ld_key(node)))) { + result = + delete_node(node, smallest_removed, object, + truncate); } else { result = tap_load(tap); if (result) @@ -1537,9 +1594,11 @@ cut_tree_worker_common (tap_t * tap, con if (*progress) coord_init_last_unit(tap->coord, node); - else if (item_plugin_by_coord(tap->coord)->b.lookup == NULL) + else if (item_plugin_by_coord(tap->coord)->b.lookup == + NULL) /* set rightmost unit for the items without lookup method */ - tap->coord->unit_pos = coord_last_unit_pos(tap->coord); + tap->coord->unit_pos = + coord_last_unit_pos(tap->coord); nplug = node->nplug; @@ -1548,18 +1607,21 @@ cut_tree_worker_common (tap_t * tap, con /* left_coord is leftmost unit cut from @node */ result = nplug->lookup(node, from_key, - FIND_MAX_NOT_MORE_THAN, &left_coord); + FIND_MAX_NOT_MORE_THAN, + &left_coord); if (IS_CBKERR(result)) break; /* adjust coordinates so that they are set to existing units */ - if (coord_set_to_right(&left_coord) || coord_set_to_left(tap->coord)) { + if (coord_set_to_right(&left_coord) + || coord_set_to_left(tap->coord)) { result = 0; break; } - if (coord_compare(&left_coord, tap->coord) == COORD_CMP_ON_RIGHT) { + if (coord_compare(&left_coord, tap->coord) == + COORD_CMP_ON_RIGHT) { /* keys from @from_key to @to_key are not in the tree */ result = 0; break; @@ -1572,27 +1634,30 @@ cut_tree_worker_common (tap_t * tap, con and extent item. We do not want to kill internal items being at twig node here because cut_tree_worker assumes killing them from level level */ coord_dup(&left_coord, tap->coord); - assert("vs-1652", coord_is_existing_unit(&left_coord)); + assert("vs-1652", + coord_is_existing_unit(&left_coord)); left_coord.unit_pos = 0; } /* cut data from one node */ // *smallest_removed = *min_key(); - result = kill_node_content(&left_coord, tap->coord, from_key, to_key, - smallest_removed, next_node_lock.node, - object, truncate); + result = + kill_node_content(&left_coord, tap->coord, from_key, + to_key, smallest_removed, + next_node_lock.node, object, + truncate); tap_relse(tap); } if (result) break; - ++ (*progress); + ++(*progress); /* Check whether all items with keys >= from_key were removed * from the tree. */ if (keyle(smallest_removed, from_key)) - /* result = 0;*/ - break; + /* result = 0; */ + break; if (next_node_lock.node == NULL) break; @@ -1605,8 +1670,7 @@ cut_tree_worker_common (tap_t * tap, con /* Break long cut_tree operation (deletion of a large file) if * atom requires commit. */ if (*progress > CUT_TREE_MIN_ITERATIONS - && current_atom_should_commit()) - { + && current_atom_should_commit()) { result = -E_REPEAT; break; } @@ -1616,7 +1680,6 @@ cut_tree_worker_common (tap_t * tap, con return result; } - /* there is a fundamental problem with optimizing deletes: VFS does it one file at a time. Another problem is that if an item can be anything, then deleting items must be done one at a time. It just @@ -1644,7 +1707,6 @@ cut_tree_worker_common (tap_t * tap, con the deletion. */ - /** * Delete everything from the reiser4 tree between two keys: @from_key and * @to_key. @@ -1661,18 +1723,19 @@ cut_tree_worker_common (tap_t * tap, con * operation was interrupted for allowing atom commit . */ -reiser4_internal int +int cut_tree_object(reiser4_tree * tree, const reiser4_key * from_key, const reiser4_key * to_key, reiser4_key * smallest_removed_p, - struct inode * object, int truncate, int *progress) + struct inode *object, int truncate, int *progress) { lock_handle lock; int result; tap_t tap; coord_t right_coord; reiser4_key smallest_removed; - int (*cut_tree_worker)(tap_t *, const reiser4_key *, const reiser4_key *, - reiser4_key *, struct inode *, int, int *); + int (*cut_tree_worker) (tap_t *, const reiser4_key *, + const reiser4_key *, reiser4_key *, + struct inode *, int, int *); STORE_COUNTERS; assert("umka-329", tree != NULL); @@ -1687,19 +1750,22 @@ cut_tree_object(reiser4_tree * tree, con do { /* Find rightmost item to cut away from the tree. */ - result = object_lookup( - object, to_key, &right_coord, &lock, - ZNODE_WRITE_LOCK, FIND_MAX_NOT_MORE_THAN, TWIG_LEVEL, - LEAF_LEVEL, CBK_UNIQUE, 0/*ra_info*/); + result = object_lookup(object, to_key, &right_coord, &lock, + ZNODE_WRITE_LOCK, FIND_MAX_NOT_MORE_THAN, + TWIG_LEVEL, LEAF_LEVEL, CBK_UNIQUE, + NULL /*ra_info */ ); if (result != CBK_COORD_FOUND) break; - if (object == NULL || inode_file_plugin(object)->cut_tree_worker == NULL) + if (object == NULL + || inode_file_plugin(object)->cut_tree_worker == NULL) cut_tree_worker = cut_tree_worker_common; else - cut_tree_worker = inode_file_plugin(object)->cut_tree_worker; + cut_tree_worker = + inode_file_plugin(object)->cut_tree_worker; tap_init(&tap, &right_coord, &lock, ZNODE_WRITE_LOCK); - result = cut_tree_worker( - &tap, from_key, to_key, smallest_removed_p, object, truncate, progress); + result = + cut_tree_worker(&tap, from_key, to_key, smallest_removed_p, + object, truncate, progress); tap_done(&tap); preempt_point(); @@ -1731,24 +1797,24 @@ cut_tree_object(reiser4_tree * tree, con /* repeat cut_tree_object until everything is deleted. unlike cut_file_items, it * does not end current transaction if -E_REPEAT is returned by * cut_tree_object. */ -reiser4_internal int -cut_tree(reiser4_tree *tree, const reiser4_key *from, const reiser4_key *to, +int +cut_tree(reiser4_tree * tree, const reiser4_key * from, const reiser4_key * to, struct inode *inode, int truncate) { int result; int progress; do { - result = cut_tree_object(tree, from, to, NULL, inode, truncate, &progress); + result = + cut_tree_object(tree, from, to, NULL, inode, truncate, + &progress); } while (result == -E_REPEAT); return result; } - /* first step of reiser4 tree initialization */ -reiser4_internal void -init_tree_0(reiser4_tree * tree) +void init_tree_0(reiser4_tree * tree) { assert("zam-683", tree != NULL); rw_tree_init(tree); @@ -1756,13 +1822,12 @@ init_tree_0(reiser4_tree * tree) } /* finishing reiser4 initialization */ -reiser4_internal int -init_tree(reiser4_tree * tree /* pointer to structure being - * initialized */ , - const reiser4_block_nr * root_block /* address of a root block - * on a disk */ , - tree_level height /* height of a tree */ , - node_plugin * nplug /* default node plugin */ ) +int init_tree(reiser4_tree * tree /* pointer to structure being + * initialized */ , + const reiser4_block_nr * root_block /* address of a root block + * on a disk */ , + tree_level height /* height of a tree */ , + node_plugin * nplug /* default node plugin */ ) { int result; @@ -1798,8 +1863,7 @@ init_tree(reiser4_tree * tree /* pointer } /* release resources associated with @tree */ -reiser4_internal void -done_tree(reiser4_tree * tree /* tree to release */ ) +void done_tree(reiser4_tree * tree /* tree to release */ ) { if (tree == NULL) return; diff -puN fs/reiser4/tree.h~reiser4-big-update fs/reiser4/tree.h --- devel/fs/reiser4/tree.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/tree.h 2005-09-15 19:51:08.000000000 -0700 @@ -10,10 +10,8 @@ #include "debug.h" #include "spin_macros.h" #include "dformat.h" -#include "type_safe_list.h" #include "plugin/node/node.h" #include "plugin/plugin.h" -#include "jnode.h" #include "znode.h" #include "tap.h" @@ -25,9 +23,6 @@ /* fictive block number never actually used */ extern const reiser4_block_nr UBER_TREE_ADDR; -/* define typed list for cbk_cache lru */ -TYPE_SAFE_LIST_DECLARE(cbk_cache); - /* &cbk_cache_slot - entry in a coord cache. This is entry in a coord_by_key (cbk) cache, represented by @@ -38,7 +33,7 @@ typedef struct cbk_cache_slot { /* cached node */ znode *node; /* linkage to the next cbk cache slot in a LRU order */ - cbk_cache_list_link lru; + struct list_head lru; } cbk_cache_slot; /* &cbk_cache - coord cache. This is part of reiser4_tree. @@ -67,7 +62,7 @@ typedef struct cbk_cache { reiser4_rw_data guard; int nr_slots; /* head of LRU list of cache slots */ - cbk_cache_list_head lru; + struct list_head lru; /* actual array of slots */ cbk_cache_slot *slot; } cbk_cache; @@ -77,9 +72,6 @@ typedef struct cbk_cache { /* defined read-write locking functions for cbk_cache */ RW_LOCK_FUNCTIONS(cbk_cache, cbk_cache, guard); -/* define list manipulation functions for cbk_cache LRU list */ -TYPE_SAFE_LIST_DEFINE(cbk_cache, cbk_cache_slot, lru); - /* level_lookup_result - possible outcome of looking up key at some level. This is used by coord_by_key when traversing tree downward. */ typedef enum { @@ -115,7 +107,7 @@ struct reiser4_tree { reiser4_block_nr root_block; /* level of the root node. If this is 1, tree consists of root - node only */ + node only */ tree_level height; /* @@ -134,11 +126,11 @@ struct reiser4_tree { j_hash_table jhash_table; /* lock protecting: - - parent pointers, - - sibling pointers, - - znode hash table - - coord cache - */ + - parent pointers, + - sibling pointers, + - znode hash table + - coord cache + */ /* NOTE: The "giant" tree lock can be replaced by more spin locks, hoping they will be less contented. We can use one spin lock per one znode hash bucket. With adding of some code complexity, sibling @@ -158,8 +150,8 @@ struct reiser4_tree { * information. */ __u64 znode_epoch; - znode *uber; - node_plugin *nplug; + znode *uber; + node_plugin *nplug; struct super_block *super; struct { /* carry flags used for insertion of new nodes */ @@ -179,63 +171,16 @@ SPIN_LOCK_FUNCTIONS(epoch, reiser4_tree, extern void init_tree_0(reiser4_tree *); extern int init_tree(reiser4_tree * tree, - const reiser4_block_nr * root_block, tree_level height, node_plugin * default_plugin); + const reiser4_block_nr * root_block, tree_level height, + node_plugin * default_plugin); extern void done_tree(reiser4_tree * tree); -/* &reiser4_item_data - description of data to be inserted or pasted - - Q: articulate the reasons for the difference between this and flow. - - A: Becides flow we insert into tree other things: stat data, directory - entry, etc. To insert them into tree one has to provide this structure. If - one is going to insert flow - he can use insert_flow, where this structure - does not have to be created -*/ -struct reiser4_item_data { - /* actual data to be inserted. If NULL, ->create_item() will not - do xmemcpy itself, leaving this up to the caller. This can - save some amount of unnecessary memory copying, for example, - during insertion of stat data. - - */ - char *data; - /* 1 if 'char * data' contains pointer to user space and 0 if it is - kernel space */ - int user; - /* amount of data we are going to insert or paste */ - int length; - /* "Arg" is opaque data that is passed down to the - ->create_item() method of node layout, which in turn - hands it to the ->create_hook() of item being created. This - arg is currently used by: - - . ->create_hook() of internal item - (fs/reiser4/plugin/item/internal.c:internal_create_hook()), - . ->paste() method of directory item. - . ->create_hook() of extent item - - For internal item, this is left "brother" of new node being - inserted and it is used to add new node into sibling list - after parent to it was just inserted into parent. - - While ->arg does look somewhat of unnecessary compication, - it actually saves a lot of headache in many places, because - all data necessary to insert or paste new data into tree are - collected in one place, and this eliminates a lot of extra - argument passing and storing everywhere. - - */ - void *arg; - /* plugin of item we are inserting */ - item_plugin *iplug; -}; - /* cbk flags: options for coord_by_key() */ typedef enum { /* coord_by_key() is called for insertion. This is necessary because of extents being located at the twig level. For explanation, see comment just above is_next_item_internal(). - */ + */ CBK_FOR_INSERT = (1 << 0), /* coord_by_key() is called with key that is known to be unique */ CBK_UNIQUE = (1 << 1), @@ -246,15 +191,15 @@ typedef enum { leftmost key in a node. This is necessary because of extents being located at the twig level. For explanation, see comment just above is_next_item_internal(). - */ + */ CBK_TRUST_DK = (1 << 2), - CBK_READA = (1 << 3), /* original: readahead leaves which contain items of certain file */ - CBK_READDIR_RA = (1 << 4), /* readdir: readahead whole directory and all its stat datas */ - CBK_DKSET = (1 << 5), - CBK_EXTENDED_COORD = (1 << 6), /* coord_t is actually */ - CBK_IN_CACHE = (1 << 7), /* node is already in cache */ - CBK_USE_CRABLOCK = (1 << 8) /* use crab_lock in stead of long term - * lock */ + CBK_READA = (1 << 3), /* original: readahead leaves which contain items of certain file */ + CBK_READDIR_RA = (1 << 4), /* readdir: readahead whole directory and all its stat datas */ + CBK_DKSET = (1 << 5), + CBK_EXTENDED_COORD = (1 << 6), /* coord_t is actually */ + CBK_IN_CACHE = (1 << 7), /* node is already in cache */ + CBK_USE_CRABLOCK = (1 << 8) /* use crab_lock in stead of long term + * lock */ } cbk_flags; /* insertion outcome. IBK = insert by key */ @@ -268,15 +213,17 @@ typedef enum { #define IS_CBKERR(err) ((err) != CBK_COORD_FOUND && (err) != CBK_COORD_NOTFOUND) -typedef int (*tree_iterate_actor_t) (reiser4_tree * tree, coord_t * coord, lock_handle * lh, void *arg); +typedef int (*tree_iterate_actor_t) (reiser4_tree * tree, coord_t * coord, + lock_handle * lh, void *arg); extern int iterate_tree(reiser4_tree * tree, coord_t * coord, lock_handle * lh, - tree_iterate_actor_t actor, void *arg, znode_lock_mode mode, int through_units_p); + tree_iterate_actor_t actor, void *arg, + znode_lock_mode mode, int through_units_p); extern int get_uber_znode(reiser4_tree * tree, znode_lock_mode mode, - znode_lock_request pri, lock_handle *lh); + znode_lock_request pri, lock_handle * lh); /* return node plugin of @node */ -static inline node_plugin * -node_plugin_by_node(const znode * node /* node to query */ ) +static inline node_plugin *node_plugin_by_node(const znode * + node /* node to query */ ) { assert("vs-213", node != NULL); assert("vs-214", znode_is_loaded(node)); @@ -285,8 +232,7 @@ node_plugin_by_node(const znode * node / } /* number of items in @node */ -static inline pos_in_node_t -node_num_items(const znode * node) +static inline pos_in_node_t node_num_items(const znode * node) { assert("nikita-2754", znode_is_loaded(node)); assert("nikita-2468", @@ -297,8 +243,7 @@ node_num_items(const znode * node) /* Return the number of items at the present node. Asserts coord->node != NULL. */ -static inline unsigned -coord_num_items(const coord_t * coord) +static inline unsigned coord_num_items(const coord_t * coord) { assert("jmacd-9805", coord->node != NULL); @@ -306,8 +251,7 @@ coord_num_items(const coord_t * coord) } /* true if @node is empty */ -static inline int -node_is_empty(const znode * node) +static inline int node_is_empty(const znode * node) { return node_num_items(node) == 0; } @@ -355,8 +299,8 @@ extern void coord_unit_move_to(coord_t * lookup_result coord_by_key(reiser4_tree * tree, const reiser4_key * key, coord_t * coord, lock_handle * handle, znode_lock_mode lock, lookup_bias bias, - tree_level lock_level, tree_level stop_level, __u32 flags, - ra_info_t *); + tree_level lock_level, tree_level stop_level, + __u32 flags, ra_info_t *); lookup_result object_lookup(struct inode *object, const reiser4_key * key, @@ -366,8 +310,7 @@ lookup_result object_lookup(struct inode lookup_bias bias, tree_level lock_level, tree_level stop_level, - __u32 flags, - ra_info_t *info); + __u32 flags, ra_info_t * info); insert_result insert_by_key(reiser4_tree * tree, const reiser4_key * key, reiser4_item_data * data, coord_t * coord, @@ -375,41 +318,50 @@ insert_result insert_by_key(reiser4_tree tree_level stop_level, __u32 flags); insert_result insert_by_coord(coord_t * coord, reiser4_item_data * data, const reiser4_key * key, - lock_handle * lh, - __u32); + lock_handle * lh, __u32); insert_result insert_extent_by_coord(coord_t * coord, - reiser4_item_data * data, const reiser4_key * key, lock_handle * lh); -int cut_node_content(coord_t *from, coord_t *to, - const reiser4_key *from_key, const reiser4_key *to_key, - reiser4_key *smallest_removed); -int kill_node_content(coord_t *from, coord_t *to, - const reiser4_key *from_key, const reiser4_key *to_key, - reiser4_key *smallest_removed, - znode *locked_left_neighbor, - struct inode *inode, int truncate); + reiser4_item_data * data, + const reiser4_key * key, lock_handle * lh); +int cut_node_content(coord_t * from, coord_t * to, const reiser4_key * from_key, + const reiser4_key * to_key, + reiser4_key * smallest_removed); +int kill_node_content(coord_t * from, coord_t * to, + const reiser4_key * from_key, const reiser4_key * to_key, + reiser4_key * smallest_removed, + znode * locked_left_neighbor, struct inode *inode, + int truncate); int resize_item(coord_t * coord, reiser4_item_data * data, reiser4_key * key, lock_handle * lh, cop_insert_flag); -int insert_into_item(coord_t * coord, lock_handle * lh, const reiser4_key * key, reiser4_item_data * data, unsigned); +int insert_into_item(coord_t * coord, lock_handle * lh, const reiser4_key * key, + reiser4_item_data * data, unsigned); int insert_flow(coord_t * coord, lock_handle * lh, flow_t * f); -int find_new_child_ptr(znode * parent, znode * child, znode * left, coord_t * result); +int find_new_child_ptr(znode * parent, znode * child, znode * left, + coord_t * result); int shift_right_of_but_excluding_insert_coord(coord_t * insert_coord); int shift_left_of_and_including_insert_coord(coord_t * insert_coord); void fake_kill_hook_tail(struct inode *, loff_t start, loff_t end, int); -extern int cut_tree_worker_common(tap_t *, const reiser4_key *, const reiser4_key *, - reiser4_key *, struct inode *, int, int*); -extern int cut_tree_object(reiser4_tree*, const reiser4_key*, const reiser4_key*, reiser4_key*, struct inode*, int, int*); -extern int cut_tree(reiser4_tree *tree, const reiser4_key *from, const reiser4_key *to, struct inode*, int); +extern int cut_tree_worker_common(tap_t *, const reiser4_key *, + const reiser4_key *, reiser4_key *, + struct inode *, int, int *); +extern int cut_tree_object(reiser4_tree *, const reiser4_key *, + const reiser4_key *, reiser4_key *, struct inode *, + int, int *); +extern int cut_tree(reiser4_tree * tree, const reiser4_key * from, + const reiser4_key * to, struct inode *, int); extern int delete_node(znode * node, reiser4_key *, struct inode *, int); extern int check_tree_pointer(const coord_t * pointer, const znode * child); -extern int find_new_child_ptr(znode * parent, znode * child UNUSED_ARG, znode * left, coord_t * result); +extern int find_new_child_ptr(znode * parent, znode * child UNUSED_ARG, + znode * left, coord_t * result); extern int find_child_ptr(znode * parent, znode * child, coord_t * result); -extern int set_child_delimiting_keys(znode * parent, const coord_t * in_parent, znode *child); -extern znode *child_znode(const coord_t * in_parent, znode * parent, int incore_p, int setup_dkeys_p); +extern int set_child_delimiting_keys(znode * parent, const coord_t * in_parent, + znode * child); +extern znode *child_znode(const coord_t * in_parent, znode * parent, + int incore_p, int setup_dkeys_p); extern int cbk_cache_init(cbk_cache * cache); extern void cbk_cache_done(cbk_cache * cache); @@ -420,7 +372,9 @@ extern char *sprint_address(const reiser #if REISER4_DEBUG extern void print_coord_content(const char *prefix, coord_t * p); extern void print_address(const char *prefix, const reiser4_block_nr * block); -extern void print_tree_rec(const char *prefix, reiser4_tree * tree, __u32 flags); +extern void print_tree_rec(const char *prefix, reiser4_tree * tree, + __u32 flags); +extern void check_dkeys(znode *node); #else #define print_coord_content(p, c) noop #define print_address(p, b) noop @@ -450,7 +404,7 @@ typedef struct cbk_handle { /* level where search will stop. Either item will be found between lock_level and stop_level, or CBK_COORD_NOTFOUND will be returned. - */ + */ tree_level stop_level; /* level we are currently at */ tree_level level; @@ -476,7 +430,7 @@ typedef struct cbk_handle { extern znode_lock_mode cbk_lock_mode(tree_level level, cbk_handle * h); /* eottl.c */ -extern int handle_eottl(cbk_handle * h, int *outcome); +extern int handle_eottl(cbk_handle *h, int *outcome); int lookup_multikey(cbk_handle * handle, int nr_keys); int lookup_couple(reiser4_tree * tree, @@ -484,7 +438,8 @@ int lookup_couple(reiser4_tree * tree, coord_t * coord1, coord_t * coord2, lock_handle * lh1, lock_handle * lh2, znode_lock_mode lock_mode, lookup_bias bias, - tree_level lock_level, tree_level stop_level, __u32 flags, int *result1, int *result2); + tree_level lock_level, tree_level stop_level, __u32 flags, + int *result1, int *result2); /* ordering constraint for tree spin lock: tree lock is "strongest" */ #define rw_ordering_pred_tree(tree) \ @@ -500,18 +455,17 @@ RW_LOCK_FUNCTIONS(tree, reiser4_tree, tr tree lock */ #define rw_ordering_pred_dk( tree ) 1 #if 0 - (lock_counters()->rw_locked_tree == 0) && \ - (lock_counters()->spin_locked_jnode == 0) && \ - (lock_counters()->rw_locked_zlock == 0) && \ - (lock_counters()->spin_locked_txnh == 0) && \ - (lock_counters()->spin_locked_atom == 0) && \ - (lock_counters()->spin_locked_inode_object == 0) && \ - (lock_counters()->spin_locked_txnmgr == 0) +(lock_counters()->rw_locked_tree == 0) && + (lock_counters()->spin_locked_jnode == 0) && + (lock_counters()->rw_locked_zlock == 0) && + (lock_counters()->spin_locked_txnh == 0) && + (lock_counters()->spin_locked_atom == 0) && + (lock_counters()->spin_locked_inode_object == 0) && + (lock_counters()->spin_locked_txnmgr == 0) #endif - /* Define spin_lock_dk(), spin_unlock_dk(), etc: locking for delimiting keys. */ -RW_LOCK_FUNCTIONS(dk, reiser4_tree, dk_lock); + RW_LOCK_FUNCTIONS(dk, reiser4_tree, dk_lock); #if REISER4_DEBUG #define check_tree() print_tree_rec( "", current_tree, REISER4_TREE_CHECK ) diff -puN fs/reiser4/tree_mod.c~reiser4-big-update fs/reiser4/tree_mod.c --- devel/fs/reiser4/tree_mod.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/tree_mod.c 2005-09-15 19:51:08.000000000 -0700 @@ -37,10 +37,9 @@ static int add_child_ptr(znode * parent, warning( __VA_ARGS__ ) /* allocate new node on the @level and immediately on the right of @brother. */ -reiser4_internal znode * -new_node(znode * brother /* existing left neighbor of new node */ , - tree_level level /* tree level at which new node is to - * be allocated */ ) +znode *new_node(znode * brother /* existing left neighbor of new node */ , + tree_level level /* tree level at which new node is to + * be allocated */ ) { znode *result; int retcode; @@ -51,15 +50,19 @@ new_node(znode * brother /* existing lef retcode = assign_fake_blocknr_formatted(&blocknr); if (retcode == 0) { - result = zget(znode_get_tree(brother), &blocknr, NULL, level, GFP_KERNEL); + result = + zget(znode_get_tree(brother), &blocknr, NULL, level, + GFP_KERNEL); if (IS_ERR(result)) { ewarning(PTR_ERR(result), "nikita-929", - "Cannot allocate znode for carry: %li", PTR_ERR(result)); + "Cannot allocate znode for carry: %li", + PTR_ERR(result)); return result; } /* cheap test, can be executed even when debugging is off */ if (!znode_just_created(result)) { - warning("nikita-2213", "Allocated already existing block: %llu", + warning("nikita-2213", + "Allocated already existing block: %llu", (unsigned long long)blocknr); zput(result); return ERR_PTR(RETERR(-EIO)); @@ -82,7 +85,7 @@ new_node(znode * brother /* existing lef This should never happen. Ever. Returning -E_REPEAT is not viable solution, because "out of disk space" is not transient error that will go away by itself. - */ + */ ewarning(retcode, "nikita-928", "Cannot allocate block for carry: %i", retcode); result = ERR_PTR(retcode); @@ -96,9 +99,8 @@ new_node(znode * brother /* existing lef This helper function is called by add_new_root(). */ -reiser4_internal znode * -add_tree_root(znode * old_root /* existing tree root */ , - znode * fake /* "fake" znode */ ) +znode *add_tree_root(znode * old_root /* existing tree root */ , + znode * fake /* "fake" znode */ ) { reiser4_tree *tree = znode_get_tree(old_root); znode *new_root = NULL; /* to shut gcc up */ @@ -114,7 +116,7 @@ add_tree_root(znode * old_root /* existi lock on a root node. This avoids race conditions with root manipulations. - */ + */ assert("nikita-1348", znode_above_root(fake)); assert("nikita-1211", znode_is_root(old_root)); @@ -126,21 +128,24 @@ add_tree_root(znode * old_root /* existi ENOSPC? -EXFULL? -EINVAL? - */ + */ result = RETERR(-ENOSPC); } else { /* Allocate block for new root. It's not that important where it will be allocated, as root is almost always in memory. Moreover, allocate on flush can be going here. - */ + */ assert("nikita-1448", znode_is_root(old_root)); new_root = new_node(fake, tree->height + 1); if (!IS_ERR(new_root) && (result = zload(new_root)) == 0) { lock_handle rlh; init_lh(&rlh); - result = longterm_lock_znode(&rlh, new_root, ZNODE_WRITE_LOCK, ZNODE_LOCK_LOPRI); + result = + longterm_lock_znode(&rlh, new_root, + ZNODE_WRITE_LOCK, + ZNODE_LOCK_LOPRI); if (result == 0) { parent_coord_t *in_parent; @@ -152,7 +157,8 @@ add_tree_root(znode * old_root /* existi ++tree->height; /* recalculate max balance overhead */ - tree->estimate_one_insert = estimate_one_insert_item(tree); + tree->estimate_one_insert = + estimate_one_insert_item(tree); tree->root_block = *znode_get_block(new_root); in_parent = &new_root->in_parent; @@ -166,7 +172,9 @@ add_tree_root(znode * old_root /* existi /* insert into new root pointer to the @old_root. */ - assert("nikita-1110", WITH_DATA(new_root, node_is_empty(new_root))); + assert("nikita-1110", + WITH_DATA(new_root, + node_is_empty(new_root))); WLOCK_DK(tree); znode_set_ld_key(new_root, min_key()); znode_set_rd_key(new_root, max_key()); @@ -193,19 +201,18 @@ add_tree_root(znode * old_root /* existi in its parent. */ -reiser4_internal void -build_child_ptr_data(znode * child /* node pointer to which will be +void build_child_ptr_data(znode * child /* node pointer to which will be * inserted */ , - reiser4_item_data * data /* where to store result */ ) + reiser4_item_data * data /* where to store result */ ) { assert("nikita-1116", child != NULL); assert("nikita-1117", data != NULL); /* this is subtle assignment to meditate upon */ - data->data = (char *) znode_get_block(child); + data->data = (char *)znode_get_block(child); /* data -> data is kernel space */ data->user = 0; - data->length = sizeof (reiser4_block_nr); + data->length = sizeof(reiser4_block_nr); /* FIXME-VS: hardcoded internal item? */ /* AUDIT: Is it possible that "item_plugin_by_id" may find nothing? */ @@ -217,8 +224,7 @@ build_child_ptr_data(znode * child /* no This is used when pointer to old root is inserted into new root which is empty. */ -static int -add_child_ptr(znode * parent, znode * child) +static int add_child_ptr(znode * parent, znode * child) { coord_t coord; reiser4_item_data data; @@ -227,7 +233,8 @@ add_child_ptr(znode * parent, znode * ch assert("nikita-1111", parent != NULL); assert("nikita-1112", child != NULL); - assert("nikita-1115", znode_get_level(parent) == znode_get_level(child) + 1); + assert("nikita-1115", + znode_get_level(parent) == znode_get_level(child) + 1); result = zload(parent); if (result != 0) @@ -238,22 +245,23 @@ add_child_ptr(znode * parent, znode * ch build_child_ptr_data(child, &data); data.arg = NULL; - key = UNDER_RW(dk, znode_get_tree(parent), read, znode_get_ld_key(child)); - result = node_plugin_by_node(parent)->create_item(&coord, key, &data, NULL); + key = + UNDER_RW(dk, znode_get_tree(parent), read, znode_get_ld_key(child)); + result = + node_plugin_by_node(parent)->create_item(&coord, key, &data, NULL); znode_make_dirty(parent); zrelse(parent); return result; } /* actually remove tree root */ -static int -kill_root(reiser4_tree * tree /* tree from which root is being - * removed */ , - znode * old_root /* root node that is being removed */ , - znode * new_root /* new root---sole child of * - * @old_root */ , - const reiser4_block_nr * new_root_blk /* disk address of - * @new_root */ ) +static int kill_root(reiser4_tree * tree /* tree from which root is being + * removed */ , + znode * old_root /* root node that is being removed */ , + znode * new_root /* new root---sole child of * + * @old_root */ , + const reiser4_block_nr * new_root_blk /* disk address of + * @new_root */ ) { znode *uber; int result; @@ -261,11 +269,13 @@ kill_root(reiser4_tree * tree /* tree fr assert("umka-265", tree != NULL); assert("nikita-1198", new_root != NULL); - assert("nikita-1199", znode_get_level(new_root) + 1 == znode_get_level(old_root)); + assert("nikita-1199", + znode_get_level(new_root) + 1 == znode_get_level(old_root)); assert("nikita-1201", znode_is_write_locked(old_root)); - assert("nikita-1203", disk_addr_eq(new_root_blk, znode_get_block(new_root))); + assert("nikita-1203", + disk_addr_eq(new_root_blk, znode_get_block(new_root))); init_lh(&handle_for_uber); /* obtain and lock "fake" znode protecting changes in tree height. */ @@ -286,11 +296,12 @@ kill_root(reiser4_tree * tree /* tree fr /* recalculate max balance overhead */ tree->estimate_one_insert = estimate_one_insert_item(tree); - assert("nikita-1202", tree->height == znode_get_level(new_root)); + assert("nikita-1202", + tree->height == znode_get_level(new_root)); /* new root is child on "fake" node */ init_parent_coord(&new_root->in_parent, uber); - ++ uber->c_count; + ++uber->c_count; /* sibling_list_insert_nolock(new_root, NULL); */ WUNLOCK_TREE(tree); @@ -325,8 +336,7 @@ kill_root(reiser4_tree * tree /* tree fr to do the actual job. */ -reiser4_internal int -kill_tree_root(znode * old_root /* tree root that we are removing */ ) +int kill_tree_root(znode * old_root /* tree root that we are removing */ ) { int result; coord_t down_link; @@ -344,7 +354,9 @@ kill_tree_root(znode * old_root /* tree tree = znode_get_tree(old_root); new_root = child_znode(&down_link, old_root, 0, 1); if (!IS_ERR(new_root)) { - result = kill_root(tree, old_root, new_root, znode_get_block(new_root)); + result = + kill_root(tree, old_root, new_root, + znode_get_block(new_root)); zput(new_root); } else result = PTR_ERR(new_root); diff -puN fs/reiser4/tree_walk.c~reiser4-big-update fs/reiser4/tree_walk.c --- devel/fs/reiser4/tree_walk.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/tree_walk.c 2005-09-15 19:51:08.000000000 -0700 @@ -45,22 +45,20 @@ each case. This is parameterized by ptr_offset argument, which is byte offset for the pointer to the desired neighbor within the current node's znode structure. This function should be called with the tree lock held */ -static int -lock_neighbor( - /* resulting lock handle*/ - lock_handle * result, - /* znode to lock */ - znode * node, - /* pointer to neighbor (or parent) znode field offset, in bytes from - the base address of znode structure */ - int ptr_offset, - /* lock mode for longterm_lock_znode call */ - znode_lock_mode mode, - /* lock request for longterm_lock_znode call */ - znode_lock_request req, - /* GN_* flags */ - int flags, - int rlocked) +static int lock_neighbor( + /* resulting lock handle */ + lock_handle * result, + /* znode to lock */ + znode * node, + /* pointer to neighbor (or parent) znode field offset, in bytes from + the base address of znode structure */ + int ptr_offset, + /* lock mode for longterm_lock_znode call */ + znode_lock_mode mode, + /* lock request for longterm_lock_znode call */ + znode_lock_request req, + /* GN_* flags */ + int flags, int rlocked) { reiser4_tree *tree = znode_get_tree(node); znode *neighbor; @@ -107,7 +105,7 @@ lock_neighbor( /* restart if node we got reference to is being invalidated. we should not get reference to this node - again.*/ + again. */ if (ret == -EINVAL) continue; if (ret) @@ -125,12 +123,13 @@ lock_neighbor( XLOCK_TREE(tree, rlocked); } } + /* get parent node with longterm lock, accepts GN* flags. */ -reiser4_internal int -reiser4_get_parent_flags(lock_handle * result /* resulting lock handle */, - znode * node /* child node */, - znode_lock_mode mode /* type of lock: read or write */, - int flags /* GN_* flags */) +int reiser4_get_parent_flags(lock_handle * result /* resulting lock handle */ , + znode * node /* child node */ , + znode_lock_mode mode + /* type of lock: read or write */ , + int flags /* GN_* flags */ ) { return UNDER_RW(tree, znode_get_tree(node), read, lock_neighbor(result, node, PARENT_PTR_OFFSET, mode, @@ -142,9 +141,7 @@ reiser4_get_parent_flags(lock_handle * r /* Audited by: umka (2002.06.14) */ static inline int lock_side_neighbor(lock_handle * result, - znode * node, - znode_lock_mode mode, - int flags, int rlocked) + znode * node, znode_lock_mode mode, int flags, int rlocked) { int ret; int ptr_offset; @@ -158,13 +155,14 @@ lock_side_neighbor(lock_handle * result, req = ZNODE_LOCK_HIPRI; } - ret = lock_neighbor(result, node, ptr_offset, mode, req, flags, rlocked); + ret = + lock_neighbor(result, node, ptr_offset, mode, req, flags, rlocked); if (ret == -E_NO_NEIGHBOR) /* if we walk left or right -E_NO_NEIGHBOR does not - * guarantee that neighbor is absent in the - * tree; in this case we return -ENOENT -- - * means neighbor at least not found in - * cache */ + * guarantee that neighbor is absent in the + * tree; in this case we return -ENOENT -- + * means neighbor at least not found in + * cache */ return RETERR(-ENOENT); return ret; @@ -225,8 +223,7 @@ int check_sibling_list(znode * node) neighbors; works if one neighbor is NULL (was not found). */ /* FIXME-VS: this is unstatic-ed to use in tree.c in prepare_twig_cut */ -reiser4_internal void -link_left_and_right(znode * left, znode * right) +void link_left_and_right(znode * left, znode * right) { assert("nikita-3275", check_sibling_list(left)); assert("nikita-3275", check_sibling_list(right)); @@ -236,14 +233,17 @@ link_left_and_right(znode * left, znode left->right = right; ZF_SET(left, JNODE_RIGHT_CONNECTED); - ON_DEBUG(left->right_version = atomic_inc_return(&delim_key_version);); - - } else if (ZF_ISSET(left->right, JNODE_HEARD_BANSHEE) && left->right != right) { - - ON_DEBUG( - left->right->left_version = atomic_inc_return(&delim_key_version); - left->right_version = atomic_inc_return(&delim_key_version); - ); + ON_DEBUG(left->right_version = + atomic_inc_return(&delim_key_version); + ); + + } else if (ZF_ISSET(left->right, JNODE_HEARD_BANSHEE) + && left->right != right) { + + ON_DEBUG(left->right->left_version = + atomic_inc_return(&delim_key_version); + left->right_version = + atomic_inc_return(&delim_key_version);); left->right->left = NULL; left->right = right; @@ -269,14 +269,17 @@ link_left_and_right(znode * left, znode right->left = left; ZF_SET(right, JNODE_LEFT_CONNECTED); - ON_DEBUG(right->left_version = atomic_inc_return(&delim_key_version);); - - } else if (ZF_ISSET(right->left, JNODE_HEARD_BANSHEE) && right->left != left) { - - ON_DEBUG( - right->left->right_version = atomic_inc_return(&delim_key_version); - right->left_version = atomic_inc_return(&delim_key_version); - ); + ON_DEBUG(right->left_version = + atomic_inc_return(&delim_key_version); + ); + + } else if (ZF_ISSET(right->left, JNODE_HEARD_BANSHEE) + && right->left != left) { + + ON_DEBUG(right->left->right_version = + atomic_inc_return(&delim_key_version); + right->left_version = + atomic_inc_return(&delim_key_version);); right->left->right = NULL; right->left = left; @@ -291,8 +294,7 @@ link_left_and_right(znode * left, znode } /* Audited by: umka (2002.06.14) */ -static void -link_znodes(znode * first, znode * second, int to_left) +static void link_znodes(znode * first, znode * second, int to_left) { if (to_left) link_left_and_right(second, first); @@ -305,8 +307,7 @@ link_znodes(znode * first, znode * secon boundary. Should be called under tree lock, it protects nonexistence of sibling link on parent level, if lock_side_neighbor() fails with -ENOENT. */ -static int -far_next_coord(coord_t * coord, lock_handle * handle, int flags) +static int far_next_coord(coord_t * coord, lock_handle * handle, int flags) { int ret; znode *node; @@ -317,11 +318,14 @@ far_next_coord(coord_t * coord, lock_han handle->owner = NULL; /* mark lock handle as unused */ - ret = (flags & GN_GO_LEFT) ? coord_prev_unit(coord) : coord_next_unit(coord); + ret = + (flags & GN_GO_LEFT) ? coord_prev_unit(coord) : + coord_next_unit(coord); if (!ret) return 0; - ret = lock_side_neighbor(handle, coord->node, ZNODE_READ_LOCK, flags, 0); + ret = + lock_side_neighbor(handle, coord->node, ZNODE_READ_LOCK, flags, 0); if (ret) return ret; @@ -351,7 +355,7 @@ far_next_coord(coord_t * coord, lock_han coord_init_first_unit(coord, node); if (0) { - error_locked: + error_locked: longterm_unlock_znode(handle); } WLOCK_TREE(tree); @@ -364,7 +368,8 @@ far_next_coord(coord_t * coord, lock_han Note: this function does not restore locking status at exit, caller should does care about proper unlocking and zrelsing */ static int -renew_sibling_link(coord_t * coord, lock_handle * handle, znode * child, tree_level level, int flags, int *nr_locked) +renew_sibling_link(coord_t * coord, lock_handle * handle, znode * child, + tree_level level, int flags, int *nr_locked) { int ret; int to_left = flags & GN_GO_LEFT; @@ -413,7 +418,8 @@ renew_sibling_link(coord_t * coord, lock if (flags & GN_NO_ALLOC) { neighbor = zlook(tree, &da); } else { - neighbor = zget(tree, &da, side_parent, level, GFP_KERNEL); + neighbor = + zget(tree, &da, side_parent, level, GFP_KERNEL); } if (IS_ERR(neighbor)) { @@ -429,7 +435,8 @@ renew_sibling_link(coord_t * coord, lock } if (likely(neighbor == NULL || - (znode_get_level(child) == znode_get_level(neighbor) && child != neighbor))) + (znode_get_level(child) == znode_get_level(neighbor) + && child != neighbor))) link_znodes(child, neighbor, to_left); else { warning("nikita-3532", @@ -450,8 +457,7 @@ renew_sibling_link(coord_t * coord, lock /* This function is for establishing of one side relation. */ /* Audited by: umka (2002.06.14) */ -static int -connect_one_side(coord_t * coord, znode * node, int flags) +static int connect_one_side(coord_t * coord, znode * node, int flags) { coord_t local; lock_handle handle; @@ -465,7 +471,9 @@ connect_one_side(coord_t * coord, znode init_lh(&handle); - ret = renew_sibling_link(&local, &handle, node, znode_get_level(node), flags | GN_NO_ALLOC, &nr_locked); + ret = + renew_sibling_link(&local, &handle, node, znode_get_level(node), + flags | GN_NO_ALLOC, &nr_locked); if (handle.owner != NULL) { /* complementary operations for zload() and lock() in far_next_coord() */ @@ -484,8 +492,7 @@ connect_one_side(coord_t * coord, znode /* if @child is not in `connected' state, performs hash searches for left and right neighbor nodes and establishes horizontal sibling links */ /* Audited by: umka (2002.06.14), umka (2002.06.15) */ -reiser4_internal int -connect_znode(coord_t * parent_coord, znode * child) +int connect_znode(coord_t * parent_coord, znode * child) { reiser4_tree *tree = znode_get_tree(child); int ret = 0; @@ -503,10 +510,10 @@ connect_znode(coord_t * parent_coord, zn ZF_SET(child, JNODE_LEFT_CONNECTED); ZF_SET(child, JNODE_RIGHT_CONNECTED); - ON_DEBUG( - child->left_version = atomic_inc_return(&delim_key_version); - child->right_version = atomic_inc_return(&delim_key_version); - ); + ON_DEBUG(child->left_version = + atomic_inc_return(&delim_key_version); + child->right_version = + atomic_inc_return(&delim_key_version);); return 0; } @@ -536,11 +543,13 @@ connect_znode(coord_t * parent_coord, zn RUNLOCK_TREE(tree); if (!ret) { - ret = connect_one_side(parent_coord, child, GN_NO_ALLOC | GN_GO_LEFT); + ret = + connect_one_side(parent_coord, child, + GN_NO_ALLOC | GN_GO_LEFT); } else ret = 0; -zrelse_and_ret: + zrelse_and_ret: zrelse(parent_coord->node); return ret; @@ -570,11 +579,13 @@ renew_neighbor(coord_t * coord, znode * /* umka (2002.06.14) Here probably should be a check for given "level" validness. Something like assert("xxx-yyy", level < REAL_MAX_ZTREE_HEIGHT); - */ + */ coord_dup(&local, coord); - ret = renew_sibling_link(&local, &empty[0], node, level, flags & ~GN_NO_ALLOC, &nr_locked); + ret = + renew_sibling_link(&local, &empty[0], node, level, + flags & ~GN_NO_ALLOC, &nr_locked); if (ret) goto out; @@ -589,13 +600,15 @@ renew_neighbor(coord_t * coord, znode * goto out; } - ret = renew_sibling_link(&local, &empty[nr_locked], neighbor, level, flags | GN_NO_ALLOC, &nr_locked); + ret = + renew_sibling_link(&local, &empty[nr_locked], neighbor, level, + flags | GN_NO_ALLOC, &nr_locked); /* second renew_sibling_link() call is used for znode connection only, so we can live with these errors */ if (-ENOENT == ret || -E_NO_NEIGHBOR == ret) ret = 0; -out: + out: for (--nr_locked; nr_locked >= 0; --nr_locked) { zrelse(empty[nr_locked].node); @@ -637,9 +650,9 @@ out: */ /* Audited by: umka (2002.06.14), umka (2002.06.15) */ -reiser4_internal int -reiser4_get_neighbor ( - lock_handle * neighbor, znode * node, znode_lock_mode lock_mode, int flags) +int +reiser4_get_neighbor(lock_handle * neighbor, znode * node, + znode_lock_mode lock_mode, int flags) { reiser4_tree *tree = znode_get_tree(node); lock_handle path[REAL_MAX_ZTREE_HEIGHT]; @@ -660,7 +673,7 @@ reiser4_get_neighbor ( coord_init_zero(&coord); -again: + again: /* first, we try to use simple lock_neighbor() which requires sibling link existence */ ret = UNDER_RW(tree, tree, read, @@ -732,7 +745,9 @@ again: /* sibling link is not available -- we go upward. */ init_lh(&path[h + 1]); - ret = reiser4_get_parent(&path[h + 1], parent, ZNODE_READ_LOCK); + ret = + reiser4_get_parent(&path[h + 1], parent, + ZNODE_READ_LOCK); if (ret) goto fail; ++h; @@ -746,11 +761,10 @@ again: /* there was lock request from hi-pri locker. if it is possible we unlock last parent node and re-lock it again. */ - while (check_deadlock()) { + for (; check_deadlock(); h--) { + done_lh(&path[h]); if (h == 0) goto fail; - - done_lh(&path[--h]); } break; @@ -759,7 +773,7 @@ again: goto fail; } } -fail: + fail: ON_DEBUG(check_lock_node_data(node)); ON_DEBUG(check_lock_data()); @@ -777,8 +791,7 @@ fail: /* remove node from sibling list */ /* Audited by: umka (2002.06.14) */ -reiser4_internal void -sibling_list_remove(znode * node) +void sibling_list_remove(znode * node) { reiser4_tree *tree; @@ -790,7 +803,9 @@ sibling_list_remove(znode * node) WLOCK_DK(tree); if (znode_is_right_connected(node) && node->right != NULL && znode_is_left_connected(node) && node->left != NULL) { - assert("zam-32245", keyeq(znode_get_rd_key(node), znode_get_ld_key(node->right))); + assert("zam-32245", + keyeq(znode_get_rd_key(node), + znode_get_ld_key(node->right))); znode_set_rd_key(node->left, znode_get_ld_key(node->right)); } WUNLOCK_DK(tree); @@ -798,27 +813,28 @@ sibling_list_remove(znode * node) if (znode_is_right_connected(node) && node->right != NULL) { assert("zam-322", znode_is_left_connected(node->right)); node->right->left = node->left; - ON_DEBUG(node->right->left_version = atomic_inc_return(&delim_key_version);); + ON_DEBUG(node->right->left_version = + atomic_inc_return(&delim_key_version); + ); } if (znode_is_left_connected(node) && node->left != NULL) { assert("zam-323", znode_is_right_connected(node->left)); node->left->right = node->right; - ON_DEBUG(node->left->right_version = atomic_inc_return(&delim_key_version);); + ON_DEBUG(node->left->right_version = + atomic_inc_return(&delim_key_version); + ); } ZF_CLR(node, JNODE_LEFT_CONNECTED); ZF_CLR(node, JNODE_RIGHT_CONNECTED); - ON_DEBUG( - node->left = node->right = NULL; - node->left_version = atomic_inc_return(&delim_key_version); - node->right_version = atomic_inc_return(&delim_key_version); - ); + ON_DEBUG(node->left = node->right = NULL; + node->left_version = atomic_inc_return(&delim_key_version); + node->right_version = atomic_inc_return(&delim_key_version);); assert("nikita-3276", check_sibling_list(node)); } /* disconnect node from sibling list */ -reiser4_internal void -sibling_list_drop(znode * node) +void sibling_list_drop(znode * node) { znode *right; znode *left; @@ -830,28 +846,29 @@ sibling_list_drop(znode * node) if (right != NULL) { assert("nikita-2465", znode_is_left_connected(right)); right->left = NULL; - ON_DEBUG(right->left_version = atomic_inc_return(&delim_key_version);); + ON_DEBUG(right->left_version = + atomic_inc_return(&delim_key_version); + ); } left = node->left; if (left != NULL) { assert("zam-323", znode_is_right_connected(left)); left->right = NULL; - ON_DEBUG(left->right_version = atomic_inc_return(&delim_key_version);); + ON_DEBUG(left->right_version = + atomic_inc_return(&delim_key_version); + ); } ZF_CLR(node, JNODE_LEFT_CONNECTED); ZF_CLR(node, JNODE_RIGHT_CONNECTED); - ON_DEBUG( - node->left = node->right = NULL; - node->left_version = atomic_inc_return(&delim_key_version); - node->right_version = atomic_inc_return(&delim_key_version); - ); + ON_DEBUG(node->left = node->right = NULL; + node->left_version = atomic_inc_return(&delim_key_version); + node->right_version = atomic_inc_return(&delim_key_version);); } /* Insert new node into sibling list. Regular balancing inserts new node after (at right side) existing and locked node (@before), except one case of adding new tree root node. @before should be NULL in that case. */ -reiser4_internal void -sibling_list_insert_nolock(znode * new, znode * before) +void sibling_list_insert_nolock(znode * new, znode * before) { assert("zam-334", new != NULL); assert("nikita-3298", !znode_is_left_connected(new)); @@ -865,23 +882,27 @@ sibling_list_insert_nolock(znode * new, assert("zam-333", znode_is_connected(before)); new->right = before->right; new->left = before; - ON_DEBUG( - new->right_version = atomic_inc_return(&delim_key_version); - new->left_version = atomic_inc_return(&delim_key_version); - ); + ON_DEBUG(new->right_version = + atomic_inc_return(&delim_key_version); + new->left_version = + atomic_inc_return(&delim_key_version);); if (before->right != NULL) { before->right->left = new; - ON_DEBUG(before->right->left_version = atomic_inc_return(&delim_key_version);); + ON_DEBUG(before->right->left_version = + atomic_inc_return(&delim_key_version); + ); } before->right = new; - ON_DEBUG(before->right_version = atomic_inc_return(&delim_key_version);); + ON_DEBUG(before->right_version = + atomic_inc_return(&delim_key_version); + ); } else { new->right = NULL; new->left = NULL; - ON_DEBUG( - new->right_version = atomic_inc_return(&delim_key_version); - new->left_version = atomic_inc_return(&delim_key_version); - ); + ON_DEBUG(new->right_version = + atomic_inc_return(&delim_key_version); + new->left_version = + atomic_inc_return(&delim_key_version);); } ZF_SET(new, JNODE_LEFT_CONNECTED); ZF_SET(new, JNODE_RIGHT_CONNECTED); @@ -892,45 +913,48 @@ sibling_list_insert_nolock(znode * new, struct tw_handle { /* A key for tree walking (re)start, updated after each successful tree * node processing */ - reiser4_key start_key; + reiser4_key start_key; /* A tree traversal current position. */ - tap_t tap; + tap_t tap; /* An externally supplied pair of functions for formatted and * unformatted nodes processing. */ - struct tree_walk_actor * actor; + struct tree_walk_actor *actor; /* It is passed to actor functions as is. */ - void * opaque; + void *opaque; /* A direction of a tree traversal: 1 if going from right to left. */ - int go_left:1; + unsigned int go_left:1; /* "Done" flag */ - int done:1; + unsigned int done:1; /* Current node was processed completely */ - int node_completed:1; + unsigned int node_completed:1; }; /* it locks the root node, handles the restarts inside */ -static int lock_tree_root (lock_handle * lock, znode_lock_mode mode) +static int lock_tree_root(lock_handle * lock, znode_lock_mode mode) { int ret; - reiser4_tree * tree = current_tree; + reiser4_tree *tree = current_tree; lock_handle uber_znode_lock; - znode * root; + znode *root; init_lh(&uber_znode_lock); - again: + again: ret = get_uber_znode(tree, mode, ZNODE_LOCK_HIPRI, &uber_znode_lock); if (ret) return ret; - root = zget(tree, &tree->root_block, uber_znode_lock.node, tree->height, GFP_KERNEL); + root = + zget(tree, &tree->root_block, uber_znode_lock.node, tree->height, + GFP_KERNEL); if (IS_ERR(root)) { done_lh(&uber_znode_lock); return PTR_ERR(root); } - ret = longterm_lock_znode(lock, root, ZNODE_WRITE_LOCK, ZNODE_LOCK_HIPRI); + ret = + longterm_lock_znode(lock, root, ZNODE_WRITE_LOCK, ZNODE_LOCK_HIPRI); zput(root); done_lh(&uber_znode_lock); @@ -943,7 +967,7 @@ static int lock_tree_root (lock_handle * /* Update the handle->start_key by the first key of the node is being * processed. */ -static int update_start_key(struct tw_handle * h) +static int update_start_key(struct tw_handle *h) { int ret; @@ -956,11 +980,12 @@ static int update_start_key(struct tw_ha } /* Move tap to the next node, load it. */ -static int go_next_node (struct tw_handle * h, lock_handle * lock, const coord_t * coord) +static int go_next_node(struct tw_handle *h, lock_handle * lock, + const coord_t * coord) { int ret; - assert ("zam-948", ergo (coord != NULL, lock->node == coord->node)); + assert("zam-948", ergo(coord != NULL, lock->node == coord->node)); tap_relse(&h->tap); @@ -982,19 +1007,19 @@ static int go_next_node (struct tw_handl } if (h->actor->process_znode != NULL) { - ret = (h->actor->process_znode)(&h->tap, h->opaque); + ret = (h->actor->process_znode) (&h->tap, h->opaque); if (ret) goto error; } ret = update_start_key(h); - error: + error: done_lh(lock); return ret; } -static void next_unit (struct tw_handle * h) +static void next_unit(struct tw_handle *h) { if (h->go_left) h->node_completed = coord_prev_unit(h->tap.coord); @@ -1002,10 +1027,9 @@ static void next_unit (struct tw_handle h->node_completed = coord_next_unit(h->tap.coord); } - /* Move tree traversal position (which is embedded into tree_walk_handle) to the * parent of current node (h->lh.node). */ -static int tw_up (struct tw_handle * h) +static int tw_up(struct tw_handle *h) { coord_t coord; lock_handle lock; @@ -1016,7 +1040,9 @@ static int tw_up (struct tw_handle * h) init_load_count(&load); do { - ret = reiser4_get_parent(&lock, h->tap.lh->node, ZNODE_WRITE_LOCK); + ret = + reiser4_get_parent(&lock, h->tap.lh->node, + ZNODE_WRITE_LOCK); if (ret) break; if (znode_above_root(lock.node)) { @@ -1043,23 +1069,25 @@ static int tw_up (struct tw_handle * h) /* Move tree traversal position to the child of current node pointed by * h->tap.coord. */ -static int tw_down(struct tw_handle * h) +static int tw_down(struct tw_handle *h) { reiser4_block_nr block; lock_handle lock; - znode * child; - item_plugin * iplug; + znode *child; + item_plugin *iplug; tree_level level = znode_get_level(h->tap.lh->node); int ret; - assert ("zam-943", item_is_internal(h->tap.coord)); + assert("zam-943", item_is_internal(h->tap.coord)); iplug = item_plugin_by_coord(h->tap.coord); iplug->s.internal.down_link(h->tap.coord, NULL, &block); init_lh(&lock); do { - child = zget(current_tree, &block, h->tap.lh->node, level - 1, GFP_KERNEL); + child = + zget(current_tree, &block, h->tap.lh->node, level - 1, + GFP_KERNEL); if (IS_ERR(child)) return PTR_ERR(child); ret = connect_znode(h->tap.coord, child); @@ -1068,19 +1096,21 @@ static int tw_down(struct tw_handle * h) ret = longterm_lock_znode(&lock, child, ZNODE_WRITE_LOCK, 0); if (ret) break; - set_child_delimiting_keys(h->tap.coord->node, h->tap.coord, child); - ret = go_next_node (h, &lock, NULL); - } while(0); + set_child_delimiting_keys(h->tap.coord->node, h->tap.coord, + child); + ret = go_next_node(h, &lock, NULL); + } while (0); zput(child); done_lh(&lock); return ret; } + /* Traverse the reiser4 tree until either all tree traversing is done or an * error encountered (including recoverable ones as -E_DEADLOCK or -E_REPEAT). The * @actor function is able to stop tree traversal by returning an appropriate * error code. */ -static int tw_by_handle (struct tw_handle * h) +static int tw_by_handle(struct tw_handle *h) { int ret; lock_handle next_lock; @@ -1089,7 +1119,7 @@ static int tw_by_handle (struct tw_handl if (ret) return ret; - init_lh (&next_lock); + init_lh(&next_lock); while (!h->done) { tree_level level; @@ -1102,7 +1132,7 @@ static int tw_by_handle (struct tw_handl continue; } - assert ("zam-944", coord_is_existing_unit(h->tap.coord)); + assert("zam-944", coord_is_existing_unit(h->tap.coord)); level = znode_get_level(h->tap.lh->node); if (level == LEAF_LEVEL) { @@ -1112,7 +1142,9 @@ static int tw_by_handle (struct tw_handl if (item_is_extent(h->tap.coord)) { if (h->actor->process_extent != NULL) { - ret = (h->actor->process_extent)(&h->tap, h->opaque); + ret = + (h->actor->process_extent) (&h->tap, + h->opaque); if (ret) break; } @@ -1130,8 +1162,9 @@ static int tw_by_handle (struct tw_handl } /* Walk the reiser4 tree in parent-first order */ -reiser4_internal int -tree_walk (const reiser4_key *start_key, int go_left, struct tree_walk_actor * actor, void * opaque) +int +tree_walk(const reiser4_key * start_key, int go_left, + struct tree_walk_actor *actor, void *opaque) { coord_t coord; lock_handle lock; @@ -1139,7 +1172,7 @@ tree_walk (const reiser4_key *start_key, int ret; - assert ("zam-950", actor != NULL); + assert("zam-950", actor != NULL); handle.actor = actor; handle.opaque = opaque; @@ -1180,11 +1213,13 @@ tree_walk (const reiser4_key *start_key, return ret; } - ret = coord_by_key(current_tree, &handle.start_key, &coord, &lock, ZNODE_WRITE_LOCK, - FIND_MAX_NOT_MORE_THAN, TWIG_LEVEL, LEAF_LEVEL, 0, NULL); + ret = + coord_by_key(current_tree, &handle.start_key, &coord, &lock, + ZNODE_WRITE_LOCK, FIND_MAX_NOT_MORE_THAN, + TWIG_LEVEL, LEAF_LEVEL, 0, NULL); if (ret != CBK_COORD_FOUND) break; - no_start_key: + no_start_key: tap_init(&handle.tap, &coord, &lock, ZNODE_WRITE_LOCK); ret = update_start_key(&handle); @@ -1193,16 +1228,15 @@ tree_walk (const reiser4_key *start_key, break; } ret = tw_by_handle(&handle); - tap_done (&handle.tap); + tap_done(&handle.tap); } while (!handle.done && (ret == -E_DEADLOCK || ret == -E_REPEAT)); - done: + done: done_lh(&lock); return ret; } - /* Local variables: c-indentation-style: "K&R" diff -puN fs/reiser4/tree_walk.h~reiser4-big-update fs/reiser4/tree_walk.h --- devel/fs/reiser4/tree_walk.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/tree_walk.h 2005-09-15 19:51:08.000000000 -0700 @@ -61,31 +61,35 @@ typedef enum { } znode_get_neigbor_flags; /* A commonly used wrapper for reiser4_get_parent_flags(). */ -static inline int reiser4_get_parent( - lock_handle * result, znode * node, znode_lock_mode mode) +static inline int reiser4_get_parent(lock_handle * result, znode * node, + znode_lock_mode mode) { - return reiser4_get_parent_flags(result, node, mode, GN_ALLOW_NOT_CONNECTED); + return reiser4_get_parent_flags(result, node, mode, + GN_ALLOW_NOT_CONNECTED); } -int reiser4_get_neighbor(lock_handle * neighbor, znode * node, znode_lock_mode lock_mode, int flags); +int reiser4_get_neighbor(lock_handle * neighbor, znode * node, + znode_lock_mode lock_mode, int flags); /* there are wrappers for most common usages of reiser4_get_neighbor() */ static inline int -reiser4_get_left_neighbor(lock_handle * result, znode * node, int lock_mode, int flags) +reiser4_get_left_neighbor(lock_handle * result, znode * node, int lock_mode, + int flags) { - return reiser4_get_neighbor(result, node, lock_mode, flags | GN_GO_LEFT); + return reiser4_get_neighbor(result, node, lock_mode, + flags | GN_GO_LEFT); } static inline int -reiser4_get_right_neighbor(lock_handle * result, znode * node, int lock_mode, int flags) +reiser4_get_right_neighbor(lock_handle * result, znode * node, int lock_mode, + int flags) { ON_DEBUG(check_lock_node_data(node)); ON_DEBUG(check_lock_data()); - return reiser4_get_neighbor(result, node, lock_mode, flags & (~GN_GO_LEFT)); + return reiser4_get_neighbor(result, node, lock_mode, + flags & (~GN_GO_LEFT)); } -extern void invalidate_lock(lock_handle * _link); - extern void sibling_list_remove(znode * node); extern void sibling_list_drop(znode * node); extern void sibling_list_insert_nolock(znode * new, znode * before); @@ -94,14 +98,15 @@ extern void link_left_and_right(znode * /* Functions called by tree_walk() when tree_walk() ... */ struct tree_walk_actor { /* ... meets a formatted node, */ - int (*process_znode)(tap_t* , void*); + int (*process_znode) (tap_t *, void *); /* ... meets an extent, */ - int (*process_extent)(tap_t*, void*); + int (*process_extent) (tap_t *, void *); /* ... begins tree traversal or repeats it after -E_REPEAT was returned by * node or extent processing functions. */ - int (*before)(void *); + int (*before) (void *); }; -extern int tree_walk(const reiser4_key *, int, struct tree_walk_actor *, void *); +extern int tree_walk(const reiser4_key *, int, struct tree_walk_actor *, + void *); #if REISER4_DEBUG int check_sibling_list(znode * node); diff -puN fs/reiser4/txnmgr.c~reiser4-big-update fs/reiser4/txnmgr.c --- devel/fs/reiser4/txnmgr.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/txnmgr.c 2005-09-15 19:51:08.000000000 -0700 @@ -219,7 +219,6 @@ year old --- define all technical terms */ #include "debug.h" -#include "type_safe_list.h" #include "txnmgr.h" #include "jnode.h" #include "znode.h" @@ -241,7 +240,7 @@ year old --- define all technical terms #include #include #include -#include /* for totalram_pages */ +#include /* for totalram_pages */ static void atom_free(txn_atom * atom); @@ -256,19 +255,23 @@ static void capture_assign_block_nolock( static int capture_assign_block(txn_handle * txnh, jnode * node); -static int capture_assign_txnh(jnode * node, txn_handle * txnh, txn_capture mode, int can_coc); +static int capture_assign_txnh(jnode * node, txn_handle * txnh, + txn_capture mode, int can_coc); static int fuse_not_fused_lock_owners(txn_handle * txnh, znode * node); -static int capture_init_fusion(jnode * node, txn_handle * txnh, txn_capture mode, int can_coc); +static int capture_init_fusion(jnode * node, txn_handle * txnh, + txn_capture mode, int can_coc); -static int capture_fuse_wait(jnode * node, txn_handle * txnh, txn_atom * atomf, txn_atom * atomh, txn_capture mode); +static int capture_fuse_wait(jnode * node, txn_handle * txnh, txn_atom * atomf, + txn_atom * atomh, txn_capture mode); static void capture_fuse_into(txn_atom * small, txn_atom * large); -static int capture_copy(jnode * node, txn_handle * txnh, txn_atom * atomf, txn_atom * atomh, txn_capture mode, int can_coc); +static int capture_copy(jnode * node, txn_handle * txnh, txn_atom * atomf, + txn_atom * atomh, txn_capture mode, int can_coc); -void invalidate_list(capture_list_head *); +void invalidate_list(struct list_head *); /* GENERIC STRUCTURES */ @@ -276,111 +279,94 @@ typedef struct _txn_wait_links txn_wait_ struct _txn_wait_links { lock_stack *_lock_stack; - fwaitfor_list_link _fwaitfor_link; - fwaiting_list_link _fwaiting_link; - int (*waitfor_cb)(txn_atom *atom, struct _txn_wait_links *wlinks); - int (*waiting_cb)(txn_atom *atom, struct _txn_wait_links *wlinks); + struct list_head _fwaitfor_link; + struct list_head _fwaiting_link; + int (*waitfor_cb) (txn_atom * atom, struct _txn_wait_links * wlinks); + int (*waiting_cb) (txn_atom * atom, struct _txn_wait_links * wlinks); }; -TYPE_SAFE_LIST_DEFINE(txnh, txn_handle, txnh_link); - -TYPE_SAFE_LIST_DEFINE(fwaitfor, txn_wait_links, _fwaitfor_link); -TYPE_SAFE_LIST_DEFINE(fwaiting, txn_wait_links, _fwaiting_link); - /* FIXME: In theory, we should be using the slab cache init & destructor methods instead of, e.g., jnode_init, etc. */ static kmem_cache_t *_atom_slab = NULL; /* this is for user-visible, cross system-call transactions. */ static kmem_cache_t *_txnh_slab = NULL; -ON_DEBUG(extern atomic_t flush_cnt;) - -/* TXN_INIT */ -/* Initialize static variables in this file. */ -reiser4_internal int -txnmgr_init_static(void) +/** + * init_txnmgr_static - create transaction manager slab caches + * + * Initializes caches of txn-atoms and txn_handle. It is part of reiser4 module + * initialization. + */ +int init_txnmgr_static(void) { assert("jmacd-600", _atom_slab == NULL); assert("jmacd-601", _txnh_slab == NULL); ON_DEBUG(atomic_set(&flush_cnt, 0)); - _atom_slab = kmem_cache_create("txn_atom", sizeof (txn_atom), 0, - SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, - NULL, NULL); - - if (_atom_slab == NULL) { - goto error; - } - - _txnh_slab = kmem_cache_create("txn_handle", sizeof (txn_handle), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + _atom_slab = kmem_cache_create("txn_atom", sizeof(txn_atom), 0, + SLAB_HWCACHE_ALIGN | + SLAB_RECLAIM_ACCOUNT, NULL, NULL); + if (_atom_slab == NULL) + return RETERR(-ENOMEM); + _txnh_slab = kmem_cache_create("txn_handle", sizeof(txn_handle), 0, + SLAB_HWCACHE_ALIGN, NULL, NULL); if (_txnh_slab == NULL) { - goto error; + kmem_cache_destroy(_atom_slab); + _atom_slab = NULL; + return RETERR(-ENOMEM); } return 0; - -error: - - if (_atom_slab != NULL) { - kmem_cache_destroy(_atom_slab); - } - if (_txnh_slab != NULL) { - kmem_cache_destroy(_txnh_slab); - } - return RETERR(-ENOMEM); } -/* Un-initialize static variables in this file. */ -reiser4_internal int -txnmgr_done_static(void) +/** + * done_txnmgr_static - delete txn_atom and txn_handle caches + * + * This is called on reiser4 module unloading or system shutdown. + */ +void done_txnmgr_static(void) { - int ret1, ret2, ret3; - - ret1 = ret2 = ret3 = 0; - - if (_atom_slab != NULL) { - ret1 = kmem_cache_destroy(_atom_slab); - _atom_slab = NULL; - } - - if (_txnh_slab != NULL) { - ret2 = kmem_cache_destroy(_txnh_slab); - _txnh_slab = NULL; - } - - return ret1 ? : ret2; + destroy_reiser4_cache(&_atom_slab); + destroy_reiser4_cache(&_txnh_slab); } -/* Initialize a new transaction manager. Called when the super_block is initialized. */ -reiser4_internal void -txnmgr_init(txn_mgr * mgr) +/** + * init_txnmgr - initialize a new transaction manager + * @mgr: pointer to transaction manager embedded in reiser4 super block + * + * This is called on mount. Makes necessary initializations. + */ +void init_txnmgr(txn_mgr *mgr) { assert("umka-169", mgr != NULL); mgr->atom_count = 0; mgr->id_count = 1; - atom_list_init(&mgr->atoms_list); + INIT_LIST_HEAD(&mgr->atoms_list); spin_txnmgr_init(mgr); sema_init(&mgr->commit_semaphore, 1); } -/* Free transaction manager. */ -reiser4_internal int -txnmgr_done(txn_mgr * mgr UNUSED_ARG) +/** + * done_txnmgr - stop transaction manager + * @mgr: pointer to transaction manager embedded in reiser4 super block + * + * This is called on umount. Does sanity checks. + */ +void done_txnmgr(txn_mgr *mgr) { assert("umka-170", mgr != NULL); - - return 0; + assert("umka-1701", list_empty_careful(&mgr->atoms_list)); + assert("umka-1702", mgr->atom_count == 0); } /* Initialize a transaction handle. */ /* Audited by: umka (2002.06.13) */ -static void -txnh_init(txn_handle * txnh, txn_mode mode) +static void txnh_init(txn_handle * txnh, txn_mode mode) { assert("umka-171", txnh != NULL); @@ -390,13 +376,12 @@ txnh_init(txn_handle * txnh, txn_mode mo spin_txnh_init(txnh); - txnh_list_clean(txnh); + INIT_LIST_HEAD(&txnh->txnh_link); } #if REISER4_DEBUG /* Check if a transaction handle is clean. */ -static int -txnh_isclean(txn_handle * txnh) +static int txnh_isclean(txn_handle * txnh) { assert("umka-172", txnh != NULL); return txnh->atom == NULL && spin_txnh_is_not_locked(txnh); @@ -404,31 +389,32 @@ txnh_isclean(txn_handle * txnh) #endif /* Initialize an atom. */ -static void -atom_init(txn_atom * atom) +static void atom_init(txn_atom * atom) { int level; assert("umka-173", atom != NULL); - memset(atom, 0, sizeof (txn_atom)); + memset(atom, 0, sizeof(txn_atom)); atom->stage = ASTAGE_FREE; atom->start_time = jiffies; for (level = 0; level < REAL_MAX_ZTREE_HEIGHT + 1; level += 1) - capture_list_init(ATOM_DIRTY_LIST(atom, level)); + INIT_LIST_HEAD(ATOM_DIRTY_LIST(atom, level)); - capture_list_init(ATOM_CLEAN_LIST(atom)); - capture_list_init(ATOM_OVRWR_LIST(atom)); - capture_list_init(ATOM_WB_LIST(atom)); - capture_list_init(&atom->inodes); + INIT_LIST_HEAD(ATOM_CLEAN_LIST(atom)); + INIT_LIST_HEAD(ATOM_OVRWR_LIST(atom)); + INIT_LIST_HEAD(ATOM_WB_LIST(atom)); + INIT_LIST_HEAD(&atom->inodes); spin_atom_init(atom); - txnh_list_init(&atom->txnh_list); - atom_list_clean(atom); - fwaitfor_list_init(&atom->fwaitfor_list); - fwaiting_list_init(&atom->fwaiting_list); - prot_list_init(&atom->protected); + /* list of transaction handles */ + INIT_LIST_HEAD(&atom->txnh_list); + /* link to transaction manager's list of atoms */ + INIT_LIST_HEAD(&atom->atom_link); + INIT_LIST_HEAD(&atom->fwaitfor_list); + INIT_LIST_HEAD(&atom->fwaiting_list); + INIT_LIST_HEAD(&atom->protected); blocknr_set_init(&atom->delete_set); blocknr_set_init(&atom->wandered_map); @@ -437,32 +423,31 @@ atom_init(txn_atom * atom) #if REISER4_DEBUG /* Check if an atom is clean. */ -static int -atom_isclean(txn_atom * atom) +static int atom_isclean(txn_atom * atom) { int level; assert("umka-174", atom != NULL); for (level = 0; level < REAL_MAX_ZTREE_HEIGHT + 1; level += 1) { - if (!capture_list_empty(ATOM_DIRTY_LIST(atom, level))) { + if (!list_empty_careful(ATOM_DIRTY_LIST(atom, level))) { return 0; } } - return - atom->stage == ASTAGE_FREE && + return atom->stage == ASTAGE_FREE && atom->txnh_count == 0 && atom->capture_count == 0 && atomic_read(&atom->refcount) == 0 && - atom_list_is_clean(atom) && - txnh_list_empty(&atom->txnh_list) && - capture_list_empty(ATOM_CLEAN_LIST(atom)) && - capture_list_empty(ATOM_OVRWR_LIST(atom)) && - capture_list_empty(ATOM_WB_LIST(atom)) && - fwaitfor_list_empty(&atom->fwaitfor_list) && - fwaiting_list_empty(&atom->fwaiting_list) && - prot_list_empty(&atom->protected) && + (&atom->atom_link == atom->atom_link.next && + &atom->atom_link == atom->atom_link.prev) && + list_empty_careful(&atom->txnh_list) && + list_empty_careful(ATOM_CLEAN_LIST(atom)) && + list_empty_careful(ATOM_OVRWR_LIST(atom)) && + list_empty_careful(ATOM_WB_LIST(atom)) && + list_empty_careful(&atom->fwaitfor_list) && + list_empty_careful(&atom->fwaiting_list) && + list_empty_careful(&atom->protected) && atom_fq_parts_are_clean(atom); } #endif @@ -471,8 +456,7 @@ atom_isclean(txn_atom * atom) trans_in_ctx, which means that transaction handles are stack-allocated. Eventually this will be extended to allow transaction handles to span several contexts. */ /* Audited by: umka (2002.06.13) */ -reiser4_internal void -txn_begin(reiser4_context * context) +void txn_begin(reiser4_context * context) { assert("jmacd-544", context->trans == NULL); @@ -482,24 +466,19 @@ txn_begin(reiser4_context * context) transcrash. Default should be TXN_WRITE_FUSING. Also, the _trans variable is stack allocated right now, but we would like to allow for dynamically allocated transcrashes that span multiple system calls. - */ + */ txnh_init(context->trans, TXN_WRITE_FUSING); } /* Finish a transaction handle context. */ -reiser4_internal int -txn_end(reiser4_context * context) +int txn_end(reiser4_context * context) { long ret = 0; txn_handle *txnh; assert("umka-283", context != NULL); assert("nikita-3012", schedulable()); - - /* closing non top-level context---nothing to do */ - if (context != context->parent) - return 0; - + assert("vs-24", context == get_current_context()); assert("nikita-2967", lock_stack_isclean(get_current_lock_stack())); txnh = context->trans; @@ -523,16 +502,14 @@ txn_end(reiser4_context * context) return ret; } -reiser4_internal void -txn_restart(reiser4_context * context) +void txn_restart(reiser4_context * context) { txn_end(context); preempt_point(); txn_begin(context); } -reiser4_internal void -txn_restart_current(void) +void txn_restart_current(void) { txn_restart(get_current_context()); } @@ -542,8 +519,7 @@ txn_restart_current(void) /* Get the atom belonging to a txnh, which is not locked. Return txnh locked. Locks atom, if atom is not NULL. This performs the necessary spin_trylock to break the lock-ordering cycle. May return NULL. */ -static txn_atom * -txnh_get_atom(txn_handle * txnh) +static txn_atom *txnh_get_atom(txn_handle * txnh) { txn_atom *atom; @@ -579,8 +555,7 @@ txnh_get_atom(txn_handle * txnh) } /* Get the current atom and spinlock it if current atom present. May return NULL */ -reiser4_internal txn_atom * -get_current_atom_locked_nocheck(void) +txn_atom *get_current_atom_locked_nocheck(void) { reiser4_context *cx; txn_atom *atom; @@ -602,8 +577,7 @@ get_current_atom_locked_nocheck(void) both jnode and atom locked. This performs the necessary spin_trylock to break the lock-ordering cycle. Assumes the jnode is already locked, and returns NULL if atom is not set. */ -reiser4_internal txn_atom * -jnode_get_atom(jnode * node) +txn_atom *jnode_get_atom(jnode * node) { txn_atom *atom; @@ -656,7 +630,7 @@ jnode_get_atom(jnode * node) /* Returns true if @node is dirty and part of the same atom as one of its neighbors. Used by flush code to indicate whether the next node (in some direction) is suitable for flushing. */ -reiser4_internal int +int same_slum_check(jnode * node, jnode * check, int alloc_check, int alloc_value) { int compat; @@ -667,14 +641,15 @@ same_slum_check(jnode * node, jnode * ch /* Not sure what this function is supposed to do if supplied with @check that is neither formatted nor unformatted (bitmap or so). */ - assert("nikita-2373", jnode_is_znode(check) || jnode_is_unformatted(check)); + assert("nikita-2373", jnode_is_znode(check) + || jnode_is_unformatted(check)); /* Need a lock on CHECK to get its atom and to check various state bits. Don't need a lock on NODE once we get the atom lock. */ /* It is not enough to lock two nodes and check (node->atom == check->atom) because atom could be locked and being fused at that moment, jnodes of the atom of that state (being fused) can point to - different objects, but the atom is the same.*/ + different objects, but the atom is the same. */ LOCK_JNODE(check); atom = jnode_get_atom(check); @@ -701,8 +676,7 @@ same_slum_check(jnode * node, jnode * ch } /* Decrement the atom's reference count and if it falls to zero, free it. */ -reiser4_internal void -atom_dec_and_unlock(txn_atom * atom) +void atom_dec_and_unlock(txn_atom * atom) { txn_mgr *mgr = &get_super_private(reiser4_get_current_sb())->tmgr; @@ -733,62 +707,43 @@ atom_dec_and_unlock(txn_atom * atom) UNLOCK_ATOM(atom); } -/* Return a new atom, locked. This adds the atom to the transaction manager's list and - sets its reference count to 1, an artificial reference which is kept until it - commits. We play strange games to avoid allocation under jnode & txnh spinlocks.*/ - -/* ZAM-FIXME-HANS: should we set node->atom and txnh->atom here also? */ -/* ANSWER(ZAM): there are special functions, capture_assign_txnh_nolock() and - capture_assign_block_nolock(), they are called right after calling - atom_begin_and_lock(). It could be done here, but, for understandability, it - is better to keep those calls inside try_capture_block main routine where all - assignments are made. */ -static txn_atom * -atom_begin_andlock(txn_atom ** atom_alloc, jnode * node, txn_handle * txnh) +/* Create new atom and connect it to given transaction handle. This adds the + atom to the transaction manager's list and sets its reference count to 1, an + artificial reference which is kept until it commits. We play strange games + to avoid allocation under jnode & txnh spinlocks.*/ + +static int atom_begin_and_assign_to_txnh(txn_atom ** atom_alloc, txn_handle * txnh) { txn_atom *atom; txn_mgr *mgr; - assert("jmacd-43228", spin_jnode_is_locked(node)); - assert("jmacd-43227", spin_txnh_is_locked(txnh)); - assert("jmacd-43226", node->atom == NULL); - assert("jmacd-43225", txnh->atom == NULL); - - if (REISER4_DEBUG && rofs_jnode(node)) { + if (REISER4_DEBUG && rofs_tree(current_tree)) { warning("nikita-3366", "Creating atom on rofs"); dump_stack(); } - /* A memory allocation may schedule we have to release those spinlocks - * before kmem_cache_alloc() call. */ - UNLOCK_JNODE(node); - UNLOCK_TXNH(txnh); - if (*atom_alloc == NULL) { (*atom_alloc) = kmem_cache_alloc(_atom_slab, GFP_KERNEL); if (*atom_alloc == NULL) - return ERR_PTR(RETERR(-ENOMEM)); + return RETERR(-ENOMEM); } /* and, also, txnmgr spin lock should be taken before jnode and txnh locks. */ mgr = &get_super_private(reiser4_get_current_sb())->tmgr; spin_lock_txnmgr(mgr); - - LOCK_JNODE(node); LOCK_TXNH(txnh); - /* Check if both atom pointers are still NULL... */ - if (node->atom != NULL || txnh->atom != NULL) { + /* Check whether new atom still needed */ + if (txnh->atom != NULL) { /* NOTE-NIKITA probably it is rather better to free * atom_alloc here than thread it up to try_capture(). */ UNLOCK_TXNH(txnh); - UNLOCK_JNODE(node); spin_unlock_txnmgr(mgr); - return ERR_PTR(-E_REPEAT); + return -E_REPEAT; } atom = *atom_alloc; @@ -802,7 +757,8 @@ atom_begin_andlock(txn_atom ** atom_allo @atom is new and inaccessible for others. */ spin_lock_atom_no_ord(atom); - atom_list_push_back(&mgr->atoms_list, atom); + /* add atom to the end of transaction manager's list of atoms */ + list_add_tail(&atom->atom_link, &mgr->atoms_list); atom->atom_id = mgr->id_count++; mgr->atom_count += 1; @@ -811,10 +767,14 @@ atom_begin_andlock(txn_atom ** atom_allo /* One reference until it commits. */ atomic_inc(&atom->refcount); - atom->stage = ASTAGE_CAPTURE_FUSE; + atom->super = reiser4_get_current_sb(); + capture_assign_txnh_nolock(atom, txnh); - return atom; + UNLOCK_ATOM(atom); + UNLOCK_TXNH(txnh); + + return -E_REPEAT; } #if REISER4_DEBUG @@ -830,8 +790,7 @@ static int atom_isopen(const txn_atom * /* Return the number of pointers to this atom that must be updated during fusion. This approximates the amount of work to be done. Fusion chooses the atom with fewer pointers to fuse into the atom with more pointers. */ -static int -atom_pointer_count(const txn_atom * atom) +static int atom_pointer_count(const txn_atom * atom) { assert("umka-187", atom != NULL); @@ -842,8 +801,7 @@ atom_pointer_count(const txn_atom * atom /* Called holding the atom lock, this removes the atom from the transaction manager list and frees it. */ -static void -atom_free(txn_atom * atom) +static void atom_free(txn_atom * atom) { txn_mgr *mgr = &get_super_private(reiser4_get_current_sb())->tmgr; @@ -853,10 +811,11 @@ atom_free(txn_atom * atom) /* Remove from the txn_mgr's atom list */ assert("nikita-2657", spin_txnmgr_is_locked(mgr)); mgr->atom_count -= 1; - atom_list_remove_clean(atom); + list_del_init(&atom->atom_link); /* Clean the atom */ - assert("jmacd-16", (atom->stage == ASTAGE_INVALID || atom->stage == ASTAGE_DONE)); + assert("jmacd-16", + (atom->stage == ASTAGE_INVALID || atom->stage == ASTAGE_DONE)); atom->stage = ASTAGE_FREE; blocknr_set_destroy(&atom->delete_set); @@ -869,36 +828,35 @@ atom_free(txn_atom * atom) kmem_cache_free(_atom_slab, atom); } -static int -atom_is_dotard(const txn_atom * atom) +static int atom_is_dotard(const txn_atom * atom) { return time_after(jiffies, atom->start_time + get_current_super_private()->tmgr.atom_max_age); } -static int atom_can_be_committed (txn_atom * atom) +static int atom_can_be_committed(txn_atom * atom) { - assert ("zam-884", spin_atom_is_locked(atom)); - assert ("zam-885", atom->txnh_count > atom->nr_waiters); + assert("zam-884", spin_atom_is_locked(atom)); + assert("zam-885", atom->txnh_count > atom->nr_waiters); return atom->txnh_count == atom->nr_waiters + 1; } /* Return true if an atom should commit now. This is determined by aging, atom size or atom flags. */ -static int -atom_should_commit(const txn_atom * atom) +static int atom_should_commit(const txn_atom * atom) { assert("umka-189", atom != NULL); return - (atom->flags & ATOM_FORCE_COMMIT) || - ((unsigned) atom_pointer_count(atom) > get_current_super_private()->tmgr.atom_max_size) || - atom_is_dotard(atom); + (atom->flags & ATOM_FORCE_COMMIT) || + ((unsigned)atom_pointer_count(atom) > + get_current_super_private()->tmgr.atom_max_size) + || atom_is_dotard(atom); } /* return 1 if current atom exists and requires commit. */ -reiser4_internal int current_atom_should_commit(void) +int current_atom_should_commit(void) { - txn_atom * atom; + txn_atom *atom; int result = 0; atom = get_current_atom_locked_nocheck(); @@ -909,33 +867,33 @@ reiser4_internal int current_atom_should return result; } -static int -atom_should_commit_asap(const txn_atom * atom) +static int atom_should_commit_asap(const txn_atom * atom) { unsigned int captured; unsigned int pinnedpages; assert("nikita-3309", atom != NULL); - captured = (unsigned) atom->capture_count; + captured = (unsigned)atom->capture_count; pinnedpages = (captured >> PAGE_CACHE_SHIFT) * sizeof(znode); - return - (pinnedpages > (totalram_pages >> 3)) || - (atom->flushed > 100); + return (pinnedpages > (totalram_pages >> 3)) || (atom->flushed > 100); } -static jnode * find_first_dirty_in_list (capture_list_head * head, int flags) +static jnode *find_first_dirty_in_list(struct list_head *head, int flags) { - jnode * first_dirty; + jnode *first_dirty; + struct list_head *pos; - for_all_type_safe_list(capture, head, first_dirty) { + list_for_each(pos, head) { + first_dirty = list_entry(pos, jnode, capture_link); if (!(flags & JNODE_FLUSH_COMMIT)) { - if ( - /* skip jnodes which have "heard banshee" */ - JF_ISSET(first_dirty, JNODE_HEARD_BANSHEE) || - /* and with active I/O */ - JF_ISSET(first_dirty, JNODE_WRITEBACK)) + /* + * skip jnodes which "heard banshee" or having active + * I/O + */ + if (JF_ISSET(first_dirty, JNODE_HEARD_BANSHEE) || + JF_ISSET(first_dirty, JNODE_WRITEBACK)) continue; } return first_dirty; @@ -945,7 +903,7 @@ static jnode * find_first_dirty_in_list /* Get first dirty node from the atom's dirty_nodes[n] lists; return NULL if atom has no dirty nodes on atom's lists */ -reiser4_internal jnode * find_first_dirty_jnode (txn_atom * atom, int flags) +jnode *find_first_dirty_jnode(txn_atom * atom, int flags) { jnode *first_dirty; tree_level level; @@ -954,10 +912,12 @@ reiser4_internal jnode * find_first_dirt /* The flush starts from LEAF_LEVEL (=1). */ for (level = 1; level < REAL_MAX_ZTREE_HEIGHT + 1; level += 1) { - if (capture_list_empty(ATOM_DIRTY_LIST(atom, level))) + if (list_empty_careful(ATOM_DIRTY_LIST(atom, level))) continue; - first_dirty = find_first_dirty_in_list(ATOM_DIRTY_LIST(atom, level), flags); + first_dirty = + find_first_dirty_in_list(ATOM_DIRTY_LIST(atom, level), + flags); if (first_dirty) return first_dirty; } @@ -977,9 +937,9 @@ spinlock_t scan_lock = SPIN_LOCK_UNLOCKE * list. */ /* NOTE: doing that in end IO handler requires using of special spinlocks which * disables interrupts in all places except IO handler. That is expensive. */ -static void dispatch_wb_list (txn_atom * atom, flush_queue_t * fq) +static void dispatch_wb_list(txn_atom * atom, flush_queue_t * fq) { - jnode * cur; + jnode *cur; int total, moved; assert("zam-905", spin_atom_is_locked(atom)); @@ -990,9 +950,9 @@ static void dispatch_wb_list (txn_atom * spin_lock(&scan_lock); cur = capture_list_front(ATOM_WB_LIST(atom)); while (!capture_list_end(ATOM_WB_LIST(atom), cur)) { - jnode * next; + jnode *next; - total ++; + total++; JF_SET(cur, JNODE_SCANNED); next = capture_list_next(cur); if (!capture_list_end(ATOM_WB_LIST(atom), next)) @@ -1003,14 +963,16 @@ static void dispatch_wb_list (txn_atom * LOCK_JNODE(cur); assert("vs-1441", NODE_LIST(cur) == WB_LIST); if (!JF_ISSET(cur, JNODE_WRITEBACK)) { - moved ++; + moved++; if (JF_ISSET(cur, JNODE_DIRTY)) { queue_jnode(fq, cur); } else { /* move from writeback list to clean list */ capture_list_remove(cur); - capture_list_push_back(ATOM_CLEAN_LIST(atom), cur); - ON_DEBUG(count_jnode(atom, cur, WB_LIST, CLEAN_LIST, 1)); + capture_list_push_back(ATOM_CLEAN_LIST(atom), + cur); + ON_DEBUG(count_jnode + (atom, cur, WB_LIST, CLEAN_LIST, 1)); } } UNLOCK_JNODE(cur); @@ -1018,47 +980,51 @@ static void dispatch_wb_list (txn_atom * spin_lock(&scan_lock); JF_CLR(cur, JNODE_SCANNED); cur = next; - assert("vs-1450", ergo(!capture_list_end(ATOM_WB_LIST(atom), cur), - JF_ISSET(cur, JNODE_SCANNED) && NODE_LIST(cur) == WB_LIST)); + assert("vs-1450", + ergo(!capture_list_end(ATOM_WB_LIST(atom), cur), + JF_ISSET(cur, JNODE_SCANNED) + && NODE_LIST(cur) == WB_LIST)); } spin_unlock(&scan_lock); } #else -static void dispatch_wb_list (txn_atom * atom, flush_queue_t * fq) +static void dispatch_wb_list(txn_atom * atom, flush_queue_t * fq) { - jnode * cur; + jnode *cur; + + assert("zam-905", atom_is_protected(atom)); - assert("zam-905", atom_is_protected(atom)); + cur = list_entry(ATOM_WB_LIST(atom)->next, jnode, capture_link); + while (ATOM_WB_LIST(atom) != &cur->capture_link) { + jnode *next = list_entry(cur->capture_link.next, jnode, capture_link); - cur = capture_list_front(ATOM_WB_LIST(atom)); - while (!capture_list_end(ATOM_WB_LIST(atom), cur)) { - jnode * next = capture_list_next(cur); - - LOCK_JNODE(cur); - if (!JF_ISSET(cur, JNODE_WRITEBACK)) { - if (JF_ISSET(cur, JNODE_DIRTY)) { - queue_jnode(fq, cur); - } else { - capture_list_remove(cur); - capture_list_push_back(ATOM_CLEAN_LIST(atom), cur); - } - } - UNLOCK_JNODE(cur); + LOCK_JNODE(cur); + if (!JF_ISSET(cur, JNODE_WRITEBACK)) { + if (JF_ISSET(cur, JNODE_DIRTY)) { + queue_jnode(fq, cur); + } else { + /* move jnode to atom's clean list */ + list_del(&cur->capture_link); + list_add_tail(&cur->capture_link, + ATOM_CLEAN_LIST(atom)); + } + } + UNLOCK_JNODE(cur); - cur = next; - } + cur = next; + } } #endif /* Scan current atom->writeback_nodes list, re-submit dirty and !writeback * jnodes to disk. */ -static int submit_wb_list (void) +static int submit_wb_list(void) { int ret; - flush_queue_t * fq; + flush_queue_t *fq; fq = get_fq_for_current_atom(); if (IS_ERR(fq)) @@ -1074,7 +1040,7 @@ static int submit_wb_list (void) } /* Wait completion of all writes, re-submit atom writeback list if needed. */ -static int current_atom_complete_writes (void) +static int current_atom_complete_writes(void) { int ret; @@ -1093,7 +1059,7 @@ static int current_atom_complete_writes /* Scan wb list again; all i/o should be completed, we re-submit dirty * nodes to disk */ ret = submit_wb_list(); - if(ret < 0) + if (ret < 0) return ret; /* Wait all nodes we just submitted */ @@ -1114,25 +1080,29 @@ static int current_atom_complete_writes Return value is an error code if commit fails. */ -static int commit_current_atom (long *nr_submitted, txn_atom ** atom) +static int commit_current_atom(long *nr_submitted, txn_atom ** atom) { - reiser4_super_info_data * sbinfo = get_current_super_private (); - long ret; + reiser4_super_info_data *sbinfo = get_current_super_private(); + long ret = 0; /* how many times jnode_flush() was called as a part of attempt to * commit this atom. */ - int flushiters; + int flushiters; - assert ("zam-888", atom != NULL && *atom != NULL); - assert ("zam-886", spin_atom_is_locked(*atom)); - assert ("zam-887", get_current_context()->trans->atom == *atom); + assert("zam-888", atom != NULL && *atom != NULL); + assert("zam-886", spin_atom_is_locked(*atom)); + assert("zam-887", get_current_context()->trans->atom == *atom); assert("jmacd-151", atom_isopen(*atom)); /* lock ordering: delete_sema and commit_sema are unordered */ assert("nikita-3184", get_current_super_private()->delete_sema_owner != current); - for (flushiters = 0 ;; ++ flushiters) { - ret = flush_current_atom(JNODE_FLUSH_WRITE_BLOCKS | JNODE_FLUSH_COMMIT, nr_submitted, atom); + for (flushiters = 0;; ++flushiters) { + ret = + flush_current_atom(JNODE_FLUSH_WRITE_BLOCKS | + JNODE_FLUSH_COMMIT, + LONG_MAX /* nr_to_write */ , + nr_submitted, atom, NULL); if (ret != -E_REPEAT) break; @@ -1153,26 +1123,28 @@ static int commit_current_atom (long *nr if (ret) return ret; - assert ("zam-882", spin_atom_is_locked(*atom)); + assert("zam-882", spin_atom_is_locked(*atom)); if (!atom_can_be_committed(*atom)) { UNLOCK_ATOM(*atom); return RETERR(-E_REPEAT); } + if ((*atom)->capture_count == 0) + goto done; + /* Up to this point we have been flushing and after flush is called we return -E_REPEAT. Now we can commit. We cannot return -E_REPEAT at this point, commit should be successful. */ atom_set_stage(*atom, ASTAGE_PRE_COMMIT); ON_DEBUG(((*atom)->committer = current)); - UNLOCK_ATOM(*atom); ret = current_atom_complete_writes(); if (ret) return ret; - assert ("zam-906", capture_list_empty(ATOM_WB_LIST(*atom))); + assert("zam-906", list_empty(ATOM_WB_LIST(*atom))); /* isolate critical code path which should be executed by only one * thread using tmgr semaphore */ @@ -1192,11 +1164,12 @@ static int commit_current_atom (long *nr invalidate_list(ATOM_CLEAN_LIST(*atom)); invalidate_list(ATOM_WB_LIST(*atom)); - assert("zam-927", capture_list_empty(&(*atom)->inodes)); + assert("zam-927", list_empty(&(*atom)->inodes)); LOCK_ATOM(*atom); + done: atom_set_stage(*atom, ASTAGE_DONE); - ON_DEBUG((*atom)->committer = 0); + ON_DEBUG((*atom)->committer = NULL); /* Atom's state changes, so wake up everybody waiting for this event. */ @@ -1218,18 +1191,18 @@ static int commit_current_atom (long *nr /* commit current atom and wait commit completion; atom and txn_handle should be * locked before call, this function unlocks them on exit. */ -static int force_commit_atom_nolock (txn_handle * txnh) +static int force_commit_atom_nolock(txn_handle * txnh) { - txn_atom * atom; + txn_atom *atom; - assert ("zam-837", txnh != NULL); - assert ("zam-835", spin_txnh_is_locked(txnh)); - assert ("nikita-2966", lock_stack_isclean(get_current_lock_stack())); + assert("zam-837", txnh != NULL); + assert("zam-835", spin_txnh_is_locked(txnh)); + assert("nikita-2966", lock_stack_isclean(get_current_lock_stack())); atom = txnh->atom; - assert ("zam-834", atom != NULL); - assert ("zam-836", spin_atom_is_locked(atom)); + assert("zam-834", atom != NULL); + assert("zam-836", spin_atom_is_locked(atom)); /* Set flags for atom and txnh: forcing atom commit and waiting for * commit completion */ @@ -1246,36 +1219,38 @@ static int force_commit_atom_nolock (txn /* Called to force commit of any outstanding atoms. @commit_all_atoms controls * should we commit all atoms including new ones which are created after this * functions is called. */ -reiser4_internal int -txnmgr_force_commit_all (struct super_block *super, int commit_all_atoms) +int txnmgr_force_commit_all(struct super_block *super, int commit_all_atoms) { int ret; txn_atom *atom; txn_mgr *mgr; txn_handle *txnh; unsigned long start_time = jiffies; - reiser4_context * ctx = get_current_context(); + reiser4_context *ctx = get_current_context(); + struct list_head *pos; assert("nikita-2965", lock_stack_isclean(get_current_lock_stack())); assert("nikita-3058", commit_check_locks()); - txn_restart(ctx); + txn_restart_current(); mgr = &get_super_private(super)->tmgr; txnh = ctx->trans; -again: + again: spin_lock_txnmgr(mgr); - for_all_type_safe_list(atom, &mgr->atoms_list, atom) { + list_for_each(pos, &mgr->atoms_list) { + atom = list_entry(pos, txn_atom, atom_link); LOCK_ATOM(atom); /* Commit any atom which can be committed. If @commit_new_atoms * is not set we commit only atoms which were created before * this call is started. */ - if (commit_all_atoms || time_before_eq(atom->start_time, start_time)) { + if (commit_all_atoms + || time_before_eq(atom->start_time, start_time)) { if (atom->stage <= ASTAGE_POST_COMMIT) { spin_unlock_txnmgr(mgr); @@ -1284,7 +1259,7 @@ again: /* Add force-context txnh */ capture_assign_txnh_nolock(atom, txnh); ret = force_commit_atom_nolock(txnh); - if(ret) + if (ret) return ret; } else /* wait atom commit */ @@ -1299,9 +1274,10 @@ again: #if REISER4_DEBUG if (commit_all_atoms) { - reiser4_super_info_data * sbinfo = get_super_private(super); + reiser4_super_info_data *sbinfo = get_super_private(super); reiser4_spin_lock_sb(sbinfo); - assert("zam-813", sbinfo->blocks_fake_allocated_unformatted == 0); + assert("zam-813", + sbinfo->blocks_fake_allocated_unformatted == 0); assert("zam-812", sbinfo->blocks_fake_allocated == 0); reiser4_spin_unlock_sb(sbinfo); } @@ -1314,24 +1290,22 @@ again: /* check whether commit_some_atoms() can commit @atom. Locking is up to the * caller */ -static int atom_is_committable(txn_atom *atom) +static int atom_is_committable(txn_atom * atom) { return - atom->stage < ASTAGE_PRE_COMMIT && - atom->txnh_count == atom->nr_waiters && - atom_should_commit(atom); + atom->stage < ASTAGE_PRE_COMMIT && + atom->txnh_count == atom->nr_waiters && atom_should_commit(atom); } /* called periodically from ktxnmgrd to commit old atoms. Releases ktxnmgrd spin * lock at exit */ -reiser4_internal int -commit_some_atoms(txn_mgr * mgr) +int commit_some_atoms(txn_mgr * mgr) { int ret = 0; txn_atom *atom; - txn_atom *next_atom; txn_handle *txnh; reiser4_context *ctx; + struct list_head *pos, *tmp; ctx = get_current_context(); assert("nikita-2444", ctx != NULL); @@ -1339,10 +1313,19 @@ commit_some_atoms(txn_mgr * mgr) txnh = ctx->trans; spin_lock_txnmgr(mgr); + /* + * this is to avoid gcc complain that atom might be used + * uninitialized + */ + atom = NULL; + /* look for atom to commit */ - for_all_type_safe_list_safe(atom, &mgr->atoms_list, atom, next_atom) { - /* first test without taking atom spin lock, whether it is - * eligible for committing at all */ + list_for_each_safe(pos, tmp, &mgr->atoms_list) { + atom = list_entry(pos, txn_atom, atom_link); + /* + * first test without taking atom spin lock, whether it is + * eligible for committing at all + */ if (atom_is_committable(atom)) { /* now, take spin lock and re-check */ LOCK_ATOM(atom); @@ -1352,7 +1335,7 @@ commit_some_atoms(txn_mgr * mgr) } } - ret = atom_list_end(&mgr->atoms_list, atom); + ret = (&mgr->atoms_list == pos); spin_unlock_txnmgr(mgr); if (ret) { @@ -1363,6 +1346,7 @@ commit_some_atoms(txn_mgr * mgr) LOCK_TXNH(txnh); + BUG_ON(atom == NULL); /* Set the atom to force committing */ atom->flags |= ATOM_FORCE_COMMIT; @@ -1376,17 +1360,18 @@ commit_some_atoms(txn_mgr * mgr) has to rescan atoms */ mgr->daemon->rescan = 1; spin_unlock(&mgr->daemon->guard); - txn_restart(ctx); + txn_restart_current(); return 0; } -static int txn_try_to_fuse_small_atom (txn_mgr * tmgr, txn_atom * atom) +static int txn_try_to_fuse_small_atom(txn_mgr * tmgr, txn_atom * atom) { int atom_stage; txn_atom *atom_2; int repeat; + struct list_head *pos; - assert ("zam-1051", atom->stage < ASTAGE_PRE_COMMIT); + assert("zam-1051", atom->stage < ASTAGE_PRE_COMMIT); atom_stage = atom->stage; repeat = 0; @@ -1400,11 +1385,14 @@ static int txn_try_to_fuse_small_atom (t goto out; } - for_all_type_safe_list(atom, &tmgr->atoms_list, atom_2) { + list_for_each(pos, &tmgr->atoms_list) { + atom_2 = list_entry(pos, txn_atom, atom_link); if (atom == atom_2) continue; - /* if trylock does not succeed we just do not fuse with that - * atom. */ + /* + * if trylock does not succeed we just do not fuse with that + * atom. + */ if (spin_trylock_atom(atom_2)) { if (atom_2->stage < ASTAGE_PRE_COMMIT) { spin_unlock_txnmgr(tmgr); @@ -1416,7 +1404,7 @@ static int txn_try_to_fuse_small_atom (t } } atom->flags |= ATOM_CANCEL_FUSION; - out: + out: spin_unlock_txnmgr(tmgr); if (repeat) { UNLOCK_ATOM(atom); @@ -1438,30 +1426,38 @@ static int txn_try_to_fuse_small_atom (t If atom is too large or too old it is committed also. */ -reiser4_internal int -flush_some_atom(long *nr_submitted, const struct writeback_control *wbc, int flags) +int +flush_some_atom(jnode * start, long *nr_submitted, const struct writeback_control *wbc, + int flags) { reiser4_context *ctx = get_current_context(); txn_mgr *tmgr = &get_super_private(ctx->super)->tmgr; txn_handle *txnh = ctx->trans; txn_atom *atom; int ret; + struct list_head *pos; + BUG_ON(wbc->nr_to_write == 0); + BUG_ON(*nr_submitted != 0); assert("zam-1042", txnh != NULL); - repeat: + repeat: if (txnh->atom == NULL) { /* current atom is not available, take first from txnmgr */ spin_lock_txnmgr(tmgr); /* traverse the list of all atoms */ - for_all_type_safe_list(atom, &tmgr->atoms_list, atom) { + list_for_each(pos, &tmgr->atoms_list) { + atom = list_entry(pos, txn_atom, atom_link); /* lock atom before checking its state */ LOCK_ATOM(atom); - /* we need an atom which is not being committed and which has no - * flushers (jnode_flush() add one flusher at the beginning and - * subtract one at the end). */ - if (atom->stage < ASTAGE_PRE_COMMIT && atom->nr_flushers == 0) { + /* + * we need an atom which is not being committed and + * which has no flushers (jnode_flush() add one flusher + * at the beginning and subtract one at the end). + */ + if (atom->stage < ASTAGE_PRE_COMMIT && + atom->nr_flushers == 0) { LOCK_TXNH(txnh); capture_assign_txnh_nolock(atom, txnh); UNLOCK_TXNH(txnh); @@ -1472,13 +1468,17 @@ flush_some_atom(long *nr_submitted, cons UNLOCK_ATOM(atom); } - /* Write throttling is case of no one atom can be - * flushed/committed. */ + /* + * Write throttling is case of no one atom can be + * flushed/committed. + */ if (!current_is_pdflush() && !wbc->nonblocking) { - for_all_type_safe_list(atom, &tmgr->atoms_list, atom) { + list_for_each(pos, &tmgr->atoms_list) { + atom = list_entry(pos, txn_atom, atom_link); LOCK_ATOM(atom); /* Repeat the check from the above. */ - if (atom->stage < ASTAGE_PRE_COMMIT && atom->nr_flushers == 0) { + if (atom->stage < ASTAGE_PRE_COMMIT + && atom->nr_flushers == 0) { LOCK_TXNH(txnh); capture_assign_txnh_nolock(atom, txnh); UNLOCK_TXNH(txnh); @@ -1487,9 +1487,11 @@ flush_some_atom(long *nr_submitted, cons } if (atom->stage <= ASTAGE_POST_COMMIT) { spin_unlock_txnmgr(tmgr); - /* we just wait until atom's flusher - makes a progress in flushing or - committing the atom */ + /* + * we just wait until atom's flusher + * makes a progress in flushing or + * committing the atom + */ atom_wait_event(atom); goto repeat; } @@ -1498,17 +1500,22 @@ flush_some_atom(long *nr_submitted, cons } spin_unlock_txnmgr(tmgr); return 0; - found: + found: spin_unlock_txnmgr(tmgr); } else atom = get_current_atom_locked(); - ret = flush_current_atom(flags, nr_submitted, &atom); + BUG_ON(atom->super != ctx->super); + assert("vs-35", atom->super == ctx->super); + ret = flush_current_atom(flags, wbc->nr_to_write, nr_submitted, &atom, start); if (ret == 0) { + /* flush_current_atom returns 0 only if it submitted for write + nothing */ + BUG_ON(*nr_submitted != 0); if (*nr_submitted == 0 || atom_should_commit_asap(atom)) { if (atom->capture_count < tmgr->atom_min_size && !(atom->flags & ATOM_CANCEL_FUSION)) { - ret =txn_try_to_fuse_small_atom(tmgr, atom); + ret = txn_try_to_fuse_small_atom(tmgr, atom); if (ret == -E_REPEAT) { preempt_point(); goto repeat; @@ -1545,8 +1552,7 @@ flush_some_atom(long *nr_submitted, cons #if REISER4_COPY_ON_CAPTURE /* Remove processed nodes from atom's clean list (thereby remove them from transaction). */ -void -invalidate_list(capture_list_head * head) +void invalidate_list(capture_list_head * head) { txn_atom *atom; @@ -1576,13 +1582,12 @@ invalidate_list(capture_list_head * head #else /* Remove processed nodes from atom's clean list (thereby remove them from transaction). */ -void -invalidate_list(capture_list_head * head) +void invalidate_list(struct list_head *head) { - while (!capture_list_empty(head)) { + while (!list_empty(head)) { jnode *node; - node = capture_list_front(head); + node = list_entry(head->next, jnode, capture_link); LOCK_JNODE(node); uncapture_block(node); jput(node); @@ -1591,18 +1596,17 @@ invalidate_list(capture_list_head * head #endif -static void -init_wlinks(txn_wait_links * wlinks) +static void init_wlinks(txn_wait_links * wlinks) { wlinks->_lock_stack = get_current_lock_stack(); - fwaitfor_list_clean(wlinks); - fwaiting_list_clean(wlinks); + INIT_LIST_HEAD(&wlinks->_fwaitfor_link); + INIT_LIST_HEAD(&wlinks->_fwaiting_link); wlinks->waitfor_cb = NULL; wlinks->waiting_cb = NULL; } /* Add atom to the atom's waitfor list and wait for somebody to wake us up; */ -reiser4_internal void atom_wait_event(txn_atom * atom) +void atom_wait_event(txn_atom * atom) { txn_wait_links _wlinks; @@ -1612,20 +1616,19 @@ reiser4_internal void atom_wait_event(tx atom->nr_running_queues > 0); init_wlinks(&_wlinks); - fwaitfor_list_push_back(&atom->fwaitfor_list, &_wlinks); + list_add_tail(&_wlinks._fwaitfor_link, &atom->fwaitfor_list); atomic_inc(&atom->refcount); UNLOCK_ATOM(atom); prepare_to_sleep(_wlinks._lock_stack); go_to_sleep(_wlinks._lock_stack); - LOCK_ATOM (atom); - fwaitfor_list_remove(&_wlinks); - atom_dec_and_unlock (atom); + LOCK_ATOM(atom); + list_del(&_wlinks._fwaitfor_link); + atom_dec_and_unlock(atom); } -reiser4_internal void -atom_set_stage(txn_atom *atom, txn_stage stage) +void atom_set_stage(txn_atom * atom, txn_stage stage) { assert("nikita-3535", atom != NULL); assert("nikita-3538", spin_atom_is_locked(atom)); @@ -1639,8 +1642,7 @@ atom_set_stage(txn_atom *atom, txn_stage } /* wake all threads which wait for an event */ -reiser4_internal void -atom_send_event(txn_atom * atom) +void atom_send_event(txn_atom * atom) { assert("zam-745", spin_atom_is_locked(atom)); wakeup_atom_waitfor_list(atom); @@ -1648,34 +1650,32 @@ atom_send_event(txn_atom * atom) /* Informs txn manager code that owner of this txn_handle should wait atom commit completion (for example, because it does fsync(2)) */ -static int -should_wait_commit(txn_handle * h) +static int should_wait_commit(txn_handle * h) { return h->flags & TXNH_WAIT_COMMIT; } typedef struct commit_data { - txn_atom *atom; - txn_handle *txnh; - long nr_written; + txn_atom *atom; + txn_handle *txnh; + long nr_written; /* as an optimization we start committing atom by first trying to * flush it few times without switching into ASTAGE_CAPTURE_WAIT. This * allows to reduce stalls due to other threads waiting for atom in * ASTAGE_CAPTURE_WAIT stage. ->preflush is counter of these * preliminary flushes. */ - int preflush; + int preflush; /* have we waited on atom. */ - int wait; - int failed; - int wake_ktxnmgrd_up; + int wait; + int failed; + int wake_ktxnmgrd_up; } commit_data; /* * Called from commit_txnh() repeatedly, until either error happens, or atom * commits successfully. */ -static int -try_commit_txnh(commit_data *cd) +static int try_commit_txnh(commit_data * cd) { int result; @@ -1687,7 +1687,7 @@ try_commit_txnh(commit_data *cd) UNLOCK_TXNH(cd->txnh); if (cd->wait) { - cd->atom->nr_waiters --; + cd->atom->nr_waiters--; cd->wait = 0; } @@ -1698,7 +1698,7 @@ try_commit_txnh(commit_data *cd) return 0; if (atom_should_commit(cd->atom)) { - /* if atom is _very_ large schedule it for commit as soon as + /* if atom is _very_ large schedule it for commit as soon as * possible. */ if (atom_should_commit_asap(cd->atom)) { /* @@ -1734,8 +1734,8 @@ try_commit_txnh(commit_data *cd) * commit this atom: no atom waiters and only one * (our) open transaction handle. */ cd->wake_ktxnmgrd_up = - cd->atom->txnh_count == 1 && - cd->atom->nr_waiters == 0; + cd->atom->txnh_count == 1 && + cd->atom->nr_waiters == 0; atom_send_event(cd->atom); result = 0; } else if (!atom_can_be_committed(cd->atom)) { @@ -1757,14 +1757,15 @@ try_commit_txnh(commit_data *cd) * should never block on atom fusion. */ result = flush_current_atom(JNODE_FLUSH_WRITE_BLOCKS, - &cd->nr_written, &cd->atom); + LONG_MAX, &cd->nr_written, + &cd->atom, NULL); if (result == 0) { UNLOCK_ATOM(cd->atom); cd->preflush = 0; result = RETERR(-E_REPEAT); } else /* Atoms wasn't flushed * completely. Rinse. Repeat. */ - -- cd->preflush; + --cd->preflush; } else { /* We change atom state to ASTAGE_CAPTURE_WAIT to prevent atom fusion and count ourself as an active @@ -1772,7 +1773,8 @@ try_commit_txnh(commit_data *cd) atom_set_stage(cd->atom, ASTAGE_CAPTURE_WAIT); cd->atom->flags |= ATOM_FORCE_COMMIT; - result = commit_current_atom(&cd->nr_written, &cd->atom); + result = + commit_current_atom(&cd->nr_written, &cd->atom); if (result != 0 && result != -E_REPEAT) cd->failed = 1; } @@ -1783,16 +1785,15 @@ try_commit_txnh(commit_data *cd) /* perfectly valid assertion, except that when atom/txnh is not locked * fusion can take place, and cd->atom points nowhere. */ /* - assert("jmacd-1028", ergo(result != 0, spin_atom_is_not_locked(cd->atom))); - */ + assert("jmacd-1028", ergo(result != 0, spin_atom_is_not_locked(cd->atom))); + */ return result; } /* Called to commit a transaction handle. This decrements the atom's number of open handles and if it is the last handle to commit and the atom should commit, initiates atom commit. if commit does not fail, return number of written blocks */ -static int -commit_txnh(txn_handle * txnh) +static int commit_txnh(txn_handle * txnh) { commit_data cd; assert("umka-192", txnh != NULL); @@ -1811,8 +1812,8 @@ commit_txnh(txn_handle * txnh) cd.atom->txnh_count -= 1; txnh->atom = NULL; - - txnh_list_remove(txnh); + /* remove transaction handle from atom's list of transaction handles */ + list_del_init(&txnh->txnh_link); UNLOCK_TXNH(txnh); atom_dec_and_unlock(cd.atom); @@ -1864,9 +1865,9 @@ commit_txnh(txn_handle * txnh) released. The external interface (try_capture) manages re-aquiring the jnode lock in the failure case. */ - static int -try_capture_block(txn_handle * txnh, jnode * node, txn_capture mode, txn_atom ** atom_alloc, int can_coc) +try_capture_block(txn_handle * txnh, jnode * node, txn_capture mode, + txn_atom ** atom_alloc, int can_coc) { int ret; txn_atom *block_atom; @@ -1927,23 +1928,23 @@ try_capture_block(txn_handle * txnh, jno missed capture and fuses current atoms of all the node lock owners by calling the fuse_not_fused_lock_owners() function. - */ + */ if ( // txnh_atom->stage >= ASTAGE_CAPTURE_WAIT && jnode_is_znode(node) && znode_is_locked(JZNODE(node)) && JF_ISSET(node, JNODE_MISSED_IN_CAPTURE)) { - JF_CLR(node, JNODE_MISSED_IN_CAPTURE); - ret = fuse_not_fused_lock_owners(txnh, JZNODE(node)); - if (ret) { JF_SET(node, JNODE_MISSED_IN_CAPTURE); - assert("zam-687", spin_txnh_is_not_locked(txnh)); - assert("zam-688", spin_jnode_is_not_locked(node)); + assert("zam-687", + spin_txnh_is_not_locked(txnh)); + assert("zam-688", + spin_jnode_is_not_locked(node)); return ret; - } + } else + JF_CLR(node, JNODE_MISSED_IN_CAPTURE); assert("zam-701", spin_txnh_is_locked(txnh)); assert("zam-702", spin_jnode_is_locked(node)); @@ -1960,8 +1961,10 @@ try_capture_block(txn_handle * txnh, jno ret = capture_assign_txnh(node, txnh, mode, can_coc); if (ret != 0) { /* E_REPEAT or otherwise */ - assert("jmacd-6129", spin_txnh_is_not_locked(txnh)); - assert("jmacd-6130", spin_jnode_is_not_locked(node)); + assert("jmacd-6129", + spin_txnh_is_not_locked(txnh)); + assert("jmacd-6130", + spin_jnode_is_not_locked(node)); return ret; } @@ -1979,8 +1982,10 @@ try_capture_block(txn_handle * txnh, jno returns -E_REPEAT on successful fusion, 0 on the fall-through case. */ ret = capture_init_fusion(node, txnh, mode, can_coc); if (ret != 0) { - assert("jmacd-6131", spin_txnh_is_not_locked(txnh)); - assert("jmacd-6132", spin_jnode_is_not_locked(node)); + assert("jmacd-6131", + spin_txnh_is_not_locked(txnh)); + assert("jmacd-6132", + spin_jnode_is_not_locked(node)); return ret; } @@ -1997,8 +2002,10 @@ try_capture_block(txn_handle * txnh, jno ret = capture_assign_block(txnh, node); if (ret != 0) { /* E_REPEAT or otherwise */ - assert("jmacd-6133", spin_txnh_is_not_locked(txnh)); - assert("jmacd-6134", spin_jnode_is_not_locked(node)); + assert("jmacd-6133", + spin_txnh_is_not_locked(txnh)); + assert("jmacd-6134", + spin_jnode_is_not_locked(node)); return ret; } @@ -2006,28 +2013,17 @@ try_capture_block(txn_handle * txnh, jno } else { - /* In this case, neither txnh nor page are assigned to an atom. */ - block_atom = atom_begin_andlock(atom_alloc, node, txnh); - - if (!IS_ERR(block_atom)) { - /* Assign both, release atom lock. */ - assert("jmacd-125", block_atom->stage == ASTAGE_CAPTURE_FUSE); - - capture_assign_txnh_nolock(block_atom, txnh); - capture_assign_block_nolock(block_atom, node); - - UNLOCK_ATOM(block_atom); - } else { - /* all locks are released already */ - return PTR_ERR(block_atom); - } - - /* Success: Locks are still held. */ + /* In this case, neither txnh nor page are assigned to + * an atom. */ + UNLOCK_JNODE(node); + UNLOCK_TXNH(txnh); + return atom_begin_and_assign_to_txnh(atom_alloc, txnh); } } else { /* The jnode is uncaptured and its a read request -- fine. */ - assert("jmacd-411", CAPTURE_TYPE(mode) == TXN_CAPTURE_READ_ATOMIC); + assert("jmacd-411", + CAPTURE_TYPE(mode) == TXN_CAPTURE_READ_ATOMIC); } /* Successful case: both jnode and txnh are still locked. */ @@ -2053,7 +2049,7 @@ build_capture_mode(jnode * node, znode_l cap_mode = TXN_CAPTURE_WRITE; } else if (node->atom != NULL) { cap_mode = TXN_CAPTURE_WRITE; - } else if (0 && /* txnh->mode == TXN_READ_FUSING && */ + } else if (0 && /* txnh->mode == TXN_READ_FUSING && */ jnode_get_level(node) == LEAF_LEVEL) { /* NOTE-NIKITA TXN_READ_FUSING is not currently used */ /* We only need a READ_FUSING capture at the leaf level. This @@ -2075,8 +2071,7 @@ build_capture_mode(jnode * node, znode_l return 0; } - cap_mode |= (flags & (TXN_CAPTURE_NONBLOCKING | - TXN_CAPTURE_DONT_FUSE)); + cap_mode |= (flags & (TXN_CAPTURE_NONBLOCKING | TXN_CAPTURE_DONT_FUSE)); assert("nikita-3186", cap_mode != 0); return cap_mode; } @@ -2093,13 +2088,13 @@ build_capture_mode(jnode * node, znode_l cannot be processed immediately as it was requested in flags, < 0 - other errors. */ -reiser4_internal int -try_capture(jnode * node, znode_lock_mode lock_mode, +int +try_capture(jnode * node, znode_lock_mode lock_mode, txn_capture flags, int can_coc) { - txn_atom *atom_alloc = NULL; + txn_atom *atom_alloc = NULL; txn_capture cap_mode; - txn_handle * txnh = get_current_context()->trans; + txn_handle *txnh = get_current_context()->trans; #if REISER4_COPY_ON_CAPTURE int coc_enabled = 1; #endif @@ -2107,14 +2102,15 @@ try_capture(jnode * node, znode_lock_mo assert("jmacd-604", spin_jnode_is_locked(node)); -repeat: + repeat: cap_mode = build_capture_mode(node, lock_mode, flags); if (cap_mode == 0) return 0; /* Repeat try_capture as long as -E_REPEAT is returned. */ #if REISER4_COPY_ON_CAPTURE - ret = try_capture_block(txnh, node, cap_mode, &atom_alloc, can_coc && coc_enabled); + ret = try_capture_block(txnh, node, cap_mode, &atom_alloc, can_coc + && coc_enabled); coc_enabled = 1; #else ret = try_capture_block(txnh, node, cap_mode, &atom_alloc, can_coc); @@ -2123,7 +2119,7 @@ repeat: If ret == 0 then jnode is still locked. If ret != 0 then jnode is unlocked. - */ + */ assert("nikita-2674", ergo(ret == 0, spin_jnode_is_locked(node))); assert("nikita-2675", ergo(ret != 0, spin_jnode_is_not_locked(node))); @@ -2157,10 +2153,9 @@ repeat: try_capture_block->capture_assign_txnh->spin_trylock_atom->E_REPEAT looks like busy loop? - */ + */ goto repeat; } - #if REISER4_COPY_ON_CAPTURE if (ret == -E_WAIT) { reiser4_stat_inc(coc.coc_wait); @@ -2182,7 +2177,8 @@ repeat: if (ret != 0) { if (ret == -E_BLOCK) { - assert("nikita-3360", cap_mode & TXN_CAPTURE_NONBLOCKING); + assert("nikita-3360", + cap_mode & TXN_CAPTURE_NONBLOCKING); ret = -E_REPEAT; } @@ -2207,12 +2203,12 @@ repeat: */ /* fuse all 'active' atoms of lock owners of given node. */ -static int -fuse_not_fused_lock_owners(txn_handle * txnh, znode * node) +static int fuse_not_fused_lock_owners(txn_handle * txnh, znode * node) { lock_handle *lh; int repeat = 0; txn_atom *atomh = txnh->atom; + struct list_head *pos; /* assert ("zam-689", znode_is_rlocked (node));*/ assert("zam-690", spin_znode_is_locked(node)); @@ -2227,10 +2223,11 @@ fuse_not_fused_lock_owners(txn_handle * } /* inspect list of lock owners */ - for_all_type_safe_list(owners, &node->lock.owners, lh) { + list_for_each(pos, &node->lock.owners) { reiser4_context *ctx; txn_atom *atomf; + lh = list_entry(pos, lock_handle, owners_link); ctx = get_context_by_lock_stack(lh->owner); if (ctx == get_current_context()) @@ -2279,7 +2276,7 @@ fuse_not_fused_lock_owners(txn_handle * /* @atomf is "small" and @atomh is "large", by definition. Small atom is destroyed and large is unlocked inside capture_fuse_into() - */ + */ capture_fuse_into(atomf, atomh); return RETERR(-E_REPEAT); } @@ -2287,7 +2284,7 @@ fuse_not_fused_lock_owners(txn_handle * UNLOCK_ATOM(atomh); if (repeat) { -fail: + fail: UNLOCK_TXNH(txnh); RUNLOCK_ZLOCK(&node->lock); spin_unlock_znode(node); @@ -2300,8 +2297,7 @@ fail: /* This is the interface to capture unformatted nodes via their struct page reference. Currently it is only used in reiser4_invalidatepage */ -reiser4_internal int -try_capture_page_to_invalidate(struct page *pg) +int try_capture_page_to_invalidate(struct page *pg) { int ret; jnode *node; @@ -2316,7 +2312,8 @@ try_capture_page_to_invalidate(struct pa LOCK_JNODE(node); unlock_page(pg); - ret = try_capture(node, ZNODE_WRITE_LOCK, 0, 0/* no copy on capture */); + ret = + try_capture(node, ZNODE_WRITE_LOCK, 0, 0 /* no copy on capture */ ); UNLOCK_JNODE(node); jput(node); lock_page(pg); @@ -2333,8 +2330,7 @@ move the loop to inside the function. VS-FIXME-HANS: can this code be at all streamlined? In particular, can you lock and unlock the jnode fewer times? */ -reiser4_internal void -uncapture_page(struct page *pg) +void uncapture_page(struct page *pg) { jnode *node; txn_atom *atom; @@ -2347,18 +2343,17 @@ uncapture_page(struct page *pg) reiser4_wait_page_writeback(pg); node = (jnode *) (pg->private); - if (node == NULL) - return; + BUG_ON(node == NULL); LOCK_JNODE(node); - eflush_del(node, 1/* page is locked */); - /*assert ("zam-815", !JF_ISSET(node, JNODE_EFLUSH));*/ + eflush_del(node, 1 /* page is locked */ ); + /*assert ("zam-815", !JF_ISSET(node, JNODE_EFLUSH)); */ atom = jnode_get_atom(node); if (atom == NULL) { assert("jmacd-7111", !jnode_is_dirty(node)); - UNLOCK_JNODE (node); + UNLOCK_JNODE(node); return; } @@ -2404,9 +2399,9 @@ uncapture_page(struct page *pg) jput(node); } -/* this is used in extent's kill hook to uncapture and unhash jnodes attached to inode's tree of jnodes */ -reiser4_internal void -uncapture_jnode(jnode *node) +/* this is used in extent's kill hook to uncapture and unhash jnodes attached to + * inode's tree of jnodes */ +void uncapture_jnode(jnode * node) { txn_atom *atom; @@ -2417,13 +2412,13 @@ uncapture_jnode(jnode *node) eflush_free(node); JF_CLR(node, JNODE_EFLUSH); } - /*eflush_del(node, 0);*/ + /*eflush_del(node, 0); */ - /*jnode_make_clean(node);*/ + /*jnode_make_clean(node); */ atom = jnode_get_atom(node); if (atom == NULL) { assert("jmacd-7111", !jnode_is_dirty(node)); - UNLOCK_JNODE (node); + UNLOCK_JNODE(node); return; } @@ -2434,8 +2429,7 @@ uncapture_jnode(jnode *node) /* No-locking version of assign_txnh. Sets the transaction handle's atom pointer, increases atom refcount and txnh_count, adds to txnh_list. */ -static void -capture_assign_txnh_nolock(txn_atom * atom, txn_handle * txnh) +static void capture_assign_txnh_nolock(txn_atom *atom, txn_handle *txnh) { assert("umka-200", atom != NULL); assert("umka-201", txnh != NULL); @@ -2444,30 +2438,30 @@ capture_assign_txnh_nolock(txn_atom * at assert("jmacd-823", spin_atom_is_locked(atom)); assert("jmacd-824", txnh->atom == NULL); assert("nikita-3540", atom_isopen(atom)); + BUG_ON(txnh->atom != NULL); atomic_inc(&atom->refcount); txnh->atom = atom; - txnh_list_push_back(&atom->txnh_list, txnh); + list_add_tail(&txnh->txnh_link, &atom->txnh_list); atom->txnh_count += 1; } /* No-locking version of assign_block. Sets the block's atom pointer, references the block, adds it to the clean or dirty capture_jnode list, increments capture_count. */ -static void -capture_assign_block_nolock(txn_atom * atom, jnode * node) +static void capture_assign_block_nolock(txn_atom *atom, jnode *node) { assert("umka-202", atom != NULL); assert("umka-203", node != NULL); assert("jmacd-321", spin_jnode_is_locked(node)); assert("umka-295", spin_atom_is_locked(atom)); assert("jmacd-323", node->atom == NULL); - BUG_ON(!capture_list_is_clean(node)); + BUG_ON(!list_empty_careful(&node->capture_link)); assert("nikita-3470", !jnode_is_dirty(node)); /* Pointer from jnode to atom is not counted in atom->refcount. */ node->atom = atom; - capture_list_push_back(ATOM_CLEAN_LIST(atom), node); + list_add_tail(&node->capture_link, ATOM_CLEAN_LIST(atom)); atom->capture_count += 1; /* reference to jnode is acquired by atom. */ jref(node); @@ -2478,29 +2472,25 @@ capture_assign_block_nolock(txn_atom * a } #if REISER4_COPY_ON_CAPTURE -static void -set_cced_bit(jnode *node) +static void set_cced_bit(jnode * node) { BUG_ON(JF_ISSET(node, JNODE_CCED)); JF_SET(node, JNODE_CCED); } #endif -static void -clear_cced_bits(jnode *node) +static void clear_cced_bits(jnode * node) { JF_CLR(node, JNODE_CCED); } -int -is_cced(const jnode *node) +int is_cced(const jnode * node) { return JF_ISSET(node, JNODE_CCED); } /* common code for dirtying both unformatted jnodes and formatted znodes. */ -static void -do_jnode_make_dirty(jnode * node, txn_atom * atom) +static void do_jnode_make_dirty(jnode * node, txn_atom * atom) { assert("zam-748", spin_jnode_is_locked(node)); assert("zam-750", spin_atom_is_locked(atom)); @@ -2508,7 +2498,7 @@ do_jnode_make_dirty(jnode * node, txn_at JF_SET(node, JNODE_DIRTY); - get_current_context()->nr_marked_dirty ++; + get_current_context()->nr_marked_dirty++; /* We grab2flush_reserve one additional block only if node was not CREATED and jnode_flush did not sort it into neither @@ -2520,7 +2510,7 @@ do_jnode_make_dirty(jnode * node, txn_at && !jnode_is_cluster_page(node)) { assert("vs-1093", !blocknr_is_fake(&node->blocknr)); assert("vs-1506", *jnode_get_block(node) != 0); - grabbed2flush_reserved_nolock(atom, (__u64)1); + grabbed2flush_reserved_nolock(atom, (__u64) 1); JF_SET(node, JNODE_FLUSH_RESERVED); } @@ -2539,10 +2529,11 @@ do_jnode_make_dirty(jnode * node, txn_at assert("nikita-2607", 0 <= level); assert("nikita-2606", level <= REAL_MAX_ZTREE_HEIGHT); - capture_list_remove(node); - capture_list_push_back(ATOM_DIRTY_LIST(atom, level), node); - ON_DEBUG(count_jnode(atom, node, NODE_LIST(node), DIRTY_LIST, 1)); - + /* move node to atom's dirty list */ + list_del(&node->capture_link); + list_add_tail(&node->capture_link, ATOM_DIRTY_LIST(atom, level)); + ON_DEBUG(count_jnode + (atom, node, NODE_LIST(node), DIRTY_LIST, 1)); /* * JNODE_CCED bit protects clean copy (page created by * copy-on-capture) from being evicted from the memory. This @@ -2557,8 +2548,7 @@ do_jnode_make_dirty(jnode * node, txn_at } /* Set the dirty status for this (spin locked) jnode. */ -reiser4_internal void -jnode_make_dirty_locked(jnode * node) +void jnode_make_dirty_locked(jnode * node) { assert("umka-204", node != NULL); assert("zam-7481", spin_jnode_is_locked(node)); @@ -2570,21 +2560,20 @@ jnode_make_dirty_locked(jnode * node) /* Fast check for already dirty node */ if (!jnode_is_dirty(node)) { - txn_atom * atom; + txn_atom *atom; - atom = jnode_get_atom (node); + atom = jnode_get_atom(node); assert("vs-1094", atom); /* Check jnode dirty status again because node spin lock might * be released inside jnode_get_atom(). */ if (likely(!jnode_is_dirty(node))) do_jnode_make_dirty(node, atom); - UNLOCK_ATOM (atom); + UNLOCK_ATOM(atom); } } /* Set the dirty status for this znode. */ -reiser4_internal void -znode_make_dirty(znode * z) +void znode_make_dirty(znode * z) { jnode *node; struct page *page; @@ -2598,7 +2587,7 @@ znode_make_dirty(znode * z) /* znode is longterm locked, we can check dirty bit without spinlock */ if (JF_ISSET(node, JNODE_DIRTY)) { /* znode is dirty already. All we have to do is to change znode version */ - z->version = znode_build_version(jnode_get_tree(node)); + z->version = znode_build_version(jnode_get_tree(node)); return; } @@ -2611,7 +2600,7 @@ znode_make_dirty(znode * z) * but it requires locking on page to check PG_writeback * bit. */ /* assert("nikita-3292", - !PageWriteback(page) || ZF_ISSET(z, JNODE_WRITEBACK)); */ + !PageWriteback(page) || ZF_ISSET(z, JNODE_WRITEBACK)); */ page_cache_get(page); /* jnode lock is not needed for the rest of @@ -2632,8 +2621,7 @@ znode_make_dirty(znode * z) assert("jmacd-9777", node->atom != NULL); } -reiser4_internal int -sync_atom(txn_atom *atom) +int sync_atom(txn_atom * atom) { int result; txn_handle *txnh; @@ -2659,13 +2647,13 @@ sync_atom(txn_atom *atom) #if REISER4_DEBUG -void check_fq(const txn_atom *atom); - /* move jnode form one list to another call this after atom->capture_count is updated */ void -count_jnode(txn_atom *atom, jnode *node, atom_list old_list, atom_list new_list, int check_lists) +count_jnode(txn_atom * atom, jnode * node, atom_list old_list, + atom_list new_list, int check_lists) { + struct list_head *pos; #if REISER4_COPY_ON_CAPTURE assert("", spin_atom_is_locked(atom)); #else @@ -2674,28 +2662,28 @@ count_jnode(txn_atom *atom, jnode *node, assert("", spin_jnode_is_locked(node)); assert("", NODE_LIST(node) == old_list); - switch(NODE_LIST(node)) { + switch (NODE_LIST(node)) { case NOT_CAPTURED: break; case DIRTY_LIST: assert("", atom->dirty > 0); - atom->dirty --; + atom->dirty--; break; case CLEAN_LIST: assert("", atom->clean > 0); - atom->clean --; + atom->clean--; break; case FQ_LIST: assert("", atom->fq > 0); - atom->fq --; + atom->fq--; break; case WB_LIST: assert("", atom->wb > 0); - atom->wb --; + atom->wb--; break; case OVRWR_LIST: assert("", atom->ovrwr > 0); - atom->ovrwr --; + atom->ovrwr--; break; case PROTECT_LIST: /* protect list is an intermediate atom's list to which jnodes @@ -2704,33 +2692,33 @@ count_jnode(txn_atom *atom, jnode *node, or back to dirty list */ assert("", atom->protect > 0); assert("", new_list == FQ_LIST || new_list == DIRTY_LIST); - atom->protect --; + atom->protect--; break; default: impossible("", ""); } - switch(new_list) { + switch (new_list) { case NOT_CAPTURED: break; case DIRTY_LIST: - atom->dirty ++; + atom->dirty++; break; case CLEAN_LIST: - atom->clean ++; + atom->clean++; break; case FQ_LIST: - atom->fq ++; + atom->fq++; break; case WB_LIST: - atom->wb ++; + atom->wb++; break; case OVRWR_LIST: - atom->ovrwr ++; + atom->ovrwr++; break; case PROTECT_LIST: assert("", old_list == DIRTY_LIST); - atom->protect ++; + atom->protect++; break; default: impossible("", ""); @@ -2739,49 +2727,59 @@ count_jnode(txn_atom *atom, jnode *node, if (0 && check_lists) { int count; tree_level level; - jnode *node; count = 0; /* flush queue list */ - /*check_fq(atom);*/ + /*check_fq(atom); */ /* dirty list */ count = 0; for (level = 0; level < REAL_MAX_ZTREE_HEIGHT + 1; level += 1) { - for_all_type_safe_list(capture, ATOM_DIRTY_LIST(atom, level), node) - count ++; + list_for_each(pos, ATOM_DIRTY_LIST(atom, level)) + count++; } if (count != atom->dirty) - warning("", "dirty counter %d, real %d\n", atom->dirty, count); + warning("", "dirty counter %d, real %d\n", atom->dirty, + count); /* clean list */ count = 0; - for_all_type_safe_list(capture, ATOM_CLEAN_LIST(atom), node) - count ++; + list_for_each(pos, ATOM_CLEAN_LIST(atom)) + count++; if (count != atom->clean) - warning("", "clean counter %d, real %d\n", atom->clean, count); + warning("", "clean counter %d, real %d\n", atom->clean, + count); /* wb list */ count = 0; - for_all_type_safe_list(capture, ATOM_WB_LIST(atom), node) - count ++; + list_for_each(pos, ATOM_WB_LIST(atom)) + count++; if (count != atom->wb) - warning("", "wb counter %d, real %d\n", atom->wb, count); + warning("", "wb counter %d, real %d\n", atom->wb, + count); /* overwrite list */ count = 0; - for_all_type_safe_list(capture, ATOM_OVRWR_LIST(atom), node) - count ++; + list_for_each(pos, ATOM_OVRWR_LIST(atom)) + count++; if (count != atom->ovrwr) - warning("", "ovrwr counter %d, real %d\n", atom->ovrwr, count); + warning("", "ovrwr counter %d, real %d\n", atom->ovrwr, + count); } assert("vs-1624", atom->num_queued == atom->fq); - if (atom->capture_count != atom->dirty + atom->clean + atom->ovrwr + atom->wb + atom->fq + atom->protect) { - printk("count %d, dirty %d clean %d ovrwr %d wb %d fq %d protect %d\n", atom->capture_count, atom->dirty, atom->clean, atom->ovrwr, atom->wb, atom->fq, atom->protect); + if (atom->capture_count != + atom->dirty + atom->clean + atom->ovrwr + atom->wb + atom->fq + + atom->protect) { + printk + ("count %d, dirty %d clean %d ovrwr %d wb %d fq %d protect %d\n", + atom->capture_count, atom->dirty, atom->clean, atom->ovrwr, + atom->wb, atom->fq, atom->protect); assert("vs-1622", - atom->capture_count == atom->dirty + atom->clean + atom->ovrwr + atom->wb + atom->fq + atom->protect); + atom->capture_count == + atom->dirty + atom->clean + atom->ovrwr + atom->wb + + atom->fq + atom->protect); } } @@ -2789,9 +2787,9 @@ count_jnode(txn_atom *atom, jnode *node, /* Make node OVRWR and put it on atom->overwrite_nodes list, atom lock and jnode * lock should be taken before calling this function. */ -reiser4_internal void jnode_make_wander_nolock (jnode * node) +void jnode_make_wander_nolock(jnode * node) { - txn_atom * atom; + txn_atom *atom; assert("nikita-2431", node != NULL); assert("nikita-2432", !JF_ISSET(node, JNODE_RELOC)); @@ -2805,21 +2803,22 @@ reiser4_internal void jnode_make_wander_ assert("zam-894", atom_is_protected(atom)); JF_SET(node, JNODE_OVRWR); - capture_list_remove_clean(node); - capture_list_push_back(ATOM_OVRWR_LIST(atom), node); - /*XXXX*/ON_DEBUG(count_jnode(atom, node, DIRTY_LIST, OVRWR_LIST, 1)); + /* move node to atom's overwrite list */ + list_del(&node->capture_link); + list_add_tail(&node->capture_link, ATOM_OVRWR_LIST(atom)); + ON_DEBUG(count_jnode(atom, node, DIRTY_LIST, OVRWR_LIST, 1)); } /* Same as jnode_make_wander_nolock, but all necessary locks are taken inside * this function. */ -reiser4_internal void jnode_make_wander (jnode * node) +void jnode_make_wander(jnode * node) { - txn_atom * atom; + txn_atom *atom; LOCK_JNODE(node); atom = jnode_get_atom(node); - assert ("zam-913", atom != NULL); - assert ("zam-914", !JF_ISSET(node, JNODE_RELOC)); + assert("zam-913", atom != NULL); + assert("zam-914", !JF_ISSET(node, JNODE_RELOC)); jnode_make_wander_nolock(node); UNLOCK_ATOM(atom); @@ -2827,30 +2826,29 @@ reiser4_internal void jnode_make_wander } /* this just sets RELOC bit */ -static void -jnode_make_reloc_nolock(flush_queue_t *fq, jnode *node) +static void jnode_make_reloc_nolock(flush_queue_t * fq, jnode * node) { assert("vs-1480", spin_jnode_is_locked(node)); - assert ("zam-916", jnode_is_dirty(node)); - assert ("zam-917", !JF_ISSET(node, JNODE_RELOC)); - assert ("zam-918", !JF_ISSET(node, JNODE_OVRWR)); - assert ("zam-920", !JF_ISSET(node, JNODE_FLUSH_QUEUED)); - assert ("nikita-3367", !blocknr_is_fake(jnode_get_block(node))); + assert("zam-916", jnode_is_dirty(node)); + assert("zam-917", !JF_ISSET(node, JNODE_RELOC)); + assert("zam-918", !JF_ISSET(node, JNODE_OVRWR)); + assert("zam-920", !JF_ISSET(node, JNODE_FLUSH_QUEUED)); + assert("nikita-3367", !blocknr_is_fake(jnode_get_block(node))); jnode_set_reloc(node); } /* Make znode RELOC and put it on flush queue */ -reiser4_internal void znode_make_reloc (znode *z, flush_queue_t * fq) +void znode_make_reloc(znode * z, flush_queue_t * fq) { jnode *node; - txn_atom * atom; + txn_atom *atom; node = ZJNODE(z); LOCK_JNODE(node); atom = jnode_get_atom(node); - assert ("zam-919", atom != NULL); + assert("zam-919", atom != NULL); jnode_make_reloc_nolock(fq, node); queue_jnode(fq, node); @@ -2861,8 +2859,7 @@ reiser4_internal void znode_make_reloc ( } /* Make unformatted node RELOC and put it on flush queue */ -reiser4_internal void -unformatted_make_reloc(jnode *node, flush_queue_t * fq) +void unformatted_make_reloc(jnode * node, flush_queue_t * fq) { assert("vs-1479", jnode_is_unformatted(node)); @@ -2870,8 +2867,7 @@ unformatted_make_reloc(jnode *node, flus mark_jnode_queued(fq, node); } -static int -trylock_wait(txn_atom *atom, txn_handle * txnh, jnode * node) +static int trylock_wait(txn_atom * atom, txn_handle * txnh, jnode * node) { if (unlikely(!spin_trylock_atom(atom))) { atomic_inc(&atom->refcount); @@ -2909,8 +2905,7 @@ trylock_wait(txn_atom *atom, txn_handle done that way in try_capture_block() where spin lock waiting was spread in a busy loop through several functions. The proper solution should be in making spin lock contention rare. */ -static int -trylock_throttle(txn_atom *atom, txn_handle * txnh, jnode * node) +static int trylock_throttle(txn_atom * atom, txn_handle * txnh, jnode * node) { assert("nikita-3224", atom != NULL); assert("nikita-3225", txnh != NULL); @@ -2929,11 +2924,10 @@ trylock_throttle(txn_atom *atom, txn_han /* This function assigns a block to an atom, but first it must obtain the atom lock. If the atom lock is busy, it returns -E_REPEAT to avoid deadlock with a fusing atom. Since the transaction handle is currently open, we know the atom must also be open. */ -static int -capture_assign_block(txn_handle * txnh, jnode * node) +static int capture_assign_block(txn_handle * txnh, jnode * node) { txn_atom *atom; - int result; + int result; assert("umka-206", txnh != NULL); assert("umka-207", node != NULL); @@ -2968,7 +2962,8 @@ capture_assign_block(txn_handle * txnh, initiate copy-on-capture. */ static int -capture_assign_txnh(jnode * node, txn_handle * txnh, txn_capture mode, int can_coc) +capture_assign_txnh(jnode * node, txn_handle * txnh, txn_capture mode, + int can_coc) { txn_atom *atom; @@ -3065,13 +3060,15 @@ capture_assign_txnh(jnode * node, txn_ha /* Perform COPY-ON-CAPTURE. Copy and try again. This function releases all three locks. */ - return capture_copy(node, txnh, atom, NULL, mode, can_coc); + return capture_copy(node, txnh, atom, NULL, mode, + can_coc); } } else { assert("jmacd-160", atom->stage == ASTAGE_CAPTURE_FUSE || - (atom->stage == ASTAGE_CAPTURE_WAIT && atom->txnh_count == 0)); + (atom->stage == ASTAGE_CAPTURE_WAIT + && atom->txnh_count == 0)); /* Add txnh to active list. */ capture_assign_txnh_nolock(atom, txnh); @@ -3085,8 +3082,7 @@ capture_assign_txnh(jnode * node, txn_ha return 0; } -reiser4_internal int -capture_super_block(struct super_block *s) +int capture_super_block(struct super_block *s) { int result; znode *uber; @@ -3100,7 +3096,7 @@ capture_super_block(struct super_block * uber = lh.node; /* Grabbing one block for superblock */ - result = reiser4_grab_space_force((__u64)1, BA_RESERVED); + result = reiser4_grab_space_force((__u64) 1, BA_RESERVED); if (result != 0) return result; @@ -3111,15 +3107,16 @@ capture_super_block(struct super_block * } /* Wakeup every handle on the atom's WAITFOR list */ -static void -wakeup_atom_waitfor_list(txn_atom * atom) +static void wakeup_atom_waitfor_list(txn_atom * atom) { txn_wait_links *wlinks; + struct list_head *pos; assert("umka-210", atom != NULL); /* atom is locked */ - for_all_type_safe_list(fwaitfor, &atom->fwaitfor_list, wlinks) { + list_for_each(pos, &atom->fwaitfor_list) { + wlinks = list_entry(pos, txn_wait_links, _fwaitfor_link); if (wlinks->waitfor_cb == NULL || wlinks->waitfor_cb(atom, wlinks)) /* Wake up. */ @@ -3128,15 +3125,16 @@ wakeup_atom_waitfor_list(txn_atom * atom } /* Wakeup every handle on the atom's WAITING list */ -static void -wakeup_atom_waiting_list(txn_atom * atom) +static void wakeup_atom_waiting_list(txn_atom * atom) { txn_wait_links *wlinks; + struct list_head *pos; assert("umka-211", atom != NULL); /* atom is locked */ - for_all_type_safe_list(fwaiting, &atom->fwaiting_list, wlinks) { + list_for_each(pos, &atom->fwaiting_list) { + wlinks = list_entry(pos, txn_wait_links, _fwaiting_link); if (wlinks->waiting_cb == NULL || wlinks->waiting_cb(atom, wlinks)) /* Wake up. */ @@ -3150,7 +3148,6 @@ static int wait_for_fusion(txn_atom * at assert("nikita-3330", atom != NULL); assert("nikita-3331", spin_atom_is_locked(atom)); - /* atom->txnh_count == 1 is for waking waiters up if we are releasing * last transaction handle. */ return atom->stage != ASTAGE_CAPTURE_WAIT || atom->txnh_count == 1; @@ -3174,11 +3171,10 @@ static int wait_for_fusion(txn_atom * at BOTH_ATOM_LOCKS. Result: all four locks are released. */ static int -capture_fuse_wait(jnode * node, txn_handle * txnh, txn_atom * atomf, txn_atom * atomh, txn_capture mode) +capture_fuse_wait(jnode * node, txn_handle * txnh, txn_atom * atomf, + txn_atom * atomh, txn_capture mode) { int ret; - - /* Initialize the waiting list links. */ txn_wait_links wlinks; assert("umka-212", node != NULL); @@ -3199,17 +3195,18 @@ capture_fuse_wait(jnode * node, txn_hand return RETERR(-E_BLOCK); } + /* Initialize the waiting list links. */ init_wlinks(&wlinks); /* Add txnh to atomf's waitfor list, unlock atomf. */ - fwaitfor_list_push_back(&atomf->fwaitfor_list, &wlinks); + list_add_tail(&wlinks._fwaitfor_link, &atomf->fwaitfor_list); wlinks.waitfor_cb = wait_for_fusion; atomic_inc(&atomf->refcount); UNLOCK_ATOM(atomf); if (atomh) { /* Add txnh to atomh's waiting list, unlock atomh. */ - fwaiting_list_push_back(&atomh->fwaiting_list, &wlinks); + list_add_tail(&wlinks._fwaiting_link, &atomh->fwaiting_list); atomic_inc(&atomh->refcount); UNLOCK_ATOM(atomh); } @@ -3225,13 +3222,14 @@ capture_fuse_wait(jnode * node, txn_hand /* Remove from the waitfor list. */ LOCK_ATOM(atomf); - fwaitfor_list_remove(&wlinks); + + list_del(&wlinks._fwaitfor_link); atom_dec_and_unlock(atomf); if (atomh) { /* Remove from the waiting list. */ LOCK_ATOM(atomh); - fwaiting_list_remove(&wlinks); + list_del(&wlinks._fwaiting_link); atom_dec_and_unlock(atomh); } @@ -3240,7 +3238,8 @@ capture_fuse_wait(jnode * node, txn_hand } static inline int -capture_init_fusion_locked(jnode * node, txn_handle * txnh, txn_capture mode, int can_coc) +capture_init_fusion_locked(jnode * node, txn_handle * txnh, txn_capture mode, + int can_coc) { txn_atom *atomf; txn_atom *atomh; @@ -3279,7 +3278,8 @@ capture_init_fusion_locked(jnode * node, } else { /* Perform COPY-ON-CAPTURE. Copy and try again. This function releases all four locks. */ - return capture_copy(node, txnh, atomf, atomh, mode, can_coc); + return capture_copy(node, txnh, atomf, atomh, mode, + can_coc); } } @@ -3288,7 +3288,10 @@ capture_init_fusion_locked(jnode * node, /* If we got here its either because the atomh is in CAPTURE_WAIT or because the atomf is not in CAPTURE_WAIT. */ - assert("jmacd-176", (atomh->stage == ASTAGE_CAPTURE_WAIT || atomf->stage != ASTAGE_CAPTURE_WAIT) || atomf->txnh_count == 0); + assert("jmacd-176", + (atomh->stage == ASTAGE_CAPTURE_WAIT + || atomf->stage != ASTAGE_CAPTURE_WAIT) + || atomf->txnh_count == 0); /* Now release the txnh lock: only holding the atoms at this point. */ UNLOCK_TXNH(txnh); @@ -3314,12 +3317,14 @@ capture_init_fusion_locked(jnode * node, * call capture_fuse_into. */ static int -capture_init_fusion(jnode * node, txn_handle * txnh, txn_capture mode, int can_coc) +capture_init_fusion(jnode * node, txn_handle * txnh, txn_capture mode, + int can_coc) { /* Have to perform two trylocks here. */ if (likely(spin_trylock_atom(node->atom))) { if (likely(spin_trylock_atom(txnh->atom))) - return capture_init_fusion_locked(node, txnh, mode, can_coc); + return capture_init_fusion_locked(node, txnh, mode, + can_coc); else { UNLOCK_ATOM(node->atom); } @@ -3329,13 +3334,16 @@ capture_init_fusion(jnode * node, txn_ha UNLOCK_TXNH(txnh); return RETERR(-E_REPEAT); } + /* This function splices together two jnode lists (small and large) and sets all jnodes in the small list to point to the large atom. Returns the length of the list. */ static int -capture_fuse_jnode_lists(txn_atom * large, capture_list_head * large_head, capture_list_head * small_head) +capture_fuse_jnode_lists(txn_atom *large, struct list_head *large_head, + struct list_head *small_head) { int count = 0; jnode *node; + struct list_head *pos; assert("umka-218", large != NULL); assert("umka-219", large_head != NULL); @@ -3344,7 +3352,8 @@ capture_fuse_jnode_lists(txn_atom * larg assert("zam-968", spin_atom_is_locked(large)); /* For every jnode on small's capture list... */ - for_all_type_safe_list(capture, small_head, node) { + list_for_each(pos, small_head) { + node = list_entry(pos, jnode, capture_link); count += 1; /* With the jnode lock held, update atom pointer. */ @@ -3352,26 +3361,30 @@ capture_fuse_jnode_lists(txn_atom * larg } /* Splice the lists. */ - capture_list_splice(large_head, small_head); + list_splice(small_head, large_head); + /* list_splice does not clean small_head */ + INIT_LIST_HEAD(small_head); return count; } /* This function splices together two txnh lists (small and large) and sets all txn handles in the small list to point to the large atom. Returns the length of the list. */ -/* Audited by: umka (2002.06.13) */ static int -capture_fuse_txnh_lists(txn_atom * large, txnh_list_head * large_head, txnh_list_head * small_head) +capture_fuse_txnh_lists(txn_atom *large, struct list_head *large_head, + struct list_head *small_head) { int count = 0; txn_handle *txnh; + struct list_head *pos; assert("umka-221", large != NULL); assert("umka-222", large_head != NULL); assert("umka-223", small_head != NULL); /* Adjust every txnh to the new atom. */ - for_all_type_safe_list(txnh, small_head, txnh) { + list_for_each(pos, small_head) { + txnh = list_entry(pos, txn_handle, txnh_link); count += 1; /* With the txnh lock held, update atom pointer. */ @@ -3379,7 +3392,9 @@ capture_fuse_txnh_lists(txn_atom * large } /* Splice the txn_handle list. */ - txnh_list_splice(large_head, small_head); + list_splice(small_head, large_head); + /* list_splice does not clean small_head */ + INIT_LIST_HEAD(small_head); return count; } @@ -3389,13 +3404,13 @@ capture_fuse_txnh_lists(txn_atom * large updated as well, and any waiting handles belonging to either are awakened. Finally the smaller atom's refcount is decremented. */ -static void -capture_fuse_into(txn_atom * small, txn_atom * large) +static void capture_fuse_into(txn_atom * small, txn_atom * large) { int level; unsigned zcount = 0; unsigned tcount = 0; protected_jnodes *prot_list; + struct list_head *pos1, *pos2; assert("umka-224", small != NULL); assert("umka-225", small != NULL); @@ -3408,20 +3423,35 @@ capture_fuse_into(txn_atom * small, txn_ /* Splice and update the per-level dirty jnode lists */ for (level = 0; level < REAL_MAX_ZTREE_HEIGHT + 1; level += 1) { - zcount += capture_fuse_jnode_lists(large, ATOM_DIRTY_LIST(large, level), ATOM_DIRTY_LIST(small, level)); + zcount += + capture_fuse_jnode_lists(large, + ATOM_DIRTY_LIST(large, level), + ATOM_DIRTY_LIST(small, level)); } /* Splice and update the [clean,dirty] jnode and txnh lists */ - zcount += capture_fuse_jnode_lists(large, ATOM_CLEAN_LIST(large), ATOM_CLEAN_LIST(small)); - zcount += capture_fuse_jnode_lists(large, ATOM_OVRWR_LIST(large), ATOM_OVRWR_LIST(small)); - zcount += capture_fuse_jnode_lists(large, ATOM_WB_LIST(large), ATOM_WB_LIST(small)); - zcount += capture_fuse_jnode_lists(large, &large->inodes, &small->inodes); - tcount += capture_fuse_txnh_lists(large, &large->txnh_list, &small->txnh_list); + zcount += + capture_fuse_jnode_lists(large, ATOM_CLEAN_LIST(large), + ATOM_CLEAN_LIST(small)); + zcount += + capture_fuse_jnode_lists(large, ATOM_OVRWR_LIST(large), + ATOM_OVRWR_LIST(small)); + zcount += + capture_fuse_jnode_lists(large, ATOM_WB_LIST(large), + ATOM_WB_LIST(small)); + zcount += + capture_fuse_jnode_lists(large, &large->inodes, &small->inodes); + tcount += + capture_fuse_txnh_lists(large, &large->txnh_list, + &small->txnh_list); + - for_all_type_safe_list(prot, &small->protected, prot_list) { + list_for_each(pos1, &small->protected) { + prot_list = list_entry(pos1, protected_jnodes, inatom); jnode *node; - for_all_type_safe_list(capture, &prot_list->nodes, node) { + list_for_each(pos2, &prot_list->nodes) { + node = list_entry(pos2, jnode, capture_link); zcount += 1; LOCK_JNODE(node); @@ -3432,10 +3462,15 @@ capture_fuse_into(txn_atom * small, txn_ } } /* Splice the lists of lists. */ - prot_list_splice(&large->protected, &small->protected); + list_splice(&small->protected, &large->protected); + /* list_splice does not clean &small->protected */ + if (!list_empty(&small->protected)) + warning("XXX", "list-splice does not clean list"); + INIT_LIST_HEAD(&small->protected); /* Check our accounting. */ - assert("jmacd-1063", zcount + small->num_queued == small->capture_count); + assert("jmacd-1063", + zcount + small->num_queued == small->capture_count); assert("jmacd-1065", tcount == small->txnh_count); /* sum numbers of waiters threads */ @@ -3456,9 +3491,7 @@ capture_fuse_into(txn_atom * small, txn_ small->wb = 0; large->fq += small->fq; small->fq = 0; - large->protect += small->protect; - small->protect = 0; - ); + large->protect += small->protect; small->protect = 0;); /* count flushers in result atom */ large->nr_flushers += small->nr_flushers; @@ -3523,28 +3556,26 @@ capture_fuse_into(txn_atom * small, txn_ atom_dec_and_unlock(small); } -reiser4_internal void -protected_jnodes_init(protected_jnodes *list) +void protected_jnodes_init(protected_jnodes *list) { txn_atom *atom; assert("nikita-3376", list != NULL); atom = get_current_atom_locked(); - prot_list_push_front(&atom->protected, list); - capture_list_init(&list->nodes); + list_add(&list->inatom, &atom->protected); + INIT_LIST_HEAD(&list->nodes); UNLOCK_ATOM(atom); } -reiser4_internal void -protected_jnodes_done(protected_jnodes *list) +void protected_jnodes_done(protected_jnodes *list) { txn_atom *atom; - assert("nikita-3379", capture_list_empty(&list->nodes)); + assert("nikita-3379", list_empty(&list->nodes)); atom = get_current_atom_locked(); - prot_list_remove(list); + list_del_init(&list->inatom); UNLOCK_ATOM(atom); } @@ -3567,8 +3598,7 @@ protected_jnodes_done(protected_jnodes * */ /* remove jnode page from mapping's tree and insert new page with the same index */ -static void -replace_page_in_mapping(jnode *node, struct page *new_page) +static void replace_page_in_mapping(jnode * node, struct page *new_page) { struct address_space *mapping; unsigned long index; @@ -3579,7 +3609,8 @@ replace_page_in_mapping(jnode *node, str spin_lock(&mapping->page_lock); /* delete old page from. This resembles __remove_from_page_cache */ - assert("vs-1416", radix_tree_lookup(&mapping->page_tree, index) == node->pg); + assert("vs-1416", + radix_tree_lookup(&mapping->page_tree, index) == node->pg); assert("vs-1428", node->pg->mapping == mapping); __remove_from_page_cache(node->pg); @@ -3596,8 +3627,7 @@ replace_page_in_mapping(jnode *node, str } /* attach page of @node to @copy, @new_page to @node */ -static void -swap_jnode_pages(jnode *node, jnode *copy, struct page *new_page) +static void swap_jnode_pages(jnode * node, jnode * copy, struct page *new_page) { /* attach old page to new jnode */ assert("vs-1414", jnode_by_page(node->pg) == node); @@ -3626,8 +3656,11 @@ swap_jnode_pages(jnode *node, jnode *cop /* insert old page into new (fake) mapping. No page_cache_get because page reference counter was not decreased on removing it from old mapping */ - assert("vs-1416", radix_tree_lookup(&mapping->page_tree, index) == NULL); - check_me("vs-1418", radix_tree_insert(&mapping->page_tree, index, copy->pg) == 0); + assert("vs-1416", + radix_tree_lookup(&mapping->page_tree, index) == NULL); + check_me("vs-1418", + radix_tree_insert(&mapping->page_tree, index, + copy->pg) == 0); ___add_to_page_cache(copy->pg, mapping, index); /* corresponding page_cache_release is in invalidate_list */ @@ -3637,8 +3670,7 @@ swap_jnode_pages(jnode *node, jnode *cop } /* this is to make capture copied jnode looking like if there were jload called for it */ -static void -fake_jload(jnode *node) +static void fake_jload(jnode * node) { jref(node); atomic_inc(&node->d_count); @@ -3646,8 +3678,7 @@ fake_jload(jnode *node) } /* for now - refuse to copy-on-capture any suspicious nodes (WRITEBACK, DIRTY, FLUSH_QUEUED) */ -static int -check_capturable(const jnode *node, const txn_atom *atom) +static int check_capturable(const jnode * node, const txn_atom * atom) { assert("vs-1429", spin_jnode_is_locked(node)); assert("vs-1487", check_spin_is_locked(&scan_lock)); @@ -3672,11 +3703,10 @@ check_capturable(const jnode *node, cons reiser4_stat_inc(coc.atom_changed); return RETERR(-E_WAIT); } - return 0; /* OK */ + return 0; /* OK */ } -static void -remove_from_capture_list(jnode *node) +static void remove_from_capture_list(jnode * node) { ON_DEBUG_MODIFY(znode_set_checksum(node, 1)); JF_CLR(node, JNODE_DIRTY); @@ -3687,19 +3717,21 @@ remove_from_capture_list(jnode *node) JF_CLR(node, JNODE_REPACK); capture_list_remove_clean(node); - node->atom->capture_count --; + node->atom->capture_count--; atomic_dec(&node->x_count); - /*XXXX*/ON_DEBUG(count_jnode(node->atom, node, NODE_LIST(node), NOT_CAPTURED, 1)); + + ON_DEBUG(count_jnode(node->atom, node, NODE_LIST(node), + NOT_CAPTURED, 1)); node->atom = 0; } /* insert new jnode (copy) to capture list instead of old one */ -static void -replace_on_capture_list(jnode *node, jnode *copy) +static void replace_on_capture_list(jnode * node, jnode * copy) { assert("vs-1415", node->atom); assert("vs-1489", !capture_list_is_clean(node)); - assert("vs-1493", JF_ISSET(copy, JNODE_CC) && JF_ISSET(copy, JNODE_HEARD_BANSHEE)); + assert("vs-1493", JF_ISSET(copy, JNODE_CC) + && JF_ISSET(copy, JNODE_HEARD_BANSHEE)); copy->state |= node->state; @@ -3707,8 +3739,10 @@ replace_on_capture_list(jnode *node, jno capture_list_insert_before(node, copy); jref(copy); copy->atom = node->atom; - node->atom->capture_count ++; - /*XXXX*/ON_DEBUG(count_jnode(node->atom, copy, NODE_LIST(copy), NODE_LIST(node), 1)); + node->atom->capture_count++; + + ON_DEBUG(count_jnode(node->atom, copy, NODE_LIST(copy), + NODE_LIST(node), 1)); /* remove old jnode from capture list */ remove_from_capture_list(node); @@ -3716,8 +3750,7 @@ replace_on_capture_list(jnode *node, jno /* when capture request is made for a node which is captured but was never dirtied copy on capture will merely uncapture it */ -static int -copy_on_capture_clean(jnode *node, txn_atom *atom) +static int copy_on_capture_clean(jnode * node, txn_atom * atom) { int result; @@ -3739,8 +3772,7 @@ copy_on_capture_clean(jnode *node, txn_a return result; } -static void -lock_two_nodes(jnode *node1, jnode *node2) +static void lock_two_nodes(jnode * node1, jnode * node2) { if (node1 > node2) { LOCK_JNODE(node2); @@ -3753,8 +3785,7 @@ lock_two_nodes(jnode *node1, jnode *node /* capture request is made for node which does not have page. In most cases this is "uber" znode */ -static int -copy_on_capture_nopage(jnode *node, txn_atom *atom) +static int copy_on_capture_nopage(jnode * node, txn_atom * atom) { int result; jnode *copy; @@ -3804,12 +3835,12 @@ copy_on_capture_nopage(jnode *node, txn_ } static int -handle_coc(jnode *node, jnode *copy, struct page *page, struct page *new_page, - txn_atom *atom) +handle_coc(jnode * node, jnode * copy, struct page *page, struct page *new_page, + txn_atom * atom) { char *to; char *from; - int result; + int result; to = kmap(new_page); lock_page(page); @@ -3833,7 +3864,8 @@ handle_coc(jnode *node, jnode *copy, str put_overwrite_set will not jrelse it */ int was_jloaded; - was_jloaded = JF_ISSET(node, JNODE_JLOADED_BY_GET_OVERWRITE_SET); + was_jloaded = + JF_ISSET(node, JNODE_JLOADED_BY_GET_OVERWRITE_SET); replace_page_in_mapping(node, new_page); swap_jnode_pages(node, copy, new_page); @@ -3863,7 +3895,9 @@ handle_coc(jnode *node, jnode *copy, str if (was_jloaded) { jrelse_tail(node); - assert("vs-1494", JF_ISSET(node, JNODE_JLOADED_BY_GET_OVERWRITE_SET)); + assert("vs-1494", + JF_ISSET(node, + JNODE_JLOADED_BY_GET_OVERWRITE_SET)); JF_CLR(node, JNODE_JLOADED_BY_GET_OVERWRITE_SET); } else kunmap(new_page); @@ -3888,8 +3922,7 @@ handle_coc(jnode *node, jnode *copy, str return result; } -static int -real_copy_on_capture(jnode *node, txn_atom *atom) +static int real_copy_on_capture(jnode * node, txn_atom * atom) { int result; jnode *copy; @@ -3934,19 +3967,18 @@ real_copy_on_capture(jnode *node, txn_at page from old jnode, attach new page to old jnode, attach old page to new jnode this returns 0 if copy on capture succeeded, E_REPEAT to have capture_fuse_wait to be called */ -static int -create_copy_and_replace(jnode *node, txn_atom *atom) +static int create_copy_and_replace(jnode * node, txn_atom * atom) { int result; - struct inode *inode; /* inode for which filemap_nopage is blocked */ + struct inode *inode; /* inode for which filemap_nopage is blocked */ assert("jmacd-321", spin_jnode_is_locked(node)); assert("umka-295", spin_atom_is_locked(atom)); assert("vs-1381", node->atom == atom); - assert("vs-1409", atom->stage > ASTAGE_CAPTURE_WAIT && atom->stage < ASTAGE_DONE); + assert("vs-1409", atom->stage > ASTAGE_CAPTURE_WAIT + && atom->stage < ASTAGE_DONE); assert("vs-1410", jnode_is_znode(node) || jnode_is_unformatted(node)); - if (JF_ISSET(node, JNODE_CCED)) { /* node is under copy on capture already */ reiser4_stat_inc(coc.coc_race); @@ -3958,7 +3990,8 @@ create_copy_and_replace(jnode *node, txn /* measure how often suspicious (WRITEBACK, DIRTY, FLUSH_QUEUED) appear here. For most often case we can return EAGAIN right here and avoid all the preparations made for copy on capture */ - ON_TRACE(TRACE_CAPTURE_COPY, "copy_on_capture: node %p, atom %p..", node, atom); + ON_TRACE(TRACE_CAPTURE_COPY, "copy_on_capture: node %p, atom %p..", + node, atom); if (JF_ISSET(node, JNODE_EFLUSH)) { UNLOCK_JNODE(node); UNLOCK_ATOM(atom); @@ -4037,11 +4070,12 @@ create_copy_and_replace(jnode *node, txn return result; } -#endif /* REISER4_COPY_ON_CAPTURE */ +#endif /* REISER4_COPY_ON_CAPTURE */ /* Perform copy-on-capture of a block. */ static int -capture_copy(jnode * node, txn_handle * txnh, txn_atom * atomf, txn_atom * atomh, txn_capture mode, int can_coc) +capture_copy(jnode * node, txn_handle * txnh, txn_atom * atomf, + txn_atom * atomh, txn_capture mode, int can_coc) { #if REISER4_COPY_ON_CAPTURE reiser4_stat_inc(coc.calls); @@ -4073,7 +4107,8 @@ capture_copy(jnode * node, txn_handle * znode *z; z = JZNODE(node); - z->version = znode_build_version(jnode_get_tree(node)); + z->version = + znode_build_version(jnode_get_tree(node)); } result = RETERR(-E_REPEAT); } @@ -4095,9 +4130,9 @@ capture_copy(jnode * node, txn_handle * NOTE: this function does not release a (journal) reference to jnode due to locking optimizations, you should call jput() somewhere after calling uncapture_block(). */ -reiser4_internal void uncapture_block(jnode * node) +void uncapture_block(jnode * node) { - txn_atom * atom; + txn_atom *atom; assert("umka-226", node != NULL); atom = node->atom; @@ -4118,15 +4153,12 @@ reiser4_internal void uncapture_block(jn JF_CLR(node, JNODE_WRITEBACK); JF_CLR(node, JNODE_REPACK); clear_cced_bits(node); -#if REISER4_DEBUG - node->written = 0; -#endif - capture_list_remove_clean(node); + list_del_init(&node->capture_link); if (JF_ISSET(node, JNODE_FLUSH_QUEUED)) { assert("zam-925", atom_isopen(atom)); assert("vs-1623", NODE_LIST(node) == FQ_LIST); - ON_DEBUG(atom->num_queued --); + ON_DEBUG(atom->num_queued--); JF_CLR(node, JNODE_FLUSH_QUEUED); } atom->capture_count -= 1; @@ -4140,34 +4172,26 @@ reiser4_internal void uncapture_block(jn /* Unconditional insert of jnode into atom's overwrite list. Currently used in bitmap-based allocator code for adding modified bitmap blocks the transaction. @atom and @node are spin locked */ -reiser4_internal void -insert_into_atom_ovrwr_list(txn_atom * atom, jnode * node) +void insert_into_atom_ovrwr_list(txn_atom * atom, jnode * node) { - assert("zam-538", spin_atom_is_locked(atom) || atom->stage >= ASTAGE_PRE_COMMIT); + assert("zam-538", spin_atom_is_locked(atom) + || atom->stage >= ASTAGE_PRE_COMMIT); assert("zam-539", spin_jnode_is_locked(node)); assert("zam-899", JF_ISSET(node, JNODE_OVRWR)); assert("zam-543", node->atom == NULL); assert("vs-1433", !jnode_is_unformatted(node) && !jnode_is_znode(node)); - capture_list_push_front(ATOM_OVRWR_LIST(atom), node); + list_add(&node->capture_link, ATOM_OVRWR_LIST(atom)); jref(node); node->atom = atom; atom->capture_count++; ON_DEBUG(count_jnode(atom, node, NODE_LIST(node), OVRWR_LIST, 1)); } -/* when atom becomes that big, commit it as soon as possible. This was found - * to be most effective by testing. */ -reiser4_internal unsigned int -txnmgr_get_max_atom_size(struct super_block *super UNUSED_ARG) -{ - return totalram_pages / 4; -} #if REISER4_DEBUG -reiser4_internal void -info_atom(const char *prefix, const txn_atom * atom) +void info_atom(const char *prefix, const txn_atom * atom) { if (atom == NULL) { printk("%s: no atom\n", prefix); @@ -4176,35 +4200,40 @@ info_atom(const char *prefix, const txn_ printk("%s: refcount: %i id: %i flags: %x txnh_count: %i" " capture_count: %i stage: %x start: %lu, flushed: %i\n", prefix, - atomic_read(&atom->refcount), atom->atom_id, atom->flags, atom->txnh_count, - atom->capture_count, atom->stage, atom->start_time, atom->flushed); + atomic_read(&atom->refcount), atom->atom_id, atom->flags, + atom->txnh_count, atom->capture_count, atom->stage, + atom->start_time, atom->flushed); } #endif -static int count_deleted_blocks_actor ( - txn_atom *atom, const reiser4_block_nr * a, const reiser4_block_nr *b, void * data) +static int count_deleted_blocks_actor(txn_atom * atom, + const reiser4_block_nr * a, + const reiser4_block_nr * b, void *data) { reiser4_block_nr *counter = data; - assert ("zam-995", data != NULL); - assert ("zam-996", a != NULL); + assert("zam-995", data != NULL); + assert("zam-996", a != NULL); if (b == NULL) *counter += 1; else *counter += *b; return 0; } -reiser4_internal reiser4_block_nr txnmgr_count_deleted_blocks (void) + +reiser4_block_nr txnmgr_count_deleted_blocks(void) { reiser4_block_nr result; txn_mgr *tmgr = &get_super_private(reiser4_get_current_sb())->tmgr; - txn_atom * atom; + txn_atom *atom; + struct list_head *pos; result = 0; spin_lock_txnmgr(tmgr); - for_all_type_safe_list(atom, &tmgr->atoms_list, atom) { + list_for_each(pos, &tmgr->atoms_list) { + atom = list_entry(pos, txn_atom, atom_link); LOCK_ATOM(atom); blocknr_set_iterator(atom, &atom->delete_set, count_deleted_blocks_actor, &result, 0); @@ -4215,12 +4244,12 @@ reiser4_internal reiser4_block_nr txnmgr return result; } -/* Make Linus happy. - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 80 - End: -*/ +/* + * Local variables: + * c-indentation-style: "K&R" + * mode-name: "LC" + * c-basic-offset: 8 + * tab-width: 8 + * fill-column: 79 + * End: + */ diff -puN fs/reiser4/txnmgr.h~reiser4-big-update fs/reiser4/txnmgr.h --- devel/fs/reiser4/txnmgr.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/txnmgr.h 2005-09-15 19:51:08.000000000 -0700 @@ -10,7 +10,6 @@ #include "forward.h" #include "spin_macros.h" #include "dformat.h" -#include "type_safe_list.h" #include #include @@ -19,54 +18,6 @@ #include #include -/* LIST TYPES */ - -/* list of all atoms controlled by single transaction manager (that is, file - * system) */ -TYPE_SAFE_LIST_DECLARE(atom); -/* list of transaction handles attached to given atom */ -TYPE_SAFE_LIST_DECLARE(txnh); - -/* - * ->fwaitfor and ->fwaiting lists. - * - * Each atom has one of these lists: one for its own handles waiting on - * another atom and one for reverse mapping. Used to prevent deadlock in the - * ASTAGE_CAPTURE_WAIT state. - * - * Thread that needs to wait for a given atom, attaches itself to the atom's - * ->fwaitfor list. This is done in atom_wait_event() (and, in - * capture_fuse_wait()). All threads waiting on this list are waked up - * whenever "event" occurs for this atom: it changes stage, commits, flush - * queue is released, etc. This is used, in particular, to implement sync(), - * where thread has to wait until atom commits. - */ -TYPE_SAFE_LIST_DECLARE(fwaitfor); - -/* - * This list is used to wait for atom fusion (in capture_fuse_wait()). Threads - * waiting on this list are waked up if atom commits or is fused into another. - * - * This is used in capture_fuse_wait() which see for more comments. - */ -TYPE_SAFE_LIST_DECLARE(fwaiting); - -/* The transaction's list of captured jnodes */ -TYPE_SAFE_LIST_DECLARE(capture); -#if REISER4_DEBUG -TYPE_SAFE_LIST_DECLARE(inode_jnodes); -#endif - -TYPE_SAFE_LIST_DECLARE(blocknr_set); /* Used for the transaction's delete set - * and wandered mapping. */ - -/* list of flush queues attached to a given atom */ -TYPE_SAFE_LIST_DECLARE(fq); - -/* list of lists of jnodes that threads take into exclusive ownership during - * allocate-on-flush.*/ -TYPE_SAFE_LIST_DECLARE(prot); - /* TYPE DECLARATIONS */ /* This enumeration describes the possible types of a capture request (try_capture). @@ -96,7 +47,8 @@ typedef enum { exclusive type designation from extra bits that may be supplied -- see below. */ TXN_CAPTURE_TYPES = (TXN_CAPTURE_READ_ATOMIC | - TXN_CAPTURE_READ_NONCOM | TXN_CAPTURE_READ_MODIFY | TXN_CAPTURE_WRITE), + TXN_CAPTURE_READ_NONCOM | TXN_CAPTURE_READ_MODIFY | + TXN_CAPTURE_WRITE), /* A subset of CAPTURE_TYPES, CAPTURE_WTYPES is a mask of request types that indicate modification will occur. */ @@ -110,10 +62,10 @@ typedef enum { TXN_CAPTURE_DONT_FUSE = (1 << 5), /* if it is set - copy on capture is allowed */ - /*TXN_CAPTURE_CAN_COC = (1 << 6)*/ + /*TXN_CAPTURE_CAN_COC = (1 << 6) */ - /* This macro selects only the exclusive capture request types, stripping out any - options that were supplied (i.e., NONBLOCKING). */ + /* This macro selects only the exclusive capture request types, stripping out any + options that were supplied (i.e., NONBLOCKING). */ #define CAPTURE_TYPE(x) ((x) & TXN_CAPTURE_TYPES) } txn_capture; @@ -210,7 +162,6 @@ typedef enum { ELSE YOU HAVE BOTH ATOM AND OBJ LOCKED - It has however been found that this wastes CPU a lot in a manner that is hard to profile. So, proper refcounting was added to atoms, and new standard locking sequence is like following: @@ -246,7 +197,7 @@ typedef enum { /* A block number set consists of only the list head. */ struct blocknr_set { - blocknr_set_list_head entries; /* blocknr_set_list_head defined from a template from tslist.h */ + struct list_head entries; }; /* An atomic transaction: this is the underlying system representation @@ -269,7 +220,7 @@ struct txn_atom { Each transaction handle counts in ->refcount. All jnodes count as one reference acquired in atom_begin_andlock(), released in commit_current_atom(). - */ + */ atomic_t refcount; /* The atom_id identifies the atom in persistent records such as the log. */ @@ -312,33 +263,33 @@ struct txn_atom { /* The transaction's list of dirty captured nodes--per level. Index by (level). dirty_nodes[0] is for znode-above-root */ - capture_list_head dirty_nodes1[REAL_MAX_ZTREE_HEIGHT + 1]; + struct list_head dirty_nodes[REAL_MAX_ZTREE_HEIGHT + 1]; /* The transaction's list of clean captured nodes. */ - capture_list_head clean_nodes1; + struct list_head clean_nodes; /* The atom's overwrite set */ - capture_list_head ovrwr_nodes1; + struct list_head ovrwr_nodes; /* nodes which are being written to disk */ - capture_list_head writeback_nodes1; + struct list_head writeback_nodes; /* list of inodes */ - capture_list_head inodes; + struct list_head inodes; /* List of handles associated with this atom. */ - txnh_list_head txnh_list; + struct list_head txnh_list; /* Transaction list link: list of atoms in the transaction manager. */ - atom_list_link atom_link; + struct list_head atom_link; /* List of handles waiting FOR this atom: see 'capture_fuse_wait' comment. */ - fwaitfor_list_head fwaitfor_list; + struct list_head fwaitfor_list; /* List of this atom's handles that are waiting: see 'capture_fuse_wait' comment. */ - fwaiting_list_head fwaiting_list; + struct list_head fwaiting_list; - prot_list_head protected; + struct list_head protected; /* Numbers of objects which were deleted/created in this transaction thereby numbers of objects IDs which were released/deallocated. */ @@ -347,7 +298,7 @@ struct txn_atom { /* number of blocks allocated during the transaction */ __u64 nr_blocks_allocated; /* All atom's flush queue objects are on this list */ - fq_list_head flush_queues; + struct list_head flush_queues; #if REISER4_DEBUG /* number of flush queues for this atom. */ int nr_flush_queues; @@ -368,27 +319,26 @@ struct txn_atom { #if REISER4_DEBUG void *committer; #endif + struct super_block *super; }; -#define ATOM_DIRTY_LIST(atom, level) (&(atom)->dirty_nodes1[level]) -#define ATOM_CLEAN_LIST(atom) (&(atom)->clean_nodes1) -#define ATOM_OVRWR_LIST(atom) (&(atom)->ovrwr_nodes1) -#define ATOM_WB_LIST(atom) (&(atom)->writeback_nodes1) -#define ATOM_FQ_LIST(fq) (&(fq)->prepped1) +#define ATOM_DIRTY_LIST(atom, level) (&(atom)->dirty_nodes[level]) +#define ATOM_CLEAN_LIST(atom) (&(atom)->clean_nodes) +#define ATOM_OVRWR_LIST(atom) (&(atom)->ovrwr_nodes) +#define ATOM_WB_LIST(atom) (&(atom)->writeback_nodes) +#define ATOM_FQ_LIST(fq) (&(fq)->prepped) -#define NODE_LIST(node) (node)->list1 +#define NODE_LIST(node) (node)->list #define ASSIGN_NODE_LIST(node, list) ON_DEBUG(NODE_LIST(node) = list) -ON_DEBUG(void count_jnode(txn_atom *, jnode *, atom_list old_list, atom_list new_list, int check_lists)); +ON_DEBUG(void + count_jnode(txn_atom *, jnode *, atom_list old_list, + atom_list new_list, int check_lists)); typedef struct protected_jnodes { - prot_list_link inatom; - capture_list_head nodes; + struct list_head inatom; /* link to atom's list these structures */ + struct list_head nodes; /* head of list of protected nodes */ } protected_jnodes; -TYPE_SAFE_LIST_DEFINE(prot, protected_jnodes, inatom); - -TYPE_SAFE_LIST_DEFINE(atom, txn_atom, atom_link); - /* A transaction handle: the client obtains and commits this handle which is assigned by the system to a txn_atom. */ struct txn_handle { @@ -405,19 +355,17 @@ struct txn_handle { /* If assigned, the atom it is part of. */ txn_atom *atom; - /* Transaction list link. */ - txnh_list_link txnh_link; + /* Transaction list link. Head is in txn_atom. */ + struct list_head txnh_link; }; -TYPE_SAFE_LIST_DECLARE(txn_mgrs); - /* The transaction manager: one is contained in the reiser4_super_info_data */ struct txn_mgr { /* A spinlock protecting the atom list, id_count, flush_control */ reiser4_spin_data tmgr_lock; /* List of atoms. */ - atom_list_head atoms_list; + struct list_head atoms_list; /* Number of atoms. */ int atom_count; @@ -429,7 +377,7 @@ struct txn_mgr { struct semaphore commit_semaphore; /* a list of all txnmrgs served by particular daemon. */ - txn_mgrs_list_link linkage; + struct list_head linkage; /* description of daemon for this txnmgr */ ktxnmgrd_context *daemon; @@ -442,19 +390,18 @@ struct txn_mgr { unsigned int atom_max_flushers; }; -/* list of all transaction managers in a system */ -TYPE_SAFE_LIST_DEFINE(txn_mgrs, txn_mgr, linkage); - /* FUNCTION DECLARATIONS */ +extern int is_cced(const jnode *node); + /* These are the externally (within Reiser4) visible transaction functions, therefore they are prefixed with "txn_". For comments, see txnmgr.c. */ -extern int txnmgr_init_static(void); -extern void txnmgr_init(txn_mgr * mgr); +extern int init_txnmgr_static(void); +extern void done_txnmgr_static(void); -extern int txnmgr_done_static(void); -extern int txnmgr_done(txn_mgr * mgr); +extern void init_txnmgr(txn_mgr *); +extern void done_txnmgr(txn_mgr *); extern int txn_reserve(int reserved); @@ -467,19 +414,21 @@ extern void txn_restart_current(void); extern int txnmgr_force_commit_all(struct super_block *, int); extern int current_atom_should_commit(void); -extern jnode * find_first_dirty_jnode (txn_atom *, int); +extern jnode *find_first_dirty_jnode(txn_atom *, int); extern int commit_some_atoms(txn_mgr *); -extern int flush_current_atom (int, long *, txn_atom **); +extern int flush_current_atom(int, long, long *, txn_atom **, jnode *); -extern int flush_some_atom(long *, const struct writeback_control *, int); +extern int flush_some_atom(jnode *, long *, const struct writeback_control *, int); -extern void atom_set_stage(txn_atom *atom, txn_stage stage); +extern void atom_set_stage(txn_atom * atom, txn_stage stage); -extern int same_slum_check(jnode * base, jnode * check, int alloc_check, int alloc_value); +extern int same_slum_check(jnode * base, jnode * check, int alloc_check, + int alloc_value); extern void atom_dec_and_unlock(txn_atom * atom); -extern int try_capture(jnode * node, znode_lock_mode mode, txn_capture flags, int can_coc); +extern int try_capture(jnode * node, znode_lock_mode mode, txn_capture flags, + int can_coc); extern int try_capture_page_to_invalidate(struct page *pg); extern void uncapture_page(struct page *pg); @@ -494,8 +443,7 @@ extern txn_atom *get_current_atom_locked #define atom_is_protected(atom) (spin_atom_is_locked(atom) || (atom)->stage >= ASTAGE_PRE_COMMIT) /* Get the current atom and spinlock it if current atom present. May not return NULL */ -static inline txn_atom * -get_current_atom_locked(void) +static inline txn_atom *get_current_atom_locked(void) { txn_atom *atom; @@ -521,14 +469,19 @@ extern void blocknr_set_merge(blocknr_se extern int blocknr_set_add_extent(txn_atom * atom, blocknr_set * bset, blocknr_set_entry ** new_bsep, - const reiser4_block_nr * start, const reiser4_block_nr * len); -extern int blocknr_set_add_pair(txn_atom * atom, - blocknr_set * bset, - blocknr_set_entry ** new_bsep, const reiser4_block_nr * a, const reiser4_block_nr * b); - -typedef int (*blocknr_set_actor_f) (txn_atom *, const reiser4_block_nr *, const reiser4_block_nr *, void *); - -extern int blocknr_set_iterator(txn_atom * atom, blocknr_set * bset, blocknr_set_actor_f actor, void *data, int delete); + const reiser4_block_nr * start, + const reiser4_block_nr * len); +extern int blocknr_set_add_pair(txn_atom * atom, blocknr_set * bset, + blocknr_set_entry ** new_bsep, + const reiser4_block_nr * a, + const reiser4_block_nr * b); + +typedef int (*blocknr_set_actor_f) (txn_atom *, const reiser4_block_nr *, + const reiser4_block_nr *, void *); + +extern int blocknr_set_iterator(txn_atom * atom, blocknr_set * bset, + blocknr_set_actor_f actor, void *data, + int delete); /* flush code takes care about how to fuse flush queues */ extern void flush_init_atom(txn_atom * atom); @@ -577,14 +530,14 @@ typedef struct flush_queue flush_queue_t struct flush_queue { /* linkage element is the first in this structure to make debugging easier. See field in atom struct for description of list. */ - fq_list_link alink; + struct list_head alink; /* A spinlock to protect changes of fq state and fq->atom pointer */ reiser4_spin_data guard; /* flush_queue state: [in_use | ready] */ flush_queue_state_t state; /* A list which contains queued nodes, queued nodes are removed from any * atom's list and put on this ->prepped one. */ - capture_list_head prepped1; + struct list_head prepped; /* number of submitted i/o requests */ atomic_t nr_submitted; /* number of i/o errors */ @@ -612,24 +565,23 @@ extern int write_fq(flush_queue_t *, lon extern int current_atom_finish_all_fq(void); extern void init_atom_fq_parts(txn_atom *); -extern unsigned int txnmgr_get_max_atom_size(struct super_block *super); -extern reiser4_block_nr txnmgr_count_deleted_blocks (void); +extern reiser4_block_nr txnmgr_count_deleted_blocks(void); extern void znode_make_dirty(znode * node); extern void jnode_make_dirty_locked(jnode * node); -extern int sync_atom(txn_atom *atom); +extern int sync_atom(txn_atom * atom); #if REISER4_DEBUG -extern int atom_fq_parts_are_clean (txn_atom *); +extern int atom_fq_parts_are_clean(txn_atom *); #endif extern void add_fq_to_bio(flush_queue_t *, struct bio *); extern flush_queue_t *get_fq_for_current_atom(void); -void protected_jnodes_init(protected_jnodes *list); -void protected_jnodes_done(protected_jnodes *list); -void invalidate_list(capture_list_head * head); +void protected_jnodes_init(protected_jnodes * list); +void protected_jnodes_done(protected_jnodes * list); +void invalidate_list(struct list_head * head); #if REISER4_DEBUG void info_atom(const char *prefix, const txn_atom * atom); diff -L fs/reiser4/type_safe_list.h -puN fs/reiser4/type_safe_list.h~reiser4-big-update /dev/null --- devel/fs/reiser4/type_safe_list.h +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,436 +0,0 @@ -/* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */ - -#ifndef __REISER4_TYPE_SAFE_LIST_H__ -#define __REISER4_TYPE_SAFE_LIST_H__ - -#include "debug.h" -/* A circular doubly linked list that differs from the previous - implementation because it is parametrized to provide - type safety. This data structure is also useful as a queue or stack. - - The "list template" consists of a set of types and methods for - implementing list operations. All of the types and methods - associated with a single list class are assigned unique names and - type signatures, thus allowing the compiler to verify correct - usage. - - The first parameter of a list class is the item type being stored - in the list. The list class maintains two pointers within each - item structure for its "next" and "prev" pointers. - - There are two structures associated with the list, in addition to - the item type itself. The "list link" contains the two pointers - that are embedded within the item itself. The "list head" also - contains two pointers which refer to the first item ("front") and - last item ("back") of the list. - - The list maintains a "circular" invariant, in that you can always - begin at the front and follow "next" pointers until eventually you - reach the same point. The "list head" is included within the - cycle, even though it does not have the correct item type. The - "list head" and "list link" types are different objects from the - user's perspective, but the core algorithms that operate on this - style of list treat the "list head" and "list link" as identical - types. That is why these algorithms are so simple. - - The implementation uses the same algorithms as those - in this file but uses only a single type "struct list_head". There - are two problems with this approach. First, there are no type - distinctions made between the two objects despite their distinct - types, which greatly increases the possibility for mistakes. For - example, the list_add function takes two "struct - list_head" arguments: the first is the item being inserted and the - second is the "struct list_head" which should precede the new - insertion to the list. You can use this function to insert at any - point in the list, but by far the most common list operations are - to insert at the front or back of the list. This common case - should accept two different argument types: a "list head" and an - "item", this allows for no confusion. - - The second problem with using a single "struct list_head" is that - it does not distinguish between list objects of distinct list - classes. If a single item can belong to two separate lists, there - is easily the possibility of a mistake being made that causes the - item to be added to a "list head" using the wrong "list link". By - using a parametrized list class we can statically detect such - mistakes, detecting mistakes as soon as they happen. - - To create a new list class takes several steps which are described - below. Suppose for this example that you would like to link - together items of type "rx_event". You should decide on - prefix-name to be used on all list functions and structures. For - example, the string "rx_event" can be as a prefix for all the list - operations, resulting in a "list head" named rx_event_list_head and - a "list link" named rx_event_list_link. The list operations on - this list class would be named "rx_event_list_empty", - "rx_event_list_init", "rx_event_list_push_front", - "rx_event_list_push_back", and so on. -*/ - -#define TYPE_SAFE_LIST_LINK_INIT(name) { &(name), &(name) } -#define TYPE_SAFE_LIST_HEAD_INIT(name) { (void *)&(name), (void *)&(name) } -#define TYPE_SAFE_LIST_LINK_ZERO { NULL, NULL } -#define TYPE_SAFE_LIST_HEAD_ZERO { NULL, NULL } - -#define TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,LINK) \ - ((ITEM_TYPE *)((char *)(LINK)-(unsigned long)(&((ITEM_TYPE *)0)->LINK_NAME))) - -/* Step 1: Use the TYPE_SAFE_LIST_DECLARE() macro to define the "list head" - and "list link" objects. This macro takes one arguments, the - prefix-name, which is prepended to every structure and function - name of the list class. Following the example, this will create - types named rx_event_list_head and rx_event_list_link. In the - example you would write: - - TYPE_SAFE_LIST_DECLARE(rx_event); - -*/ -#define TYPE_SAFE_LIST_DECLARE(PREFIX) \ - \ -typedef struct _##PREFIX##_list_head PREFIX##_list_head; \ -typedef struct _##PREFIX##_list_link PREFIX##_list_link; \ - \ -struct _##PREFIX##_list_link \ -{ \ - PREFIX##_list_link *_next; \ - PREFIX##_list_link *_prev; \ -}; \ - \ -struct _##PREFIX##_list_head \ -{ \ - PREFIX##_list_link *_next; \ - PREFIX##_list_link *_prev; \ -} - -/* Step 2: Once you have defined the two list classes, you should - define the item type you intend to use. The list classes must be - declared before the item type because the item type must contain an - embedded "list link" object. Following the example, you might define - rx_event as follows: - - typedef struct _rx_event rx_event; - - struct _rx_event - { - ... other members ... - - rx_event_list_link _link; - }; - - In this case we have given the rx_event a field named "_link" of - the appropriate type. -*/ - -/* Step 3: The final step will define the list-functions for a - specific list class using the macro TYPE_SAFE_LIST_DEFINE. There are - three arguments to the TYPE_SAFE_LIST_DEFINE macro: the prefix-name, the - item type name, and field name of the "list link" element within - the item type. In the above example you would supply "rx_event" as - the type name and "_link" as the field name (without quotes). - E.g., - - TYPE_SAFE_LIST_DEFINE(rx_event,rx_event,_link) - - The list class you define is now complete with the functions: - - rx_event_list_init Initialize a list_head - rx_event_list_clean Initialize a list_link - rx_event_list_is_clean True if list_link is not in a list - rx_event_list_push_front Insert to the front of the list - rx_event_list_push_back Insert to the back of the list - rx_event_list_insert_before Insert just before given item in the list - rx_event_list_insert_after Insert just after given item in the list - rx_event_list_remove Remove an item from anywhere in the list - rx_event_list_remove_clean Remove an item from anywhere in the list and clean link_item - rx_event_list_remove_get_next Remove an item from anywhere in the list and return the next element - rx_event_list_remove_get_prev Remove an item from anywhere in the list and return the prev element - rx_event_list_pop_front Remove and return the front of the list, cannot be empty - rx_event_list_pop_back Remove and return the back of the list, cannot be empty - rx_event_list_front Get the front of the list - rx_event_list_back Get the back of the list - rx_event_list_next Iterate front-to-back through the list - rx_event_list_prev Iterate back-to-front through the list - rx_event_list_end Test to end an iteration, either direction - rx_event_list_splice Join two lists at the head - rx_event_list_empty True if the list is empty - rx_event_list_object_ok Check that list element satisfies double - list invariants. For debugging. - - To iterate over such a list use a for-loop such as: - - rx_event_list_head *head = ...; - rx_event *item; - - for (item = rx_event_list_front (head); - ! rx_event_list_end (head, item); - item = rx_event_list_next (item)) - {...} -*/ -#define TYPE_SAFE_LIST_DEFINE(PREFIX,ITEM_TYPE,LINK_NAME) \ - \ -static __inline__ int \ -PREFIX##_list_link_invariant (const PREFIX##_list_link *_link) \ -{ \ - return (_link != NULL) && \ - (_link->_prev != NULL) && (_link->_next != NULL ) && \ - (_link->_prev->_next == _link) && \ - (_link->_next->_prev == _link); \ -} \ - \ -static __inline__ void \ -PREFIX##_list_link_ok (const PREFIX##_list_link *_link UNUSED_ARG) \ -{ \ - assert ("nikita-1054", PREFIX##_list_link_invariant (_link)); \ -} \ - \ -static __inline__ void \ -PREFIX##_list_object_ok (const ITEM_TYPE *item) \ -{ \ - PREFIX##_list_link_ok (&item->LINK_NAME); \ -} \ - \ -static __inline__ void \ -PREFIX##_list_init (PREFIX##_list_head *head) \ -{ \ - head->_next = (PREFIX##_list_link*) head; \ - head->_prev = (PREFIX##_list_link*) head; \ -} \ - \ -static __inline__ void \ -PREFIX##_list_clean (ITEM_TYPE *item) \ -{ \ - PREFIX##_list_link *_link = &item->LINK_NAME; \ - \ - _link->_next = _link; \ - _link->_prev = _link; \ -} \ - \ -static __inline__ int \ -PREFIX##_list_is_clean (const ITEM_TYPE *item) \ -{ \ - const PREFIX##_list_link *_link = &item->LINK_NAME; \ - \ - PREFIX##_list_link_ok (_link); \ - return (_link == _link->_next) && (_link == _link->_prev); \ -} \ - \ -static __inline__ void \ -PREFIX##_list_insert_int (PREFIX##_list_link *next, \ - PREFIX##_list_link *item) \ -{ \ - PREFIX##_list_link *prev = next->_prev; \ - PREFIX##_list_link_ok (next); \ - PREFIX##_list_link_ok (prev); \ - next->_prev = item; \ - item->_next = next; \ - item->_prev = prev; \ - prev->_next = item; \ - PREFIX##_list_link_ok (next); \ - PREFIX##_list_link_ok (prev); \ - PREFIX##_list_link_ok (item); \ -} \ - \ -static __inline__ void \ -PREFIX##_list_push_front (PREFIX##_list_head *head, \ - ITEM_TYPE *item) \ -{ \ - PREFIX##_list_insert_int (head->_next, & item->LINK_NAME); \ -} \ - \ -static __inline__ void \ -PREFIX##_list_push_back (PREFIX##_list_head *head, \ - ITEM_TYPE *item) \ -{ \ - PREFIX##_list_insert_int ((PREFIX##_list_link *) head, & item->LINK_NAME); \ -} \ - \ -static __inline__ void \ -PREFIX##_list_insert_before (ITEM_TYPE *reference, \ - ITEM_TYPE *item) \ -{ \ - PREFIX##_list_insert_int (& reference->LINK_NAME, & item->LINK_NAME); \ -} \ - \ -static __inline__ void \ -PREFIX##_list_insert_after (ITEM_TYPE *reference, \ - ITEM_TYPE *item) \ -{ \ - PREFIX##_list_insert_int (reference->LINK_NAME._next, & item->LINK_NAME); \ -} \ - \ -static __inline__ PREFIX##_list_link* \ -PREFIX##_list_remove_int (PREFIX##_list_link *list_link) \ -{ \ - PREFIX##_list_link *next = list_link->_next; \ - PREFIX##_list_link *prev = list_link->_prev; \ - PREFIX##_list_link_ok (list_link); \ - PREFIX##_list_link_ok (next); \ - PREFIX##_list_link_ok (prev); \ - next->_prev = prev; \ - prev->_next = next; \ - PREFIX##_list_link_ok (next); \ - PREFIX##_list_link_ok (prev); \ - return list_link; \ -} \ - \ -static __inline__ void \ -PREFIX##_list_remove (ITEM_TYPE *item) \ -{ \ - PREFIX##_list_remove_int (& item->LINK_NAME); \ -} \ - \ -static __inline__ void \ -PREFIX##_list_remove_clean (ITEM_TYPE *item) \ -{ \ - PREFIX##_list_remove_int (& item->LINK_NAME); \ - PREFIX##_list_clean (item); \ -} \ - \ -static __inline__ ITEM_TYPE* \ -PREFIX##_list_remove_get_next (ITEM_TYPE *item) \ -{ \ - PREFIX##_list_link *next = item->LINK_NAME._next; \ - PREFIX##_list_remove_int (& item->LINK_NAME); \ - return TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,next); \ -} \ - \ -static __inline__ ITEM_TYPE* \ -PREFIX##_list_remove_get_prev (ITEM_TYPE *item) \ -{ \ - PREFIX##_list_link *prev = item->LINK_NAME._prev; \ - PREFIX##_list_remove_int (& item->LINK_NAME); \ - return TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,prev); \ -} \ - \ -static __inline__ int \ -PREFIX##_list_empty (const PREFIX##_list_head *head) \ -{ \ - return head == (PREFIX##_list_head*) head->_next; \ -} \ - \ -static __inline__ ITEM_TYPE* \ -PREFIX##_list_pop_front (PREFIX##_list_head *head) \ -{ \ - assert ("nikita-1913", ! PREFIX##_list_empty (head)); \ - return TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,PREFIX##_list_remove_int (head->_next)); \ -} \ - \ -static __inline__ ITEM_TYPE* \ -PREFIX##_list_pop_back (PREFIX##_list_head *head) \ -{ \ - assert ("nikita-1914", ! PREFIX##_list_empty (head)); /* WWI started */ \ - return TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,PREFIX##_list_remove_int (head->_prev)); \ -} \ - \ -static __inline__ ITEM_TYPE* \ -PREFIX##_list_front (const PREFIX##_list_head *head) \ -{ \ - return TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,head->_next); \ -} \ - \ -static __inline__ ITEM_TYPE* \ -PREFIX##_list_back (const PREFIX##_list_head *head) \ -{ \ - return TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,head->_prev); \ -} \ - \ -static __inline__ ITEM_TYPE* \ -PREFIX##_list_next (const ITEM_TYPE *item) \ -{ \ - return TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,item->LINK_NAME._next); \ -} \ - \ -static __inline__ ITEM_TYPE* \ -PREFIX##_list_prev (const ITEM_TYPE *item) \ -{ \ - return TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,item->LINK_NAME._prev); \ -} \ - \ -static __inline__ int \ -PREFIX##_list_end (const PREFIX##_list_head *head, \ - const ITEM_TYPE *item) \ -{ \ - return ((PREFIX##_list_link *) head) == (& item->LINK_NAME); \ -} \ - \ -static __inline__ void \ -PREFIX##_list_splice (PREFIX##_list_head *head_join, \ - PREFIX##_list_head *head_empty) \ -{ \ - if (PREFIX##_list_empty (head_empty)) { \ - return; \ - } \ - \ - head_empty->_prev->_next = (PREFIX##_list_link*) head_join; \ - head_empty->_next->_prev = head_join->_prev; \ - \ - head_join->_prev->_next = head_empty->_next; \ - head_join->_prev = head_empty->_prev; \ - \ - PREFIX##_list_link_ok ((PREFIX##_list_link*) head_join); \ - PREFIX##_list_link_ok (head_join->_prev); \ - PREFIX##_list_link_ok (head_join->_next); \ - \ - PREFIX##_list_init (head_empty); \ -} \ - \ -static __inline__ void \ -PREFIX##_list_split(PREFIX##_list_head *head_split, \ - PREFIX##_list_head *head_new, \ - ITEM_TYPE *item) \ -{ \ - assert("vs-1471", PREFIX##_list_empty(head_new)); \ - \ - /* attach to new list */ \ - head_new->_next = (& item->LINK_NAME); \ - head_new->_prev = head_split->_prev; \ - \ - /* cut from old list */ \ - item->LINK_NAME._prev->_next = (PREFIX##_list_link*)head_split; \ - head_split->_prev = item->LINK_NAME._prev; \ - \ - /* link new list */ \ - head_new->_next->_prev = (PREFIX##_list_link*)head_new; \ - head_new->_prev->_next = (PREFIX##_list_link*)head_new; \ -} \ - \ -static __inline__ void \ -PREFIX##_list_check (const PREFIX##_list_head *head) \ -{ \ - const PREFIX##_list_link *link; \ - \ - for (link = head->_next ; link != ((PREFIX##_list_link *) head) ; link = link->_next) \ - PREFIX##_list_link_ok (link); \ -} \ - \ -typedef struct { int foo; } PREFIX##_list_dummy_decl - -/* The final typedef is to allow a semicolon at the end of - * TYPE_SAFE_LIST_DEFINE(); */ - -#define for_all_type_safe_list(prefix, head, item) \ - for(item = prefix ## _list_front(head), \ - prefetch(prefix ## _list_next(item)); \ - !prefix ## _list_end(head, item) ; \ - item = prefix ## _list_next(item), \ - prefetch(prefix ## _list_next(item))) - -#define for_all_type_safe_list_safe(prefix, head, item, next) \ - for(item = prefix ## _list_front(head), \ - next = prefix ## _list_next(item); \ - !prefix ## _list_end(head, item) ; \ - item = next, \ - next = prefix ## _list_next(item)) - -/* __REISER4_TYPE_SAFE_LIST_H__ */ -#endif - -/* - Local variables: - c-indentation-style: "K&R" - mode-name: "LC" - c-basic-offset: 8 - tab-width: 8 - fill-column: 120 - End: -*/ diff -puN fs/reiser4/vfs_ops.c~reiser4-big-update fs/reiser4/vfs_ops.c --- devel/fs/reiser4/vfs_ops.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/vfs_ops.c 2005-09-15 19:51:08.000000000 -0700 @@ -12,7 +12,6 @@ #include "plugin/file/file.h" #include "plugin/security/perm.h" #include "plugin/disk_format/disk_format.h" -#include "plugin/dir/dir.h" #include "plugin/plugin.h" #include "plugin/plugin_set.h" #include "plugin/object.h" @@ -29,7 +28,6 @@ #include "reiser4.h" #include "entd.h" #include "emergency_flush.h" -#include "init_super.h" #include "status_flags.h" #include "flush.h" #include "dscale.h" @@ -54,109 +52,11 @@ #include #include -/* super operations */ - -static struct inode *reiser4_alloc_inode(struct super_block *); -static void reiser4_destroy_inode(struct inode *); -static void reiser4_put_inode(struct inode *); -static void reiser4_delete_inode(struct inode *); -static void reiser4_write_super(struct super_block *); -static int reiser4_statfs(struct super_block *, struct kstatfs *); -static int reiser4_show_options(struct seq_file *m, struct vfsmount *mnt); -static void reiser4_sync_inodes(struct super_block *, struct writeback_control *); - -extern struct dentry_operations reiser4_dentry_operation; - -static struct file_system_type reiser4_fs_type; - -/* ->statfs() VFS method in reiser4 super_operations */ -static int -reiser4_statfs(struct super_block *super /* super block of file - * system in queried */ , - struct kstatfs *statfs /* buffer to fill with - * statistics */ ) -{ - sector_t total; - sector_t reserved; - sector_t free; - sector_t forroot; - sector_t deleted; - reiser4_context ctx; - - assert("nikita-408", super != NULL); - assert("nikita-409", statfs != NULL); - - init_context(&ctx, super); - - statfs->f_type = statfs_type(super); - statfs->f_bsize = super->s_blocksize; - - /* - * 5% of total block space is reserved. This is needed for flush and - * for truncates (so that we are able to perform truncate/unlink even - * on the otherwise completely full file system). If this reservation - * is hidden from statfs(2), users will mistakenly guess that they - * have enough free space to complete some operation, which is - * frustrating. - * - * Another possible solution is to subtract ->blocks_reserved from - * ->f_bfree, but changing available space seems less intrusive than - * letting user to see 5% of disk space to be used directly after - * mkfs. - */ - total = reiser4_block_count(super); - reserved = get_super_private(super)->blocks_reserved; - deleted = txnmgr_count_deleted_blocks(); - free = reiser4_free_blocks(super) + deleted; - forroot = reiser4_reserved_blocks(super, 0, 0); - - /* These counters may be in inconsistent state because we take the - * values without keeping any global spinlock. Here we do a sanity - * check that free block counter does not exceed the number of all - * blocks. */ - if (free > total) - free = total; - statfs->f_blocks = total - reserved; - /* make sure statfs->f_bfree is never larger than statfs->f_blocks */ - if (free > reserved) - free -= reserved; - else - free = 0; - statfs->f_bfree = free; - - if (free > forroot) - free -= forroot; - else - free = 0; - statfs->f_bavail = free; - -/* FIXME: Seems that various df implementations are way unhappy by such big numbers. - So we will leave those as zeroes. - statfs->f_files = oids_used(super) + oids_free(super); - statfs->f_ffree = oids_free(super); -*/ - - /* maximal acceptable name length depends on directory plugin. */ - assert("nikita-3351", super->s_root->d_inode != NULL); - statfs->f_namelen = reiser4_max_filename_len(super->s_root->d_inode); - reiser4_exit_context(&ctx); - return 0; -} - -/* this is called whenever mark_inode_dirty is to be called. Stat-data are - * updated in the tree. */ -reiser4_internal int -reiser4_mark_inode_dirty(struct inode *inode) -{ - assert("vs-1207", is_in_reiser4_context()); - return reiser4_update_sd(inode); -} /* update inode stat-data by calling plugin */ -reiser4_internal int -reiser4_update_sd(struct inode *object) +int reiser4_update_sd(struct inode *object) { - file_plugin *fplug; + file_plugin *fplug; assert("nikita-2338", object != NULL); /* check for read-only file system. */ @@ -173,10 +73,10 @@ reiser4_update_sd(struct inode *object) Used by link/create and during creation of dot and dotdot in mkdir */ -reiser4_internal int -reiser4_add_nlink(struct inode *object /* object to which link is added */ , - struct inode *parent /* parent where new entry will be */ , - int write_sd_p /* true if stat-data has to be +int reiser4_add_nlink(struct inode *object /* object to which link is added */ , + struct inode *parent /* parent where new entry will be */ + , + int write_sd_p /* true if stat-data has to be * updated */ ) { file_plugin *fplug; @@ -196,8 +96,6 @@ reiser4_add_nlink(struct inode *object / /* call plugin to do actual addition of link */ result = fplug->add_link(object, parent); - mark_inode_update(object, write_sd_p); - /* optionally update stat data */ if (result == 0 && write_sd_p) result = fplug->write_sd_by_inode(object); @@ -209,11 +107,10 @@ reiser4_add_nlink(struct inode *object / Used by unlink/create */ -reiser4_internal int -reiser4_del_nlink(struct inode *object /* object from which link is - * removed */ , - struct inode *parent /* parent where entry was */ , - int write_sd_p /* true is stat-data has to be +int reiser4_del_nlink(struct inode *object /* object from which link is + * removed */ , + struct inode *parent /* parent where entry was */ , + int write_sd_p /* true is stat-data has to be * updated */ ) { file_plugin *fplug; @@ -228,340 +125,39 @@ reiser4_del_nlink(struct inode *object / /* call plugin to do actual deletion of link */ result = fplug->rem_link(object, parent); - mark_inode_update(object, write_sd_p); + /* optionally update stat data */ if (result == 0 && write_sd_p) result = fplug->write_sd_by_inode(object); return result; } -/* slab for reiser4_dentry_fsdata */ -static kmem_cache_t *dentry_fsdata_slab; - -/* - * initializer for dentry_fsdata_slab called during boot or module load. - */ -static int -init_dentry_fsdata(void) -{ - dentry_fsdata_slab = kmem_cache_create("dentry_fsdata", - sizeof (reiser4_dentry_fsdata), - 0, - SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, - NULL, - NULL); - return (dentry_fsdata_slab == NULL) ? RETERR(-ENOMEM) : 0; -} - -/* - * dual to init_dentry_fsdata(). Called on module unload. - */ -static void -done_dentry_fsdata(void) -{ - kmem_cache_destroy(dentry_fsdata_slab); -} - - -/* Return and lazily allocate if necessary per-dentry data that we - attach to each dentry. */ -reiser4_internal reiser4_dentry_fsdata * -reiser4_get_dentry_fsdata(struct dentry *dentry /* dentry - * queried */ ) -{ - assert("nikita-1365", dentry != NULL); - if (dentry->d_fsdata == NULL) { - dentry->d_fsdata = kmem_cache_alloc(dentry_fsdata_slab, - GFP_KERNEL); - if (dentry->d_fsdata == NULL) - return ERR_PTR(RETERR(-ENOMEM)); - memset(dentry->d_fsdata, 0, sizeof (reiser4_dentry_fsdata)); - } - return dentry->d_fsdata; -} -/* opposite to reiser4_get_dentry_fsdata(), returns per-dentry data into slab - * allocator */ -reiser4_internal void -reiser4_free_dentry_fsdata(struct dentry *dentry /* dentry released */ ) -{ - if (dentry->d_fsdata != NULL) { - kmem_cache_free(dentry_fsdata_slab, dentry->d_fsdata); - dentry->d_fsdata = NULL; - } -} /* Release reiser4 dentry. This is d_op->d_release() method. */ -static void -reiser4_d_release(struct dentry *dentry /* dentry released */ ) +static void reiser4_d_release(struct dentry *dentry /* dentry released */ ) { reiser4_free_dentry_fsdata(dentry); } -/* slab for reiser4_dentry_fsdata */ -static kmem_cache_t *file_fsdata_slab; - -/* - * initialize file_fsdata_slab. This is called during boot or module load. - */ -static int -init_file_fsdata(void) -{ - file_fsdata_slab = kmem_cache_create("file_fsdata", - sizeof (reiser4_file_fsdata), - 0, - SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, - NULL, - NULL); - return (file_fsdata_slab == NULL) ? RETERR(-ENOMEM) : 0; -} - -/* - * dual to init_file_fsdata(). Called during module unload. - */ -static void -done_file_fsdata(void) -{ - kmem_cache_destroy(file_fsdata_slab); -} - -/* - * Create reiser4 specific per-file data: reiser4_file_fsdata. - */ -reiser4_internal reiser4_file_fsdata * -create_fsdata(struct file *file, int gfp) -{ - reiser4_file_fsdata *fsdata; - - fsdata = kmem_cache_alloc(file_fsdata_slab, gfp); - if (fsdata != NULL) { - memset(fsdata, 0, sizeof *fsdata); - fsdata->ra1.max_window_size = VM_MAX_READAHEAD * 1024; - fsdata->back = file; - readdir_list_clean(fsdata); - } - return fsdata; -} - -/* Return and lazily allocate if necessary per-file data that we attach - to each struct file. */ -reiser4_internal reiser4_file_fsdata * -reiser4_get_file_fsdata(struct file *f /* file - * queried */ ) -{ - assert("nikita-1603", f != NULL); - - if (f->private_data == NULL) { - reiser4_file_fsdata *fsdata; - struct inode *inode; - - fsdata = create_fsdata(f, GFP_KERNEL); - if (fsdata == NULL) - return ERR_PTR(RETERR(-ENOMEM)); - - inode = f->f_dentry->d_inode; - spin_lock_inode(inode); - if (f->private_data == NULL) { - f->private_data = fsdata; - fsdata = NULL; - } - spin_unlock_inode(inode); - if (fsdata != NULL) - /* other thread initialized ->fsdata */ - kmem_cache_free(file_fsdata_slab, fsdata); - } - assert("nikita-2665", f->private_data != NULL); - return f->private_data; -} - -/* - * Dual to create_fsdata(). Free reiser4_file_fsdata. - */ -reiser4_internal void -reiser4_free_fsdata(reiser4_file_fsdata *fsdata) -{ - if (fsdata != NULL) - kmem_cache_free(file_fsdata_slab, fsdata); -} - -/* - * Dual to reiser4_get_file_fsdata(). - */ -reiser4_internal void -reiser4_free_file_fsdata(struct file *f) -{ - reiser4_file_fsdata *fsdata; - fsdata = f->private_data; - if (fsdata != NULL) { - readdir_list_remove_clean(fsdata); - if (fsdata->cursor == NULL) - reiser4_free_fsdata(fsdata); - } - f->private_data = NULL; -} -/* our ->read_inode() is no-op. Reiser4 inodes should be loaded - through fs/reiser4/inode.c:reiser4_iget() */ -static void -noop_read_inode(struct inode *inode UNUSED_ARG) -{ -} /* initialization and shutdown */ -/* slab cache for inodes */ -static kmem_cache_t *inode_cache; - -/* initialization function passed to the kmem_cache_create() to init new pages - grabbed by our inodecache. */ -static void -init_once(void *obj /* pointer to new inode */ , - kmem_cache_t * cache UNUSED_ARG /* slab cache */ , - unsigned long flags /* cache flags */ ) -{ - reiser4_inode_object *info; - info = obj; - - if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) { - /* NOTE-NIKITA add here initializations for locks, list heads, - etc. that will be added to our private inode part. */ - inode_init_once(&info->vfs_inode); - readdir_list_init(get_readdir_list(&info->vfs_inode)); - init_rwsem(&info->p.coc_sem); - /* init semaphore which is used during inode loading */ - loading_init_once(&info->p); - INIT_RADIX_TREE(jnode_tree_by_reiser4_inode(&info->p), GFP_ATOMIC); -#if REISER4_DEBUG - info->p.nr_jnodes = 0; - info->p.captured_eflushed = 0; - info->p.anonymous_eflushed = 0; -#endif - } -} -/* initialize slab cache where reiser4 inodes will live */ -static int -init_inodecache(void) -{ - inode_cache = kmem_cache_create("reiser4_inode", - sizeof (reiser4_inode_object), - 0, - SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, - init_once, - NULL); - return (inode_cache != NULL) ? 0 : RETERR(-ENOMEM); -} - -/* initialize slab cache where reiser4 inodes lived */ -static void -destroy_inodecache(void) -{ - if (kmem_cache_destroy(inode_cache) != 0) - warning("nikita-1695", "not all inodes were freed"); -} - -/* ->alloc_inode() super operation: allocate new inode */ -static struct inode * -reiser4_alloc_inode(struct super_block *super UNUSED_ARG /* super block new - * inode is - * allocated for */ ) -{ - reiser4_inode_object *obj; - - assert("nikita-1696", super != NULL); - obj = kmem_cache_alloc(inode_cache, SLAB_KERNEL); - if (obj != NULL) { - reiser4_inode *info; - - info = &obj->p; - - info->hset = info->pset = plugin_set_get_empty(); - info->extmask = 0; - info->locality_id = 0ull; - info->plugin_mask = 0; -#if !REISER4_INO_IS_OID - info->oid_hi = 0; -#endif - seal_init(&info->sd_seal, NULL, NULL); - coord_init_invalid(&info->sd_coord, NULL); - info->flags = 0; - spin_inode_object_init(info); - /* this deals with info's loading semaphore */ - loading_alloc(info); - info->vroot = UBER_TREE_ADDR; - return &obj->vfs_inode; - } else - return NULL; -} - -/* ->destroy_inode() super operation: recycle inode */ -static void -reiser4_destroy_inode(struct inode *inode /* inode being destroyed */) -{ - reiser4_inode *info; - - info = reiser4_inode_data(inode); - - assert("vs-1220", inode_has_no_jnodes(info)); - - if (!is_bad_inode(inode) && is_inode_loaded(inode)) { - file_plugin * fplug = inode_file_plugin(inode); - if (fplug->destroy_inode != NULL) - fplug->destroy_inode(inode); - } - dispose_cursors(inode); - if (info->pset) - plugin_set_put(info->pset); - - /* cannot add similar assertion about ->i_list as prune_icache return - * inode into slab with dangling ->list.{next,prev}. This is safe, - * because they are re-initialized in the new_inode(). */ - assert("nikita-2895", list_empty(&inode->i_dentry)); - assert("nikita-2896", hlist_unhashed(&inode->i_hash)); - assert("nikita-2898", readdir_list_empty(get_readdir_list(inode))); - - /* this deals with info's loading semaphore */ - loading_destroy(info); - - kmem_cache_free(inode_cache, container_of(info, reiser4_inode_object, p)); -} - -/* put_inode of super_operations - - we use put_inode to call pre_delete method of file plugin if it is defined - and if inode is unlinked and if it is about to drop inode reference count to - 0. */ -static void -reiser4_put_inode(struct inode *inode) -{ - reiser4_context ctx; - file_plugin *fplug; - - fplug = inode_file_plugin(inode); - if (fplug == NULL || - inode->i_nlink != 0 || - atomic_read(&inode->i_count) > 1 || - fplug->pre_delete == NULL) - return; - - init_context(&ctx, inode->i_sb); - /* kill cursors which might be attached to inode if it were a directory one */ - kill_cursors(inode); - fplug->pre_delete(inode); - reiser4_exit_context(&ctx); -} /* * Called by reiser4_sync_inodes(), during speculative write-back (through * pdflush, or balance_dirty_pages()). */ -void -writeout(struct super_block *sb, struct writeback_control *wbc) +void writeout(struct super_block *sb, struct writeback_control *wbc) { long written = 0; int repeats = 0; + int result; + struct address_space *mapping; /* * Performs early flushing, trying to free some memory. If there is @@ -575,631 +171,54 @@ writeout(struct super_block *sb, struct return; } + BUG_ON(get_super_fake(sb) == NULL); + mapping = get_super_fake(sb)->i_mapping; do { long nr_submitted = 0; - struct inode *fake; + struct wbq * rq; + jnode * node = NULL; - fake = get_super_fake(sb); - if (fake != NULL) { - struct address_space *mapping; - - mapping = fake->i_mapping; - /* do not put more requests to overload write queue */ - if (wbc->nonblocking && - bdi_write_congested(mapping->backing_dev_info)) { - blk_run_address_space(mapping); - wbc->encountered_congestion = 1; - break; - } + /* do not put more requests to overload write queue */ + if (wbc->nonblocking && + bdi_write_congested(mapping->backing_dev_info)) { + blk_run_address_space(mapping); + wbc->encountered_congestion = 1; + break; } - repeats ++; - flush_some_atom(&nr_submitted, wbc, JNODE_FLUSH_WRITE_BLOCKS); + repeats++; + BUG_ON(wbc->nr_to_write <= 0); + + rq = get_wbq(sb); + node = get_jnode_by_wbq(sb, rq); + + result = flush_some_atom( + node, &nr_submitted, wbc, JNODE_FLUSH_WRITE_BLOCKS); + if (result != 0) + warning("nikita-31001", "Flush failed: %i", result); + if (rq) + put_wbq(sb, rq); + if (node) + jput(node); if (!nr_submitted) break; wbc->nr_to_write -= nr_submitted; - written += nr_submitted; - } while (wbc->nr_to_write > 0); - } -/* ->sync_inodes() method. This is called by pdflush, and synchronous - * writeback (throttling by balance_dirty_pages()). */ -static void -reiser4_sync_inodes(struct super_block * sb, struct writeback_control * wbc) -{ - reiser4_context ctx; - - /* reiser4 has its own means of periodical write-out */ - if (wbc->for_kupdate) - return; - - assert("", wbc->older_than_this == NULL); - - init_context(&ctx, sb); - - /* - * call reiser4_writepages for each of dirty inodes to turn dirty pages - * into transactions if they were not yet. - */ - generic_sync_sb_inodes(sb, wbc); - - /* flush goes here */ - writeout(sb, wbc); - - /* avoid recursive calls to ->sync_inodes */ - context_set_commit_async(&ctx); - reiser4_exit_context(&ctx); -} -void reiser4_throttle_write(struct inode * inode) +void reiser4_throttle_write(struct inode *inode) { txn_restart_current(); balance_dirty_pages_ratelimited(inode->i_mapping); } -/* ->delete_inode() super operation */ -static void -reiser4_delete_inode(struct inode *object) -{ - reiser4_context ctx; - - truncate_inode_pages(&object->i_data, 0); - - init_context(&ctx, object->i_sb); - if (is_inode_loaded(object)) { - file_plugin *fplug; - - fplug = inode_file_plugin(object); - if (fplug != NULL && fplug->delete != NULL) - fplug->delete(object); - } - - object->i_blocks = 0; - clear_inode(object); - reiser4_exit_context(&ctx); -} - -/* ->delete_inode() super operation */ -static void -reiser4_clear_inode(struct inode *object) -{ -#if REISER4_DEBUG - reiser4_inode *r4_inode; - - r4_inode = reiser4_inode_data(object); - if (!inode_has_no_jnodes(r4_inode)) - warning("vs-1732", "reiser4 inode is not clear: ae %d, ce %d, jnodes %lu\n", - r4_inode->anonymous_eflushed, r4_inode->captured_eflushed, - r4_inode->nr_jnodes); -#endif -} - const char *REISER4_SUPER_MAGIC_STRING = "ReIsEr4"; const int REISER4_MAGIC_OFFSET = 16 * 4096; /* offset to magic string from the * beginning of device */ -/* type of option parseable by parse_option() */ -typedef enum { - /* value of option is arbitrary string */ - OPT_STRING, - /* option specifies bit in a bitmask */ - OPT_BIT, - /* value of option should conform to sprintf() format */ - OPT_FORMAT, - /* option can take one of predefined values */ - OPT_ONEOF, -} opt_type_t; - -typedef struct opt_bitmask_bit { - const char *bit_name; - int bit_nr; -} opt_bitmask_bit; - -/* description of option parseable by parse_option() */ -typedef struct opt_desc { - /* option name. - - parsed portion of string has a form "name=value". - */ - const char *name; - /* type of option */ - opt_type_t type; - union { - /* where to store value of string option (type == OPT_STRING) */ - char **string; - /* description of bits for bit option (type == OPT_BIT) */ - struct { - int nr; - void *addr; - } bit; - /* description of format and targets for format option (type - == OPT_FORMAT) */ - struct { - const char *format; - int nr_args; - void *arg1; - void *arg2; - void *arg3; - void *arg4; - } f; - struct { - int *result; - const char *list[10]; - } oneof; - struct { - void *addr; - int nr_bits; - opt_bitmask_bit *bits; - } bitmask; - } u; -} opt_desc_t; - -/* parse one option */ -static int -parse_option(char *opt_string /* starting point of parsing */ , - opt_desc_t * opt /* option description */ ) -{ - /* foo=bar, - ^ ^ ^ - | | +-- replaced to '\0' - | +-- val_start - +-- opt_string - */ - char *val_start; - int result; - const char *err_msg; - - /* NOTE-NIKITA think about using lib/cmdline.c functions here. */ - - val_start = strchr(opt_string, '='); - if (val_start != NULL) { - *val_start = '\0'; - ++val_start; - } - - err_msg = NULL; - result = 0; - switch (opt->type) { - case OPT_STRING: - if (val_start == NULL) { - err_msg = "String arg missing"; - result = RETERR(-EINVAL); - } else - *opt->u.string = val_start; - break; - case OPT_BIT: - if (val_start != NULL) - err_msg = "Value ignored"; - else - set_bit(opt->u.bit.nr, opt->u.bit.addr); - break; - case OPT_FORMAT: - if (val_start == NULL) { - err_msg = "Formatted arg missing"; - result = RETERR(-EINVAL); - break; - } - if (sscanf(val_start, opt->u.f.format, - opt->u.f.arg1, opt->u.f.arg2, opt->u.f.arg3, opt->u.f.arg4) != opt->u.f.nr_args) { - err_msg = "Wrong conversion"; - result = RETERR(-EINVAL); - } - break; - case OPT_ONEOF: - { - int i = 0; - - if (val_start == NULL) { - err_msg = "Value is missing"; - result = RETERR(-EINVAL); - break; - } - err_msg = "Wrong option value"; - result = RETERR(-EINVAL); - while ( opt->u.oneof.list[i] ) { - if ( !strcmp(opt->u.oneof.list[i], val_start) ) { - result = 0; - err_msg = NULL; - *opt->u.oneof.result = i; - break; - } - i++; - } - break; - } - default: - wrong_return_value("nikita-2100", "opt -> type"); - break; - } - if (err_msg != NULL) { - warning("nikita-2496", "%s when parsing option \"%s%s%s\"", - err_msg, opt->name, val_start ? "=" : "", val_start ? : ""); - } - return result; -} - -/* parse options */ -static int -parse_options(char *opt_string /* starting point */ , - opt_desc_t * opts /* array with option description */ , - int nr_opts /* number of elements in @opts */ ) -{ - int result; - - result = 0; - while ((result == 0) && opt_string && *opt_string) { - int j; - char *next; - - next = strchr(opt_string, ','); - if (next != NULL) { - *next = '\0'; - ++next; - } - for (j = 0; j < nr_opts; ++j) { - if (!strncmp(opt_string, opts[j].name, strlen(opts[j].name))) { - result = parse_option(opt_string, &opts[j]); - break; - } - } - if (j == nr_opts) { - warning("nikita-2307", "Unrecognized option: \"%s\"", opt_string); - /* traditionally, -EINVAL is returned on wrong mount - option */ - result = RETERR(-EINVAL); - } - opt_string = next; - } - return result; -} - -#define NUM_OPT( label, fmt, addr ) \ - { \ - .name = ( label ), \ - .type = OPT_FORMAT, \ - .u = { \ - .f = { \ - .format = ( fmt ), \ - .nr_args = 1, \ - .arg1 = ( addr ), \ - .arg2 = NULL, \ - .arg3 = NULL, \ - .arg4 = NULL \ - } \ - } \ - } - -#define SB_FIELD_OPT( field, fmt ) NUM_OPT( #field, fmt, &sbinfo -> field ) - -#define BIT_OPT(label, bitnr) \ - { \ - .name = label, \ - .type = OPT_BIT, \ - .u = { \ - .bit = { \ - .nr = bitnr, \ - .addr = &sbinfo->fs_flags \ - } \ - } \ - } - - -#define MAX_NR_OPTIONS (30) - -/* parse options during mount */ -reiser4_internal int -reiser4_parse_options(struct super_block *s, char *opt_string) -{ - int result; - reiser4_super_info_data *sbinfo = get_super_private(s); - char *log_file_name; - opt_desc_t *opts, *p; - - opts = kmalloc(sizeof(opt_desc_t) * MAX_NR_OPTIONS, GFP_KERNEL); - if (opts == NULL) - return RETERR(-ENOMEM); - - p = opts; - -#if REISER4_DEBUG -# define OPT_ARRAY_CHECK if ((p) > (opts) + MAX_NR_OPTIONS) { \ - warning ("zam-1046", "opt array is overloaded"); break; \ - } -#else -# define OPT_ARRAY_CHECK noop -#endif - -#define PUSH_OPT(...) \ -do { \ - opt_desc_t o = __VA_ARGS__; \ - OPT_ARRAY_CHECK; \ - *p ++ = o; \ -} while (0) - -#define PUSH_SB_FIELD_OPT(field, format) PUSH_OPT(SB_FIELD_OPT(field, format)) -#define PUSH_BIT_OPT(name, bit) PUSH_OPT(BIT_OPT(name, bit)) - - /* trace_flags=N - - set trace flags to be N for this mount. N can be C numeric - literal recognized by %i scanf specifier. It is treated as - bitfield filled by values of debug.h:reiser4_trace_flags - enum - */ - PUSH_SB_FIELD_OPT(trace_flags, "%i"); - /* log_flags=N - - set log flags to be N for this mount. N can be C numeric - literal recognized by %i scanf specifier. It is treated as - bitfield filled by values of debug.h:reiser4_log_flags - enum - */ - PUSH_SB_FIELD_OPT(log_flags, "%i"); - /* debug_flags=N - - set debug flags to be N for this mount. N can be C numeric - literal recognized by %i scanf specifier. It is treated as - bitfield filled by values of debug.h:reiser4_debug_flags - enum - */ - PUSH_SB_FIELD_OPT(debug_flags, "%i"); - /* tmgr.atom_max_size=N - - Atoms containing more than N blocks will be forced to - commit. N is decimal. - */ - PUSH_SB_FIELD_OPT(tmgr.atom_max_size, "%u"); - /* tmgr.atom_max_age=N - - Atoms older than N seconds will be forced to commit. N is - decimal. - */ - PUSH_SB_FIELD_OPT(tmgr.atom_max_age, "%u"); - /* tmgr.atom_min_size=N - - In committing an atom to free dirty pages, force the atom less than N in - size to fuse with another one. - */ - PUSH_SB_FIELD_OPT(tmgr.atom_min_size, "%u"); - /* tmgr.atom_max_flushers=N - - limit of concurrent flushers for one atom. 0 means no limit. - */ - PUSH_SB_FIELD_OPT(tmgr.atom_max_flushers, "%u"); - /* tree.cbk_cache_slots=N - - Number of slots in the cbk cache. - */ - PUSH_SB_FIELD_OPT(tree.cbk_cache.nr_slots, "%u"); - - /* If flush finds more than FLUSH_RELOCATE_THRESHOLD adjacent - dirty leaf-level blocks it will force them to be - relocated. */ - PUSH_SB_FIELD_OPT(flush.relocate_threshold, "%u"); - /* If flush finds can find a block allocation closer than at - most FLUSH_RELOCATE_DISTANCE from the preceder it will - relocate to that position. */ - PUSH_SB_FIELD_OPT(flush.relocate_distance, "%u"); - /* If we have written this much or more blocks before - encountering busy jnode in flush list - abort flushing - hoping that next time we get called this jnode will be - clean already, and we will save some seeks. */ - PUSH_SB_FIELD_OPT(flush.written_threshold, "%u"); - /* The maximum number of nodes to scan left on a level during - flush. */ - PUSH_SB_FIELD_OPT(flush.scan_maxnodes, "%u"); - - /* preferred IO size */ - PUSH_SB_FIELD_OPT(optimal_io_size, "%u"); - - /* carry flags used for insertion of new nodes */ - PUSH_SB_FIELD_OPT(tree.carry.new_node_flags, "%u"); - /* carry flags used for insertion of new extents */ - PUSH_SB_FIELD_OPT(tree.carry.new_extent_flags, "%u"); - /* carry flags used for paste operations */ - PUSH_SB_FIELD_OPT(tree.carry.paste_flags, "%u"); - /* carry flags used for insert operations */ - PUSH_SB_FIELD_OPT(tree.carry.insert_flags, "%u"); - -#ifdef CONFIG_REISER4_BADBLOCKS - /* Alternative master superblock location in case if it's original - location is not writeable/accessable. This is offset in BYTES. */ - PUSH_SB_FIELD_OPT(altsuper, "%lu"); -#endif - - /* turn on BSD-style gid assignment */ - PUSH_BIT_OPT("bsdgroups", REISER4_BSD_GID); - /* turn on 32 bit times */ - PUSH_BIT_OPT("32bittimes", REISER4_32_BIT_TIMES); - /* turn off concurrent flushing */ - PUSH_BIT_OPT("mtflush", REISER4_MTFLUSH); - /* disable pseudo files support */ - PUSH_BIT_OPT("nopseudo", REISER4_NO_PSEUDO); - /* Don't load all bitmap blocks at mount time, it is useful - for machines with tiny RAM and large disks. */ - PUSH_BIT_OPT("dont_load_bitmap", REISER4_DONT_LOAD_BITMAP); - /* disable transaction commits during write() */ - PUSH_BIT_OPT("atomic_write", REISER4_ATOMIC_WRITE); - - PUSH_OPT ({ - /* tree traversal readahead parameters: - -o readahead:MAXNUM:FLAGS - MAXNUM - max number fo nodes to request readahead for: -1UL will set it to max_sane_readahead() - FLAGS - combination of bits: RA_ADJCENT_ONLY, RA_ALL_LEVELS, CONTINUE_ON_PRESENT - */ - .name = "readahead", - .type = OPT_FORMAT, - .u = { - .f = { - .format = "%u:%u", - .nr_args = 2, - .arg1 = &sbinfo->ra_params.max, - .arg2 = &sbinfo->ra_params.flags, - .arg3 = NULL, - .arg4 = NULL - } - } - }); - - /* What to do in case of fs error */ - PUSH_OPT ({ - .name = "onerror", - .type = OPT_ONEOF, - .u = { - .oneof = { - .result = &sbinfo->onerror, - .list = {"panic", "remount-ro", "reboot", NULL}, - } - } - }); - - sbinfo->tmgr.atom_max_size = txnmgr_get_max_atom_size(s); - sbinfo->tmgr.atom_max_age = REISER4_ATOM_MAX_AGE / HZ; - sbinfo->tmgr.atom_min_size = 256; - sbinfo->tmgr.atom_max_flushers = ATOM_MAX_FLUSHERS; - - sbinfo->tree.cbk_cache.nr_slots = CBK_CACHE_SLOTS; - - sbinfo->flush.relocate_threshold = FLUSH_RELOCATE_THRESHOLD; - sbinfo->flush.relocate_distance = FLUSH_RELOCATE_DISTANCE; - sbinfo->flush.written_threshold = FLUSH_WRITTEN_THRESHOLD; - sbinfo->flush.scan_maxnodes = FLUSH_SCAN_MAXNODES; - - sbinfo->optimal_io_size = REISER4_OPTIMAL_IO_SIZE; - - sbinfo->tree.carry.new_node_flags = REISER4_NEW_NODE_FLAGS; - sbinfo->tree.carry.new_extent_flags = REISER4_NEW_EXTENT_FLAGS; - sbinfo->tree.carry.paste_flags = REISER4_PASTE_FLAGS; - sbinfo->tree.carry.insert_flags = REISER4_INSERT_FLAGS; - - log_file_name = NULL; - - /* - init default readahead params - */ - sbinfo->ra_params.max = num_physpages / 4; - sbinfo->ra_params.flags = 0; - - result = parse_options(opt_string, opts, p - opts); - kfree(opts); - if (result != 0) - return result; - - sbinfo->tmgr.atom_max_age *= HZ; - if (sbinfo->tmgr.atom_max_age <= 0) - /* overflow */ - sbinfo->tmgr.atom_max_age = REISER4_ATOM_MAX_AGE; - - /* round optimal io size up to 512 bytes */ - sbinfo->optimal_io_size >>= VFS_BLKSIZE_BITS; - sbinfo->optimal_io_size <<= VFS_BLKSIZE_BITS; - if (sbinfo->optimal_io_size == 0) { - warning("nikita-2497", "optimal_io_size is too small"); - return RETERR(-EINVAL); - } - - /* disable single-threaded flush as it leads to deadlock */ - sbinfo->fs_flags |= (1 << REISER4_MTFLUSH); - return result; -} - -/* show mount options in /proc/mounts */ -static int -reiser4_show_options(struct seq_file *m, struct vfsmount *mnt) -{ - struct super_block *super; - reiser4_super_info_data *sbinfo; - - super = mnt->mnt_sb; - sbinfo = get_super_private(super); - - seq_printf(m, ",trace=0x%x", sbinfo->trace_flags); - seq_printf(m, ",log=0x%x", sbinfo->log_flags); - seq_printf(m, ",debug=0x%x", sbinfo->debug_flags); - seq_printf(m, ",atom_max_size=0x%x", sbinfo->tmgr.atom_max_size); - - return 0; -} - -/* ->write_super() method. Called by sync(2). */ -static void -reiser4_write_super(struct super_block *s) -{ - int ret; - reiser4_context ctx; - - assert("vs-1700", !rofs_super(s)); - - init_context(&ctx, s); - - ret = capture_super_block(s); - if (ret != 0) - warning("vs-1701", - "capture_super_block failed in write_super: %d", ret); - ret = txnmgr_force_commit_all(s, 1); - if (ret != 0) - warning("jmacd-77113", - "txn_force failed in write_super: %d", ret); - - s->s_dirt = 0; - - reiser4_exit_context(&ctx); -} - -static void -reiser4_put_super(struct super_block *s) -{ - reiser4_super_info_data *sbinfo; - reiser4_context context; - - sbinfo = get_super_private(s); - assert("vs-1699", sbinfo); - - init_context(&context, s); - stop_ktxnmgrd(&sbinfo->tmgr); - - /* have disk format plugin to free its resources */ - if (get_super_private(s)->df_plug->release) - get_super_private(s)->df_plug->release(s); - - done_ktxnmgrd_context(&sbinfo->tmgr); - done_entd_context(s); - - check_block_counters(s); - - rcu_barrier(); - /* done_formatted_fake just has finished with last jnodes (bitmap - * ones) */ - done_tree(&sbinfo->tree); - /* call finish_rcu(), because some znode were "released" in - * done_tree(). */ - rcu_barrier(); - done_formatted_fake(s); - - /* no assertions below this line */ - reiser4_exit_context(&context); - - kfree(sbinfo); - s->s_fs_info = NULL; -} - -/* ->get_sb() method of file_system operations. */ -static struct super_block * -reiser4_get_sb(struct file_system_type *fs_type /* file - * system - * type */ , - int flags /* flags */ , - const char *dev_name /* device name */ , - void *data /* mount options */ ) -{ - return get_sb_bdev(fs_type, flags, dev_name, data, reiser4_fill_super); -} -int d_cursor_init(void); -void d_cursor_done(void); /* * Reiser4 initialization/shutdown. @@ -1209,429 +228,27 @@ void d_cursor_done(void); * during reiser4 module load (when compiled as module). */ -/* - * Initialization stages for reiser4. - * - * These enumerate various things that have to be done during reiser4 - * startup. Initialization code (init_reiser4()) keeps track of what stage was - * reached, so that proper undo can be done if error occurs during - * initialization. - */ -typedef enum { - INIT_NONE, /* nothing is initialized yet */ - INIT_INODECACHE, /* inode cache created */ - INIT_CONTEXT_MGR, /* list of active contexts created */ - INIT_ZNODES, /* znode slab created */ - INIT_PLUGINS, /* plugins initialized */ - INIT_PLUGIN_SET, /* psets initialized */ - INIT_TXN, /* transaction manager initialized */ - INIT_FAKES, /* fake inode initialized */ - INIT_JNODES, /* jnode slab initialized */ - INIT_EFLUSH, /* emergency flush initialized */ - INIT_FQS, /* flush queues initialized */ - INIT_DENTRY_FSDATA, /* dentry_fsdata slab initialized */ - INIT_FILE_FSDATA, /* file_fsdata slab initialized */ - INIT_D_CURSOR, /* d_cursor suport initialized */ - INIT_FS_REGISTERED, /* reiser4 file system type registered */ -} reiser4_init_stage; - -static reiser4_init_stage init_stage; - -/* finish with reiser4: this is called either at shutdown or at module unload. */ -static void -shutdown_reiser4(void) -{ -#define DONE_IF( stage, exp ) \ - if( init_stage == ( stage ) ) { \ - exp; \ - -- init_stage; \ - } - - /* - * undo initializations already done by init_reiser4(). - */ - - DONE_IF(INIT_FS_REGISTERED, unregister_filesystem(&reiser4_fs_type)); - DONE_IF(INIT_D_CURSOR, d_cursor_done()); - DONE_IF(INIT_FILE_FSDATA, done_file_fsdata()); - DONE_IF(INIT_DENTRY_FSDATA, done_dentry_fsdata()); - DONE_IF(INIT_FQS, done_fqs()); - DONE_IF(INIT_EFLUSH, eflush_done()); - DONE_IF(INIT_JNODES, jnode_done_static()); - DONE_IF(INIT_FAKES,;); - DONE_IF(INIT_TXN, txnmgr_done_static()); - DONE_IF(INIT_PLUGIN_SET,plugin_set_done()); - DONE_IF(INIT_PLUGINS,;); - DONE_IF(INIT_ZNODES, znodes_done()); - DONE_IF(INIT_CONTEXT_MGR,;); - DONE_IF(INIT_INODECACHE, destroy_inodecache()); - assert("nikita-2516", init_stage == INIT_NONE); - -#undef DONE_IF -} - -/* initialize reiser4: this is called either at bootup or at module load. */ -static int __init -init_reiser4(void) -{ -#define CHECK_INIT_RESULT( exp ) \ -({ \ - result = exp; \ - if( result == 0 ) \ - ++ init_stage; \ - else { \ - shutdown_reiser4(); \ - return result; \ - } \ -}) - - int result; - /* - printk(KERN_INFO - "Loading Reiser4. " - "See www.namesys.com for a description of Reiser4.\n"); - */ - init_stage = INIT_NONE; - - CHECK_INIT_RESULT(init_inodecache()); - CHECK_INIT_RESULT(init_context_mgr()); - CHECK_INIT_RESULT(znodes_init()); - CHECK_INIT_RESULT(init_plugins()); - CHECK_INIT_RESULT(plugin_set_init()); - CHECK_INIT_RESULT(txnmgr_init_static()); - CHECK_INIT_RESULT(init_fakes()); - CHECK_INIT_RESULT(jnode_init_static()); - CHECK_INIT_RESULT(eflush_init()); - CHECK_INIT_RESULT(init_fqs()); - CHECK_INIT_RESULT(init_dentry_fsdata()); - CHECK_INIT_RESULT(init_file_fsdata()); - CHECK_INIT_RESULT(d_cursor_init()); - CHECK_INIT_RESULT(register_filesystem(&reiser4_fs_type)); - - assert("nikita-2515", init_stage == INIT_FS_REGISTERED); - return 0; -#undef CHECK_INIT_RESULT -} - -static void __exit -done_reiser4(void) -{ - shutdown_reiser4(); -} -reiser4_internal void reiser4_handle_error(void) +void reiser4_handle_error(void) { struct super_block *sb = reiser4_get_current_sb(); - if ( !sb ) + if (!sb) return; - reiser4_status_write(REISER4_STATUS_DAMAGED, 0, "Filesystem error occured"); - switch ( get_super_private(sb)->onerror ) { + reiser4_status_write(REISER4_STATUS_DAMAGED, 0, + "Filesystem error occured"); + switch (get_super_private(sb)->onerror) { case 0: reiser4_panic("foobar-42", "Filesystem error occured\n"); case 1: - if ( sb->s_flags & MS_RDONLY ) + default: + if (sb->s_flags & MS_RDONLY) return; sb->s_flags |= MS_RDONLY; break; - case 2: - kernel_restart(NULL); } } -module_init(init_reiser4); -module_exit(done_reiser4); - -MODULE_DESCRIPTION("Reiser4 filesystem"); -MODULE_AUTHOR("Hans Reiser "); - -MODULE_LICENSE("GPL"); - -/* description of the reiser4 file system type in the VFS eyes. */ -static struct file_system_type reiser4_fs_type = { - .owner = THIS_MODULE, - .name = "reiser4", - .fs_flags = FS_REQUIRES_DEV, - .get_sb = reiser4_get_sb, - .kill_sb = kill_block_super,/*reiser4_kill_super,*/ - .next = NULL -}; - -struct super_operations reiser4_super_operations = { - .alloc_inode = reiser4_alloc_inode, - .destroy_inode = reiser4_destroy_inode, - .read_inode = noop_read_inode, - .dirty_inode = NULL, - .write_inode = NULL, - .put_inode = reiser4_put_inode, - .drop_inode = NULL, - .delete_inode = reiser4_delete_inode, - .put_super = reiser4_put_super, - .write_super = reiser4_write_super, - .sync_fs = NULL, - .write_super_lockfs = NULL, - .unlockfs = NULL, - .statfs = reiser4_statfs, - .remount_fs = NULL, - .clear_inode = reiser4_clear_inode, - .umount_begin = NULL, - .sync_inodes = reiser4_sync_inodes, - .show_options = reiser4_show_options -}; - -/* - * Object serialization support. - * - * To support knfsd file system provides export_operations that are used to - * construct and interpret NFS file handles. As a generalization of this, - * reiser4 object plugins have serialization support: it provides methods to - * create on-wire representation of identity of reiser4 object, and - * re-create/locate object given its on-wire identity. - * - */ - -/* - * return number of bytes that on-wire representation of @inode's identity - * consumes. - */ -static int -encode_inode_size(struct inode *inode) -{ - assert("nikita-3514", inode != NULL); - assert("nikita-3515", inode_file_plugin(inode) != NULL); - assert("nikita-3516", inode_file_plugin(inode)->wire.size != NULL); - - return inode_file_plugin(inode)->wire.size(inode) + sizeof(d16); -} - -/* - * store on-wire representation of @inode's identity at the area beginning at - * @start. - */ -static char * -encode_inode(struct inode *inode, char *start) -{ - assert("nikita-3517", inode != NULL); - assert("nikita-3518", inode_file_plugin(inode) != NULL); - assert("nikita-3519", inode_file_plugin(inode)->wire.write != NULL); - - /* - * first, store two-byte identifier of object plugin, then - */ - save_plugin_id(file_plugin_to_plugin(inode_file_plugin(inode)), - (d16 *)start); - start += sizeof(d16); - /* - * call plugin to serialize object's identity - */ - return inode_file_plugin(inode)->wire.write(inode, start); -} - -/* - * Supported file-handle types - */ -typedef enum { - FH_WITH_PARENT = 0x10, /* file handle with parent */ - FH_WITHOUT_PARENT = 0x11 /* file handle without parent */ -} reiser4_fhtype; - -#define NFSERROR (255) - -/* this returns number of 32 bit long numbers encoded in @lenp. 255 is - * returned if file handle can not be stored */ -static int -reiser4_encode_fh(struct dentry *dentry, __u32 *data, int *lenp, int need_parent) -{ - struct inode *inode; - struct inode *parent; - char *addr; - int need; - int delta; - int result; - reiser4_context context; - - /* - * knfsd asks as to serialize object in @dentry, and, optionally its - * parent (if need_parent != 0). - * - * encode_inode() and encode_inode_size() is used to build - * representation of object and its parent. All hard work is done by - * object plugins. - */ - - inode = dentry->d_inode; - parent = dentry->d_parent->d_inode; - - addr = (char *)data; - - need = encode_inode_size(inode); - if (need < 0) - return NFSERROR; - if (need_parent) { - delta = encode_inode_size(parent); - if (delta < 0) - return NFSERROR; - need += delta; - } - - init_context(&context, dentry->d_inode->i_sb); - - if (need <= sizeof(__u32) * (*lenp)) { - addr = encode_inode(inode, addr); - if (need_parent) - addr = encode_inode(parent, addr); - - /* store in lenp number of 32bit words required for file - * handle. */ - *lenp = (need + sizeof(__u32) - 1) >> 2; - result = need_parent ? FH_WITH_PARENT : FH_WITHOUT_PARENT; - } else - /* no enough space in file handle */ - result = NFSERROR; - reiser4_exit_context(&context); - return result; -} - -/* - * read serialized object identity from @addr and store information about - * object in @obj. This is dual to encode_inode(). - */ -static char * -decode_inode(struct super_block *s, char *addr, reiser4_object_on_wire *obj) -{ - file_plugin *fplug; - - /* identifier of object plugin is stored in the first two bytes, - * followed by... */ - fplug = file_plugin_by_disk_id(get_tree(s), (d16 *)addr); - if (fplug != NULL) { - addr += sizeof(d16); - obj->plugin = fplug; - assert("nikita-3520", fplug->wire.read != NULL); - /* plugin specific encoding of object identity. */ - addr = fplug->wire.read(addr, obj); - } else - addr = ERR_PTR(RETERR(-EINVAL)); - return addr; -} - -/* initialize place-holder for object */ -static void -object_on_wire_init(reiser4_object_on_wire *o) -{ - o->plugin = NULL; -} - -/* finish with @o */ -static void -object_on_wire_done(reiser4_object_on_wire *o) -{ - if (o->plugin != NULL) - o->plugin->wire.done(o); -} - -/* decode knfsd file handle. This is dual to reiser4_encode_fh() */ -static struct dentry * -reiser4_decode_fh(struct super_block *s, __u32 *data, - int len, int fhtype, - int (*acceptable)(void *context, struct dentry *de), - void *context) -{ - reiser4_context ctx; - reiser4_object_on_wire object; - reiser4_object_on_wire parent; - char *addr; - int with_parent; - - init_context(&ctx, s); - - assert("vs-1482", - fhtype == FH_WITH_PARENT || fhtype == FH_WITHOUT_PARENT); - - with_parent = (fhtype == FH_WITH_PARENT); - - addr = (char *)data; - - object_on_wire_init(&object); - object_on_wire_init(&parent); - - addr = decode_inode(s, addr, &object); - if (!IS_ERR(addr)) { - if (with_parent) - addr = decode_inode(s, addr, &parent); - if (!IS_ERR(addr)) { - struct dentry *d; - typeof(s->s_export_op->find_exported_dentry) fn; - - fn = s->s_export_op->find_exported_dentry; - assert("nikita-3521", fn != NULL); - d = fn(s, &object, with_parent ? &parent : NULL, - acceptable, context); - if (d != NULL && !IS_ERR(d)) - /* FIXME check for -ENOMEM */ - reiser4_get_dentry_fsdata(d)->stateless = 1; - addr = (char *)d; - } - } - - object_on_wire_done(&object); - object_on_wire_done(&parent); - - reiser4_exit_context(&ctx); - return (void *)addr; -} - -static struct dentry * -reiser4_get_dentry(struct super_block *sb, void *data) -{ - reiser4_object_on_wire *o; - - assert("nikita-3522", sb != NULL); - assert("nikita-3523", data != NULL); - /* - * this is only supposed to be called by - * - * reiser4_decode_fh->find_exported_dentry - * - * so, reiser4_context should be here already. - * - */ - assert("nikita-3526", is_in_reiser4_context()); - - o = (reiser4_object_on_wire *)data; - assert("nikita-3524", o->plugin != NULL); - assert("nikita-3525", o->plugin->wire.get != NULL); - - return o->plugin->wire.get(sb, o); -} - -static struct dentry * -reiser4_get_dentry_parent(struct dentry *child) -{ - struct inode *dir; - dir_plugin *dplug; - - assert("nikita-3527", child != NULL); - /* see comment in reiser4_get_dentry() about following assertion */ - assert("nikita-3528", is_in_reiser4_context()); - - dir = child->d_inode; - assert("nikita-3529", dir != NULL); - dplug = inode_dir_plugin(dir); - assert("nikita-3531", ergo(dplug != NULL, dplug->get_parent != NULL)); - if (dplug != NULL) - return dplug->get_parent(dir); - else - return ERR_PTR(RETERR(-ENOTDIR)); -} - -struct export_operations reiser4_export_operations = { - .encode_fh = reiser4_encode_fh, - .decode_fh = reiser4_decode_fh, - .get_parent = reiser4_get_dentry_parent, - .get_dentry = reiser4_get_dentry -}; - struct dentry_operations reiser4_dentry_operations = { .d_revalidate = NULL, .d_hash = NULL, diff -puN fs/reiser4/vfs_ops.h~reiser4-big-update fs/reiser4/vfs_ops.h --- devel/fs/reiser4/vfs_ops.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/vfs_ops.h 2005-09-15 19:51:08.000000000 -0700 @@ -9,8 +9,6 @@ #include "forward.h" #include "coord.h" #include "seal.h" -#include "type_safe_list.h" -#include "plugin/dir/dir.h" #include "plugin/file/file.h" #include "super.h" #include "readahead.h" @@ -21,111 +19,30 @@ #include #include -extern int reiser4_mark_inode_dirty(struct inode *object); -extern int reiser4_update_sd(struct inode *object); +/* address space operations */ +int reiser4_writepage(struct page *, struct writeback_control *); +int reiser4_set_page_dirty(struct page *); +int reiser4_readpages(struct file *, struct address_space *, + struct list_head *pages, unsigned nr_pages); +int reiser4_invalidatepage(struct page *, unsigned long offset); +int reiser4_releasepage(struct page *, int gfp); + +extern int reiser4_update_sd(struct inode *); extern int reiser4_add_nlink(struct inode *, struct inode *, int); extern int reiser4_del_nlink(struct inode *, struct inode *, int); -extern struct file_operations reiser4_file_operations; -extern struct inode_operations reiser4_inode_operations; -extern struct inode_operations reiser4_symlink_inode_operations; -extern struct inode_operations reiser4_special_inode_operations; -extern struct super_operations reiser4_super_operations; -extern struct export_operations reiser4_export_operations; -extern struct address_space_operations reiser4_as_operations; -extern struct dentry_operations reiser4_dentry_operations; -extern int reiser4_invalidatepage(struct page *page, unsigned long offset); -extern int reiser4_releasepage(struct page *page, int gfp); -extern int reiser4_writepages(struct address_space *, struct writeback_control *wbc); + extern int reiser4_start_up_io(struct page *page); extern void reiser4_clear_page_dirty(struct page *); -extern void reiser4_throttle_write(struct inode*); +extern void reiser4_throttle_write(struct inode *); +ON_DEBUG(int jnode_is_releasable(jnode *)); #define CAPTURE_APAGE_BURST (1024l) void writeout(struct super_block *, struct writeback_control *); -/* - * this is used to speed up lookups for directory entry: on initial call to - * ->lookup() seal and coord of directory entry (if found, that is) are stored - * in struct dentry and reused later to avoid tree traversals. - */ -typedef struct de_location { - /* seal covering directory entry */ - seal_t entry_seal; - /* coord of directory entry */ - coord_t entry_coord; - /* ordinal number of directory entry among all entries with the same - key. (Starting from 0.) */ - int pos; -} de_location; - -/* &reiser4_dentry_fsdata - reiser4-specific data attached to dentries. - - This is allocated dynamically and released in d_op->d_release() - - Currently it only contains cached location (hint) of directory entry, but - it is expected that other information will be accumulated here. -*/ -typedef struct reiser4_dentry_fsdata { - /* here will go fields filled by ->lookup() to speedup next - create/unlink, like blocknr of znode with stat-data, or key - of stat-data. - */ - de_location dec; - int stateless; /* created through reiser4_decode_fh, needs special - * treatment in readdir. */ -} reiser4_dentry_fsdata; - -/* declare data types and manipulation functions for readdir list. */ -TYPE_SAFE_LIST_DECLARE(readdir); - -struct dir_cursor; - -/* &reiser4_dentry_fsdata - reiser4-specific data attached to files. - - This is allocated dynamically and released in reiser4_release() */ -struct reiser4_file_fsdata { - /* pointer back to the struct file which this reiser4_file_fsdata is - * part of */ - struct file *back; - /* detached cursor for stateless readdir. */ - struct dir_cursor *cursor; - /* We need both directory and regular file parts here, because there - are file system objects that are files and directories. */ - struct { - readdir_pos readdir; - readdir_list_link linkage; - } dir; - /* hints to speed up operations with regular files: read and write. */ - struct { - hint_t hint; - } reg; - /* */ - struct { - /* this is called by reiser4_readpages if set */ - void (*readpages)(struct address_space *, - struct list_head *pages, - void *data); - /* reiser4_readpaextended coord. It is set by read_extent before - calling page_cache_readahead */ - void *data; - } ra2; - struct reiser4_file_ra_state ra1; - -}; - -TYPE_SAFE_LIST_DEFINE(readdir, reiser4_file_fsdata, dir.linkage); - -extern reiser4_dentry_fsdata *reiser4_get_dentry_fsdata(struct dentry *dentry); -extern reiser4_file_fsdata *reiser4_get_file_fsdata(struct file *f); -extern void reiser4_free_dentry_fsdata(struct dentry *dentry); -extern void reiser4_free_file_fsdata(struct file *f); -extern void reiser4_free_fsdata(reiser4_file_fsdata *fsdata); - -extern reiser4_file_fsdata *create_fsdata(struct file *file, int gfp); extern void reiser4_handle_error(void); -extern int reiser4_parse_options (struct super_block *, char *); + /* __FS_REISER4_VFS_OPS_H__ */ #endif diff -puN fs/reiser4/wander.c~reiser4-big-update fs/reiser4/wander.c --- devel/fs/reiser4/wander.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/wander.c 2005-09-15 19:51:08.000000000 -0700 @@ -183,17 +183,18 @@ #include /* for struct bio */ #include -static int write_jnodes_to_disk_extent( - capture_list_head * head, jnode *, int, const reiser4_block_nr *, flush_queue_t *, int ); +static int write_jnodes_to_disk_extent(struct list_head *head, jnode *, int, + const reiser4_block_nr *, + flush_queue_t *, int); /* The commit_handle is a container for objects needed at atom commit time */ struct commit_handle { - /* A pointer to the list of OVRWR nodes */ - capture_list_head * overwrite_set; + /* A pointer to atom's list of OVRWR nodes */ + struct list_head *overwrite_set; /* atom's overwrite set size */ int overwrite_set_size; /* jnodes for wander record blocks */ - capture_list_head tx_list; + struct list_head tx_list; /* number of wander records */ int tx_size; /* 'committed' sb counters are saved here until atom is completely @@ -209,25 +210,22 @@ struct commit_handle { reiser4_block_nr nr_bitmap; }; -static void -init_commit_handle(struct commit_handle *ch, txn_atom * atom) +static void init_commit_handle(struct commit_handle *ch, txn_atom *atom) { - memset(ch, 0, sizeof (struct commit_handle)); - capture_list_init(&ch->tx_list); + memset(ch, 0, sizeof(struct commit_handle)); + INIT_LIST_HEAD(&ch->tx_list); ch->atom = atom; ch->super = reiser4_get_current_sb(); } -static void -done_commit_handle(struct commit_handle *ch UNUSED_ARG) +static void done_commit_handle(struct commit_handle *ch) { - assert("zam-690", capture_list_empty(&ch->tx_list)); + assert("zam-690", list_empty(&ch->tx_list)); } /* fill journal header block data */ -static void -format_journal_header(struct commit_handle *ch) +static void format_journal_header(struct commit_handle *ch) { struct reiser4_super_info_data *sbinfo; struct journal_header *header; @@ -237,11 +235,11 @@ format_journal_header(struct commit_hand assert("zam-479", sbinfo != NULL); assert("zam-480", sbinfo->journal_header != NULL); - txhead = capture_list_front(&ch->tx_list); + txhead = list_entry(ch->tx_list.next, jnode, capture_link); jload(sbinfo->journal_header); - header = (struct journal_header *) jdata(sbinfo->journal_header); + header = (struct journal_header *)jdata(sbinfo->journal_header); assert("zam-484", header != NULL); cputod64(*jnode_get_block(txhead), &header->last_committed_tx); @@ -250,24 +248,22 @@ format_journal_header(struct commit_hand } /* fill journal footer block data */ -static void -format_journal_footer(struct commit_handle *ch) +static void format_journal_footer(struct commit_handle *ch) { struct reiser4_super_info_data *sbinfo; struct journal_footer *footer; - jnode *tx_head; sbinfo = get_super_private(ch->super); - tx_head = capture_list_front(&ch->tx_list); + tx_head = list_entry(ch->tx_list.next, jnode, capture_link); assert("zam-493", sbinfo != NULL); assert("zam-494", sbinfo->journal_header != NULL); check_me("zam-691", jload(sbinfo->journal_footer) == 0); - footer = (struct journal_footer *) jdata(sbinfo->journal_footer); + footer = (struct journal_footer *)jdata(sbinfo->journal_footer); assert("zam-495", footer != NULL); cputod64(*jnode_get_block(tx_head), &footer->last_flushed_tx); @@ -280,37 +276,38 @@ format_journal_footer(struct commit_hand } /* wander record capacity depends on current block size */ -static int -wander_record_capacity(const struct super_block *super) +static int wander_record_capacity(const struct super_block *super) { - return (super->s_blocksize - sizeof (struct wander_record_header)) / sizeof (struct wander_entry); + return (super->s_blocksize - + sizeof(struct wander_record_header)) / + sizeof(struct wander_entry); } /* Fill first wander record (tx head) in accordance with supplied given data */ -static void -format_tx_head(struct commit_handle *ch) +static void format_tx_head(struct commit_handle *ch) { jnode *tx_head; jnode *next; struct tx_header *header; - tx_head = capture_list_front(&ch->tx_list); - assert("zam-692", !capture_list_end(&ch->tx_list, tx_head)); + tx_head = list_entry(ch->tx_list.next, jnode, capture_link); + assert("zam-692", &ch->tx_list != &tx_head->capture_link); - next = capture_list_next(tx_head); - if (capture_list_end(&ch->tx_list, next)) + next = list_entry(tx_head->capture_link.next, jnode, capture_link); + if (&ch->tx_list == &next->capture_link) next = tx_head; - header = (struct tx_header *) jdata(tx_head); + header = (struct tx_header *)jdata(tx_head); assert("zam-460", header != NULL); - assert("zam-462", ch->super->s_blocksize >= sizeof (struct tx_header)); + assert("zam-462", ch->super->s_blocksize >= sizeof(struct tx_header)); memset(jdata(tx_head), 0, (size_t) ch->super->s_blocksize); memcpy(jdata(tx_head), TX_HEADER_MAGIC, TX_HEADER_MAGIC_SIZE); cputod32((__u32) ch->tx_size, &header->total); - cputod64(get_super_private(ch->super)->last_committed_tx, &header->prev_tx); + cputod64(get_super_private(ch->super)->last_committed_tx, + &header->prev_tx); cputod64(*jnode_get_block(next), &header->next_block); cputod64(ch->free_blocks, &header->free_blocks); @@ -320,21 +317,22 @@ format_tx_head(struct commit_handle *ch) /* prepare ordinary wander record block (fill all service fields) */ static void -format_wander_record(struct commit_handle *ch, jnode * node, int serial) +format_wander_record(struct commit_handle *ch, jnode *node, int serial) { struct wander_record_header *LRH; jnode *next; assert("zam-464", node != NULL); - LRH = (struct wander_record_header *) jdata(node); - next = capture_list_next(node); + LRH = (struct wander_record_header *)jdata(node); + next = list_entry(node->capture_link.next, jnode, capture_link); - if (capture_list_end(&ch->tx_list, next)) - next = capture_list_front(&ch->tx_list); + if (&ch->tx_list == &next->capture_link) + next = list_entry(ch->tx_list.next, jnode, capture_link); assert("zam-465", LRH != NULL); - assert("zam-463", ch->super->s_blocksize > sizeof (struct wander_record_header)); + assert("zam-463", + ch->super->s_blocksize > sizeof(struct wander_record_header)); memset(jdata(node), 0, (size_t) ch->super->s_blocksize); memcpy(jdata(node), WANDER_RECORD_MAGIC, WANDER_RECORD_MAGIC_SIZE); @@ -346,7 +344,8 @@ format_wander_record(struct commit_handl /* add one wandered map entry to formatted wander record */ static void -store_entry(jnode * node, int index, const reiser4_block_nr * a, const reiser4_block_nr * b) +store_entry(jnode * node, int index, const reiser4_block_nr * a, + const reiser4_block_nr * b) { char *data; struct wander_entry *pairs; @@ -354,7 +353,8 @@ store_entry(jnode * node, int index, con data = jdata(node); assert("zam-451", data != NULL); - pairs = (struct wander_entry *) (data + sizeof (struct wander_record_header)); + pairs = + (struct wander_entry *)(data + sizeof(struct wander_record_header)); cputod64(*a, &pairs[index].original); cputod64(*b, &pairs[index].wandered); @@ -362,8 +362,7 @@ store_entry(jnode * node, int index, con /* currently, wander records contains contain only wandered map, which depend on overwrite set size */ -static void -get_tx_size(struct commit_handle *ch) +static void get_tx_size(struct commit_handle *ch) { assert("zam-440", ch->overwrite_set_size != 0); assert("zam-695", ch->tx_size == 0); @@ -371,7 +370,9 @@ get_tx_size(struct commit_handle *ch) /* count all ordinary wander records ( - 1) / + 1 and add one for tx head block */ - ch->tx_size = (ch->overwrite_set_size - 1) / wander_record_capacity(ch->super) + 2; + ch->tx_size = + (ch->overwrite_set_size - 1) / wander_record_capacity(ch->super) + + 2; } /* A special structure for using in store_wmap_actor() for saving its state @@ -382,21 +383,23 @@ struct store_wmap_params { int capacity; /* capacity */ #if REISER4_DEBUG - capture_list_head *tx_list; + struct list_head *tx_list; #endif }; /* an actor for use in blocknr_set_iterator routine which populates the list of pre-formatted wander records by wandered map info */ static int -store_wmap_actor(txn_atom * atom UNUSED_ARG, const reiser4_block_nr * a, const reiser4_block_nr * b, void *data) +store_wmap_actor(txn_atom * atom UNUSED_ARG, const reiser4_block_nr * a, + const reiser4_block_nr * b, void *data) { struct store_wmap_params *params = data; if (params->idx >= params->capacity) { /* a new wander record should be taken from the tx_list */ - params->cur = capture_list_next(params->cur); - assert("zam-454", !capture_list_end(params->tx_list, params->cur)); + params->cur = list_entry(params->cur->capture_link.next, jnode, capture_link); + assert("zam-454", + params->tx_list != ¶ms->cur->capture_link); params->idx = 0; } @@ -411,25 +414,22 @@ store_wmap_actor(txn_atom * atom UNUSED_ set is written to wandered locations and all wander records are written also. Updated journal header blocks contains a pointer (block number) to first wander record of the just written transaction */ -static int -update_journal_header(struct commit_handle *ch) +static int update_journal_header(struct commit_handle *ch) { struct reiser4_super_info_data *sbinfo = get_super_private(ch->super); - jnode *jh = sbinfo->journal_header; - jnode *head = capture_list_front(&ch->tx_list); - + jnode *head = list_entry(ch->tx_list.next, jnode, capture_link); int ret; format_journal_header(ch); - ret = write_jnodes_to_disk_extent(&ch->tx_list, jh, 1, jnode_get_block(jh), NULL, 0); - + ret = write_jnodes_to_disk_extent(&ch->tx_list, jh, 1, + jnode_get_block(jh), NULL, 0); if (ret) return ret; blk_run_address_space(sbinfo->fake->i_mapping); - /*blk_run_queues();*/ + /*blk_run_queues(); */ ret = jwait_io(jh, WRITE); @@ -444,8 +444,7 @@ update_journal_header(struct commit_hand /* This function is called after write-back is finished. We update journal footer block and free blocks which were occupied by wandered blocks and transaction wander records */ -static int -update_journal_footer(struct commit_handle *ch) +static int update_journal_footer(struct commit_handle *ch) { reiser4_super_info_data *sbinfo = get_super_private(ch->super); @@ -455,12 +454,14 @@ update_journal_footer(struct commit_hand format_journal_footer(ch); - ret = write_jnodes_to_disk_extent(&ch->tx_list, jf, 1, jnode_get_block(jf), NULL, 0); + ret = + write_jnodes_to_disk_extent(&ch->tx_list, jf, 1, + jnode_get_block(jf), NULL, 0); if (ret) return ret; blk_run_address_space(sbinfo->fake->i_mapping); - /*blk_run_queue();*/ + /*blk_run_queue(); */ ret = jwait_io(jf, WRITE); if (ret) @@ -470,14 +471,14 @@ update_journal_footer(struct commit_hand } /* free block numbers of wander records of already written in place transaction */ -static void -dealloc_tx_list(struct commit_handle *ch) +static void dealloc_tx_list(struct commit_handle *ch) { - while (!capture_list_empty(&ch->tx_list)) { - jnode *cur = capture_list_pop_front(&ch->tx_list); - - ON_DEBUG(capture_list_clean(cur)); - reiser4_dealloc_block(jnode_get_block(cur), BLOCK_NOT_COUNTED, BA_FORMATTED); + while (!list_empty(&ch->tx_list)) { + jnode *cur = list_entry(ch->tx_list.next, jnode, capture_link); + list_del(&cur->capture_link); + ON_DEBUG(INIT_LIST_HEAD(&cur->capture_link)); + reiser4_dealloc_block(jnode_get_block(cur), BLOCK_NOT_COUNTED, + BA_FORMATTED); unpin_jnode_data(cur); drop_io_head(cur); @@ -488,7 +489,8 @@ dealloc_tx_list(struct commit_handle *ch from atom's overwrite set. */ static int dealloc_wmap_actor(txn_atom * atom UNUSED_ARG, - const reiser4_block_nr * a UNUSED_ARG, const reiser4_block_nr * b, void *data UNUSED_ARG) + const reiser4_block_nr * a UNUSED_ARG, + const reiser4_block_nr * b, void *data UNUSED_ARG) { assert("zam-499", b != NULL); @@ -500,12 +502,12 @@ dealloc_wmap_actor(txn_atom * atom UNUSE } /* free wandered block locations of already written in place transaction */ -static void -dealloc_wmap(struct commit_handle *ch) +static void dealloc_wmap(struct commit_handle *ch) { assert("zam-696", ch->atom != NULL); - blocknr_set_iterator(ch->atom, &ch->atom->wandered_map, dealloc_wmap_actor, NULL, 1); + blocknr_set_iterator(ch->atom, &ch->atom->wandered_map, + dealloc_wmap_actor, NULL, 1); } /* helper function for alloc wandered blocks, which refill set of block @@ -526,9 +528,9 @@ get_more_wandered_blocks(int count, reis hint.block_stage = BLOCK_GRABBED; ret = reiser4_alloc_blocks(&hint, start, &wide_len, - BA_FORMATTED | BA_USE_DEFAULT_SEARCH_START); + BA_FORMATTED | BA_USE_DEFAULT_SEARCH_START); - *len = (int) wide_len; + *len = (int)wide_len; return ret; } @@ -536,8 +538,7 @@ get_more_wandered_blocks(int count, reis /* * roll back changes made before issuing BIO in the case of IO error. */ -static void -undo_bio(struct bio *bio) +static void undo_bio(struct bio *bio) { int i; @@ -561,9 +562,9 @@ undo_bio(struct bio *bio) extern spinlock_t scan_lock; /* put overwrite set back to atom's clean list */ -static void put_overwrite_set(struct commit_handle * ch) +static void put_overwrite_set(struct commit_handle *ch) { - jnode * cur; + jnode *cur; spin_lock(&scan_lock); cur = capture_list_front(ch->overwrite_set); @@ -584,8 +585,7 @@ static void put_overwrite_set(struct com Since we have a separate list for atom's overwrite set we just scan the list, count bitmap and other not leaf nodes which wandered blocks allocation we have to grab space for. */ -static int -get_overwrite_set(struct commit_handle *ch) +static int get_overwrite_set(struct commit_handle *ch) { int ret; jnode *cur; @@ -595,7 +595,6 @@ get_overwrite_set(struct commit_handle * __u64 nr_unformatted_leaves = 0; #endif - assert("zam-697", ch->overwrite_set_size == 0); ch->overwrite_set = ATOM_OVRWR_LIST(ch->atom); @@ -615,15 +614,17 @@ get_overwrite_set(struct commit_handle * spin_unlock(&scan_lock); if (jnode_is_znode(cur) && znode_above_root(JZNODE(cur))) { - ON_TRACE(TRACE_LOG, "fake znode found , WANDER=(%d)\n", JF_ISSET(cur, JNODE_OVRWR)); + ON_TRACE(TRACE_LOG, "fake znode found , WANDER=(%d)\n", + JF_ISSET(cur, JNODE_OVRWR)); } /* Count bitmap locks for getting correct statistics what number * of blocks were cleared by the transaction commit. */ if (jnode_get_type(cur) == JNODE_BITMAP) - ch->nr_bitmap ++; + ch->nr_bitmap++; - assert("zam-939", JF_ISSET(cur, JNODE_OVRWR) || jnode_get_type(cur) == JNODE_BITMAP); + assert("zam-939", JF_ISSET(cur, JNODE_OVRWR) + || jnode_get_type(cur) == JNODE_BITMAP); if (jnode_is_znode(cur) && znode_above_root(JZNODE(cur))) { /* we replace fake znode by another (real) @@ -635,7 +636,8 @@ get_overwrite_set(struct commit_handle * disk_layout. */ struct super_block *s = reiser4_get_current_sb(); - reiser4_super_info_data *sbinfo = get_current_super_private(); + reiser4_super_info_data *sbinfo = + get_current_super_private(); if (sbinfo->df_plug->log_super) { jnode *sj = sbinfo->df_plug->log_super(s); @@ -666,13 +668,15 @@ get_overwrite_set(struct commit_handle * spin_lock(&scan_lock); JF_CLR(cur, JNODE_SCANNED); cur = next; - nr_not_leaves ++; + nr_not_leaves++; } else { int ret; ch->overwrite_set_size++; ret = jload_gfp(cur, GFP_KERNEL, 0); if (ret) - reiser4_panic("zam-783", "cannot load e-flushed jnode back (ret = %d)\n", ret); + reiser4_panic("zam-783", + "cannot load e-flushed jnode back (ret = %d)\n", + ret); /* Count not leaves here because we have to grab disk * space for wandered blocks. They were not counted as @@ -681,7 +685,7 @@ get_overwrite_set(struct commit_handle * * flush. Counting should be done _after_ nodes are * pinned * into memory by jload(). */ if (!jnode_is_leaf(cur)) - nr_not_leaves ++; + nr_not_leaves++; /* this is to check atom's flush reserved space for * overwritten leaves */ else { @@ -691,9 +695,9 @@ get_overwrite_set(struct commit_handle * * eflushed. Locking is not strong enough to * write an assertion checking for this. */ if (jnode_is_znode(cur)) - nr_formatted_leaves ++; + nr_formatted_leaves++; else - nr_unformatted_leaves ++; + nr_unformatted_leaves++; #endif JF_CLR(cur, JNODE_FLUSH_RESERVED); } @@ -716,7 +720,9 @@ get_overwrite_set(struct commit_handle * /* Disk space for allocation of wandered blocks of leaf nodes already * reserved as "flush reserved", move it to grabbed space counter. */ spin_lock_atom(ch->atom); - assert("zam-940", nr_formatted_leaves + nr_unformatted_leaves <= ch->atom->flush_reserved); + assert("zam-940", + nr_formatted_leaves + nr_unformatted_leaves <= + ch->atom->flush_reserved); flush_reserved2grabbed(ch->atom, ch->atom->flush_reserved); spin_unlock_atom(ch->atom); @@ -737,7 +743,8 @@ Why that layer needed? Why BIOs cannot b */ static int write_jnodes_to_disk_extent(capture_list_head * head, jnode * first, int nr, - const reiser4_block_nr * block_p, flush_queue_t * fq, int flags) + const reiser4_block_nr * block_p, + flush_queue_t * fq, int flags) { struct super_block *super = reiser4_get_current_sb(); int for_reclaim = flags & WRITEOUT_FOR_PAGE_RECLAIM; @@ -751,10 +758,13 @@ write_jnodes_to_disk_extent(capture_list block = *block_p; - ON_TRACE (TRACE_IO_W, "write of %d blocks starting from %llu\n", - nr, (unsigned long long)block); + ON_TRACE(TRACE_IO_W, "write of %d blocks starting from %llu\n", + nr, (unsigned long long)block); - max_blocks = bdev_get_queue(super->s_bdev)->max_sectors >> (super->s_blocksize_bits - 9); + max_blocks = + bdev_get_queue(super->s_bdev)->max_sectors >> (super-> + s_blocksize_bits - + 9); while (nr > 0) { struct bio *bio; @@ -770,9 +780,11 @@ write_jnodes_to_disk_extent(capture_list bio->bi_sector = block * (super->s_blocksize >> 9); for (nr_used = 0, i = 0; i < nr_blocks; i++) { struct page *pg; - ON_DEBUG(int jnode_is_releasable(jnode *)); - assert("vs-1423", ergo(jnode_is_znode(cur) || jnode_is_unformatted(cur), JF_ISSET(cur, JNODE_SCANNED))); + assert("vs-1423", + ergo(jnode_is_znode(cur) + || jnode_is_unformatted(cur), JF_ISSET(cur, + JNODE_SCANNED))); pg = jnode_page(cur); assert("zam-573", pg != NULL); @@ -785,9 +797,11 @@ write_jnodes_to_disk_extent(capture_list assert("nikita-3554", jprivate(pg) == cur); assert("nikita-3166", - ergo(!JF_ISSET(cur, JNODE_CC), pg->mapping == jnode_get_mapping(cur))); + ergo(!JF_ISSET(cur, JNODE_CC), + pg->mapping == jnode_get_mapping(cur))); if (!JF_ISSET(cur, JNODE_WRITEBACK)) { - assert("nikita-3165", !jnode_is_releasable(cur)); + assert("nikita-3165", + !jnode_is_releasable(cur)); UNLOCK_JNODE(cur); if (!bio_add_page(bio, pg, super->s_blocksize, 0)) { @@ -803,7 +817,7 @@ write_jnodes_to_disk_extent(capture_list LOCK_JNODE(cur); JF_SET(cur, JNODE_WRITEBACK); JF_CLR(cur, JNODE_DIRTY); - ON_DEBUG(cur->written ++); + ON_DEBUG(cur->written++); UNLOCK_JNODE(cur); SetPageWriteback(pg); @@ -823,7 +837,7 @@ write_jnodes_to_disk_extent(capture_list spin_unlock(&pg->mapping->page_lock); - nr_used ++; + nr_used++; } else { /* jnode being WRITEBACK might be replaced on ovrwr_nodes list with jnode CC. We just @@ -834,7 +848,7 @@ write_jnodes_to_disk_extent(capture_list } unlock_page(pg); - nr --; + nr--; cur = capture_list_next(cur); } if (nr_used > 0) { @@ -851,7 +865,7 @@ write_jnodes_to_disk_extent(capture_list } block += nr_used - 1; - update_blocknr_hint_default (super, &block); + update_blocknr_hint_default(super, &block); block += 1; } else { reiser4_stat_inc(txnmgr.empty_bio); @@ -863,20 +877,18 @@ write_jnodes_to_disk_extent(capture_list /* @nr jnodes starting from @j are marked as JNODE_SCANNED. Clear this bit for all those jnodes */ -static void -unscan_sequence_nolock(jnode *j, int nr) +static void unscan_sequence_nolock(jnode * j, int nr) { int i; - for (i = 0; i < nr; i ++) { + for (i = 0; i < nr; i++) { assert("vs-1631", JF_ISSET(j, JNODE_SCANNED)); JF_CLR(j, JNODE_SCANNED); j = capture_list_next(j); } } -static void -unscan_sequence(jnode *j, int nr) +static void unscan_sequence(jnode * j, int nr) { spin_lock(&scan_lock); unscan_sequence_nolock(j, nr); @@ -886,8 +898,9 @@ unscan_sequence(jnode *j, int nr) /* This is a procedure which recovers a contiguous sequences of disk block numbers in the given list of j-nodes and submits write requests on this per-sequence basis */ -reiser4_internal int -write_jnode_list(capture_list_head *head, flush_queue_t *fq, long *nr_submitted, int flags) +int +write_jnode_list(capture_list_head * head, flush_queue_t * fq, + long *nr_submitted, int flags) { int ret; jnode *beg, *end; @@ -908,13 +921,16 @@ write_jnode_list(capture_list_head *head break; JF_SET(cur, JNODE_SCANNED); - ++ nr; + ++nr; end = cur; cur = capture_list_next(cur); } spin_unlock(&scan_lock); - ret = write_jnodes_to_disk_extent(head, beg, nr, jnode_get_block(beg), fq, flags); + ret = + write_jnodes_to_disk_extent(head, beg, nr, + jnode_get_block(beg), fq, + flags); if (ret) { unscan_sequence(beg, nr); return ret; @@ -952,8 +968,12 @@ add_region_to_wmap(jnode * cur, int len, do { atom = get_current_atom_locked(); - assert("zam-536", !blocknr_is_fake(jnode_get_block(cur))); - ret = blocknr_set_add_pair(atom, &atom->wandered_map, &new_bsep, jnode_get_block(cur), &block); + assert("zam-536", + !blocknr_is_fake(jnode_get_block(cur))); + ret = + blocknr_set_add_pair(atom, &atom->wandered_map, + &new_bsep, + jnode_get_block(cur), &block); } while (ret == -E_REPEAT); if (ret) { @@ -961,8 +981,10 @@ add_region_to_wmap(jnode * cur, int len, map */ reiser4_block_nr wide_len = len; - reiser4_dealloc_blocks(&block, &wide_len, BLOCK_NOT_COUNTED, - BA_FORMATTED/* formatted, without defer */); + reiser4_dealloc_blocks(&block, &wide_len, + BLOCK_NOT_COUNTED, + BA_FORMATTED + /* formatted, without defer */ ); return ret; } @@ -980,8 +1002,7 @@ add_region_to_wmap(jnode * cur, int len, /* Allocate wandered blocks for current atom's OVERWRITE SET and immediately submit IO for allocated blocks. We assume that current atom is in a stage when any atom fusion is impossible and atom is unlocked and it is safe. */ -static int -alloc_wandered_blocks(struct commit_handle *ch, flush_queue_t * fq) +static int alloc_wandered_blocks(struct commit_handle *ch, flush_queue_t * fq) { reiser4_block_nr block; @@ -1012,8 +1033,9 @@ alloc_wandered_blocks(struct commit_hand beg = cur; /* mark @len jnodes starting from @cur as scanned */ - for (i = 0; i < len; i ++) { - assert("vs-1633", !capture_list_end(ch->overwrite_set, cur)); + for (i = 0; i < len; i++) { + assert("vs-1633", + !capture_list_end(ch->overwrite_set, cur)); assert("vs-1632", !JF_ISSET(cur, JNODE_SCANNED)); JF_SET(cur, JNODE_SCANNED); end = cur; @@ -1027,7 +1049,9 @@ alloc_wandered_blocks(struct commit_hand unscan_sequence(beg, len); return ret; } - ret = write_jnodes_to_disk_extent(ch->overwrite_set, beg, len, &block, fq, 0); + ret = + write_jnodes_to_disk_extent(ch->overwrite_set, beg, len, + &block, fq, 0); if (ret) { unscan_sequence(beg, len); return ret; @@ -1044,23 +1068,25 @@ alloc_wandered_blocks(struct commit_hand return 0; } -#else /* !REISER4_COPY_ON_CAPTURE */ +#else /* !REISER4_COPY_ON_CAPTURE */ /* put overwrite set back to atom's clean list */ -static void put_overwrite_set(struct commit_handle * ch) +static void put_overwrite_set(struct commit_handle *ch) { - jnode * cur; + jnode *cur; + struct list_head *pos; - for_all_type_safe_list(capture, ch->overwrite_set, cur) + list_for_each(pos, ch->overwrite_set) { + cur = list_entry(pos, jnode, capture_link); jrelse_tail(cur); + } } /* Count overwrite set size, grab disk space for wandered blocks allocation. Since we have a separate list for atom's overwrite set we just scan the list, count bitmap and other not leaf nodes which wandered blocks allocation we have to grab space for. */ -static int -get_overwrite_set(struct commit_handle *ch) +static int get_overwrite_set(struct commit_handle *ch) { int ret; jnode *cur; @@ -1070,21 +1096,21 @@ get_overwrite_set(struct commit_handle * __u64 nr_unformatted_leaves = 0; #endif - assert("zam-697", ch->overwrite_set_size == 0); ch->overwrite_set = ATOM_OVRWR_LIST(ch->atom); - cur = capture_list_front(ch->overwrite_set); + cur = list_entry(ch->overwrite_set->next, jnode, capture_link); - while (!capture_list_end(ch->overwrite_set, cur)) { - jnode *next = capture_list_next(cur); + while (ch->overwrite_set != &cur->capture_link) { + jnode *next = list_entry(cur->capture_link.next, jnode, capture_link); /* Count bitmap locks for getting correct statistics what number * of blocks were cleared by the transaction commit. */ if (jnode_get_type(cur) == JNODE_BITMAP) - ch->nr_bitmap ++; + ch->nr_bitmap++; - assert("zam-939", JF_ISSET(cur, JNODE_OVRWR) || jnode_get_type(cur) == JNODE_BITMAP); + assert("zam-939", JF_ISSET(cur, JNODE_OVRWR) + || jnode_get_type(cur) == JNODE_BITMAP); if (jnode_is_znode(cur) && znode_above_root(JZNODE(cur))) { /* we replace fake znode by another (real) @@ -1096,7 +1122,8 @@ get_overwrite_set(struct commit_handle * disk_layout. */ struct super_block *s = reiser4_get_current_sb(); - reiser4_super_info_data *sbinfo = get_current_super_private(); + reiser4_super_info_data *sbinfo = + get_current_super_private(); if (sbinfo->df_plug->log_super) { jnode *sj = sbinfo->df_plug->log_super(s); @@ -1125,7 +1152,9 @@ get_overwrite_set(struct commit_handle * ch->overwrite_set_size++; ret = jload_gfp(cur, GFP_KERNEL, 0); if (ret) - reiser4_panic("zam-783", "cannot load e-flushed jnode back (ret = %d)\n", ret); + reiser4_panic("zam-783", + "cannot load e-flushed jnode back (ret = %d)\n", + ret); } /* Count not leaves here because we have to grab disk space @@ -1133,16 +1162,16 @@ get_overwrite_set(struct commit_handle * * reserved". Counting should be done _after_ nodes are pinned * into memory by jload(). */ if (!jnode_is_leaf(cur)) - nr_not_leaves ++; + nr_not_leaves++; else { #if REISER4_DEBUG /* at this point @cur either has JNODE_FLUSH_RESERVED * or is eflushed. Locking is not strong enough to * write an assertion checking for this. */ if (jnode_is_znode(cur)) - nr_formatted_leaves ++; + nr_formatted_leaves++; else - nr_unformatted_leaves ++; + nr_unformatted_leaves++; #endif JF_CLR(cur, JNODE_FLUSH_RESERVED); } @@ -1159,25 +1188,42 @@ get_overwrite_set(struct commit_handle * /* Disk space for allocation of wandered blocks of leaf nodes already * reserved as "flush reserved", move it to grabbed space counter. */ spin_lock_atom(ch->atom); - assert("zam-940", nr_formatted_leaves + nr_unformatted_leaves <= ch->atom->flush_reserved); + assert("zam-940", + nr_formatted_leaves + nr_unformatted_leaves <= + ch->atom->flush_reserved); flush_reserved2grabbed(ch->atom, ch->atom->flush_reserved); spin_unlock_atom(ch->atom); return ch->overwrite_set_size; } -/* Submit a write request for @nr jnodes beginning from the @first, other jnodes - are after the @first on the double-linked "capture" list. All jnodes will be - written to the disk region of @nr blocks starting with @block_p block number. - If @fq is not NULL it means that waiting for i/o completion will be done more - efficiently by using flush_queue_t objects. - - This function is the one which writes list of jnodes in batch mode. It does - all low-level things as bio construction and page states manipulation. -*/ +/** + * write_jnodes_to_disk_extent - submit write request + * @head: + * @first: first jnode of the list + * @nr: number of jnodes on the list + * @block_p: + * @fq: + * @flags: used to decide whether page is to get PG_reclaim flag + * + * Submits a write request for @nr jnodes beginning from the @first, other + * jnodes are after the @first on the double-linked "capture" list. All jnodes + * will be written to the disk region of @nr blocks starting with @block_p block + * number. If @fq is not NULL it means that waiting for i/o completion will be + * done more efficiently by using flush_queue_t objects. + * This function is the one which writes list of jnodes in batch mode. It does + * all low-level things as bio construction and page states manipulation. + * + * ZAM-FIXME-HANS: brief me on why this function exists, and why bios are + * aggregated in this function instead of being left to the layers below + * + * FIXME: ZAM->HANS: What layer are you talking about? Can you point me to that? + * Why that layer needed? Why BIOs cannot be constructed here? + */ static int -write_jnodes_to_disk_extent(capture_list_head * head, jnode * first, int nr, - const reiser4_block_nr * block_p, flush_queue_t * fq, int flags) +write_jnodes_to_disk_extent(struct list_head *head, jnode *first, int nr, + const reiser4_block_nr *block_p, + flush_queue_t *fq, int flags) { struct super_block *super = reiser4_get_current_sb(); int for_reclaim = flags & WRITEOUT_FOR_PAGE_RECLAIM; @@ -1190,7 +1236,10 @@ write_jnodes_to_disk_extent(capture_list assert("zam-570", nr > 0); block = *block_p; - max_blocks = bdev_get_queue(super->s_bdev)->max_sectors >> (super->s_blocksize_bits - 9); + max_blocks = + bdev_get_queue(super->s_bdev)->max_sectors >> (super-> + s_blocksize_bits - + 9); while (nr > 0) { struct bio *bio; @@ -1226,24 +1275,25 @@ write_jnodes_to_disk_extent(capture_list } LOCK_JNODE(cur); - assert("nikita-3166", pg->mapping == jnode_get_mapping(cur)); + assert("nikita-3166", + pg->mapping == jnode_get_mapping(cur)); assert("zam-912", !JF_ISSET(cur, JNODE_WRITEBACK)); assert("nikita-3165", !jnode_is_releasable(cur)); JF_SET(cur, JNODE_WRITEBACK); JF_CLR(cur, JNODE_DIRTY); - ON_DEBUG(cur->written ++); + ON_DEBUG(cur->written++); UNLOCK_JNODE(cur); set_page_writeback(pg); - if (for_reclaim) + if (for_reclaim) ent_writes_page(super, pg); /* clear DIRTY or REISER4_MOVED tag if it is set */ reiser4_clear_page_dirty(pg); unlock_page(pg); - cur = capture_list_next(cur); - nr_used ++; + cur = list_entry(cur->capture_link.next, jnode, capture_link); + nr_used++; } if (nr_used > 0) { assert("nikita-3453", @@ -1259,7 +1309,7 @@ write_jnodes_to_disk_extent(capture_list } block += nr_used - 1; - update_blocknr_hint_default (super, &block); + update_blocknr_hint_default(super, &block); block += 1; } else { bio_put(bio); @@ -1273,24 +1323,28 @@ write_jnodes_to_disk_extent(capture_list /* This is a procedure which recovers a contiguous sequences of disk block numbers in the given list of j-nodes and submits write requests on this per-sequence basis */ -reiser4_internal int -write_jnode_list (capture_list_head * head, flush_queue_t * fq, long *nr_submitted, int flags) +int +write_jnode_list(struct list_head *head, flush_queue_t *fq, + long *nr_submitted, int flags) { int ret; - jnode *beg = capture_list_front(head); + jnode *beg = list_entry(head->next, jnode, capture_link); - while (!capture_list_end(head, beg)) { + while (head != &beg->capture_link) { int nr = 1; - jnode *cur = capture_list_next(beg); + jnode *cur = list_entry(beg->capture_link.next, jnode, capture_link); - while (!capture_list_end(head, cur)) { + while (head != &cur->capture_link) { if (*jnode_get_block(cur) != *jnode_get_block(beg) + nr) break; ++nr; - cur = capture_list_next(cur); + cur = list_entry(cur->capture_link.next, jnode, capture_link); } - ret = write_jnodes_to_disk_extent(head, beg, nr, jnode_get_block(beg), fq, flags); + ret = + write_jnodes_to_disk_extent(head, beg, nr, + jnode_get_block(beg), fq, + flags); if (ret) return ret; @@ -1320,8 +1374,12 @@ add_region_to_wmap(jnode * cur, int len, while ((len--) > 0) { do { atom = get_current_atom_locked(); - assert("zam-536", !blocknr_is_fake(jnode_get_block(cur))); - ret = blocknr_set_add_pair(atom, &atom->wandered_map, &new_bsep, jnode_get_block(cur), &block); + assert("zam-536", + !blocknr_is_fake(jnode_get_block(cur))); + ret = + blocknr_set_add_pair(atom, &atom->wandered_map, + &new_bsep, + jnode_get_block(cur), &block); } while (ret == -E_REPEAT); if (ret) { @@ -1329,15 +1387,17 @@ add_region_to_wmap(jnode * cur, int len, map */ reiser4_block_nr wide_len = len; - reiser4_dealloc_blocks(&block, &wide_len, BLOCK_NOT_COUNTED, - BA_FORMATTED/* formatted, without defer */); + reiser4_dealloc_blocks(&block, &wide_len, + BLOCK_NOT_COUNTED, + BA_FORMATTED + /* formatted, without defer */ ); return ret; } UNLOCK_ATOM(atom); - cur = capture_list_next(cur); + cur = list_entry(cur->capture_link.next, jnode, capture_link); ++block; } @@ -1347,8 +1407,7 @@ add_region_to_wmap(jnode * cur, int len, /* Allocate wandered blocks for current atom's OVERWRITE SET and immediately submit IO for allocated blocks. We assume that current atom is in a stage when any atom fusion is impossible and atom is unlocked and it is safe. */ -static int -alloc_wandered_blocks(struct commit_handle *ch, flush_queue_t * fq) +static int alloc_wandered_blocks(struct commit_handle *ch, flush_queue_t *fq) { reiser4_block_nr block; @@ -1362,8 +1421,8 @@ alloc_wandered_blocks(struct commit_hand rest = ch->overwrite_set_size; - cur = capture_list_front(ch->overwrite_set); - while (!capture_list_end(ch->overwrite_set, cur)) { + cur = list_entry(ch->overwrite_set->next, jnode, capture_link); + while (ch->overwrite_set != &cur->capture_link) { assert("zam-567", JF_ISSET(cur, JNODE_OVRWR)); ret = get_more_wandered_blocks(rest, &block, &len); @@ -1376,39 +1435,38 @@ alloc_wandered_blocks(struct commit_hand if (ret) return ret; - ret = write_jnodes_to_disk_extent(ch->overwrite_set, cur, len, &block, fq, 0); + ret = write_jnodes_to_disk_extent(ch->overwrite_set, cur, len, + &block, fq, 0); if (ret) return ret; while ((len--) > 0) { - assert("zam-604", !capture_list_end(ch->overwrite_set, cur)); - cur = capture_list_next(cur); + assert("zam-604", + ch->overwrite_set != &cur->capture_link); + cur = list_entry(cur->capture_link.next, jnode, capture_link); } } return 0; } -#endif /* ! REISER4_COPY_ON_CAPTURE */ +#endif /* ! REISER4_COPY_ON_CAPTURE */ /* allocate given number of nodes over the journal area and link them into a list, return pointer to the first jnode in the list */ -static int -alloc_tx(struct commit_handle *ch, flush_queue_t * fq) +static int alloc_tx(struct commit_handle *ch, flush_queue_t * fq) { reiser4_blocknr_hint hint; - reiser4_block_nr allocated = 0; reiser4_block_nr first, len; - jnode *cur; jnode *txhead; int ret; assert("zam-698", ch->tx_size > 0); - assert("zam-699", capture_list_empty(&ch->tx_list)); + assert("zam-699", list_empty_careful(&ch->tx_list)); - while (allocated < (unsigned) ch->tx_size) { + while (allocated < (unsigned)ch->tx_size) { len = (ch->tx_size - allocated); blocknr_hint_init(&hint); @@ -1420,8 +1478,9 @@ alloc_tx(struct commit_handle *ch, flush /* We assume that disk space for wandered record blocks can be * taken from reserved area. */ - ret = reiser4_alloc_blocks (&hint, &first, &len, - BA_FORMATTED | BA_RESERVED | BA_USE_DEFAULT_SEARCH_START); + ret = reiser4_alloc_blocks(&hint, &first, &len, + BA_FORMATTED | BA_RESERVED | + BA_USE_DEFAULT_SEARCH_START); blocknr_hint_done(&hint); @@ -1448,45 +1507,46 @@ alloc_tx(struct commit_handle *ch, flush pin_jnode_data(cur); - capture_list_push_back(&ch->tx_list, cur); + list_add_tail(&cur->capture_link, &ch->tx_list); first++; } } - { /* format a on-disk linked list of wander records */ + { /* format a on-disk linked list of wander records */ int serial = 1; - txhead = capture_list_front(&ch->tx_list); + txhead = list_entry(ch->tx_list.next, jnode, capture_link); format_tx_head(ch); - cur = capture_list_next(txhead); - while (!capture_list_end(&ch->tx_list, cur)) { + cur = list_entry(txhead->capture_link.next, jnode, capture_link); + while (&ch->tx_list != &cur->capture_link) { format_wander_record(ch, cur, serial++); - cur = capture_list_next(cur); + cur = list_entry(cur->capture_link.next, jnode, capture_link); } - } - { /* Fill wander records with Wandered Set */ + { /* Fill wander records with Wandered Set */ struct store_wmap_params params; txn_atom *atom; - params.cur = capture_list_next(txhead); + params.cur = list_entry(txhead->capture_link.next, jnode, capture_link); params.idx = 0; - params.capacity = wander_record_capacity(reiser4_get_current_sb()); + params.capacity = + wander_record_capacity(reiser4_get_current_sb()); atom = get_current_atom_locked(); - blocknr_set_iterator(atom, &atom->wandered_map, &store_wmap_actor, ¶ms, 0); + blocknr_set_iterator(atom, &atom->wandered_map, + &store_wmap_actor, ¶ms, 0); UNLOCK_ATOM(atom); } - { /* relse all jnodes from tx_list */ - cur = capture_list_front(&ch->tx_list); - while (!capture_list_end(&ch->tx_list, cur)) { + { /* relse all jnodes from tx_list */ + cur = list_entry(ch->tx_list.next, jnode, capture_link); + while (&ch->tx_list != &cur->capture_link) { jrelse(cur); - cur = capture_list_next(cur); + cur = list_entry(cur->capture_link.next, jnode, capture_link); } } @@ -1494,7 +1554,7 @@ alloc_tx(struct commit_handle *ch, flush return ret; -free_not_assigned: + free_not_assigned: /* We deallocate blocks not yet assigned to jnodes on tx_list. The caller takes care about invalidating of tx list */ reiser4_dealloc_blocks(&first, &len, BLOCK_NOT_COUNTED, BA_FORMATTED); @@ -1507,7 +1567,7 @@ free_not_assigned: are submitted to write. */ -reiser4_internal int reiser4_write_logs(long * nr_submitted) +int reiser4_write_logs(long *nr_submitted) { txn_atom *atom; struct super_block *super = reiser4_get_current_sb(); @@ -1543,15 +1603,15 @@ reiser4_internal int reiser4_write_logs( UNLOCK_ATOM(atom); if (REISER4_DEBUG) { - int level; + int level; - for (level = 0; level < REAL_MAX_ZTREE_HEIGHT + 1; ++ level) - assert("nikita-3352", - capture_list_empty(ATOM_DIRTY_LIST(atom, level))); + for (level = 0; level < REAL_MAX_ZTREE_HEIGHT + 1; ++level) + assert("nikita-3352", + list_empty_careful(ATOM_DIRTY_LIST(atom, level))); } - sbinfo->nr_files_committed += (unsigned) atom->nr_objects_created; - sbinfo->nr_files_committed -= (unsigned) atom->nr_objects_deleted; + sbinfo->nr_files_committed += (unsigned)atom->nr_objects_created; + sbinfo->nr_files_committed -= (unsigned)atom->nr_objects_deleted; init_commit_handle(&ch, atom); @@ -1578,7 +1638,7 @@ reiser4_internal int reiser4_write_logs( get_tx_size(&ch); /* Grab more space for wandered records. */ - ret = reiser4_grab_space_force((__u64)(ch.tx_size), BA_RESERVED); + ret = reiser4_grab_space_force((__u64) (ch.tx_size), BA_RESERVED); if (ret) goto up_and_ret; @@ -1604,7 +1664,6 @@ reiser4_internal int reiser4_write_logs( break; } while (0); - /* Release all grabbed space if it was not fully used for * wandered blocks/records allocation. */ all_grabbed2free(); @@ -1639,7 +1698,9 @@ reiser4_internal int reiser4_write_logs( UNLOCK_ATOM(fq->atom); - ret = write_jnode_list(ch.overwrite_set, fq, NULL, WRITEOUT_FOR_PAGE_RECLAIM); + ret = + write_jnode_list(ch.overwrite_set, fq, NULL, + WRITEOUT_FOR_PAGE_RECLAIM); fq_put(fq); @@ -1657,7 +1718,7 @@ reiser4_internal int reiser4_write_logs( post_write_back_hook(); -up_and_ret: + up_and_ret: if (ret) { /* there could be fq attached to current atom; the only way to remove them is: */ @@ -1680,21 +1741,21 @@ up_and_ret: /* consistency checks for journal data/control blocks: header, footer, log records, transactions head blocks. All functions return zero on success. */ -static int -check_journal_header(const jnode * node UNUSED_ARG) +static int check_journal_header(const jnode * node UNUSED_ARG) { /* FIXME: journal header has no magic field yet. */ return 0; } /* wait for write completion for all jnodes from given list */ -static int -wait_on_jnode_list(capture_list_head * head) +static int wait_on_jnode_list(struct list_head *head) { jnode *scan; + struct list_head *pos; int ret = 0; - for_all_type_safe_list(capture, head, scan) { + list_for_each(pos, head) { + scan = list_entry(pos, jnode, capture_link); struct page *pg = jnode_page(scan); if (pg) { @@ -1709,33 +1770,34 @@ wait_on_jnode_list(capture_list_head * h return ret; } -static int -check_journal_footer(const jnode * node UNUSED_ARG) +static int check_journal_footer(const jnode * node UNUSED_ARG) { /* FIXME: journal footer has no magic field yet. */ return 0; } -static int -check_tx_head(const jnode * node) +static int check_tx_head(const jnode * node) { - struct tx_header *header = (struct tx_header *) jdata(node); + struct tx_header *header = (struct tx_header *)jdata(node); if (memcmp(&header->magic, TX_HEADER_MAGIC, TX_HEADER_MAGIC_SIZE) != 0) { - warning("zam-627", "tx head at block %s corrupted\n", sprint_address(jnode_get_block(node))); + warning("zam-627", "tx head at block %s corrupted\n", + sprint_address(jnode_get_block(node))); return RETERR(-EIO); } return 0; } -static int -check_wander_record(const jnode * node) +static int check_wander_record(const jnode * node) { - struct wander_record_header *RH = (struct wander_record_header *) jdata(node); + struct wander_record_header *RH = + (struct wander_record_header *)jdata(node); - if (memcmp(&RH->magic, WANDER_RECORD_MAGIC, WANDER_RECORD_MAGIC_SIZE) != 0) { - warning("zam-628", "wander record at block %s corrupted\n", sprint_address(jnode_get_block(node))); + if (memcmp(&RH->magic, WANDER_RECORD_MAGIC, WANDER_RECORD_MAGIC_SIZE) != + 0) { + warning("zam-628", "wander record at block %s corrupted\n", + sprint_address(jnode_get_block(node))); return RETERR(-EIO); } @@ -1743,18 +1805,16 @@ check_wander_record(const jnode * node) } /* fill commit_handler structure by everything what is needed for update_journal_footer */ -static int -restore_commit_handle(struct commit_handle *ch, jnode * tx_head) +static int restore_commit_handle(struct commit_handle *ch, jnode *tx_head) { struct tx_header *TXH; int ret; ret = jload(tx_head); - if (ret) return ret; - TXH = (struct tx_header *) jdata(tx_head); + TXH = (struct tx_header *)jdata(tx_head); ch->free_blocks = d64tocpu(&TXH->free_blocks); ch->nr_files = d64tocpu(&TXH->nr_files); @@ -1762,26 +1822,25 @@ restore_commit_handle(struct commit_hand jrelse(tx_head); - capture_list_push_front(&ch->tx_list, tx_head); + list_add(&tx_head->capture_link, &ch->tx_list); return 0; } /* replay one transaction: restore and write overwrite set in place */ -static int -replay_transaction(const struct super_block *s, - jnode * tx_head, - const reiser4_block_nr * log_rec_block_p, - const reiser4_block_nr * end_block, unsigned int nr_wander_records) +static int replay_transaction(const struct super_block *s, + jnode * tx_head, + const reiser4_block_nr * log_rec_block_p, + const reiser4_block_nr * end_block, + unsigned int nr_wander_records) { reiser4_block_nr log_rec_block = *log_rec_block_p; struct commit_handle ch; - capture_list_head overwrite_set; + LIST_HEAD(overwrite_set); jnode *log; int ret; init_commit_handle(&ch, NULL); - capture_list_init(&overwrite_set); ch.overwrite_set = &overwrite_set; restore_commit_handle(&ch, tx_head); @@ -1794,7 +1853,8 @@ replay_transaction(const struct super_bl if (nr_wander_records == 0) { warning("zam-631", - "number of wander records in the linked list" " greater than number stored in tx head.\n"); + "number of wander records in the linked list" + " greater than number stored in tx head.\n"); ret = RETERR(-EIO); goto free_ow_set; } @@ -1816,10 +1876,10 @@ replay_transaction(const struct super_bl return ret; } - header = (struct wander_record_header *) jdata(log); + header = (struct wander_record_header *)jdata(log); log_rec_block = d64tocpu(&header->next_block); - entry = (struct wander_entry *) (header + 1); + entry = (struct wander_entry *)(header + 1); /* restore overwrite set from wander record content */ for (i = 0; i < wander_record_capacity(s); i++) { @@ -1860,7 +1920,7 @@ replay_transaction(const struct super_bl jnode_set_block(node, &block); - capture_list_push_back(ch.overwrite_set, node); + list_add_tail(&node->capture_link, ch.overwrite_set); ++entry; } @@ -1879,7 +1939,7 @@ replay_transaction(const struct super_bl } { /* write wandered set in place */ - write_jnode_list(ch.overwrite_set, 0, NULL, 0); + write_jnode_list(ch.overwrite_set, NULL, NULL, 0); ret = wait_on_jnode_list(ch.overwrite_set); if (ret) { @@ -1890,16 +1950,16 @@ replay_transaction(const struct super_bl ret = update_journal_footer(&ch); -free_ow_set: + free_ow_set: - while (!capture_list_empty(ch.overwrite_set)) { - jnode *cur = capture_list_front(ch.overwrite_set); - capture_list_remove_clean (cur); + while (!list_empty(ch.overwrite_set)) { + jnode *cur = list_entry(ch.overwrite_set->next, jnode, capture_link); + list_del_init(&cur->capture_link); jrelse(cur); drop_io_head(cur); } - capture_list_remove_clean (tx_head); + list_del_init(&tx_head->capture_link); done_commit_handle(&ch); @@ -1912,8 +1972,7 @@ free_ow_set: * footer block were not completed. This function completes the process by * recovering the atom's overwrite set from their wandered locations and writes * them in-place and updating the journal footer. */ -static int -replay_oldest_transaction(struct super_block *s) +static int replay_oldest_transaction(struct super_block *s) { reiser4_super_info_data *sbinfo = get_super_private(s); jnode *jf = sbinfo->journal_footer; @@ -1932,7 +1991,7 @@ replay_oldest_transaction(struct super_b if ((ret = jload(jf)) < 0) return ret; - F = (struct journal_footer *) jdata(jf); + F = (struct journal_footer *)jdata(jf); last_flushed_tx = d64tocpu(&F->last_flushed_tx); @@ -1964,7 +2023,7 @@ replay_oldest_transaction(struct super_b return ret; } - T = (struct tx_header *) jdata(tx_head); + T = (struct tx_header *)jdata(tx_head); prev_tx = d64tocpu(&T->prev_tx); @@ -1981,7 +2040,9 @@ replay_oldest_transaction(struct super_b pin_jnode_data(tx_head); jrelse(tx_head); - ret = replay_transaction(s, tx_head, &log_rec_block, jnode_get_block(tx_head), total - 1); + ret = + replay_transaction(s, tx_head, &log_rec_block, + jnode_get_block(tx_head), total - 1); unpin_jnode_data(tx_head); drop_io_head(tx_head); @@ -2003,8 +2064,7 @@ replay_oldest_transaction(struct super_b */ /* get the information from journal footer in-memory super block */ -reiser4_internal int -reiser4_journal_recover_sb_data(struct super_block *s) +int reiser4_journal_recover_sb_data(struct super_block *s) { reiser4_super_info_data *sbinfo = get_super_private(s); struct journal_footer *jf; @@ -2020,7 +2080,7 @@ reiser4_journal_recover_sb_data(struct s if (ret != 0) goto out; - jf = (struct journal_footer *) jdata(sbinfo->journal_footer); + jf = (struct journal_footer *)jdata(sbinfo->journal_footer); /* was there at least one flushed transaction? */ if (d64tocpu(&jf->last_flushed_tx)) { @@ -2033,21 +2093,18 @@ reiser4_journal_recover_sb_data(struct s d64tocpu(&jf->nr_files), d64tocpu(&jf->next_oid)); } -out: + out: jrelse(sbinfo->journal_footer); return ret; } /* reiser4 replay journal procedure */ -reiser4_internal int -reiser4_journal_replay(struct super_block *s) +int reiser4_journal_replay(struct super_block *s) { reiser4_super_info_data *sbinfo = get_super_private(s); jnode *jh, *jf; - struct journal_header *header; int nr_tx_replayed = 0; - int ret; assert("zam-582", sbinfo != NULL); @@ -2090,7 +2147,7 @@ reiser4_journal_replay(struct super_bloc return ret; } - header = (struct journal_header *) jdata(jh); + header = (struct journal_header *)jdata(jh); sbinfo->last_committed_tx = d64tocpu(&header->last_committed_tx); jrelse(jh); @@ -2101,6 +2158,7 @@ reiser4_journal_replay(struct super_bloc return ret; } + /* load journal control block (either journal header or journal footer block) */ static int load_journal_control_block(jnode ** node, const reiser4_block_nr * block) @@ -2126,8 +2184,7 @@ load_journal_control_block(jnode ** node } /* unload journal header or footer and free jnode */ -static void -unload_journal_control_block(jnode ** node) +static void unload_journal_control_block(jnode ** node) { if (*node) { unpin_jnode_data(*node); @@ -2137,8 +2194,7 @@ unload_journal_control_block(jnode ** no } /* release journal control blocks */ -reiser4_internal void -done_journal_info(struct super_block *s) +void done_journal_info(struct super_block *s) { reiser4_super_info_data *sbinfo = get_super_private(s); @@ -2146,11 +2202,11 @@ done_journal_info(struct super_block *s) unload_journal_control_block(&sbinfo->journal_header); unload_journal_control_block(&sbinfo->journal_footer); + rcu_barrier(); } /* load journal control blocks */ -reiser4_internal int -init_journal_info(struct super_block *s) +int init_journal_info(struct super_block *s) { reiser4_super_info_data *sbinfo = get_super_private(s); journal_location *loc; diff -puN fs/reiser4/wander.h~reiser4-big-update fs/reiser4/wander.h --- devel/fs/reiser4/wander.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/wander.h 2005-09-15 19:51:08.000000000 -0700 @@ -119,7 +119,7 @@ extern int reiser4_journal_recover_sb_da extern int init_journal_info(struct super_block *); extern void done_journal_info(struct super_block *); -extern int write_jnode_list (capture_list_head*, flush_queue_t*, long*, int); +extern int write_jnode_list(struct list_head *, flush_queue_t *, long *, int); #endif /* __FS_REISER4_WANDER_H__ */ diff -puN fs/reiser4/writeout.h~reiser4-big-update fs/reiser4/writeout.h --- devel/fs/reiser4/writeout.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/writeout.h 2005-09-15 19:51:08.000000000 -0700 @@ -7,8 +7,7 @@ extern int get_writeout_flags(void); -#endif /* __FS_REISER4_WRITEOUT_H__ */ - +#endif /* __FS_REISER4_WRITEOUT_H__ */ /* Make Linus happy. Local variables: diff -puN fs/reiser4/znode.c~reiser4-big-update fs/reiser4/znode.c --- devel/fs/reiser4/znode.c~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/znode.c 2005-09-15 19:51:08.000000000 -0700 @@ -160,7 +160,8 @@ #include #include -static z_hash_table *get_htable(reiser4_tree *, const reiser4_block_nr * const blocknr); +static z_hash_table *get_htable(reiser4_tree *, + const reiser4_block_nr * const blocknr); static z_hash_table *znode_get_htable(const znode *); static void zdrop(znode *); @@ -179,7 +180,7 @@ blknreq(const reiser4_block_nr * b1, con /* Hash znode by block number. Used by hash-table macros */ /* Audited by: umka (2002.06.11) */ static inline __u32 -blknrhashfn(z_hash_table *table, const reiser4_block_nr * b) +blknrhashfn(z_hash_table * table, const reiser4_block_nr * b) { assert("nikita-536", b != NULL); @@ -187,48 +188,49 @@ blknrhashfn(z_hash_table *table, const r } /* The hash table definition */ -#define KMALLOC(size) reiser4_kmalloc((size), GFP_KERNEL) -#define KFREE(ptr, size) reiser4_kfree(ptr) -TYPE_SAFE_HASH_DEFINE(z, znode, reiser4_block_nr, zjnode.key.z, zjnode.link.z, blknrhashfn, blknreq); +#define KMALLOC(size) kmalloc((size), GFP_KERNEL) +#define KFREE(ptr, size) kfree(ptr) +TYPE_SAFE_HASH_DEFINE(z, znode, reiser4_block_nr, zjnode.key.z, zjnode.link.z, + blknrhashfn, blknreq); #undef KFREE #undef KMALLOC /* slab for znodes */ -static kmem_cache_t *znode_slab; +static kmem_cache_t *znode_cache; int znode_shift_order; -/* ZNODE INITIALIZATION */ - -/* call this once on reiser4 initialisation */ -reiser4_internal int -znodes_init(void) -{ - znode_slab = kmem_cache_create("znode", sizeof (znode), 0, - SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, - NULL, NULL); - if (znode_slab == NULL) { +/** + * init_znodes - create znode cache + * + * Initializes slab cache of znodes. It is part of reiser4 module initialization. + */ +int init_znodes(void) +{ + znode_cache = kmem_cache_create("znode", sizeof(znode), 0, + SLAB_HWCACHE_ALIGN | + SLAB_RECLAIM_ACCOUNT, NULL, NULL); + if (znode_cache == NULL) return RETERR(-ENOMEM); - } else { - for (znode_shift_order = 0; - (1 << znode_shift_order) < sizeof(znode); - ++ znode_shift_order) - ; - -- znode_shift_order; - return 0; - } + + for (znode_shift_order = 0; (1 << znode_shift_order) < sizeof(znode); + ++znode_shift_order); + --znode_shift_order; + return 0; } -/* call this before unloading reiser4 */ -reiser4_internal int -znodes_done(void) +/** + * done_znodes - delete znode cache + * + * This is called on reiser4 module unloading or system shutdown. + */ +void done_znodes(void) { - return kmem_cache_destroy(znode_slab); + destroy_reiser4_cache(&znode_cache); } /* call this to initialise tree of znodes */ -reiser4_internal int -znodes_tree_init(reiser4_tree * tree /* tree to initialise znodes for */ ) +int znodes_tree_init(reiser4_tree * tree /* tree to initialise znodes for */ ) { int result; assert("umka-050", tree != NULL); @@ -243,14 +245,14 @@ znodes_tree_init(reiser4_tree * tree /* } /* free this znode */ -reiser4_internal void -zfree(znode * node /* znode to free */ ) +void zfree(znode * node /* znode to free */ ) { assert("nikita-465", node != NULL); assert("nikita-2120", znode_page(node) == NULL); - assert("nikita-2301", owners_list_empty(&node->lock.owners)); - assert("nikita-2302", requestors_list_empty(&node->lock.requestors)); - assert("nikita-2663", capture_list_is_clean(ZJNODE(node)) && NODE_LIST(ZJNODE(node)) == NOT_CAPTURED); + assert("nikita-2301", list_empty_careful(&node->lock.owners)); + assert("nikita-2302", list_empty_careful(&node->lock.requestors)); + assert("nikita-2663", (list_empty_careful(&ZJNODE(node)->capture_link) && + NODE_LIST(ZJNODE(node)) == NOT_CAPTURED)); assert("nikita-2773", !JF_ISSET(ZJNODE(node), JNODE_EFLUSH)); assert("nikita-3220", list_empty(&ZJNODE(node)->jnodes)); assert("nikita-3293", !znode_is_right_connected(node)); @@ -258,17 +260,15 @@ zfree(znode * node /* znode to free */ ) assert("nikita-3295", node->left == NULL); assert("nikita-3296", node->right == NULL); - /* not yet phash_jnode_destroy(ZJNODE(node)); */ /* poison memory. */ ON_DEBUG(memset(node, 0xde, sizeof *node)); - kmem_cache_free(znode_slab, node); + kmem_cache_free(znode_cache, node); } /* call this to free tree of znodes */ -reiser4_internal void -znodes_tree_done(reiser4_tree * tree /* tree to finish with znodes of */ ) +void znodes_tree_done(reiser4_tree * tree /* tree to finish with znodes of */ ) { znode *node; znode *next; @@ -281,36 +281,39 @@ znodes_tree_done(reiser4_tree * tree /* ztable = &tree->zhash_table; - for_all_in_htable(ztable, z, node, next) { - node->c_count = 0; - node->in_parent.node = NULL; - assert("nikita-2179", atomic_read(&ZJNODE(node)->x_count) == 0); - zdrop(node); - } + if (ztable->_table != NULL) { + for_all_in_htable(ztable, z, node, next) { + node->c_count = 0; + node->in_parent.node = NULL; + assert("nikita-2179", atomic_read(&ZJNODE(node)->x_count) == 0); + zdrop(node); + } - z_hash_done(&tree->zhash_table); + z_hash_done(&tree->zhash_table); + } ztable = &tree->zfake_table; - for_all_in_htable(ztable, z, node, next) { - node->c_count = 0; - node->in_parent.node = NULL; - assert("nikita-2179", atomic_read(&ZJNODE(node)->x_count) == 0); - zdrop(node); - } + if (ztable->_table != NULL) { + for_all_in_htable(ztable, z, node, next) { + node->c_count = 0; + node->in_parent.node = NULL; + assert("nikita-2179", atomic_read(&ZJNODE(node)->x_count) == 0); + zdrop(node); + } - z_hash_done(&tree->zfake_table); + z_hash_done(&tree->zfake_table); + } } /* ZNODE STRUCTURES */ /* allocate fresh znode */ -reiser4_internal znode * -zalloc(int gfp_flag /* allocation flag */ ) +znode *zalloc(unsigned int gfp_flag /* allocation flag */ ) { znode *node; - node = kmem_cache_alloc(znode_slab, gfp_flag); + node = kmem_cache_alloc(znode_cache, gfp_flag); return node; } @@ -318,8 +321,7 @@ zalloc(int gfp_flag /* allocation flag * @node: znode to initialize; @parent: parent znode; @tree: tree we are in. */ -reiser4_internal void -zinit(znode * node, const znode * parent, reiser4_tree * tree) +void zinit(znode * node, const znode * parent, reiser4_tree * tree) { assert("nikita-466", node != NULL); assert("umka-268", current_tree != NULL); @@ -337,8 +339,7 @@ zinit(znode * node, const znode * parent * remove znode from indices. This is called jput() when last reference on * znode is released. */ -reiser4_internal void -znode_remove(znode * node /* znode to remove */ , reiser4_tree * tree) +void znode_remove(znode * node /* znode to remove */ , reiser4_tree * tree) { assert("nikita-2108", node != NULL); assert("nikita-470", node->c_count == 0); @@ -351,7 +352,7 @@ znode_remove(znode * node /* znode to re if (znode_parent(node) != NULL) { assert("nikita-472", znode_parent(node)->c_count > 0); /* father, onto your hands I forward my spirit... */ - znode_parent(node)->c_count --; + znode_parent(node)->c_count--; node->in_parent.node = NULL; } else { /* orphaned znode?! Root? */ @@ -364,8 +365,7 @@ znode_remove(znode * node /* znode to re /* zdrop() -- Remove znode from the tree. This is called when znode is removed from the memory. */ -static void -zdrop(znode * node /* znode to finish with */ ) +static void zdrop(znode * node /* znode to finish with */ ) { jdrop(ZJNODE(node)); } @@ -374,9 +374,8 @@ zdrop(znode * node /* znode to finish wi * put znode into right place in the hash table. This is called by relocate * code. */ -reiser4_internal int -znode_rehash(znode * node /* node to rehash */ , - const reiser4_block_nr * new_block_nr /* new block number */ ) +int znode_rehash(znode * node /* node to rehash */ , + const reiser4_block_nr * new_block_nr /* new block number */ ) { z_hash_table *oldtable; z_hash_table *newtable; @@ -413,18 +412,17 @@ znode_rehash(znode * node /* node to reh accepts pre-computed hash index. The hash table is accessed under caller's tree->hash_lock. */ -reiser4_internal znode * -zlook(reiser4_tree * tree, const reiser4_block_nr * const blocknr) +znode *zlook(reiser4_tree * tree, const reiser4_block_nr * const blocknr) { - znode *result; - __u32 hash; + znode *result; + __u32 hash; z_hash_table *htable; assert("jmacd-506", tree != NULL); assert("jmacd-507", blocknr != NULL); htable = get_htable(tree, blocknr); - hash = blknrhashfn(htable, blocknr); + hash = blknrhashfn(htable, blocknr); rcu_read_lock(); result = z_hash_find_index(htable, hash, blocknr); @@ -440,8 +438,8 @@ zlook(reiser4_tree * tree, const reiser4 /* return hash table where znode with block @blocknr is (or should be) * stored */ -static z_hash_table * -get_htable(reiser4_tree * tree, const reiser4_block_nr * const blocknr) +static z_hash_table *get_htable(reiser4_tree * tree, + const reiser4_block_nr * const blocknr) { z_hash_table *table; if (is_disk_addr_unallocated(blocknr)) @@ -452,8 +450,7 @@ get_htable(reiser4_tree * tree, const re } /* return hash table where znode @node is (or should be) stored */ -static z_hash_table * -znode_get_htable(const znode *node) +static z_hash_table *znode_get_htable(const znode * node) { return get_htable(znode_get_tree(node), znode_get_block(node)); } @@ -467,12 +464,9 @@ znode_get_htable(const znode *node) LOCKS TAKEN: TREE_LOCK, ZNODE_LOCK LOCK ORDERING: NONE */ -reiser4_internal znode * -zget(reiser4_tree * tree, - const reiser4_block_nr * const blocknr, - znode * parent, - tree_level level, - int gfp_flag) +znode *zget(reiser4_tree * tree, + const reiser4_block_nr * const blocknr, + znode * parent, tree_level level, int gfp_flag) { znode *result; __u32 hashi; @@ -504,14 +498,15 @@ zget(reiser4_tree * tree, creation of new root makes such assertion highly complicated. */ assert("nikita-2131", 1 || znode_parent(result) == parent || - (ZF_ISSET(result, JNODE_ORPHAN) && (znode_parent(result) == NULL))); + (ZF_ISSET(result, JNODE_ORPHAN) + && (znode_parent(result) == NULL))); result = znode_rip_check(tree, result); } rcu_read_unlock(); if (!result) { - znode * shadow; + znode *shadow; result = zalloc(gfp_flag); if (!result) { @@ -535,14 +530,13 @@ zget(reiser4_tree * tree, z_hash_insert_index_rcu(zth, hashi, result); if (parent != NULL) - ++ parent->c_count; + ++parent->c_count; } add_x_ref(ZJNODE(result)); WUNLOCK_TREE(tree); } - #if REISER4_DEBUG if (!blocknr_is_fake(blocknr) && *blocknr != 0) reiser4_check_block(blocknr, 1); @@ -551,7 +545,8 @@ zget(reiser4_tree * tree, if (unlikely(znode_get_level(result) != level)) { warning("jmacd-504", "Wrong level for cached block %llu: %i expecting %i", - (unsigned long long)(*blocknr), znode_get_level(result), level); + (unsigned long long)(*blocknr), znode_get_level(result), + level); zput(result); return ERR_PTR(RETERR(-EIO)); } @@ -565,11 +560,10 @@ zget(reiser4_tree * tree, /* "guess" plugin for node loaded from the disk. Plugin id of node plugin is stored at the fixed offset from the beginning of the node. */ -static node_plugin * -znode_guess_plugin(const znode * node /* znode to guess - * plugin of */ ) +static node_plugin *znode_guess_plugin(const znode * node /* znode to guess + * plugin of */ ) { - reiser4_tree * tree; + reiser4_tree *tree; assert("nikita-1053", node != NULL); assert("nikita-1055", zdata(node) != NULL); @@ -581,14 +575,15 @@ znode_guess_plugin(const znode * node /* return tree->nplug; } else { return node_plugin_by_disk_id - (tree, &((common_node_header *) zdata(node))->plugin_id); + (tree, &((common_node_header *) zdata(node))->plugin_id); #ifdef GUESS_EXISTS reiser4_plugin *plugin; /* NOTE-NIKITA add locking here when dynamic plugins will be * implemented */ for_all_plugins(REISER4_NODE_PLUGIN_TYPE, plugin) { - if ((plugin->u.node.guess != NULL) && plugin->u.node.guess(node)) + if ((plugin->u.node.guess != NULL) + && plugin->u.node.guess(node)) return plugin; } warning("nikita-1057", "Cannot guess node plugin"); @@ -599,8 +594,7 @@ znode_guess_plugin(const znode * node /* } /* parse node header and install ->node_plugin */ -reiser4_internal int -zparse(znode * node /* znode to parse */ ) +int zparse(znode * node /* znode to parse */ ) { int result; @@ -624,8 +618,7 @@ zparse(znode * node /* znode to parse */ } /* zload with readahead */ -reiser4_internal int -zload_ra(znode * node /* znode to load */, ra_info_t *info) +int zload_ra(znode * node /* znode to load */ , ra_info_t * info) { int result; @@ -644,22 +637,20 @@ zload_ra(znode * node /* znode to load * } /* load content of node into memory */ -reiser4_internal int zload(znode * node) +int zload(znode * node) { - return zload_ra(node, 0); + return zload_ra(node, NULL); } /* call node plugin to initialise newly allocated node. */ -reiser4_internal int -zinit_new(znode * node /* znode to initialise */, int gfp_flags ) +int zinit_new(znode * node /* znode to initialise */ , int gfp_flags) { return jinit_new(ZJNODE(node), gfp_flags); } /* drop reference to node data. When last reference is dropped, data are unloaded. */ -reiser4_internal void -zrelse(znode * node /* znode to release references to */ ) +void zrelse(znode * node /* znode to release references to */ ) { assert("nikita-1381", znode_invariant(node)); @@ -667,16 +658,14 @@ zrelse(znode * node /* znode to release } /* returns free space in node */ -reiser4_internal unsigned -znode_free_space(znode * node /* znode to query */ ) +unsigned znode_free_space(znode * node /* znode to query */ ) { assert("nikita-852", node != NULL); return node_plugin_by_node(node)->free_space(node); } /* left delimiting key of znode */ -reiser4_internal reiser4_key * -znode_get_rd_key(znode * node /* znode to query */ ) +reiser4_key *znode_get_rd_key(znode * node /* znode to query */ ) { assert("nikita-958", node != NULL); assert("nikita-1661", rw_dk_is_locked(znode_get_tree(node))); @@ -686,8 +675,7 @@ znode_get_rd_key(znode * node /* znode t } /* right delimiting key of znode */ -reiser4_internal reiser4_key * -znode_get_ld_key(znode * node /* znode to query */ ) +reiser4_key *znode_get_ld_key(znode * node /* znode to query */ ) { assert("nikita-974", node != NULL); assert("nikita-1662", rw_dk_is_locked(znode_get_tree(node))); @@ -696,11 +684,11 @@ znode_get_ld_key(znode * node /* znode t return &node->ld_key; } -ON_DEBUG(atomic_t delim_key_version = ATOMIC_INIT(0);) +ON_DEBUG(atomic_t delim_key_version = ATOMIC_INIT(0); + ) /* update right-delimiting key of @node */ -reiser4_internal reiser4_key * -znode_set_rd_key(znode * node, const reiser4_key * key) +reiser4_key *znode_set_rd_key(znode * node, const reiser4_key * key) { assert("nikita-2937", node != NULL); assert("nikita-2939", key != NULL); @@ -714,22 +702,19 @@ znode_set_rd_key(znode * node, const rei ZF_ISSET(node, JNODE_HEARD_BANSHEE)); node->rd_key = *key; - ON_DEBUG(node->rd_key_version = atomic_inc_return(&delim_key_version)); + ON_DEBUG(node->rd_key_version = atomic_inc_return(&delim_key_version)); return &node->rd_key; } - /* update left-delimiting key of @node */ -reiser4_internal reiser4_key * -znode_set_ld_key(znode * node, const reiser4_key * key) +reiser4_key *znode_set_ld_key(znode * node, const reiser4_key * key) { assert("nikita-2940", node != NULL); assert("nikita-2941", key != NULL); assert("nikita-2942", rw_dk_is_write_locked(znode_get_tree(node))); - assert("nikita-3070", LOCK_CNT_GTZ(write_locked_dk > 0)); + assert("nikita-3070", LOCK_CNT_GTZ(write_locked_dk)); assert("nikita-2943", - znode_is_any_locked(node) || - keyeq(&node->ld_key, min_key())); + znode_is_any_locked(node) || keyeq(&node->ld_key, min_key())); node->ld_key = *key; ON_DEBUG(node->ld_key_version = atomic_inc_return(&delim_key_version)); @@ -737,21 +722,20 @@ znode_set_ld_key(znode * node, const rei } /* true if @key is inside key range for @node */ -reiser4_internal int -znode_contains_key(znode * node /* znode to look in */ , - const reiser4_key * key /* key to look for */ ) +int znode_contains_key(znode * node /* znode to look in */ , + const reiser4_key * key /* key to look for */ ) { assert("nikita-1237", node != NULL); assert("nikita-1238", key != NULL); /* left_delimiting_key <= key <= right_delimiting_key */ - return keyle(znode_get_ld_key(node), key) && keyle(key, znode_get_rd_key(node)); + return keyle(znode_get_ld_key(node), key) + && keyle(key, znode_get_rd_key(node)); } /* same as znode_contains_key(), but lock dk lock */ -reiser4_internal int -znode_contains_key_lock(znode * node /* znode to look in */ , - const reiser4_key * key /* key to look for */ ) +int znode_contains_key_lock(znode * node /* znode to look in */ , + const reiser4_key * key /* key to look for */ ) { assert("umka-056", node != NULL); assert("umka-057", key != NULL); @@ -761,16 +745,14 @@ znode_contains_key_lock(znode * node /* } /* get parent pointer, assuming tree is not locked */ -reiser4_internal znode * -znode_parent_nolock(const znode * node /* child znode */ ) +znode *znode_parent_nolock(const znode * node /* child znode */ ) { assert("nikita-1444", node != NULL); return node->in_parent.node; } /* get parent pointer of znode */ -reiser4_internal znode * -znode_parent(const znode * node /* child znode */ ) +znode *znode_parent(const znode * node /* child znode */ ) { assert("nikita-1226", node != NULL); assert("nikita-1406", LOCK_CNT_GTZ(rw_locked_tree)); @@ -778,8 +760,7 @@ znode_parent(const znode * node /* child } /* detect uber znode used to protect in-superblock tree root pointer */ -reiser4_internal int -znode_above_root(const znode * node /* znode to query */ ) +int znode_above_root(const znode * node /* znode to query */ ) { assert("umka-059", node != NULL); @@ -789,19 +770,18 @@ znode_above_root(const znode * node /* z /* check that @node is root---that its block number is recorder in the tree as that of root node */ #if REISER4_DEBUG -static int -znode_is_true_root(const znode * node /* znode to query */ ) +static int znode_is_true_root(const znode * node /* znode to query */ ) { assert("umka-060", node != NULL); assert("umka-061", current_tree != NULL); - return disk_addr_eq(znode_get_block(node), &znode_get_tree(node)->root_block); + return disk_addr_eq(znode_get_block(node), + &znode_get_tree(node)->root_block); } #endif /* check that @node is root */ -reiser4_internal int -znode_is_root(const znode * node /* znode to query */ ) +int znode_is_root(const znode * node /* znode to query */ ) { assert("nikita-1206", node != NULL); @@ -811,29 +791,25 @@ znode_is_root(const znode * node /* znod /* Returns true is @node was just created by zget() and wasn't ever loaded into memory. */ /* NIKITA-HANS: yes */ -reiser4_internal int -znode_just_created(const znode * node) +int znode_just_created(const znode * node) { assert("nikita-2188", node != NULL); return (znode_page(node) == NULL); } /* obtain updated ->znode_epoch. See seal.c for description. */ -reiser4_internal __u64 -znode_build_version(reiser4_tree * tree) +__u64 znode_build_version(reiser4_tree * tree) { return UNDER_SPIN(epoch, tree, ++tree->znode_epoch); } -reiser4_internal void -init_load_count(load_count * dh) +void init_load_count(load_count * dh) { assert("nikita-2105", dh != NULL); memset(dh, 0, sizeof *dh); } -reiser4_internal void -done_load_count(load_count * dh) +void done_load_count(load_count * dh) { assert("nikita-2106", dh != NULL); if (dh->node != NULL) { @@ -843,8 +819,7 @@ done_load_count(load_count * dh) } } -static int -incr_load_count(load_count * dh) +static int incr_load_count(load_count * dh) { int result; @@ -857,19 +832,18 @@ incr_load_count(load_count * dh) return result; } -reiser4_internal int -incr_load_count_znode(load_count * dh, znode * node) +int incr_load_count_znode(load_count * dh, znode * node) { assert("nikita-2107", dh != NULL); assert("nikita-2158", node != NULL); - assert("nikita-2109", ergo(dh->node != NULL, (dh->node == node) || (dh->d_ref == 0))); + assert("nikita-2109", + ergo(dh->node != NULL, (dh->node == node) || (dh->d_ref == 0))); dh->node = node; return incr_load_count(dh); } -reiser4_internal int -incr_load_count_jnode(load_count * dh, jnode * node) +int incr_load_count_jnode(load_count * dh, jnode * node) { if (jnode_is_znode(node)) { return incr_load_count_znode(dh, JZNODE(node)); @@ -877,8 +851,7 @@ incr_load_count_jnode(load_count * dh, j return 0; } -reiser4_internal void -copy_load_count(load_count * new, load_count * old) +void copy_load_count(load_count * new, load_count * old) { int ret = 0; done_load_count(new); @@ -891,8 +864,7 @@ copy_load_count(load_count * new, load_c assert("jmacd-87589", ret == 0); } -reiser4_internal void -move_load_count(load_count * new, load_count * old) +void move_load_count(load_count * new, load_count * old) { done_load_count(new); new->node = old->node; @@ -902,8 +874,7 @@ move_load_count(load_count * new, load_c } /* convert parent pointer into coord */ -reiser4_internal void -parent_coord_to_coord(const parent_coord_t * pcoord, coord_t * coord) +void parent_coord_to_coord(const parent_coord_t * pcoord, coord_t * coord) { assert("nikita-3204", pcoord != NULL); assert("nikita-3205", coord != NULL); @@ -914,8 +885,7 @@ parent_coord_to_coord(const parent_coord } /* pack coord into parent_coord_t */ -reiser4_internal void -coord_to_parent_coord(const coord_t * coord, parent_coord_t * pcoord) +void coord_to_parent_coord(const coord_t * coord, parent_coord_t * pcoord) { assert("nikita-3206", pcoord != NULL); assert("nikita-3207", coord != NULL); @@ -926,22 +896,18 @@ coord_to_parent_coord(const coord_t * co /* Initialize a parent hint pointer. (parent hint pointer is a field in znode, look for comments there) */ -reiser4_internal void -init_parent_coord(parent_coord_t * pcoord, const znode * node) +void init_parent_coord(parent_coord_t * pcoord, const znode * node) { pcoord->node = (znode *) node; pcoord->item_pos = (unsigned short)~0; } - #if REISER4_DEBUG -int jnode_invariant_f(const jnode * node, char const **msg); /* debugging aid: znode invariant */ -static int -znode_invariant_f(const znode * node /* znode to check */ , - char const **msg /* where to store error - * message, if any */ ) +static int znode_invariant_f(const znode * node /* znode to check */ , + char const **msg /* where to store error + * message, if any */ ) { #define _ergo(ant, con) \ ((*msg) = "{" #ant "} ergo {" #con "}", ergo((ant), (con))) @@ -951,80 +917,67 @@ znode_invariant_f(const znode * node /* #define _check(exp) ((*msg) = #exp, (exp)) - return - jnode_invariant_f(ZJNODE(node), msg) && - - /* [znode-fake] invariant */ - - /* fake znode doesn't have a parent, and */ - _ergo(znode_get_level(node) == 0, znode_parent(node) == NULL) && - /* there is another way to express this very check, and */ - _ergo(znode_above_root(node), - znode_parent(node) == NULL) && - /* it has special block number, and */ - _ergo(znode_get_level(node) == 0, - disk_addr_eq(znode_get_block(node), &UBER_TREE_ADDR)) && - /* it is the only znode with such block number, and */ - _ergo(!znode_above_root(node) && znode_is_loaded(node), - !disk_addr_eq(znode_get_block(node), &UBER_TREE_ADDR)) && - /* it is parent of the tree root node */ - _ergo(znode_is_true_root(node), znode_above_root(znode_parent(node))) && - - /* [znode-level] invariant */ - - /* level of parent znode is one larger than that of child, - except for the fake znode, and */ - _ergo(znode_parent(node) && !znode_above_root(znode_parent(node)), - znode_get_level(znode_parent(node)) == - znode_get_level(node) + 1) && - /* left neighbor is at the same level, and */ - _ergo(znode_is_left_connected(node) && node->left != NULL, - znode_get_level(node) == znode_get_level(node->left)) && - /* right neighbor is at the same level */ - _ergo(znode_is_right_connected(node) && node->right != NULL, - znode_get_level(node) == znode_get_level(node->right)) && - - /* [znode-connected] invariant */ - - _ergo(node->left != NULL, znode_is_left_connected(node)) && - _ergo(node->right != NULL, znode_is_right_connected(node)) && - _ergo(!znode_is_root(node) && node->left != NULL, - znode_is_right_connected(node->left) && - node->left->right == node) && - _ergo(!znode_is_root(node) && node->right != NULL, - znode_is_left_connected(node->right) && - node->right->left == node) && - - /* [znode-c_count] invariant */ - - /* for any znode, c_count of its parent is greater than 0 */ - _ergo(znode_parent(node) != NULL && - !znode_above_root(znode_parent(node)), - znode_parent(node)->c_count > 0) && - /* leaves don't have children */ - _ergo(znode_get_level(node) == LEAF_LEVEL, - node->c_count == 0) && - - _check(node->zjnode.jnodes.prev != NULL) && - _check(node->zjnode.jnodes.next != NULL) && - /* orphan doesn't have a parent */ - _ergo(ZF_ISSET(node, JNODE_ORPHAN), znode_parent(node) == 0) && - - /* [znode-modify] invariant */ - - /* if znode is not write-locked, its checksum remains - * invariant */ - /* unfortunately, zlock is unordered w.r.t. jnode_lock, so we - * cannot check this. */ - /* [znode-refs] invariant */ - /* only referenced znode can be long-term locked */ - _ergo(znode_is_locked(node), - atomic_read(&ZJNODE(node)->x_count) != 0); + return jnode_invariant_f(ZJNODE(node), msg) && + /* [znode-fake] invariant */ + /* fake znode doesn't have a parent, and */ + _ergo(znode_get_level(node) == 0, znode_parent(node) == NULL) && + /* there is another way to express this very check, and */ + _ergo(znode_above_root(node), znode_parent(node) == NULL) && + /* it has special block number, and */ + _ergo(znode_get_level(node) == 0, + disk_addr_eq(znode_get_block(node), &UBER_TREE_ADDR)) && + /* it is the only znode with such block number, and */ + _ergo(!znode_above_root(node) && znode_is_loaded(node), + !disk_addr_eq(znode_get_block(node), &UBER_TREE_ADDR)) && + /* it is parent of the tree root node */ + _ergo(znode_is_true_root(node), + znode_above_root(znode_parent(node))) && + /* [znode-level] invariant */ + /* level of parent znode is one larger than that of child, + except for the fake znode, and */ + _ergo(znode_parent(node) && !znode_above_root(znode_parent(node)), + znode_get_level(znode_parent(node)) == + znode_get_level(node) + 1) && + /* left neighbor is at the same level, and */ + _ergo(znode_is_left_connected(node) && node->left != NULL, + znode_get_level(node) == znode_get_level(node->left)) && + /* right neighbor is at the same level */ + _ergo(znode_is_right_connected(node) && node->right != NULL, + znode_get_level(node) == znode_get_level(node->right)) && + /* [znode-connected] invariant */ + _ergo(node->left != NULL, znode_is_left_connected(node)) && + _ergo(node->right != NULL, znode_is_right_connected(node)) && + _ergo(!znode_is_root(node) && node->left != NULL, + znode_is_right_connected(node->left) && + node->left->right == node) && + _ergo(!znode_is_root(node) && node->right != NULL, + znode_is_left_connected(node->right) && + node->right->left == node) && + /* [znode-c_count] invariant */ + /* for any znode, c_count of its parent is greater than 0 */ + _ergo(znode_parent(node) != NULL && + !znode_above_root(znode_parent(node)), + znode_parent(node)->c_count > 0) && + /* leaves don't have children */ + _ergo(znode_get_level(node) == LEAF_LEVEL, + node->c_count == 0) && + _check(node->zjnode.jnodes.prev != NULL) && + _check(node->zjnode.jnodes.next != NULL) && + /* orphan doesn't have a parent */ + _ergo(ZF_ISSET(node, JNODE_ORPHAN), znode_parent(node) == 0) && + /* [znode-modify] invariant */ + /* if znode is not write-locked, its checksum remains + * invariant */ + /* unfortunately, zlock is unordered w.r.t. jnode_lock, so we + * cannot check this. */ + /* [znode-refs] invariant */ + /* only referenced znode can be long-term locked */ + _ergo(znode_is_locked(node), + atomic_read(&ZJNODE(node)->x_count) != 0); } /* debugging aid: check znode invariant and panic if it doesn't hold */ -int -znode_invariant(const znode * node /* znode to check */ ) +int znode_invariant(const znode * node /* znode to check */ ) { char const *failed_msg; int result; @@ -1045,9 +998,8 @@ znode_invariant(const znode * node /* zn } /* debugging aid: output human readable information about @node */ -static void -info_znode(const char *prefix /* prefix to print */ , - const znode * node /* node to print */ ) +static void info_znode(const char *prefix /* prefix to print */ , + const znode * node /* node to print */ ) { if (node == NULL) { return; @@ -1062,9 +1014,8 @@ info_znode(const char *prefix /* prefix /* debugging aid: output more human readable information about @node that info_znode(). */ -reiser4_internal void -print_znode(const char *prefix /* prefix to print */ , - const znode * node /* node to print */ ) +void print_znode(const char *prefix /* prefix to print */ , + const znode * node /* node to print */ ) { if (node == NULL) { printk("%s: null\n", prefix); @@ -1083,8 +1034,7 @@ print_znode(const char *prefix /* prefix } /* print all znodes in @tree */ -reiser4_internal void -print_znodes(const char *prefix, reiser4_tree * tree) +void print_znodes(const char *prefix, reiser4_tree * tree) { znode *node; znode *next; @@ -1097,7 +1047,7 @@ print_znodes(const char *prefix, reiser4 /* this is debugging function. It can be called by reiser4_panic() with tree spin-lock already held. Trylock is not exactly what we want here, but it is passable. - */ + */ tree_lock_taken = write_trylock_tree(tree); htable = &tree->zhash_table; @@ -1115,20 +1065,18 @@ print_znodes(const char *prefix, reiser4 } /* return non-0 iff data are loaded into znode */ -reiser4_internal int -znode_is_loaded(const znode * node /* znode to query */ ) +int znode_is_loaded(const znode * node /* znode to query */ ) { assert("nikita-497", node != NULL); return jnode_is_loaded(ZJNODE(node)); } -reiser4_internal unsigned long -znode_times_locked(const znode *z) +unsigned long znode_times_locked(const znode * z) { return z->times_locked; } -#endif /* REISER4_DEBUG */ +#endif /* REISER4_DEBUG */ /* Make Linus happy. Local variables: diff -puN fs/reiser4/znode.h~reiser4-big-update fs/reiser4/znode.h --- devel/fs/reiser4/znode.h~reiser4-big-update 2005-09-15 19:51:08.000000000 -0700 +++ devel-akpm/fs/reiser4/znode.h 2005-09-15 19:51:08.000000000 -0700 @@ -12,7 +12,6 @@ #include "spin_macros.h" #include "key.h" #include "coord.h" -#include "type_safe_list.h" #include "plugin/node/node.h" #include "jnode.h" #include "lock.h" @@ -27,8 +26,8 @@ /* znode tracks its position within parent (internal item in a parent node, * that contains znode's block number). */ typedef struct parent_coord { - znode *node; - pos_in_node_t item_pos; + znode *node; + pos_in_node_t item_pos; } parent_coord_t; /* &znode - node in a reiser4 tree. @@ -94,7 +93,7 @@ struct znode { in_parent->node points to the parent of this node, and is NOT a hint. - */ + */ parent_coord_t in_parent; /* @@ -108,7 +107,7 @@ struct znode { /* long term lock on node content. This lock supports deadlock detection. See lock.c - */ + */ zlock lock; /* You cannot remove from memory a node that has children in @@ -118,7 +117,7 @@ struct znode { removing it from memory you must decrease the c_count. This makes the code simpler, and the cases where it is suboptimal are truly obscure. - */ + */ int c_count; /* plugin of node attached to this znode. NULL if znode is not @@ -145,15 +144,16 @@ struct znode { void *creator; reiser4_key first_key; unsigned long times_locked; - int left_version; /* when node->left was updated */ - int right_version; /* when node->right was updated */ - int ld_key_version; /* when node->ld_key was updated */ - int rd_key_version; /* when node->rd_key was updated */ + int left_version; /* when node->left was updated */ + int right_version; /* when node->right was updated */ + int ld_key_version; /* when node->ld_key was updated */ + int rd_key_version; /* when node->rd_key was updated */ #endif -} __attribute__((aligned(16))); +} __attribute__ ((aligned(16))); -ON_DEBUG(extern atomic_t delim_key_version;) +ON_DEBUG(extern atomic_t delim_key_version; + ) /* In general I think these macros should not be exposed. */ #define znode_is_locked(node) (lock_is_locked(&node->lock)) @@ -162,17 +162,15 @@ ON_DEBUG(extern atomic_t delim_key_versi #define znode_is_wlocked_once(node) (lock_is_wlocked_once(&node->lock)) #define znode_can_be_rlocked(node) (lock_can_be_rlocked(&node->lock)) #define is_lock_compatible(node, mode) (lock_mode_compatible(&node->lock, mode)) - /* Macros for accessing the znode state. */ #define ZF_CLR(p,f) JF_CLR (ZJNODE(p), (f)) #define ZF_ISSET(p,f) JF_ISSET(ZJNODE(p), (f)) #define ZF_SET(p,f) JF_SET (ZJNODE(p), (f)) - extern znode *zget(reiser4_tree * tree, const reiser4_block_nr * const block, znode * parent, tree_level level, int gfp_flag); extern znode *zlook(reiser4_tree * tree, const reiser4_block_nr * const block); extern int zload(znode * node); -extern int zload_ra(znode * node, ra_info_t *info); +extern int zload_ra(znode * node, ra_info_t * info); extern int zinit_new(znode * node, int gfp_flags); extern void zrelse(znode * node); extern void znode_change_parent(znode * new_parent, reiser4_block_nr * block); @@ -185,8 +183,10 @@ znode_size(const znode * node UNUSED_ARG return PAGE_CACHE_SIZE; } -extern void parent_coord_to_coord(const parent_coord_t *pcoord, coord_t *coord); -extern void coord_to_parent_coord(const coord_t *coord, parent_coord_t *pcoord); +extern void parent_coord_to_coord(const parent_coord_t * pcoord, + coord_t * coord); +extern void coord_to_parent_coord(const coord_t * coord, + parent_coord_t * pcoord); extern void init_parent_coord(parent_coord_t * pcoord, const znode * node); extern unsigned znode_free_space(znode * node); @@ -198,49 +198,44 @@ extern reiser4_key *znode_set_rd_key(zno extern reiser4_key *znode_set_ld_key(znode * node, const reiser4_key * key); /* `connected' state checks */ -static inline int -znode_is_right_connected(const znode * node) +static inline int znode_is_right_connected(const znode * node) { return ZF_ISSET(node, JNODE_RIGHT_CONNECTED); } -static inline int -znode_is_left_connected(const znode * node) +static inline int znode_is_left_connected(const znode * node) { return ZF_ISSET(node, JNODE_LEFT_CONNECTED); } -static inline int -znode_is_connected(const znode * node) +static inline int znode_is_connected(const znode * node) { return znode_is_right_connected(node) && znode_is_left_connected(node); } +extern int znode_shift_order; extern int znode_rehash(znode * node, const reiser4_block_nr * new_block_nr); extern void znode_remove(znode *, reiser4_tree *); extern znode *znode_parent(const znode * node); extern znode *znode_parent_nolock(const znode * node); extern int znode_above_root(const znode * node); -extern int znodes_init(void); -extern int znodes_done(void); +extern int init_znodes(void); +extern void done_znodes(void); extern int znodes_tree_init(reiser4_tree * ztree); extern void znodes_tree_done(reiser4_tree * ztree); extern int znode_contains_key(znode * node, const reiser4_key * key); extern int znode_contains_key_lock(znode * node, const reiser4_key * key); extern unsigned znode_save_free_space(znode * node); extern unsigned znode_recover_free_space(znode * node); +extern znode *zalloc(unsigned int gfp_flag); +extern void zinit(znode *, const znode * parent, reiser4_tree *); +extern int zparse(znode * node); + extern int znode_just_created(const znode * node); extern void zfree(znode * node); -/* -#define znode_pre_write(n) noop -#define znode_post_write(n) noop -#define znode_set_checksum(n, l) noop -#define znode_at_read(n) (1) -*/ - #if REISER4_DEBUG extern void print_znode(const char *prefix, const znode * node); extern void print_znodes(const char *prefix, reiser4_tree * tree); @@ -278,31 +273,27 @@ extern int znode_invariant(const znode * #endif /* acquire reference to @node */ -static inline znode * -zref(znode * node) +static inline znode *zref(znode * node) { /* change of x_count from 0 to 1 is protected by tree spin-lock */ return JZNODE(jref(ZJNODE(node))); } /* release reference to @node */ -static inline void -zput(znode * node) +static inline void zput(znode * node) { assert("nikita-3564", znode_invariant(node)); jput(ZJNODE(node)); } /* get the level field for a znode */ -static inline tree_level -znode_get_level(const znode * node) +static inline tree_level znode_get_level(const znode * node) { return node->level; } /* get the level field for a jnode */ -static inline tree_level -jnode_get_level(const jnode * node) +static inline tree_level jnode_get_level(const jnode * node) { if (jnode_is_znode(node)) return znode_get_level(JZNODE(node)); @@ -323,16 +314,14 @@ static inline int jnode_is_leaf(const jn } /* return znode's tree */ -static inline reiser4_tree * -znode_get_tree(const znode * node) +static inline reiser4_tree *znode_get_tree(const znode * node) { assert("nikita-2692", node != NULL); return jnode_get_tree(ZJNODE(node)); } /* resolve race with zput */ -static inline znode * -znode_rip_check(reiser4_tree *tree, znode * node) +static inline znode *znode_rip_check(reiser4_tree * tree, znode * node) { jnode *j; @@ -344,7 +333,7 @@ znode_rip_check(reiser4_tree *tree, znod return node; } -#if defined(REISER4_DEBUG) || defined(REISER4_DEBUG_MODIFY) || defined(REISER4_DEBUG_OUTPUT) +#if defined(REISER4_DEBUG) int znode_is_loaded(const znode * node /* znode to query */ ); #endif @@ -367,8 +356,8 @@ extern void init_load_count(load_count * extern void done_load_count(load_count * dh); /* Finalize a load_count: call zrelse() if necessary */ extern int incr_load_count_znode(load_count * dh, znode * node); /* Set the argument znode to the current node, call zload(). */ extern int incr_load_count_jnode(load_count * dh, jnode * node); /* If the argument jnode is formatted, do the same as - * incr_load_count_znode, otherwise do nothing (unformatted nodes - * don't require zload/zrelse treatment). */ + * incr_load_count_znode, otherwise do nothing (unformatted nodes + * don't require zload/zrelse treatment). */ extern void move_load_count(load_count * new, load_count * old); /* Move the contents of a load_count. Old handle is released. */ extern void copy_load_count(load_count * new, load_count * old); /* Copy the contents of a load_count. Old handle remains held. */ @@ -417,7 +406,6 @@ extern void copy_load_count(load_count * WITH_DATA(__coord->node, exp); \ }) - #if REISER4_DEBUG #define STORE_COUNTERS \ lock_counters_info __entry_counters = *lock_counters() _