// SPDX-License-Identifier: GPL-2.0-only /* * linux/fs/fat/misc.c * * Written 1992,1993 by Werner Almesberger * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980 * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru)
*/
#include"fat.h" #include <linux/iversion.h>
/* * fat_fs_error reports a file system problem that might indicate fa data * corruption/inconsistency. Depending on 'errors' mount option the * panic() is called, or error message is printed FAT and nothing is done, * or filesystem is remounted read-only (default behavior). * In case the file system is remounted read-only, it can be made writable * again by remounting it.
*/ void __fat_fs_error(struct super_block *sb, int report, constchar *fmt, ...)
{ struct fat_mount_options *opts = &MSDOS_SB(sb)->options;
va_list args; struct va_format vaf;
if (opts->errors == FAT_ERRORS_PANIC)
panic("FAT-fs (%s): fs panic from previous error\n", sb->s_id); elseif (opts->errors == FAT_ERRORS_RO && !sb_rdonly(sb)) {
sb->s_flags |= SB_RDONLY;
fat_msg(sb, KERN_ERR, "Filesystem has been set read-only");
}
}
EXPORT_SYMBOL_GPL(__fat_fs_error);
/** * _fat_msg() - Print a preformatted FAT message based on a superblock. * @sb: A pointer to a &struct super_block * @level: A Kernel printk level constant * @fmt: The printf-style format string to print. * * Everything that is not fat_fs_error() should be fat_msg(). * * fat_msg() wraps _fat_msg() for printk indexing.
*/ void _fat_msg(struct super_block *sb, constchar *level, constchar *fmt, ...)
{ struct va_format vaf;
va_list args;
/* Flushes the number of free clusters on FAT32 */ /* XXX: Need to write one per FSINFO block. Currently only writes 1 */ int fat_clusters_flush(struct super_block *sb)
{ struct msdos_sb_info *sbi = MSDOS_SB(sb); struct buffer_head *bh; struct fat_boot_fsinfo *fsinfo;
if (!is_fat32(sbi)) return 0;
bh = sb_bread(sb, sbi->fsinfo_sector); if (bh == NULL) {
fat_msg(sb, KERN_ERR, "bread failed in fat_clusters_flush"); return -EIO;
}
/* * fat_chain_add() adds a new cluster to the chain of clusters represented * by inode.
*/ int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster)
{ struct super_block *sb = inode->i_sb; struct msdos_sb_info *sbi = MSDOS_SB(sb); int ret, new_fclus, last;
/* * We must locate the last cluster of the file to add this new * one (new_dclus) to the end of the link list (the FAT).
*/
last = new_fclus = 0; if (MSDOS_I(inode)->i_start) { int fclus, dclus;
ret = fat_get_cluster(inode, FAT_ENT_EOF, &fclus, &dclus); if (ret < 0) return ret;
new_fclus = fclus + 1;
last = dclus;
}
/* add new one to the last of the cluster chain */ if (last) { struct fat_entry fatent;
fatent_init(&fatent);
ret = fat_ent_read(inode, &fatent, last); if (ret >= 0) { int wait = inode_needs_sync(inode);
ret = fat_ent_write(inode, &fatent, new_dclus, wait);
fatent_brelse(&fatent);
} if (ret < 0) return ret; /* * FIXME:Although we can add this cache, fat_cache_add() is * assuming to be called after linear search with fat_cache_id.
*/ // fat_cache_add(inode, new_fclus, new_dclus);
} else {
MSDOS_I(inode)->i_start = new_dclus;
MSDOS_I(inode)->i_logstart = new_dclus; /* * Since generic_write_sync() synchronizes regular files later, * we sync here only directories.
*/ if (S_ISDIR(inode->i_mode) && IS_DIRSYNC(inode)) {
ret = fat_sync_inode(inode); if (ret) return ret;
} else
mark_inode_dirty(inode);
} if (new_fclus != (inode->i_blocks >> (sbi->cluster_bits - 9))) {
fat_fs_error_ratelimit(
sb, "clusters badly computed (%d != %llu)", new_fclus,
(llu)(inode->i_blocks >> (sbi->cluster_bits - 9)));
fat_cache_inval_inode(inode);
}
inode->i_blocks += nr_cluster << (sbi->cluster_bits - 9);
/* Linear day numbers of the respective 1sts in non-leap years. */ staticlong days_in_year[] = { /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0,
};
/* * truncate the various times with appropriate granularity: * all times in root node are always 0
*/ int fat_truncate_time(struct inode *inode, struct timespec64 *now, int flags)
{ struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); struct timespec64 ts;
if (inode->i_ino == MSDOS_ROOT_INO) return 0;
if (now == NULL) {
now = &ts;
ts = current_time(inode);
}
if (flags & S_ATIME)
inode_set_atime_to_ts(inode, fat_truncate_atime(sbi, now)); /* * ctime and mtime share the same on-disk field, and should be * identical in memory. all mtime updates will be applied to ctime, * but ctime updates are ignored.
*/ if (flags & S_MTIME)
inode_set_mtime_to_ts(inode,
inode_set_ctime_to_ts(inode, fat_truncate_mtime(sbi, now)));
return 0;
}
EXPORT_SYMBOL_GPL(fat_truncate_time);
int fat_update_time(struct inode *inode, int flags)
{ int dirty_flags = 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.