aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Altaparmakov <aia21@cantab.net>2005-09-08 16:38:05 -0400
committerAnton Altaparmakov <aia21@cantab.net>2005-09-08 16:38:05 -0400
commitbd45fdd209ca49c5010ac9af469c41ae6dd3f145 (patch)
treeeae397a23bda1ae88b2923a54751a22c46e23f72
parent8dcdebafb848415eae25924b00c4f0b9ec907da0 (diff)
NTFS: Fixup handling of sparse, compressed, and encrypted attributes in
fs/ntfs/aops.c::ntfs_writepage(). Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
-rw-r--r--fs/ntfs/ChangeLog2
-rw-r--r--fs/ntfs/aops.c104
2 files changed, 49 insertions, 57 deletions
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
index b1766642baf..4b8666d7e7f 100644
--- a/fs/ntfs/ChangeLog
+++ b/fs/ntfs/ChangeLog
@@ -79,6 +79,8 @@ ToDo/Notes:
79 fs/ntfs/inode.c::ntfs_read_locked_{,attr_,index_}inode(). 79 fs/ntfs/inode.c::ntfs_read_locked_{,attr_,index_}inode().
80 - Make ntfs_write_block() not instantiate sparse blocks if they contain 80 - Make ntfs_write_block() not instantiate sparse blocks if they contain
81 only zeroes. 81 only zeroes.
82 - Fixup handling of sparse, compressed, and encrypted attributes in
83 fs/ntfs/aops.c::ntfs_writepage().
82 84
832.1.23 - Implement extension of resident files and make writing safe as well as 852.1.23 - Implement extension of resident files and make writing safe as well as
84 many bug fixes, cleanups, and enhancements... 86 many bug fixes, cleanups, and enhancements...
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index f3ad36d8b8c..6f2954aac5a 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -1301,38 +1301,42 @@ retry_writepage:
1301 ntfs_debug("Write outside i_size - truncated?"); 1301 ntfs_debug("Write outside i_size - truncated?");
1302 return 0; 1302 return 0;
1303 } 1303 }
1304 /*
1305 * Only $DATA attributes can be encrypted and only unnamed $DATA
1306 * attributes can be compressed. Index root can have the flags set but
1307 * this means to create compressed/encrypted files, not that the
1308 * attribute is compressed/encrypted.
1309 */
1310 if (ni->type != AT_INDEX_ROOT) {
1311 /* If file is encrypted, deny access, just like NT4. */
1312 if (NInoEncrypted(ni)) {
1313 unlock_page(page);
1314 BUG_ON(ni->type != AT_DATA);
1315 ntfs_debug("Denying write access to encrypted "
1316 "file.");
1317 return -EACCES;
1318 }
1319 /* Compressed data streams are handled in compress.c. */
1320 if (NInoNonResident(ni) && NInoCompressed(ni)) {
1321 BUG_ON(ni->type != AT_DATA);
1322 BUG_ON(ni->name_len);
1323 // TODO: Implement and replace this with
1324 // return ntfs_write_compressed_block(page);
1325 unlock_page(page);
1326 ntfs_error(vi->i_sb, "Writing to compressed files is "
1327 "not supported yet. Sorry.");
1328 return -EOPNOTSUPP;
1329 }
1330 // TODO: Implement and remove this check.
1331 if (NInoNonResident(ni) && NInoSparse(ni)) {
1332 unlock_page(page);
1333 ntfs_error(vi->i_sb, "Writing to sparse files is not "
1334 "supported yet. Sorry.");
1335 return -EOPNOTSUPP;
1336 }
1337 }
1304 /* NInoNonResident() == NInoIndexAllocPresent() */ 1338 /* NInoNonResident() == NInoIndexAllocPresent() */
1305 if (NInoNonResident(ni)) { 1339 if (NInoNonResident(ni)) {
1306 /*
1307 * Only unnamed $DATA attributes can be compressed, encrypted,
1308 * and/or sparse.
1309 */
1310 if (ni->type == AT_DATA && !ni->name_len) {
1311 /* If file is encrypted, deny access, just like NT4. */
1312 if (NInoEncrypted(ni)) {
1313 unlock_page(page);
1314 ntfs_debug("Denying write access to encrypted "
1315 "file.");
1316 return -EACCES;
1317 }
1318 /* Compressed data streams are handled in compress.c. */
1319 if (NInoCompressed(ni)) {
1320 // TODO: Implement and replace this check with
1321 // return ntfs_write_compressed_block(page);
1322 unlock_page(page);
1323 ntfs_error(vi->i_sb, "Writing to compressed "
1324 "files is not supported yet. "
1325 "Sorry.");
1326 return -EOPNOTSUPP;
1327 }
1328 // TODO: Implement and remove this check.
1329 if (NInoSparse(ni)) {
1330 unlock_page(page);
1331 ntfs_error(vi->i_sb, "Writing to sparse files "
1332 "is not supported yet. Sorry.");
1333 return -EOPNOTSUPP;
1334 }
1335 }
1336 /* We have to zero every time due to mmap-at-end-of-file. */ 1340 /* We have to zero every time due to mmap-at-end-of-file. */
1337 if (page->index >= (i_size >> PAGE_CACHE_SHIFT)) { 1341 if (page->index >= (i_size >> PAGE_CACHE_SHIFT)) {
1338 /* The page straddles i_size. */ 1342 /* The page straddles i_size. */
@@ -1345,14 +1349,16 @@ retry_writepage:
1345 /* Handle mst protected attributes. */ 1349 /* Handle mst protected attributes. */
1346 if (NInoMstProtected(ni)) 1350 if (NInoMstProtected(ni))
1347 return ntfs_write_mst_block(page, wbc); 1351 return ntfs_write_mst_block(page, wbc);
1348 /* Normal data stream. */ 1352 /* Normal, non-resident data stream. */
1349 return ntfs_write_block(page, wbc); 1353 return ntfs_write_block(page, wbc);
1350 } 1354 }
1351 /* 1355 /*
1352 * Attribute is resident, implying it is not compressed, encrypted, 1356 * Attribute is resident, implying it is not compressed, encrypted, or
1353 * sparse, or mst protected. This also means the attribute is smaller 1357 * mst protected. This also means the attribute is smaller than an mft
1354 * than an mft record and hence smaller than a page, so can simply 1358 * record and hence smaller than a page, so can simply return error on
1355 * return error on any pages with index above 0. 1359 * any pages with index above 0. Note the attribute can actually be
1360 * marked compressed but if it is resident the actual data is not
1361 * compressed so we are ok to ignore the compressed flag here.
1356 */ 1362 */
1357 BUG_ON(page_has_buffers(page)); 1363 BUG_ON(page_has_buffers(page));
1358 BUG_ON(!PageUptodate(page)); 1364 BUG_ON(!PageUptodate(page));
@@ -1401,30 +1407,14 @@ retry_writepage:
1401 BUG_ON(PageWriteback(page)); 1407 BUG_ON(PageWriteback(page));
1402 set_page_writeback(page); 1408 set_page_writeback(page);
1403 unlock_page(page); 1409 unlock_page(page);
1404
1405 /* 1410 /*
1406 * Here, we don't need to zero the out of bounds area everytime because 1411 * Here, we do not need to zero the out of bounds area everytime
1407 * the below memcpy() already takes care of the mmap-at-end-of-file 1412 * because the below memcpy() already takes care of the
1408 * requirements. If the file is converted to a non-resident one, then 1413 * mmap-at-end-of-file requirements. If the file is converted to a
1409 * the code path use is switched to the non-resident one where the 1414 * non-resident one, then the code path use is switched to the
1410 * zeroing happens on each ntfs_writepage() invocation. 1415 * non-resident one where the zeroing happens on each ntfs_writepage()
1411 * 1416 * invocation.
1412 * The above also applies nicely when i_size is decreased.
1413 *
1414 * When i_size is increased, the memory between the old and new i_size
1415 * _must_ be zeroed (or overwritten with new data). Otherwise we will
1416 * expose data to userspace/disk which should never have been exposed.
1417 *
1418 * FIXME: Ensure that i_size increases do the zeroing/overwriting and
1419 * if we cannot guarantee that, then enable the zeroing below. If the
1420 * zeroing below is enabled, we MUST move the unlock_page() from above
1421 * to after the kunmap_atomic(), i.e. just before the
1422 * end_page_writeback().
1423 * UPDATE: ntfs_prepare/commit_write() do the zeroing on i_size
1424 * increases for resident attributes so those are ok.
1425 * TODO: ntfs_truncate(), others?
1426 */ 1417 */
1427
1428 attr_len = le32_to_cpu(ctx->attr->data.resident.value_length); 1418 attr_len = le32_to_cpu(ctx->attr->data.resident.value_length);
1429 i_size = i_size_read(vi); 1419 i_size = i_size_read(vi);
1430 if (unlikely(attr_len > i_size)) { 1420 if (unlikely(attr_len > i_size)) {