#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/seq_file.h>
-#include <linux/msdos_fs.h>
#include <linux/pagemap.h>
#include <linux/mpage.h>
#include <linux/buffer_head.h>
#include <linux/uio.h>
#include <linux/writeback.h>
#include <linux/log2.h>
+#include <linux/hash.h>
#include <asm/unaligned.h>
+#include "fat.h"
#ifndef CONFIG_FAT_DEFAULT_IOCHARSET
/* if user don't select VFAT, this is undefined. */
INIT_HLIST_HEAD(&sbi->inode_hashtable[i]);
}
-static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos)
+static inline unsigned long fat_hash(loff_t i_pos)
{
- unsigned long tmp = (unsigned long)i_pos | (unsigned long) sb;
- tmp = tmp + (tmp >> FAT_HASH_BITS) + (tmp >> FAT_HASH_BITS * 2);
- return tmp & FAT_HASH_MASK;
+ return hash_32(i_pos, FAT_HASH_BITS);
}
void fat_attach(struct inode *inode, loff_t i_pos)
{
- struct super_block *sb = inode->i_sb;
- struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+ struct hlist_head *head = sbi->inode_hashtable + fat_hash(i_pos);
spin_lock(&sbi->inode_hash_lock);
MSDOS_I(inode)->i_pos = i_pos;
- hlist_add_head(&MSDOS_I(inode)->i_fat_hash,
- sbi->inode_hashtable + fat_hash(sb, i_pos));
+ hlist_add_head(&MSDOS_I(inode)->i_fat_hash, head);
spin_unlock(&sbi->inode_hash_lock);
}
-
EXPORT_SYMBOL_GPL(fat_attach);
void fat_detach(struct inode *inode)
hlist_del_init(&MSDOS_I(inode)->i_fat_hash);
spin_unlock(&sbi->inode_hash_lock);
}
-
EXPORT_SYMBOL_GPL(fat_detach);
struct inode *fat_iget(struct super_block *sb, loff_t i_pos)
{
struct msdos_sb_info *sbi = MSDOS_SB(sb);
- struct hlist_head *head = sbi->inode_hashtable + fat_hash(sb, i_pos);
+ struct hlist_head *head = sbi->inode_hashtable + fat_hash(i_pos);
struct hlist_node *_p;
struct msdos_inode_info *i;
struct inode *inode = NULL;
MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
& ~((loff_t)sbi->cluster_size - 1)) >> 9;
- inode->i_mtime.tv_sec =
- date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date),
- sbi->options.tz_utc);
- inode->i_mtime.tv_nsec = 0;
+
+ fat_time_fat2unix(sbi, &inode->i_mtime, de->time, de->date, 0);
if (sbi->options.isvfat) {
- int secs = de->ctime_cs / 100;
- int csecs = de->ctime_cs % 100;
- inode->i_ctime.tv_sec =
- date_dos2unix(le16_to_cpu(de->ctime),
- le16_to_cpu(de->cdate),
- sbi->options.tz_utc) + secs;
- inode->i_ctime.tv_nsec = csecs * 10000000;
- inode->i_atime.tv_sec =
- date_dos2unix(0, le16_to_cpu(de->adate),
- sbi->options.tz_utc);
- inode->i_atime.tv_nsec = 0;
+ fat_time_fat2unix(sbi, &inode->i_ctime, de->ctime,
+ de->cdate, de->ctime_cs);
+ fat_time_fat2unix(sbi, &inode->i_atime, 0, de->adate, 0);
} else
inode->i_ctime = inode->i_atime = inode->i_mtime;
raw_entry->attr = fat_attr(inode);
raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart);
raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16);
- fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time,
- &raw_entry->date, sbi->options.tz_utc);
+ fat_time_unix2fat(sbi, &inode->i_mtime, &raw_entry->time,
+ &raw_entry->date, NULL);
if (sbi->options.isvfat) {
__le16 atime;
- fat_date_unix2dos(inode->i_ctime.tv_sec, &raw_entry->ctime,
- &raw_entry->cdate, sbi->options.tz_utc);
- fat_date_unix2dos(inode->i_atime.tv_sec, &atime,
- &raw_entry->adate, sbi->options.tz_utc);
- raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 +
- inode->i_ctime.tv_nsec / 10000000;
+ fat_time_unix2fat(sbi, &inode->i_ctime, &raw_entry->ctime,
+ &raw_entry->cdate, &raw_entry->ctime_cs);
+ fat_time_unix2fat(sbi, &inode->i_atime, &atime,
+ &raw_entry->adate, NULL);
}
spin_unlock(&sbi->inode_hash_lock);
mark_buffer_dirty(bh);