aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ntfs/lcnalloc.c
diff options
context:
space:
mode:
authorAnton Altaparmakov <aia21@cantab.net>2005-10-04 09:24:21 -0400
committerAnton Altaparmakov <aia21@cantab.net>2005-10-04 09:24:21 -0400
commit511bea5ea2b2b330e67c9e58ffb5027caebf9052 (patch)
tree142b89f44ebb15f2db326a246e0eb6c454ade6e7 /fs/ntfs/lcnalloc.c
parent69b41e3c0223bd38cf23e3d8f1385963089fbf22 (diff)
NTFS: - Change {__,}ntfs_cluster_free() to also take an optional attribute
search context as argument. This allows calling it with the mft record mapped. Update all callers. - Fix potential deadlock in ntfs_mft_data_extend_allocation_nolock() error handling by passing in the active search context when calling ntfs_cluster_free(). Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Diffstat (limited to 'fs/ntfs/lcnalloc.c')
-rw-r--r--fs/ntfs/lcnalloc.c41
1 files changed, 35 insertions, 6 deletions
diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c
index 8e60c47fafac..75313f4307e3 100644
--- a/fs/ntfs/lcnalloc.c
+++ b/fs/ntfs/lcnalloc.c
@@ -782,6 +782,7 @@ out:
782 * @ni: ntfs inode whose runlist describes the clusters to free 782 * @ni: ntfs inode whose runlist describes the clusters to free
783 * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters 783 * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters
784 * @count: number of clusters to free or -1 for all clusters 784 * @count: number of clusters to free or -1 for all clusters
785 * @ctx: active attribute search context if present or NULL if not
785 * @is_rollback: true if this is a rollback operation 786 * @is_rollback: true if this is a rollback operation
786 * 787 *
787 * 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
@@ -791,15 +792,39 @@ out:
791 * deallocated. Thus, to completely free all clusters in a runlist, use 792 * deallocated. Thus, to completely free all clusters in a runlist, use
792 * @start_vcn = 0 and @count = -1. 793 * @start_vcn = 0 and @count = -1.
793 * 794 *
795 * If @ctx is specified, it is an active search context of @ni and its base mft
796 * record. This is needed when __ntfs_cluster_free() encounters unmapped
797 * runlist fragments and allows their mapping. If you do not have the mft
798 * record mapped, you can specify @ctx as NULL and __ntfs_cluster_free() will
799 * perform the necessary mapping and unmapping.
800 *
801 * Note, __ntfs_cluster_free() saves the state of @ctx on entry and restores it
802 * before returning. Thus, @ctx will be left pointing to the same attribute on
803 * return as on entry. However, the actual pointers in @ctx may point to
804 * different memory locations on return, so you must remember to reset any
805 * cached pointers from the @ctx, i.e. after the call to __ntfs_cluster_free(),
806 * you will probably want to do:
807 * m = ctx->mrec;
808 * a = ctx->attr;
809 * Assuming you cache ctx->attr in a variable @a of type ATTR_RECORD * and that
810 * you cache ctx->mrec in a variable @m of type MFT_RECORD *.
811 *
794 * @is_rollback should always be FALSE, it is for internal use to rollback 812 * @is_rollback should always be FALSE, it is for internal use to rollback
795 * errors. You probably want to use ntfs_cluster_free() instead. 813 * errors. You probably want to use ntfs_cluster_free() instead.
796 * 814 *
797 * Note, ntfs_cluster_free() does not modify the runlist at all, so the caller 815 * Note, __ntfs_cluster_free() does not modify the runlist, so you have to
798 * has to deal with it later. 816 * remove from the runlist or mark sparse the freed runs later.
799 * 817 *
800 * Return the number of deallocated clusters (not counting sparse ones) on 818 * Return the number of deallocated clusters (not counting sparse ones) on
801 * success and -errno on error. 819 * success and -errno on error.
802 * 820 *
821 * WARNING: If @ctx is supplied, regardless of whether success or failure is
822 * returned, you need to check IS_ERR(@ctx->mrec) and if TRUE the @ctx
823 * is no longer valid, i.e. you need to either call
824 * ntfs_attr_reinit_search_ctx() or ntfs_attr_put_search_ctx() on it.
825 * In that case PTR_ERR(@ctx->mrec) will give you the error code for
826 * why the mapping of the old inode failed.
827 *
803 * Locking: - The runlist described by @ni must be locked for writing on entry 828 * Locking: - The runlist described by @ni must be locked for writing on entry
804 * and is locked on return. Note the runlist may be modified when 829 * and is locked on return. Note the runlist may be modified when
805 * needed runlist fragments need to be mapped. 830 * needed runlist fragments need to be mapped.
@@ -807,9 +832,13 @@ out:
807 * on return. 832 * on return.
808 * - This function takes the volume lcn bitmap lock for writing and 833 * - This function takes the volume lcn bitmap lock for writing and
809 * modifies the bitmap contents. 834 * modifies the bitmap contents.
835 * - If @ctx is NULL, the base mft record of @ni must not be mapped on
836 * entry and it will be left unmapped on return.
837 * - If @ctx is not NULL, the base mft record must be mapped on entry
838 * and it will be left mapped on return.
810 */ 839 */
811s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count, 840s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count,
812 const BOOL is_rollback) 841 ntfs_attr_search_ctx *ctx, const BOOL is_rollback)
813{ 842{
814 s64 delta, to_free, total_freed, real_freed; 843 s64 delta, to_free, total_freed, real_freed;
815 ntfs_volume *vol; 844 ntfs_volume *vol;
@@ -839,7 +868,7 @@ s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count,
839 868
840 total_freed = real_freed = 0; 869 total_freed = real_freed = 0;
841 870
842 rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, NULL); 871 rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, ctx);
843 if (IS_ERR(rl)) { 872 if (IS_ERR(rl)) {
844 if (!is_rollback) 873 if (!is_rollback)
845 ntfs_error(vol->sb, "Failed to find first runlist " 874 ntfs_error(vol->sb, "Failed to find first runlist "
@@ -893,7 +922,7 @@ s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count,
893 922
894 /* Attempt to map runlist. */ 923 /* Attempt to map runlist. */
895 vcn = rl->vcn; 924 vcn = rl->vcn;
896 rl = ntfs_attr_find_vcn_nolock(ni, vcn, NULL); 925 rl = ntfs_attr_find_vcn_nolock(ni, vcn, ctx);
897 if (IS_ERR(rl)) { 926 if (IS_ERR(rl)) {
898 err = PTR_ERR(rl); 927 err = PTR_ERR(rl);
899 if (!is_rollback) 928 if (!is_rollback)
@@ -961,7 +990,7 @@ err_out:
961 * If rollback fails, set the volume errors flag, emit an error 990 * If rollback fails, set the volume errors flag, emit an error
962 * message, and return the error code. 991 * message, and return the error code.
963 */ 992 */
964 delta = __ntfs_cluster_free(ni, start_vcn, total_freed, TRUE); 993 delta = __ntfs_cluster_free(ni, start_vcn, total_freed, ctx, TRUE);
965 if (delta < 0) { 994 if (delta < 0) {
966 ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving " 995 ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving "
967 "inconsistent metadata! Unmount and run " 996 "inconsistent metadata! Unmount and run "