aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ntfs/attrib.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ntfs/attrib.c')
-rw-r--r--fs/ntfs/attrib.c125
1 files changed, 107 insertions, 18 deletions
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index cd0f9e740b14..3f9a4ff42ee5 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -43,6 +43,9 @@
43 * which is not an error as such. This is -ENOENT. It means that @vcn is out 43 * which is not an error as such. This is -ENOENT. It means that @vcn is out
44 * of bounds of the runlist. 44 * of bounds of the runlist.
45 * 45 *
46 * Note the runlist can be NULL after this function returns if @vcn is zero and
47 * the attribute has zero allocated size, i.e. there simply is no runlist.
48 *
46 * Locking: - The runlist must be locked for writing. 49 * Locking: - The runlist must be locked for writing.
47 * - This function modifies the runlist. 50 * - This function modifies the runlist.
48 */ 51 */
@@ -54,6 +57,7 @@ int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn)
54 ATTR_RECORD *a; 57 ATTR_RECORD *a;
55 ntfs_attr_search_ctx *ctx; 58 ntfs_attr_search_ctx *ctx;
56 runlist_element *rl; 59 runlist_element *rl;
60 unsigned long flags;
57 int err = 0; 61 int err = 0;
58 62
59 ntfs_debug("Mapping runlist part containing vcn 0x%llx.", 63 ntfs_debug("Mapping runlist part containing vcn 0x%llx.",
@@ -85,8 +89,11 @@ int ntfs_map_runlist_nolock(ntfs_inode *ni, VCN vcn)
85 * ntfs_mapping_pairs_decompress() fails. 89 * ntfs_mapping_pairs_decompress() fails.
86 */ 90 */
87 end_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn) + 1; 91 end_vcn = sle64_to_cpu(a->data.non_resident.highest_vcn) + 1;
88 if (unlikely(!a->data.non_resident.lowest_vcn && end_vcn <= 1)) 92 if (unlikely(!a->data.non_resident.lowest_vcn && end_vcn <= 1)) {
93 read_lock_irqsave(&ni->size_lock, flags);
89 end_vcn = ni->allocated_size >> ni->vol->cluster_size_bits; 94 end_vcn = ni->allocated_size >> ni->vol->cluster_size_bits;
95 read_unlock_irqrestore(&ni->size_lock, flags);
96 }
90 if (unlikely(vcn >= end_vcn)) { 97 if (unlikely(vcn >= end_vcn)) {
91 err = -ENOENT; 98 err = -ENOENT;
92 goto err_out; 99 goto err_out;
@@ -165,6 +172,7 @@ LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn,
165 const BOOL write_locked) 172 const BOOL write_locked)
166{ 173{
167 LCN lcn; 174 LCN lcn;
175 unsigned long flags;
168 BOOL is_retry = FALSE; 176 BOOL is_retry = FALSE;
169 177
170 ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, %s_locked.", 178 ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, %s_locked.",
@@ -173,6 +181,14 @@ LCN ntfs_attr_vcn_to_lcn_nolock(ntfs_inode *ni, const VCN vcn,
173 BUG_ON(!ni); 181 BUG_ON(!ni);
174 BUG_ON(!NInoNonResident(ni)); 182 BUG_ON(!NInoNonResident(ni));
175 BUG_ON(vcn < 0); 183 BUG_ON(vcn < 0);
184 if (!ni->runlist.rl) {
185 read_lock_irqsave(&ni->size_lock, flags);
186 if (!ni->allocated_size) {
187 read_unlock_irqrestore(&ni->size_lock, flags);
188 return LCN_ENOENT;
189 }
190 read_unlock_irqrestore(&ni->size_lock, flags);
191 }
176retry_remap: 192retry_remap:
177 /* Convert vcn to lcn. If that fails map the runlist and retry once. */ 193 /* Convert vcn to lcn. If that fails map the runlist and retry once. */
178 lcn = ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn); 194 lcn = ntfs_rl_vcn_to_lcn(ni->runlist.rl, vcn);
@@ -255,6 +271,7 @@ retry_remap:
255runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, const VCN vcn, 271runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, const VCN vcn,
256 const BOOL write_locked) 272 const BOOL write_locked)
257{ 273{
274 unsigned long flags;
258 runlist_element *rl; 275 runlist_element *rl;
259 int err = 0; 276 int err = 0;
260 BOOL is_retry = FALSE; 277 BOOL is_retry = FALSE;
@@ -265,6 +282,14 @@ runlist_element *ntfs_attr_find_vcn_nolock(ntfs_inode *ni, const VCN vcn,
265 BUG_ON(!ni); 282 BUG_ON(!ni);
266 BUG_ON(!NInoNonResident(ni)); 283 BUG_ON(!NInoNonResident(ni));
267 BUG_ON(vcn < 0); 284 BUG_ON(vcn < 0);
285 if (!ni->runlist.rl) {
286 read_lock_irqsave(&ni->size_lock, flags);
287 if (!ni->allocated_size) {
288 read_unlock_irqrestore(&ni->size_lock, flags);
289 return ERR_PTR(-ENOENT);
290 }
291 read_unlock_irqrestore(&ni->size_lock, flags);
292 }
268retry_remap: 293retry_remap:
269 rl = ni->runlist.rl; 294 rl = ni->runlist.rl;
270 if (likely(rl && vcn >= rl[0].vcn)) { 295 if (likely(rl && vcn >= rl[0].vcn)) {
@@ -528,6 +553,11 @@ int load_attribute_list(ntfs_volume *vol, runlist *runlist, u8 *al_start,
528 block_size_bits = sb->s_blocksize_bits; 553 block_size_bits = sb->s_blocksize_bits;
529 down_read(&runlist->lock); 554 down_read(&runlist->lock);
530 rl = runlist->rl; 555 rl = runlist->rl;
556 if (!rl) {
557 ntfs_error(sb, "Cannot read attribute list since runlist is "
558 "missing.");
559 goto err_out;
560 }
531 /* Read all clusters specified by the runlist one run at a time. */ 561 /* Read all clusters specified by the runlist one run at a time. */
532 while (rl->length) { 562 while (rl->length) {
533 lcn = ntfs_rl_vcn_to_lcn(rl, rl->vcn); 563 lcn = ntfs_rl_vcn_to_lcn(rl, rl->vcn);
@@ -1247,6 +1277,46 @@ int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size)
1247} 1277}
1248 1278
1249/** 1279/**
1280 * ntfs_resident_attr_value_resize - resize the value of a resident attribute
1281 * @m: mft record containing attribute record
1282 * @a: attribute record whose value to resize
1283 * @new_size: new size in bytes to which to resize the attribute value of @a
1284 *
1285 * Resize the value of the attribute @a in the mft record @m to @new_size bytes.
1286 * If the value is made bigger, the newly allocated space is cleared.
1287 *
1288 * Return 0 on success and -errno on error. The following error codes are
1289 * defined:
1290 * -ENOSPC - Not enough space in the mft record @m to perform the resize.
1291 *
1292 * Note: On error, no modifications have been performed whatsoever.
1293 *
1294 * Warning: If you make a record smaller without having copied all the data you
1295 * are interested in the data may be overwritten.
1296 */
1297int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a,
1298 const u32 new_size)
1299{
1300 u32 old_size;
1301
1302 /* Resize the resident part of the attribute record. */
1303 if (ntfs_attr_record_resize(m, a,
1304 le16_to_cpu(a->data.resident.value_offset) + new_size))
1305 return -ENOSPC;
1306 /*
1307 * The resize succeeded! If we made the attribute value bigger, clear
1308 * the area between the old size and @new_size.
1309 */
1310 old_size = le32_to_cpu(a->data.resident.value_length);
1311 if (new_size > old_size)
1312 memset((u8*)a + le16_to_cpu(a->data.resident.value_offset) +
1313 old_size, 0, new_size - old_size);
1314 /* Finally update the length of the attribute value. */
1315 a->data.resident.value_length = cpu_to_le32(new_size);
1316 return 0;
1317}
1318
1319/**
1250 * ntfs_attr_make_non_resident - convert a resident to a non-resident attribute 1320 * ntfs_attr_make_non_resident - convert a resident to a non-resident attribute
1251 * @ni: ntfs inode describing the attribute to convert 1321 * @ni: ntfs inode describing the attribute to convert
1252 * 1322 *
@@ -1302,6 +1372,12 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni)
1302 return err; 1372 return err;
1303 } 1373 }
1304 /* 1374 /*
1375 * FIXME: Compressed and encrypted attributes are not supported when
1376 * writing and we should never have gotten here for them.
1377 */
1378 BUG_ON(NInoCompressed(ni));
1379 BUG_ON(NInoEncrypted(ni));
1380 /*
1305 * The size needs to be aligned to a cluster boundary for allocation 1381 * The size needs to be aligned to a cluster boundary for allocation
1306 * purposes. 1382 * purposes.
1307 */ 1383 */
@@ -1377,10 +1453,15 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni)
1377 BUG_ON(a->non_resident); 1453 BUG_ON(a->non_resident);
1378 /* 1454 /*
1379 * Calculate new offsets for the name and the mapping pairs array. 1455 * Calculate new offsets for the name and the mapping pairs array.
1380 * We assume the attribute is not compressed or sparse.
1381 */ 1456 */
1382 name_ofs = (offsetof(ATTR_REC, 1457 if (NInoSparse(ni) || NInoCompressed(ni))
1383 data.non_resident.compressed_size) + 7) & ~7; 1458 name_ofs = (offsetof(ATTR_REC,
1459 data.non_resident.compressed_size) +
1460 sizeof(a->data.non_resident.compressed_size) +
1461 7) & ~7;
1462 else
1463 name_ofs = (offsetof(ATTR_REC,
1464 data.non_resident.compressed_size) + 7) & ~7;
1384 mp_ofs = (name_ofs + a->name_length * sizeof(ntfschar) + 7) & ~7; 1465 mp_ofs = (name_ofs + a->name_length * sizeof(ntfschar) + 7) & ~7;
1385 /* 1466 /*
1386 * Determine the size of the resident part of the now non-resident 1467 * Determine the size of the resident part of the now non-resident
@@ -1419,24 +1500,23 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni)
1419 memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset), 1500 memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset),
1420 a->name_length * sizeof(ntfschar)); 1501 a->name_length * sizeof(ntfschar));
1421 a->name_offset = cpu_to_le16(name_ofs); 1502 a->name_offset = cpu_to_le16(name_ofs);
1422 /*
1423 * FIXME: For now just clear all of these as we do not support them
1424 * when writing.
1425 */
1426 a->flags &= cpu_to_le16(0xffff & ~le16_to_cpu(ATTR_IS_SPARSE |
1427 ATTR_IS_ENCRYPTED | ATTR_COMPRESSION_MASK));
1428 /* Setup the fields specific to non-resident attributes. */ 1503 /* Setup the fields specific to non-resident attributes. */
1429 a->data.non_resident.lowest_vcn = 0; 1504 a->data.non_resident.lowest_vcn = 0;
1430 a->data.non_resident.highest_vcn = cpu_to_sle64((new_size - 1) >> 1505 a->data.non_resident.highest_vcn = cpu_to_sle64((new_size - 1) >>
1431 vol->cluster_size_bits); 1506 vol->cluster_size_bits);
1432 a->data.non_resident.mapping_pairs_offset = cpu_to_le16(mp_ofs); 1507 a->data.non_resident.mapping_pairs_offset = cpu_to_le16(mp_ofs);
1433 a->data.non_resident.compression_unit = 0;
1434 memset(&a->data.non_resident.reserved, 0, 1508 memset(&a->data.non_resident.reserved, 0,
1435 sizeof(a->data.non_resident.reserved)); 1509 sizeof(a->data.non_resident.reserved));
1436 a->data.non_resident.allocated_size = cpu_to_sle64(new_size); 1510 a->data.non_resident.allocated_size = cpu_to_sle64(new_size);
1437 a->data.non_resident.data_size = 1511 a->data.non_resident.data_size =
1438 a->data.non_resident.initialized_size = 1512 a->data.non_resident.initialized_size =
1439 cpu_to_sle64(attr_size); 1513 cpu_to_sle64(attr_size);
1514 if (NInoSparse(ni) || NInoCompressed(ni)) {
1515 a->data.non_resident.compression_unit = 4;
1516 a->data.non_resident.compressed_size =
1517 a->data.non_resident.allocated_size;
1518 } else
1519 a->data.non_resident.compression_unit = 0;
1440 /* Generate the mapping pairs array into the attribute record. */ 1520 /* Generate the mapping pairs array into the attribute record. */
1441 err = ntfs_mapping_pairs_build(vol, (u8*)a + mp_ofs, 1521 err = ntfs_mapping_pairs_build(vol, (u8*)a + mp_ofs,
1442 arec_size - mp_ofs, rl, 0, -1, NULL); 1522 arec_size - mp_ofs, rl, 0, -1, NULL);
@@ -1446,16 +1526,19 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni)
1446 goto undo_err_out; 1526 goto undo_err_out;
1447 } 1527 }
1448 /* Setup the in-memory attribute structure to be non-resident. */ 1528 /* Setup the in-memory attribute structure to be non-resident. */
1449 /*
1450 * FIXME: For now just clear all of these as we do not support them
1451 * when writing.
1452 */
1453 NInoClearSparse(ni);
1454 NInoClearEncrypted(ni);
1455 NInoClearCompressed(ni);
1456 ni->runlist.rl = rl; 1529 ni->runlist.rl = rl;
1457 write_lock_irqsave(&ni->size_lock, flags); 1530 write_lock_irqsave(&ni->size_lock, flags);
1458 ni->allocated_size = new_size; 1531 ni->allocated_size = new_size;
1532 if (NInoSparse(ni) || NInoCompressed(ni)) {
1533 ni->itype.compressed.size = ni->allocated_size;
1534 ni->itype.compressed.block_size = 1U <<
1535 (a->data.non_resident.compression_unit +
1536 vol->cluster_size_bits);
1537 ni->itype.compressed.block_size_bits =
1538 ffs(ni->itype.compressed.block_size) - 1;
1539 ni->itype.compressed.block_clusters = 1U <<
1540 a->data.non_resident.compression_unit;
1541 }
1459 write_unlock_irqrestore(&ni->size_lock, flags); 1542 write_unlock_irqrestore(&ni->size_lock, flags);
1460 /* 1543 /*
1461 * This needs to be last since the address space operations ->readpage 1544 * This needs to be last since the address space operations ->readpage
@@ -1603,6 +1686,12 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val)
1603 BUG_ON(cnt < 0); 1686 BUG_ON(cnt < 0);
1604 if (!cnt) 1687 if (!cnt)
1605 goto done; 1688 goto done;
1689 /*
1690 * FIXME: Compressed and encrypted attributes are not supported when
1691 * writing and we should never have gotten here for them.
1692 */
1693 BUG_ON(NInoCompressed(ni));
1694 BUG_ON(NInoEncrypted(ni));
1606 mapping = VFS_I(ni)->i_mapping; 1695 mapping = VFS_I(ni)->i_mapping;
1607 /* Work out the starting index and page offset. */ 1696 /* Work out the starting index and page offset. */
1608 idx = ofs >> PAGE_CACHE_SHIFT; 1697 idx = ofs >> PAGE_CACHE_SHIFT;