diff options
Diffstat (limited to 'fs/ntfs/inode.c')
-rw-r--r-- | fs/ntfs/inode.c | 111 |
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 @@ | |||
1 | /** | 1 | /** |
2 | * inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project. | 2 | * inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project. |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2005 Anton Altaparmakov | 4 | * Copyright (c) 2001-2006 Anton Altaparmakov |
5 | * | 5 | * |
6 | * This program/include file is free software; you can redistribute it and/or | 6 | * This program/include file is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License as published | 7 | * modify it under the terms of the GNU General Public License as published |
@@ -19,13 +19,19 @@ | |||
19 | * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/pagemap.h> | ||
23 | #include <linux/buffer_head.h> | 22 | #include <linux/buffer_head.h> |
24 | #include <linux/smp_lock.h> | 23 | #include <linux/fs.h> |
25 | #include <linux/quotaops.h> | 24 | #include <linux/mm.h> |
26 | #include <linux/mount.h> | 25 | #include <linux/mount.h> |
26 | #include <linux/mutex.h> | ||
27 | #include <linux/pagemap.h> | ||
28 | #include <linux/quotaops.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/smp_lock.h> | ||
27 | 31 | ||
28 | #include "aops.h" | 32 | #include "aops.h" |
33 | #include "attrib.h" | ||
34 | #include "bitmap.h" | ||
29 | #include "dir.h" | 35 | #include "dir.h" |
30 | #include "debug.h" | 36 | #include "debug.h" |
31 | #include "inode.h" | 37 | #include "inode.h" |
@@ -382,7 +388,7 @@ void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni) | |||
382 | atomic_set(&ni->count, 1); | 388 | atomic_set(&ni->count, 1); |
383 | ni->vol = NTFS_SB(sb); | 389 | ni->vol = NTFS_SB(sb); |
384 | ntfs_init_runlist(&ni->runlist); | 390 | ntfs_init_runlist(&ni->runlist); |
385 | init_MUTEX(&ni->mrec_lock); | 391 | mutex_init(&ni->mrec_lock); |
386 | ni->page = NULL; | 392 | ni->page = NULL; |
387 | ni->page_ofs = 0; | 393 | ni->page_ofs = 0; |
388 | ni->attr_list_size = 0; | 394 | ni->attr_list_size = 0; |
@@ -394,7 +400,7 @@ void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni) | |||
394 | ni->itype.index.collation_rule = 0; | 400 | ni->itype.index.collation_rule = 0; |
395 | ni->itype.index.block_size_bits = 0; | 401 | ni->itype.index.block_size_bits = 0; |
396 | ni->itype.index.vcn_size_bits = 0; | 402 | ni->itype.index.vcn_size_bits = 0; |
397 | init_MUTEX(&ni->extent_lock); | 403 | mutex_init(&ni->extent_lock); |
398 | ni->nr_extents = 0; | 404 | ni->nr_extents = 0; |
399 | ni->ext.base_ntfs_ino = NULL; | 405 | ni->ext.base_ntfs_ino = NULL; |
400 | } | 406 | } |
@@ -1064,10 +1070,10 @@ skip_large_dir_stuff: | |||
1064 | if (a->non_resident) { | 1070 | if (a->non_resident) { |
1065 | NInoSetNonResident(ni); | 1071 | NInoSetNonResident(ni); |
1066 | if (NInoCompressed(ni) || NInoSparse(ni)) { | 1072 | if (NInoCompressed(ni) || NInoSparse(ni)) { |
1067 | if (a->data.non_resident.compression_unit != | 1073 | if (NInoCompressed(ni) && a->data.non_resident. |
1068 | 4) { | 1074 | compression_unit != 4) { |
1069 | ntfs_error(vi->i_sb, "Found " | 1075 | ntfs_error(vi->i_sb, "Found " |
1070 | "nonstandard " | 1076 | "non-standard " |
1071 | "compression unit (%u " | 1077 | "compression unit (%u " |
1072 | "instead of 4). " | 1078 | "instead of 4). " |
1073 | "Cannot handle this.", | 1079 | "Cannot handle this.", |
@@ -1076,16 +1082,26 @@ skip_large_dir_stuff: | |||
1076 | err = -EOPNOTSUPP; | 1082 | err = -EOPNOTSUPP; |
1077 | goto unm_err_out; | 1083 | goto unm_err_out; |
1078 | } | 1084 | } |
1079 | ni->itype.compressed.block_clusters = 1U << | 1085 | if (a->data.non_resident.compression_unit) { |
1080 | a->data.non_resident. | 1086 | ni->itype.compressed.block_size = 1U << |
1081 | compression_unit; | 1087 | (a->data.non_resident. |
1082 | ni->itype.compressed.block_size = 1U << ( | 1088 | compression_unit + |
1083 | a->data.non_resident. | 1089 | vol->cluster_size_bits); |
1084 | compression_unit + | 1090 | ni->itype.compressed.block_size_bits = |
1085 | vol->cluster_size_bits); | 1091 | ffs(ni->itype. |
1086 | ni->itype.compressed.block_size_bits = ffs( | 1092 | compressed. |
1087 | ni->itype.compressed. | 1093 | block_size) - 1; |
1088 | block_size) - 1; | 1094 | ni->itype.compressed.block_clusters = |
1095 | 1U << a->data. | ||
1096 | non_resident. | ||
1097 | compression_unit; | ||
1098 | } else { | ||
1099 | ni->itype.compressed.block_size = 0; | ||
1100 | ni->itype.compressed.block_size_bits = | ||
1101 | 0; | ||
1102 | ni->itype.compressed.block_clusters = | ||
1103 | 0; | ||
1104 | } | ||
1089 | ni->itype.compressed.size = sle64_to_cpu( | 1105 | ni->itype.compressed.size = sle64_to_cpu( |
1090 | a->data.non_resident. | 1106 | a->data.non_resident. |
1091 | compressed_size); | 1107 | compressed_size); |
@@ -1338,8 +1354,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) | |||
1338 | goto unm_err_out; | 1354 | goto unm_err_out; |
1339 | } | 1355 | } |
1340 | if (NInoCompressed(ni) || NInoSparse(ni)) { | 1356 | if (NInoCompressed(ni) || NInoSparse(ni)) { |
1341 | if (a->data.non_resident.compression_unit != 4) { | 1357 | if (NInoCompressed(ni) && a->data.non_resident. |
1342 | ntfs_error(vi->i_sb, "Found nonstandard " | 1358 | compression_unit != 4) { |
1359 | ntfs_error(vi->i_sb, "Found non-standard " | ||
1343 | "compression unit (%u instead " | 1360 | "compression unit (%u instead " |
1344 | "of 4). Cannot handle this.", | 1361 | "of 4). Cannot handle this.", |
1345 | a->data.non_resident. | 1362 | a->data.non_resident. |
@@ -1347,13 +1364,22 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) | |||
1347 | err = -EOPNOTSUPP; | 1364 | err = -EOPNOTSUPP; |
1348 | goto unm_err_out; | 1365 | goto unm_err_out; |
1349 | } | 1366 | } |
1350 | ni->itype.compressed.block_clusters = 1U << | 1367 | if (a->data.non_resident.compression_unit) { |
1351 | a->data.non_resident.compression_unit; | 1368 | ni->itype.compressed.block_size = 1U << |
1352 | ni->itype.compressed.block_size = 1U << ( | 1369 | (a->data.non_resident. |
1353 | a->data.non_resident.compression_unit + | 1370 | compression_unit + |
1354 | vol->cluster_size_bits); | 1371 | vol->cluster_size_bits); |
1355 | ni->itype.compressed.block_size_bits = ffs( | 1372 | ni->itype.compressed.block_size_bits = |
1356 | ni->itype.compressed.block_size) - 1; | 1373 | ffs(ni->itype.compressed. |
1374 | block_size) - 1; | ||
1375 | ni->itype.compressed.block_clusters = 1U << | ||
1376 | a->data.non_resident. | ||
1377 | compression_unit; | ||
1378 | } else { | ||
1379 | ni->itype.compressed.block_size = 0; | ||
1380 | ni->itype.compressed.block_size_bits = 0; | ||
1381 | ni->itype.compressed.block_clusters = 0; | ||
1382 | } | ||
1357 | ni->itype.compressed.size = sle64_to_cpu( | 1383 | ni->itype.compressed.size = sle64_to_cpu( |
1358 | a->data.non_resident.compressed_size); | 1384 | a->data.non_resident.compressed_size); |
1359 | } | 1385 | } |
@@ -1406,7 +1432,6 @@ err_out: | |||
1406 | "Run chkdsk.", err, vi->i_ino, ni->type, ni->name_len, | 1432 | "Run chkdsk.", err, vi->i_ino, ni->type, ni->name_len, |
1407 | base_vi->i_ino); | 1433 | base_vi->i_ino); |
1408 | make_bad_inode(vi); | 1434 | make_bad_inode(vi); |
1409 | make_bad_inode(base_vi); | ||
1410 | if (err != -ENOMEM) | 1435 | if (err != -ENOMEM) |
1411 | NVolSetErrors(vol); | 1436 | NVolSetErrors(vol); |
1412 | return err; | 1437 | return err; |
@@ -1591,6 +1616,7 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi) | |||
1591 | "$INDEX_ALLOCATION attribute."); | 1616 | "$INDEX_ALLOCATION attribute."); |
1592 | goto unm_err_out; | 1617 | goto unm_err_out; |
1593 | } | 1618 | } |
1619 | a = ctx->attr; | ||
1594 | if (!a->non_resident) { | 1620 | if (!a->non_resident) { |
1595 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is " | 1621 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is " |
1596 | "resident."); | 1622 | "resident."); |
@@ -2823,11 +2849,8 @@ done: | |||
2823 | old_bad_out: | 2849 | old_bad_out: |
2824 | old_size = -1; | 2850 | old_size = -1; |
2825 | bad_out: | 2851 | bad_out: |
2826 | if (err != -ENOMEM && err != -EOPNOTSUPP) { | 2852 | if (err != -ENOMEM && err != -EOPNOTSUPP) |
2827 | make_bad_inode(vi); | ||
2828 | make_bad_inode(VFS_I(base_ni)); | ||
2829 | NVolSetErrors(vol); | 2853 | NVolSetErrors(vol); |
2830 | } | ||
2831 | if (err != -EOPNOTSUPP) | 2854 | if (err != -EOPNOTSUPP) |
2832 | NInoSetTruncateFailed(ni); | 2855 | NInoSetTruncateFailed(ni); |
2833 | else if (old_size >= 0) | 2856 | else if (old_size >= 0) |
@@ -2842,11 +2865,8 @@ out: | |||
2842 | ntfs_debug("Failed. Returning error code %i.", err); | 2865 | ntfs_debug("Failed. Returning error code %i.", err); |
2843 | return err; | 2866 | return err; |
2844 | conv_err_out: | 2867 | conv_err_out: |
2845 | if (err != -ENOMEM && err != -EOPNOTSUPP) { | 2868 | if (err != -ENOMEM && err != -EOPNOTSUPP) |
2846 | make_bad_inode(vi); | ||
2847 | make_bad_inode(VFS_I(base_ni)); | ||
2848 | NVolSetErrors(vol); | 2869 | NVolSetErrors(vol); |
2849 | } | ||
2850 | if (err != -EOPNOTSUPP) | 2870 | if (err != -EOPNOTSUPP) |
2851 | NInoSetTruncateFailed(ni); | 2871 | NInoSetTruncateFailed(ni); |
2852 | else | 2872 | else |
@@ -3044,15 +3064,18 @@ int ntfs_write_inode(struct inode *vi, int sync) | |||
3044 | * record will be cleaned and written out to disk below, i.e. before | 3064 | * record will be cleaned and written out to disk below, i.e. before |
3045 | * this function returns. | 3065 | * this function returns. |
3046 | */ | 3066 | */ |
3047 | if (modified && !NInoTestSetDirty(ctx->ntfs_ino)) | 3067 | if (modified) { |
3048 | mark_ntfs_record_dirty(ctx->ntfs_ino->page, | 3068 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
3049 | ctx->ntfs_ino->page_ofs); | 3069 | if (!NInoTestSetDirty(ctx->ntfs_ino)) |
3070 | mark_ntfs_record_dirty(ctx->ntfs_ino->page, | ||
3071 | ctx->ntfs_ino->page_ofs); | ||
3072 | } | ||
3050 | ntfs_attr_put_search_ctx(ctx); | 3073 | ntfs_attr_put_search_ctx(ctx); |
3051 | /* Now the access times are updated, write the base mft record. */ | 3074 | /* Now the access times are updated, write the base mft record. */ |
3052 | if (NInoDirty(ni)) | 3075 | if (NInoDirty(ni)) |
3053 | err = write_mft_record(ni, m, sync); | 3076 | err = write_mft_record(ni, m, sync); |
3054 | /* Write all attached extent mft records. */ | 3077 | /* Write all attached extent mft records. */ |
3055 | down(&ni->extent_lock); | 3078 | mutex_lock(&ni->extent_lock); |
3056 | if (ni->nr_extents > 0) { | 3079 | if (ni->nr_extents > 0) { |
3057 | ntfs_inode **extent_nis = ni->ext.extent_ntfs_inos; | 3080 | ntfs_inode **extent_nis = ni->ext.extent_ntfs_inos; |
3058 | int i; | 3081 | int i; |
@@ -3079,7 +3102,7 @@ int ntfs_write_inode(struct inode *vi, int sync) | |||
3079 | } | 3102 | } |
3080 | } | 3103 | } |
3081 | } | 3104 | } |
3082 | up(&ni->extent_lock); | 3105 | mutex_unlock(&ni->extent_lock); |
3083 | unmap_mft_record(ni); | 3106 | unmap_mft_record(ni); |
3084 | if (unlikely(err)) | 3107 | if (unlikely(err)) |
3085 | goto err_out; | 3108 | goto err_out; |
@@ -3094,9 +3117,7 @@ err_out: | |||
3094 | "retries later."); | 3117 | "retries later."); |
3095 | mark_inode_dirty(vi); | 3118 | mark_inode_dirty(vi); |
3096 | } else { | 3119 | } else { |
3097 | ntfs_error(vi->i_sb, "Failed (error code %i): Marking inode " | 3120 | ntfs_error(vi->i_sb, "Failed (error %i): Run chkdsk.", -err); |
3098 | "as bad. You should run chkdsk.", -err); | ||
3099 | make_bad_inode(vi); | ||
3100 | NVolSetErrors(ni->vol); | 3121 | NVolSetErrors(ni->vol); |
3101 | } | 3122 | } |
3102 | return err; | 3123 | return err; |