fat.h 13.0 KB
Newer Older
O
OGAWA Hirofumi 已提交
1 2 3 4 5 6 7
#ifndef _FAT_H
#define _FAT_H

#include <linux/buffer_head.h>
#include <linux/string.h>
#include <linux/nls.h>
#include <linux/fs.h>
8
#include <linux/hash.h>
O
OGAWA Hirofumi 已提交
9
#include <linux/mutex.h>
10
#include <linux/ratelimit.h>
O
OGAWA Hirofumi 已提交
11 12 13 14 15 16 17 18 19 20 21
#include <linux/msdos_fs.h>

/*
 * vfat shortname flags
 */
#define VFAT_SFN_DISPLAY_LOWER	0x0001 /* convert to lowercase for display */
#define VFAT_SFN_DISPLAY_WIN95	0x0002 /* emulate win95 rule for display */
#define VFAT_SFN_DISPLAY_WINNT	0x0004 /* emulate winnt rule for display */
#define VFAT_SFN_CREATE_WIN95	0x0100 /* emulate win95 rule for create */
#define VFAT_SFN_CREATE_WINNT	0x0200 /* emulate winnt rule for create */

D
Denis Karpov 已提交
22 23 24 25
#define FAT_ERRORS_CONT		1      /* ignore error and continue */
#define FAT_ERRORS_PANIC	2      /* panic on error */
#define FAT_ERRORS_RO		3      /* remount r/o on error */

O
OGAWA Hirofumi 已提交
26
struct fat_mount_options {
27 28
	kuid_t fs_uid;
	kgid_t fs_gid;
O
OGAWA Hirofumi 已提交
29 30
	unsigned short fs_fmask;
	unsigned short fs_dmask;
31
	unsigned short codepage;   /* Codepage for shortname conversions */
32
	int time_offset;	   /* Offset of timestamps from UTC (in minutes) */
33 34 35 36
	char *iocharset;           /* Charset used for filename input/display */
	unsigned short shortname;  /* flags for shortname display/create rule */
	unsigned char name_check;  /* r = relaxed, n = normal, s = strict */
	unsigned char errors;	   /* On error: continue, panic, remount-ro */
O
OGAWA Hirofumi 已提交
37
	unsigned short allow_utime;/* permission for setting the [am]time */
38 39 40 41 42 43 44 45 46 47 48
	unsigned quiet:1,          /* set = fake successful chmods and chowns */
		 showexec:1,       /* set = only set x bit for com/exe/bat */
		 sys_immutable:1,  /* set = system files are immutable */
		 dotsOK:1,         /* set = hidden and system files are named '.filename' */
		 isvfat:1,         /* 0=no vfat long filename support, 1=vfat support */
		 utf8:1,	   /* Use of UTF-8 character set (Default) */
		 unicode_xlate:1,  /* create escape sequences for unhandled Unicode */
		 numtail:1,        /* Does first alias have a numeric '~1' type tail? */
		 flush:1,	   /* write things quickly */
		 nocase:1,	   /* Does this need case conversion? 0=need case conversion*/
		 usefree:1,	   /* Use free_clusters for FAT32 */
49
		 tz_set:1,	   /* Filesystem timestamps' offset set */
50 51 52
		 rodir:1,	   /* allow ATTR_RO for directory */
		 discard:1,	   /* Issue discard requests on deletions */
		 nfs:1;		   /* Do extra work needed for NFS export */
O
OGAWA Hirofumi 已提交
53 54 55 56 57 58 59 60 61
};

#define FAT_HASH_BITS	8
#define FAT_HASH_SIZE	(1UL << FAT_HASH_BITS)

/*
 * MS-DOS file system in-core superblock data
 */
struct msdos_sb_info {
62 63 64
	unsigned short sec_per_clus;  /* sectors/cluster */
	unsigned short cluster_bits;  /* log2(cluster_size) */
	unsigned int cluster_size;    /* cluster size */
65
	unsigned char fats, fat_bits; /* number of FATs, FAT bits (12 or 16) */
O
OGAWA Hirofumi 已提交
66
	unsigned short fat_start;
67
	unsigned long fat_length;     /* FAT start & length (sec.) */
O
OGAWA Hirofumi 已提交
68
	unsigned long dir_start;
69 70 71 72 73
	unsigned short dir_entries;   /* root dir start & entries */
	unsigned long data_start;     /* first data sector */
	unsigned long max_cluster;    /* maximum cluster number */
	unsigned long root_cluster;   /* first cluster of the root directory */
	unsigned long fsinfo_sector;  /* sector number of FAT32 fsinfo */
O
OGAWA Hirofumi 已提交
74
	struct mutex fat_lock;
M
Marco Stornelli 已提交
75 76 77
	struct mutex s_lock;
	unsigned int prev_free;      /* previously allocated cluster number */
	unsigned int free_clusters;  /* -1 if undefined */
O
OGAWA Hirofumi 已提交
78 79
	unsigned int free_clus_valid; /* is free_clusters valid? */
	struct fat_mount_options options;
80 81 82 83 84
	struct nls_table *nls_disk;   /* Codepage used on disk */
	struct nls_table *nls_io;     /* Charset used for input and display */
	const void *dir_ops;	      /* Opaque; default directory operations */
	int dir_per_block;	      /* dir entries per block */
	int dir_per_block_bits;	      /* log2(dir_per_block) */
O
OGAWA Hirofumi 已提交
85 86 87

	int fatent_shift;
	struct fatent_operations *fatent_ops;
A
Al Viro 已提交
88
	struct inode *fat_inode;
89
	struct inode *fsinfo_inode;
O
OGAWA Hirofumi 已提交
90

91 92
	struct ratelimit_state ratelimit;

O
OGAWA Hirofumi 已提交
93 94
	spinlock_t inode_hash_lock;
	struct hlist_head inode_hashtable[FAT_HASH_SIZE];
95 96 97

	spinlock_t dir_hash_lock;
	struct hlist_head dir_hashtable[FAT_HASH_SIZE];
O
OGAWA Hirofumi 已提交
98 99 100 101 102 103 104 105 106 107 108 109 110 111
};

#define FAT_CACHE_VALID	0	/* special case for valid cache */

/*
 * MS-DOS file system inode data in memory
 */
struct msdos_inode_info {
	spinlock_t cache_lru_lock;
	struct list_head cache_lru;
	int nr_caches;
	/* for avoiding the race between fat_free() and fat_get_cluster() */
	unsigned int cache_valid_id;

O
OGAWA Hirofumi 已提交
112 113 114
	/* NOTE: mmu_private is 64bits, so must hold ->i_mutex to access */
	loff_t mmu_private;	/* physically allocated size */

O
OGAWA Hirofumi 已提交
115 116 117 118 119
	int i_start;		/* first cluster or 0 */
	int i_logstart;		/* logical first cluster */
	int i_attrs;		/* unused attribute bits */
	loff_t i_pos;		/* on-disk position of directory entry or 0 */
	struct hlist_node i_fat_hash;	/* hash by i_location */
120
	struct hlist_node i_dir_hash;	/* hash by i_logstart */
121
	struct rw_semaphore truncate_lock; /* protect bmap against truncate */
O
OGAWA Hirofumi 已提交
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
	struct inode vfs_inode;
};

struct fat_slot_info {
	loff_t i_pos;		/* on-disk position of directory entry */
	loff_t slot_off;	/* offset for slot or de start */
	int nr_slots;		/* number of slots + 1(de) in filename */
	struct msdos_dir_entry *de;
	struct buffer_head *bh;
};

static inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb)
{
	return sb->s_fs_info;
}

static inline struct msdos_inode_info *MSDOS_I(struct inode *inode)
{
	return container_of(inode, struct msdos_inode_info, vfs_inode);
}

143 144 145
/*
 * If ->i_mode can't hold S_IWUGO (i.e. ATTR_RO), we use ->i_attrs to
 * save ATTR_RO instead of ->i_mode.
O
OGAWA Hirofumi 已提交
146 147 148
 *
 * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only
 * bit, it's just used as flag for app.
149 150 151 152
 */
static inline int fat_mode_can_hold_ro(struct inode *inode)
{
	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
A
Al Viro 已提交
153
	umode_t mask;
154

O
OGAWA Hirofumi 已提交
155 156 157
	if (S_ISDIR(inode->i_mode)) {
		if (!sbi->options.rodir)
			return 0;
158
		mask = ~sbi->options.fs_dmask;
O
OGAWA Hirofumi 已提交
159
	} else
160 161 162 163 164 165 166
		mask = ~sbi->options.fs_fmask;

	if (!(mask & S_IWUGO))
		return 0;
	return 1;
}

O
OGAWA Hirofumi 已提交
167
/* Convert attribute bits and a mask to the UNIX mode. */
A
Al Viro 已提交
168 169
static inline umode_t fat_make_mode(struct msdos_sb_info *sbi,
				   u8 attrs, umode_t mode)
O
OGAWA Hirofumi 已提交
170
{
O
OGAWA Hirofumi 已提交
171
	if (attrs & ATTR_RO && !((attrs & ATTR_DIR) && !sbi->options.rodir))
O
OGAWA Hirofumi 已提交
172 173 174 175 176 177 178 179
		mode &= ~S_IWUGO;

	if (attrs & ATTR_DIR)
		return (mode & ~sbi->options.fs_dmask) | S_IFDIR;
	else
		return (mode & ~sbi->options.fs_fmask) | S_IFREG;
}

O
OGAWA Hirofumi 已提交
180
/* Return the FAT attribute byte for this inode */
O
OGAWA Hirofumi 已提交
181
static inline u8 fat_make_attrs(struct inode *inode)
O
OGAWA Hirofumi 已提交
182
{
183 184 185 186 187 188
	u8 attrs = MSDOS_I(inode)->i_attrs;
	if (S_ISDIR(inode->i_mode))
		attrs |= ATTR_DIR;
	if (fat_mode_can_hold_ro(inode) && !(inode->i_mode & S_IWUGO))
		attrs |= ATTR_RO;
	return attrs;
O
OGAWA Hirofumi 已提交
189 190
}

O
OGAWA Hirofumi 已提交
191 192
static inline void fat_save_attrs(struct inode *inode, u8 attrs)
{
193 194 195 196
	if (fat_mode_can_hold_ro(inode))
		MSDOS_I(inode)->i_attrs = attrs & ATTR_UNUSED;
	else
		MSDOS_I(inode)->i_attrs = attrs & (ATTR_UNUSED | ATTR_RO);
O
OGAWA Hirofumi 已提交
197 198
}

O
OGAWA Hirofumi 已提交
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
static inline unsigned char fat_checksum(const __u8 *name)
{
	unsigned char s = name[0];
	s = (s<<7) + (s>>1) + name[1];	s = (s<<7) + (s>>1) + name[2];
	s = (s<<7) + (s>>1) + name[3];	s = (s<<7) + (s>>1) + name[4];
	s = (s<<7) + (s>>1) + name[5];	s = (s<<7) + (s>>1) + name[6];
	s = (s<<7) + (s>>1) + name[7];	s = (s<<7) + (s>>1) + name[8];
	s = (s<<7) + (s>>1) + name[9];	s = (s<<7) + (s>>1) + name[10];
	return s;
}

static inline sector_t fat_clus_to_blknr(struct msdos_sb_info *sbi, int clus)
{
	return ((sector_t)clus - FAT_START_ENT) * sbi->sec_per_clus
		+ sbi->data_start;
}

static inline void fat16_towchar(wchar_t *dst, const __u8 *src, size_t len)
{
#ifdef __BIG_ENDIAN
	while (len--) {
		*dst++ = src[0] | (src[1] << 8);
		src += 2;
	}
#else
	memcpy(dst, src, len * 2);
#endif
}

228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
static inline int fat_get_start(const struct msdos_sb_info *sbi,
				const struct msdos_dir_entry *de)
{
	int cluster = le16_to_cpu(de->start);
	if (sbi->fat_bits == 32)
		cluster |= (le16_to_cpu(de->starthi) << 16);
	return cluster;
}

static inline void fat_set_start(struct msdos_dir_entry *de, int cluster)
{
	de->start   = cpu_to_le16(cluster);
	de->starthi = cpu_to_le16(cluster >> 16);
}

O
OGAWA Hirofumi 已提交
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
static inline void fatwchar_to16(__u8 *dst, const wchar_t *src, size_t len)
{
#ifdef __BIG_ENDIAN
	while (len--) {
		dst[0] = *src & 0x00FF;
		dst[1] = (*src & 0xFF00) >> 8;
		dst += 2;
		src++;
	}
#else
	memcpy(dst, src, len * 2);
#endif
}

/* fat/cache.c */
extern void fat_cache_inval_inode(struct inode *inode);
extern int fat_get_cluster(struct inode *inode, int cluster,
			   int *fclus, int *dclus);
extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys,
O
OGAWA Hirofumi 已提交
262
		    unsigned long *mapped_blocks, int create);
O
OGAWA Hirofumi 已提交
263 264 265 266 267 268 269 270 271 272

/* fat/dir.c */
extern const struct file_operations fat_dir_operations;
extern int fat_search_long(struct inode *inode, const unsigned char *name,
			   int name_len, struct fat_slot_info *sinfo);
extern int fat_dir_empty(struct inode *dir);
extern int fat_subdirs(struct inode *dir);
extern int fat_scan(struct inode *dir, const unsigned char *name,
		    struct fat_slot_info *sinfo);
extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh,
273
				struct msdos_dir_entry **de);
O
OGAWA Hirofumi 已提交
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts);
extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
			   struct fat_slot_info *sinfo);
extern int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo);

/* fat/fatent.c */
struct fat_entry {
	int entry;
	union {
		u8 *ent12_p[2];
		__le16 *ent16_p;
		__le32 *ent32_p;
	} u;
	int nr_bhs;
	struct buffer_head *bhs[2];
A
Al Viro 已提交
289
	struct inode *fat_inode;
O
OGAWA Hirofumi 已提交
290 291 292 293 294 295 296 297
};

static inline void fatent_init(struct fat_entry *fatent)
{
	fatent->nr_bhs = 0;
	fatent->entry = 0;
	fatent->u.ent32_p = NULL;
	fatent->bhs[0] = fatent->bhs[1] = NULL;
A
Al Viro 已提交
298
	fatent->fat_inode = NULL;
O
OGAWA Hirofumi 已提交
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
}

static inline void fatent_set_entry(struct fat_entry *fatent, int entry)
{
	fatent->entry = entry;
	fatent->u.ent32_p = NULL;
}

static inline void fatent_brelse(struct fat_entry *fatent)
{
	int i;
	fatent->u.ent32_p = NULL;
	for (i = 0; i < fatent->nr_bhs; i++)
		brelse(fatent->bhs[i]);
	fatent->nr_bhs = 0;
	fatent->bhs[0] = fatent->bhs[1] = NULL;
A
Al Viro 已提交
315
	fatent->fat_inode = NULL;
O
OGAWA Hirofumi 已提交
316 317 318 319 320 321 322 323 324 325 326 327 328
}

extern void fat_ent_access_init(struct super_block *sb);
extern int fat_ent_read(struct inode *inode, struct fat_entry *fatent,
			int entry);
extern int fat_ent_write(struct inode *inode, struct fat_entry *fatent,
			 int new, int wait);
extern int fat_alloc_clusters(struct inode *inode, int *cluster,
			      int nr_cluster);
extern int fat_free_clusters(struct inode *inode, int cluster);
extern int fat_count_free_clusters(struct super_block *sb);

/* fat/file.c */
A
Arnd Bergmann 已提交
329 330
extern long fat_generic_ioctl(struct file *filp, unsigned int cmd,
			      unsigned long arg);
O
OGAWA Hirofumi 已提交
331 332
extern const struct file_operations fat_file_operations;
extern const struct inode_operations fat_file_inode_operations;
333
extern int fat_setattr(struct dentry *dentry, struct iattr *attr);
334
extern void fat_truncate_blocks(struct inode *inode, loff_t offset);
O
OGAWA Hirofumi 已提交
335 336
extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry,
		       struct kstat *stat);
337 338
extern int fat_file_fsync(struct file *file, loff_t start, loff_t end,
			  int datasync);
O
OGAWA Hirofumi 已提交
339 340 341 342 343 344 345 346 347

/* fat/inode.c */
extern void fat_attach(struct inode *inode, loff_t i_pos);
extern void fat_detach(struct inode *inode);
extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos);
extern struct inode *fat_build_inode(struct super_block *sb,
			struct msdos_dir_entry *de, loff_t i_pos);
extern int fat_sync_inode(struct inode *inode);
extern int fat_fill_super(struct super_block *sb, void *data, int silent,
348
			  int isvfat, void (*setup)(struct super_block *));
O
OGAWA Hirofumi 已提交
349 350

extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
351
			    struct inode *i2);
352
static inline unsigned long fat_dir_hash(int logstart)
353
{
354
	return hash_32(logstart, FAT_HASH_BITS);
355 356
}

O
OGAWA Hirofumi 已提交
357
/* fat/misc.c */
358 359
extern __printf(3, 4) __cold
void __fat_fs_error(struct super_block *sb, int report, const char *fmt, ...);
360 361 362 363
#define fat_fs_error(sb, fmt, args...)		\
	__fat_fs_error(sb, 1, fmt , ## args)
#define fat_fs_error_ratelimit(sb, fmt, args...) \
	__fat_fs_error(sb, __ratelimit(&MSDOS_SB(sb)->ratelimit), fmt , ## args)
364 365
__printf(3, 4) __cold
void fat_msg(struct super_block *sb, const char *level, const char *fmt, ...);
N
Namjae Jeon 已提交
366 367 368 369 370
#define fat_msg_ratelimit(sb, level, fmt, args...)	\
	do {	\
			if (__ratelimit(&MSDOS_SB(sb)->ratelimit))	\
				fat_msg(sb, level, fmt, ## args);	\
	 } while (0)
371
extern int fat_clusters_flush(struct super_block *sb);
O
OGAWA Hirofumi 已提交
372
extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster);
373 374 375 376
extern void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts,
			      __le16 __time, __le16 __date, u8 time_cs);
extern void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts,
			      __le16 *time, __le16 *date, u8 *time_cs);
O
OGAWA Hirofumi 已提交
377 378 379 380 381
extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);

int fat_cache_init(void);
void fat_cache_destroy(void);

382 383 384 385
/* fat/nfs.c */
struct fid;
extern struct dentry *fat_fh_to_dentry(struct super_block *sb, struct fid *fid,
				       int fh_len, int fh_type);
386 387
extern struct dentry *fat_fh_to_parent(struct super_block *sb, struct fid *fid,
				       int fh_len, int fh_type);
388 389
extern struct dentry *fat_get_parent(struct dentry *child_dir);

O
OGAWA Hirofumi 已提交
390 391 392
/* helper for printk */
typedef unsigned long long	llu;

O
OGAWA Hirofumi 已提交
393
#endif /* !_FAT_H */