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