inode.c 17.2 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
/*
 *  linux/fs/minix/inode.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
G
Gertjan van Wingerde 已提交
6
 *  Copyright (C) 1996  Gertjan van Wingerde
L
Linus Torvalds 已提交
7 8 9
 *	Minix V2 fs support.
 *
 *  Modified for 680x0 by Andreas Schwab
A
Andries Brouwer 已提交
10
 *  Updated to filesystem version 3 by Daniel Aragones
L
Linus Torvalds 已提交
11 12 13 14 15 16 17 18 19
 */

#include <linux/module.h>
#include "minix.h"
#include <linux/buffer_head.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/highuid.h>
#include <linux/vfs.h>
20
#include <linux/writeback.h>
L
Linus Torvalds 已提交
21

22 23
static int minix_write_inode(struct inode *inode,
		struct writeback_control *wbc);
24
static int minix_statfs(struct dentry *dentry, struct kstatfs *buf);
L
Linus Torvalds 已提交
25 26
static int minix_remount (struct super_block * sb, int * flags, char * data);

27
static void minix_evict_inode(struct inode *inode)
L
Linus Torvalds 已提交
28
{
29
	truncate_inode_pages(&inode->i_data, 0);
30 31 32 33 34 35 36 37
	if (!inode->i_nlink) {
		inode->i_size = 0;
		minix_truncate(inode);
	}
	invalidate_inode_buffers(inode);
	end_writeback(inode);
	if (!inode->i_nlink)
		minix_free_inode(inode);
L
Linus Torvalds 已提交
38 39 40 41 42 43 44 45
}

static void minix_put_super(struct super_block *sb)
{
	int i;
	struct minix_sb_info *sbi = minix_sb(sb);

	if (!(sb->s_flags & MS_RDONLY)) {
A
Andries Brouwer 已提交
46 47
		if (sbi->s_version != MINIX_V3)	 /* s_state is now out from V3 sb */
			sbi->s_ms->s_state = sbi->s_mount_state;
L
Linus Torvalds 已提交
48 49 50 51 52 53 54 55 56 57 58 59
		mark_buffer_dirty(sbi->s_sbh);
	}
	for (i = 0; i < sbi->s_imap_blocks; i++)
		brelse(sbi->s_imap[i]);
	for (i = 0; i < sbi->s_zmap_blocks; i++)
		brelse(sbi->s_zmap[i]);
	brelse (sbi->s_sbh);
	kfree(sbi->s_imap);
	sb->s_fs_info = NULL;
	kfree(sbi);
}

60
static struct kmem_cache * minix_inode_cachep;
L
Linus Torvalds 已提交
61 62 63 64

static struct inode *minix_alloc_inode(struct super_block *sb)
{
	struct minix_inode_info *ei;
65
	ei = (struct minix_inode_info *)kmem_cache_alloc(minix_inode_cachep, GFP_KERNEL);
L
Linus Torvalds 已提交
66 67 68 69 70 71 72 73 74 75
	if (!ei)
		return NULL;
	return &ei->vfs_inode;
}

static void minix_destroy_inode(struct inode *inode)
{
	kmem_cache_free(minix_inode_cachep, minix_i(inode));
}

76
static void init_once(void *foo)
L
Linus Torvalds 已提交
77 78 79
{
	struct minix_inode_info *ei = (struct minix_inode_info *) foo;

C
Christoph Lameter 已提交
80
	inode_init_once(&ei->vfs_inode);
L
Linus Torvalds 已提交
81
}
82

L
Linus Torvalds 已提交
83 84 85 86
static int init_inodecache(void)
{
	minix_inode_cachep = kmem_cache_create("minix_inode_cache",
					     sizeof(struct minix_inode_info),
87 88
					     0, (SLAB_RECLAIM_ACCOUNT|
						SLAB_MEM_SPREAD),
89
					     init_once);
L
Linus Torvalds 已提交
90 91 92 93 94 95 96
	if (minix_inode_cachep == NULL)
		return -ENOMEM;
	return 0;
}

static void destroy_inodecache(void)
{
97
	kmem_cache_destroy(minix_inode_cachep);
L
Linus Torvalds 已提交
98 99
}

100
static const struct super_operations minix_sops = {
L
Linus Torvalds 已提交
101 102 103
	.alloc_inode	= minix_alloc_inode,
	.destroy_inode	= minix_destroy_inode,
	.write_inode	= minix_write_inode,
104
	.evict_inode	= minix_evict_inode,
L
Linus Torvalds 已提交
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
	.put_super	= minix_put_super,
	.statfs		= minix_statfs,
	.remount_fs	= minix_remount,
};

static int minix_remount (struct super_block * sb, int * flags, char * data)
{
	struct minix_sb_info * sbi = minix_sb(sb);
	struct minix_super_block * ms;

	ms = sbi->s_ms;
	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
		return 0;
	if (*flags & MS_RDONLY) {
		if (ms->s_state & MINIX_VALID_FS ||
		    !(sbi->s_mount_state & MINIX_VALID_FS))
			return 0;
		/* Mounting a rw partition read-only. */
A
Andries Brouwer 已提交
123 124
		if (sbi->s_version != MINIX_V3)
			ms->s_state = sbi->s_mount_state;
L
Linus Torvalds 已提交
125 126 127
		mark_buffer_dirty(sbi->s_sbh);
	} else {
	  	/* Mount a partition which is read-only, read-write. */
A
Andries Brouwer 已提交
128 129 130 131 132 133
		if (sbi->s_version != MINIX_V3) {
			sbi->s_mount_state = ms->s_state;
			ms->s_state &= ~MINIX_VALID_FS;
		} else {
			sbi->s_mount_state = MINIX_VALID_FS;
		}
L
Linus Torvalds 已提交
134 135 136
		mark_buffer_dirty(sbi->s_sbh);

		if (!(sbi->s_mount_state & MINIX_VALID_FS))
137 138
			printk("MINIX-fs warning: remounting unchecked fs, "
				"running fsck is recommended\n");
L
Linus Torvalds 已提交
139
		else if ((sbi->s_mount_state & MINIX_ERROR_FS))
140 141
			printk("MINIX-fs warning: remounting fs with errors, "
				"running fsck is recommended\n");
L
Linus Torvalds 已提交
142 143 144 145 146 147 148 149 150
	}
	return 0;
}

static int minix_fill_super(struct super_block *s, void *data, int silent)
{
	struct buffer_head *bh;
	struct buffer_head **map;
	struct minix_super_block *ms;
A
Andries Brouwer 已提交
151 152
	struct minix3_super_block *m3s = NULL;
	unsigned long i, block;
L
Linus Torvalds 已提交
153 154
	struct inode *root_inode;
	struct minix_sb_info *sbi;
155
	int ret = -EINVAL;
L
Linus Torvalds 已提交
156

157
	sbi = kzalloc(sizeof(struct minix_sb_info), GFP_KERNEL);
L
Linus Torvalds 已提交
158 159 160 161
	if (!sbi)
		return -ENOMEM;
	s->s_fs_info = sbi;

A
Alexey Dobriyan 已提交
162 163
	BUILD_BUG_ON(32 != sizeof (struct minix_inode));
	BUILD_BUG_ON(64 != sizeof(struct minix2_inode));
L
Linus Torvalds 已提交
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204

	if (!sb_set_blocksize(s, BLOCK_SIZE))
		goto out_bad_hblock;

	if (!(bh = sb_bread(s, 1)))
		goto out_bad_sb;

	ms = (struct minix_super_block *) bh->b_data;
	sbi->s_ms = ms;
	sbi->s_sbh = bh;
	sbi->s_mount_state = ms->s_state;
	sbi->s_ninodes = ms->s_ninodes;
	sbi->s_nzones = ms->s_nzones;
	sbi->s_imap_blocks = ms->s_imap_blocks;
	sbi->s_zmap_blocks = ms->s_zmap_blocks;
	sbi->s_firstdatazone = ms->s_firstdatazone;
	sbi->s_log_zone_size = ms->s_log_zone_size;
	sbi->s_max_size = ms->s_max_size;
	s->s_magic = ms->s_magic;
	if (s->s_magic == MINIX_SUPER_MAGIC) {
		sbi->s_version = MINIX_V1;
		sbi->s_dirsize = 16;
		sbi->s_namelen = 14;
		sbi->s_link_max = MINIX_LINK_MAX;
	} else if (s->s_magic == MINIX_SUPER_MAGIC2) {
		sbi->s_version = MINIX_V1;
		sbi->s_dirsize = 32;
		sbi->s_namelen = 30;
		sbi->s_link_max = MINIX_LINK_MAX;
	} else if (s->s_magic == MINIX2_SUPER_MAGIC) {
		sbi->s_version = MINIX_V2;
		sbi->s_nzones = ms->s_zones;
		sbi->s_dirsize = 16;
		sbi->s_namelen = 14;
		sbi->s_link_max = MINIX2_LINK_MAX;
	} else if (s->s_magic == MINIX2_SUPER_MAGIC2) {
		sbi->s_version = MINIX_V2;
		sbi->s_nzones = ms->s_zones;
		sbi->s_dirsize = 32;
		sbi->s_namelen = 30;
		sbi->s_link_max = MINIX2_LINK_MAX;
A
Andries Brouwer 已提交
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
	} else if ( *(__u16 *)(bh->b_data + 24) == MINIX3_SUPER_MAGIC) {
		m3s = (struct minix3_super_block *) bh->b_data;
		s->s_magic = m3s->s_magic;
		sbi->s_imap_blocks = m3s->s_imap_blocks;
		sbi->s_zmap_blocks = m3s->s_zmap_blocks;
		sbi->s_firstdatazone = m3s->s_firstdatazone;
		sbi->s_log_zone_size = m3s->s_log_zone_size;
		sbi->s_max_size = m3s->s_max_size;
		sbi->s_ninodes = m3s->s_ninodes;
		sbi->s_nzones = m3s->s_zones;
		sbi->s_dirsize = 64;
		sbi->s_namelen = 60;
		sbi->s_version = MINIX_V3;
		sbi->s_link_max = MINIX2_LINK_MAX;
		sbi->s_mount_state = MINIX_VALID_FS;
		sb_set_blocksize(s, m3s->s_blocksize);
L
Linus Torvalds 已提交
221 222 223 224 225 226
	} else
		goto out_no_fs;

	/*
	 * Allocate the buffer map to keep the superblock small.
	 */
A
Andries Brouwer 已提交
227 228
	if (sbi->s_imap_blocks == 0 || sbi->s_zmap_blocks == 0)
		goto out_illegal_sb;
L
Linus Torvalds 已提交
229
	i = (sbi->s_imap_blocks + sbi->s_zmap_blocks) * sizeof(bh);
230
	map = kzalloc(i, GFP_KERNEL);
L
Linus Torvalds 已提交
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
	if (!map)
		goto out_no_map;
	sbi->s_imap = &map[0];
	sbi->s_zmap = &map[sbi->s_imap_blocks];

	block=2;
	for (i=0 ; i < sbi->s_imap_blocks ; i++) {
		if (!(sbi->s_imap[i]=sb_bread(s, block)))
			goto out_no_bitmap;
		block++;
	}
	for (i=0 ; i < sbi->s_zmap_blocks ; i++) {
		if (!(sbi->s_zmap[i]=sb_bread(s, block)))
			goto out_no_bitmap;
		block++;
	}

	minix_set_bit(0,sbi->s_imap[0]->b_data);
	minix_set_bit(0,sbi->s_zmap[0]->b_data);

	/* set up enough so that it can read an inode */
	s->s_op = &minix_sops;
253 254 255
	root_inode = minix_iget(s, MINIX_ROOT_INO);
	if (IS_ERR(root_inode)) {
		ret = PTR_ERR(root_inode);
L
Linus Torvalds 已提交
256
		goto out_no_root;
257
	}
L
Linus Torvalds 已提交
258

259
	ret = -ENOMEM;
L
Linus Torvalds 已提交
260 261 262 263 264
	s->s_root = d_alloc_root(root_inode);
	if (!s->s_root)
		goto out_iput;

	if (!(s->s_flags & MS_RDONLY)) {
A
Andries Brouwer 已提交
265 266
		if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */
			ms->s_state &= ~MINIX_VALID_FS;
L
Linus Torvalds 已提交
267 268 269
		mark_buffer_dirty(bh);
	}
	if (!(sbi->s_mount_state & MINIX_VALID_FS))
270 271
		printk("MINIX-fs: mounting unchecked file system, "
			"running fsck is recommended\n");
L
Linus Torvalds 已提交
272
 	else if (sbi->s_mount_state & MINIX_ERROR_FS)
273 274
		printk("MINIX-fs: mounting file system with errors, "
			"running fsck is recommended\n");
L
Linus Torvalds 已提交
275 276 277 278 279 280 281 282 283 284 285 286 287
	return 0;

out_iput:
	iput(root_inode);
	goto out_freemap;

out_no_root:
	if (!silent)
		printk("MINIX-fs: get root inode failed\n");
	goto out_freemap;

out_no_bitmap:
	printk("MINIX-fs: bad superblock or unable to read bitmaps\n");
A
Andries Brouwer 已提交
288
out_freemap:
L
Linus Torvalds 已提交
289 290 291 292 293 294 295 296
	for (i = 0; i < sbi->s_imap_blocks; i++)
		brelse(sbi->s_imap[i]);
	for (i = 0; i < sbi->s_zmap_blocks; i++)
		brelse(sbi->s_zmap[i]);
	kfree(sbi->s_imap);
	goto out_release;

out_no_map:
297
	ret = -ENOMEM;
L
Linus Torvalds 已提交
298
	if (!silent)
299
		printk("MINIX-fs: can't allocate map\n");
L
Linus Torvalds 已提交
300 301
	goto out_release;

A
Andries Brouwer 已提交
302 303 304 305 306
out_illegal_sb:
	if (!silent)
		printk("MINIX-fs: bad superblock\n");
	goto out_release;

L
Linus Torvalds 已提交
307 308
out_no_fs:
	if (!silent)
A
Andries Brouwer 已提交
309 310
		printk("VFS: Can't find a Minix filesystem V1 | V2 | V3 "
		       "on device %s.\n", s->s_id);
A
Andries Brouwer 已提交
311
out_release:
L
Linus Torvalds 已提交
312 313 314 315
	brelse(bh);
	goto out;

out_bad_hblock:
316
	printk("MINIX-fs: blocksize too small for device\n");
L
Linus Torvalds 已提交
317 318 319 320
	goto out;

out_bad_sb:
	printk("MINIX-fs: unable to read superblock\n");
A
Andries Brouwer 已提交
321
out:
L
Linus Torvalds 已提交
322 323
	s->s_fs_info = NULL;
	kfree(sbi);
324
	return ret;
L
Linus Torvalds 已提交
325 326
}

327
static int minix_statfs(struct dentry *dentry, struct kstatfs *buf)
L
Linus Torvalds 已提交
328
{
C
Coly Li 已提交
329 330 331 332 333
	struct super_block *sb = dentry->d_sb;
	struct minix_sb_info *sbi = minix_sb(sb);
	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
	buf->f_type = sb->s_magic;
	buf->f_bsize = sb->s_blocksize;
L
Linus Torvalds 已提交
334 335 336 337 338 339
	buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size;
	buf->f_bfree = minix_count_free_blocks(sbi);
	buf->f_bavail = buf->f_bfree;
	buf->f_files = sbi->s_ninodes;
	buf->f_ffree = minix_count_free_inodes(sbi);
	buf->f_namelen = sbi->s_namelen;
C
Coly Li 已提交
340 341 342
	buf->f_fsid.val[0] = (u32)id;
	buf->f_fsid.val[1] = (u32)(id >> 32);

L
Linus Torvalds 已提交
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
	return 0;
}

static int minix_get_block(struct inode *inode, sector_t block,
		    struct buffer_head *bh_result, int create)
{
	if (INODE_VERSION(inode) == MINIX_V1)
		return V1_minix_get_block(inode, block, bh_result, create);
	else
		return V2_minix_get_block(inode, block, bh_result, create);
}

static int minix_writepage(struct page *page, struct writeback_control *wbc)
{
	return block_write_full_page(page, minix_get_block, wbc);
}
N
Nick Piggin 已提交
359

L
Linus Torvalds 已提交
360 361 362 363
static int minix_readpage(struct file *file, struct page *page)
{
	return block_read_full_page(page,minix_get_block);
}
N
Nick Piggin 已提交
364

365
int minix_prepare_chunk(struct page *page, loff_t pos, unsigned len)
L
Linus Torvalds 已提交
366
{
367
	return __block_write_begin(page, pos, len, minix_get_block);
L
Linus Torvalds 已提交
368
}
N
Nick Piggin 已提交
369 370 371 372 373

static int minix_write_begin(struct file *file, struct address_space *mapping,
			loff_t pos, unsigned len, unsigned flags,
			struct page **pagep, void **fsdata)
{
374 375 376
	int ret;

	ret = block_write_begin(mapping, pos, len, flags, pagep,
377
				minix_get_block);
378 379 380 381 382 383 384
	if (unlikely(ret)) {
		loff_t isize = mapping->host->i_size;
		if (pos + len > isize)
			vmtruncate(mapping->host, isize);
	}

	return ret;
N
Nick Piggin 已提交
385 386
}

L
Linus Torvalds 已提交
387 388 389 390
static sector_t minix_bmap(struct address_space *mapping, sector_t block)
{
	return generic_block_bmap(mapping,block,minix_get_block);
}
N
Nick Piggin 已提交
391

392
static const struct address_space_operations minix_aops = {
L
Linus Torvalds 已提交
393 394 395
	.readpage = minix_readpage,
	.writepage = minix_writepage,
	.sync_page = block_sync_page,
N
Nick Piggin 已提交
396 397
	.write_begin = minix_write_begin,
	.write_end = generic_write_end,
L
Linus Torvalds 已提交
398 399 400
	.bmap = minix_bmap
};

401
static const struct inode_operations minix_symlink_inode_operations = {
L
Linus Torvalds 已提交
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
	.readlink	= generic_readlink,
	.follow_link	= page_follow_link_light,
	.put_link	= page_put_link,
	.getattr	= minix_getattr,
};

void minix_set_inode(struct inode *inode, dev_t rdev)
{
	if (S_ISREG(inode->i_mode)) {
		inode->i_op = &minix_file_inode_operations;
		inode->i_fop = &minix_file_operations;
		inode->i_mapping->a_ops = &minix_aops;
	} else if (S_ISDIR(inode->i_mode)) {
		inode->i_op = &minix_dir_inode_operations;
		inode->i_fop = &minix_dir_operations;
		inode->i_mapping->a_ops = &minix_aops;
	} else if (S_ISLNK(inode->i_mode)) {
		inode->i_op = &minix_symlink_inode_operations;
		inode->i_mapping->a_ops = &minix_aops;
	} else
		init_special_inode(inode, inode->i_mode, rdev);
}

/*
 * The minix V1 function to read an inode.
 */
428
static struct inode *V1_minix_iget(struct inode *inode)
L
Linus Torvalds 已提交
429 430 431 432 433 434 435 436
{
	struct buffer_head * bh;
	struct minix_inode * raw_inode;
	struct minix_inode_info *minix_inode = minix_i(inode);
	int i;

	raw_inode = minix_V1_raw_inode(inode->i_sb, inode->i_ino, &bh);
	if (!raw_inode) {
437 438
		iget_failed(inode);
		return ERR_PTR(-EIO);
L
Linus Torvalds 已提交
439 440 441 442 443 444 445 446 447 448
	}
	inode->i_mode = raw_inode->i_mode;
	inode->i_uid = (uid_t)raw_inode->i_uid;
	inode->i_gid = (gid_t)raw_inode->i_gid;
	inode->i_nlink = raw_inode->i_nlinks;
	inode->i_size = raw_inode->i_size;
	inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = raw_inode->i_time;
	inode->i_mtime.tv_nsec = 0;
	inode->i_atime.tv_nsec = 0;
	inode->i_ctime.tv_nsec = 0;
449
	inode->i_blocks = 0;
L
Linus Torvalds 已提交
450 451 452 453
	for (i = 0; i < 9; i++)
		minix_inode->u.i1_data[i] = raw_inode->i_zone[i];
	minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0]));
	brelse(bh);
454 455
	unlock_new_inode(inode);
	return inode;
L
Linus Torvalds 已提交
456 457 458 459 460
}

/*
 * The minix V2 function to read an inode.
 */
461
static struct inode *V2_minix_iget(struct inode *inode)
L
Linus Torvalds 已提交
462 463 464 465 466 467 468 469
{
	struct buffer_head * bh;
	struct minix2_inode * raw_inode;
	struct minix_inode_info *minix_inode = minix_i(inode);
	int i;

	raw_inode = minix_V2_raw_inode(inode->i_sb, inode->i_ino, &bh);
	if (!raw_inode) {
470 471
		iget_failed(inode);
		return ERR_PTR(-EIO);
L
Linus Torvalds 已提交
472 473 474 475 476 477 478 479 480 481 482 483
	}
	inode->i_mode = raw_inode->i_mode;
	inode->i_uid = (uid_t)raw_inode->i_uid;
	inode->i_gid = (gid_t)raw_inode->i_gid;
	inode->i_nlink = raw_inode->i_nlinks;
	inode->i_size = raw_inode->i_size;
	inode->i_mtime.tv_sec = raw_inode->i_mtime;
	inode->i_atime.tv_sec = raw_inode->i_atime;
	inode->i_ctime.tv_sec = raw_inode->i_ctime;
	inode->i_mtime.tv_nsec = 0;
	inode->i_atime.tv_nsec = 0;
	inode->i_ctime.tv_nsec = 0;
484
	inode->i_blocks = 0;
L
Linus Torvalds 已提交
485 486 487 488
	for (i = 0; i < 10; i++)
		minix_inode->u.i2_data[i] = raw_inode->i_zone[i];
	minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0]));
	brelse(bh);
489 490
	unlock_new_inode(inode);
	return inode;
L
Linus Torvalds 已提交
491 492 493 494 495
}

/*
 * The global function to read an inode.
 */
496
struct inode *minix_iget(struct super_block *sb, unsigned long ino)
L
Linus Torvalds 已提交
497
{
498 499 500 501 502 503 504 505
	struct inode *inode;

	inode = iget_locked(sb, ino);
	if (!inode)
		return ERR_PTR(-ENOMEM);
	if (!(inode->i_state & I_NEW))
		return inode;

L
Linus Torvalds 已提交
506
	if (INODE_VERSION(inode) == MINIX_V1)
507
		return V1_minix_iget(inode);
L
Linus Torvalds 已提交
508
	else
509
		return V2_minix_iget(inode);
L
Linus Torvalds 已提交
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
}

/*
 * The minix V1 function to synchronize an inode.
 */
static struct buffer_head * V1_minix_update_inode(struct inode * inode)
{
	struct buffer_head * bh;
	struct minix_inode * raw_inode;
	struct minix_inode_info *minix_inode = minix_i(inode);
	int i;

	raw_inode = minix_V1_raw_inode(inode->i_sb, inode->i_ino, &bh);
	if (!raw_inode)
		return NULL;
	raw_inode->i_mode = inode->i_mode;
	raw_inode->i_uid = fs_high2lowuid(inode->i_uid);
	raw_inode->i_gid = fs_high2lowgid(inode->i_gid);
	raw_inode->i_nlinks = inode->i_nlink;
	raw_inode->i_size = inode->i_size;
	raw_inode->i_time = inode->i_mtime.tv_sec;
	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
		raw_inode->i_zone[0] = old_encode_dev(inode->i_rdev);
	else for (i = 0; i < 9; i++)
		raw_inode->i_zone[i] = minix_inode->u.i1_data[i];
	mark_buffer_dirty(bh);
	return bh;
}

/*
 * The minix V2 function to synchronize an inode.
 */
static struct buffer_head * V2_minix_update_inode(struct inode * inode)
{
	struct buffer_head * bh;
	struct minix2_inode * raw_inode;
	struct minix_inode_info *minix_inode = minix_i(inode);
	int i;

	raw_inode = minix_V2_raw_inode(inode->i_sb, inode->i_ino, &bh);
	if (!raw_inode)
		return NULL;
	raw_inode->i_mode = inode->i_mode;
	raw_inode->i_uid = fs_high2lowuid(inode->i_uid);
	raw_inode->i_gid = fs_high2lowgid(inode->i_gid);
	raw_inode->i_nlinks = inode->i_nlink;
	raw_inode->i_size = inode->i_size;
	raw_inode->i_mtime = inode->i_mtime.tv_sec;
	raw_inode->i_atime = inode->i_atime.tv_sec;
	raw_inode->i_ctime = inode->i_ctime.tv_sec;
	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
		raw_inode->i_zone[0] = old_encode_dev(inode->i_rdev);
	else for (i = 0; i < 10; i++)
		raw_inode->i_zone[i] = minix_inode->u.i2_data[i];
	mark_buffer_dirty(bh);
	return bh;
}

568
static int minix_write_inode(struct inode *inode, struct writeback_control *wbc)
L
Linus Torvalds 已提交
569 570 571 572
{
	int err = 0;
	struct buffer_head *bh;

A
Al Viro 已提交
573 574 575 576 577 578
	if (INODE_VERSION(inode) == MINIX_V1)
		bh = V1_minix_update_inode(inode);
	else
		bh = V2_minix_update_inode(inode);
	if (!bh)
		return -EIO;
579
	if (wbc->sync_mode == WB_SYNC_ALL && buffer_dirty(bh)) {
L
Linus Torvalds 已提交
580
		sync_dirty_buffer(bh);
A
Al Viro 已提交
581
		if (buffer_req(bh) && !buffer_uptodate(bh)) {
582
			printk("IO error syncing minix inode [%s:%08lx]\n",
L
Linus Torvalds 已提交
583
				inode->i_sb->s_id, inode->i_ino);
A
Al Viro 已提交
584
			err = -EIO;
L
Linus Torvalds 已提交
585 586 587 588 589 590 591 592
		}
	}
	brelse (bh);
	return err;
}

int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
{
A
Andries Brouwer 已提交
593 594
	struct inode *dir = dentry->d_parent->d_inode;
	struct super_block *sb = dir->i_sb;
L
Linus Torvalds 已提交
595 596
	generic_fillattr(dentry->d_inode, stat);
	if (INODE_VERSION(dentry->d_inode) == MINIX_V1)
A
Andries Brouwer 已提交
597
		stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size, sb);
L
Linus Torvalds 已提交
598
	else
A
Andries Brouwer 已提交
599 600
		stat->blocks = (sb->s_blocksize / 512) * V2_minix_blocks(stat->size, sb);
	stat->blksize = sb->s_blocksize;
L
Linus Torvalds 已提交
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
	return 0;
}

/*
 * The function that is called for file truncation.
 */
void minix_truncate(struct inode * inode)
{
	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)))
		return;
	if (INODE_VERSION(inode) == MINIX_V1)
		V1_minix_truncate(inode);
	else
		V2_minix_truncate(inode);
}

617 618
static int minix_get_sb(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
L
Linus Torvalds 已提交
619
{
620 621
	return get_sb_bdev(fs_type, flags, dev_name, data, minix_fill_super,
			   mnt);
L
Linus Torvalds 已提交
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656
}

static struct file_system_type minix_fs_type = {
	.owner		= THIS_MODULE,
	.name		= "minix",
	.get_sb		= minix_get_sb,
	.kill_sb	= kill_block_super,
	.fs_flags	= FS_REQUIRES_DEV,
};

static int __init init_minix_fs(void)
{
	int err = init_inodecache();
	if (err)
		goto out1;
	err = register_filesystem(&minix_fs_type);
	if (err)
		goto out;
	return 0;
out:
	destroy_inodecache();
out1:
	return err;
}

static void __exit exit_minix_fs(void)
{
        unregister_filesystem(&minix_fs_type);
	destroy_inodecache();
}

module_init(init_minix_fs)
module_exit(exit_minix_fs)
MODULE_LICENSE("GPL");