diff options
author | Anton Altaparmakov <aia21@cantab.net> | 2005-03-10 11:06:19 +0000 |
---|---|---|
committer | Anton Altaparmakov <aia21@cantab.net> | 2005-05-05 11:26:01 +0100 |
commit | 905685f68fc72844b8c2689c39a5c6c35e840152 (patch) | |
tree | 0ff1d145a7771b24643c1b685ecbb3f791cda6fb /fs/ntfs/aops.c | |
parent | 43b01fda8b17b2b63e7dcdeed11c2ebba56b1fc9 (diff) | |
download | linux-3.10-905685f68fc72844b8c2689c39a5c6c35e840152.tar.gz linux-3.10-905685f68fc72844b8c2689c39a5c6c35e840152.tar.bz2 linux-3.10-905685f68fc72844b8c2689c39a5c6c35e840152.zip |
NTFS: - Modify ->readpage and ->writepage (fs/ntfs/aops.c) so they detect
and handle the case where an attribute is converted from resident
to non-resident by a concurrent file write.
- Reorder some operations when converting an attribute from resident
to non-resident (fs/ntfs/attrib.c) so it is safe wrt concurrent
->readpage and ->writepage.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Diffstat (limited to 'fs/ntfs/aops.c')
-rw-r--r-- | fs/ntfs/aops.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index 2a7cba258cc..6241c4cfbe2 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c @@ -355,6 +355,7 @@ static int ntfs_readpage(struct file *file, struct page *page) u32 attr_len; int err = 0; +retry_readpage: BUG_ON(!PageLocked(page)); /* * This can potentially happen because we clear PageUptodate() during @@ -408,6 +409,14 @@ static int ntfs_readpage(struct file *file, struct page *page) err = PTR_ERR(mrec); goto err_out; } + /* + * If a parallel write made the attribute non-resident, drop the mft + * record and retry the readpage. + */ + if (unlikely(NInoNonResident(ni))) { + unmap_mft_record(base_ni); + goto retry_readpage; + } ctx = ntfs_attr_get_search_ctx(base_ni, mrec); if (unlikely(!ctx)) { err = -ENOMEM; @@ -1248,6 +1257,7 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc) u32 attr_len; int err; +retry_writepage: BUG_ON(!PageLocked(page)); i_size = i_size_read(vi); /* Is the page fully outside i_size? (truncate in progress) */ @@ -1338,6 +1348,14 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc) ctx = NULL; goto err_out; } + /* + * If a parallel write made the attribute non-resident, drop the mft + * record and retry the writepage. + */ + if (unlikely(NInoNonResident(ni))) { + unmap_mft_record(base_ni); + goto retry_writepage; + } ctx = ntfs_attr_get_search_ctx(base_ni, m); if (unlikely(!ctx)) { err = -ENOMEM; |