[PATCH] read_mapping_page for address space
[powerpc.git] / fs / ntfs / attrib.c
index 338e471..6708e1d 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * attrib.c - NTFS attribute operations.  Part of the Linux-NTFS project.
  *
- * Copyright (c) 2001-2005 Anton Altaparmakov
+ * Copyright (c) 2001-2006 Anton Altaparmakov
  * Copyright (c) 2002 Richard Russon
  *
  * This program/include file is free software; you can redistribute it and/or
@@ -91,7 +91,7 @@ int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn, ntfs_attr_search_ctx *ctx)
        struct page *put_this_page = NULL;
        int err = 0;
        BOOL ctx_is_temporary, ctx_needs_reset;
-       ntfs_attr_search_ctx old_ctx;
+       ntfs_attr_search_ctx old_ctx = { NULL, };
 
        ntfs_debug("Mapping runlist part containing vcn 0x%llx.",
                        (unsigned long long)vcn);
@@ -1048,7 +1048,7 @@ do_next_attr_loop:
                                le32_to_cpu(ctx->mrec->bytes_allocated))
                        break;
                if (a->type == AT_END)
-                       continue;
+                       break;
                if (!a->length)
                        break;
                if (al_entry->instance != a->instance)
@@ -1411,7 +1411,7 @@ int ntfs_attr_can_be_non_resident(const ntfs_volume *vol, const ATTR_TYPE type)
  */
 int ntfs_attr_can_be_resident(const ntfs_volume *vol, const ATTR_TYPE type)
 {
-       if (type == AT_INDEX_ALLOCATION || type == AT_EA)
+       if (type == AT_INDEX_ALLOCATION)
                return -EPERM;
        return 0;
 }
@@ -1532,7 +1532,7 @@ int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a,
  * NOTE to self: No changes in the attribute list are required to move from
  *              a resident to a non-resident attribute.
  *
- * Locking: - The caller must hold i_sem on the inode.
+ * Locking: - The caller must hold i_mutex on the inode.
  */
 int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size)
 {
@@ -1695,7 +1695,9 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size)
                        a->data.non_resident.initialized_size =
                        cpu_to_sle64(attr_size);
        if (NInoSparse(ni) || NInoCompressed(ni)) {
-               a->data.non_resident.compression_unit = 4;
+               a->data.non_resident.compression_unit = 0;
+               if (NInoCompressed(ni) || vol->major_ver < 3)
+                       a->data.non_resident.compression_unit = 4;
                a->data.non_resident.compressed_size =
                                a->data.non_resident.allocated_size;
        } else
@@ -1714,13 +1716,20 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size)
        ni->allocated_size = new_size;
        if (NInoSparse(ni) || NInoCompressed(ni)) {
                ni->itype.compressed.size = ni->allocated_size;
-               ni->itype.compressed.block_size = 1U <<
-                               (a->data.non_resident.compression_unit +
-                               vol->cluster_size_bits);
-               ni->itype.compressed.block_size_bits =
-                               ffs(ni->itype.compressed.block_size) - 1;
-               ni->itype.compressed.block_clusters = 1U <<
-                               a->data.non_resident.compression_unit;
+               if (a->data.non_resident.compression_unit) {
+                       ni->itype.compressed.block_size = 1U << (a->data.
+                                       non_resident.compression_unit +
+                                       vol->cluster_size_bits);
+                       ni->itype.compressed.block_size_bits =
+                                       ffs(ni->itype.compressed.block_size) -
+                                       1;
+                       ni->itype.compressed.block_clusters = 1U <<
+                                       a->data.non_resident.compression_unit;
+               } else {
+                       ni->itype.compressed.block_size = 0;
+                       ni->itype.compressed.block_size_bits = 0;
+                       ni->itype.compressed.block_clusters = 0;
+               }
                vi->i_blocks = ni->itype.compressed.size >> 9;
        } else
                vi->i_blocks = ni->allocated_size >> 9;
@@ -1728,7 +1737,7 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size)
        /*
         * This needs to be last since the address space operations ->readpage
         * and ->writepage can run concurrently with us as they are not
-        * serialized on i_sem.  Note, we are not allowed to fail once we flip
+        * serialized on i_mutex.  Note, we are not allowed to fail once we flip
         * this switch, which is another reason to do this last.
         */
        NInoSetNonResident(ni);
@@ -2429,16 +2438,12 @@ undo_alloc:
                                "chkdsk to recover.", IS_ERR(m) ?
                                "restore attribute search context" :
                                "truncate attribute runlist");
-               make_bad_inode(vi);
-               make_bad_inode(VFS_I(base_ni));
                NVolSetErrors(vol);
        } else if (mp_rebuilt) {
                if (ntfs_attr_record_resize(m, a, attr_len)) {
                        ntfs_error(vol->sb, "Failed to restore attribute "
                                        "record in error code path.  Run "
                                        "chkdsk to recover.");
-                       make_bad_inode(vi);
-                       make_bad_inode(VFS_I(base_ni));
                        NVolSetErrors(vol);
                } else /* if (success) */ {
                        if (ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu(
@@ -2451,8 +2456,6 @@ undo_alloc:
                                                "mapping pairs array in error "
                                                "code path.  Run chkdsk to "
                                                "recover.");
-                               make_bad_inode(vi);
-                               make_bad_inode(VFS_I(base_ni));
                                NVolSetErrors(vol);
                        }
                        flush_dcache_mft_record_page(ctx->ntfs_ino);
@@ -2526,8 +2529,7 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val)
        end >>= PAGE_CACHE_SHIFT;
        /* If there is a first partial page, need to do it the slow way. */
        if (start_ofs) {
-               page = read_cache_page(mapping, idx,
-                               (filler_t*)mapping->a_ops->readpage, NULL);
+               page = read_mapping_page(mapping, idx, NULL);
                if (IS_ERR(page)) {
                        ntfs_error(vol->sb, "Failed to read first partial "
                                        "page (sync error, index 0x%lx).", idx);
@@ -2597,8 +2599,7 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val)
        }
        /* If there is a last partial page, need to do it the slow way. */
        if (end_ofs) {
-               page = read_cache_page(mapping, idx,
-                               (filler_t*)mapping->a_ops->readpage, NULL);
+               page = read_mapping_page(mapping, idx, NULL);
                if (IS_ERR(page)) {
                        ntfs_error(vol->sb, "Failed to read last partial page "
                                        "(sync error, index 0x%lx).", idx);