brintos

brintos / linux-shallow public Read only

0
0
Text · 10.9 KiB · e8c2c45 Raw
328 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2#ifdef pr_fmt3#undef pr_fmt4#endif5 6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt7 8#include <linux/types.h>9#include <linux/fs.h>10#include <linux/buffer_head.h>11#include "amigaffs.h"12#include <linux/mutex.h>13#include <linux/workqueue.h>14 15/* Ugly macros make the code more pretty. */16 17#define AFFS_BLOCK(sb, bh, blk)		(AFFS_HEAD(bh)->table[AFFS_SB(sb)->s_hashsize-1-(blk)])18 19#define AFFS_HEAD(bh)		((struct affs_head *)(bh)->b_data)20#define AFFS_TAIL(sb, bh)	((struct affs_tail *)((bh)->b_data+(sb)->s_blocksize-sizeof(struct affs_tail)))21#define AFFS_ROOT_HEAD(bh)	((struct affs_root_head *)(bh)->b_data)22#define AFFS_ROOT_TAIL(sb, bh)	((struct affs_root_tail *)((bh)->b_data+(sb)->s_blocksize-sizeof(struct affs_root_tail)))23#define AFFS_DATA_HEAD(bh)	((struct affs_data_head *)(bh)->b_data)24#define AFFS_DATA(bh)		(((struct affs_data_head *)(bh)->b_data)->data)25 26#define AFFS_CACHE_SIZE		PAGE_SIZE27 28#define AFFS_LC_SIZE		(AFFS_CACHE_SIZE/sizeof(u32)/2)29#define AFFS_AC_SIZE		(AFFS_CACHE_SIZE/sizeof(struct affs_ext_key)/2)30#define AFFS_AC_MASK		(AFFS_AC_SIZE-1)31 32#define AFFSNAMEMAX 30U33 34struct affs_ext_key {35	u32	ext;				/* idx of the extended block */36	u32	key;				/* block number */37};38 39/*40 * affs fs inode data in memory41 */42struct affs_inode_info {43	atomic_t i_opencnt;44	struct mutex i_link_lock;		/* Protects internal inode access. */45	struct mutex i_ext_lock;		/* Protects internal inode access. */46#define i_hash_lock i_ext_lock47	u32	 i_blkcnt;			/* block count */48	u32	 i_extcnt;			/* extended block count */49	u32	*i_lc;				/* linear cache of extended blocks */50	u32	 i_lc_size;51	u32	 i_lc_shift;52	u32	 i_lc_mask;53	struct affs_ext_key *i_ac;		/* associative cache of extended blocks */54	u32	 i_ext_last;			/* last accessed extended block */55	struct buffer_head *i_ext_bh;		/* bh of last extended block */56	loff_t	 mmu_private;57	u32	 i_protect;			/* unused attribute bits */58	u32	 i_lastalloc;			/* last allocated block */59	int	 i_pa_cnt;			/* number of preallocated blocks */60	struct inode vfs_inode;61};62 63/* short cut to get to the affs specific inode data */64static inline struct affs_inode_info *AFFS_I(struct inode *inode)65{66	return container_of(inode, struct affs_inode_info, vfs_inode);67}68 69/*70 * super-block data in memory71 *72 * Block numbers are adjusted for their actual size73 *74 */75 76struct affs_bm_info {77	u32 bm_key;			/* Disk block number */78	u32 bm_free;			/* Free blocks in here */79};80 81struct affs_sb_info {82	int s_partition_size;		/* Partition size in blocks. */83	int s_reserved;			/* Number of reserved blocks. */84	//u32 s_blksize;			/* Initial device blksize */85	u32 s_data_blksize;		/* size of the data block w/o header */86	u32 s_root_block;		/* FFS root block number. */87	int s_hashsize;			/* Size of hash table. */88	unsigned long s_flags;		/* See below. */89	kuid_t s_uid;			/* uid to override */90	kgid_t s_gid;			/* gid to override */91	umode_t s_mode;			/* mode to override */92	struct buffer_head *s_root_bh;	/* Cached root block. */93	struct mutex s_bmlock;		/* Protects bitmap access. */94	struct affs_bm_info *s_bitmap;	/* Bitmap infos. */95	u32 s_bmap_count;		/* # of bitmap blocks. */96	u32 s_bmap_bits;		/* # of bits in one bitmap blocks */97	u32 s_last_bmap;98	struct buffer_head *s_bmap_bh;99	char *s_prefix;			/* Prefix for volumes and assigns. */100	char s_volume[32];		/* Volume prefix for absolute symlinks. */101	spinlock_t symlink_lock;	/* protects the previous two */102	struct super_block *sb;		/* the VFS superblock object */103	int work_queued;		/* non-zero delayed work is queued */104	struct delayed_work sb_work;	/* superblock flush delayed work */105	spinlock_t work_lock;		/* protects sb_work and work_queued */106	struct rcu_head rcu;107};108 109#define AFFS_MOUNT_SF_INTL		0x0001 /* International filesystem. */110#define AFFS_MOUNT_SF_BM_VALID		0x0002 /* Bitmap is valid. */111#define AFFS_MOUNT_SF_IMMUTABLE		0x0004 /* Protection bits cannot be changed */112#define AFFS_MOUNT_SF_QUIET		0x0008 /* chmod errors will be not reported */113#define AFFS_MOUNT_SF_SETUID		0x0010 /* Ignore Amiga uid */114#define AFFS_MOUNT_SF_SETGID		0x0020 /* Ignore Amiga gid */115#define AFFS_MOUNT_SF_SETMODE		0x0040 /* Ignore Amiga protection bits */116#define AFFS_MOUNT_SF_MUFS		0x0100 /* Use MUFS uid/gid mapping */117#define AFFS_MOUNT_SF_OFS		0x0200 /* Old filesystem */118#define AFFS_MOUNT_SF_PREFIX		0x0400 /* Buffer for prefix is allocated */119#define AFFS_MOUNT_SF_VERBOSE		0x0800 /* Talk about fs when mounting */120#define AFFS_MOUNT_SF_NO_TRUNCATE	0x1000 /* Don't truncate filenames */121 122#define affs_clear_opt(o, opt)    (o &= ~AFFS_MOUNT_##opt)123#define affs_set_opt(o, opt)      (o |= AFFS_MOUNT_##opt)124#define affs_test_opt(o, opt)     ((o) & AFFS_MOUNT_##opt)125 126/* short cut to get to the affs specific sb data */127static inline struct affs_sb_info *AFFS_SB(struct super_block *sb)128{129	return sb->s_fs_info;130}131 132void affs_mark_sb_dirty(struct super_block *sb);133 134/* amigaffs.c */135 136extern int	affs_insert_hash(struct inode *inode, struct buffer_head *bh);137extern int	affs_remove_hash(struct inode *dir, struct buffer_head *rem_bh);138extern int	affs_remove_header(struct dentry *dentry);139extern u32	affs_checksum_block(struct super_block *sb, struct buffer_head *bh);140extern void	affs_fix_checksum(struct super_block *sb, struct buffer_head *bh);141extern void	affs_secs_to_datestamp(time64_t secs, struct affs_date *ds);142extern umode_t	affs_prot_to_mode(u32 prot);143extern void	affs_mode_to_prot(struct inode *inode);144__printf(3, 4)145extern void	affs_error(struct super_block *sb, const char *function,146			   const char *fmt, ...);147__printf(3, 4)148extern void	affs_warning(struct super_block *sb, const char *function,149			     const char *fmt, ...);150extern bool	affs_nofilenametruncate(const struct dentry *dentry);151extern int	affs_check_name(const unsigned char *name, int len,152				bool notruncate);153extern int	affs_copy_name(unsigned char *bstr, struct dentry *dentry);154 155/* bitmap. c */156 157extern u32	affs_count_free_blocks(struct super_block *s);158extern void	affs_free_block(struct super_block *sb, u32 block);159extern u32	affs_alloc_block(struct inode *inode, u32 goal);160extern int	affs_init_bitmap(struct super_block *sb, int *flags);161extern void	affs_free_bitmap(struct super_block *sb);162 163/* namei.c */164 165extern const struct export_operations affs_export_ops;166extern int	affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len);167extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int);168extern int	affs_unlink(struct inode *dir, struct dentry *dentry);169extern int	affs_create(struct mnt_idmap *idmap, struct inode *dir,170			struct dentry *dentry, umode_t mode, bool);171extern int	affs_mkdir(struct mnt_idmap *idmap, struct inode *dir,172			struct dentry *dentry, umode_t mode);173extern int	affs_rmdir(struct inode *dir, struct dentry *dentry);174extern int	affs_link(struct dentry *olddentry, struct inode *dir,175			  struct dentry *dentry);176extern int	affs_symlink(struct mnt_idmap *idmap,177			struct inode *dir, struct dentry *dentry,178			const char *symname);179extern int	affs_rename2(struct mnt_idmap *idmap,180			struct inode *old_dir, struct dentry *old_dentry,181			struct inode *new_dir, struct dentry *new_dentry,182			unsigned int flags);183 184/* inode.c */185 186extern struct inode		*affs_new_inode(struct inode *dir);187extern int			 affs_notify_change(struct mnt_idmap *idmap,188					struct dentry *dentry, struct iattr *attr);189extern void			 affs_evict_inode(struct inode *inode);190extern struct inode		*affs_iget(struct super_block *sb,191					unsigned long ino);192extern int			 affs_write_inode(struct inode *inode,193					struct writeback_control *wbc);194extern int			 affs_add_entry(struct inode *dir, struct inode *inode,195					struct dentry *dentry, s32 type);196 197/* file.c */198 199void		affs_free_prealloc(struct inode *inode);200extern void	affs_truncate(struct inode *);201int		affs_file_fsync(struct file *, loff_t, loff_t, int);202 203/* dir.c */204 205extern void   affs_dir_truncate(struct inode *);206 207/* jump tables */208 209extern const struct inode_operations	 affs_file_inode_operations;210extern const struct inode_operations	 affs_dir_inode_operations;211extern const struct inode_operations   affs_symlink_inode_operations;212extern const struct file_operations	 affs_file_operations;213extern const struct file_operations	 affs_file_operations_ofs;214extern const struct file_operations	 affs_dir_operations;215extern const struct address_space_operations	 affs_symlink_aops;216extern const struct address_space_operations	 affs_aops;217extern const struct address_space_operations	 affs_aops_ofs;218 219extern const struct dentry_operations	 affs_dentry_operations;220extern const struct dentry_operations	 affs_intl_dentry_operations;221 222static inline bool affs_validblock(struct super_block *sb, int block)223{224	return(block >= AFFS_SB(sb)->s_reserved &&225	       block < AFFS_SB(sb)->s_partition_size);226}227 228static inline void229affs_set_blocksize(struct super_block *sb, int size)230{231	sb_set_blocksize(sb, size);232}233static inline struct buffer_head *234affs_bread(struct super_block *sb, int block)235{236	pr_debug("%s: %d\n", __func__, block);237	if (affs_validblock(sb, block))238		return sb_bread(sb, block);239	return NULL;240}241static inline struct buffer_head *242affs_getblk(struct super_block *sb, int block)243{244	pr_debug("%s: %d\n", __func__, block);245	if (affs_validblock(sb, block))246		return sb_getblk(sb, block);247	return NULL;248}249static inline struct buffer_head *250affs_getzeroblk(struct super_block *sb, int block)251{252	struct buffer_head *bh;253	pr_debug("%s: %d\n", __func__, block);254	if (affs_validblock(sb, block)) {255		bh = sb_getblk(sb, block);256		lock_buffer(bh);257		memset(bh->b_data, 0 , sb->s_blocksize);258		set_buffer_uptodate(bh);259		unlock_buffer(bh);260		return bh;261	}262	return NULL;263}264static inline struct buffer_head *265affs_getemptyblk(struct super_block *sb, int block)266{267	struct buffer_head *bh;268	pr_debug("%s: %d\n", __func__, block);269	if (affs_validblock(sb, block)) {270		bh = sb_getblk(sb, block);271		wait_on_buffer(bh);272		set_buffer_uptodate(bh);273		return bh;274	}275	return NULL;276}277static inline void278affs_brelse(struct buffer_head *bh)279{280	if (bh)281		pr_debug("%s: %lld\n", __func__, (long long) bh->b_blocknr);282	brelse(bh);283}284 285static inline void286affs_adjust_checksum(struct buffer_head *bh, u32 val)287{288	u32 tmp = be32_to_cpu(((__be32 *)bh->b_data)[5]);289	((__be32 *)bh->b_data)[5] = cpu_to_be32(tmp - val);290}291static inline void292affs_adjust_bitmapchecksum(struct buffer_head *bh, u32 val)293{294	u32 tmp = be32_to_cpu(((__be32 *)bh->b_data)[0]);295	((__be32 *)bh->b_data)[0] = cpu_to_be32(tmp - val);296}297 298static inline void299affs_lock_link(struct inode *inode)300{301	mutex_lock(&AFFS_I(inode)->i_link_lock);302}303static inline void304affs_unlock_link(struct inode *inode)305{306	mutex_unlock(&AFFS_I(inode)->i_link_lock);307}308static inline void309affs_lock_dir(struct inode *inode)310{311	mutex_lock_nested(&AFFS_I(inode)->i_hash_lock, SINGLE_DEPTH_NESTING);312}313static inline void314affs_unlock_dir(struct inode *inode)315{316	mutex_unlock(&AFFS_I(inode)->i_hash_lock);317}318static inline void319affs_lock_ext(struct inode *inode)320{321	mutex_lock(&AFFS_I(inode)->i_ext_lock);322}323static inline void324affs_unlock_ext(struct inode *inode)325{326	mutex_unlock(&AFFS_I(inode)->i_ext_lock);327}328