inode.c 47.8 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
 *  linux/fs/fat/inode.c
 *
 *  Written 1992,1993 by Werner Almesberger
 *  VFAT extensions by Gordon Chaffee, merged with msdos fs by Henrik Storner
 *  Rewritten for the constant inumbers support by Al Viro
 *
 *  Fixes:
 *
 *	Max Cohan: Fixed invalid FSINFO offset when info_sector is 0
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/time.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
#include <linux/pagemap.h>
19
#include <linux/mpage.h>
Linus Torvalds's avatar
Linus Torvalds committed
20
21
#include <linux/buffer_head.h>
#include <linux/mount.h>
22
#include <linux/aio.h>
Linus Torvalds's avatar
Linus Torvalds committed
23
24
#include <linux/vfs.h>
#include <linux/parser.h>
25
#include <linux/uio.h>
Chris Mason's avatar
Chris Mason committed
26
#include <linux/writeback.h>
Vignesh Babu BM's avatar
Vignesh Babu BM committed
27
#include <linux/log2.h>
OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
28
#include <linux/hash.h>
29
#include <linux/blkdev.h>
Linus Torvalds's avatar
Linus Torvalds committed
30
#include <asm/unaligned.h>
OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
31
#include "fat.h"
Linus Torvalds's avatar
Linus Torvalds committed
32
33
34
35
36
37

#ifndef CONFIG_FAT_DEFAULT_IOCHARSET
/* if user don't select VFAT, this is undefined. */
#define CONFIG_FAT_DEFAULT_IOCHARSET	""
#endif

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#define KB_IN_SECTORS 2

/*
 * A deserialized copy of the on-disk structure laid out in struct
 * fat_boot_sector.
 */
struct fat_bios_param_block {
	u16	fat_sector_size;
	u8	fat_sec_per_clus;
	u16	fat_reserved;
	u8	fat_fats;
	u16	fat_dir_entries;
	u16	fat_sectors;
	u16	fat_fat_length;
	u32	fat_total_sect;

	u8	fat16_state;
	u32	fat16_vol_id;

	u32	fat32_length;
	u32	fat32_root_cluster;
	u16	fat32_info_sector;
	u8	fat32_state;
	u32	fat32_vol_id;
};

Linus Torvalds's avatar
Linus Torvalds committed
64
65
66
static int fat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE;
static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET;

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
static struct fat_floppy_defaults {
	unsigned nr_sectors;
	unsigned sec_per_clus;
	unsigned dir_entries;
	unsigned media;
	unsigned fat_length;
} floppy_defaults[] = {
{
	.nr_sectors = 160 * KB_IN_SECTORS,
	.sec_per_clus = 1,
	.dir_entries = 64,
	.media = 0xFE,
	.fat_length = 1,
},
{
	.nr_sectors = 180 * KB_IN_SECTORS,
	.sec_per_clus = 1,
	.dir_entries = 64,
	.media = 0xFC,
	.fat_length = 2,
},
{
	.nr_sectors = 320 * KB_IN_SECTORS,
	.sec_per_clus = 2,
	.dir_entries = 112,
	.media = 0xFF,
	.fat_length = 1,
},
{
	.nr_sectors = 360 * KB_IN_SECTORS,
	.sec_per_clus = 2,
	.dir_entries = 112,
	.media = 0xFD,
	.fat_length = 2,
},
};
Linus Torvalds's avatar
Linus Torvalds committed
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

static int fat_add_cluster(struct inode *inode)
{
	int err, cluster;

	err = fat_alloc_clusters(inode, &cluster, 1);
	if (err)
		return err;
	/* FIXME: this cluster should be added after data of this
	 * cluster is writed */
	err = fat_chain_add(inode, cluster, 1);
	if (err)
		fat_free_clusters(inode, cluster);
	return err;
}

119
120
121
static inline int __fat_get_block(struct inode *inode, sector_t iblock,
				  unsigned long *max_blocks,
				  struct buffer_head *bh_result, int create)
Linus Torvalds's avatar
Linus Torvalds committed
122
123
{
	struct super_block *sb = inode->i_sb;
124
125
	struct msdos_sb_info *sbi = MSDOS_SB(sb);
	unsigned long mapped_blocks;
126
	sector_t phys;
127
	int err, offset;
Linus Torvalds's avatar
Linus Torvalds committed
128

OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
129
	err = fat_bmap(inode, iblock, &phys, &mapped_blocks, create);
Linus Torvalds's avatar
Linus Torvalds committed
130
131
132
133
	if (err)
		return err;
	if (phys) {
		map_bh(bh_result, sb, phys);
134
		*max_blocks = min(mapped_blocks, *max_blocks);
Linus Torvalds's avatar
Linus Torvalds committed
135
136
137
138
		return 0;
	}
	if (!create)
		return 0;
139

Linus Torvalds's avatar
Linus Torvalds committed
140
	if (iblock != MSDOS_I(inode)->mmu_private >> sb->s_blocksize_bits) {
Denis Karpov's avatar
Denis Karpov committed
141
		fat_fs_error(sb, "corrupted file size (i_pos %lld, %lld)",
142
			MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private);
Linus Torvalds's avatar
Linus Torvalds committed
143
144
		return -EIO;
	}
145
146
147
148

	offset = (unsigned long)iblock & (sbi->sec_per_clus - 1);
	if (!offset) {
		/* TODO: multiple cluster allocation would be desirable. */
Linus Torvalds's avatar
Linus Torvalds committed
149
150
151
152
		err = fat_add_cluster(inode);
		if (err)
			return err;
	}
153
154
155
156
157
158
	/* available blocks on this cluster */
	mapped_blocks = sbi->sec_per_clus - offset;

	*max_blocks = min(mapped_blocks, *max_blocks);
	MSDOS_I(inode)->mmu_private += *max_blocks << sb->s_blocksize_bits;

OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
159
	err = fat_bmap(inode, iblock, &phys, &mapped_blocks, create);
Linus Torvalds's avatar
Linus Torvalds committed
160
161
	if (err)
		return err;
162

163
164
	BUG_ON(!phys);
	BUG_ON(*max_blocks != mapped_blocks);
Linus Torvalds's avatar
Linus Torvalds committed
165
166
	set_buffer_new(bh_result);
	map_bh(bh_result, sb, phys);
167

Linus Torvalds's avatar
Linus Torvalds committed
168
169
170
	return 0;
}

171
172
static int fat_get_block(struct inode *inode, sector_t iblock,
			 struct buffer_head *bh_result, int create)
173
174
{
	struct super_block *sb = inode->i_sb;
175
	unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
176
	int err;
177

178
	err = __fat_get_block(inode, iblock, &max_blocks, bh_result, create);
179
180
181
182
183
184
	if (err)
		return err;
	bh_result->b_size = max_blocks << sb->s_blocksize_bits;
	return 0;
}

Linus Torvalds's avatar
Linus Torvalds committed
185
186
187
188
189
static int fat_writepage(struct page *page, struct writeback_control *wbc)
{
	return block_write_full_page(page, fat_get_block, wbc);
}

190
191
192
193
194
195
static int fat_writepages(struct address_space *mapping,
			  struct writeback_control *wbc)
{
	return mpage_writepages(mapping, wbc, fat_get_block);
}

Linus Torvalds's avatar
Linus Torvalds committed
196
197
static int fat_readpage(struct file *file, struct page *page)
{
198
199
200
201
202
203
204
	return mpage_readpage(page, fat_get_block);
}

static int fat_readpages(struct file *file, struct address_space *mapping,
			 struct list_head *pages, unsigned nr_pages)
{
	return mpage_readpages(mapping, pages, nr_pages, fat_get_block);
Linus Torvalds's avatar
Linus Torvalds committed
205
206
}

207
208
209
210
211
static void fat_write_failed(struct address_space *mapping, loff_t to)
{
	struct inode *inode = mapping->host;

	if (to > inode->i_size) {
212
		truncate_pagecache(inode, inode->i_size);
213
214
215
216
		fat_truncate_blocks(inode, inode->i_size);
	}
}

Nick Piggin's avatar
Nick Piggin committed
217
218
219
static int fat_write_begin(struct file *file, struct address_space *mapping,
			loff_t pos, unsigned len, unsigned flags,
			struct page **pagep, void **fsdata)
Linus Torvalds's avatar
Linus Torvalds committed
220
{
221
222
	int err;

Nick Piggin's avatar
Nick Piggin committed
223
	*pagep = NULL;
224
	err = cont_write_begin(file, mapping, pos, len, flags,
225
				pagep, fsdata, fat_get_block,
Nick Piggin's avatar
Nick Piggin committed
226
				&MSDOS_I(mapping->host)->mmu_private);
227
228
229
	if (err < 0)
		fat_write_failed(mapping, pos + len);
	return err;
Linus Torvalds's avatar
Linus Torvalds committed
230
231
}

Nick Piggin's avatar
Nick Piggin committed
232
233
234
static int fat_write_end(struct file *file, struct address_space *mapping,
			loff_t pos, unsigned len, unsigned copied,
			struct page *pagep, void *fsdata)
235
{
Nick Piggin's avatar
Nick Piggin committed
236
237
238
	struct inode *inode = mapping->host;
	int err;
	err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
239
240
	if (err < len)
		fat_write_failed(mapping, pos + len);
Nick Piggin's avatar
Nick Piggin committed
241
	if (!(err < 0) && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) {
242
243
244
245
246
247
248
		inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
		MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
		mark_inode_dirty(inode);
	}
	return err;
}

249
static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
Al Viro's avatar
Al Viro committed
250
251
			     struct iov_iter *iter,
			     loff_t offset)
252
253
{
	struct file *file = iocb->ki_filp;
254
255
	struct address_space *mapping = file->f_mapping;
	struct inode *inode = mapping->host;
256
	size_t count = iov_iter_count(iter);
257
	ssize_t ret;
258
259
260

	if (rw == WRITE) {
		/*
261
		 * FIXME: blockdev_direct_IO() doesn't use ->write_begin(),
262
263
264
265
		 * so we need to update the ->mmu_private to block boundary.
		 *
		 * But we must fill the remaining area or hole by nul for
		 * updating ->mmu_private.
266
267
		 *
		 * Return 0, and fallback to normal buffered write.
268
		 */
269
		loff_t size = offset + count;
270
		if (MSDOS_I(inode)->mmu_private < size)
271
			return 0;
272
273
274
275
276
277
	}

	/*
	 * FAT need to use the DIO_LOCKING for avoiding the race
	 * condition of fat_get_block() and ->truncate().
	 */
278
	ret = blockdev_direct_IO(rw, iocb, inode, iter, offset, fat_get_block);
279
	if (ret < 0 && (rw & WRITE))
280
		fat_write_failed(mapping, offset + count);
281
282

	return ret;
283
284
}

Linus Torvalds's avatar
Linus Torvalds committed
285
286
static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
{
OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
287
288
289
	sector_t blocknr;

	/* fat_get_cluster() assumes the requested blocknr isn't truncated. */
290
	down_read(&MSDOS_I(mapping->host)->truncate_lock);
OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
291
	blocknr = generic_block_bmap(mapping, block, fat_get_block);
292
	up_read(&MSDOS_I(mapping->host)->truncate_lock);
OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
293
294

	return blocknr;
Linus Torvalds's avatar
Linus Torvalds committed
295
296
}

297
298
299
300
301
302
303
304
305
306
307
308
/*
 * fat_block_truncate_page() zeroes out a mapping from file offset `from'
 * up to the end of the block which corresponds to `from'.
 * This is required during truncate to physically zeroout the tail end
 * of that block so it doesn't yield old data if the file is later grown.
 * Also, avoid causing failure from fsx for cases of "data past EOF"
 */
int fat_block_truncate_page(struct inode *inode, loff_t from)
{
	return block_truncate_page(inode->i_mapping, from, fat_get_block);
}

309
static const struct address_space_operations fat_aops = {
Linus Torvalds's avatar
Linus Torvalds committed
310
	.readpage	= fat_readpage,
311
	.readpages	= fat_readpages,
Linus Torvalds's avatar
Linus Torvalds committed
312
	.writepage	= fat_writepage,
313
	.writepages	= fat_writepages,
Nick Piggin's avatar
Nick Piggin committed
314
315
	.write_begin	= fat_write_begin,
	.write_end	= fat_write_end,
316
	.direct_IO	= fat_direct_IO,
Linus Torvalds's avatar
Linus Torvalds committed
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
	.bmap		= _fat_bmap
};

/*
 * New FAT inode stuff. We do the following:
 *	a) i_ino is constant and has nothing with on-disk location.
 *	b) FAT manages its own cache of directory entries.
 *	c) *This* cache is indexed by on-disk location.
 *	d) inode has an associated directory entry, all right, but
 *		it may be unhashed.
 *	e) currently entries are stored within struct inode. That should
 *		change.
 *	f) we deal with races in the following way:
 *		1. readdir() and lookup() do FAT-dir-cache lookup.
 *		2. rename() unhashes the F-d-c entry and rehashes it in
 *			a new place.
 *		3. unlink() and rmdir() unhash F-d-c entry.
 *		4. fat_write_inode() checks whether the thing is unhashed.
 *			If it is we silently return. If it isn't we do bread(),
 *			check if the location is still valid and retry if it
 *			isn't. Otherwise we do changes.
 *		5. Spinlock is used to protect hash/unhash/location check/lookup
Al Viro's avatar
Al Viro committed
339
 *		6. fat_evict_inode() unhashes the F-d-c entry.
Linus Torvalds's avatar
Linus Torvalds committed
340
341
342
343
344
345
346
347
348
349
350
351
352
353
 *		7. lookup() and readdir() do igrab() if they find a F-d-c entry
 *			and consider negative result as cache miss.
 */

static void fat_hash_init(struct super_block *sb)
{
	struct msdos_sb_info *sbi = MSDOS_SB(sb);
	int i;

	spin_lock_init(&sbi->inode_hash_lock);
	for (i = 0; i < FAT_HASH_SIZE; i++)
		INIT_HLIST_HEAD(&sbi->inode_hashtable[i]);
}

OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
354
static inline unsigned long fat_hash(loff_t i_pos)
Linus Torvalds's avatar
Linus Torvalds committed
355
{
OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
356
	return hash_32(i_pos, FAT_HASH_BITS);
Linus Torvalds's avatar
Linus Torvalds committed
357
358
}

359
360
361
362
363
364
365
366
367
368
static void dir_hash_init(struct super_block *sb)
{
	struct msdos_sb_info *sbi = MSDOS_SB(sb);
	int i;

	spin_lock_init(&sbi->dir_hash_lock);
	for (i = 0; i < FAT_HASH_SIZE; i++)
		INIT_HLIST_HEAD(&sbi->dir_hashtable[i]);
}

Linus Torvalds's avatar
Linus Torvalds committed
369
370
void fat_attach(struct inode *inode, loff_t i_pos)
{
OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
371
	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
Linus Torvalds's avatar
Linus Torvalds committed
372

373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
	if (inode->i_ino != MSDOS_ROOT_INO) {
		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, head);
		spin_unlock(&sbi->inode_hash_lock);
	}

	/* If NFS support is enabled, cache the mapping of start cluster
	 * to directory inode. This is used during reconnection of
	 * dentries to the filesystem root.
	 */
	if (S_ISDIR(inode->i_mode) && sbi->options.nfs) {
		struct hlist_head *d_head = sbi->dir_hashtable;
		d_head += fat_dir_hash(MSDOS_I(inode)->i_logstart);

		spin_lock(&sbi->dir_hash_lock);
		hlist_add_head(&MSDOS_I(inode)->i_dir_hash, d_head);
		spin_unlock(&sbi->dir_hash_lock);
	}
Linus Torvalds's avatar
Linus Torvalds committed
395
}
396
EXPORT_SYMBOL_GPL(fat_attach);
Linus Torvalds's avatar
Linus Torvalds committed
397
398
399
400
401
402
403
404

void fat_detach(struct inode *inode)
{
	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
	spin_lock(&sbi->inode_hash_lock);
	MSDOS_I(inode)->i_pos = 0;
	hlist_del_init(&MSDOS_I(inode)->i_fat_hash);
	spin_unlock(&sbi->inode_hash_lock);
405
406
407
408
409
410

	if (S_ISDIR(inode->i_mode) && sbi->options.nfs) {
		spin_lock(&sbi->dir_hash_lock);
		hlist_del_init(&MSDOS_I(inode)->i_dir_hash);
		spin_unlock(&sbi->dir_hash_lock);
	}
Linus Torvalds's avatar
Linus Torvalds committed
411
}
412
EXPORT_SYMBOL_GPL(fat_detach);
Linus Torvalds's avatar
Linus Torvalds committed
413
414
415
416

struct inode *fat_iget(struct super_block *sb, loff_t i_pos)
{
	struct msdos_sb_info *sbi = MSDOS_SB(sb);
OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
417
	struct hlist_head *head = sbi->inode_hashtable + fat_hash(i_pos);
Linus Torvalds's avatar
Linus Torvalds committed
418
419
420
421
	struct msdos_inode_info *i;
	struct inode *inode = NULL;

	spin_lock(&sbi->inode_hash_lock);
422
	hlist_for_each_entry(i, head, i_fat_hash) {
Linus Torvalds's avatar
Linus Torvalds committed
423
424
425
426
427
428
429
430
431
432
433
434
435
		BUG_ON(i->vfs_inode.i_sb != sb);
		if (i->i_pos != i_pos)
			continue;
		inode = igrab(&i->vfs_inode);
		if (inode)
			break;
	}
	spin_unlock(&sbi->inode_hash_lock);
	return inode;
}

static int is_exec(unsigned char *extension)
{
436
	unsigned char exe_extensions[] = "EXECOMBAT", *walk;
Linus Torvalds's avatar
Linus Torvalds committed
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461

	for (walk = exe_extensions; *walk; walk += 3)
		if (!strncmp(extension, walk, 3))
			return 1;
	return 0;
}

static int fat_calc_dir_size(struct inode *inode)
{
	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
	int ret, fclus, dclus;

	inode->i_size = 0;
	if (MSDOS_I(inode)->i_start == 0)
		return 0;

	ret = fat_get_cluster(inode, FAT_ENT_EOF, &fclus, &dclus);
	if (ret < 0)
		return ret;
	inode->i_size = (fclus + 1) << sbi->cluster_bits;

	return 0;
}

/* doesn't deal with root inode */
462
int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
Linus Torvalds's avatar
Linus Torvalds committed
463
464
465
466
467
468
469
470
471
472
473
474
{
	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
	int error;

	MSDOS_I(inode)->i_pos = 0;
	inode->i_uid = sbi->options.fs_uid;
	inode->i_gid = sbi->options.fs_gid;
	inode->i_version++;
	inode->i_generation = get_seconds();

	if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) {
		inode->i_generation &= ~1;
475
		inode->i_mode = fat_make_mode(sbi, de->attr, S_IRWXUGO);
Linus Torvalds's avatar
Linus Torvalds committed
476
477
478
		inode->i_op = sbi->dir_ops;
		inode->i_fop = &fat_dir_operations;

479
		MSDOS_I(inode)->i_start = fat_get_start(sbi, de);
Linus Torvalds's avatar
Linus Torvalds committed
480
481
482
483
484
485
		MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start;
		error = fat_calc_dir_size(inode);
		if (error < 0)
			return error;
		MSDOS_I(inode)->mmu_private = inode->i_size;

Miklos Szeredi's avatar
Miklos Szeredi committed
486
		set_nlink(inode, fat_subdirs(inode));
Linus Torvalds's avatar
Linus Torvalds committed
487
488
	} else { /* not a directory */
		inode->i_generation |= 1;
489
490
491
		inode->i_mode = fat_make_mode(sbi, de->attr,
			((sbi->options.showexec && !is_exec(de->name + 8))
			 ? S_IRUGO|S_IWUGO : S_IRWXUGO));
492
		MSDOS_I(inode)->i_start = fat_get_start(sbi, de);
Linus Torvalds's avatar
Linus Torvalds committed
493
494
495
496
497
498
499
500
501
502
503
504

		MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start;
		inode->i_size = le32_to_cpu(de->size);
		inode->i_op = &fat_file_inode_operations;
		inode->i_fop = &fat_file_operations;
		inode->i_mapping->a_ops = &fat_aops;
		MSDOS_I(inode)->mmu_private = inode->i_size;
	}
	if (de->attr & ATTR_SYS) {
		if (sbi->options.sys_immutable)
			inode->i_flags |= S_IMMUTABLE;
	}
505
506
	fat_save_attrs(inode, de->attr);

Linus Torvalds's avatar
Linus Torvalds committed
507
508
	inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
			   & ~((loff_t)sbi->cluster_size - 1)) >> 9;
509
510

	fat_time_fat2unix(sbi, &inode->i_mtime, de->time, de->date, 0);
Linus Torvalds's avatar
Linus Torvalds committed
511
	if (sbi->options.isvfat) {
512
513
514
		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);
Linus Torvalds's avatar
Linus Torvalds committed
515
	} else
Stephane Kardas's avatar
Stephane Kardas committed
516
		inode->i_ctime = inode->i_atime = inode->i_mtime;
Linus Torvalds's avatar
Linus Torvalds committed
517
518
519
520

	return 0;
}

521
522
523
524
525
526
527
528
529
530
531
532
static inline void fat_lock_build_inode(struct msdos_sb_info *sbi)
{
	if (sbi->options.nfs == FAT_NFS_NOSTALE_RO)
		mutex_lock(&sbi->nfs_build_inode_lock);
}

static inline void fat_unlock_build_inode(struct msdos_sb_info *sbi)
{
	if (sbi->options.nfs == FAT_NFS_NOSTALE_RO)
		mutex_unlock(&sbi->nfs_build_inode_lock);
}

Linus Torvalds's avatar
Linus Torvalds committed
533
534
535
536
537
538
struct inode *fat_build_inode(struct super_block *sb,
			struct msdos_dir_entry *de, loff_t i_pos)
{
	struct inode *inode;
	int err;

539
	fat_lock_build_inode(MSDOS_SB(sb));
Linus Torvalds's avatar
Linus Torvalds committed
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
	inode = fat_iget(sb, i_pos);
	if (inode)
		goto out;
	inode = new_inode(sb);
	if (!inode) {
		inode = ERR_PTR(-ENOMEM);
		goto out;
	}
	inode->i_ino = iunique(sb, MSDOS_ROOT_INO);
	inode->i_version = 1;
	err = fat_fill_inode(inode, de);
	if (err) {
		iput(inode);
		inode = ERR_PTR(err);
		goto out;
	}
	fat_attach(inode, i_pos);
	insert_inode_hash(inode);
out:
559
	fat_unlock_build_inode(MSDOS_SB(sb));
Linus Torvalds's avatar
Linus Torvalds committed
560
561
562
	return inode;
}

563
EXPORT_SYMBOL_GPL(fat_build_inode);
Linus Torvalds's avatar
Linus Torvalds committed
564

Al Viro's avatar
Al Viro committed
565
static void fat_evict_inode(struct inode *inode)
Linus Torvalds's avatar
Linus Torvalds committed
566
{
567
	truncate_inode_pages_final(&inode->i_data);
Al Viro's avatar
Al Viro committed
568
569
570
571
572
	if (!inode->i_nlink) {
		inode->i_size = 0;
		fat_truncate_blocks(inode, 0);
	}
	invalidate_inode_buffers(inode);
573
	clear_inode(inode);
Linus Torvalds's avatar
Linus Torvalds committed
574
	fat_cache_inval_inode(inode);
575
	fat_detach(inode);
Linus Torvalds's avatar
Linus Torvalds committed
576
577
}

578
579
580
581
582
static void fat_set_state(struct super_block *sb,
			unsigned int set, unsigned int force)
{
	struct buffer_head *bh;
	struct fat_boot_sector *b;
583
	struct msdos_sb_info *sbi = MSDOS_SB(sb);
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624

	/* do not change any thing if mounted read only */
	if ((sb->s_flags & MS_RDONLY) && !force)
		return;

	/* do not change state if fs was dirty */
	if (sbi->dirty) {
		/* warn only on set (mount). */
		if (set)
			fat_msg(sb, KERN_WARNING, "Volume was not properly "
				"unmounted. Some data may be corrupt. "
				"Please run fsck.");
		return;
	}

	bh = sb_bread(sb, 0);
	if (bh == NULL) {
		fat_msg(sb, KERN_ERR, "unable to read boot sector "
			"to mark fs as dirty");
		return;
	}

	b = (struct fat_boot_sector *) bh->b_data;

	if (sbi->fat_bits == 32) {
		if (set)
			b->fat32.state |= FAT_STATE_DIRTY;
		else
			b->fat32.state &= ~FAT_STATE_DIRTY;
	} else /* fat 16 and 12 */ {
		if (set)
			b->fat16.state |= FAT_STATE_DIRTY;
		else
			b->fat16.state &= ~FAT_STATE_DIRTY;
	}

	mark_buffer_dirty(bh);
	sync_dirty_buffer(bh);
	brelse(bh);
}

625
626
627
628
629
630
631
632
633
634
static void delayed_free(struct rcu_head *p)
{
	struct msdos_sb_info *sbi = container_of(p, struct msdos_sb_info, rcu);
	unload_nls(sbi->nls_disk);
	unload_nls(sbi->nls_io);
	if (sbi->options.iocharset != fat_default_iocharset)
		kfree(sbi->options.iocharset);
	kfree(sbi);
}

635
636
637
static void fat_put_super(struct super_block *sb)
{
	struct msdos_sb_info *sbi = MSDOS_SB(sb);
Linus Torvalds's avatar
Linus Torvalds committed
638

639
640
	fat_set_state(sb, 0, 0);

641
	iput(sbi->fsinfo_inode);
Al Viro's avatar
Al Viro committed
642
643
	iput(sbi->fat_inode);

644
	call_rcu(&sbi->rcu, delayed_free);
Linus Torvalds's avatar
Linus Torvalds committed
645
646
}

647
static struct kmem_cache *fat_inode_cachep;
Linus Torvalds's avatar
Linus Torvalds committed
648
649
650
651

static struct inode *fat_alloc_inode(struct super_block *sb)
{
	struct msdos_inode_info *ei;
652
	ei = kmem_cache_alloc(fat_inode_cachep, GFP_NOFS);
Linus Torvalds's avatar
Linus Torvalds committed
653
654
	if (!ei)
		return NULL;
655
656

	init_rwsem(&ei->truncate_lock);
Linus Torvalds's avatar
Linus Torvalds committed
657
658
659
	return &ei->vfs_inode;
}

Nick Piggin's avatar
Nick Piggin committed
660
static void fat_i_callback(struct rcu_head *head)
Linus Torvalds's avatar
Linus Torvalds committed
661
{
Nick Piggin's avatar
Nick Piggin committed
662
	struct inode *inode = container_of(head, struct inode, i_rcu);
Linus Torvalds's avatar
Linus Torvalds committed
663
664
665
	kmem_cache_free(fat_inode_cachep, MSDOS_I(inode));
}

Nick Piggin's avatar
Nick Piggin committed
666
667
668
669
670
static void fat_destroy_inode(struct inode *inode)
{
	call_rcu(&inode->i_rcu, fat_i_callback);
}

671
static void init_once(void *foo)
Linus Torvalds's avatar
Linus Torvalds committed
672
673
674
{
	struct msdos_inode_info *ei = (struct msdos_inode_info *)foo;

675
676
677
678
679
	spin_lock_init(&ei->cache_lru_lock);
	ei->nr_caches = 0;
	ei->cache_valid_id = FAT_CACHE_VALID + 1;
	INIT_LIST_HEAD(&ei->cache_lru);
	INIT_HLIST_NODE(&ei->i_fat_hash);
680
	INIT_HLIST_NODE(&ei->i_dir_hash);
681
	inode_init_once(&ei->vfs_inode);
Linus Torvalds's avatar
Linus Torvalds committed
682
683
684
685
686
687
}

static int __init fat_init_inodecache(void)
{
	fat_inode_cachep = kmem_cache_create("fat_inode_cache",
					     sizeof(struct msdos_inode_info),
688
689
					     0, (SLAB_RECLAIM_ACCOUNT|
						SLAB_MEM_SPREAD),
690
					     init_once);
Linus Torvalds's avatar
Linus Torvalds committed
691
692
693
694
695
696
697
	if (fat_inode_cachep == NULL)
		return -ENOMEM;
	return 0;
}

static void __exit fat_destroy_inodecache(void)
{
698
699
700
701
702
	/*
	 * Make sure all delayed rcu free inodes are flushed before we
	 * destroy cache.
	 */
	rcu_barrier();
703
	kmem_cache_destroy(fat_inode_cachep);
Linus Torvalds's avatar
Linus Torvalds committed
704
705
706
707
}

static int fat_remount(struct super_block *sb, int *flags, char *data)
{
708
	int new_rdonly;
Linus Torvalds's avatar
Linus Torvalds committed
709
710
	struct msdos_sb_info *sbi = MSDOS_SB(sb);
	*flags |= MS_NODIRATIME | (sbi->options.isvfat ? 0 : MS_NOATIME);
711

712
713
	sync_filesystem(sb);

714
715
716
717
718
719
720
721
	/* make sure we update state on remount. */
	new_rdonly = *flags & MS_RDONLY;
	if (new_rdonly != (sb->s_flags & MS_RDONLY)) {
		if (new_rdonly)
			fat_set_state(sb, 0, 0);
		else
			fat_set_state(sb, 1, 1);
	}
Linus Torvalds's avatar
Linus Torvalds committed
722
723
724
	return 0;
}

725
static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)
Linus Torvalds's avatar
Linus Torvalds committed
726
{
Coly Li's avatar
Coly Li committed
727
728
729
	struct super_block *sb = dentry->d_sb;
	struct msdos_sb_info *sbi = MSDOS_SB(sb);
	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
Linus Torvalds's avatar
Linus Torvalds committed
730
731

	/* If the count of free cluster is still unknown, counts it here. */
732
	if (sbi->free_clusters == -1 || !sbi->free_clus_valid) {
733
		int err = fat_count_free_clusters(dentry->d_sb);
Linus Torvalds's avatar
Linus Torvalds committed
734
735
736
737
		if (err)
			return err;
	}

738
	buf->f_type = dentry->d_sb->s_magic;
Linus Torvalds's avatar
Linus Torvalds committed
739
740
741
742
	buf->f_bsize = sbi->cluster_size;
	buf->f_blocks = sbi->max_cluster - FAT_START_ENT;
	buf->f_bfree = sbi->free_clusters;
	buf->f_bavail = sbi->free_clusters;
Coly Li's avatar
Coly Li committed
743
744
	buf->f_fsid.val[0] = (u32)id;
	buf->f_fsid.val[1] = (u32)(id >> 32);
OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
745
746
	buf->f_namelen =
		(sbi->options.isvfat ? FAT_LFN_LEN : 12) * NLS_MAX_CHARSET_SIZE;
Linus Torvalds's avatar
Linus Torvalds committed
747
748
749
750

	return 0;
}

751
static int __fat_write_inode(struct inode *inode, int wait)
Linus Torvalds's avatar
Linus Torvalds committed
752
753
754
755
756
757
{
	struct super_block *sb = inode->i_sb;
	struct msdos_sb_info *sbi = MSDOS_SB(sb);
	struct buffer_head *bh;
	struct msdos_dir_entry *raw_entry;
	loff_t i_pos;
758
759
	sector_t blocknr;
	int err, offset;
Linus Torvalds's avatar
Linus Torvalds committed
760

OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
761
762
763
	if (inode->i_ino == MSDOS_ROOT_INO)
		return 0;

Linus Torvalds's avatar
Linus Torvalds committed
764
retry:
OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
765
766
	i_pos = fat_i_pos_read(sbi, inode);
	if (!i_pos)
Linus Torvalds's avatar
Linus Torvalds committed
767
768
		return 0;

769
770
	fat_get_blknr_offset(sbi, i_pos, &blocknr, &offset);
	bh = sb_bread(sb, blocknr);
Linus Torvalds's avatar
Linus Torvalds committed
771
	if (!bh) {
772
773
		fat_msg(sb, KERN_ERR, "unable to read inode block "
		       "for updating (i_pos %lld)", i_pos);
774
		return -EIO;
Linus Torvalds's avatar
Linus Torvalds committed
775
776
777
778
779
780
781
782
	}
	spin_lock(&sbi->inode_hash_lock);
	if (i_pos != MSDOS_I(inode)->i_pos) {
		spin_unlock(&sbi->inode_hash_lock);
		brelse(bh);
		goto retry;
	}

783
	raw_entry = &((struct msdos_dir_entry *) (bh->b_data))[offset];
Linus Torvalds's avatar
Linus Torvalds committed
784
785
786
787
	if (S_ISDIR(inode->i_mode))
		raw_entry->size = 0;
	else
		raw_entry->size = cpu_to_le32(inode->i_size);
788
	raw_entry->attr = fat_make_attrs(inode);
789
	fat_set_start(raw_entry, MSDOS_I(inode)->i_logstart);
790
791
	fat_time_unix2fat(sbi, &inode->i_mtime, &raw_entry->time,
			  &raw_entry->date, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
792
	if (sbi->options.isvfat) {
Stephane Kardas's avatar
Stephane Kardas committed
793
		__le16 atime;
794
795
796
797
		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);
Linus Torvalds's avatar
Linus Torvalds committed
798
799
800
	}
	spin_unlock(&sbi->inode_hash_lock);
	mark_buffer_dirty(bh);
801
	err = 0;
Linus Torvalds's avatar
Linus Torvalds committed
802
803
804
805
806
807
	if (wait)
		err = sync_dirty_buffer(bh);
	brelse(bh);
	return err;
}

808
809
static int fat_write_inode(struct inode *inode, struct writeback_control *wbc)
{
Artem Bityutskiy's avatar
Artem Bityutskiy committed
810
811
812
813
814
	int err;

	if (inode->i_ino == MSDOS_FSINFO_INO) {
		struct super_block *sb = inode->i_sb;

Marco Stornelli's avatar
Marco Stornelli committed
815
		mutex_lock(&MSDOS_SB(sb)->s_lock);
Artem Bityutskiy's avatar
Artem Bityutskiy committed
816
		err = fat_clusters_flush(sb);
Marco Stornelli's avatar
Marco Stornelli committed
817
		mutex_unlock(&MSDOS_SB(sb)->s_lock);
Artem Bityutskiy's avatar
Artem Bityutskiy committed
818
819
820
821
	} else
		err = __fat_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);

	return err;
822
823
}

Linus Torvalds's avatar
Linus Torvalds committed
824
825
int fat_sync_inode(struct inode *inode)
{
826
	return __fat_write_inode(inode, 1);
Linus Torvalds's avatar
Linus Torvalds committed
827
828
}

829
EXPORT_SYMBOL_GPL(fat_sync_inode);
Linus Torvalds's avatar
Linus Torvalds committed
830

831
static int fat_show_options(struct seq_file *m, struct dentry *root);
832
static const struct super_operations fat_sops = {
Linus Torvalds's avatar
Linus Torvalds committed
833
834
835
	.alloc_inode	= fat_alloc_inode,
	.destroy_inode	= fat_destroy_inode,
	.write_inode	= fat_write_inode,
Al Viro's avatar
Al Viro committed
836
	.evict_inode	= fat_evict_inode,
Linus Torvalds's avatar
Linus Torvalds committed
837
838
839
840
841
842
843
	.put_super	= fat_put_super,
	.statfs		= fat_statfs,
	.remount_fs	= fat_remount,

	.show_options	= fat_show_options,
};

844
static int fat_show_options(struct seq_file *m, struct dentry *root)
Linus Torvalds's avatar
Linus Torvalds committed
845
{
846
	struct msdos_sb_info *sbi = MSDOS_SB(root->d_sb);
Linus Torvalds's avatar
Linus Torvalds committed
847
848
849
	struct fat_mount_options *opts = &sbi->options;
	int isvfat = opts->isvfat;

850
851
852
853
854
855
	if (!uid_eq(opts->fs_uid, GLOBAL_ROOT_UID))
		seq_printf(m, ",uid=%u",
				from_kuid_munged(&init_user_ns, opts->fs_uid));
	if (!gid_eq(opts->fs_gid, GLOBAL_ROOT_GID))
		seq_printf(m, ",gid=%u",
				from_kgid_munged(&init_user_ns, opts->fs_gid));
Linus Torvalds's avatar
Linus Torvalds committed
856
857
	seq_printf(m, ",fmask=%04o", opts->fs_fmask);
	seq_printf(m, ",dmask=%04o", opts->fs_dmask);
OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
858
859
	if (opts->allow_utime)
		seq_printf(m, ",allow_utime=%04o", opts->allow_utime);
Linus Torvalds's avatar
Linus Torvalds committed
860
	if (sbi->nls_disk)
861
862
		/* strip "cp" prefix from displayed option */
		seq_printf(m, ",codepage=%s", &sbi->nls_disk->charset[2]);
Linus Torvalds's avatar
Linus Torvalds committed
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
	if (isvfat) {
		if (sbi->nls_io)
			seq_printf(m, ",iocharset=%s", sbi->nls_io->charset);

		switch (opts->shortname) {
		case VFAT_SFN_DISPLAY_WIN95 | VFAT_SFN_CREATE_WIN95:
			seq_puts(m, ",shortname=win95");
			break;
		case VFAT_SFN_DISPLAY_WINNT | VFAT_SFN_CREATE_WINNT:
			seq_puts(m, ",shortname=winnt");
			break;
		case VFAT_SFN_DISPLAY_WINNT | VFAT_SFN_CREATE_WIN95:
			seq_puts(m, ",shortname=mixed");
			break;
		case VFAT_SFN_DISPLAY_LOWER | VFAT_SFN_CREATE_WIN95:
878
			seq_puts(m, ",shortname=lower");
Linus Torvalds's avatar
Linus Torvalds committed
879
880
881
882
883
884
885
886
			break;
		default:
			seq_puts(m, ",shortname=unknown");
			break;
		}
	}
	if (opts->name_check != 'n')
		seq_printf(m, ",check=%c", opts->name_check);
887
888
	if (opts->usefree)
		seq_puts(m, ",usefree");
Linus Torvalds's avatar
Linus Torvalds committed
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
	if (opts->quiet)
		seq_puts(m, ",quiet");
	if (opts->showexec)
		seq_puts(m, ",showexec");
	if (opts->sys_immutable)
		seq_puts(m, ",sys_immutable");
	if (!isvfat) {
		if (opts->dotsOK)
			seq_puts(m, ",dotsOK=yes");
		if (opts->nocase)
			seq_puts(m, ",nocase");
	} else {
		if (opts->utf8)
			seq_puts(m, ",utf8");
		if (opts->unicode_xlate)
			seq_puts(m, ",uni_xlate");
		if (!opts->numtail)
			seq_puts(m, ",nonumtail");
907
908
		if (opts->rodir)
			seq_puts(m, ",rodir");
Linus Torvalds's avatar
Linus Torvalds committed
909
	}
910
	if (opts->flush)
Miklos Szeredi's avatar
Miklos Szeredi committed
911
		seq_puts(m, ",flush");
912
913
914
915
916
917
	if (opts->tz_set) {
		if (opts->time_offset)
			seq_printf(m, ",time_offset=%d", opts->time_offset);
		else
			seq_puts(m, ",tz=UTC");
	}
Denis Karpov's avatar
Denis Karpov committed
918
919
920
921
922
923
	if (opts->errors == FAT_ERRORS_CONT)
		seq_puts(m, ",errors=continue");
	else if (opts->errors == FAT_ERRORS_PANIC)
		seq_puts(m, ",errors=panic");
	else
		seq_puts(m, ",errors=remount-ro");
924
925
926
927
	if (opts->nfs == FAT_NFS_NOSTALE_RO)
		seq_puts(m, ",nfs=nostale_ro");
	else if (opts->nfs)
		seq_puts(m, ",nfs=stale_rw");
928
929
	if (opts->discard)
		seq_puts(m, ",discard");
930
931
	if (opts->dos1xfloppy)
		seq_puts(m, ",dos1xfloppy");
Linus Torvalds's avatar
Linus Torvalds committed
932
933
934
935
936
937

	return 0;
}

enum {
	Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid,
OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
938
939
940
	Opt_umask, Opt_dmask, Opt_fmask, Opt_allow_utime, Opt_codepage,
	Opt_usefree, Opt_nocase, Opt_quiet, Opt_showexec, Opt_debug,
	Opt_immutable, Opt_dots, Opt_nodots,
Linus Torvalds's avatar
Linus Torvalds committed
941
942
943
	Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
	Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
	Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
944
	Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont,
945
	Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_time_offset,
946
	Opt_nfs_stale_rw, Opt_nfs_nostale_ro, Opt_err, Opt_dos1xfloppy,
Linus Torvalds's avatar
Linus Torvalds committed
947
948
};

949
static const match_table_t fat_tokens = {
Linus Torvalds's avatar
Linus Torvalds committed
950
951
952
953
954
955
956
957
958
959
960
	{Opt_check_r, "check=relaxed"},
	{Opt_check_s, "check=strict"},
	{Opt_check_n, "check=normal"},
	{Opt_check_r, "check=r"},
	{Opt_check_s, "check=s"},
	{Opt_check_n, "check=n"},
	{Opt_uid, "uid=%u"},
	{Opt_gid, "gid=%u"},
	{Opt_umask, "umask=%o"},
	{Opt_dmask, "dmask=%o"},
	{Opt_fmask, "fmask=%o"},
OGAWA Hirofumi's avatar
OGAWA Hirofumi committed
961
	{Opt_allow_utime, "allow_utime=%o"},
Linus Torvalds's avatar
Linus Torvalds committed
962
	{Opt_codepage, "codepage=%u"},
963
	{Opt_usefree, "usefree"},
Linus Torvalds's avatar
Linus Torvalds committed
964
965
966
967
968
	{Opt_nocase, "nocase"},
	{Opt_quiet, "quiet"},
	{Opt_showexec, "showexec"},
	{Opt_debug, "debug"},
	{Opt_immutable, "sys_immutable"},
Denis Karpov's avatar
Denis Karpov committed
969
970
	{Opt_flush, "flush"},
	{Opt_tz_utc, "tz=UTC"},
971
	{Opt_time_offset, "time_offset=%d"},
Denis Karpov's avatar
Denis Karpov committed
972
973
974
	{Opt_err_cont, "errors=continue"},
	{Opt_err_panic, "errors=panic"},
	{Opt_err_ro, "errors=remount-ro"},
975
	{Opt_discard, "discard"},
976
977
978
	{Opt_nfs_stale_rw, "nfs"},
	{Opt_nfs_stale_rw, "nfs=stale_rw"},
	{Opt_nfs_nostale_ro, "nfs=nostale_ro"},
979
	{Opt_dos1xfloppy, "dos1xfloppy"},
980
981
982
983
984
985
986
987
988
989
990
	{Opt_obsolete, "conv=binary"},
	{Opt_obsolete, "conv=text"},
	{Opt_obsolete, "conv=auto"},
	{Opt_obsolete, "conv=b"},
	{Opt_obsolete, "conv=t"},
	{Opt_obsolete, "conv=a"},
	{Opt_obsolete, "fat=%u"},
	{Opt_obsolete, "blocksize=%u"},
	{Opt_obsolete, "cvf_format=%20s"},
	{Opt_obsolete, "cvf_options=%100s"},
	{Opt_obsolete, "posix"},
Chris Mason's avatar
Chris Mason committed
991
	{Opt_err, NULL},
Linus Torvalds's avatar
Linus Torvalds committed
992
};
993
static const match_table_t msdos_tokens = {
Linus Torvalds's avatar
Linus Torvalds committed
994
995
996
997
998
999
	{Opt_nodots, "nodots"},
	{Opt_nodots, "dotsOK=no"},
	{Opt_dots, "dots"},
	{Opt_dots, "dotsOK=yes"},
	{Opt_err, NULL}
};
1000
static const match_table_t vfat_tokens = {