diff --git a/Kconfig b/Kconfig
index d31dd4b..2ab3e99 100644
--- a/Kconfig
+++ b/Kconfig
@@ -6,7 +6,7 @@ config SDFAT_FS
select NLS_CODEPAGE_437
select NLS_ISO8859_1
help
- If you want to use the sdFAT file system, then you must say Y or M
+ If you want to use the sdFAT file system, then you must say Y or M
here to inlucde sdFAT support.
sdFAT is unified FAT-based file system which supports not only fat12/
16/32 with vfat but also exfat. sdFAT supports winnt short-name rule.
@@ -21,12 +21,15 @@ config SDFAT_DELAYED_META_DIRTY
depends on SDFAT_FS
help
If you enable this feature, metadata(FAT/Directory entry) is updated
- by flush thread.
+ by flush thread.
config SDFAT_SUPPORT_DIR_SYNC
bool "Enable supporting dir sync"
default n
depends on SDFAT_FS
+ help
+ If you enable this feature, the modification for directory operation
+ is written to a storage at once.
config SDFAT_DEFAULT_CODEPAGE
int "Default codepage for sdFAT"
@@ -93,3 +96,8 @@ config SDFAT_DBG_BUGON
bool "enable strict BUG_ON() for debugging"
depends on SDFAT_FS && SDFAT_DEBUG
default n
+
+config SDFAT_STATISTICS
+ bool "enable statistics for bigdata"
+ depends on SDFAT_FS
+ default y
diff --git a/Makefile b/Makefile
index 6be6324..a5cd085 100644
--- a/Makefile
+++ b/Makefile
@@ -5,10 +5,11 @@
obj-$(CONFIG_SDFAT_FS) += sdfat_fs.o
sdfat_fs-objs := sdfat.o core.o core_fat.o core_exfat.o api.o blkdev.o \
- fatent.o amap_smart.o cache.o dfr.o nls.o misc.o xattr.o \
+ fatent.o amap_smart.o cache.o dfr.o nls.o misc.o \
mpage.o extent.o
-
+sdfat_fs-$(CONFIG_SDFAT_VIRTUAL_XATTR) += xattr.o
+sdfat_fs-$(CONFIG_SDFAT_STATISTICS) += statistics.o
all:
diff --git a/amap_smart.c b/amap_smart.c
index a86d5c6..99e32a6 100644
--- a/amap_smart.c
+++ b/amap_smart.c
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
/************************************************************************/
@@ -85,7 +83,7 @@ static inline int amap_remove_from_list(AU_INFO_T *au, struct slist_head *shead)
}
/* Full-linear serach => Find AU with max. number of fclu */
-static inline AU_INFO_T* amap_find_hot_au_largest(struct slist_head *shead)
+static inline AU_INFO_T *amap_find_hot_au_largest(struct slist_head *shead)
{
struct slist_head *iter;
uint16_t max_fclu = 0;
@@ -98,7 +96,7 @@ static inline AU_INFO_T* amap_find_hot_au_largest(struct slist_head *shead)
while (iter) {
entry = list_entry(iter, AU_INFO_T, shead);
-
+
if (entry->free_clusters > max_fclu) {
max_fclu = entry->free_clusters;
ret = entry;
@@ -111,8 +109,9 @@ static inline AU_INFO_T* amap_find_hot_au_largest(struct slist_head *shead)
}
/* Find partially used AU with max. number of fclu.
- If there is no partial AU available, pick a clean one */
-static inline AU_INFO_T* amap_find_hot_au_partial(AMAP_T *amap)
+ * If there is no partial AU available, pick a clean one
+ */
+static inline AU_INFO_T *amap_find_hot_au_partial(AMAP_T *amap)
{
struct slist_head *iter;
uint16_t max_fclu = 0;
@@ -126,7 +125,7 @@ static inline AU_INFO_T* amap_find_hot_au_partial(AMAP_T *amap)
while (iter) {
entry = list_entry(iter, AU_INFO_T, shead);
-
+
if (entry->free_clusters > max_fclu) {
if (entry->free_clusters < amap->clusters_per_au) {
max_fclu = entry->free_clusters;
@@ -147,13 +146,13 @@ static inline AU_INFO_T* amap_find_hot_au_partial(AMAP_T *amap)
/*
- Size-base AU management functions
-*/
+ * Size-base AU management functions
+ */
/*
- Add au into cold AU MAP
- au: an isolated (not in a list) AU data structure
-*/
+ * Add au into cold AU MAP
+ * au: an isolated (not in a list) AU data structure
+ */
int amap_add_cold_au(AMAP_T *amap, AU_INFO_T *au)
{
FCLU_NODE_T *fclu_node = NULL;
@@ -179,9 +178,9 @@ int amap_add_cold_au(AMAP_T *amap, AU_INFO_T *au)
}
/*
- Remove an AU from AU MAP
-*/
-int amap_remove_cold_au(AMAP_T *amap, AU_INFO_T* au)
+ * Remove an AU from AU MAP
+ */
+int amap_remove_cold_au(AMAP_T *amap, AU_INFO_T *au)
{
struct list_head *prev = au->head.prev;
@@ -198,13 +197,13 @@ int amap_remove_cold_au(AMAP_T *amap, AU_INFO_T* au)
}
-/* "Find" best fit AU
- returns NULL if there is no AU w/ enough free space.
-
- This function doesn't change AU status.
- The caller should call amap_remove_cold_au() if needed.
-*/
-AU_INFO_T* amap_find_cold_au_bestfit(AMAP_T *amap, uint16_t free_clusters)
+/* "Find" best fit AU
+ * returns NULL if there is no AU w/ enough free space.
+ *
+ * This function doesn't change AU status.
+ * The caller should call amap_remove_cold_au() if needed.
+ */
+AU_INFO_T *amap_find_cold_au_bestfit(AMAP_T *amap, uint16_t free_clusters)
{
AU_INFO_T *au = NULL;
FCLU_NODE_T *fclu_iter;
@@ -214,7 +213,7 @@ AU_INFO_T* amap_find_cold_au_bestfit(AMAP_T *amap, uint16_t free_clusters)
free_clusters);
return NULL;
}
-
+
fclu_iter = NODE(free_clusters, amap);
if (amap->fclu_hint < free_clusters) {
@@ -243,14 +242,15 @@ AU_INFO_T* amap_find_cold_au_bestfit(AMAP_T *amap, uint16_t free_clusters)
}
-/* "Pop" best fit AU
- returns NULL if there is no AU w/ enough free space.
- The returned AU will not be in the list anymore.
-*/
-AU_INFO_T* amap_pop_cold_au_bestfit(AMAP_T *amap, uint16_t free_clusters)
+/* "Pop" best fit AU
+ *
+ * returns NULL if there is no AU w/ enough free space.
+ * The returned AU will not be in the list anymore.
+ */
+AU_INFO_T *amap_pop_cold_au_bestfit(AMAP_T *amap, uint16_t free_clusters)
{
/* Naive implementation */
- AU_INFO_T* au;
+ AU_INFO_T *au;
au = amap_find_cold_au_bestfit(amap, free_clusters);
if (au)
@@ -262,15 +262,14 @@ AU_INFO_T* amap_pop_cold_au_bestfit(AMAP_T *amap, uint16_t free_clusters)
/* Pop the AU with the largest free space
-
- search from 'start_fclu' to 0
- (target freecluster : -1 for each step)
-
- start_fclu = 0 means to search from the max. value
-*/
-AU_INFO_T* amap_pop_cold_au_largest(AMAP_T *amap, uint16_t start_fclu)
+ *
+ * search from 'start_fclu' to 0
+ * (target freecluster : -1 for each step)
+ * start_fclu = 0 means to search from the max. value
+ */
+AU_INFO_T *amap_pop_cold_au_largest(AMAP_T *amap, uint16_t start_fclu)
{
- AU_INFO_T* au = NULL;
+ AU_INFO_T *au = NULL;
FCLU_NODE_T *fclu_iter;
if (!start_fclu)
@@ -283,7 +282,7 @@ AU_INFO_T* amap_pop_cold_au_largest(AMAP_T *amap, uint16_t start_fclu)
fclu_iter = NODE(amap->fclu_hint, amap);
else
fclu_iter = NODE(start_fclu, amap);
-
+
/* Naive Hash management */
do {
if (!list_empty(&fclu_iter->head)) {
@@ -311,10 +310,10 @@ AU_INFO_T* amap_pop_cold_au_largest(AMAP_T *amap, uint16_t start_fclu)
/*
-===============================================
- Allocation Map related functions
-===============================================
-*/
+ * ===============================================
+ * Allocation Map related functions
+ * ===============================================
+ */
/* Create AMAP related data structure (mount time) */
int amap_create(struct super_block *sb, u32 pack_ratio, u32 sect_per_au, u32 hidden_sect)
@@ -350,7 +349,7 @@ int amap_create(struct super_block *sb, u32 pack_ratio, u32 sect_per_au, u32 hid
sdfat_msg(sb, KERN_ERR,
"invalid AU size (sect_per_au : %u, "
"sect_per_clus : %u) "
- "please re-format for performance.",
+ "please re-format for performance.",
sect_per_au, fsi->sect_per_clus);
return -EINVAL;
}
@@ -360,7 +359,7 @@ int amap_create(struct super_block *sb, u32 pack_ratio, u32 sect_per_au, u32 hid
sdfat_msg(sb, KERN_ERR,
"misaligned part (start sect : %u, "
"sect_per_clus : %u) "
- "please re-format for performance.",
+ "please re-format for performance.",
misaligned_sect, fsi->sect_per_clus);
return -EINVAL;
}
@@ -370,7 +369,7 @@ int amap_create(struct super_block *sb, u32 pack_ratio, u32 sect_per_au, u32 hid
sdfat_msg(sb, KERN_ERR,
"misaligned data area (start sect : %u, "
"sect_per_clus : %u) "
- "please re-format for performance.",
+ "please re-format for performance.",
fsi->data_start_sector, fsi->sect_per_clus);
return -EINVAL;
}
@@ -383,22 +382,23 @@ int amap_create(struct super_block *sb, u32 pack_ratio, u32 sect_per_au, u32 hid
return -ENOMEM;
amap->sb = sb;
-
+
amap->n_au = (fsi->num_sectors + misaligned_sect + sect_per_au - 1) / sect_per_au;
amap->n_clean_au = 0;
amap->n_full_au = 0;
- /* Reflect block-partition align first,
- then partition-data_start align */
+ /* Reflect block-partition align first,
+ * then partition-data_start align
+ */
amap->clu_align_bias = (misaligned_sect / fsi->sect_per_clus);
amap->clu_align_bias += (fsi->data_start_sector >> fsi->sect_per_clus_bits) - CLUS_BASE;
amap->clusters_per_au = sect_per_au / fsi->sect_per_clus;
- /* That is,
+ /* That is,
* the size of cluster is at least 4KB if the size of AU is 4MB
*/
if (amap->clusters_per_au > MAX_CLU_PER_AU) {
- sdfat_log_msg(sb, KERN_INFO,
+ sdfat_log_msg(sb, KERN_INFO,
"too many clusters per AU (clus/au:%d > %d).",
amap->clusters_per_au,
MAX_CLU_PER_AU);
@@ -417,7 +417,6 @@ int amap_create(struct super_block *sb, u32 pack_ratio, u32 sect_per_au, u32 hid
/* Allocate AU info table */
n_au_table = (amap->n_au + N_AU_PER_TABLE - 1) / N_AU_PER_TABLE;
amap->au_table = kmalloc(sizeof(AU_INFO_T *) * n_au_table, GFP_NOIO);
-
if (!amap->au_table) {
sdfat_msg(sb, KERN_ERR,
"failed to alloc amap->au_table\n");
@@ -439,9 +438,9 @@ int amap_create(struct super_block *sb, u32 pack_ratio, u32 sect_per_au, u32 hid
(unsigned long)sizeof(FCLU_NODE_T));
if (!amap->fclu_order)
- amap->fclu_nodes = (FCLU_NODE_T*)get_zeroed_page(GFP_NOIO);
- else
- amap->fclu_nodes = (FCLU_NODE_T*)vzalloc(PAGE_SIZE << amap->fclu_order);
+ amap->fclu_nodes = (FCLU_NODE_T *)get_zeroed_page(GFP_NOIO);
+ else
+ amap->fclu_nodes = vzalloc(PAGE_SIZE << amap->fclu_order);
amap->fclu_hint = amap->clusters_per_au;
@@ -468,16 +467,15 @@ int amap_create(struct super_block *sb, u32 pack_ratio, u32 sect_per_au, u32 hid
for (i = 0; i < amap->clusters_per_au; i++)
INIT_LIST_HEAD(&amap->fclu_nodes[i].head);
-
/*
- Thanks to kzalloc()
- amap->entries[i_au].free_clusters = 0;
- amap->entries[i_au].head.prev = NULL;
- amap->entries[i_au].head.next = NULL;
- */
-
+ * Thanks to kzalloc()
+ * amap->entries[i_au].free_clusters = 0;
+ * amap->entries[i_au].head.prev = NULL;
+ * amap->entries[i_au].head.next = NULL;
+ */
+
/* Parse FAT table */
- for (i_clu = CLUS_BASE; i_clu < fsi->num_clusters; i_clu++){
+ for (i_clu = CLUS_BASE; i_clu < fsi->num_clusters; i_clu++) {
u32 clu_data;
AU_INFO_T *au;
@@ -486,7 +484,7 @@ int amap_create(struct super_block *sb, u32 pack_ratio, u32 sect_per_au, u32 hid
"failed to read fat entry(%u)\n", i_clu);
goto free_and_eio;
}
-
+
if (IS_CLUS_FREE(clu_data)) {
au = GET_AU(amap, i_AU_of_CLU(amap, i_clu));
au->free_clusters++;
@@ -495,7 +493,7 @@ int amap_create(struct super_block *sb, u32 pack_ratio, u32 sect_per_au, u32 hid
}
/* Build AU list */
- for (i_au = 0; i_au < amap->n_au; i_au++){
+ for (i_au = 0; i_au < amap->n_au; i_au++) {
AU_INFO_T *au = GET_AU(amap, i_au);
au->idx = i_au;
@@ -522,13 +520,12 @@ int amap_create(struct super_block *sb, u32 pack_ratio, u32 sect_per_au, u32 hid
amap->total_fclu_hot += GET_AU(amap, i_au_root)->free_clusters;
}
-
fsi->amap = amap;
fsi->used_clusters = total_used_clusters;
- sdfat_msg(sb, KERN_INFO,
+ sdfat_msg(sb, KERN_INFO,
"AMAP: Smart allocation enabled (opt : %u / %u / %u)",
- amap->option.au_size, amap->option.au_align_factor,
+ amap->option.au_size, amap->option.au_align_factor,
amap->option.packing_ratio);
/* Debug purpose - check */
@@ -575,6 +572,7 @@ void amap_destroy(struct super_block *sb)
if (amap->au_table) {
int i;
+
for (i = 0; i < n_au_table; i++)
free_page((unsigned long)amap->au_table[i]);
@@ -586,16 +584,14 @@ void amap_destroy(struct super_block *sb)
vfree(amap->fclu_nodes);
kfree(amap);
SDFAT_SB(sb)->fsi.amap = NULL;
-
- return;
}
/*
- Check status of FS
- and change destination if needed to disable AU-aligned alloc.
- (from ALLOC_COLD_ALIGNED to ALLOC_COLD_SEQ)
-*/
+ * Check status of FS
+ * and change destination if needed to disable AU-aligned alloc.
+ * (from ALLOC_COLD_ALIGNED to ALLOC_COLD_SEQ)
+ */
static inline int amap_update_dest(AMAP_T *amap, int ori_dest)
{
FS_INFO_T *fsi = &(SDFAT_SB(amap->sb)->fsi);
@@ -609,23 +605,22 @@ static inline int amap_update_dest(AMAP_T *amap, int ori_dest)
n_partial_freeclus = fsi->num_clusters - fsi->used_clusters -
amap->clusters_per_au * amap->n_clean_au;
- /* Status of AUs : Full / Partial / Clean
- If there are many partial (and badly fragmented) AUs,
- the throughput will decrease extremly.
+ /* Status of AUs : Full / Partial / Clean
+ * If there are many partial (and badly fragmented) AUs,
+ * the throughput will decrease extremly.
+ *
+ * The follow code will treat those worst cases.
+ */
- The follow code will treat those worst cases.
- */
-
- // XXX: AMAP heuristics
+ /* XXX: AMAP heuristics */
if ((amap->n_clean_au * 50 <= amap->n_au) &&
(n_partial_freeclus*2) < (n_partial_au*amap->clusters_per_au)) {
/* If clean AUs are fewer than 2% of n_au (80 AUs per 16GB)
- and fragment ratio is more than 2 (AVG free_clusters=half AU)
-
- disable clean-first allocation
- enable VFAT-like sequential allocation
- */
-
+ * and fragment ratio is more than 2 (AVG free_clusters=half AU)
+ *
+ * disable clean-first allocation
+ * enable VFAT-like sequential allocation
+ */
return ALLOC_COLD_SEQ;
}
@@ -635,39 +630,37 @@ static inline int amap_update_dest(AMAP_T *amap, int ori_dest)
#define PACKING_SOFTLIMIT (amap->option.packing_ratio)
#define PACKING_HARDLIMIT (amap->option.packing_ratio * 4)
-/*
- Pick a packing AU if needed.
- Otherwise just return NULL
-
- This function includes some heuristics.
-*/
-static inline AU_INFO_T* amap_get_packing_au(AMAP_T *amap, int dest, int num_to_wb, int *clu_to_skip)
+/*
+ * Pick a packing AU if needed.
+ * Otherwise just return NULL
+ *
+ * This function includes some heuristics.
+ */
+static inline AU_INFO_T *amap_get_packing_au(AMAP_T *amap, int dest, int num_to_wb, int *clu_to_skip)
{
- AU_INFO_T* au = NULL;
+ AU_INFO_T *au = NULL;
if (dest == ALLOC_COLD_PACKING) {
- /* ALLOC_COLD_PACKING:
- Packing-first mode for defrag.
- Optimized to save clean AU
-
- 1) best-fit AU
- 2) Smallest AU (w/ minimum free clusters)
- */
-
+ /* ALLOC_COLD_PACKING:
+ * Packing-first mode for defrag.
+ * Optimized to save clean AU
+ *
+ * 1) best-fit AU
+ * 2) Smallest AU (w/ minimum free clusters)
+ */
if (num_to_wb >= amap->clusters_per_au)
- num_to_wb = num_to_wb % amap->clusters_per_au;
-
+ num_to_wb = num_to_wb % amap->clusters_per_au;
+
/* 이거 주석처리하면, AU size 딱 맞을때는 clean, 나머지는 작은거부터 */
if (num_to_wb == 0)
num_to_wb = 1; // Don't use clean AUs
-
- au = amap_find_cold_au_bestfit(amap, num_to_wb);
+ au = amap_find_cold_au_bestfit(amap, num_to_wb);
if (au && au->free_clusters == amap->clusters_per_au && num_to_wb > 1) {
- // if au is clean then get a new partial one
+ /* if au is clean then get a new partial one */
au = amap_find_cold_au_bestfit(amap, 1);
}
-
+
if (au) {
amap->n_need_packing = 0;
amap_remove_cold_au(amap, au);
@@ -676,28 +669,27 @@ static inline AU_INFO_T* amap_get_packing_au(AMAP_T *amap, int dest, int num_to_
}
- /* Heuristic packing:
- This will improve QoS greatly.
-
- Count # of AU_ALLIGNED allocation.
- If the number exceeds the specific threshold,
- allocate on a partial AU or generate random I/O.
- */
- if ((PACKING_SOFTLIMIT > 0) && \
- (amap->n_need_packing >= PACKING_SOFTLIMIT) && \
- (num_to_wb < (int)amap->clusters_per_au) ){
+ /* Heuristic packing:
+ * This will improve QoS greatly.
+ *
+ * Count # of AU_ALIGNED allocation.
+ * If the number exceeds the specific threshold,
+ * allocate on a partial AU or generate random I/O.
+ */
+ if ((PACKING_SOFTLIMIT > 0) &&
+ (amap->n_need_packing >= PACKING_SOFTLIMIT) &&
+ (num_to_wb < (int)amap->clusters_per_au)) {
/* Best-fit packing:
- If num_to_wb (expected number to be allocated) is smaller than AU_SIZE,
- find a best-fit AU.
- */
+ * If num_to_wb (expected number to be allocated) is smaller
+ * than AU_SIZE, find a best-fit AU.
+ */
- // Back margin (heuristics)
+ /* Back margin (heuristics) */
if (num_to_wb < amap->clusters_per_au / 4)
num_to_wb = amap->clusters_per_au / 4;
au = amap_find_cold_au_bestfit(amap, num_to_wb);
-
- if ((au != NULL)) {
+ if (au != NULL) {
amap_remove_cold_au(amap, au);
MMSG("AMAP: packing (cnt: %d) / softlimit, "
@@ -712,16 +704,14 @@ static inline AU_INFO_T* amap_get_packing_au(AMAP_T *amap, int dest, int num_to_
return au;
}
}
-
- if (PACKING_HARDLIMIT != 0 && \
- amap->n_need_packing >= PACKING_HARDLIMIT) {
- /* Compulsory SLC flushing:
- If there was no chance to do best-fit packing
- and the # of AU-aligned allocation exceeds HARD threshold,
- then pick a clean AU and generate a compulsory random I/O.
- */
- au = amap_pop_cold_au_largest(amap, amap->clusters_per_au);
+ if ((PACKING_HARDLIMIT) && amap->n_need_packing >= PACKING_HARDLIMIT) {
+ /* Compulsory SLC flushing:
+ * If there was no chance to do best-fit packing
+ * and the # of AU-aligned allocation exceeds HARD threshold,
+ * then pick a clean AU and generate a compulsory random I/O.
+ */
+ au = amap_pop_cold_au_largest(amap, amap->clusters_per_au);
if (au) {
MMSG("AMAP: packing (cnt: %d) / hard-limit, largest)\n",
amap->n_need_packing);
@@ -741,9 +731,10 @@ static inline AU_INFO_T* amap_get_packing_au(AMAP_T *amap, int dest, int num_to_
}
-/* Pick a target AU
- - This function should be called only if there are one or more free clusters in the bdev.
-*/
+/* Pick a target AU:
+ * This function should be called
+ * only if there are one or more free clusters in the bdev.
+ */
TARGET_AU_T *amap_get_target_au(AMAP_T *amap, int dest, int num_to_wb)
{
int loop_count = 0;
@@ -751,10 +742,9 @@ TARGET_AU_T *amap_get_target_au(AMAP_T *amap, int dest, int num_to_wb)
retry:
if (++loop_count >= 3) {
/* No space available (or AMAP consistency error)
- This could happen because of the ignored AUs
- but not likely
- (because the defrag daemon will not work if there is no enough space)
- */
+ * This could happen because of the ignored AUs but not likely
+ * (because the defrag daemon will not work if there is no enough space)
+ */
BUG_ON(amap->slist_ignored.next == NULL);
return NULL;
}
@@ -787,13 +777,12 @@ retry:
return &amap->cur_hot;
}
-
/* Cold allocation:
- If amap->cur_cold.au has one or more free cluster(s),
- then just return amap->cur_cold
- */
- if ( (!amap->cur_cold.au) \
- || (amap->cur_cold.idx == amap->clusters_per_au) \
+ * If amap->cur_cold.au has one or more free cluster(s),
+ * then just return amap->cur_cold
+ */
+ if ((!amap->cur_cold.au)
+ || (amap->cur_cold.idx == amap->clusters_per_au)
|| (amap->cur_cold.au->free_clusters == 0)) {
AU_INFO_T *au = NULL;
@@ -802,20 +791,21 @@ retry:
if (old_au) {
ASSERT(!IS_AU_WORKING(old_au, amap));
- // must be NOT WORKING AU. (only for information gathering)
+ /* must be NOT WORKING AU.
+ * (only for information gathering)
+ */
}
/* Next target AU is needed:
- There are 3 possible ALLOC options for cold AU
-
- ALLOC_COLD_ALGINED: Clean AU first, but heuristic packing is ON
- ALLOC_COLD_PACKING: Packing AU first (usually for defrag)
- ALLOC_COLD_SEQ : Sequential AU allocation (VFAT-like)
- */
-
+ * There are 3 possible ALLOC options for cold AU
+ *
+ * ALLOC_COLD_ALIGNED: Clean AU first, but heuristic packing is ON
+ * ALLOC_COLD_PACKING: Packing AU first (usually for defrag)
+ * ALLOC_COLD_SEQ : Sequential AU allocation (VFAT-like)
+ */
/* Experimental: Modify allocation destination if needed (ALIGNED => SEQ) */
- // dest = amap_update_dest(amap, dest);
+ // dest = amap_update_dest(amap, dest);
if ((dest == ALLOC_COLD_SEQ) && old_au) {
int i_au = old_au->idx + 1;
@@ -823,10 +813,9 @@ retry:
while (i_au != old_au->idx) {
au = GET_AU(amap, i_au);
- if ((au->free_clusters > 0) &&
- !IS_AU_HOT(au, amap) &&
+ if ((au->free_clusters > 0) &&
+ !IS_AU_HOT(au, amap) &&
!IS_AU_IGNORED(au, amap)) {
-
MMSG("AMAP: new cold AU(%d) with %d "
"clusters (seq)\n",
au->idx, au->free_clusters);
@@ -845,9 +834,9 @@ retry:
}
- /*
- * Check if packing is needed
- * (ALLOC_COLD_PACKING is treated by this function)
+ /*
+ * Check if packing is needed
+ * (ALLOC_COLD_PACKING is treated by this function)
*/
au = amap_get_packing_au(amap, dest, num_to_wb, &n_clu_to_skip);
if (au) {
@@ -855,14 +844,13 @@ retry:
"(packing)\n", au->idx, au->free_clusters);
goto ret_new_cold;
}
-
+
/* ALLOC_COLD_ALIGNED */
/* Check if the adjacent AU is clean */
if (old_au && ((old_au->idx + 1) < amap->n_au)) {
au = GET_AU(amap, old_au->idx + 1);
-
- if ((au->free_clusters == amap->clusters_per_au) &&
- !IS_AU_HOT(au, amap) &&
+ if ((au->free_clusters == amap->clusters_per_au) &&
+ !IS_AU_HOT(au, amap) &&
!IS_AU_IGNORED(au, amap)) {
MMSG("AMAP: new cold AU(%d) with %d clusters "
"(adjacent)\n", au->idx, au->free_clusters);
@@ -879,7 +867,7 @@ retry:
goto retry;
}
- MMSG("AMAP: New cold AU (%d) with %d clusters\n", \
+ MMSG("AMAP: New cold AU (%d) with %d clusters\n",
au->idx, au->free_clusters);
ret_new_cold:
@@ -897,14 +885,14 @@ ret_new_cold:
void amap_put_target_au(AMAP_T *amap, TARGET_AU_T *cur, int num_allocated)
{
/* Update AMAP info vars. */
- if (num_allocated > 0 && \
- (cur->au->free_clusters + num_allocated) == amap->clusters_per_au)
- // if the target AU was a clean AU before this allocation ...
+ if (num_allocated > 0 &&
+ (cur->au->free_clusters + num_allocated) == amap->clusters_per_au) {
+ /* if the target AU was a clean AU before this allocation ... */
amap->n_clean_au--;
- if (num_allocated > 0 && \
+ }
+ if (num_allocated > 0 &&
cur->au->free_clusters == 0)
amap->n_full_au++;
-
if (IS_AU_HOT(cur->au, amap)) {
/* Hot AU */
@@ -936,11 +924,9 @@ void amap_put_target_au(AMAP_T *amap, TARGET_AU_T *cur, int num_allocated)
}
-/* Reposition target->idx for packing
- (Heuristics)
-
- Skip (num_to_skip) free clusters in (cur->au)
-*/
+/* Reposition target->idx for packing (Heuristics):
+ * Skip (num_to_skip) free clusters in (cur->au)
+ */
static inline int amap_skip_cluster(struct super_block *sb, TARGET_AU_T *cur, int num_to_skip)
{
AMAP_T *amap = SDFAT_SB(sb)->fsi.amap;
@@ -953,12 +939,11 @@ static inline int amap_skip_cluster(struct super_block *sb, TARGET_AU_T *cur, in
}
clu = CLU_of_i_AU(amap, cur->au->idx, cur->idx);
-
while (num_to_skip > 0) {
if (clu >= CLUS_BASE) {
/* Cf.
* If AMAP's integrity is okay,
- * we don't need to check if (clu < fsi->num_clusters)
+ * we don't need to check if (clu < fsi->num_clusters)
*/
if (fat_ent_get(sb, clu, &read_clu))
@@ -980,7 +965,7 @@ static inline int amap_skip_cluster(struct super_block *sb, TARGET_AU_T *cur, in
}
}
- MMSG("AMAP: Skip_clusters (%d skipped => %d, among %d free clus)\n",\
+ MMSG("AMAP: Skip_clusters (%d skipped => %d, among %d free clus)\n",
num_to_skip_orig, cur->idx, cur->au->free_clusters);
return 0;
@@ -1005,11 +990,12 @@ s32 amap_fat_alloc_cluster(struct super_block *sb, s32 num_alloc, CHAIN_T *p_cha
if ((fsi->used_clusters + num_alloc) > (fsi->num_clusters - CLUS_BASE)) {
/* Reserved count management error
- or called by dir. management function on fully filled disk */
+ * or called by dir. management function on fully filled disk
+ */
num_alloc = fsi->num_clusters - fsi->used_clusters - CLUS_BASE;
if (unlikely(num_alloc < 0)) {
- sdfat_fs_error_ratelimit(sb,
+ sdfat_fs_error_ratelimit(sb,
"AMAP(%s): invalid used clusters(t:%u,u:%u)\n",
__func__, fsi->num_clusters, fsi->used_clusters);
return -EIO;
@@ -1040,13 +1026,11 @@ retry_alloc:
}
target_au = cur->au;
-
- /*
+ /*
* cur->au : target AU info pointer
- * cur->idx : the intra-cluster idx in the AU to start from
+ * cur->idx : the intra-cluster idx in the AU to start from
*/
-
BUG_ON(!cur->au);
BUG_ON(!cur->au->free_clusters);
BUG_ON(cur->idx >= amap->clusters_per_au);
@@ -1075,7 +1059,6 @@ retry_alloc:
else
if (fat_ent_set(sb, last_clu, new_clu))
return -EIO;
-
last_clu = new_clu;
/* Update au info */
@@ -1090,8 +1073,7 @@ retry_alloc:
/* End of the AU */
if ((cur->idx >= amap->clusters_per_au) || !(target_au->free_clusters))
break;
- } while(num_allocated_each < num_alloc);
-
+ } while (num_allocated_each < num_alloc);
/* Update strategy info */
amap_put_target_au(amap, cur, num_allocated_each);
@@ -1118,9 +1100,9 @@ s32 amap_free_cluster(struct super_block *sb, CHAIN_T *p_chain, s32 do_relse)
/*
- This is called by fat_free_cluster()
- to update AMAP info.
-*/
+ * This is called by fat_free_cluster()
+ * to update AMAP info.
+ */
s32 amap_release_cluster(struct super_block *sb, u32 clu)
{
AMAP_T *amap = SDFAT_SB(sb)->fsi.amap;
@@ -1133,7 +1115,12 @@ s32 amap_release_cluster(struct super_block *sb, u32 clu)
i_au = i_AU_of_CLU(amap, clu);
BUG_ON(i_au >= amap->n_au);
au = GET_AU(amap, i_au);
- BUG_ON(au->free_clusters >= amap->clusters_per_au);
+ if (au->free_clusters >= amap->clusters_per_au) {
+ sdfat_fs_error(sb, "%s, au->free_clusters(%hd) is "
+ "greater than or equal to amap->clusters_per_au(%hd)"
+ , __func__, au->free_clusters, amap->clusters_per_au);
+ return -EIO;
+ }
if (IS_AU_HOT(au, amap)) {
MMSG("AMAP: Hot cluster freed\n");
@@ -1141,7 +1128,7 @@ s32 amap_release_cluster(struct super_block *sb, u32 clu)
amap->total_fclu_hot++;
} else if (!IS_AU_WORKING(au, amap) && !IS_AU_IGNORED(au, amap)) {
/* Ordinary AU - update AU tree */
- // Can be optimized by implmenting amap_update_au
+ // Can be optimized by implementing amap_update_au
amap_remove_cold_au(amap, au);
au->free_clusters++;
amap_add_cold_au(amap, au);
@@ -1161,57 +1148,51 @@ s32 amap_release_cluster(struct super_block *sb, u32 clu)
/*
- Check if the cluster is in a working AU
- The caller should hold sb lock.
- This func. should be used only if smart allocation is on
-*/
+ * Check if the cluster is in a working AU
+ * The caller should hold sb lock.
+ * This func. should be used only if smart allocation is on
+ */
s32 amap_check_working(struct super_block *sb, u32 clu)
{
AMAP_T *amap = SDFAT_SB(sb)->fsi.amap;
AU_INFO_T *au;
BUG_ON(!amap);
-
au = GET_AU(amap, i_AU_of_CLU(amap, clu));
-
- return (IS_AU_WORKING(au, amap));
+ return IS_AU_WORKING(au, amap);
}
/*
- Return the # of free clusters in that AU
-*/
+ * Return the # of free clusters in that AU
+ */
s32 amap_get_freeclus(struct super_block *sb, u32 clu)
{
AMAP_T *amap = SDFAT_SB(sb)->fsi.amap;
AU_INFO_T *au;
BUG_ON(!amap);
-
au = GET_AU(amap, i_AU_of_CLU(amap, clu));
-
- return ((s32)au->free_clusters);
+ return (s32)au->free_clusters;
}
/*
- Add the AU containing 'clu' to the ignored AU list.
- The AU will not be used by the allocator.
-
- XXX: Ignored counter needed
-*/
+ * Add the AU containing 'clu' to the ignored AU list.
+ * The AU will not be used by the allocator.
+ *
+ * XXX: Ignored counter needed
+ */
s32 amap_mark_ignore(struct super_block *sb, u32 clu)
{
AMAP_T *amap = SDFAT_SB(sb)->fsi.amap;
AU_INFO_T *au;
BUG_ON(!amap);
-
au = GET_AU(amap, i_AU_of_CLU(amap, clu));
-
if (IS_AU_HOT(au, amap)) {
- // Doesn't work with hot AUs
+ /* Doesn't work with hot AUs */
return -EPERM;
} else if (IS_AU_WORKING(au, amap)) {
return -EBUSY;
@@ -1227,17 +1208,15 @@ s32 amap_mark_ignore(struct super_block *sb, u32 clu)
BUG_ON(!IS_AU_IGNORED(au, amap));
//INC_IGN_CNT(au);
-
MMSG("AMAP: Mark ignored AU (%d)\n", au->idx);
-
return 0;
}
/*
- This function could be used only on IGNORED AUs.
- The caller should care whether it's ignored or not before using this func.
-*/
+ * This function could be used only on IGNORED AUs.
+ * The caller should care whether it's ignored or not before using this func.
+ */
s32 amap_unmark_ignore(struct super_block *sb, u32 clu)
{
AMAP_T *amap = SDFAT_SB(sb)->fsi.amap;
@@ -1263,9 +1242,9 @@ s32 amap_unmark_ignore(struct super_block *sb, u32 clu)
}
/*
- Unmark all ignored AU
- This will return # of unmarked AUs
-*/
+ * Unmark all ignored AU
+ * This will return # of unmarked AUs
+ */
s32 amap_unmark_ignore_all(struct super_block *sb)
{
AMAP_T *amap = SDFAT_SB(sb)->fsi.amap;
@@ -1274,7 +1253,6 @@ s32 amap_unmark_ignore_all(struct super_block *sb)
int n = 0;
BUG_ON(!amap);
-
entry = amap->slist_ignored.next;
while (entry) {
au = list_entry(entry, AU_INFO_T, shead);
@@ -1283,13 +1261,12 @@ s32 amap_unmark_ignore_all(struct super_block *sb)
BUG_ON(!IS_AU_IGNORED(au, amap));
//CLEAR_IGN_CNT(au);
-
amap_remove_from_list(au, &amap->slist_ignored);
amap_add_cold_au(amap, au);
-
+
MMSG("AMAP: Unmark ignored AU (%d)\n", au->idx);
n++;
-
+
entry = amap->slist_ignored.next;
}
diff --git a/amap_smart.h b/amap_smart.h
index ffd931d..b628ff4 100644
--- a/amap_smart.h
+++ b/amap_smart.h
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
#ifndef _SDFAT_AMAP_H
@@ -25,16 +23,19 @@
#include
/* AMAP Configuration Variable */
-#define SMART_ALLOC_N_HOT_AU 5
+#define SMART_ALLOC_N_HOT_AU (5)
-
-/* Allocating Destination (for smart allocator) */
-#define ALLOC_COLD_ALIGNED 1
-#define ALLOC_COLD_PACKING 2
-#define ALLOC_COLD_SEQ 4
+/* Allocating Destination (for smart allocator):
+ * moved to sdfat.h
+ */
+/*
+ * #define ALLOC_COLD_ALIGNED (1)
+ * #define ALLOC_COLD_PACKING (2)
+ * #define ALLOC_COLD_SEQ (4)
+ */
/* Minimum sectors for support AMAP create */
-#define AMAP_MIN_SUPPORT_SECTORS 1048576
+#define AMAP_MIN_SUPPORT_SECTORS (1048576)
#define amap_add_hot_au(amap, au) amap_insert_to_list(au, &amap->slist_hot)
@@ -45,20 +46,20 @@ struct slist_head {
};
/* AU entry type */
-typedef struct __AU_INFO_T{
- uint16_t idx; /* the index of the AU (0, 1, 2, ... ) */
- uint16_t free_clusters; /* # of available cluster */
+typedef struct __AU_INFO_T {
+ uint16_t idx; /* the index of the AU (0, 1, 2, ... ) */
+ uint16_t free_clusters; /* # of available cluster */
union {
struct list_head head;
- struct slist_head shead; /* singly linked list head for hot list */
+ struct slist_head shead;/* singly linked list head for hot list */
};
} AU_INFO_T;
/* Allocation Target AU */
-typedef struct __TARGET_AU_T{
- AU_INFO_T *au; /* Working AU */
- uint16_t idx; /* Intra-AU cluster index */
+typedef struct __TARGET_AU_T {
+ AU_INFO_T *au; /* Working AU */
+ uint16_t idx; /* Intra-AU cluster index */
uint16_t clu_to_skip; /* Clusters to skip */
} TARGET_AU_T;
@@ -71,29 +72,29 @@ typedef struct {
/* AMAP options */
typedef struct {
- unsigned int packing_ratio; /* Tunable packing ratio */
- unsigned int au_size; /* AU size in sectors */
+ unsigned int packing_ratio; /* Tunable packing ratio */
+ unsigned int au_size; /* AU size in sectors */
unsigned int au_align_factor; /* Hidden sectors % au_size */
} AMAP_OPT_T;
-typedef struct __AMAP_T{
- spinlock_t amap_lock; // obsolete
+typedef struct __AMAP_T {
+ spinlock_t amap_lock; /* obsolete */
struct super_block *sb;
int n_au;
int n_clean_au, n_full_au;
int clu_align_bias;
uint16_t clusters_per_au;
- AU_INFO_T **au_table; /* An array of AU_INFO entries */
+ AU_INFO_T **au_table; /* An array of AU_INFO entries */
AMAP_OPT_T option;
/* Size-based AU management pool (cold) */
- FCLU_NODE_T *fclu_nodes; /* An array of listheads */
- int fclu_order; /* Page order that fclu_nodes needs */
- int fclu_hint; /* maximum # of free clusters in an AU */
+ FCLU_NODE_T *fclu_nodes; /* An array of listheads */
+ int fclu_order; /* Page order that fclu_nodes needs */
+ int fclu_hint; /* maximum # of free clusters in an AU */
/* Hot AU list */
- int total_fclu_hot; /* Free clusters in hot list */
+ int total_fclu_hot; /* Free clusters in hot list */
struct slist_head slist_hot; /* Hot AU list */
/* Ignored AU list */
@@ -113,23 +114,24 @@ typedef struct __AMAP_T{
#define MAX_CLU_PER_AU (1024)
/* Cold AU bucket <-> # of freeclusters */
-#define NODE_CLEAN(amap) &amap->fclu_nodes[amap->clusters_per_au - 1]
-#define NODE(fclu, amap) &amap->fclu_nodes[fclu - 1]
+#define NODE_CLEAN(amap) (&amap->fclu_nodes[amap->clusters_per_au - 1])
+#define NODE(fclu, amap) (&amap->fclu_nodes[fclu - 1])
#define FREE_CLUSTERS(node, amap) ((int)(node - amap->fclu_nodes) + 1)
/* AU status */
-#define MAGIC_WORKING (struct slist_head*)0xFFFF5091
-#define IS_AU_HOT(au, amap) (au->shead.head == &amap->slist_hot)
-#define IS_AU_IGNORED(au, amap) (au->shead.head == &amap->slist_ignored)
-#define IS_AU_WORKING(au, amap) (au->shead.head == MAGIC_WORKING)
-#define SET_AU_WORKING(au) (au->shead.head = MAGIC_WORKING)
+#define MAGIC_WORKING ((struct slist_head *)0xFFFF5091)
+#define IS_AU_HOT(au, amap) (au->shead.head == &amap->slist_hot)
+#define IS_AU_IGNORED(au, amap) (au->shead.head == &amap->slist_ignored)
+#define IS_AU_WORKING(au, amap) (au->shead.head == MAGIC_WORKING)
+#define SET_AU_WORKING(au) (au->shead.head = MAGIC_WORKING)
/* AU <-> cluster */
-#define i_AU_of_CLU(amap, clu) ((amap->clu_align_bias + clu) / amap->clusters_per_au)
-#define CLU_of_i_AU(amap, i_au, idx) ((uint32_t)(i_au) * (uint32_t)amap->clusters_per_au + (idx) - amap->clu_align_bias)
+#define i_AU_of_CLU(amap, clu) ((amap->clu_align_bias + clu) / amap->clusters_per_au)
+#define CLU_of_i_AU(amap, i_au, idx) \
+ ((uint32_t)(i_au) * (uint32_t)amap->clusters_per_au + (idx) - amap->clu_align_bias)
-/*
- * NOTE : AMAP internal functions are moved to core.h
+/*
+ * NOTE : AMAP internal functions are moved to core.h
*/
#endif /* _SDFAT_AMAP_H */
diff --git a/api.c b/api.c
index bf8e343..e1f17cc 100644
--- a/api.c
+++ b/api.c
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
/************************************************************************/
@@ -132,10 +130,11 @@ s32 fsapi_statfs(struct super_block *sb, VOL_INFO_T *info)
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
/* check the validity of pointer parameters */
- ASSERT(info);
+ ASSERT(info);
if (fsi->used_clusters == (u32) ~0) {
s32 err;
+
mutex_lock(&(SDFAT_SB(sb)->s_vlock));
err = fscore_statfs(sb, info);
mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
@@ -156,6 +155,7 @@ EXPORT_SYMBOL(fsapi_statfs);
s32 fsapi_sync_fs(struct super_block *sb, s32 do_sync)
{
s32 err;
+
mutex_lock(&(SDFAT_SB(sb)->s_vlock));
err = fscore_sync_fs(sb, do_sync);
mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
@@ -166,6 +166,7 @@ EXPORT_SYMBOL(fsapi_sync_fs);
s32 fsapi_set_vol_flags(struct super_block *sb, u16 new_flag, s32 always_sync)
{
s32 err;
+
mutex_lock(&(SDFAT_SB(sb)->s_vlock));
err = fscore_set_vol_flags(sb, new_flag, always_sync);
mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
@@ -263,7 +264,8 @@ s32 fsapi_truncate(struct inode *inode, u64 old_size, u64 new_size)
EXPORT_SYMBOL(fsapi_truncate);
/* rename or move a old file into a new file */
-s32 fsapi_rename(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry)
+s32 fsapi_rename(struct inode *old_parent_inode, FILE_ID_T *fid,
+ struct inode *new_parent_inode, struct dentry *new_dentry)
{
s32 err;
struct super_block *sb = old_parent_inode->i_sb;
@@ -299,7 +301,7 @@ s32 fsapi_read_inode(struct inode *inode, DIR_ENTRY_T *info)
{
s32 err;
struct super_block *sb = inode->i_sb;
-
+
mutex_lock(&(SDFAT_SB(sb)->s_vlock));
TMSG("%s entered (inode %p info %p\n", __func__, inode, info);
err = fscore_read_inode(inode, info);
@@ -414,13 +416,14 @@ s32 fsapi_rmdir(struct inode *inode, FILE_ID_T *fid)
}
EXPORT_SYMBOL(fsapi_rmdir);
-/* unlink a file.
- * that is, remove an entry from a directory. BUT don't truncate */
+/* unlink a file.
+ * that is, remove an entry from a directory. BUT don't truncate
+ */
s32 fsapi_unlink(struct inode *inode, FILE_ID_T *fid)
{
s32 err;
struct super_block *sb = inode->i_sb;
-
+
/* check the validity of pointer parameters */
ASSERT(fid);
mutex_lock(&(SDFAT_SB(sb)->s_vlock));
@@ -441,7 +444,6 @@ s32 fsapi_cache_flush(struct super_block *sb, int do_sync)
}
EXPORT_SYMBOL(fsapi_cache_flush);
-
/* release FAT & buf cache */
s32 fsapi_cache_release(struct super_block *sb)
{
@@ -457,7 +459,6 @@ s32 fsapi_cache_release(struct super_block *sb)
}
EXPORT_SYMBOL(fsapi_cache_release);
-
u32 fsapi_get_au_stat(struct super_block *sb, s32 mode)
{
/* volume lock is not required */
@@ -490,7 +491,6 @@ s32 fsapi_dfr_get_info(struct super_block *sb, void *arg)
}
EXPORT_SYMBOL(fsapi_dfr_get_info);
-
s32 fsapi_dfr_scan_dir(struct super_block *sb, void *args)
{
s32 err;
@@ -505,23 +505,23 @@ s32 fsapi_dfr_scan_dir(struct super_block *sb, void *args)
}
EXPORT_SYMBOL(fsapi_dfr_scan_dir);
-
s32 fsapi_dfr_validate_clus(struct inode *inode, void *chunk, int skip_prev)
{
s32 err;
struct super_block *sb = inode->i_sb;
+
mutex_lock(&(SDFAT_SB(sb)->s_vlock));
- err = defrag_validate_cluster(inode,
- (struct defrag_chunk_info *)chunk, skip_prev);
+ err = defrag_validate_cluster(inode,
+ (struct defrag_chunk_info *)chunk, skip_prev);
mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
- return(err);
+ return err;
}
EXPORT_SYMBOL(fsapi_dfr_validate_clus);
-
s32 fsapi_dfr_reserve_clus(struct super_block *sb, s32 nr_clus)
{
s32 err;
+
mutex_lock(&(SDFAT_SB(sb)->s_vlock));
err = defrag_reserve_clusters(sb, nr_clus);
mutex_unlock(&(SDFAT_SB(sb)->s_vlock));
@@ -529,7 +529,6 @@ s32 fsapi_dfr_reserve_clus(struct super_block *sb, s32 nr_clus)
}
EXPORT_SYMBOL(fsapi_dfr_reserve_clus);
-
s32 fsapi_dfr_mark_ignore(struct super_block *sb, unsigned int clus)
{
/* volume lock is not required */
@@ -537,7 +536,6 @@ s32 fsapi_dfr_mark_ignore(struct super_block *sb, unsigned int clus)
}
EXPORT_SYMBOL(fsapi_dfr_mark_ignore);
-
void fsapi_dfr_unmark_ignore_all(struct super_block *sb)
{
/* volume lock is not required */
@@ -545,7 +543,6 @@ void fsapi_dfr_unmark_ignore_all(struct super_block *sb)
}
EXPORT_SYMBOL(fsapi_dfr_unmark_ignore_all);
-
s32 fsapi_dfr_map_clus(struct inode *inode, u32 clu_offset, u32 *clu)
{
s32 err;
@@ -562,7 +559,6 @@ s32 fsapi_dfr_map_clus(struct inode *inode, u32 clu_offset, u32 *clu)
}
EXPORT_SYMBOL(fsapi_dfr_map_clus);
-
void fsapi_dfr_writepage_endio(struct page *page)
{
/* volume lock is not required */
@@ -570,7 +566,6 @@ void fsapi_dfr_writepage_endio(struct page *page)
}
EXPORT_SYMBOL(fsapi_dfr_writepage_endio);
-
void fsapi_dfr_update_fat_prev(struct super_block *sb, int force)
{
mutex_lock(&(SDFAT_SB(sb)->s_vlock));
@@ -579,7 +574,6 @@ void fsapi_dfr_update_fat_prev(struct super_block *sb, int force)
}
EXPORT_SYMBOL(fsapi_dfr_update_fat_prev);
-
void fsapi_dfr_update_fat_next(struct super_block *sb)
{
mutex_lock(&(SDFAT_SB(sb)->s_vlock));
@@ -588,7 +582,6 @@ void fsapi_dfr_update_fat_next(struct super_block *sb)
}
EXPORT_SYMBOL(fsapi_dfr_update_fat_next);
-
void fsapi_dfr_check_discard(struct super_block *sb)
{
mutex_lock(&(SDFAT_SB(sb)->s_vlock));
@@ -597,7 +590,6 @@ void fsapi_dfr_check_discard(struct super_block *sb)
}
EXPORT_SYMBOL(fsapi_dfr_check_discard);
-
void fsapi_dfr_free_clus(struct super_block *sb, u32 clus)
{
mutex_lock(&(SDFAT_SB(sb)->s_vlock));
@@ -606,7 +598,6 @@ void fsapi_dfr_free_clus(struct super_block *sb, u32 clus)
}
EXPORT_SYMBOL(fsapi_dfr_free_clus);
-
s32 fsapi_dfr_check_dfr_required(struct super_block *sb, int *totalau, int *cleanau, int *fullau)
{
/* volume lock is not required */
@@ -614,7 +605,6 @@ s32 fsapi_dfr_check_dfr_required(struct super_block *sb, int *totalau, int *clea
}
EXPORT_SYMBOL(fsapi_dfr_check_dfr_required);
-
s32 fsapi_dfr_check_dfr_on(struct inode *inode, loff_t start, loff_t end, s32 cancel, const char *caller)
{
/* volume lock is not required */
diff --git a/api.h b/api.h
index 26bc816..fb0bf7a 100644
--- a/api.h
+++ b/api.h
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
#ifndef _SDFAT_API_H
@@ -83,13 +81,13 @@ extern "C" {
/* NLS Type Definitions */
/*----------------------------------------------------------------------*/
-/* DOS name stucture */
+/* DOS name structure */
typedef struct {
u8 name[DOS_NAME_LENGTH];
u8 name_case;
} DOS_NAME_T;
-/* unicode name stucture */
+/* unicode name structure */
typedef struct {
u16 name[MAX_NAME_LENGTH+3]; /* +3 for null and for converting */
u16 name_hash;
@@ -187,8 +185,8 @@ typedef struct {
} FILE_ID_T;
typedef struct {
- s8* lfn;
- s8* sfn;
+ s8 *lfn;
+ s8 *sfn;
s32 lfnbuf_len; //usally MAX_UNINAME_BUF_SIZE
s32 sfnbuf_len; //usally MAX_DOSNAME_BUF_SIZE, used only for vfat, not for exfat
} DENTRY_NAMEBUF_T;
@@ -225,32 +223,32 @@ typedef struct __FATENT_OPS_T {
} FATENT_OPS_T;
typedef struct {
- s32 (*alloc_cluster)(struct super_block *sb, s32 num_alloc, CHAIN_T *p_chain, int dest);
- s32 (*free_cluster)(struct super_block *sb, CHAIN_T *p_chain, s32 do_relse);
- s32 (*count_used_clusters)(struct super_block *sb, u32* ret_count);
- s32 (*init_dir_entry)(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 type,u32 start_clu, u64 size);
- s32 (*init_ext_entry)(struct super_block *sb, CHAIN_T *p_dir, s32 entry, s32 num_entries, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname);
- s32 (*find_dir_entry)(struct super_block *sb, FILE_ID_T *fid, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, s32 num_entries, DOS_NAME_T *p_dosname, u32 type);
- s32 (*delete_dir_entry)(struct super_block *sb, CHAIN_T *p_dir, s32 entry, s32 offset, s32 num_entries);
- void (*get_uniname_from_ext_entry)(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u16 *uniname);
- s32 (*count_ext_entries)(struct super_block *sb, CHAIN_T *p_dir, s32 entry, DENTRY_T *p_entry);
- s32 (*calc_num_entries)(UNI_NAME_T *p_uniname);
- u32 (*get_entry_type)(DENTRY_T *p_entry);
- void (*set_entry_type)(DENTRY_T *p_entry, u32 type);
- u32 (*get_entry_attr)(DENTRY_T *p_entry);
- void (*set_entry_attr)(DENTRY_T *p_entry, u32 attr);
- u8 (*get_entry_flag)(DENTRY_T *p_entry);
- void (*set_entry_flag)(DENTRY_T *p_entry, u8 flag);
- u32 (*get_entry_clu0)(DENTRY_T *p_entry);
- void (*set_entry_clu0)(DENTRY_T *p_entry, u32 clu0);
- u64 (*get_entry_size)(DENTRY_T *p_entry);
- void (*set_entry_size)(DENTRY_T *p_entry, u64 size);
- void (*get_entry_time)(DENTRY_T *p_entry, TIMESTAMP_T *tp, u8 mode);
- void (*set_entry_time)(DENTRY_T *p_entry, TIMESTAMP_T *tp, u8 mode);
- u32 (*get_au_stat)(struct super_block *sb, s32 mode);
+ s32 (*alloc_cluster)(struct super_block *, s32, CHAIN_T *, int);
+ s32 (*free_cluster)(struct super_block *, CHAIN_T *, s32);
+ s32 (*count_used_clusters)(struct super_block *, u32 *);
+ s32 (*init_dir_entry)(struct super_block *, CHAIN_T *, s32, u32, u32, u64);
+ s32 (*init_ext_entry)(struct super_block *, CHAIN_T *, s32, s32, UNI_NAME_T *, DOS_NAME_T *);
+ s32 (*find_dir_entry)(struct super_block *, FILE_ID_T *, CHAIN_T *, UNI_NAME_T *, s32, DOS_NAME_T *, u32);
+ s32 (*delete_dir_entry)(struct super_block *, CHAIN_T *, s32, s32, s32);
+ void (*get_uniname_from_ext_entry)(struct super_block *, CHAIN_T *, s32, u16 *);
+ s32 (*count_ext_entries)(struct super_block *, CHAIN_T *, s32, DENTRY_T *);
+ s32 (*calc_num_entries)(UNI_NAME_T *);
+ s32 (*check_max_dentries)(FILE_ID_T *);
+ u32 (*get_entry_type)(DENTRY_T *);
+ void (*set_entry_type)(DENTRY_T *, u32);
+ u32 (*get_entry_attr)(DENTRY_T *);
+ void (*set_entry_attr)(DENTRY_T *, u32);
+ u8 (*get_entry_flag)(DENTRY_T *);
+ void (*set_entry_flag)(DENTRY_T *, u8);
+ u32 (*get_entry_clu0)(DENTRY_T *);
+ void (*set_entry_clu0)(DENTRY_T *, u32);
+ u64 (*get_entry_size)(DENTRY_T *);
+ void (*set_entry_size)(DENTRY_T *, u64);
+ void (*get_entry_time)(DENTRY_T *, TIMESTAMP_T *, u8);
+ void (*set_entry_time)(DENTRY_T *, TIMESTAMP_T *, u8);
+ u32 (*get_au_stat)(struct super_block *, s32);
} FS_FUNC_T;
-
typedef struct __FS_INFO_T {
s32 bd_opened; // opened or not
u32 vol_type; // volume FAT type
@@ -270,7 +268,7 @@ typedef struct __FS_INFO_T {
u32 dentries_in_root; // num of dentries in root dir
u32 dentries_per_clu; // num of dentries per cluster
u32 vol_flag; // volume dirty flag
- struct buffer_head *pbr_bh; // buffer_head of PBR sector
+ struct buffer_head *pbr_bh; // buffer_head of PBR sector
u32 map_clu; // allocation bitmap start cluster
u32 map_sectors; // num of allocation bitmap sectors
@@ -334,7 +332,8 @@ s32 fsapi_read_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count
s32 fsapi_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *wcount);
s32 fsapi_remove(struct inode *inode, FILE_ID_T *fid); /* unlink and truncate */
s32 fsapi_truncate(struct inode *inode, u64 old_size, u64 new_size);
-s32 fsapi_rename(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry);
+s32 fsapi_rename(struct inode *old_parent_inode, FILE_ID_T *fid,
+ struct inode *new_parent_inode, struct dentry *new_dentry);
s32 fsapi_unlink(struct inode *inode, FILE_ID_T *fid);
s32 fsapi_read_inode(struct inode *inode, DIR_ENTRY_T *info);
s32 fsapi_write_inode(struct inode *inode, DIR_ENTRY_T *info, int sync);
diff --git a/blkdev.c b/blkdev.c
index f5af49e..d0f38db 100644
--- a/blkdev.c
+++ b/blkdev.c
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
/************************************************************************/
@@ -50,14 +48,14 @@
/* FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY */
/************************************************************************/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
/* EMPTY */
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0) */
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) */
static struct backing_dev_info *inode_to_bdi(struct inode *bd_inode)
{
return bd_inode->i_mapping->backing_dev_info;
}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0) */
+#endif
/*======================================================================*/
/* Function Definitions */
@@ -66,7 +64,7 @@ s32 bdev_open_dev(struct super_block *sb)
{
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
- if (fsi->bd_opened)
+ if (fsi->bd_opened)
return 0;
fsi->bd_opened = true;
@@ -86,12 +84,13 @@ static inline s32 block_device_ejected(struct super_block *sb)
struct inode *bd_inode = sb->s_bdev->bd_inode;
struct backing_dev_info *bdi = inode_to_bdi(bd_inode);
- return bdi->dev == NULL;
+ return (bdi->dev == NULL);
}
s32 bdev_check_bdi_valid(struct super_block *sb)
{
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
+
if (block_device_ejected(sb)) {
if (!(fsi->prev_eio & SDFAT_EIO_BDI)) {
fsi->prev_eio |= SDFAT_EIO_BDI;
@@ -101,6 +100,7 @@ s32 bdev_check_bdi_valid(struct super_block *sb)
}
return -ENXIO;
}
+
return 0;
}
@@ -113,7 +113,7 @@ s32 bdev_readahead(struct super_block *sb, u32 secno, u32 num_secs)
struct blk_plug plug;
u32 i;
- if (!fsi->bd_opened)
+ if (!fsi->bd_opened)
return -EIO;
blk_start_plug(&plug);
@@ -135,11 +135,11 @@ s32 bdev_mread(struct super_block *sb, u32 secno, struct buffer_head **bh, u32 n
struct sdfat_sb_info *sbi = SDFAT_SB(sb);
long flags = sbi->debug_flags;
- if (flags & SDFAT_DEBUGFLAGS_ERROR_RW)
+ if (flags & SDFAT_DEBUGFLAGS_ERROR_RW)
return -EIO;
#endif /* CONFIG_SDFAT_DBG_IOCTL */
- if (!fsi->bd_opened)
+ if (!fsi->bd_opened)
return -EIO;
brelse(*bh);
@@ -153,17 +153,16 @@ s32 bdev_mread(struct super_block *sb, u32 secno, struct buffer_head **bh, u32 n
if (*bh)
return 0;
- /*
+ /*
* patch 1.2.4 : reset ONCE warning message per volume.
*/
- if(!(fsi->prev_eio & SDFAT_EIO_READ)) {
+ if (!(fsi->prev_eio & SDFAT_EIO_READ)) {
fsi->prev_eio |= SDFAT_EIO_READ;
sdfat_log_msg(sb, KERN_ERR, "%s: No bh. I/O error.", __func__);
sdfat_debug_warn_on(1);
}
return -EIO;
-
}
s32 bdev_mwrite(struct super_block *sb, u32 secno, struct buffer_head *bh, u32 num_secs, s32 sync)
@@ -175,11 +174,11 @@ s32 bdev_mwrite(struct super_block *sb, u32 secno, struct buffer_head *bh, u32 n
struct sdfat_sb_info *sbi = SDFAT_SB(sb);
long flags = sbi->debug_flags;
- if (flags & SDFAT_DEBUGFLAGS_ERROR_RW)
+ if (flags & SDFAT_DEBUGFLAGS_ERROR_RW)
return -EIO;
#endif /* CONFIG_SDFAT_DBG_IOCTL */
- if (!fsi->bd_opened)
+ if (!fsi->bd_opened)
return -EIO;
if (secno == bh->b_blocknr) {
@@ -206,14 +205,12 @@ s32 bdev_mwrite(struct super_block *sb, u32 secno, struct buffer_head *bh, u32 n
}
__brelse(bh2);
}
-
return 0;
-
no_bh:
- /*
+ /*
* patch 1.2.4 : reset ONCE warning message per volume.
*/
- if(!(fsi->prev_eio & SDFAT_EIO_WRITE)) {
+ if (!(fsi->prev_eio & SDFAT_EIO_WRITE)) {
fsi->prev_eio |= SDFAT_EIO_WRITE;
sdfat_log_msg(sb, KERN_ERR, "%s: No bh. I/O error.", __func__);
sdfat_debug_warn_on(1);
@@ -229,11 +226,11 @@ s32 bdev_sync_all(struct super_block *sb)
struct sdfat_sb_info *sbi = SDFAT_SB(sb);
long flags = sbi->debug_flags;
- if (flags & SDFAT_DEBUGFLAGS_ERROR_RW)
+ if (flags & SDFAT_DEBUGFLAGS_ERROR_RW)
return -EIO;
#endif /* CONFIG_SDFAT_DBG_IOCTL */
- if (!fsi->bd_opened)
+ if (!fsi->bd_opened)
return -EIO;
return sync_blockdev(sb->s_bdev);
@@ -245,85 +242,83 @@ s32 bdev_sync_all(struct super_block *sb)
s32 read_sect(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 read)
{
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
- BUG_ON(!bh);
- if ( (sec >= fsi->num_sectors)
- && (fsi->num_sectors > 0) ) {
- sdfat_fs_error_ratelimit(sb, "%s: out of range (sect:%u)",
- __func__, sec);
+ BUG_ON(!bh);
+ if ((sec >= fsi->num_sectors) && (fsi->num_sectors > 0)) {
+ sdfat_fs_error_ratelimit(sb,
+ "%s: out of range (sect:%u)", __func__, sec);
return -EIO;
}
if (bdev_mread(sb, sec, bh, 1, read)) {
- sdfat_fs_error_ratelimit(sb, "%s: I/O error (sect:%u)",
- __func__, sec);
+ sdfat_fs_error_ratelimit(sb,
+ "%s: I/O error (sect:%u)", __func__, sec);
return -EIO;
}
return 0;
-} /* end of read_sect */
+}
s32 write_sect(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 sync)
{
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
- BUG_ON(!bh);
- if ( (sec >= fsi->num_sectors)
- && (fsi->num_sectors > 0) ) {
- sdfat_fs_error_ratelimit(sb, "%s: out of range (sect:%u)",
- __func__, sec);
+ BUG_ON(!bh);
+ if ((sec >= fsi->num_sectors) && (fsi->num_sectors > 0)) {
+ sdfat_fs_error_ratelimit(sb,
+ "%s: out of range (sect:%u)", __func__, sec);
return -EIO;
}
if (bdev_mwrite(sb, sec, bh, 1, sync)) {
sdfat_fs_error_ratelimit(sb, "%s: I/O error (sect:%u)",
- __func__, sec);
+ __func__, sec);
return -EIO;
}
return 0;
-} /* end of write_sect */
+}
s32 read_msect(struct super_block *sb, u32 sec, struct buffer_head **bh, s32 num_secs, s32 read)
{
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
- BUG_ON(!bh);
- if ( ((sec+num_secs) > fsi->num_sectors) && (fsi->num_sectors > 0) ) {
+ BUG_ON(!bh);
+ if (((sec+num_secs) > fsi->num_sectors) && (fsi->num_sectors > 0)) {
sdfat_fs_error_ratelimit(sb, "%s: out of range(sect:%u len:%d)",
- __func__ ,sec, num_secs);
+ __func__, sec, num_secs);
return -EIO;
}
if (bdev_mread(sb, sec, bh, num_secs, read)) {
sdfat_fs_error_ratelimit(sb, "%s: I/O error (sect:%u len:%d)",
- __func__,sec, num_secs);
+ __func__, sec, num_secs);
return -EIO;
}
return 0;
-} /* end of read_msect */
+}
s32 write_msect(struct super_block *sb, u32 sec, struct buffer_head *bh, s32 num_secs, s32 sync)
{
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
- BUG_ON(!bh);
- if ( ((sec+num_secs) > fsi->num_sectors) && (fsi->num_sectors > 0) ) {
+ BUG_ON(!bh);
+ if (((sec+num_secs) > fsi->num_sectors) && (fsi->num_sectors > 0)) {
sdfat_fs_error_ratelimit(sb, "%s: out of range(sect:%u len:%d)",
- __func__ ,sec, num_secs);
+ __func__, sec, num_secs);
return -EIO;
}
if (bdev_mwrite(sb, sec, bh, num_secs, sync)) {
sdfat_fs_error_ratelimit(sb, "%s: I/O error (sect:%u len:%d)",
- __func__,sec, num_secs);
+ __func__, sec, num_secs);
return -EIO;
}
return 0;
-} /* end of write_msect */
+}
static inline void __blkdev_write_bhs(struct buffer_head **bhs, s32 nr_bhs)
{
@@ -347,8 +342,6 @@ static inline s32 __blkdev_sync_bhs(struct buffer_head **bhs, s32 nr_bhs)
static inline s32 __buffer_zeroed(struct super_block *sb, u32 blknr, s32 num_secs)
{
-#define MAX_BUF_PER_PAGE (PAGE_CACHE_SIZE / 512)
-
struct buffer_head *bhs[MAX_BUF_PER_PAGE];
s32 nr_bhs = MAX_BUF_PER_PAGE;
u32 last_blknr = blknr + num_secs;
@@ -407,14 +400,14 @@ s32 write_msect_zero(struct super_block *sb, u32 sec, s32 num_secs)
{
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
- if ( ((sec+num_secs) > fsi->num_sectors) && (fsi->num_sectors > 0) ) {
+ if (((sec+num_secs) > fsi->num_sectors) && (fsi->num_sectors > 0)) {
sdfat_fs_error_ratelimit(sb, "%s: out of range(sect:%u len:%d)",
- __func__ ,sec, num_secs);
+ __func__, sec, num_secs);
return -EIO;
}
/* Just return -EAGAIN if it is failed */
- if ( __buffer_zeroed(sb, sec, num_secs))
+ if (__buffer_zeroed(sb, sec, num_secs))
return -EAGAIN;
return 0;
diff --git a/cache.c b/cache.c
index 328b5e3..33901fa 100644
--- a/cache.c
+++ b/cache.c
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
/************************************************************************/
@@ -48,9 +46,9 @@
/*----------------------------------------------------------------------*/
/* Local Variable Definitions */
/*----------------------------------------------------------------------*/
-#define LOCKBIT 0x01
-#define DIRTYBIT 0x02
-#define KEEPBIT 0x04
+#define LOCKBIT (0x01)
+#define DIRTYBIT (0x02)
+#define KEEPBIT (0x04)
/*----------------------------------------------------------------------*/
/* Cache handling function declarations */
@@ -74,7 +72,7 @@ static void push_to_mru(cache_ent_t *bp, cache_ent_t *list)
bp->prev = list;
list->next->prev = bp;
list->next = bp;
-} /* end of __dcache_push_to_mru */
+}
static void push_to_lru(cache_ent_t *bp, cache_ent_t *list)
{
@@ -82,31 +80,31 @@ static void push_to_lru(cache_ent_t *bp, cache_ent_t *list)
bp->next = list;
list->prev->next = bp;
list->prev = bp;
-} /* end of __dcache_push_to_lru */
+}
static void move_to_mru(cache_ent_t *bp, cache_ent_t *list)
{
bp->prev->next = bp->next;
bp->next->prev = bp->prev;
push_to_mru(bp, list);
-} /* end of __dcache_move_to_mru */
+}
static void move_to_lru(cache_ent_t *bp, cache_ent_t *list)
{
bp->prev->next = bp->next;
bp->next->prev = bp->prev;
push_to_lru(bp, list);
-} /* end of __dcache_move_to_lru */
+}
static inline s32 __check_hash_valid(cache_ent_t *bp)
{
#ifdef DEBUG_HASH_LIST
- if ( (bp->hash.next == (cache_ent_t*)DEBUG_HASH_NEXT) ||
- (bp->hash.prev == (cache_ent_t*)DEBUG_HASH_PREV) ) {
+ if ((bp->hash.next == (cache_ent_t *)DEBUG_HASH_NEXT) ||
+ (bp->hash.prev == (cache_ent_t *)DEBUG_HASH_PREV)) {
return -EINVAL;
}
#endif
- if ( (bp->hash.next == bp) || (bp->hash.prev == bp) )
+ if ((bp->hash.next == bp) || (bp->hash.prev == bp))
return -EINVAL;
return 0;
@@ -119,15 +117,15 @@ static inline void __remove_from_hash(cache_ent_t *bp)
bp->hash.next = bp;
bp->hash.prev = bp;
#ifdef DEBUG_HASH_LIST
- bp->hash.next = (cache_ent_t*)DEBUG_HASH_NEXT;
- bp->hash.prev = (cache_ent_t*)DEBUG_HASH_PREV;
+ bp->hash.next = (cache_ent_t *)DEBUG_HASH_NEXT;
+ bp->hash.prev = (cache_ent_t *)DEBUG_HASH_PREV;
#endif
}
-/* Do FAT mirroring (don't sync)
- sec: sector No. in FAT1
- bh: bh of sec.
-*/
+/* Do FAT mirroring (don't sync)
+ * sec: sector No. in FAT1
+ * bh: bh of sec.
+ */
static inline s32 __fat_copy(struct super_block *sb, u32 sec, struct buffer_head *bh, int sync)
{
#ifdef CONFIG_SDFAT_FAT_MIRRORING
@@ -150,7 +148,7 @@ static inline s32 __fat_copy(struct super_block *sb, u32 sec, struct buffer_head
/*
* returns 1, if bp is flushed
- * returns 0, if bp is not dirty
+ * returns 0, if bp is not dirty
* returns -1, if error occurs
*/
static s32 __fcache_ent_flush(struct super_block *sb, cache_ent_t *bp, u32 sync)
@@ -176,11 +174,12 @@ static s32 __fcache_ent_flush(struct super_block *sb, cache_ent_t *bp, u32 sync)
static s32 __fcache_ent_discard(struct super_block *sb, cache_ent_t *bp)
{
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
+
__fcache_remove_hash(bp);
bp->sec = ~0;
bp->flag = 0;
- if(bp->bh) {
+ if (bp->bh) {
__brelse(bp->bh);
bp->bh = NULL;
}
@@ -202,11 +201,10 @@ u8 *fcache_getblk(struct super_block *sb, u32 sec)
return NULL;
}
move_to_mru(bp, &fsi->fcache.lru_list);
- return(bp->bh->b_data);
+ return bp->bh->b_data;
}
bp = __fcache_get(sb, sec);
-
if (!__check_hash_valid(bp))
__fcache_remove_hash(bp);
@@ -218,10 +216,10 @@ u8 *fcache_getblk(struct super_block *sb, u32 sec)
if ((sec & (page_ra_count - 1)) == 0)
bdev_readahead(sb, sec, page_ra_count);
- /*
+ /*
* patch 1.2.4 : buffer_head null pointer exception problem.
*
- * When read_sect is failed, fcache should be moved to
+ * When read_sect is failed, fcache should be moved to
* EMPTY hash_list and the first of lru_list.
*/
if (read_sect(sb, sec, &(bp->bh), 1)) {
@@ -236,9 +234,10 @@ static inline int __mark_delayed_dirty(struct super_block *sb, cache_ent_t *bp)
{
#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
+
if (fsi->vol_type == EXFAT)
return -ENOTSUPP;
-
+
bp->flag |= DIRTYBIT;
return 0;
#else
@@ -253,8 +252,10 @@ s32 fcache_modify(struct super_block *sb, u32 sec)
cache_ent_t *bp;
bp = __fcache_find(sb, sec);
- if (!bp)
+ if (!bp) {
+ sdfat_fs_error(sb, "Can`t find fcache (sec 0x%08x)", sec);
return -EIO;
+ }
if (!__mark_delayed_dirty(sb, bp))
return 0;
@@ -346,15 +347,16 @@ s32 fcache_release_all(struct super_block *sb)
bp = fsi->fcache.lru_list.next;
while (bp != &fsi->fcache.lru_list) {
s32 ret_tmp = __fcache_ent_flush(sb, bp, 0);
+
if (ret_tmp < 0)
ret = ret_tmp;
else
dirtycnt += ret_tmp;
-
+
bp->sec = ~0;
bp->flag = 0;
- if(bp->bh) {
+ if (bp->bh) {
__brelse(bp->bh);
bp->bh = NULL;
}
@@ -383,7 +385,7 @@ s32 fcache_flush(struct super_block *sb, u32 sync)
dirtycnt += ret;
bp = bp->next;
}
-
+
MMSG("BD: flush / dirty fat cache: %d (err:%d)\n", dirtycnt, ret);
return ret;
}
@@ -395,11 +397,9 @@ static cache_ent_t *__fcache_find(struct super_block *sb, u32 sec)
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
off = (sec + (sec >> fsi->sect_per_clus_bits)) & (FAT_CACHE_HASH_SIZE - 1);
-
hp = &(fsi->fcache.hash_list[off]);
for (bp = hp->hash.next; bp != hp; bp = bp->hash.next) {
if (bp->sec == sec) {
-
/*
* patch 1.2.4 : for debugging
*/
@@ -407,11 +407,11 @@ static cache_ent_t *__fcache_find(struct super_block *sb, u32 sec)
"It will make system panic.\n");
touch_buffer(bp->bh);
- return(bp);
+ return bp;
}
}
- return(NULL);
-} /* end of __fcache_find */
+ return NULL;
+}
static cache_ent_t *__fcache_get(struct super_block *sb, u32 sec)
{
@@ -419,7 +419,6 @@ static cache_ent_t *__fcache_get(struct super_block *sb, u32 sec)
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
bp = fsi->fcache.lru_list.prev;
-
#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY
while (bp->flag & DIRTYBIT) {
cache_ent_t *bp_prev = bp->prev;
@@ -436,8 +435,8 @@ static cache_ent_t *__fcache_get(struct super_block *sb, u32 sec)
// sync_dirty_buffer(bp->bh);
move_to_mru(bp, &fsi->fcache.lru_list);
- return(bp);
-} /* end of __fcache_get */
+ return bp;
+}
static void __fcache_insert_hash(struct super_block *sb, cache_ent_t *bp)
{
@@ -453,14 +452,14 @@ static void __fcache_insert_hash(struct super_block *sb, cache_ent_t *bp)
bp->hash.prev = hp;
hp->hash.next->hash.prev = bp;
hp->hash.next = bp;
-} /* end of __fcache_insert_hash */
+}
static void __fcache_remove_hash(cache_ent_t *bp)
{
#ifdef DEBUG_HASH_LIST
- if ( (bp->hash.next == (cache_ent_t*)DEBUG_HASH_NEXT) ||
- (bp->hash.prev == (cache_ent_t*)DEBUG_HASH_PREV) ) {
+ if ((bp->hash.next == (cache_ent_t *)DEBUG_HASH_NEXT) ||
+ (bp->hash.prev == (cache_ent_t *)DEBUG_HASH_PREV)) {
EMSG("%s: FATAL: tried to remove already-removed-cache-entry"
"(bp:%p)\n", __func__, bp);
return;
@@ -468,7 +467,7 @@ static void __fcache_remove_hash(cache_ent_t *bp)
#endif
WARN_ON(bp->flag & DIRTYBIT);
__remove_from_hash(bp);
-} /* end of __fcache_remove_hash */
+}
/*======================================================================*/
/* Buffer Read/Write Functions */
@@ -483,12 +482,12 @@ s32 dcache_readahead(struct super_block *sb, u32 sec)
u32 adj_ra_count = max(fsi->sect_per_clus, page_ra_count);
u32 ra_count = min(adj_ra_count, max_ra_count);
- /* Read-ahead is not required */
+ /* Read-ahead is not required */
if (fsi->sect_per_clus == 1)
return 0;
if (sec < fsi->data_start_sector) {
- EMSG("BD: %s: requested sector is invalid(sect:%u, root:%u)\n",
+ EMSG("BD: %s: requested sector is invalid(sect:%u, root:%u)\n",
__func__, sec, fsi->data_start_sector);
return -EIO;
}
@@ -508,7 +507,7 @@ s32 dcache_readahead(struct super_block *sb, u32 sec)
/*
* returns 1, if bp is flushed
- * returns 0, if bp is not dirty
+ * returns 0, if bp is not dirty
* returns -1, if error occurs
*/
static s32 __dcache_ent_flush(struct super_block *sb, cache_ent_t *bp, u32 sync)
@@ -533,15 +532,15 @@ static s32 __dcache_ent_discard(struct super_block *sb, cache_ent_t *bp)
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
MMSG("%s : bp[%p] (sec:%08x flag:%08x bh:%p) list(prev:%p next:%p) "
- "hash(prev:%p next:%p)\n", __func__,
+ "hash(prev:%p next:%p)\n", __func__,
bp, bp->sec, bp->flag, bp->bh, bp->prev, bp->next,
bp->hash.prev, bp->hash.next);
-
+
__dcache_remove_hash(bp);
bp->sec = ~0;
bp->flag = 0;
- if(bp->bh) {
+ if (bp->bh) {
__brelse(bp->bh);
bp->bh = NULL;
}
@@ -568,7 +567,7 @@ u8 *dcache_getblk(struct super_block *sb, u32 sec)
if (!(bp->flag & KEEPBIT)) // already in keep list
move_to_mru(bp, &fsi->dcache.lru_list);
- return(bp->bh->b_data);
+ return bp->bh->b_data;
}
bp = __dcache_get(sb, sec);
@@ -597,20 +596,21 @@ s32 dcache_modify(struct super_block *sb, u32 sec)
set_sb_dirty(sb);
bp = __dcache_find(sb, sec);
- if (likely(bp)) {
-#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY
- FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
- if (fsi->vol_type != EXFAT) {
- bp->flag |= DIRTYBIT;
- return 0;
- }
-#endif
- ret = write_sect(sb, sec, bp->bh, 0);
+ if (unlikely(!bp)) {
+ sdfat_fs_error(sb, "Can`t find dcache (sec 0x%08x)", sec);
+ return -EIO;
}
+#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY
+ if (SDFAT_SB(sb)->fsi.vol_type != EXFAT) {
+ bp->flag |= DIRTYBIT;
+ return 0;
+ }
+#endif
+ ret = write_sect(sb, sec, bp->bh, 0);
if (ret) {
DMSG("%s : failed to modify buffer(err:%d, sec:%u, bp:0x%p)\n",
- __func__, ret, sec, bp);
+ __func__, ret, sec, bp);
}
return ret;
@@ -621,7 +621,7 @@ s32 dcache_lock(struct super_block *sb, u32 sec)
cache_ent_t *bp;
bp = __dcache_find(sb, sec);
- if (likely(bp)) {
+ if (likely(bp)) {
bp->flag |= LOCKBIT;
return 0;
}
@@ -662,7 +662,7 @@ s32 dcache_release(struct super_block *sb, u32 sec)
bp->sec = ~0;
bp->flag = 0;
- if(bp->bh) {
+ if (bp->bh) {
__brelse(bp->bh);
bp->bh = NULL;
}
@@ -678,9 +678,10 @@ s32 dcache_release_all(struct super_block *sb)
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
s32 dirtycnt = 0;
- /* Connect list elements */
- /* LRU list : (A - B - ... - bp_front) + (bp_first + ... + bp_last) */
- while (fsi->dcache.keep_list.prev != &fsi->dcache.keep_list){
+ /* Connect list elements:
+ * LRU list : (A - B - ... - bp_front) + (bp_first + ... + bp_last)
+ */
+ while (fsi->dcache.keep_list.prev != &fsi->dcache.keep_list) {
cache_ent_t *bp_keep = fsi->dcache.keep_list.prev;
// bp_keep->flag &= ~(KEEPBIT); // Will be 0-ed later
move_to_mru(bp_keep, &fsi->dcache.lru_list);
@@ -695,11 +696,10 @@ s32 dcache_release_all(struct super_block *sb)
ret = -EIO;
}
#endif
-
bp->sec = ~0;
bp->flag = 0;
- if(bp->bh) {
+ if (bp->bh) {
__brelse(bp->bh);
bp->bh = NULL;
}
@@ -719,14 +719,14 @@ s32 dcache_flush(struct super_block *sb, u32 sync)
s32 dirtycnt = 0;
s32 keepcnt = 0;
- /* Connect list elements */
- /* LRU list : (A - B - ... - bp_front) + (bp_first + ... + bp_last) */
- // XXX: optimization
- while (fsi->dcache.keep_list.prev != &fsi->dcache.keep_list){
+ /* Connect list elements:
+ * LRU list : (A - B - ... - bp_front) + (bp_first + ... + bp_last)
+ */
+ while (fsi->dcache.keep_list.prev != &fsi->dcache.keep_list) {
cache_ent_t *bp_keep = fsi->dcache.keep_list.prev;
+
bp_keep->flag &= ~(KEEPBIT); // Will be 0-ed later
move_to_mru(bp_keep, &fsi->dcache.lru_list);
-
keepcnt++;
}
@@ -750,7 +750,7 @@ s32 dcache_flush(struct super_block *sb, u32 sync)
bp = bp->next;
}
- MMSG("BD: flush / dirty dentry cache: %d (%d from keeplist, err:%d)\n",
+ MMSG("BD: flush / dirty dentry cache: %d (%d from keeplist, err:%d)\n",
dirtycnt, keepcnt, ret);
return ret;
}
@@ -767,11 +767,11 @@ static cache_ent_t *__dcache_find(struct super_block *sb, u32 sec)
for (bp = hp->hash.next; bp != hp; bp = bp->hash.next) {
if (bp->sec == sec) {
touch_buffer(bp->bh);
- return(bp);
+ return bp;
}
}
return NULL;
-} /* end of __dcache_find */
+}
static cache_ent_t *__dcache_get(struct super_block *sb, u32 sec)
{
@@ -788,7 +788,6 @@ static cache_ent_t *__dcache_get(struct super_block *sb, u32 sec)
bp->flag |= KEEPBIT;
move_to_mru(bp, &fsi->dcache.keep_list);
}
-
bp = bp_prev;
/* If all dcaches are dirty */
@@ -799,15 +798,15 @@ static cache_ent_t *__dcache_get(struct super_block *sb, u32 sec)
}
}
#else
- while (bp->flag & LOCKBIT)
+ while (bp->flag & LOCKBIT)
bp = bp->prev;
#endif
// if (bp->flag & DIRTYBIT)
// sync_dirty_buffer(bp->bh);
move_to_mru(bp, &fsi->dcache.lru_list);
- return(bp);
-} /* end of __dcache_get */
+ return bp;
+}
static void __dcache_insert_hash(struct super_block *sb, cache_ent_t *bp)
{
@@ -823,13 +822,13 @@ static void __dcache_insert_hash(struct super_block *sb, cache_ent_t *bp)
bp->hash.prev = hp;
hp->hash.next->hash.prev = bp;
hp->hash.next = bp;
-} /* end of __dcache_insert_hash */
+}
static void __dcache_remove_hash(cache_ent_t *bp)
{
#ifdef DEBUG_HASH_LIST
- if ( (bp->hash.next == (cache_ent_t*)DEBUG_HASH_NEXT) ||
- (bp->hash.prev == (cache_ent_t*)DEBUG_HASH_PREV) ) {
+ if ((bp->hash.next == (cache_ent_t *)DEBUG_HASH_NEXT) ||
+ (bp->hash.prev == (cache_ent_t *)DEBUG_HASH_PREV)) {
EMSG("%s: FATAL: tried to remove already-removed-cache-entry"
"(bp:%p)\n", __func__, bp);
return;
@@ -837,7 +836,7 @@ static void __dcache_remove_hash(cache_ent_t *bp)
#endif
WARN_ON(bp->flag & DIRTYBIT);
__remove_from_hash(bp);
-} /* end of __dcache_remove_hash */
+}
/* end of cache.c */
diff --git a/config.h b/config.h
index e786fe8..6e2a4e8 100644
--- a/config.h
+++ b/config.h
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
#ifndef _SDFAT_CONFIG_H
@@ -65,7 +63,7 @@
#ifndef CONFIG_SDFAT_FAT32_SHORTNAME_SEQ /* Shortname ~1, ... ~9 have higher
* priority (WIN32/VFAT-like)
*/
-//#define CONFIG_SDFAT_FAT32_SHORTNAME_SEQ
+//#define CONFIG_SDFAT_FAT32_SHORTNAME_SEQ
#endif
#ifndef CONFIG_SDFAT_ALIGNED_MPAGE_WRITE
@@ -101,7 +99,7 @@
#endif
#ifndef CONFIG_SDFAT_VIRTUAL_XATTR
-#define CONFIG_SDFAT_VIRTUAL_XATTR
+//#define CONFIG_SDFAT_VIRTUAL_XATTR
#endif
#ifndef CONFIG_SDFAT_SUPPORT_STLOG
@@ -114,7 +112,7 @@
#ifndef CONFIG_SDFAT_DBG_IOCTL
//#define CONFIG_SDFAT_DBG_IOCTL
-#endif
+#endif
#ifndef CONFIG_SDFAT_DBG_MSG
//#define CONFIG_SDFAT_DBG_MSG
diff --git a/core.c b/core.c
index b38909f..4384816 100644
--- a/core.c
+++ b/core.c
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
/************************************************************************/
@@ -46,18 +44,19 @@
/*----------------------------------------------------------------------*/
static inline void __set_sb_dirty(struct super_block *sb)
{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)
sb->s_dirt = 1;
-#else
+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) */
struct sdfat_sb_info *sbi = SDFAT_SB(sb);
- sbi->s_dirt = 1; // XXX: really needed?
+ sbi->s_dirt = 1;
/* Insert work */
spin_lock(&sbi->work_lock);
if (!sbi->write_super_queued) {
unsigned long delay;
+
delay = msecs_to_jiffies(CONFIG_SDFAT_WRITE_SB_INTERVAL_CSECS * 10);
- queue_delayed_work(system_long_wq , &sbi->write_super_work, delay);
+ queue_delayed_work(system_long_wq, &sbi->write_super_work, delay);
sbi->write_super_queued = 1;
}
spin_unlock(&sbi->work_lock);
@@ -99,41 +98,32 @@ static s8 *reserved_names[] = {
static s32 check_type_size(void)
{
/* critical check for system requirement on size of DENTRY_T structure */
- if (sizeof(DENTRY_T) != DENTRY_SIZE) {
+ if (sizeof(DENTRY_T) != DENTRY_SIZE)
return -EINVAL;
- }
- if (sizeof(DOS_DENTRY_T) != DENTRY_SIZE) {
+ if (sizeof(DOS_DENTRY_T) != DENTRY_SIZE)
return -EINVAL;
- }
- if (sizeof(EXT_DENTRY_T) != DENTRY_SIZE) {
+ if (sizeof(EXT_DENTRY_T) != DENTRY_SIZE)
return -EINVAL;
- }
- if (sizeof(FILE_DENTRY_T) != DENTRY_SIZE) {
+ if (sizeof(FILE_DENTRY_T) != DENTRY_SIZE)
return -EINVAL;
- }
- if (sizeof(STRM_DENTRY_T) != DENTRY_SIZE) {
+ if (sizeof(STRM_DENTRY_T) != DENTRY_SIZE)
return -EINVAL;
- }
- if (sizeof(NAME_DENTRY_T) != DENTRY_SIZE) {
+ if (sizeof(NAME_DENTRY_T) != DENTRY_SIZE)
return -EINVAL;
- }
- if (sizeof(BMAP_DENTRY_T) != DENTRY_SIZE) {
+ if (sizeof(BMAP_DENTRY_T) != DENTRY_SIZE)
return -EINVAL;
- }
- if (sizeof(CASE_DENTRY_T) != DENTRY_SIZE) {
+ if (sizeof(CASE_DENTRY_T) != DENTRY_SIZE)
return -EINVAL;
- }
- if (sizeof(VOLM_DENTRY_T) != DENTRY_SIZE) {
+ if (sizeof(VOLM_DENTRY_T) != DENTRY_SIZE)
return -EINVAL;
- }
return 0;
}
@@ -150,8 +140,9 @@ static s32 __fs_set_vol_flags(struct super_block *sb, u16 new_flag, s32 always_s
fsi->vol_flag = new_flag;
- /* skip updating volume dirty flag,
- * if this volume has been mounted with read-only */
+ /* skip updating volume dirty flag,
+ * if this volume has been mounted with read-only
+ */
if (sb->s_flags & MS_RDONLY)
return 0;
@@ -164,12 +155,12 @@ static s32 __fs_set_vol_flags(struct super_block *sb, u16 new_flag, s32 always_s
}
if (fsi->vol_type == EXFAT) {
- pbr64_t *bpb = (pbr64_t *) fsi->pbr_bh->b_data;
+ pbr64_t *bpb = (pbr64_t *)fsi->pbr_bh->b_data;
bpb->bsx.vol_flags = cpu_to_le16(new_flag);
} else if (fsi->vol_type == FAT32) {
- pbr32_t *bpb = (pbr32_t *) fsi->pbr_bh->b_data;
+ pbr32_t *bpb = (pbr32_t *)fsi->pbr_bh->b_data;
bpb->bsx.state = new_flag & VOL_DIRTY ? FAT_VOL_DIRTY : 0x00;
- } else {
+ } else { /* FAT16/12 */
pbr16_t *bpb = (pbr16_t *) fsi->pbr_bh->b_data;
bpb->bpb.state = new_flag & VOL_DIRTY ? FAT_VOL_DIRTY : 0x00;
}
@@ -202,7 +193,7 @@ static inline s32 __fs_meta_sync(struct super_block *sb, s32 do_sync)
{
#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
-
+
if (fsi->vol_type != EXFAT) {
MMSG("meta flush in fs_sync(sync=%d)\n", do_sync);
fcache_flush(sb, 0);
@@ -218,14 +209,14 @@ static s32 fs_sync(struct super_block *sb, s32 do_sync)
{
s32 err;
- if (!do_sync)
+ if (!do_sync)
return 0;
err = __fs_meta_sync(sb, do_sync);
if (!err)
err = bdev_sync_all(sb);
-
+
if (err)
EMSG("%s : failed to sync. (err:%d)\n", __func__, err);
@@ -280,17 +271,17 @@ out:
return ret;
} /* end of __clear_cluster */
-static s32 __find_last_cluster(struct super_block *sb, CHAIN_T *p_chain, u32* ret_clu)
+static s32 __find_last_cluster(struct super_block *sb, CHAIN_T *p_chain, u32 *ret_clu)
{
u32 clu, next;
s32 count = 0;
- next = p_chain->dir;
+ next = p_chain->dir;
if (p_chain->flags == 0x03) {
*ret_clu = next + p_chain->size - 1;
return 0;
}
-
+
do {
count++;
clu = next;
@@ -311,7 +302,7 @@ static s32 __find_last_cluster(struct super_block *sb, CHAIN_T *p_chain, u32* re
}
-static s32 __count_num_clusters(struct super_block *sb, CHAIN_T *p_chain, s32* ret_count)
+static s32 __count_num_clusters(struct super_block *sb, CHAIN_T *p_chain, s32 *ret_count)
{
s32 i, count;
u32 clu;
@@ -326,7 +317,7 @@ static s32 __count_num_clusters(struct super_block *sb, CHAIN_T *p_chain, s32* r
*ret_count = p_chain->size;
return 0;
}
-
+
clu = p_chain->dir;
count = 0;
for (i = CLUS_BASE; i < fsi->num_clusters; i++) {
@@ -351,15 +342,15 @@ static void free_upcase_table(struct super_block *sb)
u16 **upcase_table;
upcase_table = fsi->vol_utbl;
- for(i = 0 ; i < UTBL_COL_COUNT ; i ++) {
- if (upcase_table[i])
- kfree(upcase_table[i]);
+ for (i = 0 ; i < UTBL_COL_COUNT ; i++) {
+ /* kfree(NULL) is safe */
+ kfree(upcase_table[i]);
+ upcase_table[i] = NULL;
}
- if (fsi->vol_utbl) {
- kfree(fsi->vol_utbl);
- fsi->vol_utbl = NULL;
- }
+ /* kfree(NULL) is safe */
+ kfree(fsi->vol_utbl);
+ fsi->vol_utbl = NULL;
}
static s32 __load_upcase_table(struct super_block *sb, u32 sector, u32 num_sectors, u32 utbl_checksum)
@@ -373,8 +364,9 @@ static s32 __load_upcase_table(struct super_block *sb, u32 sector, u32 num_secto
u8 skip = false;
u32 index = 0;
u32 checksum = 0;
- u16 **upcase_table = (u16 **)kzalloc((UTBL_COL_COUNT * sizeof(u16 *)), GFP_KERNEL);
- if(!upcase_table)
+ u16 **upcase_table = kzalloc((UTBL_COL_COUNT * sizeof(u16 *)), GFP_KERNEL);
+
+ if (!upcase_table)
return -ENOMEM;
/* thanks for kzalloc
* memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *));
@@ -383,28 +375,28 @@ static s32 __load_upcase_table(struct super_block *sb, u32 sector, u32 num_secto
fsi->vol_utbl = upcase_table;
num_sectors += sector;
- while(sector < num_sectors) {
+ while (sector < num_sectors) {
ret = read_sect(sb, sector, &tmp_bh, 1);
if (ret) {
- EMSG("%s: failed to read sector(0x%x)\n",
+ EMSG("%s: failed to read sector(0x%x)\n",
__func__, sector);
goto error;
}
sector++;
- for(i = 0; i < sect_size && index <= 0xFFFF; i += 2) {
+ for (i = 0; i < sect_size && index <= 0xFFFF; i += 2) {
/* FIXME : is __le16 ok? */
//u16 uni = le16_to_cpu(((__le16*)(tmp_bh->b_data))[i]);
- u16 uni = get_unaligned_le16((u8*)tmp_bh->b_data+i);
+ u16 uni = get_unaligned_le16((u8 *)tmp_bh->b_data+i);
- checksum = ((checksum & 1) ? 0x80000000 : 0 ) +
- (checksum >> 1) + *(((u8*)tmp_bh->b_data)+i);
- checksum = ((checksum & 1) ? 0x80000000 : 0 ) +
- (checksum >> 1) + *(((u8*)tmp_bh->b_data)+(i+1));
+ checksum = ((checksum & 1) ? 0x80000000 : 0) +
+ (checksum >> 1) + *(((u8 *)tmp_bh->b_data)+i);
+ checksum = ((checksum & 1) ? 0x80000000 : 0) +
+ (checksum >> 1) + *(((u8 *)tmp_bh->b_data)+(i+1));
if (skip) {
MMSG("skip from 0x%X to 0x%X(amount of 0x%X)\n",
- index, index+uni, uni);
+ index, index+uni, uni);
index += uni;
skip = false;
} else if (uni == index) {
@@ -413,17 +405,19 @@ static s32 __load_upcase_table(struct super_block *sb, u32 sector, u32 num_secto
skip = true;
} else { /* uni != index , uni != 0xFFFF */
u16 col_index = get_col_index(index);
+
if (!upcase_table[col_index]) {
- upcase_table[col_index] = (u16 *)kmalloc((UTBL_ROW_COUNT * sizeof(u16)), GFP_KERNEL);
+ upcase_table[col_index] =
+ kmalloc((UTBL_ROW_COUNT * sizeof(u16)), GFP_KERNEL);
if (!upcase_table[col_index]) {
EMSG("failed to allocate memory"
- " for column 0x%X\n",
+ " for column 0x%X\n",
col_index);
ret = -ENOMEM;
goto error;
}
- for(j = 0 ; j < UTBL_ROW_COUNT ; j++)
+ for (j = 0; j < UTBL_ROW_COUNT; j++)
upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j;
}
@@ -434,22 +428,22 @@ static s32 __load_upcase_table(struct super_block *sb, u32 sector, u32 num_secto
}
if (index >= 0xFFFF && utbl_checksum == checksum) {
DMSG("%s: load upcase table successfully"
- "(idx:0x%08x, utbl_chksum:0x%08x)\n",
- __func__, index, utbl_checksum);
- if(tmp_bh)
+ "(idx:0x%08x, utbl_chksum:0x%08x)\n",
+ __func__, index, utbl_checksum);
+ if (tmp_bh)
brelse(tmp_bh);
return 0;
}
EMSG("%s: failed to load upcase table"
- "(idx:0x%08x, chksum:0x%08x, utbl_chksum:0x%08x)\n",
+ "(idx:0x%08x, chksum:0x%08x, utbl_chksum:0x%08x)\n",
__func__, index, checksum, utbl_checksum);
ret = -EINVAL;
error:
- if(tmp_bh)
+ if (tmp_bh)
brelse(tmp_bh);
- free_upcase_table(sb);
+ free_upcase_table(sb);
return ret;
}
@@ -459,36 +453,36 @@ static s32 __load_default_upcase_table(struct super_block *sb)
u32 j;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
- u8 skip = false;
- u32 index = 0;
- u16 uni = 0;
+ u8 skip = false;
+ u32 index = 0;
+ u16 uni = 0;
u16 **upcase_table;
- upcase_table = (u16 **) kmalloc((UTBL_COL_COUNT * sizeof(u16 *)), GFP_KERNEL);
- if(!upcase_table)
+ upcase_table = kmalloc((UTBL_COL_COUNT * sizeof(u16 *)), GFP_KERNEL);
+ if (!upcase_table)
return -ENOMEM;
-
+
fsi->vol_utbl = upcase_table;
memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *));
- for(i = 0; index <= 0xFFFF && i < SDFAT_NUM_UPCASE*2; i += 2) {
+ for (i = 0; index <= 0xFFFF && i < SDFAT_NUM_UPCASE*2; i += 2) {
/* FIXME : is __le16 ok? */
//uni = le16_to_cpu(((__le16*)uni_def_upcase)[i>>1]);
- uni = get_unaligned_le16((u8*)uni_def_upcase+i);
- if(skip) {
+ uni = get_unaligned_le16((u8 *)uni_def_upcase+i);
+ if (skip) {
MMSG("skip from 0x%x ", index);
index += uni;
MMSG("to 0x%x (amount of 0x%x)\n", index, uni);
skip = false;
- } else if(uni == index)
+ } else if (uni == index) {
index++;
- else if(uni == 0xFFFF)
+ } else if (uni == 0xFFFF) {
skip = true;
- else { /* uni != index , uni != 0xFFFF */
+ } else { /* uni != index , uni != 0xFFFF */
u16 col_index = get_col_index(index);
if (!upcase_table[col_index]) {
- upcase_table[col_index] = (u16 *) kmalloc((UTBL_ROW_COUNT * sizeof(u16)), GFP_KERNEL);
+ upcase_table[col_index] = kmalloc((UTBL_ROW_COUNT * sizeof(u16)), GFP_KERNEL);
if (!upcase_table[col_index]) {
EMSG("failed to allocate memory for "
"new column 0x%x\n", col_index);
@@ -496,21 +490,21 @@ static s32 __load_default_upcase_table(struct super_block *sb)
goto error;
}
- for(j = 0 ; j < UTBL_ROW_COUNT ; j++)
+ for (j = 0; j < UTBL_ROW_COUNT; j++)
upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j;
}
upcase_table[col_index][get_row_index(index)] = uni;
- index ++;
+ index++;
}
}
- if(index >= 0xFFFF)
+ if (index >= 0xFFFF)
return 0;
error:
/* FATAL error: default upcase table has error */
- free_upcase_table(sb);
+ free_upcase_table(sb);
return ret;
}
@@ -548,7 +542,7 @@ static s32 load_upcase_table(struct super_block *sb)
sector = CLUS_TO_SECT(fsi, tbl_clu);
num_sectors = ((tbl_size-1) >> blksize_bits) + 1;
- ret = __load_upcase_table(sb, sector, num_sectors,
+ ret = __load_upcase_table(sb, sector, num_sectors,
le32_to_cpu(ep->checksum));
if (ret && (ret != -EIO))
@@ -607,7 +601,7 @@ static s32 find_location(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32
{
s32 ret;
u32 off, clu = 0;
- u32 blksize_mask = (u32)(sb->s_blocksize-1);
+ u32 blksize_mask = (u32)(sb->s_blocksize-1);
u8 blksize_bits = sb->s_blocksize_bits;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
@@ -620,19 +614,19 @@ static s32 find_location(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32
*sector += fsi->root_start_sector;
return 0;
}
-
- ret =walk_fat_chain(sb, p_dir, off, &clu);
+
+ ret = walk_fat_chain(sb, p_dir, off, &clu);
if (ret)
return ret;
/* byte offset in cluster */
- off &= (fsi->cluster_size - 1);
+ off &= (fsi->cluster_size - 1);
/* byte offset in sector */
*offset = off & blksize_mask;
/* sector offset in cluster */
- *sector = off >> blksize_bits;
+ *sector = off >> blksize_bits;
*sector += CLUS_TO_SECT(fsi, clu);
return 0;
} /* end of find_location */
@@ -832,10 +826,8 @@ static s32 find_empty_entry(struct inode *inode, CHAIN_T *p_dir, s32 num_entries
if (dentry == -EIO)
break;
- if ((fid->size >> DENTRY_SIZE_BITS) >= MAX_FAT_DENTRIES) {
- /* FAT spec allows a dir to grow upto 65536 dentries */
+ if (fsi->fs_func->check_max_dentries(fid))
return -ENOSPC;
- }
/* we trust p_dir->size regardless of FAT type */
if (__find_last_cluster(sb, p_dir, &last_clu))
@@ -848,9 +840,10 @@ static s32 find_empty_entry(struct inode *inode, CHAIN_T *p_dir, s32 num_entries
clu.size = 0; /* UNUSED */
clu.flags = p_dir->flags;
- /* (0) check if there are reserved clusters
- (create_dir 의 주석 참고) */
- if (!IS_CLUS_EOF(fsi->used_clusters) && \
+ /* (0) check if there are reserved clusters
+ * (create_dir 의 주석 참고)
+ */
+ if (!IS_CLUS_EOF(fsi->used_clusters) &&
((fsi->used_clusters + fsi->reserved_clusters) >= (fsi->num_clusters - 2)))
return -ENOSPC;
@@ -873,6 +866,7 @@ static s32 find_empty_entry(struct inode *inode, CHAIN_T *p_dir, s32 num_entries
p_dir->flags = 0x01;
hint_femp.cur.flags = 0x01;
}
+
if (clu.flags == 0x01)
if (fat_ent_set(sb, last_clu, clu.dir))
return -EIO;
@@ -881,7 +875,6 @@ static s32 find_empty_entry(struct inode *inode, CHAIN_T *p_dir, s32 num_entries
/* the special case that new dentry
* should be allocated from the start of new cluster
*/
-
hint_femp.eidx = p_dir->size <<
(fsi->cluster_size_bits - DENTRY_SIZE_BITS);
hint_femp.count = fsi->dentries_per_clu;
@@ -921,11 +914,10 @@ static s32 find_empty_entry(struct inode *inode, CHAIN_T *p_dir, s32 num_entries
return dentry;
} /* end of find_empty_entry */
-
#define SDFAT_MIN_SUBDIR (2)
-static const char * dot_name[SDFAT_MIN_SUBDIR] = { DOS_CUR_DIR_NAME, DOS_PAR_DIR_NAME };
+static const char *dot_name[SDFAT_MIN_SUBDIR] = { DOS_CUR_DIR_NAME, DOS_PAR_DIR_NAME };
-static s32 __count_dos_name_entries(struct super_block *sb, CHAIN_T *p_dir, u32 type, u32* dotcnt)
+static s32 __count_dos_name_entries(struct super_block *sb, CHAIN_T *p_dir, u32 type, u32 *dotcnt)
{
s32 i, count = 0, check_dot = 0;
s32 dentries_per_clu;
@@ -1022,19 +1014,21 @@ s32 check_dir_empty(struct super_block *sb, CHAIN_T *p_dir)
if (type == TYPE_UNUSED)
return 0;
+
if ((type != TYPE_FILE) && (type != TYPE_DIR))
continue;
- if (IS_CLUS_FREE(p_dir->dir)) { /* FAT16 root_dir */
+ /* FAT16 root_dir */
+ if (IS_CLUS_FREE(p_dir->dir))
+ return -ENOTEMPTY;
+
+ if (fsi->vol_type == EXFAT)
+ return -ENOTEMPTY;
+
+ if ((p_dir->dir == fsi->root_dir) || (++count > 2))
return -ENOTEMPTY;
- } else {
- if (fsi->vol_type == EXFAT)
- return -ENOTEMPTY;
- if ((p_dir->dir == fsi->root_dir) || ((++count) > 2))
- return -ENOTEMPTY;
- }
}
-
+
/* FAT16 root_dir */
if (IS_CLUS_FREE(p_dir->dir))
return -ENOTEMPTY;
@@ -1102,8 +1096,11 @@ static inline void preprocess_ext_only_sfn(s32 lookup, u16 first_char, DOS_NAME_
}
/* input : dir, uni_name
- output : num_of_entry, dos_name(format : aaaaaa~1.bbb) */
-static s32 get_num_entries_and_dos_name(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, s32 *entries, DOS_NAME_T *p_dosname, s32 lookup)
+ * output : num_of_entry, dos_name(format : aaaaaa~1.bbb)
+ */
+static s32 get_num_entries_and_dos_name(struct super_block *sb, CHAIN_T *p_dir,
+ UNI_NAME_T *p_uniname, s32 *entries,
+ DOS_NAME_T *p_dosname, s32 lookup)
{
s32 ret, num_entries, lossy = NLS_NAME_NO_LOSSY;
s8 **r;
@@ -1221,14 +1218,16 @@ static s32 __resolve_path(struct inode *inode, const u8 *path, CHAIN_T *p_dir, U
p_dir->flags = fid->flags;
return 0;
-} /* end of resolve_path */
-
-static inline s32 resolve_path(struct inode *inode, const u8 *path, CHAIN_T *p_dir, UNI_NAME_T *p_uniname) {
- return __resolve_path(inode, path, p_dir, p_uniname, 0);
}
-static inline s32 resolve_path_for_lookup(struct inode *inode, const u8 *path, CHAIN_T *p_dir, UNI_NAME_T *p_uniname) {
- return __resolve_path(inode, path, p_dir, p_uniname, 1);
+static inline s32 resolve_path(struct inode *inode, const u8 *path, CHAIN_T *dir, UNI_NAME_T *uni)
+{
+ return __resolve_path(inode, path, dir, uni, 0);
+}
+
+static inline s32 resolve_path_for_lookup(struct inode *inode, const u8 *path, CHAIN_T *dir, UNI_NAME_T *uni)
+{
+ return __resolve_path(inode, path, dir, uni, 1);
}
static s32 create_dir(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, FILE_ID_T *fid)
@@ -1254,10 +1253,10 @@ static s32 create_dir(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname
clu.flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01;
/* (0) Check if there are reserved clusters up to max. */
- if ((fsi->used_clusters != (u32) ~0) && \
+ if ((fsi->used_clusters != (u32) ~0) &&
((fsi->used_clusters + fsi->reserved_clusters) >= (fsi->num_clusters - 2)))
return -ENOSPC;
-
+
/* (1) allocate a cluster */
ret = fsi->fs_func->alloc_cluster(sb, 1, &clu, ALLOC_HOT);
@@ -1274,8 +1273,9 @@ static s32 create_dir(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname
size = fsi->cluster_size;
if (fsi->vol_type != EXFAT) {
/* initialize the . and .. entry
- Information for . points to itself
- Information for .. points to parent dir */
+ * Information for . points to itself
+ * Information for .. points to parent dir
+ */
dot_name.name_case = 0x0;
memcpy(dot_name.name, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH);
@@ -1323,7 +1323,7 @@ static s32 create_dir(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname
fid->size = size;
fid->start_clu = clu.dir;
- fid->type= TYPE_DIR;
+ fid->type = TYPE_DIR;
fid->rwoffset = 0;
fid->hint_bmap.off = -1;
@@ -1354,7 +1354,8 @@ static s32 create_file(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uninam
/* (1) update the directory entry */
/* fill the dos name directory entry information of the created file.
- the first cluster is not determined yet. (0) */
+ * the first cluster is not determined yet. (0)
+ */
ret = fsi->fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_FILE | mode, CLUS_FREE, 0);
if (ret)
return ret;
@@ -1373,7 +1374,7 @@ static s32 create_file(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uninam
fid->size = 0;
fid->start_clu = CLUS_EOF;
- fid->type= TYPE_FILE;
+ fid->type = TYPE_FILE;
fid->rwoffset = 0;
fid->hint_bmap.off = -1;
@@ -1503,7 +1504,8 @@ static s32 rename_file(struct inode *inode, CHAIN_T *p_dir, s32 oldentry, UNI_NA
return 0;
} /* end of rename_file */
-static s32 move_file(struct inode *inode, CHAIN_T *p_olddir, s32 oldentry, CHAIN_T *p_newdir, UNI_NAME_T *p_uniname, FILE_ID_T *fid)
+static s32 move_file(struct inode *inode, CHAIN_T *p_olddir, s32 oldentry,
+ CHAIN_T *p_newdir, UNI_NAME_T *p_uniname, FILE_ID_T *fid)
{
s32 ret, newentry, num_new_entries, num_old_entries;
u32 sector_mov, sector_new;
@@ -1627,10 +1629,11 @@ s32 fscore_shutdown(void)
static bool is_exfat(pbr_t *pbr)
{
int i = 53;
+
do {
if (pbr->bpb.f64.res_zero[i-1])
break;
- } while(--i);
+ } while (--i);
return i ? false : true;
}
@@ -1663,7 +1666,7 @@ inline pbr_t *read_pbr_with_logical_sector(struct super_block *sb, struct buffer
}
if (logical_sect < sb->s_blocksize) {
- sdfat_log_msg(sb, KERN_ERR,
+ sdfat_log_msg(sb, KERN_ERR,
"logical sector size too small for device"
" (logical sector size = %u)", logical_sect);
return NULL;
@@ -1676,13 +1679,13 @@ inline pbr_t *read_pbr_with_logical_sector(struct super_block *sb, struct buffer
*prev_bh = NULL;
if (!sb_set_blocksize(sb, logical_sect)) {
- sdfat_log_msg(sb, KERN_ERR,
+ sdfat_log_msg(sb, KERN_ERR,
"unable to set blocksize %u", logical_sect);
return NULL;
}
bh = sb_bread(sb, 0);
if (!bh) {
- sdfat_log_msg(sb, KERN_ERR,
+ sdfat_log_msg(sb, KERN_ERR,
"unable to read boot sector "
"(logical sector size = %lu)", sb->s_blocksize);
return NULL;
@@ -1691,8 +1694,8 @@ inline pbr_t *read_pbr_with_logical_sector(struct super_block *sb, struct buffer
*prev_bh = bh;
p_pbr = (pbr_t *) bh->b_data;
}
-
- sdfat_log_msg(sb, KERN_INFO,
+
+ sdfat_log_msg(sb, KERN_INFO,
"set logical sector size : %lu", sb->s_blocksize);
return p_pbr;
@@ -1704,6 +1707,7 @@ s32 fscore_mount(struct super_block *sb)
s32 ret;
pbr_t *p_pbr;
struct buffer_head *tmp_bh = NULL;
+ struct gendisk *disk = sb->s_bdev->bd_disk;
struct sdfat_mount_options *opts = &(SDFAT_SB(sb)->options);
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
@@ -1746,8 +1750,8 @@ s32 fscore_mount(struct super_block *sb)
/* fill fs_struct */
if (is_exfat(p_pbr)) {
- if(opts->fs_type && opts->fs_type != FS_TYPE_EXFAT) {
- sdfat_log_msg(sb, KERN_ERR,
+ if (opts->fs_type && opts->fs_type != FS_TYPE_EXFAT) {
+ sdfat_log_msg(sb, KERN_ERR,
"not specified filesystem type "
"(media:exfat, opts:%s)",
FS_TYPE_STR[opts->fs_type]);
@@ -1759,9 +1763,9 @@ s32 fscore_mount(struct super_block *sb)
opts->improved_allocation = 0;
opts->defrag = 0;
ret = mount_exfat(sb, p_pbr);
- } else if(is_fat32(p_pbr)) {
- if(opts->fs_type && opts->fs_type != FS_TYPE_VFAT) {
- sdfat_log_msg(sb, KERN_ERR,
+ } else if (is_fat32(p_pbr)) {
+ if (opts->fs_type && opts->fs_type != FS_TYPE_VFAT) {
+ sdfat_log_msg(sb, KERN_ERR,
"not specified filesystem type "
"(media:vfat, opts:%s)",
FS_TYPE_STR[opts->fs_type]);
@@ -1772,8 +1776,8 @@ s32 fscore_mount(struct super_block *sb)
sb->s_maxbytes = 0xffffffff;
ret = mount_fat32(sb, p_pbr);
} else {
- if(opts->fs_type && opts->fs_type != FS_TYPE_VFAT) {
- sdfat_log_msg(sb, KERN_ERR,
+ if (opts->fs_type && opts->fs_type != FS_TYPE_VFAT) {
+ sdfat_log_msg(sb, KERN_ERR,
"not specified filesystem type "
"(media:vfat, opts:%s)",
FS_TYPE_STR[opts->fs_type]);
@@ -1802,8 +1806,13 @@ free_bh:
(fsi->data_start_sector & (fsi->sect_per_clus - 1)) ?
"misaligned" : "aligned");
- ret = load_upcase_table(sb);
- if (ret) {
+ sdfat_log_msg(sb, KERN_INFO,
+ "detected volume size : %u MB (disk_size : %llu MB)",
+ fsi->num_sectors >> 11,
+ disk ? (u64)((disk->part0.nr_sects) >> 11) : 0);
+
+ ret = load_upcase_table(sb);
+ if (ret) {
sdfat_log_msg(sb, KERN_ERR, "failed to load upcase table");
goto bd_close;
}
@@ -1831,7 +1840,7 @@ s32 fscore_umount(struct super_block *sb)
{
s32 ret = 0;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
-
+
if (fs_sync(sb, 0))
ret = -EIO;
@@ -1886,7 +1895,7 @@ s32 fscore_sync_fs(struct super_block *sb, s32 do_sync)
if (fs_set_vol_flags(sb, VOL_CLEAN))
return -EIO;
-
+
return 0;
}
@@ -1894,6 +1903,7 @@ s32 fscore_sync_fs(struct super_block *sb, s32 do_sync)
u32 fscore_get_au_stat(struct super_block *sb, s32 mode)
{
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
+
if (fsi->fs_func->get_au_stat)
return fsi->fs_func->get_au_stat(sb, mode);
@@ -1913,7 +1923,7 @@ s32 fscore_lookup(struct inode *inode, u8 *path, FILE_ID_T *fid)
UNI_NAME_T uni_name;
DOS_NAME_T dos_name;
DENTRY_T *ep, *ep2;
- ENTRY_SET_CACHE_T *es=NULL;
+ ENTRY_SET_CACHE_T *es = NULL;
struct super_block *sb = inode->i_sb;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
FILE_ID_T *dir_fid = &(SDFAT_I(inode)->fid);
@@ -2236,7 +2246,7 @@ s32 fscore_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 cou
} else {
if (new_clu.flags != fid->flags) {
/* no-fat-chain bit is disabled,
- * so fat-chain should be synced with
+ * so fat-chain should be synced with
* alloc-bmp
*/
chain_cont_cluster(sb, fid->start_clu, num_clusters);
@@ -2261,9 +2271,9 @@ s32 fscore_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 cou
/* byte offset in cluster */
offset = (s32)(fid->rwoffset & (fsi->cluster_size-1));
/* sector offset in cluster */
- sec_offset = offset >> blksize_bits;
+ sec_offset = offset >> blksize_bits;
/* byte offset in sector */
- offset &= blksize_mask;
+ offset &= blksize_mask;
LogSector = CLUS_TO_SECT(fsi, clu) + sec_offset;
oneblkwrite = (u64)(blksize - offset);
@@ -2275,9 +2285,9 @@ s32 fscore_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 cou
if (ret)
goto err_out;
- memcpy( ((s8 *) tmp_bh->b_data),
- ((s8 *) buffer)+write_bytes,
- (s32) oneblkwrite);
+ memcpy(((s8 *)tmp_bh->b_data),
+ ((s8 *)buffer)+write_bytes,
+ (s32)oneblkwrite);
ret = write_sect(sb, LogSector, tmp_bh, 0);
if (ret) {
@@ -2387,9 +2397,9 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size)
struct super_block *sb = inode->i_sb;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
FILE_ID_T *fid = &(SDFAT_I(inode)->fid);
- ENTRY_SET_CACHE_T *es=NULL;
+ ENTRY_SET_CACHE_T *es = NULL;
s32 evict = (fid->dir.dir == DIR_DELETED) ? 1 : 0;
-
+
/* check if the given file ID is opened */
if ((fid->type != TYPE_FILE) && (fid->type != TYPE_DIR))
return -EPERM;
@@ -2403,7 +2413,7 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size)
/* It can be when write failed */
#if 0
if (fid->size != old_size) {
- DMSG( "%s: inode(%p) size-mismatch(old:%lld != fid:%lld)\n",
+ DMSG("%s: inode(%p) size-mismatch(old:%lld != fid:%lld)\n",
__func__, inode, old_size, fid->size);
WARN_ON(1);
}
@@ -2429,13 +2439,13 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size)
/* for debugging (FIXME: is okay on no-da case?) */
BUG_ON(num_clusters_da < num_clusters_phys);
- if ( (num_clusters_da != num_clusters_phys) &&
- (num_clusters_new < num_clusters_da) ) {
+ if ((num_clusters_da != num_clusters_phys) &&
+ (num_clusters_new < num_clusters_da)) {
/* Decrement reserved clusters
- * n_reserved = num_clusters_da - max(new,phys)
+ * n_reserved = num_clusters_da - max(new,phys)
*/
- int n_reserved = (num_clusters_new > num_clusters_phys) ? \
- (num_clusters_da - num_clusters_new) : \
+ int n_reserved = (num_clusters_new > num_clusters_phys) ?
+ (num_clusters_da - num_clusters_new) :
(num_clusters_da - num_clusters_phys);
fsi->reserved_clusters -= n_reserved;
@@ -2444,22 +2454,24 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size)
clu.dir = fid->start_clu;
/* In no-da case, num_clusters_phys is equal to below value
- * clu.size = (s32)((old_size-1) >> fsi->cluster_size_bits) + 1;
+ * clu.size = (s32)((old_size-1) >> fsi->cluster_size_bits) + 1;
*/
clu.size = num_clusters_phys;
clu.flags = fid->flags;
+ /* For bigdata */
+ sdfat_statistics_set_trunc(clu.flags, &clu);
+
if (new_size > 0) {
/* Truncate FAT chain num_clusters after the first cluster
- * num_clusters = min(new, phys);
+ * num_clusters = min(new, phys);
*/
- s32 num_clusters = (num_clusters_new < num_clusters_phys) ? \
+ s32 num_clusters = (num_clusters_new < num_clusters_phys) ?
num_clusters_new : num_clusters_phys;
/* Follow FAT chain
- (defensive coding - works fine even with corrupted FAT table
- */
-
+ * (defensive coding - works fine even with corrupted FAT table
+ */
if (clu.flags == 0x03) {
clu.dir += num_clusters;
clu.size -= num_clusters;
@@ -2478,7 +2490,8 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size)
if ((num_clusters > 1) && (last_clu == fid->start_clu)) {
s32 fclus_tmp = 0;
u32 temp = 0;
- err = extent_get_clus(inode, num_clusters -1,
+
+ err = extent_get_clus(inode, num_clusters - 1,
&fclus_tmp, &last_clu, &temp, 0);
if (err)
return -EIO;
@@ -2499,20 +2512,18 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size)
}
}
- /*
- Optimization avialable
-
+ /* Optimization avialable: */
+#if 0
if (num_clusters_new < num_clusters) {
-
-
+ < loop >
} else {
- // num_clusters_new >= num_clusters_phys
+ // num_clusters_new >= num_clusters_phys
// FAT truncation is not necessary
clu.dir = CLUS_EOF;
clu.size = 0;
}
- */
+#endif
} else if (new_size == 0) {
fid->flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01;
fid->start_clu = CLUS_EOF;
@@ -2524,11 +2535,10 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size)
fid->attr |= ATTR_ARCHIVE;
/*
- clu.dir: free from
- clu.size: # of clusters to free (exFAT, 0x03 only)
- if 0, no fat_free
- clu.flags: fid->flags (exFAT only)
- */
+ * clu.dir: free from
+ * clu.size: # of clusters to free (exFAT, 0x03 only), no fat_free if 0
+ * clu.flags: fid->flags (exFAT only)
+ */
/* (1) update the directory entry */
if (!evict) {
@@ -2548,8 +2558,10 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size)
fsi->fs_func->set_entry_time(ep, tm_now(SDFAT_SB(sb), &tm), TM_MODIFY);
fsi->fs_func->set_entry_attr(ep, fid->attr);
- /* if (fsi->vol_type != EXFAT)
- dcache_modify(sb, sector); */
+ /*
+ * if (fsi->vol_type != EXFAT)
+ * dcache_modify(sb, sector);
+ */
/* File size should be zero if there is no cluster allocated */
if (IS_CLUS_EOF(fid->start_clu))
@@ -2579,8 +2591,8 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size)
/* (2) cut off from the FAT chain */
if ((fid->flags == 0x01) &&
(!IS_CLUS_FREE(last_clu)) && (!IS_CLUS_EOF(last_clu))) {
- if (fat_ent_set(sb, last_clu, CLUS_EOF))
- return -EIO;
+ if (fat_ent_set(sb, last_clu, CLUS_EOF))
+ return -EIO;
}
/* (3) invalidate cache and free the clusters */
@@ -2608,9 +2620,9 @@ s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size)
return 0;
} /* end of fscore_truncate */
-static void update_parent_info( FILE_ID_T *fid, struct inode *parent_inode)
+static void update_parent_info(FILE_ID_T *fid, struct inode *parent_inode)
{
- FS_INFO_T *fsi = &(SDFAT_SB(parent_inode->i_sb)->fsi);
+ FS_INFO_T *fsi = &(SDFAT_SB(parent_inode->i_sb)->fsi);
FILE_ID_T *parent_fid = &(SDFAT_I(parent_inode)->fid);
/*
@@ -2625,18 +2637,19 @@ static void update_parent_info( FILE_ID_T *fid, struct inode *parent_inode)
fid->dir.dir = parent_fid->start_clu;
fid->dir.flags = parent_fid->flags;
- fid->dir.size = ((parent_fid->size + (fsi->cluster_size-1))
+ fid->dir.size = ((parent_fid->size + (fsi->cluster_size-1))
>> fsi->cluster_size_bits);
}
}
/* rename or move a old file into a new file */
-s32 fscore_rename(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry)
+s32 fscore_rename(struct inode *old_parent_inode, FILE_ID_T *fid,
+ struct inode *new_parent_inode, struct dentry *new_dentry)
{
s32 ret;
s32 dentry;
CHAIN_T olddir, newdir;
- CHAIN_T *p_dir=NULL;
+ CHAIN_T *p_dir = NULL;
UNI_NAME_T uni_name;
DENTRY_T *ep;
struct super_block *sb = old_parent_inode->i_sb;
@@ -2646,7 +2659,7 @@ s32 fscore_rename(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *
int num_entries;
FILE_ID_T *new_fid = NULL;
u32 new_entry_type = TYPE_UNUSED;
- s32 new_entry=0;
+ s32 new_entry = 0;
/* check the validity of pointer parameters */
if ((new_path == NULL) || (strlen(new_path) == 0))
@@ -2691,7 +2704,7 @@ s32 fscore_rename(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *
goto out;
}
- /* patch 1.2.4 :
+ /* patch 1.2.4 :
* the problem that FILE_ID_T caches wrong parent info.
*
* FIXME : is needed?
@@ -2711,6 +2724,7 @@ s32 fscore_rename(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *
if (new_entry_type == TYPE_DIR) {
CHAIN_T new_clu;
+
new_clu.dir = new_fid->start_clu;
new_clu.size = (s32)((new_fid->size-1) >> fsi->cluster_size_bits) + 1;
new_clu.flags = new_fid->flags;
@@ -2757,6 +2771,7 @@ s32 fscore_rename(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *
if (new_entry_type == TYPE_DIR) {
/* new_fid, new_clu_to_free */
CHAIN_T new_clu_to_free;
+
new_clu_to_free.dir = new_fid->start_clu;
new_clu_to_free.size = (s32)((new_fid->size-1) >> fsi->cluster_size_bits) + 1;
new_clu_to_free.flags = new_fid->flags;
@@ -2772,7 +2787,7 @@ s32 fscore_rename(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *
}
del_out:
/* Update new_inode fid
- * Prevent syncing removed new_inode
+ * Prevent syncing removed new_inode
* (new_fid is already initialized above code ("if (new_inode)")
*/
new_fid->dir.dir = DIR_DELETED;
@@ -2836,7 +2851,7 @@ s32 fscore_remove(struct inode *inode, FILE_ID_T *fid)
/* (3) update FILE_ID_T */
fid->size = 0;
fid->start_clu = CLUS_EOF;
- fid->flags = (fsi->vol_type == EXFAT)? 0x03: 0x01;
+ fid->flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01;
fid->dir.dir = DIR_DELETED;
fs_sync(sb, 0);
@@ -2864,7 +2879,7 @@ s32 fscore_read_inode(struct inode *inode, DIR_ENTRY_T *info)
struct super_block *sb = inode->i_sb;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
FILE_ID_T *fid = &(SDFAT_I(inode)->fid);
- ENTRY_SET_CACHE_T *es=NULL;
+ ENTRY_SET_CACHE_T *es = NULL;
u8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0;
TMSG("%s entered\n", __func__);
@@ -2872,7 +2887,7 @@ s32 fscore_read_inode(struct inode *inode, DIR_ENTRY_T *info)
extent_cache_init_inode(inode);
/* if root directory */
- if ( is_dir && (fid->dir.dir == fsi->root_dir) && (fid->entry == -1) ) {
+ if (is_dir && (fid->dir.dir == fsi->root_dir) && (fid->entry == -1)) {
info->Attr = ATTR_SUBDIR;
memset((s8 *) &info->CreateTimestamp, 0, sizeof(DATE_TIME_T));
memset((s8 *) &info->ModifyTimestamp, 0, sizeof(DATE_TIME_T));
@@ -2889,6 +2904,7 @@ s32 fscore_read_inode(struct inode *inode, DIR_ENTRY_T *info)
info->Size = fsi->dentries_in_root << DENTRY_SIZE_BITS;
} else {
s32 num_clu;
+
if (__count_num_clusters(sb, &dir, &num_clu))
return -EIO;
info->Size = (u64)num_clu << fsi->cluster_size_bits;
@@ -2951,6 +2967,7 @@ s32 fscore_read_inode(struct inode *inode, DIR_ENTRY_T *info)
if (is_dir) {
u32 dotcnt = 0;
+
dir.dir = fid->start_clu;
dir.flags = fid->flags;
dir.size = fid->size >> fsi->cluster_size_bits;
@@ -2958,18 +2975,19 @@ s32 fscore_read_inode(struct inode *inode, DIR_ENTRY_T *info)
* NOTE :
* If "dir.flags" has 0x01, "dir.size" is meaningless.
*/
+#if 0
+ if (info->Size == 0) {
+ s32 num_clu;
-// if (info->Size == 0) {
-// s32 num_clu;
-// if (__count_num_clusters(sb, &dir, &num_clu))
-// return -EIO;
-// info->Size = (u64)num_clu << fsi->cluster_size_bits;
-// }
-
+ if (__count_num_clusters(sb, &dir, &num_clu))
+ return -EIO;
+ info->Size = (u64)num_clu << fsi->cluster_size_bits;
+ }
+#endif
count = __count_dos_name_entries(sb, &dir, TYPE_DIR, &dotcnt);
if (count < 0)
return -EIO;
-
+
if (fsi->vol_type == EXFAT) {
count += SDFAT_MIN_SUBDIR;
} else {
@@ -3001,7 +3019,7 @@ s32 fscore_write_inode(struct inode *inode, DIR_ENTRY_T *info, s32 sync)
u32 sector;
TIMESTAMP_T tm;
DENTRY_T *ep, *ep2;
- ENTRY_SET_CACHE_T *es=NULL;
+ ENTRY_SET_CACHE_T *es = NULL;
struct super_block *sb = inode->i_sb;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
FILE_ID_T *fid = &(SDFAT_I(inode)->fid);
@@ -3055,13 +3073,13 @@ s32 fscore_write_inode(struct inode *inode, DIR_ENTRY_T *info, s32 sync)
fsi->fs_func->set_entry_time(ep, &tm, TM_MODIFY);
if (is_dir && fsi->vol_type != EXFAT) {
- /* if FAT32, and dir size != 0
- overwrite dirsize */
+ /* overwirte dirsize if FAT32 and dir size != 0 */
if (fsi->fs_func->get_entry_size(ep2))
fsi->fs_func->set_entry_size(ep2, 0);
} else {
/* File size should be zero if there is no cluster allocated */
u64 on_disk_size = info->Size;
+
if (IS_CLUS_EOF(fid->start_clu))
on_disk_size = 0;
@@ -3109,7 +3127,7 @@ s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest)
num_clusters = (s32)((SDFAT_I(inode)->i_size_ondisk-1) >> fsi->cluster_size_bits) + 1;
num_to_be_allocated = clu_offset - num_clusters + 1;
- if ((dest==ALLOC_NOWHERE) && (num_to_be_allocated > 0)) {
+ if ((dest == ALLOC_NOWHERE) && (num_to_be_allocated > 0)) {
*clu = CLUS_EOF;
return 0;
}
@@ -3119,7 +3137,8 @@ s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest)
*clu = last_clu = fid->start_clu;
/* XXX: Defensive code needed.
- what if i_size_ondisk != # of allocated clusters */
+ * what if i_size_ondisk != # of allocated clusters
+ */
if (fid->flags == 0x03) {
if ((clu_offset > 0) && (!IS_CLUS_EOF(*clu))) {
last_clu += clu_offset - 1;
@@ -3129,7 +3148,7 @@ s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest)
else
*clu += clu_offset;
}
- } else if (fid->type == TYPE_FILE){
+ } else if (fid->type == TYPE_FILE) {
s32 fclus = 0;
s32 err = extent_get_clus(inode, clu_offset,
&fclus, clu, &last_clu, 1);
@@ -3172,7 +3191,7 @@ s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest)
"fid->hint_clu(%u) fid->rwoffset(%llu) "
"modified_clu_off(%d) last_clu(%08x) "
"new_clu(%08x)", __func__, inode,
- num_to_be_allocated,
+ num_to_be_allocated,
(SDFAT_I(inode)->i_size_ondisk),
fid->flags, fid->start_clu,
fid->hint_bmap.off, fid->hint_bmap.clu,
@@ -3190,7 +3209,7 @@ s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest)
ASSERT(!num_alloced);
} else {
DMSG("%s : ENOSPC (requested:%d, alloced:%d)\n",
- __func__, num_alloced,
+ __func__, num_alloced,
num_to_be_allocated);
}
return -ENOSPC;
@@ -3255,7 +3274,7 @@ s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest)
if (fsi->fs_func->get_entry_flag(ep) != fid->flags)
fsi->fs_func->set_entry_flag(ep, fid->flags);
-
+
if (fsi->fs_func->get_entry_clu0(ep) != fid->start_clu)
fsi->fs_func->set_entry_clu0(ep, fid->start_clu);
@@ -3274,7 +3293,7 @@ s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest)
}
} /* end of if != DIR_DELETED */
-
+
/* add number of new blocks to inode (non-DA only) */
if (!(SDFAT_SB(sb)->options.improved_allocation & SDFAT_ALLOC_DELAY)) {
@@ -3283,10 +3302,10 @@ s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest)
// DA의 경우, i_blocks가 이미 증가해있어야 함.
BUG_ON(clu_offset >= (inode->i_blocks >> (fsi->cluster_size_bits - sb->s_blocksize_bits)));
}
- /* fs_sync(sb, 0);
- fs_set_vol_flags(sb, VOL_CLEAN); */
-
-
+#if 0
+ fs_sync(sb, 0);
+ fs_set_vol_flags(sb, VOL_CLEAN);
+#endif
/* (4) Move *clu pointer along FAT chains (hole care)
* because the caller of this function expect *clu to be the last cluster.
* This only works when num_to_be_allocated >= 2,
@@ -3326,15 +3345,14 @@ s32 fscore_reserve_clus(struct inode *inode)
return -EIO;
}
- if ((fsi->used_clusters + fsi->reserved_clusters) >=
- (fsi->num_clusters - 2))
+ if ((fsi->used_clusters + fsi->reserved_clusters) >= (fsi->num_clusters - 2))
return -ENOSPC;
if (bdev_check_bdi_valid(sb))
return -EIO;
fsi->reserved_clusters++;
-
+
/* inode->i_blocks update */
inode->i_blocks += 1 << (fsi->cluster_size_bits - sb->s_blocksize_bits);
@@ -3629,8 +3647,8 @@ s32 fscore_rmdir(struct inode *inode, FILE_ID_T *fid)
ret = check_dir_empty(sb, &clu_to_free);
if (ret) {
if (ret == -EIO)
- EMSG("%s : failed to check_dir_empty : err(%d)\n",
- __func__,ret);
+ EMSG("%s : failed to check_dir_empty : err(%d)\n",
+ __func__, ret);
return ret;
}
diff --git a/core.h b/core.h
index 8f3c367..303f02d 100644
--- a/core.h
+++ b/core.h
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
#ifndef _SDFAT_CORE_H
@@ -90,7 +88,8 @@ s32 fscore_create(struct inode *inode, u8 *path, u8 mode, FILE_ID_T *fid);
s32 fscore_read_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *rcount);
s32 fscore_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *wcount);
s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size);
-s32 fscore_rename(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry);
+s32 fscore_rename(struct inode *old_parent_inode, FILE_ID_T *fid,
+ struct inode *new_parent_inode, struct dentry *new_dentry);
s32 fscore_remove(struct inode *inode, FILE_ID_T *fid);
s32 fscore_read_inode(struct inode *inode, DIR_ENTRY_T *info);
s32 fscore_write_inode(struct inode *inode, DIR_ENTRY_T *info, int sync);
@@ -116,17 +115,17 @@ DENTRY_T *get_dentry_in_dir(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u
void get_uniname_from_dos_entry(struct super_block *sb, DOS_DENTRY_T *ep, UNI_NAME_T *p_uniname, u8 mode);
/* file operation functions */
-s32 walk_fat_chain (struct super_block *sb, CHAIN_T *p_dir, s32 byte_offset, u32 *clu);
+s32 walk_fat_chain(struct super_block *sb, CHAIN_T *p_dir, s32 byte_offset, u32 *clu);
/* sdfat/cache.c */
s32 meta_cache_init(struct super_block *sb);
s32 meta_cache_shutdown(struct super_block *sb);
-u8* fcache_getblk(struct super_block *sb, u32 sec);
+u8 *fcache_getblk(struct super_block *sb, u32 sec);
s32 fcache_modify(struct super_block *sb, u32 sec);
s32 fcache_release_all(struct super_block *sb);
s32 fcache_flush(struct super_block *sb, u32 sync);
-u8* dcache_getblk(struct super_block *sb, u32 sec);
+u8 *dcache_getblk(struct super_block *sb, u32 sec);
s32 dcache_modify(struct super_block *sb, u32 sec);
s32 dcache_lock(struct super_block *sb, u32 sec);
s32 dcache_unlock(struct super_block *sb, u32 sec);
@@ -151,10 +150,11 @@ s32 mount_fat32(struct super_block *sb, pbr_t *p_pbr);
s32 load_alloc_bmp(struct super_block *sb);
void free_alloc_bmp(struct super_block *sb);
-ENTRY_SET_CACHE_T *get_dentry_set_in_dir (struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 type, DENTRY_T **file_ep);
-void release_dentry_set (ENTRY_SET_CACHE_T *es);
+ENTRY_SET_CACHE_T *get_dentry_set_in_dir(struct super_block *sb,
+ CHAIN_T *p_dir, s32 entry, u32 type, DENTRY_T **file_ep);
+void release_dentry_set(ENTRY_SET_CACHE_T *es);
s32 update_dir_chksum(struct super_block *sb, CHAIN_T *p_dir, s32 entry);
-s32 update_dir_chksum_with_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es);
+s32 update_dir_chksum_with_entry_set(struct super_block *sb, ENTRY_SET_CACHE_T *es);
bool is_dir_empty(struct super_block *sb, CHAIN_T *p_dir);
s32 mount_exfat(struct super_block *sb, pbr_t *p_pbr);
@@ -164,7 +164,7 @@ void amap_destroy(struct super_block *sb);
/* amap_smart.c : (de)allocation functions */
s32 amap_fat_alloc_cluster(struct super_block *sb, s32 num_alloc, CHAIN_T *p_chain, int dest);
-s32 amap_free_cluster(struct super_block *sb, CHAIN_T *p_chain, s32 do_relse); /* Free a FAT chain (Not impelmented) */
+s32 amap_free_cluster(struct super_block *sb, CHAIN_T *p_chain, s32 do_relse);/* Not impelmented */
s32 amap_release_cluster(struct super_block *sb, u32 clu); /* Only update AMAP */
/* amap_smart.c : misc (for defrag) */
diff --git a/core_exfat.c b/core_exfat.c
index 35b79c4..f88c488 100644
--- a/core_exfat.c
+++ b/core_exfat.c
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
/************************************************************************/
@@ -94,46 +92,44 @@ static u32 exfat_get_entry_type(DENTRY_T *p_entry)
{
FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
- if (ep->type == EXFAT_UNUSED) {
+ if (ep->type == EXFAT_UNUSED)
return TYPE_UNUSED;
- } else if (ep->type < 0x80) {
+ if (ep->type < 0x80)
return TYPE_DELETED;
- } else if (ep->type == 0x80) {
+ if (ep->type == 0x80)
return TYPE_INVALID;
- } else if (ep->type < 0xA0) {
- if (ep->type == 0x81) {
+ if (ep->type < 0xA0) {
+ if (ep->type == 0x81)
return TYPE_BITMAP;
- } else if (ep->type == 0x82) {
+ if (ep->type == 0x82)
return TYPE_UPCASE;
- } else if (ep->type == 0x83) {
+ if (ep->type == 0x83)
return TYPE_VOLUME;
- } else if (ep->type == 0x85) {
+ if (ep->type == 0x85) {
if (le16_to_cpu(ep->attr) & ATTR_SUBDIR)
return TYPE_DIR;
- else
- return TYPE_FILE;
+ return TYPE_FILE;
}
return TYPE_CRITICAL_PRI;
- } else if (ep->type < 0xC0) {
- if (ep->type == 0xA0) {
+ }
+ if (ep->type < 0xC0) {
+ if (ep->type == 0xA0)
return TYPE_GUID;
- } else if (ep->type == 0xA1) {
+ if (ep->type == 0xA1)
return TYPE_PADDING;
- } else if (ep->type == 0xA2) {
+ if (ep->type == 0xA2)
return TYPE_ACLTAB;
- }
return TYPE_BENIGN_PRI;
- } else if (ep->type < 0xE0) {
- if (ep->type == 0xC0) {
+ }
+ if (ep->type < 0xE0) {
+ if (ep->type == 0xC0)
return TYPE_STREAM;
- } else if (ep->type == 0xC1) {
+ if (ep->type == 0xC1)
return TYPE_EXTEND;
- } else if (ep->type == 0xC2) {
+ if (ep->type == 0xC2)
return TYPE_ACL;
- }
return TYPE_CRITICAL_SEC;
}
-
return TYPE_BENIGN_SEC;
} /* end of exfat_get_entry_type */
@@ -169,49 +165,57 @@ static void exfat_set_entry_type(DENTRY_T *p_entry, u32 type)
static u32 exfat_get_entry_attr(DENTRY_T *p_entry)
{
- FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
- return((u32) le16_to_cpu(ep->attr));
+ FILE_DENTRY_T *ep = (FILE_DENTRY_T *)p_entry;
+
+ return (u32)le16_to_cpu(ep->attr);
} /* end of exfat_get_entry_attr */
static void exfat_set_entry_attr(DENTRY_T *p_entry, u32 attr)
{
- FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
+ FILE_DENTRY_T *ep = (FILE_DENTRY_T *)p_entry;
+
ep->attr = cpu_to_le16((u16) attr);
} /* end of exfat_set_entry_attr */
static u8 exfat_get_entry_flag(DENTRY_T *p_entry)
{
- STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
- return(ep->flags);
+ STRM_DENTRY_T *ep = (STRM_DENTRY_T *)p_entry;
+
+ return ep->flags;
} /* end of exfat_get_entry_flag */
static void exfat_set_entry_flag(DENTRY_T *p_entry, u8 flags)
{
- STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
+ STRM_DENTRY_T *ep = (STRM_DENTRY_T *)p_entry;
+
ep->flags = flags;
} /* end of exfat_set_entry_flag */
static u32 exfat_get_entry_clu0(DENTRY_T *p_entry)
{
- STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
- return le32_to_cpu(ep->start_clu);
+ STRM_DENTRY_T *ep = (STRM_DENTRY_T *)p_entry;
+
+ return (u32)le32_to_cpu(ep->start_clu);
} /* end of exfat_get_entry_clu0 */
static void exfat_set_entry_clu0(DENTRY_T *p_entry, u32 start_clu)
{
- STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
+ STRM_DENTRY_T *ep = (STRM_DENTRY_T *)p_entry;
+
ep->start_clu = cpu_to_le32(start_clu);
} /* end of exfat_set_entry_clu0 */
static u64 exfat_get_entry_size(DENTRY_T *p_entry)
{
- STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
+ STRM_DENTRY_T *ep = (STRM_DENTRY_T *)p_entry;
+
return le64_to_cpu(ep->valid_size);
} /* end of exfat_get_entry_size */
static void exfat_set_entry_size(DENTRY_T *p_entry, u64 size)
{
- STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
+ STRM_DENTRY_T *ep = (STRM_DENTRY_T *)p_entry;
+
ep->valid_size = cpu_to_le64(size);
ep->size = cpu_to_le64(size);
} /* end of exfat_set_entry_size */
@@ -219,7 +223,7 @@ static void exfat_set_entry_size(DENTRY_T *p_entry, u64 size)
static void exfat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, u8 mode)
{
u16 t = 0x00, d = 0x21;
- FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
+ FILE_DENTRY_T *ep = (FILE_DENTRY_T *)p_entry;
switch (mode) {
case TM_CREATE:
@@ -247,7 +251,7 @@ static void exfat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, u8 mode)
static void exfat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, u8 mode)
{
u16 t, d;
- FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
+ FILE_DENTRY_T *ep = (FILE_DENTRY_T *)p_entry;
t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1);
d = (tp->year << 9) | (tp->mon << 5) | tp->day;
@@ -432,7 +436,8 @@ static s32 exfat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, s32 en
return 0;
}
-static s32 __write_partial_entries_in_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es, u32 sec, s32 off, u32 count)
+static s32 __write_partial_entries_in_entry_set(struct super_block *sb,
+ ENTRY_SET_CACHE_T *es, u32 sec, s32 off, u32 count)
{
s32 num_entries, buf_off = (off - es->offset);
u32 remaining_byte_in_sector, copy_entries;
@@ -444,10 +449,10 @@ static s32 __write_partial_entries_in_entry_set (struct super_block *sb, ENTRY_S
MMSG("%s: es %p sec %u off %d cnt %d\n", __func__, es, sec, off, count);
num_entries = count;
- while(num_entries) {
- // white per sector base
+ while (num_entries) {
+ /* write per sector base */
remaining_byte_in_sector = (1 << sb->s_blocksize_bits) - off;
- copy_entries = min((s32)(remaining_byte_in_sector>> DENTRY_SIZE_BITS) , num_entries);
+ copy_entries = min((s32)(remaining_byte_in_sector >> DENTRY_SIZE_BITS), num_entries);
buf = dcache_getblk(sb, sec);
if (!buf)
goto err_out;
@@ -484,18 +489,18 @@ err_out:
/* write back all entries in entry set */
static s32 __write_whole_entry_set(struct super_block *sb, ENTRY_SET_CACHE_T *es)
{
- return __write_partial_entries_in_entry_set(sb, es, es->sector,es->offset, es->num_entries);
+ return __write_partial_entries_in_entry_set(sb, es, es->sector, es->offset, es->num_entries);
}
-s32 update_dir_chksum_with_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es)
+s32 update_dir_chksum_with_entry_set(struct super_block *sb, ENTRY_SET_CACHE_T *es)
{
DENTRY_T *ep;
u16 chksum = 0;
s32 chksum_type = CS_DIR_ENTRY, i;
ep = (DENTRY_T *)&(es->__buf);
- for (i=0; i < es->num_entries; i++) {
- MMSG ("%s %p\n", __func__, ep);
+ for (i = 0; i < es->num_entries; i++) {
+ MMSG("%s %p\n", __func__, ep);
chksum = calc_chksum_2byte((void *) ep, DENTRY_SIZE, chksum, chksum_type);
ep++;
chksum_type = CS_DEFAULT;
@@ -524,10 +529,11 @@ s32 update_dir_chksum_with_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T
#define ES_MODE_GET_STRM_ENTRY 2
#define ES_MODE_GET_NAME_ENTRY 3
#define ES_MODE_GET_CRITICAL_SEC_ENTRY 4
-ENTRY_SET_CACHE_T *get_dentry_set_in_dir (struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 type, DENTRY_T **file_ep)
+ENTRY_SET_CACHE_T *get_dentry_set_in_dir(struct super_block *sb,
+ CHAIN_T *p_dir, s32 entry, u32 type, DENTRY_T **file_ep)
{
s32 off, ret, byte_offset;
- u32 clu=0;
+ u32 clu = 0;
u32 sec, entry_type;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
ENTRY_SET_CACHE_T *es = NULL;
@@ -593,15 +599,15 @@ ENTRY_SET_CACHE_T *get_dentry_set_in_dir (struct super_block *sb, CHAIN_T *p_dir
pos = (DENTRY_T *) &(es->__buf);
- while(num_entries) {
+ while (num_entries) {
// instead of copying whole sector, we will check every entry.
- // this will provide minimum stablity and consistancy.
+ // this will provide minimum stablity and consistency.
entry_type = exfat_get_entry_type(ep);
if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED))
goto err_out;
- switch(mode) {
+ switch (mode) {
case ES_MODE_STARTED:
if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR))
mode = ES_MODE_GET_FILE_ENTRY;
@@ -644,8 +650,8 @@ ENTRY_SET_CACHE_T *get_dentry_set_in_dir (struct super_block *sb, CHAIN_T *p_dir
if (--num_entries == 0)
break;
- if ( ((off + DENTRY_SIZE) & (u32)(sb->s_blocksize - 1)) <
- (off & (u32)(sb->s_blocksize - 1)) ) {
+ if (((off + DENTRY_SIZE) & (u32)(sb->s_blocksize - 1)) <
+ (off & (u32)(sb->s_blocksize - 1))) {
// get the next sector
if (IS_LAST_SECT_IN_CLUS(fsi, sec)) {
if (es->alloc_flag == 0x03)
@@ -677,20 +683,20 @@ ENTRY_SET_CACHE_T *get_dentry_set_in_dir (struct super_block *sb, CHAIN_T *p_dir
return es;
err_out:
TMSG("%s exited (return NULL) (es %p)\n", __func__, es);
- if (es) {
- kfree(es);
- es = NULL;
- }
+
+ /* kfree(NULL) is safe */
+ kfree(es);
+ es = NULL;
return NULL;
}
-void release_dentry_set (ENTRY_SET_CACHE_T *es)
+void release_dentry_set(ENTRY_SET_CACHE_T *es)
{
TMSG("%s %p\n", __func__, es);
- if (es) {
- kfree(es);
- es = NULL;
- }
+
+ /* kfree(NULL) is safe */
+ kfree(es);
+ es = NULL;
}
static s32 __extract_uni_name_from_name_entry(NAME_DENTRY_T *ep, u16 *uniname, s32 order)
@@ -701,14 +707,13 @@ static s32 __extract_uni_name_from_name_entry(NAME_DENTRY_T *ep, u16 *uniname, s
/* FIXME : unaligned? */
*uniname = le16_to_cpu(ep->unicode_0_14[i]);
if (*uniname == 0x0)
- return(len);
+ return len;
uniname++;
len++;
}
*uniname = 0x0;
- return(len);
-
+ return len;
} /* end of __extract_uni_name_from_name_entry */
#define DIRENT_STEP_FILE (0)
@@ -722,7 +727,8 @@ static s32 __extract_uni_name_from_name_entry(NAME_DENTRY_T *ep, u16 *uniname, s
* -ENOENT : entry with the name does not exist
* -EIO : I/O error
*/
-static s32 exfat_find_dir_entry(struct super_block *sb, FILE_ID_T *fid, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, s32 num_entries, DOS_NAME_T *unused, u32 type)
+static s32 exfat_find_dir_entry(struct super_block *sb, FILE_ID_T *fid,
+ CHAIN_T *p_dir, UNI_NAME_T *p_uniname, s32 num_entries, DOS_NAME_T *unused, u32 type)
{
s32 i, rewind = 0, dentry = 0, end_eidx = 0, num_ext = 0, len;
s32 order, step, name_len;
@@ -909,6 +915,7 @@ found:
/* next dentry we'll find is out of this cluster */
if (!((dentry + 1) & (dentries_per_clu-1))) {
int ret = 0;
+
if (clu.flags == 0x03) {
if ((--clu.size) > 0)
clu.dir++;
@@ -945,11 +952,10 @@ static s32 exfat_count_ext_entries(struct super_block *sb, CHAIN_T *p_dir, s32 e
return -EIO;
type = exfat_get_entry_type(ext_ep);
- if ((type == TYPE_EXTEND) || (type == TYPE_STREAM)) {
+ if ((type == TYPE_EXTEND) || (type == TYPE_STREAM))
count++;
- } else {
+ else
return count;
- }
}
return count;
@@ -1006,6 +1012,15 @@ static s32 exfat_calc_num_entries(UNI_NAME_T *p_uniname)
} /* end of exfat_calc_num_entries */
+static s32 exfat_check_max_dentries(FILE_ID_T *fid)
+{
+ if ((fid->size >> DENTRY_SIZE_BITS) >= MAX_EXFAT_DENTRIES) {
+ /* exFAT spec allows a dir to grow upto 8388608(256MB) dentries */
+ return -ENOSPC;
+ }
+ return 0;
+} /* end of check_max_dentries */
+
/*
* Allocation Bitmap Management Functions
@@ -1013,7 +1028,7 @@ static s32 exfat_calc_num_entries(UNI_NAME_T *p_uniname)
s32 load_alloc_bmp(struct super_block *sb)
{
s32 i, j, ret;
- u32 map_size;
+ u32 map_size, need_map_size;
u32 type, sector;
CHAIN_T clu;
BMAP_DENTRY_T *ep;
@@ -1039,8 +1054,18 @@ s32 load_alloc_bmp(struct super_block *sb)
fsi->map_clu = le32_to_cpu(ep->start_clu);
map_size = (u32) le64_to_cpu(ep->size);
- fsi->map_sectors = ((map_size-1) >> (sb->s_blocksize_bits)) + 1;
- fsi->vol_amap = (struct buffer_head **) kmalloc((sizeof(struct buffer_head *) * fsi->map_sectors), GFP_KERNEL);
+ need_map_size = (((fsi->num_clusters - CLUS_BASE) - 1) >> 3) + 1;
+ if (need_map_size != map_size) {
+ sdfat_log_msg(sb, KERN_ERR,
+ "bogus allocation bitmap size(need : %u, cur : %u)",
+ need_map_size, map_size);
+ /* Only allowed when bogus allocation bitmap size is large */
+ if (need_map_size > map_size)
+ return -EIO;
+ }
+ fsi->map_sectors = ((need_map_size - 1) >> (sb->s_blocksize_bits)) + 1;
+ fsi->vol_amap =
+ kmalloc((sizeof(struct buffer_head *) * fsi->map_sectors), GFP_KERNEL);
if (!fsi->vol_amap)
return -ENOMEM;
@@ -1051,14 +1076,13 @@ s32 load_alloc_bmp(struct super_block *sb)
ret = read_sect(sb, sector+j, &(fsi->vol_amap[j]), 1);
if (ret) {
/* release all buffers and free vol_amap */
- i=0;
+ i = 0;
while (i < j)
brelse(fsi->vol_amap[i++]);
- if (fsi->vol_amap) {
- kfree(fsi->vol_amap);
- fsi->vol_amap = NULL;
- }
+ /* kfree(NULL) is safe */
+ kfree(fsi->vol_amap);
+ fsi->vol_amap = NULL;
return ret;
}
}
@@ -1082,14 +1106,12 @@ void free_alloc_bmp(struct super_block *sb)
brelse(fsi->pbr_bh);
- for (i = 0; i < fsi->map_sectors; i++) {
+ for (i = 0; i < fsi->map_sectors; i++)
__brelse(fsi->vol_amap[i]);
- }
- if(fsi->vol_amap) {
- kfree(fsi->vol_amap);
- fsi->vol_amap = NULL;
- }
+ /* kfree(NULL) is safe */
+ kfree(fsi->vol_amap);
+ fsi->vol_amap = NULL;
}
/* WARN :
@@ -1106,8 +1128,7 @@ static s32 set_alloc_bitmap(struct super_block *sb, u32 clu)
b = clu & (u32)((sb->s_blocksize << 3) - 1);
sector = CLUS_TO_SECT(fsi, fsi->map_clu) + i;
-
- bitmap_set((unsigned long*)(fsi->vol_amap[i]->b_data), b, 1);
+ bitmap_set((unsigned long *)(fsi->vol_amap[i]->b_data), b, 1);
return write_sect(sb, sector, fsi->vol_amap[i], 0);
} /* end of set_alloc_bitmap */
@@ -1130,12 +1151,13 @@ static s32 clr_alloc_bitmap(struct super_block *sb, u32 clu)
sector = CLUS_TO_SECT(fsi, fsi->map_clu) + i;
- bitmap_clear((unsigned long*)(fsi->vol_amap[i]->b_data), b, 1);
+ bitmap_clear((unsigned long *)(fsi->vol_amap[i]->b_data), b, 1);
ret = write_sect(sb, sector, fsi->vol_amap[i], 0);
if (opts->discard) {
s32 ret_discard;
+
TMSG("discard cluster(%08x)\n", clu+2);
ret_discard = sb_issue_discard(sb, CLUS_TO_SECT(fsi, clu+2),
(1 << fsi->sect_per_clus_bits), GFP_NOFS, 0);
@@ -1254,7 +1276,7 @@ static s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, CHAIN_T *p
ASSERT(0);
hint_clu = 2;
if (p_chain->flags == 0x03) {
- if (exfat_chain_cont_cluster( sb, p_chain->dir, num_clusters))
+ if (exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters))
return -EIO;
p_chain->flags = 0x01;
}
@@ -1265,8 +1287,8 @@ static s32 exfat_alloc_cluster(struct super_block *sb, s32 num_alloc, CHAIN_T *p
p_chain->dir = CLUS_EOF;
while ((new_clu = test_alloc_bitmap(sb, hint_clu-2)) != CLUS_EOF) {
- if ( (new_clu != hint_clu) && (p_chain->flags == 0x03) ) {
- if (exfat_chain_cont_cluster( sb, p_chain->dir, num_clusters))
+ if ((new_clu != hint_clu) && (p_chain->flags == 0x03)) {
+ if (exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters))
return -EIO;
p_chain->flags = 0x01;
}
@@ -1395,7 +1417,7 @@ out:
return ret;
} /* end of exfat_free_cluster */
-static s32 exfat_count_used_clusters(struct super_block *sb, u32* ret_count)
+static s32 exfat_count_used_clusters(struct super_block *sb, u32 *ret_count)
{
u32 count = 0;
u32 i, map_i, map_b;
@@ -1406,8 +1428,8 @@ static s32 exfat_count_used_clusters(struct super_block *sb, u32* ret_count)
for (i = 0; i < total_clus; i += 8) {
u8 k = *(((u8 *) fsi->vol_amap[map_i]->b_data) + map_b);
- count += used_bit[k];
+ count += used_bit[k];
if ((++map_b) >= (u32)sb->s_blocksize) {
map_i++;
map_b = 0;
@@ -1438,6 +1460,7 @@ static FS_FUNC_T exfat_fs_func = {
.get_uniname_from_ext_entry = exfat_get_uniname_from_ext_entry,
.count_ext_entries = exfat_count_ext_entries,
.calc_num_entries = exfat_calc_num_entries,
+ .check_max_dentries = exfat_check_max_dentries,
.get_entry_type = exfat_get_entry_type,
.set_entry_type = exfat_set_entry_type,
@@ -1496,7 +1519,7 @@ s32 mount_exfat(struct super_block *sb, pbr_t *p_pbr)
fsi->fs_func = &exfat_fs_func;
fat_ent_ops_init(sb);
-
+
if (p_bpb->bsx.vol_flags & VOL_DIRTY) {
fsi->vol_flag |= VOL_DIRTY;
sdfat_log_msg(sb, KERN_WARNING, "Volume was not properly "
diff --git a/core_fat.c b/core_fat.c
index 4bbfd22..fc40c6e 100644
--- a/core_fat.c
+++ b/core_fat.c
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
/************************************************************************/
@@ -141,7 +139,7 @@ static u32 __calc_default_au_size(struct super_block *sb)
out:
if (sb->s_blocksize != 512) {
ASSERT(sb->s_blocksize_bits > 9);
- sdfat_log_msg(sb, KERN_INFO,
+ sdfat_log_msg(sb, KERN_INFO,
"adjustment est_au_size by logical block size(%lu)",
sb->s_blocksize);
est_au_sect >>= (sb->s_blocksize_bits - 9);
@@ -250,26 +248,31 @@ static s32 fat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, s32 do_rel
goto out;
}
}
-
+
prev = clu;
- if (get_next_clus(sb, &clu))
- goto out;
-
- /* FAT validity check */
- if (IS_CLUS_FREE(clu)) {
- /* GRACEFUL ERROR HANDLING */
- /* Broken FAT chain (Already FREE) */
- sdfat_fs_error(sb, "%s : deleting FAT entry beyond EOF (clu[%u]->0)", __func__, prev);
+ if (get_next_clus_safe(sb, &clu)) {
+ /* print more helpful log */
+ if (IS_CLUS_BAD(clu)) {
+ sdfat_log_msg(sb, KERN_ERR, "%s : "
+ "deleting bad cluster (clu[%u]->BAD)",
+ __func__, prev);
+ } else if (IS_CLUS_FREE(clu)) {
+ sdfat_log_msg(sb, KERN_ERR, "%s : "
+ "deleting free cluster (clu[%u]->FREE)",
+ __func__, prev);
+ }
goto out;
}
/* Free FAT chain */
if (fat_ent_set(sb, prev, CLUS_FREE))
goto out;
-
+
/* Update AMAP if needed */
- if (fsi->amap)
- amap_release_cluster(sb, prev);
+ if (fsi->amap) {
+ if (amap_release_cluster(sb, prev))
+ return -EIO;
+ }
num_clusters++;
@@ -283,7 +286,7 @@ out:
return ret;
} /* end of fat_free_cluster */
-static s32 fat_count_used_clusters(struct super_block *sb, u32* ret_count)
+static s32 fat_count_used_clusters(struct super_block *sb, u32 *ret_count)
{
s32 i;
u32 clu, count = 0;
@@ -307,7 +310,7 @@ static s32 fat_count_used_clusters(struct super_block *sb, u32* ret_count)
*/
static u32 fat_get_entry_type(DENTRY_T *p_entry)
{
- DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
+ DOS_DENTRY_T *ep = (DOS_DENTRY_T *)p_entry;
/* first byte of 32bytes dummy */
if (*(ep->name) == MSDOS_UNUSED)
@@ -335,7 +338,7 @@ static u32 fat_get_entry_type(DENTRY_T *p_entry)
static void fat_set_entry_type(DENTRY_T *p_entry, u32 type)
{
- DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
+ DOS_DENTRY_T *ep = (DOS_DENTRY_T *)p_entry;
if (type == TYPE_UNUSED)
*(ep->name) = MSDOS_UNUSED; /* 0x0 */
@@ -358,14 +361,16 @@ static void fat_set_entry_type(DENTRY_T *p_entry, u32 type)
static u32 fat_get_entry_attr(DENTRY_T *p_entry)
{
- DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
- return((u32) ep->attr);
+ DOS_DENTRY_T *ep = (DOS_DENTRY_T *)p_entry;
+
+ return (u32)ep->attr;
} /* end of fat_get_entry_attr */
static void fat_set_entry_attr(DENTRY_T *p_entry, u32 attr)
{
- DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
- ep->attr = (u8) attr;
+ DOS_DENTRY_T *ep = (DOS_DENTRY_T *)p_entry;
+
+ ep->attr = (u8)attr;
} /* end of fat_set_entry_attr */
static u8 fat_get_entry_flag(DENTRY_T *p_entry)
@@ -379,27 +384,30 @@ static void fat_set_entry_flag(DENTRY_T *p_entry, u8 flags)
static u32 fat_get_entry_clu0(DENTRY_T *p_entry)
{
- DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
+ DOS_DENTRY_T *ep = (DOS_DENTRY_T *)p_entry;
/* FIXME : is ok? */
return(((u32)(le16_to_cpu(ep->start_clu_hi)) << 16) | le16_to_cpu(ep->start_clu_lo));
} /* end of fat_get_entry_clu0 */
static void fat_set_entry_clu0(DENTRY_T *p_entry, u32 start_clu)
{
- DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
+ DOS_DENTRY_T *ep = (DOS_DENTRY_T *)p_entry;
+
ep->start_clu_lo = cpu_to_le16(CLUSTER_16(start_clu));
ep->start_clu_hi = cpu_to_le16(CLUSTER_16(start_clu >> 16));
} /* end of fat_set_entry_clu0 */
static u64 fat_get_entry_size(DENTRY_T *p_entry)
{
- DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
- return((u64) le32_to_cpu(ep->size));
+ DOS_DENTRY_T *ep = (DOS_DENTRY_T *)p_entry;
+
+ return (u64)le32_to_cpu(ep->size);
} /* end of fat_get_entry_size */
static void fat_set_entry_size(DENTRY_T *p_entry, u64 size)
{
- DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
+ DOS_DENTRY_T *ep = (DOS_DENTRY_T *)p_entry;
+
ep->size = cpu_to_le32((u32)size);
} /* end of fat_set_entry_size */
@@ -488,7 +496,7 @@ static void __init_ext_entry(EXT_DENTRY_T *ep, s32 order, u8 chksum, u16 *uninam
}
/* aligned name */
- for (i = 0; i < 6; i ++) {
+ for (i = 0; i < 6; i++) {
if (!end) {
ep->unicode_5_10[i] = cpu_to_le16(*uniname);
if (*uniname == 0x0)
@@ -608,7 +616,8 @@ static inline s32 __get_dentries_per_clu(FS_INFO_T *fsi, s32 clu)
return fsi->dentries_per_clu;
}
-static s32 fat_find_dir_entry(struct super_block *sb, FILE_ID_T *fid, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, s32 num_entries, DOS_NAME_T *p_dosname, u32 type)
+static s32 fat_find_dir_entry(struct super_block *sb, FILE_ID_T *fid,
+ CHAIN_T *p_dir, UNI_NAME_T *p_uniname, s32 num_entries, DOS_NAME_T *p_dosname, u32 type)
{
s32 i, rewind = 0, dentry = 0, end_eidx = 0;
s32 chksum = 0, lfn_ord = 0, lfn_len = 0;
@@ -685,8 +694,8 @@ rewind:
}
/* invalid lfn order */
- if ( !cur_ord || (cur_ord > MAX_LFN_ORDER) ||
- ((cur_ord + 1) != lfn_ord) )
+ if (!cur_ord || (cur_ord > MAX_LFN_ORDER) ||
+ ((cur_ord + 1) != lfn_ord))
goto reset_dentry_set;
/* check checksum of directory entry set */
@@ -702,7 +711,7 @@ rewind:
continue;
}
- if(!uniname) {
+ if (!uniname) {
sdfat_fs_error(sb,
"%s : abnormal dentry "
"(start_clu[%u], "
@@ -760,16 +769,16 @@ rewind:
*/
if (!lfn_len || (cur_chksum != chksum)) {
/* check shortname */
- if ( (p_dosname->name[0] != '\0') &&
+ if ((p_dosname->name[0] != '\0') &&
!nls_cmp_sfn(sb,
p_dosname->name,
- dos_ep->name) ) {
+ dos_ep->name)) {
goto found;
}
/* check name length */
- } else if ( (lfn_len > 0) &&
+ } else if ((lfn_len > 0) &&
((s32)p_uniname->name_len ==
- lfn_len) ) {
+ lfn_len)) {
goto found;
}
@@ -872,12 +881,12 @@ static s32 fat_count_ext_entries(struct super_block *sb, CHAIN_T *p_dir, s32 ent
chksum = calc_chksum_1byte((void *) dos_ep->name, DOS_NAME_LENGTH, 0);
for (entry--; entry >= 0; entry--) {
- ext_ep = (EXT_DENTRY_T*)get_dentry_in_dir(sb,p_dir,entry,NULL);
+ ext_ep = (EXT_DENTRY_T *)get_dentry_in_dir(sb, p_dir, entry, NULL);
if (!ext_ep)
return -EIO;
- if ( (fat_get_entry_type((DENTRY_T*)ext_ep) == TYPE_EXTEND) &&
- (ext_ep->checksum == chksum) ) {
+ if ((fat_get_entry_type((DENTRY_T *)ext_ep) == TYPE_EXTEND) &&
+ (ext_ep->checksum == chksum)) {
count++;
if (ext_ep->order > MSDOS_LAST_LFN)
return count;
@@ -900,7 +909,7 @@ static s32 __extract_uni_name_from_ext_entry(EXT_DENTRY_T *ep, u16 *uniname, s32
for (i = 0; i < 5; i++) {
*uniname = get_unaligned_le16(&(ep->unicode_0_4[i<<1]));
if (*uniname == 0x0)
- return(len);
+ return len;
uniname++;
len++;
}
@@ -910,7 +919,7 @@ static s32 __extract_uni_name_from_ext_entry(EXT_DENTRY_T *ep, u16 *uniname, s32
/* FIXME : unaligned? */
*uniname = le16_to_cpu(ep->unicode_5_10[i]);
if (*uniname == 0x0)
- return(len);
+ return len;
uniname++;
len++;
}
@@ -919,25 +928,25 @@ static s32 __extract_uni_name_from_ext_entry(EXT_DENTRY_T *ep, u16 *uniname, s32
/* FIXME : unaligned? */
*uniname = le16_to_cpu(ep->unicode_5_10[i]);
if (*uniname == 0x0)
- return(len);
+ return len;
uniname++;
len++;
}
*uniname = 0x0; /* uniname[MAX_NAME_LENGTH] */
- return(len);
+ return len;
}
for (i = 0; i < 2; i++) {
/* FIXME : unaligned? */
*uniname = le16_to_cpu(ep->unicode_11_12[i]);
if (*uniname == 0x0)
- return(len);
+ return len;
uniname++;
len++;
}
*uniname = 0x0;
- return(len);
+ return len;
} /* end of __extract_uni_name_from_ext_entry */
@@ -959,6 +968,7 @@ static void fat_get_uniname_from_ext_entry(struct super_block *sb, CHAIN_T *p_di
for (entry--, i = 1; entry >= 0; entry--, i++) {
EXT_DENTRY_T *ep;
+
ep = (EXT_DENTRY_T *)get_dentry_in_dir(sb, p_dir, entry, NULL);
if (!ep)
goto invalid_lfn;
@@ -980,13 +990,13 @@ static void fat_get_uniname_from_ext_entry(struct super_block *sb, CHAIN_T *p_di
}
invalid_lfn:
*uniname = (u16)0x0;
- return;
} /* end of fat_get_uniname_from_ext_entry */
/* Find if the shortname exists
- and check if there are free entries
-*/
-static s32 __fat_find_shortname_entry(struct super_block *sb, CHAIN_T *p_dir, u8 *p_dosname, s32 *offset, __attribute__((unused))int n_entry_needed)
+ * and check if there are free entries
+ */
+static s32 __fat_find_shortname_entry(struct super_block *sb, CHAIN_T *p_dir,
+ u8 *p_dosname, s32 *offset, __attribute__((unused))int n_entry_needed)
{
u32 type;
s32 i, dentry = 0;
@@ -1004,7 +1014,7 @@ static s32 __fat_find_shortname_entry(struct super_block *sb, CHAIN_T *p_dir, u8
else
dentries_per_clu = fsi->dentries_per_clu;
- while(!IS_CLUS_EOF(clu.dir)) {
+ while (!IS_CLUS_EOF(clu.dir)) {
for (i = 0; i < dentries_per_clu; i++, dentry++) {
ep = get_dentry_in_dir(sb, &clu, i, NULL);
if (!ep)
@@ -1072,8 +1082,9 @@ s32 fat_generate_dos_name_new(struct super_block *sb, CHAIN_T *p_dir, DOS_NAME_T
memset(work, ' ', DOS_NAME_LENGTH);
memcpy(work, p_dosname->name, DOS_NAME_LENGTH);
- while(baselen && (work[--baselen] == ' '));
-
+ while (baselen && (work[--baselen] == ' ')) {
+ /* DO NOTHING, JUST FOR CHECK_PATCH */
+ }
if (baselen > 6)
baselen = 6;
@@ -1091,7 +1102,7 @@ s32 fat_generate_dos_name_new(struct super_block *sb, CHAIN_T *p_dir, DOS_NAME_T
/* void return */
__fat_attach_count_to_dos_name(p_dosname->name, i);
return 0;
- }
+ }
/* any other error */
if (err)
@@ -1141,6 +1152,14 @@ static s32 fat_calc_num_entries(UNI_NAME_T *p_uniname)
} /* end of calc_num_enties */
+static s32 fat_check_max_dentries(FILE_ID_T *fid)
+{
+ if ((fid->size >> DENTRY_SIZE_BITS) >= MAX_FAT_DENTRIES) {
+ /* FAT spec allows a dir to grow upto 65536 dentries */
+ return -ENOSPC;
+ }
+ return 0;
+} /* end of check_max_dentries */
/*
@@ -1158,6 +1177,7 @@ static FS_FUNC_T fat_fs_func = {
.get_uniname_from_ext_entry = fat_get_uniname_from_ext_entry,
.count_ext_entries = fat_count_ext_entries,
.calc_num_entries = fat_calc_num_entries,
+ .check_max_dentries = fat_check_max_dentries,
.get_entry_type = fat_get_entry_type,
.set_entry_type = fat_set_entry_type,
@@ -1185,6 +1205,7 @@ static FS_FUNC_T amap_fat_fs_func = {
.get_uniname_from_ext_entry = fat_get_uniname_from_ext_entry,
.count_ext_entries = fat_count_ext_entries,
.calc_num_entries = fat_calc_num_entries,
+ .check_max_dentries = fat_check_max_dentries,
.get_entry_type = fat_get_entry_type,
.set_entry_type = fat_set_entry_type,
@@ -1348,7 +1369,7 @@ s32 mount_fat32(struct super_block *sb, pbr_t *p_pbr)
fsi->num_clusters = ((fsi->num_sectors-num_reserved) >> fsi->sect_per_clus_bits) + 2;
/* because the cluster index starts with 2 */
-
+
fsi->vol_type = FAT32;
fsi->vol_id = get_unaligned_le32(p_bpb->bsx.vol_serial);
@@ -1382,23 +1403,23 @@ s32 mount_fat32(struct super_block *sb, pbr_t *p_pbr)
"sector : bpb(%u) != ondisk(%u)",
hidden_sectors, calc_hid_sect);
if (SDFAT_SB(sb)->options.adj_hidsect) {
- sdfat_log_msg(sb, KERN_INFO,
+ sdfat_log_msg(sb, KERN_INFO,
"adjustment hidden sector : "
- "bpb(%u) -> ondisk(%u)",
+ "bpb(%u) -> ondisk(%u)",
hidden_sectors, calc_hid_sect);
hidden_sectors = calc_hid_sect;
}
}
SDFAT_SB(sb)->options.amap_opt.misaligned_sect = hidden_sectors;
-
+
/* calculate AU size if it's not set */
if (!SDFAT_SB(sb)->options.amap_opt.sect_per_au) {
- SDFAT_SB(sb)->options.amap_opt.sect_per_au =
+ SDFAT_SB(sb)->options.amap_opt.sect_per_au =
__calc_default_au_size(sb);
}
-
- ret = amap_create(sb,
+
+ ret = amap_create(sb,
SDFAT_SB(sb)->options.amap_opt.pack_ratio,
SDFAT_SB(sb)->options.amap_opt.sect_per_au,
SDFAT_SB(sb)->options.amap_opt.misaligned_sect);
@@ -1412,8 +1433,8 @@ s32 mount_fat32(struct super_block *sb, pbr_t *p_pbr)
}
/* Check dependency of mount options */
- if (SDFAT_SB(sb)->options.improved_allocation !=
- (SDFAT_ALLOC_DELAY | SDFAT_ALLOC_SMART) ) {
+ if (SDFAT_SB(sb)->options.improved_allocation !=
+ (SDFAT_ALLOC_DELAY | SDFAT_ALLOC_SMART)) {
sdfat_log_msg(sb, KERN_INFO, "disabling defragmentation because"
" smart, delay options are disabled");
SDFAT_SB(sb)->options.defrag = 0;
diff --git a/dfr.c b/dfr.c
index aed7544..b06ae84 100644
--- a/dfr.c
+++ b/dfr.c
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
/************************************************************************/
@@ -62,7 +60,7 @@ defrag_get_info(
arg->total_sec = fsi->num_sectors;
arg->fat_offset_sec = fsi->FAT1_start_sector;
arg->fat_sz_sec = fsi->num_FAT_sectors;
- arg->n_fat = (fsi->FAT1_start_sector == fsi->FAT2_start_sector)? 1:2;
+ arg->n_fat = (fsi->FAT1_start_sector == fsi->FAT2_start_sector) ? 1 : 2;
arg->sec_per_au = amap->option.au_size;
arg->hidden_sectors = amap->option.au_align_factor % amap->option.au_size;
@@ -139,7 +137,7 @@ error:
* @return 0 on success, -errno otherwise
* @param sb super block
* @param args traverse args
- * @remark protected by i_mutex, super_block and volume lock
+ * @remark protected by inode_lock, super_block and volume lock
*/
int
defrag_scan_dir(
@@ -149,7 +147,7 @@ defrag_scan_dir(
struct sdfat_sb_info *sbi = NULL;
FS_INFO_T *fsi = NULL;
struct defrag_trav_header *header = NULL;
- IN DOS_DENTRY_T *dos_ep;
+ DOS_DENTRY_T *dos_ep;
CHAIN_T chain;
int dot_found = 0, args_idx = DFR_TRAV_HEADER_IDX + 1, clus = 0, index = 0;
int err = 0, j = 0;
@@ -186,9 +184,9 @@ defrag_scan_dir(
}
/* For more-scan case */
- if ((header->stat == DFR_TRAV_STAT_MORE) &&
- (header->start_clus == sbi->dfr_hint_clus) &&
- (sbi->dfr_hint_idx > 0) ) {
+ if ((header->stat == DFR_TRAV_STAT_MORE) &&
+ (header->start_clus == sbi->dfr_hint_clus) &&
+ (sbi->dfr_hint_idx > 0)) {
index = sbi->dfr_hint_idx;
for (j = 0; j < (sbi->dfr_hint_idx / fsi->dentries_per_clu); j++) {
@@ -236,7 +234,7 @@ scan_fat_chain:
err = __defrag_scan_dir(sb, dos_ep, i_pos, &args[args_idx]);
if (!err) {
/* More-scan case */
- if ( ++args_idx >= (PAGE_SIZE / sizeof(struct defrag_trav_arg)) ) {
+ if (++args_idx >= (PAGE_SIZE / sizeof(struct defrag_trav_arg))) {
sbi->dfr_hint_clus = header->start_clus;
sbi->dfr_hint_idx = clus * fsi->dentries_per_clu + index + 1;
@@ -252,10 +250,10 @@ scan_fat_chain:
/* End case */
} else if (err == -ENOENT) {
sbi->dfr_hint_clus = sbi->dfr_hint_idx = 0;
- err = 0;
+ err = 0;
goto done;
} else {
- ;
+ /* DO NOTHING */
}
err = 0;
}
@@ -299,7 +297,7 @@ __defrag_validate_cluster_prev(
dir.flags = 0x1; // Assume non-continuous
entry = GET64_LO(chunk->i_pos);
-
+
FAT32_CHECK_CLUSTER(fsi, dir.dir, err);
ERR_HANDLE(err);
ep = get_dentry_in_dir(sb, &dir, entry, NULL);
@@ -369,7 +367,7 @@ __defrag_check_au(
{
unsigned int nr_free = amap_get_freeclus(sb, clus);
-#if defined(CONFIG_SDFAT_DFR_DEBUG) || defined(CONFIG_SDFAT_DBG_MSG)
+#if defined(CONFIG_SDFAT_DFR_DEBUG) && defined(CONFIG_SDFAT_DBG_MSG)
if (nr_free < limit) {
AMAP_T *amap = SDFAT_SB(sb)->fsi.amap;
AU_INFO_T *au = GET_AU(amap, i_AU_of_CLU(amap, clus));
@@ -377,8 +375,7 @@ __defrag_check_au(
dfr_debug("AU[%d] nr_free %d, limit %d", au->idx, nr_free, limit);
}
#endif
-
- return ((nr_free < limit)? 1 : 0);
+ return ((nr_free < limit) ? 1 : 0);
}
@@ -406,15 +403,15 @@ defrag_validate_cluster(
if (fid->dir.dir == DIR_DELETED)
return -ENOENT;
- /* Skip working-AU */
- err = amap_check_working(sb, chunk->d_clus);
- if (err)
- return -EBUSY;
+ /* Skip working-AU */
+ err = amap_check_working(sb, chunk->d_clus);
+ if (err)
+ return -EBUSY;
/* Check # of free_clus of belonged AU */
- err = __defrag_check_au(inode->i_sb, chunk->d_clus, CLUS_PER_AU(sb) - chunk->au_clus);
- if (err)
- return -EINVAL;
+ err = __defrag_check_au(inode->i_sb, chunk->d_clus, CLUS_PER_AU(sb) - chunk->au_clus);
+ if (err)
+ return -EINVAL;
/* Check chunk's clusters */
for (i = 0; i < chunk->nr_clus; i++) {
@@ -457,7 +454,7 @@ defrag_reserve_clusters(
struct sdfat_sb_info *sbi = SDFAT_SB(sb);
FS_INFO_T *fsi = &(sbi->fsi);
- if ( !(sbi->options.improved_allocation & SDFAT_ALLOC_DELAY) )
+ if (!(sbi->options.improved_allocation & SDFAT_ALLOC_DELAY))
/* Nothing to do */
return 0;
@@ -519,8 +516,6 @@ defrag_unmark_ignore_all(struct super_block *sb)
{
if (SDFAT_SB(sb)->options.improved_allocation & SDFAT_ALLOC_SMART)
amap_unmark_ignore_all(sb);
-
- return;
}
@@ -535,7 +530,7 @@ defrag_unmark_ignore_all(struct super_block *sb)
*/
int
defrag_map_cluster(
- struct inode *inode,
+ struct inode *inode,
unsigned int clu_offset,
unsigned int *clu)
{
@@ -596,11 +591,10 @@ defrag_map_cluster(
/* Make FAT-chain for new_clus */
for (i = 0; i < chunk->nr_clus; i++) {
#if 0
- if (sbi->dfr_new_clus[chunk->new_idx + i]) {
+ if (sbi->dfr_new_clus[chunk->new_idx + i])
nr_new++;
- } else {
+ else
break;
- }
#else
if (!sbi->dfr_new_clus[chunk->new_idx + i])
break;
@@ -611,7 +605,7 @@ defrag_map_cluster(
for (i = 0; i < chunk->nr_clus - 1; i++) {
FAT32_CHECK_CLUSTER(fsi, sbi->dfr_new_clus[chunk->new_idx + i], err);
BUG_ON(err);
- if (fat_ent_set(sb,
+ if (fat_ent_set(sb,
sbi->dfr_new_clus[chunk->new_idx + i],
sbi->dfr_new_clus[chunk->new_idx + i + 1]))
return -EIO;
@@ -654,11 +648,11 @@ defrag_writepage_end_io(
chunk_start = chunk->f_clus;
chunk_end = chunk->f_clus + chunk->nr_clus;
- if ( (clus_start >= chunk_start) && (clus_end <= chunk_end) ) {
+ if ((clus_start >= chunk_start) && (clus_end <= chunk_end)) {
int off = clus_start - chunk_start;
- clear_bit( (page->index & (PAGES_PER_CLUS(sb) - 1)),
- (volatile unsigned long *)&(sbi->dfr_page_wb[chunk->new_idx + off]) );
+ clear_bit((page->index & (PAGES_PER_CLUS(sb) - 1)),
+ (volatile unsigned long *)&(sbi->dfr_page_wb[chunk->new_idx + off]));
}
}
}
@@ -683,7 +677,7 @@ __defrag_check_wb(
/* Check WB complete status first */
for (wb_i = 0; wb_i < chunk->nr_clus; wb_i++) {
- if ( atomic_read((atomic_t *)&(sbi->dfr_page_wb[chunk->new_idx + wb_i])) ) {
+ if (atomic_read((atomic_t *)&(sbi->dfr_page_wb[chunk->new_idx + wb_i]))) {
err = -EBUSY;
break;
}
@@ -700,7 +694,7 @@ __defrag_check_wb(
if (nr_new == chunk->nr_clus) {
err = 0;
- if ( (wb_i != chunk->nr_clus) && (wb_i != chunk->nr_clus - 1) )
+ if ((wb_i != chunk->nr_clus) && (wb_i != chunk->nr_clus - 1))
dfr_debug("submit_fullpage_bio() called on a page (nr_clus %d, wb_i %d)",
chunk->nr_clus, wb_i);
@@ -741,9 +735,9 @@ __defrag_check_fat_old(
err = fat_ent_get(sb, clus, &clus);
ERR_HANDLE(err);
- if ( (idx < max_idx - 1) && (IS_CLUS_EOF(clus) || IS_CLUS_FREE(clus)) ) {
+ if ((idx < max_idx - 1) && (IS_CLUS_EOF(clus) || IS_CLUS_FREE(clus))) {
dfr_err("FAT: inode %p, max_idx %d, idx %d, clus %08x, "
- "f_clus %d, nr_clus %d", inode, max_idx,
+ "f_clus %d, nr_clus %d", inode, max_idx,
idx, clus, chunk->f_clus, chunk->nr_clus);
BUG_ON(idx < max_idx - 1);
goto error;
@@ -804,14 +798,13 @@ __defrag_check_fat_new(
BUG_ON(err);
err = fat_ent_get(sb, sbi->dfr_new_clus[chunk->new_idx + chunk->nr_clus - 1], &clus);
BUG_ON(err);
- if ( (chunk->next_clus & 0x0FFFFFFF) != (clus & 0x0FFFFFFF) ) {
+ if ((chunk->next_clus & 0x0FFFFFFF) != (clus & 0x0FFFFFFF)) {
dfr_err("FAT: inode %p, next_clus %08x, read_clus %08x", inode, chunk->next_clus, clus);
err = EIO;
}
error:
BUG_ON(err);
- return;
}
@@ -872,7 +865,7 @@ defrag_update_fat_prev(
struct defrag_info *sb_dfr = &sbi->dfr_info, *ino_dfr = NULL;
int skip = 0, done = 0;
- /* Check if FS_ERROR occured */
+ /* Check if FS_ERROR occurred */
if (sb->s_flags & MS_RDONLY) {
dfr_err("RDONLY partition (err %d)", -EPERM);
goto out;
@@ -885,7 +878,7 @@ defrag_update_fat_prev(
int i = 0, j = 0;
mutex_lock(&ino_dfr->lock);
- BUG_ON (atomic_read(&ino_dfr->stat) != DFR_INO_STAT_REQ);
+ BUG_ON(atomic_read(&ino_dfr->stat) != DFR_INO_STAT_REQ);
for (i = 0; i < ino_dfr->nr_chunks; i++) {
struct defrag_chunk_info *chunk = NULL;
int err = 0;
@@ -906,15 +899,16 @@ defrag_update_fat_prev(
}
/* Double-check clusters */
- if ( chunk_prev &&
+ if (chunk_prev &&
(chunk->f_clus == chunk_prev->f_clus + chunk_prev->nr_clus) &&
- (chunk_prev->stat == DFR_CHUNK_STAT_PASS) ) {
+ (chunk_prev->stat == DFR_CHUNK_STAT_PASS)) {
err = defrag_validate_cluster(inode, chunk, 1);
/* Handle continuous chunks in a file */
if (!err) {
- chunk->prev_clus = sbi->dfr_new_clus[chunk_prev->new_idx + chunk_prev->nr_clus - 1];
+ chunk->prev_clus =
+ sbi->dfr_new_clus[chunk_prev->new_idx + chunk_prev->nr_clus - 1];
dfr_debug("prev->f_clus %d, prev->nr_clus %d, chunk->f_clus %d",
chunk_prev->f_clus, chunk_prev->nr_clus, chunk->f_clus);
}
@@ -932,7 +926,7 @@ defrag_update_fat_prev(
* Skip update_fat_prev if WB or update_fat_next not completed.
* Go to error case if FORCE set.
*/
- if ( __defrag_check_wb(sbi, chunk) || (chunk->stat != DFR_CHUNK_STAT_PREP) ) {
+ if (__defrag_check_wb(sbi, chunk) || (chunk->stat != DFR_CHUNK_STAT_PREP)) {
if (force) {
err = -EPERM;
dfr_err("Skip case: inode %p, stat %x, f_clus %d, err %d",
@@ -1014,13 +1008,13 @@ error:
out:
if (skip) {
- dfr_debug("%s skipped (nr_reqs %d, done %d, skip %d)",
+ dfr_debug("%s skipped (nr_reqs %d, done %d, skip %d)",
__func__, sb_dfr->nr_chunks - 1, done, skip);
} else {
/* Make dfr_reserved_clus zero */
if (sbi->dfr_reserved_clus > 0) {
if (fsi->reserved_clusters < sbi->dfr_reserved_clus) {
- dfr_err("Reserved count: reserved_clus %d, dfr_reserved_clus %d",
+ dfr_err("Reserved count: reserved_clus %d, dfr_reserved_clus %d",
fsi->reserved_clusters, sbi->dfr_reserved_clus);
BUG_ON(fsi->reserved_clusters < sbi->dfr_reserved_clus);
}
@@ -1050,7 +1044,7 @@ defrag_update_fat_next(
struct defrag_chunk_info *chunk = NULL;
int done = 0, i = 0, j = 0, err = 0;
- /* Check if FS_ERROR occured */
+ /* Check if FS_ERROR occurred */
if (sb->s_flags & MS_RDONLY) {
dfr_err("RDONLY partition (err %d)", -EROFS);
goto out;
@@ -1063,7 +1057,7 @@ defrag_update_fat_next(
chunk = &(ino_dfr->chunks[i]);
- /* Do nothing if error occured or update_fat_next already passed */
+ /* Do nothing if error occurred or update_fat_next already passed */
if (chunk->stat == DFR_CHUNK_STAT_ERR)
continue;
if (chunk->stat & DFR_CHUNK_STAT_FAT) {
@@ -1083,7 +1077,7 @@ defrag_update_fat_next(
/* Update chunk's next cluster */
FAT32_CHECK_CLUSTER(fsi,
- sbi->dfr_new_clus[chunk->new_idx + chunk->nr_clus - 1], err);
+ sbi->dfr_new_clus[chunk->new_idx + chunk->nr_clus - 1], err);
BUG_ON(err);
if (fat_ent_set(sb,
sbi->dfr_new_clus[chunk->new_idx + chunk->nr_clus - 1],
@@ -1126,8 +1120,8 @@ defrag_check_discard(
BUG_ON(!amap);
- if ( !(SDFAT_SB(sb)->options.discard) ||
- !(SDFAT_SB(sb)->options.improved_allocation & SDFAT_ALLOC_SMART) )
+ if (!(SDFAT_SB(sb)->options.discard) ||
+ !(SDFAT_SB(sb)->options.improved_allocation & SDFAT_ALLOC_SMART))
return;
memset(tmp, 0, sizeof(int) * DFR_MAX_AU_MOVED);
@@ -1139,8 +1133,8 @@ defrag_check_discard(
au = GET_AU(amap, i_AU_of_CLU(amap, chunk->d_clus));
/* Send DISCARD for free AU */
- if ( (IS_AU_IGNORED(au, amap)) &&
- (amap_get_freeclus(sb, chunk->d_clus) == CLUS_PER_AU(sb)) ) {
+ if ((IS_AU_IGNORED(au, amap)) &&
+ (amap_get_freeclus(sb, chunk->d_clus) == CLUS_PER_AU(sb))) {
sector_t blk = 0, nr_blks = 0;
unsigned int au_align_factor = amap->option.au_align_factor % amap->option.au_size;
@@ -1157,11 +1151,11 @@ defrag_check_discard(
continue;
/* Send DISCARD cmd */
- blk = (sector_t) ( ((au->idx * CLUS_PER_AU(sb)) << fsi->sect_per_clus_bits)
- - au_align_factor );
+ blk = (sector_t) (((au->idx * CLUS_PER_AU(sb)) << fsi->sect_per_clus_bits)
+ - au_align_factor);
nr_blks = ((sector_t)CLUS_PER_AU(sb)) << fsi->sect_per_clus_bits;
- dfr_debug("Send DISCARD for AU[%d] (blk %08llx)", au->idx, blk);
+ dfr_debug("Send DISCARD for AU[%d] (blk %08zx)", au->idx, blk);
sb_issue_discard(sb, blk, nr_blks, GFP_NOFS, 0);
/* Save previous AU's index */
@@ -1204,7 +1198,7 @@ defrag_free_cluster(
dfr_err("Free: Already freed, clus %08x, val %08x", clus, val);
BUG_ON(!val);
}
-
+
set_sb_dirty(sb);
fsi->used_clusters--;
if (fsi->amap)
@@ -1236,14 +1230,14 @@ defrag_check_defrag_required(
int clean_ratio = 0, frag_ratio = 0;
int ret = 0;
- if( !(sb) || !(SDFAT_SB(sb)->options.defrag) )
+ if (!sb || !(SDFAT_SB(sb)->options.defrag))
return 0;
/* Check DFR_DEFAULT_STOP_RATIO first */
fsi = &(SDFAT_SB(sb)->fsi);
if (fsi->used_clusters == (unsigned int)(~0)) {
- if (fsi->fs_func->count_used_clusters(sb, &fsi->used_clusters))
- return -EIO;
+ if (fsi->fs_func->count_used_clusters(sb, &fsi->used_clusters))
+ return -EIO;
}
if (fsi->used_clusters * DFR_FULL_RATIO >= fsi->num_clusters * DFR_DEFAULT_STOP_RATIO) {
dfr_debug("used_clusters %d, num_clusters %d", fsi->used_clusters, fsi->num_clusters);
@@ -1262,12 +1256,11 @@ defrag_check_defrag_required(
(fsi->used_clusters * CLUS_PER_AU(sb));
/*
- * Wake-up defrag_daemon
- * when # of clean AUs too small,
- * or frag_ratio exceeds the limit
+ * Wake-up defrag_daemon:
+ * when # of clean AUs too small, or frag_ratio exceeds the limit
*/
- if ( (clean_ratio < DFR_DEFAULT_WAKEUP_RATIO) ||
- ((clean_ratio < DFR_DEFAULT_CLEAN_RATIO) && (frag_ratio >= DFR_DEFAULT_FRAG_RATIO)) ) {
+ if ((clean_ratio < DFR_DEFAULT_WAKEUP_RATIO) ||
+ ((clean_ratio < DFR_DEFAULT_CLEAN_RATIO) && (frag_ratio >= DFR_DEFAULT_FRAG_RATIO))) {
if (totalau)
*totalau = amap->n_au;
@@ -1315,8 +1308,8 @@ defrag_check_defrag_on(
if (atomic_read(&ino_dfr->stat) == DFR_INO_STAT_REQ) {
clus_start = start >> (fsi->cluster_size_bits);
- clus_end = (end >> (fsi->cluster_size_bits)) +
- ((end & (fsi->cluster_size - 1))? 1:0);
+ clus_end = (end >> (fsi->cluster_size_bits)) +
+ ((end & (fsi->cluster_size - 1)) ? 1 : 0);
if (!ino_dfr->chunks)
goto error;
@@ -1326,18 +1319,17 @@ defrag_check_defrag_on(
struct defrag_chunk_info *chunk = &(ino_dfr->chunks[i]);
unsigned int chunk_start = 0, chunk_end = 0;
- /* Skip this chunk when error occured or it already passed defrag process */
+ /* Skip this chunk when error occurred or it already passed defrag process */
if ((chunk->stat == DFR_CHUNK_STAT_ERR) || (chunk->stat == DFR_CHUNK_STAT_PASS))
continue;
chunk_start = chunk->f_clus;
chunk_end = chunk->f_clus + chunk->nr_clus;
- if ( ((clus_start >= chunk_start) && (clus_start < chunk_end)) ||
+ if (((clus_start >= chunk_start) && (clus_start < chunk_end)) ||
((clus_end > chunk_start) && (clus_end <= chunk_end)) ||
- ((clus_start < chunk_start) && (clus_end > chunk_end)) ) {
- ret = 1;
-
+ ((clus_start < chunk_start) && (clus_end > chunk_end))) {
+ ret = 1;
if (cancel) {
chunk->stat = DFR_CHUNK_STAT_ERR;
dfr_debug("Defrag canceled: inode %p, start %08x, end %08x, caller %s",
@@ -1371,15 +1363,13 @@ defrag_spo_test(
{
struct sdfat_sb_info *sbi = SDFAT_SB(sb);
- if( !(sb) || !(SDFAT_SB(sb)->options.defrag) )
+ if (!sb || !(SDFAT_SB(sb)->options.defrag))
return;
if (flag == sbi->dfr_spo_flag) {
dfr_err("Defrag SPO test (flag %d, caller %s)", flag, caller);
panic("Defrag SPO test");
}
-
- return;
}
#endif /* CONFIG_SDFAT_DFR_DEBUG */
diff --git a/dfr.h b/dfr.h
index 38f0bdd..19edab3 100644
--- a/dfr.h
+++ b/dfr.h
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
#ifndef _SDFAT_DEFRAG_H
@@ -23,45 +21,47 @@
#ifdef CONFIG_SDFAT_DFR
/* Tuning parameters */
-#define DFR_MIN_TIMEOUT (1 * HZ) // Minimum timeout for forced-sync
-#define DFR_DEFAULT_TIMEOUT (10 * HZ) // Default timeout for forced-sync
+#define DFR_MIN_TIMEOUT (1 * HZ) // Minimum timeout for forced-sync
+#define DFR_DEFAULT_TIMEOUT (10 * HZ) // Default timeout for forced-sync
-#define DFR_DEFAULT_CLEAN_RATIO (50) // Wake-up daemon when clean AU ratio under 50%
-#define DFR_DEFAULT_WAKEUP_RATIO (10) // Wake-up daemon when clean AU ratio under 10%, regardless of frag_ratio
+#define DFR_DEFAULT_CLEAN_RATIO (50) // Wake-up daemon when clean AU ratio under 50%
+#define DFR_DEFAULT_WAKEUP_RATIO (10) // Wake-up daemon when clean AU ratio under 10%, regardless of frag_ratio
-#define DFR_DEFAULT_FRAG_RATIO (130) // Wake-up daemon when frag_ratio over 130%
+#define DFR_DEFAULT_FRAG_RATIO (130) // Wake-up daemon when frag_ratio over 130%
-#define DFR_DEFAULT_PACKING_RATIO (10) // Call allocator with PACKING flag, when clean AU ratio under 10%
+#define DFR_DEFAULT_PACKING_RATIO (10) // Call allocator with PACKING flag, when clean AU ratio under 10%
-#define DFR_DEFAULT_STOP_RATIO (98) // Stop defrag_daemon when disk used ratio over 98%
-#define DFR_FULL_RATIO (100)
+#define DFR_DEFAULT_STOP_RATIO (98) // Stop defrag_daemon when disk used ratio over 98%
+#define DFR_FULL_RATIO (100)
-#define DFR_MAX_AU_MOVED (16) // Maximum # of AUs for a request
+#define DFR_MAX_AU_MOVED (16) // Maximum # of AUs for a request
/* Debugging support*/
-#define dfr_err(fmt, args...) EMSG("DFR: " fmt "\n", args)
+#define dfr_err(fmt, args...) pr_err("DFR: " fmt "\n", args)
#ifdef CONFIG_SDFAT_DFR_DEBUG
-#define dfr_debug(fmt, args...) DMSG("DFR: " fmt "\n", args)
+#define dfr_debug(fmt, args...) pr_debug("DFR: " fmt "\n", args)
#else
#define dfr_debug(fmt, args...)
#endif
/* Error handling */
-#define ERR_HANDLE(err) \
- if (err) { \
- dfr_debug("err %d", err); \
- goto error; \
- }
+#define ERR_HANDLE(err) { \
+ if (err) { \
+ dfr_debug("err %d", err); \
+ goto error; \
+ } \
+}
-#define ERR_HANDLE2(cond, err, val) \
- if (cond) { \
- err = val; \
- dfr_debug("err %d", err); \
- goto error; \
- }
+#define ERR_HANDLE2(cond, err, val) { \
+ if (cond) { \
+ err = val; \
+ dfr_debug("err %d", err); \
+ goto error; \
+ } \
+}
/* Arguments IN-OUT */
@@ -91,16 +91,16 @@
(SDFAT_SB(sb)->options.amap_opt.sect_per_au) >> (SDFAT_SB(sb)->fsi.sect_per_clus_bits) \
)
#define PAGES_PER_AU(sb) ( \
- ( (SDFAT_SB(sb)->options.amap_opt.sect_per_au) << ((sb)->s_blocksize_bits) ) \
+ ((SDFAT_SB(sb)->options.amap_opt.sect_per_au) << ((sb)->s_blocksize_bits)) \
>> PAGE_SHIFT \
)
#define PAGES_PER_CLUS(sb) ((SDFAT_SB(sb)->fsi.cluster_size) >> PAGE_SHIFT)
#define FAT32_CHECK_CLUSTER(fsi, clus, err) \
{ \
- if ( ((clus) < FAT32_UNUSED_CLUS) || \
+ if (((clus) < FAT32_UNUSED_CLUS) || \
((clus) > (fsi)->num_clusters) || \
- ((clus) >= FAT32_RESERVED) ) { \
+ ((clus) >= FAT32_RESERVED)) { \
dfr_err("clus %08x, fsi->num_clusters %08x", (clus), (fsi)->num_clusters); \
err = -EINVAL; \
} else { \
@@ -143,7 +143,7 @@ struct defrag_trav_arg {
char dummy1;
int dummy2;
};
-
+
#define DFR_TRAV_STAT_DONE (0x1)
#define DFR_TRAV_STAT_MORE (0x2)
#define DFR_TRAV_STAT_ERR (0xFF)
@@ -156,7 +156,7 @@ struct defrag_trav_header {
char stat;
unsigned int nr_entries;
};
-
+
/* IOC_DFR_REQ */
#define REQ_HEADER_IDX (0)
diff --git a/extent.c b/extent.c
index 276f18e..9349a59 100644
--- a/extent.c
+++ b/extent.c
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
/*
@@ -272,7 +270,7 @@ static inline void cache_init(struct extent_cache_id *cid, s32 fclus, u32 dclus)
}
s32 extent_get_clus(struct inode *inode, s32 cluster, s32 *fclus,
- u32 *dclus, u32 *last_dclus, s32 allow_eof)
+ u32 *dclus, u32 *last_dclus, s32 allow_eof)
{
struct super_block *sb = inode->i_sb;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
@@ -347,11 +345,11 @@ s32 extent_get_clus(struct inode *inode, s32 cluster, s32 *fclus,
break;
}
-
+
if (!cache_contiguous(&cid, *dclus))
cache_init(&cid, *fclus, *dclus);
}
-
+
extent_cache_add(inode, &cid);
return 0;
}
diff --git a/fatent.c b/fatent.c
index 8fb88a5..71d3653 100644
--- a/fatent.c
+++ b/fatent.c
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
/************************************************************************/
@@ -53,7 +51,7 @@
static s32 exfat_ent_get(struct super_block *sb, u32 loc, u32 *content)
{
u32 sec, off, _content;
- u8 *fat_sector;
+ u8 *fat_sector;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
/* fsi->vol_type == EXFAT */
@@ -64,12 +62,11 @@ static s32 exfat_ent_get(struct super_block *sb, u32 loc, u32 *content)
if (!fat_sector)
return -EIO;
- _content = le32_to_cpu(*(__le32*)(&fat_sector[off]));
- if (_content >= CLUSTER_32(0xFFFFFFF8)) {
- //return 0xFFFFFFFF to simplify code
- *content = CLUS_EOF;
- return 0;
- }
+ _content = le32_to_cpu(*(__le32 *)(&fat_sector[off]));
+
+ /* remap reserved clusters to simplify code */
+ if (_content >= CLUSTER_32(0xFFFFFFF8))
+ _content = CLUS_EOF;
*content = CLUSTER_32(_content);
return 0;
@@ -78,7 +75,7 @@ static s32 exfat_ent_get(struct super_block *sb, u32 loc, u32 *content)
static s32 exfat_ent_set(struct super_block *sb, u32 loc, u32 content)
{
u32 sec, off;
- u8 *fat_sector;
+ u8 *fat_sector;
__le32 *fat_entry;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
@@ -95,10 +92,12 @@ static s32 exfat_ent_set(struct super_block *sb, u32 loc, u32 content)
return fcache_modify(sb, sec);
}
+#define FATENT_FAT32_VALID_MASK (0x0FFFFFFFU)
+#define FATENT_FAT32_IGNORE_MASK (0xF0000000U)
static s32 fat32_ent_get(struct super_block *sb, u32 loc, u32 *content)
{
u32 sec, off, _content;
- u8 *fat_sector;
+ u8 *fat_sector;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
sec = fsi->FAT1_start_sector + (loc >> (sb->s_blocksize_bits-2));
@@ -108,14 +107,14 @@ static s32 fat32_ent_get(struct super_block *sb, u32 loc, u32 *content)
if (!fat_sector)
return -EIO;
- _content = le32_to_cpu(*(__le32*)(&fat_sector[off]));
- _content &= 0x0FFFFFFF;
+ _content = le32_to_cpu(*(__le32 *)(&fat_sector[off]));
+ _content &= FATENT_FAT32_VALID_MASK;
- if (_content >= CLUSTER_32(0x0FFFFFF8)) {
- //return 0xFFFFFFFF to simplify code
- *content = CLUS_EOF;
- return 0;
- }
+ /* remap reserved clusters to simplify code */
+ if (_content == CLUSTER_32(0x0FFFFFF7U))
+ _content = CLUS_BAD;
+ else if (_content >= CLUSTER_32(0x0FFFFFF8U))
+ _content = CLUS_EOF;
*content = CLUSTER_32(_content);
return 0;
@@ -128,7 +127,7 @@ static s32 fat32_ent_set(struct super_block *sb, u32 loc, u32 content)
__le32 *fat_entry;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
- content &= 0x0FFFFFFF;
+ content &= FATENT_FAT32_VALID_MASK;
sec = fsi->FAT1_start_sector + (loc >> (sb->s_blocksize_bits-2));
off = (loc << 2) & (u32)(sb->s_blocksize - 1);
@@ -138,34 +137,35 @@ static s32 fat32_ent_set(struct super_block *sb, u32 loc, u32 content)
return -EIO;
fat_entry = (__le32 *)&(fat_sector[off]);
- content |= (le32_to_cpu(*fat_entry) & 0xF0000000);
+ content |= (le32_to_cpu(*fat_entry) & FATENT_FAT32_IGNORE_MASK);
*fat_entry = cpu_to_le32(content);
return fcache_modify(sb, sec);
}
+#define FATENT_FAT16_VALID_MASK (0x0000FFFFU)
static s32 fat16_ent_get(struct super_block *sb, u32 loc, u32 *content)
{
u32 sec, off, _content;
- u8 *fat_sector;
+ u8 *fat_sector;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
sec = fsi->FAT1_start_sector + (loc >> (sb->s_blocksize_bits-1));
off = (loc << 1) & (u32)(sb->s_blocksize - 1);
fat_sector = fcache_getblk(sb, sec);
- if(!fat_sector)
+ if (!fat_sector)
return -EIO;
- _content = (u32)le16_to_cpu(*(__le16*)(&fat_sector[off]));
- _content &= 0x0000FFFF;
+ _content = (u32)le16_to_cpu(*(__le16 *)(&fat_sector[off]));
+ _content &= FATENT_FAT16_VALID_MASK;
+
+ /* remap reserved clusters to simplify code */
+ if (_content == CLUSTER_16(0xFFF7U))
+ _content = CLUS_BAD;
+ else if (_content >= CLUSTER_16(0xFFF8U))
+ _content = CLUS_EOF;
- if (_content >= CLUSTER_16(0xFFF8)) {
- // return 0x0FFFFFFF to simplify code
- *content = CLUS_EOF;
- return 0;
- }
-
*content = CLUSTER_32(_content);
return 0;
}
@@ -177,7 +177,7 @@ static s32 fat16_ent_set(struct super_block *sb, u32 loc, u32 content)
__le16 *fat_entry;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
- content &= 0x0000FFFF;
+ content &= FATENT_FAT16_VALID_MASK;
sec = fsi->FAT1_start_sector + (loc >> (sb->s_blocksize_bits-1));
off = (loc << 1) & (u32)(sb->s_blocksize - 1);
@@ -186,16 +186,17 @@ static s32 fat16_ent_set(struct super_block *sb, u32 loc, u32 content)
if (!fat_sector)
return -EIO;
- fat_entry = (__le16*)&(fat_sector[off]);
+ fat_entry = (__le16 *)&(fat_sector[off]);
*fat_entry = cpu_to_le16(content);
return fcache_modify(sb, sec);
}
+#define FATENT_FAT12_VALID_MASK (0x00000FFFU)
static s32 fat12_ent_get(struct super_block *sb, u32 loc, u32 *content)
{
u32 sec, off, _content;
- u8 *fat_sector;
+ u8 *fat_sector;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
sec = fsi->FAT1_start_sector + ((loc + (loc >> 1)) >> sb->s_blocksize_bits);
@@ -217,15 +218,16 @@ static s32 fat12_ent_get(struct super_block *sb, u32 loc, u32 *content)
_content = get_unaligned_le16(&fat_sector[off]);
}
- if (loc & 1) _content >>= 4;
+ if (loc & 1)
+ _content >>= 4;
- _content &= 0x00000FFF;
+ _content &= FATENT_FAT12_VALID_MASK;
- if (_content >= CLUSTER_16(0x0FF8)) {
- /* return 0xFFFFFFFF to simplify code */
- *content = CLUS_EOF;
- return 0;
- }
+ /* remap reserved clusters to simplify code */
+ if (_content == CLUSTER_16(0x0FF7U))
+ _content = CLUS_BAD;
+ else if (_content >= CLUSTER_16(0x0FF8U))
+ _content = CLUS_EOF;
*content = CLUSTER_32(_content);
return 0;
@@ -237,7 +239,7 @@ static s32 fat12_ent_set(struct super_block *sb, u32 loc, u32 content)
u8 *fat_sector, *fat_entry;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
- content &= 0x00000FFF;
+ content &= FATENT_FAT12_VALID_MASK;
sec = fsi->FAT1_start_sector + ((loc + (loc >> 1)) >> sb->s_blocksize_bits);
off = (loc + (loc >> 1)) & (u32)(sb->s_blocksize - 1);
@@ -262,9 +264,7 @@ static s32 fat12_ent_set(struct super_block *sb, u32 loc, u32 content)
fat_sector[0] = (u8)(content >> 8);
} else {
fat_entry = &(fat_sector[off]);
- content |= 0x000F &
- get_unaligned_le16(fat_entry);
-
+ content |= 0x000F & get_unaligned_le16(fat_entry);
put_unaligned_le16(content, fat_entry);
}
} else { /* even */
@@ -282,9 +282,7 @@ static s32 fat12_ent_set(struct super_block *sb, u32 loc, u32 content)
fat_sector[0] = (u8)((fat_sector[0] & 0xF0) | (content >> 8));
} else {
fat_entry = &(fat_sector[off]);
- content |= 0xF000 &
- get_unaligned_le16(fat_entry);
-
+ content |= 0xF000 & get_unaligned_le16(fat_entry);
put_unaligned_le16(content, fat_entry);
}
}
@@ -338,12 +336,30 @@ s32 fat_ent_ops_init(struct super_block *sb)
return 0;
}
+static inline bool is_reserved_clus(u32 clus)
+{
+ if (IS_CLUS_FREE(clus))
+ return true;
+ if (IS_CLUS_EOF(clus))
+ return true;
+ if (IS_CLUS_BAD(clus))
+ return true;
+ return false;
+}
+
+static inline bool is_valid_clus(FS_INFO_T *fsi, u32 clus)
+{
+ if (clus < CLUS_BASE || fsi->num_clusters <= clus)
+ return false;
+ return true;
+}
+
s32 fat_ent_get(struct super_block *sb, u32 loc, u32 *content)
{
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
s32 err;
- if (loc < CLUS_BASE || fsi->num_clusters <= loc) {
+ if (!is_valid_clus(fsi, loc)) {
sdfat_fs_error(sb, "invalid access to FAT (entry 0x%08x)", loc);
return -EIO;
}
@@ -355,8 +371,7 @@ s32 fat_ent_get(struct super_block *sb, u32 loc, u32 *content)
return err;
}
- if (*content && !IS_CLUS_EOF(*content) &&
- (*content < CLUS_BASE || fsi->num_clusters <= *content)) {
+ if (!is_reserved_clus(*content) && !is_valid_clus(fsi, *content)) {
sdfat_fs_error(sb, "invalid access to FAT (entry 0x%08x) "
"bogus content (0x%08x)", loc, *content);
return -EIO;
@@ -368,17 +383,25 @@ s32 fat_ent_get(struct super_block *sb, u32 loc, u32 *content)
s32 fat_ent_set(struct super_block *sb, u32 loc, u32 content)
{
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
+
return fsi->fatent_ops->ent_set(sb, loc, content);
}
s32 fat_ent_get_safe(struct super_block *sb, u32 loc, u32 *content)
{
s32 err = fat_ent_get(sb, loc, content);
+
if (err)
return err;
if (IS_CLUS_FREE(*content)) {
- sdfat_fs_error(sb, "invalid access to free FAT "
+ sdfat_fs_error(sb, "invalid access to FAT free cluster "
+ "(entry 0x%08x)", loc);
+ return -EIO;
+ }
+
+ if (IS_CLUS_BAD(*content)) {
+ sdfat_fs_error(sb, "invalid access to FAT bad cluster "
"(entry 0x%08x)", loc);
return -EIO;
}
diff --git a/misc.c b/misc.c
index 8cab489..566f99b 100644
--- a/misc.c
+++ b/misc.c
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
/*
@@ -70,7 +68,7 @@ void __sdfat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
- printk(KERN_ERR "[SDFAT](%s[%d:%d]):ERR: %pV\n",
+ pr_err("[SDFAT](%s[%d:%d]):ERR: %pV\n",
sb->s_id, MAJOR(bd_dev), MINOR(bd_dev), &vaf);
#ifdef CONFIG_SDFAT_SUPPORT_STLOG
if (opts->errors == SDFAT_ERRORS_RO && !(sb->s_flags & MS_RDONLY)) {
@@ -82,11 +80,11 @@ void __sdfat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
}
if (opts->errors == SDFAT_ERRORS_PANIC) {
- panic("[SDFAT](%s[%d:%d]): fs panic from previous error\n",
+ panic("[SDFAT](%s[%d:%d]): fs panic from previous error\n",
sb->s_id, MAJOR(bd_dev), MINOR(bd_dev));
} else if (opts->errors == SDFAT_ERRORS_RO && !(sb->s_flags & MS_RDONLY)) {
sb->s_flags |= MS_RDONLY;
- printk(KERN_ERR "[SDFAT](%s[%d:%d]): Filesystem has been set "
+ pr_err("[SDFAT](%s[%d:%d]): Filesystem has been set "
"read-only\n", sb->s_id, MAJOR(bd_dev), MINOR(bd_dev));
#ifdef CONFIG_SDFAT_SUPPORT_STLOG
ST_LOG("[SDFAT](%s[%d:%d]): Filesystem has been set read-only\n",
@@ -97,9 +95,9 @@ void __sdfat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
EXPORT_SYMBOL(__sdfat_fs_error);
/**
- * __sdfat_msg() - print preformated FAT specific messages.
- * Every thing what is not sdfat_fs_error() should be __sdfat_msg().
- * If 'st' is set to 1, it means that this message should be saved on ST_LOG.
+ * __sdfat_msg() - print preformated SDFAT specific messages.
+ * All logs except what uses sdfat_fs_error() should be written by __sdfat_msg()
+ * If 'st' is set, the log is propagated to ST_LOG.
*/
void __sdfat_msg(struct super_block *sb, const char *level, int st, const char *fmt, ...)
{
@@ -111,11 +109,12 @@ void __sdfat_msg(struct super_block *sb, const char *level, int st, const char *
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
+ /* level means KERN_ pacility level */
printk("%s[SDFAT](%s[%d:%d]): %pV\n", level,
sb->s_id, MAJOR(bd_dev), MINOR(bd_dev), &vaf);
#ifdef CONFIG_SDFAT_SUPPORT_STLOG
if (st) {
- ST_LOG("[SDFAT](%s[%d:%d]): %pV\n",
+ ST_LOG("[SDFAT](%s[%d:%d]): %pV\n",
sb->s_id, MAJOR(bd_dev), MINOR(bd_dev), &vaf);
}
#endif
@@ -125,15 +124,16 @@ EXPORT_SYMBOL(__sdfat_msg);
void sdfat_log_version(void)
{
- printk(KERN_INFO "[SDFAT] Filesystem version %s\n", SDFAT_VERSION);
+ pr_info("[SDFAT] Filesystem version %s\n", SDFAT_VERSION);
#ifdef CONFIG_SDFAT_SUPPORT_STLOG
ST_LOG("[SDFAT] Filesystem version %s\n", SDFAT_VERSION);
#endif
}
EXPORT_SYMBOL(sdfat_log_version);
-extern struct timezone sys_tz;
-
+/* externs sys_tz
+ * extern struct timezone sys_tz;
+ */
#define UNIX_SECS_1980 315532800L
#if BITS_PER_LONG == 64
@@ -154,15 +154,15 @@ extern struct timezone sys_tz;
do { \
/* 2100 isn't leap year */ \
if (unlikely(year > NO_LEAP_YEAR_2100)) \
- leap_year = ((year + 3) / 4) - 1; \
+ leap_year = ((year + 3) / 4) - 1; \
else \
- leap_year = ((year + 3) / 4); \
- } while(0)
+ leap_year = ((year + 3) / 4); \
+ } while (0)
/* Linear day numbers of the respective 1sts in non-leap years. */
static time_t accum_days_in_year[] = {
- /* Month : 01 02 03 04 05 06 07 08 09 10 11 12 */
- 0, 0, 31, 59, 90,120,151,181,212,243,273,304,334, 0, 0, 0,
+ /* Month : N 01 02 03 04 05 06 07 08 09 10 11 12 */
+ 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0,
};
/* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */
@@ -179,10 +179,10 @@ void sdfat_time_fat2unix(struct sdfat_sb_info *sbi, struct timespec *ts,
ts->tv_sec = tp->Second + tp->Minute * SECS_PER_MIN
+ tp->Hour * SECS_PER_HOUR
- + (year * 365 + ld + accum_days_in_year[(tp->Month)]
+ + (year * 365 + ld + accum_days_in_year[tp->Month]
+ (tp->Day - 1) + DAYS_DELTA_DECADE) * SECS_PER_DAY;
- if(!sbi->options.tz_utc)
+ if (!sbi->options.tz_utc)
ts->tv_sec += sys_tz.tz_minuteswest * SECS_PER_MIN;
ts->tv_nsec = 0;
@@ -255,6 +255,7 @@ TIMESTAMP_T *tm_now(struct sdfat_sb_info *sbi, TIMESTAMP_T *tp)
{
struct timespec ts = CURRENT_TIME_SEC;
DATE_TIME_T dt;
+
sdfat_time_unix2fat(sbi, &ts, &dt);
tp->year = dt.Year;
@@ -264,7 +265,7 @@ TIMESTAMP_T *tm_now(struct sdfat_sb_info *sbi, TIMESTAMP_T *tp)
tp->min = dt.Minute;
tp->sec = dt.Second;
- return(tp);
+ return tp;
}
u8 calc_chksum_1byte(void *data, s32 len, u8 chksum)
@@ -275,7 +276,7 @@ u8 calc_chksum_1byte(void *data, s32 len, u8 chksum)
for (i = 0; i < len; i++, c++)
chksum = (((chksum & 1) << 7) | ((chksum & 0xFE) >> 1)) + *c;
- return(chksum);
+ return chksum;
}
u16 calc_chksum_2byte(void *data, s32 len, u16 chksum, s32 type)
@@ -302,7 +303,8 @@ u32 sdfat_time_current_usec(struct timeval *tv)
#ifdef CONFIG_SDFAT_DBG_CAREFUL
/* Check the consistency of i_size_ondisk (FAT32, or flags 0x01 only) */
-void sdfat_debug_check_clusters(struct inode *inode){
+void sdfat_debug_check_clusters(struct inode *inode)
+{
int num_clusters;
volatile uint32_t tmp_fat_chain[50];
volatile int num_clusters_org, tmp_i = 0;
@@ -321,7 +323,8 @@ void sdfat_debug_check_clusters(struct inode *inode){
num_clusters_org = num_clusters;
- if (clu.flags == 0x03) return;
+ if (clu.flags == 0x03)
+ return;
while (num_clusters > 0) {
/* FAT chain logging */
@@ -357,6 +360,7 @@ void __sdfat_dmsg(int level, const char *fmt, ...)
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
+ /* fmt already includes KERN_ pacility level */
printk("[%u] %pV", current->pid, &vaf);
va_end(args);
#else
@@ -367,6 +371,7 @@ void __sdfat_dmsg(int level, const char *fmt, ...)
return;
va_start(args, fmt);
+ /* fmt already includes KERN_ pacility level */
vprintk(fmt, args);
va_end(args);
#endif
diff --git a/mpage.c b/mpage.c
index cfda066..8a0ce7f 100644
--- a/mpage.c
+++ b/mpage.c
@@ -26,9 +26,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
/************************************************************************/
@@ -64,7 +62,7 @@
#include /* for mark_page_accessed() */
#include
#include
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
#include
#endif
@@ -80,30 +78,43 @@ static void __mpage_write_end_io(struct bio *bio, int err);
/*************************************************************************
* FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY
*************************************************************************/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
+static inline void __sdfat_submit_bio_write2(int flags, struct bio *bio)
+{
+ bio_set_op_attrs(bio, REQ_OP_WRITE, flags);
+ submit_bio(bio);
+}
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0) */
+static inline void __sdfat_submit_bio_write2(int flags, struct bio *bio)
+{
+ submit_bio(WRITE | flags, bio);
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)
static void mpage_write_end_io(struct bio *bio)
{
__mpage_write_end_io(bio, bio->bi_error);
}
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0) */
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4,3,0) */
static void mpage_write_end_io(struct bio *bio, int err)
{
if (test_bit(BIO_UPTODATE, &bio->bi_flags))
err = 0;
__mpage_write_end_io(bio, err);
}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0) */
+#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
static inline int bio_get_nr_vecs(struct block_device *bdev)
{
return BIO_MAX_PAGES;
}
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) */
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4,1,0) */
/* EMPTY */
#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
static inline sector_t __sdfat_bio_sector(struct bio *bio)
{
return bio->bi_iter.bi_sector;
@@ -123,10 +134,10 @@ static inline void __sdfat_set_bio_size(struct bio *bio, unsigned int size)
{
bio->bi_iter.bi_size = size;
}
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) */
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */
static inline sector_t __sdfat_bio_sector(struct bio *bio)
{
- return bio->bi_sector;
+ return bio->bi_sector;
}
static inline void __sdfat_set_bio_sector(struct bio *bio, sector_t sector)
@@ -136,26 +147,26 @@ static inline void __sdfat_set_bio_sector(struct bio *bio, sector_t sector)
static inline unsigned int __sdfat_bio_size(struct bio *bio)
{
- return bio->bi_size;
+ return bio->bi_size;
}
static inline void __sdfat_set_bio_size(struct bio *bio, unsigned int size)
{
bio->bi_size = size;
}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) */
+#endif
-/* __check_dfr_on() and __dfr_writepage_end_io() functions are copied from
- * sdfat.c.
- * Each function should be same perfectly
+/* __check_dfr_on() and __dfr_writepage_end_io() functions
+ * are copied from sdfat.c
+ * Each function should be same perfectly
*/
static inline int __check_dfr_on(struct inode *inode, loff_t start, loff_t end, const char *fname)
{
-#ifdef CONFIG_SDFAT_DFR
+#ifdef CONFIG_SDFAT_DFR
struct defrag_info *ino_dfr = &(SDFAT_I(inode)->dfr_info);
- if ( (atomic_read(&ino_dfr->stat) == DFR_INO_STAT_REQ) &&
- fsapi_dfr_check_dfr_on(inode, start, end, 0, fname) )
+ if ((atomic_read(&ino_dfr->stat) == DFR_INO_STAT_REQ) &&
+ fsapi_dfr_check_dfr_on(inode, start, end, 0, fname))
return 1;
#endif
return 0;
@@ -163,8 +174,9 @@ static inline int __check_dfr_on(struct inode *inode, loff_t start, loff_t end,
static inline int __dfr_writepage_end_io(struct page *page)
{
-#ifdef CONFIG_SDFAT_DFR
+#ifdef CONFIG_SDFAT_DFR
struct defrag_info *ino_dfr = &(SDFAT_I(page->mapping->host)->dfr_info);
+
if (atomic_read(&ino_dfr->stat) == DFR_INO_STAT_REQ)
fsapi_dfr_writepage_endio(page);
#endif
@@ -172,7 +184,7 @@ static inline int __dfr_writepage_end_io(struct page *page)
}
-static inline unsigned int __calc_size_to_align(struct super_block* sb)
+static inline unsigned int __calc_size_to_align(struct super_block *sb)
{
struct block_device *bdev = sb->s_bdev;
struct gendisk *disk;
@@ -180,7 +192,7 @@ static inline unsigned int __calc_size_to_align(struct super_block* sb)
struct queue_limits *limit;
unsigned int max_sectors;
unsigned int aligned = 0;
-
+
disk = bdev->bd_disk;
if (!disk)
goto out;
@@ -203,8 +215,8 @@ struct mpage_data {
struct bio *bio;
sector_t last_block_in_bio;
get_block_t *get_block;
- unsigned use_writepage;
- unsigned size_to_align;
+ unsigned int use_writepage;
+ unsigned int size_to_align;
};
/*
@@ -235,7 +247,7 @@ static void __mpage_write_end_io(struct bio *bio, int err)
if (page->mapping)
mapping_set_error(page->mapping, err);
}
-
+
__dfr_writepage_end_io(page);
end_page_writeback(page);
@@ -243,10 +255,10 @@ static void __mpage_write_end_io(struct bio *bio, int err)
bio_put(bio);
}
-static struct bio *mpage_bio_submit(int rw, struct bio *bio)
+static struct bio *mpage_bio_submit_write(int flags, struct bio *bio)
{
bio->bi_end_io = mpage_write_end_io;
- submit_bio(rw, bio);
+ __sdfat_submit_bio_write2(flags, bio);
return NULL;
}
@@ -271,20 +283,20 @@ mpage_alloc(struct block_device *bdev,
return bio;
}
-static int sdfat_mpage_writepage(struct page *page,
+static int sdfat_mpage_writepage(struct page *page,
struct writeback_control *wbc, void *data)
{
struct mpage_data *mpd = data;
struct bio *bio = mpd->bio;
struct address_space *mapping = page->mapping;
struct inode *inode = page->mapping->host;
- const unsigned blkbits = inode->i_blkbits;
- const unsigned blocks_per_page = PAGE_CACHE_SIZE >> blkbits;
+ const unsigned int blkbits = inode->i_blkbits;
+ const unsigned int blocks_per_page = PAGE_SIZE >> blkbits;
sector_t last_block;
sector_t block_in_file;
sector_t blocks[MAX_BUF_PER_PAGE];
- unsigned page_block;
- unsigned first_unmapped = blocks_per_page;
+ unsigned int page_block;
+ unsigned int first_unmapped = blocks_per_page;
struct block_device *bdev = NULL;
int boundary = 0;
sector_t boundary_block = 0;
@@ -292,7 +304,7 @@ static int sdfat_mpage_writepage(struct page *page,
int length;
struct buffer_head map_bh;
loff_t i_size = i_size_read(inode);
- unsigned long end_index = i_size >> PAGE_CACHE_SHIFT;
+ unsigned long end_index = i_size >> PAGE_SHIFT;
int ret = 0;
if (page_has_buffers(page)) {
@@ -323,9 +335,10 @@ static int sdfat_mpage_writepage(struct page *page,
/* bh should be mapped if delay is set */
if (buffer_delay(bh)) {
- sector_t blk_in_file = (sector_t)(page->index << (PAGE_CACHE_SHIFT - blkbits)) + page_block;
- BUG_ON(bh->b_size != (1 << blkbits));
+ sector_t blk_in_file =
+ (sector_t)(page->index << (PAGE_SHIFT - blkbits)) + page_block;
+ BUG_ON(bh->b_size != (1 << blkbits));
if (page->index > end_index) {
MMSG("%s(inode:%p) "
"over end with delayed buffer"
@@ -351,7 +364,7 @@ static int sdfat_mpage_writepage(struct page *page,
unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr);
}
}
-
+
if (page_block) {
if (bh->b_blocknr != blocks[page_block-1] + 1) {
MMSG("%s(inode:%p) pblk(%d) "
@@ -387,7 +400,7 @@ static int sdfat_mpage_writepage(struct page *page,
* The page has no buffers: map it to disk
*/
BUG_ON(!PageUptodate(page));
- block_in_file = (sector_t)page->index << (PAGE_CACHE_SHIFT - blkbits);
+ block_in_file = (sector_t)page->index << (PAGE_SHIFT - blkbits);
last_block = (i_size - 1) >> blkbits;
map_bh.b_page = page;
for (page_block = 0; page_block < blocks_per_page; ) {
@@ -396,7 +409,7 @@ static int sdfat_mpage_writepage(struct page *page,
map_bh.b_size = 1 << blkbits;
if (mpd->get_block(inode, block_in_file, &map_bh, 1))
goto confused;
-
+
if (buffer_new(&map_bh))
unmap_underlying_metadata(map_bh.b_bdev,
map_bh.b_blocknr);
@@ -430,7 +443,7 @@ page_is_mapped:
* is zeroed when mapped, and writes to that region are not
* written out to the file."
*/
- unsigned offset = i_size & (PAGE_CACHE_SIZE - 1);
+ unsigned int offset = i_size & (PAGE_SIZE - 1);
if (page->index > end_index || !offset) {
MMSG("%s(inode:%p) over end "
@@ -439,7 +452,7 @@ page_is_mapped:
(u32)end_index, (u32)offset);
goto confused;
}
- zero_user_segment(page, offset, PAGE_CACHE_SIZE);
+ zero_user_segment(page, offset, PAGE_SIZE);
}
/*
@@ -449,22 +462,22 @@ page_is_mapped:
*/
if (bio) {
if (mpd->last_block_in_bio != blocks[0] - 1) {
- bio = mpage_bio_submit(WRITE, bio);
+ bio = mpage_bio_submit_write(0, bio);
} else if (mpd->size_to_align) {
- unsigned mask = mpd->size_to_align - 1;
- sector_t max_end_block =
+ unsigned int mask = mpd->size_to_align - 1;
+ sector_t max_end_block =
(__sdfat_bio_sector(bio) & ~(mask)) + mask;
- if ( (__sdfat_bio_size(bio) != (1 << (mask + 1))) &&
- (mpd->last_block_in_bio == max_end_block) ) {
+ if ((__sdfat_bio_size(bio) != (1 << (mask + 1))) &&
+ (mpd->last_block_in_bio == max_end_block)) {
MMSG("%s(inode:%p) alignment mpage_bio_submit"
"(start:%u, len:%u aligned:%u)\n",
__func__, inode,
- (unsigned)__sdfat_bio_sector(bio),
- (unsigned)(mpd->last_block_in_bio -
+ (unsigned int)__sdfat_bio_sector(bio),
+ (unsigned int)(mpd->last_block_in_bio -
__sdfat_bio_sector(bio) + 1),
- (unsigned)mpd->size_to_align);
- bio = mpage_bio_submit(WRITE | REQ_NOMERGE, bio);
+ (unsigned int)mpd->size_to_align);
+ bio = mpage_bio_submit_write(REQ_NOMERGE, bio);
}
}
}
@@ -484,7 +497,7 @@ alloc_new:
*/
length = first_unmapped << blkbits;
if (bio_add_page(bio, page, length, 0) < length) {
- bio = mpage_bio_submit(WRITE, bio);
+ bio = mpage_bio_submit_write(0, bio);
goto alloc_new;
}
@@ -495,7 +508,7 @@ alloc_new:
if (page_has_buffers(page)) {
struct buffer_head *head = page_buffers(page);
struct buffer_head *bh = head;
- unsigned buffer_counter = 0;
+ unsigned int buffer_counter = 0;
do {
if (buffer_counter++ == first_unmapped)
@@ -516,28 +529,29 @@ alloc_new:
BUG_ON(PageWriteback(page));
set_page_writeback(page);
- /*
+ /*
* FIXME FOR DEFRAGMENTATION : CODE REVIEW IS REQUIRED
*
* Turn off MAPPED flag in victim's bh if defrag on.
- * Another write_begin can starts after get_block for defrag victims
+ * Another write_begin can starts after get_block for defrag victims
* called.
- * In this case, write_begin calls get_block and get original block
+ * In this case, write_begin calls get_block and get original block
* number and previous defrag will be canceled.
*/
if (unlikely(__check_dfr_on(inode, (loff_t)(page->index << PAGE_SHIFT),
(loff_t)((page->index + 1) << PAGE_SHIFT), __func__))) {
struct buffer_head *head = page_buffers(page);
struct buffer_head *bh = head;
+
do {
clear_buffer_mapped(bh);
bh = bh->b_this_page;
} while (bh != head);
}
-
+
unlock_page(page);
if (boundary || (first_unmapped != blocks_per_page)) {
- bio = mpage_bio_submit(WRITE, bio);
+ bio = mpage_bio_submit_write(0, bio);
if (boundary_block) {
write_boundary_block(boundary_bdev,
boundary_block, 1 << blkbits);
@@ -550,7 +564,7 @@ alloc_new:
confused:
if (bio)
- bio = mpage_bio_submit(WRITE, bio);
+ bio = mpage_bio_submit_write(0, bio);
if (mpd->use_writepage) {
ret = mapping->a_ops->writepage(page, wbc);
@@ -579,14 +593,12 @@ int sdfat_mpage_writepages(struct address_space *mapping,
.use_writepage = 1,
.size_to_align = __calc_size_to_align(mapping->host->i_sb),
};
-
- BUG_ON(!get_block);
-
- blk_start_plug(&plug);
+ BUG_ON(!get_block);
+ blk_start_plug(&plug);
ret = write_cache_pages(mapping, wbc, sdfat_mpage_writepage, &mpd);
if (mpd.bio)
- mpage_bio_submit(WRITE, mpd.bio);
+ mpage_bio_submit_write(0, mpd.bio);
blk_finish_plug(&plug);
return ret;
}
diff --git a/nls.c b/nls.c
index 439fc02..b656344 100644
--- a/nls.c
+++ b/nls.c
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
/************************************************************************/
@@ -52,7 +50,7 @@ static u16 bad_dos_chars[] = {
/*
* Allow full-width illegal characters :
* "MS windows 7" supports full-width-invalid-name-characters.
- * So we should check half-width-invalid-name-characters(ASCII) only
+ * So we should check half-width-invalid-name-characters(ASCII) only
* for compatibility.
*
* " * / : < > ? \ |
@@ -62,10 +60,10 @@ static u16 bad_dos_chars[] = {
static u16 bad_uni_chars[] = {
0x0022, 0x002A, 0x002F, 0x003A,
0x003C, 0x003E, 0x003F, 0x005C, 0x007C,
- /*
+#if 0 /* allow full-width characters */
0x201C, 0x201D, 0xFF0A, 0xFF0F, 0xFF1A,
0xFF1C, 0xFF1E, 0xFF1F, 0xFF3C, 0xFF5C,
- */
+#endif
0
};
@@ -101,7 +99,7 @@ u16 *nls_wstrchr(u16 *str, u16 wchar)
s32 nls_cmp_sfn(struct super_block *sb, u8 *a, u8 *b)
{
- return(strncmp((void *) a, (void *) b, DOS_NAME_LENGTH));
+ return strncmp((void *)a, (void *)b, DOS_NAME_LENGTH);
}
s32 nls_cmp_uniname(struct super_block *sb, u16 *a, u16 *b)
@@ -109,10 +107,10 @@ s32 nls_cmp_uniname(struct super_block *sb, u16 *a, u16 *b)
s32 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;
+ if (nls_upper(sb, *a) != nls_upper(sb, *b))
+ return 1;
+ if (*a == 0x0)
+ return 0;
}
return 0;
}
@@ -146,7 +144,8 @@ s32 nls_uni16s_to_sfn(struct super_block *sb, UNI_NAME_T *p_uniname, DOS_NAME_T
i = 0;
while (i < DOS_NAME_LENGTH) {
if (i == 8) {
- if (last_period == NULL) break;
+ if (last_period == NULL)
+ break;
if (uniname <= last_period) {
if (uniname < last_period)
@@ -172,9 +171,9 @@ s32 nls_uni16s_to_sfn(struct super_block *sb, UNI_NAME_T *p_uniname, DOS_NAME_T
len = convert_uni_to_ch(nls, *uniname, buf, &lossy);
if (len > 1) {
- if ((i >= 8) && ((i+len) > DOS_NAME_LENGTH)) {
+ if ((i >= 8) && ((i+len) > DOS_NAME_LENGTH))
break;
- }
+
if ((i < 8) && ((i+len) > 8)) {
i = 8;
continue;
@@ -182,9 +181,8 @@ s32 nls_uni16s_to_sfn(struct super_block *sb, UNI_NAME_T *p_uniname, DOS_NAME_T
lower = 0xFF;
- for (j = 0; j < len; j++, i++) {
+ for (j = 0; j < len; j++, i++)
*(dosname+i) = *(buf+j);
- }
} else { /* len == 1 */
if ((*buf >= 'a') && (*buf <= 'z')) {
*(dosname+i) = *buf - ('a' - 'A');
@@ -208,18 +206,18 @@ s32 nls_uni16s_to_sfn(struct super_block *sb, UNI_NAME_T *p_uniname, DOS_NAME_T
uniname++;
}
- if (*dosname == 0xE5)
- *dosname = 0x05;
- if (*uniname != 0x0)
- lossy |= NLS_NAME_OVERLEN;
+ if (*dosname == 0xE5)
+ *dosname = 0x05;
+ if (*uniname != 0x0)
+ lossy |= NLS_NAME_OVERLEN;
- if (upper & lower)
- p_dosname->name_case = 0xFF;
- else
- p_dosname->name_case = lower;
+ if (upper & lower)
+ p_dosname->name_case = 0xFF;
+ else
+ p_dosname->name_case = lower;
- if (p_lossy)
- *p_lossy = lossy;
+ if (p_lossy)
+ *p_lossy = lossy;
return i;
}
@@ -266,7 +264,7 @@ s32 nls_sfn_to_uni16s(struct super_block *sb, DOS_NAME_T *p_dosname, UNI_NAME_T
i = j = 0;
while (j < MAX_NAME_LENGTH) {
- if (*(buf+i) == '\0')
+ if (*(buf+i) == '\0')
break;
i += convert_ch_to_uni(nls, (buf+i), uniname, NULL);
@@ -291,7 +289,8 @@ static s32 __nls_utf16s_to_vfsname(struct super_block *sb, UNI_NAME_T *p_uniname
return len;
}
-static s32 __nls_vfsname_to_utf16s(struct super_block *sb, const u8 *p_cstring, const s32 len, UNI_NAME_T *p_uniname, s32 *p_lossy)
+static s32 __nls_vfsname_to_utf16s(struct super_block *sb, const u8 *p_cstring,
+ const s32 len, UNI_NAME_T *p_uniname, s32 *p_lossy)
{
s32 i, unilen, lossy = NLS_NAME_NO_LOSSY;
u16 upname[MAX_NAME_LENGTH+1];
@@ -307,7 +306,7 @@ static s32 __nls_vfsname_to_utf16s(struct super_block *sb, const u8 *p_cstring,
return unilen;
}
- if (unilen > MAX_NAME_LENGTH ) {
+ if (unilen > MAX_NAME_LENGTH) {
MMSG("%s: failed to vfsname_to_utf16(estr:ENAMETOOLONG) "
"vfsnamelen:%d, unilen:%d>%d",
__func__, len, unilen, MAX_NAME_LENGTH);
@@ -316,7 +315,7 @@ static s32 __nls_vfsname_to_utf16s(struct super_block *sb, const u8 *p_cstring,
p_uniname->name_len = (u8)(unilen & 0xFF);
- for (i=0; iname_len = unilen;
p_uniname->name_hash =
calc_chksum_2byte((void *) upname, unilen<<1, 0, CS_DEFAULT);
- if (p_lossy)
+ if (p_lossy)
*p_lossy = lossy;
return unilen;
@@ -435,16 +435,16 @@ static s32 convert_ch_to_uni(struct nls_table *nls, u8 *ch, u16 *uni, s32 *lossy
return 1;
}
- if ((len = nls->char2uni(ch, MAX_CHARSET_SIZE, uni)) < 0) {
+ len = nls->char2uni(ch, MAX_CHARSET_SIZE, uni);
+ if (len < 0) {
/* conversion failed */
- DMSG("%s: fail to use nls \n", __func__);
+ DMSG("%s: fail to use nls\n", __func__);
if (lossy != NULL)
*lossy |= NLS_NAME_LOSSY;
*uni = (u16) '_';
- if (!strcmp(nls->charset, "utf8"))
+ if (!strcmp(nls->charset, "utf8"))
return 1;
- else
- return 2;
+ return 2;
}
return len;
@@ -461,9 +461,10 @@ static s32 convert_uni_to_ch(struct nls_table *nls, u16 uni, u8 *ch, s32 *lossy)
return 1;
}
- if ((len = nls->uni2char(uni, ch, MAX_CHARSET_SIZE)) < 0) {
+ len = nls->uni2char(uni, ch, MAX_CHARSET_SIZE);
+ if (len < 0) {
/* conversion failed */
- DMSG("%s: fail to use nls \n", __func__);
+ DMSG("%s: fail to use nls\n", __func__);
if (lossy != NULL)
*lossy |= NLS_NAME_LOSSY;
ch[0] = '_';
diff --git a/sdfat.c b/sdfat.c
index 4cb1cff..49bc22f 100644
--- a/sdfat.c
+++ b/sdfat.c
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
/************************************************************************/
@@ -56,11 +54,11 @@
#include
#include
#include
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
#include
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)
#error SDFAT only supports linux kernel version 3.0 or higher
#endif
@@ -71,7 +69,7 @@
#define ITER_POS_FILLED_DOTS (2)
/* type index declare at sdfat.h */
-const char* FS_TYPE_STR[] = {
+const char *FS_TYPE_STR[] = {
"auto",
"exfat",
"vfat"
@@ -80,7 +78,6 @@ const char* FS_TYPE_STR[] = {
static struct kset *sdfat_kset;
static struct kmem_cache *sdfat_inode_cachep;
-
static int sdfat_default_codepage = CONFIG_SDFAT_DEFAULT_CODEPAGE;
static char sdfat_default_iocharset[] = CONFIG_SDFAT_DEFAULT_IOCHARSET;
static const char sdfat_iocharset_with_utf8[] = "iso8859-1";
@@ -104,9 +101,9 @@ static int sdfat_write_inode(struct inode *inode, struct writeback_control *wbc)
static void sdfat_write_super(struct super_block *sb);
static void sdfat_write_failed(struct address_space *mapping, loff_t to);
-static void sdfat_init_namebuf(DENTRY_NAMEBUF_T* nb);
-static int sdfat_alloc_namebuf(DENTRY_NAMEBUF_T* nb);
-static void sdfat_free_namebuf(DENTRY_NAMEBUF_T* nb);
+static void sdfat_init_namebuf(DENTRY_NAMEBUF_T *nb);
+static int sdfat_alloc_namebuf(DENTRY_NAMEBUF_T *nb);
+static void sdfat_free_namebuf(DENTRY_NAMEBUF_T *nb);
/*************************************************************************
* INNER FUNCTIONS FOR FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY
@@ -118,62 +115,126 @@ static int __sdfat_create(struct inode *dir, struct dentry *dentry);
static int __sdfat_revalidate(struct dentry *dentry);
static int __sdfat_revalidate_ci(struct dentry *dentry, unsigned int flags);
static int __sdfat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync);
-static struct dentry* __sdfat_lookup(struct inode *dir, struct dentry *dentry);
+static struct dentry *__sdfat_lookup(struct inode *dir, struct dentry *dentry);
static int __sdfat_mkdir(struct inode *dir, struct dentry *dentry);
+static int __sdfat_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry);
static int __sdfat_show_options(struct seq_file *m, struct super_block *sb);
static inline ssize_t __sdfat_blkdev_direct_IO(int rw, struct kiocb *iocb,
struct inode *inode, void *iov_u, loff_t offset,
unsigned long nr_segs);
static inline ssize_t __sdfat_direct_IO(int rw, struct kiocb *iocb,
struct inode *inode, void *iov_u, loff_t offset,
- loff_t count);
+ loff_t count, unsigned long nr_segs);
static int __sdfat_d_hash(const struct dentry *dentry, struct qstr *qstr);
static int __sdfat_d_hashi(const struct dentry *dentry, struct qstr *qstr);
-static int __sdfat_cmp(const struct dentry *parent, const struct dentry *dentry,
- unsigned int len, const char *str, const struct qstr *name);
-static int __sdfat_cmpi(const struct dentry *parent, const struct dentry *dentry,
- unsigned int len, const char *str, const struct qstr *name);
+static int __sdfat_cmp(const struct dentry *dentry, unsigned int len,
+ const char *str, const struct qstr *name);
+static int __sdfat_cmpi(const struct dentry *dentry, unsigned int len,
+ const char *str, const struct qstr *name);
/*************************************************************************
* FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY
*************************************************************************/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
+static int sdfat_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry,
+ unsigned int flags)
+{
+ /*
+ * The VFS already checks for existence, so for local filesystems
+ * the RENAME_NOREPLACE implementation is equivalent to plain rename.
+ * Don't support any other flags
+ */
+ if (flags & ~RENAME_NOREPLACE)
+ return -EINVAL;
+ return __sdfat_rename(old_dir, old_dentry, new_dir, new_dentry);
+}
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) */
+static int sdfat_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
+{
+ return __sdfat_rename(old_dir, old_dentry, new_dir, new_dentry);
+}
+
+static int setattr_prepare(struct dentry *dentry, struct iattr *attr)
+{
+ struct inode *inode = dentry->d_inode;
+
+ return inode_change_ok(inode, attr);
+}
+#endif
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
+static inline void __sdfat_submit_bio_write(struct bio *bio)
+{
+ bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
+ submit_bio(bio);
+}
+
+static inline unsigned int __sdfat_full_name_hash(const struct dentry *dentry, const char *name, unsigned int len)
+{
+ return full_name_hash(dentry, name, len);
+}
+
+static inline unsigned long __sdfat_init_name_hash(const struct dentry *dentry)
+{
+ return init_name_hash(dentry);
+}
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) */
+static inline void __sdfat_submit_bio_write(struct bio *bio)
+{
+ submit_bio(WRITE, bio);
+}
+
+static inline unsigned int __sdfat_full_name_hash(const struct dentry *unused, const char *name, unsigned int len)
+{
+ return full_name_hash(name, len);
+}
+
+static inline unsigned long __sdfat_init_name_hash(const struct dentry *unused)
+{
+ return init_name_hash();
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 21)
+ /* EMPTY */
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 21) */
+static inline void inode_lock(struct inode *inode)
+{
+ mutex_lock(&inode->i_mutex);
+}
+
+static inline void inode_unlock(struct inode *inode)
+{
+ mutex_unlock(&inode->i_mutex);
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)
static void sdfat_writepage_end_io(struct bio *bio)
{
__sdfat_writepage_end_io(bio, bio->bi_error);
}
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0) */
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) */
static void sdfat_writepage_end_io(struct bio *bio, int err)
{
if (test_bit(BIO_UPTODATE, &bio->bi_flags))
err = 0;
__sdfat_writepage_end_io(bio, err);
}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0) */
+#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0)
-static const char *sdfat_follow_link(struct dentry *dentry, void **cookie)
-{
- return simple_follow_link(dentry, cookie);
-}
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0) */
-static void *sdfat_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
- struct sdfat_inode_info *ei = SDFAT_I(dentry->d_inode);
- nd_set_link(nd, (char *)(ei->target));
- return NULL;
-}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0) */
-
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
static inline int sdfat_remount_syncfs(struct super_block *sb)
{
sync_filesystem(sb);
return 0;
}
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) */
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) */
static inline int sdfat_remount_syncfs(struct super_block *sb)
{
/*
@@ -182,25 +243,27 @@ static inline int sdfat_remount_syncfs(struct super_block *sb)
*/
return 0;
}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) */
+#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
static inline sector_t __sdfat_bio_sector(struct bio *bio)
{
return bio->bi_iter.bi_sector;
}
-static inline void __sdfat_set_bio_iterate(struct bio *bio, sector_t sector, unsigned int size, unsigned int idx, unsigned int done)
+static inline void __sdfat_set_bio_iterate(struct bio *bio, sector_t sector,
+ unsigned int size, unsigned int idx, unsigned int done)
{
- struct bvec_iter* iter = &(bio->bi_iter);
+ struct bvec_iter *iter = &(bio->bi_iter);
+
iter->bi_sector = sector;
iter->bi_size = size;
iter->bi_idx = idx;
iter->bi_bvec_done = done;
}
-static void __sdfat_truncate_pagecache(struct inode *inode,
+static void __sdfat_truncate_pagecache(struct inode *inode,
loff_t to, loff_t newsize)
{
truncate_pagecache(inode, newsize);
@@ -216,18 +279,6 @@ static int sdfat_d_hashi(const struct dentry *dentry, struct qstr *qstr)
return __sdfat_d_hashi(dentry, qstr);
}
-static int sdfat_cmp(const struct dentry *parent, const struct dentry *dentry,
- unsigned int len, const char *str, const struct qstr *name)
-{
- return __sdfat_cmp(parent, dentry, len, str, name);
-}
-
-static int sdfat_cmpi(const struct dentry *parent, const struct dentry *dentry,
- unsigned int len, const char *str, const struct qstr *name)
-{
- return __sdfat_cmpi(parent, dentry, len, str, name);
-}
-
//instead of sdfat_readdir
static int sdfat_iterate(struct file *filp, struct dir_context *ctx)
{
@@ -294,8 +345,8 @@ get_new:
} else {
loff_t i_pos = ((loff_t) SDFAT_I(inode)->fid.start_clu << 32) |
((SDFAT_I(inode)->fid.rwoffset-1) & 0xffffffff);
-
struct inode *tmp = sdfat_iget(sb, i_pos);
+
if (tmp) {
inum = tmp->i_ino;
iput(tmp);
@@ -331,20 +382,21 @@ out_unlocked:
sdfat_free_namebuf(nb);
return err;
}
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) */
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */
static inline sector_t __sdfat_bio_sector(struct bio *bio)
{
return bio->bi_sector;
}
-static inline void __sdfat_set_bio_iterate(struct bio *bio, sector_t sector, unsigned int size, unsigned int idx, unsigned int done)
+static inline void __sdfat_set_bio_iterate(struct bio *bio, sector_t sector,
+ unsigned int size, unsigned int idx, unsigned int done)
{
bio->bi_sector = sector;
bio->bi_idx = idx;
- bio->bi_size = size; //PAGE_CACHE_SIZE;
+ bio->bi_size = size; //PAGE_SIZE;
}
-static void __sdfat_truncate_pagecache(struct inode *inode,
+static void __sdfat_truncate_pagecache(struct inode *inode,
loff_t to, loff_t newsize)
{
truncate_pagecache(inode, to, newsize);
@@ -362,20 +414,6 @@ static int sdfat_d_hashi(const struct dentry *dentry,
return __sdfat_d_hashi(dentry, qstr);
}
-static int sdfat_cmp(const struct dentry *parent, const struct inode *pinode,
- const struct dentry *dentry, const struct inode *inode,
- unsigned int len, const char *str, const struct qstr *name)
-{
- return __sdfat_cmp(parent, dentry, len, str, name);
-}
-
-static int sdfat_cmpi(const struct dentry *parent, const struct inode *pinode,
- const struct dentry *dentry, const struct inode *inode,
- unsigned int len, const char *str, const struct qstr *name)
-{
- return __sdfat_cmpi(parent, dentry, len, str, name);
-}
-
static int sdfat_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
struct inode *inode = filp->f_path.dentry->d_inode;
@@ -453,8 +491,8 @@ get_new:
} else {
loff_t i_pos = ((loff_t) SDFAT_I(inode)->fid.start_clu << 32) |
((SDFAT_I(inode)->fid.rwoffset-1) & 0xffffffff);
-
struct inode *tmp = sdfat_iget(sb, i_pos);
+
if (tmp) {
inum = tmp->i_ino;
iput(tmp);
@@ -490,23 +528,23 @@ out_unlocked:
sdfat_free_namebuf(nb);
return err;
}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) */
+#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
/* EMPTY */
-#else
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0) */
static inline struct inode *file_inode(const struct file *f)
{
return f->f_dentry->d_inode;
}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0) */
+#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
static inline int __is_sb_dirty(struct super_block *sb)
{
- return SDFAT_SB(sb)->s_dirt;
+ return SDFAT_SB(sb)->s_dirt;
}
static inline void __set_sb_clean(struct super_block *sb)
@@ -542,9 +580,9 @@ static void __write_super_delayed(struct work_struct *work)
static void setup_sdfat_sync_super_wq(struct super_block *sb)
{
- struct sdfat_sb_info* sbi = SDFAT_SB(sb);
- mutex_init(&sbi->s_lock);
+ struct sdfat_sb_info *sbi = SDFAT_SB(sb);
+ mutex_init(&sbi->s_lock);
spin_lock_init(&sbi->work_lock);
INIT_DELAYED_WORK(&sbi->write_super_work, __write_super_delayed);
sbi->host_sb = sb;
@@ -558,12 +596,14 @@ static inline bool __cancel_delayed_work_sync(struct sdfat_sb_info *sbi)
static inline void lock_super(struct super_block *sb)
{
struct sdfat_sb_info *sbi = SDFAT_SB(sb);
+
mutex_lock(&sbi->s_lock);
}
static inline void unlock_super(struct super_block *sb)
{
struct sdfat_sb_info *sbi = SDFAT_SB(sb);
+
mutex_unlock(&sbi->s_lock);
}
@@ -583,7 +623,8 @@ static int sdfat_revalidate_ci(struct dentry *dentry, unsigned int flags)
return __sdfat_revalidate_ci(dentry, flags);
}
-static struct inode *sdfat_iget(struct super_block *sb, loff_t i_pos) {
+static struct inode *sdfat_iget(struct super_block *sb, loff_t i_pos)
+{
struct sdfat_sb_info *sbi = SDFAT_SB(sb);
struct sdfat_inode_info *info;
struct hlist_head *head = sbi->inode_hashtable + sdfat_hash(i_pos);
@@ -602,10 +643,10 @@ static struct inode *sdfat_iget(struct super_block *sb, loff_t i_pos) {
spin_unlock(&sbi->inode_hash_lock);
return inode;
}
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) */
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0) */
static inline int __is_sb_dirty(struct super_block *sb)
{
- return sb->s_dirt;
+ return sb->s_dirt;
}
static inline void __set_sb_clean(struct super_block *sb)
@@ -615,7 +656,8 @@ static inline void __set_sb_clean(struct super_block *sb)
static void setup_sdfat_sync_super_wq(struct super_block *sb)
{
- struct sdfat_sb_info* sbi = SDFAT_SB(sb);
+ struct sdfat_sb_info *sbi = SDFAT_SB(sb);
+
sbi->host_sb = sb;
}
@@ -634,7 +676,7 @@ static int sdfat_revalidate(struct dentry *dentry, struct nameidata *nd)
{
if (nd && nd->flags & LOOKUP_RCU)
return -ECHILD;
-
+
return __sdfat_revalidate(dentry);
}
@@ -647,7 +689,8 @@ static int sdfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
}
-static struct inode *sdfat_iget(struct super_block *sb, loff_t i_pos) {
+static struct inode *sdfat_iget(struct super_block *sb, loff_t i_pos)
+{
struct sdfat_sb_info *sbi = SDFAT_SB(sb);
struct sdfat_inode_info *info;
struct hlist_node *node;
@@ -667,27 +710,27 @@ static struct inode *sdfat_iget(struct super_block *sb, loff_t i_pos) {
spin_unlock(&sbi->inode_hash_lock);
return inode;
}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) */
+#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
static struct dentry *sdfat_lookup(struct inode *dir, struct dentry *dentry,
unsigned int flags)
{
return __sdfat_lookup(dir, dentry);
}
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) */
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) */
static struct dentry *sdfat_lookup(struct inode *dir, struct dentry *dentry,
struct nameidata *nd)
{
return __sdfat_lookup(dir, dentry);
}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) */
+#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
/* NOTHING NOW */
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) */
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) */
#define GLOBAL_ROOT_UID (0)
#define GLOBAL_ROOT_GID (0)
@@ -720,21 +763,21 @@ static inline gid_t make_kgid(struct user_namespace *from, gid_t gid)
{
return gid;
}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) */
+#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
-static struct dentry* __d_make_root(struct inode *root_inode)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+static struct dentry *__d_make_root(struct inode *root_inode)
{
return d_make_root(root_inode);
}
static void __sdfat_do_truncate(struct inode *inode, loff_t old, loff_t new)
{
- down_write(&SDFAT_I(inode)->truncate_lock);
- truncate_setsize(inode, new);
- sdfat_truncate(inode, old);
- up_write(&SDFAT_I(inode)->truncate_lock);
+ down_write(&SDFAT_I(inode)->truncate_lock);
+ truncate_setsize(inode, new);
+ sdfat_truncate(inode, old);
+ up_write(&SDFAT_I(inode)->truncate_lock);
}
static sector_t sdfat_aop_bmap(struct address_space *mapping, sector_t block)
@@ -757,13 +800,13 @@ static int sdfat_show_options(struct seq_file *m, struct dentry *root)
{
return __sdfat_show_options(m, root->d_sb);
}
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) */
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */
static inline void set_nlink(struct inode *inode, unsigned int nlink)
{
inode->i_nlink = nlink;
}
-static struct dentry* __d_make_root(struct inode *root_inode)
+static struct dentry *__d_make_root(struct inode *root_inode)
{
return d_alloc_root(root_inode);
}
@@ -794,10 +837,10 @@ static int sdfat_show_options(struct seq_file *m, struct vfsmount *mnt)
{
return __sdfat_show_options(m, mnt->mnt_sb);
}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) */
+#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
#define __sdfat_generic_file_fsync(filp, start, end, datasync) \
generic_file_fsync(filp, start, end, datasync)
@@ -805,17 +848,97 @@ static int sdfat_file_fsync(struct file *filp, loff_t start, loff_t end, int dat
{
return __sdfat_file_fsync(filp, start, end, datasync);
}
-#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) */
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) */
#define __sdfat_generic_file_fsync(filp, start, end, datasync) \
generic_file_fsync(filp, datasync)
static int sdfat_file_fsync(struct file *filp, int datasync)
{
return __sdfat_file_fsync(filp, 0, 0, datasync);
}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) */
+#endif
+
+/*************************************************************************
+ * MORE FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY
+ *************************************************************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)
+static int sdfat_cmp(const struct dentry *dentry,
+ unsigned int len, const char *str, const struct qstr *name)
+{
+ return __sdfat_cmp(dentry, len, str, name);
+}
+
+static int sdfat_cmpi(const struct dentry *dentry,
+ unsigned int len, const char *str, const struct qstr *name)
+{
+ return __sdfat_cmpi(dentry, len, str, name);
+}
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
+static int sdfat_cmp(const struct dentry *parent, const struct dentry *dentry,
+ unsigned int len, const char *str, const struct qstr *name)
+{
+ return __sdfat_cmp(dentry, len, str, name);
+}
+
+static int sdfat_cmpi(const struct dentry *parent, const struct dentry *dentry,
+ unsigned int len, const char *str, const struct qstr *name)
+{
+ return __sdfat_cmpi(dentry, len, str, name);
+}
+#else
+static int sdfat_cmp(const struct dentry *parent, const struct inode *pinode,
+ const struct dentry *dentry, const struct inode *inode,
+ unsigned int len, const char *str, const struct qstr *name)
+{
+ return __sdfat_cmp(dentry, len, str, name);
+}
+
+static int sdfat_cmpi(const struct dentry *parent, const struct inode *pinode,
+ const struct dentry *dentry, const struct inode *inode,
+ unsigned int len, const char *str, const struct qstr *name)
+{
+ return __sdfat_cmpi(dentry, len, str, name);
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+static const char *sdfat_follow_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done)
+{
+ struct sdfat_inode_info *ei = SDFAT_I(inode);
+
+ return (char *)(ei->target);
+}
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
+static const char *sdfat_follow_link(struct dentry *dentry, void **cookie)
+{
+ struct sdfat_inode_info *ei = SDFAT_I(dentry->d_inode);
+
+ return *cookie = (char *)(ei->target);
+}
+#else
+static void *sdfat_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+ struct sdfat_inode_info *ei = SDFAT_I(dentry->d_inode);
+
+ nd_set_link(nd, (char *)(ei->target));
+ return NULL;
+}
+#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
+static ssize_t sdfat_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
+{
+ struct file *file = iocb->ki_filp;
+ struct address_space *mapping = file->f_mapping;
+ struct inode *inode = mapping->host;
+ size_t count = iov_iter_count(iter);
+ int rw = iov_iter_rw(iter);
+ loff_t offset = iocb->ki_pos;
+
+ return __sdfat_direct_IO(rw, iocb, inode,
+ (void *)iter, offset, count, 0 /* UNUSED */);
+}
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
static ssize_t sdfat_direct_IO(struct kiocb *iocb,
struct iov_iter *iter,
loff_t offset)
@@ -826,9 +949,10 @@ static ssize_t sdfat_direct_IO(struct kiocb *iocb,
size_t count = iov_iter_count(iter);
int rw = iov_iter_rw(iter);
- return __sdfat_direct_IO(rw, iocb, inode, (void*)iter, offset, count);
+ return __sdfat_direct_IO(rw, iocb, inode,
+ (void *)iter, offset, count, 0 /* UNUSED */);
}
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
static ssize_t sdfat_direct_IO(int rw, struct kiocb *iocb,
struct iov_iter *iter,
loff_t offset)
@@ -838,7 +962,8 @@ static ssize_t sdfat_direct_IO(int rw, struct kiocb *iocb,
struct inode *inode = mapping->host;
size_t count = iov_iter_count(iter);
- return __sdfat_direct_IO(rw, iocb, inode, (void*)iter, offset, count);
+ return __sdfat_direct_IO(rw, iocb, inode,
+ (void *)iter, offset, count, 0 /* UNUSED */);
}
#else
static ssize_t sdfat_direct_IO(int rw, struct kiocb *iocb,
@@ -849,35 +974,47 @@ static ssize_t sdfat_direct_IO(int rw, struct kiocb *iocb,
struct inode *inode = mapping->host;
size_t count = iov_length(iov, nr_segs);
- return __sdfat_direct_IO(rw, iocb, inode, (void*)iov, offset, count);
+ return __sdfat_direct_IO(rw, iocb, inode,
+ (void *)iov, offset, count, nr_segs);
}
#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
+static inline ssize_t __sdfat_blkdev_direct_IO(int unused, struct kiocb *iocb,
+ struct inode *inode, void *iov_u, loff_t unused_1,
+ unsigned long nr_segs)
+{
+ struct iov_iter *iter = (struct iov_iter *)iov_u;
+
+ return blockdev_direct_IO(iocb, inode, iter, sdfat_get_block);
+}
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
static inline ssize_t __sdfat_blkdev_direct_IO(int unused, struct kiocb *iocb,
struct inode *inode, void *iov_u, loff_t offset,
unsigned long nr_segs)
{
struct iov_iter *iter = (struct iov_iter *)iov_u;
- return blockdev_direct_IO(iocb, inode, iter,
- offset, sdfat_get_block);
+
+ return blockdev_direct_IO(iocb, inode, iter, offset, sdfat_get_block);
}
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
static inline ssize_t __sdfat_blkdev_direct_IO(int rw, struct kiocb *iocb,
struct inode *inode, void *iov_u, loff_t offset,
unsigned long nr_segs)
{
struct iov_iter *iter = (struct iov_iter *)iov_u;
- return blockdev_direct_IO(rw, iocb, inode, iter,
+
+ return blockdev_direct_IO(rw, iocb, inode, iter,
offset, sdfat_get_block);
}
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
static inline ssize_t __sdfat_blkdev_direct_IO(int rw, struct kiocb *iocb,
struct inode *inode, void *iov_u, loff_t offset,
unsigned long nr_segs)
{
const struct iovec *iov = (const struct iovec *)iov_u;
+
return blockdev_direct_IO(rw, iocb, inode, iov,
offset, nr_segs, sdfat_get_block);
}
@@ -887,27 +1024,28 @@ static inline ssize_t __sdfat_blkdev_direct_IO(int rw, struct kiocb *iocb,
unsigned long nr_segs)
{
const struct iovec *iov = (const struct iovec *)iov_u;
- return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
+
+ return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
offset, nr_segs, sdfat_get_block, NULL);
}
#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,00)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
static int sdfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
- bool excl)
+ bool excl)
{
return __sdfat_create(dir, dentry);
}
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
static int sdfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
- struct nameidata *nd)
+ struct nameidata *nd)
{
return __sdfat_create(dir, dentry);
}
#else
static int sdfat_create(struct inode *dir, struct dentry *dentry, int mode,
- struct nameidata *nd)
+ struct nameidata *nd)
{
return __sdfat_create(dir, dentry);
}
@@ -929,7 +1067,7 @@ static inline void __unlock_super(struct super_block *sb)
int time = ((jiffies - __lock_jiffies) * 1000 / HZ);
/* FIXME : error message should be modified */
if (time > 10)
- EMSG("lock_super in %s (%d ms) \n", __func__, time);
+ EMSG("lock_super in %s (%d ms)\n", __func__, time);
unlock_super(sb);
}
@@ -956,7 +1094,7 @@ static inline loff_t sdfat_make_i_pos(FILE_ID_T *fid)
/*======================================================================*/
/* Directory Entry Name Buffer Operations */
/*======================================================================*/
-static void sdfat_init_namebuf(DENTRY_NAMEBUF_T* nb)
+static void sdfat_init_namebuf(DENTRY_NAMEBUF_T *nb)
{
nb->lfn = NULL;
nb->sfn = NULL;
@@ -964,7 +1102,7 @@ static void sdfat_init_namebuf(DENTRY_NAMEBUF_T* nb)
nb->sfnbuf_len = 0;
}
-static int sdfat_alloc_namebuf(DENTRY_NAMEBUF_T* nb)
+static int sdfat_alloc_namebuf(DENTRY_NAMEBUF_T *nb)
{
nb->lfn = __getname();
if (!nb->lfn)
@@ -975,7 +1113,7 @@ static int sdfat_alloc_namebuf(DENTRY_NAMEBUF_T* nb)
return 0;
}
-static void sdfat_free_namebuf(DENTRY_NAMEBUF_T* nb)
+static void sdfat_free_namebuf(DENTRY_NAMEBUF_T *nb)
{
if (!nb->lfn)
return;
@@ -1024,6 +1162,7 @@ static inline int __check_dstate_locked(struct dentry *dentry)
static int __sdfat_revalidate_common(struct dentry *dentry)
{
int ret = 1;
+
spin_lock(&dentry->d_lock);
if ((!dentry->d_inode) && (!__check_dstate_locked(dentry) &&
(dentry->d_time != dentry->d_parent->d_inode->i_version))) {
@@ -1095,7 +1234,9 @@ static unsigned int sdfat_striptail_len(const struct qstr *qstr)
*/
static int __sdfat_d_hash(const struct dentry *dentry, struct qstr *qstr)
{
- qstr->hash = full_name_hash(qstr->name, sdfat_striptail_len(qstr));
+ unsigned int len = sdfat_striptail_len(qstr);
+
+ qstr->hash = __sdfat_full_name_hash(dentry, qstr->name, len);
return 0;
}
@@ -1115,7 +1256,7 @@ static int __sdfat_d_hashi(const struct dentry *dentry, struct qstr *qstr)
name = qstr->name;
len = sdfat_striptail_len(qstr);
- hash = init_name_hash();
+ hash = __sdfat_init_name_hash(dentry);
while (len--)
hash = partial_name_hash(nls_tolower(t, *name++), hash);
qstr->hash = end_name_hash(hash);
@@ -1126,8 +1267,8 @@ static int __sdfat_d_hashi(const struct dentry *dentry, struct qstr *qstr)
/*
* Case sensitive compare of two sdfat names.
*/
-static int __sdfat_cmp(const struct dentry *parent, const struct dentry *dentry,
- unsigned int len, const char *str, const struct qstr *name)
+static int __sdfat_cmp(const struct dentry *dentry, unsigned int len,
+ const char *str, const struct qstr *name)
{
unsigned int alen, blen;
@@ -1144,10 +1285,10 @@ static int __sdfat_cmp(const struct dentry *parent, const struct dentry *dentry,
/*
* Case insensitive compare of two sdfat names.
*/
-static int __sdfat_cmpi(const struct dentry *parent, const struct dentry *dentry,
- unsigned int len, const char *str, const struct qstr *name)
+static int __sdfat_cmpi(const struct dentry *dentry, unsigned int len,
+ const char *str, const struct qstr *name)
{
- struct nls_table *t = SDFAT_SB(parent->d_sb)->nls_io;
+ struct nls_table *t = SDFAT_SB(dentry->d_sb)->nls_io;
unsigned int alen, blen;
/* A filename cannot end in '.' or we treat it like it has none */
@@ -1234,7 +1375,7 @@ static void defrag_cleanup_reqs(INOUT struct super_block *sb, IN int error)
* @return 0 on success, -errno otherwise
* @param inode inode
* @param chunk given chunk
- * @remark protected by i_mutex and super_lock
+ * @remark protected by inode_lock and super_lock
*/
static int
defrag_validate_pages(
@@ -1249,14 +1390,15 @@ defrag_validate_pages(
i_size = i_size_read(inode);
page_off = chunk->f_clus * PAGES_PER_CLUS(sb);
- page_nr = (i_size / PAGE_SIZE) + ((i_size % PAGE_SIZE)? 1 : 0);
- if ( (i_size <= 0) || (page_nr <= 0) ) {
+ page_nr = (i_size / PAGE_SIZE) + ((i_size % PAGE_SIZE) ? 1 : 0);
+ if ((i_size <= 0) || (page_nr <= 0)) {
dfr_err("inode %p, i_size %d, page_nr %d", inode, i_size, page_nr);
return -EINVAL;
}
/* Get victim pages
- * and check its dirty/writeback/mapped state */
+ * and check its dirty/writeback/mapped state
+ */
for (i = 0;
i < min((int)(page_nr - page_off), (int)(chunk->nr_clus * PAGES_PER_CLUS(sb)));
i++) {
@@ -1274,16 +1416,19 @@ defrag_validate_pages(
}
sbi->dfr_pagep[buf_i++] = page;
- if (PageError(page) || !PageUptodate(page) || PageDirty(page) || PageWriteback(page) || page_mapped(page)) {
- dfr_debug("page %p, err %d, uptodate %d, dirty %d, wb %d, mapped %d",
- page, PageError(page), PageUptodate(page), PageDirty(page),
- PageWriteback(page), page_mapped(page));
+ if (PageError(page) || !PageUptodate(page) || PageDirty(page) ||
+ PageWriteback(page) || page_mapped(page)) {
+ dfr_debug("page %p, err %d, uptodate %d, "
+ "dirty %d, wb %d, mapped %d",
+ page, PageError(page), PageUptodate(page),
+ PageDirty(page), PageWriteback(page),
+ page_mapped(page));
err = -EINVAL;
goto error;
}
- set_bit( (page->index & (PAGES_PER_CLUS(sb) - 1)),
- (volatile unsigned long *)&(sbi->dfr_page_wb[chunk->new_idx + i/PAGES_PER_CLUS(sb)]) );
+ set_bit((page->index & (PAGES_PER_CLUS(sb) - 1)),
+ (volatile unsigned long *)&(sbi->dfr_page_wb[chunk->new_idx + i / PAGES_PER_CLUS(sb)]));
page = NULL;
}
@@ -1291,9 +1436,8 @@ defrag_validate_pages(
/**
* All pages in the chunks are valid.
*/
-
- i_size -= (chunk->f_clus * (sbi->fsi.cluster_size));
- BUG_ON( ((i_size/PAGE_SIZE) + ((i_size % PAGE_SIZE)? 1 : 0)) != (page_nr - page_off) );
+ i_size -= (chunk->f_clus * (sbi->fsi.cluster_size));
+ BUG_ON(((i_size / PAGE_SIZE) + ((i_size % PAGE_SIZE) ? 1 : 0)) != (page_nr - page_off));
for (i = 0; i < buf_i; i++) {
struct buffer_head *bh = NULL, *head = NULL;
@@ -1314,7 +1458,7 @@ defrag_validate_pages(
bh = head = page_buffers(page);
BUG_ON(!bh && !i_size);
do {
- if ( (bh_idx >= 1) && (bh_idx >= (i_size >> inode->i_blkbits)) ) {
+ if ((bh_idx >= 1) && (bh_idx >= (i_size >> inode->i_blkbits))) {
clear_buffer_dirty(bh);
} else {
if (PageUptodate(page))
@@ -1392,14 +1536,14 @@ defrag_validate_reqs(
i, inode, chunk->i_pos, chunk->f_clus, chunk->d_clus,
chunk->nr_clus, chunk->prev_clus, chunk->next_clus);
/**
- * Lock ordering: i_mutex -> lock_super
+ * Lock ordering: inode_lock -> lock_super
*/
- mutex_lock(&inode->i_mutex);
+ inode_lock(inode);
__lock_super(sb);
/* Check if enough buffers exist for chunk->new_idx */
- if ( (sbi->dfr_new_idx + chunk->nr_clus) >= (PAGE_SIZE/sizeof(int)) ) {
- dfr_err("dfr_new_idx %d, chunk->nr_clus %d",
+ if ((sbi->dfr_new_idx + chunk->nr_clus) >= (PAGE_SIZE / sizeof(int))) {
+ dfr_err("dfr_new_idx %d, chunk->nr_clus %d",
sbi->dfr_new_idx, chunk->nr_clus);
err = -ENOSPC;
goto unlock;
@@ -1460,7 +1604,7 @@ unlock:
}
iput(inode);
__unlock_super(sb);
- mutex_unlock(&inode->i_mutex);
+ inode_unlock(inode);
}
/* Return error if all chunks are invalid */
@@ -1547,8 +1691,9 @@ sdfat_ioctl_defrag_req(
ERR_HANDLE(err);
/* If FS busy, cancel defrag */
- if ( !(head.mode == DFR_MODE_TEST) ) {
+ if (!(head.mode == DFR_MODE_TEST)) {
int reserved_clus = 0, queued_pages = 0;
+
err = defrag_check_fs_busy(sb, &reserved_clus, &queued_pages);
if (err) {
dfr_debug("FS busy, cancel defrag (reserved_clus %d, queued_pages %d)",
@@ -1563,8 +1708,8 @@ sdfat_ioctl_defrag_req(
ERR_HANDLE2(!len, err, -EINVAL);
dfr_debug("IOC_DFR_REQ started (mode %d, nr_req %d)", head.mode, len - 1);
- if ( get_order(len * sizeof(struct defrag_chunk_info)) > MAX_ORDER) {
- dfr_debug("len %d, sizeof(struct defrag_chunk_info) %d, MAX_ORDER %d",
+ if (get_order(len * sizeof(struct defrag_chunk_info)) > MAX_ORDER) {
+ dfr_debug("len %u, sizeof(struct defrag_chunk_info) %lu, MAX_ORDER %d",
len, sizeof(struct defrag_chunk_info), MAX_ORDER);
err = -EINVAL;
goto error;
@@ -1702,7 +1847,7 @@ sdfat_ioctl_defrag_trav(
* Check args.
* ROOT directory has i_pos = 0 and start_clus = 0 .
*/
- if ( !(header->type & DFR_TRAV_TYPE_HEADER) ) {
+ if (!(header->type & DFR_TRAV_TYPE_HEADER)) {
err = -EINVAL;
dfr_debug("type %d, i_pos %08llx, start_clus %08x",
header->type, header->i_pos, header->start_clus);
@@ -1710,7 +1855,7 @@ sdfat_ioctl_defrag_trav(
}
/* If FS busy, cancel defrag */
- if ( !(header->type & DFR_TRAV_TYPE_TEST) ) {
+ if (!(header->type & DFR_TRAV_TYPE_TEST)) {
unsigned int reserved_clus = 0, queued_pages = 0;
err = defrag_check_fs_busy(sb, &reserved_clus, &queued_pages);
@@ -1723,11 +1868,11 @@ sdfat_ioctl_defrag_trav(
}
/* Scan given directory and gather info */
- mutex_lock(&inode->i_mutex);
+ inode_lock(inode);
__lock_super(sb);
err = fsapi_dfr_scan_dir(sb, (void *)args);
__unlock_super(sb);
- mutex_unlock(&inode->i_mutex);
+ inode_unlock(inode);
ERR_HANDLE(err);
/* Copy the result to user */
@@ -1772,7 +1917,7 @@ error:
#endif /* CONFIG_SDFAT_DFR */
-static inline int __do_dfr_map_cluster(struct inode *inode, u32 clu_offset, unsigned int* clus_ptr)
+static inline int __do_dfr_map_cluster(struct inode *inode, u32 clu_offset, unsigned int *clus_ptr)
{
#ifdef CONFIG_SDFAT_DFR
return fsapi_dfr_map_clus(inode, clu_offset, clus_ptr);
@@ -1786,8 +1931,8 @@ static inline int __check_dfr_on(struct inode *inode, loff_t start, loff_t end,
#ifdef CONFIG_SDFAT_DFR
struct defrag_info *ino_dfr = &(SDFAT_I(inode)->dfr_info);
- if ( (atomic_read(&ino_dfr->stat) == DFR_INO_STAT_REQ) &&
- fsapi_dfr_check_dfr_on(inode, start, end, 0, fname) )
+ if ((atomic_read(&ino_dfr->stat) == DFR_INO_STAT_REQ) &&
+ fsapi_dfr_check_dfr_on(inode, start, end, 0, fname))
return 1;
#endif
return 0;
@@ -1808,6 +1953,7 @@ static inline int __dfr_writepage_end_io(struct page *page)
{
#ifdef CONFIG_SDFAT_DFR
struct defrag_info *ino_dfr = &(SDFAT_I(page->mapping->host)->dfr_info);
+
if (atomic_read(&ino_dfr->stat) == DFR_INO_STAT_REQ)
fsapi_dfr_writepage_endio(page);
#endif
@@ -1848,7 +1994,7 @@ static inline int __alloc_dfr_mem_if_required(struct super_block *sb)
return -ENOMEM;
}
- sbi->dfr_pagep = alloc_pages_exact( sizeof(struct page *) *
+ sbi->dfr_pagep = alloc_pages_exact(sizeof(struct page *) *
PAGES_PER_AU(sb), GFP_KERNEL | __GFP_ZERO);
if (!sbi->dfr_pagep) {
dfr_debug("error %d", -ENOMEM);
@@ -1867,25 +2013,24 @@ static void __free_dfr_mem_if_required(struct super_block *sb)
free_pages_exact(sbi->dfr_pagep, sizeof(struct page *) * PAGES_PER_AU(sb));
sbi->dfr_pagep = NULL;
}
- if (sbi->dfr_page_wb) {
- kfree(sbi->dfr_page_wb);
- sbi->dfr_page_wb = NULL;
- }
- if (sbi->dfr_new_clus) {
- kfree(sbi->dfr_new_clus);
- sbi->dfr_new_clus = NULL;
- }
+
+ /* thanks for kfree */
+ kfree(sbi->dfr_page_wb);
+ sbi->dfr_page_wb = NULL;
+
+ kfree(sbi->dfr_new_clus);
+ sbi->dfr_new_clus = NULL;
#endif
}
-static int sdfat_file_mmap( struct file *file, struct vm_area_struct *vm_struct)
+static int sdfat_file_mmap(struct file *file, struct vm_area_struct *vm_struct)
{
__cancel_dfr_work(file->f_mapping->host,
(loff_t)vm_struct->vm_start,
(loff_t)(vm_struct->vm_end - 1),
__func__);
-
+
return generic_file_mmap(file, vm_struct);
}
@@ -1917,7 +2062,7 @@ static int sdfat_dfr_ioctl(struct inode *inode, struct file *filp,
}
/* Check if SB's defrag option enabled */
- if ( !(SDFAT_SB(sb)->options.defrag) ) {
+ if (!(SDFAT_SB(sb)->options.defrag)) {
dfr_err("Defrag not supported, sbi->options.defrag %d", SDFAT_SB(sb)->options.defrag);
__unlock_super(sb);
return -EPERM;
@@ -1949,7 +2094,7 @@ static int sdfat_dfr_ioctl(struct inode *inode, struct file *filp,
}
/* Check if SB's defrag option enabled */
- if ( !(SDFAT_SB(sb)->options.defrag) ) {
+ if (!(SDFAT_SB(sb)->options.defrag)) {
dfr_err("Defrag not supported, sbi->options.defrag %d", SDFAT_SB(sb)->options.defrag);
__unlock_super(sb);
return -EPERM;
@@ -1965,7 +2110,7 @@ static int sdfat_dfr_ioctl(struct inode *inode, struct file *filp,
__lock_super(sb);
- /* Check if FS_ERROR occured */
+ /* Check if FS_ERROR occurred */
if (sb->s_flags & MS_RDONLY) {
dfr_err("RDONLY partition (err %d)", -EPERM);
__unlock_super(sb);
@@ -1981,7 +2126,7 @@ static int sdfat_dfr_ioctl(struct inode *inode, struct file *filp,
}
/* Check if SB's defrag option enabled */
- if ( !(SDFAT_SB(sb)->options.defrag) ) {
+ if (!(SDFAT_SB(sb)->options.defrag)) {
dfr_err("Defrag not supported, sbi->options.defrag %d", SDFAT_SB(sb)->options.defrag);
__unlock_super(sb);
return -EPERM;
@@ -2041,10 +2186,10 @@ static int sdfat_dbg_ioctl(struct inode *inode, struct file *filp,
__unlock_super(sb);
return 0;
case SDFAT_IOCTL_PANIC:
- panic("ioctl panic for test");
+ panic("ioctl panic for test");
/* COULD NOT REACH HEAR */
- return 0;
+ return 0;
}
#endif /* CONFIG_SDFAT_DBG_IOCTL */
return -ENOTTY;
@@ -2073,9 +2218,9 @@ static void __sdfat_writepage_end_io(struct bio *bio, int err)
struct super_block *sb = page->mapping->host->i_sb;
ASSERT(bio->bi_vcnt == 1); /* Single page endio */
- ASSERT(bio->bi_rw & 1); /* Write */
+ ASSERT(bio_data_dir(bio)); /* Write */
- if (err){
+ if (err) {
SetPageError(page);
mapping_set_error(page->mapping, err);
}
@@ -2092,8 +2237,9 @@ static void __sdfat_writepage_end_io(struct bio *bio, int err)
sbi->stat_n_bdev_pages_written++;
/* 4 MB = 1024 pages => 0.4 sec (approx.)
- 32 KB = 64 pages => 0.025 sec
- Min. average latency b/w msgs. ~= 0.025 sec */
+ * 32 KB = 64 pages => 0.025 sec
+ * Min. average latency b/w msgs. ~= 0.025 sec
+ */
if ((sbi->stat_n_pages_written & 63) == 0) {
DMSG("STAT:%u, %u, %u, %u (Sector #: %u)\n",
sbi->stat_n_pages_added, sbi->stat_n_pages_written,
@@ -2110,11 +2256,13 @@ static void __sdfat_writepage_end_io(struct bio *bio, int err)
atomic_dec(&SDFAT_SB(sb)->stat_n_pages_queued);
}
+
static int __support_write_inode_sync(struct super_block *sb)
{
#ifdef CONFIG_SDFAT_SUPPORT_DIR_SYNC
#ifdef CONFIG_SDFAT_DELAYED_META_DIRTY
struct sdfat_sb_info *sbi = SDFAT_SB(sb);
+
if (sbi->fsi.vol_type != EXFAT)
return 0;
#endif
@@ -2132,7 +2280,7 @@ static int __sdfat_file_fsync(struct file *filp, loff_t start, loff_t end, int d
res = __sdfat_generic_file_fsync(filp, start, end, datasync);
- if(!__support_write_inode_sync(sb))
+ if (!__support_write_inode_sync(sb))
err = fsapi_sync_fs(sb, 1);
return res ? res : err;
@@ -2142,9 +2290,9 @@ static int __sdfat_file_fsync(struct file *filp, loff_t start, loff_t end, int d
static const struct file_operations sdfat_dir_operations = {
.llseek = generic_file_llseek,
.read = generic_read_dir,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,00)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
.iterate = sdfat_iterate,
-#else
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */
.readdir = sdfat_readdir,
#endif
.fsync = sdfat_file_fsync,
@@ -2194,6 +2342,8 @@ out:
__unlock_d_revalidate(dentry);
__unlock_super(sb);
TMSG("%s exited with err(%d)\n", __func__, err);
+ if (!err)
+ sdfat_statistics_set_create(fid.flags);
return err;
}
@@ -2217,7 +2367,7 @@ static int sdfat_d_anon_disconn(struct dentry *dentry)
return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED);
}
-static struct dentry* __sdfat_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *__sdfat_lookup(struct inode *dir, struct dentry *dentry)
{
struct super_block *sb = dir->i_sb;
struct inode *inode;
@@ -2247,7 +2397,7 @@ static struct dentry* __sdfat_lookup(struct inode *dir, struct dentry *dentry)
}
i_mode = inode->i_mode;
- if (S_ISLNK(i_mode)) {
+ if (S_ISLNK(i_mode) && !SDFAT_I(inode)->target) {
SDFAT_I(inode)->target = kmalloc((i_size_read(inode)+1), GFP_KERNEL);
if (!SDFAT_I(inode)->target) {
err = -ENOMEM;
@@ -2292,9 +2442,8 @@ static struct dentry* __sdfat_lookup(struct inode *dir, struct dentry *dentry)
__unlock_super(sb);
TMSG("%s exited\n", __func__);
return alias;
- } else {
- dput(alias);
}
+ dput(alias);
out:
/* initialize d_time even though it is positive dentry */
dentry->d_time = dir->i_version;
@@ -2365,7 +2514,7 @@ static int sdfat_symlink(struct inode *dir, struct dentry *dentry, const char *t
/* symlink option check */
if (!SDFAT_SB(sb)->options.symlink)
- return -ENOTSUPP;
+ return -ENOTSUPP;
__lock_super(sb);
@@ -2464,6 +2613,8 @@ out:
__unlock_d_revalidate(dentry);
__unlock_super(sb);
TMSG("%s exited with err(%d)\n", __func__, err);
+ if (!err)
+ sdfat_statistics_set_mkdir(fid.flags);
return err;
}
@@ -2508,8 +2659,8 @@ out:
return err;
}
-static int sdfat_rename(struct inode *old_dir, struct dentry *old_dentry,
- struct inode *new_dir, struct dentry *new_dentry)
+static int __sdfat_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
{
struct inode *old_inode, *new_inode;
struct super_block *sb = old_dir->i_sb;
@@ -2554,7 +2705,8 @@ static int sdfat_rename(struct inode *old_dir, struct dentry *old_dentry,
if ((S_ISDIR(old_inode->i_mode)) && (old_dir != new_dir)) {
drop_nlink(old_dir);
- if (!new_inode) inc_nlink(new_dir);
+ if (!new_inode)
+ inc_nlink(new_dir);
}
old_dir->i_version++;
@@ -2606,7 +2758,7 @@ static int sdfat_cont_expand(struct inode *inode, loff_t size)
if (!IS_SYNC(inode))
return 0;
-
+
err = filemap_fdatawrite_range(mapping, start, start + count - 1);
err2 = sync_mapping_buffers(mapping);
err = (err)?(err):(err2);
@@ -2648,7 +2800,7 @@ static int sdfat_sanitize_mode(const struct sdfat_sb_info *sbi,
perm = *mode_ptr & ~(S_IFMT | mask);
/* Of the r and x bits, all (subject to umask) must be present.*/
- if ((perm & (S_IRUGO | S_IXUGO)) != (i_mode & (S_IRUGO|S_IXUGO)))
+ if ((perm & (S_IRUGO | S_IXUGO)) != (i_mode & (S_IRUGO | S_IXUGO)))
return -EPERM;
if (sdfat_mode_can_hold_ro(inode)) {
@@ -2685,18 +2837,17 @@ static int sdfat_setattr(struct dentry *dentry, struct iattr *attr)
attr->ia_valid &= ~ATTR_SIZE;
}
+ /* Check for setting the inode time. */
ia_valid = attr->ia_valid;
-
if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET))
&& sdfat_allow_set_time(sbi, inode)) {
attr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET);
}
- error = inode_change_ok(inode, attr);
+ error = setattr_prepare(dentry, attr);
attr->ia_valid = ia_valid;
- if (error) {
+ if (error)
return error;
- }
if (((attr->ia_valid & ATTR_UID) &&
(!uid_eq(attr->ia_uid, sbi->options.fs_uid))) ||
@@ -2723,7 +2874,7 @@ static int sdfat_setattr(struct dentry *dentry, struct iattr *attr)
old_size = i_size_read(inode);
/* TO CHECK evicting directory works correctly */
- MMSG("%s: inode(%p) truncate size (%llu->%llu)\n", __func__,
+ MMSG("%s: inode(%p) truncate size (%llu->%llu)\n", __func__,
inode, (u64)old_size, (u64)attr->ia_size);
__sdfat_do_truncate(inode, old_size, attr->ia_size);
}
@@ -2759,11 +2910,13 @@ static const struct inode_operations sdfat_dir_inode_operations = {
.setattr = sdfat_setattr,
.getattr = sdfat_getattr,
#ifdef CONFIG_SDFAT_VIRTUAL_XATTR
+ .listxattr = sdfat_listxattr,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)
.setxattr = sdfat_setxattr,
.getxattr = sdfat_getxattr,
- .listxattr = sdfat_listxattr,
.removexattr = sdfat_removexattr,
#endif
+#endif
};
/*======================================================================*/
@@ -2771,13 +2924,19 @@ static const struct inode_operations sdfat_dir_inode_operations = {
/*======================================================================*/
static const struct inode_operations sdfat_symlink_inode_operations = {
.readlink = generic_readlink,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
+ .get_link = sdfat_follow_link,
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0) */
.follow_link = sdfat_follow_link,
+#endif
#ifdef CONFIG_SDFAT_VIRTUAL_XATTR
+ .listxattr = sdfat_listxattr,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)
.setxattr = sdfat_setxattr,
.getxattr = sdfat_getxattr,
- .listxattr = sdfat_listxattr,
.removexattr = sdfat_removexattr,
#endif
+#endif
};
static int sdfat_file_release(struct inode *inode, struct file *filp)
@@ -2796,15 +2955,15 @@ static int sdfat_file_release(struct inode *inode, struct file *filp)
static const struct file_operations sdfat_file_operations = {
.llseek = generic_file_llseek,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
.read_iter = generic_file_read_iter,
.write_iter = generic_file_write_iter,
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
.read = new_sync_read,
.write = new_sync_write,
.read_iter = generic_file_read_iter,
.write_iter = generic_file_write_iter,
-#else
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) */
.read = do_sync_read,
.write = do_sync_write,
.aio_read = generic_file_aio_read,
@@ -2831,13 +2990,10 @@ static void sdfat_truncate(struct inode *inode, loff_t old_size)
__lock_super(sb);
-
if (SDFAT_I(inode)->fid.start_clu == 0) {
- /*
- ?! Stange statement
- Empty start_clu != ~0 (not allocated)
- */
- /* FIXME:fata error? */
+ /* Stange statement:
+ * Empty start_clu != ~0 (not allocated)
+ */
sdfat_fs_error(sb, "tried to truncate zeroed cluster.");
goto out;
}
@@ -2855,18 +3011,17 @@ static void sdfat_truncate(struct inode *inode, loff_t old_size)
(void) sdfat_sync_inode(inode);
else
mark_inode_dirty(inode);
-
+
// FIXME: 확인 요망
// inode->i_blocks = ((SDFAT_I(inode)->i_size_ondisk + (fsi->cluster_size - 1))
- inode->i_blocks = ( (i_size_read(inode) + (fsi->cluster_size - 1))
- & ~((loff_t)fsi->cluster_size - 1) ) >> inode->i_blkbits;
-
+ inode->i_blocks = ((i_size_read(inode) + (fsi->cluster_size - 1)) &
+ ~((loff_t)fsi->cluster_size - 1)) >> inode->i_blkbits;
out:
- /*
+ /*
* This protects against truncating a file bigger than it was then
* trying to write into the hole.
*
- * comment by sh.hong:
+ * comment by sh.hong:
* This seems to mean 'intra page/block' truncate and writing.
* I couldn't find a reason to change the values prior to fsapi_truncate
* Therefore, I switched the order of operations
@@ -2879,9 +3034,9 @@ out:
aligned_size++;
}
- if (SDFAT_I(inode)->i_size_ondisk > i_size_read(inode)) {
+ if (SDFAT_I(inode)->i_size_ondisk > i_size_read(inode))
SDFAT_I(inode)->i_size_ondisk = aligned_size;
- }
+
sdfat_debug_check_clusters(inode);
if (SDFAT_I(inode)->i_size_aligned > i_size_read(inode))
@@ -2889,11 +3044,11 @@ out:
/* After truncation :
* 1) Delayed allocation is OFF
- * i_size = i_size_ondisk <= i_size_aligned
+ * i_size = i_size_ondisk <= i_size_aligned
* (useless size var.)
* (block-aligned)
* 2) Delayed allocation is ON
- * i_size = i_size_ondisk = i_size_aligned
+ * i_size = i_size_ondisk = i_size_aligned
* (will be block-aligned after write)
* or
* i_size_ondisk < i_size <= i_size_aligned (block_aligned)
@@ -2907,11 +3062,13 @@ static const struct inode_operations sdfat_file_inode_operations = {
.setattr = sdfat_setattr,
.getattr = sdfat_getattr,
#ifdef CONFIG_SDFAT_VIRTUAL_XATTR
+ .listxattr = sdfat_listxattr,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0)
.setxattr = sdfat_setxattr,
.getxattr = sdfat_getxattr,
- .listxattr = sdfat_listxattr,
.removexattr = sdfat_removexattr,
#endif
+#endif
};
/*======================================================================*/
@@ -2938,19 +3095,19 @@ static int sdfat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
*mapped_blocks = 0;
/* core code should handle EIO */
- /*
- if(fsi->prev_eio && BLOCK_ADDED(*create))
+#if 0
+ if (fsi->prev_eio && BLOCK_ADDED(*create))
return -EIO;
- */
+#endif
- if ( ((fsi->vol_type == FAT12) || (fsi->vol_type == FAT16)) &&
- (inode->i_ino == SDFAT_ROOT_INO) ) {
- if (sector < (fsi->dentries_in_root >>
- (sb->s_blocksize_bits-DENTRY_SIZE_BITS)) ) {
+ if (((fsi->vol_type == FAT12) || (fsi->vol_type == FAT16)) &&
+ (inode->i_ino == SDFAT_ROOT_INO)) {
+ if (sector < (fsi->dentries_in_root >>
+ (sb->s_blocksize_bits-DENTRY_SIZE_BITS))) {
*phys = sector + fsi->root_start_sector;
*mapped_blocks = 1;
}
- return 0;
+ return 0;
}
last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits;
@@ -2963,10 +3120,10 @@ static int sdfat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
SDFAT_I(inode)->fid.size = i_size_read(inode);
- if ( unlikely(__check_dfr_on(inode,
- (loff_t)((loff_t)clu_offset << fsi->cluster_size_bits),
+ if (unlikely(__check_dfr_on(inode,
+ (loff_t)((loff_t)clu_offset << fsi->cluster_size_bits),
(loff_t)((loff_t)(clu_offset + 1) << fsi->cluster_size_bits),
- __func__)) ) {
+ __func__))) {
err = __do_dfr_map_cluster(inode, clu_offset, &cluster);
} else {
if (*create & BMAP_ADD_CLUSTER)
@@ -2981,9 +3138,13 @@ static int sdfat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
return err;
}
+ /* FOR BIGDATA */
+ sdfat_statistics_set_rw(SDFAT_I(inode)->fid.flags,
+ clu_offset, *create & BMAP_ADD_CLUSTER);
+
if (!IS_CLUS_EOF(cluster)) {
/* sector offset in cluster */
- sec_offset = sector & (fsi->sect_per_clus - 1);
+ sec_offset = sector & (fsi->sect_per_clus - 1);
*phys = CLUS_TO_SECT(fsi, cluster) + sec_offset;
*mapped_blocks = fsi->sect_per_clus - sec_offset;
@@ -2998,25 +3159,22 @@ static int sdfat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
if (sector < last_block)
*create = BMAP_NOT_CREATE;
- /*
+#if 0
else if (sector >= last_block)
*create = non-zero;
- */
- /*
if (iblock <= last mapped-block)
*phys != 0
*create = BMAP_NOT_CREATE
else if (iblock <= last cluster)
*phys != 0
*create = non-zero
- */
-
+#endif
return 0;
}
static int sdfat_da_prep_block(struct inode *inode, sector_t iblock,
- struct buffer_head *bh_result, int create)
+ struct buffer_head *bh_result, int create)
{
struct super_block *sb = inode->i_sb;
struct sdfat_sb_info *sbi = SDFAT_SB(sb);
@@ -3038,7 +3196,7 @@ static int sdfat_da_prep_block(struct inode *inode, sector_t iblock,
if (err) {
if (err != -ENOSPC)
sdfat_fs_error_ratelimit(sb, "%s: failed to bmap "
- "(iblock:%u, err:%d)", __func__,
+ "(iblock:%u, err:%d)", __func__,
(u32)iblock, err);
goto unlock_ret;
}
@@ -3050,7 +3208,7 @@ static int sdfat_da_prep_block(struct inode *inode, sector_t iblock,
max_blocks = min(mapped_blocks, max_blocks);
map_bh(bh_result, sb, phys);
- BUG_ON(BLOCK_ADDED(bmap_create) && (sec_offset == 0));
+ BUG_ON(BLOCK_ADDED(bmap_create) && (sec_offset == 0));
} else if (create == 1) {
/* Not exist: new cluster needed */
@@ -3061,9 +3219,9 @@ static int sdfat_da_prep_block(struct inode *inode, sector_t iblock,
err = fsapi_reserve_clus(inode);
if (err) {
if (err != -ENOSPC)
- sdfat_fs_error_ratelimit(sb,
+ sdfat_fs_error_ratelimit(sb,
"%s: failed to bmap "
- "(iblock:%u, err:%d)", __func__,
+ "(iblock:%u, err:%d)", __func__,
(u32)iblock, err);
goto unlock_ret;
@@ -3078,11 +3236,11 @@ static int sdfat_da_prep_block(struct inode *inode, sector_t iblock,
} else {
/* get_block on non-existing addr. with create==0 */
/*
- * CHECKME:
- * i_size_aligned 보다 작으면 delay 매핑을 일단
+ * CHECKME:
+ * i_size_aligned 보다 작으면 delay 매핑을 일단
* 켜줘야되는 게 아닌가?
* - 0-fill 을 항상 하기에, FAT 에서는 문제 없음.
- * 중간에 영역이 꽉 찼으면, 디스크에 내려가지 않고는
+ * 중간에 영역이 꽉 찼으면, 디스크에 내려가지 않고는
* invalidate 될 일이 없음
*/
goto unlock_ret;
@@ -3099,18 +3257,17 @@ static int sdfat_da_prep_block(struct inode *inode, sector_t iblock,
#define num_clusters(value) ((value) ? (s32)((value - 1) >> fsi->cluster_size_bits) + 1 : 0)
/* FOR GRACEFUL ERROR HANDLING */
- if (num_clusters(SDFAT_I(inode)->i_size_aligned) !=
+ if (num_clusters(SDFAT_I(inode)->i_size_aligned) !=
num_clusters(SDFAT_I(inode)->i_size_ondisk)) {
EMSG("%s: inode(%p) invalid size (create(%d) "
"bmap_create(%d) phys(%lld) aligned(%lld) "
- "on_disk(%lld) iblock(%u) sec_off(%d))\n",
+ "on_disk(%lld) iblock(%u) sec_off(%d))\n",
__func__, inode, create, bmap_create, (s64)phys,
(s64)SDFAT_I(inode)->i_size_aligned,
(s64)SDFAT_I(inode)->i_size_ondisk,
(u32)iblock,
(s32)sec_offset);
sdfat_debug_bug_on(1);
-
}
SDFAT_I(inode)->i_size_ondisk = SDFAT_I(inode)->i_size_aligned;
}
@@ -3132,7 +3289,7 @@ static int sdfat_da_prep_block(struct inode *inode, sector_t iblock,
/* FOR GRACEFUL ERROR HANDLING */
if (i_size_read(inode) > SDFAT_I(inode)->i_size_aligned) {
sdfat_fs_error_ratelimit(sb, "%s: invalid size (inode(%p), "
- "size(%llu) > aligned(%llu)\n", __func__, inode,
+ "size(%llu) > aligned(%llu)\n", __func__, inode,
i_size_read(inode), SDFAT_I(inode)->i_size_aligned);
sdfat_debug_bug_on(1);
}
@@ -3189,38 +3346,36 @@ static int sdfat_get_block(struct inode *inode, sector_t iblock,
* create == 1 only if iblock > i_size
* (in block unit)
*/
-
+
/* 20130723 CHECK
* Truncate와 동시에 발생할 경우,
* i_size < (i_block 위치) 면서 buffer_delay()가
* 켜져있을 수 있다.
*
* 기존에 할당된 영역을 다시 쓸 뿐이므로 큰 문제
- * 없지만, 그 경우, 미리 i_size_algined 가 확장된
+ * 없지만, 그 경우, 미리 i_size_aligned 가 확장된
* 영역이어야 한다.
*/
- /* FOR GRACEFUL ERROR HANDLING :
- *
- * sdfat_debug_bug_on(buffer_delay(bh_result) && (pos > SDFAT_I(inode)->i_size_aligned));
- */
- if (buffer_delay(bh_result) &&
+ /* FOR GRACEFUL ERROR HANDLING */
+ if (buffer_delay(bh_result) &&
(pos > SDFAT_I(inode)->i_size_aligned)) {
- sdfat_fs_error(sb, "requested for bmap out of range(pos:(%llu)>i_size_aligned(%llu)\n", pos, SDFAT_I(inode)->i_size_aligned);
+ sdfat_fs_error(sb, "requested for bmap "
+ "out of range(pos:(%llu)>i_size_aligned(%llu)\n",
+ pos, SDFAT_I(inode)->i_size_aligned);
sdfat_debug_bug_on(1);
err = -EIO;
goto unlock_ret;
}
-
set_buffer_new(bh_result);
-
- /* i_size_ondisk 이 i_size_aligned 보다 먼저
- * 움직인 경우, (예: non-DA 상황)
- * 두 변수 사이의 관계 유지
+
+ /*
+ * adjust i_size_aligned if i_size_ondisk is
+ * bigger than it. (i.e. non-DA)
*/
- if (SDFAT_I(inode)->i_size_ondisk >
- SDFAT_I(inode)->i_size_aligned) {
- SDFAT_I(inode)->i_size_aligned =
+ if (SDFAT_I(inode)->i_size_ondisk >
+ SDFAT_I(inode)->i_size_aligned) {
+ SDFAT_I(inode)->i_size_aligned =
SDFAT_I(inode)->i_size_ondisk;
}
}
@@ -3230,18 +3385,18 @@ static int sdfat_get_block(struct inode *inode, sector_t iblock,
#if 0
/* Debug purpose */
- if (SDFAT_I(inode)->i_size_ondisk >
- SDFAT_I(inode)->i_size_aligned ) {
+ if (SDFAT_I(inode)->i_size_ondisk >
+ SDFAT_I(inode)->i_size_aligned) {
/* Only after truncate
- * and the two size variables should indicate
- * same i_block
+ * and the two size variables should indicate
+ * same i_block
*/
unsigned int blocksize = 1 << inode->i_blkbits;
- BUG_ON(SDFAT_I(inode)->i_size_ondisk - SDFAT_I(inode)->i_size_aligned >= blocksize);
+ BUG_ON(SDFAT_I(inode)->i_size_ondisk -
+ SDFAT_I(inode)->i_size_aligned >= blocksize);
}
#endif
}
-
map_bh(bh_result, sb, phys);
}
@@ -3254,24 +3409,27 @@ unlock_ret:
static int sdfat_readpage(struct file *file, struct page *page)
{
int ret;
+
ret = mpage_readpage(page, sdfat_get_block);
return ret;
}
static int sdfat_readpages(struct file *file, struct address_space *mapping,
- struct list_head *pages, unsigned nr_pages)
+ struct list_head *pages, unsigned int nr_pages)
{
int ret;
+
ret = mpage_readpages(mapping, pages, nr_pages, sdfat_get_block);
return ret;
}
-static inline void sdfat_submit_fullpage_bio(struct block_device *bdev, sector_t sector, unsigned int length, struct page *page)
+static inline void sdfat_submit_fullpage_bio(struct block_device *bdev,
+ sector_t sector, unsigned int length, struct page *page)
{
/* Single page bio submit */
struct bio *bio;
- BUG_ON((length > PAGE_CACHE_SIZE) || (length == 0));
+ BUG_ON((length > PAGE_SIZE) || (length == 0));
/*
* If __GFP_WAIT is set, then bio_alloc will always be able to allocate
@@ -3279,18 +3437,18 @@ static inline void sdfat_submit_fullpage_bio(struct block_device *bdev, sector_t
* must never allocate more than 1 bio at a time from this pool.
*
* #define GFP_NOIO (__GFP_WAIT)
- */
+ */
bio = bio_alloc(GFP_NOIO, 1);
bio->bi_bdev = bdev;
bio->bi_vcnt = 1;
- bio->bi_io_vec[0].bv_page = page; /* Inline vec */
- bio->bi_io_vec[0].bv_len = length; //PAGE_CACHE_SIZE;
+ bio->bi_io_vec[0].bv_page = page; /* Inline vec */
+ bio->bi_io_vec[0].bv_len = length; /* PAGE_SIZE */
bio->bi_io_vec[0].bv_offset = 0;
__sdfat_set_bio_iterate(bio, sector, length, 0, 0);
bio->bi_end_io = sdfat_writepage_end_io;
- submit_bio(WRITE, bio);
+ __sdfat_submit_bio_write(bio);
}
static int sdfat_writepage(struct page *page, struct writeback_control *wbc)
@@ -3298,45 +3456,45 @@ static int sdfat_writepage(struct page *page, struct writeback_control *wbc)
struct inode * const inode = page->mapping->host;
struct super_block *sb = inode->i_sb;
loff_t i_size = i_size_read(inode);
- const pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
- const unsigned int blocks_per_page = PAGE_CACHE_SIZE >> inode->i_blkbits;
+ const pgoff_t end_index = i_size >> PAGE_SHIFT;
+ const unsigned int blocks_per_page = PAGE_SIZE >> inode->i_blkbits;
FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
struct buffer_head *bh, *head;
sector_t block, block_0, last_phys;
int ret;
unsigned int nr_blocks_towrite = blocks_per_page;
- /* Don't distinguish 0-filled/clean block.
- * Just write back the whole page
+ /* Don't distinguish 0-filled/clean block.
+ * Just write back the whole page
*/
- if (fsi->cluster_size < PAGE_CACHE_SIZE)
+ if (fsi->cluster_size < PAGE_SIZE)
goto confused;
- if (!PageUptodate(page)){
- MMSG("%s: Not up-to-date page -> block_write_full_page\n",
+ if (!PageUptodate(page)) {
+ MMSG("%s: Not up-to-date page -> block_write_full_page\n",
__func__);
goto confused;
}
if (page->index >= end_index) {
/* last page or outside i_size */
- unsigned offset = i_size & (PAGE_CACHE_SIZE-1);
+ unsigned int offset = i_size & (PAGE_SIZE-1);
/* If a truncation is in progress */
if (page->index > end_index || !offset)
goto confused;
- /* 0-fill after i_size */
- zero_user_segment(page, offset, PAGE_CACHE_SIZE);
+ /* 0-fill after i_size */
+ zero_user_segment(page, offset, PAGE_SIZE);
}
- if (!page_has_buffers(page)){
+ if (!page_has_buffers(page)) {
MMSG("WP: No buffers -> block_write_full_page\n");
goto confused;
}
- block = (sector_t)page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
- block_0 = block; // first block
+ block = (sector_t)page->index << (PAGE_SHIFT - inode->i_blkbits);
+ block_0 = block; /* first block */
head = page_buffers(page);
bh = head;
@@ -3359,7 +3517,7 @@ static int sdfat_writepage(struct page *page, struct writeback_control *wbc)
block++;
continue;
}
-
+
if (nr_blocks_towrite != blocks_per_page)
// Dirty -> Non-dirty -> Dirty again case
goto confused;
@@ -3368,9 +3526,8 @@ static int sdfat_writepage(struct page *page, struct writeback_control *wbc)
if (!buffer_mapped(bh) || buffer_delay(bh)) {
BUG_ON(bh->b_size != (1 << (inode->i_blkbits)));
ret = sdfat_get_block(inode, block, bh, 1);
- if (ret) {
+ if (ret)
goto confused;
- }
if (buffer_new(bh)) {
clear_buffer_new(bh);
@@ -3399,7 +3556,7 @@ static int sdfat_writepage(struct page *page, struct writeback_control *wbc)
do {
clear_buffer_dirty(bh);
bh = bh->b_this_page;
- }while (bh != head);
+ } while (bh != head);
BUG_ON(PageWriteback(page));
set_page_writeback(page);
@@ -3410,10 +3567,10 @@ static int sdfat_writepage(struct page *page, struct writeback_control *wbc)
* In this case, write_begin calls get_block and get original block number
* and previous defrag will be canceled.
*/
- if ( unlikely(__check_dfr_on(inode,
+ if (unlikely(__check_dfr_on(inode,
(loff_t)(page->index << PAGE_SHIFT),
(loff_t)((page->index + 1) << PAGE_SHIFT),
- __func__)) ) {
+ __func__))) {
do {
clear_buffer_mapped(bh);
bh = bh->b_this_page;
@@ -3479,6 +3636,7 @@ static int sdfat_writepages(struct address_space *mapping,
static void sdfat_write_failed(struct address_space *mapping, loff_t to)
{
struct inode *inode = mapping->host;
+
if (to > i_size_read(inode)) {
__sdfat_truncate_pagecache(inode, to, i_size_read(inode));
sdfat_truncate(inode, SDFAT_I(inode)->i_size_aligned);
@@ -3486,51 +3644,50 @@ static void sdfat_write_failed(struct address_space *mapping, loff_t to)
}
static int __sdfat_write_begin(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned flags,
- struct page **pagep, void **fsdata,
- get_block_t *get_block,
- loff_t *bytes,
- const char *fname)
+ loff_t pos, unsigned int len,
+ unsigned int flags, struct page **pagep,
+ void **fsdata, get_block_t *get_block,
+ loff_t *bytes, const char *fname)
{
int ret;
__cancel_dfr_work(mapping->host, pos, (loff_t)(pos + len), fname);
-
+
*pagep = NULL;
ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
get_block, bytes);
if (ret < 0)
sdfat_write_failed(mapping, pos+len);
-
+
return ret;
}
static int sdfat_da_write_begin(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned flags,
- struct page **pagep, void **fsdata)
+ loff_t pos, unsigned int len, unsigned int flags,
+ struct page **pagep, void **fsdata)
{
- return __sdfat_write_begin(file, mapping, pos, len, flags,
- pagep, fsdata, sdfat_da_prep_block,
+ return __sdfat_write_begin(file, mapping, pos, len, flags,
+ pagep, fsdata, sdfat_da_prep_block,
&SDFAT_I(mapping->host)->i_size_aligned,
__func__);
}
static int sdfat_write_begin(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned flags,
- struct page **pagep, void **fsdata)
+ loff_t pos, unsigned int len, unsigned int flags,
+ struct page **pagep, void **fsdata)
{
- return __sdfat_write_begin(file, mapping, pos, len, flags,
+ return __sdfat_write_begin(file, mapping, pos, len, flags,
pagep, fsdata, sdfat_get_block,
&SDFAT_I(mapping->host)->i_size_ondisk,
__func__);
}
static int sdfat_write_end(struct file *file, struct address_space *mapping,
- loff_t pos, unsigned len, unsigned copied,
- struct page *pagep, void *fsdata)
+ loff_t pos, unsigned int len, unsigned int copied,
+ struct page *pagep, void *fsdata)
{
struct inode *inode = mapping->host;
FILE_ID_T *fid = &(SDFAT_I(inode)->fid);
@@ -3560,7 +3717,7 @@ static int sdfat_write_end(struct file *file, struct address_space *mapping,
static inline ssize_t __sdfat_direct_IO(int rw, struct kiocb *iocb,
struct inode *inode, void *iov_u, loff_t offset,
- loff_t count)
+ loff_t count, unsigned long nr_segs)
{
struct address_space *mapping = inode->i_mapping;
loff_t size = offset + count;
@@ -3584,7 +3741,7 @@ static inline ssize_t __sdfat_direct_IO(int rw, struct kiocb *iocb,
* sdFAT need to use the DIO_LOCKING for avoiding the race
* condition of sdfat_get_block() and ->truncate().
*/
- ret = __sdfat_blkdev_direct_IO(rw, iocb, inode, iov_u, offset, 0);
+ ret = __sdfat_blkdev_direct_IO(rw, iocb, inode, iov_u, offset, nr_segs);
if (ret < 0 && (rw & WRITE))
sdfat_write_failed(mapping, size);
@@ -3660,7 +3817,7 @@ static int sdfat_fill_inode(struct inode *inode, const FILE_ID_T *fid)
inode->i_gid = sbi->options.fs_gid;
inode->i_version++;
inode->i_generation = get_seconds();
-
+
if (fsapi_read_inode(inode, &info) < 0) {
MMSG("%s: failed to read stat!\n", __func__);
return -EIO;
@@ -3672,7 +3829,7 @@ static int sdfat_fill_inode(struct inode *inode, const FILE_ID_T *fid)
inode->i_op = &sdfat_dir_inode_operations;
inode->i_fop = &sdfat_dir_operations;
- set_nlink(inode,info.NumSubdirs);
+ set_nlink(inode, info.NumSubdirs);
} else if (info.Attr & ATTR_SYMLINK) { /* symbolic link */
inode->i_op = &sdfat_symlink_inode_operations;
inode->i_generation |= 1;
@@ -3710,8 +3867,8 @@ static int sdfat_fill_inode(struct inode *inode, const FILE_ID_T *fid)
sdfat_save_attr(inode, info.Attr);
- inode->i_blocks = ( (i_size_read(inode) + (fsi->cluster_size - 1))
- & ~((loff_t)fsi->cluster_size - 1) ) >> inode->i_blkbits;
+ inode->i_blocks = ((i_size_read(inode) + (fsi->cluster_size - 1))
+ & ~((loff_t)fsi->cluster_size - 1)) >> inode->i_blkbits;
sdfat_time_fat2unix(sbi, &inode->i_mtime, &info.ModifyTimestamp);
sdfat_time_fat2unix(sbi, &inode->i_ctime, &info.CreateTimestamp);
@@ -3749,17 +3906,16 @@ out:
return inode;
}
-static struct inode *sdfat_alloc_inode(struct super_block *sb) {
+static struct inode *sdfat_alloc_inode(struct super_block *sb)
+{
struct sdfat_inode_info *ei;
ei = kmem_cache_alloc(sdfat_inode_cachep, GFP_NOFS);
if (!ei)
return NULL;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
init_rwsem(&ei->truncate_lock);
#endif
-
return &ei->vfs_inode;
}
@@ -3820,7 +3976,7 @@ static void sdfat_evict_inode(struct inode *inode)
__cancel_dfr_work(inode, 0, (loff_t)old_size, __func__);
/* TO CHECK evicting directory works correctly */
- MMSG("%s: inode(%p) evict %s (size(%llu) to zero)\n",
+ MMSG("%s: inode(%p) evict %s (size(%llu) to zero)\n",
__func__, inode,
S_ISDIR(inode->i_mode) ? "directory" : "file",
(u64)old_size);
@@ -3898,9 +4054,8 @@ static void sdfat_write_super(struct super_block *sb)
__set_sb_clean(sb);
#ifdef CONFIG_SDFAT_DFR
- if (atomic_read(&(SDFAT_SB(sb)->dfr_info.stat)) == DFR_SB_STAT_VALID) {
- fsapi_dfr_update_fat_next(sb);
- }
+ if (atomic_read(&(SDFAT_SB(sb)->dfr_info.stat)) == DFR_SB_STAT_VALID)
+ fsapi_dfr_update_fat_next(sb);
#endif
/* flush delayed FAT/DIR dirty */
@@ -3914,18 +4069,16 @@ static void sdfat_write_super(struct super_block *sb)
time = jiffies;
/* Issuing bdev requests is needed
- to guarantee DIR updates in time
- whether w/ or w/o delayed DIR dirty feature.
-
- (otherwise DIR updates could be delayed for 5 + 5 secs at max.)
- */
+ * to guarantee DIR updates in time
+ * whether w/ or w/o delayed DIR dirty feature.
+ * (otherwise DIR updates could be delayed for 5 + 5 secs at max.)
+ */
sync_blockdev(sb->s_bdev);
#if (defined(CONFIG_SDFAT_DFR) && defined(CONFIG_SDFAT_DFR_DEBUG))
/* SPO test */
fsapi_dfr_spo_test(sb, DFR_SPO_FAT_NEXT, __func__);
#endif
-
MMSG("BD: sdfat_write_super (bdev_sync for %ld ms)\n",
(jiffies - time) * 1000 / HZ);
}
@@ -3935,8 +4088,9 @@ static void __dfr_update_fat_next(struct super_block *sb)
{
#ifdef CONFIG_SDFAT_DFR
struct sdfat_sb_info *sbi = SDFAT_SB(sb);
- if ( sbi->options.defrag &&
- (atomic_read(&sbi->dfr_info.stat) == DFR_SB_STAT_VALID) ) {
+
+ if (sbi->options.defrag &&
+ (atomic_read(&sbi->dfr_info.stat) == DFR_SB_STAT_VALID)) {
fsapi_dfr_update_fat_next(sb);
}
#endif
@@ -3948,11 +4102,11 @@ static void __dfr_update_fat_prev(struct super_block *sb, int wait)
struct sdfat_sb_info *sbi = SDFAT_SB(sb);
struct defrag_info *sb_dfr = &sbi->dfr_info;
/* static time available? */
- static int time= 0;
+ static int time; /* initialized by zero */
int uevent = 0, total = 0, clean = 0, full = 0;
int spent = jiffies - time;
- if ( !(sbi->options.defrag && wait) )
+ if (!(sbi->options.defrag && wait))
return;
__lock_super(sb);
@@ -3968,8 +4122,8 @@ static void __dfr_update_fat_prev(struct super_block *sb, int wait)
fsapi_sync_fs(sb, 1);
atomic_set(&sb_dfr->stat, DFR_SB_STAT_REQ);
complete_all(&sbi->dfr_complete);
- } else if ( ((spent < 0) || (spent > DFR_DEFAULT_TIMEOUT)) &&
- (atomic_read(&(sbi->dfr_info.stat)) == DFR_SB_STAT_IDLE) ) {
+ } else if (((spent < 0) || (spent > DFR_DEFAULT_TIMEOUT)) &&
+ (atomic_read(&(sbi->dfr_info.stat)) == DFR_SB_STAT_IDLE)) {
uevent = fsapi_dfr_check_dfr_required(sb, &total, &clean, &full);
time = jiffies;
}
@@ -4011,8 +4165,8 @@ static int sdfat_sync_fs(struct super_block *sb, int wait)
static int sdfat_statfs(struct dentry *dentry, struct kstatfs *buf)
{
- /*
- * patch 1.2.2 :
+ /*
+ * patch 1.2.2 :
* fixed the slow-call problem because of volume-lock contention.
*/
struct super_block *sb = dentry->d_sb;
@@ -4059,7 +4213,7 @@ static int sdfat_remount(struct super_block *sb, int *flags, char *data)
(prev_sb_flags & MS_RDONLY) ? "ro" : "rw",
(*flags & MS_RDONLY) ? "ro" : "rw",
fsi->prev_eio, orig_data);
- kfree(orig_data);
+ kfree(orig_data);
return 0;
}
@@ -4097,8 +4251,7 @@ static int __sdfat_show_options(struct seq_file *m, struct super_block *sb)
if (opts->improved_allocation & SDFAT_ALLOC_DELAY)
seq_puts(m, ",delay");
if (opts->improved_allocation & SDFAT_ALLOC_SMART)
- seq_printf(m, ",smart,ausize=%u",\
- opts->amap_opt.sect_per_au);
+ seq_printf(m, ",smart,ausize=%u", opts->amap_opt.sect_per_au);
if (opts->defrag)
seq_puts(m, ",defrag");
if (opts->adj_hidsect)
@@ -4114,8 +4267,8 @@ static int __sdfat_show_options(struct seq_file *m, struct super_block *sb)
else
seq_puts(m, ",errors=remount-ro");
if (opts->discard)
- seq_printf(m, ",discard");
-
+ seq_puts(m, ",discard");
+
return 0;
}
@@ -4125,7 +4278,7 @@ static const struct super_operations sdfat_sops = {
.write_inode = sdfat_write_inode,
.evict_inode = sdfat_evict_inode,
.put_super = sdfat_put_super,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,00)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)
.write_super = sdfat_write_super,
#endif
.sync_fs = sdfat_sync_fs,
@@ -4150,14 +4303,16 @@ static ssize_t sdfat_attr_show(struct kobject *kobj, struct attribute *attr, cha
{
struct sdfat_sb_info *sbi = container_of(kobj, struct sdfat_sb_info, sb_kobj);
struct sdfat_attr *a = container_of(attr, struct sdfat_attr, attr);
+
return a->show ? a->show(sbi, buf) : 0;
}
static ssize_t sdfat_attr_store(struct kobject *kobj, struct attribute *attr,
- const char *buf, size_t len)
+ const char *buf, size_t len)
{
struct sdfat_sb_info *sbi = container_of(kobj, struct sdfat_sb_info, sb_kobj);
struct sdfat_attr *a = container_of(attr, struct sdfat_attr, attr);
+
return a->store ? a->store(sbi, buf, len) : len;
}
@@ -4169,14 +4324,16 @@ static const struct sysfs_ops sdfat_attr_ops = {
static ssize_t type_show(struct sdfat_sb_info *sbi, char *buf)
{
- FS_INFO_T *fsi = &(sbi->fsi);
+ FS_INFO_T *fsi = &(sbi->fsi);
+
return snprintf(buf, PAGE_SIZE, "%s\n", sdfat_get_vol_type_str(fsi->vol_type));
}
SDFAT_ATTR(type, 0444, type_show, NULL);
static ssize_t eio_show(struct sdfat_sb_info *sbi, char *buf)
{
- FS_INFO_T *fsi = &(sbi->fsi);
+ FS_INFO_T *fsi = &(sbi->fsi);
+
return snprintf(buf, PAGE_SIZE, "0x%x\n", fsi->prev_eio);
}
SDFAT_ATTR(eio, 0444, eio_show, NULL);
@@ -4196,9 +4353,9 @@ static ssize_t fratio_show(struct sdfat_sb_info *sbi, char *buf)
if (!n_dirty_au)
fr = 0;
- else if(!n_clean_au)
+ else if (!n_clean_au)
fr = 100;
- else
+ else
fr = (n_dirty_au * 100) / (n_clean_au + n_dirty_au);
return snprintf(buf, PAGE_SIZE, "%u\n", fr);
@@ -4326,7 +4483,7 @@ static const match_table_t sdfat_tokens = {
{Opt_err, NULL}
};
-static int parse_options(struct super_block *sb, char *options, int silent,
+static int parse_options(struct super_block *sb, char *options, int silent,
int *debug, struct sdfat_mount_options *opts)
{
char *p;
@@ -4345,7 +4502,7 @@ static int parse_options(struct super_block *sb, char *options, int silent,
opts->adj_hidsect = 0;
opts->tz_utc = 0;
opts->improved_allocation = 0;
- opts->amap_opt.pack_ratio = 0; // Default packing
+ opts->amap_opt.pack_ratio = 0; // Default packing
opts->amap_opt.sect_per_au = 0;
opts->amap_opt.misaligned_sect = 0;
opts->symlink = 0;
@@ -4358,9 +4515,9 @@ static int parse_options(struct super_block *sb, char *options, int silent,
while ((p = strsep(&options, ",")) != NULL) {
int token;
+
if (!*p)
continue;
-
token = match_token(p, sdfat_tokens, args);
switch (token) {
case Opt_uid:
@@ -4404,7 +4561,7 @@ static int parse_options(struct super_block *sb, char *options, int silent,
case Opt_namecase:
if (match_int(&args[0], &option))
return 0;
- opts->casesensitive = option > 0 ? 1 : 0;
+ opts->casesensitive = (option > 0) ? 1:0;
break;
case Opt_utf8:
opts->utf8 = 1;
@@ -4465,8 +4622,8 @@ static int parse_options(struct super_block *sb, char *options, int silent,
tmpstr = match_strdup(&args[0]);
if (!tmpstr)
return -ENOMEM;
- for (i=0; ifs_type = (unsigned char)i;
sdfat_log_msg(sb, KERN_ERR,
"set fs-type by option : %s",
@@ -4491,7 +4648,7 @@ static int parse_options(struct super_block *sb, char *options, int silent,
break;
default:
if (!silent) {
- sdfat_msg(sb, KERN_ERR,
+ sdfat_msg(sb, KERN_ERR,
"unrecognized mount option \"%s\" "
"or missing value", p);
}
@@ -4511,6 +4668,7 @@ out:
if (opts->discard) {
struct request_queue *q = bdev_get_queue(sb->s_bdev);
+
if (!blk_queue_discard(q))
sdfat_msg(sb, KERN_WARNING,
"mounting with \"discard\" option, but "
@@ -4569,15 +4727,15 @@ static int sdfat_read_root(struct inode *inode)
i_size_write(inode, info.Size);
SDFAT_I(inode)->fid.size = info.Size;
- inode->i_blocks = ( (i_size_read(inode) + (fsi->cluster_size - 1))
- & ~((loff_t)fsi->cluster_size - 1) ) >> inode->i_blkbits;
+ inode->i_blocks = ((i_size_read(inode) + (fsi->cluster_size - 1))
+ & ~((loff_t)fsi->cluster_size - 1)) >> inode->i_blkbits;
SDFAT_I(inode)->i_pos = ((loff_t) fsi->root_dir << 32) | 0xffffffff;
SDFAT_I(inode)->i_size_aligned = i_size_read(inode);
SDFAT_I(inode)->i_size_ondisk = i_size_read(inode);
sdfat_save_attr(inode, ATTR_SUBDIR);
inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
- set_nlink(inode,info.NumSubdirs + 2);
+ set_nlink(inode, info.NumSubdirs + 2);
return 0;
}
@@ -4585,10 +4743,10 @@ static int sdfat_read_root(struct inode *inode)
static void setup_dops(struct super_block *sb)
{
- if (SDFAT_SB(sb)->options.casesensitive == 0)
- sb->s_d_op = &sdfat_ci_dentry_ops;
- else
- sb->s_d_op = &sdfat_dentry_ops;
+ if (SDFAT_SB(sb)->options.casesensitive == 0)
+ sb->s_d_op = &sdfat_ci_dentry_ops;
+ else
+ sb->s_d_op = &sdfat_dentry_ops;
}
static int sdfat_fill_super(struct super_block *sb, void *data, int silent)
@@ -4611,7 +4769,7 @@ static int sdfat_fill_super(struct super_block *sb, void *data, int silent)
*/
sbi = kzalloc(sizeof(struct sdfat_sb_info), GFP_KERNEL);
if (!sbi) {
- sdfat_log_msg(sb, KERN_INFO,
+ sdfat_log_msg(sb, KERN_INFO,
"trying to alloc sbi with vzalloc()");
sbi = vzalloc(sizeof(struct sdfat_sb_info));
if (!sbi) {
@@ -4620,20 +4778,21 @@ static int sdfat_fill_super(struct super_block *sb, void *data, int silent)
}
sbi->use_vmalloc = 1;
}
-
+
mutex_init(&sbi->s_vlock);
sb->s_fs_info = sbi;
sb->s_flags |= MS_NODIRATIME;
sb->s_magic = SDFAT_SUPER_MAGIC;
sb->s_op = &sdfat_sops;
ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL,
- DEFAULT_RATELIMIT_BURST);
+ DEFAULT_RATELIMIT_BURST);
err = parse_options(sb, data, silent, &debug, &sbi->options);
if (err) {
sdfat_log_msg(sb, KERN_ERR, "failed to parse options");
goto failed_mount;
}
+ setup_sdfat_xattr_handler(sb);
setup_sdfat_sync_super_wq(sb);
setup_dops(sb);
@@ -4711,12 +4870,15 @@ static int sdfat_fill_super(struct super_block *sb, void *data, int silent)
"%s[%d:%d]", sb->s_id, MAJOR(bd_dev), MINOR(bd_dev));
if (err) {
sdfat_msg(sb, KERN_ERR, "Unable to create sdfat attributes for"
- " %s[%d:%d](%d)", sb->s_id,
+ " %s[%d:%d](%d)", sb->s_id,
MAJOR(bd_dev), MINOR(bd_dev), err);
goto failed_mount3;
}
sdfat_log_msg(sb, KERN_INFO, "mounted successfully!");
+ /* FOR BIGDATA */
+ sdfat_statistics_set_mnt(&sbi->fsi);
+ sdfat_statistics_set_vol_size(sb);
return 0;
failed_mount3:
@@ -4759,7 +4921,7 @@ static void init_once(void *foo)
static int __init sdfat_init_inodecache(void)
{
- sdfat_inode_cachep = kmem_cache_create("sdfat_inode_cache",
+ sdfat_inode_cachep = kmem_cache_create("sdfat_inode_cache",
sizeof(struct sdfat_inode_info),
0, (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD),
init_once);
@@ -4786,7 +4948,8 @@ static void sdfat_debug_kill_sb(struct super_block *sb)
if (flags & SDFAT_DEBUGFLAGS_INVALID_UMOUNT) {
/* invalidate_bdev drops all device cache include dirty.
- we use this to simulate device removal */
+ * we use this to simulate device removal
+ */
fsapi_cache_release(sb);
invalidate_bdev(bdev);
}
@@ -4819,32 +4982,37 @@ static int __init init_sdfat_fs(void)
sdfat_kset = kset_create_and_add("sdfat", NULL, fs_kobj);
if (!sdfat_kset) {
- printk(KERN_ERR "[SDFAT] failed to create fs_kobj\n");
+ pr_err("[SDFAT] failed to create fs_kobj\n");
err = -ENOMEM;
goto error;
}
err = sysfs_create_group(&sdfat_kset->kobj, &attr_group);
if (err) {
- printk(KERN_ERR "[SDFAT] failed to create sdfat "
- "version attributes\n");
+ pr_err("[SDFAT] failed to create sdfat version attributes\n");
goto error;
}
+ err = sdfat_statistics_init(sdfat_kset);
+ if (err)
+ goto error;
+
err = sdfat_init_inodecache();
if (err) {
- printk(KERN_ERR "[SDFAT] failed to initialize inode cache\n");
+ pr_err("[SDFAT] failed to initialize inode cache\n");
goto error;
}
err = register_filesystem(&sdfat_fs_type);
if (err) {
- printk(KERN_ERR "[SDFAT] failed to register filesystem\n");
+ pr_err("[SDFAT] failed to register filesystem\n");
goto error;
}
return 0;
error:
+ sdfat_statistics_uninit();
+
if (sdfat_kset) {
sysfs_remove_group(&sdfat_kset->kobj, &attr_group);
kset_unregister(sdfat_kset);
@@ -4854,19 +5022,20 @@ error:
sdfat_destroy_inodecache();
fsapi_shutdown();
- printk(KERN_ERR "[SDFAT] failed to initialize FS driver "
- "(err:%d)\n", err);
+ pr_err("[SDFAT] failed to initialize FS driver(err:%d)\n", err);
return err;
}
static void __exit exit_sdfat_fs(void)
{
+ sdfat_statistics_uninit();
+
if (sdfat_kset) {
sysfs_remove_group(&sdfat_kset->kobj, &attr_group);
kset_unregister(sdfat_kset);
sdfat_kset = NULL;
}
-
+
sdfat_destroy_inodecache();
unregister_filesystem(&sdfat_fs_type);
diff --git a/sdfat.h b/sdfat.h
index 4dade10..2f10b96 100644
--- a/sdfat.h
+++ b/sdfat.h
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
#ifndef _SDFAT_H
@@ -35,28 +33,28 @@
#include "dfr.h"
#endif
-/*
+/*
* sdfat error flags
*/
-#define SDFAT_ERRORS_CONT 1 /* ignore error and continue */
-#define SDFAT_ERRORS_PANIC 2 /* panic on error */
-#define SDFAT_ERRORS_RO 3 /* remount r/o on error */
+#define SDFAT_ERRORS_CONT (1) /* ignore error and continue */
+#define SDFAT_ERRORS_PANIC (2) /* panic on error */
+#define SDFAT_ERRORS_RO (3) /* remount r/o on error */
/*
* sdfat allocator flags
*/
-#define SDFAT_ALLOC_DELAY 1 /* Delayed allocation */
-#define SDFAT_ALLOC_SMART 2 /* Smart allocation */
+#define SDFAT_ALLOC_DELAY (1) /* Delayed allocation */
+#define SDFAT_ALLOC_SMART (2) /* Smart allocation */
/*
* sdfat allocator destination for smart allocation
*/
-#define ALLOC_NOWHERE 0
-#define ALLOC_COLD 1
-#define ALLOC_HOT 16
-#define ALLOC_COLD_ALIGNED 1
-#define ALLOC_COLD_PACKING 2
-#define ALLOC_COLD_SEQ 4
+#define ALLOC_NOWHERE (0)
+#define ALLOC_COLD (1)
+#define ALLOC_HOT (16)
+#define ALLOC_COLD_ALIGNED (1)
+#define ALLOC_COLD_PACKING (2)
+#define ALLOC_COLD_SEQ (4)
/*
* sdfat nls lossy flag
@@ -71,22 +69,24 @@
#define CLUSTER_16(x) ((u16)((x) & 0xFFFFU))
#define CLUSTER_32(x) ((u32)((x) & 0xFFFFFFFFU))
#define CLUS_EOF CLUSTER_32(~0)
+#define CLUS_BAD (0xFFFFFFF7U)
#define CLUS_FREE (0)
#define CLUS_BASE (2)
-#define IS_CLUS_EOF(x) (x == CLUS_EOF)
-#define IS_CLUS_FREE(x) (x == CLUS_FREE)
-#define IS_LAST_SECT_IN_CLUS(fsi, sec) \
- ( (((sec) - (fsi)->data_start_sector + 1) \
- & ((1 << (fsi)->sect_per_clus_bits) -1)) == 0 )
+#define IS_CLUS_EOF(x) ((x) == CLUS_EOF)
+#define IS_CLUS_BAD(x) ((x) == CLUS_BAD)
+#define IS_CLUS_FREE(x) ((x) == CLUS_FREE)
+#define IS_LAST_SECT_IN_CLUS(fsi, sec) \
+ ((((sec) - (fsi)->data_start_sector + 1) \
+ & ((1 << (fsi)->sect_per_clus_bits) - 1)) == 0)
#define CLUS_TO_SECT(fsi, x) \
- ( (((x) - CLUS_BASE) << (fsi)->sect_per_clus_bits) + (fsi)->data_start_sector )
+ ((((x) - CLUS_BASE) << (fsi)->sect_per_clus_bits) + (fsi)->data_start_sector)
#define SECT_TO_CLUS(fsi, sec) \
- ((((sec) - (fsi)->data_start_sector) >> (fsi)->sect_per_clus_bits) + CLUS_BASE)
+ ((((sec) - (fsi)->data_start_sector) >> (fsi)->sect_per_clus_bits) + CLUS_BASE)
/* variables defined at sdfat.c */
-extern const char* FS_TYPE_STR[];
+extern const char *FS_TYPE_STR[];
enum {
FS_TYPE_AUTO,
@@ -99,12 +99,12 @@ enum {
* sdfat mount in-memory data
*/
struct sdfat_mount_options {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
- uid_t fs_uid;
- gid_t fs_gid;
-#else
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
kuid_t fs_uid;
kgid_t fs_gid;
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0) */
+ uid_t fs_uid;
+ gid_t fs_gid;
#endif
unsigned short fs_fmask;
unsigned short fs_dmask;
@@ -142,7 +142,7 @@ struct sdfat_sb_info {
struct mutex s_vlock; /* volume lock */
int use_vmalloc;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,00)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
int s_dirt;
struct mutex s_lock; /* superblock lock */
int write_super_queued; /* Write_super work is pending? */
@@ -195,12 +195,12 @@ struct sdfat_sb_info {
struct sdfat_inode_info {
FILE_ID_T fid;
char *target;
- /* NOTE: i_size_ondisk is 64bits, so must hold ->i_mutex to access */
+ /* NOTE: i_size_ondisk is 64bits, so must hold ->inode_lock to access */
loff_t i_size_ondisk; /* physically allocated size */
loff_t i_size_aligned; /* block-aligned i_size (used in cont_write_begin) */
loff_t i_pos; /* on-disk position of directory entry or 0 */
struct hlist_node i_hash_fat; /* hash by i_location */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
struct rw_semaphore truncate_lock; /* protect bmap against truncate */
#endif
#ifdef CONFIG_SDFAT_DFR
@@ -218,7 +218,7 @@ static inline const char *sdfat_get_vol_type_str(unsigned int type)
{
if (type == EXFAT)
return "exfat";
- else if (type == FAT32)
+ else if (type == FAT32)
return "vfat:32";
else if (type == FAT16)
return "vfat:16";
@@ -230,10 +230,10 @@ static inline const char *sdfat_get_vol_type_str(unsigned int type)
static inline struct sdfat_sb_info *SDFAT_SB(struct super_block *sb)
{
- return (struct sdfat_sb_info*)sb->s_fs_info;
+ return (struct sdfat_sb_info *)sb->s_fs_info;
}
-static inline struct sdfat_inode_info *SDFAT_I(struct inode *inode)
+static inline struct sdfat_inode_info *SDFAT_I(struct inode *inode)
{
return container_of(inode, struct sdfat_inode_info, vfs_inode);
}
@@ -279,6 +279,7 @@ static inline mode_t sdfat_make_mode(struct sdfat_sb_info *sbi,
static inline u32 sdfat_make_attr(struct inode *inode)
{
u32 attrs = SDFAT_I(inode)->fid.attr;
+
if (S_ISDIR(inode->i_mode))
attrs |= ATTR_SUBDIR;
if (sdfat_mode_can_hold_ro(inode) && !(inode->i_mode & S_IWUGO))
@@ -294,6 +295,31 @@ static inline void sdfat_save_attr(struct inode *inode, u32 attr)
SDFAT_I(inode)->fid.attr = attr & (ATTR_RWMASK | ATTR_READONLY);
}
+/* sdfat/statistics.c */
+/* bigdata function */
+#ifdef CONFIG_SDFAT_STATISTICS
+extern int sdfat_statistics_init(struct kset *sdfat_kset);
+extern void sdfat_statistics_uninit(void);
+extern void sdfat_statistics_set_mnt(FS_INFO_T *fsi);
+extern void sdfat_statistics_set_mkdir(u8 flags);
+extern void sdfat_statistics_set_create(u8 flags);
+extern void sdfat_statistics_set_rw(u8 flags, u32 clu_offset, s32 create);
+extern void sdfat_statistics_set_trunc(u8 flags, CHAIN_T *clu);
+extern void sdfat_statistics_set_vol_size(struct super_block *sb);
+#else
+static inline int sdfat_statistics_init(struct kset *sdfat_kset)
+{
+ return 0;
+}
+static inline void sdfat_statistics_uninit(void) {};
+static inline void sdfat_statistics_set_mnt(FS_INFO_T *fsi) {};
+static inline void sdfat_statistics_set_mkdir(u8 flags) {};
+static inline void sdfat_statistics_set_create(u8 flags) {};
+static inline void sdfat_statistics_set_rw(u8 flags, u32 clu_offset, s32 create) {};
+static inline void sdfat_statistics_set_trunc(u8 flags, CHAIN_T *clu) {};
+static inline void sdfat_statistics_set_vol_size(struct super_block *sb) {};
+#endif
+
/* sdfat/nls.c */
/* NLS management function */
s32 nls_cmp_sfn(struct super_block *sb, u8 *a, u8 *b);
@@ -301,37 +327,41 @@ s32 nls_cmp_uniname(struct super_block *sb, u16 *a, u16 *b);
s32 nls_uni16s_to_sfn(struct super_block *sb, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname, s32 *p_lossy);
s32 nls_sfn_to_uni16s(struct super_block *sb, DOS_NAME_T *p_dosname, UNI_NAME_T *p_uniname);
s32 nls_uni16s_to_vfsname(struct super_block *sb, UNI_NAME_T *uniname, u8 *p_cstring, s32 len);
-s32 nls_vfsname_to_uni16s(struct super_block *sb, const u8 *p_cstring, const s32 len, UNI_NAME_T *uniname, s32 *p_lossy);
+s32 nls_vfsname_to_uni16s(struct super_block *sb, const u8 *p_cstring,
+ const s32 len, UNI_NAME_T *uniname, s32 *p_lossy);
/* sdfat/mpage.c */
#ifdef CONFIG_SDFAT_ALIGNED_MPAGE_WRITE
int sdfat_mpage_writepages(struct address_space *mapping,
- struct writeback_control *wbc, get_block_t *get_block);
+ struct writeback_control *wbc, get_block_t *get_block);
#endif
/* sdfat/xattr.c */
#ifdef CONFIG_SDFAT_VIRTUAL_XATTR
-extern int sdfat_setxattr(struct dentry*dentry, const char *name, const void *value, size_t size, int flags);
+void setup_sdfat_xattr_handler(struct super_block *sb);
+extern int sdfat_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags);
extern ssize_t sdfat_getxattr(struct dentry *dentry, const char *name, void *value, size_t size);
extern ssize_t sdfat_listxattr(struct dentry *dentry, char *list, size_t size);
extern int sdfat_removexattr(struct dentry *dentry, const char *name);
+#else
+static inline void setup_sdfat_xattr_handler(struct super_block *sb) {};
#endif
/* sdfat/misc.c */
extern void
__sdfat_fs_error(struct super_block *sb, int report, const char *fmt, ...)
- __attribute__ ((format (printf, 3, 4))) __cold;
+ __printf(3, 4) __cold;
#define sdfat_fs_error(sb, fmt, args...) \
- __sdfat_fs_error(sb, 1, fmt , ## args)
+ __sdfat_fs_error(sb, 1, fmt, ## args)
#define sdfat_fs_error_ratelimit(sb, fmt, args...) \
__sdfat_fs_error(sb, __ratelimit(&SDFAT_SB(sb)->ratelimit), fmt, ## args)
-extern void
+extern void
__sdfat_msg(struct super_block *sb, const char *lv, int st, const char *fmt, ...)
- __attribute__ ((format (printf, 4, 5))) __cold;
+ __printf(4, 5) __cold;
#define sdfat_msg(sb, lv, fmt, args...) \
- __sdfat_msg(sb, lv, 0, fmt , ## args)
+ __sdfat_msg(sb, lv, 0, fmt, ## args)
#define sdfat_log_msg(sb, lv, fmt, args...) \
- __sdfat_msg(sb, lv, 1, fmt , ## args)
+ __sdfat_msg(sb, lv, 1, fmt, ## args)
extern void sdfat_log_version(void);
extern void sdfat_time_fat2unix(struct sdfat_sb_info *sbi, struct timespec *ts,
DATE_TIME_T *tp);
@@ -367,20 +397,16 @@ void sdfat_debug_check_clusters(struct inode *inode);
#endif /* CONFIG_SDFAT_DEBUG */
#ifdef CONFIG_SDFAT_TRACE_ELAPSED_TIME
-u32 sdfat_time_current_usec(struct timeval* tv);
+u32 sdfat_time_current_usec(struct timeval *tv);
extern struct timeval __t1;
extern struct timeval __t2;
-#define TIME_GET(tv) sdfat_time_current_usec(tv)
-#define TIME_START(s) do {sdfat_time_current_usec(s); } while (0)
-#define TIME_END(e) do {sdfat_time_current_usec(e); } while (0)
+#define TIME_GET(tv) sdfat_time_current_usec(tv)
+#define TIME_START(s) sdfat_time_current_usec(s)
+#define TIME_END(e) sdfat_time_current_usec(e)
#define TIME_ELAPSED(s, e) ((u32)(((e)->tv_sec - (s)->tv_sec) * 1000000 + \
((e)->tv_usec - (s)->tv_usec)))
-#define PRINT_TIME(n) \
- do { \
- printk("[SDFAT] Elapsed time %d = %d (usec)\n", \
- n, (__t2 - __t1)); \
- } while(0)
+#define PRINT_TIME(n) pr_info("[SDFAT] Elapsed time %d = %d (usec)\n", n, (__t2 - __t1))
#else /* CONFIG_SDFAT_TRACE_ELAPSED_TIME */
#define TIME_GET(tv) (0)
#define TIME_START(s)
@@ -403,11 +429,12 @@ extern struct timeval __t2;
#define __S(x) #x
#define _S(x) __S(x)
-extern void __sdfat_dmsg(int level, const char *fmt, ...)
- __attribute__ ((format (printf, 2, 3))) __cold;
+extern void __sdfat_dmsg(int level, const char *fmt, ...) __printf(2, 3) __cold;
-#define SDFAT_EMSG_T(level, ...) __sdfat_dmsg(level, KERN_ERR "[" SDFAT_TAG_NAME "] [" _S(__FILE__) "(" _S(__LINE__) ")] " __VA_ARGS__)
-#define SDFAT_DMSG_T(level, ...) __sdfat_dmsg(level, KERN_INFO "[" SDFAT_TAG_NAME "] " __VA_ARGS__)
+#define SDFAT_EMSG_T(level, ...) \
+ __sdfat_dmsg(level, KERN_ERR "[" SDFAT_TAG_NAME "] [" _S(__FILE__) "(" _S(__LINE__) ")] " __VA_ARGS__)
+#define SDFAT_DMSG_T(level, ...) \
+ __sdfat_dmsg(level, KERN_INFO "[" SDFAT_TAG_NAME "] " __VA_ARGS__)
#define SDFAT_EMSG(...) SDFAT_EMSG_T(SDFAT_MSG_LV_ERR, __VA_ARGS__)
#define SDFAT_IMSG(...) SDFAT_DMSG_T(SDFAT_MSG_LV_INFO, __VA_ARGS__)
@@ -469,11 +496,12 @@ extern void __sdfat_dmsg(int level, const char *fmt, ...)
#endif /* CONFIG_SDFAT_DBG_MSG */
-#define ASSERT(expr) \
- if (!(expr)) { \
- printk(KERN_ERR "Assertion failed! %s\n", #expr); \
- BUG_ON(1); \
- }
+#define ASSERT(expr) { \
+ if (!(expr)) { \
+ pr_err("Assertion failed! %s\n", #expr); \
+ BUG_ON(1); \
+ } \
+}
#endif /* !_SDFAT_H */
diff --git a/sdfat_fs.h b/sdfat_fs.h
index 4c273d4..998ca84 100644
--- a/sdfat_fs.h
+++ b/sdfat_fs.h
@@ -12,8 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
#ifndef _SDFAT_FS_H
@@ -59,7 +58,7 @@
/* NOTE :
* The maximum length of input or output is limited to 256 including NULL,
* But we allocate 4 extra bytes for utf8 translation reside in last position,
- * because utf8 can uses memory upto 6 bytes per one charactor.
+ * because utf8 can uses memory upto 6 bytes per one character.
* Therefore, MAX_CHARSET_SIZE supports upto 6 bytes for utf8
*/
#define MAX_UNINAME_BUF_SIZE (((MAX_NAME_LENGTH+1)*2)+4)
@@ -73,6 +72,7 @@
#define DENTRY_SIZE_BITS 5
#define MAX_FAT_DENTRIES 65536 /* FAT allows 65536 directory entries */
+#define MAX_EXFAT_DENTRIES 8388608 /* exFAT allows 8388608(256MB) directory entries */
/* PBR entries */
#define PBR_SIGNATURE 0xAA55
@@ -100,7 +100,7 @@
#define MSDOS_UNUSED 0x00 /* end of directory */
#define EXFAT_UNUSED 0x00 /* end of directory */
-#define IS_EXFAT_DELETED(x) ((x)<0x80) /* deleted file (0x01~0x7F) */
+#define IS_EXFAT_DELETED(x) ((x) < 0x80) /* deleted file (0x01~0x7F) */
#define EXFAT_INVAL 0x80 /* invalid value */
#define EXFAT_BITMAP 0x81 /* allocation bitmap */
#define EXFAT_UPCASE 0x82 /* upcase table */
@@ -143,17 +143,17 @@
#define CS_PBR_SECTOR 1
#define CS_DEFAULT 2
-/*
- * ioctl command
+/*
+ * ioctl command
*/
#define SDFAT_IOCTL_GET_VOLUME_ID _IOR('r', 0x12, __u32)
#define SDFAT_IOCTL_DFR_INFO _IOC(_IOC_NONE, 'E', 0x13, sizeof(u32))
-#define SDFAT_IOCTL_DFR_TRAV _IOC(_IOC_NONE, 'E', 0x14, sizeof(u32))
+#define SDFAT_IOCTL_DFR_TRAV _IOC(_IOC_NONE, 'E', 0x14, sizeof(u32))
#define SDFAT_IOCTL_DFR_REQ _IOC(_IOC_NONE, 'E', 0x15, sizeof(u32))
#define SDFAT_IOCTL_DFR_SPO_FLAG _IOC(_IOC_NONE, 'E', 0x16, sizeof(u32))
#define SDFAT_IOCTL_PANIC _IOC(_IOC_NONE, 'E', 0x17, sizeof(u32))
-/*
+/*
* ioctl command for debugging
*/
@@ -162,7 +162,7 @@
* - file systems typically #0~0x1F
* - embedded terminal devices #128~
* - exts for debugging purpose #99
- * number 100 and 101 is availble now but has possible conflicts
+ * number 100 and 101 is available now but has possible conflicts
*
* NOTE : This is available only If CONFIG_SDFAT_DVBG_IOCTL is enabled.
*
@@ -184,15 +184,15 @@ typedef struct {
__u8 sect_size[2]; /* unaligned */
__u8 sect_per_clus;
- __le16 num_reserved; /* . */
+ __le16 num_reserved; /* . */
__u8 num_fats;
- __u8 num_root_entries[2]; /* unaligned */
+ __u8 num_root_entries[2]; /* unaligned */
__u8 num_sectors[2]; /* unaligned */
__u8 media_type;
__le16 num_fat_sectors;
__le16 sectors_in_track;
__le16 num_heads;
- __le32 num_hid_sectors; /* . */
+ __le32 num_hid_sectors; /* . */
__le32 num_huge_sectors;
__u8 phy_drv_no;
@@ -213,7 +213,7 @@ typedef struct {
__u8 sect_per_clus;
__le16 num_reserved;
__u8 num_fats;
- __u8 num_root_entries[2]; /* unaligned */
+ __u8 num_root_entries[2]; /* unaligned */
__u8 num_sectors[2]; /* unaligned */
__u8 media_type;
__le16 num_fat_sectors; /* zero */
diff --git a/statistics.c b/statistics.c
new file mode 100644
index 0000000..cf4baab
--- /dev/null
+++ b/statistics.c
@@ -0,0 +1,262 @@
+#include "sdfat.h"
+
+#define SDFAT_VF_CLUS_MAX 7 /* 512 Byte ~ 32 KByte */
+#define SDFAT_EF_CLUS_MAX 17 /* 512 Byte ~ 32 MByte */
+
+enum {
+ SDFAT_MNT_FAT12,
+ SDFAT_MNT_FAT16,
+ SDFAT_MNT_FAT32,
+ SDFAT_MNT_EXFAT,
+ SDFAT_MNT_MAX
+};
+
+enum {
+ SDFAT_OP_EXFAT_MNT,
+ SDFAT_OP_MKDIR,
+ SDFAT_OP_CREATE,
+ SDFAT_OP_READ,
+ SDFAT_OP_WRITE,
+ SDFAT_OP_TRUNC,
+ SDFAT_OP_MAX
+};
+
+enum {
+ SDFAT_VOL_4G,
+ SDFAT_VOL_8G,
+ SDFAT_VOL_16G,
+ SDFAT_VOL_32G,
+ SDFAT_VOL_64G,
+ SDFAT_VOL_128G,
+ SDFAT_VOL_256G,
+ SDFAT_VOL_512G,
+ SDFAT_VOL_XTB,
+ SDFAT_VOL_MAX
+};
+
+static struct sdfat_statistics {
+ u32 clus_vfat[SDFAT_VF_CLUS_MAX];
+ u32 clus_exfat[SDFAT_EF_CLUS_MAX];
+ u32 mnt_cnt[SDFAT_MNT_MAX];
+ u32 nofat_op[SDFAT_OP_MAX];
+ u32 vol_size[SDFAT_VOL_MAX];
+} statistics;
+
+static struct kset *sdfat_statistics_kset;
+
+static ssize_t vfat_cl_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buff)
+{
+ return snprintf(buff, PAGE_SIZE, "VCL_512B_I:%u,VCL_1K_I:%u,VCL_2K_I:%u,"
+ "VCL_4K_I:%u,VCL_8K_I:%u,VCL_16K_I:%u,VCL_32K_I:%u\n",
+ statistics.clus_vfat[0], statistics.clus_vfat[1],
+ statistics.clus_vfat[2], statistics.clus_vfat[3],
+ statistics.clus_vfat[4], statistics.clus_vfat[5],
+ statistics.clus_vfat[6]);
+}
+
+static ssize_t exfat_cl_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buff)
+{
+ return snprintf(buff, PAGE_SIZE, "ECL_512B_I:%u,ECL_1K_I:%u,ECL_2K_I:%u,"
+ "ECL_4K_I:%u,ECL_8K_I:%u,ECL_16K_I:%u,ECL_32K_I:%u,ECL_64K_I:%u,"
+ "ECL_128K_I:%u,ECL_256K_I:%u,ECL_512K_I:%u,ECL_1M_I:%u,"
+ "ECL_2M_I:%u,ECL_4M_I:%u,ECL_8M_I:%u,ECL_16M_I:%u,ECL_32M_I:%u\n",
+ statistics.clus_exfat[0], statistics.clus_exfat[1],
+ statistics.clus_exfat[2], statistics.clus_exfat[3],
+ statistics.clus_exfat[4], statistics.clus_exfat[5],
+ statistics.clus_exfat[6], statistics.clus_exfat[7],
+ statistics.clus_exfat[8], statistics.clus_exfat[9],
+ statistics.clus_exfat[10], statistics.clus_exfat[11],
+ statistics.clus_exfat[12], statistics.clus_exfat[13],
+ statistics.clus_exfat[14], statistics.clus_exfat[15],
+ statistics.clus_exfat[16]);
+}
+
+static ssize_t mount_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buff)
+{
+ return snprintf(buff, PAGE_SIZE, "FAT12_MNT_I:%u,FAT16_MNT_I:%u,FAT32_MNT_I:%u,"
+ "EXFAT_MNT_I:%u\n",
+ statistics.mnt_cnt[SDFAT_MNT_FAT12],
+ statistics.mnt_cnt[SDFAT_MNT_FAT16],
+ statistics.mnt_cnt[SDFAT_MNT_FAT32],
+ statistics.mnt_cnt[SDFAT_MNT_EXFAT]);
+}
+
+static ssize_t nofat_op_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buff)
+{
+ return snprintf(buff, PAGE_SIZE, "NOFAT_MOUNT_I:%u,NOFAT_MKDIR_I:%u,NOFAT_CREATE_I:%u,"
+ "NOFAT_READ_I:%u,NOFAT_WRITE_I:%u,NOFAT_TRUNC_I:%u\n",
+ statistics.nofat_op[SDFAT_OP_EXFAT_MNT],
+ statistics.nofat_op[SDFAT_OP_MKDIR],
+ statistics.nofat_op[SDFAT_OP_CREATE],
+ statistics.nofat_op[SDFAT_OP_READ],
+ statistics.nofat_op[SDFAT_OP_WRITE],
+ statistics.nofat_op[SDFAT_OP_TRUNC]);
+}
+
+static ssize_t vol_size_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buff)
+{
+ return snprintf(buff, PAGE_SIZE, "VOL_4G_I:%u,VOL_8G_I:%u,VOL_16G_I:%u,"
+ "VOL_32G_I:%u,VOL_64G_I:%u,VOL_128G_I:%u,VOL_256G_I:%u,"
+ "VOL_512G_I:%u,VOL_XTB_I:%u\n",
+ statistics.vol_size[SDFAT_VOL_4G],
+ statistics.vol_size[SDFAT_VOL_8G],
+ statistics.vol_size[SDFAT_VOL_16G],
+ statistics.vol_size[SDFAT_VOL_32G],
+ statistics.vol_size[SDFAT_VOL_64G],
+ statistics.vol_size[SDFAT_VOL_128G],
+ statistics.vol_size[SDFAT_VOL_256G],
+ statistics.vol_size[SDFAT_VOL_512G],
+ statistics.vol_size[SDFAT_VOL_XTB]);
+}
+
+static struct kobj_attribute vfat_cl_attr = __ATTR_RO(vfat_cl);
+static struct kobj_attribute exfat_cl_attr = __ATTR_RO(exfat_cl);
+static struct kobj_attribute mount_attr = __ATTR_RO(mount);
+static struct kobj_attribute nofat_op_attr = __ATTR_RO(nofat_op);
+static struct kobj_attribute vol_size_attr = __ATTR_RO(vol_size);
+
+static struct attribute *attributes_statistics[] = {
+ &vfat_cl_attr.attr,
+ &exfat_cl_attr.attr,
+ &mount_attr.attr,
+ &nofat_op_attr.attr,
+ &vol_size_attr.attr,
+ NULL,
+};
+
+static struct attribute_group attr_group_statistics = {
+ .attrs = attributes_statistics,
+};
+
+int sdfat_statistics_init(struct kset *sdfat_kset)
+{
+ int err;
+
+ sdfat_statistics_kset = kset_create_and_add("statistics", NULL, &sdfat_kset->kobj);
+ if (!sdfat_statistics_kset) {
+ pr_err("[SDFAT] failed to create sdfat statistics kobj\n");
+ return -ENOMEM;
+ }
+
+ err = sysfs_create_group(&sdfat_statistics_kset->kobj, &attr_group_statistics);
+ if (err) {
+ pr_err("[SDFAT] failed to create sdfat statistics attributes\n");
+ kset_unregister(sdfat_statistics_kset);
+ sdfat_statistics_kset = NULL;
+ return err;
+ }
+
+ return 0;
+}
+
+void sdfat_statistics_uninit(void)
+{
+ if (sdfat_statistics_kset) {
+ sysfs_remove_group(&sdfat_statistics_kset->kobj, &attr_group_statistics);
+ kset_unregister(sdfat_statistics_kset);
+ sdfat_statistics_kset = NULL;
+ }
+ memset(&statistics, 0, sizeof(struct sdfat_statistics));
+}
+
+void sdfat_statistics_set_mnt(FS_INFO_T *fsi)
+{
+ if (fsi->vol_type == EXFAT) {
+ statistics.mnt_cnt[SDFAT_MNT_EXFAT]++;
+ statistics.nofat_op[SDFAT_OP_EXFAT_MNT] = 1;
+ if (fsi->sect_per_clus_bits < SDFAT_EF_CLUS_MAX)
+ statistics.clus_exfat[fsi->sect_per_clus_bits]++;
+ else
+ statistics.clus_exfat[SDFAT_EF_CLUS_MAX - 1]++;
+ return;
+ }
+
+ if (fsi->vol_type == FAT32)
+ statistics.mnt_cnt[SDFAT_MNT_FAT32]++;
+ else if (fsi->vol_type == FAT16)
+ statistics.mnt_cnt[SDFAT_MNT_FAT16]++;
+ else if (fsi->vol_type == FAT12)
+ statistics.mnt_cnt[SDFAT_MNT_FAT12]++;
+
+ if (fsi->sect_per_clus_bits < SDFAT_VF_CLUS_MAX)
+ statistics.clus_vfat[fsi->sect_per_clus_bits]++;
+ else
+ statistics.clus_vfat[SDFAT_VF_CLUS_MAX - 1]++;
+}
+
+void sdfat_statistics_set_mkdir(u8 flags)
+{
+ if (flags != 0x03)
+ return;
+ statistics.nofat_op[SDFAT_OP_MKDIR] = 1;
+}
+
+void sdfat_statistics_set_create(u8 flags)
+{
+ if (flags != 0x03)
+ return;
+ statistics.nofat_op[SDFAT_OP_CREATE] = 1;
+}
+
+/* flags : file or dir flgas, 0x03 means no fat-chain.
+ * clu_offset : file or dir logical cluster offset
+ * create : BMAP_ADD_CLUSTER or not
+ *
+ * File or dir have BMAP_ADD_CLUSTER is no fat-chain write
+ * when they have 0x03 flag and two or more clusters.
+ * And don`t have BMAP_ADD_CLUSTER is no fat-chain read
+ * when above same condition.
+ */
+void sdfat_statistics_set_rw(u8 flags, u32 clu_offset, s32 create)
+{
+ if ((flags == 0x03) && (clu_offset > 1)) {
+ if (create)
+ statistics.nofat_op[SDFAT_OP_WRITE] = 1;
+ else
+ statistics.nofat_op[SDFAT_OP_READ] = 1;
+ }
+}
+
+/* flags : file or dir flgas, 0x03 means no fat-chain.
+ * clu : cluster chain
+ *
+ * Set no fat-chain trunc when file or dir have 0x03 flag
+ * and tow or more clusters.
+ */
+void sdfat_statistics_set_trunc(u8 flags, CHAIN_T *clu)
+{
+ if ((flags == 0x03) && (clu->size > 1))
+ statistics.nofat_op[SDFAT_OP_TRUNC] = 1;
+}
+
+void sdfat_statistics_set_vol_size(struct super_block *sb)
+{
+ u64 vol_size;
+ FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
+
+ vol_size = (u64)fsi->num_sectors << sb->s_blocksize_bits;
+
+ if (vol_size <= ((u64)1 << 32))
+ statistics.vol_size[SDFAT_VOL_4G]++;
+ else if (vol_size <= ((u64)1 << 33))
+ statistics.vol_size[SDFAT_VOL_8G]++;
+ else if (vol_size <= ((u64)1 << 34))
+ statistics.vol_size[SDFAT_VOL_16G]++;
+ else if (vol_size <= ((u64)1 << 35))
+ statistics.vol_size[SDFAT_VOL_32G]++;
+ else if (vol_size <= ((u64)1 << 36))
+ statistics.vol_size[SDFAT_VOL_64G]++;
+ else if (vol_size <= ((u64)1 << 37))
+ statistics.vol_size[SDFAT_VOL_128G]++;
+ else if (vol_size <= ((u64)1 << 38))
+ statistics.vol_size[SDFAT_VOL_256G]++;
+ else if (vol_size <= ((u64)1 << 39))
+ statistics.vol_size[SDFAT_VOL_512G]++;
+ else
+ statistics.vol_size[SDFAT_VOL_XTB]++;
+}
diff --git a/upcase.h b/upcase.h
index 4d3c2ac..386772c 100644
--- a/upcase.h
+++ b/upcase.h
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
#ifndef _UPCASE_H
@@ -30,11 +28,11 @@
static inline u16 get_col_index(u16 i)
{
- return i >> LOW_INDEX_BIT;
+ return i >> LOW_INDEX_BIT;
}
static inline u16 get_row_index(u16 i)
{
- return i & ~HIGH_INDEX_MASK;
+ return i & ~HIGH_INDEX_MASK;
}
diff --git a/version.h b/version.h
index 33c5804..831475e 100644
--- a/version.h
+++ b/version.h
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
/************************************************************************/
@@ -24,4 +22,4 @@
/* PURPOSE : sdFAT File Manager */
/* */
/************************************************************************/
-#define SDFAT_VERSION "1.3.24"
+#define SDFAT_VERSION "1.4.16"
diff --git a/xattr.c b/xattr.c
index e6ed8ca..40bb850 100644
--- a/xattr.c
+++ b/xattr.c
@@ -12,9 +12,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
+ * along with this program; if not, see .
*/
/************************************************************************/
@@ -48,7 +46,16 @@ static int can_support(const char *name)
return 0;
}
-int sdfat_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
+ssize_t sdfat_listxattr(struct dentry *dentry, char *list, size_t size)
+{
+ return 0;
+}
+
+
+/*************************************************************************
+ * INNER FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY
+ *************************************************************************/
+static int __sdfat_xattr_check_support(const char *name)
{
if (can_support(name))
return -EOPNOTSUPP;
@@ -56,7 +63,7 @@ int sdfat_setxattr(struct dentry *dentry, const char *name, const void *value, s
return 0;
}
-ssize_t sdfat_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
+ssize_t __sdfat_getxattr(const char *name, void *value, size_t size)
{
if (can_support(name))
return -EOPNOTSUPP;
@@ -67,17 +74,59 @@ ssize_t sdfat_getxattr(struct dentry *dentry, const char *name, void *value, siz
return strlen(default_xattr);
}
-ssize_t sdfat_listxattr(struct dentry *dentry, char *list, size_t size)
+
+/*************************************************************************
+ * FUNCTIONS WHICH HAS KERNEL VERSION DEPENDENCY
+ *************************************************************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
+static int sdfat_xattr_get(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+ const char *name, void *buffer, size_t size)
{
- return 0;
+ return __sdfat_getxattr(name, buffer, size);
+}
+
+static int sdfat_xattr_set(const struct xattr_handler *handler,
+ struct dentry *dentry, struct inode *inode,
+ const char *name, const void *value, size_t size,
+ int flags)
+{
+ return __sdfat_xattr_check_support(name);
+}
+
+const struct xattr_handler sdfat_xattr_handler = {
+ .prefix = "", /* match anything */
+ .get = sdfat_xattr_get,
+ .set = sdfat_xattr_set,
+};
+
+const struct xattr_handler *sdfat_xattr_handlers[] = {
+ &sdfat_xattr_handler,
+ NULL
+};
+
+void setup_sdfat_xattr_handler(struct super_block *sb)
+{
+ sb->s_xattr = sdfat_xattr_handlers;
+}
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0) */
+int sdfat_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
+{
+ return __sdfat_xattr_check_support(name);
+}
+
+ssize_t sdfat_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
+{
+ return __sdfat_getxattr(name, value, size);
}
int sdfat_removexattr(struct dentry *dentry, const char *name)
{
- if (can_support(name))
- return -EOPNOTSUPP;
-
- return 0;
+ return __sdfat_xattr_check_support(name);
}
-
+void setup_sdfat_xattr_handler(struct super_block *sb)
+{
+ /* DO NOTHING */
+}
+#endif