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.c72
1 files changed, 29 insertions, 43 deletions
diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c
index 23fd911078b1..a4bc07616e5d 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
@@ -60,7 +60,7 @@ int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
60 if (rl->lcn < 0) 60 if (rl->lcn < 0)
61 continue; 61 continue;
62 err = ntfs_bitmap_clear_run(lcnbmp_vi, rl->lcn, rl->length); 62 err = ntfs_bitmap_clear_run(lcnbmp_vi, rl->lcn, rl->length);
63 if (unlikely(err && (!ret || ret == ENOMEM) && ret != err)) 63 if (unlikely(err && (!ret || ret == -ENOMEM) && ret != err))
64 ret = err; 64 ret = err;
65 } 65 }
66 ntfs_debug("Done."); 66 ntfs_debug("Done.");
@@ -140,6 +140,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; 140 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; 141 LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size;
142 s64 clusters; 142 s64 clusters;
143 loff_t i_size;
143 struct inode *lcnbmp_vi; 144 struct inode *lcnbmp_vi;
144 runlist_element *rl = NULL; 145 runlist_element *rl = NULL;
145 struct address_space *mapping; 146 struct address_space *mapping;
@@ -249,6 +250,7 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
249 clusters = count; 250 clusters = count;
250 rlpos = rlsize = 0; 251 rlpos = rlsize = 0;
251 mapping = lcnbmp_vi->i_mapping; 252 mapping = lcnbmp_vi->i_mapping;
253 i_size = i_size_read(lcnbmp_vi);
252 while (1) { 254 while (1) {
253 ntfs_debug("Start of outer while loop: done_zones 0x%x, " 255 ntfs_debug("Start of outer while loop: done_zones 0x%x, "
254 "search_zone %i, pass %i, zone_start 0x%llx, " 256 "search_zone %i, pass %i, zone_start 0x%llx, "
@@ -263,7 +265,7 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
263 last_read_pos = bmp_pos >> 3; 265 last_read_pos = bmp_pos >> 3;
264 ntfs_debug("last_read_pos 0x%llx.", 266 ntfs_debug("last_read_pos 0x%llx.",
265 (unsigned long long)last_read_pos); 267 (unsigned long long)last_read_pos);
266 if (last_read_pos > lcnbmp_vi->i_size) { 268 if (last_read_pos > i_size) {
267 ntfs_debug("End of attribute reached. " 269 ntfs_debug("End of attribute reached. "
268 "Skipping to zone_pass_done."); 270 "Skipping to zone_pass_done.");
269 goto zone_pass_done; 271 goto zone_pass_done;
@@ -287,11 +289,11 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
287 buf_size = last_read_pos & ~PAGE_CACHE_MASK; 289 buf_size = last_read_pos & ~PAGE_CACHE_MASK;
288 buf = page_address(page) + buf_size; 290 buf = page_address(page) + buf_size;
289 buf_size = PAGE_CACHE_SIZE - buf_size; 291 buf_size = PAGE_CACHE_SIZE - buf_size;
290 if (unlikely(last_read_pos + buf_size > lcnbmp_vi->i_size)) 292 if (unlikely(last_read_pos + buf_size > i_size))
291 buf_size = lcnbmp_vi->i_size - last_read_pos; 293 buf_size = i_size - last_read_pos;
292 buf_size <<= 3; 294 buf_size <<= 3;
293 lcn = bmp_pos & 7; 295 lcn = bmp_pos & 7;
294 bmp_pos &= ~7; 296 bmp_pos &= ~(LCN)7;
295 ntfs_debug("Before inner while loop: buf_size %i, lcn 0x%llx, " 297 ntfs_debug("Before inner while loop: buf_size %i, lcn 0x%llx, "
296 "bmp_pos 0x%llx, need_writeback %i.", buf_size, 298 "bmp_pos 0x%llx, need_writeback %i.", buf_size,
297 (unsigned long long)lcn, 299 (unsigned long long)lcn,
@@ -309,7 +311,7 @@ runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
309 (unsigned int)*byte); 311 (unsigned int)*byte);
310 /* Skip full bytes. */ 312 /* Skip full bytes. */
311 if (*byte == 0xff) { 313 if (*byte == 0xff) {
312 lcn = (lcn + 8) & ~7; 314 lcn = (lcn + 8) & ~(LCN)7;
313 ntfs_debug("Continuing while loop 1."); 315 ntfs_debug("Continuing while loop 1.");
314 continue; 316 continue;
315 } 317 }
@@ -691,7 +693,7 @@ switch_to_data1_zone: search_zone = 2;
691 if (zone == MFT_ZONE || mft_zone_size <= 0) { 693 if (zone == MFT_ZONE || mft_zone_size <= 0) {
692 ntfs_debug("No free clusters left, going to out."); 694 ntfs_debug("No free clusters left, going to out.");
693 /* Really no more space left on device. */ 695 /* Really no more space left on device. */
694 err = ENOSPC; 696 err = -ENOSPC;
695 goto out; 697 goto out;
696 } /* zone == DATA_ZONE && mft_zone_size > 0 */ 698 } /* zone == DATA_ZONE && mft_zone_size > 0 */
697 ntfs_debug("Shrinking mft zone."); 699 ntfs_debug("Shrinking mft zone.");
@@ -755,13 +757,13 @@ out:
755 if (rl) { 757 if (rl) {
756 int err2; 758 int err2;
757 759
758 if (err == ENOSPC) 760 if (err == -ENOSPC)
759 ntfs_debug("Not enough space to complete allocation, " 761 ntfs_debug("Not enough space to complete allocation, "
760 "err ENOSPC, first free lcn 0x%llx, " 762 "err -ENOSPC, first free lcn 0x%llx, "
761 "could allocate up to 0x%llx " 763 "could allocate up to 0x%llx "
762 "clusters.", 764 "clusters.",
763 (unsigned long long)rl[0].lcn, 765 (unsigned long long)rl[0].lcn,
764 (unsigned long long)count - clusters); 766 (unsigned long long)(count - clusters));
765 /* Deallocate all allocated clusters. */ 767 /* Deallocate all allocated clusters. */
766 ntfs_debug("Attempting rollback..."); 768 ntfs_debug("Attempting rollback...");
767 err2 = ntfs_cluster_free_from_rl_nolock(vol, rl); 769 err2 = ntfs_cluster_free_from_rl_nolock(vol, rl);
@@ -773,10 +775,10 @@ out:
773 } 775 }
774 /* Free the runlist. */ 776 /* Free the runlist. */
775 ntfs_free(rl); 777 ntfs_free(rl);
776 } else if (err == ENOSPC) 778 } else if (err == -ENOSPC)
777 ntfs_debug("No space left at all, err = ENOSPC, " 779 ntfs_debug("No space left at all, err = -ENOSPC, first free "
778 "first free lcn = 0x%llx.", 780 "lcn = 0x%llx.",
779 (unsigned long long)vol->data1_zone_pos); 781 (long long)vol->data1_zone_pos);
780 up_write(&vol->lcnbmp_lock); 782 up_write(&vol->lcnbmp_lock);
781 return ERR_PTR(err); 783 return ERR_PTR(err);
782} 784}
@@ -846,8 +848,8 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
846 848
847 total_freed = real_freed = 0; 849 total_freed = real_freed = 0;
848 850
849 /* This returns with ni->runlist locked for reading on success. */ 851 down_read(&ni->runlist.lock);
850 rl = ntfs_find_vcn(ni, start_vcn, FALSE); 852 rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, FALSE);
851 if (IS_ERR(rl)) { 853 if (IS_ERR(rl)) {
852 if (!is_rollback) 854 if (!is_rollback)
853 ntfs_error(vol->sb, "Failed to find first runlist " 855 ntfs_error(vol->sb, "Failed to find first runlist "
@@ -861,7 +863,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
861 ntfs_error(vol->sb, "First runlist element has " 863 ntfs_error(vol->sb, "First runlist element has "
862 "invalid lcn, aborting."); 864 "invalid lcn, aborting.");
863 err = -EIO; 865 err = -EIO;
864 goto unl_err_out; 866 goto err_out;
865 } 867 }
866 /* Find the starting cluster inside the run that needs freeing. */ 868 /* Find the starting cluster inside the run that needs freeing. */
867 delta = start_vcn - rl->vcn; 869 delta = start_vcn - rl->vcn;
@@ -879,7 +881,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
879 if (!is_rollback) 881 if (!is_rollback)
880 ntfs_error(vol->sb, "Failed to clear first run " 882 ntfs_error(vol->sb, "Failed to clear first run "
881 "(error %i), aborting.", err); 883 "(error %i), aborting.", err);
882 goto unl_err_out; 884 goto err_out;
883 } 885 }
884 /* We have freed @to_free real clusters. */ 886 /* We have freed @to_free real clusters. */
885 real_freed = to_free; 887 real_freed = to_free;
@@ -899,30 +901,15 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
899 if (unlikely(rl->lcn < LCN_HOLE)) { 901 if (unlikely(rl->lcn < LCN_HOLE)) {
900 VCN vcn; 902 VCN vcn;
901 903
902 /* 904 /* Attempt to map runlist. */
903 * Attempt to map runlist, dropping runlist lock for
904 * the duration.
905 */
906 vcn = rl->vcn; 905 vcn = rl->vcn;
907 up_read(&ni->runlist.lock); 906 rl = ntfs_attr_find_vcn_nolock(ni, vcn, FALSE);
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)) { 907 if (IS_ERR(rl)) {
923 err = PTR_ERR(rl); 908 err = PTR_ERR(rl);
924 if (!is_rollback) 909 if (!is_rollback)
925 ntfs_error(vol->sb, "Failed to find " 910 ntfs_error(vol->sb, "Failed to map "
911 "runlist fragment or "
912 "failed to find "
926 "subsequent runlist " 913 "subsequent runlist "
927 "element."); 914 "element.");
928 goto err_out; 915 goto err_out;
@@ -935,7 +922,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
935 (unsigned long long) 922 (unsigned long long)
936 rl->lcn); 923 rl->lcn);
937 err = -EIO; 924 err = -EIO;
938 goto unl_err_out; 925 goto err_out;
939 } 926 }
940 } 927 }
941 /* The number of clusters in this run that need freeing. */ 928 /* The number of clusters in this run that need freeing. */
@@ -951,7 +938,7 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
951 if (!is_rollback) 938 if (!is_rollback)
952 ntfs_error(vol->sb, "Failed to clear " 939 ntfs_error(vol->sb, "Failed to clear "
953 "subsequent run."); 940 "subsequent run.");
954 goto unl_err_out; 941 goto err_out;
955 } 942 }
956 /* We have freed @to_free real clusters. */ 943 /* We have freed @to_free real clusters. */
957 real_freed += to_free; 944 real_freed += to_free;
@@ -972,9 +959,8 @@ s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
972 /* We are done. Return the number of actually freed clusters. */ 959 /* We are done. Return the number of actually freed clusters. */
973 ntfs_debug("Done."); 960 ntfs_debug("Done.");
974 return real_freed; 961 return real_freed;
975unl_err_out:
976 up_read(&ni->runlist.lock);
977err_out: 962err_out:
963 up_read(&ni->runlist.lock);
978 if (is_rollback) 964 if (is_rollback)
979 return err; 965 return err;
980 /* If no real clusters were freed, no need to rollback. */ 966 /* If no real clusters were freed, no need to rollback. */