initial commit of the fpgafs
git-svn-id: svn+ssh://en.codiert.org/home/staff/ben/dev/misc.svn/projects/fpgafs@338 766a2236-cff9-0310-b0c0-a81a5f92509a
This commit is contained in:
		
						commit
						9e05e670b4
					
				
							
								
								
									
										6
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | #
 | ||||||
|  | # Makefile for the fpgafs virtual filesystem
 | ||||||
|  | #
 | ||||||
|  | obj-$(CONFIG_FPGA_FS) += fpgafs.o | ||||||
|  | 
 | ||||||
|  | fpgafs-objs :=  inode.o files.o | ||||||
							
								
								
									
										71
									
								
								files.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								files.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,71 @@ | |||||||
|  | #include <linux/fs.h> | ||||||
|  | #include <linux/module.h> | ||||||
|  | #include <linux/version.h> | ||||||
|  | #include <linux/init.h> | ||||||
|  | #include <linux/fs.h> | ||||||
|  | #include <linux/pagemap.h> | ||||||
|  | #include "fpgafs.h" | ||||||
|  | 
 | ||||||
|  | /* generic open function for all pipe-like files */ | ||||||
|  | static int fpgafs_pipe_open(struct inode *inode, struct file *file) | ||||||
|  | { | ||||||
|  | 	struct fpgafs_inode_info *i = FPGAFS_I(inode); | ||||||
|  | 	file->private_data = i->i_ctx; | ||||||
|  | 
 | ||||||
|  |   return nonseekable_open(inode, file); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static ssize_t fpgafs_stat_read(struct file *file, char __user *buf, | ||||||
|  | 	                              size_t len, loff_t *pos) | ||||||
|  | { | ||||||
|  | 	struct fpga_context *ctx = file->private_data; | ||||||
|  | 	u32 data, __user *udata; | ||||||
|  | 	ssize_t count; | ||||||
|  | 
 | ||||||
|  | 	if (len < 4) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 
 | ||||||
|  | 	if (!access_ok(VERIFY_WRITE, buf, len)) | ||||||
|  | 	return -EFAULT; | ||||||
|  | 
 | ||||||
|  | 	udata = (void __user *)buf; | ||||||
|  | 
 | ||||||
|  | 	for (count = 0; (count + 4) <= len; count += 4, udata++) { | ||||||
|  | 		int ret; | ||||||
|  | 
 | ||||||
|  | 		/* operation to read the status ... */ | ||||||
|  | 		data=0x42; | ||||||
|  | 		ret = 0; | ||||||
|  | 		if (ret == 0) | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		ret = __put_user(data, udata); | ||||||
|  | 
 | ||||||
|  | 		if (ret) { | ||||||
|  | 			if (!count) | ||||||
|  | 				count = -EFAULT; | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!count) | ||||||
|  | 		count = -EAGAIN; | ||||||
|  | 
 | ||||||
|  | 	return count; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct file_operations fpgafs_stat_fops = { | ||||||
|  | 	.open = fpgafs_pipe_open, | ||||||
|  | 	.read = fpgafs_stat_read, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct tree_descr fpgafs_dir_contents[] = { | ||||||
|  | #if 0 | ||||||
|  | 	{ "cmd",  &fpgafs_cmd_fops,  0222, }, | ||||||
|  | 	{ "din",  &spufs_mbox_fops, 0222, }, | ||||||
|  | 	{ "dout", &spufs_ibox_fops, 0444, }, | ||||||
|  | 	{ "load", &spufs_wbox_fops, 0666, }, | ||||||
|  | #endif | ||||||
|  | 	{ "stat", &fpgafs_stat_fops, 0444, }, | ||||||
|  | 	{}, | ||||||
|  | }; | ||||||
							
								
								
									
										29
									
								
								fpgafs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								fpgafs.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | |||||||
|  | #ifndef FPGAFS_H | ||||||
|  | #define FPGAFS_H | ||||||
|  | 
 | ||||||
|  | #include <linux/kref.h> | ||||||
|  | #include <linux/mutex.h> | ||||||
|  | #include <linux/spinlock.h> | ||||||
|  | #include <linux/fs.h> | ||||||
|  | 
 | ||||||
|  | /* magic number the file system */ | ||||||
|  | enum { | ||||||
|  |   FPGAFS_MAGIC = 0x4255AA42, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct fpga_context { | ||||||
|  | 	int bla1; | ||||||
|  | 	int bla2; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct fpgafs_inode_info { | ||||||
|  | 	struct fpga_context *i_ctx; | ||||||
|  | 	struct inode vfs_inode; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | extern struct tree_descr fpgafs_dir_contents[]; | ||||||
|  | 
 | ||||||
|  | #define FPGAFS_I(inode) \ | ||||||
|  | 		container_of(inode, struct fpgafs_inode_info, vfs_inode) | ||||||
|  | 
 | ||||||
|  | #endif /* FPGAFS_H */ | ||||||
							
								
								
									
										307
									
								
								inode.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										307
									
								
								inode.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,307 @@ | |||||||
|  | #include <linux/module.h> | ||||||
|  | #include <linux/version.h> | ||||||
|  | #include <linux/init.h> | ||||||
|  | #include <linux/fs.h> | ||||||
|  | #include <linux/pagemap.h> | ||||||
|  | 
 | ||||||
|  | #include "fpgafs.h" | ||||||
|  | 
 | ||||||
|  | static struct inode *fpgafs_alloc_inode(struct super_block *sb); | ||||||
|  | static void fpgafs_destroy_inode(struct inode *inode); | ||||||
|  | static void fpgafs_delete_inode(struct inode *inode); | ||||||
|  | static struct inode *fpgafs_new_inode(struct super_block *sb, int mode); | ||||||
|  | 
 | ||||||
|  | static void fpgafs_prune_dir(struct dentry *dir); | ||||||
|  | int fpgafs_mkdir(struct inode *dir, struct dentry *dentry, int mode); | ||||||
|  | static int fpgafs_rmdir(struct inode *dir, struct dentry *dentry); | ||||||
|  | 
 | ||||||
|  | static int fpgafs_new_file(struct super_block *sb, struct dentry *dentry, | ||||||
|  |                            const struct file_operations *fops, int mode, | ||||||
|  |                            struct fpga_context *ctx); | ||||||
|  | static int fpgafs_setattr(struct dentry *dentry, struct iattr *attr); | ||||||
|  | 
 | ||||||
|  | const struct file_operations fpgafs_context_foperations = { | ||||||
|  | 	.open     = dcache_dir_open, | ||||||
|  | 	//.release  = fpgafs_dir_close,
 | ||||||
|  | 	.llseek   = dcache_dir_lseek, | ||||||
|  | 	.read     = generic_read_dir, | ||||||
|  | 	.readdir  = dcache_readdir, | ||||||
|  | 	.fsync    = simple_sync_file, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const struct inode_operations fpgafs_simple_dir_inode_operations = { | ||||||
|  | 	.lookup = simple_lookup, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const struct inode_operations fpgafs_dir_inode_operations = { | ||||||
|  | 	.lookup = simple_lookup, | ||||||
|  | 	.mkdir  = fpgafs_mkdir, | ||||||
|  | 	.rmdir  = fpgafs_rmdir, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static struct kmem_cache *fpgafs_inode_cache; | ||||||
|  | 
 | ||||||
|  | /* basic inode operations */ | ||||||
|  | static struct inode *fpgafs_alloc_inode(struct super_block *sb) | ||||||
|  | { | ||||||
|  | 	struct fpgafs_inode_info *fsi; | ||||||
|  | 
 | ||||||
|  | 	fsi = kmem_cache_alloc(fpgafs_inode_cache, GFP_KERNEL); | ||||||
|  | 	if (!fsi) | ||||||
|  | 		return NULL; | ||||||
|  | 
 | ||||||
|  |   fsi->i_ctx = NULL; | ||||||
|  | 
 | ||||||
|  |   return &fsi->vfs_inode; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void fpgafs_destroy_inode(struct inode *inode) | ||||||
|  | { | ||||||
|  | 	kmem_cache_free(fpgafs_inode_cache, FPGAFS_I(inode)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void fpgafs_delete_inode(struct inode *inode) | ||||||
|  | { | ||||||
|  | 	//struct fpgafs_inode_info *fsi = FPGAFS_I(inode);
 | ||||||
|  | 
 | ||||||
|  | //	XXX: do some fpga interface operations....
 | ||||||
|  | //	if (fsi->i_ctx)
 | ||||||
|  | //		put_fpga_context(ei->i_ctx);
 | ||||||
|  | 	clear_inode(inode); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static struct inode *fpgafs_new_inode(struct super_block *sb, int mode) | ||||||
|  | { | ||||||
|  | 	struct inode *inode; | ||||||
|  | 
 | ||||||
|  | 	inode = new_inode(sb); | ||||||
|  | 	if (!inode) | ||||||
|  | 		return inode; | ||||||
|  | 
 | ||||||
|  | 	inode->i_mode = mode; | ||||||
|  | 	inode->i_uid = current->fsuid; | ||||||
|  | 	inode->i_gid = current->fsgid; | ||||||
|  | 	inode->i_blocks = 0; | ||||||
|  | 	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||||||
|  |   return inode; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* FPGA FS specific functions */ | ||||||
|  | static int fpgafs_fill_dir(struct dentry *dir, struct tree_descr *files, | ||||||
|  | 		        int mode, struct fpga_context *ctx) | ||||||
|  | { | ||||||
|  | 	struct dentry *dentry; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	while (files->name && files->name[0]) { | ||||||
|  | 		ret = -ENOMEM; | ||||||
|  | 		dentry = d_alloc_name(dir, files->name); | ||||||
|  | 		if (!dentry) | ||||||
|  | 			goto out; | ||||||
|  | 		ret = fpgafs_new_file(dir->d_sb, dentry, files->ops, | ||||||
|  | 		                     files->mode & mode, ctx); | ||||||
|  | 		if (ret) | ||||||
|  | 			goto out; | ||||||
|  | 			files++; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | out: | ||||||
|  |   fpgafs_prune_dir(dir); | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* specific operations */ | ||||||
|  | static int fpgafs_setattr(struct dentry *dentry, struct iattr *attr) | ||||||
|  | { | ||||||
|  | 	struct inode *inode = dentry->d_inode; | ||||||
|  | 
 | ||||||
|  | 	if ((attr->ia_valid & ATTR_SIZE) && | ||||||
|  | 	    (attr->ia_size != inode->i_size)) | ||||||
|  | 		return -EINVAL; | ||||||
|  | 	return inode_setattr(inode, attr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int fpgafs_new_file(struct super_block *sb, struct dentry *dentry, | ||||||
|  |                            const struct file_operations *fops, int mode, | ||||||
|  |                            struct fpga_context *ctx) | ||||||
|  | { | ||||||
|  | 	static struct inode_operations fpgafs_file_iops = { | ||||||
|  | 		.setattr = fpgafs_setattr, | ||||||
|  | 	}; | ||||||
|  | 	struct inode *inode; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	ret = -ENOSPC; | ||||||
|  | 	inode = fpgafs_new_inode(sb, S_IFREG | mode); | ||||||
|  | 	if (!inode) | ||||||
|  | 		goto out; | ||||||
|  | 
 | ||||||
|  | 	ret = 0; | ||||||
|  | 	inode->i_op = &fpgafs_file_iops; | ||||||
|  | 	inode->i_fop = fops; | ||||||
|  | 	//inode->i_private = SPUFS_I(inode)->i_ctx = get_spu_context(ctx);
 | ||||||
|  | 	d_add(dentry, inode); | ||||||
|  | out: | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int fpgafs_mkdir( struct inode *dir, struct dentry *dentry, int mode) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 	struct inode *inode; | ||||||
|  | 	struct fpga_context *ctx; | ||||||
|  | 
 | ||||||
|  | 	ret = -ENOSPC; | ||||||
|  | 	inode = fpgafs_new_inode(dir->i_sb, mode | S_IFDIR); | ||||||
|  | 	if (!inode) | ||||||
|  | 		goto unmutex; | ||||||
|  | 
 | ||||||
|  | 	if (dir->i_mode & S_ISGID) { | ||||||
|  | 		inode->i_gid = dir->i_gid; | ||||||
|  | 		inode->i_mode &= S_ISGID; | ||||||
|  | 	} | ||||||
|  | 	// ctx = alloc fpga context ....
 | ||||||
|  | 	// FPGAFS_I(inode)->i_ctx = ctx;
 | ||||||
|  | 	//if (!ctx)
 | ||||||
|  | 	//	goto unmutex;
 | ||||||
|  | 
 | ||||||
|  | 	inode->i_op = &fpgafs_simple_dir_inode_operations; | ||||||
|  | 	inode->i_fop = &simple_dir_operations; | ||||||
|  | 
 | ||||||
|  |   ret = fpgafs_fill_dir(dentry, fpgafs_dir_contents, mode, ctx); | ||||||
|  | 	ret = 0; | ||||||
|  |   //if (ret) {
 | ||||||
|  | 	//	FREEE CONTENT
 | ||||||
|  | 	//	goto unmutex;
 | ||||||
|  | 	//}
 | ||||||
|  | 
 | ||||||
|  | 	d_instantiate(dentry, inode); | ||||||
|  | 	dget(dentry); | ||||||
|  | 	dir->i_nlink++; | ||||||
|  | 	dentry->d_inode->i_nlink++; | ||||||
|  | 
 | ||||||
|  | unmutex: | ||||||
|  | 	mutex_unlock(&inode->i_mutex); | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void fpgafs_prune_dir(struct dentry *dir) | ||||||
|  | { | ||||||
|  | 	struct dentry *dentry, *tmp; | ||||||
|  | 
 | ||||||
|  | 	mutex_lock(&dir->d_inode->i_mutex); | ||||||
|  | 	list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) { | ||||||
|  | 		spin_lock(&dcache_lock); | ||||||
|  | 		spin_lock(&dentry->d_lock); | ||||||
|  | 		if (!(d_unhashed(dentry)) && dentry->d_inode) { | ||||||
|  | 			dget_locked(dentry); | ||||||
|  | 			__d_drop(dentry); | ||||||
|  | 			spin_unlock(&dentry->d_lock); | ||||||
|  | 			simple_unlink(dir->d_inode, dentry); | ||||||
|  | 			spin_unlock(&dcache_lock); | ||||||
|  | 			dput(dentry); | ||||||
|  |     } else { | ||||||
|  | 			spin_unlock(&dentry->d_lock); | ||||||
|  | 			spin_unlock(&dcache_lock); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   shrink_dcache_parent(dir); | ||||||
|  |   mutex_unlock(&dir->d_inode->i_mutex); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Caller must hold parent->i_mutex */ | ||||||
|  | static int fpgafs_rmdir(struct inode *dir, struct dentry *dentry) | ||||||
|  | { | ||||||
|  | 	/* remove all entries */ | ||||||
|  | 	// fpgafs_prune_dir(dir);
 | ||||||
|  | 	//fpgafs_remove_inode
 | ||||||
|  | 
 | ||||||
|  | 	return simple_rmdir(dir, dentry); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* SUPERBLOCK operations */ | ||||||
|  | int fpgafs_fill_sb(struct super_block *sb, void *data, int silent) | ||||||
|  | { | ||||||
|  |   struct inode *inode; | ||||||
|  |   int ret = -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	static struct super_operations fpgafs_ops = { | ||||||
|  | 		//.read_inode = fpgafs_read_inode,
 | ||||||
|  | 		//.put_super  = fpgafs_put_super,
 | ||||||
|  | 		.alloc_inode = fpgafs_alloc_inode, | ||||||
|  |     .destroy_inode = fpgafs_destroy_inode, | ||||||
|  |     .statfs = simple_statfs, | ||||||
|  |     .delete_inode = fpgafs_delete_inode, | ||||||
|  |     .drop_inode = generic_delete_inode, | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  |   sb->s_maxbytes = MAX_LFS_FILESIZE; | ||||||
|  |   sb->s_blocksize = PAGE_CACHE_SIZE; | ||||||
|  |   sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | ||||||
|  |   sb->s_magic = FPGAFS_MAGIC; | ||||||
|  |   sb->s_op = &fpgafs_ops; | ||||||
|  | 
 | ||||||
|  | 	inode = fpgafs_new_inode(sb, S_IFDIR | 0775); | ||||||
|  | 	if (!inode) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  |   inode->i_op = &fpgafs_dir_inode_operations; | ||||||
|  |   inode->i_fop = &simple_dir_operations; | ||||||
|  |   FPGAFS_I(inode)->i_ctx = NULL; | ||||||
|  | 
 | ||||||
|  |   sb->s_root = d_alloc_root(inode); | ||||||
|  |   if (!sb->s_root) | ||||||
|  | 		return ret; | ||||||
|  | 
 | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int fpgafs_get_sb(struct file_system_type *fs_type, | ||||||
|  |      int flags, const char *dev_name, void *data, struct vfsmount *mnt) | ||||||
|  | { | ||||||
|  | 	return get_sb_nodev(fs_type, flags, data, fpgafs_fill_sb, mnt); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static struct file_system_type fpgafs_type = { | ||||||
|  | 	.owner   = THIS_MODULE, | ||||||
|  | 	.name    = "fpgafs", | ||||||
|  | 	.get_sb  = fpgafs_get_sb, | ||||||
|  | 	.kill_sb = kill_anon_super | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static void fpgafs_init_once(void *p, struct kmem_cache * cachep, | ||||||
|  |                             unsigned long flags) | ||||||
|  | { | ||||||
|  |   struct fpgafs_inode_info *fsi = p; | ||||||
|  |   if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == | ||||||
|  | 			      SLAB_CTOR_CONSTRUCTOR) { | ||||||
|  | 	    inode_init_once(&fsi->vfs_inode); | ||||||
|  | 	  } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* init exit functions ... */ | ||||||
|  | int __init fpgafs_init(void) | ||||||
|  | { | ||||||
|  | 	fpgafs_inode_cache = kmem_cache_create("fpgafs_inode_cache", | ||||||
|  | 	               sizeof(struct fpgafs_inode_info), 0, | ||||||
|  | 	               SLAB_HWCACHE_ALIGN, fpgafs_init_once, NULL); | ||||||
|  | 	if(!fpgafs_inode_cache) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	register_filesystem(&fpgafs_type); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void __exit fpgafs_exit(void) | ||||||
|  | { | ||||||
|  | 	kmem_cache_destroy(fpgafs_inode_cache); | ||||||
|  | 	unregister_filesystem(&fpgafs_type); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | module_init(fpgafs_init); | ||||||
|  | module_exit(fpgafs_exit); | ||||||
|  | 
 | ||||||
|  | MODULE_LICENSE("GPL"); | ||||||
|  | MODULE_AUTHOR("Benjamin Krill <ben@codiert.org>"); | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user