diff options
author | Anton Altaparmakov <aia21@cantab.net> | 2004-11-18 15:34:59 -0500 |
---|---|---|
committer | Anton Altaparmakov <aia21@cantab.net> | 2005-05-05 05:34:45 -0400 |
commit | 218357ff1b1b2f1bfdce89d608dbe33dd2f9f14b (patch) | |
tree | b7621daec3c516507fed85a25e9e82198589f216 /fs | |
parent | 206f9f35b2348b7b966ff18a5564b8a3ca325ed5 (diff) |
NTFS: - Use i_size_read() in fs/ntfs/super.c once and then use the cached
value afterwards. Cache the initialized_size in the same way and
protect access to the two sizes using the size_lock.
- Minor optimization to fs/ntfs/super.c::ntfs_statfs() and its helpers.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ntfs/ChangeLog | 4 | ||||
-rw-r--r-- | fs/ntfs/super.c | 102 |
2 files changed, 58 insertions, 48 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 7bbbb9152fee..f4e087a83e78 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog | |||
@@ -43,6 +43,10 @@ ToDo/Notes: | |||
43 | same way and protect access to the two sizes using the size_lock. | 43 | same way and protect access to the two sizes using the size_lock. |
44 | - Use i_size_read() in fs/ntfs/dir.c once and then use the cached | 44 | - Use i_size_read() in fs/ntfs/dir.c once and then use the cached |
45 | value afterwards. | 45 | value afterwards. |
46 | - Use i_size_read() in fs/ntfs/super.c once and then use the cached | ||
47 | value afterwards. Cache the initialized_size in the same way and | ||
48 | protect access to the two sizes using the size_lock. | ||
49 | - Minor optimization to fs/ntfs/super.c::ntfs_statfs() and its helpers. | ||
46 | 50 | ||
47 | 2.1.22 - Many bug and race fixes and error handling improvements. | 51 | 2.1.22 - Many bug and race fixes and error handling improvements. |
48 | 52 | ||
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 212a3d0f2073..0ad0c51e9eb9 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c | |||
@@ -990,12 +990,12 @@ static BOOL load_and_init_mft_mirror(ntfs_volume *vol) | |||
990 | */ | 990 | */ |
991 | static BOOL check_mft_mirror(ntfs_volume *vol) | 991 | static BOOL check_mft_mirror(ntfs_volume *vol) |
992 | { | 992 | { |
993 | unsigned long index; | ||
994 | struct super_block *sb = vol->sb; | 993 | struct super_block *sb = vol->sb; |
995 | ntfs_inode *mirr_ni; | 994 | ntfs_inode *mirr_ni; |
996 | struct page *mft_page, *mirr_page; | 995 | struct page *mft_page, *mirr_page; |
997 | u8 *kmft, *kmirr; | 996 | u8 *kmft, *kmirr; |
998 | runlist_element *rl, rl2[2]; | 997 | runlist_element *rl, rl2[2]; |
998 | pgoff_t index; | ||
999 | int mrecs_per_page, i; | 999 | int mrecs_per_page, i; |
1000 | 1000 | ||
1001 | ntfs_debug("Entering."); | 1001 | ntfs_debug("Entering."); |
@@ -1205,10 +1205,11 @@ static BOOL load_and_init_quota(ntfs_volume *vol) | |||
1205 | */ | 1205 | */ |
1206 | static BOOL load_and_init_attrdef(ntfs_volume *vol) | 1206 | static BOOL load_and_init_attrdef(ntfs_volume *vol) |
1207 | { | 1207 | { |
1208 | loff_t i_size; | ||
1208 | struct super_block *sb = vol->sb; | 1209 | struct super_block *sb = vol->sb; |
1209 | struct inode *ino; | 1210 | struct inode *ino; |
1210 | struct page *page; | 1211 | struct page *page; |
1211 | unsigned long index, max_index; | 1212 | pgoff_t index, max_index; |
1212 | unsigned int size; | 1213 | unsigned int size; |
1213 | 1214 | ||
1214 | ntfs_debug("Entering."); | 1215 | ntfs_debug("Entering."); |
@@ -1220,13 +1221,14 @@ static BOOL load_and_init_attrdef(ntfs_volume *vol) | |||
1220 | goto failed; | 1221 | goto failed; |
1221 | } | 1222 | } |
1222 | /* The size of FILE_AttrDef must be above 0 and fit inside 31 bits. */ | 1223 | /* The size of FILE_AttrDef must be above 0 and fit inside 31 bits. */ |
1223 | if (!ino->i_size || ino->i_size > 0x7fffffff) | 1224 | i_size = i_size_read(ino); |
1225 | if (i_size <= 0 || i_size > 0x7fffffff) | ||
1224 | goto iput_failed; | 1226 | goto iput_failed; |
1225 | vol->attrdef = (ATTR_DEF*)ntfs_malloc_nofs(ino->i_size); | 1227 | vol->attrdef = (ATTR_DEF*)ntfs_malloc_nofs(i_size); |
1226 | if (!vol->attrdef) | 1228 | if (!vol->attrdef) |
1227 | goto iput_failed; | 1229 | goto iput_failed; |
1228 | index = 0; | 1230 | index = 0; |
1229 | max_index = ino->i_size >> PAGE_CACHE_SHIFT; | 1231 | max_index = i_size >> PAGE_CACHE_SHIFT; |
1230 | size = PAGE_CACHE_SIZE; | 1232 | size = PAGE_CACHE_SIZE; |
1231 | while (index < max_index) { | 1233 | while (index < max_index) { |
1232 | /* Read the attrdef table and copy it into the linear buffer. */ | 1234 | /* Read the attrdef table and copy it into the linear buffer. */ |
@@ -1239,12 +1241,12 @@ read_partial_attrdef_page: | |||
1239 | ntfs_unmap_page(page); | 1241 | ntfs_unmap_page(page); |
1240 | }; | 1242 | }; |
1241 | if (size == PAGE_CACHE_SIZE) { | 1243 | if (size == PAGE_CACHE_SIZE) { |
1242 | size = ino->i_size & ~PAGE_CACHE_MASK; | 1244 | size = i_size & ~PAGE_CACHE_MASK; |
1243 | if (size) | 1245 | if (size) |
1244 | goto read_partial_attrdef_page; | 1246 | goto read_partial_attrdef_page; |
1245 | } | 1247 | } |
1246 | vol->attrdef_size = ino->i_size; | 1248 | vol->attrdef_size = i_size; |
1247 | ntfs_debug("Read %llu bytes from $AttrDef.", ino->i_size); | 1249 | ntfs_debug("Read %llu bytes from $AttrDef.", i_size); |
1248 | iput(ino); | 1250 | iput(ino); |
1249 | return TRUE; | 1251 | return TRUE; |
1250 | free_iput_failed: | 1252 | free_iput_failed: |
@@ -1267,10 +1269,11 @@ failed: | |||
1267 | */ | 1269 | */ |
1268 | static BOOL load_and_init_upcase(ntfs_volume *vol) | 1270 | static BOOL load_and_init_upcase(ntfs_volume *vol) |
1269 | { | 1271 | { |
1272 | loff_t i_size; | ||
1270 | struct super_block *sb = vol->sb; | 1273 | struct super_block *sb = vol->sb; |
1271 | struct inode *ino; | 1274 | struct inode *ino; |
1272 | struct page *page; | 1275 | struct page *page; |
1273 | unsigned long index, max_index; | 1276 | pgoff_t index, max_index; |
1274 | unsigned int size; | 1277 | unsigned int size; |
1275 | int i, max; | 1278 | int i, max; |
1276 | 1279 | ||
@@ -1286,14 +1289,15 @@ static BOOL load_and_init_upcase(ntfs_volume *vol) | |||
1286 | * The upcase size must not be above 64k Unicode characters, must not | 1289 | * The upcase size must not be above 64k Unicode characters, must not |
1287 | * be zero and must be a multiple of sizeof(ntfschar). | 1290 | * be zero and must be a multiple of sizeof(ntfschar). |
1288 | */ | 1291 | */ |
1289 | if (!ino->i_size || ino->i_size & (sizeof(ntfschar) - 1) || | 1292 | i_size = i_size_read(ino); |
1290 | ino->i_size > 64ULL * 1024 * sizeof(ntfschar)) | 1293 | if (!i_size || i_size & (sizeof(ntfschar) - 1) || |
1294 | i_size > 64ULL * 1024 * sizeof(ntfschar)) | ||
1291 | goto iput_upcase_failed; | 1295 | goto iput_upcase_failed; |
1292 | vol->upcase = (ntfschar*)ntfs_malloc_nofs(ino->i_size); | 1296 | vol->upcase = (ntfschar*)ntfs_malloc_nofs(i_size); |
1293 | if (!vol->upcase) | 1297 | if (!vol->upcase) |
1294 | goto iput_upcase_failed; | 1298 | goto iput_upcase_failed; |
1295 | index = 0; | 1299 | index = 0; |
1296 | max_index = ino->i_size >> PAGE_CACHE_SHIFT; | 1300 | max_index = i_size >> PAGE_CACHE_SHIFT; |
1297 | size = PAGE_CACHE_SIZE; | 1301 | size = PAGE_CACHE_SIZE; |
1298 | while (index < max_index) { | 1302 | while (index < max_index) { |
1299 | /* Read the upcase table and copy it into the linear buffer. */ | 1303 | /* Read the upcase table and copy it into the linear buffer. */ |
@@ -1306,13 +1310,13 @@ read_partial_upcase_page: | |||
1306 | ntfs_unmap_page(page); | 1310 | ntfs_unmap_page(page); |
1307 | }; | 1311 | }; |
1308 | if (size == PAGE_CACHE_SIZE) { | 1312 | if (size == PAGE_CACHE_SIZE) { |
1309 | size = ino->i_size & ~PAGE_CACHE_MASK; | 1313 | size = i_size & ~PAGE_CACHE_MASK; |
1310 | if (size) | 1314 | if (size) |
1311 | goto read_partial_upcase_page; | 1315 | goto read_partial_upcase_page; |
1312 | } | 1316 | } |
1313 | vol->upcase_len = ino->i_size >> UCHAR_T_SIZE_BITS; | 1317 | vol->upcase_len = i_size >> UCHAR_T_SIZE_BITS; |
1314 | ntfs_debug("Read %llu bytes from $UpCase (expected %zu bytes).", | 1318 | ntfs_debug("Read %llu bytes from $UpCase (expected %zu bytes).", |
1315 | ino->i_size, 64 * 1024 * sizeof(ntfschar)); | 1319 | i_size, 64 * 1024 * sizeof(ntfschar)); |
1316 | iput(ino); | 1320 | iput(ino); |
1317 | down(&ntfs_lock); | 1321 | down(&ntfs_lock); |
1318 | if (!default_upcase) { | 1322 | if (!default_upcase) { |
@@ -1435,7 +1439,7 @@ static BOOL load_system_files(ntfs_volume *vol) | |||
1435 | iput(vol->lcnbmp_ino); | 1439 | iput(vol->lcnbmp_ino); |
1436 | goto bitmap_failed; | 1440 | goto bitmap_failed; |
1437 | } | 1441 | } |
1438 | if ((vol->nr_clusters + 7) >> 3 > vol->lcnbmp_ino->i_size) { | 1442 | if ((vol->nr_clusters + 7) >> 3 > i_size_read(vol->lcnbmp_ino)) { |
1439 | iput(vol->lcnbmp_ino); | 1443 | iput(vol->lcnbmp_ino); |
1440 | bitmap_failed: | 1444 | bitmap_failed: |
1441 | ntfs_error(sb, "Failed to load $Bitmap."); | 1445 | ntfs_error(sb, "Failed to load $Bitmap."); |
@@ -1959,8 +1963,7 @@ static s64 get_nr_free_clusters(ntfs_volume *vol) | |||
1959 | struct address_space *mapping = vol->lcnbmp_ino->i_mapping; | 1963 | struct address_space *mapping = vol->lcnbmp_ino->i_mapping; |
1960 | filler_t *readpage = (filler_t*)mapping->a_ops->readpage; | 1964 | filler_t *readpage = (filler_t*)mapping->a_ops->readpage; |
1961 | struct page *page; | 1965 | struct page *page; |
1962 | unsigned long index, max_index; | 1966 | pgoff_t index, max_index; |
1963 | unsigned int max_size; | ||
1964 | 1967 | ||
1965 | ntfs_debug("Entering."); | 1968 | ntfs_debug("Entering."); |
1966 | /* Serialize accesses to the cluster bitmap. */ | 1969 | /* Serialize accesses to the cluster bitmap. */ |
@@ -1972,11 +1975,10 @@ static s64 get_nr_free_clusters(ntfs_volume *vol) | |||
1972 | */ | 1975 | */ |
1973 | max_index = (((vol->nr_clusters + 7) >> 3) + PAGE_CACHE_SIZE - 1) >> | 1976 | max_index = (((vol->nr_clusters + 7) >> 3) + PAGE_CACHE_SIZE - 1) >> |
1974 | PAGE_CACHE_SHIFT; | 1977 | PAGE_CACHE_SHIFT; |
1975 | /* Use multiples of 4 bytes. */ | 1978 | /* Use multiples of 4 bytes, thus max_size is PAGE_CACHE_SIZE / 4. */ |
1976 | max_size = PAGE_CACHE_SIZE >> 2; | 1979 | ntfs_debug("Reading $Bitmap, max_index = 0x%lx, max_size = 0x%lx.", |
1977 | ntfs_debug("Reading $Bitmap, max_index = 0x%lx, max_size = 0x%x.", | 1980 | max_index, PAGE_CACHE_SIZE / 4); |
1978 | max_index, max_size); | 1981 | for (index = 0; index < max_index; index++) { |
1979 | for (index = 0UL; index < max_index; index++) { | ||
1980 | unsigned int i; | 1982 | unsigned int i; |
1981 | /* | 1983 | /* |
1982 | * Read the page from page cache, getting it from backing store | 1984 | * Read the page from page cache, getting it from backing store |
@@ -2008,7 +2010,7 @@ static s64 get_nr_free_clusters(ntfs_volume *vol) | |||
2008 | * the result as all out of range bytes are set to zero by | 2010 | * the result as all out of range bytes are set to zero by |
2009 | * ntfs_readpage(). | 2011 | * ntfs_readpage(). |
2010 | */ | 2012 | */ |
2011 | for (i = 0; i < max_size; i++) | 2013 | for (i = 0; i < PAGE_CACHE_SIZE / 4; i++) |
2012 | nr_free -= (s64)hweight32(kaddr[i]); | 2014 | nr_free -= (s64)hweight32(kaddr[i]); |
2013 | kunmap_atomic(kaddr, KM_USER0); | 2015 | kunmap_atomic(kaddr, KM_USER0); |
2014 | page_cache_release(page); | 2016 | page_cache_release(page); |
@@ -2031,6 +2033,8 @@ static s64 get_nr_free_clusters(ntfs_volume *vol) | |||
2031 | /** | 2033 | /** |
2032 | * __get_nr_free_mft_records - return the number of free inodes on a volume | 2034 | * __get_nr_free_mft_records - return the number of free inodes on a volume |
2033 | * @vol: ntfs volume for which to obtain free inode count | 2035 | * @vol: ntfs volume for which to obtain free inode count |
2036 | * @nr_free: number of mft records in file system | ||
2037 | * @max_index: maximum number of pages containing set bits | ||
2034 | * | 2038 | * |
2035 | * Calculate the number of free mft records (inodes) on the mounted NTFS | 2039 | * Calculate the number of free mft records (inodes) on the mounted NTFS |
2036 | * volume @vol. We actually calculate the number of mft records in use instead | 2040 | * volume @vol. We actually calculate the number of mft records in use instead |
@@ -2043,32 +2047,20 @@ static s64 get_nr_free_clusters(ntfs_volume *vol) | |||
2043 | * | 2047 | * |
2044 | * NOTE: Caller must hold mftbmp_lock rw_semaphore for reading or writing. | 2048 | * NOTE: Caller must hold mftbmp_lock rw_semaphore for reading or writing. |
2045 | */ | 2049 | */ |
2046 | static unsigned long __get_nr_free_mft_records(ntfs_volume *vol) | 2050 | static unsigned long __get_nr_free_mft_records(ntfs_volume *vol, |
2051 | s64 nr_free, const pgoff_t max_index) | ||
2047 | { | 2052 | { |
2048 | s64 nr_free; | ||
2049 | u32 *kaddr; | 2053 | u32 *kaddr; |
2050 | struct address_space *mapping = vol->mftbmp_ino->i_mapping; | 2054 | struct address_space *mapping = vol->mftbmp_ino->i_mapping; |
2051 | filler_t *readpage = (filler_t*)mapping->a_ops->readpage; | 2055 | filler_t *readpage = (filler_t*)mapping->a_ops->readpage; |
2052 | struct page *page; | 2056 | struct page *page; |
2053 | unsigned long index, max_index; | 2057 | pgoff_t index; |
2054 | unsigned int max_size; | ||
2055 | 2058 | ||
2056 | ntfs_debug("Entering."); | 2059 | ntfs_debug("Entering."); |
2057 | /* Number of mft records in file system (at this point in time). */ | 2060 | /* Use multiples of 4 bytes, thus max_size is PAGE_CACHE_SIZE / 4. */ |
2058 | nr_free = vol->mft_ino->i_size >> vol->mft_record_size_bits; | ||
2059 | /* | ||
2060 | * Convert the maximum number of set bits into bytes rounded up, then | ||
2061 | * convert into multiples of PAGE_CACHE_SIZE, rounding up so that if we | ||
2062 | * have one full and one partial page max_index = 2. | ||
2063 | */ | ||
2064 | max_index = ((((NTFS_I(vol->mft_ino)->initialized_size >> | ||
2065 | vol->mft_record_size_bits) + 7) >> 3) + | ||
2066 | PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | ||
2067 | /* Use multiples of 4 bytes. */ | ||
2068 | max_size = PAGE_CACHE_SIZE >> 2; | ||
2069 | ntfs_debug("Reading $MFT/$BITMAP, max_index = 0x%lx, max_size = " | 2061 | ntfs_debug("Reading $MFT/$BITMAP, max_index = 0x%lx, max_size = " |
2070 | "0x%x.", max_index, max_size); | 2062 | "0x%lx.", max_index, PAGE_CACHE_SIZE / 4); |
2071 | for (index = 0UL; index < max_index; index++) { | 2063 | for (index = 0; index < max_index; index++) { |
2072 | unsigned int i; | 2064 | unsigned int i; |
2073 | /* | 2065 | /* |
2074 | * Read the page from page cache, getting it from backing store | 2066 | * Read the page from page cache, getting it from backing store |
@@ -2100,7 +2092,7 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol) | |||
2100 | * the result as all out of range bytes are set to zero by | 2092 | * the result as all out of range bytes are set to zero by |
2101 | * ntfs_readpage(). | 2093 | * ntfs_readpage(). |
2102 | */ | 2094 | */ |
2103 | for (i = 0; i < max_size; i++) | 2095 | for (i = 0; i < PAGE_CACHE_SIZE / 4; i++) |
2104 | nr_free -= (s64)hweight32(kaddr[i]); | 2096 | nr_free -= (s64)hweight32(kaddr[i]); |
2105 | kunmap_atomic(kaddr, KM_USER0); | 2097 | kunmap_atomic(kaddr, KM_USER0); |
2106 | page_cache_release(page); | 2098 | page_cache_release(page); |
@@ -2134,8 +2126,11 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol) | |||
2134 | */ | 2126 | */ |
2135 | static int ntfs_statfs(struct super_block *sb, struct kstatfs *sfs) | 2127 | static int ntfs_statfs(struct super_block *sb, struct kstatfs *sfs) |
2136 | { | 2128 | { |
2137 | ntfs_volume *vol = NTFS_SB(sb); | ||
2138 | s64 size; | 2129 | s64 size; |
2130 | ntfs_volume *vol = NTFS_SB(sb); | ||
2131 | ntfs_inode *mft_ni = NTFS_I(vol->mft_ino); | ||
2132 | pgoff_t max_index; | ||
2133 | unsigned long flags; | ||
2139 | 2134 | ||
2140 | ntfs_debug("Entering."); | 2135 | ntfs_debug("Entering."); |
2141 | /* Type of filesystem. */ | 2136 | /* Type of filesystem. */ |
@@ -2158,10 +2153,20 @@ static int ntfs_statfs(struct super_block *sb, struct kstatfs *sfs) | |||
2158 | sfs->f_bavail = sfs->f_bfree = size; | 2153 | sfs->f_bavail = sfs->f_bfree = size; |
2159 | /* Serialize accesses to the inode bitmap. */ | 2154 | /* Serialize accesses to the inode bitmap. */ |
2160 | down_read(&vol->mftbmp_lock); | 2155 | down_read(&vol->mftbmp_lock); |
2156 | read_lock_irqsave(&mft_ni->size_lock, flags); | ||
2157 | size = i_size_read(vol->mft_ino) >> vol->mft_record_size_bits; | ||
2158 | /* | ||
2159 | * Convert the maximum number of set bits into bytes rounded up, then | ||
2160 | * convert into multiples of PAGE_CACHE_SIZE, rounding up so that if we | ||
2161 | * have one full and one partial page max_index = 2. | ||
2162 | */ | ||
2163 | max_index = ((((mft_ni->initialized_size >> vol->mft_record_size_bits) | ||
2164 | + 7) >> 3) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | ||
2165 | read_unlock_irqrestore(&mft_ni->size_lock, flags); | ||
2161 | /* Number of inodes in file system (at this point in time). */ | 2166 | /* Number of inodes in file system (at this point in time). */ |
2162 | sfs->f_files = vol->mft_ino->i_size >> vol->mft_record_size_bits; | 2167 | sfs->f_files = size; |
2163 | /* Free inodes in fs (based on current total count). */ | 2168 | /* Free inodes in fs (based on current total count). */ |
2164 | sfs->f_ffree = __get_nr_free_mft_records(vol); | 2169 | sfs->f_ffree = __get_nr_free_mft_records(vol, size, max_index); |
2165 | up_read(&vol->mftbmp_lock); | 2170 | up_read(&vol->mftbmp_lock); |
2166 | /* | 2171 | /* |
2167 | * File system id. This is extremely *nix flavour dependent and even | 2172 | * File system id. This is extremely *nix flavour dependent and even |
@@ -2347,7 +2352,8 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) | |||
2347 | } | 2352 | } |
2348 | 2353 | ||
2349 | /* Get the size of the device in units of NTFS_BLOCK_SIZE bytes. */ | 2354 | /* Get the size of the device in units of NTFS_BLOCK_SIZE bytes. */ |
2350 | vol->nr_blocks = sb->s_bdev->bd_inode->i_size >> NTFS_BLOCK_SIZE_BITS; | 2355 | vol->nr_blocks = i_size_read(sb->s_bdev->bd_inode) >> |
2356 | NTFS_BLOCK_SIZE_BITS; | ||
2351 | 2357 | ||
2352 | /* Read the boot sector and return unlocked buffer head to it. */ | 2358 | /* Read the boot sector and return unlocked buffer head to it. */ |
2353 | if (!(bh = read_ntfs_boot_sector(sb, silent))) { | 2359 | if (!(bh = read_ntfs_boot_sector(sb, silent))) { |