📄 super.c
字号:
/* Switch from mft zone to data1 zone. */switch_to_data1_zone: search_zone = 2; zone_start = initial_location = vol->data1_zone_pos; zone_end = vol->nr_clusters; if (zone_start == vol->mft_zone_end) pass = 2; if (zone_start >= zone_end) { vol->data1_zone_pos = zone_start = vol->mft_zone_end; pass = 2; } break; case 2: ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): " "Switching from data1 zone to " "data2 zone.\n"); /* Update data1 zone position. */ if (rlpos) { ntfs_cluster_t tc; ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Before checks, " "vol->data1_zone_pos = " "0x%x.\n", vol->data1_zone_pos); tc = rl2[rlpos - 1].lcn + rl2[rlpos - 1].len; if (tc >= vol->nr_clusters) vol->data1_zone_pos = vol->mft_zone_end; else if ((initial_location >= vol->data1_zone_pos || tc > vol->data1_zone_pos) && tc >= vol->mft_zone_end) vol->data1_zone_pos = tc; ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): After checks, " "vol->data1_zone_pos = " "0x%x.\n", vol->data1_zone_pos); } /* Switch from data1 zone to data2 zone. */ search_zone = 4; zone_start = initial_location = vol->data2_zone_pos; zone_end = vol->mft_zone_start; if (!zone_start) pass = 2; if (zone_start >= zone_end) { vol->data2_zone_pos = zone_start = initial_location = (ntfs_cluster_t)0; pass = 2; } break; case 4: ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): " "Switching from data2 zone to " "data1 zone.\n"); /* Update data2 zone position. */ if (rlpos) { ntfs_cluster_t tc; ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Before checks, " "vol->data2_zone_pos = " "0x%x.\n", vol->data2_zone_pos); tc = rl2[rlpos - 1].lcn + rl2[rlpos - 1].len; if (tc >= vol->mft_zone_start) vol->data2_zone_pos = (ntfs_cluster_t)0; else if (initial_location >= vol->data2_zone_pos || tc > vol->data2_zone_pos) vol->data2_zone_pos = tc; ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): After checks, " "vol->data2_zone_pos = " "0x%x.\n", vol->data2_zone_pos); } /* Switch from data2 zone to data1 zone. */ goto switch_to_data1_zone; /* See above. */ default: BUG(); } ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): After zone " "switch, search_zone = %i, pass = %i, " "initial_location = 0x%x, zone_start " "= 0x%x, zone_end = 0x%x.\n", search_zone, pass, initial_location, zone_start, zone_end); buf_pos = zone_start; if (zone_start == zone_end) { ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): " "Empty zone, going to " "done_zones_check.\n"); /* Empty zone. Don't bother searching it. */ goto done_zones_check; } ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Continuing " "outer while loop.\n"); continue; } /* done_zones == 7 */ ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): All zones are " "finished.\n"); /* * All zones are finished! If DATA_ZONE, shrink mft zone. If * MFT_ZONE, we have really run out of space. */ mft_zone_size = vol->mft_zone_end - vol->mft_zone_start; ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): vol->mft_zone_start " "= 0x%x, vol->mft_zone_end = 0x%x, " "mft_zone_size = 0x%x.\n", vol->mft_zone_start, vol->mft_zone_end, mft_zone_size); if (zone == MFT_ZONE || mft_zone_size <= (ntfs_cluster_t)0) { ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): No free " "clusters left, returning -ENOSPC, " "going to fail_ret.\n"); /* Really no more space left on device. */ err = -ENOSPC; goto fail_ret; } /* zone == DATA_ZONE && mft_zone_size > 0 */ ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Shrinking mft " "zone.\n"); zone_end = vol->mft_zone_end; mft_zone_size >>= 1; if (mft_zone_size > (ntfs_cluster_t)0) vol->mft_zone_end = vol->mft_zone_start + mft_zone_size; else /* mft zone and data2 zone no longer exist. */ vol->data2_zone_pos = vol->mft_zone_start = vol->mft_zone_end = (ntfs_cluster_t)0; if (vol->mft_zone_pos >= vol->mft_zone_end) { vol->mft_zone_pos = vol->mft_lcn; if (!vol->mft_zone_end) vol->mft_zone_pos = (ntfs_cluster_t)0; } buf_pos = zone_start = initial_location = vol->data1_zone_pos = vol->mft_zone_end; search_zone = 2; pass = 2; done_zones &= ~2; ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): After shrinking mft " "zone, mft_zone_size = 0x%x, " "vol->mft_zone_start = 0x%x, vol->mft_zone_end " "= 0x%x, vol->mft_zone_pos = 0x%x, search_zone " "= 2, pass = 2, dones_zones = 0x%x, zone_start " "= 0x%x, zone_end = 0x%x, vol->data1_zone_pos " "= 0x%x, continuing outer while loop.\n", mft_zone_size, vol->mft_zone_start, vol->mft_zone_end, vol->mft_zone_pos, search_zone, pass, done_zones, zone_start, zone_end, vol->data1_zone_pos); } ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): After outer while loop.\n");done_ret: ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): At done_ret.\n"); rl2[rlpos].lcn = (ntfs_cluster_t)-1; rl2[rlpos].len = (ntfs_cluster_t)0; *rl = rl2; *rl_len = rlpos; if (need_writeback) { ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Writing back.\n"); need_writeback = 0; io.param = buf; io.do_read = 0; err = ntfs_readwrite_attr(vol->bitmap, data, last_read_pos, &io); if (err) { ntfs_error(__FUNCTION__ "(): Bitmap writeback failed " "in done code path with error code " "%i.\n", -err); goto err_ret; } ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Wrote 0x%Lx bytes.\n", io.size); }done_fail_ret: ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): At done_fail_ret (follows " "done_ret).\n"); unlock_kernel(); free_page((unsigned long)buf); if (err) ntfs_debug(DEBUG_FILE3, __FUNCTION__ "(): Failed to allocate " "clusters. Returning with error code %i.\n", -err); ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Syncing $Bitmap inode.\n"); if (ntfs_update_inode(vol->bitmap)) ntfs_error(__FUNCTION__ "(): Failed to sync inode $Bitmap. " "Continuing anyway.\n"); ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Returning with code %i.\n", err); return err;fail_ret: ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): At fail_ret.\n"); if (rl2) { if (err == -ENOSPC) { /* Return first free lcn and count of free clusters. */ *location = rl2[0].lcn; *count -= clusters; ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): err = " "-ENOSPC, *location = 0x%x, *count = " "0x%x.\n", *location, *count); } /* Deallocate all allocated clusters. */ ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Deallocating " "allocated clusters.\n"); ntfs_deallocate_clusters(vol, rl2, rlpos); /* Free the runlist. */ ntfs_vfree(rl2); } else { if (err == -ENOSPC) { /* Nothing free at all. */ *location = vol->data1_zone_pos; /* Irrelevant... */ *count = 0; ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): No space " "left at all, err = -ENOSPC, *location " "= 0x%x, *count = 0.\n", *location); } } *rl = NULL; *rl_len = 0; ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): *rl = NULL, *rl_len = 0, " "going to done_fail_ret.\n"); goto done_fail_ret;wb_err_ret: ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): At wb_err_ret.\n"); if (need_writeback) { int __err; ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Writing back.\n"); io.param = buf; io.do_read = 0; __err = ntfs_readwrite_attr(vol->bitmap, data, last_read_pos, &io); if (__err) ntfs_error(__FUNCTION__ "(): Bitmap writeback failed " "in error code path with error code " "%i.\n", -__err); need_writeback = 0; }err_ret: ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): At err_ret, *location = -1, " "*count = 0, going to fail_ret.\n"); *location = -1; *count = 0; goto fail_ret;}/* * IMPORTANT: Caller has to hold big kernel lock or the race monster will come * to get you! (-; * TODO: Need our own lock for bitmap accesses but BKL is more secure for now, * considering we might not have covered all places with a lock yet. In that * case the BKL offers a one way exclusion which is better than no exclusion * at all... (AIA) */static int ntfs_clear_bitrange(ntfs_inode *bitmap, const ntfs_cluster_t start_bit, const ntfs_cluster_t count){ ntfs_cluster_t buf_size, bit, nr_bits = count; unsigned char *buf, *byte; int err; ntfs_io io; io.fn_put = ntfs_put; io.fn_get = ntfs_get; /* Calculate the required buffer size in bytes. */ buf_size = (ntfs_cluster_t)((start_bit & 7) + nr_bits + 7) >> 3; if (buf_size <= (ntfs_cluster_t)(64 * 1024)) buf = ntfs_malloc(buf_size); else buf = ntfs_vmalloc(buf_size); if (!buf) return -ENOMEM; /* Read the bitmap from the data attribute. */ io.param = byte = buf; io.size = buf_size; err = ntfs_read_attr(bitmap, bitmap->vol->at_data, 0, start_bit >> 3, &io); if (err || io.size != buf_size) goto err_out; /* Now clear the bits in the read bitmap. */ bit = start_bit & 7; while (bit && nr_bits) { /* Process first partial byte, if present. */ *byte &= ~(1 << bit++); nr_bits--; bit &= 7; if (!bit) byte++; } while (nr_bits >= 8) { /* Process full bytes. */ *byte = 0; nr_bits -= 8; byte++; } bit = 0; while (nr_bits) { /* Process last partial byte, if present. */ *byte &= ~(1 << bit); nr_bits--; bit++; } /* Write the modified bitmap back to disk. */ io.param = buf; io.size = buf_size; err = ntfs_write_attr(bitmap, bitmap->vol->at_data, 0, start_bit >> 3, &io);err_out: if (buf_size <= (ntfs_cluster_t)(64 * 1024)) ntfs_free(buf); else ntfs_vfree(buf); if (!err && io.size != buf_size) err = -EIO; return err;}/* * See comments for lack of zone adjustments below in the description of the * function ntfs_deallocate_clusters(). */int ntfs_deallocate_cluster_run(const ntfs_volume *vol, const ntfs_cluster_t lcn, const ntfs_cluster_t len){ int err; lock_kernel(); err = ntfs_clear_bitrange(vol->bitmap, lcn, len); unlock_kernel(); return err;}/* * This is inefficient, but logically trivial, so will do for now. Note, we * do not touch the mft nor the data zones here because we want to minimize * recycling of clusters to enhance the chances of data being undeleteable. * Also we don't want the overhead. Instead we do one additional sweep of the * current data zone during cluster allocation to check for freed clusters. */int ntfs_deallocate_clusters(const ntfs_volume *vol, const ntfs_runlist *rl, const int rl_len){ int i, err; lock_kernel(); for (i = err = 0; i < rl_len && !err; i++) err = ntfs_clear_bitrange(vol->bitmap, rl[i].lcn, rl[i].len); unlock_kernel(); return err;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -