aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ntfs/lcnalloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ntfs/lcnalloc.c')
-rw-r--r--fs/ntfs/lcnalloc.c103
1 files changed, 41 insertions, 62 deletions
diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c
index 23fd911078b1..7b5934290685 100644
--- a/fs/ntfs/lcnalloc.c
+++ b/fs/ntfs/lcnalloc.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * lcnalloc.c - Cluster (de)allocation code. Part of the Linux-NTFS project. 2 * lcnalloc.c - Cluster (de)allocation code. Part of the Linux-NTFS project.
3 * 3 *
4 * Copyright (c) 2004 Anton Altaparmakov 4 * Copyright (c) 2004-2005 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
@@ -54,13 +54,15 @@ int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
54 int ret = 0; 54 int ret = 0;
55 55
56 ntfs_debug("Entering."); 56 ntfs_debug("Entering.");
57 if (!rl)
58 return 0;
57 for (; rl->length; rl++) { 59 for (; rl->length; rl++) {
58 int err; 60 int err;
59 61
60 if (rl->lcn < 0) 62 if (rl->lcn < 0)
61 continue; 63 continue;
62 err = ntfs_bitmap_clear_run(lcnbmp_vi, rl->lcn, rl->length); 64 err = ntfs_bitmap_clear_run(lcnbmp_vi, rl->lcn, rl->length);
63 if (unlikely(err && (!ret || ret == ENOMEM) && ret != err)) 65 if (unlikely(err && (!ret || ret == -ENOMEM) && ret != err))
64 ret = err; 66 ret = err;
65 } 67 }
66 ntfs_debug("Done."); 68 ntfs_debug("Done.");
@@ -140,6 +142,7 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
140 LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn; 142 LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn;
141 LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size; 143 LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size;
142 s64 clusters; 144 s64 clusters;
145 loff_t i_size;
143 struct inode *lcnbmp_vi; 146 struct inode *lcnbmp_vi;
144 runlist_element *rl = NULL; 147 runlist_element *rl = NULL;
145 struct address_space *mapping; 148 struct address_space *mapping;
@@ -162,17 +165,9 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
162 BUG_ON(zone < FIRST_ZONE); 165 BUG_ON(zone < FIRST_ZONE);
163 BUG_ON(zone > LAST_ZONE); 166 BUG_ON(zone > LAST_ZONE);
164 167
165 /* Return empty runlist if @count == 0 */ 168 /* Return NULL if @count is zero. */
166 // FIXME: Do we want to just return NULL instead? (AIA) 169 if (!count)
167 if (!count) { 170 return NULL;
168 rl = ntfs_malloc_nofs(PAGE_SIZE);
169 if (!rl)
170 return ERR_PTR(-ENOMEM);
171 rl[0].vcn = start_vcn;
172 rl[0].lcn = LCN_RL_NOT_MAPPED;
173 rl[0].length = 0;
174 return rl;
175 }
176 /* Take the lcnbmp lock for writing. */ 171 /* Take the lcnbmp lock for writing. */
177 down_write(&vol->lcnbmp_lock); 172 down_write(&vol->lcnbmp_lock);
178 /* 173 /*
@@ -249,6 +244,7 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
249 clusters = count; 244 clusters = count;
250 rlpos = rlsize = 0; 245 rlpos = rlsize = 0;
251 mapping = lcnbmp_vi->i_mapping; 246 mapping = lcnbmp_vi->i_mapping;
247 i_size = i_size_read(lcnbmp_vi);
252 while (1) { 248 while (1) {
253 ntfs_debug("Start of outer while loop: done_zones 0x%x, " 249 ntfs_debug("Start of outer while loop: done_zones 0x%x, "
254 "search_zone %i, pass %i, zone_start 0x%llx, " 250 "search_zone %i, pass %i, zone_start 0x%llx, "
@@ -263,7 +259,7 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
263 last_read_pos = bmp_pos >> 3; 259 last_read_pos = bmp_pos >> 3;
264 ntfs_debug("last_read_pos 0x%llx.", 260 ntfs_debug("last_read_pos 0x%llx.",
265 (unsigned long long)last_read_pos); 261 (unsigned long long)last_read_pos);
266 if (last_read_pos > lcnbmp_vi->i_size) { 262 if (last_read_pos > i_size) {
267 ntfs_debug("End of attribute reached. " 263 ntfs_debug("End of attribute reached. "
268 "Skipping to zone_pass_done."); 264 "Skipping to zone_pass_done.");
269 goto zone_pass_done; 265 goto zone_pass_done;
@@ -287,11 +283,11 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
287 buf_size = last_read_pos & ~PAGE_CACHE_MASK; 283 buf_size = last_read_pos & ~PAGE_CACHE_MASK;
288 buf = page_address(page) + buf_size; 284 buf = page_address(page) + buf_size;
289 buf_size = PAGE_CACHE_SIZE - buf_size; 285 buf_size = PAGE_CACHE_SIZE - buf_size;
290 if (unlikely(last_read_pos + buf_size > lcnbmp_vi->i_size)) 286 if (unlikely(last_read_pos + buf_size > i_size))
291 buf_size = lcnbmp_vi->i_size - last_read_pos; 287 buf_size = i_size - last_read_pos;
292 buf_size <<= 3; 288 buf_size <<= 3;
293 lcn = bmp_pos & 7; 289 lcn = bmp_pos & 7;
294 bmp_pos &= ~7; 290 bmp_pos &= ~(LCN)7;
295 ntfs_debug("Before inner while loop: buf_size %i, lcn 0x%llx, " 291 ntfs_debug("Before inner while loop: buf_size %i, lcn 0x%llx, "
296 "bmp_pos 0x%llx, need_writeback %i.", buf_size, 292 "bmp_pos 0x%llx, need_writeback %i.", buf_size,
297 (unsigned long long)lcn, 293 (unsigned long long)lcn,
@@ -309,7 +305,7 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
309 (unsigned int)*byte); 305 (unsigned int)*byte);
310 /* Skip full bytes. */ 306 /* Skip full bytes. */
311 if (*byte == 0xff) { 307 if (*byte == 0xff) {
312 lcn = (lcn + 8) & ~7; 308 lcn = (lcn + 8) & ~(LCN)7;
313 ntfs_debug("Continuing while loop 1."); 309 ntfs_debug("Continuing while loop 1.");
314 continue; 310 continue;
315 } 311 }
@@ -691,7 +687,7 @@ switch_to_data1_zone: search_zone = 2;
691 if (zone == MFT_ZONE || mft_zone_size <= 0) { 687 if (zone == MFT_ZONE || mft_zone_size <= 0) {
692 ntfs_debug("No free clusters left, going to out."); 688 ntfs_debug("No free clusters left, going to out.");
693 /* Really no more space left on device. */ 689 /* Really no more space left on device. */
694 err = ENOSPC; 690 err = -ENOSPC;
695 goto out; 691 goto out;
696 } /* zone == DATA_ZONE && mft_zone_size > 0 */ 692 } /* zone == DATA_ZONE && mft_zone_size > 0 */
697 ntfs_debug("Shrinking mft zone."); 693 ntfs_debug("Shrinking mft zone.");
@@ -755,13 +751,13 @@ out:
755 if (rl) { 751 if (rl) {
756 int err2; 752 int err2;
757 753
758 if (err == ENOSPC) 754 if (err == -ENOSPC)
759 ntfs_debug("Not enough space to complete allocation, " 755 ntfs_debug("Not enough space to complete allocation, "
760 "err ENOSPC, first free lcn 0x%llx, " 756 "err -ENOSPC, first free lcn 0x%llx, "
761 "could allocate up to 0x%llx " 757 "could allocate up to 0x%llx "
762 "clusters.", 758 "clusters.",
763 (unsigned long long)rl[0].lcn, 759 (unsigned long long)rl[0].lcn,
764 (unsigned long long)count - clusters); 760 (unsigned long long)(count - clusters));
765 /* Deallocate all allocated clusters. */ 761 /* Deallocate all allocated clusters. */
766 ntfs_debug("Attempting rollback..."); 762 ntfs_debug("Attempting rollback...");
767 err2 = ntfs_cluster_free_from_rl_nolock(vol, rl); 763 err2 = ntfs_cluster_free_from_rl_nolock(vol, rl);
@@ -773,10 +769,10 @@ out:
773 } 769 }
774 /* Free the runlist. */ 770 /* Free the runlist. */
775 ntfs_free(rl); 771 ntfs_free(rl);
776 } else if (err == ENOSPC) 772 } else if (err == -ENOSPC)
777 ntfs_debug("No space left at all, err = ENOSPC, " 773 ntfs_debug("No space left at all, err = -ENOSPC, first free "
778 "first free lcn = 0x%llx.", 774 "lcn = 0x%llx.",
779 (unsigned long long)vol->data1_zone_pos); 775 (long long)vol->data1_zone_pos);
780 up_write(&vol->lcnbmp_lock); 776 up_write(&vol->lcnbmp_lock);
781 return ERR_PTR(err); 777 return ERR_PTR(err);
782} 778}
@@ -786,7 +782,8 @@ out:
786 * @vi: vfs inode whose runlist describes the clusters to free 782 * @vi: vfs inode whose runlist describes the clusters to free
787 * @start_vcn: vcn in the runlist of @vi at which to start freeing clusters 783 * @start_vcn: vcn in the runlist of @vi at which to start freeing clusters
788 * @count: number of clusters to free or -1 for all clusters 784 * @count: number of clusters to free or -1 for all clusters
789 * @is_rollback: if TRUE this is a rollback operation 785 * @write_locked: true if the runlist is locked for writing
786 * @is_rollback: true if this is a rollback operation
790 * 787 *
791 * Free @count clusters starting at the cluster @start_vcn in the runlist 788 * Free @count clusters starting at the cluster @start_vcn in the runlist
792 * described by the vfs inode @vi. 789 * described by the vfs inode @vi.
@@ -804,17 +801,17 @@ out:
804 * Return the number of deallocated clusters (not counting sparse ones) on 801 * Return the number of deallocated clusters (not counting sparse ones) on
805 * success and -errno on error. 802 * success and -errno on error.
806 * 803 *
807 * Locking: - The runlist described by @vi must be unlocked on entry and is 804 * Locking: - The runlist described by @vi must be locked on entry and is
808 * unlocked on return. 805 * locked on return. Note if the runlist is locked for reading the
809 * - This function takes the runlist lock of @vi for reading and 806 * lock may be dropped and reacquired. Note the runlist may be
810 * sometimes for writing and sometimes modifies the runlist. 807 * modified when needed runlist fragments need to be mapped.
811 * - The volume lcn bitmap must be unlocked on entry and is unlocked 808 * - The volume lcn bitmap must be unlocked on entry and is unlocked
812 * on return. 809 * on return.
813 * - This function takes the volume lcn bitmap lock for writing and 810 * - This function takes the volume lcn bitmap lock for writing and
814 * modifies the bitmap contents. 811 * modifies the bitmap contents.
815 */ 812 */
816s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count, 813s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
817 const BOOL is_rollback) 814 const BOOL write_locked, const BOOL is_rollback)
818{ 815{
819 s64 delta, to_free, total_freed, real_freed; 816 s64 delta, to_free, total_freed, real_freed;
820 ntfs_inode *ni; 817 ntfs_inode *ni;
@@ -846,8 +843,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
846 843
847 total_freed = real_freed = 0; 844 total_freed = real_freed = 0;
848 845
849 /* This returns with ni->runlist locked for reading on success. */ 846 rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, write_locked);
850 rl = ntfs_find_vcn(ni, start_vcn, FALSE);
851 if (IS_ERR(rl)) { 847 if (IS_ERR(rl)) {
852 if (!is_rollback) 848 if (!is_rollback)
853 ntfs_error(vol->sb, "Failed to find first runlist " 849 ntfs_error(vol->sb, "Failed to find first runlist "
@@ -861,7 +857,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
861 ntfs_error(vol->sb, "First runlist element has " 857 ntfs_error(vol->sb, "First runlist element has "
862 "invalid lcn, aborting."); 858 "invalid lcn, aborting.");
863 err = -EIO; 859 err = -EIO;
864 goto unl_err_out; 860 goto err_out;
865 } 861 }
866 /* Find the starting cluster inside the run that needs freeing. */ 862 /* Find the starting cluster inside the run that needs freeing. */
867 delta = start_vcn - rl->vcn; 863 delta = start_vcn - rl->vcn;
@@ -879,7 +875,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
879 if (!is_rollback) 875 if (!is_rollback)
880 ntfs_error(vol->sb, "Failed to clear first run " 876 ntfs_error(vol->sb, "Failed to clear first run "
881 "(error %i), aborting.", err); 877 "(error %i), aborting.", err);
882 goto unl_err_out; 878 goto err_out;
883 } 879 }
884 /* We have freed @to_free real clusters. */ 880 /* We have freed @to_free real clusters. */
885 real_freed = to_free; 881 real_freed = to_free;
@@ -899,30 +895,15 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
899 if (unlikely(rl->lcn < LCN_HOLE)) { 895 if (unlikely(rl->lcn < LCN_HOLE)) {
900 VCN vcn; 896 VCN vcn;
901 897
902 /* 898 /* Attempt to map runlist. */
903 * Attempt to map runlist, dropping runlist lock for
904 * the duration.
905 */
906 vcn = rl->vcn; 899 vcn = rl->vcn;
907 up_read(&ni->runlist.lock); 900 rl = ntfs_attr_find_vcn_nolock(ni, vcn, write_locked);
908 err = ntfs_map_runlist(ni, vcn);
909 if (err) {
910 if (!is_rollback)
911 ntfs_error(vol->sb, "Failed to map "
912 "runlist fragment.");
913 if (err == -EINVAL || err == -ENOENT)
914 err = -EIO;
915 goto err_out;
916 }
917 /*
918 * This returns with ni->runlist locked for reading on
919 * success.
920 */
921 rl = ntfs_find_vcn(ni, vcn, FALSE);
922 if (IS_ERR(rl)) { 901 if (IS_ERR(rl)) {
923 err = PTR_ERR(rl); 902 err = PTR_ERR(rl);
924 if (!is_rollback) 903 if (!is_rollback)
925 ntfs_error(vol->sb, "Failed to find " 904 ntfs_error(vol->sb, "Failed to map "
905 "runlist fragment or "
906 "failed to find "
926 "subsequent runlist " 907 "subsequent runlist "
927 "element."); 908 "element.");
928 goto err_out; 909 goto err_out;
@@ -935,7 +916,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
935 (unsigned long long) 916 (unsigned long long)
936 rl->lcn); 917 rl->lcn);
937 err = -EIO; 918 err = -EIO;
938 goto unl_err_out; 919 goto err_out;
939 } 920 }
940 } 921 }
941 /* The number of clusters in this run that need freeing. */ 922 /* The number of clusters in this run that need freeing. */
@@ -951,7 +932,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
951 if (!is_rollback) 932 if (!is_rollback)
952 ntfs_error(vol->sb, "Failed to clear " 933 ntfs_error(vol->sb, "Failed to clear "
953 "subsequent run."); 934 "subsequent run.");
954 goto unl_err_out; 935 goto err_out;
955 } 936 }
956 /* We have freed @to_free real clusters. */ 937 /* We have freed @to_free real clusters. */
957 real_freed += to_free; 938 real_freed += to_free;
@@ -963,7 +944,6 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
963 /* Update the total done clusters. */ 944 /* Update the total done clusters. */
964 total_freed += to_free; 945 total_freed += to_free;
965 } 946 }
966 up_read(&ni->runlist.lock);
967 if (likely(!is_rollback)) 947 if (likely(!is_rollback))
968 up_write(&vol->lcnbmp_lock); 948 up_write(&vol->lcnbmp_lock);
969 949
@@ -972,8 +952,6 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
972 /* We are done. Return the number of actually freed clusters. */ 952 /* We are done. Return the number of actually freed clusters. */
973 ntfs_debug("Done."); 953 ntfs_debug("Done.");
974 return real_freed; 954 return real_freed;
975unl_err_out:
976 up_read(&ni->runlist.lock);
977err_out: 955err_out:
978 if (is_rollback) 956 if (is_rollback)
979 return err; 957 return err;
@@ -987,7 +965,8 @@ err_out:
987 * If rollback fails, set the volume errors flag, emit an error 965 * If rollback fails, set the volume errors flag, emit an error
988 * message, and return the error code. 966 * message, and return the error code.
989 */ 967 */
990 delta = __ntfs_cluster_free(vi, start_vcn, total_freed, TRUE); 968 delta = __ntfs_cluster_free(vi, start_vcn, total_freed, write_locked,
969 TRUE);
991 if (delta < 0) { 970 if (delta < 0) {
992 ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving " 971 ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving "
993 "inconsistent metadata! Unmount and run " 972 "inconsistent metadata! Unmount and run "