super.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,070 行 · 第 1/5 页
C
2,070 行
// TODO: Delete or checkpoint the $UsnJrnl if it exists.#endif /* NTFS_RW */ return TRUE;#ifdef NTFS_RWiput_quota_err_out: if (vol->quota_q_ino) iput(vol->quota_q_ino); if (vol->quota_ino) iput(vol->quota_ino); iput(vol->extend_ino);#endif /* NTFS_RW */iput_sec_err_out: iput(vol->secure_ino);iput_root_err_out: iput(vol->root_ino);iput_logfile_err_out:#ifdef NTFS_RW if (vol->logfile_ino) iput(vol->logfile_ino);iput_vol_err_out:#endif /* NTFS_RW */ iput(vol->vol_ino);iput_lcnbmp_err_out: iput(vol->lcnbmp_ino);iput_attrdef_err_out: vol->attrdef_size = 0; if (vol->attrdef) { ntfs_free(vol->attrdef); vol->attrdef = NULL; }#ifdef NTFS_RWiput_upcase_err_out:#endif /* NTFS_RW */ vol->upcase_len = 0; down(&ntfs_lock); if (vol->upcase == default_upcase) { ntfs_nr_upcase_users--; vol->upcase = NULL; } up(&ntfs_lock); if (vol->upcase) { ntfs_free(vol->upcase); vol->upcase = NULL; }iput_mftbmp_err_out: iput(vol->mftbmp_ino);iput_mirr_err_out:#ifdef NTFS_RW if (vol->mftmirr_ino) iput(vol->mftmirr_ino);#endif /* NTFS_RW */ return FALSE;}/** * ntfs_put_super - called by the vfs to unmount a volume * @sb: vfs superblock of volume to unmount * * ntfs_put_super() is called by the VFS (from fs/super.c::do_umount()) when * the volume is being unmounted (umount system call has been invoked) and it * releases all inodes and memory belonging to the NTFS specific part of the * super block. */static void ntfs_put_super(struct super_block *sb){ ntfs_volume *vol = NTFS_SB(sb); ntfs_debug("Entering.");#ifdef NTFS_RW /* * Commit all inodes while they are still open in case some of them * cause others to be dirtied. */ ntfs_commit_inode(vol->vol_ino); /* NTFS 3.0+ specific. */ if (vol->major_ver >= 3) { if (vol->quota_q_ino) ntfs_commit_inode(vol->quota_q_ino); if (vol->quota_ino) ntfs_commit_inode(vol->quota_ino); if (vol->extend_ino) ntfs_commit_inode(vol->extend_ino); if (vol->secure_ino) ntfs_commit_inode(vol->secure_ino); } ntfs_commit_inode(vol->root_ino); down_write(&vol->lcnbmp_lock); ntfs_commit_inode(vol->lcnbmp_ino); up_write(&vol->lcnbmp_lock); down_write(&vol->mftbmp_lock); ntfs_commit_inode(vol->mftbmp_ino); up_write(&vol->mftbmp_lock); if (vol->logfile_ino) ntfs_commit_inode(vol->logfile_ino); if (vol->mftmirr_ino) ntfs_commit_inode(vol->mftmirr_ino); ntfs_commit_inode(vol->mft_ino); /* * If a read-write mount and no volume errors have occured, mark the * volume clean. Also, re-commit all affected inodes. */ if (!(sb->s_flags & MS_RDONLY)) { if (!NVolErrors(vol)) { if (ntfs_clear_volume_flags(vol, VOLUME_IS_DIRTY)) ntfs_warning(sb, "Failed to clear dirty bit " "in volume information " "flags. Run chkdsk."); ntfs_commit_inode(vol->vol_ino); ntfs_commit_inode(vol->root_ino); if (vol->mftmirr_ino) ntfs_commit_inode(vol->mftmirr_ino); ntfs_commit_inode(vol->mft_ino); } else { ntfs_warning(sb, "Volume has errors. Leaving volume " "marked dirty. Run chkdsk."); } }#endif /* NTFS_RW */ iput(vol->vol_ino); vol->vol_ino = NULL; /* NTFS 3.0+ specific clean up. */ if (vol->major_ver >= 3) {#ifdef NTFS_RW if (vol->quota_q_ino) { iput(vol->quota_q_ino); vol->quota_q_ino = NULL; } if (vol->quota_ino) { iput(vol->quota_ino); vol->quota_ino = NULL; }#endif /* NTFS_RW */ if (vol->extend_ino) { iput(vol->extend_ino); vol->extend_ino = NULL; } if (vol->secure_ino) { iput(vol->secure_ino); vol->secure_ino = NULL; } } iput(vol->root_ino); vol->root_ino = NULL; down_write(&vol->lcnbmp_lock); iput(vol->lcnbmp_ino); vol->lcnbmp_ino = NULL; up_write(&vol->lcnbmp_lock); down_write(&vol->mftbmp_lock); iput(vol->mftbmp_ino); vol->mftbmp_ino = NULL; up_write(&vol->mftbmp_lock);#ifdef NTFS_RW if (vol->logfile_ino) { iput(vol->logfile_ino); vol->logfile_ino = NULL; } if (vol->mftmirr_ino) { /* Re-commit the mft mirror and mft just in case. */ ntfs_commit_inode(vol->mftmirr_ino); ntfs_commit_inode(vol->mft_ino); iput(vol->mftmirr_ino); vol->mftmirr_ino = NULL; } /* * If any dirty inodes are left, throw away all mft data page cache * pages to allow a clean umount. This should never happen any more * due to mft.c::ntfs_mft_writepage() cleaning all the dirty pages as * the underlying mft records are written out and cleaned. If it does, * happen anyway, we want to know... */ ntfs_commit_inode(vol->mft_ino); write_inode_now(vol->mft_ino, 1); if (!list_empty(&sb->s_dirty)) { const char *s1, *s2; down(&vol->mft_ino->i_sem); truncate_inode_pages(vol->mft_ino->i_mapping, 0); up(&vol->mft_ino->i_sem); write_inode_now(vol->mft_ino, 1); if (!list_empty(&sb->s_dirty)) { static const char *_s1 = "inodes"; static const char *_s2 = ""; s1 = _s1; s2 = _s2; } else { static const char *_s1 = "mft pages"; static const char *_s2 = "They have been thrown " "away. "; s1 = _s1; s2 = _s2; } ntfs_error(sb, "Dirty %s found at umount time. %sYou should " "run chkdsk. Please email " "linux-ntfs-dev@lists.sourceforge.net and say " "that you saw this message. Thank you.", s1, s2); }#endif /* NTFS_RW */ iput(vol->mft_ino); vol->mft_ino = NULL; /* Throw away the table of attribute definitions. */ vol->attrdef_size = 0; if (vol->attrdef) { ntfs_free(vol->attrdef); vol->attrdef = NULL; } vol->upcase_len = 0; /* * Destroy the global default upcase table if necessary. Also decrease * the number of upcase users if we are a user. */ down(&ntfs_lock); if (vol->upcase == default_upcase) { ntfs_nr_upcase_users--; vol->upcase = NULL; } if (!ntfs_nr_upcase_users && default_upcase) { ntfs_free(default_upcase); default_upcase = NULL; } if (vol->cluster_size <= 4096 && !--ntfs_nr_compression_users) free_compression_buffers(); up(&ntfs_lock); if (vol->upcase) { ntfs_free(vol->upcase); vol->upcase = NULL; } if (vol->nls_map) { unload_nls(vol->nls_map); vol->nls_map = NULL; } sb->s_fs_info = NULL; kfree(vol); return;}/** * get_nr_free_clusters - return the number of free clusters on a volume * @vol: ntfs volume for which to obtain free cluster count * * Calculate the number of free clusters on the mounted NTFS volume @vol. We * actually calculate the number of clusters in use instead because this * allows us to not care about partial pages as these will be just zero filled * and hence not be counted as allocated clusters. * * The only particularity is that clusters beyond the end of the logical ntfs * volume will be marked as allocated to prevent errors which means we have to * discount those at the end. This is important as the cluster bitmap always * has a size in multiples of 8 bytes, i.e. up to 63 clusters could be outside * the logical volume and marked in use when they are not as they do not exist. * * If any pages cannot be read we assume all clusters in the erroring pages are * in use. This means we return an underestimate on errors which is better than * an overestimate. */static s64 get_nr_free_clusters(ntfs_volume *vol){ s64 nr_free = vol->nr_clusters; u32 *kaddr; struct address_space *mapping = vol->lcnbmp_ino->i_mapping; filler_t *readpage = (filler_t*)mapping->a_ops->readpage; struct page *page; unsigned long index, max_index; unsigned int max_size; ntfs_debug("Entering."); /* Serialize accesses to the cluster bitmap. */ down_read(&vol->lcnbmp_lock); /* * Convert the number of bits into bytes rounded up, then convert into * multiples of PAGE_CACHE_SIZE, rounding up so that if we have one * full and one partial page max_index = 2. */ max_index = (((vol->nr_clusters + 7) >> 3) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; /* Use multiples of 4 bytes. */ max_size = PAGE_CACHE_SIZE >> 2; ntfs_debug("Reading $Bitmap, max_index = 0x%lx, max_size = 0x%x.", max_index, max_size); for (index = 0UL; index < max_index; index++) { unsigned int i; /* * Read the page from page cache, getting it from backing store * if necessary, and increment the use count. */ page = read_cache_page(mapping, index, (filler_t*)readpage, NULL); /* Ignore pages which errored synchronously. */ if (IS_ERR(page)) { ntfs_debug("Sync read_cache_page() error. Skipping " "page (index 0x%lx).", index); nr_free -= PAGE_CACHE_SIZE * 8; continue; } wait_on_page_locked(page); /* Ignore pages which errored asynchronously. */ if (!PageUptodate(page)) { ntfs_debug("Async read_cache_page() error. Skipping " "page (index 0x%lx).", index); page_cache_release(page); nr_free -= PAGE_CACHE_SIZE * 8; continue; } kaddr = (u32*)kmap_atomic(page, KM_USER0); /* * For each 4 bytes, subtract the number of set bits. If this * is the last page and it is partial we don't really care as * it just means we do a little extra work but it won't affect * the result as all out of range bytes are set to zero by * ntfs_readpage(). */ for (i = 0; i < max_size; i++) nr_free -= (s64)hweight32(kaddr[i]); kunmap_atomic(kaddr, KM_USER0); page_cache_release(page); } ntfs_debug("Finished reading $Bitmap, last index = 0x%lx.", index - 1); /* * Fixup for eventual bits outside logical ntfs volume (see function * description above). */ if (vol->nr_clusters & 63) nr_free += 64 - (vol->nr_clusters & 63); up_read(&vol->lcnbmp_lock); /* If errors occured we may well have gone below zero, fix this. */ if (nr_free < 0) nr_free = 0; ntfs_debug("Exiting."); return nr_free;}/** * __get_nr_free_mft_records - return the number of free inodes on a volume * @vol: ntfs volume for which to obtain free inode count * * Calculate the number of free mft records (inodes) on the mounted NTFS * volume @vol. We actually calculate the number of mft records in use instead * because this allows us to not care about partial pages as these will be just * zero filled and hence not be counted as allocated mft record. * * If any pages cannot be read we assume all mft records in the erroring pages * are in use. This means we return an underestimate on errors which is better * than an overestimate. * * NOTE: Caller must hold mftbmp_lock rw_semaphore for reading or writing. */static unsigned long __get_nr_free_mft_records(ntfs_volume *vol){ s64 nr_free; u32 *kaddr; struct address_space *mapping = vol->mftbmp_ino->i_mapping; filler_t *readpage = (filler_t*)mapping->a_ops->readpage; struct page *page; unsigned long index, max_index; unsigned int max_size; ntfs_debug("Entering."); /* Number of mft records in file system (at this point in time). */ nr_free = vol->mft_ino->i_size >> vol->mft_record_size_bits; /* * Convert the maximum number of set bits into bytes rounded up, then * convert into multiples of PAGE_CACHE_SIZE, rounding up so that if we * have one full and one partial page max_index = 2. */ max_index = ((((NTFS_I(vol->mft_ino)->initialized_size >> vol->mft_record_size_bits) + 7) >> 3) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; /* Use multiples of 4 bytes. */ max_size = PAGE_CACHE_SIZE >> 2; ntfs_debug("Reading $MFT/$BITMAP, max_index = 0x%lx, max_size = " "0x%x.", max_index, max_size); for (index = 0UL; index < max_index; index++) { unsigned int i; /* * Read the page from page cache, getting it from backing store * if necessary, and increment the use count. */ page = read_cache_page(mapping, index, (filler_t*)readpage, NULL); /* Ignore pages which errored synchronously. */ if (IS_ERR(page)) { ntfs_debug("Sync read_cache_page() error. Skipping " "page (index 0x%lx).", index); nr_free -= PAGE_CACHE_SIZE * 8; continue; } wait_on_page_locked(page); /* Ignore pages which errored asynchronously. */ if (!PageUptodate(page)) { ntfs_debug("Async read_cache_page() error. Skipping " "page (index 0x%lx).", index); page_cache_release(page); nr_free -= PAGE_CACHE_SIZE * 8; continue; } kaddr = (u32*)kmap_atomic(page, KM_USER0); /* * For each 4 bytes, subtract the number of set bits. If this * is the last page and
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?