diff options
-rw-r--r-- | fs/ntfs/attrib.c | 13 | ||||
-rw-r--r-- | fs/ntfs/attrib.h | 4 | ||||
-rw-r--r-- | fs/ntfs/lcnalloc.c | 1 | ||||
-rw-r--r-- | fs/ntfs/runlist.c | 35 | ||||
-rw-r--r-- | fs/ntfs/runlist.h | 9 |
5 files changed, 59 insertions, 3 deletions
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 97e6fb047aa0..1b95f39234a3 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c | |||
@@ -1057,6 +1057,8 @@ void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx) | |||
1057 | return; | 1057 | return; |
1058 | } | 1058 | } |
1059 | 1059 | ||
1060 | #ifdef NTFS_RW | ||
1061 | |||
1060 | /** | 1062 | /** |
1061 | * ntfs_attr_find_in_attrdef - find an attribute in the $AttrDef system file | 1063 | * ntfs_attr_find_in_attrdef - find an attribute in the $AttrDef system file |
1062 | * @vol: ntfs volume to which the attribute belongs | 1064 | * @vol: ntfs volume to which the attribute belongs |
@@ -1243,6 +1245,13 @@ int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size) | |||
1243 | * -ENOSPC - Not enough disk space. | 1245 | * -ENOSPC - Not enough disk space. |
1244 | * -EINVAL - Attribute not defined on the volume. | 1246 | * -EINVAL - Attribute not defined on the volume. |
1245 | * -EIO - I/o error or other error. | 1247 | * -EIO - I/o error or other error. |
1248 | * Note that -ENOSPC is also returned in the case that there is not enough | ||
1249 | * space in the mft record to do the conversion. This can happen when the mft | ||
1250 | * record is already very full. The caller is responsible for trying to make | ||
1251 | * space in the mft record and trying again. FIXME: Do we need a separate | ||
1252 | * error return code for this kind of -ENOSPC or is it always worth trying | ||
1253 | * again in case the attribute may then fit in a resident state so no need to | ||
1254 | * make it non-resident at all? Ho-hum... (AIA) | ||
1246 | * | 1255 | * |
1247 | * NOTE to self: No changes in the attribute list are required to move from | 1256 | * NOTE to self: No changes in the attribute list are required to move from |
1248 | * a resident to a non-resident attribute. | 1257 | * a resident to a non-resident attribute. |
@@ -1520,13 +1529,13 @@ err_out: | |||
1520 | rl_err_out: | 1529 | rl_err_out: |
1521 | if (rl) { | 1530 | if (rl) { |
1522 | if (ntfs_cluster_free_from_rl(vol, rl) < 0) { | 1531 | if (ntfs_cluster_free_from_rl(vol, rl) < 0) { |
1523 | ntfs_free(rl); | ||
1524 | ntfs_error(vol->sb, "Failed to release allocated " | 1532 | ntfs_error(vol->sb, "Failed to release allocated " |
1525 | "cluster(s) in error code path. Run " | 1533 | "cluster(s) in error code path. Run " |
1526 | "chkdsk to recover the lost " | 1534 | "chkdsk to recover the lost " |
1527 | "cluster(s)."); | 1535 | "cluster(s)."); |
1528 | NVolSetErrors(vol); | 1536 | NVolSetErrors(vol); |
1529 | } | 1537 | } |
1538 | ntfs_free(rl); | ||
1530 | page_err_out: | 1539 | page_err_out: |
1531 | unlock_page(page); | 1540 | unlock_page(page); |
1532 | page_cache_release(page); | 1541 | page_cache_release(page); |
@@ -1680,3 +1689,5 @@ done: | |||
1680 | ntfs_debug("Done."); | 1689 | ntfs_debug("Done."); |
1681 | return 0; | 1690 | return 0; |
1682 | } | 1691 | } |
1692 | |||
1693 | #endif /* NTFS_RW */ | ||
diff --git a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h index d73385198336..0e4ac6d3c0e7 100644 --- a/fs/ntfs/attrib.h +++ b/fs/ntfs/attrib.h | |||
@@ -89,6 +89,8 @@ extern ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, | |||
89 | MFT_RECORD *mrec); | 89 | MFT_RECORD *mrec); |
90 | extern void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx); | 90 | extern void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx); |
91 | 91 | ||
92 | #ifdef NTFS_RW | ||
93 | |||
92 | extern int ntfs_attr_size_bounds_check(const ntfs_volume *vol, | 94 | extern int ntfs_attr_size_bounds_check(const ntfs_volume *vol, |
93 | const ATTR_TYPE type, const s64 size); | 95 | const ATTR_TYPE type, const s64 size); |
94 | extern int ntfs_attr_can_be_non_resident(const ntfs_volume *vol, | 96 | extern int ntfs_attr_can_be_non_resident(const ntfs_volume *vol, |
@@ -103,4 +105,6 @@ extern int ntfs_attr_make_non_resident(ntfs_inode *ni); | |||
103 | extern int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, | 105 | extern int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, |
104 | const u8 val); | 106 | const u8 val); |
105 | 107 | ||
108 | #endif /* NTFS_RW */ | ||
109 | |||
106 | #endif /* _LINUX_NTFS_ATTRIB_H */ | 110 | #endif /* _LINUX_NTFS_ATTRIB_H */ |
diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c index 71bf08730b05..7087b5b0e6ce 100644 --- a/fs/ntfs/lcnalloc.c +++ b/fs/ntfs/lcnalloc.c | |||
@@ -848,7 +848,6 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, | |||
848 | 848 | ||
849 | total_freed = real_freed = 0; | 849 | total_freed = real_freed = 0; |
850 | 850 | ||
851 | /* This returns with ni->runlist locked for reading on success. */ | ||
852 | down_read(&ni->runlist.lock); | 851 | down_read(&ni->runlist.lock); |
853 | rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, FALSE); | 852 | rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, FALSE); |
854 | if (IS_ERR(rl)) { | 853 | if (IS_ERR(rl)) { |
diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c index 3f479f176610..396d767c2cab 100644 --- a/fs/ntfs/runlist.c +++ b/fs/ntfs/runlist.c | |||
@@ -980,6 +980,39 @@ LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn) | |||
980 | return LCN_ENOENT; | 980 | return LCN_ENOENT; |
981 | } | 981 | } |
982 | 982 | ||
983 | #ifdef NTFS_RW | ||
984 | |||
985 | /** | ||
986 | * ntfs_rl_find_vcn_nolock - find a vcn in a runlist | ||
987 | * @rl: runlist to search | ||
988 | * @vcn: vcn to find | ||
989 | * | ||
990 | * Find the virtual cluster number @vcn in the runlist @rl and return the | ||
991 | * address of the runlist element containing the @vcn on success. | ||
992 | * | ||
993 | * Return NULL if @rl is NULL or @vcn is in an unmapped part/out of bounds of | ||
994 | * the runlist. | ||
995 | * | ||
996 | * Locking: The runlist must be locked on entry. | ||
997 | */ | ||
998 | runlist_element *ntfs_rl_find_vcn_nolock(runlist_element *rl, const VCN vcn) | ||
999 | { | ||
1000 | BUG_ON(vcn < 0); | ||
1001 | if (unlikely(!rl || vcn < rl[0].vcn)) | ||
1002 | return NULL; | ||
1003 | while (likely(rl->length)) { | ||
1004 | if (unlikely(vcn < rl[1].vcn)) { | ||
1005 | if (likely(rl->lcn >= LCN_HOLE)) | ||
1006 | return rl; | ||
1007 | return NULL; | ||
1008 | } | ||
1009 | rl++; | ||
1010 | } | ||
1011 | if (likely(rl->lcn == LCN_ENOENT)) | ||
1012 | return rl; | ||
1013 | return NULL; | ||
1014 | } | ||
1015 | |||
983 | /** | 1016 | /** |
984 | * ntfs_get_nr_significant_bytes - get number of bytes needed to store a number | 1017 | * ntfs_get_nr_significant_bytes - get number of bytes needed to store a number |
985 | * @n: number for which to get the number of bytes for | 1018 | * @n: number for which to get the number of bytes for |
@@ -1452,3 +1485,5 @@ int ntfs_rl_truncate_nolock(const ntfs_volume *vol, runlist *const runlist, | |||
1452 | ntfs_debug("Done."); | 1485 | ntfs_debug("Done."); |
1453 | return 0; | 1486 | return 0; |
1454 | } | 1487 | } |
1488 | |||
1489 | #endif /* NTFS_RW */ | ||
diff --git a/fs/ntfs/runlist.h b/fs/ntfs/runlist.h index 60c42f3a3fc4..cf5c1b44bea8 100644 --- a/fs/ntfs/runlist.h +++ b/fs/ntfs/runlist.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * runlist.h - Defines for runlist handling in NTFS Linux kernel driver. | 2 | * runlist.h - Defines for runlist handling in NTFS Linux kernel driver. |
3 | * Part of the Linux-NTFS project. | 3 | * Part of the Linux-NTFS project. |
4 | * | 4 | * |
5 | * Copyright (c) 2001-2004 Anton Altaparmakov | 5 | * Copyright (c) 2001-2005 Anton Altaparmakov |
6 | * Copyright (c) 2002 Richard Russon | 6 | * Copyright (c) 2002 Richard Russon |
7 | * | 7 | * |
8 | * This program/include file is free software; you can redistribute it and/or | 8 | * This program/include file is free software; you can redistribute it and/or |
@@ -78,6 +78,11 @@ extern runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol, | |||
78 | 78 | ||
79 | extern LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn); | 79 | extern LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn); |
80 | 80 | ||
81 | #ifdef NTFS_RW | ||
82 | |||
83 | extern runlist_element *ntfs_rl_find_vcn_nolock(runlist_element *rl, | ||
84 | const VCN vcn); | ||
85 | |||
81 | extern int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol, | 86 | extern int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol, |
82 | const runlist_element *rl, const VCN start_vcn); | 87 | const runlist_element *rl, const VCN start_vcn); |
83 | 88 | ||
@@ -88,4 +93,6 @@ extern int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst, | |||
88 | extern int ntfs_rl_truncate_nolock(const ntfs_volume *vol, | 93 | extern int ntfs_rl_truncate_nolock(const ntfs_volume *vol, |
89 | runlist *const runlist, const s64 new_length); | 94 | runlist *const runlist, const s64 new_length); |
90 | 95 | ||
96 | #endif /* NTFS_RW */ | ||
97 | |||
91 | #endif /* _LINUX_NTFS_RUNLIST_H */ | 98 | #endif /* _LINUX_NTFS_RUNLIST_H */ |