X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fntfs%2Fcompress.c;h=68a607ff9fd36d2f7e62b76546392029ff1111a7;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=c39391bab1d944c2ffd116e73f952d2075917c7f;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c index c39391bab..68a607ff9 100644 --- a/fs/ntfs/compress.c +++ b/fs/ntfs/compress.c @@ -24,7 +24,11 @@ #include #include #include +#include +#include "attrib.h" +#include "inode.h" +#include "debug.h" #include "ntfs.h" /** @@ -58,12 +62,12 @@ static u8 *ntfs_compression_buffer = NULL; /** * ntfs_cb_lock - spinlock which protects ntfs_compression_buffer */ -static spinlock_t ntfs_cb_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(ntfs_cb_lock); /** * allocate_compression_buffers - allocate the decompression buffers * - * Caller has to hold the ntfs_lock semaphore. + * Caller has to hold the ntfs_lock mutex. * * Return 0 on success or -ENOMEM if the allocations failed. */ @@ -80,7 +84,7 @@ int allocate_compression_buffers(void) /** * free_compression_buffers - free the decompression buffers * - * Caller has to hold the ntfs_lock semaphore. + * Caller has to hold the ntfs_lock mutex. */ void free_compression_buffers(void) { @@ -92,13 +96,14 @@ void free_compression_buffers(void) /** * zero_partial_compressed_page - zero out of bounds compressed page region */ -static void zero_partial_compressed_page(ntfs_inode *ni, struct page *page) +static void zero_partial_compressed_page(struct page *page, + const s64 initialized_size) { u8 *kp = page_address(page); unsigned int kp_ofs; ntfs_debug("Zeroing page region outside initialized size."); - if (((s64)page->index << PAGE_CACHE_SHIFT) >= ni->initialized_size) { + if (((s64)page->index << PAGE_CACHE_SHIFT) >= initialized_size) { /* * FIXME: Using clear_page() will become wrong when we get * PAGE_CACHE_SIZE != PAGE_SIZE but for now there is no problem. @@ -106,7 +111,7 @@ static void zero_partial_compressed_page(ntfs_inode *ni, struct page *page) clear_page(kp); return; } - kp_ofs = ni->initialized_size & ~PAGE_CACHE_MASK; + kp_ofs = initialized_size & ~PAGE_CACHE_MASK; memset(kp + kp_ofs, 0, PAGE_CACHE_SIZE - kp_ofs); return; } @@ -114,12 +119,12 @@ static void zero_partial_compressed_page(ntfs_inode *ni, struct page *page) /** * handle_bounds_compressed_page - test for&handle out of bounds compressed page */ -static inline void handle_bounds_compressed_page(ntfs_inode *ni, - struct page *page) +static inline void handle_bounds_compressed_page(struct page *page, + const loff_t i_size, const s64 initialized_size) { - if ((page->index >= (ni->initialized_size >> PAGE_CACHE_SHIFT)) && - (ni->initialized_size < VFS_I(ni)->i_size)) - zero_partial_compressed_page(ni, page); + if ((page->index >= (initialized_size >> PAGE_CACHE_SHIFT)) && + (initialized_size < i_size)) + zero_partial_compressed_page(page, initialized_size); return; } @@ -134,6 +139,8 @@ static inline void handle_bounds_compressed_page(ntfs_inode *ni, * @xpage_done: set to 1 if xpage was completed successfully (IN/OUT) * @cb_start: compression block to decompress (IN) * @cb_size: size of compression block @cb_start in bytes (IN) + * @i_size: file size when we started the read (IN) + * @initialized_size: initialized file size when we started the read (IN) * * The caller must have disabled preemption. ntfs_decompress() reenables it when * the critical section is finished. @@ -161,7 +168,8 @@ static inline void handle_bounds_compressed_page(ntfs_inode *ni, static int ntfs_decompress(struct page *dest_pages[], int *dest_index, int *dest_ofs, const int dest_max_index, const int dest_max_ofs, const int xpage, char *xpage_done, u8 *const cb_start, - const u32 cb_size) + const u32 cb_size, const loff_t i_size, + const s64 initialized_size) { /* * Pointers into the compressed data, i.e. the compression block (cb), @@ -203,7 +211,7 @@ do_next_sb: * position in the compression block is one byte before its end so the * first two checks do not detect it. */ - if (cb == cb_end || !le16_to_cpup((u16*)cb) || + if (cb == cb_end || !le16_to_cpup((le16*)cb) || (*dest_index == dest_max_index && *dest_ofs == dest_max_ofs)) { int i; @@ -215,9 +223,6 @@ return_error: spin_unlock(&ntfs_cb_lock); /* Second stage: finalize completed pages. */ if (nr_completed_pages > 0) { - struct page *page = dest_pages[completed_pages[0]]; - ntfs_inode *ni = NTFS_I(page->mapping->host); - for (i = 0; i < nr_completed_pages; i++) { int di = completed_pages[i]; @@ -226,7 +231,8 @@ return_error: * If we are outside the initialized size, zero * the out of bounds page range. */ - handle_bounds_compressed_page(ni, dp); + handle_bounds_compressed_page(dp, i_size, + initialized_size); flush_dcache_page(dp); kunmap(dp); SetPageUptodate(dp); @@ -255,7 +261,7 @@ return_error: /* Setup the current sub-block source pointers and validate range. */ cb_sb_start = cb; - cb_sb_end = cb_sb_start + (le16_to_cpup((u16*)cb) & NTFS_SB_SIZE_MASK) + cb_sb_end = cb_sb_start + (le16_to_cpup((le16*)cb) & NTFS_SB_SIZE_MASK) + 3; if (cb_sb_end > cb_end) goto return_overflow; @@ -277,7 +283,7 @@ return_error: dp_addr = (u8*)page_address(dp) + do_sb_start; /* Now, we are ready to process the current sub-block (sb). */ - if (!(le16_to_cpup((u16*)cb) & NTFS_SB_IS_COMPRESSED)) { + if (!(le16_to_cpup((le16*)cb) & NTFS_SB_IS_COMPRESSED)) { ntfs_debug("Found uncompressed sub-block."); /* This sb is not compressed, just copy it into destination. */ @@ -382,7 +388,7 @@ do_next_tag: lg++; /* Get the phrase token into i. */ - pt = le16_to_cpup((u16*)cb); + pt = le16_to_cpup((le16*)cb); /* * Calculate starting position of the byte sequence in @@ -474,12 +480,14 @@ return_overflow: */ int ntfs_read_compressed_block(struct page *page) { + loff_t i_size; + s64 initialized_size; struct address_space *mapping = page->mapping; ntfs_inode *ni = NTFS_I(mapping->host); ntfs_volume *vol = ni->vol; struct super_block *sb = vol->sb; - run_list_element *rl; - unsigned long block_size = sb->s_blocksize; + runlist_element *rl; + unsigned long flags, block_size = sb->s_blocksize; unsigned char block_size_bits = sb->s_blocksize_bits; u8 *cb, *cb_pos, *cb_end; struct buffer_head **bhs; @@ -531,7 +539,6 @@ int ntfs_read_compressed_block(struct page *page) if (unlikely(!pages || !bhs)) { kfree(bhs); kfree(pages); - SetPageError(page); unlock_page(page); ntfs_error(vol->sb, "Failed to allocate internal buffers."); return -ENOMEM; @@ -548,8 +555,12 @@ int ntfs_read_compressed_block(struct page *page) * The remaining pages need to be allocated and inserted into the page * cache, alignment guarantees keep all the below much simpler. (-8 */ - max_page = ((VFS_I(ni)->i_size + PAGE_CACHE_SIZE - 1) >> - PAGE_CACHE_SHIFT) - offset; + read_lock_irqsave(&ni->size_lock, flags); + i_size = i_size_read(VFS_I(ni)); + initialized_size = ni->initialized_size; + read_unlock_irqrestore(&ni->size_lock, flags); + max_page = ((i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) - + offset; if (nr_pages < max_page) max_page = nr_pages; for (i = 0; i < max_page; i++, offset++) { @@ -575,7 +586,7 @@ int ntfs_read_compressed_block(struct page *page) } /* - * We have the run list, and all the destination pages we need to fill. + * We have the runlist, and all the destination pages we need to fill. * Now read the first compression block. */ cur_page = 0; @@ -593,16 +604,16 @@ do_next_cb: if (!rl) { lock_retry_remap: - down_read(&ni->run_list.lock); - rl = ni->run_list.rl; + down_read(&ni->runlist.lock); + rl = ni->runlist.rl; } if (likely(rl != NULL)) { /* Seek to element containing target vcn. */ while (rl->length && rl[1].vcn <= vcn) rl++; - lcn = vcn_to_lcn(rl, vcn); + lcn = ntfs_rl_vcn_to_lcn(rl, vcn); } else - lcn = (LCN)LCN_RL_NOT_MAPPED; + lcn = LCN_RL_NOT_MAPPED; ntfs_debug("Reading vcn = 0x%llx, lcn = 0x%llx.", (unsigned long long)vcn, (unsigned long long)lcn); @@ -617,11 +628,11 @@ lock_retry_remap: goto rl_err; is_retry = TRUE; /* - * Attempt to map run list, dropping lock for the + * Attempt to map runlist, dropping lock for the * duration. */ - up_read(&ni->run_list.lock); - if (!map_run_list(ni, vcn)) + up_read(&ni->runlist.lock); + if (!ntfs_map_runlist(ni, vcn)) goto lock_retry_remap; goto map_rl_err; } @@ -638,7 +649,7 @@ lock_retry_remap: /* Release the lock if we took it. */ if (rl) - up_read(&ni->run_list.lock); + up_read(&ni->runlist.lock); /* Setup and initiate io on all buffer heads. */ for (i = 0; i < nr_bhs; i++) { @@ -820,7 +831,8 @@ lock_retry_remap: * If we are outside the initialized size, zero * the out of bounds page range. */ - handle_bounds_compressed_page(ni, page); + handle_bounds_compressed_page(page, i_size, + initialized_size); flush_dcache_page(page); kunmap(page); SetPageUptodate(page); @@ -843,7 +855,8 @@ lock_retry_remap: ntfs_debug("Found compressed compression block."); err = ntfs_decompress(pages, &cur_page, &cur_ofs, cb_max_page, cb_max_ofs, xpage, &xpage_done, - cb_pos, cb_size - (cb_pos - cb)); + cb_pos, cb_size - (cb_pos - cb), i_size, + initialized_size); /* * We can sleep from now on, lock already dropped by * ntfs_decompress(). @@ -857,9 +870,6 @@ lock_retry_remap: for (; prev_cur_page < cur_page; prev_cur_page++) { page = pages[prev_cur_page]; if (page) { - if (prev_cur_page == xpage && - !xpage_done) - SetPageError(page); flush_dcache_page(page); kunmap(page); unlock_page(page); @@ -890,8 +900,6 @@ lock_retry_remap: "Terminating them with extreme " "prejudice. Inode 0x%lx, page index " "0x%lx.", ni->mft_no, page->index); - if (cur_page == xpage && !xpage_done) - SetPageError(page); flush_dcache_page(page); kunmap(page); unlock_page(page); @@ -920,18 +928,18 @@ read_err: goto err_out; map_rl_err: - ntfs_error(vol->sb, "map_run_list() failed. Cannot read compression " - "block."); + ntfs_error(vol->sb, "ntfs_map_runlist() failed. Cannot read " + "compression block."); goto err_out; rl_err: - up_read(&ni->run_list.lock); - ntfs_error(vol->sb, "vcn_to_lcn() failed. Cannot read compression " - "block."); + up_read(&ni->runlist.lock); + ntfs_error(vol->sb, "ntfs_rl_vcn_to_lcn() failed. Cannot read " + "compression block."); goto err_out; getblk_err: - up_read(&ni->run_list.lock); + up_read(&ni->runlist.lock); ntfs_error(vol->sb, "getblk() failed. Cannot read compression block."); err_out: @@ -939,8 +947,6 @@ err_out: for (i = cur_page; i < max_page; i++) { page = pages[i]; if (page) { - if (i == xpage && !xpage_done) - SetPageError(page); flush_dcache_page(page); kunmap(page); unlock_page(page);