From db30d160cd8dfe1e53435fd76f4189778f1c728e Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Thu, 11 Nov 2004 12:42:00 +0000 Subject: NTFS: Use i_size_read() once and then use the cached value in fs/ntfs/lcnalloc.c::ntfs_cluster_alloc(). Signed-off-by: Anton Altaparmakov --- fs/ntfs/lcnalloc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'fs/ntfs/lcnalloc.c') diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c index 23fd911078b..5346596fa87 100644 --- a/fs/ntfs/lcnalloc.c +++ b/fs/ntfs/lcnalloc.c @@ -140,6 +140,7 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn, LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn; LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size; s64 clusters; + loff_t i_size; struct inode *lcnbmp_vi; runlist_element *rl = NULL; struct address_space *mapping; @@ -249,6 +250,7 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn, clusters = count; rlpos = rlsize = 0; mapping = lcnbmp_vi->i_mapping; + i_size = i_size_read(lcnbmp_vi); while (1) { ntfs_debug("Start of outer while loop: done_zones 0x%x, " "search_zone %i, pass %i, zone_start 0x%llx, " @@ -263,7 +265,7 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn, last_read_pos = bmp_pos >> 3; ntfs_debug("last_read_pos 0x%llx.", (unsigned long long)last_read_pos); - if (last_read_pos > lcnbmp_vi->i_size) { + if (last_read_pos > i_size) { ntfs_debug("End of attribute reached. " "Skipping to zone_pass_done."); goto zone_pass_done; @@ -287,8 +289,8 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn, buf_size = last_read_pos & ~PAGE_CACHE_MASK; buf = page_address(page) + buf_size; buf_size = PAGE_CACHE_SIZE - buf_size; - if (unlikely(last_read_pos + buf_size > lcnbmp_vi->i_size)) - buf_size = lcnbmp_vi->i_size - last_read_pos; + if (unlikely(last_read_pos + buf_size > i_size)) + buf_size = i_size - last_read_pos; buf_size <<= 3; lcn = bmp_pos & 7; bmp_pos &= ~7; -- cgit v1.2.3-70-g09d2 From b6ad6c52fe36ab35d0fe28c064f59de2ba670c2a Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Tue, 15 Feb 2005 10:08:43 +0000 Subject: NTFS: - Split ntfs_map_runlist() into ntfs_map_runlist() and a non-locking helper ntfs_map_runlist_nolock() which is used by ntfs_map_runlist(). This allows us to map runlist fragments with the runlist lock already held without having to drop and reacquire it around the call. Adapt all callers. - Change ntfs_find_vcn() to ntfs_find_vcn_nolock() which takes a locked runlist. This allows us to find runlist elements with the runlist lock already held without having to drop and reacquire it around the call. Adapt all callers. Signed-off-by: Anton Altaparmakov --- fs/ntfs/ChangeLog | 9 +++++ fs/ntfs/aops.c | 34 +++++------------ fs/ntfs/attrib.c | 107 +++++++++++++++++++++++++++++++---------------------- fs/ntfs/attrib.h | 5 ++- fs/ntfs/lcnalloc.c | 39 ++++++------------- fs/ntfs/mft.c | 38 +++++++++++-------- 6 files changed, 119 insertions(+), 113 deletions(-) (limited to 'fs/ntfs/lcnalloc.c') diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index b40c334e616..9d42393c16c 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -63,6 +63,15 @@ ToDo/Notes: - Fix a bug in fs/ntfs/runlist.c::ntfs_mapping_pairs_decompress() in the creation of the unmapped runlist element for the base attribute extent. + - Split ntfs_map_runlist() into ntfs_map_runlist() and a non-locking + helper ntfs_map_runlist_nolock() which is used by ntfs_map_runlist(). + This allows us to map runlist fragments with the runlist lock already + held without having to drop and reacquire it around the call. Adapt + all callers. + - Change ntfs_find_vcn() to ntfs_find_vcn_nolock() which takes a locked + runlist. This allows us to find runlist elements with the runlist + lock already held without having to drop and reacquire it around the + call. Adapt all callers. 2.1.22 - Many bug and race fixes and error handling improvements. diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index 812d53e9335..2b4b8b9e879 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c @@ -2,7 +2,7 @@ * aops.c - NTFS kernel address space operations and page cache handling. * Part of the Linux-NTFS project. * - * Copyright (c) 2001-2004 Anton Altaparmakov + * Copyright (c) 2001-2005 Anton Altaparmakov * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or @@ -135,7 +135,7 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate) i * rec_size), rec_size); flush_dcache_page(page); kunmap_atomic(addr, KM_BIO_SRC_IRQ); - if (likely(!PageError(page) && page_uptodate)) + if (likely(page_uptodate && !PageError(page))) SetPageUptodate(page); } unlock_page(page); @@ -347,11 +347,11 @@ handle_zblock: */ static int ntfs_readpage(struct file *file, struct page *page) { - loff_t i_size; ntfs_inode *ni, *base_ni; u8 *kaddr; ntfs_attr_search_ctx *ctx; MFT_RECORD *mrec; + unsigned long flags; u32 attr_len; int err = 0; @@ -389,9 +389,9 @@ static int ntfs_readpage(struct file *file, struct page *page) * Attribute is resident, implying it is not compressed or encrypted. * This also means the attribute is smaller than an mft record and * hence smaller than a page, so can simply zero out any pages with - * index above 0. We can also do this if the file size is 0. + * index above 0. */ - if (unlikely(page->index > 0 || !i_size_read(VFS_I(ni)))) { + if (unlikely(page->index > 0)) { kaddr = kmap_atomic(page, KM_USER0); memset(kaddr, 0, PAGE_CACHE_SIZE); flush_dcache_page(page); @@ -418,9 +418,10 @@ static int ntfs_readpage(struct file *file, struct page *page) if (unlikely(err)) goto put_unm_err_out; attr_len = le32_to_cpu(ctx->attr->data.resident.value_length); - i_size = i_size_read(VFS_I(ni)); - if (unlikely(attr_len > i_size)) - attr_len = i_size; + read_lock_irqsave(&ni->size_lock, flags); + if (unlikely(attr_len > ni->initialized_size)) + attr_len = ni->initialized_size; + read_unlock_irqrestore(&ni->size_lock, flags); kaddr = kmap_atomic(page, KM_USER0); /* Copy the data to the page. */ memcpy(kaddr, (u8*)ctx->attr + @@ -1247,20 +1248,6 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc) int err; BUG_ON(!PageLocked(page)); - /* - * If a previous ntfs_truncate() failed, repeat it and abort if it - * fails again. - */ - if (unlikely(NInoTruncateFailed(ni))) { - down_write(&vi->i_alloc_sem); - err = ntfs_truncate(vi); - up_write(&vi->i_alloc_sem); - if (err || NInoTruncateFailed(ni)) { - if (!err) - err = -EIO; - goto err_out; - } - } i_size = i_size_read(vi); /* Is the page fully outside i_size? (truncate in progress) */ if (unlikely(page->index >= (i_size + PAGE_CACHE_SIZE - 1) >> @@ -1490,13 +1477,12 @@ static int ntfs_prepare_nonresident_write(struct page *page, read_lock_irqsave(&ni->size_lock, flags); /* - * The first out of bounds block for the allocated size. No need to + * The first out of bounds block for the allocated size. No need to * round up as allocated_size is in multiples of cluster size and the * minimum cluster size is 512 bytes, which is equal to the smallest * blocksize. */ ablock = ni->allocated_size >> blocksize_bits; - i_size = i_size_read(vi); initialized_size = ni->initialized_size; read_unlock_irqrestore(&ni->size_lock, flags); diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 7d668466dcd..7a16f7ca76d 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c @@ -1,7 +1,7 @@ /** * attrib.c - NTFS attribute operations. Part of the Linux-NTFS project. * - * Copyright (c) 2001-2004 Anton Altaparmakov + * Copyright (c) 2001-2005 Anton Altaparmakov * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or @@ -30,7 +30,7 @@ #include "types.h" /** - * ntfs_map_runlist - map (a part of) a runlist of an ntfs inode + * ntfs_map_runlist_nolock - map (a part of) a runlist of an ntfs inode * @ni: ntfs inode for which to map (part of) a runlist * @vcn: map runlist part containing this vcn * @@ -38,24 +38,23 @@ * * Return 0 on success and -errno on error. * - * Locking: - The runlist must be unlocked on entry and is unlocked on return. - * - This function takes the lock for writing and modifies the runlist. + * Locking: - The runlist must be locked for writing. + * - This function modifies the runlist. */ -int ntfs_map_runlist(ntfs_inode *ni, VCN vcn) +int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn) { ntfs_inode *base_ni; - ntfs_attr_search_ctx *ctx; MFT_RECORD *mrec; + ntfs_attr_search_ctx *ctx; + runlist_element *rl; int err = 0; ntfs_debug("Mapping runlist part containing vcn 0x%llx.", (unsigned long long)vcn); - if (!NInoAttr(ni)) base_ni = ni; else base_ni = ni->ext.base_ntfs_ino; - mrec = map_mft_record(base_ni); if (IS_ERR(mrec)) return PTR_ERR(mrec); @@ -66,15 +65,7 @@ int ntfs_map_runlist(ntfs_inode *ni, VCN vcn) } err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len, CASE_SENSITIVE, vcn, NULL, 0, ctx); - if (unlikely(err)) - goto put_err_out; - - down_write(&ni->runlist.lock); - /* Make sure someone else didn't do the work while we were sleeping. */ - if (likely(ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn) <= - LCN_RL_NOT_MAPPED)) { - runlist_element *rl; - + if (likely(!err)) { rl = ntfs_mapping_pairs_decompress(ni->vol, ctx->attr, ni->runlist.rl); if (IS_ERR(rl)) @@ -82,9 +73,6 @@ int ntfs_map_runlist(ntfs_inode *ni, VCN vcn) else ni->runlist.rl = rl; } - up_write(&ni->runlist.lock); - -put_err_out: ntfs_attr_put_search_ctx(ctx); err_out: unmap_mft_record(base_ni); @@ -92,17 +80,45 @@ err_out: } /** - * ntfs_find_vcn - find a vcn in the runlist described by an ntfs inode - * @ni: ntfs inode describing the runlist to search - * @vcn: vcn to find - * @need_write: if false, lock for reading and if true, lock for writing + * ntfs_map_runlist - map (a part of) a runlist of an ntfs inode + * @ni: ntfs inode for which to map (part of) a runlist + * @vcn: map runlist part containing this vcn + * + * Map the part of a runlist containing the @vcn of the ntfs inode @ni. + * + * Return 0 on success and -errno on error. + * + * Locking: - The runlist must be unlocked on entry and is unlocked on return. + * - This function takes the runlist lock for writing and modifies the + * runlist. + */ +int ntfs_map_runlist(ntfs_inode *ni, VCN vcn) +{ + int err = 0; + + down_write(&ni->runlist.lock); + /* Make sure someone else didn't do the work while we were sleeping. */ + if (likely(ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn) <= + LCN_RL_NOT_MAPPED)) + err = ntfs_map_runlist_nolock(ni, vcn); + up_write(&ni->runlist.lock); + return err; +} + +/** + * ntfs_find_vcn_nolock - find a vcn in the runlist described by an ntfs inode + * @ni: ntfs inode describing the runlist to search + * @vcn: vcn to find + * @write_locked: true if the runlist is locked for writing * * Find the virtual cluster number @vcn in the runlist described by the ntfs * inode @ni and return the address of the runlist element containing the @vcn. - * The runlist is left locked and the caller has to unlock it. If @need_write - * is true, the runlist is locked for writing and if @need_write is false, the - * runlist is locked for reading. In the error case, the runlist is not left - * locked. + * The runlist is left locked and the caller has to unlock it. In the error + * case, the runlist is left in the same locking state as on entry. + * + * Note if @write_locked is FALSE the lock may be dropped inside the function + * so you cannot rely on the runlist still being the same when this function + * returns. * * Note you need to distinguish between the lcn of the returned runlist element * being >= 0 and LCN_HOLE. In the later case you have to return zeroes on @@ -124,28 +140,24 @@ err_out: * true, it is locked for writing. Otherwise is is locked for * reading. */ -runlist_element *ntfs_find_vcn(ntfs_inode *ni, const VCN vcn, - const BOOL need_write) +runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, + const BOOL write_locked) { runlist_element *rl; int err = 0; BOOL is_retry = FALSE; - ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, lock for %sing.", + ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, %s_locked.", ni->mft_no, (unsigned long long)vcn, - !need_write ? "read" : "writ"); + write_locked ? "write" : "read"); BUG_ON(!ni); BUG_ON(!NInoNonResident(ni)); BUG_ON(vcn < 0); -lock_retry_remap: - if (!need_write) - down_read(&ni->runlist.lock); - else - down_write(&ni->runlist.lock); +retry_remap: rl = ni->runlist.rl; if (likely(rl && vcn >= rl[0].vcn)) { while (likely(rl->length)) { - if (likely(vcn < rl[1].vcn)) { + if (unlikely(vcn < rl[1].vcn)) { if (likely(rl->lcn >= LCN_HOLE)) { ntfs_debug("Done."); return rl; @@ -161,19 +173,23 @@ lock_retry_remap: err = -EIO; } } - if (!need_write) - up_read(&ni->runlist.lock); - else - up_write(&ni->runlist.lock); if (!err && !is_retry) { /* * The @vcn is in an unmapped region, map the runlist and * retry. */ - err = ntfs_map_runlist(ni, vcn); + if (!write_locked) { + up_read(&ni->runlist.lock); + down_write(&ni->runlist.lock); + } + err = ntfs_map_runlist_nolock(ni, vcn); + if (!write_locked) { + up_write(&ni->runlist.lock); + down_read(&ni->runlist.lock); + } if (likely(!err)) { is_retry = TRUE; - goto lock_retry_remap; + goto retry_remap; } /* * -EINVAL and -ENOENT coming from a failed mapping attempt are @@ -184,7 +200,8 @@ lock_retry_remap: err = -EIO; } else if (!err) err = -EIO; - ntfs_error(ni->vol->sb, "Failed with error code %i.", err); + if (err != -ENOENT) + ntfs_error(ni->vol->sb, "Failed with error code %i.", err); return ERR_PTR(err); } diff --git a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h index e0c2c6c81bc..3eb45165702 100644 --- a/fs/ntfs/attrib.h +++ b/fs/ntfs/attrib.h @@ -60,10 +60,11 @@ typedef struct { ATTR_RECORD *base_attr; } ntfs_attr_search_ctx; +extern int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn); extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn); -extern runlist_element *ntfs_find_vcn(ntfs_inode *ni, const VCN vcn, - const BOOL need_write); +extern runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, + const BOOL write_locked); int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name, const u32 name_len, const IGNORE_CASE_BOOL ic, diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c index 5346596fa87..8db4492b139 100644 --- a/fs/ntfs/lcnalloc.c +++ b/fs/ntfs/lcnalloc.c @@ -849,7 +849,8 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, total_freed = real_freed = 0; /* This returns with ni->runlist locked for reading on success. */ - rl = ntfs_find_vcn(ni, start_vcn, FALSE); + down_read(&ni->runlist.lock); + rl = ntfs_find_vcn_nolock(ni, start_vcn, FALSE); if (IS_ERR(rl)) { if (!is_rollback) ntfs_error(vol->sb, "Failed to find first runlist " @@ -863,7 +864,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, ntfs_error(vol->sb, "First runlist element has " "invalid lcn, aborting."); err = -EIO; - goto unl_err_out; + goto err_out; } /* Find the starting cluster inside the run that needs freeing. */ delta = start_vcn - rl->vcn; @@ -881,7 +882,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, if (!is_rollback) ntfs_error(vol->sb, "Failed to clear first run " "(error %i), aborting.", err); - goto unl_err_out; + goto err_out; } /* We have freed @to_free real clusters. */ real_freed = to_free; @@ -901,30 +902,15 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, if (unlikely(rl->lcn < LCN_HOLE)) { VCN vcn; - /* - * Attempt to map runlist, dropping runlist lock for - * the duration. - */ + /* Attempt to map runlist. */ vcn = rl->vcn; - up_read(&ni->runlist.lock); - err = ntfs_map_runlist(ni, vcn); - if (err) { - if (!is_rollback) - ntfs_error(vol->sb, "Failed to map " - "runlist fragment."); - if (err == -EINVAL || err == -ENOENT) - err = -EIO; - goto err_out; - } - /* - * This returns with ni->runlist locked for reading on - * success. - */ - rl = ntfs_find_vcn(ni, vcn, FALSE); + rl = ntfs_find_vcn_nolock(ni, vcn, FALSE); if (IS_ERR(rl)) { err = PTR_ERR(rl); if (!is_rollback) - ntfs_error(vol->sb, "Failed to find " + ntfs_error(vol->sb, "Failed to map " + "runlist fragment or " + "failed to find " "subsequent runlist " "element."); goto err_out; @@ -937,7 +923,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, (unsigned long long) rl->lcn); err = -EIO; - goto unl_err_out; + goto err_out; } } /* The number of clusters in this run that need freeing. */ @@ -953,7 +939,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, if (!is_rollback) ntfs_error(vol->sb, "Failed to clear " "subsequent run."); - goto unl_err_out; + goto err_out; } /* We have freed @to_free real clusters. */ real_freed += to_free; @@ -974,9 +960,8 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, /* We are done. Return the number of actually freed clusters. */ ntfs_debug("Done."); return real_freed; -unl_err_out: - up_read(&ni->runlist.lock); err_out: + up_read(&ni->runlist.lock); if (is_rollback) return err; /* If no real clusters were freed, no need to rollback. */ diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 4e0bf39426c..0975d738834 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -1,7 +1,7 @@ /** * mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project. * - * Copyright (c) 2001-2004 Anton Altaparmakov + * Copyright (c) 2001-2005 Anton Altaparmakov * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or @@ -287,7 +287,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref, } unmap_mft_record(ni); ntfs_error(base_ni->vol->sb, "Found stale extent mft " - "reference! Corrupt file system. " + "reference! Corrupt filesystem. " "Run chkdsk."); return ERR_PTR(-EIO); } @@ -318,7 +318,7 @@ map_err_out: /* Verify the sequence number if it is present. */ if (seq_no && (le16_to_cpu(m->sequence_number) != seq_no)) { ntfs_error(base_ni->vol->sb, "Found stale extent mft " - "reference! Corrupt file system. Run chkdsk."); + "reference! Corrupt filesystem. Run chkdsk."); destroy_ni = TRUE; m = ERR_PTR(-EIO); goto unm_err_out; @@ -1292,19 +1292,20 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol) /* * Determine the last lcn of the mft bitmap. The allocated size of the * mft bitmap cannot be zero so we are ok to do this. - * ntfs_find_vcn() returns the runlist locked on success. */ + down_write(&mftbmp_ni->runlist.lock); read_lock_irqsave(&mftbmp_ni->size_lock, flags); ll = mftbmp_ni->allocated_size; read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); - rl = ntfs_find_vcn(mftbmp_ni, (ll - 1) >> vol->cluster_size_bits, TRUE); + rl = ntfs_find_vcn_nolock(mftbmp_ni, + (ll - 1) >> vol->cluster_size_bits, TRUE); if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { + up_write(&mftbmp_ni->runlist.lock); ntfs_error(vol->sb, "Failed to determine last allocated " "cluster of mft bitmap attribute."); - if (!IS_ERR(rl)) { - up_write(&mftbmp_ni->runlist.lock); + if (!IS_ERR(rl)) ret = -EIO; - } else + else ret = PTR_ERR(rl); return ret; } @@ -1428,6 +1429,8 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol) // TODO: Deal with this by moving this extent to a new mft // record or by starting a new extent in a new mft record or by // moving other attributes out of this mft record. + // Note: It will need to be a special mft record and if none of + // those are available it gets rather complicated... ntfs_error(vol->sb, "Not enough space in this mft record to " "accomodate extended mft bitmap attribute " "extent. Cannot handle this yet."); @@ -1719,19 +1722,20 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) * Determine the preferred allocation location, i.e. the last lcn of * the mft data attribute. The allocated size of the mft data * attribute cannot be zero so we are ok to do this. - * ntfs_find_vcn() returns the runlist locked on success. */ + down_write(&mft_ni->runlist.lock); read_lock_irqsave(&mft_ni->size_lock, flags); ll = mft_ni->allocated_size; read_unlock_irqrestore(&mft_ni->size_lock, flags); - rl = ntfs_find_vcn(mft_ni, (ll - 1) >> vol->cluster_size_bits, TRUE); + rl = ntfs_find_vcn_nolock(mft_ni, (ll - 1) >> vol->cluster_size_bits, + TRUE); if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { + up_write(&mft_ni->runlist.lock); ntfs_error(vol->sb, "Failed to determine last allocated " "cluster of mft data attribute."); - if (!IS_ERR(rl)) { - up_write(&mft_ni->runlist.lock); + if (!IS_ERR(rl)) ret = -EIO; - } else + else ret = PTR_ERR(rl); return ret; } @@ -1858,7 +1862,11 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) // moving other attributes out of this mft record. // Note: Use the special reserved mft records and ensure that // this extent is not required to find the mft record in - // question. + // question. If no free special records left we would need to + // move an existing record away, insert ours in its place, and + // then place the moved record into the newly allocated space + // and we would then need to update all references to this mft + // record appropriately. This is rather complicated... ntfs_error(vol->sb, "Not enough space in this mft record to " "accomodate extended mft data attribute " "extent. Cannot handle this yet."); @@ -2021,7 +2029,7 @@ static int ntfs_mft_record_layout(const ntfs_volume *vol, const s64 mft_no, "reports this as corruption, please email " "linux-ntfs-dev@lists.sourceforge.net stating " "that you saw this message and that the " - "modified file system created was corrupt. " + "modified filesystem created was corrupt. " "Thank you."); } /* Set the update sequence number to 1. */ -- cgit v1.2.3-70-g09d2 From 8907547d4b099e67762ea4891c127ea1f6dd1cb7 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 3 Mar 2005 11:19:53 +0000 Subject: NTFS: Fix printk format warnings on ia64. (Randy Dunlap) Signed-off-by: Randy Dunlap Signed-off-by: Anton Altaparmakov --- fs/ntfs/ChangeLog | 1 + fs/ntfs/aops.c | 3 ++- fs/ntfs/debug.c | 15 +++++++++------ fs/ntfs/inode.c | 12 ++++++------ fs/ntfs/lcnalloc.c | 2 +- fs/ntfs/mft.c | 2 +- 6 files changed, 20 insertions(+), 15 deletions(-) (limited to 'fs/ntfs/lcnalloc.c') diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index ad2c4e88f05..bfd86c5cc48 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -29,6 +29,7 @@ ToDo/Notes: compiled without debug. This avoids a possible denial of service attack. Thanks to Carl-Daniel Hailfinger from SuSE for pointing this out. + - Fix compilation warnings on ia64. (Randy Dunlap) - Use i_size_read() in fs/ntfs/attrib.c::ntfs_attr_set(). - Use i_size_read() in fs/ntfs/logfile.c::ntfs_{check,empty}_logfile(). - Use i_size_read() once and then use the cached value in diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index 2b4b8b9e879..2a7cba258cc 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c @@ -965,7 +965,8 @@ lock_retry_remap: "attribute type 0x%x) because " "its location on disk could " "not be determined (error " - "code %lli).", (s64)block << + "code %lli).", + (long long)block << bh_size_bits >> vol->mft_record_size_bits, ni->mft_no, ni->type, diff --git a/fs/ntfs/debug.c b/fs/ntfs/debug.c index 6fb6bb5e372..807150e2c2b 100644 --- a/fs/ntfs/debug.c +++ b/fs/ntfs/debug.c @@ -164,14 +164,17 @@ void ntfs_debug_dump_runlist(const runlist_element *rl) if (index > -LCN_ENOENT - 1) index = 3; printk(KERN_DEBUG "%-16Lx %s %-16Lx%s\n", - (rl + i)->vcn, lcn_str[index], - (rl + i)->length, (rl + i)->length ? - "" : " (runlist end)"); + (long long)(rl + i)->vcn, lcn_str[index], + (long long)(rl + i)->length, + (rl + i)->length ? "" : + " (runlist end)"); } else printk(KERN_DEBUG "%-16Lx %-16Lx %-16Lx%s\n", - (rl + i)->vcn, (rl + i)->lcn, - (rl + i)->length, (rl + i)->length ? - "" : " (runlist end)"); + (long long)(rl + i)->vcn, + (long long)(rl + i)->lcn, + (long long)(rl + i)->length, + (rl + i)->length ? "" : + " (runlist end)"); if (!(rl + i)->length) break; } diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index cfca1738411..7ae647c640b 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -2518,18 +2518,18 @@ int ntfs_write_inode(struct inode *vi, int sync) nt = utc2ntfs(vi->i_mtime); if (si->last_data_change_time != nt) { ntfs_debug("Updating mtime for inode 0x%lx: old = 0x%llx, " - "new = 0x%llx", vi->i_ino, + "new = 0x%llx", vi->i_ino, (long long) sle64_to_cpu(si->last_data_change_time), - sle64_to_cpu(nt)); + (long long)sle64_to_cpu(nt)); si->last_data_change_time = nt; modified = TRUE; } nt = utc2ntfs(vi->i_ctime); if (si->last_mft_change_time != nt) { ntfs_debug("Updating ctime for inode 0x%lx: old = 0x%llx, " - "new = 0x%llx", vi->i_ino, + "new = 0x%llx", vi->i_ino, (long long) sle64_to_cpu(si->last_mft_change_time), - sle64_to_cpu(nt)); + (long long)sle64_to_cpu(nt)); si->last_mft_change_time = nt; modified = TRUE; } @@ -2537,8 +2537,8 @@ int ntfs_write_inode(struct inode *vi, int sync) if (si->last_access_time != nt) { ntfs_debug("Updating atime for inode 0x%lx: old = 0x%llx, " "new = 0x%llx", vi->i_ino, - sle64_to_cpu(si->last_access_time), - sle64_to_cpu(nt)); + (long long)sle64_to_cpu(si->last_access_time), + (long long)sle64_to_cpu(nt)); si->last_access_time = nt; modified = TRUE; } diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c index 8db4492b139..f2b7f8582c5 100644 --- a/fs/ntfs/lcnalloc.c +++ b/fs/ntfs/lcnalloc.c @@ -763,7 +763,7 @@ out: "could allocate up to 0x%llx " "clusters.", (unsigned long long)rl[0].lcn, - (unsigned long long)count - clusters); + (unsigned long long)(count - clusters)); /* Deallocate all allocated clusters. */ ntfs_debug("Attempting rollback..."); err2 = ntfs_cluster_free_from_rl_nolock(vol, rl); diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 0975d738834..66ef6e275a4 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -1802,7 +1802,7 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) return PTR_ERR(rl); } mft_ni->runlist.rl = rl; - ntfs_debug("Allocated %lli clusters.", nr); + ntfs_debug("Allocated %lli clusters.", (long long)nr); /* Find the last run in the new runlist. */ for (; rl[1].length; rl++) ; -- cgit v1.2.3-70-g09d2 From c0c1cc0e46b36347f11b566f99087dc5e6fc1b89 Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Mon, 7 Mar 2005 21:43:38 +0000 Subject: NTFS: - Fix bug in fs/ntfs/attrib.c::ntfs_find_vcn_nolock() where after dropping the read lock and taking the write lock we were not checking whether someone else did not already do the work we wanted to do. - Rename ntfs_find_vcn_nolock() to ntfs_attr_find_vcn_nolock(). - Tidy up some comments in fs/ntfs/runlist.c. - Add LCN_ENOMEM and LCN_EIO definitions to fs/ntfs/runlist.h. Signed-off-by: Anton Altaparmakov --- fs/ntfs/ChangeLog | 5 +++++ fs/ntfs/attrib.c | 29 +++++++++++++++++------------ fs/ntfs/attrib.h | 4 ++-- fs/ntfs/lcnalloc.c | 4 ++-- fs/ntfs/mft.c | 6 +++--- fs/ntfs/runlist.c | 15 ++++++++------- fs/ntfs/runlist.h | 2 ++ 7 files changed, 39 insertions(+), 26 deletions(-) (limited to 'fs/ntfs/lcnalloc.c') diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 4af6ae6ff12..7507a56a492 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -92,6 +92,11 @@ ToDo/Notes: non-resident in fs/ntfs/attrib.c::ntfs_attr_can_be_non_resident(). - Add fs/ntfs/attrib.c::ntfs_attr_vcn_to_lcn_nolock() used by the new write code. + - Fix bug in fs/ntfs/attrib.c::ntfs_find_vcn_nolock() where after + dropping the read lock and taking the write lock we were not checking + whether someone else did not already do the work we wanted to do. + - Rename fs/ntfs/attrib.c::ntfs_find_vcn_nolock() to + ntfs_attr_find_vcn_nolock() and update all callers. 2.1.22 - Many bug and race fixes and error handling improvements. diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 1610f1cd286..6de5e04e97a 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c @@ -193,19 +193,19 @@ retry_remap: } /** - * ntfs_find_vcn_nolock - find a vcn in the runlist described by an ntfs inode + * ntfs_attr_find_vcn_nolock - find a vcn in the runlist of an ntfs inode * @ni: ntfs inode describing the runlist to search * @vcn: vcn to find * @write_locked: true if the runlist is locked for writing * * Find the virtual cluster number @vcn in the runlist described by the ntfs * inode @ni and return the address of the runlist element containing the @vcn. - * The runlist is left locked and the caller has to unlock it. In the error - * case, the runlist is left in the same locking state as on entry. * - * Note if @write_locked is FALSE the lock may be dropped inside the function - * so you cannot rely on the runlist still being the same when this function - * returns. + * If the @vcn is not mapped yet, the attempt is made to map the attribute + * extent containing the @vcn and the vcn to lcn conversion is retried. + * + * If @write_locked is true the caller has locked the runlist for writing and + * if false for reading. * * Note you need to distinguish between the lcn of the returned runlist element * being >= 0 and LCN_HOLE. In the later case you have to return zeroes on @@ -221,13 +221,12 @@ retry_remap: * -ENOMEM - Not enough memory to map runlist. * -EIO - Critical error (runlist/file is corrupt, i/o error, etc). * - * Locking: - The runlist must be unlocked on entry. - * - On failing return, the runlist is unlocked. - * - On successful return, the runlist is locked. If @need_write us - * true, it is locked for writing. Otherwise is is locked for - * reading. + * Locking: - The runlist must be locked on entry and is left locked on return. + * - If @write_locked is FALSE, i.e. the runlist is locked for reading, + * the lock may be dropped inside the function so you cannot rely on + * the runlist still being the same when this function returns. */ -runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, +runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, const BOOL write_locked) { runlist_element *rl; @@ -268,6 +267,12 @@ retry_remap: if (!write_locked) { up_read(&ni->runlist.lock); down_write(&ni->runlist.lock); + if (unlikely(ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn) != + LCN_RL_NOT_MAPPED)) { + up_write(&ni->runlist.lock); + down_read(&ni->runlist.lock); + goto retry_remap; + } } err = ntfs_map_runlist_nolock(ni, vcn); if (!write_locked) { diff --git a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h index 75041c89c73..e0a50f1ca76 100644 --- a/fs/ntfs/attrib.h +++ b/fs/ntfs/attrib.h @@ -66,8 +66,8 @@ extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn); extern LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn, const BOOL write_locked); -extern runlist_element *ntfs_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, - const BOOL write_locked); +extern runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, + const VCN vcn, const BOOL write_locked); int ntfs_attr_lookup(const ATTR_TYPE type, const ntfschar *name, const u32 name_len, const IGNORE_CASE_BOOL ic, diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c index f2b7f8582c5..6e584ab743c 100644 --- a/fs/ntfs/lcnalloc.c +++ b/fs/ntfs/lcnalloc.c @@ -850,7 +850,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, /* This returns with ni->runlist locked for reading on success. */ down_read(&ni->runlist.lock); - rl = ntfs_find_vcn_nolock(ni, start_vcn, FALSE); + rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, FALSE); if (IS_ERR(rl)) { if (!is_rollback) ntfs_error(vol->sb, "Failed to find first runlist " @@ -904,7 +904,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, /* Attempt to map runlist. */ vcn = rl->vcn; - rl = ntfs_find_vcn_nolock(ni, vcn, FALSE); + rl = ntfs_attr_find_vcn_nolock(ni, vcn, FALSE); if (IS_ERR(rl)) { err = PTR_ERR(rl); if (!is_rollback) diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 66ef6e275a4..61ce09f1b65 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -1297,7 +1297,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(ntfs_volume *vol) read_lock_irqsave(&mftbmp_ni->size_lock, flags); ll = mftbmp_ni->allocated_size; read_unlock_irqrestore(&mftbmp_ni->size_lock, flags); - rl = ntfs_find_vcn_nolock(mftbmp_ni, + rl = ntfs_attr_find_vcn_nolock(mftbmp_ni, (ll - 1) >> vol->cluster_size_bits, TRUE); if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { up_write(&mftbmp_ni->runlist.lock); @@ -1727,8 +1727,8 @@ static int ntfs_mft_data_extend_allocation_nolock(ntfs_volume *vol) read_lock_irqsave(&mft_ni->size_lock, flags); ll = mft_ni->allocated_size; read_unlock_irqrestore(&mft_ni->size_lock, flags); - rl = ntfs_find_vcn_nolock(mft_ni, (ll - 1) >> vol->cluster_size_bits, - TRUE); + rl = ntfs_attr_find_vcn_nolock(mft_ni, + (ll - 1) >> vol->cluster_size_bits, TRUE); if (unlikely(IS_ERR(rl) || !rl->length || rl->lcn < 0)) { up_write(&mft_ni->runlist.lock); ntfs_error(vol->sb, "Failed to determine last allocated " diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c index 1b344dd4d40..3f479f17661 100644 --- a/fs/ntfs/runlist.c +++ b/fs/ntfs/runlist.c @@ -933,17 +933,18 @@ err_out: * * It is up to the caller to serialize access to the runlist @rl. * - * Since lcns must be >= 0, we use negative return values with special meaning: + * Since lcns must be >= 0, we use negative return codes with special meaning: * - * Return value Meaning / Description + * Return code Meaning / Description * ================================================== - * -1 = LCN_HOLE Hole / not allocated on disk. - * -2 = LCN_RL_NOT_MAPPED This is part of the runlist which has not been - * inserted into the runlist yet. - * -3 = LCN_ENOENT There is no such vcn in the attribute. + * LCN_HOLE Hole / not allocated on disk. + * LCN_RL_NOT_MAPPED This is part of the runlist which has not been + * inserted into the runlist yet. + * LCN_ENOENT There is no such vcn in the attribute. * * Locking: - The caller must have locked the runlist (for reading or writing). - * - This function does not touch the lock. + * - This function does not touch the lock, nor does it modify the + * runlist. */ LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn) { diff --git a/fs/ntfs/runlist.h b/fs/ntfs/runlist.h index 7107fde59df..60c42f3a3fc 100644 --- a/fs/ntfs/runlist.h +++ b/fs/ntfs/runlist.h @@ -66,6 +66,8 @@ typedef enum { LCN_HOLE = -1, /* Keep this as highest value or die! */ LCN_RL_NOT_MAPPED = -2, LCN_ENOENT = -3, + LCN_ENOMEM = -4, + LCN_EIO = -5, } LCN_SPECIAL_VALUES; extern runlist_element *ntfs_runlists_merge(runlist_element *drl, -- cgit v1.2.3-70-g09d2 From 43b01fda8b17b2b63e7dcdeed11c2ebba56b1fc9 Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Wed, 9 Mar 2005 15:18:43 +0000 Subject: NTFS: Fix sign of various error return values to be negative in fs/ntfs/lcnalloc.c. Signed-off-by: Anton Altaparmakov --- fs/ntfs/ChangeLog | 2 ++ fs/ntfs/lcnalloc.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'fs/ntfs/lcnalloc.c') diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 71680a92b4d..e0b4adf5adc 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -98,6 +98,8 @@ ToDo/Notes: - Rename fs/ntfs/attrib.c::ntfs_find_vcn_nolock() to ntfs_attr_find_vcn_nolock() and update all callers. - Add fs/ntfs/attrib.[hc]::ntfs_attr_make_non_resident(). + - Fix sign of various error return values to be negative in + fs/ntfs/lcnalloc.c. 2.1.22 - Many bug and race fixes and error handling improvements. diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c index 6e584ab743c..71bf08730b0 100644 --- a/fs/ntfs/lcnalloc.c +++ b/fs/ntfs/lcnalloc.c @@ -1,7 +1,7 @@ /* * lcnalloc.c - Cluster (de)allocation code. Part of the Linux-NTFS project. * - * Copyright (c) 2004 Anton Altaparmakov + * Copyright (c) 2004-2005 Anton Altaparmakov * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -60,7 +60,7 @@ int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol, if (rl->lcn < 0) continue; err = ntfs_bitmap_clear_run(lcnbmp_vi, rl->lcn, rl->length); - if (unlikely(err && (!ret || ret == ENOMEM) && ret != err)) + if (unlikely(err && (!ret || ret == -ENOMEM) && ret != err)) ret = err; } ntfs_debug("Done."); @@ -693,7 +693,7 @@ switch_to_data1_zone: search_zone = 2; if (zone == MFT_ZONE || mft_zone_size <= 0) { ntfs_debug("No free clusters left, going to out."); /* Really no more space left on device. */ - err = ENOSPC; + err = -ENOSPC; goto out; } /* zone == DATA_ZONE && mft_zone_size > 0 */ ntfs_debug("Shrinking mft zone."); @@ -757,9 +757,9 @@ out: if (rl) { int err2; - if (err == ENOSPC) + if (err == -ENOSPC) ntfs_debug("Not enough space to complete allocation, " - "err ENOSPC, first free lcn 0x%llx, " + "err -ENOSPC, first free lcn 0x%llx, " "could allocate up to 0x%llx " "clusters.", (unsigned long long)rl[0].lcn, @@ -775,10 +775,10 @@ out: } /* Free the runlist. */ ntfs_free(rl); - } else if (err == ENOSPC) - ntfs_debug("No space left at all, err = ENOSPC, " - "first free lcn = 0x%llx.", - (unsigned long long)vol->data1_zone_pos); + } else if (err == -ENOSPC) + ntfs_debug("No space left at all, err = -ENOSPC, first free " + "lcn = 0x%llx.", + (long long)vol->data1_zone_pos); up_write(&vol->lcnbmp_lock); return ERR_PTR(err); } -- cgit v1.2.3-70-g09d2 From 53d59aad9326199ef5749c97513db498309a057e Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Thu, 17 Mar 2005 10:51:33 +0000 Subject: NTFS: Fix compilation when configured read-only. - Add ifdef NTFS_RW around write specific code if fs/ntfs/runlist.[hc] and fs/ntfs/attrib.[hc]. - Minor bugfix to fs/ntfs/attrib.c::ntfs_attr_make_non_resident() where the runlist was not freed in all error cases. - Add fs/ntfs/runlist.[hc]::ntfs_rl_find_vcn_nolock(). Signed-off-by: Anton Altaparmakov --- fs/ntfs/attrib.c | 13 ++++++++++++- fs/ntfs/attrib.h | 4 ++++ fs/ntfs/lcnalloc.c | 1 - fs/ntfs/runlist.c | 35 +++++++++++++++++++++++++++++++++++ fs/ntfs/runlist.h | 9 ++++++++- 5 files changed, 59 insertions(+), 3 deletions(-) (limited to 'fs/ntfs/lcnalloc.c') diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 97e6fb047aa..1b95f39234a 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c @@ -1057,6 +1057,8 @@ void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx) return; } +#ifdef NTFS_RW + /** * ntfs_attr_find_in_attrdef - find an attribute in the $AttrDef system file * @vol: ntfs volume to which the attribute belongs @@ -1243,6 +1245,13 @@ int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size) * -ENOSPC - Not enough disk space. * -EINVAL - Attribute not defined on the volume. * -EIO - I/o error or other error. + * Note that -ENOSPC is also returned in the case that there is not enough + * space in the mft record to do the conversion. This can happen when the mft + * record is already very full. The caller is responsible for trying to make + * space in the mft record and trying again. FIXME: Do we need a separate + * error return code for this kind of -ENOSPC or is it always worth trying + * again in case the attribute may then fit in a resident state so no need to + * make it non-resident at all? Ho-hum... (AIA) * * NOTE to self: No changes in the attribute list are required to move from * a resident to a non-resident attribute. @@ -1520,13 +1529,13 @@ err_out: rl_err_out: if (rl) { if (ntfs_cluster_free_from_rl(vol, rl) < 0) { - ntfs_free(rl); ntfs_error(vol->sb, "Failed to release allocated " "cluster(s) in error code path. Run " "chkdsk to recover the lost " "cluster(s)."); NVolSetErrors(vol); } + ntfs_free(rl); page_err_out: unlock_page(page); page_cache_release(page); @@ -1680,3 +1689,5 @@ done: ntfs_debug("Done."); return 0; } + +#endif /* NTFS_RW */ diff --git a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h index d7338519833..0e4ac6d3c0e 100644 --- a/fs/ntfs/attrib.h +++ b/fs/ntfs/attrib.h @@ -89,6 +89,8 @@ extern ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec); extern void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx); +#ifdef NTFS_RW + extern int ntfs_attr_size_bounds_check(const ntfs_volume *vol, const ATTR_TYPE type, const s64 size); extern int ntfs_attr_can_be_non_resident(const ntfs_volume *vol, @@ -103,4 +105,6 @@ extern int ntfs_attr_make_non_resident(ntfs_inode *ni); extern int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val); +#endif /* NTFS_RW */ + #endif /* _LINUX_NTFS_ATTRIB_H */ diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c index 71bf08730b0..7087b5b0e6c 100644 --- a/fs/ntfs/lcnalloc.c +++ b/fs/ntfs/lcnalloc.c @@ -848,7 +848,6 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, total_freed = real_freed = 0; - /* This returns with ni->runlist locked for reading on success. */ down_read(&ni->runlist.lock); rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, FALSE); if (IS_ERR(rl)) { diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c index 3f479f17661..396d767c2ca 100644 --- a/fs/ntfs/runlist.c +++ b/fs/ntfs/runlist.c @@ -980,6 +980,39 @@ LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn) return LCN_ENOENT; } +#ifdef NTFS_RW + +/** + * ntfs_rl_find_vcn_nolock - find a vcn in a runlist + * @rl: runlist to search + * @vcn: vcn to find + * + * Find the virtual cluster number @vcn in the runlist @rl and return the + * address of the runlist element containing the @vcn on success. + * + * Return NULL if @rl is NULL or @vcn is in an unmapped part/out of bounds of + * the runlist. + * + * Locking: The runlist must be locked on entry. + */ +runlist_element *ntfs_rl_find_vcn_nolock(runlist_element *rl, const VCN vcn) +{ + BUG_ON(vcn < 0); + if (unlikely(!rl || vcn < rl[0].vcn)) + return NULL; + while (likely(rl->length)) { + if (unlikely(vcn < rl[1].vcn)) { + if (likely(rl->lcn >= LCN_HOLE)) + return rl; + return NULL; + } + rl++; + } + if (likely(rl->lcn == LCN_ENOENT)) + return rl; + return NULL; +} + /** * ntfs_get_nr_significant_bytes - get number of bytes needed to store a number * @n: number for which to get the number of bytes for @@ -1452,3 +1485,5 @@ int ntfs_rl_truncate_nolock(const ntfs_volume *vol, runlist *const runlist, ntfs_debug("Done."); return 0; } + +#endif /* NTFS_RW */ diff --git a/fs/ntfs/runlist.h b/fs/ntfs/runlist.h index 60c42f3a3fc..cf5c1b44bea 100644 --- a/fs/ntfs/runlist.h +++ b/fs/ntfs/runlist.h @@ -2,7 +2,7 @@ * runlist.h - Defines for runlist handling in NTFS Linux kernel driver. * Part of the Linux-NTFS project. * - * Copyright (c) 2001-2004 Anton Altaparmakov + * Copyright (c) 2001-2005 Anton Altaparmakov * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or @@ -78,6 +78,11 @@ extern runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol, extern LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn); +#ifdef NTFS_RW + +extern runlist_element *ntfs_rl_find_vcn_nolock(runlist_element *rl, + const VCN vcn); + extern int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol, const runlist_element *rl, const VCN start_vcn); @@ -88,4 +93,6 @@ extern int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst, extern int ntfs_rl_truncate_nolock(const ntfs_volume *vol, runlist *const runlist, const s64 new_length); +#endif /* NTFS_RW */ + #endif /* _LINUX_NTFS_RUNLIST_H */ -- cgit v1.2.3-70-g09d2 From 3bd1f4a173a3445f9919c21e775de2d8b9deacf8 Mon Sep 17 00:00:00 2001 From: Anton Altaparmakov Date: Sat, 25 Jun 2005 16:51:58 +0100 Subject: NTFS: Fix several occurences of a bug where we would perform 'var & ~const' with a 64-bit variable and a int, i.e. 32-bit, constant. This causes the higher order 32-bits of the 64-bit variable to be zeroed. To fix this cast the 'const' to the same 64-bit type as 'var'. Signed-off-by: Anton Altaparmakov --- fs/ntfs/ChangeLog | 4 ++++ fs/ntfs/dir.c | 3 ++- fs/ntfs/inode.h | 2 +- fs/ntfs/lcnalloc.c | 4 ++-- fs/ntfs/logfile.c | 6 +++--- 5 files changed, 12 insertions(+), 7 deletions(-) (limited to 'fs/ntfs/lcnalloc.c') diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index c089bf0c02a..a916c8b0697 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog @@ -128,6 +128,10 @@ ToDo/Notes: - Detect the case when Windows has been suspended to disk on the volume to be mounted and if this is the case do not allow (re)mounting read-write. This is done by parsing hiberfil.sys if present. + - Fix several occurences of a bug where we would perform 'var & ~const' + with a 64-bit variable and a int, i.e. 32-bit, constant. This causes + the higher order 32-bits of the 64-bit variable to be zeroed. To fix + this cast the 'const' to the same 64-bit type as 'var'. 2.1.22 - Many bug and race fixes and error handling improvements. diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c index a56ca1821ee..46779471c54 100644 --- a/fs/ntfs/dir.c +++ b/fs/ntfs/dir.c @@ -1308,7 +1308,8 @@ find_next_index_buffer: ntfs_debug("Handling index buffer 0x%llx.", (unsigned long long)bmp_pos + cur_bmp_pos); /* If the current index buffer is in the same page we reuse the page. */ - if ((prev_ia_pos & PAGE_CACHE_MASK) != (ia_pos & PAGE_CACHE_MASK)) { + if ((prev_ia_pos & (s64)PAGE_CACHE_MASK) != + (ia_pos & (s64)PAGE_CACHE_MASK)) { prev_ia_pos = ia_pos; if (likely(ia_page != NULL)) { unlock_page(ia_page); diff --git a/fs/ntfs/inode.h b/fs/ntfs/inode.h index 6eb99777a72..3de5c023196 100644 --- a/fs/ntfs/inode.h +++ b/fs/ntfs/inode.h @@ -110,7 +110,7 @@ struct _ntfs_inode { u8 block_size_bits; /* Log2 of the above. */ u8 vcn_size_bits; /* Log2 of the above. */ } index; - struct { /* It is a compressed file or an attribute inode. */ + struct { /* It is a compressed/sparse file/attribute inode. */ s64 size; /* Copy of compressed_size from $DATA. */ u32 block_size; /* Size of a compression block diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c index 7087b5b0e6c..a4bc07616e5 100644 --- a/fs/ntfs/lcnalloc.c +++ b/fs/ntfs/lcnalloc.c @@ -293,7 +293,7 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn, buf_size = i_size - last_read_pos; buf_size <<= 3; lcn = bmp_pos & 7; - bmp_pos &= ~7; + bmp_pos &= ~(LCN)7; ntfs_debug("Before inner while loop: buf_size %i, lcn 0x%llx, " "bmp_pos 0x%llx, need_writeback %i.", buf_size, (unsigned long long)lcn, @@ -311,7 +311,7 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn, (unsigned int)*byte); /* Skip full bytes. */ if (*byte == 0xff) { - lcn = (lcn + 8) & ~7; + lcn = (lcn + 8) & ~(LCN)7; ntfs_debug("Continuing while loop 1."); continue; } diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c index e680dd0cdb6..8edb8e20fb0 100644 --- a/fs/ntfs/logfile.c +++ b/fs/ntfs/logfile.c @@ -1,7 +1,7 @@ /* * logfile.c - NTFS kernel journal handling. Part of the Linux-NTFS project. * - * Copyright (c) 2002-2004 Anton Altaparmakov + * Copyright (c) 2002-2005 Anton Altaparmakov * * This program/include file is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published @@ -410,7 +410,7 @@ err_out: } /** - * ntfs_ckeck_logfile - check in the journal if the volume is consistent + * ntfs_check_logfile - check the journal for consistency * @log_vi: struct inode of loaded journal $LogFile to check * * Check the $LogFile journal for consistency and return TRUE if it is @@ -464,7 +464,7 @@ BOOL ntfs_check_logfile(struct inode *log_vi) * optimize log_page_size and log_page_bits into constants. */ log_page_bits = generic_ffs(log_page_size) - 1; - size &= ~(log_page_size - 1); + size &= ~(s64)(log_page_size - 1); /* * Ensure the log file is big enough to store at least the two restart * pages and the minimum number of log record pages. -- cgit v1.2.3-70-g09d2