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 + -
显示快捷键?