Blame view

fs/befs/linuxvfs.c 23.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
  /*
   * linux/fs/befs/linuxvfs.c
   *
   * Copyright (C) 2001 Will Dyson <will_dyson@pobox.com
   *
   */
dac52fc18   Fabian Frederick   BEFS: logging cle...
7
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
13
14
15
16
17
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/fs.h>
  #include <linux/errno.h>
  #include <linux/stat.h>
  #include <linux/nls.h>
  #include <linux/buffer_head.h>
  #include <linux/vfs.h>
  #include <linux/parser.h>
  #include <linux/namei.h>
31aba059b   Eric W. Biederman   userns: Convert b...
18
  #include <linux/sched.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
22
23
24
25
  
  #include "befs.h"
  #include "btree.h"
  #include "inode.h"
  #include "datastream.h"
  #include "super.h"
  #include "io.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
29
30
31
32
  
  MODULE_DESCRIPTION("BeOS File System (BeFS) driver");
  MODULE_AUTHOR("Will Dyson");
  MODULE_LICENSE("GPL");
  
  /* The units the vfs expects inode->i_blocks to be in */
  #define VFS_BLOCK_SIZE 512
f0f49ef5c   Al Viro   [readdir] convert...
33
  static int befs_readdir(struct file *, struct dir_context *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
  static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int);
  static int befs_readpage(struct file *file, struct page *page);
  static sector_t befs_bmap(struct address_space *mapping, sector_t block);
00cd8dd3b   Al Viro   stop passing name...
37
  static struct dentry *befs_lookup(struct inode *, struct dentry *, unsigned int);
96eb54194   David Howells   iget: stop BEFS f...
38
  static struct inode *befs_iget(struct super_block *, unsigned long);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
  static struct inode *befs_alloc_inode(struct super_block *sb);
  static void befs_destroy_inode(struct inode *inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
  static void befs_destroy_inodecache(void);
11803f97f   Al Viro   switch befs long ...
42
  static int befs_symlink_readpage(struct file *, struct page *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
45
46
47
48
  static int befs_utf2nls(struct super_block *sb, const char *in, int in_len,
  			char **out, int *out_len);
  static int befs_nls2utf(struct super_block *sb, const char *in, int in_len,
  			char **out, int *out_len);
  static void befs_put_super(struct super_block *);
  static int befs_remount(struct super_block *, int *, char *);
726c33422   David Howells   [PATCH] VFS: Perm...
49
  static int befs_statfs(struct dentry *, struct kstatfs *);
09ad0eae5   Fabian Frederick   befs: replace typ...
50
  static int parse_options(char *, struct befs_mount_options *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
  
  static const struct super_operations befs_sops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
54
55
56
57
  	.alloc_inode	= befs_alloc_inode,	/* allocate a new inode */
  	.destroy_inode	= befs_destroy_inode, /* deallocate an inode */
  	.put_super	= befs_put_super,	/* uninit super */
  	.statfs		= befs_statfs,	/* statfs */
  	.remount_fs	= befs_remount,
552c3c6c5   Miklos Szeredi   mount options: fi...
58
  	.show_options	= generic_show_options,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
  };
  
  /* slab cache for befs_inode_info objects */
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
62
  static struct kmem_cache *befs_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63

4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
64
  static const struct file_operations befs_dir_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  	.read		= generic_read_dir,
e23e9aa75   Al Viro   befs: switch to -...
66
  	.iterate_shared	= befs_readdir,
59af1584b   Al Viro   [PATCH] fix ->lls...
67
  	.llseek		= generic_file_llseek,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
  };
754661f14   Arjan van de Ven   [PATCH] mark stru...
69
  static const struct inode_operations befs_dir_inode_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
  	.lookup		= befs_lookup,
  };
f5e54d6e5   Christoph Hellwig   [PATCH] mark addr...
72
  static const struct address_space_operations befs_aops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
  	.readpage	= befs_readpage,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
  	.bmap		= befs_bmap,
  };
11803f97f   Al Viro   switch befs long ...
76
77
  static const struct address_space_operations befs_symlink_aops = {
  	.readpage	= befs_symlink_readpage,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
  };
  
  /* 
   * Called by generic_file_read() to read a page of data
   * 
   * In turn, simply calls a generic block read function and
   * passes it the address of befs_get_block, for mapping file
   * positions to disk blocks.
   */
  static int
  befs_readpage(struct file *file, struct page *page)
  {
  	return block_read_full_page(page, befs_get_block);
  }
  
  static sector_t
  befs_bmap(struct address_space *mapping, sector_t block)
  {
  	return generic_block_bmap(mapping, block, befs_get_block);
  }
  
  /* 
   * Generic function to map a file position (block) to a 
   * disk offset (passed back in bh_result).
   *
   * Used by many higher level functions.
   *
   * Calls befs_fblock2brun() in datastream.c to do the real work.
   *
   * -WD 10-26-01
   */
  
  static int
  befs_get_block(struct inode *inode, sector_t block,
  	       struct buffer_head *bh_result, int create)
  {
  	struct super_block *sb = inode->i_sb;
  	befs_data_stream *ds = &BEFS_I(inode)->i_data.ds;
  	befs_block_run run = BAD_IADDR;
abcf91169   Salah Triki   fs: befs: remove ...
117
  	int res;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
119
120
  	ulong disk_off;
  
  	befs_debug(sb, "---> befs_get_block() for inode %lu, block %ld",
dac52fc18   Fabian Frederick   BEFS: logging cle...
121
  		   (unsigned long)inode->i_ino, (long)block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
  	if (create) {
  		befs_error(sb, "befs_get_block() was asked to write to "
dac52fc18   Fabian Frederick   BEFS: logging cle...
124
125
  			   "block %ld in inode %lu", (long)block,
  			   (unsigned long)inode->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
129
130
131
  		return -EPERM;
  	}
  
  	res = befs_fblock2brun(sb, ds, block, &run);
  	if (res != BEFS_OK) {
  		befs_error(sb,
dac52fc18   Fabian Frederick   BEFS: logging cle...
132
133
134
  			   "<--- %s for inode %lu, block %ld ERROR",
  			   __func__, (unsigned long)inode->i_ino,
  			   (long)block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
136
137
138
139
140
  		return -EFBIG;
  	}
  
  	disk_off = (ulong) iaddr2blockno(sb, &run);
  
  	map_bh(bh_result, inode->i_sb, disk_off);
dac52fc18   Fabian Frederick   BEFS: logging cle...
141
142
143
  	befs_debug(sb, "<--- %s for inode %lu, block %ld, disk address %lu",
  		  __func__, (unsigned long)inode->i_ino, (long)block,
  		  (unsigned long)disk_off);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
146
147
148
  
  	return 0;
  }
  
  static struct dentry *
00cd8dd3b   Al Viro   stop passing name...
149
  befs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
  {
c94087636   Salah Triki   fs/befs/linuxvfs....
151
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
  	struct super_block *sb = dir->i_sb;
22341d8f3   Al Viro   befs: constify st...
153
  	const befs_data_stream *ds = &BEFS_I(dir)->i_data.ds;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
157
158
  	befs_off_t offset;
  	int ret;
  	int utfnamelen;
  	char *utfname;
  	const char *name = dentry->d_name.name;
a455589f1   Al Viro   assorted conversi...
159
160
  	befs_debug(sb, "---> %s name %pd inode %ld", __func__,
  		   dentry, dir->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
162
163
164
165
166
  
  	/* Convert to UTF-8 */
  	if (BEFS_SB(sb)->nls) {
  		ret =
  		    befs_nls2utf(sb, name, strlen(name), &utfname, &utfnamelen);
  		if (ret < 0) {
dac52fc18   Fabian Frederick   BEFS: logging cle...
167
  			befs_debug(sb, "<--- %s ERROR", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
170
171
172
173
  			return ERR_PTR(ret);
  		}
  		ret = befs_btree_find(sb, ds, utfname, &offset);
  		kfree(utfname);
  
  	} else {
f7769f9cf   Luis de Bethencourt   befs: avoid deref...
174
  		ret = befs_btree_find(sb, ds, name, &offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
177
  	}
  
  	if (ret == BEFS_BT_NOT_FOUND) {
a455589f1   Al Viro   assorted conversi...
178
  		befs_debug(sb, "<--- %s %pd not found", __func__, dentry);
a26bc1adc   Salah Triki   fs: befs: Insert ...
179
  		d_add(dentry, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
182
  		return ERR_PTR(-ENOENT);
  
  	} else if (ret != BEFS_OK || offset == 0) {
4c3897cce   Luis de Bethencourt   befs: make consis...
183
  		befs_error(sb, "<--- %s Error", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
  		return ERR_PTR(-ENODATA);
  	}
96eb54194   David Howells   iget: stop BEFS f...
186
187
188
  	inode = befs_iget(dir->i_sb, (ino_t) offset);
  	if (IS_ERR(inode))
  		return ERR_CAST(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
  
  	d_add(dentry, inode);
dac52fc18   Fabian Frederick   BEFS: logging cle...
191
  	befs_debug(sb, "<--- %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
194
195
196
  
  	return NULL;
  }
  
  static int
f0f49ef5c   Al Viro   [readdir] convert...
197
  befs_readdir(struct file *file, struct dir_context *ctx)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  {
f0f49ef5c   Al Viro   [readdir] convert...
199
  	struct inode *inode = file_inode(file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  	struct super_block *sb = inode->i_sb;
22341d8f3   Al Viro   befs: constify st...
201
  	const befs_data_stream *ds = &BEFS_I(inode)->i_data.ds;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
204
  	befs_off_t value;
  	int result;
  	size_t keysize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
  	char keybuf[BEFS_NAME_LEN + 1];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206

a455589f1   Al Viro   assorted conversi...
207
208
  	befs_debug(sb, "---> %s name %pD, inode %ld, ctx->pos %lld",
  		  __func__, file, inode->i_ino, ctx->pos);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209

9ae51a32b   Luis de Bethencourt   befs: use simpler...
210
211
212
  	while (1) {
  		result = befs_btree_read(sb, ds, ctx->pos, BEFS_NAME_LEN + 1,
  					 keybuf, &keysize, &value);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213

9ae51a32b   Luis de Bethencourt   befs: use simpler...
214
  		if (result == BEFS_ERR) {
dac52fc18   Fabian Frederick   BEFS: logging cle...
215
  			befs_debug(sb, "<--- %s ERROR", __func__);
9ae51a32b   Luis de Bethencourt   befs: use simpler...
216
217
218
  			befs_error(sb, "IO error reading %pD (inode %lu)",
  				   file, inode->i_ino);
  			return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219

9ae51a32b   Luis de Bethencourt   befs: use simpler...
220
221
222
  		} else if (result == BEFS_BT_END) {
  			befs_debug(sb, "<--- %s END", __func__);
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223

9ae51a32b   Luis de Bethencourt   befs: use simpler...
224
225
226
  		} else if (result == BEFS_BT_EMPTY) {
  			befs_debug(sb, "<--- %s Empty directory", __func__);
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
  		}
9ae51a32b   Luis de Bethencourt   befs: use simpler...
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
  
  		/* Convert to NLS */
  		if (BEFS_SB(sb)->nls) {
  			char *nlsname;
  			int nlsnamelen;
  
  			result =
  			    befs_utf2nls(sb, keybuf, keysize, &nlsname,
  					 &nlsnamelen);
  			if (result < 0) {
  				befs_debug(sb, "<--- %s ERROR", __func__);
  				return result;
  			}
  			if (!dir_emit(ctx, nlsname, nlsnamelen,
  				      (ino_t) value, DT_UNKNOWN)) {
  				kfree(nlsname);
  				return 0;
  			}
f0f49ef5c   Al Viro   [readdir] convert...
246
  			kfree(nlsname);
9ae51a32b   Luis de Bethencourt   befs: use simpler...
247
248
249
250
  		} else {
  			if (!dir_emit(ctx, keybuf, keysize,
  				      (ino_t) value, DT_UNKNOWN))
  				return 0;
f0f49ef5c   Al Viro   [readdir] convert...
251
  		}
9ae51a32b   Luis de Bethencourt   befs: use simpler...
252
  		ctx->pos++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
255
256
257
258
  }
  
  static struct inode *
  befs_alloc_inode(struct super_block *sb)
  {
111d639dd   Fabian Frederick   fs/befs/linuxvfs....
259
260
261
  	struct befs_inode_info *bi;
  
  	bi = kmem_cache_alloc(befs_inode_cachep, GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
263
264
265
          if (!bi)
                  return NULL;
          return &bi->vfs_inode;
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
266
  static void befs_i_callback(struct rcu_head *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
  {
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
268
  	struct inode *inode = container_of(head, struct inode, i_rcu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
          kmem_cache_free(befs_inode_cachep, BEFS_I(inode));
  }
fa0d7e3de   Nick Piggin   fs: icache RCU fr...
271
272
273
274
  static void befs_destroy_inode(struct inode *inode)
  {
  	call_rcu(&inode->i_rcu, befs_i_callback);
  }
51cc50685   Alexey Dobriyan   SL*B: drop kmem c...
275
  static void init_once(void *foo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
  {
          struct befs_inode_info *bi = (struct befs_inode_info *) foo;
a35afb830   Christoph Lameter   Remove SLAB_CTOR_...
278
279
  
  	inode_init_once(&bi->vfs_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
  }
96eb54194   David Howells   iget: stop BEFS f...
281
  static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
  {
e4c7f5b10   Salah Triki   fs/befs/linuxvfs....
283
  	struct buffer_head *bh;
44ad80986   Salah Triki   fs/befs/linuxvfs....
284
  	befs_inode *raw_inode;
038428fcf   Fabian Frederick   befs: replace typ...
285
  	struct befs_sb_info *befs_sb = BEFS_SB(sb);
d6e020336   Salah Triki   fs/befs/linuxvfs....
286
  	struct befs_inode_info *befs_ino;
96eb54194   David Howells   iget: stop BEFS f...
287
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288

dac52fc18   Fabian Frederick   BEFS: logging cle...
289
  	befs_debug(sb, "---> %s inode = %lu", __func__, ino);
96eb54194   David Howells   iget: stop BEFS f...
290
291
  
  	inode = iget_locked(sb, ino);
ac34a1b35   Rakesh Pandit   befs: iget_locked...
292
293
  	if (!inode)
  		return ERR_PTR(-ENOMEM);
96eb54194   David Howells   iget: stop BEFS f...
294
295
  	if (!(inode->i_state & I_NEW))
  		return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
299
300
301
302
303
304
  
  	befs_ino = BEFS_I(inode);
  
  	/* convert from vfs's inode number to befs's inode number */
  	befs_ino->i_inode_num = blockno2iaddr(sb, inode->i_ino);
  
  	befs_debug(sb, "  real inode number [%u, %hu, %hu]",
  		   befs_ino->i_inode_num.allocation_group,
  		   befs_ino->i_inode_num.start, befs_ino->i_inode_num.len);
f7f675406   Salah Triki   fs: befs: replace...
305
  	bh = sb_bread(sb, inode->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
307
308
  	if (!bh) {
  		befs_error(sb, "unable to read inode block - "
  			   "inode = %lu", inode->i_ino);
0418726bb   Adrian Bunk   typo fixes: aquir...
309
  		goto unacquire_none;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
311
312
313
314
315
316
317
  	}
  
  	raw_inode = (befs_inode *) bh->b_data;
  
  	befs_dump_inode(sb, raw_inode);
  
  	if (befs_check_inode(sb, raw_inode, inode->i_ino) != BEFS_OK) {
  		befs_error(sb, "Bad inode: %lu", inode->i_ino);
0418726bb   Adrian Bunk   typo fixes: aquir...
318
  		goto unacquire_bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
320
321
322
323
324
325
326
327
328
  	}
  
  	inode->i_mode = (umode_t) fs32_to_cpu(sb, raw_inode->mode);
  
  	/*
  	 * set uid and gid.  But since current BeOS is single user OS, so
  	 * you can change by "uid" or "gid" options.
  	 */   
  
  	inode->i_uid = befs_sb->mount_opts.use_uid ?
31aba059b   Eric W. Biederman   userns: Convert b...
329
330
  		befs_sb->mount_opts.uid :
  		make_kuid(&init_user_ns, fs32_to_cpu(sb, raw_inode->uid));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
  	inode->i_gid = befs_sb->mount_opts.use_gid ?
31aba059b   Eric W. Biederman   userns: Convert b...
332
333
  		befs_sb->mount_opts.gid :
  		make_kgid(&init_user_ns, fs32_to_cpu(sb, raw_inode->gid));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334

bfe868486   Miklos Szeredi   filesystems: add ...
335
  	set_nlink(inode, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
  
  	/*
  	 * BEFS's time is 64 bits, but current VFS is 32 bits...
  	 * BEFS don't have access time. Nor inode change time. VFS
  	 * doesn't have creation time.
  	 * Also, the lower 16 bits of the last_modified_time and 
  	 * create_time are just a counter to help ensure uniqueness
  	 * for indexing purposes. (PFD, page 54)
  	 */
  
  	inode->i_mtime.tv_sec =
  	    fs64_to_cpu(sb, raw_inode->last_modified_time) >> 16;
  	inode->i_mtime.tv_nsec = 0;   /* lower 16 bits are not a time */	
  	inode->i_ctime = inode->i_mtime;
  	inode->i_atime = inode->i_mtime;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
353
354
355
356
357
358
359
  
  	befs_ino->i_inode_num = fsrun_to_cpu(sb, raw_inode->inode_num);
  	befs_ino->i_parent = fsrun_to_cpu(sb, raw_inode->parent);
  	befs_ino->i_attribute = fsrun_to_cpu(sb, raw_inode->attributes);
  	befs_ino->i_flags = fs32_to_cpu(sb, raw_inode->flags);
  
  	if (S_ISLNK(inode->i_mode) && !(befs_ino->i_flags & BEFS_LONG_SYMLINK)){
  		inode->i_size = 0;
  		inode->i_blocks = befs_sb->block_size / VFS_BLOCK_SIZE;
39d7a29f8   Fabian Frederick   fs/befs/linuxvfs....
360
361
  		strlcpy(befs_ino->i_data.symlink, raw_inode->data.symlink,
  			BEFS_SYMLINK_LEN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
364
365
  	} else {
  		int num_blks;
  
  		befs_ino->i_data.ds =
e0e3d32bb   Jesper Juhl   befs: don't pass ...
366
  		    fsds_to_cpu(sb, &raw_inode->data.datastream);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
368
369
370
371
372
373
374
375
376
  
  		num_blks = befs_count_blocks(sb, &befs_ino->i_data.ds);
  		inode->i_blocks =
  		    num_blks * (befs_sb->block_size / VFS_BLOCK_SIZE);
  		inode->i_size = befs_ino->i_data.ds.size;
  	}
  
  	inode->i_mapping->a_ops = &befs_aops;
  
  	if (S_ISREG(inode->i_mode)) {
2cf069162   Christoph Hellwig   [PATCH] befs: use...
377
  		inode->i_fop = &generic_ro_fops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
379
380
381
  	} else if (S_ISDIR(inode->i_mode)) {
  		inode->i_op = &befs_dir_inode_operations;
  		inode->i_fop = &befs_dir_operations;
  	} else if (S_ISLNK(inode->i_mode)) {
d0deec199   Al Viro   befs: switch to s...
382
  		if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
11803f97f   Al Viro   switch befs long ...
383
  			inode->i_op = &page_symlink_inode_operations;
21fc61c73   Al Viro   don't put symlink...
384
  			inode_nohighmem(inode);
11803f97f   Al Viro   switch befs long ...
385
  			inode->i_mapping->a_ops = &befs_symlink_aops;
d0deec199   Al Viro   befs: switch to s...
386
387
388
389
  		} else {
  			inode->i_link = befs_ino->i_data.symlink;
  			inode->i_op = &simple_symlink_inode_operations;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
390
391
392
393
  	} else {
  		befs_error(sb, "Inode %lu is not a regular file, "
  			   "directory or symlink. THAT IS WRONG! BeFS has no "
  			   "on disk special files", inode->i_ino);
0418726bb   Adrian Bunk   typo fixes: aquir...
394
  		goto unacquire_bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
396
397
  	}
  
  	brelse(bh);
dac52fc18   Fabian Frederick   BEFS: logging cle...
398
  	befs_debug(sb, "<--- %s", __func__);
96eb54194   David Howells   iget: stop BEFS f...
399
400
  	unlock_new_inode(inode);
  	return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401

0418726bb   Adrian Bunk   typo fixes: aquir...
402
        unacquire_bh:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
  	brelse(bh);
0418726bb   Adrian Bunk   typo fixes: aquir...
404
        unacquire_none:
96eb54194   David Howells   iget: stop BEFS f...
405
  	iget_failed(inode);
dac52fc18   Fabian Frederick   BEFS: logging cle...
406
  	befs_debug(sb, "<--- %s - Bad inode", __func__);
33c712b4f   Salah Triki   fs: befs: remove ...
407
  	return ERR_PTR(-EIO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
409
410
  }
  
  /* Initialize the inode cache. Called at fs setup.
20c2df83d   Paul Mundt   mm: Remove slab d...
411
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
413
   * Taken from NFS implementation by Al Viro.
   */
91a52ab7d   Fabian Frederick   fs/befs/linuxvfs....
414
  static int __init
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
416
417
418
  befs_init_inodecache(void)
  {
  	befs_inode_cachep = kmem_cache_create("befs_inode_cache",
  					      sizeof (struct befs_inode_info),
fffb60f93   Paul Jackson   [PATCH] cpuset me...
419
  					      0, (SLAB_RECLAIM_ACCOUNT|
5d097056c   Vladimir Davydov   kmemcg: account c...
420
  						SLAB_MEM_SPREAD|SLAB_ACCOUNT),
20c2df83d   Paul Mundt   mm: Remove slab d...
421
  					      init_once);
c08f1cb62   Salah Triki   fs: befs: remove ...
422
  	if (befs_inode_cachep == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
  		return -ENOMEM;
c08f1cb62   Salah Triki   fs: befs: remove ...
424

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
425
426
427
428
429
430
431
432
433
434
  	return 0;
  }
  
  /* Called at fs teardown.
   * 
   * Taken from NFS implementation by Al Viro.
   */
  static void
  befs_destroy_inodecache(void)
  {
8c0a85377   Kirill A. Shutemov   fs: push rcu_barr...
435
436
437
438
439
  	/*
  	 * Make sure all delayed rcu free inodes are flushed before we
  	 * destroy cache.
  	 */
  	rcu_barrier();
1a1d92c10   Alexey Dobriyan   [PATCH] Really ig...
440
  	kmem_cache_destroy(befs_inode_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
442
443
444
445
446
447
  }
  
  /*
   * The inode of symbolic link is different to data stream.
   * The data stream become link name. Unless the LONG_SYMLINK
   * flag is set.
   */
11803f97f   Al Viro   switch befs long ...
448
  static int befs_symlink_readpage(struct file *unused, struct page *page)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
  {
11803f97f   Al Viro   switch befs long ...
450
451
452
  	struct inode *inode = page->mapping->host;
  	struct super_block *sb = inode->i_sb;
  	struct befs_inode_info *befs_ino = BEFS_I(inode);
48bc06e74   Al Viro   befs: split symli...
453
454
  	befs_data_stream *data = &befs_ino->i_data.ds;
  	befs_off_t len = data->size;
21fc61c73   Al Viro   don't put symlink...
455
  	char *link = page_address(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456

11803f97f   Al Viro   switch befs long ...
457
  	if (len == 0 || len > PAGE_SIZE) {
48bc06e74   Al Viro   befs: split symli...
458
  		befs_error(sb, "Long symlink with illegal length");
11803f97f   Al Viro   switch befs long ...
459
  		goto fail;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
  	}
680baacbc   Al Viro   new ->follow_link...
461
  	befs_debug(sb, "Follow long symlink");
680baacbc   Al Viro   new ->follow_link...
462
  	if (befs_read_lsymlink(sb, data, link, len) != len) {
680baacbc   Al Viro   new ->follow_link...
463
  		befs_error(sb, "Failed to read entire long symlink");
11803f97f   Al Viro   switch befs long ...
464
  		goto fail;
680baacbc   Al Viro   new ->follow_link...
465
466
  	}
  	link[len - 1] = '\0';
11803f97f   Al Viro   switch befs long ...
467
  	SetPageUptodate(page);
11803f97f   Al Viro   switch befs long ...
468
469
470
471
  	unlock_page(page);
  	return 0;
  fail:
  	SetPageError(page);
11803f97f   Al Viro   switch befs long ...
472
473
  	unlock_page(page);
  	return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
476
477
478
479
480
481
482
483
484
485
486
487
488
  /*
   * UTF-8 to NLS charset  convert routine
   * 
   *
   * Changed 8/10/01 by Will Dyson. Now use uni2char() / char2uni() rather than
   * the nls tables directly
   */
  
  static int
  befs_utf2nls(struct super_block *sb, const char *in,
  	     int in_len, char **out, int *out_len)
  {
  	struct nls_table *nls = BEFS_SB(sb)->nls;
  	int i, o;
74675a585   Alan Stern   NLS: update handl...
489
  	unicode_t uni;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
491
  	int unilen, utflen;
  	char *result;
94f563c42   Diego Calleja   [PATCH] Fix BeFS ...
492
493
494
495
496
  	/* The utf8->nls conversion won't make the final nls string bigger
  	 * than the utf one, but if the string is pure ascii they'll have the
  	 * same width and an extra char is needed to save the additional \0
  	 */
  	int maxlen = in_len + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
497

dac52fc18   Fabian Frederick   BEFS: logging cle...
498
  	befs_debug(sb, "---> %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499
500
  
  	if (!nls) {
dac52fc18   Fabian Frederick   BEFS: logging cle...
501
  		befs_error(sb, "%s called with no NLS table loaded", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
503
504
505
506
  		return -EINVAL;
  	}
  
  	*out = result = kmalloc(maxlen, GFP_NOFS);
  	if (!*out) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
507
508
509
510
511
512
  		return -ENOMEM;
  	}
  
  	for (i = o = 0; i < in_len; i += utflen, o += unilen) {
  
  		/* convert from UTF-8 to Unicode */
74675a585   Alan Stern   NLS: update handl...
513
514
  		utflen = utf8_to_utf32(&in[i], in_len - i, &uni);
  		if (utflen < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
  			goto conv_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
  
  		/* convert from Unicode to nls */
74675a585   Alan Stern   NLS: update handl...
518
519
  		if (uni > MAX_WCHAR_T)
  			goto conv_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520
  		unilen = nls->uni2char(uni, &result[o], in_len - o);
74675a585   Alan Stern   NLS: update handl...
521
  		if (unilen < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
  			goto conv_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
524
525
  	}
  	result[o] = '\0';
  	*out_len = o;
dac52fc18   Fabian Frederick   BEFS: logging cle...
526
  	befs_debug(sb, "<--- %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
527
528
529
530
531
532
  
  	return o;
  
        conv_err:
  	befs_error(sb, "Name using character set %s contains a character that "
  		   "cannot be converted to unicode.", nls->charset);
dac52fc18   Fabian Frederick   BEFS: logging cle...
533
  	befs_debug(sb, "<--- %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
535
536
537
538
539
540
  	kfree(result);
  	return -EILSEQ;
  }
  
  /**
   * befs_nls2utf - Convert NLS string to utf8 encodeing
   * @sb: Superblock
817e1d902   Fabian Frederick   fs/befs: kernel-d...
541
542
543
544
   * @in: Input string buffer in NLS format
   * @in_len: Length of input string in bytes
   * @out: The output string in UTF-8 format
   * @out_len: Length of the output buffer
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
   * 
817e1d902   Fabian Frederick   fs/befs: kernel-d...
546
   * Converts input string @in, which is in the format of the loaded NLS map,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
548
   * into a utf8 string.
   * 
817e1d902   Fabian Frederick   fs/befs: kernel-d...
549
   * The destination string @out is allocated by this function and the caller is
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
551
   * responsible for freeing it with kfree()
   * 
817e1d902   Fabian Frederick   fs/befs: kernel-d...
552
   * On return, *@out_len is the length of @out in bytes.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
553
554
   *
   * On success, the return value is the number of utf8 characters written to
817e1d902   Fabian Frederick   fs/befs: kernel-d...
555
   * the output buffer @out.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
556
557
558
559
560
561
562
563
564
565
566
567
568
   *  
   * On Failure, a negative number coresponding to the error code is returned.
   */
  
  static int
  befs_nls2utf(struct super_block *sb, const char *in,
  	     int in_len, char **out, int *out_len)
  {
  	struct nls_table *nls = BEFS_SB(sb)->nls;
  	int i, o;
  	wchar_t uni;
  	int unilen, utflen;
  	char *result;
94f563c42   Diego Calleja   [PATCH] Fix BeFS ...
569
570
571
572
  	/* There're nls characters that will translate to 3-chars-wide UTF-8
  	 * characters, a additional byte is needed to save the final \0
  	 * in special cases */
  	int maxlen = (3 * in_len) + 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573

dac52fc18   Fabian Frederick   BEFS: logging cle...
574
575
  	befs_debug(sb, "---> %s
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
577
  
  	if (!nls) {
dac52fc18   Fabian Frederick   BEFS: logging cle...
578
579
  		befs_error(sb, "%s called with no NLS table loaded.",
  			   __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
582
583
584
  		return -EINVAL;
  	}
  
  	*out = result = kmalloc(maxlen, GFP_NOFS);
  	if (!*out) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
586
587
588
589
590
591
592
  		*out_len = 0;
  		return -ENOMEM;
  	}
  
  	for (i = o = 0; i < in_len; i += unilen, o += utflen) {
  
  		/* convert from nls to unicode */
  		unilen = nls->char2uni(&in[i], in_len - i, &uni);
74675a585   Alan Stern   NLS: update handl...
593
  		if (unilen < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
  			goto conv_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
596
  
  		/* convert from unicode to UTF-8 */
74675a585   Alan Stern   NLS: update handl...
597
598
  		utflen = utf32_to_utf8(uni, &result[o], 3);
  		if (utflen <= 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
  			goto conv_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
601
602
603
  	}
  
  	result[o] = '\0';
  	*out_len = o;
dac52fc18   Fabian Frederick   BEFS: logging cle...
604
  	befs_debug(sb, "<--- %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
606
607
608
609
610
  
  	return i;
  
        conv_err:
  	befs_error(sb, "Name using charecter set %s contains a charecter that "
  		   "cannot be converted to unicode.", nls->charset);
dac52fc18   Fabian Frederick   BEFS: logging cle...
611
  	befs_debug(sb, "<--- %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
613
614
  	kfree(result);
  	return -EILSEQ;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
616
617
  enum {
  	Opt_uid, Opt_gid, Opt_charset, Opt_debug, Opt_err,
  };
a447c0932   Steven Whitehouse   vfs: Use const fo...
618
  static const match_table_t befs_tokens = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
620
621
622
623
624
625
626
  	{Opt_uid, "uid=%d"},
  	{Opt_gid, "gid=%d"},
  	{Opt_charset, "iocharset=%s"},
  	{Opt_debug, "debug"},
  	{Opt_err, NULL}
  };
  
  static int
09ad0eae5   Fabian Frederick   befs: replace typ...
627
  parse_options(char *options, struct befs_mount_options *opts)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
628
629
630
631
  {
  	char *p;
  	substring_t args[MAX_OPT_ARGS];
  	int option;
31aba059b   Eric W. Biederman   userns: Convert b...
632
633
  	kuid_t uid;
  	kgid_t gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
635
  
  	/* Initialize options */
31aba059b   Eric W. Biederman   userns: Convert b...
636
637
  	opts->uid = GLOBAL_ROOT_UID;
  	opts->gid = GLOBAL_ROOT_GID;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
  	opts->use_uid = 0;
  	opts->use_gid = 0;
  	opts->iocharset = NULL;
  	opts->debug = 0;
  
  	if (!options)
  		return 1;
  
  	while ((p = strsep(&options, ",")) != NULL) {
  		int token;
  		if (!*p)
  			continue;
  
  		token = match_token(p, befs_tokens, args);
  		switch (token) {
  		case Opt_uid:
  			if (match_int(&args[0], &option))
  				return 0;
31aba059b   Eric W. Biederman   userns: Convert b...
656
657
658
659
  			uid = INVALID_UID;
  			if (option >= 0)
  				uid = make_kuid(current_user_ns(), option);
  			if (!uid_valid(uid)) {
dac52fc18   Fabian Frederick   BEFS: logging cle...
660
661
662
  				pr_err("Invalid uid %d, "
  				       "using default
  ", option);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
663
664
  				break;
  			}
31aba059b   Eric W. Biederman   userns: Convert b...
665
  			opts->uid = uid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666
667
668
669
670
  			opts->use_uid = 1;
  			break;
  		case Opt_gid:
  			if (match_int(&args[0], &option))
  				return 0;
31aba059b   Eric W. Biederman   userns: Convert b...
671
672
673
674
  			gid = INVALID_GID;
  			if (option >= 0)
  				gid = make_kgid(current_user_ns(), option);
  			if (!gid_valid(gid)) {
dac52fc18   Fabian Frederick   BEFS: logging cle...
675
676
677
  				pr_err("Invalid gid %d, "
  				       "using default
  ", option);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
679
  				break;
  			}
31aba059b   Eric W. Biederman   userns: Convert b...
680
  			opts->gid = gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
682
683
684
685
686
  			opts->use_gid = 1;
  			break;
  		case Opt_charset:
  			kfree(opts->iocharset);
  			opts->iocharset = match_strdup(&args[0]);
  			if (!opts->iocharset) {
dac52fc18   Fabian Frederick   BEFS: logging cle...
687
688
689
  				pr_err("allocation failure for "
  				       "iocharset string
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
690
691
692
693
694
695
696
  				return 0;
  			}
  			break;
  		case Opt_debug:
  			opts->debug = 1;
  			break;
  		default:
dac52fc18   Fabian Frederick   BEFS: logging cle...
697
698
699
  			pr_err("Unrecognized mount option \"%s\" "
  			       "or missing value
  ", p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
701
702
703
704
705
706
707
  			return 0;
  		}
  	}
  	return 1;
  }
  
  /* This function has the responsibiltiy of getting the
   * filesystem ready for unmounting. 
25985edce   Lucas De Marchi   Fix common misspe...
708
   * Basically, we free everything that we allocated in
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
709
710
711
712
713
   * befs_read_inode
   */
  static void
  befs_put_super(struct super_block *sb)
  {
f99d49adf   Jesper Juhl   [PATCH] kfree cle...
714
715
  	kfree(BEFS_SB(sb)->mount_opts.iocharset);
  	BEFS_SB(sb)->mount_opts.iocharset = NULL;
6d729e44a   Thomas Gleixner   fs: Make unload_n...
716
  	unload_nls(BEFS_SB(sb)->nls);
f99d49adf   Jesper Juhl   [PATCH] kfree cle...
717
718
  	kfree(sb->s_fs_info);
  	sb->s_fs_info = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719
720
721
722
723
724
725
726
727
728
729
730
  }
  
  /* Allocate private field of the superblock, fill it.
   *
   * Finish filling the public superblock fields
   * Make the root directory
   * Load a set of NLS translations if needed.
   */
  static int
  befs_fill_super(struct super_block *sb, void *data, int silent)
  {
  	struct buffer_head *bh;
038428fcf   Fabian Frederick   befs: replace typ...
731
  	struct befs_sb_info *befs_sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
733
  	befs_super_block *disk_sb;
  	struct inode *root;
96eb54194   David Howells   iget: stop BEFS f...
734
  	long ret = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
735
736
  	const unsigned long sb_block = 0;
  	const off_t x86_sb_off = 512;
173b066f5   Luis de Bethencourt   befs: check retur...
737
  	int blocksize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
738

552c3c6c5   Miklos Szeredi   mount options: fi...
739
  	save_mount_options(sb, data);
2d4319ef5   Fabian Frederick   befs: replace kma...
740
  	sb->s_fs_info = kzalloc(sizeof(*befs_sb), GFP_KERNEL);
c625426fb   Salah Triki   fs/befs/linuxvfs....
741
  	if (sb->s_fs_info == NULL)
0418726bb   Adrian Bunk   typo fixes: aquir...
742
  		goto unacquire_none;
c625426fb   Salah Triki   fs/befs/linuxvfs....
743

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
  	befs_sb = BEFS_SB(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
746
  
  	if (!parse_options((char *) data, &befs_sb->mount_opts)) {
dceee2e23   Salah Triki   fs/befs/linuxvfs....
747
748
  		if (!silent)
  			befs_error(sb, "cannot parse mount options");
0418726bb   Adrian Bunk   typo fixes: aquir...
749
  		goto unacquire_priv_sbp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750
  	}
dac52fc18   Fabian Frederick   BEFS: logging cle...
751
  	befs_debug(sb, "---> %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
753
754
755
756
757
  	if (!(sb->s_flags & MS_RDONLY)) {
  		befs_warning(sb,
  			     "No write support. Marking filesystem read-only");
  		sb->s_flags |= MS_RDONLY;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
758
759
760
761
762
763
  
  	/*
  	 * Set dummy blocksize to read super block.
  	 * Will be set to real fs blocksize later.
  	 *
  	 * Linux 2.4.10 and later refuse to read blocks smaller than
a441b0d09   Linus Walleij   block: remove rem...
764
  	 * the logical block size for the device. But we also need to read at
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765
766
767
  	 * least 1k to get the second 512 bytes of the volume.
  	 * -WD 10-26-01
  	 */ 
173b066f5   Luis de Bethencourt   befs: check retur...
768
769
  	blocksize = sb_min_blocksize(sb, 1024);
  	if (!blocksize) {
a64998504   Luis de Bethencourt   fs: befs: check s...
770
771
  		if (!silent)
  			befs_error(sb, "unable to set blocksize");
173b066f5   Luis de Bethencourt   befs: check retur...
772
773
  		goto unacquire_priv_sbp;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
775
  
  	if (!(bh = sb_bread(sb, sb_block))) {
dceee2e23   Salah Triki   fs/befs/linuxvfs....
776
777
  		if (!silent)
  			befs_error(sb, "unable to read superblock");
0418726bb   Adrian Bunk   typo fixes: aquir...
778
  		goto unacquire_priv_sbp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
779
780
781
782
  	}
  
  	/* account for offset of super block on x86 */
  	disk_sb = (befs_super_block *) bh->b_data;
152b95a1e   Harvey Harrison   befs: annotate fs...
783
784
  	if ((disk_sb->magic1 == BEFS_SUPER_MAGIC1_LE) ||
  	    (disk_sb->magic1 == BEFS_SUPER_MAGIC1_BE)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
786
787
788
789
790
  		befs_debug(sb, "Using PPC superblock location");
  	} else {
  		befs_debug(sb, "Using x86 superblock location");
  		disk_sb =
  		    (befs_super_block *) ((void *) bh->b_data + x86_sb_off);
  	}
8e19189ef   Fabian Frederick   fs/befs/linuxvfs....
791
792
  	if ((befs_load_sb(sb, disk_sb) != BEFS_OK) ||
  	    (befs_check_sb(sb) != BEFS_OK))
0418726bb   Adrian Bunk   typo fixes: aquir...
793
  		goto unacquire_bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
794
795
796
797
  
  	befs_dump_super_block(sb, disk_sb);
  
  	brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798
  	if( befs_sb->num_blocks > ~((sector_t)0) ) {
dceee2e23   Salah Triki   fs/befs/linuxvfs....
799
800
801
  		if (!silent)
  			befs_error(sb, "blocks count: %llu is larger than the host can use",
  					befs_sb->num_blocks);
0418726bb   Adrian Bunk   typo fixes: aquir...
802
  		goto unacquire_priv_sbp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803
804
805
806
807
808
809
810
811
  	}
  
  	/*
  	 * set up enough so that it can read an inode
  	 * Fill in kernel superblock fields from private sb
  	 */
  	sb->s_magic = BEFS_SUPER_MAGIC;
  	/* Set real blocksize of fs */
  	sb_set_blocksize(sb, (ulong) befs_sb->block_size);
b87221de6   Alexey Dobriyan   const: mark remai...
812
  	sb->s_op = &befs_sops;
96eb54194   David Howells   iget: stop BEFS f...
813
814
815
816
817
  	root = befs_iget(sb, iaddr2blockno(sb, &(befs_sb->root_dir)));
  	if (IS_ERR(root)) {
  		ret = PTR_ERR(root);
  		goto unacquire_priv_sbp;
  	}
48fde701a   Al Viro   switch open-coded...
818
  	sb->s_root = d_make_root(root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819
  	if (!sb->s_root) {
dceee2e23   Salah Triki   fs/befs/linuxvfs....
820
821
  		if (!silent)
  			befs_error(sb, "get root inode failed");
0418726bb   Adrian Bunk   typo fixes: aquir...
822
  		goto unacquire_priv_sbp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
  	}
  
  	/* load nls library */
  	if (befs_sb->mount_opts.iocharset) {
  		befs_debug(sb, "Loading nls: %s",
  			   befs_sb->mount_opts.iocharset);
  		befs_sb->nls = load_nls(befs_sb->mount_opts.iocharset);
  		if (!befs_sb->nls) {
  			befs_warning(sb, "Cannot load nls %s"
  					" loading default nls",
  					befs_sb->mount_opts.iocharset);
  			befs_sb->nls = load_nls_default();
  		}
  	/* load default nls if none is specified  in mount options */
  	} else {
  		befs_debug(sb, "Loading default nls");
  		befs_sb->nls = load_nls_default();
  	}
  
  	return 0;
  /*****************/
0418726bb   Adrian Bunk   typo fixes: aquir...
844
        unacquire_bh:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845
  	brelse(bh);
0418726bb   Adrian Bunk   typo fixes: aquir...
846
        unacquire_priv_sbp:
8dd5ca532   Al Viro   befs: fix leak
847
  	kfree(befs_sb->mount_opts.iocharset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
848
  	kfree(sb->s_fs_info);
30982583e   Salah Triki   fs/befs/linuxvfs....
849
  	sb->s_fs_info = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
850

0418726bb   Adrian Bunk   typo fixes: aquir...
851
        unacquire_none:
96eb54194   David Howells   iget: stop BEFS f...
852
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
853
854
855
856
857
  }
  
  static int
  befs_remount(struct super_block *sb, int *flags, char *data)
  {
02b9984d6   Theodore Ts'o   fs: push sync_fil...
858
  	sync_filesystem(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
859
860
861
862
863
864
  	if (!(*flags & MS_RDONLY))
  		return -EINVAL;
  	return 0;
  }
  
  static int
726c33422   David Howells   [PATCH] VFS: Perm...
865
  befs_statfs(struct dentry *dentry, struct kstatfs *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
866
  {
726c33422   David Howells   [PATCH] VFS: Perm...
867
  	struct super_block *sb = dentry->d_sb;
8587246a0   Coly Li   fs/befs: return f...
868
  	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
869

dac52fc18   Fabian Frederick   BEFS: logging cle...
870
  	befs_debug(sb, "---> %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
871
872
873
874
875
876
877
878
  
  	buf->f_type = BEFS_SUPER_MAGIC;
  	buf->f_bsize = sb->s_blocksize;
  	buf->f_blocks = BEFS_SB(sb)->num_blocks;
  	buf->f_bfree = BEFS_SB(sb)->num_blocks - BEFS_SB(sb)->used_blocks;
  	buf->f_bavail = buf->f_bfree;
  	buf->f_files = 0;	/* UNKNOWN */
  	buf->f_ffree = 0;	/* UNKNOWN */
8587246a0   Coly Li   fs/befs: return f...
879
880
  	buf->f_fsid.val[0] = (u32)id;
  	buf->f_fsid.val[1] = (u32)(id >> 32);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
881
  	buf->f_namelen = BEFS_NAME_LEN;
dac52fc18   Fabian Frederick   BEFS: logging cle...
882
  	befs_debug(sb, "<--- %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883
884
885
  
  	return 0;
  }
152a08366   Al Viro   new helper: mount...
886
887
888
  static struct dentry *
  befs_mount(struct file_system_type *fs_type, int flags, const char *dev_name,
  	    void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
889
  {
152a08366   Al Viro   new helper: mount...
890
  	return mount_bdev(fs_type, flags, dev_name, data, befs_fill_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
891
892
893
894
895
  }
  
  static struct file_system_type befs_fs_type = {
  	.owner		= THIS_MODULE,
  	.name		= "befs",
152a08366   Al Viro   new helper: mount...
896
  	.mount		= befs_mount,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
898
899
  	.kill_sb	= kill_block_super,
  	.fs_flags	= FS_REQUIRES_DEV,	
  };
7f78e0351   Eric W. Biederman   fs: Limit sys_mou...
900
  MODULE_ALIAS_FS("befs");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
901
902
903
904
905
  
  static int __init
  init_befs_fs(void)
  {
  	int err;
dac52fc18   Fabian Frederick   BEFS: logging cle...
906
907
  	pr_info("version: %s
  ", BEFS_VERSION);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
908
909
910
  
  	err = befs_init_inodecache();
  	if (err)
0418726bb   Adrian Bunk   typo fixes: aquir...
911
  		goto unacquire_none;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912
913
914
  
  	err = register_filesystem(&befs_fs_type);
  	if (err)
0418726bb   Adrian Bunk   typo fixes: aquir...
915
  		goto unacquire_inodecache;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916
917
  
  	return 0;
0418726bb   Adrian Bunk   typo fixes: aquir...
918
  unacquire_inodecache:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
  	befs_destroy_inodecache();
0418726bb   Adrian Bunk   typo fixes: aquir...
920
  unacquire_none:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
  	return err;
  }
  
  static void __exit
  exit_befs_fs(void)
  {
  	befs_destroy_inodecache();
  
  	unregister_filesystem(&befs_fs_type);
  }
  
  /*
  Macros that typecheck the init and exit functions,
  ensures that they are called at init and cleanup,
  and eliminates warnings about unused functions.
  */
  module_init(init_befs_fs)
  module_exit(exit_befs_fs)