diff options
author | Anton Altaparmakov <aia21@hera.kernel.org> | 2006-03-23 12:08:12 -0500 |
---|---|---|
committer | Anton Altaparmakov <aia21@hera.kernel.org> | 2006-03-23 12:08:12 -0500 |
commit | b425c8c5922562c562dc55a636c3c8d758ed6d17 (patch) | |
tree | 3dba4faa78f1bbe4be503275173e3a63b5d60f22 | |
parent | a05ba4561fa3ad8b64a27577d0d38c190f60f762 (diff) | |
parent | 92fe7b9ea8ef101bff3c75ade89b93b5f62a7955 (diff) |
Merge branch 'master' of git://imp.csi.cam.ac.uk/home/src/ntfs-2.6-devel/
-rw-r--r-- | Documentation/filesystems/ntfs.txt | 5 | ||||
-rw-r--r-- | fs/ntfs/ChangeLog | 30 | ||||
-rw-r--r-- | fs/ntfs/Makefile | 2 | ||||
-rw-r--r-- | fs/ntfs/aops.c | 14 | ||||
-rw-r--r-- | fs/ntfs/attrib.c | 35 | ||||
-rw-r--r-- | fs/ntfs/compress.c | 4 | ||||
-rw-r--r-- | fs/ntfs/file.c | 13 | ||||
-rw-r--r-- | fs/ntfs/inode.c | 111 | ||||
-rw-r--r-- | fs/ntfs/inode.h | 13 | ||||
-rw-r--r-- | fs/ntfs/layout.h | 44 | ||||
-rw-r--r-- | fs/ntfs/mft.c | 68 | ||||
-rw-r--r-- | fs/ntfs/mft.h | 5 | ||||
-rw-r--r-- | fs/ntfs/namei.c | 9 | ||||
-rw-r--r-- | fs/ntfs/ntfs.h | 2 | ||||
-rw-r--r-- | fs/ntfs/runlist.c | 12 | ||||
-rw-r--r-- | fs/ntfs/super.c | 84 | ||||
-rw-r--r-- | fs/ntfs/unistr.c | 51 |
17 files changed, 291 insertions, 211 deletions
diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt index 251168587899..638cbd3d2b00 100644 --- a/Documentation/filesystems/ntfs.txt +++ b/Documentation/filesystems/ntfs.txt | |||
@@ -457,6 +457,11 @@ ChangeLog | |||
457 | 457 | ||
458 | Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. | 458 | Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. |
459 | 459 | ||
460 | 2.1.27: | ||
461 | - Implement page migration support so the kernel can move memory used | ||
462 | by NTFS files and directories around for management purposes. | ||
463 | - Add support for writing to sparse files created with Windows XP SP2. | ||
464 | - Many minor improvements and bug fixes. | ||
460 | 2.1.26: | 465 | 2.1.26: |
461 | - Implement support for sector sizes above 512 bytes (up to the maximum | 466 | - Implement support for sector sizes above 512 bytes (up to the maximum |
462 | supported by NTFS which is 4096 bytes). | 467 | supported by NTFS which is 4096 bytes). |
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 9d8ffa89e2c2..35cc4b1d60f7 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog | |||
@@ -16,8 +16,34 @@ ToDo/Notes: | |||
16 | inode having been discarded already. Whether this can actually ever | 16 | inode having been discarded already. Whether this can actually ever |
17 | happen is unclear however so it is worth waiting until someone hits | 17 | happen is unclear however so it is worth waiting until someone hits |
18 | the problem. | 18 | the problem. |
19 | - Enable the code for setting the NT4 compatibility flag when we start | 19 | |
20 | making NTFS 1.2 specific modifications. | 20 | 2.1.27 - Various bug fixes and cleanups. |
21 | |||
22 | - Fix two compiler warnings on Alpha. Thanks to Andrew Morton for | ||
23 | reporting them. | ||
24 | - Fix an (innocent) off-by-one error in the runlist code. | ||
25 | - Fix a buggette in an "should be impossible" case handling where we | ||
26 | continued the attribute lookup loop instead of aborting it. | ||
27 | - Use buffer_migrate_page() for the ->migratepage function of all ntfs | ||
28 | address space operations. | ||
29 | - Fix comparison of $MFT and $MFTMirr to not bail out when there are | ||
30 | unused, invalid mft records which are the same in both $MFT and | ||
31 | $MFTMirr. | ||
32 | - Add support for sparse files which have a compression unit of 0. | ||
33 | - Remove all the make_bad_inode() calls. This should only be called | ||
34 | from read inode and new inode code paths. | ||
35 | - Limit name length in fs/ntfs/unistr.c::ntfs_nlstoucs() to maximum | ||
36 | allowed by NTFS, i.e. 255 Unicode characters, not including the | ||
37 | terminating NULL (which is not stored on disk). | ||
38 | - Improve comments on file attribute flags in fs/ntfs/layout.h. | ||
39 | - Fix a bug in fs/ntfs/inode.c::ntfs_read_locked_index_inode() where we | ||
40 | forgot to update a temporary variable so loading index inodes which | ||
41 | have an index allocation attribute failed. | ||
42 | - Add a missing call to flush_dcache_mft_record_page() in | ||
43 | fs/ntfs/inode.c::ntfs_write_inode(). | ||
44 | - Handle the recently introduced -ENAMETOOLONG return value from | ||
45 | fs/ntfs/unistr.c::ntfs_nlstoucs() in fs/ntfs/namei.c::ntfs_lookup(). | ||
46 | - Semaphore to mutex conversion. (Ingo Molnar) | ||
21 | 47 | ||
22 | 2.1.26 - Minor bug fixes and updates. | 48 | 2.1.26 - Minor bug fixes and updates. |
23 | 49 | ||
diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile index d95fac7fdeb6..e27b4eacffbf 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.26\" | 9 | EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.27\" |
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/aops.c b/fs/ntfs/aops.c index 7e361da770b3..580412d330cb 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c | |||
@@ -22,6 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
25 | #include <linux/fs.h> | ||
25 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
26 | #include <linux/pagemap.h> | 27 | #include <linux/pagemap.h> |
27 | #include <linux/swap.h> | 28 | #include <linux/swap.h> |
@@ -1277,18 +1278,18 @@ unm_done: | |||
1277 | 1278 | ||
1278 | tni = locked_nis[nr_locked_nis]; | 1279 | tni = locked_nis[nr_locked_nis]; |
1279 | /* Get the base inode. */ | 1280 | /* Get the base inode. */ |
1280 | down(&tni->extent_lock); | 1281 | mutex_lock(&tni->extent_lock); |
1281 | if (tni->nr_extents >= 0) | 1282 | if (tni->nr_extents >= 0) |
1282 | base_tni = tni; | 1283 | base_tni = tni; |
1283 | else { | 1284 | else { |
1284 | base_tni = tni->ext.base_ntfs_ino; | 1285 | base_tni = tni->ext.base_ntfs_ino; |
1285 | BUG_ON(!base_tni); | 1286 | BUG_ON(!base_tni); |
1286 | } | 1287 | } |
1287 | up(&tni->extent_lock); | 1288 | mutex_unlock(&tni->extent_lock); |
1288 | ntfs_debug("Unlocking %s inode 0x%lx.", | 1289 | ntfs_debug("Unlocking %s inode 0x%lx.", |
1289 | tni == base_tni ? "base" : "extent", | 1290 | tni == base_tni ? "base" : "extent", |
1290 | tni->mft_no); | 1291 | tni->mft_no); |
1291 | up(&tni->mrec_lock); | 1292 | mutex_unlock(&tni->mrec_lock); |
1292 | atomic_dec(&tni->count); | 1293 | atomic_dec(&tni->count); |
1293 | iput(VFS_I(base_tni)); | 1294 | iput(VFS_I(base_tni)); |
1294 | } | 1295 | } |
@@ -1529,7 +1530,6 @@ err_out: | |||
1529 | "error %i.", err); | 1530 | "error %i.", err); |
1530 | SetPageError(page); | 1531 | SetPageError(page); |
1531 | NVolSetErrors(ni->vol); | 1532 | NVolSetErrors(ni->vol); |
1532 | make_bad_inode(vi); | ||
1533 | } | 1533 | } |
1534 | unlock_page(page); | 1534 | unlock_page(page); |
1535 | if (ctx) | 1535 | if (ctx) |
@@ -1551,6 +1551,9 @@ struct address_space_operations ntfs_aops = { | |||
1551 | #ifdef NTFS_RW | 1551 | #ifdef NTFS_RW |
1552 | .writepage = ntfs_writepage, /* Write dirty page to disk. */ | 1552 | .writepage = ntfs_writepage, /* Write dirty page to disk. */ |
1553 | #endif /* NTFS_RW */ | 1553 | #endif /* NTFS_RW */ |
1554 | .migratepage = buffer_migrate_page, /* Move a page cache page from | ||
1555 | one physical page to an | ||
1556 | other. */ | ||
1554 | }; | 1557 | }; |
1555 | 1558 | ||
1556 | /** | 1559 | /** |
@@ -1567,6 +1570,9 @@ struct address_space_operations ntfs_mst_aops = { | |||
1567 | without touching the buffers | 1570 | without touching the buffers |
1568 | belonging to the page. */ | 1571 | belonging to the page. */ |
1569 | #endif /* NTFS_RW */ | 1572 | #endif /* NTFS_RW */ |
1573 | .migratepage = buffer_migrate_page, /* Move a page cache page from | ||
1574 | one physical page to an | ||
1575 | other. */ | ||
1570 | }; | 1576 | }; |
1571 | 1577 | ||
1572 | #ifdef NTFS_RW | 1578 | #ifdef NTFS_RW |
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 9480a0526cd3..1663f5c3c6aa 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /** | 1 | /** |
2 | * attrib.c - NTFS attribute operations. Part of the Linux-NTFS project. | 2 | * attrib.c - NTFS attribute operations. Part of the Linux-NTFS project. |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2005 Anton Altaparmakov | 4 | * Copyright (c) 2001-2006 Anton Altaparmakov |
5 | * Copyright (c) 2002 Richard Russon | 5 | * Copyright (c) 2002 Richard Russon |
6 | * | 6 | * |
7 | * This program/include file is free software; you can redistribute it and/or | 7 | * This program/include file is free software; you can redistribute it and/or |
@@ -1048,7 +1048,7 @@ do_next_attr_loop: | |||
1048 | le32_to_cpu(ctx->mrec->bytes_allocated)) | 1048 | le32_to_cpu(ctx->mrec->bytes_allocated)) |
1049 | break; | 1049 | break; |
1050 | if (a->type == AT_END) | 1050 | if (a->type == AT_END) |
1051 | continue; | 1051 | break; |
1052 | if (!a->length) | 1052 | if (!a->length) |
1053 | break; | 1053 | break; |
1054 | if (al_entry->instance != a->instance) | 1054 | if (al_entry->instance != a->instance) |
@@ -1695,7 +1695,9 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size) | |||
1695 | a->data.non_resident.initialized_size = | 1695 | a->data.non_resident.initialized_size = |
1696 | cpu_to_sle64(attr_size); | 1696 | cpu_to_sle64(attr_size); |
1697 | if (NInoSparse(ni) || NInoCompressed(ni)) { | 1697 | if (NInoSparse(ni) || NInoCompressed(ni)) { |
1698 | a->data.non_resident.compression_unit = 4; | 1698 | a->data.non_resident.compression_unit = 0; |
1699 | if (NInoCompressed(ni) || vol->major_ver < 3) | ||
1700 | a->data.non_resident.compression_unit = 4; | ||
1699 | a->data.non_resident.compressed_size = | 1701 | a->data.non_resident.compressed_size = |
1700 | a->data.non_resident.allocated_size; | 1702 | a->data.non_resident.allocated_size; |
1701 | } else | 1703 | } else |
@@ -1714,13 +1716,20 @@ int ntfs_attr_make_non_resident(ntfs_inode *ni, const u32 data_size) | |||
1714 | ni->allocated_size = new_size; | 1716 | ni->allocated_size = new_size; |
1715 | if (NInoSparse(ni) || NInoCompressed(ni)) { | 1717 | if (NInoSparse(ni) || NInoCompressed(ni)) { |
1716 | ni->itype.compressed.size = ni->allocated_size; | 1718 | ni->itype.compressed.size = ni->allocated_size; |
1717 | ni->itype.compressed.block_size = 1U << | 1719 | if (a->data.non_resident.compression_unit) { |
1718 | (a->data.non_resident.compression_unit + | 1720 | ni->itype.compressed.block_size = 1U << (a->data. |
1719 | vol->cluster_size_bits); | 1721 | non_resident.compression_unit + |
1720 | ni->itype.compressed.block_size_bits = | 1722 | vol->cluster_size_bits); |
1721 | ffs(ni->itype.compressed.block_size) - 1; | 1723 | ni->itype.compressed.block_size_bits = |
1722 | ni->itype.compressed.block_clusters = 1U << | 1724 | ffs(ni->itype.compressed.block_size) - |
1723 | a->data.non_resident.compression_unit; | 1725 | 1; |
1726 | ni->itype.compressed.block_clusters = 1U << | ||
1727 | a->data.non_resident.compression_unit; | ||
1728 | } else { | ||
1729 | ni->itype.compressed.block_size = 0; | ||
1730 | ni->itype.compressed.block_size_bits = 0; | ||
1731 | ni->itype.compressed.block_clusters = 0; | ||
1732 | } | ||
1724 | vi->i_blocks = ni->itype.compressed.size >> 9; | 1733 | vi->i_blocks = ni->itype.compressed.size >> 9; |
1725 | } else | 1734 | } else |
1726 | vi->i_blocks = ni->allocated_size >> 9; | 1735 | vi->i_blocks = ni->allocated_size >> 9; |
@@ -2429,16 +2438,12 @@ undo_alloc: | |||
2429 | "chkdsk to recover.", IS_ERR(m) ? | 2438 | "chkdsk to recover.", IS_ERR(m) ? |
2430 | "restore attribute search context" : | 2439 | "restore attribute search context" : |
2431 | "truncate attribute runlist"); | 2440 | "truncate attribute runlist"); |
2432 | make_bad_inode(vi); | ||
2433 | make_bad_inode(VFS_I(base_ni)); | ||
2434 | NVolSetErrors(vol); | 2441 | NVolSetErrors(vol); |
2435 | } else if (mp_rebuilt) { | 2442 | } else if (mp_rebuilt) { |
2436 | if (ntfs_attr_record_resize(m, a, attr_len)) { | 2443 | if (ntfs_attr_record_resize(m, a, attr_len)) { |
2437 | ntfs_error(vol->sb, "Failed to restore attribute " | 2444 | ntfs_error(vol->sb, "Failed to restore attribute " |
2438 | "record in error code path. Run " | 2445 | "record in error code path. Run " |
2439 | "chkdsk to recover."); | 2446 | "chkdsk to recover."); |
2440 | make_bad_inode(vi); | ||
2441 | make_bad_inode(VFS_I(base_ni)); | ||
2442 | NVolSetErrors(vol); | 2447 | NVolSetErrors(vol); |
2443 | } else /* if (success) */ { | 2448 | } else /* if (success) */ { |
2444 | if (ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu( | 2449 | if (ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu( |
@@ -2451,8 +2456,6 @@ undo_alloc: | |||
2451 | "mapping pairs array in error " | 2456 | "mapping pairs array in error " |
2452 | "code path. Run chkdsk to " | 2457 | "code path. Run chkdsk to " |
2453 | "recover."); | 2458 | "recover."); |
2454 | make_bad_inode(vi); | ||
2455 | make_bad_inode(VFS_I(base_ni)); | ||
2456 | NVolSetErrors(vol); | 2459 | NVolSetErrors(vol); |
2457 | } | 2460 | } |
2458 | flush_dcache_mft_record_page(ctx->ntfs_ino); | 2461 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c index 25d24106f893..68a607ff9fd3 100644 --- a/fs/ntfs/compress.c +++ b/fs/ntfs/compress.c | |||
@@ -67,7 +67,7 @@ static DEFINE_SPINLOCK(ntfs_cb_lock); | |||
67 | /** | 67 | /** |
68 | * allocate_compression_buffers - allocate the decompression buffers | 68 | * allocate_compression_buffers - allocate the decompression buffers |
69 | * | 69 | * |
70 | * Caller has to hold the ntfs_lock semaphore. | 70 | * Caller has to hold the ntfs_lock mutex. |
71 | * | 71 | * |
72 | * Return 0 on success or -ENOMEM if the allocations failed. | 72 | * Return 0 on success or -ENOMEM if the allocations failed. |
73 | */ | 73 | */ |
@@ -84,7 +84,7 @@ int allocate_compression_buffers(void) | |||
84 | /** | 84 | /** |
85 | * free_compression_buffers - free the decompression buffers | 85 | * free_compression_buffers - free the decompression buffers |
86 | * | 86 | * |
87 | * Caller has to hold the ntfs_lock semaphore. | 87 | * Caller has to hold the ntfs_lock mutex. |
88 | */ | 88 | */ |
89 | void free_compression_buffers(void) | 89 | void free_compression_buffers(void) |
90 | { | 90 | { |
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index 2e5ba0c535d9..f5d057e4acc2 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c | |||
@@ -1207,8 +1207,6 @@ rl_not_mapped_enoent: | |||
1207 | "attribute runlist in error code " | 1207 | "attribute runlist in error code " |
1208 | "path. Run chkdsk to recover the " | 1208 | "path. Run chkdsk to recover the " |
1209 | "lost cluster."); | 1209 | "lost cluster."); |
1210 | make_bad_inode(vi); | ||
1211 | make_bad_inode(VFS_I(base_ni)); | ||
1212 | NVolSetErrors(vol); | 1210 | NVolSetErrors(vol); |
1213 | } else /* if (success) */ { | 1211 | } else /* if (success) */ { |
1214 | status.runlist_merged = 0; | 1212 | status.runlist_merged = 0; |
@@ -1239,8 +1237,6 @@ rl_not_mapped_enoent: | |||
1239 | ntfs_error(vol->sb, "Failed to restore attribute " | 1237 | ntfs_error(vol->sb, "Failed to restore attribute " |
1240 | "record in error code path. Run " | 1238 | "record in error code path. Run " |
1241 | "chkdsk to recover."); | 1239 | "chkdsk to recover."); |
1242 | make_bad_inode(vi); | ||
1243 | make_bad_inode(VFS_I(base_ni)); | ||
1244 | NVolSetErrors(vol); | 1240 | NVolSetErrors(vol); |
1245 | } else /* if (success) */ { | 1241 | } else /* if (success) */ { |
1246 | if (ntfs_mapping_pairs_build(vol, (u8*)a + | 1242 | if (ntfs_mapping_pairs_build(vol, (u8*)a + |
@@ -1253,8 +1249,6 @@ rl_not_mapped_enoent: | |||
1253 | "mapping pairs array in error " | 1249 | "mapping pairs array in error " |
1254 | "code path. Run chkdsk to " | 1250 | "code path. Run chkdsk to " |
1255 | "recover."); | 1251 | "recover."); |
1256 | make_bad_inode(vi); | ||
1257 | make_bad_inode(VFS_I(base_ni)); | ||
1258 | NVolSetErrors(vol); | 1252 | NVolSetErrors(vol); |
1259 | } | 1253 | } |
1260 | flush_dcache_mft_record_page(ctx->ntfs_ino); | 1254 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
@@ -1623,11 +1617,8 @@ err_out: | |||
1623 | unmap_mft_record(base_ni); | 1617 | unmap_mft_record(base_ni); |
1624 | ntfs_error(vi->i_sb, "Failed to update initialized_size/i_size (error " | 1618 | ntfs_error(vi->i_sb, "Failed to update initialized_size/i_size (error " |
1625 | "code %i).", err); | 1619 | "code %i).", err); |
1626 | if (err != -ENOMEM) { | 1620 | if (err != -ENOMEM) |
1627 | NVolSetErrors(ni->vol); | 1621 | NVolSetErrors(ni->vol); |
1628 | make_bad_inode(VFS_I(base_ni)); | ||
1629 | make_bad_inode(vi); | ||
1630 | } | ||
1631 | return err; | 1622 | return err; |
1632 | } | 1623 | } |
1633 | 1624 | ||
@@ -1802,8 +1793,6 @@ err_out: | |||
1802 | ntfs_error(vi->i_sb, "Resident attribute commit write failed " | 1793 | ntfs_error(vi->i_sb, "Resident attribute commit write failed " |
1803 | "with error %i.", err); | 1794 | "with error %i.", err); |
1804 | NVolSetErrors(ni->vol); | 1795 | NVolSetErrors(ni->vol); |
1805 | make_bad_inode(VFS_I(base_ni)); | ||
1806 | make_bad_inode(vi); | ||
1807 | } | 1796 | } |
1808 | if (ctx) | 1797 | if (ctx) |
1809 | ntfs_attr_put_search_ctx(ctx); | 1798 | ntfs_attr_put_search_ctx(ctx); |
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 55263b7de9c0..4c86b7e1d1eb 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /** | 1 | /** |
2 | * inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project. | 2 | * inode.c - NTFS kernel inode handling. Part of the Linux-NTFS project. |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2005 Anton Altaparmakov | 4 | * Copyright (c) 2001-2006 Anton Altaparmakov |
5 | * | 5 | * |
6 | * This program/include file is free software; you can redistribute it and/or | 6 | * This program/include file is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License as published | 7 | * modify it under the terms of the GNU General Public License as published |
@@ -19,13 +19,19 @@ | |||
19 | * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/pagemap.h> | ||
23 | #include <linux/buffer_head.h> | 22 | #include <linux/buffer_head.h> |
24 | #include <linux/smp_lock.h> | 23 | #include <linux/fs.h> |
25 | #include <linux/quotaops.h> | 24 | #include <linux/mm.h> |
26 | #include <linux/mount.h> | 25 | #include <linux/mount.h> |
26 | #include <linux/mutex.h> | ||
27 | #include <linux/pagemap.h> | ||
28 | #include <linux/quotaops.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/smp_lock.h> | ||
27 | 31 | ||
28 | #include "aops.h" | 32 | #include "aops.h" |
33 | #include "attrib.h" | ||
34 | #include "bitmap.h" | ||
29 | #include "dir.h" | 35 | #include "dir.h" |
30 | #include "debug.h" | 36 | #include "debug.h" |
31 | #include "inode.h" | 37 | #include "inode.h" |
@@ -382,7 +388,7 @@ void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni) | |||
382 | atomic_set(&ni->count, 1); | 388 | atomic_set(&ni->count, 1); |
383 | ni->vol = NTFS_SB(sb); | 389 | ni->vol = NTFS_SB(sb); |
384 | ntfs_init_runlist(&ni->runlist); | 390 | ntfs_init_runlist(&ni->runlist); |
385 | init_MUTEX(&ni->mrec_lock); | 391 | mutex_init(&ni->mrec_lock); |
386 | ni->page = NULL; | 392 | ni->page = NULL; |
387 | ni->page_ofs = 0; | 393 | ni->page_ofs = 0; |
388 | ni->attr_list_size = 0; | 394 | ni->attr_list_size = 0; |
@@ -394,7 +400,7 @@ void __ntfs_init_inode(struct super_block *sb, ntfs_inode *ni) | |||
394 | ni->itype.index.collation_rule = 0; | 400 | ni->itype.index.collation_rule = 0; |
395 | ni->itype.index.block_size_bits = 0; | 401 | ni->itype.index.block_size_bits = 0; |
396 | ni->itype.index.vcn_size_bits = 0; | 402 | ni->itype.index.vcn_size_bits = 0; |
397 | init_MUTEX(&ni->extent_lock); | 403 | mutex_init(&ni->extent_lock); |
398 | ni->nr_extents = 0; | 404 | ni->nr_extents = 0; |
399 | ni->ext.base_ntfs_ino = NULL; | 405 | ni->ext.base_ntfs_ino = NULL; |
400 | } | 406 | } |
@@ -1064,10 +1070,10 @@ skip_large_dir_stuff: | |||
1064 | if (a->non_resident) { | 1070 | if (a->non_resident) { |
1065 | NInoSetNonResident(ni); | 1071 | NInoSetNonResident(ni); |
1066 | if (NInoCompressed(ni) || NInoSparse(ni)) { | 1072 | if (NInoCompressed(ni) || NInoSparse(ni)) { |
1067 | if (a->data.non_resident.compression_unit != | 1073 | if (NInoCompressed(ni) && a->data.non_resident. |
1068 | 4) { | 1074 | compression_unit != 4) { |
1069 | ntfs_error(vi->i_sb, "Found " | 1075 | ntfs_error(vi->i_sb, "Found " |
1070 | "nonstandard " | 1076 | "non-standard " |
1071 | "compression unit (%u " | 1077 | "compression unit (%u " |
1072 | "instead of 4). " | 1078 | "instead of 4). " |
1073 | "Cannot handle this.", | 1079 | "Cannot handle this.", |
@@ -1076,16 +1082,26 @@ skip_large_dir_stuff: | |||
1076 | err = -EOPNOTSUPP; | 1082 | err = -EOPNOTSUPP; |
1077 | goto unm_err_out; | 1083 | goto unm_err_out; |
1078 | } | 1084 | } |
1079 | ni->itype.compressed.block_clusters = 1U << | 1085 | if (a->data.non_resident.compression_unit) { |
1080 | a->data.non_resident. | 1086 | ni->itype.compressed.block_size = 1U << |
1081 | compression_unit; | 1087 | (a->data.non_resident. |
1082 | ni->itype.compressed.block_size = 1U << ( | 1088 | compression_unit + |
1083 | a->data.non_resident. | 1089 | vol->cluster_size_bits); |
1084 | compression_unit + | 1090 | ni->itype.compressed.block_size_bits = |
1085 | vol->cluster_size_bits); | 1091 | ffs(ni->itype. |
1086 | ni->itype.compressed.block_size_bits = ffs( | 1092 | compressed. |
1087 | ni->itype.compressed. | 1093 | block_size) - 1; |
1088 | block_size) - 1; | 1094 | ni->itype.compressed.block_clusters = |
1095 | 1U << a->data. | ||
1096 | non_resident. | ||
1097 | compression_unit; | ||
1098 | } else { | ||
1099 | ni->itype.compressed.block_size = 0; | ||
1100 | ni->itype.compressed.block_size_bits = | ||
1101 | 0; | ||
1102 | ni->itype.compressed.block_clusters = | ||
1103 | 0; | ||
1104 | } | ||
1089 | ni->itype.compressed.size = sle64_to_cpu( | 1105 | ni->itype.compressed.size = sle64_to_cpu( |
1090 | a->data.non_resident. | 1106 | a->data.non_resident. |
1091 | compressed_size); | 1107 | compressed_size); |
@@ -1338,8 +1354,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) | |||
1338 | goto unm_err_out; | 1354 | goto unm_err_out; |
1339 | } | 1355 | } |
1340 | if (NInoCompressed(ni) || NInoSparse(ni)) { | 1356 | if (NInoCompressed(ni) || NInoSparse(ni)) { |
1341 | if (a->data.non_resident.compression_unit != 4) { | 1357 | if (NInoCompressed(ni) && a->data.non_resident. |
1342 | ntfs_error(vi->i_sb, "Found nonstandard " | 1358 | compression_unit != 4) { |
1359 | ntfs_error(vi->i_sb, "Found non-standard " | ||
1343 | "compression unit (%u instead " | 1360 | "compression unit (%u instead " |
1344 | "of 4). Cannot handle this.", | 1361 | "of 4). Cannot handle this.", |
1345 | a->data.non_resident. | 1362 | a->data.non_resident. |
@@ -1347,13 +1364,22 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) | |||
1347 | err = -EOPNOTSUPP; | 1364 | err = -EOPNOTSUPP; |
1348 | goto unm_err_out; | 1365 | goto unm_err_out; |
1349 | } | 1366 | } |
1350 | ni->itype.compressed.block_clusters = 1U << | 1367 | if (a->data.non_resident.compression_unit) { |
1351 | a->data.non_resident.compression_unit; | 1368 | ni->itype.compressed.block_size = 1U << |
1352 | ni->itype.compressed.block_size = 1U << ( | 1369 | (a->data.non_resident. |
1353 | a->data.non_resident.compression_unit + | 1370 | compression_unit + |
1354 | vol->cluster_size_bits); | 1371 | vol->cluster_size_bits); |
1355 | ni->itype.compressed.block_size_bits = ffs( | 1372 | ni->itype.compressed.block_size_bits = |
1356 | ni->itype.compressed.block_size) - 1; | 1373 | ffs(ni->itype.compressed. |
1374 | block_size) - 1; | ||
1375 | ni->itype.compressed.block_clusters = 1U << | ||
1376 | a->data.non_resident. | ||
1377 | compression_unit; | ||
1378 | } else { | ||
1379 | ni->itype.compressed.block_size = 0; | ||
1380 | ni->itype.compressed.block_size_bits = 0; | ||
1381 | ni->itype.compressed.block_clusters = 0; | ||
1382 | } | ||
1357 | ni->itype.compressed.size = sle64_to_cpu( | 1383 | ni->itype.compressed.size = sle64_to_cpu( |
1358 | a->data.non_resident.compressed_size); | 1384 | a->data.non_resident.compressed_size); |
1359 | } | 1385 | } |
@@ -1406,7 +1432,6 @@ err_out: | |||
1406 | "Run chkdsk.", err, vi->i_ino, ni->type, ni->name_len, | 1432 | "Run chkdsk.", err, vi->i_ino, ni->type, ni->name_len, |
1407 | base_vi->i_ino); | 1433 | base_vi->i_ino); |
1408 | make_bad_inode(vi); | 1434 | make_bad_inode(vi); |
1409 | make_bad_inode(base_vi); | ||
1410 | if (err != -ENOMEM) | 1435 | if (err != -ENOMEM) |
1411 | NVolSetErrors(vol); | 1436 | NVolSetErrors(vol); |
1412 | return err; | 1437 | return err; |
@@ -1591,6 +1616,7 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi) | |||
1591 | "$INDEX_ALLOCATION attribute."); | 1616 | "$INDEX_ALLOCATION attribute."); |
1592 | goto unm_err_out; | 1617 | goto unm_err_out; |
1593 | } | 1618 | } |
1619 | a = ctx->attr; | ||
1594 | if (!a->non_resident) { | 1620 | if (!a->non_resident) { |
1595 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is " | 1621 | ntfs_error(vi->i_sb, "$INDEX_ALLOCATION attribute is " |
1596 | "resident."); | 1622 | "resident."); |
@@ -2823,11 +2849,8 @@ done: | |||
2823 | old_bad_out: | 2849 | old_bad_out: |
2824 | old_size = -1; | 2850 | old_size = -1; |
2825 | bad_out: | 2851 | bad_out: |
2826 | if (err != -ENOMEM && err != -EOPNOTSUPP) { | 2852 | if (err != -ENOMEM && err != -EOPNOTSUPP) |
2827 | make_bad_inode(vi); | ||
2828 | make_bad_inode(VFS_I(base_ni)); | ||
2829 | NVolSetErrors(vol); | 2853 | NVolSetErrors(vol); |
2830 | } | ||
2831 | if (err != -EOPNOTSUPP) | 2854 | if (err != -EOPNOTSUPP) |
2832 | NInoSetTruncateFailed(ni); | 2855 | NInoSetTruncateFailed(ni); |
2833 | else if (old_size >= 0) | 2856 | else if (old_size >= 0) |
@@ -2842,11 +2865,8 @@ out: | |||
2842 | ntfs_debug("Failed. Returning error code %i.", err); | 2865 | ntfs_debug("Failed. Returning error code %i.", err); |
2843 | return err; | 2866 | return err; |
2844 | conv_err_out: | 2867 | conv_err_out: |
2845 | if (err != -ENOMEM && err != -EOPNOTSUPP) { | 2868 | if (err != -ENOMEM && err != -EOPNOTSUPP) |
2846 | make_bad_inode(vi); | ||
2847 | make_bad_inode(VFS_I(base_ni)); | ||
2848 | NVolSetErrors(vol); | 2869 | NVolSetErrors(vol); |
2849 | } | ||
2850 | if (err != -EOPNOTSUPP) | 2870 | if (err != -EOPNOTSUPP) |
2851 | NInoSetTruncateFailed(ni); | 2871 | NInoSetTruncateFailed(ni); |
2852 | else | 2872 | else |
@@ -3044,15 +3064,18 @@ int ntfs_write_inode(struct inode *vi, int sync) | |||
3044 | * record will be cleaned and written out to disk below, i.e. before | 3064 | * record will be cleaned and written out to disk below, i.e. before |
3045 | * this function returns. | 3065 | * this function returns. |
3046 | */ | 3066 | */ |
3047 | if (modified && !NInoTestSetDirty(ctx->ntfs_ino)) | 3067 | if (modified) { |
3048 | mark_ntfs_record_dirty(ctx->ntfs_ino->page, | 3068 | flush_dcache_mft_record_page(ctx->ntfs_ino); |
3049 | ctx->ntfs_ino->page_ofs); | 3069 | if (!NInoTestSetDirty(ctx->ntfs_ino)) |
3070 | mark_ntfs_record_dirty(ctx->ntfs_ino->page, | ||
3071 | ctx->ntfs_ino->page_ofs); | ||
3072 | } | ||
3050 | ntfs_attr_put_search_ctx(ctx); | 3073 | ntfs_attr_put_search_ctx(ctx); |
3051 | /* Now the access times are updated, write the base mft record. */ | 3074 | /* Now the access times are updated, write the base mft record. */ |
3052 | if (NInoDirty(ni)) | 3075 | if (NInoDirty(ni)) |
3053 | err = write_mft_record(ni, m, sync); | 3076 | err = write_mft_record(ni, m, sync); |
3054 | /* Write all attached extent mft records. */ | 3077 | /* Write all attached extent mft records. */ |
3055 | down(&ni->extent_lock); | 3078 | mutex_lock(&ni->extent_lock); |
3056 | if (ni->nr_extents > 0) { | 3079 | if (ni->nr_extents > 0) { |
3057 | ntfs_inode **extent_nis = ni->ext.extent_ntfs_inos; | 3080 | ntfs_inode **extent_nis = ni->ext.extent_ntfs_inos; |
3058 | int i; | 3081 | int i; |
@@ -3079,7 +3102,7 @@ int ntfs_write_inode(struct inode *vi, int sync) | |||
3079 | } | 3102 | } |
3080 | } | 3103 | } |
3081 | } | 3104 | } |
3082 | up(&ni->extent_lock); | 3105 | mutex_unlock(&ni->extent_lock); |
3083 | unmap_mft_record(ni); | 3106 | unmap_mft_record(ni); |
3084 | if (unlikely(err)) | 3107 | if (unlikely(err)) |
3085 | goto err_out; | 3108 | goto err_out; |
@@ -3094,9 +3117,7 @@ err_out: | |||
3094 | "retries later."); | 3117 | "retries later."); |
3095 | mark_inode_dirty(vi); | 3118 | mark_inode_dirty(vi); |
3096 | } else { | 3119 | } else { |
3097 | ntfs_error(vi->i_sb, "Failed (error code %i): Marking inode " | 3120 | ntfs_error(vi->i_sb, "Failed (error %i): Run chkdsk.", -err); |
3098 | "as bad. You should run chkdsk.", -err); | ||
3099 | make_bad_inode(vi); | ||
3100 | NVolSetErrors(ni->vol); | 3121 | NVolSetErrors(ni->vol); |
3101 | } | 3122 | } |
3102 | return err; | 3123 | return err; |
diff --git a/fs/ntfs/inode.h b/fs/ntfs/inode.h index 3de5c0231966..f088291e017c 100644 --- a/fs/ntfs/inode.h +++ b/fs/ntfs/inode.h | |||
@@ -24,12 +24,13 @@ | |||
24 | #ifndef _LINUX_NTFS_INODE_H | 24 | #ifndef _LINUX_NTFS_INODE_H |
25 | #define _LINUX_NTFS_INODE_H | 25 | #define _LINUX_NTFS_INODE_H |
26 | 26 | ||
27 | #include <linux/mm.h> | 27 | #include <asm/atomic.h> |
28 | |||
28 | #include <linux/fs.h> | 29 | #include <linux/fs.h> |
29 | #include <linux/seq_file.h> | ||
30 | #include <linux/list.h> | 30 | #include <linux/list.h> |
31 | #include <asm/atomic.h> | 31 | #include <linux/mm.h> |
32 | #include <asm/semaphore.h> | 32 | #include <linux/mutex.h> |
33 | #include <linux/seq_file.h> | ||
33 | 34 | ||
34 | #include "layout.h" | 35 | #include "layout.h" |
35 | #include "volume.h" | 36 | #include "volume.h" |
@@ -81,7 +82,7 @@ struct _ntfs_inode { | |||
81 | * The following fields are only valid for real inodes and extent | 82 | * The following fields are only valid for real inodes and extent |
82 | * inodes. | 83 | * inodes. |
83 | */ | 84 | */ |
84 | struct semaphore mrec_lock; /* Lock for serializing access to the | 85 | struct mutex mrec_lock; /* Lock for serializing access to the |
85 | mft record belonging to this inode. */ | 86 | mft record belonging to this inode. */ |
86 | struct page *page; /* The page containing the mft record of the | 87 | struct page *page; /* The page containing the mft record of the |
87 | inode. This should only be touched by the | 88 | inode. This should only be touched by the |
@@ -119,7 +120,7 @@ struct _ntfs_inode { | |||
119 | u8 block_clusters; /* Number of clusters per cb. */ | 120 | u8 block_clusters; /* Number of clusters per cb. */ |
120 | } compressed; | 121 | } compressed; |
121 | } itype; | 122 | } itype; |
122 | struct semaphore extent_lock; /* Lock for accessing/modifying the | 123 | struct mutex extent_lock; /* Lock for accessing/modifying the |
123 | below . */ | 124 | below . */ |
124 | s32 nr_extents; /* For a base mft record, the number of attached extent | 125 | s32 nr_extents; /* For a base mft record, the number of attached extent |
125 | inodes (0 if none), for extent records and for fake | 126 | inodes (0 if none), for extent records and for fake |
diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h index bb408d4dcbb0..d34b93cb8b48 100644 --- a/fs/ntfs/layout.h +++ b/fs/ntfs/layout.h | |||
@@ -769,7 +769,7 @@ typedef struct { | |||
769 | compressed. (This effectively limits the | 769 | compressed. (This effectively limits the |
770 | compression unit size to be a power of two | 770 | compression unit size to be a power of two |
771 | clusters.) WinNT4 only uses a value of 4. | 771 | clusters.) WinNT4 only uses a value of 4. |
772 | Sparse files also have this set to 4. */ | 772 | Sparse files have this set to 0 on XPSP2. */ |
773 | /* 35*/ u8 reserved[5]; /* Align to 8-byte boundary. */ | 773 | /* 35*/ u8 reserved[5]; /* Align to 8-byte boundary. */ |
774 | /* The sizes below are only used when lowest_vcn is zero, as otherwise it would | 774 | /* The sizes below are only used when lowest_vcn is zero, as otherwise it would |
775 | be difficult to keep them up-to-date.*/ | 775 | be difficult to keep them up-to-date.*/ |
@@ -801,13 +801,16 @@ typedef struct { | |||
801 | typedef ATTR_RECORD ATTR_REC; | 801 | typedef ATTR_RECORD ATTR_REC; |
802 | 802 | ||
803 | /* | 803 | /* |
804 | * File attribute flags (32-bit). | 804 | * File attribute flags (32-bit) appearing in the file_attributes fields of the |
805 | * STANDARD_INFORMATION attribute of MFT_RECORDs and the FILENAME_ATTR | ||
806 | * attributes of MFT_RECORDs and directory index entries. | ||
807 | * | ||
808 | * All of the below flags appear in the directory index entries but only some | ||
809 | * appear in the STANDARD_INFORMATION attribute whilst only some others appear | ||
810 | * in the FILENAME_ATTR attribute of MFT_RECORDs. Unless otherwise stated the | ||
811 | * flags appear in all of the above. | ||
805 | */ | 812 | */ |
806 | enum { | 813 | enum { |
807 | /* | ||
808 | * The following flags are only present in the STANDARD_INFORMATION | ||
809 | * attribute (in the field file_attributes). | ||
810 | */ | ||
811 | FILE_ATTR_READONLY = const_cpu_to_le32(0x00000001), | 814 | FILE_ATTR_READONLY = const_cpu_to_le32(0x00000001), |
812 | FILE_ATTR_HIDDEN = const_cpu_to_le32(0x00000002), | 815 | FILE_ATTR_HIDDEN = const_cpu_to_le32(0x00000002), |
813 | FILE_ATTR_SYSTEM = const_cpu_to_le32(0x00000004), | 816 | FILE_ATTR_SYSTEM = const_cpu_to_le32(0x00000004), |
@@ -839,18 +842,14 @@ enum { | |||
839 | F_A_COMPRESSED, and F_A_ENCRYPTED and preserves the rest. This mask | 842 | F_A_COMPRESSED, and F_A_ENCRYPTED and preserves the rest. This mask |
840 | is used to to obtain all flags that are valid for setting. */ | 843 | is used to to obtain all flags that are valid for setting. */ |
841 | /* | 844 | /* |
842 | * The following flag is only present in the FILE_NAME attribute (in | 845 | * The flag FILE_ATTR_DUP_FILENAME_INDEX_PRESENT is present in all |
843 | * the field file_attributes). | 846 | * FILENAME_ATTR attributes but not in the STANDARD_INFORMATION |
847 | * attribute of an mft record. | ||
844 | */ | 848 | */ |
845 | FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT = const_cpu_to_le32(0x10000000), | 849 | FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT = const_cpu_to_le32(0x10000000), |
846 | /* Note, this is a copy of the corresponding bit from the mft record, | 850 | /* Note, this is a copy of the corresponding bit from the mft record, |
847 | telling us whether this is a directory or not, i.e. whether it has | 851 | telling us whether this is a directory or not, i.e. whether it has |
848 | an index root attribute or not. */ | 852 | an index root attribute or not. */ |
849 | /* | ||
850 | * The following flag is present both in the STANDARD_INFORMATION | ||
851 | * attribute and in the FILE_NAME attribute (in the field | ||
852 | * file_attributes). | ||
853 | */ | ||
854 | FILE_ATTR_DUP_VIEW_INDEX_PRESENT = const_cpu_to_le32(0x20000000), | 853 | FILE_ATTR_DUP_VIEW_INDEX_PRESENT = const_cpu_to_le32(0x20000000), |
855 | /* Note, this is a copy of the corresponding bit from the mft record, | 854 | /* Note, this is a copy of the corresponding bit from the mft record, |
856 | telling us whether this file has a view index present (eg. object id | 855 | telling us whether this file has a view index present (eg. object id |
@@ -891,7 +890,7 @@ typedef struct { | |||
891 | Windows this is only updated when | 890 | Windows this is only updated when |
892 | accessed if some time delta has | 891 | accessed if some time delta has |
893 | passed since the last update. Also, | 892 | passed since the last update. Also, |
894 | last access times updates can be | 893 | last access time updates can be |
895 | disabled altogether for speed. */ | 894 | disabled altogether for speed. */ |
896 | /* 32*/ FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */ | 895 | /* 32*/ FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */ |
897 | /* 36*/ union { | 896 | /* 36*/ union { |
@@ -1076,16 +1075,21 @@ typedef struct { | |||
1076 | /* 20*/ sle64 last_access_time; /* Time this mft record was last | 1075 | /* 20*/ sle64 last_access_time; /* Time this mft record was last |
1077 | accessed. */ | 1076 | accessed. */ |
1078 | /* 28*/ sle64 allocated_size; /* Byte size of on-disk allocated space | 1077 | /* 28*/ sle64 allocated_size; /* Byte size of on-disk allocated space |
1079 | for the data attribute. So for | 1078 | for the unnamed data attribute. So |
1080 | normal $DATA, this is the | 1079 | for normal $DATA, this is the |
1081 | allocated_size from the unnamed | 1080 | allocated_size from the unnamed |
1082 | $DATA attribute and for compressed | 1081 | $DATA attribute and for compressed |
1083 | and/or sparse $DATA, this is the | 1082 | and/or sparse $DATA, this is the |
1084 | compressed_size from the unnamed | 1083 | compressed_size from the unnamed |
1085 | $DATA attribute. NOTE: This is a | 1084 | $DATA attribute. For a directory or |
1086 | multiple of the cluster size. */ | 1085 | other inode without an unnamed $DATA |
1087 | /* 30*/ sle64 data_size; /* Byte size of actual data in data | 1086 | attribute, this is always 0. NOTE: |
1088 | attribute. */ | 1087 | This is a multiple of the cluster |
1088 | size. */ | ||
1089 | /* 30*/ sle64 data_size; /* Byte size of actual data in unnamed | ||
1090 | data attribute. For a directory or | ||
1091 | other inode without an unnamed $DATA | ||
1092 | attribute, this is always 0. */ | ||
1089 | /* 38*/ FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */ | 1093 | /* 38*/ FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */ |
1090 | /* 3c*/ union { | 1094 | /* 3c*/ union { |
1091 | /* 3c*/ struct { | 1095 | /* 3c*/ struct { |
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 6499aafc2258..4e72bc7afdf9 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c | |||
@@ -93,6 +93,7 @@ static inline MFT_RECORD *map_mft_record_page(ntfs_inode *ni) | |||
93 | "Run chkdsk.", ni->mft_no); | 93 | "Run chkdsk.", ni->mft_no); |
94 | ntfs_unmap_page(page); | 94 | ntfs_unmap_page(page); |
95 | page = ERR_PTR(-EIO); | 95 | page = ERR_PTR(-EIO); |
96 | NVolSetErrors(vol); | ||
96 | } | 97 | } |
97 | err_out: | 98 | err_out: |
98 | ni->page = NULL; | 99 | ni->page = NULL; |
@@ -104,8 +105,8 @@ err_out: | |||
104 | * map_mft_record - map, pin and lock an mft record | 105 | * map_mft_record - map, pin and lock an mft record |
105 | * @ni: ntfs inode whose MFT record to map | 106 | * @ni: ntfs inode whose MFT record to map |
106 | * | 107 | * |
107 | * First, take the mrec_lock semaphore. We might now be sleeping, while waiting | 108 | * First, take the mrec_lock mutex. We might now be sleeping, while waiting |
108 | * for the semaphore if it was already locked by someone else. | 109 | * for the mutex if it was already locked by someone else. |
109 | * | 110 | * |
110 | * The page of the record is mapped using map_mft_record_page() before being | 111 | * The page of the record is mapped using map_mft_record_page() before being |
111 | * returned to the caller. | 112 | * returned to the caller. |
@@ -135,9 +136,9 @@ err_out: | |||
135 | * So that code will end up having to own the mrec_lock of all mft | 136 | * So that code will end up having to own the mrec_lock of all mft |
136 | * records/inodes present in the page before I/O can proceed. In that case we | 137 | * records/inodes present in the page before I/O can proceed. In that case we |
137 | * wouldn't need to bother with PG_locked and PG_uptodate as nobody will be | 138 | * wouldn't need to bother with PG_locked and PG_uptodate as nobody will be |
138 | * accessing anything without owning the mrec_lock semaphore. But we do need | 139 | * accessing anything without owning the mrec_lock mutex. But we do need to |
139 | * to use them because of the read_cache_page() invocation and the code becomes | 140 | * use them because of the read_cache_page() invocation and the code becomes so |
140 | * so much simpler this way that it is well worth it. | 141 | * much simpler this way that it is well worth it. |
141 | * | 142 | * |
142 | * The mft record is now ours and we return a pointer to it. You need to check | 143 | * The mft record is now ours and we return a pointer to it. You need to check |
143 | * the returned pointer with IS_ERR() and if that is true, PTR_ERR() will return | 144 | * the returned pointer with IS_ERR() and if that is true, PTR_ERR() will return |
@@ -160,13 +161,13 @@ MFT_RECORD *map_mft_record(ntfs_inode *ni) | |||
160 | atomic_inc(&ni->count); | 161 | atomic_inc(&ni->count); |
161 | 162 | ||
162 | /* Serialize access to this mft record. */ | 163 | /* Serialize access to this mft record. */ |
163 | down(&ni->mrec_lock); | 164 | mutex_lock(&ni->mrec_lock); |
164 | 165 | ||
165 | m = map_mft_record_page(ni); | 166 | m = map_mft_record_page(ni); |
166 | if (likely(!IS_ERR(m))) | 167 | if (likely(!IS_ERR(m))) |
167 | return m; | 168 | return m; |
168 | 169 | ||
169 | up(&ni->mrec_lock); | 170 | mutex_unlock(&ni->mrec_lock); |
170 | atomic_dec(&ni->count); | 171 | atomic_dec(&ni->count); |
171 | ntfs_error(ni->vol->sb, "Failed with error code %lu.", -PTR_ERR(m)); | 172 | ntfs_error(ni->vol->sb, "Failed with error code %lu.", -PTR_ERR(m)); |
172 | return m; | 173 | return m; |
@@ -217,7 +218,7 @@ void unmap_mft_record(ntfs_inode *ni) | |||
217 | ntfs_debug("Entering for mft_no 0x%lx.", ni->mft_no); | 218 | ntfs_debug("Entering for mft_no 0x%lx.", ni->mft_no); |
218 | 219 | ||
219 | unmap_mft_record_page(ni); | 220 | unmap_mft_record_page(ni); |
220 | up(&ni->mrec_lock); | 221 | mutex_unlock(&ni->mrec_lock); |
221 | atomic_dec(&ni->count); | 222 | atomic_dec(&ni->count); |
222 | /* | 223 | /* |
223 | * If pure ntfs_inode, i.e. no vfs inode attached, we leave it to | 224 | * If pure ntfs_inode, i.e. no vfs inode attached, we leave it to |
@@ -261,7 +262,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref, | |||
261 | * in which case just return it. If not found, add it to the base | 262 | * in which case just return it. If not found, add it to the base |
262 | * inode before returning it. | 263 | * inode before returning it. |
263 | */ | 264 | */ |
264 | down(&base_ni->extent_lock); | 265 | mutex_lock(&base_ni->extent_lock); |
265 | if (base_ni->nr_extents > 0) { | 266 | if (base_ni->nr_extents > 0) { |
266 | extent_nis = base_ni->ext.extent_ntfs_inos; | 267 | extent_nis = base_ni->ext.extent_ntfs_inos; |
267 | for (i = 0; i < base_ni->nr_extents; i++) { | 268 | for (i = 0; i < base_ni->nr_extents; i++) { |
@@ -274,7 +275,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref, | |||
274 | } | 275 | } |
275 | } | 276 | } |
276 | if (likely(ni != NULL)) { | 277 | if (likely(ni != NULL)) { |
277 | up(&base_ni->extent_lock); | 278 | mutex_unlock(&base_ni->extent_lock); |
278 | atomic_dec(&base_ni->count); | 279 | atomic_dec(&base_ni->count); |
279 | /* We found the record; just have to map and return it. */ | 280 | /* We found the record; just have to map and return it. */ |
280 | m = map_mft_record(ni); | 281 | m = map_mft_record(ni); |
@@ -301,7 +302,7 @@ map_err_out: | |||
301 | /* Record wasn't there. Get a new ntfs inode and initialize it. */ | 302 | /* Record wasn't there. Get a new ntfs inode and initialize it. */ |
302 | ni = ntfs_new_extent_inode(base_ni->vol->sb, mft_no); | 303 | ni = ntfs_new_extent_inode(base_ni->vol->sb, mft_no); |
303 | if (unlikely(!ni)) { | 304 | if (unlikely(!ni)) { |
304 | up(&base_ni->extent_lock); | 305 | mutex_unlock(&base_ni->extent_lock); |
305 | atomic_dec(&base_ni->count); | 306 | atomic_dec(&base_ni->count); |
306 | return ERR_PTR(-ENOMEM); | 307 | return ERR_PTR(-ENOMEM); |
307 | } | 308 | } |
@@ -312,7 +313,7 @@ map_err_out: | |||
312 | /* Now map the record. */ | 313 | /* Now map the record. */ |
313 | m = map_mft_record(ni); | 314 | m = map_mft_record(ni); |
314 | if (IS_ERR(m)) { | 315 | if (IS_ERR(m)) { |
315 | up(&base_ni->extent_lock); | 316 | mutex_unlock(&base_ni->extent_lock); |
316 | atomic_dec(&base_ni->count); | 317 | atomic_dec(&base_ni->count); |
317 | ntfs_clear_extent_inode(ni); | 318 | ntfs_clear_extent_inode(ni); |
318 | goto map_err_out; | 319 | goto map_err_out; |
@@ -347,14 +348,14 @@ map_err_out: | |||
347 | base_ni->ext.extent_ntfs_inos = tmp; | 348 | base_ni->ext.extent_ntfs_inos = tmp; |
348 | } | 349 | } |
349 | base_ni->ext.extent_ntfs_inos[base_ni->nr_extents++] = ni; | 350 | base_ni->ext.extent_ntfs_inos[base_ni->nr_extents++] = ni; |
350 | up(&base_ni->extent_lock); | 351 | mutex_unlock(&base_ni->extent_lock); |
351 | atomic_dec(&base_ni->count); | 352 | atomic_dec(&base_ni->count); |
352 | ntfs_debug("Done 2."); | 353 | ntfs_debug("Done 2."); |
353 | *ntfs_ino = ni; | 354 | *ntfs_ino = ni; |
354 | return m; | 355 | return m; |
355 | unm_err_out: | 356 | unm_err_out: |
356 | unmap_mft_record(ni); | 357 | unmap_mft_record(ni); |
357 | up(&base_ni->extent_lock); | 358 | mutex_unlock(&base_ni->extent_lock); |
358 | atomic_dec(&base_ni->count); | 359 | atomic_dec(&base_ni->count); |
359 | /* | 360 | /* |
360 | * If the extent inode was not attached to the base inode we need to | 361 | * If the extent inode was not attached to the base inode we need to |
@@ -399,12 +400,12 @@ void __mark_mft_record_dirty(ntfs_inode *ni) | |||
399 | BUG_ON(NInoAttr(ni)); | 400 | BUG_ON(NInoAttr(ni)); |
400 | mark_ntfs_record_dirty(ni->page, ni->page_ofs); | 401 | mark_ntfs_record_dirty(ni->page, ni->page_ofs); |
401 | /* Determine the base vfs inode and mark it dirty, too. */ | 402 | /* Determine the base vfs inode and mark it dirty, too. */ |
402 | down(&ni->extent_lock); | 403 | mutex_lock(&ni->extent_lock); |
403 | if (likely(ni->nr_extents >= 0)) | 404 | if (likely(ni->nr_extents >= 0)) |
404 | base_ni = ni; | 405 | base_ni = ni; |
405 | else | 406 | else |
406 | base_ni = ni->ext.base_ntfs_ino; | 407 | base_ni = ni->ext.base_ntfs_ino; |
407 | up(&ni->extent_lock); | 408 | mutex_unlock(&ni->extent_lock); |
408 | __mark_inode_dirty(VFS_I(base_ni), I_DIRTY_SYNC | I_DIRTY_DATASYNC); | 409 | __mark_inode_dirty(VFS_I(base_ni), I_DIRTY_SYNC | I_DIRTY_DATASYNC); |
409 | } | 410 | } |
410 | 411 | ||
@@ -650,10 +651,7 @@ err_out: | |||
650 | * fs/ntfs/aops.c::mark_ntfs_record_dirty(). | 651 | * fs/ntfs/aops.c::mark_ntfs_record_dirty(). |
651 | * | 652 | * |
652 | * On success, clean the mft record and return 0. On error, leave the mft | 653 | * On success, clean the mft record and return 0. On error, leave the mft |
653 | * record dirty and return -errno. The caller should call make_bad_inode() on | 654 | * record dirty and return -errno. |
654 | * the base inode to ensure no more access happens to this inode. We do not do | ||
655 | * it here as the caller may want to finish writing other extent mft records | ||
656 | * first to minimize on-disk metadata inconsistencies. | ||
657 | * | 655 | * |
658 | * NOTE: We always perform synchronous i/o and ignore the @sync parameter. | 656 | * NOTE: We always perform synchronous i/o and ignore the @sync parameter. |
659 | * However, if the mft record has a counterpart in the mft mirror and @sync is | 657 | * However, if the mft record has a counterpart in the mft mirror and @sync is |
@@ -983,7 +981,7 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no, | |||
983 | } | 981 | } |
984 | ntfs_debug("Inode 0x%lx is not dirty.", mft_no); | 982 | ntfs_debug("Inode 0x%lx is not dirty.", mft_no); |
985 | /* The inode is not dirty, try to take the mft record lock. */ | 983 | /* The inode is not dirty, try to take the mft record lock. */ |
986 | if (unlikely(down_trylock(&ni->mrec_lock))) { | 984 | if (unlikely(!mutex_trylock(&ni->mrec_lock))) { |
987 | ntfs_debug("Mft record 0x%lx is already locked, do " | 985 | ntfs_debug("Mft record 0x%lx is already locked, do " |
988 | "not write it.", mft_no); | 986 | "not write it.", mft_no); |
989 | atomic_dec(&ni->count); | 987 | atomic_dec(&ni->count); |
@@ -1043,13 +1041,13 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no, | |||
1043 | * corresponding to this extent mft record attached. | 1041 | * corresponding to this extent mft record attached. |
1044 | */ | 1042 | */ |
1045 | ni = NTFS_I(vi); | 1043 | ni = NTFS_I(vi); |
1046 | down(&ni->extent_lock); | 1044 | mutex_lock(&ni->extent_lock); |
1047 | if (ni->nr_extents <= 0) { | 1045 | if (ni->nr_extents <= 0) { |
1048 | /* | 1046 | /* |
1049 | * The base inode has no attached extent inodes, write this | 1047 | * The base inode has no attached extent inodes, write this |
1050 | * extent mft record. | 1048 | * extent mft record. |
1051 | */ | 1049 | */ |
1052 | up(&ni->extent_lock); | 1050 | mutex_unlock(&ni->extent_lock); |
1053 | iput(vi); | 1051 | iput(vi); |
1054 | ntfs_debug("Base inode 0x%lx has no attached extent inodes, " | 1052 | ntfs_debug("Base inode 0x%lx has no attached extent inodes, " |
1055 | "write the extent record.", na.mft_no); | 1053 | "write the extent record.", na.mft_no); |
@@ -1072,7 +1070,7 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no, | |||
1072 | * extent mft record. | 1070 | * extent mft record. |
1073 | */ | 1071 | */ |
1074 | if (!eni) { | 1072 | if (!eni) { |
1075 | up(&ni->extent_lock); | 1073 | mutex_unlock(&ni->extent_lock); |
1076 | iput(vi); | 1074 | iput(vi); |
1077 | ntfs_debug("Extent inode 0x%lx is not attached to its base " | 1075 | ntfs_debug("Extent inode 0x%lx is not attached to its base " |
1078 | "inode 0x%lx, write the extent record.", | 1076 | "inode 0x%lx, write the extent record.", |
@@ -1083,12 +1081,12 @@ BOOL ntfs_may_write_mft_record(ntfs_volume *vol, const unsigned long mft_no, | |||
1083 | mft_no, na.mft_no); | 1081 | mft_no, na.mft_no); |
1084 | /* Take a reference to the extent ntfs inode. */ | 1082 | /* Take a reference to the extent ntfs inode. */ |
1085 | atomic_inc(&eni->count); | 1083 | atomic_inc(&eni->count); |
1086 | up(&ni->extent_lock); | 1084 | mutex_unlock(&ni->extent_lock); |
1087 | /* | 1085 | /* |
1088 | * Found the extent inode coresponding to this extent mft record. | 1086 | * Found the extent inode coresponding to this extent mft record. |
1089 | * Try to take the mft record lock. | 1087 | * Try to take the mft record lock. |
1090 | */ | 1088 | */ |
1091 | if (unlikely(down_trylock(&eni->mrec_lock))) { | 1089 | if (unlikely(!mutex_trylock(&eni->mrec_lock))) { |
1092 | atomic_dec(&eni->count); | 1090 | atomic_dec(&eni->count); |
1093 | iput(vi); | 1091 | iput(vi); |
1094 | ntfs_debug("Extent mft record 0x%lx is already locked, do " | 1092 | ntfs_debug("Extent mft record 0x%lx is already locked, do " |
@@ -2711,7 +2709,7 @@ mft_rec_already_initialized: | |||
2711 | * have its page mapped and it is very easy to do. | 2709 | * have its page mapped and it is very easy to do. |
2712 | */ | 2710 | */ |
2713 | atomic_inc(&ni->count); | 2711 | atomic_inc(&ni->count); |
2714 | down(&ni->mrec_lock); | 2712 | mutex_lock(&ni->mrec_lock); |
2715 | ni->page = page; | 2713 | ni->page = page; |
2716 | ni->page_ofs = ofs; | 2714 | ni->page_ofs = ofs; |
2717 | /* | 2715 | /* |
@@ -2798,22 +2796,22 @@ int ntfs_extent_mft_record_free(ntfs_inode *ni, MFT_RECORD *m) | |||
2798 | BUG_ON(NInoAttr(ni)); | 2796 | BUG_ON(NInoAttr(ni)); |
2799 | BUG_ON(ni->nr_extents != -1); | 2797 | BUG_ON(ni->nr_extents != -1); |
2800 | 2798 | ||
2801 | down(&ni->extent_lock); | 2799 | mutex_lock(&ni->extent_lock); |
2802 | base_ni = ni->ext.base_ntfs_ino; | 2800 | base_ni = ni->ext.base_ntfs_ino; |
2803 | up(&ni->extent_lock); | 2801 | mutex_unlock(&ni->extent_lock); |
2804 | 2802 | ||
2805 | BUG_ON(base_ni->nr_extents <= 0); | 2803 | BUG_ON(base_ni->nr_extents <= 0); |
2806 | 2804 | ||
2807 | ntfs_debug("Entering for extent inode 0x%lx, base inode 0x%lx.\n", | 2805 | ntfs_debug("Entering for extent inode 0x%lx, base inode 0x%lx.\n", |
2808 | mft_no, base_ni->mft_no); | 2806 | mft_no, base_ni->mft_no); |
2809 | 2807 | ||
2810 | down(&base_ni->extent_lock); | 2808 | mutex_lock(&base_ni->extent_lock); |
2811 | 2809 | ||
2812 | /* Make sure we are holding the only reference to the extent inode. */ | 2810 | /* Make sure we are holding the only reference to the extent inode. */ |
2813 | if (atomic_read(&ni->count) > 2) { | 2811 | if (atomic_read(&ni->count) > 2) { |
2814 | ntfs_error(vol->sb, "Tried to free busy extent inode 0x%lx, " | 2812 | ntfs_error(vol->sb, "Tried to free busy extent inode 0x%lx, " |
2815 | "not freeing.", base_ni->mft_no); | 2813 | "not freeing.", base_ni->mft_no); |
2816 | up(&base_ni->extent_lock); | 2814 | mutex_unlock(&base_ni->extent_lock); |
2817 | return -EBUSY; | 2815 | return -EBUSY; |
2818 | } | 2816 | } |
2819 | 2817 | ||
@@ -2831,7 +2829,7 @@ int ntfs_extent_mft_record_free(ntfs_inode *ni, MFT_RECORD *m) | |||
2831 | break; | 2829 | break; |
2832 | } | 2830 | } |
2833 | 2831 | ||
2834 | up(&base_ni->extent_lock); | 2832 | mutex_unlock(&base_ni->extent_lock); |
2835 | 2833 | ||
2836 | if (unlikely(err)) { | 2834 | if (unlikely(err)) { |
2837 | ntfs_error(vol->sb, "Extent inode 0x%lx is not attached to " | 2835 | ntfs_error(vol->sb, "Extent inode 0x%lx is not attached to " |
@@ -2890,7 +2888,7 @@ rollback_error: | |||
2890 | return 0; | 2888 | return 0; |
2891 | rollback: | 2889 | rollback: |
2892 | /* Rollback what we did... */ | 2890 | /* Rollback what we did... */ |
2893 | down(&base_ni->extent_lock); | 2891 | mutex_lock(&base_ni->extent_lock); |
2894 | extent_nis = base_ni->ext.extent_ntfs_inos; | 2892 | extent_nis = base_ni->ext.extent_ntfs_inos; |
2895 | if (!(base_ni->nr_extents & 3)) { | 2893 | if (!(base_ni->nr_extents & 3)) { |
2896 | int new_size = (base_ni->nr_extents + 4) * sizeof(ntfs_inode*); | 2894 | int new_size = (base_ni->nr_extents + 4) * sizeof(ntfs_inode*); |
@@ -2899,7 +2897,7 @@ rollback: | |||
2899 | if (unlikely(!extent_nis)) { | 2897 | if (unlikely(!extent_nis)) { |
2900 | ntfs_error(vol->sb, "Failed to allocate internal " | 2898 | ntfs_error(vol->sb, "Failed to allocate internal " |
2901 | "buffer during rollback.%s", es); | 2899 | "buffer during rollback.%s", es); |
2902 | up(&base_ni->extent_lock); | 2900 | mutex_unlock(&base_ni->extent_lock); |
2903 | NVolSetErrors(vol); | 2901 | NVolSetErrors(vol); |
2904 | goto rollback_error; | 2902 | goto rollback_error; |
2905 | } | 2903 | } |
@@ -2914,7 +2912,7 @@ rollback: | |||
2914 | m->flags |= MFT_RECORD_IN_USE; | 2912 | m->flags |= MFT_RECORD_IN_USE; |
2915 | m->sequence_number = old_seq_no; | 2913 | m->sequence_number = old_seq_no; |
2916 | extent_nis[base_ni->nr_extents++] = ni; | 2914 | extent_nis[base_ni->nr_extents++] = ni; |
2917 | up(&base_ni->extent_lock); | 2915 | mutex_unlock(&base_ni->extent_lock); |
2918 | mark_mft_record_dirty(ni); | 2916 | mark_mft_record_dirty(ni); |
2919 | return err; | 2917 | return err; |
2920 | } | 2918 | } |
diff --git a/fs/ntfs/mft.h b/fs/ntfs/mft.h index 407de2cef1d6..639cd1bab08b 100644 --- a/fs/ntfs/mft.h +++ b/fs/ntfs/mft.h | |||
@@ -97,10 +97,7 @@ extern int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync); | |||
97 | * uptodate. | 97 | * uptodate. |
98 | * | 98 | * |
99 | * On success, clean the mft record and return 0. On error, leave the mft | 99 | * On success, clean the mft record and return 0. On error, leave the mft |
100 | * record dirty and return -errno. The caller should call make_bad_inode() on | 100 | * record dirty and return -errno. |
101 | * the base inode to ensure no more access happens to this inode. We do not do | ||
102 | * it here as the caller may want to finish writing other extent mft records | ||
103 | * first to minimize on-disk metadata inconsistencies. | ||
104 | */ | 101 | */ |
105 | static inline int write_mft_record(ntfs_inode *ni, MFT_RECORD *m, int sync) | 102 | static inline int write_mft_record(ntfs_inode *ni, MFT_RECORD *m, int sync) |
106 | { | 103 | { |
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c index 5ea9eb93af62..eddb2247cec5 100644 --- a/fs/ntfs/namei.c +++ b/fs/ntfs/namei.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * namei.c - NTFS kernel directory inode operations. Part of the Linux-NTFS | 2 | * namei.c - NTFS kernel directory inode operations. Part of the Linux-NTFS |
3 | * project. | 3 | * project. |
4 | * | 4 | * |
5 | * Copyright (c) 2001-2004 Anton Altaparmakov | 5 | * Copyright (c) 2001-2006 Anton Altaparmakov |
6 | * | 6 | * |
7 | * This program/include file is free software; you can redistribute it and/or | 7 | * This program/include file is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License as published | 8 | * modify it under the terms of the GNU General Public License as published |
@@ -115,7 +115,9 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, | |||
115 | uname_len = ntfs_nlstoucs(vol, dent->d_name.name, dent->d_name.len, | 115 | uname_len = ntfs_nlstoucs(vol, dent->d_name.name, dent->d_name.len, |
116 | &uname); | 116 | &uname); |
117 | if (uname_len < 0) { | 117 | if (uname_len < 0) { |
118 | ntfs_error(vol->sb, "Failed to convert name to Unicode."); | 118 | if (uname_len != -ENAMETOOLONG) |
119 | ntfs_error(vol->sb, "Failed to convert name to " | ||
120 | "Unicode."); | ||
119 | return ERR_PTR(uname_len); | 121 | return ERR_PTR(uname_len); |
120 | } | 122 | } |
121 | mref = ntfs_lookup_inode_by_name(NTFS_I(dir_ino), uname, uname_len, | 123 | mref = ntfs_lookup_inode_by_name(NTFS_I(dir_ino), uname, uname_len, |
@@ -157,7 +159,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, | |||
157 | /* Return the error code. */ | 159 | /* Return the error code. */ |
158 | return (struct dentry *)dent_inode; | 160 | return (struct dentry *)dent_inode; |
159 | } | 161 | } |
160 | /* It is guaranteed that name is no longer allocated at this point. */ | 162 | /* It is guaranteed that @name is no longer allocated at this point. */ |
161 | if (MREF_ERR(mref) == -ENOENT) { | 163 | if (MREF_ERR(mref) == -ENOENT) { |
162 | ntfs_debug("Entry was not found, adding negative dentry."); | 164 | ntfs_debug("Entry was not found, adding negative dentry."); |
163 | /* The dcache will handle negative entries. */ | 165 | /* The dcache will handle negative entries. */ |
@@ -168,7 +170,6 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, | |||
168 | ntfs_error(vol->sb, "ntfs_lookup_ino_by_name() failed with error " | 170 | ntfs_error(vol->sb, "ntfs_lookup_ino_by_name() failed with error " |
169 | "code %i.", -MREF_ERR(mref)); | 171 | "code %i.", -MREF_ERR(mref)); |
170 | return ERR_PTR(MREF_ERR(mref)); | 172 | return ERR_PTR(MREF_ERR(mref)); |
171 | |||
172 | // TODO: Consider moving this lot to a separate function! (AIA) | 173 | // TODO: Consider moving this lot to a separate function! (AIA) |
173 | handle_name: | 174 | handle_name: |
174 | { | 175 | { |
diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h index 653d2a5c4899..0624c8ef4d9c 100644 --- a/fs/ntfs/ntfs.h +++ b/fs/ntfs/ntfs.h | |||
@@ -91,7 +91,7 @@ extern void free_compression_buffers(void); | |||
91 | 91 | ||
92 | /* From fs/ntfs/super.c */ | 92 | /* From fs/ntfs/super.c */ |
93 | #define default_upcase_len 0x10000 | 93 | #define default_upcase_len 0x10000 |
94 | extern struct semaphore ntfs_lock; | 94 | extern struct mutex ntfs_lock; |
95 | 95 | ||
96 | typedef struct { | 96 | typedef struct { |
97 | int val; | 97 | int val; |
diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c index 061b5ff6b73c..eb52b801512b 100644 --- a/fs/ntfs/runlist.c +++ b/fs/ntfs/runlist.c | |||
@@ -381,6 +381,7 @@ static inline runlist_element *ntfs_rl_insert(runlist_element *dst, | |||
381 | static inline runlist_element *ntfs_rl_replace(runlist_element *dst, | 381 | static inline runlist_element *ntfs_rl_replace(runlist_element *dst, |
382 | int dsize, runlist_element *src, int ssize, int loc) | 382 | int dsize, runlist_element *src, int ssize, int loc) |
383 | { | 383 | { |
384 | signed delta; | ||
384 | BOOL left = FALSE; /* Left end of @src needs merging. */ | 385 | BOOL left = FALSE; /* Left end of @src needs merging. */ |
385 | BOOL right = FALSE; /* Right end of @src needs merging. */ | 386 | BOOL right = FALSE; /* Right end of @src needs merging. */ |
386 | int tail; /* Start of tail of @dst. */ | 387 | int tail; /* Start of tail of @dst. */ |
@@ -396,11 +397,14 @@ static inline runlist_element *ntfs_rl_replace(runlist_element *dst, | |||
396 | left = ntfs_are_rl_mergeable(dst + loc - 1, src); | 397 | left = ntfs_are_rl_mergeable(dst + loc - 1, src); |
397 | /* | 398 | /* |
398 | * Allocate some space. We will need less if the left, right, or both | 399 | * Allocate some space. We will need less if the left, right, or both |
399 | * ends get merged. | 400 | * ends get merged. The -1 accounts for the run being replaced. |
400 | */ | 401 | */ |
401 | dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left - right); | 402 | delta = ssize - 1 - left - right; |
402 | if (IS_ERR(dst)) | 403 | if (delta > 0) { |
403 | return dst; | 404 | dst = ntfs_rl_realloc(dst, dsize, dsize + delta); |
405 | if (IS_ERR(dst)) | ||
406 | return dst; | ||
407 | } | ||
404 | /* | 408 | /* |
405 | * We are guaranteed to succeed from here so can start modifying the | 409 | * We are guaranteed to succeed from here so can start modifying the |
406 | * original runlists. | 410 | * original runlists. |
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 368a8ec10668..7646b5059389 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c | |||
@@ -1099,26 +1099,38 @@ static BOOL check_mft_mirror(ntfs_volume *vol) | |||
1099 | kmirr = page_address(mirr_page); | 1099 | kmirr = page_address(mirr_page); |
1100 | ++index; | 1100 | ++index; |
1101 | } | 1101 | } |
1102 | /* Make sure the record is ok. */ | 1102 | /* Do not check the record if it is not in use. */ |
1103 | if (ntfs_is_baad_recordp((le32*)kmft)) { | 1103 | if (((MFT_RECORD*)kmft)->flags & MFT_RECORD_IN_USE) { |
1104 | ntfs_error(sb, "Incomplete multi sector transfer " | 1104 | /* Make sure the record is ok. */ |
1105 | "detected in mft record %i.", i); | 1105 | if (ntfs_is_baad_recordp((le32*)kmft)) { |
1106 | ntfs_error(sb, "Incomplete multi sector " | ||
1107 | "transfer detected in mft " | ||
1108 | "record %i.", i); | ||
1106 | mm_unmap_out: | 1109 | mm_unmap_out: |
1107 | ntfs_unmap_page(mirr_page); | 1110 | ntfs_unmap_page(mirr_page); |
1108 | mft_unmap_out: | 1111 | mft_unmap_out: |
1109 | ntfs_unmap_page(mft_page); | 1112 | ntfs_unmap_page(mft_page); |
1110 | return FALSE; | 1113 | return FALSE; |
1114 | } | ||
1111 | } | 1115 | } |
1112 | if (ntfs_is_baad_recordp((le32*)kmirr)) { | 1116 | /* Do not check the mirror record if it is not in use. */ |
1113 | ntfs_error(sb, "Incomplete multi sector transfer " | 1117 | if (((MFT_RECORD*)kmirr)->flags & MFT_RECORD_IN_USE) { |
1114 | "detected in mft mirror record %i.", i); | 1118 | if (ntfs_is_baad_recordp((le32*)kmirr)) { |
1115 | goto mm_unmap_out; | 1119 | ntfs_error(sb, "Incomplete multi sector " |
1120 | "transfer detected in mft " | ||
1121 | "mirror record %i.", i); | ||
1122 | goto mm_unmap_out; | ||
1123 | } | ||
1116 | } | 1124 | } |
1117 | /* Get the amount of data in the current record. */ | 1125 | /* Get the amount of data in the current record. */ |
1118 | bytes = le32_to_cpu(((MFT_RECORD*)kmft)->bytes_in_use); | 1126 | bytes = le32_to_cpu(((MFT_RECORD*)kmft)->bytes_in_use); |
1119 | if (!bytes || bytes > vol->mft_record_size) { | 1127 | if (bytes < sizeof(MFT_RECORD_OLD) || |
1128 | bytes > vol->mft_record_size || | ||
1129 | ntfs_is_baad_recordp((le32*)kmft)) { | ||
1120 | bytes = le32_to_cpu(((MFT_RECORD*)kmirr)->bytes_in_use); | 1130 | bytes = le32_to_cpu(((MFT_RECORD*)kmirr)->bytes_in_use); |
1121 | if (!bytes || bytes > vol->mft_record_size) | 1131 | if (bytes < sizeof(MFT_RECORD_OLD) || |
1132 | bytes > vol->mft_record_size || | ||
1133 | ntfs_is_baad_recordp((le32*)kmirr)) | ||
1122 | bytes = vol->mft_record_size; | 1134 | bytes = vol->mft_record_size; |
1123 | } | 1135 | } |
1124 | /* Compare the two records. */ | 1136 | /* Compare the two records. */ |
@@ -1665,11 +1677,11 @@ read_partial_upcase_page: | |||
1665 | ntfs_debug("Read %llu bytes from $UpCase (expected %zu bytes).", | 1677 | ntfs_debug("Read %llu bytes from $UpCase (expected %zu bytes).", |
1666 | i_size, 64 * 1024 * sizeof(ntfschar)); | 1678 | i_size, 64 * 1024 * sizeof(ntfschar)); |
1667 | iput(ino); | 1679 | iput(ino); |
1668 | down(&ntfs_lock); | 1680 | mutex_lock(&ntfs_lock); |
1669 | if (!default_upcase) { | 1681 | if (!default_upcase) { |
1670 | ntfs_debug("Using volume specified $UpCase since default is " | 1682 | ntfs_debug("Using volume specified $UpCase since default is " |
1671 | "not present."); | 1683 | "not present."); |
1672 | up(&ntfs_lock); | 1684 | mutex_unlock(&ntfs_lock); |
1673 | return TRUE; | 1685 | return TRUE; |
1674 | } | 1686 | } |
1675 | max = default_upcase_len; | 1687 | max = default_upcase_len; |
@@ -1683,12 +1695,12 @@ read_partial_upcase_page: | |||
1683 | vol->upcase = default_upcase; | 1695 | vol->upcase = default_upcase; |
1684 | vol->upcase_len = max; | 1696 | vol->upcase_len = max; |
1685 | ntfs_nr_upcase_users++; | 1697 | ntfs_nr_upcase_users++; |
1686 | up(&ntfs_lock); | 1698 | mutex_unlock(&ntfs_lock); |
1687 | ntfs_debug("Volume specified $UpCase matches default. Using " | 1699 | ntfs_debug("Volume specified $UpCase matches default. Using " |
1688 | "default."); | 1700 | "default."); |
1689 | return TRUE; | 1701 | return TRUE; |
1690 | } | 1702 | } |
1691 | up(&ntfs_lock); | 1703 | mutex_unlock(&ntfs_lock); |
1692 | ntfs_debug("Using volume specified $UpCase since it does not match " | 1704 | ntfs_debug("Using volume specified $UpCase since it does not match " |
1693 | "the default."); | 1705 | "the default."); |
1694 | return TRUE; | 1706 | return TRUE; |
@@ -1697,17 +1709,17 @@ iput_upcase_failed: | |||
1697 | ntfs_free(vol->upcase); | 1709 | ntfs_free(vol->upcase); |
1698 | vol->upcase = NULL; | 1710 | vol->upcase = NULL; |
1699 | upcase_failed: | 1711 | upcase_failed: |
1700 | down(&ntfs_lock); | 1712 | mutex_lock(&ntfs_lock); |
1701 | if (default_upcase) { | 1713 | if (default_upcase) { |
1702 | vol->upcase = default_upcase; | 1714 | vol->upcase = default_upcase; |
1703 | vol->upcase_len = default_upcase_len; | 1715 | vol->upcase_len = default_upcase_len; |
1704 | ntfs_nr_upcase_users++; | 1716 | ntfs_nr_upcase_users++; |
1705 | up(&ntfs_lock); | 1717 | mutex_unlock(&ntfs_lock); |
1706 | ntfs_error(sb, "Failed to load $UpCase from the volume. Using " | 1718 | ntfs_error(sb, "Failed to load $UpCase from the volume. Using " |
1707 | "default."); | 1719 | "default."); |
1708 | return TRUE; | 1720 | return TRUE; |
1709 | } | 1721 | } |
1710 | up(&ntfs_lock); | 1722 | mutex_unlock(&ntfs_lock); |
1711 | ntfs_error(sb, "Failed to initialize upcase table."); | 1723 | ntfs_error(sb, "Failed to initialize upcase table."); |
1712 | return FALSE; | 1724 | return FALSE; |
1713 | } | 1725 | } |
@@ -2183,12 +2195,12 @@ iput_attrdef_err_out: | |||
2183 | iput_upcase_err_out: | 2195 | iput_upcase_err_out: |
2184 | #endif /* NTFS_RW */ | 2196 | #endif /* NTFS_RW */ |
2185 | vol->upcase_len = 0; | 2197 | vol->upcase_len = 0; |
2186 | down(&ntfs_lock); | 2198 | mutex_lock(&ntfs_lock); |
2187 | if (vol->upcase == default_upcase) { | 2199 | if (vol->upcase == default_upcase) { |
2188 | ntfs_nr_upcase_users--; | 2200 | ntfs_nr_upcase_users--; |
2189 | vol->upcase = NULL; | 2201 | vol->upcase = NULL; |
2190 | } | 2202 | } |
2191 | up(&ntfs_lock); | 2203 | mutex_unlock(&ntfs_lock); |
2192 | if (vol->upcase) { | 2204 | if (vol->upcase) { |
2193 | ntfs_free(vol->upcase); | 2205 | ntfs_free(vol->upcase); |
2194 | vol->upcase = NULL; | 2206 | vol->upcase = NULL; |
@@ -2393,7 +2405,7 @@ static void ntfs_put_super(struct super_block *sb) | |||
2393 | * Destroy the global default upcase table if necessary. Also decrease | 2405 | * Destroy the global default upcase table if necessary. Also decrease |
2394 | * the number of upcase users if we are a user. | 2406 | * the number of upcase users if we are a user. |
2395 | */ | 2407 | */ |
2396 | down(&ntfs_lock); | 2408 | mutex_lock(&ntfs_lock); |
2397 | if (vol->upcase == default_upcase) { | 2409 | if (vol->upcase == default_upcase) { |
2398 | ntfs_nr_upcase_users--; | 2410 | ntfs_nr_upcase_users--; |
2399 | vol->upcase = NULL; | 2411 | vol->upcase = NULL; |
@@ -2404,7 +2416,7 @@ static void ntfs_put_super(struct super_block *sb) | |||
2404 | } | 2416 | } |
2405 | if (vol->cluster_size <= 4096 && !--ntfs_nr_compression_users) | 2417 | if (vol->cluster_size <= 4096 && !--ntfs_nr_compression_users) |
2406 | free_compression_buffers(); | 2418 | free_compression_buffers(); |
2407 | up(&ntfs_lock); | 2419 | mutex_unlock(&ntfs_lock); |
2408 | if (vol->upcase) { | 2420 | if (vol->upcase) { |
2409 | ntfs_free(vol->upcase); | 2421 | ntfs_free(vol->upcase); |
2410 | vol->upcase = NULL; | 2422 | vol->upcase = NULL; |
@@ -2878,7 +2890,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) | |||
2878 | ntfs_error(sb, "Failed to load essential metadata."); | 2890 | ntfs_error(sb, "Failed to load essential metadata."); |
2879 | goto iput_tmp_ino_err_out_now; | 2891 | goto iput_tmp_ino_err_out_now; |
2880 | } | 2892 | } |
2881 | down(&ntfs_lock); | 2893 | mutex_lock(&ntfs_lock); |
2882 | /* | 2894 | /* |
2883 | * The current mount is a compression user if the cluster size is | 2895 | * The current mount is a compression user if the cluster size is |
2884 | * less than or equal 4kiB. | 2896 | * less than or equal 4kiB. |
@@ -2889,7 +2901,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) | |||
2889 | ntfs_error(NULL, "Failed to allocate buffers " | 2901 | ntfs_error(NULL, "Failed to allocate buffers " |
2890 | "for compression engine."); | 2902 | "for compression engine."); |
2891 | ntfs_nr_compression_users--; | 2903 | ntfs_nr_compression_users--; |
2892 | up(&ntfs_lock); | 2904 | mutex_unlock(&ntfs_lock); |
2893 | goto iput_tmp_ino_err_out_now; | 2905 | goto iput_tmp_ino_err_out_now; |
2894 | } | 2906 | } |
2895 | } | 2907 | } |
@@ -2901,7 +2913,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) | |||
2901 | if (!default_upcase) | 2913 | if (!default_upcase) |
2902 | default_upcase = generate_default_upcase(); | 2914 | default_upcase = generate_default_upcase(); |
2903 | ntfs_nr_upcase_users++; | 2915 | ntfs_nr_upcase_users++; |
2904 | up(&ntfs_lock); | 2916 | mutex_unlock(&ntfs_lock); |
2905 | /* | 2917 | /* |
2906 | * From now on, ignore @silent parameter. If we fail below this line, | 2918 | * From now on, ignore @silent parameter. If we fail below this line, |
2907 | * it will be due to a corrupt fs or a system error, so we report it. | 2919 | * it will be due to a corrupt fs or a system error, so we report it. |
@@ -2919,12 +2931,12 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) | |||
2919 | atomic_inc(&vol->root_ino->i_count); | 2931 | atomic_inc(&vol->root_ino->i_count); |
2920 | ntfs_debug("Exiting, status successful."); | 2932 | ntfs_debug("Exiting, status successful."); |
2921 | /* Release the default upcase if it has no users. */ | 2933 | /* Release the default upcase if it has no users. */ |
2922 | down(&ntfs_lock); | 2934 | mutex_lock(&ntfs_lock); |
2923 | if (!--ntfs_nr_upcase_users && default_upcase) { | 2935 | if (!--ntfs_nr_upcase_users && default_upcase) { |
2924 | ntfs_free(default_upcase); | 2936 | ntfs_free(default_upcase); |
2925 | default_upcase = NULL; | 2937 | default_upcase = NULL; |
2926 | } | 2938 | } |
2927 | up(&ntfs_lock); | 2939 | mutex_unlock(&ntfs_lock); |
2928 | sb->s_export_op = &ntfs_export_ops; | 2940 | sb->s_export_op = &ntfs_export_ops; |
2929 | lock_kernel(); | 2941 | lock_kernel(); |
2930 | return 0; | 2942 | return 0; |
@@ -2992,12 +3004,12 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent) | |||
2992 | vol->attrdef = NULL; | 3004 | vol->attrdef = NULL; |
2993 | } | 3005 | } |
2994 | vol->upcase_len = 0; | 3006 | vol->upcase_len = 0; |
2995 | down(&ntfs_lock); | 3007 | mutex_lock(&ntfs_lock); |
2996 | if (vol->upcase == default_upcase) { | 3008 | if (vol->upcase == default_upcase) { |
2997 | ntfs_nr_upcase_users--; | 3009 | ntfs_nr_upcase_users--; |
2998 | vol->upcase = NULL; | 3010 | vol->upcase = NULL; |
2999 | } | 3011 | } |
3000 | up(&ntfs_lock); | 3012 | mutex_unlock(&ntfs_lock); |
3001 | if (vol->upcase) { | 3013 | if (vol->upcase) { |
3002 | ntfs_free(vol->upcase); | 3014 | ntfs_free(vol->upcase); |
3003 | vol->upcase = NULL; | 3015 | vol->upcase = NULL; |
@@ -3012,14 +3024,14 @@ unl_upcase_iput_tmp_ino_err_out_now: | |||
3012 | * Decrease the number of upcase users and destroy the global default | 3024 | * Decrease the number of upcase users and destroy the global default |
3013 | * upcase table if necessary. | 3025 | * upcase table if necessary. |
3014 | */ | 3026 | */ |
3015 | down(&ntfs_lock); | 3027 | mutex_lock(&ntfs_lock); |
3016 | if (!--ntfs_nr_upcase_users && default_upcase) { | 3028 | if (!--ntfs_nr_upcase_users && default_upcase) { |
3017 | ntfs_free(default_upcase); | 3029 | ntfs_free(default_upcase); |
3018 | default_upcase = NULL; | 3030 | default_upcase = NULL; |
3019 | } | 3031 | } |
3020 | if (vol->cluster_size <= 4096 && !--ntfs_nr_compression_users) | 3032 | if (vol->cluster_size <= 4096 && !--ntfs_nr_compression_users) |
3021 | free_compression_buffers(); | 3033 | free_compression_buffers(); |
3022 | up(&ntfs_lock); | 3034 | mutex_unlock(&ntfs_lock); |
3023 | iput_tmp_ino_err_out_now: | 3035 | iput_tmp_ino_err_out_now: |
3024 | iput(tmp_ino); | 3036 | iput(tmp_ino); |
3025 | if (vol->mft_ino && vol->mft_ino != tmp_ino) | 3037 | if (vol->mft_ino && vol->mft_ino != tmp_ino) |
@@ -3078,8 +3090,8 @@ static void ntfs_big_inode_init_once(void *foo, struct kmem_cache *cachep, | |||
3078 | struct kmem_cache *ntfs_attr_ctx_cache; | 3090 | struct kmem_cache *ntfs_attr_ctx_cache; |
3079 | struct kmem_cache *ntfs_index_ctx_cache; | 3091 | struct kmem_cache *ntfs_index_ctx_cache; |
3080 | 3092 | ||
3081 | /* Driver wide semaphore. */ | 3093 | /* Driver wide mutex. */ |
3082 | DECLARE_MUTEX(ntfs_lock); | 3094 | DEFINE_MUTEX(ntfs_lock); |
3083 | 3095 | ||
3084 | static struct super_block *ntfs_get_sb(struct file_system_type *fs_type, | 3096 | static struct super_block *ntfs_get_sb(struct file_system_type *fs_type, |
3085 | int flags, const char *dev_name, void *data) | 3097 | int flags, const char *dev_name, void *data) |
@@ -3234,7 +3246,7 @@ static void __exit exit_ntfs_fs(void) | |||
3234 | } | 3246 | } |
3235 | 3247 | ||
3236 | MODULE_AUTHOR("Anton Altaparmakov <aia21@cantab.net>"); | 3248 | MODULE_AUTHOR("Anton Altaparmakov <aia21@cantab.net>"); |
3237 | MODULE_DESCRIPTION("NTFS 1.2/3.x driver - Copyright (c) 2001-2005 Anton Altaparmakov"); | 3249 | MODULE_DESCRIPTION("NTFS 1.2/3.x driver - Copyright (c) 2001-2006 Anton Altaparmakov"); |
3238 | MODULE_VERSION(NTFS_VERSION); | 3250 | MODULE_VERSION(NTFS_VERSION); |
3239 | MODULE_LICENSE("GPL"); | 3251 | MODULE_LICENSE("GPL"); |
3240 | #ifdef DEBUG | 3252 | #ifdef DEBUG |
diff --git a/fs/ntfs/unistr.c b/fs/ntfs/unistr.c index 0ea887fc859c..b123c0fa6bf6 100644 --- a/fs/ntfs/unistr.c +++ b/fs/ntfs/unistr.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * unistr.c - NTFS Unicode string handling. Part of the Linux-NTFS project. | 2 | * unistr.c - NTFS Unicode string handling. Part of the Linux-NTFS project. |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2005 Anton Altaparmakov | 4 | * Copyright (c) 2001-2006 Anton Altaparmakov |
5 | * | 5 | * |
6 | * This program/include file is free software; you can redistribute it and/or | 6 | * This program/include file is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License as published | 7 | * modify it under the terms of the GNU General Public License as published |
@@ -19,6 +19,8 @@ | |||
19 | * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/slab.h> | ||
23 | |||
22 | #include "types.h" | 24 | #include "types.h" |
23 | #include "debug.h" | 25 | #include "debug.h" |
24 | #include "ntfs.h" | 26 | #include "ntfs.h" |
@@ -242,7 +244,7 @@ int ntfs_file_compare_values(FILE_NAME_ATTR *file_name_attr1, | |||
242 | * map dictates, into a little endian, 2-byte Unicode string. | 244 | * map dictates, into a little endian, 2-byte Unicode string. |
243 | * | 245 | * |
244 | * This function allocates the string and the caller is responsible for | 246 | * This function allocates the string and the caller is responsible for |
245 | * calling kmem_cache_free(ntfs_name_cache, @outs); when finished with it. | 247 | * calling kmem_cache_free(ntfs_name_cache, *@outs); when finished with it. |
246 | * | 248 | * |
247 | * On success the function returns the number of Unicode characters written to | 249 | * On success the function returns the number of Unicode characters written to |
248 | * the output string *@outs (>= 0), not counting the terminating Unicode NULL | 250 | * the output string *@outs (>= 0), not counting the terminating Unicode NULL |
@@ -262,37 +264,48 @@ int ntfs_nlstoucs(const ntfs_volume *vol, const char *ins, | |||
262 | wchar_t wc; | 264 | wchar_t wc; |
263 | int i, o, wc_len; | 265 | int i, o, wc_len; |
264 | 266 | ||
265 | /* We don't trust outside sources. */ | 267 | /* We do not trust outside sources. */ |
266 | if (ins) { | 268 | if (likely(ins)) { |
267 | ucs = kmem_cache_alloc(ntfs_name_cache, SLAB_NOFS); | 269 | ucs = kmem_cache_alloc(ntfs_name_cache, SLAB_NOFS); |
268 | if (ucs) { | 270 | if (likely(ucs)) { |
269 | for (i = o = 0; i < ins_len; i += wc_len) { | 271 | for (i = o = 0; i < ins_len; i += wc_len) { |
270 | wc_len = nls->char2uni(ins + i, ins_len - i, | 272 | wc_len = nls->char2uni(ins + i, ins_len - i, |
271 | &wc); | 273 | &wc); |
272 | if (wc_len >= 0) { | 274 | if (likely(wc_len >= 0 && |
273 | if (wc) { | 275 | o < NTFS_MAX_NAME_LEN)) { |
276 | if (likely(wc)) { | ||
274 | ucs[o++] = cpu_to_le16(wc); | 277 | ucs[o++] = cpu_to_le16(wc); |
275 | continue; | 278 | continue; |
276 | } /* else (!wc) */ | 279 | } /* else if (!wc) */ |
277 | break; | 280 | break; |
278 | } /* else (wc_len < 0) */ | 281 | } /* else if (wc_len < 0 || |
279 | goto conversion_err; | 282 | o >= NTFS_MAX_NAME_LEN) */ |
283 | goto name_err; | ||
280 | } | 284 | } |
281 | ucs[o] = 0; | 285 | ucs[o] = 0; |
282 | *outs = ucs; | 286 | *outs = ucs; |
283 | return o; | 287 | return o; |
284 | } /* else (!ucs) */ | 288 | } /* else if (!ucs) */ |
285 | ntfs_error(vol->sb, "Failed to allocate name from " | 289 | ntfs_error(vol->sb, "Failed to allocate buffer for converted " |
286 | "ntfs_name_cache!"); | 290 | "name from ntfs_name_cache."); |
287 | return -ENOMEM; | 291 | return -ENOMEM; |
288 | } /* else (!ins) */ | 292 | } /* else if (!ins) */ |
289 | ntfs_error(NULL, "Received NULL pointer."); | 293 | ntfs_error(vol->sb, "Received NULL pointer."); |
290 | return -EINVAL; | 294 | return -EINVAL; |
291 | conversion_err: | 295 | name_err: |
292 | ntfs_error(vol->sb, "Name using character set %s contains characters " | ||
293 | "that cannot be converted to Unicode.", nls->charset); | ||
294 | kmem_cache_free(ntfs_name_cache, ucs); | 296 | kmem_cache_free(ntfs_name_cache, ucs); |
295 | return -EILSEQ; | 297 | if (wc_len < 0) { |
298 | ntfs_error(vol->sb, "Name using character set %s contains " | ||
299 | "characters that cannot be converted to " | ||
300 | "Unicode.", nls->charset); | ||
301 | i = -EILSEQ; | ||
302 | } else /* if (o >= NTFS_MAX_NAME_LEN) */ { | ||
303 | ntfs_error(vol->sb, "Name is too long (maximum length for a " | ||
304 | "name on NTFS is %d Unicode characters.", | ||
305 | NTFS_MAX_NAME_LEN); | ||
306 | i = -ENAMETOOLONG; | ||
307 | } | ||
308 | return i; | ||
296 | } | 309 | } |
297 | 310 | ||
298 | /** | 311 | /** |