Blame view

fs/minix/inode.c 17.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
  /*
   *  linux/fs/minix/inode.c
   *
   *  Copyright (C) 1991, 1992  Linus Torvalds
   *
f762dd682   Gertjan van Wingerde   Update my email a...
6
   *  Copyright (C) 1996  Gertjan van Wingerde
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
   *	Minix V2 fs support.
   *
   *  Modified for 680x0 by Andreas Schwab
939b00df0   Andries Brouwer   [PATCH] Minix V3 ...
10
   *  Updated to filesystem version 3 by Daniel Aragones
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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>
a9185b41a   Christoph Hellwig   pass writeback_co...
20
  #include <linux/writeback.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21

a9185b41a   Christoph Hellwig   pass writeback_co...
22
23
  static int minix_write_inode(struct inode *inode,
  		struct writeback_control *wbc);
726c33422   David Howells   [PATCH] VFS: Perm...
24
  static int minix_statfs(struct dentry *dentry, struct kstatfs *buf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
  static int minix_remount (struct super_block * sb, int * flags, char * data);
5ccb4a78d   Al Viro   switch minix to -...
26
  static void minix_evict_inode(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
  {
fef266580   Mark Fasheh   [PATCH] update fi...
28
  	truncate_inode_pages(&inode->i_data, 0);
5ccb4a78d   Al Viro   switch minix to -...
29
30
31
32
33
34
35
36
  	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);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
41
42
43
44
  }
  
  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)) {
939b00df0   Andries Brouwer   [PATCH] Minix V3 ...
45
46
  		if (sbi->s_version != MINIX_V3)	 /* s_state is now out from V3 sb */
  			sbi->s_ms->s_state = sbi->s_mount_state;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
49
50
51
52
53
54
55
56
  		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);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
  }
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
58
  static struct kmem_cache * minix_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
62
  
  static struct inode *minix_alloc_inode(struct super_block *sb)
  {
  	struct minix_inode_info *ei;
e94b17660   Christoph Lameter   [PATCH] slab: rem...
63
  	ei = (struct minix_inode_info *)kmem_cache_alloc(minix_inode_cachep, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
  	if (!ei)
  		return NULL;
  	return &ei->vfs_inode;
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
68
  static void minix_i_callback(struct rcu_head *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
  {
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
70
  	struct inode *inode = container_of(head, struct inode, i_rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
  	kmem_cache_free(minix_inode_cachep, minix_i(inode));
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
73
74
75
76
  static void minix_destroy_inode(struct inode *inode)
  {
  	call_rcu(&inode->i_rcu, minix_i_callback);
  }
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
77
  static void init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
  {
  	struct minix_inode_info *ei = (struct minix_inode_info *) foo;
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
80
  	inode_init_once(&ei->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  }
20c2df83d   Paul Mundt   mm: Remove slab d...
82

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
84
85
86
  static int init_inodecache(void)
  {
  	minix_inode_cachep = kmem_cache_create("minix_inode_cache",
  					     sizeof(struct minix_inode_info),
fffb60f93   Paul Jackson   [PATCH] cpuset me...
87
88
  					     0, (SLAB_RECLAIM_ACCOUNT|
  						SLAB_MEM_SPREAD),
20c2df83d   Paul Mundt   mm: Remove slab d...
89
  					     init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
91
92
93
94
95
96
  	if (minix_inode_cachep == NULL)
  		return -ENOMEM;
  	return 0;
  }
  
  static void destroy_inodecache(void)
  {
1a1d92c10   Alexey Dobriyan   [PATCH] Really ig...
97
  	kmem_cache_destroy(minix_inode_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  }
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
99
  static const struct super_operations minix_sops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
  	.alloc_inode	= minix_alloc_inode,
  	.destroy_inode	= minix_destroy_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
  	.write_inode	= minix_write_inode,
5ccb4a78d   Al Viro   switch minix to -...
103
  	.evict_inode	= minix_evict_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
  	.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. */
939b00df0   Andries Brouwer   [PATCH] Minix V3 ...
122
123
  		if (sbi->s_version != MINIX_V3)
  			ms->s_state = sbi->s_mount_state;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
126
  		mark_buffer_dirty(sbi->s_sbh);
  	} else {
  	  	/* Mount a partition which is read-only, read-write. */
939b00df0   Andries Brouwer   [PATCH] Minix V3 ...
127
128
129
130
131
132
  		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;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
134
135
  		mark_buffer_dirty(sbi->s_sbh);
  
  		if (!(sbi->s_mount_state & MINIX_VALID_FS))
11b844875   Denis Vlasenko   [PATCH] fix messa...
136
137
138
  			printk("MINIX-fs warning: remounting unchecked fs, "
  				"running fsck is recommended
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
  		else if ((sbi->s_mount_state & MINIX_ERROR_FS))
11b844875   Denis Vlasenko   [PATCH] fix messa...
140
141
142
  			printk("MINIX-fs warning: remounting fs with errors, "
  				"running fsck is recommended
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
145
146
147
148
149
150
151
  	}
  	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;
939b00df0   Andries Brouwer   [PATCH] Minix V3 ...
152
153
  	struct minix3_super_block *m3s = NULL;
  	unsigned long i, block;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
  	struct inode *root_inode;
  	struct minix_sb_info *sbi;
a90a08802   David Howells   iget: stop the MI...
156
  	int ret = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157

f8314dc60   Panagiotis Issaris   [PATCH] fs: Conve...
158
  	sbi = kzalloc(sizeof(struct minix_sb_info), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
161
  	if (!sbi)
  		return -ENOMEM;
  	s->s_fs_info = sbi;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162

2ecd05ae6   Alexey Dobriyan   [PATCH] fs/*: use...
163
164
  	BUILD_BUG_ON(32 != sizeof (struct minix_inode));
  	BUILD_BUG_ON(64 != sizeof(struct minix2_inode));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
205
  
  	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;
939b00df0   Andries Brouwer   [PATCH] Minix V3 ...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
  	} 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);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
224
225
226
227
  	} else
  		goto out_no_fs;
  
  	/*
  	 * Allocate the buffer map to keep the superblock small.
  	 */
f5fb09fa3   Andries Brouwer   [PATCH] Fix for m...
228
229
  	if (sbi->s_imap_blocks == 0 || sbi->s_zmap_blocks == 0)
  		goto out_illegal_sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
  	i = (sbi->s_imap_blocks + sbi->s_zmap_blocks) * sizeof(bh);
f8314dc60   Panagiotis Issaris   [PATCH] fs: Conve...
231
  	map = kzalloc(i, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
  	if (!map)
  		goto out_no_map;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
  	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;
a90a08802   David Howells   iget: stop the MI...
254
255
256
  	root_inode = minix_iget(s, MINIX_ROOT_INO);
  	if (IS_ERR(root_inode)) {
  		ret = PTR_ERR(root_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
  		goto out_no_root;
a90a08802   David Howells   iget: stop the MI...
258
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259

016e8d44b   Josh Boyer   fs/minix: Verify ...
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
  	/* Apparently minix can create filesystems that allocate more blocks for
  	 * the bitmaps than needed.  We simply ignore that, but verify it didn't
  	 * create one with not enough blocks and bail out if so.
  	 */
  	block = minix_blocks_needed(sbi->s_ninodes, s->s_blocksize);
  	if (sbi->s_imap_blocks < block) {
  		printk("MINIX-fs: file system does not have enough "
  				"imap blocks allocated.  Refusing to mount
  ");
  		goto out_iput;
  	}
  
  	block = minix_blocks_needed(
  			(sbi->s_nzones - (sbi->s_firstdatazone + 1)),
  			s->s_blocksize);
  	if (sbi->s_zmap_blocks < block) {
  		printk("MINIX-fs: file system does not have enough "
  				"zmap blocks allocated.  Refusing to mount.
  ");
  		goto out_iput;
  	}
d6042eac4   Al Viro   minixfs: misplace...
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
  	ret = -ENOMEM;
  	s->s_root = d_alloc_root(root_inode);
  	if (!s->s_root)
  		goto out_iput;
  
  	if (!(s->s_flags & MS_RDONLY)) {
  		if (sbi->s_version != MINIX_V3) /* s_state is now out from V3 sb */
  			ms->s_state &= ~MINIX_VALID_FS;
  		mark_buffer_dirty(bh);
  	}
  	if (!(sbi->s_mount_state & MINIX_VALID_FS))
  		printk("MINIX-fs: mounting unchecked file system, "
  			"running fsck is recommended
  ");
  	else if (sbi->s_mount_state & MINIX_ERROR_FS)
  		printk("MINIX-fs: mounting file system with errors, "
  			"running fsck is recommended
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
  	return 0;
  
  out_iput:
  	iput(root_inode);
  	goto out_freemap;
  
  out_no_root:
  	if (!silent)
  		printk("MINIX-fs: get root inode failed
  ");
  	goto out_freemap;
  
  out_no_bitmap:
  	printk("MINIX-fs: bad superblock or unable to read bitmaps
  ");
f5fb09fa3   Andries Brouwer   [PATCH] Fix for m...
314
  out_freemap:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
316
317
318
319
320
321
322
  	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:
a90a08802   David Howells   iget: stop the MI...
323
  	ret = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
324
  	if (!silent)
11b844875   Denis Vlasenko   [PATCH] fix messa...
325
326
  		printk("MINIX-fs: can't allocate map
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
  	goto out_release;
f5fb09fa3   Andries Brouwer   [PATCH] Fix for m...
328
329
330
331
332
  out_illegal_sb:
  	if (!silent)
  		printk("MINIX-fs: bad superblock
  ");
  	goto out_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
334
  out_no_fs:
  	if (!silent)
939b00df0   Andries Brouwer   [PATCH] Minix V3 ...
335
336
337
  		printk("VFS: Can't find a Minix filesystem V1 | V2 | V3 "
  		       "on device %s.
  ", s->s_id);
f5fb09fa3   Andries Brouwer   [PATCH] Fix for m...
338
  out_release:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
341
342
  	brelse(bh);
  	goto out;
  
  out_bad_hblock:
11b844875   Denis Vlasenko   [PATCH] fix messa...
343
344
  	printk("MINIX-fs: blocksize too small for device
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
346
347
348
349
  	goto out;
  
  out_bad_sb:
  	printk("MINIX-fs: unable to read superblock
  ");
f5fb09fa3   Andries Brouwer   [PATCH] Fix for m...
350
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
  	s->s_fs_info = NULL;
  	kfree(sbi);
a90a08802   David Howells   iget: stop the MI...
353
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
  }
726c33422   David Howells   [PATCH] VFS: Perm...
355
  static int minix_statfs(struct dentry *dentry, struct kstatfs *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
  {
054475d2a   Coly Li   fs/minix: return ...
357
358
359
360
361
  	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;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
  	buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size;
016e8d44b   Josh Boyer   fs/minix: Verify ...
363
  	buf->f_bfree = minix_count_free_blocks(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
365
  	buf->f_bavail = buf->f_bfree;
  	buf->f_files = sbi->s_ninodes;
016e8d44b   Josh Boyer   fs/minix: Verify ...
366
  	buf->f_ffree = minix_count_free_inodes(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
  	buf->f_namelen = sbi->s_namelen;
054475d2a   Coly Li   fs/minix: return ...
368
369
  	buf->f_fsid.val[0] = (u32)id;
  	buf->f_fsid.val[1] = (u32)(id >> 32);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
  	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);
  }
4a66af9ea   Nick Piggin   minixfs: convert ...
386

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
388
389
390
  static int minix_readpage(struct file *file, struct page *page)
  {
  	return block_read_full_page(page,minix_get_block);
  }
4a66af9ea   Nick Piggin   minixfs: convert ...
391

f4e420dc4   Christoph Hellwig   clean up write_be...
392
  int minix_prepare_chunk(struct page *page, loff_t pos, unsigned len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
  {
6e1db88d5   Christoph Hellwig   introduce __block...
394
  	return __block_write_begin(page, pos, len, minix_get_block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
  }
4a66af9ea   Nick Piggin   minixfs: convert ...
396
397
398
399
400
  
  static int minix_write_begin(struct file *file, struct address_space *mapping,
  			loff_t pos, unsigned len, unsigned flags,
  			struct page **pagep, void **fsdata)
  {
155130a4f   Christoph Hellwig   get rid of block_...
401
402
403
  	int ret;
  
  	ret = block_write_begin(mapping, pos, len, flags, pagep,
f4e420dc4   Christoph Hellwig   clean up write_be...
404
  				minix_get_block);
155130a4f   Christoph Hellwig   get rid of block_...
405
406
407
408
409
410
411
  	if (unlikely(ret)) {
  		loff_t isize = mapping->host->i_size;
  		if (pos + len > isize)
  			vmtruncate(mapping->host, isize);
  	}
  
  	return ret;
4a66af9ea   Nick Piggin   minixfs: convert ...
412
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
414
415
416
  static sector_t minix_bmap(struct address_space *mapping, sector_t block)
  {
  	return generic_block_bmap(mapping,block,minix_get_block);
  }
4a66af9ea   Nick Piggin   minixfs: convert ...
417

f5e54d6e5   Christoph Hellwig   [PATCH] mark addr...
418
  static const struct address_space_operations minix_aops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
420
  	.readpage = minix_readpage,
  	.writepage = minix_writepage,
4a66af9ea   Nick Piggin   minixfs: convert ...
421
422
  	.write_begin = minix_write_begin,
  	.write_end = generic_write_end,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
424
  	.bmap = minix_bmap
  };
92e1d5be9   Arjan van de Ven   [PATCH] mark stru...
425
  static const struct inode_operations minix_symlink_inode_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
  	.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.
   */
a90a08802   David Howells   iget: stop the MI...
452
  static struct inode *V1_minix_iget(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
455
456
457
458
459
460
  {
  	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) {
a90a08802   David Howells   iget: stop the MI...
461
462
  		iget_failed(inode);
  		return ERR_PTR(-EIO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
464
465
466
  	}
  	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;
bfe868486   Miklos Szeredi   filesystems: add ...
467
  	set_nlink(inode, raw_inode->i_nlinks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
469
470
471
472
  	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;
ba52de123   Theodore Ts'o   [PATCH] inode-die...
473
  	inode->i_blocks = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
476
477
  	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);
a90a08802   David Howells   iget: stop the MI...
478
479
  	unlock_new_inode(inode);
  	return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
481
482
483
484
  }
  
  /*
   * The minix V2 function to read an inode.
   */
a90a08802   David Howells   iget: stop the MI...
485
  static struct inode *V2_minix_iget(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
487
488
489
490
491
492
493
  {
  	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) {
a90a08802   David Howells   iget: stop the MI...
494
495
  		iget_failed(inode);
  		return ERR_PTR(-EIO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
497
498
499
  	}
  	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;
bfe868486   Miklos Szeredi   filesystems: add ...
500
  	set_nlink(inode, raw_inode->i_nlinks);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
501
502
503
504
505
506
507
  	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;
ba52de123   Theodore Ts'o   [PATCH] inode-die...
508
  	inode->i_blocks = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
510
511
512
  	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);
a90a08802   David Howells   iget: stop the MI...
513
514
  	unlock_new_inode(inode);
  	return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
516
517
518
519
  }
  
  /*
   * The global function to read an inode.
   */
a90a08802   David Howells   iget: stop the MI...
520
  struct inode *minix_iget(struct super_block *sb, unsigned long ino)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
  {
a90a08802   David Howells   iget: stop the MI...
522
523
524
525
526
527
528
  	struct inode *inode;
  
  	inode = iget_locked(sb, ino);
  	if (!inode)
  		return ERR_PTR(-ENOMEM);
  	if (!(inode->i_state & I_NEW))
  		return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
  	if (INODE_VERSION(inode) == MINIX_V1)
a90a08802   David Howells   iget: stop the MI...
530
  		return V1_minix_iget(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
  	else
a90a08802   David Howells   iget: stop the MI...
532
  		return V2_minix_iget(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
  }
  
  /*
   * 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;
  }
a9185b41a   Christoph Hellwig   pass writeback_co...
590
  static int minix_write_inode(struct inode *inode, struct writeback_control *wbc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591
592
593
  {
  	int err = 0;
  	struct buffer_head *bh;
0d7916d7e   Al Viro   switch minix to s...
594
595
596
597
598
599
  	if (INODE_VERSION(inode) == MINIX_V1)
  		bh = V1_minix_update_inode(inode);
  	else
  		bh = V2_minix_update_inode(inode);
  	if (!bh)
  		return -EIO;
a9185b41a   Christoph Hellwig   pass writeback_co...
600
  	if (wbc->sync_mode == WB_SYNC_ALL && buffer_dirty(bh)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
  		sync_dirty_buffer(bh);
0d7916d7e   Al Viro   switch minix to s...
602
  		if (buffer_req(bh) && !buffer_uptodate(bh)) {
11b844875   Denis Vlasenko   [PATCH] fix messa...
603
604
  			printk("IO error syncing minix inode [%s:%08lx]
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
  				inode->i_sb->s_id, inode->i_ino);
0d7916d7e   Al Viro   switch minix to s...
606
  			err = -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
607
608
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
610
611
612
613
614
  	brelse (bh);
  	return err;
  }
  
  int minix_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
  {
2def9e4ec   Al Viro   minix_getattr(): ...
615
  	struct super_block *sb = dentry->d_sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
616
617
  	generic_fillattr(dentry->d_inode, stat);
  	if (INODE_VERSION(dentry->d_inode) == MINIX_V1)
939b00df0   Andries Brouwer   [PATCH] Minix V3 ...
618
  		stat->blocks = (BLOCK_SIZE / 512) * V1_minix_blocks(stat->size, sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
  	else
939b00df0   Andries Brouwer   [PATCH] Minix V3 ...
620
621
  		stat->blocks = (sb->s_blocksize / 512) * V2_minix_blocks(stat->size, sb);
  	stat->blksize = sb->s_blocksize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
  	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);
  }
152a08366   Al Viro   new helper: mount...
637
638
  static struct dentry *minix_mount(struct file_system_type *fs_type,
  	int flags, const char *dev_name, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639
  {
152a08366   Al Viro   new helper: mount...
640
  	return mount_bdev(fs_type, flags, dev_name, data, minix_fill_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
641
642
643
644
645
  }
  
  static struct file_system_type minix_fs_type = {
  	.owner		= THIS_MODULE,
  	.name		= "minix",
152a08366   Al Viro   new helper: mount...
646
  	.mount		= minix_mount,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
  	.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");