linuxvfs.c 23.8 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7
/*
 * linux/fs/befs/linuxvfs.c
 *
 * Copyright (C) 2001 Will Dyson <will_dyson@pobox.com
 *
 */

F
Fabian Frederick 已提交
8 9
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

L
Linus Torvalds 已提交
10 11 12 13 14 15 16 17 18 19
#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>
20
#include <linux/sched.h>
L
Linus Torvalds 已提交
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

#include "befs.h"
#include "btree.h"
#include "inode.h"
#include "datastream.h"
#include "super.h"
#include "io.h"

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

A
Al Viro 已提交
36
static int befs_readdir(struct file *, struct dir_context *);
L
Linus Torvalds 已提交
37 38 39
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);
A
Al Viro 已提交
40
static struct dentry *befs_lookup(struct inode *, struct dentry *, unsigned int);
41
static struct inode *befs_iget(struct super_block *, unsigned long);
L
Linus Torvalds 已提交
42 43 44
static struct inode *befs_alloc_inode(struct super_block *sb);
static void befs_destroy_inode(struct inode *inode);
static void befs_destroy_inodecache(void);
45
static int befs_symlink_readpage(struct file *, struct page *);
L
Linus Torvalds 已提交
46 47 48 49 50 51
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 *);
52
static int befs_statfs(struct dentry *, struct kstatfs *);
53
static int parse_options(char *, struct befs_mount_options *);
L
Linus Torvalds 已提交
54 55 56 57 58 59 60

static const struct super_operations befs_sops = {
	.alloc_inode	= befs_alloc_inode,	/* allocate a new inode */
	.destroy_inode	= befs_destroy_inode, /* deallocate an inode */
	.put_super	= befs_put_super,	/* uninit super */
	.statfs		= befs_statfs,	/* statfs */
	.remount_fs	= befs_remount,
M
Miklos Szeredi 已提交
61
	.show_options	= generic_show_options,
L
Linus Torvalds 已提交
62 63 64
};

/* slab cache for befs_inode_info objects */
65
static struct kmem_cache *befs_inode_cachep;
L
Linus Torvalds 已提交
66

67
static const struct file_operations befs_dir_operations = {
L
Linus Torvalds 已提交
68
	.read		= generic_read_dir,
A
Al Viro 已提交
69
	.iterate_shared	= befs_readdir,
70
	.llseek		= generic_file_llseek,
L
Linus Torvalds 已提交
71 72
};

73
static const struct inode_operations befs_dir_inode_operations = {
L
Linus Torvalds 已提交
74 75 76
	.lookup		= befs_lookup,
};

77
static const struct address_space_operations befs_aops = {
L
Linus Torvalds 已提交
78 79 80 81
	.readpage	= befs_readpage,
	.bmap		= befs_bmap,
};

82 83
static const struct address_space_operations befs_symlink_aops = {
	.readpage	= befs_symlink_readpage,
L
Linus Torvalds 已提交
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
};

/* 
 * Called by generic_file_read() to read a page of data
 * 
 * In turn, simply calls a generic block read function and
 * passes it the address of befs_get_block, for mapping file
 * positions to disk blocks.
 */
static int
befs_readpage(struct file *file, struct page *page)
{
	return block_read_full_page(page, befs_get_block);
}

static sector_t
befs_bmap(struct address_space *mapping, sector_t block)
{
	return generic_block_bmap(mapping, block, befs_get_block);
}

/* 
 * Generic function to map a file position (block) to a 
 * disk offset (passed back in bh_result).
 *
 * Used by many higher level functions.
 *
 * Calls befs_fblock2brun() in datastream.c to do the real work.
 *
 * -WD 10-26-01
 */

static int
befs_get_block(struct inode *inode, sector_t block,
	       struct buffer_head *bh_result, int create)
{
	struct super_block *sb = inode->i_sb;
	befs_data_stream *ds = &BEFS_I(inode)->i_data.ds;
	befs_block_run run = BAD_IADDR;
	int res = 0;
	ulong disk_off;

	befs_debug(sb, "---> befs_get_block() for inode %lu, block %ld",
F
Fabian Frederick 已提交
127
		   (unsigned long)inode->i_ino, (long)block);
L
Linus Torvalds 已提交
128 129
	if (create) {
		befs_error(sb, "befs_get_block() was asked to write to "
F
Fabian Frederick 已提交
130 131
			   "block %ld in inode %lu", (long)block,
			   (unsigned long)inode->i_ino);
L
Linus Torvalds 已提交
132 133 134 135 136 137
		return -EPERM;
	}

	res = befs_fblock2brun(sb, ds, block, &run);
	if (res != BEFS_OK) {
		befs_error(sb,
F
Fabian Frederick 已提交
138 139 140
			   "<--- %s for inode %lu, block %ld ERROR",
			   __func__, (unsigned long)inode->i_ino,
			   (long)block);
L
Linus Torvalds 已提交
141 142 143 144 145 146 147
		return -EFBIG;
	}

	disk_off = (ulong) iaddr2blockno(sb, &run);

	map_bh(bh_result, inode->i_sb, disk_off);

F
Fabian Frederick 已提交
148 149 150
	befs_debug(sb, "<--- %s for inode %lu, block %ld, disk address %lu",
		  __func__, (unsigned long)inode->i_ino, (long)block,
		  (unsigned long)disk_off);
L
Linus Torvalds 已提交
151 152 153 154 155

	return 0;
}

static struct dentry *
A
Al Viro 已提交
156
befs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
L
Linus Torvalds 已提交
157
{
158
	struct inode *inode;
L
Linus Torvalds 已提交
159
	struct super_block *sb = dir->i_sb;
A
Al Viro 已提交
160
	const befs_data_stream *ds = &BEFS_I(dir)->i_data.ds;
L
Linus Torvalds 已提交
161 162 163 164 165 166
	befs_off_t offset;
	int ret;
	int utfnamelen;
	char *utfname;
	const char *name = dentry->d_name.name;

A
Al Viro 已提交
167 168
	befs_debug(sb, "---> %s name %pd inode %ld", __func__,
		   dentry, dir->i_ino);
L
Linus Torvalds 已提交
169 170 171 172 173 174

	/* Convert to UTF-8 */
	if (BEFS_SB(sb)->nls) {
		ret =
		    befs_nls2utf(sb, name, strlen(name), &utfname, &utfnamelen);
		if (ret < 0) {
F
Fabian Frederick 已提交
175
			befs_debug(sb, "<--- %s ERROR", __func__);
L
Linus Torvalds 已提交
176 177 178 179 180 181 182 183 184 185
			return ERR_PTR(ret);
		}
		ret = befs_btree_find(sb, ds, utfname, &offset);
		kfree(utfname);

	} else {
		ret = befs_btree_find(sb, ds, dentry->d_name.name, &offset);
	}

	if (ret == BEFS_BT_NOT_FOUND) {
A
Al Viro 已提交
186
		befs_debug(sb, "<--- %s %pd not found", __func__, dentry);
L
Linus Torvalds 已提交
187 188 189
		return ERR_PTR(-ENOENT);

	} else if (ret != BEFS_OK || offset == 0) {
F
Fabian Frederick 已提交
190
		befs_warning(sb, "<--- %s Error", __func__);
L
Linus Torvalds 已提交
191 192 193
		return ERR_PTR(-ENODATA);
	}

194 195 196
	inode = befs_iget(dir->i_sb, (ino_t) offset);
	if (IS_ERR(inode))
		return ERR_CAST(inode);
L
Linus Torvalds 已提交
197 198 199

	d_add(dentry, inode);

F
Fabian Frederick 已提交
200
	befs_debug(sb, "<--- %s", __func__);
L
Linus Torvalds 已提交
201 202 203 204 205

	return NULL;
}

static int
A
Al Viro 已提交
206
befs_readdir(struct file *file, struct dir_context *ctx)
L
Linus Torvalds 已提交
207
{
A
Al Viro 已提交
208
	struct inode *inode = file_inode(file);
L
Linus Torvalds 已提交
209
	struct super_block *sb = inode->i_sb;
A
Al Viro 已提交
210
	const befs_data_stream *ds = &BEFS_I(inode)->i_data.ds;
L
Linus Torvalds 已提交
211 212 213 214 215 216
	befs_off_t value;
	int result;
	size_t keysize;
	unsigned char d_type;
	char keybuf[BEFS_NAME_LEN + 1];

A
Al Viro 已提交
217 218
	befs_debug(sb, "---> %s name %pD, inode %ld, ctx->pos %lld",
		  __func__, file, inode->i_ino, ctx->pos);
L
Linus Torvalds 已提交
219

A
Al Viro 已提交
220 221
more:
	result = befs_btree_read(sb, ds, ctx->pos, BEFS_NAME_LEN + 1,
L
Linus Torvalds 已提交
222 223 224
				 keybuf, &keysize, &value);

	if (result == BEFS_ERR) {
F
Fabian Frederick 已提交
225
		befs_debug(sb, "<--- %s ERROR", __func__);
A
Al Viro 已提交
226 227
		befs_error(sb, "IO error reading %pD (inode %lu)",
			   file, inode->i_ino);
L
Linus Torvalds 已提交
228 229 230
		return -EIO;

	} else if (result == BEFS_BT_END) {
F
Fabian Frederick 已提交
231
		befs_debug(sb, "<--- %s END", __func__);
L
Linus Torvalds 已提交
232 233 234
		return 0;

	} else if (result == BEFS_BT_EMPTY) {
F
Fabian Frederick 已提交
235
		befs_debug(sb, "<--- %s Empty directory", __func__);
L
Linus Torvalds 已提交
236 237 238 239 240 241 242
		return 0;
	}

	d_type = DT_UNKNOWN;

	/* Convert to NLS */
	if (BEFS_SB(sb)->nls) {
A
Al Viro 已提交
243 244
		char *nlsname;
		int nlsnamelen;
L
Linus Torvalds 已提交
245 246 247
		result =
		    befs_utf2nls(sb, keybuf, keysize, &nlsname, &nlsnamelen);
		if (result < 0) {
F
Fabian Frederick 已提交
248
			befs_debug(sb, "<--- %s ERROR", __func__);
L
Linus Torvalds 已提交
249 250
			return result;
		}
A
Al Viro 已提交
251 252 253 254 255
		if (!dir_emit(ctx, nlsname, nlsnamelen,
				 (ino_t) value, d_type)) {
			kfree(nlsname);
			return 0;
		}
L
Linus Torvalds 已提交
256 257
		kfree(nlsname);
	} else {
A
Al Viro 已提交
258 259 260
		if (!dir_emit(ctx, keybuf, keysize,
				 (ino_t) value, d_type))
			return 0;
L
Linus Torvalds 已提交
261
	}
A
Al Viro 已提交
262 263
	ctx->pos++;
	goto more;
L
Linus Torvalds 已提交
264 265 266 267 268
}

static struct inode *
befs_alloc_inode(struct super_block *sb)
{
269 270 271
	struct befs_inode_info *bi;

	bi = kmem_cache_alloc(befs_inode_cachep, GFP_KERNEL);
L
Linus Torvalds 已提交
272 273 274 275 276
        if (!bi)
                return NULL;
        return &bi->vfs_inode;
}

N
Nick Piggin 已提交
277
static void befs_i_callback(struct rcu_head *head)
L
Linus Torvalds 已提交
278
{
N
Nick Piggin 已提交
279
	struct inode *inode = container_of(head, struct inode, i_rcu);
L
Linus Torvalds 已提交
280 281 282
        kmem_cache_free(befs_inode_cachep, BEFS_I(inode));
}

N
Nick Piggin 已提交
283 284 285 286 287
static void befs_destroy_inode(struct inode *inode)
{
	call_rcu(&inode->i_rcu, befs_i_callback);
}

288
static void init_once(void *foo)
L
Linus Torvalds 已提交
289 290
{
        struct befs_inode_info *bi = (struct befs_inode_info *) foo;
C
Christoph Lameter 已提交
291 292

	inode_init_once(&bi->vfs_inode);
L
Linus Torvalds 已提交
293 294
}

295
static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
L
Linus Torvalds 已提交
296
{
297
	struct buffer_head *bh;
L
Linus Torvalds 已提交
298
	befs_inode *raw_inode = NULL;
299
	struct befs_sb_info *befs_sb = BEFS_SB(sb);
300
	struct befs_inode_info *befs_ino = NULL;
301 302
	struct inode *inode;
	long ret = -EIO;
L
Linus Torvalds 已提交
303

F
Fabian Frederick 已提交
304
	befs_debug(sb, "---> %s inode = %lu", __func__, ino);
305 306

	inode = iget_locked(sb, ino);
307 308
	if (!inode)
		return ERR_PTR(-ENOMEM);
309 310
	if (!(inode->i_state & I_NEW))
		return inode;
L
Linus Torvalds 已提交
311 312 313 314 315 316 317 318 319 320 321 322 323 324

	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);

	bh = befs_bread(sb, inode->i_ino);
	if (!bh) {
		befs_error(sb, "unable to read inode block - "
			   "inode = %lu", inode->i_ino);
A
Adrian Bunk 已提交
325
		goto unacquire_none;
L
Linus Torvalds 已提交
326 327 328 329 330 331 332 333
	}

	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);
A
Adrian Bunk 已提交
334
		goto unacquire_bh;
L
Linus Torvalds 已提交
335 336 337 338 339 340 341 342 343 344
	}

	inode->i_mode = (umode_t) fs32_to_cpu(sb, raw_inode->mode);

	/*
	 * set uid and gid.  But since current BeOS is single user OS, so
	 * you can change by "uid" or "gid" options.
	 */   

	inode->i_uid = befs_sb->mount_opts.use_uid ?
345 346
		befs_sb->mount_opts.uid :
		make_kuid(&init_user_ns, fs32_to_cpu(sb, raw_inode->uid));
L
Linus Torvalds 已提交
347
	inode->i_gid = befs_sb->mount_opts.use_gid ?
348 349
		befs_sb->mount_opts.gid :
		make_kgid(&init_user_ns, fs32_to_cpu(sb, raw_inode->gid));
L
Linus Torvalds 已提交
350

M
Miklos Szeredi 已提交
351
	set_nlink(inode, 1);
L
Linus Torvalds 已提交
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375

	/*
	 * BEFS's time is 64 bits, but current VFS is 32 bits...
	 * BEFS don't have access time. Nor inode change time. VFS
	 * doesn't have creation time.
	 * Also, the lower 16 bits of the last_modified_time and 
	 * create_time are just a counter to help ensure uniqueness
	 * for indexing purposes. (PFD, page 54)
	 */

	inode->i_mtime.tv_sec =
	    fs64_to_cpu(sb, raw_inode->last_modified_time) >> 16;
	inode->i_mtime.tv_nsec = 0;   /* lower 16 bits are not a time */	
	inode->i_ctime = inode->i_mtime;
	inode->i_atime = inode->i_mtime;

	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;
376 377
		strlcpy(befs_ino->i_data.symlink, raw_inode->data.symlink,
			BEFS_SYMLINK_LEN);
L
Linus Torvalds 已提交
378 379 380 381
	} else {
		int num_blks;

		befs_ino->i_data.ds =
382
		    fsds_to_cpu(sb, &raw_inode->data.datastream);
L
Linus Torvalds 已提交
383 384 385 386 387 388 389 390 391 392

		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)) {
393
		inode->i_fop = &generic_ro_fops;
L
Linus Torvalds 已提交
394 395 396 397
	} 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)) {
A
Al Viro 已提交
398
		if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
399
			inode->i_op = &page_symlink_inode_operations;
400
			inode_nohighmem(inode);
401
			inode->i_mapping->a_ops = &befs_symlink_aops;
A
Al Viro 已提交
402 403 404 405
		} else {
			inode->i_link = befs_ino->i_data.symlink;
			inode->i_op = &simple_symlink_inode_operations;
		}
L
Linus Torvalds 已提交
406 407 408 409
	} 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);
A
Adrian Bunk 已提交
410
		goto unacquire_bh;
L
Linus Torvalds 已提交
411 412 413
	}

	brelse(bh);
F
Fabian Frederick 已提交
414
	befs_debug(sb, "<--- %s", __func__);
415 416
	unlock_new_inode(inode);
	return inode;
L
Linus Torvalds 已提交
417

A
Adrian Bunk 已提交
418
      unacquire_bh:
L
Linus Torvalds 已提交
419 420
	brelse(bh);

A
Adrian Bunk 已提交
421
      unacquire_none:
422
	iget_failed(inode);
F
Fabian Frederick 已提交
423
	befs_debug(sb, "<--- %s - Bad inode", __func__);
424
	return ERR_PTR(ret);
L
Linus Torvalds 已提交
425 426 427
}

/* Initialize the inode cache. Called at fs setup.
428
 *
L
Linus Torvalds 已提交
429 430
 * Taken from NFS implementation by Al Viro.
 */
431
static int __init
L
Linus Torvalds 已提交
432 433 434 435
befs_init_inodecache(void)
{
	befs_inode_cachep = kmem_cache_create("befs_inode_cache",
					      sizeof (struct befs_inode_info),
436
					      0, (SLAB_RECLAIM_ACCOUNT|
437
						SLAB_MEM_SPREAD|SLAB_ACCOUNT),
438
					      init_once);
L
Linus Torvalds 已提交
439
	if (befs_inode_cachep == NULL) {
F
Fabian Frederick 已提交
440
		pr_err("%s: Couldn't initialize inode slabcache\n", __func__);
L
Linus Torvalds 已提交
441 442 443 444 445 446 447 448 449 450 451 452
		return -ENOMEM;
	}
	return 0;
}

/* Called at fs teardown.
 * 
 * Taken from NFS implementation by Al Viro.
 */
static void
befs_destroy_inodecache(void)
{
453 454 455 456 457
	/*
	 * Make sure all delayed rcu free inodes are flushed before we
	 * destroy cache.
	 */
	rcu_barrier();
458
	kmem_cache_destroy(befs_inode_cachep);
L
Linus Torvalds 已提交
459 460 461 462 463 464 465
}

/*
 * The inode of symbolic link is different to data stream.
 * The data stream become link name. Unless the LONG_SYMLINK
 * flag is set.
 */
466
static int befs_symlink_readpage(struct file *unused, struct page *page)
L
Linus Torvalds 已提交
467
{
468 469 470
	struct inode *inode = page->mapping->host;
	struct super_block *sb = inode->i_sb;
	struct befs_inode_info *befs_ino = BEFS_I(inode);
471 472
	befs_data_stream *data = &befs_ino->i_data.ds;
	befs_off_t len = data->size;
473
	char *link = page_address(page);
L
Linus Torvalds 已提交
474

475
	if (len == 0 || len > PAGE_SIZE) {
476
		befs_error(sb, "Long symlink with illegal length");
477
		goto fail;
L
Linus Torvalds 已提交
478
	}
479 480 481 482
	befs_debug(sb, "Follow long symlink");

	if (befs_read_lsymlink(sb, data, link, len) != len) {
		befs_error(sb, "Failed to read entire long symlink");
483
		goto fail;
484 485
	}
	link[len - 1] = '\0';
486 487 488 489 490 491 492
	SetPageUptodate(page);
	unlock_page(page);
	return 0;
fail:
	SetPageError(page);
	unlock_page(page);
	return -EIO;
L
Linus Torvalds 已提交
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
}

/*
 * UTF-8 to NLS charset  convert routine
 * 
 *
 * Changed 8/10/01 by Will Dyson. Now use uni2char() / char2uni() rather than
 * the nls tables directly
 */

static int
befs_utf2nls(struct super_block *sb, const char *in,
	     int in_len, char **out, int *out_len)
{
	struct nls_table *nls = BEFS_SB(sb)->nls;
	int i, o;
A
Alan Stern 已提交
509
	unicode_t uni;
L
Linus Torvalds 已提交
510 511
	int unilen, utflen;
	char *result;
D
Diego Calleja 已提交
512 513 514 515 516
	/* 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;
L
Linus Torvalds 已提交
517

F
Fabian Frederick 已提交
518
	befs_debug(sb, "---> %s", __func__);
L
Linus Torvalds 已提交
519 520

	if (!nls) {
F
Fabian Frederick 已提交
521
		befs_error(sb, "%s called with no NLS table loaded", __func__);
L
Linus Torvalds 已提交
522 523 524 525 526
		return -EINVAL;
	}

	*out = result = kmalloc(maxlen, GFP_NOFS);
	if (!*out) {
F
Fabian Frederick 已提交
527
		befs_error(sb, "%s cannot allocate memory", __func__);
L
Linus Torvalds 已提交
528 529 530 531 532 533 534
		*out_len = 0;
		return -ENOMEM;
	}

	for (i = o = 0; i < in_len; i += utflen, o += unilen) {

		/* convert from UTF-8 to Unicode */
A
Alan Stern 已提交
535 536
		utflen = utf8_to_utf32(&in[i], in_len - i, &uni);
		if (utflen < 0)
L
Linus Torvalds 已提交
537 538 539
			goto conv_err;

		/* convert from Unicode to nls */
A
Alan Stern 已提交
540 541
		if (uni > MAX_WCHAR_T)
			goto conv_err;
L
Linus Torvalds 已提交
542
		unilen = nls->uni2char(uni, &result[o], in_len - o);
A
Alan Stern 已提交
543
		if (unilen < 0)
L
Linus Torvalds 已提交
544 545 546 547 548
			goto conv_err;
	}
	result[o] = '\0';
	*out_len = o;

F
Fabian Frederick 已提交
549
	befs_debug(sb, "<--- %s", __func__);
L
Linus Torvalds 已提交
550 551 552 553 554 555

	return o;

      conv_err:
	befs_error(sb, "Name using character set %s contains a character that "
		   "cannot be converted to unicode.", nls->charset);
F
Fabian Frederick 已提交
556
	befs_debug(sb, "<--- %s", __func__);
L
Linus Torvalds 已提交
557 558 559 560 561 562 563
	kfree(result);
	return -EILSEQ;
}

/**
 * befs_nls2utf - Convert NLS string to utf8 encodeing
 * @sb: Superblock
F
Fabian Frederick 已提交
564 565 566 567
 * @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
L
Linus Torvalds 已提交
568
 * 
F
Fabian Frederick 已提交
569
 * Converts input string @in, which is in the format of the loaded NLS map,
L
Linus Torvalds 已提交
570 571
 * into a utf8 string.
 * 
F
Fabian Frederick 已提交
572
 * The destination string @out is allocated by this function and the caller is
L
Linus Torvalds 已提交
573 574
 * responsible for freeing it with kfree()
 * 
F
Fabian Frederick 已提交
575
 * On return, *@out_len is the length of @out in bytes.
L
Linus Torvalds 已提交
576 577
 *
 * On success, the return value is the number of utf8 characters written to
F
Fabian Frederick 已提交
578
 * the output buffer @out.
L
Linus Torvalds 已提交
579 580 581 582 583 584 585 586 587 588 589 590 591
 *  
 * 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;
D
Diego Calleja 已提交
592 593 594 595
	/* There're nls characters that will translate to 3-chars-wide UTF-8
	 * characters, a additional byte is needed to save the final \0
	 * in special cases */
	int maxlen = (3 * in_len) + 1;
L
Linus Torvalds 已提交
596

F
Fabian Frederick 已提交
597
	befs_debug(sb, "---> %s\n", __func__);
L
Linus Torvalds 已提交
598 599

	if (!nls) {
F
Fabian Frederick 已提交
600 601
		befs_error(sb, "%s called with no NLS table loaded.",
			   __func__);
L
Linus Torvalds 已提交
602 603 604 605 606
		return -EINVAL;
	}

	*out = result = kmalloc(maxlen, GFP_NOFS);
	if (!*out) {
F
Fabian Frederick 已提交
607
		befs_error(sb, "%s cannot allocate memory", __func__);
L
Linus Torvalds 已提交
608 609 610 611 612 613 614 615
		*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);
A
Alan Stern 已提交
616
		if (unilen < 0)
L
Linus Torvalds 已提交
617 618 619
			goto conv_err;

		/* convert from unicode to UTF-8 */
A
Alan Stern 已提交
620 621
		utflen = utf32_to_utf8(uni, &result[o], 3);
		if (utflen <= 0)
L
Linus Torvalds 已提交
622 623 624 625 626 627
			goto conv_err;
	}

	result[o] = '\0';
	*out_len = o;

F
Fabian Frederick 已提交
628
	befs_debug(sb, "<--- %s", __func__);
L
Linus Torvalds 已提交
629 630 631 632 633 634

	return i;

      conv_err:
	befs_error(sb, "Name using charecter set %s contains a charecter that "
		   "cannot be converted to unicode.", nls->charset);
F
Fabian Frederick 已提交
635
	befs_debug(sb, "<--- %s", __func__);
L
Linus Torvalds 已提交
636 637 638 639 640 641 642 643 644 645 646 647
	kfree(result);
	return -EILSEQ;
}

/**
 * Use the
 *
 */
enum {
	Opt_uid, Opt_gid, Opt_charset, Opt_debug, Opt_err,
};

648
static const match_table_t befs_tokens = {
L
Linus Torvalds 已提交
649 650 651 652 653 654 655 656
	{Opt_uid, "uid=%d"},
	{Opt_gid, "gid=%d"},
	{Opt_charset, "iocharset=%s"},
	{Opt_debug, "debug"},
	{Opt_err, NULL}
};

static int
657
parse_options(char *options, struct befs_mount_options *opts)
L
Linus Torvalds 已提交
658 659 660 661
{
	char *p;
	substring_t args[MAX_OPT_ARGS];
	int option;
662 663
	kuid_t uid;
	kgid_t gid;
L
Linus Torvalds 已提交
664 665

	/* Initialize options */
666 667
	opts->uid = GLOBAL_ROOT_UID;
	opts->gid = GLOBAL_ROOT_GID;
L
Linus Torvalds 已提交
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
	opts->use_uid = 0;
	opts->use_gid = 0;
	opts->iocharset = NULL;
	opts->debug = 0;

	if (!options)
		return 1;

	while ((p = strsep(&options, ",")) != NULL) {
		int token;
		if (!*p)
			continue;

		token = match_token(p, befs_tokens, args);
		switch (token) {
		case Opt_uid:
			if (match_int(&args[0], &option))
				return 0;
686 687 688 689
			uid = INVALID_UID;
			if (option >= 0)
				uid = make_kuid(current_user_ns(), option);
			if (!uid_valid(uid)) {
F
Fabian Frederick 已提交
690 691
				pr_err("Invalid uid %d, "
				       "using default\n", option);
L
Linus Torvalds 已提交
692 693
				break;
			}
694
			opts->uid = uid;
L
Linus Torvalds 已提交
695 696 697 698 699
			opts->use_uid = 1;
			break;
		case Opt_gid:
			if (match_int(&args[0], &option))
				return 0;
700 701 702 703
			gid = INVALID_GID;
			if (option >= 0)
				gid = make_kgid(current_user_ns(), option);
			if (!gid_valid(gid)) {
F
Fabian Frederick 已提交
704 705
				pr_err("Invalid gid %d, "
				       "using default\n", option);
L
Linus Torvalds 已提交
706 707
				break;
			}
708
			opts->gid = gid;
L
Linus Torvalds 已提交
709 710 711 712 713 714
			opts->use_gid = 1;
			break;
		case Opt_charset:
			kfree(opts->iocharset);
			opts->iocharset = match_strdup(&args[0]);
			if (!opts->iocharset) {
F
Fabian Frederick 已提交
715 716
				pr_err("allocation failure for "
				       "iocharset string\n");
L
Linus Torvalds 已提交
717 718 719 720 721 722 723
				return 0;
			}
			break;
		case Opt_debug:
			opts->debug = 1;
			break;
		default:
F
Fabian Frederick 已提交
724 725
			pr_err("Unrecognized mount option \"%s\" "
			       "or missing value\n", p);
L
Linus Torvalds 已提交
726 727 728 729 730 731 732 733
			return 0;
		}
	}
	return 1;
}

/* This function has the responsibiltiy of getting the
 * filesystem ready for unmounting. 
L
Lucas De Marchi 已提交
734
 * Basically, we free everything that we allocated in
L
Linus Torvalds 已提交
735 736 737 738 739
 * befs_read_inode
 */
static void
befs_put_super(struct super_block *sb)
{
J
Jesper Juhl 已提交
740 741
	kfree(BEFS_SB(sb)->mount_opts.iocharset);
	BEFS_SB(sb)->mount_opts.iocharset = NULL;
742
	unload_nls(BEFS_SB(sb)->nls);
J
Jesper Juhl 已提交
743 744
	kfree(sb->s_fs_info);
	sb->s_fs_info = NULL;
L
Linus Torvalds 已提交
745 746 747 748 749 750 751 752 753 754 755 756
}

/* 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;
757
	struct befs_sb_info *befs_sb;
L
Linus Torvalds 已提交
758 759
	befs_super_block *disk_sb;
	struct inode *root;
760
	long ret = -EINVAL;
L
Linus Torvalds 已提交
761 762 763
	const unsigned long sb_block = 0;
	const off_t x86_sb_off = 512;

M
Miklos Szeredi 已提交
764 765
	save_mount_options(sb, data);

766
	sb->s_fs_info = kzalloc(sizeof(*befs_sb), GFP_KERNEL);
L
Linus Torvalds 已提交
767
	if (sb->s_fs_info == NULL) {
F
Fabian Frederick 已提交
768
		pr_err("(%s): Unable to allocate memory for private "
L
Linus Torvalds 已提交
769
		       "portion of superblock. Bailing.\n", sb->s_id);
A
Adrian Bunk 已提交
770
		goto unacquire_none;
L
Linus Torvalds 已提交
771 772 773 774 775
	}
	befs_sb = BEFS_SB(sb);

	if (!parse_options((char *) data, &befs_sb->mount_opts)) {
		befs_error(sb, "cannot parse mount options");
A
Adrian Bunk 已提交
776
		goto unacquire_priv_sbp;
L
Linus Torvalds 已提交
777 778
	}

F
Fabian Frederick 已提交
779
	befs_debug(sb, "---> %s", __func__);
L
Linus Torvalds 已提交
780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799

	if (!(sb->s_flags & MS_RDONLY)) {
		befs_warning(sb,
			     "No write support. Marking filesystem read-only");
		sb->s_flags |= MS_RDONLY;
	}

	/*
	 * 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
	 * the hardsect size for the device. But we also need to read at 
	 * least 1k to get the second 512 bytes of the volume.
	 * -WD 10-26-01
	 */ 
	sb_min_blocksize(sb, 1024);

	if (!(bh = sb_bread(sb, sb_block))) {
		befs_error(sb, "unable to read superblock");
A
Adrian Bunk 已提交
800
		goto unacquire_priv_sbp;
L
Linus Torvalds 已提交
801 802 803 804
	}

	/* account for offset of super block on x86 */
	disk_sb = (befs_super_block *) bh->b_data;
805 806
	if ((disk_sb->magic1 == BEFS_SUPER_MAGIC1_LE) ||
	    (disk_sb->magic1 == BEFS_SUPER_MAGIC1_BE)) {
L
Linus Torvalds 已提交
807 808 809 810 811 812 813
		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);
	}

814 815
	if ((befs_load_sb(sb, disk_sb) != BEFS_OK) ||
	    (befs_check_sb(sb) != BEFS_OK))
A
Adrian Bunk 已提交
816
		goto unacquire_bh;
L
Linus Torvalds 已提交
817 818 819 820 821 822

	befs_dump_super_block(sb, disk_sb);

	brelse(bh);

	if( befs_sb->num_blocks > ~((sector_t)0) ) {
F
Fabian Frederick 已提交
823
		befs_error(sb, "blocks count: %llu "
L
Linus Torvalds 已提交
824 825
			"is larger than the host can use",
			befs_sb->num_blocks);
A
Adrian Bunk 已提交
826
		goto unacquire_priv_sbp;
L
Linus Torvalds 已提交
827 828 829 830 831 832 833 834 835
	}

	/*
	 * 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);
836
	sb->s_op = &befs_sops;
837 838 839 840 841
	root = befs_iget(sb, iaddr2blockno(sb, &(befs_sb->root_dir)));
	if (IS_ERR(root)) {
		ret = PTR_ERR(root);
		goto unacquire_priv_sbp;
	}
842
	sb->s_root = d_make_root(root);
L
Linus Torvalds 已提交
843 844
	if (!sb->s_root) {
		befs_error(sb, "get root inode failed");
A
Adrian Bunk 已提交
845
		goto unacquire_priv_sbp;
L
Linus Torvalds 已提交
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866
	}

	/* 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;
/*****************/
A
Adrian Bunk 已提交
867
      unacquire_bh:
L
Linus Torvalds 已提交
868 869
	brelse(bh);

A
Adrian Bunk 已提交
870
      unacquire_priv_sbp:
A
Al Viro 已提交
871
	kfree(befs_sb->mount_opts.iocharset);
L
Linus Torvalds 已提交
872 873
	kfree(sb->s_fs_info);

A
Adrian Bunk 已提交
874
      unacquire_none:
L
Linus Torvalds 已提交
875
	sb->s_fs_info = NULL;
876
	return ret;
L
Linus Torvalds 已提交
877 878 879 880 881
}

static int
befs_remount(struct super_block *sb, int *flags, char *data)
{
882
	sync_filesystem(sb);
L
Linus Torvalds 已提交
883 884 885 886 887 888
	if (!(*flags & MS_RDONLY))
		return -EINVAL;
	return 0;
}

static int
889
befs_statfs(struct dentry *dentry, struct kstatfs *buf)
L
Linus Torvalds 已提交
890
{
891
	struct super_block *sb = dentry->d_sb;
C
Coly Li 已提交
892
	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
L
Linus Torvalds 已提交
893

F
Fabian Frederick 已提交
894
	befs_debug(sb, "---> %s", __func__);
L
Linus Torvalds 已提交
895 896 897 898 899 900 901 902

	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 */
C
Coly Li 已提交
903 904
	buf->f_fsid.val[0] = (u32)id;
	buf->f_fsid.val[1] = (u32)(id >> 32);
L
Linus Torvalds 已提交
905 906
	buf->f_namelen = BEFS_NAME_LEN;

F
Fabian Frederick 已提交
907
	befs_debug(sb, "<--- %s", __func__);
L
Linus Torvalds 已提交
908 909 910 911

	return 0;
}

A
Al Viro 已提交
912 913 914
static struct dentry *
befs_mount(struct file_system_type *fs_type, int flags, const char *dev_name,
	    void *data)
L
Linus Torvalds 已提交
915
{
A
Al Viro 已提交
916
	return mount_bdev(fs_type, flags, dev_name, data, befs_fill_super);
L
Linus Torvalds 已提交
917 918 919 920 921
}

static struct file_system_type befs_fs_type = {
	.owner		= THIS_MODULE,
	.name		= "befs",
A
Al Viro 已提交
922
	.mount		= befs_mount,
L
Linus Torvalds 已提交
923 924 925
	.kill_sb	= kill_block_super,
	.fs_flags	= FS_REQUIRES_DEV,	
};
926
MODULE_ALIAS_FS("befs");
L
Linus Torvalds 已提交
927 928 929 930 931 932

static int __init
init_befs_fs(void)
{
	int err;

F
Fabian Frederick 已提交
933
	pr_info("version: %s\n", BEFS_VERSION);
L
Linus Torvalds 已提交
934 935 936

	err = befs_init_inodecache();
	if (err)
A
Adrian Bunk 已提交
937
		goto unacquire_none;
L
Linus Torvalds 已提交
938 939 940

	err = register_filesystem(&befs_fs_type);
	if (err)
A
Adrian Bunk 已提交
941
		goto unacquire_inodecache;
L
Linus Torvalds 已提交
942 943 944

	return 0;

A
Adrian Bunk 已提交
945
unacquire_inodecache:
L
Linus Torvalds 已提交
946 947
	befs_destroy_inodecache();

A
Adrian Bunk 已提交
948
unacquire_none:
L
Linus Torvalds 已提交
949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966
	return err;
}

static void __exit
exit_befs_fs(void)
{
	befs_destroy_inodecache();

	unregister_filesystem(&befs_fs_type);
}

/*
Macros that typecheck the init and exit functions,
ensures that they are called at init and cleanup,
and eliminates warnings about unused functions.
*/
module_init(init_befs_fs)
module_exit(exit_befs_fs)