diff options
author | Anton Altaparmakov <aia21@cantab.net> | 2005-02-03 07:02:56 -0500 |
---|---|---|
committer | Anton Altaparmakov <aia21@cantab.net> | 2005-05-05 05:53:01 -0400 |
commit | c002f42543e155dd2b5b5039ea2637ab26c82513 (patch) | |
tree | ea408493d2e0e9096166ab39a8657689c15c7dfa /fs/ntfs/super.c | |
parent | f40661be038ce6ed9ef6a8b80307a9153bd95769 (diff) |
NTFS: - Add disable_sparse mount option together with a per volume sparse
enable bit which is set appropriately and a per inode sparse disable
bit which is preset on some system file inodes as appropriate.
- Enforce that sparse support is disabled on NTFS volumes pre 3.0.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Diffstat (limited to 'fs/ntfs/super.c')
-rw-r--r-- | fs/ntfs/super.c | 65 |
1 files changed, 47 insertions, 18 deletions
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 0ad0c51e9eb9..b676cf6fd93c 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * super.c - NTFS kernel super block handling. Part of the Linux-NTFS project. | 2 | * super.c - NTFS kernel super block handling. Part of the Linux-NTFS project. |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2004 Anton Altaparmakov | 4 | * Copyright (c) 2001-2005 Anton Altaparmakov |
5 | * Copyright (c) 2001,2002 Richard Russon | 5 | * Copyright (c) 2001,2002 Richard Russon |
6 | * | 6 | * |
7 | * This program/include file is free software; you can redistribute it and/or | 7 | * This program/include file is free software; you can redistribute it and/or |
@@ -41,7 +41,7 @@ | |||
41 | #include "malloc.h" | 41 | #include "malloc.h" |
42 | #include "ntfs.h" | 42 | #include "ntfs.h" |
43 | 43 | ||
44 | /* Number of mounted file systems which have compression enabled. */ | 44 | /* Number of mounted filesystems which have compression enabled. */ |
45 | static unsigned long ntfs_nr_compression_users; | 45 | static unsigned long ntfs_nr_compression_users; |
46 | 46 | ||
47 | /* A global default upcase table and a corresponding reference count. */ | 47 | /* A global default upcase table and a corresponding reference count. */ |
@@ -102,7 +102,7 @@ static BOOL parse_options(ntfs_volume *vol, char *opt) | |||
102 | gid_t gid = (gid_t)-1; | 102 | gid_t gid = (gid_t)-1; |
103 | mode_t fmask = (mode_t)-1, dmask = (mode_t)-1; | 103 | mode_t fmask = (mode_t)-1, dmask = (mode_t)-1; |
104 | int mft_zone_multiplier = -1, on_errors = -1; | 104 | int mft_zone_multiplier = -1, on_errors = -1; |
105 | int show_sys_files = -1, case_sensitive = -1; | 105 | int show_sys_files = -1, case_sensitive = -1, disable_sparse = -1; |
106 | struct nls_table *nls_map = NULL, *old_nls; | 106 | struct nls_table *nls_map = NULL, *old_nls; |
107 | 107 | ||
108 | /* I am lazy... (-8 */ | 108 | /* I am lazy... (-8 */ |
@@ -162,6 +162,7 @@ static BOOL parse_options(ntfs_volume *vol, char *opt) | |||
162 | else NTFS_GETOPT_WITH_DEFAULT("sloppy", sloppy, TRUE) | 162 | else NTFS_GETOPT_WITH_DEFAULT("sloppy", sloppy, TRUE) |
163 | else NTFS_GETOPT_BOOL("show_sys_files", show_sys_files) | 163 | else NTFS_GETOPT_BOOL("show_sys_files", show_sys_files) |
164 | else NTFS_GETOPT_BOOL("case_sensitive", case_sensitive) | 164 | else NTFS_GETOPT_BOOL("case_sensitive", case_sensitive) |
165 | else NTFS_GETOPT_BOOL("disable_sparse", disable_sparse) | ||
165 | else NTFS_GETOPT_OPTIONS_ARRAY("errors", on_errors, | 166 | else NTFS_GETOPT_OPTIONS_ARRAY("errors", on_errors, |
166 | on_errors_arr) | 167 | on_errors_arr) |
167 | else if (!strcmp(p, "posix") || !strcmp(p, "show_inodes")) | 168 | else if (!strcmp(p, "posix") || !strcmp(p, "show_inodes")) |
@@ -291,6 +292,21 @@ no_mount_options: | |||
291 | else | 292 | else |
292 | NVolClearCaseSensitive(vol); | 293 | NVolClearCaseSensitive(vol); |
293 | } | 294 | } |
295 | if (disable_sparse != -1) { | ||
296 | if (disable_sparse) | ||
297 | NVolClearSparseEnabled(vol); | ||
298 | else { | ||
299 | if (!NVolSparseEnabled(vol) && | ||
300 | vol->major_ver && vol->major_ver < 3) | ||
301 | ntfs_warning(vol->sb, "Not enabling sparse " | ||
302 | "support due to NTFS volume " | ||
303 | "version %i.%i (need at least " | ||
304 | "version 3.0).", vol->major_ver, | ||
305 | vol->minor_ver); | ||
306 | else | ||
307 | NVolSetSparseEnabled(vol); | ||
308 | } | ||
309 | } | ||
294 | return TRUE; | 310 | return TRUE; |
295 | needs_arg: | 311 | needs_arg: |
296 | ntfs_error(vol->sb, "The %s option requires an argument.", p); | 312 | ntfs_error(vol->sb, "The %s option requires an argument.", p); |
@@ -967,6 +983,7 @@ static BOOL load_and_init_mft_mirror(ntfs_volume *vol) | |||
967 | tmp_ni = NTFS_I(tmp_ino); | 983 | tmp_ni = NTFS_I(tmp_ino); |
968 | /* The $MFTMirr, like the $MFT is multi sector transfer protected. */ | 984 | /* The $MFTMirr, like the $MFT is multi sector transfer protected. */ |
969 | NInoSetMstProtected(tmp_ni); | 985 | NInoSetMstProtected(tmp_ni); |
986 | NInoSetSparseDisabled(tmp_ni); | ||
970 | /* | 987 | /* |
971 | * Set up our little cheat allowing us to reuse the async read io | 988 | * Set up our little cheat allowing us to reuse the async read io |
972 | * completion handler for directories. | 989 | * completion handler for directories. |
@@ -1122,6 +1139,7 @@ static BOOL load_and_check_logfile(ntfs_volume *vol) | |||
1122 | /* ntfs_check_logfile() will have displayed error output. */ | 1139 | /* ntfs_check_logfile() will have displayed error output. */ |
1123 | return FALSE; | 1140 | return FALSE; |
1124 | } | 1141 | } |
1142 | NInoSetSparseDisabled(NTFS_I(tmp_ino)); | ||
1125 | vol->logfile_ino = tmp_ino; | 1143 | vol->logfile_ino = tmp_ino; |
1126 | ntfs_debug("Done."); | 1144 | ntfs_debug("Done."); |
1127 | return TRUE; | 1145 | return TRUE; |
@@ -1220,6 +1238,7 @@ static BOOL load_and_init_attrdef(ntfs_volume *vol) | |||
1220 | iput(ino); | 1238 | iput(ino); |
1221 | goto failed; | 1239 | goto failed; |
1222 | } | 1240 | } |
1241 | NInoSetSparseDisabled(NTFS_I(ino)); | ||
1223 | /* The size of FILE_AttrDef must be above 0 and fit inside 31 bits. */ | 1242 | /* The size of FILE_AttrDef must be above 0 and fit inside 31 bits. */ |
1224 | i_size = i_size_read(ino); | 1243 | i_size = i_size_read(ino); |
1225 | if (i_size <= 0 || i_size > 0x7fffffff) | 1244 | if (i_size <= 0 || i_size > 0x7fffffff) |
@@ -1439,6 +1458,7 @@ static BOOL load_system_files(ntfs_volume *vol) | |||
1439 | iput(vol->lcnbmp_ino); | 1458 | iput(vol->lcnbmp_ino); |
1440 | goto bitmap_failed; | 1459 | goto bitmap_failed; |
1441 | } | 1460 | } |
1461 | NInoSetSparseDisabled(NTFS_I(vol->lcnbmp_ino)); | ||
1442 | if ((vol->nr_clusters + 7) >> 3 > i_size_read(vol->lcnbmp_ino)) { | 1462 | if ((vol->nr_clusters + 7) >> 3 > i_size_read(vol->lcnbmp_ino)) { |
1443 | iput(vol->lcnbmp_ino); | 1463 | iput(vol->lcnbmp_ino); |
1444 | bitmap_failed: | 1464 | bitmap_failed: |
@@ -1490,6 +1510,12 @@ get_ctx_vol_failed: | |||
1490 | unmap_mft_record(NTFS_I(vol->vol_ino)); | 1510 | unmap_mft_record(NTFS_I(vol->vol_ino)); |
1491 | printk(KERN_INFO "NTFS volume version %i.%i.\n", vol->major_ver, | 1511 | printk(KERN_INFO "NTFS volume version %i.%i.\n", vol->major_ver, |
1492 | vol->minor_ver); | 1512 | vol->minor_ver); |
1513 | if (vol->major_ver < 3 && NVolSparseEnabled(vol)) { | ||
1514 | ntfs_warning(vol->sb, "Disabling sparse support due to NTFS " | ||
1515 | "volume version %i.%i (need at least version " | ||
1516 | "3.0).", vol->major_ver, vol->minor_ver); | ||
1517 | NVolClearSparseEnabled(vol); | ||
1518 | } | ||
1493 | #ifdef NTFS_RW | 1519 | #ifdef NTFS_RW |
1494 | /* Make sure that no unsupported volume flags are set. */ | 1520 | /* Make sure that no unsupported volume flags are set. */ |
1495 | if (vol->vol_flags & VOLUME_MUST_MOUNT_RO_MASK) { | 1521 | if (vol->vol_flags & VOLUME_MUST_MOUNT_RO_MASK) { |
@@ -2033,7 +2059,7 @@ static s64 get_nr_free_clusters(ntfs_volume *vol) | |||
2033 | /** | 2059 | /** |
2034 | * __get_nr_free_mft_records - return the number of free inodes on a volume | 2060 | * __get_nr_free_mft_records - return the number of free inodes on a volume |
2035 | * @vol: ntfs volume for which to obtain free inode count | 2061 | * @vol: ntfs volume for which to obtain free inode count |
2036 | * @nr_free: number of mft records in file system | 2062 | * @nr_free: number of mft records in filesystem |
2037 | * @max_index: maximum number of pages containing set bits | 2063 | * @max_index: maximum number of pages containing set bits |
2038 | * | 2064 | * |
2039 | * Calculate the number of free mft records (inodes) on the mounted NTFS | 2065 | * Calculate the number of free mft records (inodes) on the mounted NTFS |
@@ -2138,13 +2164,13 @@ static int ntfs_statfs(struct super_block *sb, struct kstatfs *sfs) | |||
2138 | /* Optimal transfer block size. */ | 2164 | /* Optimal transfer block size. */ |
2139 | sfs->f_bsize = PAGE_CACHE_SIZE; | 2165 | sfs->f_bsize = PAGE_CACHE_SIZE; |
2140 | /* | 2166 | /* |
2141 | * Total data blocks in file system in units of f_bsize and since | 2167 | * Total data blocks in filesystem in units of f_bsize and since |
2142 | * inodes are also stored in data blocs ($MFT is a file) this is just | 2168 | * inodes are also stored in data blocs ($MFT is a file) this is just |
2143 | * the total clusters. | 2169 | * the total clusters. |
2144 | */ | 2170 | */ |
2145 | sfs->f_blocks = vol->nr_clusters << vol->cluster_size_bits >> | 2171 | sfs->f_blocks = vol->nr_clusters << vol->cluster_size_bits >> |
2146 | PAGE_CACHE_SHIFT; | 2172 | PAGE_CACHE_SHIFT; |
2147 | /* Free data blocks in file system in units of f_bsize. */ | 2173 | /* Free data blocks in filesystem in units of f_bsize. */ |
2148 | size = get_nr_free_clusters(vol) << vol->cluster_size_bits >> | 2174 | size = get_nr_free_clusters(vol) << vol->cluster_size_bits >> |
2149 | PAGE_CACHE_SHIFT; | 2175 | PAGE_CACHE_SHIFT; |
2150 | if (size < 0LL) | 2176 | if (size < 0LL) |
@@ -2163,7 +2189,7 @@ static int ntfs_statfs(struct super_block *sb, struct kstatfs *sfs) | |||
2163 | max_index = ((((mft_ni->initialized_size >> vol->mft_record_size_bits) | 2189 | max_index = ((((mft_ni->initialized_size >> vol->mft_record_size_bits) |
2164 | + 7) >> 3) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 2190 | + 7) >> 3) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
2165 | read_unlock_irqrestore(&mft_ni->size_lock, flags); | 2191 | read_unlock_irqrestore(&mft_ni->size_lock, flags); |
2166 | /* Number of inodes in file system (at this point in time). */ | 2192 | /* Number of inodes in filesystem (at this point in time). */ |
2167 | sfs->f_files = size; | 2193 | sfs->f_files = size; |
2168 | /* Free inodes in fs (based on current total count). */ | 2194 | /* Free inodes in fs (based on current total count). */ |
2169 | sfs->f_ffree = __get_nr_free_mft_records(vol, size, max_index); | 2195 | sfs->f_ffree = __get_nr_free_mft_records(vol, size, max_index); |
@@ -2172,8 +2198,8 @@ static int ntfs_statfs(struct super_block *sb, struct kstatfs *sfs) | |||
2172 | * File system id. This is extremely *nix flavour dependent and even | 2198 | * File system id. This is extremely *nix flavour dependent and even |
2173 | * within Linux itself all fs do their own thing. I interpret this to | 2199 | * within Linux itself all fs do their own thing. I interpret this to |
2174 | * mean a unique id associated with the mounted fs and not the id | 2200 | * mean a unique id associated with the mounted fs and not the id |
2175 | * associated with the file system driver, the latter is already given | 2201 | * associated with the filesystem driver, the latter is already given |
2176 | * by the file system type in sfs->f_type. Thus we use the 64-bit | 2202 | * by the filesystem type in sfs->f_type. Thus we use the 64-bit |
2177 | * volume serial number splitting it into two 32-bit parts. We enter | 2203 | * volume serial number splitting it into two 32-bit parts. We enter |
2178 | * the least significant 32-bits in f_fsid[0] and the most significant | 2204 | * the least significant 32-bits in f_fsid[0] and the most significant |
2179 | * 32-bits in f_fsid[1]. | 2205 | * 32-bits in f_fsid[1]. |
@@ -2259,18 +2285,18 @@ static struct export_operations ntfs_export_ops = { | |||
2259 | }; | 2285 | }; |
2260 | 2286 | ||
2261 | /** | 2287 | /** |
2262 | * ntfs_fill_super - mount an ntfs files system | 2288 | * ntfs_fill_super - mount an ntfs filesystem |
2263 | * @sb: super block of ntfs file system to mount | 2289 | * @sb: super block of ntfs filesystem to mount |
2264 | * @opt: string containing the mount options | 2290 | * @opt: string containing the mount options |
2265 | * @silent: silence error output | 2291 | * @silent: silence error output |
2266 | * | 2292 | * |
2267 | * ntfs_fill_super() is called by the VFS to mount the device described by @sb | 2293 | * ntfs_fill_super() is called by the VFS to mount the device described by @sb |
2268 | * with the mount otions in @data with the NTFS file system. | 2294 | * with the mount otions in @data with the NTFS filesystem. |
2269 | * | 2295 | * |
2270 | * If @silent is true, remain silent even if errors are detected. This is used | 2296 | * If @silent is true, remain silent even if errors are detected. This is used |
2271 | * during bootup, when the kernel tries to mount the root file system with all | 2297 | * during bootup, when the kernel tries to mount the root filesystem with all |
2272 | * registered file systems one after the other until one succeeds. This implies | 2298 | * registered filesystems one after the other until one succeeds. This implies |
2273 | * that all file systems except the correct one will quite correctly and | 2299 | * that all filesystems except the correct one will quite correctly and |
2274 | * expectedly return an error, but nobody wants to see error messages when in | 2300 | * expectedly return an error, but nobody wants to see error messages when in |
2275 | * fact this is what is supposed to happen. | 2301 | * fact this is what is supposed to happen. |
2276 | * | 2302 | * |
@@ -2330,6 +2356,9 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) | |||
2330 | 2356 | ||
2331 | unlock_kernel(); | 2357 | unlock_kernel(); |
2332 | 2358 | ||
2359 | /* By default, enable sparse support. */ | ||
2360 | NVolSetSparseEnabled(vol); | ||
2361 | |||
2333 | /* Important to get the mount options dealt with now. */ | 2362 | /* Important to get the mount options dealt with now. */ |
2334 | if (!parse_options(vol, (char*)opt)) | 2363 | if (!parse_options(vol, (char*)opt)) |
2335 | goto err_out_now; | 2364 | goto err_out_now; |
@@ -2711,7 +2740,7 @@ static int __init init_ntfs_fs(void) | |||
2711 | ntfs_debug("NTFS driver registered successfully."); | 2740 | ntfs_debug("NTFS driver registered successfully."); |
2712 | return 0; /* Success! */ | 2741 | return 0; /* Success! */ |
2713 | } | 2742 | } |
2714 | printk(KERN_CRIT "NTFS: Failed to register NTFS file system driver!\n"); | 2743 | printk(KERN_CRIT "NTFS: Failed to register NTFS filesystem driver!\n"); |
2715 | 2744 | ||
2716 | sysctl_err_out: | 2745 | sysctl_err_out: |
2717 | kmem_cache_destroy(ntfs_big_inode_cache); | 2746 | kmem_cache_destroy(ntfs_big_inode_cache); |
@@ -2725,7 +2754,7 @@ actx_err_out: | |||
2725 | kmem_cache_destroy(ntfs_index_ctx_cache); | 2754 | kmem_cache_destroy(ntfs_index_ctx_cache); |
2726 | ictx_err_out: | 2755 | ictx_err_out: |
2727 | if (!err) { | 2756 | if (!err) { |
2728 | printk(KERN_CRIT "NTFS: Aborting NTFS file system driver " | 2757 | printk(KERN_CRIT "NTFS: Aborting NTFS filesystem driver " |
2729 | "registration...\n"); | 2758 | "registration...\n"); |
2730 | err = -ENOMEM; | 2759 | err = -ENOMEM; |
2731 | } | 2760 | } |
@@ -2765,7 +2794,7 @@ static void __exit exit_ntfs_fs(void) | |||
2765 | } | 2794 | } |
2766 | 2795 | ||
2767 | MODULE_AUTHOR("Anton Altaparmakov <aia21@cantab.net>"); | 2796 | MODULE_AUTHOR("Anton Altaparmakov <aia21@cantab.net>"); |
2768 | MODULE_DESCRIPTION("NTFS 1.2/3.x driver - Copyright (c) 2001-2004 Anton Altaparmakov"); | 2797 | MODULE_DESCRIPTION("NTFS 1.2/3.x driver - Copyright (c) 2001-2005 Anton Altaparmakov"); |
2769 | MODULE_VERSION(NTFS_VERSION); | 2798 | MODULE_VERSION(NTFS_VERSION); |
2770 | MODULE_LICENSE("GPL"); | 2799 | MODULE_LICENSE("GPL"); |
2771 | #ifdef DEBUG | 2800 | #ifdef DEBUG |