mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
staging: exfat: remove symlink feature.
Remove symlink feature completely. Becouse -Uses reserved areas(defined in the Microsoft exfat specification), causing future incompatibilities. -Not described in Microsoft exfat specifications or SD standards. -For REMOVABLE media, causes incompatibility with other implementations. -Not supported by other major exfat drivers. -Not implemented symlink feature in linux FAT/VFAT. Remove this feature completely because of serious media compatibility issues. (Can't enable even with CONFIG) If you have any questions about this patch, please let me know. Reviewed-by: Takahiro Mori <Mori.Takahiro@ab.MitsubishiElectric.co.jp> Acked-by: Valdis Kletnieks <valdis.kletnieks@vt.edu> Signed-off-by: Tetsuhiro Kohada <Kohada.Tetsuhiro@dc.MitsubishiElectric.co.jp> Link: https://lore.kernel.org/r/20200219055727.12867-1-Kohada.Tetsuhiro@dc.MitsubishiElectric.co.jp Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
55b9b8f67d
commit
bb9397a356
@ -660,375 +660,6 @@ static int ffsCreateFile(struct inode *inode, char *path, u8 mode,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer,
|
||||
u64 count, u64 *rcount)
|
||||
{
|
||||
s32 offset, sec_offset, clu_offset;
|
||||
u32 clu;
|
||||
int ret = 0;
|
||||
sector_t LogSector;
|
||||
u64 oneblkread, read_bytes;
|
||||
struct buffer_head *tmp_bh = NULL;
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
|
||||
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
|
||||
|
||||
/* check the validity of the given file id */
|
||||
if (!fid)
|
||||
return -EINVAL;
|
||||
|
||||
/* check the validity of pointer parameters */
|
||||
if (!buffer)
|
||||
return -EINVAL;
|
||||
|
||||
/* acquire the lock for file system critical section */
|
||||
mutex_lock(&p_fs->v_mutex);
|
||||
|
||||
/* check if the given file ID is opened */
|
||||
if (fid->type != TYPE_FILE) {
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fid->rwoffset > fid->size)
|
||||
fid->rwoffset = fid->size;
|
||||
|
||||
if (count > (fid->size - fid->rwoffset))
|
||||
count = fid->size - fid->rwoffset;
|
||||
|
||||
if (count == 0) {
|
||||
if (rcount)
|
||||
*rcount = 0;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
read_bytes = 0;
|
||||
|
||||
while (count > 0) {
|
||||
clu_offset = (s32)(fid->rwoffset >> p_fs->cluster_size_bits);
|
||||
clu = fid->start_clu;
|
||||
|
||||
if (fid->flags == 0x03) {
|
||||
clu += clu_offset;
|
||||
} else {
|
||||
/* hint information */
|
||||
if ((clu_offset > 0) && (fid->hint_last_off > 0) &&
|
||||
(clu_offset >= fid->hint_last_off)) {
|
||||
clu_offset -= fid->hint_last_off;
|
||||
clu = fid->hint_last_clu;
|
||||
}
|
||||
|
||||
while (clu_offset > 0) {
|
||||
/* clu = exfat_fat_read(sb, clu); */
|
||||
if (exfat_fat_read(sb, clu, &clu) == -1) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
clu_offset--;
|
||||
}
|
||||
}
|
||||
|
||||
/* hint information */
|
||||
fid->hint_last_off = (s32)(fid->rwoffset >>
|
||||
p_fs->cluster_size_bits);
|
||||
fid->hint_last_clu = clu;
|
||||
|
||||
/* byte offset in cluster */
|
||||
offset = (s32)(fid->rwoffset & (p_fs->cluster_size - 1));
|
||||
|
||||
/* sector offset in cluster */
|
||||
sec_offset = offset >> p_bd->sector_size_bits;
|
||||
|
||||
/* byte offset in sector */
|
||||
offset &= p_bd->sector_size_mask;
|
||||
|
||||
LogSector = START_SECTOR(clu) + sec_offset;
|
||||
|
||||
oneblkread = (u64)(p_bd->sector_size - offset);
|
||||
if (oneblkread > count)
|
||||
oneblkread = count;
|
||||
|
||||
if ((offset == 0) && (oneblkread == p_bd->sector_size)) {
|
||||
if (sector_read(sb, LogSector, &tmp_bh, 1) !=
|
||||
0)
|
||||
goto err_out;
|
||||
memcpy((char *)buffer + read_bytes,
|
||||
(char *)tmp_bh->b_data, (s32)oneblkread);
|
||||
} else {
|
||||
if (sector_read(sb, LogSector, &tmp_bh, 1) !=
|
||||
0)
|
||||
goto err_out;
|
||||
memcpy((char *)buffer + read_bytes,
|
||||
(char *)tmp_bh->b_data + offset,
|
||||
(s32)oneblkread);
|
||||
}
|
||||
count -= oneblkread;
|
||||
read_bytes += oneblkread;
|
||||
fid->rwoffset += oneblkread;
|
||||
}
|
||||
brelse(tmp_bh);
|
||||
|
||||
/* How did this ever work and not leak a brlse()?? */
|
||||
err_out:
|
||||
/* set the size of read bytes */
|
||||
if (rcount)
|
||||
*rcount = read_bytes;
|
||||
|
||||
if (p_fs->dev_ejected)
|
||||
ret = -EIO;
|
||||
|
||||
out:
|
||||
/* release the lock for file system critical section */
|
||||
mutex_unlock(&p_fs->v_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ffsWriteFile(struct inode *inode, struct file_id_t *fid,
|
||||
void *buffer, u64 count, u64 *wcount)
|
||||
{
|
||||
bool modified = false;
|
||||
s32 offset, sec_offset, clu_offset;
|
||||
s32 num_clusters, num_alloc, num_alloced = (s32)~0;
|
||||
int ret = 0;
|
||||
u32 clu, last_clu;
|
||||
sector_t LogSector;
|
||||
u64 oneblkwrite, write_bytes;
|
||||
struct chain_t new_clu;
|
||||
struct timestamp_t tm;
|
||||
struct dentry_t *ep, *ep2;
|
||||
struct entry_set_cache_t *es = NULL;
|
||||
struct buffer_head *tmp_bh = NULL;
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
|
||||
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
|
||||
|
||||
/* check the validity of the given file id */
|
||||
if (!fid)
|
||||
return -EINVAL;
|
||||
|
||||
/* check the validity of pointer parameters */
|
||||
if (!buffer)
|
||||
return -EINVAL;
|
||||
|
||||
/* acquire the lock for file system critical section */
|
||||
mutex_lock(&p_fs->v_mutex);
|
||||
|
||||
/* check if the given file ID is opened */
|
||||
if (fid->type != TYPE_FILE) {
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fid->rwoffset > fid->size)
|
||||
fid->rwoffset = fid->size;
|
||||
|
||||
if (count == 0) {
|
||||
if (wcount)
|
||||
*wcount = 0;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fs_set_vol_flags(sb, VOL_DIRTY);
|
||||
|
||||
if (fid->size == 0)
|
||||
num_clusters = 0;
|
||||
else
|
||||
num_clusters = (s32)((fid->size - 1) >>
|
||||
p_fs->cluster_size_bits) + 1;
|
||||
|
||||
write_bytes = 0;
|
||||
|
||||
while (count > 0) {
|
||||
clu_offset = (s32)(fid->rwoffset >> p_fs->cluster_size_bits);
|
||||
clu = fid->start_clu;
|
||||
last_clu = fid->start_clu;
|
||||
|
||||
if (fid->flags == 0x03) {
|
||||
if ((clu_offset > 0) && (clu != CLUSTER_32(~0))) {
|
||||
last_clu += clu_offset - 1;
|
||||
|
||||
if (clu_offset == num_clusters)
|
||||
clu = CLUSTER_32(~0);
|
||||
else
|
||||
clu += clu_offset;
|
||||
}
|
||||
} else {
|
||||
/* hint information */
|
||||
if ((clu_offset > 0) && (fid->hint_last_off > 0) &&
|
||||
(clu_offset >= fid->hint_last_off)) {
|
||||
clu_offset -= fid->hint_last_off;
|
||||
clu = fid->hint_last_clu;
|
||||
}
|
||||
|
||||
while ((clu_offset > 0) && (clu != CLUSTER_32(~0))) {
|
||||
last_clu = clu;
|
||||
/* clu = exfat_fat_read(sb, clu); */
|
||||
if (exfat_fat_read(sb, clu, &clu) == -1) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
clu_offset--;
|
||||
}
|
||||
}
|
||||
|
||||
if (clu == CLUSTER_32(~0)) {
|
||||
num_alloc = (s32)((count - 1) >>
|
||||
p_fs->cluster_size_bits) + 1;
|
||||
new_clu.dir = (last_clu == CLUSTER_32(~0)) ?
|
||||
CLUSTER_32(~0) : last_clu + 1;
|
||||
new_clu.size = 0;
|
||||
new_clu.flags = fid->flags;
|
||||
|
||||
/* (1) allocate a chain of clusters */
|
||||
num_alloced = exfat_alloc_cluster(sb,
|
||||
num_alloc,
|
||||
&new_clu);
|
||||
if (num_alloced == 0)
|
||||
break;
|
||||
if (num_alloced < 0) {
|
||||
ret = num_alloced;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* (2) append to the FAT chain */
|
||||
if (last_clu == CLUSTER_32(~0)) {
|
||||
if (new_clu.flags == 0x01)
|
||||
fid->flags = 0x01;
|
||||
fid->start_clu = new_clu.dir;
|
||||
modified = true;
|
||||
} else {
|
||||
if (new_clu.flags != fid->flags) {
|
||||
exfat_chain_cont_cluster(sb,
|
||||
fid->start_clu,
|
||||
num_clusters);
|
||||
fid->flags = 0x01;
|
||||
modified = true;
|
||||
}
|
||||
if (new_clu.flags == 0x01)
|
||||
exfat_fat_write(sb, last_clu, new_clu.dir);
|
||||
}
|
||||
|
||||
num_clusters += num_alloced;
|
||||
clu = new_clu.dir;
|
||||
}
|
||||
|
||||
/* hint information */
|
||||
fid->hint_last_off = (s32)(fid->rwoffset >>
|
||||
p_fs->cluster_size_bits);
|
||||
fid->hint_last_clu = clu;
|
||||
|
||||
/* byte offset in cluster */
|
||||
offset = (s32)(fid->rwoffset & (p_fs->cluster_size - 1));
|
||||
|
||||
/* sector offset in cluster */
|
||||
sec_offset = offset >> p_bd->sector_size_bits;
|
||||
|
||||
/* byte offset in sector */
|
||||
offset &= p_bd->sector_size_mask;
|
||||
|
||||
LogSector = START_SECTOR(clu) + sec_offset;
|
||||
|
||||
oneblkwrite = (u64)(p_bd->sector_size - offset);
|
||||
if (oneblkwrite > count)
|
||||
oneblkwrite = count;
|
||||
|
||||
if ((offset == 0) && (oneblkwrite == p_bd->sector_size)) {
|
||||
if (sector_read(sb, LogSector, &tmp_bh, 0) !=
|
||||
0)
|
||||
goto err_out;
|
||||
memcpy((char *)tmp_bh->b_data,
|
||||
(char *)buffer + write_bytes, (s32)oneblkwrite);
|
||||
if (sector_write(sb, LogSector, tmp_bh, 0) !=
|
||||
0) {
|
||||
brelse(tmp_bh);
|
||||
goto err_out;
|
||||
}
|
||||
} else {
|
||||
if ((offset > 0) ||
|
||||
((fid->rwoffset + oneblkwrite) < fid->size)) {
|
||||
if (sector_read(sb, LogSector, &tmp_bh, 1) !=
|
||||
0)
|
||||
goto err_out;
|
||||
} else {
|
||||
if (sector_read(sb, LogSector, &tmp_bh, 0) !=
|
||||
0)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
memcpy((char *)tmp_bh->b_data + offset,
|
||||
(char *)buffer + write_bytes, (s32)oneblkwrite);
|
||||
if (sector_write(sb, LogSector, tmp_bh, 0) !=
|
||||
0) {
|
||||
brelse(tmp_bh);
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
count -= oneblkwrite;
|
||||
write_bytes += oneblkwrite;
|
||||
fid->rwoffset += oneblkwrite;
|
||||
|
||||
fid->attr |= ATTR_ARCHIVE;
|
||||
|
||||
if (fid->size < fid->rwoffset) {
|
||||
fid->size = fid->rwoffset;
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
brelse(tmp_bh);
|
||||
|
||||
/* (3) update the direcoty entry */
|
||||
es = get_entry_set_in_dir(sb, &fid->dir, fid->entry,
|
||||
ES_ALL_ENTRIES, &ep);
|
||||
if (!es)
|
||||
goto err_out;
|
||||
ep2 = ep + 1;
|
||||
|
||||
exfat_set_entry_time(ep, tm_current(&tm), TM_MODIFY);
|
||||
exfat_set_entry_attr(ep, fid->attr);
|
||||
|
||||
if (modified) {
|
||||
if (exfat_get_entry_flag(ep2) != fid->flags)
|
||||
exfat_set_entry_flag(ep2, fid->flags);
|
||||
|
||||
if (exfat_get_entry_size(ep2) != fid->size)
|
||||
exfat_set_entry_size(ep2, fid->size);
|
||||
|
||||
if (exfat_get_entry_clu0(ep2) != fid->start_clu)
|
||||
exfat_set_entry_clu0(ep2, fid->start_clu);
|
||||
}
|
||||
|
||||
update_dir_checksum_with_entry_set(sb, es);
|
||||
release_entry_set(es);
|
||||
|
||||
#ifndef CONFIG_STAGING_EXFAT_DELAYED_SYNC
|
||||
fs_sync(sb, true);
|
||||
fs_set_vol_flags(sb, VOL_CLEAN);
|
||||
#endif
|
||||
|
||||
err_out:
|
||||
/* set the size of written bytes */
|
||||
if (wcount)
|
||||
*wcount = write_bytes;
|
||||
|
||||
if (num_alloced == 0)
|
||||
ret = -ENOSPC;
|
||||
|
||||
else if (p_fs->dev_ejected)
|
||||
ret = -EIO;
|
||||
|
||||
out:
|
||||
/* release the lock for file system critical section */
|
||||
mutex_unlock(&p_fs->v_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size)
|
||||
{
|
||||
s32 num_clusters;
|
||||
@ -2273,7 +1904,6 @@ static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry,
|
||||
int err;
|
||||
struct file_id_t fid;
|
||||
loff_t i_pos;
|
||||
u64 ret;
|
||||
mode_t i_mode;
|
||||
|
||||
__lock_super(sb);
|
||||
@ -2295,18 +1925,6 @@ static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry,
|
||||
}
|
||||
|
||||
i_mode = inode->i_mode;
|
||||
if (S_ISLNK(i_mode) && !EXFAT_I(inode)->target) {
|
||||
EXFAT_I(inode)->target = kmalloc(i_size_read(inode) + 1,
|
||||
GFP_KERNEL);
|
||||
if (!EXFAT_I(inode)->target) {
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
ffsReadFile(dir, &fid, EXFAT_I(inode)->target,
|
||||
i_size_read(inode), &ret);
|
||||
*(EXFAT_I(inode)->target + i_size_read(inode)) = '\0';
|
||||
}
|
||||
|
||||
alias = d_find_alias(inode);
|
||||
if (alias && !exfat_d_anon_disconn(alias)) {
|
||||
BUG_ON(d_unhashed(alias));
|
||||
@ -2398,73 +2016,6 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int exfat_symlink(struct inode *dir, struct dentry *dentry,
|
||||
const char *target)
|
||||
{
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct timespec64 curtime;
|
||||
struct inode *inode;
|
||||
struct file_id_t fid;
|
||||
loff_t i_pos;
|
||||
int err;
|
||||
u64 len = (u64)strlen(target);
|
||||
u64 ret;
|
||||
|
||||
__lock_super(sb);
|
||||
|
||||
pr_debug("%s entered\n", __func__);
|
||||
|
||||
err = ffsCreateFile(dir, (u8 *)dentry->d_name.name, FM_SYMLINK, &fid);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
||||
err = ffsWriteFile(dir, &fid, (char *)target, len, &ret);
|
||||
|
||||
if (err) {
|
||||
ffsRemoveFile(dir, &fid);
|
||||
goto out;
|
||||
}
|
||||
|
||||
INC_IVERSION(dir);
|
||||
curtime = current_time(dir);
|
||||
dir->i_ctime = curtime;
|
||||
dir->i_mtime = curtime;
|
||||
dir->i_atime = curtime;
|
||||
if (IS_DIRSYNC(dir))
|
||||
(void)exfat_sync_inode(dir);
|
||||
else
|
||||
mark_inode_dirty(dir);
|
||||
|
||||
i_pos = ((loff_t)fid.dir.dir << 32) | (fid.entry & 0xffffffff);
|
||||
|
||||
inode = exfat_build_inode(sb, &fid, i_pos);
|
||||
if (IS_ERR(inode)) {
|
||||
err = PTR_ERR(inode);
|
||||
goto out;
|
||||
}
|
||||
INC_IVERSION(inode);
|
||||
curtime = current_time(inode);
|
||||
inode->i_mtime = curtime;
|
||||
inode->i_atime = curtime;
|
||||
inode->i_ctime = curtime;
|
||||
/* timestamp is already written, so mark_inode_dirty() is unneeded. */
|
||||
|
||||
EXFAT_I(inode)->target = kmemdup(target, len + 1, GFP_KERNEL);
|
||||
if (!EXFAT_I(inode)->target) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode);
|
||||
d_instantiate(dentry, inode);
|
||||
|
||||
out:
|
||||
__unlock_super(sb);
|
||||
pr_debug("%s exited\n", __func__);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
struct super_block *sb = dir->i_sb;
|
||||
@ -2838,7 +2389,6 @@ static const struct inode_operations exfat_dir_inode_operations = {
|
||||
.create = exfat_create,
|
||||
.lookup = exfat_lookup,
|
||||
.unlink = exfat_unlink,
|
||||
.symlink = exfat_symlink,
|
||||
.mkdir = exfat_mkdir,
|
||||
.rmdir = exfat_rmdir,
|
||||
.rename = exfat_rename,
|
||||
|
Loading…
Reference in New Issue
Block a user