109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * linux/fs/befs/linuxvfs.c 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (C) 2001 Will Dyson <will_dyson@pobox.com 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds */ 81da177e4SLinus Torvalds 9dac52fc1SFabian Frederick #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10dac52fc1SFabian Frederick 111da177e4SLinus Torvalds #include <linux/module.h> 121da177e4SLinus Torvalds #include <linux/slab.h> 131da177e4SLinus Torvalds #include <linux/fs.h> 141da177e4SLinus Torvalds #include <linux/errno.h> 151da177e4SLinus Torvalds #include <linux/stat.h> 161da177e4SLinus Torvalds #include <linux/nls.h> 171da177e4SLinus Torvalds #include <linux/buffer_head.h> 181da177e4SLinus Torvalds #include <linux/vfs.h> 191da177e4SLinus Torvalds #include <linux/parser.h> 201da177e4SLinus Torvalds #include <linux/namei.h> 2131aba059SEric W. Biederman #include <linux/sched.h> 225b825c3aSIngo Molnar #include <linux/cred.h> 23ac632f5bSLuis de Bethencourt #include <linux/exportfs.h> 243ab7947aSDavid Howells #include <linux/seq_file.h> 25621c1f42SChristoph Hellwig #include <linux/blkdev.h> 261da177e4SLinus Torvalds 271da177e4SLinus Torvalds #include "befs.h" 281da177e4SLinus Torvalds #include "btree.h" 291da177e4SLinus Torvalds #include "inode.h" 301da177e4SLinus Torvalds #include "datastream.h" 311da177e4SLinus Torvalds #include "super.h" 321da177e4SLinus Torvalds #include "io.h" 331da177e4SLinus Torvalds 341da177e4SLinus Torvalds MODULE_DESCRIPTION("BeOS File System (BeFS) driver"); 351da177e4SLinus Torvalds MODULE_AUTHOR("Will Dyson"); 361da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 371da177e4SLinus Torvalds 381da177e4SLinus Torvalds /* The units the vfs expects inode->i_blocks to be in */ 391da177e4SLinus Torvalds #define VFS_BLOCK_SIZE 512 401da177e4SLinus Torvalds 41f0f49ef5SAl Viro static int befs_readdir(struct file *, struct dir_context *); 421da177e4SLinus Torvalds static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int); 432c69e205SMatthew Wilcox (Oracle) static int befs_read_folio(struct file *file, struct folio *folio); 441da177e4SLinus Torvalds static sector_t befs_bmap(struct address_space *mapping, sector_t block); 4562b80719SLuis de Bethencourt static struct dentry *befs_lookup(struct inode *, struct dentry *, 4662b80719SLuis de Bethencourt unsigned int); 4796eb5419SDavid Howells static struct inode *befs_iget(struct super_block *, unsigned long); 481da177e4SLinus Torvalds static struct inode *befs_alloc_inode(struct super_block *sb); 4949f82a80SAl Viro static void befs_free_inode(struct inode *inode); 501da177e4SLinus Torvalds static void befs_destroy_inodecache(void); 51a13fe692SMatthew Wilcox (Oracle) static int befs_symlink_read_folio(struct file *, struct folio *); 521da177e4SLinus Torvalds static int befs_utf2nls(struct super_block *sb, const char *in, int in_len, 531da177e4SLinus Torvalds char **out, int *out_len); 541da177e4SLinus Torvalds static int befs_nls2utf(struct super_block *sb, const char *in, int in_len, 551da177e4SLinus Torvalds char **out, int *out_len); 561da177e4SLinus Torvalds static void befs_put_super(struct super_block *); 571da177e4SLinus Torvalds static int befs_remount(struct super_block *, int *, char *); 58726c3342SDavid Howells static int befs_statfs(struct dentry *, struct kstatfs *); 593ab7947aSDavid Howells static int befs_show_options(struct seq_file *, struct dentry *); 6009ad0eaeSFabian Frederick static int parse_options(char *, struct befs_mount_options *); 61ac632f5bSLuis de Bethencourt static struct dentry *befs_fh_to_dentry(struct super_block *sb, 62ac632f5bSLuis de Bethencourt struct fid *fid, int fh_len, int fh_type); 63ac632f5bSLuis de Bethencourt static struct dentry *befs_fh_to_parent(struct super_block *sb, 64ac632f5bSLuis de Bethencourt struct fid *fid, int fh_len, int fh_type); 65dcfd9b21SFabian Frederick static struct dentry *befs_get_parent(struct dentry *child); 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds static const struct super_operations befs_sops = { 681da177e4SLinus Torvalds .alloc_inode = befs_alloc_inode, /* allocate a new inode */ 6949f82a80SAl Viro .free_inode = befs_free_inode, /* deallocate an inode */ 701da177e4SLinus Torvalds .put_super = befs_put_super, /* uninit super */ 711da177e4SLinus Torvalds .statfs = befs_statfs, /* statfs */ 721da177e4SLinus Torvalds .remount_fs = befs_remount, 733ab7947aSDavid Howells .show_options = befs_show_options, 741da177e4SLinus Torvalds }; 751da177e4SLinus Torvalds 761da177e4SLinus Torvalds /* slab cache for befs_inode_info objects */ 77e18b890bSChristoph Lameter static struct kmem_cache *befs_inode_cachep; 781da177e4SLinus Torvalds 794b6f5d20SArjan van de Ven static const struct file_operations befs_dir_operations = { 801da177e4SLinus Torvalds .read = generic_read_dir, 81e23e9aa7SAl Viro .iterate_shared = befs_readdir, 8259af1584SAl Viro .llseek = generic_file_llseek, 831da177e4SLinus Torvalds }; 841da177e4SLinus Torvalds 85754661f1SArjan van de Ven static const struct inode_operations befs_dir_inode_operations = { 861da177e4SLinus Torvalds .lookup = befs_lookup, 871da177e4SLinus Torvalds }; 881da177e4SLinus Torvalds 89f5e54d6eSChristoph Hellwig static const struct address_space_operations befs_aops = { 902c69e205SMatthew Wilcox (Oracle) .read_folio = befs_read_folio, 911da177e4SLinus Torvalds .bmap = befs_bmap, 921da177e4SLinus Torvalds }; 931da177e4SLinus Torvalds 9411803f97SAl Viro static const struct address_space_operations befs_symlink_aops = { 95a13fe692SMatthew Wilcox (Oracle) .read_folio = befs_symlink_read_folio, 961da177e4SLinus Torvalds }; 971da177e4SLinus Torvalds 98ac632f5bSLuis de Bethencourt static const struct export_operations befs_export_operations = { 99ac632f5bSLuis de Bethencourt .fh_to_dentry = befs_fh_to_dentry, 100ac632f5bSLuis de Bethencourt .fh_to_parent = befs_fh_to_parent, 101dcfd9b21SFabian Frederick .get_parent = befs_get_parent, 102ac632f5bSLuis de Bethencourt }; 103ac632f5bSLuis de Bethencourt 1041da177e4SLinus Torvalds /* 1052c69e205SMatthew Wilcox (Oracle) * Called by generic_file_read() to read a folio of data 1061da177e4SLinus Torvalds * 1071da177e4SLinus Torvalds * In turn, simply calls a generic block read function and 1081da177e4SLinus Torvalds * passes it the address of befs_get_block, for mapping file 1091da177e4SLinus Torvalds * positions to disk blocks. 1101da177e4SLinus Torvalds */ 111ac09d88bSMatthew Wilcox (Oracle) static int befs_read_folio(struct file *file, struct folio *folio) 1121da177e4SLinus Torvalds { 1132c69e205SMatthew Wilcox (Oracle) return block_read_full_folio(folio, befs_get_block); 1141da177e4SLinus Torvalds } 1151da177e4SLinus Torvalds 1161da177e4SLinus Torvalds static sector_t 1171da177e4SLinus Torvalds befs_bmap(struct address_space *mapping, sector_t block) 1181da177e4SLinus Torvalds { 1191da177e4SLinus Torvalds return generic_block_bmap(mapping, block, befs_get_block); 1201da177e4SLinus Torvalds } 1211da177e4SLinus Torvalds 1221da177e4SLinus Torvalds /* 1231da177e4SLinus Torvalds * Generic function to map a file position (block) to a 1241da177e4SLinus Torvalds * disk offset (passed back in bh_result). 1251da177e4SLinus Torvalds * 1261da177e4SLinus Torvalds * Used by many higher level functions. 1271da177e4SLinus Torvalds * 1281da177e4SLinus Torvalds * Calls befs_fblock2brun() in datastream.c to do the real work. 1291da177e4SLinus Torvalds */ 1301da177e4SLinus Torvalds 1311da177e4SLinus Torvalds static int 1321da177e4SLinus Torvalds befs_get_block(struct inode *inode, sector_t block, 1331da177e4SLinus Torvalds struct buffer_head *bh_result, int create) 1341da177e4SLinus Torvalds { 1351da177e4SLinus Torvalds struct super_block *sb = inode->i_sb; 1361da177e4SLinus Torvalds befs_data_stream *ds = &BEFS_I(inode)->i_data.ds; 1371da177e4SLinus Torvalds befs_block_run run = BAD_IADDR; 138abcf9116SSalah Triki int res; 1391da177e4SLinus Torvalds ulong disk_off; 1401da177e4SLinus Torvalds 1411da177e4SLinus Torvalds befs_debug(sb, "---> befs_get_block() for inode %lu, block %ld", 142dac52fc1SFabian Frederick (unsigned long)inode->i_ino, (long)block); 1431da177e4SLinus Torvalds if (create) { 1441da177e4SLinus Torvalds befs_error(sb, "befs_get_block() was asked to write to " 145dac52fc1SFabian Frederick "block %ld in inode %lu", (long)block, 146dac52fc1SFabian Frederick (unsigned long)inode->i_ino); 1471da177e4SLinus Torvalds return -EPERM; 1481da177e4SLinus Torvalds } 1491da177e4SLinus Torvalds 1501da177e4SLinus Torvalds res = befs_fblock2brun(sb, ds, block, &run); 1511da177e4SLinus Torvalds if (res != BEFS_OK) { 1521da177e4SLinus Torvalds befs_error(sb, 153dac52fc1SFabian Frederick "<--- %s for inode %lu, block %ld ERROR", 154dac52fc1SFabian Frederick __func__, (unsigned long)inode->i_ino, 155dac52fc1SFabian Frederick (long)block); 1561da177e4SLinus Torvalds return -EFBIG; 1571da177e4SLinus Torvalds } 1581da177e4SLinus Torvalds 1591da177e4SLinus Torvalds disk_off = (ulong) iaddr2blockno(sb, &run); 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds map_bh(bh_result, inode->i_sb, disk_off); 1621da177e4SLinus Torvalds 163dac52fc1SFabian Frederick befs_debug(sb, "<--- %s for inode %lu, block %ld, disk address %lu", 164dac52fc1SFabian Frederick __func__, (unsigned long)inode->i_ino, (long)block, 165dac52fc1SFabian Frederick (unsigned long)disk_off); 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds return 0; 1681da177e4SLinus Torvalds } 1691da177e4SLinus Torvalds 1701da177e4SLinus Torvalds static struct dentry * 17100cd8dd3SAl Viro befs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) 1721da177e4SLinus Torvalds { 173c9408763SSalah Triki struct inode *inode; 1741da177e4SLinus Torvalds struct super_block *sb = dir->i_sb; 17522341d8fSAl Viro const befs_data_stream *ds = &BEFS_I(dir)->i_data.ds; 1761da177e4SLinus Torvalds befs_off_t offset; 1771da177e4SLinus Torvalds int ret; 1781da177e4SLinus Torvalds int utfnamelen; 1791da177e4SLinus Torvalds char *utfname; 1801da177e4SLinus Torvalds const char *name = dentry->d_name.name; 1811da177e4SLinus Torvalds 182a455589fSAl Viro befs_debug(sb, "---> %s name %pd inode %ld", __func__, 183a455589fSAl Viro dentry, dir->i_ino); 1841da177e4SLinus Torvalds 1851da177e4SLinus Torvalds /* Convert to UTF-8 */ 1861da177e4SLinus Torvalds if (BEFS_SB(sb)->nls) { 1871da177e4SLinus Torvalds ret = 1881da177e4SLinus Torvalds befs_nls2utf(sb, name, strlen(name), &utfname, &utfnamelen); 1891da177e4SLinus Torvalds if (ret < 0) { 190dac52fc1SFabian Frederick befs_debug(sb, "<--- %s ERROR", __func__); 1911da177e4SLinus Torvalds return ERR_PTR(ret); 1921da177e4SLinus Torvalds } 1931da177e4SLinus Torvalds ret = befs_btree_find(sb, ds, utfname, &offset); 1941da177e4SLinus Torvalds kfree(utfname); 1951da177e4SLinus Torvalds 1961da177e4SLinus Torvalds } else { 197f7769f9cSLuis de Bethencourt ret = befs_btree_find(sb, ds, name, &offset); 1981da177e4SLinus Torvalds } 1991da177e4SLinus Torvalds 2001da177e4SLinus Torvalds if (ret == BEFS_BT_NOT_FOUND) { 201a455589fSAl Viro befs_debug(sb, "<--- %s %pd not found", __func__, dentry); 202f4e4d434SAl Viro inode = NULL; 2031da177e4SLinus Torvalds } else if (ret != BEFS_OK || offset == 0) { 2044c3897ccSLuis de Bethencourt befs_error(sb, "<--- %s Error", __func__); 205f4e4d434SAl Viro inode = ERR_PTR(-ENODATA); 206f4e4d434SAl Viro } else { 20796eb5419SDavid Howells inode = befs_iget(dir->i_sb, (ino_t) offset); 208f4e4d434SAl Viro } 209dac52fc1SFabian Frederick befs_debug(sb, "<--- %s", __func__); 2101da177e4SLinus Torvalds 211f4e4d434SAl Viro return d_splice_alias(inode, dentry); 2121da177e4SLinus Torvalds } 2131da177e4SLinus Torvalds 2141da177e4SLinus Torvalds static int 215f0f49ef5SAl Viro befs_readdir(struct file *file, struct dir_context *ctx) 2161da177e4SLinus Torvalds { 217f0f49ef5SAl Viro struct inode *inode = file_inode(file); 2181da177e4SLinus Torvalds struct super_block *sb = inode->i_sb; 21922341d8fSAl Viro const befs_data_stream *ds = &BEFS_I(inode)->i_data.ds; 2201da177e4SLinus Torvalds befs_off_t value; 2211da177e4SLinus Torvalds int result; 2221da177e4SLinus Torvalds size_t keysize; 2231da177e4SLinus Torvalds char keybuf[BEFS_NAME_LEN + 1]; 2241da177e4SLinus Torvalds 225a455589fSAl Viro befs_debug(sb, "---> %s name %pD, inode %ld, ctx->pos %lld", 226a455589fSAl Viro __func__, file, inode->i_ino, ctx->pos); 2271da177e4SLinus Torvalds 2289ae51a32SLuis de Bethencourt while (1) { 229f0f49ef5SAl Viro result = befs_btree_read(sb, ds, ctx->pos, BEFS_NAME_LEN + 1, 2301da177e4SLinus Torvalds keybuf, &keysize, &value); 2311da177e4SLinus Torvalds 2321da177e4SLinus Torvalds if (result == BEFS_ERR) { 233dac52fc1SFabian Frederick befs_debug(sb, "<--- %s ERROR", __func__); 234a455589fSAl Viro befs_error(sb, "IO error reading %pD (inode %lu)", 235a455589fSAl Viro file, inode->i_ino); 2361da177e4SLinus Torvalds return -EIO; 2371da177e4SLinus Torvalds 2381da177e4SLinus Torvalds } else if (result == BEFS_BT_END) { 239dac52fc1SFabian Frederick befs_debug(sb, "<--- %s END", __func__); 2401da177e4SLinus Torvalds return 0; 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds } else if (result == BEFS_BT_EMPTY) { 243dac52fc1SFabian Frederick befs_debug(sb, "<--- %s Empty directory", __func__); 2441da177e4SLinus Torvalds return 0; 2451da177e4SLinus Torvalds } 2461da177e4SLinus Torvalds 2471da177e4SLinus Torvalds /* Convert to NLS */ 2481da177e4SLinus Torvalds if (BEFS_SB(sb)->nls) { 249f0f49ef5SAl Viro char *nlsname; 250f0f49ef5SAl Viro int nlsnamelen; 2519ae51a32SLuis de Bethencourt 2521da177e4SLinus Torvalds result = 2539ae51a32SLuis de Bethencourt befs_utf2nls(sb, keybuf, keysize, &nlsname, 2549ae51a32SLuis de Bethencourt &nlsnamelen); 2551da177e4SLinus Torvalds if (result < 0) { 256dac52fc1SFabian Frederick befs_debug(sb, "<--- %s ERROR", __func__); 2571da177e4SLinus Torvalds return result; 2581da177e4SLinus Torvalds } 259f0f49ef5SAl Viro if (!dir_emit(ctx, nlsname, nlsnamelen, 26050858ef9SLuis de Bethencourt (ino_t) value, DT_UNKNOWN)) { 2611da177e4SLinus Torvalds kfree(nlsname); 262f0f49ef5SAl Viro return 0; 2631da177e4SLinus Torvalds } 264f0f49ef5SAl Viro kfree(nlsname); 265f0f49ef5SAl Viro } else { 266f0f49ef5SAl Viro if (!dir_emit(ctx, keybuf, keysize, 26750858ef9SLuis de Bethencourt (ino_t) value, DT_UNKNOWN)) 268f0f49ef5SAl Viro return 0; 269f0f49ef5SAl Viro } 270f0f49ef5SAl Viro ctx->pos++; 2719ae51a32SLuis de Bethencourt } 2721da177e4SLinus Torvalds } 2731da177e4SLinus Torvalds 2741da177e4SLinus Torvalds static struct inode * 2751da177e4SLinus Torvalds befs_alloc_inode(struct super_block *sb) 2761da177e4SLinus Torvalds { 2771da177e4SLinus Torvalds struct befs_inode_info *bi; 278111d639dSFabian Frederick 279fd60b288SMuchun Song bi = alloc_inode_sb(sb, befs_inode_cachep, GFP_KERNEL); 2801da177e4SLinus Torvalds if (!bi) 2811da177e4SLinus Torvalds return NULL; 2821da177e4SLinus Torvalds return &bi->vfs_inode; 2831da177e4SLinus Torvalds } 2841da177e4SLinus Torvalds 28549f82a80SAl Viro static void befs_free_inode(struct inode *inode) 2861da177e4SLinus Torvalds { 2871da177e4SLinus Torvalds kmem_cache_free(befs_inode_cachep, BEFS_I(inode)); 2881da177e4SLinus Torvalds } 2891da177e4SLinus Torvalds 29051cc5068SAlexey Dobriyan static void init_once(void *foo) 2911da177e4SLinus Torvalds { 2921da177e4SLinus Torvalds struct befs_inode_info *bi = (struct befs_inode_info *) foo; 2931da177e4SLinus Torvalds 2941da177e4SLinus Torvalds inode_init_once(&bi->vfs_inode); 2951da177e4SLinus Torvalds } 2961da177e4SLinus Torvalds 29796eb5419SDavid Howells static struct inode *befs_iget(struct super_block *sb, unsigned long ino) 2981da177e4SLinus Torvalds { 299e4c7f5b1SSalah Triki struct buffer_head *bh; 30044ad8098SSalah Triki befs_inode *raw_inode; 301038428fcSFabian Frederick struct befs_sb_info *befs_sb = BEFS_SB(sb); 302d6e02033SSalah Triki struct befs_inode_info *befs_ino; 30396eb5419SDavid Howells struct inode *inode; 3041da177e4SLinus Torvalds 305dac52fc1SFabian Frederick befs_debug(sb, "---> %s inode = %lu", __func__, ino); 30696eb5419SDavid Howells 30796eb5419SDavid Howells inode = iget_locked(sb, ino); 308ac34a1b3SRakesh Pandit if (!inode) 309ac34a1b3SRakesh Pandit return ERR_PTR(-ENOMEM); 31096eb5419SDavid Howells if (!(inode->i_state & I_NEW)) 31196eb5419SDavid Howells return inode; 3121da177e4SLinus Torvalds 3131da177e4SLinus Torvalds befs_ino = BEFS_I(inode); 3141da177e4SLinus Torvalds 3151da177e4SLinus Torvalds /* convert from vfs's inode number to befs's inode number */ 3161da177e4SLinus Torvalds befs_ino->i_inode_num = blockno2iaddr(sb, inode->i_ino); 3171da177e4SLinus Torvalds 3181da177e4SLinus Torvalds befs_debug(sb, " real inode number [%u, %hu, %hu]", 3191da177e4SLinus Torvalds befs_ino->i_inode_num.allocation_group, 3201da177e4SLinus Torvalds befs_ino->i_inode_num.start, befs_ino->i_inode_num.len); 3211da177e4SLinus Torvalds 322f7f67540SSalah Triki bh = sb_bread(sb, inode->i_ino); 3231da177e4SLinus Torvalds if (!bh) { 3241da177e4SLinus Torvalds befs_error(sb, "unable to read inode block - " 3251da177e4SLinus Torvalds "inode = %lu", inode->i_ino); 3260418726bSAdrian Bunk goto unacquire_none; 3271da177e4SLinus Torvalds } 3281da177e4SLinus Torvalds 3291da177e4SLinus Torvalds raw_inode = (befs_inode *) bh->b_data; 3301da177e4SLinus Torvalds 3311da177e4SLinus Torvalds befs_dump_inode(sb, raw_inode); 3321da177e4SLinus Torvalds 3331da177e4SLinus Torvalds if (befs_check_inode(sb, raw_inode, inode->i_ino) != BEFS_OK) { 3341da177e4SLinus Torvalds befs_error(sb, "Bad inode: %lu", inode->i_ino); 3350418726bSAdrian Bunk goto unacquire_bh; 3361da177e4SLinus Torvalds } 3371da177e4SLinus Torvalds 3381da177e4SLinus Torvalds inode->i_mode = (umode_t) fs32_to_cpu(sb, raw_inode->mode); 3391da177e4SLinus Torvalds 3401da177e4SLinus Torvalds /* 3411da177e4SLinus Torvalds * set uid and gid. But since current BeOS is single user OS, so 3421da177e4SLinus Torvalds * you can change by "uid" or "gid" options. 3431da177e4SLinus Torvalds */ 3441da177e4SLinus Torvalds 3451da177e4SLinus Torvalds inode->i_uid = befs_sb->mount_opts.use_uid ? 34631aba059SEric W. Biederman befs_sb->mount_opts.uid : 34731aba059SEric W. Biederman make_kuid(&init_user_ns, fs32_to_cpu(sb, raw_inode->uid)); 3481da177e4SLinus Torvalds inode->i_gid = befs_sb->mount_opts.use_gid ? 34931aba059SEric W. Biederman befs_sb->mount_opts.gid : 35031aba059SEric W. Biederman make_kgid(&init_user_ns, fs32_to_cpu(sb, raw_inode->gid)); 3511da177e4SLinus Torvalds 352bfe86848SMiklos Szeredi set_nlink(inode, 1); 3531da177e4SLinus Torvalds 3541da177e4SLinus Torvalds /* 3551da177e4SLinus Torvalds * BEFS's time is 64 bits, but current VFS is 32 bits... 3561da177e4SLinus Torvalds * BEFS don't have access time. Nor inode change time. VFS 3571da177e4SLinus Torvalds * doesn't have creation time. 3581da177e4SLinus Torvalds * Also, the lower 16 bits of the last_modified_time and 3591da177e4SLinus Torvalds * create_time are just a counter to help ensure uniqueness 3601da177e4SLinus Torvalds * for indexing purposes. (PFD, page 54) 3611da177e4SLinus Torvalds */ 3621da177e4SLinus Torvalds 3631da177e4SLinus Torvalds inode->i_mtime.tv_sec = 3641da177e4SLinus Torvalds fs64_to_cpu(sb, raw_inode->last_modified_time) >> 16; 3651da177e4SLinus Torvalds inode->i_mtime.tv_nsec = 0; /* lower 16 bits are not a time */ 3661da177e4SLinus Torvalds inode->i_ctime = inode->i_mtime; 3671da177e4SLinus Torvalds inode->i_atime = inode->i_mtime; 3681da177e4SLinus Torvalds 3691da177e4SLinus Torvalds befs_ino->i_inode_num = fsrun_to_cpu(sb, raw_inode->inode_num); 3701da177e4SLinus Torvalds befs_ino->i_parent = fsrun_to_cpu(sb, raw_inode->parent); 3711da177e4SLinus Torvalds befs_ino->i_attribute = fsrun_to_cpu(sb, raw_inode->attributes); 3721da177e4SLinus Torvalds befs_ino->i_flags = fs32_to_cpu(sb, raw_inode->flags); 3731da177e4SLinus Torvalds 3741da177e4SLinus Torvalds if (S_ISLNK(inode->i_mode) && !(befs_ino->i_flags & BEFS_LONG_SYMLINK)){ 3751da177e4SLinus Torvalds inode->i_size = 0; 3761da177e4SLinus Torvalds inode->i_blocks = befs_sb->block_size / VFS_BLOCK_SIZE; 377*73919280SAzeem Shaikh strscpy(befs_ino->i_data.symlink, raw_inode->data.symlink, 37839d7a29fSFabian Frederick BEFS_SYMLINK_LEN); 3791da177e4SLinus Torvalds } else { 3801da177e4SLinus Torvalds int num_blks; 3811da177e4SLinus Torvalds 3821da177e4SLinus Torvalds befs_ino->i_data.ds = 383e0e3d32bSJesper Juhl fsds_to_cpu(sb, &raw_inode->data.datastream); 3841da177e4SLinus Torvalds 3851da177e4SLinus Torvalds num_blks = befs_count_blocks(sb, &befs_ino->i_data.ds); 3861da177e4SLinus Torvalds inode->i_blocks = 3871da177e4SLinus Torvalds num_blks * (befs_sb->block_size / VFS_BLOCK_SIZE); 3881da177e4SLinus Torvalds inode->i_size = befs_ino->i_data.ds.size; 3891da177e4SLinus Torvalds } 3901da177e4SLinus Torvalds 3911da177e4SLinus Torvalds inode->i_mapping->a_ops = &befs_aops; 3921da177e4SLinus Torvalds 3931da177e4SLinus Torvalds if (S_ISREG(inode->i_mode)) { 3942cf06916SChristoph Hellwig inode->i_fop = &generic_ro_fops; 3951da177e4SLinus Torvalds } else if (S_ISDIR(inode->i_mode)) { 3961da177e4SLinus Torvalds inode->i_op = &befs_dir_inode_operations; 3971da177e4SLinus Torvalds inode->i_fop = &befs_dir_operations; 3981da177e4SLinus Torvalds } else if (S_ISLNK(inode->i_mode)) { 399d0deec19SAl Viro if (befs_ino->i_flags & BEFS_LONG_SYMLINK) { 40011803f97SAl Viro inode->i_op = &page_symlink_inode_operations; 40121fc61c7SAl Viro inode_nohighmem(inode); 40211803f97SAl Viro inode->i_mapping->a_ops = &befs_symlink_aops; 403d0deec19SAl Viro } else { 404d0deec19SAl Viro inode->i_link = befs_ino->i_data.symlink; 405d0deec19SAl Viro inode->i_op = &simple_symlink_inode_operations; 406d0deec19SAl Viro } 4071da177e4SLinus Torvalds } else { 4081da177e4SLinus Torvalds befs_error(sb, "Inode %lu is not a regular file, " 4091da177e4SLinus Torvalds "directory or symlink. THAT IS WRONG! BeFS has no " 4101da177e4SLinus Torvalds "on disk special files", inode->i_ino); 4110418726bSAdrian Bunk goto unacquire_bh; 4121da177e4SLinus Torvalds } 4131da177e4SLinus Torvalds 4141da177e4SLinus Torvalds brelse(bh); 415dac52fc1SFabian Frederick befs_debug(sb, "<--- %s", __func__); 41696eb5419SDavid Howells unlock_new_inode(inode); 41796eb5419SDavid Howells return inode; 4181da177e4SLinus Torvalds 4190418726bSAdrian Bunk unacquire_bh: 4201da177e4SLinus Torvalds brelse(bh); 4211da177e4SLinus Torvalds 4220418726bSAdrian Bunk unacquire_none: 42396eb5419SDavid Howells iget_failed(inode); 424dac52fc1SFabian Frederick befs_debug(sb, "<--- %s - Bad inode", __func__); 42533c712b4SSalah Triki return ERR_PTR(-EIO); 4261da177e4SLinus Torvalds } 4271da177e4SLinus Torvalds 4281da177e4SLinus Torvalds /* Initialize the inode cache. Called at fs setup. 4291da177e4SLinus Torvalds * 4301da177e4SLinus Torvalds * Taken from NFS implementation by Al Viro. 4311da177e4SLinus Torvalds */ 43291a52ab7SFabian Frederick static int __init 4331da177e4SLinus Torvalds befs_init_inodecache(void) 4341da177e4SLinus Torvalds { 4350fc256d3SDavid Windsor befs_inode_cachep = kmem_cache_create_usercopy("befs_inode_cache", 4360fc256d3SDavid Windsor sizeof(struct befs_inode_info), 0, 4370fc256d3SDavid Windsor (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD| 4380fc256d3SDavid Windsor SLAB_ACCOUNT), 4390fc256d3SDavid Windsor offsetof(struct befs_inode_info, 4400fc256d3SDavid Windsor i_data.symlink), 4410fc256d3SDavid Windsor sizeof_field(struct befs_inode_info, 4420fc256d3SDavid Windsor i_data.symlink), 44320c2df83SPaul Mundt init_once); 444c08f1cb6SSalah Triki if (befs_inode_cachep == NULL) 4451da177e4SLinus Torvalds return -ENOMEM; 446c08f1cb6SSalah Triki 4471da177e4SLinus Torvalds return 0; 4481da177e4SLinus Torvalds } 4491da177e4SLinus Torvalds 4501da177e4SLinus Torvalds /* Called at fs teardown. 4511da177e4SLinus Torvalds * 4521da177e4SLinus Torvalds * Taken from NFS implementation by Al Viro. 4531da177e4SLinus Torvalds */ 4541da177e4SLinus Torvalds static void 4551da177e4SLinus Torvalds befs_destroy_inodecache(void) 4561da177e4SLinus Torvalds { 4578c0a8537SKirill A. Shutemov /* 4588c0a8537SKirill A. Shutemov * Make sure all delayed rcu free inodes are flushed before we 4598c0a8537SKirill A. Shutemov * destroy cache. 4608c0a8537SKirill A. Shutemov */ 4618c0a8537SKirill A. Shutemov rcu_barrier(); 4621a1d92c1SAlexey Dobriyan kmem_cache_destroy(befs_inode_cachep); 4631da177e4SLinus Torvalds } 4641da177e4SLinus Torvalds 4651da177e4SLinus Torvalds /* 4661da177e4SLinus Torvalds * The inode of symbolic link is different to data stream. 4671da177e4SLinus Torvalds * The data stream become link name. Unless the LONG_SYMLINK 4681da177e4SLinus Torvalds * flag is set. 4691da177e4SLinus Torvalds */ 470a13fe692SMatthew Wilcox (Oracle) static int befs_symlink_read_folio(struct file *unused, struct folio *folio) 4711da177e4SLinus Torvalds { 472ac09d88bSMatthew Wilcox (Oracle) struct inode *inode = folio->mapping->host; 47311803f97SAl Viro struct super_block *sb = inode->i_sb; 47411803f97SAl Viro struct befs_inode_info *befs_ino = BEFS_I(inode); 4751da177e4SLinus Torvalds befs_data_stream *data = &befs_ino->i_data.ds; 4761da177e4SLinus Torvalds befs_off_t len = data->size; 477ac09d88bSMatthew Wilcox (Oracle) char *link = folio_address(folio); 4781da177e4SLinus Torvalds 47911803f97SAl Viro if (len == 0 || len > PAGE_SIZE) { 480338d0f0aSTimo Warns befs_error(sb, "Long symlink with illegal length"); 48111803f97SAl Viro goto fail; 482680baacbSAl Viro } 4831da177e4SLinus Torvalds befs_debug(sb, "Follow long symlink"); 4841da177e4SLinus Torvalds 485680baacbSAl Viro if (befs_read_lsymlink(sb, data, link, len) != len) { 4861da177e4SLinus Torvalds befs_error(sb, "Failed to read entire long symlink"); 48711803f97SAl Viro goto fail; 488680baacbSAl Viro } 4897df5fa06SDuane Griffin link[len - 1] = '\0'; 490ac09d88bSMatthew Wilcox (Oracle) folio_mark_uptodate(folio); 491ac09d88bSMatthew Wilcox (Oracle) folio_unlock(folio); 49211803f97SAl Viro return 0; 49311803f97SAl Viro fail: 494ac09d88bSMatthew Wilcox (Oracle) folio_set_error(folio); 495ac09d88bSMatthew Wilcox (Oracle) folio_unlock(folio); 49611803f97SAl Viro return -EIO; 4971da177e4SLinus Torvalds } 4981da177e4SLinus Torvalds 4991da177e4SLinus Torvalds /* 5001da177e4SLinus Torvalds * UTF-8 to NLS charset convert routine 5011da177e4SLinus Torvalds * 5021ca7087eSLuis de Bethencourt * Uses uni2char() / char2uni() rather than the nls tables directly 5031da177e4SLinus Torvalds */ 5041da177e4SLinus Torvalds static int 5051da177e4SLinus Torvalds befs_utf2nls(struct super_block *sb, const char *in, 5061da177e4SLinus Torvalds int in_len, char **out, int *out_len) 5071da177e4SLinus Torvalds { 5081da177e4SLinus Torvalds struct nls_table *nls = BEFS_SB(sb)->nls; 5091da177e4SLinus Torvalds int i, o; 51074675a58SAlan Stern unicode_t uni; 5111da177e4SLinus Torvalds int unilen, utflen; 5121da177e4SLinus Torvalds char *result; 51394f563c4SDiego Calleja /* The utf8->nls conversion won't make the final nls string bigger 51494f563c4SDiego Calleja * than the utf one, but if the string is pure ascii they'll have the 51594f563c4SDiego Calleja * same width and an extra char is needed to save the additional \0 51694f563c4SDiego Calleja */ 51794f563c4SDiego Calleja int maxlen = in_len + 1; 5181da177e4SLinus Torvalds 519dac52fc1SFabian Frederick befs_debug(sb, "---> %s", __func__); 5201da177e4SLinus Torvalds 5211da177e4SLinus Torvalds if (!nls) { 522dac52fc1SFabian Frederick befs_error(sb, "%s called with no NLS table loaded", __func__); 5231da177e4SLinus Torvalds return -EINVAL; 5241da177e4SLinus Torvalds } 5251da177e4SLinus Torvalds 5261da177e4SLinus Torvalds *out = result = kmalloc(maxlen, GFP_NOFS); 52762b80719SLuis de Bethencourt if (!*out) 5281da177e4SLinus Torvalds return -ENOMEM; 5291da177e4SLinus Torvalds 5301da177e4SLinus Torvalds for (i = o = 0; i < in_len; i += utflen, o += unilen) { 5311da177e4SLinus Torvalds 5321da177e4SLinus Torvalds /* convert from UTF-8 to Unicode */ 53374675a58SAlan Stern utflen = utf8_to_utf32(&in[i], in_len - i, &uni); 53474675a58SAlan Stern if (utflen < 0) 5351da177e4SLinus Torvalds goto conv_err; 5361da177e4SLinus Torvalds 5371da177e4SLinus Torvalds /* convert from Unicode to nls */ 53874675a58SAlan Stern if (uni > MAX_WCHAR_T) 5391da177e4SLinus Torvalds goto conv_err; 54074675a58SAlan Stern unilen = nls->uni2char(uni, &result[o], in_len - o); 54174675a58SAlan Stern if (unilen < 0) 54274675a58SAlan Stern goto conv_err; 5431da177e4SLinus Torvalds } 5441da177e4SLinus Torvalds result[o] = '\0'; 5451da177e4SLinus Torvalds *out_len = o; 5461da177e4SLinus Torvalds 547dac52fc1SFabian Frederick befs_debug(sb, "<--- %s", __func__); 5481da177e4SLinus Torvalds 5491da177e4SLinus Torvalds return o; 5501da177e4SLinus Torvalds 5511da177e4SLinus Torvalds conv_err: 5521da177e4SLinus Torvalds befs_error(sb, "Name using character set %s contains a character that " 5531da177e4SLinus Torvalds "cannot be converted to unicode.", nls->charset); 554dac52fc1SFabian Frederick befs_debug(sb, "<--- %s", __func__); 5551da177e4SLinus Torvalds kfree(result); 5561da177e4SLinus Torvalds return -EILSEQ; 5571da177e4SLinus Torvalds } 5581da177e4SLinus Torvalds 5591da177e4SLinus Torvalds /** 5601da177e4SLinus Torvalds * befs_nls2utf - Convert NLS string to utf8 encodeing 5611da177e4SLinus Torvalds * @sb: Superblock 562817e1d90SFabian Frederick * @in: Input string buffer in NLS format 563817e1d90SFabian Frederick * @in_len: Length of input string in bytes 564817e1d90SFabian Frederick * @out: The output string in UTF-8 format 565817e1d90SFabian Frederick * @out_len: Length of the output buffer 5661da177e4SLinus Torvalds * 567817e1d90SFabian Frederick * Converts input string @in, which is in the format of the loaded NLS map, 5681da177e4SLinus Torvalds * into a utf8 string. 5691da177e4SLinus Torvalds * 570817e1d90SFabian Frederick * The destination string @out is allocated by this function and the caller is 5711da177e4SLinus Torvalds * responsible for freeing it with kfree() 5721da177e4SLinus Torvalds * 573817e1d90SFabian Frederick * On return, *@out_len is the length of @out in bytes. 5741da177e4SLinus Torvalds * 5751da177e4SLinus Torvalds * On success, the return value is the number of utf8 characters written to 576817e1d90SFabian Frederick * the output buffer @out. 5771da177e4SLinus Torvalds * 5781da177e4SLinus Torvalds * On Failure, a negative number coresponding to the error code is returned. 5791da177e4SLinus Torvalds */ 5801da177e4SLinus Torvalds 5811da177e4SLinus Torvalds static int 5821da177e4SLinus Torvalds befs_nls2utf(struct super_block *sb, const char *in, 5831da177e4SLinus Torvalds int in_len, char **out, int *out_len) 5841da177e4SLinus Torvalds { 5851da177e4SLinus Torvalds struct nls_table *nls = BEFS_SB(sb)->nls; 5861da177e4SLinus Torvalds int i, o; 5871da177e4SLinus Torvalds wchar_t uni; 5881da177e4SLinus Torvalds int unilen, utflen; 5891da177e4SLinus Torvalds char *result; 5901ca7087eSLuis de Bethencourt /* 5911ca7087eSLuis de Bethencourt * There are nls characters that will translate to 3-chars-wide UTF-8 5921ca7087eSLuis de Bethencourt * characters, an additional byte is needed to save the final \0 59362b80719SLuis de Bethencourt * in special cases 59462b80719SLuis de Bethencourt */ 59594f563c4SDiego Calleja int maxlen = (3 * in_len) + 1; 5961da177e4SLinus Torvalds 597dac52fc1SFabian Frederick befs_debug(sb, "---> %s\n", __func__); 5981da177e4SLinus Torvalds 5991da177e4SLinus Torvalds if (!nls) { 600dac52fc1SFabian Frederick befs_error(sb, "%s called with no NLS table loaded.", 601dac52fc1SFabian Frederick __func__); 6021da177e4SLinus Torvalds return -EINVAL; 6031da177e4SLinus Torvalds } 6041da177e4SLinus Torvalds 6051da177e4SLinus Torvalds *out = result = kmalloc(maxlen, GFP_NOFS); 6061da177e4SLinus Torvalds if (!*out) { 6071da177e4SLinus Torvalds *out_len = 0; 6081da177e4SLinus Torvalds return -ENOMEM; 6091da177e4SLinus Torvalds } 6101da177e4SLinus Torvalds 6111da177e4SLinus Torvalds for (i = o = 0; i < in_len; i += unilen, o += utflen) { 6121da177e4SLinus Torvalds 6131da177e4SLinus Torvalds /* convert from nls to unicode */ 6141da177e4SLinus Torvalds unilen = nls->char2uni(&in[i], in_len - i, &uni); 61574675a58SAlan Stern if (unilen < 0) 6161da177e4SLinus Torvalds goto conv_err; 6171da177e4SLinus Torvalds 6181da177e4SLinus Torvalds /* convert from unicode to UTF-8 */ 61974675a58SAlan Stern utflen = utf32_to_utf8(uni, &result[o], 3); 62074675a58SAlan Stern if (utflen <= 0) 6211da177e4SLinus Torvalds goto conv_err; 6221da177e4SLinus Torvalds } 6231da177e4SLinus Torvalds 6241da177e4SLinus Torvalds result[o] = '\0'; 6251da177e4SLinus Torvalds *out_len = o; 6261da177e4SLinus Torvalds 627dac52fc1SFabian Frederick befs_debug(sb, "<--- %s", __func__); 6281da177e4SLinus Torvalds 6291da177e4SLinus Torvalds return i; 6301da177e4SLinus Torvalds 6311da177e4SLinus Torvalds conv_err: 6321ca7087eSLuis de Bethencourt befs_error(sb, "Name using character set %s contains a character that " 6331da177e4SLinus Torvalds "cannot be converted to unicode.", nls->charset); 634dac52fc1SFabian Frederick befs_debug(sb, "<--- %s", __func__); 6351da177e4SLinus Torvalds kfree(result); 6361da177e4SLinus Torvalds return -EILSEQ; 6371da177e4SLinus Torvalds } 6381da177e4SLinus Torvalds 639ac632f5bSLuis de Bethencourt static struct inode *befs_nfs_get_inode(struct super_block *sb, uint64_t ino, 640ac632f5bSLuis de Bethencourt uint32_t generation) 641ac632f5bSLuis de Bethencourt { 642ac632f5bSLuis de Bethencourt /* No need to handle i_generation */ 643ac632f5bSLuis de Bethencourt return befs_iget(sb, ino); 644ac632f5bSLuis de Bethencourt } 645ac632f5bSLuis de Bethencourt 646ac632f5bSLuis de Bethencourt /* 647ac632f5bSLuis de Bethencourt * Map a NFS file handle to a corresponding dentry 648ac632f5bSLuis de Bethencourt */ 649ac632f5bSLuis de Bethencourt static struct dentry *befs_fh_to_dentry(struct super_block *sb, 650ac632f5bSLuis de Bethencourt struct fid *fid, int fh_len, int fh_type) 651ac632f5bSLuis de Bethencourt { 652ac632f5bSLuis de Bethencourt return generic_fh_to_dentry(sb, fid, fh_len, fh_type, 653ac632f5bSLuis de Bethencourt befs_nfs_get_inode); 654ac632f5bSLuis de Bethencourt } 655ac632f5bSLuis de Bethencourt 656ac632f5bSLuis de Bethencourt /* 657ac632f5bSLuis de Bethencourt * Find the parent for a file specified by NFS handle 658ac632f5bSLuis de Bethencourt */ 659ac632f5bSLuis de Bethencourt static struct dentry *befs_fh_to_parent(struct super_block *sb, 660ac632f5bSLuis de Bethencourt struct fid *fid, int fh_len, int fh_type) 661ac632f5bSLuis de Bethencourt { 662ac632f5bSLuis de Bethencourt return generic_fh_to_parent(sb, fid, fh_len, fh_type, 663ac632f5bSLuis de Bethencourt befs_nfs_get_inode); 664ac632f5bSLuis de Bethencourt } 665ac632f5bSLuis de Bethencourt 666dcfd9b21SFabian Frederick static struct dentry *befs_get_parent(struct dentry *child) 667dcfd9b21SFabian Frederick { 668dcfd9b21SFabian Frederick struct inode *parent; 669dcfd9b21SFabian Frederick struct befs_inode_info *befs_ino = BEFS_I(d_inode(child)); 670dcfd9b21SFabian Frederick 671dcfd9b21SFabian Frederick parent = befs_iget(child->d_sb, 672dcfd9b21SFabian Frederick (unsigned long)befs_ino->i_parent.start); 673dcfd9b21SFabian Frederick if (IS_ERR(parent)) 674dcfd9b21SFabian Frederick return ERR_CAST(parent); 675dcfd9b21SFabian Frederick 676dcfd9b21SFabian Frederick return d_obtain_alias(parent); 677dcfd9b21SFabian Frederick } 678dcfd9b21SFabian Frederick 6791da177e4SLinus Torvalds enum { 6801da177e4SLinus Torvalds Opt_uid, Opt_gid, Opt_charset, Opt_debug, Opt_err, 6811da177e4SLinus Torvalds }; 6821da177e4SLinus Torvalds 683a447c093SSteven Whitehouse static const match_table_t befs_tokens = { 6841da177e4SLinus Torvalds {Opt_uid, "uid=%d"}, 6851da177e4SLinus Torvalds {Opt_gid, "gid=%d"}, 6861da177e4SLinus Torvalds {Opt_charset, "iocharset=%s"}, 6871da177e4SLinus Torvalds {Opt_debug, "debug"}, 6881da177e4SLinus Torvalds {Opt_err, NULL} 6891da177e4SLinus Torvalds }; 6901da177e4SLinus Torvalds 6911da177e4SLinus Torvalds static int 69209ad0eaeSFabian Frederick parse_options(char *options, struct befs_mount_options *opts) 6931da177e4SLinus Torvalds { 6941da177e4SLinus Torvalds char *p; 6951da177e4SLinus Torvalds substring_t args[MAX_OPT_ARGS]; 6961da177e4SLinus Torvalds int option; 69731aba059SEric W. Biederman kuid_t uid; 69831aba059SEric W. Biederman kgid_t gid; 6991da177e4SLinus Torvalds 7001da177e4SLinus Torvalds /* Initialize options */ 70131aba059SEric W. Biederman opts->uid = GLOBAL_ROOT_UID; 70231aba059SEric W. Biederman opts->gid = GLOBAL_ROOT_GID; 7031da177e4SLinus Torvalds opts->use_uid = 0; 7041da177e4SLinus Torvalds opts->use_gid = 0; 7051da177e4SLinus Torvalds opts->iocharset = NULL; 7061da177e4SLinus Torvalds opts->debug = 0; 7071da177e4SLinus Torvalds 7081da177e4SLinus Torvalds if (!options) 7091da177e4SLinus Torvalds return 1; 7101da177e4SLinus Torvalds 7111da177e4SLinus Torvalds while ((p = strsep(&options, ",")) != NULL) { 7121da177e4SLinus Torvalds int token; 71362b80719SLuis de Bethencourt 7141da177e4SLinus Torvalds if (!*p) 7151da177e4SLinus Torvalds continue; 7161da177e4SLinus Torvalds 7171da177e4SLinus Torvalds token = match_token(p, befs_tokens, args); 7181da177e4SLinus Torvalds switch (token) { 7191da177e4SLinus Torvalds case Opt_uid: 7201da177e4SLinus Torvalds if (match_int(&args[0], &option)) 7211da177e4SLinus Torvalds return 0; 72231aba059SEric W. Biederman uid = INVALID_UID; 72331aba059SEric W. Biederman if (option >= 0) 72431aba059SEric W. Biederman uid = make_kuid(current_user_ns(), option); 72531aba059SEric W. Biederman if (!uid_valid(uid)) { 726dac52fc1SFabian Frederick pr_err("Invalid uid %d, " 7271da177e4SLinus Torvalds "using default\n", option); 7281da177e4SLinus Torvalds break; 7291da177e4SLinus Torvalds } 73031aba059SEric W. Biederman opts->uid = uid; 7311da177e4SLinus Torvalds opts->use_uid = 1; 7321da177e4SLinus Torvalds break; 7331da177e4SLinus Torvalds case Opt_gid: 7341da177e4SLinus Torvalds if (match_int(&args[0], &option)) 7351da177e4SLinus Torvalds return 0; 73631aba059SEric W. Biederman gid = INVALID_GID; 73731aba059SEric W. Biederman if (option >= 0) 73831aba059SEric W. Biederman gid = make_kgid(current_user_ns(), option); 73931aba059SEric W. Biederman if (!gid_valid(gid)) { 740dac52fc1SFabian Frederick pr_err("Invalid gid %d, " 7411da177e4SLinus Torvalds "using default\n", option); 7421da177e4SLinus Torvalds break; 7431da177e4SLinus Torvalds } 74431aba059SEric W. Biederman opts->gid = gid; 7451da177e4SLinus Torvalds opts->use_gid = 1; 7461da177e4SLinus Torvalds break; 7471da177e4SLinus Torvalds case Opt_charset: 7481da177e4SLinus Torvalds kfree(opts->iocharset); 7491da177e4SLinus Torvalds opts->iocharset = match_strdup(&args[0]); 7501da177e4SLinus Torvalds if (!opts->iocharset) { 751dac52fc1SFabian Frederick pr_err("allocation failure for " 7521da177e4SLinus Torvalds "iocharset string\n"); 7531da177e4SLinus Torvalds return 0; 7541da177e4SLinus Torvalds } 7551da177e4SLinus Torvalds break; 7561da177e4SLinus Torvalds case Opt_debug: 7571da177e4SLinus Torvalds opts->debug = 1; 7581da177e4SLinus Torvalds break; 7591da177e4SLinus Torvalds default: 760dac52fc1SFabian Frederick pr_err("Unrecognized mount option \"%s\" " 7611da177e4SLinus Torvalds "or missing value\n", p); 7621da177e4SLinus Torvalds return 0; 7631da177e4SLinus Torvalds } 7641da177e4SLinus Torvalds } 7651da177e4SLinus Torvalds return 1; 7661da177e4SLinus Torvalds } 7671da177e4SLinus Torvalds 7683ab7947aSDavid Howells static int befs_show_options(struct seq_file *m, struct dentry *root) 7693ab7947aSDavid Howells { 7703ab7947aSDavid Howells struct befs_sb_info *befs_sb = BEFS_SB(root->d_sb); 7713ab7947aSDavid Howells struct befs_mount_options *opts = &befs_sb->mount_opts; 7723ab7947aSDavid Howells 7733ab7947aSDavid Howells if (!uid_eq(opts->uid, GLOBAL_ROOT_UID)) 7743ab7947aSDavid Howells seq_printf(m, ",uid=%u", 7753ab7947aSDavid Howells from_kuid_munged(&init_user_ns, opts->uid)); 7763ab7947aSDavid Howells if (!gid_eq(opts->gid, GLOBAL_ROOT_GID)) 7773ab7947aSDavid Howells seq_printf(m, ",gid=%u", 7783ab7947aSDavid Howells from_kgid_munged(&init_user_ns, opts->gid)); 7793ab7947aSDavid Howells if (opts->iocharset) 7803ab7947aSDavid Howells seq_printf(m, ",charset=%s", opts->iocharset); 7813ab7947aSDavid Howells if (opts->debug) 7823ab7947aSDavid Howells seq_puts(m, ",debug"); 7833ab7947aSDavid Howells return 0; 7843ab7947aSDavid Howells } 7853ab7947aSDavid Howells 7861da177e4SLinus Torvalds /* This function has the responsibiltiy of getting the 7871da177e4SLinus Torvalds * filesystem ready for unmounting. 78825985edcSLucas De Marchi * Basically, we free everything that we allocated in 7891da177e4SLinus Torvalds * befs_read_inode 7901da177e4SLinus Torvalds */ 7911da177e4SLinus Torvalds static void 7921da177e4SLinus Torvalds befs_put_super(struct super_block *sb) 7931da177e4SLinus Torvalds { 7941da177e4SLinus Torvalds kfree(BEFS_SB(sb)->mount_opts.iocharset); 7951da177e4SLinus Torvalds BEFS_SB(sb)->mount_opts.iocharset = NULL; 7961da177e4SLinus Torvalds unload_nls(BEFS_SB(sb)->nls); 7971da177e4SLinus Torvalds kfree(sb->s_fs_info); 7981da177e4SLinus Torvalds sb->s_fs_info = NULL; 7991da177e4SLinus Torvalds } 8001da177e4SLinus Torvalds 8011da177e4SLinus Torvalds /* Allocate private field of the superblock, fill it. 8021da177e4SLinus Torvalds * 8031da177e4SLinus Torvalds * Finish filling the public superblock fields 8041da177e4SLinus Torvalds * Make the root directory 8051da177e4SLinus Torvalds * Load a set of NLS translations if needed. 8061da177e4SLinus Torvalds */ 8071da177e4SLinus Torvalds static int 8081da177e4SLinus Torvalds befs_fill_super(struct super_block *sb, void *data, int silent) 8091da177e4SLinus Torvalds { 8101da177e4SLinus Torvalds struct buffer_head *bh; 811038428fcSFabian Frederick struct befs_sb_info *befs_sb; 8121da177e4SLinus Torvalds befs_super_block *disk_sb; 8131da177e4SLinus Torvalds struct inode *root; 81496eb5419SDavid Howells long ret = -EINVAL; 8151da177e4SLinus Torvalds const unsigned long sb_block = 0; 8161da177e4SLinus Torvalds const off_t x86_sb_off = 512; 817173b066fSLuis de Bethencourt int blocksize; 8181da177e4SLinus Torvalds 8192d4319efSFabian Frederick sb->s_fs_info = kzalloc(sizeof(*befs_sb), GFP_KERNEL); 820c625426fSSalah Triki if (sb->s_fs_info == NULL) 8210418726bSAdrian Bunk goto unacquire_none; 822c625426fSSalah Triki 8231da177e4SLinus Torvalds befs_sb = BEFS_SB(sb); 8241da177e4SLinus Torvalds 8251da177e4SLinus Torvalds if (!parse_options((char *) data, &befs_sb->mount_opts)) { 826dceee2e2SSalah Triki if (!silent) 8271da177e4SLinus Torvalds befs_error(sb, "cannot parse mount options"); 8280418726bSAdrian Bunk goto unacquire_priv_sbp; 8291da177e4SLinus Torvalds } 8301da177e4SLinus Torvalds 831dac52fc1SFabian Frederick befs_debug(sb, "---> %s", __func__); 8321da177e4SLinus Torvalds 833bc98a42cSDavid Howells if (!sb_rdonly(sb)) { 8341da177e4SLinus Torvalds befs_warning(sb, 8351da177e4SLinus Torvalds "No write support. Marking filesystem read-only"); 8361751e8a6SLinus Torvalds sb->s_flags |= SB_RDONLY; 8371da177e4SLinus Torvalds } 8381da177e4SLinus Torvalds 8391da177e4SLinus Torvalds /* 8401da177e4SLinus Torvalds * Set dummy blocksize to read super block. 8411da177e4SLinus Torvalds * Will be set to real fs blocksize later. 8421da177e4SLinus Torvalds * 8431da177e4SLinus Torvalds * Linux 2.4.10 and later refuse to read blocks smaller than 844a441b0d0SLinus Walleij * the logical block size for the device. But we also need to read at 8451da177e4SLinus Torvalds * least 1k to get the second 512 bytes of the volume. 8461da177e4SLinus Torvalds */ 847173b066fSLuis de Bethencourt blocksize = sb_min_blocksize(sb, 1024); 848173b066fSLuis de Bethencourt if (!blocksize) { 849a6499850SLuis de Bethencourt if (!silent) 850173b066fSLuis de Bethencourt befs_error(sb, "unable to set blocksize"); 851173b066fSLuis de Bethencourt goto unacquire_priv_sbp; 852173b066fSLuis de Bethencourt } 8531da177e4SLinus Torvalds 85462b80719SLuis de Bethencourt bh = sb_bread(sb, sb_block); 85562b80719SLuis de Bethencourt if (!bh) { 856dceee2e2SSalah Triki if (!silent) 8571da177e4SLinus Torvalds befs_error(sb, "unable to read superblock"); 8580418726bSAdrian Bunk goto unacquire_priv_sbp; 8591da177e4SLinus Torvalds } 8601da177e4SLinus Torvalds 8611da177e4SLinus Torvalds /* account for offset of super block on x86 */ 8621da177e4SLinus Torvalds disk_sb = (befs_super_block *) bh->b_data; 863152b95a1SHarvey Harrison if ((disk_sb->magic1 == BEFS_SUPER_MAGIC1_LE) || 864152b95a1SHarvey Harrison (disk_sb->magic1 == BEFS_SUPER_MAGIC1_BE)) { 8651da177e4SLinus Torvalds befs_debug(sb, "Using PPC superblock location"); 8661da177e4SLinus Torvalds } else { 8671da177e4SLinus Torvalds befs_debug(sb, "Using x86 superblock location"); 8681da177e4SLinus Torvalds disk_sb = 8691da177e4SLinus Torvalds (befs_super_block *) ((void *) bh->b_data + x86_sb_off); 8701da177e4SLinus Torvalds } 8711da177e4SLinus Torvalds 8728e19189eSFabian Frederick if ((befs_load_sb(sb, disk_sb) != BEFS_OK) || 8738e19189eSFabian Frederick (befs_check_sb(sb) != BEFS_OK)) 8740418726bSAdrian Bunk goto unacquire_bh; 8751da177e4SLinus Torvalds 8761da177e4SLinus Torvalds befs_dump_super_block(sb, disk_sb); 8771da177e4SLinus Torvalds 8781da177e4SLinus Torvalds brelse(bh); 8791da177e4SLinus Torvalds 8801da177e4SLinus Torvalds if (befs_sb->num_blocks > ~((sector_t)0)) { 881dceee2e2SSalah Triki if (!silent) 882dceee2e2SSalah Triki befs_error(sb, "blocks count: %llu is larger than the host can use", 8831da177e4SLinus Torvalds befs_sb->num_blocks); 8840418726bSAdrian Bunk goto unacquire_priv_sbp; 8851da177e4SLinus Torvalds } 8861da177e4SLinus Torvalds 8871da177e4SLinus Torvalds /* 8881da177e4SLinus Torvalds * set up enough so that it can read an inode 8891da177e4SLinus Torvalds * Fill in kernel superblock fields from private sb 8901da177e4SLinus Torvalds */ 8911da177e4SLinus Torvalds sb->s_magic = BEFS_SUPER_MAGIC; 8921da177e4SLinus Torvalds /* Set real blocksize of fs */ 8931da177e4SLinus Torvalds sb_set_blocksize(sb, (ulong) befs_sb->block_size); 894b87221deSAlexey Dobriyan sb->s_op = &befs_sops; 895ac632f5bSLuis de Bethencourt sb->s_export_op = &befs_export_operations; 89622b13969SDeepa Dinamani sb->s_time_min = 0; 89722b13969SDeepa Dinamani sb->s_time_max = 0xffffffffffffll; 89896eb5419SDavid Howells root = befs_iget(sb, iaddr2blockno(sb, &(befs_sb->root_dir))); 89996eb5419SDavid Howells if (IS_ERR(root)) { 90096eb5419SDavid Howells ret = PTR_ERR(root); 90196eb5419SDavid Howells goto unacquire_priv_sbp; 90296eb5419SDavid Howells } 90348fde701SAl Viro sb->s_root = d_make_root(root); 9041da177e4SLinus Torvalds if (!sb->s_root) { 905dceee2e2SSalah Triki if (!silent) 9061da177e4SLinus Torvalds befs_error(sb, "get root inode failed"); 9070418726bSAdrian Bunk goto unacquire_priv_sbp; 9081da177e4SLinus Torvalds } 9091da177e4SLinus Torvalds 9101da177e4SLinus Torvalds /* load nls library */ 9111da177e4SLinus Torvalds if (befs_sb->mount_opts.iocharset) { 9121da177e4SLinus Torvalds befs_debug(sb, "Loading nls: %s", 9131da177e4SLinus Torvalds befs_sb->mount_opts.iocharset); 9141da177e4SLinus Torvalds befs_sb->nls = load_nls(befs_sb->mount_opts.iocharset); 9151da177e4SLinus Torvalds if (!befs_sb->nls) { 9161da177e4SLinus Torvalds befs_warning(sb, "Cannot load nls %s" 9171da177e4SLinus Torvalds " loading default nls", 9181da177e4SLinus Torvalds befs_sb->mount_opts.iocharset); 9191da177e4SLinus Torvalds befs_sb->nls = load_nls_default(); 9201da177e4SLinus Torvalds } 9211da177e4SLinus Torvalds /* load default nls if none is specified in mount options */ 9221da177e4SLinus Torvalds } else { 9231da177e4SLinus Torvalds befs_debug(sb, "Loading default nls"); 9241da177e4SLinus Torvalds befs_sb->nls = load_nls_default(); 9251da177e4SLinus Torvalds } 9261da177e4SLinus Torvalds 9271da177e4SLinus Torvalds return 0; 92862b80719SLuis de Bethencourt 9290418726bSAdrian Bunk unacquire_bh: 9301da177e4SLinus Torvalds brelse(bh); 9311da177e4SLinus Torvalds 9320418726bSAdrian Bunk unacquire_priv_sbp: 9338dd5ca53SAl Viro kfree(befs_sb->mount_opts.iocharset); 9341da177e4SLinus Torvalds kfree(sb->s_fs_info); 93530982583SSalah Triki sb->s_fs_info = NULL; 9361da177e4SLinus Torvalds 9370418726bSAdrian Bunk unacquire_none: 93896eb5419SDavid Howells return ret; 9391da177e4SLinus Torvalds } 9401da177e4SLinus Torvalds 9411da177e4SLinus Torvalds static int 9421da177e4SLinus Torvalds befs_remount(struct super_block *sb, int *flags, char *data) 9431da177e4SLinus Torvalds { 94402b9984dSTheodore Ts'o sync_filesystem(sb); 9451751e8a6SLinus Torvalds if (!(*flags & SB_RDONLY)) 9461da177e4SLinus Torvalds return -EINVAL; 9471da177e4SLinus Torvalds return 0; 9481da177e4SLinus Torvalds } 9491da177e4SLinus Torvalds 9501da177e4SLinus Torvalds static int 951726c3342SDavid Howells befs_statfs(struct dentry *dentry, struct kstatfs *buf) 9521da177e4SLinus Torvalds { 953726c3342SDavid Howells struct super_block *sb = dentry->d_sb; 9548587246aSColy Li u64 id = huge_encode_dev(sb->s_bdev->bd_dev); 9551da177e4SLinus Torvalds 956dac52fc1SFabian Frederick befs_debug(sb, "---> %s", __func__); 9571da177e4SLinus Torvalds 9581da177e4SLinus Torvalds buf->f_type = BEFS_SUPER_MAGIC; 9591da177e4SLinus Torvalds buf->f_bsize = sb->s_blocksize; 9601da177e4SLinus Torvalds buf->f_blocks = BEFS_SB(sb)->num_blocks; 9611da177e4SLinus Torvalds buf->f_bfree = BEFS_SB(sb)->num_blocks - BEFS_SB(sb)->used_blocks; 9621da177e4SLinus Torvalds buf->f_bavail = buf->f_bfree; 9631da177e4SLinus Torvalds buf->f_files = 0; /* UNKNOWN */ 9641da177e4SLinus Torvalds buf->f_ffree = 0; /* UNKNOWN */ 9656d1349c7SAl Viro buf->f_fsid = u64_to_fsid(id); 9661da177e4SLinus Torvalds buf->f_namelen = BEFS_NAME_LEN; 9671da177e4SLinus Torvalds 968dac52fc1SFabian Frederick befs_debug(sb, "<--- %s", __func__); 9691da177e4SLinus Torvalds 9701da177e4SLinus Torvalds return 0; 9711da177e4SLinus Torvalds } 9721da177e4SLinus Torvalds 973152a0836SAl Viro static struct dentry * 974152a0836SAl Viro befs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, 975152a0836SAl Viro void *data) 9761da177e4SLinus Torvalds { 977152a0836SAl Viro return mount_bdev(fs_type, flags, dev_name, data, befs_fill_super); 9781da177e4SLinus Torvalds } 9791da177e4SLinus Torvalds 9801da177e4SLinus Torvalds static struct file_system_type befs_fs_type = { 9811da177e4SLinus Torvalds .owner = THIS_MODULE, 9821da177e4SLinus Torvalds .name = "befs", 983152a0836SAl Viro .mount = befs_mount, 9841da177e4SLinus Torvalds .kill_sb = kill_block_super, 9851da177e4SLinus Torvalds .fs_flags = FS_REQUIRES_DEV, 9861da177e4SLinus Torvalds }; 9877f78e035SEric W. Biederman MODULE_ALIAS_FS("befs"); 9881da177e4SLinus Torvalds 9891da177e4SLinus Torvalds static int __init 9901da177e4SLinus Torvalds init_befs_fs(void) 9911da177e4SLinus Torvalds { 9921da177e4SLinus Torvalds int err; 9931da177e4SLinus Torvalds 994dac52fc1SFabian Frederick pr_info("version: %s\n", BEFS_VERSION); 9951da177e4SLinus Torvalds 9961da177e4SLinus Torvalds err = befs_init_inodecache(); 9971da177e4SLinus Torvalds if (err) 9980418726bSAdrian Bunk goto unacquire_none; 9991da177e4SLinus Torvalds 10001da177e4SLinus Torvalds err = register_filesystem(&befs_fs_type); 10011da177e4SLinus Torvalds if (err) 10020418726bSAdrian Bunk goto unacquire_inodecache; 10031da177e4SLinus Torvalds 10041da177e4SLinus Torvalds return 0; 10051da177e4SLinus Torvalds 10060418726bSAdrian Bunk unacquire_inodecache: 10071da177e4SLinus Torvalds befs_destroy_inodecache(); 10081da177e4SLinus Torvalds 10090418726bSAdrian Bunk unacquire_none: 10101da177e4SLinus Torvalds return err; 10111da177e4SLinus Torvalds } 10121da177e4SLinus Torvalds 10131da177e4SLinus Torvalds static void __exit 10141da177e4SLinus Torvalds exit_befs_fs(void) 10151da177e4SLinus Torvalds { 10161da177e4SLinus Torvalds befs_destroy_inodecache(); 10171da177e4SLinus Torvalds 10181da177e4SLinus Torvalds unregister_filesystem(&befs_fs_type); 10191da177e4SLinus Torvalds } 10201da177e4SLinus Torvalds 10211da177e4SLinus Torvalds /* 102262b80719SLuis de Bethencourt * Macros that typecheck the init and exit functions, 102362b80719SLuis de Bethencourt * ensures that they are called at init and cleanup, 102462b80719SLuis de Bethencourt * and eliminates warnings about unused functions. 10251da177e4SLinus Torvalds */ 10261da177e4SLinus Torvalds module_init(init_befs_fs) 10271da177e4SLinus Torvalds module_exit(exit_befs_fs) 1028