diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ntfs/ChangeLog | 29 | ||||
-rw-r--r-- | fs/ntfs/Makefile | 2 | ||||
-rw-r--r-- | fs/ntfs/attrib.c | 6 | ||||
-rw-r--r-- | fs/ntfs/file.c | 2 | ||||
-rw-r--r-- | fs/ntfs/lcnalloc.c | 8 | ||||
-rw-r--r-- | fs/ntfs/logfile.c | 5 |
6 files changed, 31 insertions, 21 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 1d2ad15f15..6d2a99c13d 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog | |||
@@ -2,20 +2,18 @@ ToDo/Notes: | |||
2 | - Find and fix bugs. | 2 | - Find and fix bugs. |
3 | - Checkpoint or disable the user space journal ($UsnJrnl). | 3 | - Checkpoint or disable the user space journal ($UsnJrnl). |
4 | - In between ntfs_prepare/commit_write, need exclusion between | 4 | - In between ntfs_prepare/commit_write, need exclusion between |
5 | simultaneous file extensions. Need perhaps an NInoResizeUnderway() | 5 | simultaneous file extensions. This is given to us by holding i_sem |
6 | flag which we can set in ntfs_prepare_write() and clear again in | 6 | on the inode. The only places in the kernel when a file is resized |
7 | ntfs_commit_write(). Just have to be careful in readpage/writepage, | 7 | are prepare/commit write and truncate for both of which i_sem is |
8 | as well as in truncate, that we play nice... We might need to have | 8 | held. Just have to be careful in readpage/writepage and all other |
9 | a data_size field in the ntfs_inode to store the real attribute | 9 | helpers not running under i_sem that we play nice... |
10 | length. Also need to be careful with initialized_size extention in | 10 | Also need to be careful with initialized_size extention in |
11 | ntfs_prepare_write. Basically, just be _very_ careful in this code... | 11 | ntfs_prepare_write. Basically, just be _very_ careful in this code... |
12 | OTOH, perhaps i_sem, which is held accross generic_file_write is | 12 | UPDATE: The only things that need to be checked are read/writepage |
13 | sufficient for synchronisation here. We then just need to make sure | 13 | which do not hold i_sem. Note writepage cannot change i_size but it |
14 | ntfs_readpage/writepage/truncate interoperate properly with us. | 14 | needs to cope with a concurrent i_size change, just like readpage. |
15 | UPDATE: The above is all ok as it is due to i_sem held. The only | 15 | Also both need to cope with concurrent changes to the other sizes, |
16 | thing that needs to be checked is ntfs_writepage() which does not | 16 | i.e. initialized/allocated/compressed size, as well. |
17 | hold i_sem. It cannot change i_size but it needs to cope with a | ||
18 | concurrent i_size change. | ||
19 | - Implement mft.c::sync_mft_mirror_umount(). We currently will just | 17 | - Implement mft.c::sync_mft_mirror_umount(). We currently will just |
20 | leave the volume dirty on umount if the final iput(vol->mft_ino) | 18 | leave the volume dirty on umount if the final iput(vol->mft_ino) |
21 | causes a write of any mirrored mft records due to the mft mirror | 19 | causes a write of any mirrored mft records due to the mft mirror |
@@ -31,6 +29,11 @@ ToDo/Notes: | |||
31 | compiled without debug. This avoids a possible denial of service | 29 | compiled without debug. This avoids a possible denial of service |
32 | attack. Thanks to Carl-Daniel Hailfinger from SuSE for pointing this | 30 | attack. Thanks to Carl-Daniel Hailfinger from SuSE for pointing this |
33 | out. | 31 | out. |
32 | - Use i_size_read() in fs/ntfs/attrib.c::ntfs_attr_set(). | ||
33 | - Use i_size_read() in fs/ntfs/logfile.c::ntfs_{check,empty}_logfile(). | ||
34 | - Use i_size_read() once and then use the cached value in | ||
35 | fs/ntfs/lcnalloc.c::ntfs_cluster_alloc(). | ||
36 | - Use i_size_read() in fs/ntfs/file.c::ntfs_file_open(). | ||
34 | 37 | ||
35 | 2.1.22 - Many bug and race fixes and error handling improvements. | 38 | 2.1.22 - Many bug and race fixes and error handling improvements. |
36 | 39 | ||
diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile index 7b66381a0b..f8c97d4122 100644 --- a/fs/ntfs/Makefile +++ b/fs/ntfs/Makefile | |||
@@ -6,7 +6,7 @@ ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \ | |||
6 | index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \ | 6 | index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \ |
7 | unistr.o upcase.o | 7 | unistr.o upcase.o |
8 | 8 | ||
9 | EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.22\" | 9 | EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.23-WIP\" |
10 | 10 | ||
11 | ifeq ($(CONFIG_NTFS_DEBUG),y) | 11 | ifeq ($(CONFIG_NTFS_DEBUG),y) |
12 | EXTRA_CFLAGS += -DDEBUG | 12 | EXTRA_CFLAGS += -DDEBUG |
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 1ff7f90a18..7d668466dc 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c | |||
@@ -1127,6 +1127,10 @@ int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size) | |||
1127 | * byte offset @ofs inside the attribute with the constant byte @val. | 1127 | * byte offset @ofs inside the attribute with the constant byte @val. |
1128 | * | 1128 | * |
1129 | * This function is effectively like memset() applied to an ntfs attribute. | 1129 | * This function is effectively like memset() applied to an ntfs attribute. |
1130 | * Note thie function actually only operates on the page cache pages belonging | ||
1131 | * to the ntfs attribute and it marks them dirty after doing the memset(). | ||
1132 | * Thus it relies on the vm dirty page write code paths to cause the modified | ||
1133 | * pages to be written to the mft record/disk. | ||
1130 | * | 1134 | * |
1131 | * Return 0 on success and -errno on error. An error code of -ESPIPE means | 1135 | * Return 0 on success and -errno on error. An error code of -ESPIPE means |
1132 | * that @ofs + @cnt were outside the end of the attribute and no write was | 1136 | * that @ofs + @cnt were outside the end of the attribute and no write was |
@@ -1155,7 +1159,7 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val) | |||
1155 | end = ofs + cnt; | 1159 | end = ofs + cnt; |
1156 | end_ofs = end & ~PAGE_CACHE_MASK; | 1160 | end_ofs = end & ~PAGE_CACHE_MASK; |
1157 | /* If the end is outside the inode size return -ESPIPE. */ | 1161 | /* If the end is outside the inode size return -ESPIPE. */ |
1158 | if (unlikely(end > VFS_I(ni)->i_size)) { | 1162 | if (unlikely(end > i_size_read(VFS_I(ni)))) { |
1159 | ntfs_error(vol->sb, "Request exceeds end of attribute."); | 1163 | ntfs_error(vol->sb, "Request exceeds end of attribute."); |
1160 | return -ESPIPE; | 1164 | return -ESPIPE; |
1161 | } | 1165 | } |
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index db8713ea0d..e0f530ce6b 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c | |||
@@ -47,7 +47,7 @@ | |||
47 | static int ntfs_file_open(struct inode *vi, struct file *filp) | 47 | static int ntfs_file_open(struct inode *vi, struct file *filp) |
48 | { | 48 | { |
49 | if (sizeof(unsigned long) < 8) { | 49 | if (sizeof(unsigned long) < 8) { |
50 | if (vi->i_size > MAX_LFS_FILESIZE) | 50 | if (i_size_read(vi) > MAX_LFS_FILESIZE) |
51 | return -EFBIG; | 51 | return -EFBIG; |
52 | } | 52 | } |
53 | return generic_file_open(vi, filp); | 53 | return generic_file_open(vi, filp); |
diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c index 23fd911078..5346596fa8 100644 --- a/fs/ntfs/lcnalloc.c +++ b/fs/ntfs/lcnalloc.c | |||
@@ -140,6 +140,7 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn, | |||
140 | LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn; | 140 | LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn; |
141 | LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size; | 141 | LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size; |
142 | s64 clusters; | 142 | s64 clusters; |
143 | loff_t i_size; | ||
143 | struct inode *lcnbmp_vi; | 144 | struct inode *lcnbmp_vi; |
144 | runlist_element *rl = NULL; | 145 | runlist_element *rl = NULL; |
145 | struct address_space *mapping; | 146 | struct address_space *mapping; |
@@ -249,6 +250,7 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn, | |||
249 | clusters = count; | 250 | clusters = count; |
250 | rlpos = rlsize = 0; | 251 | rlpos = rlsize = 0; |
251 | mapping = lcnbmp_vi->i_mapping; | 252 | mapping = lcnbmp_vi->i_mapping; |
253 | i_size = i_size_read(lcnbmp_vi); | ||
252 | while (1) { | 254 | while (1) { |
253 | ntfs_debug("Start of outer while loop: done_zones 0x%x, " | 255 | ntfs_debug("Start of outer while loop: done_zones 0x%x, " |
254 | "search_zone %i, pass %i, zone_start 0x%llx, " | 256 | "search_zone %i, pass %i, zone_start 0x%llx, " |
@@ -263,7 +265,7 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn, | |||
263 | last_read_pos = bmp_pos >> 3; | 265 | last_read_pos = bmp_pos >> 3; |
264 | ntfs_debug("last_read_pos 0x%llx.", | 266 | ntfs_debug("last_read_pos 0x%llx.", |
265 | (unsigned long long)last_read_pos); | 267 | (unsigned long long)last_read_pos); |
266 | if (last_read_pos > lcnbmp_vi->i_size) { | 268 | if (last_read_pos > i_size) { |
267 | ntfs_debug("End of attribute reached. " | 269 | ntfs_debug("End of attribute reached. " |
268 | "Skipping to zone_pass_done."); | 270 | "Skipping to zone_pass_done."); |
269 | goto zone_pass_done; | 271 | goto zone_pass_done; |
@@ -287,8 +289,8 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn, | |||
287 | buf_size = last_read_pos & ~PAGE_CACHE_MASK; | 289 | buf_size = last_read_pos & ~PAGE_CACHE_MASK; |
288 | buf = page_address(page) + buf_size; | 290 | buf = page_address(page) + buf_size; |
289 | buf_size = PAGE_CACHE_SIZE - buf_size; | 291 | buf_size = PAGE_CACHE_SIZE - buf_size; |
290 | if (unlikely(last_read_pos + buf_size > lcnbmp_vi->i_size)) | 292 | if (unlikely(last_read_pos + buf_size > i_size)) |
291 | buf_size = lcnbmp_vi->i_size - last_read_pos; | 293 | buf_size = i_size - last_read_pos; |
292 | buf_size <<= 3; | 294 | buf_size <<= 3; |
293 | lcn = bmp_pos & 7; | 295 | lcn = bmp_pos & 7; |
294 | bmp_pos &= ~7; | 296 | bmp_pos &= ~7; |
diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c index 5e280abafa..e680dd0cdb 100644 --- a/fs/ntfs/logfile.c +++ b/fs/ntfs/logfile.c | |||
@@ -443,7 +443,7 @@ BOOL ntfs_check_logfile(struct inode *log_vi) | |||
443 | /* An empty $LogFile must have been clean before it got emptied. */ | 443 | /* An empty $LogFile must have been clean before it got emptied. */ |
444 | if (NVolLogFileEmpty(vol)) | 444 | if (NVolLogFileEmpty(vol)) |
445 | goto is_empty; | 445 | goto is_empty; |
446 | size = log_vi->i_size; | 446 | size = i_size_read(log_vi); |
447 | /* Make sure the file doesn't exceed the maximum allowed size. */ | 447 | /* Make sure the file doesn't exceed the maximum allowed size. */ |
448 | if (size > MaxLogFileSize) | 448 | if (size > MaxLogFileSize) |
449 | size = MaxLogFileSize; | 449 | size = MaxLogFileSize; |
@@ -689,7 +689,8 @@ BOOL ntfs_empty_logfile(struct inode *log_vi) | |||
689 | if (!NVolLogFileEmpty(vol)) { | 689 | if (!NVolLogFileEmpty(vol)) { |
690 | int err; | 690 | int err; |
691 | 691 | ||
692 | err = ntfs_attr_set(NTFS_I(log_vi), 0, log_vi->i_size, 0xff); | 692 | err = ntfs_attr_set(NTFS_I(log_vi), 0, i_size_read(log_vi), |
693 | 0xff); | ||
693 | if (unlikely(err)) { | 694 | if (unlikely(err)) { |
694 | ntfs_error(vol->sb, "Failed to fill $LogFile with " | 695 | ntfs_error(vol->sb, "Failed to fill $LogFile with " |
695 | "0xff bytes (error code %i).", err); | 696 | "0xff bytes (error code %i).", err); |