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. */ |
