diff options
Diffstat (limited to 'fs/ntfs/lcnalloc.c')
-rw-r--r-- | fs/ntfs/lcnalloc.c | 72 |
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; |
975 | unl_err_out: | ||
976 | up_read(&ni->runlist.lock); | ||
977 | err_out: | 962 | err_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. */ |