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>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
26
27
28
29
  
  #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
30
31
32
33
34
35
36
  
  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...
37
  static int befs_readdir(struct file *, struct dir_context *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
40
  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...
41
42
  static struct dentry *befs_lookup(struct inode *, struct dentry *,
  				  unsigned int);
96eb54194   David Howells   iget: stop BEFS f...
43
  static struct inode *befs_iget(struct super_block *, unsigned long);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
  static struct inode *befs_alloc_inode(struct super_block *sb);
49f82a808   Al Viro   befs: switch to -...
45
  static void befs_free_inode(struct inode *inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
  static void befs_destroy_inodecache(void);
11803f97f   Al Viro   switch befs long ...
47
  static int befs_symlink_readpage(struct file *, struct page *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
50
51
52
53
  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...
54
  static int befs_statfs(struct dentry *, struct kstatfs *);
3ab7947ac   David Howells   befs: Implement s...
55
  static int befs_show_options(struct seq_file *, struct dentry *);
09ad0eae5   Fabian Frederick   befs: replace typ...
56
  static int parse_options(char *, struct befs_mount_options *);
ac632f5b6   Luis de Bethencourt   befs: add NFS exp...
57
58
59
60
  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...
61
  static struct dentry *befs_get_parent(struct dentry *child);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
63
  
  static const struct super_operations befs_sops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
  	.alloc_inode	= befs_alloc_inode,	/* allocate a new inode */
49f82a808   Al Viro   befs: switch to -...
65
  	.free_inode	= befs_free_inode, /* deallocate an inode */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
  	.put_super	= befs_put_super,	/* uninit super */
  	.statfs		= befs_statfs,	/* statfs */
  	.remount_fs	= befs_remount,
3ab7947ac   David Howells   befs: Implement s...
69
  	.show_options	= befs_show_options,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
72
  };
  
  /* slab cache for befs_inode_info objects */
e18b890bb   Christoph Lameter   [PATCH] slab: rem...
73
  static struct kmem_cache *befs_inode_cachep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74

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

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

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

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

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

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

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

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

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

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

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

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

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

dac52fc18   Fabian Frederick   BEFS: logging cle...
577
578
  	befs_debug(sb, "---> %s
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
580
  
  	if (!nls) {
dac52fc18   Fabian Frederick   BEFS: logging cle...
581
582
  		befs_error(sb, "%s called with no NLS table loaded.",
  			   __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583
584
585
586
587
  		return -EINVAL;
  	}
  
  	*out = result = kmalloc(maxlen, GFP_NOFS);
  	if (!*out) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
589
590
591
592
593
594
595
  		*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...
596
  		if (unilen < 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
  			goto conv_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
598
599
  
  		/* convert from unicode to UTF-8 */
74675a585   Alan Stern   NLS: update handl...
600
601
  		utflen = utf32_to_utf8(uni, &result[o], 3);
  		if (utflen <= 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
602
  			goto conv_err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
604
605
606
  	}
  
  	result[o] = '\0';
  	*out_len = o;
dac52fc18   Fabian Frederick   BEFS: logging cle...
607
  	befs_debug(sb, "<--- %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
608
609
  
  	return i;
62b80719d   Luis de Bethencourt   befs: fix style i...
610
  conv_err:
1ca7087e5   Luis de Bethencourt   befs: fix typos i...
611
  	befs_error(sb, "Name using character set %s contains a character that "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
612
  		   "cannot be converted to unicode.", nls->charset);
dac52fc18   Fabian Frederick   BEFS: logging cle...
613
  	befs_debug(sb, "<--- %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614
615
616
  	kfree(result);
  	return -EILSEQ;
  }
ac632f5b6   Luis de Bethencourt   befs: add NFS exp...
617
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
  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...
643
644
645
646
647
648
649
650
651
652
653
654
  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
655
656
657
  enum {
  	Opt_uid, Opt_gid, Opt_charset, Opt_debug, Opt_err,
  };
a447c0932   Steven Whitehouse   vfs: Use const fo...
658
  static const match_table_t befs_tokens = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
659
660
661
662
663
664
665
666
  	{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...
667
  parse_options(char *options, struct befs_mount_options *opts)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668
669
670
671
  {
  	char *p;
  	substring_t args[MAX_OPT_ARGS];
  	int option;
31aba059b   Eric W. Biederman   userns: Convert b...
672
673
  	kuid_t uid;
  	kgid_t gid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
674
675
  
  	/* Initialize options */
31aba059b   Eric W. Biederman   userns: Convert b...
676
677
  	opts->uid = GLOBAL_ROOT_UID;
  	opts->gid = GLOBAL_ROOT_GID;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
679
680
681
682
683
684
685
686
687
  	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...
688

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

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

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

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

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

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

dac52fc18   Fabian Frederick   BEFS: logging cle...
929
  	befs_debug(sb, "---> %s", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
931
932
933
934
935
936
937
  
  	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...
938
939
  	buf->f_fsid.val[0] = (u32)id;
  	buf->f_fsid.val[1] = (u32)(id >> 32);
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)