brintos

brintos / linux-shallow public Read only

0
0
Text · 10.9 KiB · e399e2d Raw
436 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * QNX4 file system, Linux implementation.4 *5 * Version : 0.2.16 *7 * Using parts of the xiafs filesystem.8 *9 * History :10 *11 * 01-06-1998 by Richard Frowijn : first release.12 * 20-06-1998 by Frank Denis : Linux 2.1.99+ support, boot signature, misc.13 * 30-06-1998 by Frank Denis : first step to write inodes.14 */15 16#include <linux/module.h>17#include <linux/init.h>18#include <linux/slab.h>19#include <linux/highuid.h>20#include <linux/pagemap.h>21#include <linux/buffer_head.h>22#include <linux/writeback.h>23#include <linux/statfs.h>24#include <linux/fs_context.h>25#include "qnx4.h"26 27#define QNX4_VERSION  428#define QNX4_BMNAME   ".bitmap"29 30static const struct super_operations qnx4_sops;31 32static struct inode *qnx4_alloc_inode(struct super_block *sb);33static void qnx4_free_inode(struct inode *inode);34static int qnx4_statfs(struct dentry *, struct kstatfs *);35static int qnx4_get_tree(struct fs_context *fc);36 37static const struct super_operations qnx4_sops =38{39	.alloc_inode	= qnx4_alloc_inode,40	.free_inode	= qnx4_free_inode,41	.statfs		= qnx4_statfs,42};43 44static int qnx4_reconfigure(struct fs_context *fc)45{46	struct super_block *sb = fc->root->d_sb;47	struct qnx4_sb_info *qs;48 49	sync_filesystem(sb);50	qs = qnx4_sb(sb);51	qs->Version = QNX4_VERSION;52	fc->sb_flags |= SB_RDONLY;53	return 0;54}55 56static const struct fs_context_operations qnx4_context_opts = {57	.get_tree	= qnx4_get_tree,58	.reconfigure	= qnx4_reconfigure,59};60 61static int qnx4_get_block( struct inode *inode, sector_t iblock, struct buffer_head *bh, int create )62{63	unsigned long phys;64 65	QNX4DEBUG((KERN_INFO "qnx4: qnx4_get_block inode=[%ld] iblock=[%ld]\n",inode->i_ino,iblock));66 67	phys = qnx4_block_map( inode, iblock );68	if ( phys ) {69		// logical block is before EOF70		map_bh(bh, inode->i_sb, phys);71	}72	return 0;73}74 75static inline u32 try_extent(qnx4_xtnt_t *extent, u32 *offset)76{77	u32 size = le32_to_cpu(extent->xtnt_size);78	if (*offset < size)79		return le32_to_cpu(extent->xtnt_blk) + *offset - 1;80	*offset -= size;81	return 0;82}83 84unsigned long qnx4_block_map( struct inode *inode, long iblock )85{86	int ix;87	long i_xblk;88	struct buffer_head *bh = NULL;89	struct qnx4_xblk *xblk = NULL;90	struct qnx4_inode_entry *qnx4_inode = qnx4_raw_inode(inode);91	u16 nxtnt = le16_to_cpu(qnx4_inode->di_num_xtnts);92	u32 offset = iblock;93	u32 block = try_extent(&qnx4_inode->di_first_xtnt, &offset);94 95	if (block) {96		// iblock is in the first extent. This is easy.97	} else {98		// iblock is beyond first extent. We have to follow the extent chain.99		i_xblk = le32_to_cpu(qnx4_inode->di_xblk);100		ix = 0;101		while ( --nxtnt > 0 ) {102			if ( ix == 0 ) {103				// read next xtnt block.104				bh = sb_bread(inode->i_sb, i_xblk - 1);105				if ( !bh ) {106					QNX4DEBUG((KERN_ERR "qnx4: I/O error reading xtnt block [%ld])\n", i_xblk - 1));107					return -EIO;108				}109				xblk = (struct qnx4_xblk*)bh->b_data;110				if ( memcmp( xblk->xblk_signature, "IamXblk", 7 ) ) {111					QNX4DEBUG((KERN_ERR "qnx4: block at %ld is not a valid xtnt\n", qnx4_inode->i_xblk));112					return -EIO;113				}114			}115			block = try_extent(&xblk->xblk_xtnts[ix], &offset);116			if (block) {117				// got it!118				break;119			}120			if ( ++ix >= xblk->xblk_num_xtnts ) {121				i_xblk = le32_to_cpu(xblk->xblk_next_xblk);122				ix = 0;123				brelse( bh );124				bh = NULL;125			}126		}127		if ( bh )128			brelse( bh );129	}130 131	QNX4DEBUG((KERN_INFO "qnx4: mapping block %ld of inode %ld = %ld\n",iblock,inode->i_ino,block));132	return block;133}134 135static int qnx4_statfs(struct dentry *dentry, struct kstatfs *buf)136{137	struct super_block *sb = dentry->d_sb;138	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);139 140	buf->f_type    = sb->s_magic;141	buf->f_bsize   = sb->s_blocksize;142	buf->f_blocks  = le32_to_cpu(qnx4_sb(sb)->BitMap->di_size) * 8;143	buf->f_bfree   = qnx4_count_free_blocks(sb);144	buf->f_bavail  = buf->f_bfree;145	buf->f_namelen = QNX4_NAME_MAX;146	buf->f_fsid    = u64_to_fsid(id);147 148	return 0;149}150 151/*152 * Check the root directory of the filesystem to make sure153 * it really _is_ a qnx4 filesystem, and to check the size154 * of the directory entry.155 */156static const char *qnx4_checkroot(struct super_block *sb,157				  struct qnx4_super_block *s)158{159	struct buffer_head *bh;160	struct qnx4_inode_entry *rootdir;161	int rd, rl;162	int i, j;163 164	if (s->RootDir.di_fname[0] != '/' || s->RootDir.di_fname[1] != '\0')165		return "no qnx4 filesystem (no root dir).";166	QNX4DEBUG((KERN_NOTICE "QNX4 filesystem found on dev %s.\n", sb->s_id));167	rd = le32_to_cpu(s->RootDir.di_first_xtnt.xtnt_blk) - 1;168	rl = le32_to_cpu(s->RootDir.di_first_xtnt.xtnt_size);169	for (j = 0; j < rl; j++) {170		bh = sb_bread(sb, rd + j);	/* root dir, first block */171		if (bh == NULL)172			return "unable to read root entry.";173		rootdir = (struct qnx4_inode_entry *) bh->b_data;174		for (i = 0; i < QNX4_INODES_PER_BLOCK; i++, rootdir++) {175			QNX4DEBUG((KERN_INFO "rootdir entry found : [%s]\n", rootdir->di_fname));176			if (strcmp(rootdir->di_fname, QNX4_BMNAME) != 0)177				continue;178			qnx4_sb(sb)->BitMap = kmemdup(rootdir,179						      sizeof(struct qnx4_inode_entry),180						      GFP_KERNEL);181			brelse(bh);182			if (!qnx4_sb(sb)->BitMap)183				return "not enough memory for bitmap inode";184			/* keep bitmap inode known */185			return NULL;186		}187		brelse(bh);188	}189	return "bitmap file not found.";190}191 192static int qnx4_fill_super(struct super_block *s, struct fs_context *fc)193{194	struct buffer_head *bh;195	struct inode *root;196	const char *errmsg;197	struct qnx4_sb_info *qs;198	int silent = fc->sb_flags & SB_SILENT;199 200	qs = kzalloc(sizeof(struct qnx4_sb_info), GFP_KERNEL);201	if (!qs)202		return -ENOMEM;203	s->s_fs_info = qs;204 205	sb_set_blocksize(s, QNX4_BLOCK_SIZE);206 207	s->s_op = &qnx4_sops;208	s->s_magic = QNX4_SUPER_MAGIC;209	s->s_flags |= SB_RDONLY;	/* Yup, read-only yet */210	s->s_time_min = 0;211	s->s_time_max = U32_MAX;212 213	/* Check the superblock signature. Since the qnx4 code is214	   dangerous, we should leave as quickly as possible215	   if we don't belong here... */216	bh = sb_bread(s, 1);217	if (!bh) {218		printk(KERN_ERR "qnx4: unable to read the superblock\n");219		return -EINVAL;220	}221 222 	/* check before allocating dentries, inodes, .. */223	errmsg = qnx4_checkroot(s, (struct qnx4_super_block *) bh->b_data);224	brelse(bh);225	if (errmsg != NULL) {226		if (!silent)227			printk(KERN_ERR "qnx4: %s\n", errmsg);228		return -EINVAL;229	}230 231 	/* does root not have inode number QNX4_ROOT_INO ?? */232	root = qnx4_iget(s, QNX4_ROOT_INO * QNX4_INODES_PER_BLOCK);233	if (IS_ERR(root)) {234		printk(KERN_ERR "qnx4: get inode failed\n");235		return PTR_ERR(root);236 	}237 238 	s->s_root = d_make_root(root);239 	if (s->s_root == NULL)240 		return -ENOMEM;241 242	return 0;243}244 245static int qnx4_get_tree(struct fs_context *fc)246{247	return get_tree_bdev(fc, qnx4_fill_super);248}249 250static int qnx4_init_fs_context(struct fs_context *fc)251{252	fc->ops = &qnx4_context_opts;253 254	return 0;255}256 257static void qnx4_kill_sb(struct super_block *sb)258{259	struct qnx4_sb_info *qs = qnx4_sb(sb);260	kill_block_super(sb);261	if (qs) {262		kfree(qs->BitMap);263		kfree(qs);264	}265}266 267static int qnx4_read_folio(struct file *file, struct folio *folio)268{269	return block_read_full_folio(folio, qnx4_get_block);270}271 272static sector_t qnx4_bmap(struct address_space *mapping, sector_t block)273{274	return generic_block_bmap(mapping,block,qnx4_get_block);275}276 277static const struct address_space_operations qnx4_aops = {278	.read_folio	= qnx4_read_folio,279	.bmap		= qnx4_bmap280};281 282struct inode *qnx4_iget(struct super_block *sb, unsigned long ino)283{284	struct buffer_head *bh;285	struct qnx4_inode_entry *raw_inode;286	int block;287	struct qnx4_inode_entry *qnx4_inode;288	struct inode *inode;289 290	inode = iget_locked(sb, ino);291	if (!inode)292		return ERR_PTR(-ENOMEM);293	if (!(inode->i_state & I_NEW))294		return inode;295 296	qnx4_inode = qnx4_raw_inode(inode);297	inode->i_mode = 0;298 299	QNX4DEBUG((KERN_INFO "reading inode : [%d]\n", ino));300	if (!ino) {301		printk(KERN_ERR "qnx4: bad inode number on dev %s: %lu is "302				"out of range\n",303		       sb->s_id, ino);304		iget_failed(inode);305		return ERR_PTR(-EIO);306	}307	block = ino / QNX4_INODES_PER_BLOCK;308 309	if (!(bh = sb_bread(sb, block))) {310		printk(KERN_ERR "qnx4: major problem: unable to read inode from dev "311		       "%s\n", sb->s_id);312		iget_failed(inode);313		return ERR_PTR(-EIO);314	}315	raw_inode = ((struct qnx4_inode_entry *) bh->b_data) +316	    (ino % QNX4_INODES_PER_BLOCK);317 318	inode->i_mode    = le16_to_cpu(raw_inode->di_mode);319	i_uid_write(inode, (uid_t)le16_to_cpu(raw_inode->di_uid));320	i_gid_write(inode, (gid_t)le16_to_cpu(raw_inode->di_gid));321	set_nlink(inode, le16_to_cpu(raw_inode->di_nlink));322	inode->i_size    = le32_to_cpu(raw_inode->di_size);323	inode_set_mtime(inode, le32_to_cpu(raw_inode->di_mtime), 0);324	inode_set_atime(inode, le32_to_cpu(raw_inode->di_atime), 0);325	inode_set_ctime(inode, le32_to_cpu(raw_inode->di_ctime), 0);326	inode->i_blocks  = le32_to_cpu(raw_inode->di_first_xtnt.xtnt_size);327 328	memcpy(qnx4_inode, raw_inode, QNX4_DIR_ENTRY_SIZE);329	if (S_ISREG(inode->i_mode)) {330		inode->i_fop = &generic_ro_fops;331		inode->i_mapping->a_ops = &qnx4_aops;332		qnx4_i(inode)->mmu_private = inode->i_size;333	} else if (S_ISDIR(inode->i_mode)) {334		inode->i_op = &qnx4_dir_inode_operations;335		inode->i_fop = &qnx4_dir_operations;336	} else if (S_ISLNK(inode->i_mode)) {337		inode->i_op = &page_symlink_inode_operations;338		inode_nohighmem(inode);339		inode->i_mapping->a_ops = &qnx4_aops;340		qnx4_i(inode)->mmu_private = inode->i_size;341	} else {342		printk(KERN_ERR "qnx4: bad inode %lu on dev %s\n",343			ino, sb->s_id);344		iget_failed(inode);345		brelse(bh);346		return ERR_PTR(-EIO);347	}348	brelse(bh);349	unlock_new_inode(inode);350	return inode;351}352 353static struct kmem_cache *qnx4_inode_cachep;354 355static struct inode *qnx4_alloc_inode(struct super_block *sb)356{357	struct qnx4_inode_info *ei;358	ei = alloc_inode_sb(sb, qnx4_inode_cachep, GFP_KERNEL);359	if (!ei)360		return NULL;361	return &ei->vfs_inode;362}363 364static void qnx4_free_inode(struct inode *inode)365{366	kmem_cache_free(qnx4_inode_cachep, qnx4_i(inode));367}368 369static void init_once(void *foo)370{371	struct qnx4_inode_info *ei = (struct qnx4_inode_info *) foo;372 373	inode_init_once(&ei->vfs_inode);374}375 376static int init_inodecache(void)377{378	qnx4_inode_cachep = kmem_cache_create("qnx4_inode_cache",379					     sizeof(struct qnx4_inode_info),380					     0, (SLAB_RECLAIM_ACCOUNT|381						SLAB_ACCOUNT),382					     init_once);383	if (qnx4_inode_cachep == NULL)384		return -ENOMEM;385	return 0;386}387 388static void destroy_inodecache(void)389{390	/*391	 * Make sure all delayed rcu free inodes are flushed before we392	 * destroy cache.393	 */394	rcu_barrier();395	kmem_cache_destroy(qnx4_inode_cachep);396}397 398static struct file_system_type qnx4_fs_type = {399	.owner			= THIS_MODULE,400	.name			= "qnx4",401	.kill_sb		= qnx4_kill_sb,402	.fs_flags		= FS_REQUIRES_DEV,403	.init_fs_context	= qnx4_init_fs_context,404};405MODULE_ALIAS_FS("qnx4");406 407static int __init init_qnx4_fs(void)408{409	int err;410 411	err = init_inodecache();412	if (err)413		return err;414 415	err = register_filesystem(&qnx4_fs_type);416	if (err) {417		destroy_inodecache();418		return err;419	}420 421	printk(KERN_INFO "QNX4 filesystem 0.2.3 registered.\n");422	return 0;423}424 425static void __exit exit_qnx4_fs(void)426{427	unregister_filesystem(&qnx4_fs_type);428	destroy_inodecache();429}430 431module_init(init_qnx4_fs)432module_exit(exit_qnx4_fs)433MODULE_DESCRIPTION("QNX4 file system");434MODULE_LICENSE("GPL");435 436