summaryrefslogtreecommitdiff
path: root/fs/ntfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ntfs/inode.c')
-rw-r--r--fs/ntfs/inode.c111
1 files changed, 66 insertions, 45 deletions
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 55263b7de9c0..4c86b7e1d1eb 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -1,7 +1,7 @@
/**
* inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project.
*
- * Copyright (c) 2001-2005 Anton Altaparmakov
+ * Copyright (c) 2001-2006 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
@@ -19,13 +19,19 @@
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/pagemap.h>
#include <linux/buffer_head.h>
-#include <linux/smp_lock.h>
-#include <linux/quotaops.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
#include <linux/mount.h>
+#include <linux/mutex.h>
+#include <linux/pagemap.h>
+#include <linux/quotaops.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
#include "aops.h"
+#include "attrib.h"
+#include "bitmap.h"
#include "dir.h"
#include "debug.h"
#include "inode.h"
@@ -382,7 +388,7 @@ void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni)
atomic_set(&ni->count, 1);
ni->vol = NTFS_SB(sb);
ntfs_init_runlist(&ni->runlist);
- init_MUTEX(&ni->mrec_lock);
+ mutex_init(&ni->mrec_lock);
ni->page = NULL;
ni->page_ofs = 0;
ni->attr_list_size = 0;
@@ -394,7 +400,7 @@ void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni)
ni->itype.index.collation_rule = 0;
ni->itype.index.block_size_bits = 0;
ni->itype.index.vcn_size_bits = 0;
- init_MUTEX(&ni->extent_lock);
+ mutex_init(&ni->extent_lock);
ni->nr_extents = 0;
ni->ext.base_ntfs_ino = NULL;
}
@@ -1064,10 +1070,10 @@ skip_large_dir_stuff:
if (a->non_resident) {
NInoSetNonResident(ni);
if (NInoCompressed(ni) || NInoSparse(ni)) {
- if (a->data.non_resident.compression_unit !=
- 4) {
+ if (NInoCompressed(ni) && a->data.non_resident.
+ compression_unit != 4) {
ntfs_error(vi->i_sb, "Found "
- "nonstandard "
+ "non-standard "
"compression unit (%u "
"instead of 4). "
"Cannot handle this.",
@@ -1076,16 +1082,26 @@ skip_large_dir_stuff:
err = -EOPNOTSUPP;
goto unm_err_out;
}
- ni->itype.compressed.block_clusters = 1U <<
- 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;
+ 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;
+ }
ni->itype.compressed.size = sle64_to_cpu(
a->data.non_resident.
compressed_size);
@@ -1338,8 +1354,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
goto unm_err_out;
}
if (NInoCompressed(ni) || NInoSparse(ni)) {
- if (a->data.non_resident.compression_unit != 4) {
- ntfs_error(vi->i_sb, "Found nonstandard "
+ if (NInoCompressed(ni) && a->data.non_resident.
+ compression_unit != 4) {
+ ntfs_error(vi->i_sb, "Found non-standard "
"compression unit (%u instead "
"of 4). Cannot handle this.",
a->data.non_resident.
@@ -1347,13 +1364,22 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
err = -EOPNOTSUPP;
goto unm_err_out;
}
- ni->itype.compressed.block_clusters = 1U <<
- 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;
+ 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;
+ }
ni->itype.compressed.size = sle64_to_cpu(
a->data.non_resident.compressed_size);
}
@@ -1406,7 +1432,6 @@ err_out:
"Run chkdsk.", err, vi->i_ino, ni->type, ni->name_len,
base_vi->i_ino);
make_bad_inode(vi);
- make_bad_inode(base_vi);
if (err != -ENOMEM)
NVolSetErrors(vol);
return err;
@@ -1591,6 +1616,7 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
"$INDEX_ALLOCATION attribute.");
goto unm_err_out;
}
+ a = ctx->attr;
if (!a->non_resident) {
ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is "
"resident.");
@@ -2823,11 +2849,8 @@ done:
old_bad_out:
old_size = -1;
bad_out:
- if (err != -ENOMEM && err != -EOPNOTSUPP) {
- make_bad_inode(vi);
- make_bad_inode(VFS_I(base_ni));
+ if (err != -ENOMEM && err != -EOPNOTSUPP)
NVolSetErrors(vol);
- }
if (err != -EOPNOTSUPP)
NInoSetTruncateFailed(ni);
else if (old_size >= 0)
@@ -2842,11 +2865,8 @@ out:
ntfs_debug("Failed. Returning error code %i.", err);
return err;
conv_err_out:
- if (err != -ENOMEM && err != -EOPNOTSUPP) {
- make_bad_inode(vi);
- make_bad_inode(VFS_I(base_ni));
+ if (err != -ENOMEM && err != -EOPNOTSUPP)
NVolSetErrors(vol);
- }
if (err != -EOPNOTSUPP)
NInoSetTruncateFailed(ni);
else
@@ -3044,15 +3064,18 @@ int ntfs_write_inode(struct inode *vi, int sync)
* record will be cleaned and written out to disk below, i.e. before
* this function returns.
*/
- if (modified && !NInoTestSetDirty(ctx->ntfs_ino))
- mark_ntfs_record_dirty(ctx->ntfs_ino->page,
- ctx->ntfs_ino->page_ofs);
+ if (modified) {
+ flush_dcache_mft_record_page(ctx->ntfs_ino);
+ if (!NInoTestSetDirty(ctx->ntfs_ino))
+ mark_ntfs_record_dirty(ctx->ntfs_ino->page,
+ ctx->ntfs_ino->page_ofs);
+ }
ntfs_attr_put_search_ctx(ctx);
/* Now the access times are updated, write the base mft record. */
if (NInoDirty(ni))
err = write_mft_record(ni, m, sync);
/* Write all attached extent mft records. */
- down(&ni->extent_lock);
+ mutex_lock(&ni->extent_lock);
if (ni->nr_extents > 0) {
ntfs_inode **extent_nis = ni->ext.extent_ntfs_inos;
int i;
@@ -3079,7 +3102,7 @@ int ntfs_write_inode(struct inode *vi, int sync)
}
}
}
- up(&ni->extent_lock);
+ mutex_unlock(&ni->extent_lock);
unmap_mft_record(ni);
if (unlikely(err))
goto err_out;
@@ -3094,9 +3117,7 @@ err_out:
"retries later.");
mark_inode_dirty(vi);
} else {
- ntfs_error(vi->i_sb, "Failed (error code %i): Marking inode "
- "as bad. You should run chkdsk.", -err);
- make_bad_inode(vi);
+ ntfs_error(vi->i_sb, "Failed (error %i): Run chkdsk.", -err);
NVolSetErrors(ni->vol);
}
return err;