diff options
Diffstat (limited to 'drivers/staging/exfat/exfat_super.c')
-rw-r--r-- | drivers/staging/exfat/exfat_super.c | 900 |
1 files changed, 368 insertions, 532 deletions
diff --git a/drivers/staging/exfat/exfat_super.c b/drivers/staging/exfat/exfat_super.c index 3b2b0ceb7297..9f91853b189b 100644 --- a/drivers/staging/exfat/exfat_super.c +++ b/drivers/staging/exfat/exfat_super.c @@ -26,7 +26,7 @@ #include <linux/sched.h> #include <linux/fs_struct.h> #include <linux/namei.h> - +#include <linux/random.h> #include <linux/string.h> #include <linux/nls.h> #include <linux/mutex.h> @@ -284,12 +284,12 @@ static const struct dentry_operations exfat_dentry_ops = { .d_compare = exfat_cmp, }; -static DEFINE_SEMAPHORE(z_sem); +static DEFINE_MUTEX(z_mutex); static inline void fs_sync(struct super_block *sb, bool do_sync) { if (do_sync) - bdev_sync(sb); + exfat_bdev_sync(sb); } /* @@ -353,26 +353,28 @@ static int ffsMountVol(struct super_block *sb) pr_info("[EXFAT] trying to mount...\n"); - down(&z_sem); + mutex_lock(&z_mutex); - buf_init(sb); + exfat_buf_init(sb); - sema_init(&p_fs->v_sem, 1); + mutex_init(&p_fs->v_mutex); p_fs->dev_ejected = 0; /* open the block device */ - bdev_open(sb); + exfat_bdev_open(sb); if (p_bd->sector_size < sb->s_blocksize) { - ret = FFS_MEDIAERR; + printk(KERN_INFO "EXFAT: mount failed - sector size %d less than blocksize %ld\n", + p_bd->sector_size, sb->s_blocksize); + ret = -EINVAL; goto out; } if (p_bd->sector_size > sb->s_blocksize) sb_set_blocksize(sb, p_bd->sector_size); /* read Sector 0 */ - if (sector_read(sb, 0, &tmp_bh, 1) != FFS_SUCCESS) { - ret = FFS_MEDIAERR; + if (sector_read(sb, 0, &tmp_bh, 1) != 0) { + ret = -EIO; goto out; } @@ -383,8 +385,8 @@ static int ffsMountVol(struct super_block *sb) /* check the validity of PBR */ if (GET16_A(p_pbr->signature) != PBR_SIGNATURE) { brelse(tmp_bh); - bdev_close(sb); - ret = FFS_FORMATERR; + exfat_bdev_close(sb); + ret = -EFSCORRUPTED; goto out; } @@ -394,16 +396,10 @@ static int ffsMountVol(struct super_block *sb) break; if (i < 53) { -#ifdef CONFIG_EXFAT_DONT_MOUNT_VFAT + /* Not sure how we'd get here, but complain if it does */ ret = -EINVAL; - printk(KERN_INFO "EXFAT: Attempted to mount VFAT filesystem\n"); + pr_info("EXFAT: Attempted to mount VFAT filesystem\n"); goto out; -#else - if (GET16(p_pbr->bpb + 11)) /* num_fat_sectors */ - ret = fat16_mount(sb, p_pbr); - else - ret = fat32_mount(sb, p_pbr); -#endif } else { ret = exfat_mount(sb, p_pbr); } @@ -411,38 +407,34 @@ static int ffsMountVol(struct super_block *sb) brelse(tmp_bh); if (ret) { - bdev_close(sb); + exfat_bdev_close(sb); goto out; } - if (p_fs->vol_type == EXFAT) { - ret = load_alloc_bitmap(sb); - if (ret) { - bdev_close(sb); - goto out; - } - ret = load_upcase_table(sb); - if (ret) { - free_alloc_bitmap(sb); - bdev_close(sb); - goto out; - } + ret = load_alloc_bitmap(sb); + if (ret) { + exfat_bdev_close(sb); + goto out; + } + ret = load_upcase_table(sb); + if (ret) { + free_alloc_bitmap(sb); + exfat_bdev_close(sb); + goto out; } if (p_fs->dev_ejected) { - if (p_fs->vol_type == EXFAT) { - free_upcase_table(sb); - free_alloc_bitmap(sb); - } - bdev_close(sb); - ret = FFS_MEDIAERR; + free_upcase_table(sb); + free_alloc_bitmap(sb); + exfat_bdev_close(sb); + ret = -EIO; goto out; } pr_info("[EXFAT] mounted successfully\n"); out: - up(&z_sem); + mutex_unlock(&z_mutex); return ret; } @@ -450,39 +442,37 @@ out: static int ffsUmountVol(struct super_block *sb) { struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - int err = FFS_SUCCESS; + int err = 0; pr_info("[EXFAT] trying to unmount...\n"); - down(&z_sem); + mutex_lock(&z_mutex); /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); - fs_sync(sb, false); + fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); - if (p_fs->vol_type == EXFAT) { - free_upcase_table(sb); - free_alloc_bitmap(sb); - } + free_upcase_table(sb); + free_alloc_bitmap(sb); - FAT_release_all(sb); - buf_release_all(sb); + exfat_fat_release_all(sb); + exfat_buf_release_all(sb); /* close the block device */ - bdev_close(sb); + exfat_bdev_close(sb); if (p_fs->dev_ejected) { pr_info("[EXFAT] unmounted with media errors. Device is already ejected.\n"); - err = FFS_MEDIAERR; + err = -EIO; } - buf_shutdown(sb); + exfat_buf_shutdown(sb); /* release the lock for file system critical section */ - up(&p_fs->v_sem); - up(&z_sem); + mutex_unlock(&p_fs->v_mutex); + mutex_unlock(&z_mutex); pr_info("[EXFAT] unmounted successfully\n"); @@ -491,15 +481,15 @@ static int ffsUmountVol(struct super_block *sb) static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info) { - int err = FFS_SUCCESS; + int err = 0; struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); /* check the validity of pointer parameters */ if (!info) - return FFS_ERROR; + return -EINVAL; /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); if (p_fs->used_clusters == UINT_MAX) p_fs->used_clusters = p_fs->fs_func->count_used_clusters(sb); @@ -511,31 +501,31 @@ static int ffsGetVolInfo(struct super_block *sb, struct vol_info_t *info) info->FreeClusters = info->NumClusters - info->UsedClusters; if (p_fs->dev_ejected) - err = FFS_MEDIAERR; + err = -EIO; /* release the lock for file system critical section */ - up(&p_fs->v_sem); + mutex_unlock(&p_fs->v_mutex); return err; } static int ffsSyncVol(struct super_block *sb, bool do_sync) { - int err = FFS_SUCCESS; + int err = 0; struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); /* synchronize the file system */ fs_sync(sb, do_sync); fs_set_vol_flags(sb, VOL_CLEAN); if (p_fs->dev_ejected) - err = FFS_MEDIAERR; + err = -EIO; /* release the lock for file system critical section */ - up(&p_fs->v_sem); + mutex_unlock(&p_fs->v_mutex); return err; } @@ -559,10 +549,10 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid) /* check the validity of pointer parameters */ if (!fid || !path || (*path == '\0')) - return FFS_ERROR; + return -EINVAL; /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); /* check the validity of directory name in the given pathname */ ret = resolve_path(inode, path, &dir, &uni_name); @@ -578,7 +568,7 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid) dentry = p_fs->fs_func->find_dir_entry(sb, &dir, &uni_name, num_entries, &dos_name, TYPE_ALL); if (dentry < -1) { - ret = FFS_NOTFOUND; + ret = -ENOENT; goto out; } @@ -597,22 +587,13 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid) fid->size = 0; fid->start_clu = p_fs->root_dir; } else { - if (p_fs->vol_type == EXFAT) { - es = get_entry_set_in_dir(sb, &dir, dentry, - ES_2_ENTRIES, &ep); - if (!es) { - ret = FFS_MEDIAERR; - goto out; - } - ep2 = ep + 1; - } else { - ep = get_entry_in_dir(sb, &dir, dentry, NULL); - if (!ep) { - ret = FFS_MEDIAERR; - goto out; - } - ep2 = ep; + es = get_entry_set_in_dir(sb, &dir, dentry, + ES_2_ENTRIES, &ep); + if (!es) { + ret = -ENOENT; + goto out; } + ep2 = ep + 1; fid->type = p_fs->fs_func->get_entry_type(ep); fid->rwoffset = 0; @@ -628,15 +609,14 @@ static int ffsLookupFile(struct inode *inode, char *path, struct file_id_t *fid) fid->start_clu = p_fs->fs_func->get_entry_clu0(ep2); } - if (p_fs->vol_type == EXFAT) - release_entry_set(es); + release_entry_set(es); } if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; out: /* release the lock for file system critical section */ - up(&p_fs->v_sem); + mutex_unlock(&p_fs->v_mutex); return ret; } @@ -648,14 +628,14 @@ static int ffsCreateFile(struct inode *inode, char *path, u8 mode, struct uni_name_t uni_name; struct super_block *sb = inode->i_sb; struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); - int ret; + int ret = 0; /* check the validity of pointer parameters */ if (!fid || !path || (*path == '\0')) - return FFS_ERROR; + return -EINVAL; /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); /* check the validity of directory name in the given pathname */ ret = resolve_path(inode, path, &dir, &uni_name); @@ -667,17 +647,17 @@ static int ffsCreateFile(struct inode *inode, char *path, u8 mode, /* create a new file */ ret = create_file(inode, &dir, &uni_name, mode, fid); -#ifdef CONFIG_EXFAT_DELAYED_SYNC - fs_sync(sb, false); +#ifndef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); #endif if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; out: /* release the lock for file system critical section */ - up(&p_fs->v_sem); + mutex_unlock(&p_fs->v_mutex); return ret; } @@ -697,18 +677,18 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer, /* check the validity of the given file id */ if (!fid) - return FFS_INVALIDFID; + return -EINVAL; /* check the validity of pointer parameters */ if (!buffer) - return FFS_ERROR; + return -EINVAL; /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); /* check if the given file ID is opened */ if (fid->type != TYPE_FILE) { - ret = FFS_PERMISSIONERR; + ret = -EPERM; goto out; } @@ -721,7 +701,7 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer, if (count == 0) { if (rcount) *rcount = 0; - ret = FFS_EOF; + ret = 0; goto out; } @@ -742,9 +722,11 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer, } while (clu_offset > 0) { - /* clu = FAT_read(sb, clu); */ - if (FAT_read(sb, clu, &clu) == -1) - return FFS_MEDIAERR; + /* clu = exfat_fat_read(sb, clu); */ + if (exfat_fat_read(sb, clu, &clu) == -1) { + ret = -EIO; + goto out; + } clu_offset--; } @@ -772,13 +754,13 @@ static int ffsReadFile(struct inode *inode, struct file_id_t *fid, void *buffer, if ((offset == 0) && (oneblkread == p_bd->sector_size)) { if (sector_read(sb, LogSector, &tmp_bh, 1) != - FFS_SUCCESS) + 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) != - FFS_SUCCESS) + 0) goto err_out; memcpy((char *)buffer + read_bytes, (char *)tmp_bh->b_data + offset, @@ -797,11 +779,11 @@ err_out: *rcount = read_bytes; if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; out: /* release the lock for file system critical section */ - up(&p_fs->v_sem); + mutex_unlock(&p_fs->v_mutex); return ret; } @@ -814,7 +796,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, s32 num_clusters, num_alloc, num_alloced = (s32)~0; int ret = 0; u32 clu, last_clu; - sector_t LogSector, sector = 0; + sector_t LogSector; u64 oneblkwrite, write_bytes; struct chain_t new_clu; struct timestamp_t tm; @@ -827,18 +809,18 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, /* check the validity of the given file id */ if (!fid) - return FFS_INVALIDFID; + return -EINVAL; /* check the validity of pointer parameters */ if (!buffer) - return FFS_ERROR; + return -EINVAL; /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); /* check if the given file ID is opened */ if (fid->type != TYPE_FILE) { - ret = FFS_PERMISSIONERR; + ret = -EPERM; goto out; } @@ -848,7 +830,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, if (count == 0) { if (wcount) *wcount = 0; - ret = FFS_SUCCESS; + ret = 0; goto out; } @@ -864,7 +846,8 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, while (count > 0) { clu_offset = (s32)(fid->rwoffset >> p_fs->cluster_size_bits); - clu = last_clu = fid->start_clu; + clu = fid->start_clu; + last_clu = fid->start_clu; if (fid->flags == 0x03) { if ((clu_offset > 0) && (clu != CLUSTER_32(~0))) { @@ -885,9 +868,9 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, while ((clu_offset > 0) && (clu != CLUSTER_32(~0))) { last_clu = clu; - /* clu = FAT_read(sb, clu); */ - if (FAT_read(sb, clu, &clu) == -1) { - ret = FFS_MEDIAERR; + /* clu = exfat_fat_read(sb, clu); */ + if (exfat_fat_read(sb, clu, &clu) == -1) { + ret = -EIO; goto out; } clu_offset--; @@ -909,7 +892,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, if (num_alloced == 0) break; if (num_alloced < 0) { - ret = FFS_MEDIAERR; + ret = num_alloced; goto out; } @@ -928,7 +911,7 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, modified = true; } if (new_clu.flags == 0x01) - FAT_write(sb, last_clu, new_clu.dir); + exfat_fat_write(sb, last_clu, new_clu.dir); } num_clusters += num_alloced; @@ -957,12 +940,12 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, if ((offset == 0) && (oneblkwrite == p_bd->sector_size)) { if (sector_read(sb, LogSector, &tmp_bh, 0) != - FFS_SUCCESS) + 0) goto err_out; memcpy((char *)tmp_bh->b_data, (char *)buffer + write_bytes, (s32)oneblkwrite); if (sector_write(sb, LogSector, tmp_bh, 0) != - FFS_SUCCESS) { + 0) { brelse(tmp_bh); goto err_out; } @@ -970,18 +953,18 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, if ((offset > 0) || ((fid->rwoffset + oneblkwrite) < fid->size)) { if (sector_read(sb, LogSector, &tmp_bh, 1) != - FFS_SUCCESS) + 0) goto err_out; } else { if (sector_read(sb, LogSector, &tmp_bh, 0) != - FFS_SUCCESS) + 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) != - FFS_SUCCESS) { + 0) { brelse(tmp_bh); goto err_out; } @@ -1002,25 +985,15 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, brelse(tmp_bh); /* (3) update the direcoty entry */ - if (p_fs->vol_type == EXFAT) { - es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, - ES_ALL_ENTRIES, &ep); - if (!es) - goto err_out; - ep2 = ep + 1; - } else { - ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); - if (!ep) - goto err_out; - ep2 = ep; - } + es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, + ES_ALL_ENTRIES, &ep); + if (!es) + goto err_out; + ep2 = ep + 1; p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY); p_fs->fs_func->set_entry_attr(ep, fid->attr); - if (p_fs->vol_type != EXFAT) - buf_modify(sb, sector); - if (modified) { if (p_fs->fs_func->get_entry_flag(ep2) != fid->flags) p_fs->fs_func->set_entry_flag(ep2, fid->flags); @@ -1030,18 +1003,13 @@ static int ffsWriteFile(struct inode *inode, struct file_id_t *fid, if (p_fs->fs_func->get_entry_clu0(ep2) != fid->start_clu) p_fs->fs_func->set_entry_clu0(ep2, fid->start_clu); - - if (p_fs->vol_type != EXFAT) - buf_modify(sb, sector); } - if (p_fs->vol_type == EXFAT) { - update_dir_checksum_with_entry_set(sb, es); - release_entry_set(es); - } + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); -#ifdef CONFIG_EXFAT_DELAYED_SYNC - fs_sync(sb, false); +#ifndef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); #endif @@ -1051,14 +1019,14 @@ err_out: *wcount = write_bytes; if (num_alloced == 0) - ret = FFS_FULL; + ret = -ENOSPC; else if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; out: /* release the lock for file system critical section */ - up(&p_fs->v_sem); + mutex_unlock(&p_fs->v_mutex); return ret; } @@ -1068,7 +1036,6 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) s32 num_clusters; u32 last_clu = CLUSTER_32(0); int ret = 0; - sector_t sector = 0; struct chain_t clu; struct timestamp_t tm; struct dentry_t *ep, *ep2; @@ -1081,11 +1048,11 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) new_size); /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); /* check if the given file ID is opened */ if (fid->type != TYPE_FILE) { - ret = FFS_PERMISSIONERR; + ret = -EPERM; goto out; } @@ -1095,7 +1062,7 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) } if (old_size <= new_size) { - ret = FFS_SUCCESS; + ret = 0; goto out; } @@ -1114,8 +1081,8 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) } else { while (num_clusters > 0) { last_clu = clu.dir; - if (FAT_read(sb, clu.dir, &clu.dir) == -1) { - ret = FFS_MEDIAERR; + if (exfat_fat_read(sb, clu.dir, &clu.dir) == -1) { + ret = -EIO; goto out; } num_clusters--; @@ -1133,22 +1100,13 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) } /* (1) update the directory entry */ - if (p_fs->vol_type == EXFAT) { - es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, - ES_ALL_ENTRIES, &ep); - if (!es) { - ret = FFS_MEDIAERR; - goto out; - } - ep2 = ep + 1; - } else { - ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); - if (!ep) { - ret = FFS_MEDIAERR; - goto out; + es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, + ES_ALL_ENTRIES, &ep); + if (!es) { + ret = -ENOENT; + goto out; } - ep2 = ep; - } + ep2 = ep + 1; p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY); p_fs->fs_func->set_entry_attr(ep, fid->attr); @@ -1159,17 +1117,13 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) p_fs->fs_func->set_entry_clu0(ep2, CLUSTER_32(0)); } - if (p_fs->vol_type != EXFAT) { - buf_modify(sb, sector); - } else { - update_dir_checksum_with_entry_set(sb, es); - release_entry_set(es); - } + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); /* (2) cut off from the FAT chain */ if (last_clu != CLUSTER_32(0)) { if (fid->flags == 0x01) - FAT_write(sb, last_clu, CLUSTER_32(~0)); + exfat_fat_write(sb, last_clu, CLUSTER_32(~0)); } /* (3) free the clusters */ @@ -1180,18 +1134,18 @@ static int ffsTruncateFile(struct inode *inode, u64 old_size, u64 new_size) if (fid->rwoffset > fid->size) fid->rwoffset = fid->size; -#ifdef CONFIG_EXFAT_DELAYED_SYNC - fs_sync(sb, false); +#ifndef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); #endif if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; out: pr_debug("%s exited (%d)\n", __func__, ret); /* release the lock for file system critical section */ - up(&p_fs->v_sem); + mutex_unlock(&p_fs->v_mutex); return ret; } @@ -1232,14 +1186,14 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid, /* check the validity of the given file id */ if (!fid) - return FFS_INVALIDFID; + return -EINVAL; /* check the validity of pointer parameters */ if (!new_path || (*new_path == '\0')) - return FFS_ERROR; + return -EINVAL; /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); update_parent_info(fid, old_parent_inode); @@ -1252,19 +1206,19 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid, /* check if the old file is "." or ".." */ if (p_fs->vol_type != EXFAT) { if ((olddir.dir != p_fs->root_dir) && (dentry < 2)) { - ret = FFS_PERMISSIONERR; + ret = -EPERM; goto out2; } } ep = get_entry_in_dir(sb, &olddir, dentry, NULL); if (!ep) { - ret = FFS_MEDIAERR; + ret = -ENOENT; goto out2; } if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) { - ret = FFS_PERMISSIONERR; + ret = -EPERM; goto out2; } @@ -1272,12 +1226,12 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid, if (new_inode) { u32 entry_type; - ret = FFS_MEDIAERR; + ret = -ENOENT; new_fid = &EXFAT_I(new_inode)->fid; update_parent_info(new_fid, new_parent_inode); - p_dir = &(new_fid->dir); + p_dir = &new_fid->dir; new_entry = new_fid->entry; ep = get_entry_in_dir(sb, p_dir, new_entry, NULL); if (!ep) @@ -1294,7 +1248,7 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid, new_clu.flags = new_fid->flags; if (!is_dir_empty(sb, &new_clu)) { - ret = FFS_FILEEXIST; + ret = -EEXIST; goto out; } } @@ -1308,13 +1262,13 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid, fs_set_vol_flags(sb, VOL_DIRTY); if (olddir.dir == newdir.dir) - ret = rename_file(new_parent_inode, &olddir, dentry, &uni_name, - fid); + ret = exfat_rename_file(new_parent_inode, &olddir, dentry, + &uni_name, fid); else ret = move_file(new_parent_inode, &olddir, dentry, &newdir, &uni_name, fid); - if ((ret == FFS_SUCCESS) && new_inode) { + if ((ret == 0) && new_inode) { /* delete entries of new_dir */ ep = get_entry_in_dir(sb, p_dir, new_entry, NULL); if (!ep) @@ -1328,16 +1282,16 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid, num_entries + 1); } out: -#ifdef CONFIG_EXFAT_DELAYED_SYNC - fs_sync(sb, false); +#ifndef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); #endif if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; out2: /* release the lock for file system critical section */ - up(&p_fs->v_sem); + mutex_unlock(&p_fs->v_mutex); return ret; } @@ -1345,7 +1299,7 @@ out2: static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid) { s32 dentry; - int ret = FFS_SUCCESS; + int ret = 0; struct chain_t dir, clu_to_free; struct dentry_t *ep; struct super_block *sb = inode->i_sb; @@ -1353,10 +1307,10 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid) /* check the validity of the given file id */ if (!fid) - return FFS_INVALIDFID; + return -EINVAL; /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); dir.dir = fid->dir.dir; dir.size = fid->dir.size; @@ -1366,12 +1320,12 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid) ep = get_entry_in_dir(sb, &dir, dentry, NULL); if (!ep) { - ret = FFS_MEDIAERR; + ret = -ENOENT; goto out; } if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) { - ret = FFS_PERMISSIONERR; + ret = -EPERM; goto out; } fs_set_vol_flags(sb, VOL_DIRTY); @@ -1390,16 +1344,16 @@ static int ffsRemoveFile(struct inode *inode, struct file_id_t *fid) fid->start_clu = CLUSTER_32(~0); fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; -#ifdef CONFIG_EXFAT_DELAYED_SYNC - fs_sync(sb, false); +#ifndef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); #endif if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; out: /* release the lock for file system critical section */ - up(&p_fs->v_sem); + mutex_unlock(&p_fs->v_mutex); return ret; } @@ -1409,7 +1363,7 @@ out: static int ffsSetAttr(struct inode *inode, u32 attr) { u32 type; - int ret = FFS_SUCCESS; + int ret = 0; sector_t sector = 0; struct dentry_t *ep; struct super_block *sb = inode->i_sb; @@ -1420,36 +1374,28 @@ static int ffsSetAttr(struct inode *inode, u32 attr) if (fid->attr == attr) { if (p_fs->dev_ejected) - return FFS_MEDIAERR; - return FFS_SUCCESS; + return -EIO; + return 0; } if (is_dir) { if ((fid->dir.dir == p_fs->root_dir) && (fid->entry == -1)) { if (p_fs->dev_ejected) - return FFS_MEDIAERR; - return FFS_SUCCESS; + return -EIO; + return 0; } } /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); /* get the directory entry of given file */ - if (p_fs->vol_type == EXFAT) { - es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, - ES_ALL_ENTRIES, &ep); - if (!es) { - ret = FFS_MEDIAERR; - goto out; - } - } else { - ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); - if (!ep) { - ret = FFS_MEDIAERR; - goto out; - } + es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, + ES_ALL_ENTRIES, &ep); + if (!es) { + ret = -ENOENT; + goto out; } type = p_fs->fs_func->get_entry_type(ep); @@ -1457,12 +1403,11 @@ static int ffsSetAttr(struct inode *inode, u32 attr) if (((type == TYPE_FILE) && (attr & ATTR_SUBDIR)) || ((type == TYPE_DIR) && (!(attr & ATTR_SUBDIR)))) { if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; else - ret = FFS_ERROR; + ret = -EINVAL; - if (p_fs->vol_type == EXFAT) - release_entry_set(es); + release_entry_set(es); goto out; } @@ -1472,23 +1417,19 @@ static int ffsSetAttr(struct inode *inode, u32 attr) fid->attr = attr; p_fs->fs_func->set_entry_attr(ep, attr); - if (p_fs->vol_type != EXFAT) { - buf_modify(sb, sector); - } else { - update_dir_checksum_with_entry_set(sb, es); - release_entry_set(es); - } + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); -#ifdef CONFIG_EXFAT_DELAYED_SYNC - fs_sync(sb, false); +#ifndef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); #endif if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; out: /* release the lock for file system critical section */ - up(&p_fs->v_sem); + mutex_unlock(&p_fs->v_mutex); return ret; } @@ -1496,9 +1437,8 @@ out: static int ffsReadStat(struct inode *inode, struct dir_entry_t *info) { - sector_t sector = 0; s32 count; - int ret = FFS_SUCCESS; + int ret = 0; struct chain_t dir; struct uni_name_t uni_name; struct timestamp_t tm; @@ -1512,7 +1452,7 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info) pr_debug("%s entered\n", __func__); /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); if (is_dir) { if ((fid->dir.dir == p_fs->root_dir) && @@ -1541,35 +1481,25 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info) count = count_dos_name_entries(sb, &dir, TYPE_DIR); if (count < 0) { - ret = FFS_MEDIAERR; + ret = count; /* propogate error upward */ goto out; } info->NumSubdirs = count; if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; goto out; } } /* get the directory entry of given file or directory */ - if (p_fs->vol_type == EXFAT) { - es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, - ES_2_ENTRIES, &ep); - if (!es) { - ret = FFS_MEDIAERR; - goto out; - } - ep2 = ep + 1; - } else { - ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); - if (!ep) { - ret = FFS_MEDIAERR; - goto out; - } - ep2 = ep; - buf_lock(sb, sector); + es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, + ES_2_ENTRIES, &ep); + if (!es) { + ret = -ENOENT; + goto out; } + ep2 = ep + 1; /* set FILE_INFO structure using the acquired struct dentry_t */ info->Attr = p_fs->fs_func->get_entry_attr(ep); @@ -1594,31 +1524,19 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info) memset((char *)&info->AccessTimestamp, 0, sizeof(struct date_time_t)); - *(uni_name.name) = 0x0; + *uni_name.name = 0x0; /* XXX this is very bad for exfat cuz name is already included in es. * API should be revised */ - p_fs->fs_func->get_uni_name_from_ext_entry(sb, &(fid->dir), fid->entry, + p_fs->fs_func->get_uni_name_from_ext_entry(sb, &fid->dir, fid->entry, uni_name.name); - if (*uni_name.name == 0x0 && p_fs->vol_type != EXFAT) - get_uni_name_from_dos_entry(sb, (struct dos_dentry_t *)ep, - &uni_name, 0x1); nls_uniname_to_cstring(sb, info->Name, &uni_name); - if (p_fs->vol_type == EXFAT) { - info->NumSubdirs = 2; - } else { - buf_unlock(sb, sector); - get_uni_name_from_dos_entry(sb, (struct dos_dentry_t *)ep, - &uni_name, 0x0); - nls_uniname_to_cstring(sb, info->ShortName, &uni_name); - info->NumSubdirs = 0; - } + info->NumSubdirs = 2; info->Size = p_fs->fs_func->get_entry_size(ep2); - if (p_fs->vol_type == EXFAT) - release_entry_set(es); + release_entry_set(es); if (is_dir) { dir.dir = fid->start_clu; @@ -1630,18 +1548,18 @@ static int ffsReadStat(struct inode *inode, struct dir_entry_t *info) count = count_dos_name_entries(sb, &dir, TYPE_DIR); if (count < 0) { - ret = FFS_MEDIAERR; + ret = count; /* propogate error upward */ goto out; } info->NumSubdirs += count; } if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; out: /* release the lock for file system critical section */ - up(&p_fs->v_sem); + mutex_unlock(&p_fs->v_mutex); pr_debug("%s exited successfully\n", __func__); return ret; @@ -1649,8 +1567,7 @@ out: static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info) { - sector_t sector = 0; - int ret = FFS_SUCCESS; + int ret = 0; struct timestamp_t tm; struct dentry_t *ep, *ep2; struct entry_set_cache_t *es = NULL; @@ -1662,14 +1579,14 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info) pr_debug("%s entered (inode %p info %p\n", __func__, inode, info); /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); if (is_dir) { if ((fid->dir.dir == p_fs->root_dir) && (fid->entry == -1)) { if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; - ret = FFS_SUCCESS; + ret = -EIO; + ret = 0; goto out; } } @@ -1677,23 +1594,13 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info) fs_set_vol_flags(sb, VOL_DIRTY); /* get the directory entry of given file or directory */ - if (p_fs->vol_type == EXFAT) { - es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, - ES_ALL_ENTRIES, &ep); - if (!es) { - ret = FFS_MEDIAERR; - goto out; - } - ep2 = ep + 1; - } else { - /* for other than exfat */ - ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); - if (!ep) { - ret = FFS_MEDIAERR; - goto out; - } - ep2 = ep; + es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, + ES_ALL_ENTRIES, &ep); + if (!es) { + ret = -ENOENT; + goto out; } + ep2 = ep + 1; p_fs->fs_func->set_entry_attr(ep, info->Attr); @@ -1716,19 +1623,15 @@ static int ffsWriteStat(struct inode *inode, struct dir_entry_t *info) p_fs->fs_func->set_entry_size(ep2, info->Size); - if (p_fs->vol_type != EXFAT) { - buf_modify(sb, sector); - } else { - update_dir_checksum_with_entry_set(sb, es); - release_entry_set(es); - } + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; out: /* release the lock for file system critical section */ - up(&p_fs->v_sem); + mutex_unlock(&p_fs->v_mutex); pr_debug("%s exited (%d)\n", __func__, ret); @@ -1740,8 +1643,7 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) s32 num_clusters, num_alloced; bool modified = false; u32 last_clu; - int ret = FFS_SUCCESS; - sector_t sector = 0; + int ret = 0; struct chain_t new_clu; struct dentry_t *ep; struct entry_set_cache_t *es = NULL; @@ -1751,10 +1653,10 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) /* check the validity of pointer parameters */ if (!clu) - return FFS_ERROR; + return -EINVAL; /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); fid->rwoffset = (s64)(clu_offset) << p_fs->cluster_size_bits; @@ -1785,8 +1687,8 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) while ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) { last_clu = *clu; - if (FAT_read(sb, *clu, clu) == -1) { - ret = FFS_MEDIAERR; + if (exfat_fat_read(sb, *clu, clu) == -1) { + ret = -EIO; goto out; } clu_offset--; @@ -1804,10 +1706,10 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) /* (1) allocate a cluster */ num_alloced = p_fs->fs_func->alloc_cluster(sb, 1, &new_clu); if (num_alloced < 0) { - ret = FFS_MEDIAERR; + ret = -EIO; goto out; } else if (num_alloced == 0) { - ret = FFS_FULL; + ret = -ENOSPC; goto out; } @@ -1825,34 +1727,23 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) modified = true; } if (new_clu.flags == 0x01) - FAT_write(sb, last_clu, new_clu.dir); + exfat_fat_write(sb, last_clu, new_clu.dir); } num_clusters += num_alloced; *clu = new_clu.dir; - if (p_fs->vol_type == EXFAT) { - es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, - ES_ALL_ENTRIES, &ep); - if (!es) { - ret = FFS_MEDIAERR; - goto out; - } - /* get stream entry */ - ep++; + es = get_entry_set_in_dir(sb, &fid->dir, fid->entry, + ES_ALL_ENTRIES, &ep); + if (!es) { + ret = -ENOENT; + goto out; } + /* get stream entry */ + ep++; /* (3) update directory entry */ if (modified) { - if (p_fs->vol_type != EXFAT) { - ep = get_entry_in_dir(sb, &(fid->dir), - fid->entry, §or); - if (!ep) { - ret = FFS_MEDIAERR; - goto out; - } - } - if (p_fs->fs_func->get_entry_flag(ep) != fid->flags) p_fs->fs_func->set_entry_flag(ep, fid->flags); @@ -1860,14 +1751,10 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) p_fs->fs_func->set_entry_clu0(ep, fid->start_clu); - if (p_fs->vol_type != EXFAT) - buf_modify(sb, sector); } - if (p_fs->vol_type == EXFAT) { - update_dir_checksum_with_entry_set(sb, es); - release_entry_set(es); - } + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); /* add number of new blocks to inode */ inode->i_blocks += num_alloced << (p_fs->cluster_size_bits - 9); @@ -1878,11 +1765,11 @@ static int ffsMapCluster(struct inode *inode, s32 clu_offset, u32 *clu) fid->hint_last_clu = *clu; if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; out: /* release the lock for file system critical section */ - up(&p_fs->v_sem); + mutex_unlock(&p_fs->v_mutex); return ret; } @@ -1893,7 +1780,7 @@ out: static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid) { - int ret = FFS_SUCCESS; + int ret = 0; struct chain_t dir; struct uni_name_t uni_name; struct super_block *sb = inode->i_sb; @@ -1903,10 +1790,10 @@ static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid) /* check the validity of pointer parameters */ if (!fid || !path || (*path == '\0')) - return FFS_ERROR; + return -EINVAL; /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); /* check the validity of directory name in the given old pathname */ ret = resolve_path(inode, path, &dir, &uni_name); @@ -1917,16 +1804,16 @@ static int ffsCreateDir(struct inode *inode, char *path, struct file_id_t *fid) ret = create_dir(inode, &dir, &uni_name, fid); -#ifdef CONFIG_EXFAT_DELAYED_SYNC - fs_sync(sb, false); +#ifndef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); #endif if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; out: /* release the lock for file system critical section */ - up(&p_fs->v_sem); + mutex_unlock(&p_fs->v_mutex); return ret; } @@ -1934,7 +1821,7 @@ out: static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) { int i, dentry, clu_offset; - int ret = FFS_SUCCESS; + int ret = 0; s32 dentries_per_clu, dentries_per_clu_bits = 0; u32 type; sector_t sector; @@ -1949,14 +1836,14 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) /* check the validity of pointer parameters */ if (!dir_entry) - return FFS_ERROR; + return -EINVAL; /* check if the given file ID is opened */ if (fid->type != TYPE_DIR) - return FFS_PERMISSIONERR; + return -ENOTDIR; /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); if (fid->entry == -1) { dir.dir = p_fs->root_dir; @@ -2001,9 +1888,9 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) } while (clu_offset > 0) { - /* clu.dir = FAT_read(sb, clu.dir); */ - if (FAT_read(sb, clu.dir, &clu.dir) == -1) { - ret = FFS_MEDIAERR; + /* clu.dir = exfat_fat_read(sb, clu.dir); */ + if (exfat_fat_read(sb, clu.dir, &clu.dir) == -1) { + ret = -EIO; goto out; } clu_offset--; @@ -2023,7 +1910,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) for ( ; i < dentries_per_clu; i++, dentry++) { ep = get_entry_in_dir(sb, &clu, i, §or); if (!ep) { - ret = FFS_MEDIAERR; + ret = -ENOENT; goto out; } type = fs_func->get_entry_type(ep); @@ -2034,7 +1921,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) if ((type != TYPE_FILE) && (type != TYPE_DIR)) continue; - buf_lock(sb, sector); + exfat_buf_lock(sb, sector); dir_entry->Attr = fs_func->get_entry_attr(ep); fs_func->get_entry_time(ep, &tm, TM_CREATE); @@ -2058,28 +1945,16 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) memset((char *)&dir_entry->AccessTimestamp, 0, sizeof(struct date_time_t)); - *(uni_name.name) = 0x0; + *uni_name.name = 0x0; fs_func->get_uni_name_from_ext_entry(sb, &dir, dentry, uni_name.name); - if (*uni_name.name == 0x0 && p_fs->vol_type != EXFAT) - get_uni_name_from_dos_entry(sb, - (struct dos_dentry_t *)ep, - &uni_name, 0x1); nls_uniname_to_cstring(sb, dir_entry->Name, &uni_name); - buf_unlock(sb, sector); + exfat_buf_unlock(sb, sector); - if (p_fs->vol_type == EXFAT) { - ep = get_entry_in_dir(sb, &clu, i + 1, NULL); - if (!ep) { - ret = FFS_MEDIAERR; - goto out; - } - } else { - get_uni_name_from_dos_entry(sb, - (struct dos_dentry_t *)ep, - &uni_name, 0x0); - nls_uniname_to_cstring(sb, dir_entry->ShortName, - &uni_name); + ep = get_entry_in_dir(sb, &clu, i + 1, NULL); + if (!ep) { + ret = -ENOENT; + goto out; } dir_entry->Size = fs_func->get_entry_size(ep); @@ -2095,7 +1970,7 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) fid->rwoffset = (s64)(++dentry); if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; goto out; } @@ -2108,24 +1983,24 @@ static int ffsReadDir(struct inode *inode, struct dir_entry_t *dir_entry) else clu.dir = CLUSTER_32(~0); } else { - /* clu.dir = FAT_read(sb, clu.dir); */ - if (FAT_read(sb, clu.dir, &clu.dir) == -1) { - ret = FFS_MEDIAERR; + /* clu.dir = exfat_fat_read(sb, clu.dir); */ + if (exfat_fat_read(sb, clu.dir, &clu.dir) == -1) { + ret = -EIO; goto out; } } } - *(dir_entry->Name) = '\0'; + *dir_entry->Name = '\0'; fid->rwoffset = (s64)(++dentry); if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; out: /* release the lock for file system critical section */ - up(&p_fs->v_sem); + mutex_unlock(&p_fs->v_mutex); return ret; } @@ -2133,14 +2008,14 @@ out: static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid) { s32 dentry; - int ret = FFS_SUCCESS; + int ret = 0; struct chain_t dir, clu_to_free; struct super_block *sb = inode->i_sb; struct fs_info_t *p_fs = &(EXFAT_SB(sb)->fs_info); /* check the validity of the given file id */ if (!fid) - return FFS_INVALIDFID; + return -EINVAL; dir.dir = fid->dir.dir; dir.size = fid->dir.size; @@ -2151,18 +2026,18 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid) /* check if the file is "." or ".." */ if (p_fs->vol_type != EXFAT) { if ((dir.dir != p_fs->root_dir) && (dentry < 2)) - return FFS_PERMISSIONERR; + return -EPERM; } /* acquire the lock for file system critical section */ - down(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); clu_to_free.dir = fid->start_clu; clu_to_free.size = (s32)((fid->size - 1) >> p_fs->cluster_size_bits) + 1; clu_to_free.flags = fid->flags; if (!is_dir_empty(sb, &clu_to_free)) { - ret = FFS_FILEEXIST; + ret = -ENOTEMPTY; goto out; } @@ -2178,17 +2053,17 @@ static int ffsRemoveDir(struct inode *inode, struct file_id_t *fid) fid->start_clu = CLUSTER_32(~0); fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; -#ifdef CONFIG_EXFAT_DELAYED_SYNC - fs_sync(sb, false); +#ifndef CONFIG_EXFAT_DELAYED_SYNC + fs_sync(sb, true); fs_set_vol_flags(sb, VOL_CLEAN); #endif if (p_fs->dev_ejected) - ret = FFS_MEDIAERR; + ret = -EIO; out: /* release the lock for file system critical section */ - up(&p_fs->v_sem); + mutex_unlock(&p_fs->v_mutex); return ret; } @@ -2202,7 +2077,7 @@ static int exfat_readdir(struct file *filp, struct dir_context *ctx) struct inode *inode = file_inode(filp); struct super_block *sb = inode->i_sb; struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct fs_info_t *p_fs = &(sbi->fs_info); + struct fs_info_t *p_fs = &sbi->fs_info; struct bd_info_t *p_bd = &(EXFAT_SB(sb)->bd_info); struct dir_entry_t de; unsigned long inum; @@ -2244,12 +2119,11 @@ get_new: /* at least we tried to read a sector * move cpos to next sector position (should be aligned) */ - if (err == FFS_MEDIAERR) { + if (err == -EIO) { cpos += 1 << p_bd->sector_size_bits; cpos &= ~((1 << p_bd->sector_size_bits) - 1); } - err = -EIO; goto end_of_dir; } @@ -2293,7 +2167,7 @@ static int exfat_ioctl_volume_id(struct inode *dir) { struct super_block *sb = dir->i_sb; struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct fs_info_t *p_fs = &(sbi->fs_info); + struct fs_info_t *p_fs = &sbi->fs_info; return p_fs->vol_id; } @@ -2301,7 +2175,7 @@ static int exfat_ioctl_volume_id(struct inode *dir) static long exfat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { -struct inode *inode = filp->f_path.dentry->d_inode; + struct inode *inode = filp->f_path.dentry->d_inode; #ifdef CONFIG_EXFAT_KERNEL_DEBUG unsigned int flags; #endif /* CONFIG_EXFAT_KERNEL_DEBUG */ @@ -2351,6 +2225,7 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) { struct super_block *sb = dir->i_sb; + struct timespec64 curtime; struct inode *inode; struct file_id_t fid; loff_t i_pos; @@ -2361,21 +2236,14 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, pr_debug("%s entered\n", __func__); err = ffsCreateFile(dir, (u8 *)dentry->d_name.name, FM_REGULAR, &fid); - if (err) { - if (err == FFS_INVALIDPATH) - err = -EINVAL; - else if (err == FFS_FILEEXIST) - err = -EEXIST; - else if (err == FFS_FULL) - err = -ENOSPC; - else if (err == FFS_NAMETOOLONG) - err = -ENAMETOOLONG; - else - err = -EIO; + if (err) goto out; - } + INC_IVERSION(dir); - dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(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 @@ -2389,7 +2257,10 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, goto out; } INC_IVERSION(inode); - inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(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 unnecessary. */ @@ -2522,6 +2393,7 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry) { struct inode *inode = dentry->d_inode; struct super_block *sb = dir->i_sb; + struct timespec64 curtime; int err; __lock_super(sb); @@ -2531,22 +2403,22 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry) EXFAT_I(inode)->fid.size = i_size_read(inode); err = ffsRemoveFile(dir, &(EXFAT_I(inode)->fid)); - if (err) { - if (err == FFS_PERMISSIONERR) - err = -EPERM; - else - err = -EIO; + if (err) goto out; - } + INC_IVERSION(dir); - dir->i_mtime = dir->i_atime = current_time(dir); + curtime = current_time(dir); + dir->i_mtime = curtime; + dir->i_atime = curtime; if (IS_DIRSYNC(dir)) (void)exfat_sync_inode(dir); else mark_inode_dirty(dir); clear_nlink(inode); - inode->i_mtime = inode->i_atime = current_time(inode); + curtime = current_time(inode); + inode->i_mtime = curtime; + inode->i_atime = curtime; exfat_detach(inode); remove_inode_hash(inode); @@ -2560,6 +2432,7 @@ 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; @@ -2572,32 +2445,22 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry, pr_debug("%s entered\n", __func__); err = ffsCreateFile(dir, (u8 *)dentry->d_name.name, FM_SYMLINK, &fid); - if (err) { - if (err == FFS_INVALIDPATH) - err = -EINVAL; - else if (err == FFS_FILEEXIST) - err = -EEXIST; - else if (err == FFS_FULL) - err = -ENOSPC; - else - err = -EIO; + if (err) goto out; - } + err = ffsWriteFile(dir, &fid, (char *)target, len, &ret); if (err) { ffsRemoveFile(dir, &fid); - - if (err == FFS_FULL) - err = -ENOSPC; - else - err = -EIO; goto out; } INC_IVERSION(dir); - dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(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 @@ -2611,7 +2474,10 @@ static int exfat_symlink(struct inode *dir, struct dentry *dentry, goto out; } INC_IVERSION(inode); - inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(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); @@ -2632,6 +2498,7 @@ out: static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { struct super_block *sb = dir->i_sb; + struct timespec64 curtime; struct inode *inode; struct file_id_t fid; loff_t i_pos; @@ -2642,21 +2509,14 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) pr_debug("%s entered\n", __func__); err = ffsCreateDir(dir, (u8 *)dentry->d_name.name, &fid); - if (err) { - if (err == FFS_INVALIDPATH) - err = -EINVAL; - else if (err == FFS_FILEEXIST) - err = -EEXIST; - else if (err == FFS_FULL) - err = -ENOSPC; - else if (err == FFS_NAMETOOLONG) - err = -ENAMETOOLONG; - else - err = -EIO; + if (err) goto out; - } + INC_IVERSION(dir); - dir->i_ctime = dir->i_mtime = dir->i_atime = current_time(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 @@ -2671,7 +2531,10 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) goto out; } INC_IVERSION(inode); - inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(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. */ dentry->d_time = GET_IVERSION(dentry->d_parent->d_inode); @@ -2687,6 +2550,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry) { struct inode *inode = dentry->d_inode; struct super_block *sb = dir->i_sb; + struct timespec64 curtime; int err; __lock_super(sb); @@ -2696,21 +2560,13 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry) EXFAT_I(inode)->fid.size = i_size_read(inode); err = ffsRemoveDir(dir, &(EXFAT_I(inode)->fid)); - if (err) { - if (err == FFS_INVALIDPATH) - err = -EINVAL; - else if (err == FFS_FILEEXIST) - err = -ENOTEMPTY; - else if (err == FFS_NOTFOUND) - err = -ENOENT; - else if (err == FFS_DIRBUSY) - err = -EBUSY; - else - err = -EIO; + if (err) goto out; - } + INC_IVERSION(dir); - dir->i_mtime = dir->i_atime = current_time(dir); + curtime = current_time(dir); + dir->i_mtime = curtime; + dir->i_atime = curtime; if (IS_DIRSYNC(dir)) (void)exfat_sync_inode(dir); else @@ -2718,7 +2574,9 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry) drop_nlink(dir); clear_nlink(inode); - inode->i_mtime = inode->i_atime = current_time(inode); + curtime = current_time(inode); + inode->i_mtime = curtime; + inode->i_atime = curtime; exfat_detach(inode); remove_inode_hash(inode); @@ -2734,6 +2592,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, { struct inode *old_inode, *new_inode; struct super_block *sb = old_dir->i_sb; + struct timespec64 curtime; loff_t i_pos; int err; @@ -2751,24 +2610,15 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, err = ffsMoveFile(old_dir, &(EXFAT_I(old_inode)->fid), new_dir, new_dentry); - if (err) { - if (err == FFS_PERMISSIONERR) - err = -EPERM; - else if (err == FFS_INVALIDPATH) - err = -EINVAL; - else if (err == FFS_FILEEXIST) - err = -EEXIST; - else if (err == FFS_NOTFOUND) - err = -ENOENT; - else if (err == FFS_FULL) - err = -ENOSPC; - else - err = -EIO; + if (err) goto out; - } + INC_IVERSION(new_dir); - new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = - current_time(new_dir); + curtime = current_time(new_dir); + new_dir->i_ctime = curtime; + new_dir->i_mtime = curtime; + new_dir->i_atime = curtime; + if (IS_DIRSYNC(new_dir)) (void)exfat_sync_inode(new_dir); else @@ -2790,7 +2640,9 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, inc_nlink(new_dir); } INC_IVERSION(old_dir); - old_dir->i_ctime = old_dir->i_mtime = current_time(old_dir); + curtime = current_time(old_dir); + old_dir->i_ctime = curtime; + old_dir->i_mtime = curtime; if (IS_DIRSYNC(old_dir)) (void)exfat_sync_inode(old_dir); else @@ -2814,13 +2666,16 @@ static int exfat_cont_expand(struct inode *inode, loff_t size) { struct address_space *mapping = inode->i_mapping; loff_t start = i_size_read(inode), count = size - i_size_read(inode); + struct timespec64 curtime; int err, err2; err = generic_cont_expand_simple(inode, size); if (err != 0) return err; - inode->i_ctime = inode->i_mtime = current_time(inode); + curtime = current_time(inode); + inode->i_ctime = curtime; + inode->i_mtime = curtime; mark_inode_dirty(inode); if (IS_SYNC(inode)) { @@ -2895,7 +2750,8 @@ static void exfat_truncate(struct inode *inode, loff_t old_size) { struct super_block *sb = inode->i_sb; struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct fs_info_t *p_fs = &(sbi->fs_info); + struct fs_info_t *p_fs = &sbi->fs_info; + struct timespec64 curtime; int err; __lock_super(sb); @@ -2914,7 +2770,9 @@ static void exfat_truncate(struct inode *inode, loff_t old_size) if (err) goto out; - inode->i_ctime = inode->i_mtime = current_time(inode); + curtime = current_time(inode); + inode->i_ctime = curtime; + inode->i_mtime = curtime; if (IS_DIRSYNC(inode)) (void)exfat_sync_inode(inode); else @@ -2936,8 +2794,8 @@ static int exfat_setattr(struct dentry *dentry, struct iattr *attr) pr_debug("%s entered\n", __func__); - if ((attr->ia_valid & ATTR_SIZE) - && (attr->ia_size > i_size_read(inode))) { + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size > i_size_read(inode)) { error = exfat_cont_expand(inode, attr->ia_size); if (error || attr->ia_valid == ATTR_SIZE) return error; @@ -2946,8 +2804,8 @@ static int exfat_setattr(struct dentry *dentry, struct iattr *attr) ia_valid = attr->ia_valid; - if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) - && exfat_allow_set_time(sbi, inode)) { + if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) && + exfat_allow_set_time(sbi, inode)) { attr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET); @@ -3073,8 +2931,7 @@ static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys, { struct super_block *sb = inode->i_sb; struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct fs_info_t *p_fs = &(sbi->fs_info); - struct bd_info_t *p_bd = &(sbi->bd_info); + struct fs_info_t *p_fs = &sbi->fs_info; const unsigned long blocksize = sb->s_blocksize; const unsigned char blocksize_bits = sb->s_blocksize_bits; sector_t last_block; @@ -3084,18 +2941,6 @@ static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys, *phys = 0; *mapped_blocks = 0; - if ((p_fs->vol_type == FAT12) || (p_fs->vol_type == FAT16)) { - if (inode->i_ino == EXFAT_ROOT_INO) { - if (sector < - (p_fs->dentries_in_root >> - (p_bd->sector_size_bits - DENTRY_SIZE_BITS))) { - *phys = sector + p_fs->root_start_sector; - *mapped_blocks = 1; - } - return 0; - } - } - last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits; if (sector >= last_block) { if (*create == 0) @@ -3114,12 +2959,7 @@ static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys, err = ffsMapCluster(inode, clu_offset, &cluster); - if (err) { - if (err == FFS_FULL) - return -ENOSPC; - else - return -EIO; - } else if (cluster != CLUSTER_32(~0)) { + if (!err && (cluster != CLUSTER_32(~0))) { *phys = START_SECTOR(cluster) + sec_offset; *mapped_blocks = p_fs->sectors_per_clu - sec_offset; } @@ -3215,6 +3055,7 @@ static int exfat_write_end(struct file *file, struct address_space *mapping, { struct inode *inode = mapping->host; struct file_id_t *fid = &(EXFAT_I(inode)->fid); + struct timespec64 curtime; int err; err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata); @@ -3223,7 +3064,9 @@ static int exfat_write_end(struct file *file, struct address_space *mapping, exfat_write_failed(mapping, pos + len); if (!(err < 0) && !(fid->attr & ATTR_ARCHIVE)) { - inode->i_mtime = inode->i_ctime = current_time(inode); + curtime = current_time(inode); + inode->i_mtime = curtime; + inode->i_ctime = curtime; fid->attr |= ATTR_ARCHIVE; mark_inode_dirty(inode); } @@ -3302,7 +3145,7 @@ static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos) static int exfat_fill_inode(struct inode *inode, struct file_id_t *fid) { struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); - struct fs_info_t *p_fs = &(sbi->fs_info); + struct fs_info_t *p_fs = &sbi->fs_info; struct dir_entry_t info; memcpy(&(EXFAT_I(inode)->fid), fid, sizeof(struct file_id_t)); @@ -3314,7 +3157,7 @@ static int exfat_fill_inode(struct inode *inode, struct file_id_t *fid) inode->i_uid = sbi->options.fs_uid; inode->i_gid = sbi->options.fs_gid; INC_IVERSION(inode); - inode->i_generation = get_seconds(); + inode->i_generation = prandom_u32(); if (info.Attr & ATTR_SUBDIR) { /* directory */ inode->i_generation &= ~1; @@ -3501,7 +3344,7 @@ static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf) struct vol_info_t info; if (p_fs->used_clusters == UINT_MAX) { - if (ffsGetVolInfo(sb, &info) == FFS_MEDIAERR) + if (ffsGetVolInfo(sb, &info) == -EIO) return -EIO; } else { @@ -3674,7 +3517,8 @@ static int parse_options(char *options, int silent, int *debug, opts->fs_uid = current_uid(); opts->fs_gid = current_gid(); - opts->fs_fmask = opts->fs_dmask = current->fs->umask; + opts->fs_fmask = current->fs->umask; + opts->fs_dmask = current->fs->umask; opts->allow_utime = U16_MAX; opts->codepage = exfat_default_codepage; opts->iocharset = exfat_default_iocharset; @@ -3787,7 +3631,8 @@ static int exfat_read_root(struct inode *inode) { struct super_block *sb = inode->i_sb; struct exfat_sb_info *sbi = EXFAT_SB(sb); - struct fs_info_t *p_fs = &(sbi->fs_info); + struct fs_info_t *p_fs = &sbi->fs_info; + struct timespec64 curtime; struct dir_entry_t info; EXFAT_I(inode)->fid.dir.dir = p_fs->root_dir; @@ -3818,7 +3663,10 @@ static int exfat_read_root(struct inode *inode) EXFAT_I(inode)->mmu_private = i_size_read(inode); exfat_save_attr(inode, ATTR_SUBDIR); - inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); + curtime = current_time(inode); + inode->i_mtime = curtime; + inode->i_atime = curtime; + inode->i_ctime = curtime; set_nlink(inode, info.NumSubdirs + 2); return 0; @@ -3838,7 +3686,6 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent) struct exfat_sb_info *sbi; int debug, ret; long error; - char buf[50]; /* * GFP_KERNEL is ok here, because while we do hold the @@ -3885,17 +3732,6 @@ static int exfat_fill_super(struct super_block *sb, void *data, int silent) * if (FAT_FIRST_ENT(sb, media) != first) */ - /* codepage is not meaningful in exfat */ - if (sbi->fs_info.vol_type != EXFAT) { - error = -EINVAL; - sprintf(buf, "cp%d", sbi->options.codepage); - sbi->nls_disk = load_nls(buf); - if (!sbi->nls_disk) { - pr_err("[EXFAT] Codepage %s not found\n", buf); - goto out_fail2; - } - } - sbi->nls_io = load_nls(sbi->options.iocharset); error = -ENOMEM; @@ -3984,10 +3820,10 @@ static void exfat_debug_kill_sb(struct super_block *sb) * invalidate_bdev drops all device cache include * dirty. We use this to simulate device removal. */ - down(&p_fs->v_sem); - FAT_release_all(sb); - buf_release_all(sb); - up(&p_fs->v_sem); + mutex_lock(&p_fs->v_mutex); + exfat_fat_release_all(sb); + exfat_buf_release_all(sb); + mutex_unlock(&p_fs->v_mutex); invalidate_bdev(bdev); } |