Blame view

fs/bfs/inode.c 11.7 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   *	fs/bfs/inode.c
   *	BFS superblock and inode operations.
69688262f   Tigran Aivazian   [PATCH] update Ti...
4
   *	Copyright (C) 1999-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
   *	From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds.
fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
6
7
   *
   *      Made endianness-clean by Andrew Stribblehill <ads@wompom.org>, 2005.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
13
14
   */
  
  #include <linux/module.h>
  #include <linux/mm.h>
  #include <linux/slab.h>
  #include <linux/init.h>
  #include <linux/fs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
  #include <linux/buffer_head.h>
  #include <linux/vfs.h>
a9185b41a   Christoph Hellwig   pass writeback_co...
17
  #include <linux/writeback.h>
e2e40f2c1   Christoph Hellwig   fs: move struct k...
18
  #include <linux/uio.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
  #include <asm/uaccess.h>
  #include "bfs.h"
69688262f   Tigran Aivazian   [PATCH] update Ti...
21
  MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
26
27
28
29
30
31
  MODULE_DESCRIPTION("SCO UnixWare BFS filesystem for Linux");
  MODULE_LICENSE("GPL");
  
  #undef DEBUG
  
  #ifdef DEBUG
  #define dprintf(x...)	printf(x)
  #else
  #define dprintf(x...)
  #endif
e33ab086a   David Howells   iget: stop BFS fr...
32
  struct inode *bfs_iget(struct super_block *sb, unsigned long ino)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
  {
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
34
  	struct bfs_inode *di;
e33ab086a   David Howells   iget: stop BFS fr...
35
  	struct inode *inode;
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
36
  	struct buffer_head *bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
  	int block, off;
e33ab086a   David Howells   iget: stop BFS fr...
38
  	inode = iget_locked(sb, ino);
821ff77c6   Dan Carpenter   bfs: iget_locked(...
39
  	if (!inode)
e33ab086a   David Howells   iget: stop BFS fr...
40
41
42
  		return ERR_PTR(-ENOMEM);
  	if (!(inode->i_state & I_NEW))
  		return inode;
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
43
  	if ((ino < BFS_ROOT_INO) || (ino > BFS_SB(inode->i_sb)->si_lasti)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
  		printf("Bad inode number %s:%08lx
  ", inode->i_sb->s_id, ino);
e33ab086a   David Howells   iget: stop BFS fr...
46
  		goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
  	}
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
48
  	block = (ino - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
  	bh = sb_bread(inode->i_sb, block);
  	if (!bh) {
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
51
52
53
  		printf("Unable to read inode %s:%08lx
  ", inode->i_sb->s_id,
  									ino);
e33ab086a   David Howells   iget: stop BFS fr...
54
  		goto error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
57
58
  	}
  
  	off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
  	di = (struct bfs_inode *)bh->b_data + off;
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
59
  	inode->i_mode = 0x0000FFFF & le32_to_cpu(di->i_mode);
fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
60
  	if (le32_to_cpu(di->i_vtype) == BFS_VDIR) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
63
  		inode->i_mode |= S_IFDIR;
  		inode->i_op = &bfs_dir_inops;
  		inode->i_fop = &bfs_dir_operations;
fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
64
  	} else if (le32_to_cpu(di->i_vtype) == BFS_VREG) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
66
67
68
69
  		inode->i_mode |= S_IFREG;
  		inode->i_op = &bfs_file_inops;
  		inode->i_fop = &bfs_file_operations;
  		inode->i_mapping->a_ops = &bfs_aops;
  	}
fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
70
71
  	BFS_I(inode)->i_sblock =  le32_to_cpu(di->i_sblock);
  	BFS_I(inode)->i_eblock =  le32_to_cpu(di->i_eblock);
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
72
  	BFS_I(inode)->i_dsk_ino = le16_to_cpu(di->i_ino);
7f5b82b83   Eric W. Biederman   userns: Convert b...
73
74
  	i_uid_write(inode, le32_to_cpu(di->i_uid));
  	i_gid_write(inode,  le32_to_cpu(di->i_gid));
bfe868486   Miklos Szeredi   filesystems: add ...
75
  	set_nlink(inode, le32_to_cpu(di->i_nlink));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
77
  	inode->i_size = BFS_FILESIZE(di);
  	inode->i_blocks = BFS_FILEBLOCKS(di);
fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
78
79
80
  	inode->i_atime.tv_sec =  le32_to_cpu(di->i_atime);
  	inode->i_mtime.tv_sec =  le32_to_cpu(di->i_mtime);
  	inode->i_ctime.tv_sec =  le32_to_cpu(di->i_ctime);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
83
  	inode->i_atime.tv_nsec = 0;
  	inode->i_mtime.tv_nsec = 0;
  	inode->i_ctime.tv_nsec = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
  
  	brelse(bh);
e33ab086a   David Howells   iget: stop BFS fr...
86
87
88
89
90
91
  	unlock_new_inode(inode);
  	return inode;
  
  error:
  	iget_failed(inode);
  	return ERR_PTR(-EIO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
  }
9df2f8512   Al Viro   switch bfs to ->e...
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
  static struct bfs_inode *find_inode(struct super_block *sb, u16 ino, struct buffer_head **p)
  {
  	if ((ino < BFS_ROOT_INO) || (ino > BFS_SB(sb)->si_lasti)) {
  		printf("Bad inode number %s:%08x
  ", sb->s_id, ino);
  		return ERR_PTR(-EIO);
  	}
  
  	ino -= BFS_ROOT_INO;
  
  	*p = sb_bread(sb, 1 + ino / BFS_INODES_PER_BLOCK);
  	if (!*p) {
  		printf("Unable to read inode %s:%08x
  ", sb->s_id, ino);
  		return ERR_PTR(-EIO);
  	}
  
  	return (struct bfs_inode *)(*p)->b_data +  ino % BFS_INODES_PER_BLOCK;
  }
a9185b41a   Christoph Hellwig   pass writeback_co...
112
  static int bfs_write_inode(struct inode *inode, struct writeback_control *wbc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
  {
4427f0c36   Al Viro   repair bfs_write_...
114
  	struct bfs_sb_info *info = BFS_SB(inode->i_sb);
fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
115
116
  	unsigned int ino = (u16)inode->i_ino;
          unsigned long i_sblock;
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
117
118
  	struct bfs_inode *di;
  	struct buffer_head *bh;
4427f0c36   Al Viro   repair bfs_write_...
119
  	int err = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120

fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
121
122
          dprintf("ino=%08x
  ", ino);
9df2f8512   Al Viro   switch bfs to ->e...
123
124
125
  	di = find_inode(inode->i_sb, ino, &bh);
  	if (IS_ERR(di))
  		return PTR_ERR(di);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126

3f165e4cf   Dmitri Vorobiev   bfs: kill BKL
127
  	mutex_lock(&info->bfs_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128

fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
129
130
  	if (ino == BFS_ROOT_INO)
  		di->i_vtype = cpu_to_le32(BFS_VDIR);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
  	else
fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
132
133
134
135
  		di->i_vtype = cpu_to_le32(BFS_VREG);
  
  	di->i_ino = cpu_to_le16(ino);
  	di->i_mode = cpu_to_le32(inode->i_mode);
7f5b82b83   Eric W. Biederman   userns: Convert b...
136
137
  	di->i_uid = cpu_to_le32(i_uid_read(inode));
  	di->i_gid = cpu_to_le32(i_gid_read(inode));
fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
138
139
140
141
142
143
144
145
  	di->i_nlink = cpu_to_le32(inode->i_nlink);
  	di->i_atime = cpu_to_le32(inode->i_atime.tv_sec);
  	di->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec);
  	di->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
          i_sblock = BFS_I(inode)->i_sblock;
  	di->i_sblock = cpu_to_le32(i_sblock);
  	di->i_eblock = cpu_to_le32(BFS_I(inode)->i_eblock);
  	di->i_eoffset = cpu_to_le32(i_sblock * BFS_BSIZE + inode->i_size - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
147
  
  	mark_buffer_dirty(bh);
a9185b41a   Christoph Hellwig   pass writeback_co...
148
  	if (wbc->sync_mode == WB_SYNC_ALL) {
4427f0c36   Al Viro   repair bfs_write_...
149
150
151
152
  		sync_dirty_buffer(bh);
  		if (buffer_req(bh) && !buffer_uptodate(bh))
  			err = -EIO;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
  	brelse(bh);
3f165e4cf   Dmitri Vorobiev   bfs: kill BKL
154
  	mutex_unlock(&info->bfs_lock);
4427f0c36   Al Viro   repair bfs_write_...
155
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
  }
9df2f8512   Al Viro   switch bfs to ->e...
157
  static void bfs_evict_inode(struct inode *inode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
  {
  	unsigned long ino = inode->i_ino;
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
160
161
  	struct bfs_inode *di;
  	struct buffer_head *bh;
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
162
163
164
  	struct super_block *s = inode->i_sb;
  	struct bfs_sb_info *info = BFS_SB(s);
  	struct bfs_inode_info *bi = BFS_I(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165

fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
166
167
  	dprintf("ino=%08lx
  ", ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168

91b0abe36   Johannes Weiner   mm + fs: store sh...
169
  	truncate_inode_pages_final(&inode->i_data);
9df2f8512   Al Viro   switch bfs to ->e...
170
  	invalidate_inode_buffers(inode);
dbd5768f8   Jan Kara   vfs: Rename end_w...
171
  	clear_inode(inode);
fef266580   Mark Fasheh   [PATCH] update fi...
172

9df2f8512   Al Viro   switch bfs to ->e...
173
  	if (inode->i_nlink)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
  		return;
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
175

9df2f8512   Al Viro   switch bfs to ->e...
176
177
  	di = find_inode(s, inode->i_ino, &bh);
  	if (IS_ERR(di))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
  		return;
9df2f8512   Al Viro   switch bfs to ->e...
179
180
181
182
  
  	mutex_lock(&info->bfs_lock);
  	/* clear on-disk inode */
  	memset(di, 0, sizeof(struct bfs_inode));
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
183
184
  	mark_buffer_dirty(bh);
  	brelse(bh);
fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
185
          if (bi->i_dsk_ino) {
7e46aa5c8   Al Viro   regression: bfs e...
186
187
  		if (bi->i_sblock)
  			info->si_freeb += bi->i_eblock + 1 - bi->i_sblock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  		info->si_freei++;
fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
189
  		clear_bit(ino, info->si_imap);
1da85fdff   Fabian Frederick   fs/bfs: use bfs p...
190
  		bfs_dump_imap("delete_inode", s);
fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
191
          }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192

f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
193
194
195
196
197
  	/*
  	 * If this was the last file, make the previous block
  	 * "last block of the last file" even if there is no
  	 * real file there, saves us 1 gap.
  	 */
4e29d50a2   Artem Bityutskiy   BFS: clean up the...
198
  	if (info->si_lf_eblk == bi->i_eblock)
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
199
  		info->si_lf_eblk = bi->i_sblock - 1;
3f165e4cf   Dmitri Vorobiev   bfs: kill BKL
200
  	mutex_unlock(&info->bfs_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
203
204
205
  }
  
  static void bfs_put_super(struct super_block *s)
  {
  	struct bfs_sb_info *info = BFS_SB(s);
3f165e4cf   Dmitri Vorobiev   bfs: kill BKL
206

e1f89ec95   Eric Sesterhenn   bfs: add some bas...
207
208
  	if (!info)
  		return;
3f165e4cf   Dmitri Vorobiev   bfs: kill BKL
209
  	mutex_destroy(&info->bfs_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
211
212
213
  	kfree(info->si_imap);
  	kfree(info);
  	s->s_fs_info = NULL;
  }
726c33422   David Howells   [PATCH] VFS: Perm...
214
  static int bfs_statfs(struct dentry *dentry, struct kstatfs *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
  {
726c33422   David Howells   [PATCH] VFS: Perm...
216
  	struct super_block *s = dentry->d_sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
219
220
221
222
223
224
225
226
227
228
229
  	struct bfs_sb_info *info = BFS_SB(s);
  	u64 id = huge_encode_dev(s->s_bdev->bd_dev);
  	buf->f_type = BFS_MAGIC;
  	buf->f_bsize = s->s_blocksize;
  	buf->f_blocks = info->si_blocks;
  	buf->f_bfree = buf->f_bavail = info->si_freeb;
  	buf->f_files = info->si_lasti + 1 - BFS_ROOT_INO;
  	buf->f_ffree = info->si_freei;
  	buf->f_fsid.val[0] = (u32)id;
  	buf->f_fsid.val[1] = (u32)(id >> 32);
  	buf->f_namelen = BFS_NAMELEN;
  	return 0;
  }
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
230
  static struct kmem_cache *bfs_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
232
233
234
  
  static struct inode *bfs_alloc_inode(struct super_block *sb)
  {
  	struct bfs_inode_info *bi;
e94b17660   Christoph Lameter   [PATCH] slab: rem...
235
  	bi = kmem_cache_alloc(bfs_inode_cachep, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
237
238
239
  	if (!bi)
  		return NULL;
  	return &bi->vfs_inode;
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
240
  static void bfs_i_callback(struct rcu_head *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
  {
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
242
  	struct inode *inode = container_of(head, struct inode, i_rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
  	kmem_cache_free(bfs_inode_cachep, BFS_I(inode));
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
245
246
247
248
  static void bfs_destroy_inode(struct inode *inode)
  {
  	call_rcu(&inode->i_rcu, bfs_i_callback);
  }
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
249
  static void init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
251
  {
  	struct bfs_inode_info *bi = foo;
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
252
  	inode_init_once(&bi->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
  }
20c2df83d   Paul Mundt   mm: Remove slab d...
254

758b44407   Fabian Frederick   fs/bfs/inode.c: a...
255
  static int __init init_inodecache(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
257
258
  {
  	bfs_inode_cachep = kmem_cache_create("bfs_inode_cache",
  					     sizeof(struct bfs_inode_info),
fffb60f93   Paul Jackson   [PATCH] cpuset me...
259
  					     0, (SLAB_RECLAIM_ACCOUNT|
5d097056c   Vladimir Davydov   kmemcg: account c...
260
  						SLAB_MEM_SPREAD|SLAB_ACCOUNT),
20c2df83d   Paul Mundt   mm: Remove slab d...
261
  					     init_once);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
263
264
265
266
267
268
  	if (bfs_inode_cachep == NULL)
  		return -ENOMEM;
  	return 0;
  }
  
  static void destroy_inodecache(void)
  {
8c0a85377   Kirill A. Shutemov   fs: push rcu_barr...
269
270
271
272
273
  	/*
  	 * Make sure all delayed rcu free inodes are flushed before we
  	 * destroy cache.
  	 */
  	rcu_barrier();
1a1d92c10   Alexey Dobriyan   [PATCH] Really ig...
274
  	kmem_cache_destroy(bfs_inode_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275
  }
ee9b6d61a   Josef 'Jeff' Sipek   [PATCH] Mark stru...
276
  static const struct super_operations bfs_sops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
278
  	.alloc_inode	= bfs_alloc_inode,
  	.destroy_inode	= bfs_destroy_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
  	.write_inode	= bfs_write_inode,
9df2f8512   Al Viro   switch bfs to ->e...
280
  	.evict_inode	= bfs_evict_inode,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
  	.put_super	= bfs_put_super,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
  	.statfs		= bfs_statfs,
  };
1da85fdff   Fabian Frederick   fs/bfs: use bfs p...
284
  void bfs_dump_imap(const char *prefix, struct super_block *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
  {
fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
286
  #ifdef DEBUG
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
288
289
290
291
  	int i;
  	char *tmpbuf = (char *)get_zeroed_page(GFP_KERNEL);
  
  	if (!tmpbuf)
  		return;
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
292
293
  	for (i = BFS_SB(s)->si_lasti; i >= 0; i--) {
  		if (i > PAGE_SIZE - 100) break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294
295
296
297
298
  		if (test_bit(i, BFS_SB(s)->si_imap))
  			strcat(tmpbuf, "1");
  		else
  			strcat(tmpbuf, "0");
  	}
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
299
300
301
  	printf("BFS-fs: %s: lasti=%08lx <%s>
  ",
  				prefix, BFS_SB(s)->si_lasti, tmpbuf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302
303
304
305
306
307
  	free_page((unsigned long)tmpbuf);
  #endif
  }
  
  static int bfs_fill_super(struct super_block *s, void *data, int silent)
  {
4e29d50a2   Artem Bityutskiy   BFS: clean up the...
308
  	struct buffer_head *bh, *sbh;
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
309
310
  	struct bfs_super_block *bfs_sb;
  	struct inode *inode;
fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
311
  	unsigned i, imap_len;
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
312
  	struct bfs_sb_info *info;
5998649f7   Al Viro   Fix failure exits...
313
  	int ret = -EINVAL;
e1f89ec95   Eric Sesterhenn   bfs: add some bas...
314
  	unsigned long i_sblock, i_eblock, i_eoff, s_size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315

f8314dc60   Panagiotis Issaris   [PATCH] fs: Conve...
316
  	info = kzalloc(sizeof(*info), GFP_KERNEL);
ba13d597a   Jan Blunck   BKL: Remove BKL f...
317
  	if (!info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
  		return -ENOMEM;
5998649f7   Al Viro   Fix failure exits...
319
  	mutex_init(&info->bfs_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320
  	s->s_fs_info = info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
322
  
  	sb_set_blocksize(s, BFS_BSIZE);
4e29d50a2   Artem Bityutskiy   BFS: clean up the...
323
324
  	sbh = sb_bread(s, 0);
  	if (!sbh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  		goto out;
4e29d50a2   Artem Bityutskiy   BFS: clean up the...
326
  	bfs_sb = (struct bfs_super_block *)sbh->b_data;
fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
327
  	if (le32_to_cpu(bfs_sb->s_magic) != BFS_MAGIC) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
330
  		if (!silent)
  			printf("No BFS filesystem on %s (magic=%08x)
  ", 
fac92becd   Andrew Stribblehill   [PATCH] bfs: fix ...
331
  				s->s_id,  le32_to_cpu(bfs_sb->s_magic));
5998649f7   Al Viro   Fix failure exits...
332
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
334
335
336
337
338
  	}
  	if (BFS_UNCLEAN(bfs_sb, s) && !silent)
  		printf("%s is unclean, continuing
  ", s->s_id);
  
  	s->s_magic = BFS_MAGIC;
e1f89ec95   Eric Sesterhenn   bfs: add some bas...
339
340
341
342
  
  	if (le32_to_cpu(bfs_sb->s_start) > le32_to_cpu(bfs_sb->s_end)) {
  		printf("Superblock is corrupted
  ");
5998649f7   Al Viro   Fix failure exits...
343
  		goto out1;
e1f89ec95   Eric Sesterhenn   bfs: add some bas...
344
  	}
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
345
346
347
348
  	info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) /
  					sizeof(struct bfs_inode)
  					+ BFS_ROOT_INO - 1;
  	imap_len = (info->si_lasti / 8) + 1;
f8314dc60   Panagiotis Issaris   [PATCH] fs: Conve...
349
  	info->si_imap = kzalloc(imap_len, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
  	if (!info->si_imap)
5998649f7   Al Viro   Fix failure exits...
351
  		goto out1;
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
352
  	for (i = 0; i < BFS_ROOT_INO; i++)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353
354
355
  		set_bit(i, info->si_imap);
  
  	s->s_op = &bfs_sops;
e33ab086a   David Howells   iget: stop BFS fr...
356
357
358
  	inode = bfs_iget(s, BFS_ROOT_INO);
  	if (IS_ERR(inode)) {
  		ret = PTR_ERR(inode);
5998649f7   Al Viro   Fix failure exits...
359
  		goto out2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360
  	}
48fde701a   Al Viro   switch open-coded...
361
  	s->s_root = d_make_root(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
  	if (!s->s_root) {
e33ab086a   David Howells   iget: stop BFS fr...
363
  		ret = -ENOMEM;
5998649f7   Al Viro   Fix failure exits...
364
  		goto out2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
  	}
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
366
367
368
  	info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1) >> BFS_BSIZE_BITS;
  	info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1
  			- le32_to_cpu(bfs_sb->s_start)) >> BFS_BSIZE_BITS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
370
  	info->si_freei = 0;
  	info->si_lf_eblk = 0;
50682bb4d   Eric Sesterhenn   bfs: check that f...
371
372
373
374
375
376
  
  	/* can we read the last block? */
  	bh = sb_bread(s, info->si_blocks - 1);
  	if (!bh) {
  		printf("Last block not available: %lu
  ", info->si_blocks - 1);
50682bb4d   Eric Sesterhenn   bfs: check that f...
377
  		ret = -EIO;
5998649f7   Al Viro   Fix failure exits...
378
  		goto out3;
50682bb4d   Eric Sesterhenn   bfs: check that f...
379
380
  	}
  	brelse(bh);
c2b513dfb   Al Viro   [PATCH] bfs iget(...
381
  	bh = NULL;
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
382
  	for (i = BFS_ROOT_INO; i <= info->si_lasti; i++) {
c2b513dfb   Al Viro   [PATCH] bfs iget(...
383
  		struct bfs_inode *di;
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
384
  		int block = (i - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1;
c2b513dfb   Al Viro   [PATCH] bfs iget(...
385
  		int off = (i - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
75b25b4ca   Dmitri Vorobiev   bfs: assorted cle...
386
  		unsigned long eblock;
c2b513dfb   Al Viro   [PATCH] bfs iget(...
387
388
389
390
391
392
393
394
395
396
  
  		if (!off) {
  			brelse(bh);
  			bh = sb_bread(s, block);
  		}
  
  		if (!bh)
  			continue;
  
  		di = (struct bfs_inode *)bh->b_data + off;
e1f89ec95   Eric Sesterhenn   bfs: add some bas...
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
  		/* test if filesystem is not corrupted */
  
  		i_eoff = le32_to_cpu(di->i_eoffset);
  		i_sblock = le32_to_cpu(di->i_sblock);
  		i_eblock = le32_to_cpu(di->i_eblock);
  		s_size = le32_to_cpu(bfs_sb->s_end);
  
  		if (i_sblock > info->si_blocks ||
  			i_eblock > info->si_blocks ||
  			i_sblock > i_eblock ||
  			i_eoff > s_size ||
  			i_sblock * BFS_BSIZE > i_eoff) {
  
  			printf("Inode 0x%08x corrupted
  ", i);
  
  			brelse(bh);
5998649f7   Al Viro   Fix failure exits...
414
415
  			ret = -EIO;
  			goto out3;
e1f89ec95   Eric Sesterhenn   bfs: add some bas...
416
  		}
c2b513dfb   Al Viro   [PATCH] bfs iget(...
417
  		if (!di->i_ino) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
  			info->si_freei++;
c2b513dfb   Al Viro   [PATCH] bfs iget(...
419
420
421
422
  			continue;
  		}
  		set_bit(i, info->si_imap);
  		info->si_freeb -= BFS_FILEBLOCKS(di);
c2b513dfb   Al Viro   [PATCH] bfs iget(...
423
  		eblock =  le32_to_cpu(di->i_eblock);
f433dc563   Dmitri Vorobiev   Fixes to the BFS ...
424
  		if (eblock > info->si_lf_eblk)
c2b513dfb   Al Viro   [PATCH] bfs iget(...
425
  			info->si_lf_eblk = eblock;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
  	}
c2b513dfb   Al Viro   [PATCH] bfs iget(...
427
  	brelse(bh);
4e29d50a2   Artem Bityutskiy   BFS: clean up the...
428
  	brelse(sbh);
1da85fdff   Fabian Frederick   fs/bfs: use bfs p...
429
  	bfs_dump_imap("read_super", s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
  	return 0;
5998649f7   Al Viro   Fix failure exits...
431
432
433
434
435
436
  out3:
  	dput(s->s_root);
  	s->s_root = NULL;
  out2:
  	kfree(info->si_imap);
  out1:
4e29d50a2   Artem Bityutskiy   BFS: clean up the...
437
  	brelse(sbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
  out:
5998649f7   Al Viro   Fix failure exits...
439
  	mutex_destroy(&info->bfs_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
441
  	kfree(info);
  	s->s_fs_info = NULL;
e33ab086a   David Howells   iget: stop BFS fr...
442
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
  }
152a08366   Al Viro   new helper: mount...
444
445
  static struct dentry *bfs_mount(struct file_system_type *fs_type,
  	int flags, const char *dev_name, void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
  {
152a08366   Al Viro   new helper: mount...
447
  	return mount_bdev(fs_type, flags, dev_name, data, bfs_fill_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
450
451
452
  }
  
  static struct file_system_type bfs_fs_type = {
  	.owner		= THIS_MODULE,
  	.name		= "bfs",
152a08366   Al Viro   new helper: mount...
453
  	.mount		= bfs_mount,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
455
456
  	.kill_sb	= kill_block_super,
  	.fs_flags	= FS_REQUIRES_DEV,
  };
7f78e0351   Eric W. Biederman   fs: Limit sys_mou...
457
  MODULE_ALIAS_FS("bfs");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
  
  static int __init init_bfs_fs(void)
  {
  	int err = init_inodecache();
  	if (err)
  		goto out1;
          err = register_filesystem(&bfs_fs_type);
  	if (err)
  		goto out;
  	return 0;
  out:
  	destroy_inodecache();
  out1:
  	return err;
  }
  
  static void __exit exit_bfs_fs(void)
  {
  	unregister_filesystem(&bfs_fs_type);
  	destroy_inodecache();
  }
  
  module_init(init_bfs_fs)
  module_exit(exit_bfs_fs)