// SPDX-License-Identifier: GPL-2.0-only /* * linux/fs/fat/inode.c * * Written 1992,1993 by Werner Almesberger * VFAT extensions by Gordon Chaffee, merged with msdos fs by Henrik Storner * Rewritten for the constant inumbers support by Al Viro * * Fixes: * * Max Cohan: Fixed invalid FSINFO offset when info_sector is 0
*/
int fat_add_cluster(struct inode *inode)
{ int err, cluster;
err = fat_alloc_clusters(inode, &cluster, 1); if (err) return err; /* FIXME: this cluster should be added after data of this
* cluster is writed */
err = fat_chain_add(inode, cluster, 1); if (err)
fat_free_clusters(inode, cluster); return err;
}
last_block = inode->i_blocks >> (sb->s_blocksize_bits - 9);
offset = (unsignedlong)iblock & (sbi->sec_per_clus - 1); /* * allocate a cluster according to the following. * 1) no more available blocks * 2) not part of fallocate region
*/ if (!offset && !(iblock < last_block)) { /* TODO: multiple cluster allocation would be desirable. */
err = fat_add_cluster(inode); if (err) return err;
} /* available blocks on this cluster */
mapped_blocks = sbi->sec_per_clus - offset;
if (iov_iter_rw(iter) == WRITE) { /* * FIXME: blockdev_direct_IO() doesn't use ->write_begin(), * so we need to update the ->mmu_private to block boundary. * * But we must fill the remaining area or hole by nul for * updating ->mmu_private. * * Return 0, and fallback to normal buffered write.
*/
loff_t size = offset + count; if (MSDOS_I(inode)->mmu_private < size) return 0;
}
/* * FAT need to use the DIO_LOCKING for avoiding the race * condition of fat_get_block() and ->truncate().
*/
ret = blockdev_direct_IO(iocb, inode, iter, fat_get_block); if (ret < 0 && iov_iter_rw(iter) == WRITE)
fat_write_failed(mapping, offset + count);
/* * fat_block_truncate_page() zeroes out a mapping from file offset `from' * up to the end of the block which corresponds to `from'. * This is required during truncate to physically zeroout the tail end * of that block so it doesn't yield old data if the file is later grown. * Also, avoid causing failure from fsx for cases of "data past EOF"
*/ int fat_block_truncate_page(struct inode *inode, loff_t from)
{ return block_truncate_page(inode->i_mapping, from, fat_get_block);
}
/* * New FAT inode stuff. We do the following: * a) i_ino is constant and has nothing with on-disk location. * b) FAT manages its own cache of directory entries. * c) *This* cache is indexed by on-disk location. * d) inode has an associated directory entry, all right, but * it may be unhashed. * e) currently entries are stored within struct inode. That should * change. * f) we deal with races in the following way: * 1. readdir() and lookup() do FAT-dir-cache lookup. * 2. rename() unhashes the F-d-c entry and rehashes it in * a new place. * 3. unlink() and rmdir() unhash F-d-c entry. * 4. fat_write_inode() checks whether the thing is unhashed. * If it is we silently return. If it isn't we do bread(), * check if the location is still valid and retry if it * isn't. Otherwise we do changes. * 5. Spinlock is used to protect hash/unhash/location check/lookup * 6. fat_evict_inode() unhashes the F-d-c entry. * 7. lookup() and readdir() do igrab() if they find a F-d-c entry * and consider negative result as cache miss.
*/
/* If NFS support is enabled, cache the mapping of start cluster * to directory inode. This is used during reconnection of * dentries to the filesystem root.
*/ if (S_ISDIR(inode->i_mode) && sbi->options.nfs) { struct hlist_head *d_head = sbi->dir_hashtable;
d_head += fat_dir_hash(MSDOS_I(inode)->i_logstart);
staticint __fat_write_inode(struct inode *inode, int wait);
staticvoid fat_free_eofblocks(struct inode *inode)
{ /* Release unwritten fallocated blocks on inode eviction. */ if ((inode->i_blocks << 9) >
round_up(MSDOS_I(inode)->mmu_private,
MSDOS_SB(inode->i_sb)->cluster_size)) { int err;
fat_truncate_blocks(inode, MSDOS_I(inode)->mmu_private); /* Fallocate results in updating the i_start/iogstart * for the zero byte file. So, make it return to * original state during evict and commit it to avoid * any corruption on the next access to the cluster * chain for the file.
*/
err = __fat_write_inode(inode, inode_needs_sync(inode)); if (err) {
fat_msg(inode->i_sb, KERN_WARNING, "Failed to " "update on disk inode for unused " "fallocated blocks, inode could be " "corrupted. Please run fsck");
}
/* do not change any thing if mounted read only */ if (sb_rdonly(sb) && !force) return;
/* do not change state if fs was dirty */ if (sbi->dirty) { /* warn only on set (mount). */ if (set)
fat_msg(sb, KERN_WARNING, "Volume was not properly " "unmounted. Some data may be corrupt. " "Please run fsck."); return;
}
bh = sb_bread(sb, 0); if (bh == NULL) {
fat_msg(sb, KERN_ERR, "unable to read boot sector " "to mark fs as dirty"); return;
}
b = (struct fat_boot_sector *) bh->b_data;
if (is_fat32(sbi)) { if (set)
b->fat32.state |= FAT_STATE_DIRTY; else
b->fat32.state &= ~FAT_STATE_DIRTY;
} else/* fat 16 and 12 */ { if (set)
b->fat16.state |= FAT_STATE_DIRTY; else
b->fat16.state &= ~FAT_STATE_DIRTY;
}
staticvoid __exit fat_destroy_inodecache(void)
{ /* * Make sure all delayed rcu free inodes are flushed before we * destroy cache.
*/
rcu_barrier();
kmem_cache_destroy(fat_inode_cachep);
}
/* If the count of free cluster is still unknown, counts it here. */ if (sbi->free_clusters == -1 || !sbi->free_clus_valid) { int err = fat_count_free_clusters(dentry->d_sb); if (err) return err;
}
/* * These are all obsolete but we still reject invalid options. * The corresponding values are therefore meaningless.
*/ staticconststruct constant_table fat_param_conv[] = {
{"binary", 0},
{"text", 0},
{"auto", 0},
{"b", 0},
{"t", 0},
{"a", 0},
{}
};
staticbool fat_bpb_is_zero(struct fat_boot_sector *b)
{ if (get_unaligned_le16(&b->sector_size)) returnfalse; if (b->sec_per_clus) returnfalse; if (b->reserved) returnfalse; if (b->fats) returnfalse; if (get_unaligned_le16(&b->dir_entries)) returnfalse; if (get_unaligned_le16(&b->sectors)) returnfalse; if (b->media) returnfalse; if (b->fat_length) returnfalse; if (b->secs_track) returnfalse; if (b->heads) returnfalse; returntrue;
}
staticint fat_read_bpb(struct super_block *sb, struct fat_boot_sector *b, int silent, struct fat_bios_param_block *bpb)
{ int error = -EINVAL;
/* Validate this looks like a FAT filesystem BPB */ if (!bpb->fat_reserved) { if (!silent)
fat_msg(sb, KERN_ERR, "bogus number of reserved sectors"); goto out;
} if (!bpb->fat_fats) { if (!silent)
fat_msg(sb, KERN_ERR, "bogus number of FAT structure"); goto out;
}
/* * Earlier we checked here that b->secs_track and b->head are nonzero, * but it turns out valid FAT filesystems can have zero there.
*/
if (!fat_valid_media(b->media)) { if (!silent)
fat_msg(sb, KERN_ERR, "invalid media value (0x%02x)",
(unsigned)b->media); goto out;
}
if (!is_power_of_2(bpb->fat_sec_per_clus)) { if (!silent)
fat_msg(sb, KERN_ERR, "bogus sectors per cluster %u",
(unsigned)bpb->fat_sec_per_clus); goto out;
}
if (bpb->fat_fat_length == 0 && bpb->fat32_length == 0) { if (!silent)
fat_msg(sb, KERN_ERR, "bogus number of FAT sectors"); goto out;
}
error = 0;
out: return error;
}
staticint fat_read_static_bpb(struct super_block *sb, struct fat_boot_sector *b, int silent, struct fat_bios_param_block *bpb)
{ staticconstchar *notdos1x = "This doesn't look like a DOS 1.x volume";
sector_t bd_sects = bdev_nr_sectors(sb->s_bdev); struct fat_floppy_defaults *fdefaults = NULL; int error = -EINVAL; unsigned i;
/* 16-bit DOS 1.x reliably wrote bootstrap short-jmp code */ if (b->ignored[0] != 0xeb || b->ignored[2] != 0x90) { if (!silent)
fat_msg(sb, KERN_ERR, "%s; no bootstrapping code", notdos1x); goto out;
}
/* * If any value in this region is non-zero, it isn't archaic * DOS.
*/ if (!fat_bpb_is_zero(b)) { if (!silent)
fat_msg(sb, KERN_ERR, "%s; DOS 2.x BPB is non-zero", notdos1x); goto out;
}
for (i = 0; i < ARRAY_SIZE(floppy_defaults); i++) { if (floppy_defaults[i].nr_sectors == bd_sects) {
fdefaults = &floppy_defaults[i]; break;
}
}
if (fdefaults == NULL) { if (!silent)
fat_msg(sb, KERN_WARNING, "This looks like a DOS 1.x volume, but isn't a recognized floppy size (%llu sectors)",
(u64)bd_sects); goto out;
}
if (!silent)
fat_msg(sb, KERN_INFO, "This looks like a DOS 1.x volume; assuming default BPB values");
/* * Read the super block of an MS-DOS FS.
*/ int fat_fill_super(struct super_block *sb, struct fs_context *fc, void (*setup)(struct super_block *))
{ struct fat_mount_options *opts = fc->fs_private; int silent = fc->sb_flags & SB_SILENT; struct inode *root_inode = NULL, *fat_inode = NULL; struct inode *fsinfo_inode = NULL; struct buffer_head *bh; struct fat_bios_param_block bpb; struct msdos_sb_info *sbi;
u16 logical_sector_size;
u32 total_sectors, total_clusters, fat_clusters, rootdir_sectors; long error; char buf[50]; struct timespec64 ts;
/* * GFP_KERNEL is ok here, because while we do hold the * superblock lock, memory pressure can't call back into * the filesystem, since we're only just about to mount * it and have no inodes etc active!
*/
sbi = kzalloc(sizeof(struct msdos_sb_info), GFP_KERNEL); if (!sbi) return -ENOMEM;
sb->s_fs_info = sbi;
sb->s_flags |= SB_NODIRATIME;
sb->s_magic = MSDOS_SUPER_MAGIC;
sb->s_op = &fat_sops;
sb->s_export_op = &fat_export_ops; /* * fat timestamps are complex and truncated by fat itself, so * we set 1 here to be fast
*/
sb->s_time_gran = 1;
mutex_init(&sbi->nfs_build_inode_lock);
ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL,
DEFAULT_RATELIMIT_BURST);
/* UTF-8 doesn't provide FAT semantics */ if (!strcmp(opts->iocharset, "utf8")) {
fat_msg(sb, KERN_WARNING, "utf8 is not a recommended IO charset" " for FAT filesystems, filesystem will be" " case sensitive!");
}
/* If user doesn't specify allow_utime, it's initialized from dmask. */ if (opts->allow_utime == (unsignedshort)-1)
opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH); if (opts->unicode_xlate)
opts->utf8 = 0; if (opts->nfs == FAT_NFS_NOSTALE_RO) {
sb->s_flags |= SB_RDONLY;
sb->s_export_op = &fat_export_ops_nostale;
}
/* Apply parsed options to sbi (structure copy) */
sbi->options = *opts; /* Transfer ownership of iocharset to sbi->options */
opts->iocharset = NULL;
setup(sb); /* flavour-specific stuff that needs options */
/* interpret volume ID as a little endian 32 bit integer */ if (is_fat32(sbi))
sbi->vol_id = bpb.fat32_vol_id; else/* fat 16 or 12 */
sbi->vol_id = bpb.fat16_vol_id;
/* some OSes set FAT_STATE_DIRTY and clean it on unmount. */ if (is_fat32(sbi))
sbi->dirty = bpb.fat32_state & FAT_STATE_DIRTY; else/* fat 16 or 12 */
sbi->dirty = bpb.fat16_state & FAT_STATE_DIRTY;
/* check that FAT table does not overflow */
fat_clusters = calc_fat_clusters(sb);
total_clusters = min(total_clusters, fat_clusters - FAT_START_ENT); if (total_clusters > max_fat(sb)) { if (!silent)
fat_msg(sb, KERN_ERR, "count of clusters too big (%u)",
total_clusters); goto out_invalid;
}
sbi->max_cluster = total_clusters + FAT_START_ENT; /* check the free_clusters, it's not necessarily correct */ if (sbi->free_clusters != -1 && sbi->free_clusters > total_clusters)
sbi->free_clusters = -1; /* check the prev_free, it's not necessarily correct */
sbi->prev_free %= sbi->max_cluster; if (sbi->prev_free < FAT_START_ENT)
sbi->prev_free = FAT_START_ENT;
/* set up enough so that it can read an inode */
fat_hash_init(sb);
dir_hash_init(sb);
fat_ent_access_init(sb);
/* * The low byte of the first FAT entry must have the same value as * the media field of the boot sector. But in real world, too many * devices are writing wrong values. So, removed that validity check. * * The removed check compared the first FAT entry to a value dependent * on the media field like this: * == (0x0F00 | media), for FAT12 * == (0XFF00 | media), for FAT16 * == (0x0FFFFF | media), for FAT32
*/
if (sbi->options.discard && !bdev_max_discard_sectors(sb->s_bdev))
fat_msg(sb, KERN_WARNING, "mounting with \"discard\" option, but the device does not support discard");
fat_set_state(sb, 1, 0); return 0;
out_invalid:
error = -EINVAL; if (!silent)
fat_msg(sb, KERN_INFO, "Can't find a valid FAT filesystem");
/* * helper function for fat_flush_inodes. This writes both the inode * and the file data blocks, waiting for in flight data blocks before * the start of the call. It does not wait for any io started * during the call
*/ staticint writeback_inode(struct inode *inode)
{
int ret;
/* if we used wait=1, sync_inode_metadata waits for the io for the * inode to finish. So wait=0 is sent down to sync_inode_metadata * and filemap_fdatawrite is used for the data blocks
*/
ret = sync_inode_metadata(inode, 0); if (!ret)
ret = filemap_fdatawrite(inode->i_mapping); return ret;
}
/* * write data and metadata corresponding to i1 and i2. The io is * started but we do not wait for any of it to finish. * * filemap_flush is used for the block device, so if there is a dirty * page for a block already in flight, we will not wait and start the * io over again
*/ int fat_flush_inodes(struct super_block *sb, struct inode *i1, struct inode *i2)
{ int ret = 0; if (!MSDOS_SB(sb)->options.flush) return 0; if (i1)
ret = writeback_inode(i1); if (!ret && i2)
ret = writeback_inode(i2); if (!ret)
ret = sync_blockdev_nowait(sb->s_bdev); return ret;
}
EXPORT_SYMBOL_GPL(fat_flush_inodes);
int fat_init_fs_context(struct fs_context *fc, bool is_vfat)
{ struct fat_mount_options *opts;
opts = kzalloc(sizeof(*opts), GFP_KERNEL); if (!opts) return -ENOMEM;
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.