Commit 590a95e4 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

staging: exfat: remove staging version of exfat filesystem

Now that there is a "real" solution for exfat in the vfs tree queued up
to be merged in 5.7-rc1 the "old" exfat code in staging can be removed.

Many thanks to Valdis for doing the work to get this into the tree in
the first place, it was greatly appreciated.
Acked-by: default avatarValdis Kletnieks <valdis.kletnieks@vt.edu>
Cc: Pali Rohár <pali@kernel.org>
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Namjae Jeon <namjae.jeon@samsung.com>
Cc: Sungjong Seo <sj1557.seo@samsung.com>
Cc: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20200310105421.GA2810679@kroah.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 9a5e71a6
......@@ -6301,12 +6301,6 @@ F: include/trace/events/mdio.h
F: include/uapi/linux/mdio.h
F: include/uapi/linux/mii.h
EXFAT FILE SYSTEM
M: Valdis Kletnieks <valdis.kletnieks@vt.edu>
L: linux-fsdevel@vger.kernel.org
S: Maintained
F: drivers/staging/exfat/
EXT2 FILE SYSTEM
M: Jan Kara <jack@suse.com>
L: linux-ext4@vger.kernel.org
......
......@@ -116,8 +116,6 @@ source "drivers/staging/fieldbus/Kconfig"
source "drivers/staging/kpc2000/Kconfig"
source "drivers/staging/exfat/Kconfig"
source "drivers/staging/qlge/Kconfig"
source "drivers/staging/hp/Kconfig"
......
......@@ -48,7 +48,6 @@ obj-$(CONFIG_STAGING_GASKET_FRAMEWORK) += gasket/
obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/
obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/
obj-$(CONFIG_KPC2000) += kpc2000/
obj-$(CONFIG_STAGING_EXFAT_FS) += exfat/
obj-$(CONFIG_QLGE) += qlge/
obj-$(CONFIG_NET_VENDOR_HP) += hp/
obj-$(CONFIG_WFX) += wfx/
# SPDX-License-Identifier: GPL-2.0
config STAGING_EXFAT_FS
tristate "exFAT fs support"
depends on BLOCK
select NLS
help
This adds support for the exFAT file system.
config STAGING_EXFAT_DISCARD
bool "enable discard support"
depends on STAGING_EXFAT_FS
default y
config STAGING_EXFAT_DELAYED_SYNC
bool "enable delayed sync"
depends on STAGING_EXFAT_FS
default n
config STAGING_EXFAT_KERNEL_DEBUG
bool "enable kernel debug features via ioctl"
depends on STAGING_EXFAT_FS
default n
config STAGING_EXFAT_DEBUG_MSG
bool "print debug messages"
depends on STAGING_EXFAT_FS
default n
config STAGING_EXFAT_DEFAULT_CODEPAGE
int "Default codepage for exFAT"
default 437
depends on STAGING_EXFAT_FS
help
This option should be set to the codepage of your exFAT filesystems.
config STAGING_EXFAT_DEFAULT_IOCHARSET
string "Default iocharset for exFAT"
default "utf8"
depends on STAGING_EXFAT_FS
help
Set this to the default input/output character set you'd like exFAT to use.
# SPDX-License-Identifier: GPL-2.0-or-later
obj-$(CONFIG_STAGING_EXFAT_FS) += exfat.o
exfat-y := exfat_core.o \
exfat_super.o \
exfat_blkdev.o \
exfat_cache.o \
exfat_nls.o \
exfat_upcase.o
A laundry list of things that need looking at, most of which will
require more work than the average checkpatch cleanup...
Note that some of these entries may not be bugs - they're things
that need to be looked at, and *possibly* fixed.
Clean up the ffsCamelCase function names.
Fix (thing)->flags to not use magic numbers - multiple offenders
Sort out all the s32/u32/u8 nonsense - most of these should be plain int.
exfat_core.c - ffsReadFile - the goto err_out seem to leak a brelse().
same for ffsWriteFile.
All the calls to fs_sync() need to be looked at, particularly in the
context of EXFAT_DELAYED_SYNC. Currently, if that's defined, we only
flush to disk when sync() gets called. We should be doing at least
metadata flushes at appropriate times.
ffsTruncateFile - if (old_size <= new_size) {
That doesn't look right. How did it ever work? Are they relying on lazy
block allocation when actual writes happen? If nothing else, it never
does the 'fid->size = new_size' and do the inode update....
ffsSetAttr() is just dangling in the breeze, not wired up at all...
Convert global mutexes to a per-superblock mutex.
Right now, we load exactly one UTF-8 table. Check to see
if that plays nice with different codepage and iocharset values
for simultanous mounts of different devices
exfat_rmdir() checks for -EBUSY but ffsRemoveDir() doesn't return it.
In fact, there's a complete lack of -EBUSY testing anywhere.
There's probably a few missing checks for -EEXIST
check return codes of sync_dirty_buffer()
Why is remove_file doing a num_entries++??
Double check a lot of can't-happen parameter checks (for null pointers for
things that have only one call site and can't pass a null, etc).
All the DEBUG stuff can probably be tossed, including the ioctl(). Either
that, or convert to a proper fault-injection system.
exfat_remount does exactly one thing. Fix to actually deal with remount
options, particularly handling R/O correctly. For that matter, allow
R/O mounts in the first place.
Figure out why the VFAT code used multi_sector_(read|write) but the
exfat code doesn't use it. The difference matters on SSDs with wear leveling.
exfat_fat_sync(), exfat_buf_sync(), and sync_alloc_bitmap()
aren't called anyplace....
Create helper function for exfat_set_entry_time() and exfat_set_entry_type()
because it's sort of ugly to be calling the same functionn directly and
other code calling through the fs_func struc ponters...
clean up the remaining vol_type checks, which are of two types:
some are ?: operators with magic numbers, and the rest are places
where we're doing stuff with '.' and '..'.
Patches to:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Valdis Kletnieks <valdis.kletnieks@vt.edu>
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
*/
#include <linux/blkdev.h>
#include <linux/buffer_head.h>
#include <linux/fs.h>
#include "exfat.h"
void exfat_bdev_open(struct super_block *sb)
{
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
if (p_bd->opened)
return;
p_bd->sector_size = bdev_logical_block_size(sb->s_bdev);
p_bd->sector_size_bits = ilog2(p_bd->sector_size);
p_bd->sector_size_mask = p_bd->sector_size - 1;
p_bd->num_sectors = i_size_read(sb->s_bdev->bd_inode) >>
p_bd->sector_size_bits;
p_bd->opened = true;
}
void exfat_bdev_close(struct super_block *sb)
{
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
p_bd->opened = false;
}
int exfat_bdev_read(struct super_block *sb, sector_t secno,
struct buffer_head **bh, u32 num_secs,
bool read)
{
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG
struct exfat_sb_info *sbi = EXFAT_SB(sb);
long flags = sbi->debug_flags;
if (flags & EXFAT_DEBUGFLAGS_ERROR_RW)
return -EIO;
#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */
if (!p_bd->opened)
return -ENODEV;
if (*bh)
__brelse(*bh);
if (read)
*bh = __bread(sb->s_bdev, secno,
num_secs << p_bd->sector_size_bits);
else
*bh = __getblk(sb->s_bdev, secno,
num_secs << p_bd->sector_size_bits);
if (*bh)
return 0;
WARN(!p_fs->dev_ejected,
"[EXFAT] No bh, device seems wrong or to be ejected.\n");
return -EIO;
}
int exfat_bdev_write(struct super_block *sb, sector_t secno,
struct buffer_head *bh,
u32 num_secs, bool sync)
{
s32 count;
struct buffer_head *bh2;
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG
struct exfat_sb_info *sbi = EXFAT_SB(sb);
long flags = sbi->debug_flags;
if (flags & EXFAT_DEBUGFLAGS_ERROR_RW)
return -EIO;
#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */
if (!p_bd->opened)
return -ENODEV;
if (secno == bh->b_blocknr) {
lock_buffer(bh);
set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
unlock_buffer(bh);
if (sync && (sync_dirty_buffer(bh) != 0))
return -EIO;
} else {
count = num_secs << p_bd->sector_size_bits;
bh2 = __getblk(sb->s_bdev, secno, count);
if (!bh2)
goto no_bh;
lock_buffer(bh2);
memcpy(bh2->b_data, bh->b_data, count);
set_buffer_uptodate(bh2);
mark_buffer_dirty(bh2);
unlock_buffer(bh2);
if (sync && (sync_dirty_buffer(bh2) != 0)) {
__brelse(bh2);
goto no_bh;
}
__brelse(bh2);
}
return 0;
no_bh:
WARN(!p_fs->dev_ejected,
"[EXFAT] No bh, device seems wrong or to be ejected.\n");
return -EIO;
}
int exfat_bdev_sync(struct super_block *sb)
{
struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info);
#ifdef CONFIG_STAGING_EXFAT_KERNEL_DEBUG
struct exfat_sb_info *sbi = EXFAT_SB(sb);
long flags = sbi->debug_flags;
if (flags & EXFAT_DEBUGFLAGS_ERROR_RW)
return -EIO;
#endif /* CONFIG_STAGING_EXFAT_KERNEL_DEBUG */
if (!p_bd->opened)
return -ENODEV;
return sync_blockdev(sb->s_bdev);
}
This diff is collapsed.
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
*/
#include <linux/string.h>
#include <linux/nls.h>
#include "exfat.h"
static u16 bad_uni_chars[] = {
/* " * / : < > ? \ | */
0x0022, 0x002A, 0x002F, 0x003A,
0x003C, 0x003E, 0x003F, 0x005C, 0x007C,
0
};
static int convert_ch_to_uni(struct nls_table *nls, u16 *uni, u8 *ch,
bool *lossy)
{
int len;
*uni = 0x0;
if (ch[0] < 0x80) {
*uni = (u16)ch[0];
return 1;
}
len = nls->char2uni(ch, NLS_MAX_CHARSET_SIZE, uni);
if (len < 0) {
/* conversion failed */
pr_info("%s: fail to use nls\n", __func__);
if (lossy)
*lossy = true;
*uni = (u16)'_';
if (!strcmp(nls->charset, "utf8"))
return 1;
else
return 2;
}
return len;
}
static int convert_uni_to_ch(struct nls_table *nls, u8 *ch, u16 uni,
bool *lossy)
{
int len;
ch[0] = 0x0;
if (uni < 0x0080) {
ch[0] = (u8)uni;
return 1;
}
len = nls->uni2char(uni, ch, NLS_MAX_CHARSET_SIZE);
if (len < 0) {
/* conversion failed */
pr_info("%s: fail to use nls\n", __func__);
if (lossy)
*lossy = true;
ch[0] = '_';
return 1;
}
return len;
}
u16 nls_upper(struct super_block *sb, u16 a)
{
struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info);
if (EXFAT_SB(sb)->options.casesensitive)
return a;
if (p_fs->vol_utbl && p_fs->vol_utbl[get_col_index(a)])
return p_fs->vol_utbl[get_col_index(a)][get_row_index(a)];
else
return a;
}
static u16 *nls_wstrchr(u16 *str, u16 wchar)
{
while (*str) {
if (*(str++) == wchar)
return str;
}
return NULL;
}
int nls_uniname_cmp(struct super_block *sb, u16 *a, u16 *b)
{
int i;
for (i = 0; i < MAX_NAME_LENGTH; i++, a++, b++) {
if (nls_upper(sb, *a) != nls_upper(sb, *b))
return 1;
if (*a == 0x0)
return 0;
}
return 0;
}
void nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring,
struct uni_name_t *p_uniname)
{
int i, j, len;
u8 buf[MAX_CHARSET_SIZE];
u16 *uniname = p_uniname->name;
struct nls_table *nls = EXFAT_SB(sb)->nls_io;
if (!nls) {
len = utf16s_to_utf8s(uniname, MAX_NAME_LENGTH,
UTF16_HOST_ENDIAN, p_cstring,
MAX_NAME_LENGTH);
p_cstring[len] = 0;
return;
}
i = 0;
while (i < (MAX_NAME_LENGTH - 1)) {
if (*uniname == (u16)'\0')
break;
len = convert_uni_to_ch(nls, buf, *uniname, NULL);
if (len > 1) {
for (j = 0; j < len; j++)
*p_cstring++ = (char)*(buf + j);
} else { /* len == 1 */
*p_cstring++ = (char)*buf;
}
uniname++;
i++;
}
*p_cstring = '\0';
}
void nls_cstring_to_uniname(struct super_block *sb,
struct uni_name_t *p_uniname, u8 *p_cstring,
bool *p_lossy)
{
int i, j;
bool lossy = false;
u8 *end_of_name;
u8 upname[MAX_NAME_LENGTH * 2];
u16 *uniname = p_uniname->name;
struct nls_table *nls = EXFAT_SB(sb)->nls_io;
/* strip all trailing spaces */
end_of_name = p_cstring + strlen(p_cstring);
while (*(--end_of_name) == ' ') {
if (end_of_name < p_cstring)
break;
}
*(++end_of_name) = '\0';
if (strcmp(p_cstring, ".") && strcmp(p_cstring, "..")) {
/* strip all trailing periods */
while (*(--end_of_name) == '.') {
if (end_of_name < p_cstring)
break;
}
*(++end_of_name) = '\0';
}
if (*p_cstring == '\0')
lossy = true;
if (!nls) {
i = utf8s_to_utf16s(p_cstring, MAX_NAME_LENGTH,
UTF16_HOST_ENDIAN, uniname,
MAX_NAME_LENGTH);
for (j = 0; j < i; j++)
SET16_A(upname + j * 2, nls_upper(sb, uniname[j]));
uniname[i] = '\0';
} else {
i = 0;
j = 0;
while (j < (MAX_NAME_LENGTH - 1)) {
if (*(p_cstring + i) == '\0')
break;
i += convert_ch_to_uni(nls, uniname,
(u8 *)(p_cstring + i), &lossy);
if ((*uniname < 0x0020) ||
nls_wstrchr(bad_uni_chars, *uniname))
lossy = true;
SET16_A(upname + j * 2, nls_upper(sb, *uniname));
uniname++;
j++;
}
if (*(p_cstring + i) != '\0')
lossy = true;
*uniname = (u16)'\0';
}
p_uniname->name_len = j;
p_uniname->name_hash = calc_checksum_2byte(upname, j << 1, 0,
CS_DEFAULT);
if (p_lossy)
*p_lossy = lossy;
}
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment