Blame view

fs/befs/linuxvfs.c 25.5 KB
09c434b8a   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
  /*
   * linux/fs/befs/linuxvfs.c
   *
   * Copyright (C) 2001 Will Dyson <will_dyson@pobox.com
   *
   */
dac52fc18   Fabian Frederick   BEFS: logging cle...
8
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
14
15
16
17
18
  #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...
19
  #include <linux/sched.h>
5b825c3af   Ingo Molnar   sched/headers: Pr...
20
  #include <linux/cred.h>
ac632f5b6   Luis de Bethencourt   befs: add NFS exp...
21
  #include <linux/exportfs.h>
3ab7947ac   David Howells   befs: Implement s...
22
  #include <linux/seq_file.h>
621c1f429   Christoph Hellwig   block: move struc...
23
  #include <linux/blkdev.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
27
28
29
30
  
  #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
31
32
33
34
35
36
37
  
  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...
38
  static int befs_readdir(struct file *, struct dir_context *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
41
  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);
62b80719d   Luis de Bethencourt   befs: fix style i...
42
43
  static struct dentry *befs_lookup(struct inode *, struct dentry *,
  				  unsigned int);
96eb54194   David Howells   iget: stop BEFS f...
44
  static struct inode *befs_iget(struct super_block *, unsigned long);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
  static struct inode *befs_alloc_inode(struct super_block *sb);
49f82a808   Al Viro   befs: switch to -...
46
  static void befs_free_inode(struct inode *inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
  static void befs_destroy_inodecache(void);
11803f97f   Al Viro   switch befs long ...
48
  static int befs_symlink_readpage(struct file *, struct page *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
52
53
54
  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...
55
  static int befs_statfs(struct dentry *, struct kstatfs *);
3ab7947ac   David Howells   befs: Implement s...
56
  static int befs_show_options(struct seq_file *, struct dentry *);
09ad0eae5   Fabian Frederick   befs: replace typ...
57
  static int parse_options(char *, struct befs_mount_options *);
ac632f5b6   Luis de Bethencourt   befs: add NFS exp...
58
59
60
61
  static struct dentry *befs_fh_to_dentry(struct super_block *sb,
  				struct fid *fid, int fh_len, int fh_type);
  static struct dentry *befs_fh_to_parent(struct super_block *sb,
  				struct fid *fid, int fh_len, int fh_type);
dcfd9b215   Fabian Frederick   befs: make export...
62
  static struct dentry *befs_get_parent(struct dentry *child);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
64
  
  static const struct super_operations befs_sops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  	.alloc_inode	= befs_alloc_inode,	/* allocate a new inode */
49f82a808   Al Viro   befs: switch to -...
66
  	.free_inode	= befs_free_inode, /* deallocate an inode */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
69
  	.put_super	= befs_put_super,	/* uninit super */
  	.statfs		= befs_statfs,	/* statfs */
  	.remount_fs	= befs_remount,
3ab7947ac   David Howells   befs: Implement s...
70
  	.show_options	= befs_show_options,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
72
73
  };
  
  /* slab cache for befs_inode_info objects */
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
74
  static struct kmem_cache *befs_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75

4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
76
  static const struct file_operations befs_dir_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
  	.read		= generic_read_dir,
e23e9aa75   Al Viro   befs: switch to -...
78
  	.iterate_shared	= befs_readdir,
59af1584b   Al Viro   [PATCH] fix ->lls...
79
  	.llseek		= generic_file_llseek,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
  };
754661f14   Arjan van de Ven   [PATCH] mark stru...
81
  static const struct inode_operations befs_dir_inode_operations = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
83
  	.lookup		= befs_lookup,
  };
f5e54d6e5   Christoph Hellwig   [PATCH] mark addr...
84
  static const struct address_space_operations befs_aops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
  	.readpage	= befs_readpage,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
  	.bmap		= befs_bmap,
  };
11803f97f   Al Viro   switch befs long ...
88
89
  static const struct address_space_operations befs_symlink_aops = {
  	.readpage	= befs_symlink_readpage,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
  };
ac632f5b6   Luis de Bethencourt   befs: add NFS exp...
91
92
93
  static const struct export_operations befs_export_operations = {
  	.fh_to_dentry	= befs_fh_to_dentry,
  	.fh_to_parent	= befs_fh_to_parent,
dcfd9b215   Fabian Frederick   befs: make export...
94
  	.get_parent	= befs_get_parent,
ac632f5b6   Luis de Bethencourt   befs: add NFS exp...
95
  };
e60f749b6   Luis de Bethencourt   befs: remove trai...
96
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
   * Called by generic_file_read() to read a page of data
e60f749b6   Luis de Bethencourt   befs: remove trai...
98
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
   * 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);
  }
e60f749b6   Luis de Bethencourt   befs: remove trai...
114
115
  /*
   * Generic function to map a file position (block) to a
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
117
118
119
120
   * disk offset (passed back in bh_result).
   *
   * Used by many higher level functions.
   *
   * Calls befs_fblock2brun() in datastream.c to do the real work.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
125
126
127
128
129
   */
  
  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 ...
130
  	int res;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
  	ulong disk_off;
  
  	befs_debug(sb, "---> befs_get_block() for inode %lu, block %ld",
dac52fc18   Fabian Frederick   BEFS: logging cle...
134
  		   (unsigned long)inode->i_ino, (long)block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
136
  	if (create) {
  		befs_error(sb, "befs_get_block() was asked to write to "
dac52fc18   Fabian Frederick   BEFS: logging cle...
137
138
  			   "block %ld in inode %lu", (long)block,
  			   (unsigned long)inode->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
142
143
144
  		return -EPERM;
  	}
  
  	res = befs_fblock2brun(sb, ds, block, &run);
  	if (res != BEFS_OK) {
  		befs_error(sb,
dac52fc18   Fabian Frederick   BEFS: logging cle...
145
146
147
  			   "<--- %s for inode %lu, block %ld ERROR",
  			   __func__, (unsigned long)inode->i_ino,
  			   (long)block);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
149
150
151
152
153
  		return -EFBIG;
  	}
  
  	disk_off = (ulong) iaddr2blockno(sb, &run);
  
  	map_bh(bh_result, inode->i_sb, disk_off);
dac52fc18   Fabian Frederick   BEFS: logging cle...
154
155
156
  	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
157
158
159
160
161
  
  	return 0;
  }
  
  static struct dentry *
00cd8dd3b   Al Viro   stop passing name...
162
  befs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
  {
c94087636   Salah Triki   fs/befs/linuxvfs....
164
  	struct inode *inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
  	struct super_block *sb = dir->i_sb;
22341d8f3   Al Viro   befs: constify st...
166
  	const befs_data_stream *ds = &BEFS_I(dir)->i_data.ds;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
169
170
171
  	befs_off_t offset;
  	int ret;
  	int utfnamelen;
  	char *utfname;
  	const char *name = dentry->d_name.name;
a455589f1   Al Viro   assorted conversi...
172
173
  	befs_debug(sb, "---> %s name %pd inode %ld", __func__,
  		   dentry, dir->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
176
177
178
179
  
  	/* 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...
180
  			befs_debug(sb, "<--- %s ERROR", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
182
183
184
185
186
  			return ERR_PTR(ret);
  		}
  		ret = befs_btree_find(sb, ds, utfname, &offset);
  		kfree(utfname);
  
  	} else {
f7769f9cf   Luis de Bethencourt   befs: avoid deref...
187
  		ret = befs_btree_find(sb, ds, name, &offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
189
190
  	}
  
  	if (ret == BEFS_BT_NOT_FOUND) {
a455589f1   Al Viro   assorted conversi...
191
  		befs_debug(sb, "<--- %s %pd not found", __func__, dentry);
f4e4d434f   Al Viro   befs_lookup(): us...
192
  		inode = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
  	} else if (ret != BEFS_OK || offset == 0) {
4c3897cce   Luis de Bethencourt   befs: make consis...
194
  		befs_error(sb, "<--- %s Error", __func__);
f4e4d434f   Al Viro   befs_lookup(): us...
195
196
197
  		inode = ERR_PTR(-ENODATA);
  	} else {
  		inode = befs_iget(dir->i_sb, (ino_t) offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
  	}
dac52fc18   Fabian Frederick   BEFS: logging cle...
199
  	befs_debug(sb, "<--- %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200

f4e4d434f   Al Viro   befs_lookup(): us...
201
  	return d_splice_alias(inode, dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
204
  }
  
  static int
f0f49ef5c   Al Viro   [readdir] convert...
205
  befs_readdir(struct file *file, struct dir_context *ctx)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
  {
f0f49ef5c   Al Viro   [readdir] convert...
207
  	struct inode *inode = file_inode(file);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
  	struct super_block *sb = inode->i_sb;
22341d8f3   Al Viro   befs: constify st...
209
  	const befs_data_stream *ds = &BEFS_I(inode)->i_data.ds;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
211
212
  	befs_off_t value;
  	int result;
  	size_t keysize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
  	char keybuf[BEFS_NAME_LEN + 1];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214

a455589f1   Al Viro   assorted conversi...
215
216
  	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
217

9ae51a32b   Luis de Bethencourt   befs: use simpler...
218
219
220
  	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
221

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

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

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

dac52fc18   Fabian Frederick   BEFS: logging cle...
292
  	befs_debug(sb, "---> %s inode = %lu", __func__, ino);
96eb54194   David Howells   iget: stop BEFS f...
293
294
  
  	inode = iget_locked(sb, ino);
ac34a1b35   Rakesh Pandit   befs: iget_locked...
295
296
  	if (!inode)
  		return ERR_PTR(-ENOMEM);
96eb54194   David Howells   iget: stop BEFS f...
297
298
  	if (!(inode->i_state & I_NEW))
  		return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
301
302
303
304
305
306
307
  
  	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...
308
  	bh = sb_bread(sb, inode->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
311
  	if (!bh) {
  		befs_error(sb, "unable to read inode block - "
  			   "inode = %lu", inode->i_ino);
0418726bb   Adrian Bunk   typo fixes: aquir...
312
  		goto unacquire_none;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
314
315
316
317
318
319
320
  	}
  
  	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...
321
  		goto unacquire_bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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.
e60f749b6   Luis de Bethencourt   befs: remove trai...
329
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
331
  
  	inode->i_uid = befs_sb->mount_opts.use_uid ?
31aba059b   Eric W. Biederman   userns: Convert b...
332
333
  		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
334
  	inode->i_gid = befs_sb->mount_opts.use_gid ?
31aba059b   Eric W. Biederman   userns: Convert b...
335
336
  		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
337

bfe868486   Miklos Szeredi   filesystems: add ...
338
  	set_nlink(inode, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
341
342
343
  
  	/*
  	 * 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.
e60f749b6   Luis de Bethencourt   befs: remove trai...
344
  	 * Also, the lower 16 bits of the last_modified_time and
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
346
347
348
349
350
  	 * 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;
e60f749b6   Luis de Bethencourt   befs: remove trai...
351
  	inode->i_mtime.tv_nsec = 0;   /* lower 16 bits are not a time */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
353
  	inode->i_ctime = inode->i_mtime;
  	inode->i_atime = inode->i_mtime;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
355
356
357
358
359
360
361
362
  
  	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....
363
364
  		strlcpy(befs_ino->i_data.symlink, raw_inode->data.symlink,
  			BEFS_SYMLINK_LEN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
365
366
367
368
  	} else {
  		int num_blks;
  
  		befs_ino->i_data.ds =
e0e3d32bb   Jesper Juhl   befs: don't pass ...
369
  		    fsds_to_cpu(sb, &raw_inode->data.datastream);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
372
373
374
375
376
377
378
379
  
  		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...
380
  		inode->i_fop = &generic_ro_fops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
382
383
384
  	} 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...
385
  		if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
11803f97f   Al Viro   switch befs long ...
386
  			inode->i_op = &page_symlink_inode_operations;
21fc61c73   Al Viro   don't put symlink...
387
  			inode_nohighmem(inode);
11803f97f   Al Viro   switch befs long ...
388
  			inode->i_mapping->a_ops = &befs_symlink_aops;
d0deec199   Al Viro   befs: switch to s...
389
390
391
392
  		} else {
  			inode->i_link = befs_ino->i_data.symlink;
  			inode->i_op = &simple_symlink_inode_operations;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
395
396
  	} 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...
397
  		goto unacquire_bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
399
400
  	}
  
  	brelse(bh);
dac52fc18   Fabian Frederick   BEFS: logging cle...
401
  	befs_debug(sb, "<--- %s", __func__);
96eb54194   David Howells   iget: stop BEFS f...
402
403
  	unlock_new_inode(inode);
  	return inode;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404

62b80719d   Luis de Bethencourt   befs: fix style i...
405
  unacquire_bh:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
  	brelse(bh);
62b80719d   Luis de Bethencourt   befs: fix style i...
407
  unacquire_none:
96eb54194   David Howells   iget: stop BEFS f...
408
  	iget_failed(inode);
dac52fc18   Fabian Frederick   BEFS: logging cle...
409
  	befs_debug(sb, "<--- %s - Bad inode", __func__);
33c712b4f   Salah Triki   fs: befs: remove ...
410
  	return ERR_PTR(-EIO);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
412
413
  }
  
  /* Initialize the inode cache. Called at fs setup.
20c2df83d   Paul Mundt   mm: Remove slab d...
414
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
416
   * Taken from NFS implementation by Al Viro.
   */
91a52ab7d   Fabian Frederick   fs/befs/linuxvfs....
417
  static int __init
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
418
419
  befs_init_inodecache(void)
  {
0fc256d3a   David Windsor   befs: Define user...
420
421
422
423
424
425
426
427
428
  	befs_inode_cachep = kmem_cache_create_usercopy("befs_inode_cache",
  				sizeof(struct befs_inode_info), 0,
  				(SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD|
  					SLAB_ACCOUNT),
  				offsetof(struct befs_inode_info,
  					i_data.symlink),
  				sizeof_field(struct befs_inode_info,
  					i_data.symlink),
  				init_once);
c08f1cb62   Salah Triki   fs: befs: remove ...
429
  	if (befs_inode_cachep == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
  		return -ENOMEM;
c08f1cb62   Salah Triki   fs: befs: remove ...
431

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
432
433
434
435
  	return 0;
  }
  
  /* Called at fs teardown.
e60f749b6   Luis de Bethencourt   befs: remove trai...
436
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
438
439
440
441
   * Taken from NFS implementation by Al Viro.
   */
  static void
  befs_destroy_inodecache(void)
  {
8c0a85377   Kirill A. Shutemov   fs: push rcu_barr...
442
443
444
445
446
  	/*
  	 * Make sure all delayed rcu free inodes are flushed before we
  	 * destroy cache.
  	 */
  	rcu_barrier();
1a1d92c10   Alexey Dobriyan   [PATCH] Really ig...
447
  	kmem_cache_destroy(befs_inode_cachep);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
450
451
452
453
454
  }
  
  /*
   * 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 ...
455
  static int befs_symlink_readpage(struct file *unused, struct page *page)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456
  {
11803f97f   Al Viro   switch befs long ...
457
458
459
  	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...
460
461
  	befs_data_stream *data = &befs_ino->i_data.ds;
  	befs_off_t len = data->size;
21fc61c73   Al Viro   don't put symlink...
462
  	char *link = page_address(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463

11803f97f   Al Viro   switch befs long ...
464
  	if (len == 0 || len > PAGE_SIZE) {
48bc06e74   Al Viro   befs: split symli...
465
  		befs_error(sb, "Long symlink with illegal length");
11803f97f   Al Viro   switch befs long ...
466
  		goto fail;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
467
  	}
680baacbc   Al Viro   new ->follow_link...
468
  	befs_debug(sb, "Follow long symlink");
680baacbc   Al Viro   new ->follow_link...
469
  	if (befs_read_lsymlink(sb, data, link, len) != len) {
680baacbc   Al Viro   new ->follow_link...
470
  		befs_error(sb, "Failed to read entire long symlink");
11803f97f   Al Viro   switch befs long ...
471
  		goto fail;
680baacbc   Al Viro   new ->follow_link...
472
473
  	}
  	link[len - 1] = '\0';
11803f97f   Al Viro   switch befs long ...
474
  	SetPageUptodate(page);
11803f97f   Al Viro   switch befs long ...
475
476
477
478
  	unlock_page(page);
  	return 0;
  fail:
  	SetPageError(page);
11803f97f   Al Viro   switch befs long ...
479
480
  	unlock_page(page);
  	return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
  /*
1ca7087e5   Luis de Bethencourt   befs: fix typos i...
483
   * UTF-8 to NLS charset convert routine
e60f749b6   Luis de Bethencourt   befs: remove trai...
484
   *
1ca7087e5   Luis de Bethencourt   befs: fix typos i...
485
   * Uses uni2char() / char2uni() rather than the nls tables directly
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
488
489
490
491
492
  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...
493
  	unicode_t uni;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
495
  	int unilen, utflen;
  	char *result;
94f563c42   Diego Calleja   [PATCH] Fix BeFS ...
496
497
498
499
500
  	/* 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
501

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

dac52fc18   Fabian Frederick   BEFS: logging cle...
578
579
  	befs_debug(sb, "---> %s
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
  
  	if (!nls) {
dac52fc18   Fabian Frederick   BEFS: logging cle...
582
583
  		befs_error(sb, "%s called with no NLS table loaded.",
  			   __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
585
586
587
588
  		return -EINVAL;
  	}
  
  	*out = result = kmalloc(maxlen, GFP_NOFS);
  	if (!*out) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
590
591
592
593
594
595
596
  		*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...
597
  		if (unilen < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598
  			goto conv_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599
600
  
  		/* convert from unicode to UTF-8 */
74675a585   Alan Stern   NLS: update handl...
601
602
  		utflen = utf32_to_utf8(uni, &result[o], 3);
  		if (utflen <= 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
  			goto conv_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
604
605
606
607
  	}
  
  	result[o] = '\0';
  	*out_len = o;
dac52fc18   Fabian Frederick   BEFS: logging cle...
608
  	befs_debug(sb, "<--- %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
610
  
  	return i;
62b80719d   Luis de Bethencourt   befs: fix style i...
611
  conv_err:
1ca7087e5   Luis de Bethencourt   befs: fix typos i...
612
  	befs_error(sb, "Name using character set %s contains a character that "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
  		   "cannot be converted to unicode.", nls->charset);
dac52fc18   Fabian Frederick   BEFS: logging cle...
614
  	befs_debug(sb, "<--- %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
616
617
  	kfree(result);
  	return -EILSEQ;
  }
ac632f5b6   Luis de Bethencourt   befs: add NFS exp...
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
  static struct inode *befs_nfs_get_inode(struct super_block *sb, uint64_t ino,
  					 uint32_t generation)
  {
  	/* No need to handle i_generation */
  	return befs_iget(sb, ino);
  }
  
  /*
   * Map a NFS file handle to a corresponding dentry
   */
  static struct dentry *befs_fh_to_dentry(struct super_block *sb,
  				struct fid *fid, int fh_len, int fh_type)
  {
  	return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
  				    befs_nfs_get_inode);
  }
  
  /*
   * Find the parent for a file specified by NFS handle
   */
  static struct dentry *befs_fh_to_parent(struct super_block *sb,
  				struct fid *fid, int fh_len, int fh_type)
  {
  	return generic_fh_to_parent(sb, fid, fh_len, fh_type,
  				    befs_nfs_get_inode);
  }
dcfd9b215   Fabian Frederick   befs: make export...
644
645
646
647
648
649
650
651
652
653
654
655
  static struct dentry *befs_get_parent(struct dentry *child)
  {
  	struct inode *parent;
  	struct befs_inode_info *befs_ino = BEFS_I(d_inode(child));
  
  	parent = befs_iget(child->d_sb,
  			   (unsigned long)befs_ino->i_parent.start);
  	if (IS_ERR(parent))
  		return ERR_CAST(parent);
  
  	return d_obtain_alias(parent);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
657
658
  enum {
  	Opt_uid, Opt_gid, Opt_charset, Opt_debug, Opt_err,
  };
a447c0932   Steven Whitehouse   vfs: Use const fo...
659
  static const match_table_t befs_tokens = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
660
661
662
663
664
665
666
667
  	{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...
668
  parse_options(char *options, struct befs_mount_options *opts)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
669
670
671
672
  {
  	char *p;
  	substring_t args[MAX_OPT_ARGS];
  	int option;
31aba059b   Eric W. Biederman   userns: Convert b...
673
674
  	kuid_t uid;
  	kgid_t gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
676
  
  	/* Initialize options */
31aba059b   Eric W. Biederman   userns: Convert b...
677
678
  	opts->uid = GLOBAL_ROOT_UID;
  	opts->gid = GLOBAL_ROOT_GID;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679
680
681
682
683
684
685
686
687
688
  	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;
62b80719d   Luis de Bethencourt   befs: fix style i...
689

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
690
691
692
693
694
695
696
697
  		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...
698
699
700
701
  			uid = INVALID_UID;
  			if (option >= 0)
  				uid = make_kuid(current_user_ns(), option);
  			if (!uid_valid(uid)) {
dac52fc18   Fabian Frederick   BEFS: logging cle...
702
703
704
  				pr_err("Invalid uid %d, "
  				       "using default
  ", option);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705
706
  				break;
  			}
31aba059b   Eric W. Biederman   userns: Convert b...
707
  			opts->uid = uid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708
709
710
711
712
  			opts->use_uid = 1;
  			break;
  		case Opt_gid:
  			if (match_int(&args[0], &option))
  				return 0;
31aba059b   Eric W. Biederman   userns: Convert b...
713
714
715
716
  			gid = INVALID_GID;
  			if (option >= 0)
  				gid = make_kgid(current_user_ns(), option);
  			if (!gid_valid(gid)) {
dac52fc18   Fabian Frederick   BEFS: logging cle...
717
718
719
  				pr_err("Invalid gid %d, "
  				       "using default
  ", option);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
721
  				break;
  			}
31aba059b   Eric W. Biederman   userns: Convert b...
722
  			opts->gid = gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723
724
725
726
727
728
  			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...
729
730
731
  				pr_err("allocation failure for "
  				       "iocharset string
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
733
734
735
736
737
738
  				return 0;
  			}
  			break;
  		case Opt_debug:
  			opts->debug = 1;
  			break;
  		default:
dac52fc18   Fabian Frederick   BEFS: logging cle...
739
740
741
  			pr_err("Unrecognized mount option \"%s\" "
  			       "or missing value
  ", p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
742
743
744
745
746
  			return 0;
  		}
  	}
  	return 1;
  }
3ab7947ac   David Howells   befs: Implement s...
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
  static int befs_show_options(struct seq_file *m, struct dentry *root)
  {
  	struct befs_sb_info *befs_sb = BEFS_SB(root->d_sb);
  	struct befs_mount_options *opts = &befs_sb->mount_opts;
  
  	if (!uid_eq(opts->uid, GLOBAL_ROOT_UID))
  		seq_printf(m, ",uid=%u",
  			   from_kuid_munged(&init_user_ns, opts->uid));
  	if (!gid_eq(opts->gid, GLOBAL_ROOT_GID))
  		seq_printf(m, ",gid=%u",
  			   from_kgid_munged(&init_user_ns, opts->gid));
  	if (opts->iocharset)
  		seq_printf(m, ",charset=%s", opts->iocharset);
  	if (opts->debug)
  		seq_puts(m, ",debug");
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
  /* This function has the responsibiltiy of getting the
e60f749b6   Luis de Bethencourt   befs: remove trai...
765
   * filesystem ready for unmounting.
25985edce   Lucas De Marchi   Fix common misspe...
766
   * Basically, we free everything that we allocated in
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
768
769
770
771
   * befs_read_inode
   */
  static void
  befs_put_super(struct super_block *sb)
  {
f99d49adf   Jesper Juhl   [PATCH] kfree cle...
772
773
  	kfree(BEFS_SB(sb)->mount_opts.iocharset);
  	BEFS_SB(sb)->mount_opts.iocharset = NULL;
6d729e44a   Thomas Gleixner   fs: Make unload_n...
774
  	unload_nls(BEFS_SB(sb)->nls);
f99d49adf   Jesper Juhl   [PATCH] kfree cle...
775
776
  	kfree(sb->s_fs_info);
  	sb->s_fs_info = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
777
778
779
780
781
782
783
784
785
786
787
788
  }
  
  /* 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...
789
  	struct befs_sb_info *befs_sb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
790
791
  	befs_super_block *disk_sb;
  	struct inode *root;
96eb54194   David Howells   iget: stop BEFS f...
792
  	long ret = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
793
794
  	const unsigned long sb_block = 0;
  	const off_t x86_sb_off = 512;
173b066f5   Luis de Bethencourt   befs: check retur...
795
  	int blocksize;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796

2d4319ef5   Fabian Frederick   befs: replace kma...
797
  	sb->s_fs_info = kzalloc(sizeof(*befs_sb), GFP_KERNEL);
c625426fb   Salah Triki   fs/befs/linuxvfs....
798
  	if (sb->s_fs_info == NULL)
0418726bb   Adrian Bunk   typo fixes: aquir...
799
  		goto unacquire_none;
c625426fb   Salah Triki   fs/befs/linuxvfs....
800

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
801
  	befs_sb = BEFS_SB(sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
803
  
  	if (!parse_options((char *) data, &befs_sb->mount_opts)) {
dceee2e23   Salah Triki   fs/befs/linuxvfs....
804
805
  		if (!silent)
  			befs_error(sb, "cannot parse mount options");
0418726bb   Adrian Bunk   typo fixes: aquir...
806
  		goto unacquire_priv_sbp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
  	}
dac52fc18   Fabian Frederick   BEFS: logging cle...
808
  	befs_debug(sb, "---> %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809

bc98a42c1   David Howells   VFS: Convert sb->...
810
  	if (!sb_rdonly(sb)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
811
812
  		befs_warning(sb,
  			     "No write support. Marking filesystem read-only");
1751e8a6c   Linus Torvalds   Rename superblock...
813
  		sb->s_flags |= SB_RDONLY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
814
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815
816
817
818
819
820
  
  	/*
  	 * 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...
821
  	 * the logical block size for the device. But we also need to read at
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
  	 * least 1k to get the second 512 bytes of the volume.
e60f749b6   Luis de Bethencourt   befs: remove trai...
823
  	 */
173b066f5   Luis de Bethencourt   befs: check retur...
824
825
  	blocksize = sb_min_blocksize(sb, 1024);
  	if (!blocksize) {
a64998504   Luis de Bethencourt   fs: befs: check s...
826
827
  		if (!silent)
  			befs_error(sb, "unable to set blocksize");
173b066f5   Luis de Bethencourt   befs: check retur...
828
829
  		goto unacquire_priv_sbp;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
830

62b80719d   Luis de Bethencourt   befs: fix style i...
831
832
  	bh = sb_bread(sb, sb_block);
  	if (!bh) {
dceee2e23   Salah Triki   fs/befs/linuxvfs....
833
834
  		if (!silent)
  			befs_error(sb, "unable to read superblock");
0418726bb   Adrian Bunk   typo fixes: aquir...
835
  		goto unacquire_priv_sbp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
836
837
838
839
  	}
  
  	/* account for offset of super block on x86 */
  	disk_sb = (befs_super_block *) bh->b_data;
152b95a1e   Harvey Harrison   befs: annotate fs...
840
841
  	if ((disk_sb->magic1 == BEFS_SUPER_MAGIC1_LE) ||
  	    (disk_sb->magic1 == BEFS_SUPER_MAGIC1_BE)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
842
843
844
845
846
847
  		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....
848
849
  	if ((befs_load_sb(sb, disk_sb) != BEFS_OK) ||
  	    (befs_check_sb(sb) != BEFS_OK))
0418726bb   Adrian Bunk   typo fixes: aquir...
850
  		goto unacquire_bh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
851
852
853
854
  
  	befs_dump_super_block(sb, disk_sb);
  
  	brelse(bh);
62b80719d   Luis de Bethencourt   befs: fix style i...
855
  	if (befs_sb->num_blocks > ~((sector_t)0)) {
dceee2e23   Salah Triki   fs/befs/linuxvfs....
856
857
858
  		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...
859
  		goto unacquire_priv_sbp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
860
861
862
863
864
865
866
867
868
  	}
  
  	/*
  	 * 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...
869
  	sb->s_op = &befs_sops;
ac632f5b6   Luis de Bethencourt   befs: add NFS exp...
870
  	sb->s_export_op = &befs_export_operations;
22b139691   Deepa Dinamani   fs: Fill in max a...
871
872
  	sb->s_time_min = 0;
  	sb->s_time_max = 0xffffffffffffll;
96eb54194   David Howells   iget: stop BEFS f...
873
874
875
876
877
  	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...
878
  	sb->s_root = d_make_root(root);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
879
  	if (!sb->s_root) {
dceee2e23   Salah Triki   fs/befs/linuxvfs....
880
881
  		if (!silent)
  			befs_error(sb, "get root inode failed");
0418726bb   Adrian Bunk   typo fixes: aquir...
882
  		goto unacquire_priv_sbp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
  	}
  
  	/* 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;
62b80719d   Luis de Bethencourt   befs: fix style i...
903
904
  
  unacquire_bh:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
  	brelse(bh);
62b80719d   Luis de Bethencourt   befs: fix style i...
906
  unacquire_priv_sbp:
8dd5ca532   Al Viro   befs: fix leak
907
  	kfree(befs_sb->mount_opts.iocharset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
908
  	kfree(sb->s_fs_info);
30982583e   Salah Triki   fs/befs/linuxvfs....
909
  	sb->s_fs_info = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
910

62b80719d   Luis de Bethencourt   befs: fix style i...
911
  unacquire_none:
96eb54194   David Howells   iget: stop BEFS f...
912
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
913
914
915
916
917
  }
  
  static int
  befs_remount(struct super_block *sb, int *flags, char *data)
  {
02b9984d6   Theodore Ts'o   fs: push sync_fil...
918
  	sync_filesystem(sb);
1751e8a6c   Linus Torvalds   Rename superblock...
919
  	if (!(*flags & SB_RDONLY))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
920
921
922
923
924
  		return -EINVAL;
  	return 0;
  }
  
  static int
726c33422   David Howells   [PATCH] VFS: Perm...
925
  befs_statfs(struct dentry *dentry, struct kstatfs *buf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
  {
726c33422   David Howells   [PATCH] VFS: Perm...
927
  	struct super_block *sb = dentry->d_sb;
8587246a0   Coly Li   fs/befs: return f...
928
  	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
929

dac52fc18   Fabian Frederick   BEFS: logging cle...
930
  	befs_debug(sb, "---> %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
931
932
933
934
935
936
937
938
  
  	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 */
6d1349c76   Al Viro   [PATCH] reduce bo...
939
  	buf->f_fsid = u64_to_fsid(id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
940
  	buf->f_namelen = BEFS_NAME_LEN;
dac52fc18   Fabian Frederick   BEFS: logging cle...
941
  	befs_debug(sb, "<--- %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
942
943
944
  
  	return 0;
  }
152a08366   Al Viro   new helper: mount...
945
946
947
  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
948
  {
152a08366   Al Viro   new helper: mount...
949
  	return mount_bdev(fs_type, flags, dev_name, data, befs_fill_super);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
950
951
952
953
954
  }
  
  static struct file_system_type befs_fs_type = {
  	.owner		= THIS_MODULE,
  	.name		= "befs",
152a08366   Al Viro   new helper: mount...
955
  	.mount		= befs_mount,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
956
  	.kill_sb	= kill_block_super,
e60f749b6   Luis de Bethencourt   befs: remove trai...
957
  	.fs_flags	= FS_REQUIRES_DEV,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
958
  };
7f78e0351   Eric W. Biederman   fs: Limit sys_mou...
959
  MODULE_ALIAS_FS("befs");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
960
961
962
963
964
  
  static int __init
  init_befs_fs(void)
  {
  	int err;
dac52fc18   Fabian Frederick   BEFS: logging cle...
965
966
  	pr_info("version: %s
  ", BEFS_VERSION);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
967
968
969
  
  	err = befs_init_inodecache();
  	if (err)
0418726bb   Adrian Bunk   typo fixes: aquir...
970
  		goto unacquire_none;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
971
972
973
  
  	err = register_filesystem(&befs_fs_type);
  	if (err)
0418726bb   Adrian Bunk   typo fixes: aquir...
974
  		goto unacquire_inodecache;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
975
976
  
  	return 0;
0418726bb   Adrian Bunk   typo fixes: aquir...
977
  unacquire_inodecache:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
978
  	befs_destroy_inodecache();
0418726bb   Adrian Bunk   typo fixes: aquir...
979
  unacquire_none:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
980
981
982
983
984
985
986
987
988
989
990
991
  	return err;
  }
  
  static void __exit
  exit_befs_fs(void)
  {
  	befs_destroy_inodecache();
  
  	unregister_filesystem(&befs_fs_type);
  }
  
  /*
62b80719d   Luis de Bethencourt   befs: fix style i...
992
993
994
995
   * Macros that typecheck the init and exit functions,
   * ensures that they are called at init and cleanup,
   * and eliminates warnings about unused functions.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
996
997
  module_init(init_befs_fs)
  module_exit(exit_befs_fs)