⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myfsdir.c

📁 一个LINUX下一个框架文件系统,运行编译环境:RED HAT LINUX7.3
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "common.h"
#include "mytypes.h"

extern struct myfs_inode *myfs_inop(struct inode *ino);

/* dentry ops */
static int myfs_dentry_revalidate(struct dentry *de, int);

/* dir inode-ops */
static struct dentry *myfs_lookup(struct inode *dir, struct dentry *target);
static int myfs_unlink(struct inode *dir_inode, struct dentry *entry);
static int myfs_mkdir(struct inode *dir_inode, struct dentry *entry, int mode);
static int myfs_rmdir(struct inode *dir_inode, struct dentry *entry);
int myfs_rename(struct inode *old_dir, struct dentry *old_dentry, 
				struct inode *new_dir, struct dentry *new_dentry);
int myfs_revalidate_inode(struct dentry *dentry);

/* dir file-ops */
static int myfs_readdir(struct file *file, void *dirent, filldir_t filldir);
static ssize_t myfs_dir_read(struct file *file, char *buf, size_t count,
	loff_t *ppos);

struct dentry_operations myfs_dentry_operations =
{
	d_revalidate:     myfs_dentry_revalidate
};

struct inode_operations myfs_dir_inode_operations =
{
	/* put this in right later... myfs_notify_change */
	/* &myfs_dir_operations, */
//	create: myfs_file_create,    /* create TODO: DOES THIS NEED TO BE HERE? */
	lookup: myfs_lookup,      /* lookup */
	unlink: myfs_unlink, /* unlink called on parent directory to unlink a file */
	mkdir: myfs_mkdir,           /* mkdir */
	rmdir: myfs_rmdir,              /* rmdir */
	rename: myfs_rename,         /* rename */
	revalidate: myfs_revalidate_inode,   /* revalidate */
//	setattr: myfs_notify_change
};

struct file_operations myfs_dir_operations = {
	read: myfs_dir_read,   /* read -- returns -EISDIR  */
	readdir: myfs_readdir  /* readdir */
};

/* inode operations for directories */

/* myfs_lookup(dir, entry)
 *
 * Notes:
 * - name to look for is in the entry (entry->d_name.name, entry->d_name.len)
 * - dir is the directory in which we are doing the lookup
 *
 * Behavior:
 * - call ll_myfs_lookup to get a handle
 * - grab an inode for the new handle
 * - fill in the inode metadata
 * - add the dentry/inode pair into the dcache
 * - (optionally) set up pointer to new dentry functions
 *
 * Returns NULL pretty much all the time.  I know, this seems really
 * screwed up, but the ext2 fs seems to be doing the same thing...
 */
static struct dentry *myfs_lookup(struct inode *dir, struct dentry *entry)
{
	int error = 0, len_dir, len_file;
//	struct myfs_inode *pinode;
//	struct myfs_meta meta;
//	struct inode *inode = NULL;
//	char *ptr;

	printk("myfs_lookup called on %ld for %s\n", dir->i_ino, entry->d_name.name);
	
	printk("name might be %s/%s\n", myfs_inop(dir)->name, entry->d_name.name);

/*	len_dir = strlen(myfs_inop(dir)->name);
	len_file = entry->d_name.len;
	if ((pinode = (struct myfs_inode *) kmalloc(sizeof(struct myfs_inode)
	+ len_dir + len_file + 2, GFP_KERNEL)) == NULL){
		return NULL;
	}

	// fill in myfs_inode name field first
	pinode->name = (int8_t *)pinode + sizeof(struct myfs_inode);
	ptr = pinode->name;
	strcpy(ptr, myfs_inop(dir)->name);
	ptr += len_dir;
	*ptr = '/';
	ptr++;
	strcpy(ptr, entry->d_name.name);

	// do the lookup, grabs metadata
	error = ll_myfs_lookup(myfs_sbp(dir->i_sb), pinode->name,
		len_dir + len_file + 1, &meta);
	if (error < 0 && error != -ENOENT) {
		// real error
		kfree(pinode);
		return ERR_PTR(error);
	}

	if (error == -ENOENT) {
		// no file found; need to insert NULL inode so that create calls
		// can work correctly (or so says Gooch)
		entry->d_time = 0;
		entry->d_op = &myfs_dentry_operations;
		d_add(entry, NULL);
		kfree(pinode);
		return NULL;
	}

	if ((inode = iget(dir->i_sb, meta.handle)) == NULL) {
		// let's drop the dentry here...
		kfree(pinode);
		return ERR_PTR(-ENOMEM);
	}

	// fill in inode structure, remainder of myfs_inode
	pinode->handle = inode->i_ino;
	pinode->super = myfs_sbp(inode->i_sb);
	myfs_meta_to_inode(&meta, inode);
	inode->u.generic_ip = pinode;

	entry->d_time = 0;
	entry->d_op = &myfs_dentry_operations;

	printk(D_DIR, "saved name is %s\n", myfs_inop(inode)->name);

	if (S_ISDIR(inode->i_mode)) {
		inode->i_op = &myfs_dir_inode_operations;
#ifdef HAVE_LINUX_STRUCT_INODE_I_FOP
		inode->i_fop = &myfs_dir_operations;
#endif
	}
   else if (S_ISREG(inode->i_mode)) {
		inode->i_op = &myfs_file_inode_operations;
#ifdef HAVE_LINUX_STRUCT_INODE_I_FOP
		inode->i_fop = &myfs_file_operations;
#endif
#ifdef HAVE_LINUX_STRUCT_ADDRESS_SPACE_OPERATIONS
		inode->i_data.a_ops = &myfs_file_aops;
#endif
	}
   else {
		inode->i_op = NULL;
#ifdef HAVE_LINUX_STRUCT_INODE_I_FOP
		inode->i_fop = NULL;
#endif
	}

	d_add(entry, inode);
*/
	return NULL;
}


/* myfs_mkdir()
 *
 * Called on parent directory with dentry of directory to create.
 *
 * This is pretty much a carbon copy of myfs_file_create().
 */
static int myfs_mkdir(struct inode *dir, struct dentry *entry, int mode)
{
	int error = 0, len_dir, len_file;
//	struct inode *inode;
//	struct myfs_meta meta;
//	struct myfs_inode *pinode;
//	char *ptr;

	printk("myfs_mkdir called on %ld for %s\n", dir->i_ino,	entry->d_name.name);

/*	len_dir = strlen(myfs_inop(dir)->name);
	len_file = entry->d_name.len;
	if ((pinode = (struct myfs_inode *) kmalloc(sizeof(struct myfs_inode)
	+ len_dir + len_file + 2, GFP_KERNEL)) == NULL){
		return -ENOMEM;
	}

	// build myfs_inode name field first 
	pinode->name = (int8_t *)pinode + sizeof(struct myfs_inode);
	ptr = pinode->name;
	strcpy(ptr, myfs_inop(dir)->name);
	ptr += len_dir;
	*ptr = '/';
	ptr++;
	strcpy(ptr, entry->d_name.name);

	// do the create
	meta.valid = V_MODE | V_UID | V_GID | V_TIMES;
	meta.uid = current->fsuid;
	meta.gid = current->fsgid;
	meta.mode = mode;
	meta.mtime = meta.atime = meta.ctime = CURRENT_TIME;

	printk(D_DIR, "myfs_mkdir calling ll_myfs_mkdir\n");
	if ((error = ll_myfs_mkdir(myfs_sbp(dir->i_sb), pinode->name,
	len_dir + len_file + 1, &meta )) < 0)
	{
		kfree(pinode);
		return error;
	}

	// do a lookup so we can fill in the inode
	printk(D_DIR, "myfs_mkdir calling ll_myfs_lookup\n");
	if ((error = ll_myfs_lookup(myfs_sbp(dir->i_sb), pinode->name,
	len_dir + len_file + 1, &meta)) < 0)
	{
		kfree(pinode);
		return error;
	}

	// fill in inode structure and remainder of myfs_inode
	if ((inode = iget(dir->i_sb, meta.handle)) == NULL) {
		kfree(pinode);
		return -ENOMEM;
	}

	pinode->handle = inode->i_ino;
	pinode->super = myfs_sbp(inode->i_sb);
	myfs_meta_to_inode(&meta, inode);
	inode->u.generic_ip = pinode;

	d_instantiate(entry, inode); // do I know what this does?  nope!

	printk(D_DIR, "saved name is %s\n", myfs_inop(inode)->name);

	if (S_ISDIR(inode->i_mode)) {
		inode->i_op = &myfs_dir_inode_operations;
#ifdef HAVE_LINUX_STRUCT_INODE_I_FOP
		inode->i_fop = &myfs_dir_operations;
#endif
	}
   else if (S_ISREG(inode->i_mode)) {
		inode->i_op = &myfs_file_inode_operations;
#ifdef HAVE_LINUX_STRUCT_INODE_I_FOP
		inode->i_fop = &myfs_file_operations;
#endif
#ifdef HAVE_LINUX_STRUCT_ADDRESS_SPACE_OPERATIONS
		inode->i_data.a_ops = &myfs_file_aops;
#endif
	}
   else {
		inode->i_op = NULL;
#ifdef HAVE_LINUX_STRUCT_INODE_I_FOP
		inode->i_fop = NULL;
#endif
	}
*/
	return error;
}

/* myfs_unlink(dir, entry)
 *
 * Called on parent directory with dentry of file to unlink.  We call
 * d_delete(entry) when done to take the dentry out of the cache.  This
 * call also frees the inode associated with the unlinked file.
 * 
 */
int myfs_unlink(struct inode *dir, struct dentry *entry)
{
	int error = 0;

	printk("myfs_unlink called on %ld for %s\n", dir->i_ino, entry->d_name.name);
/*
	if (entry->d_inode == NULL) {
		// negative dentry ?!? 
		PERROR("myfs_unlink: negative dentry?\n");
		// TODO: should look up the file? 
		return -ENOENT;
	}
	if (entry->d_inode->i_nlink == 0) {
		PERROR("myfs_unlink: deleting nonexistent file?\n");
	}

	error = ll_myfs_unlink(myfs_inop(entry->d_inode));

	if (error == 0)
	{
		entry->d_inode->i_nlink--;	
#ifndef HAVE_LINUX_STRUCT_ADDRESS_SPACE_OPERATIONS
		// We should only do a d_delete() on 2.2 kernels.  i
		// There isn't a good autoconf test to detect this yet, 
		// so we use this ifndef.  
		d_delete(entry); // this also frees the inode
#endif
	}
*/
	return error;
}


/* myfs_rmdir()
 *
 * Called on parent directory with dentry of directory to remove.
 *
 * TODO: I'm not so sure that I know everything this call should be
 * doing; look at minix/namei.c:minix_rmdir() for some possible ideas.
 */
int myfs_rmdir(struct inode *dir, struct dentry *entry)
{
	int error = 0;

/*
#ifdef HAVE_D_UNHASHED
	if (!d_unhashed(entry))
#else
	if (!list_empty(&entry->d_hash))
#endif // HAVE_D_UNHASHED 
	{
		printk(D_DIR, "myfs_rmdir failing because dir (%s) is busy.\n", 
			entry->d_name.name);
		return -EBUSY;
	}

	printk(D_DIR, "myfs_rmdir called on %ld for %s\n", dir->i_ino,
	entry->d_name.name);
	if (entry->d_inode == NULL) {
		// negative dentry ?!? 
		PERROR("myfs_rmdir: negative dentry?\n");
		// TODO: should look up the file? 
		return -ENOENT;
	}
	if (entry->d_inode->i_nlink == 0) {
		PERROR("myfs_rmdir: deleting nonexistent directory?\n");
	}

	error = ll_myfs_rmdir(myfs_inop(entry->d_inode));

	if (error == 0)
	{
		entry->d_inode->i_nlink--;	
#ifndef HAVE_LINUX_STRUCT_ADDRESS_SPACE_OPERATIONS
		// We should only do a d_delete() on 2.2 kernels.  i
		// There isn't a good autoconf test to detect this yet, 
		// so we use this ifndef.  
		d_delete(entry); // this also frees the inode 
#endif
	}
*/
	return error;
}


/* myfs_rename(old_dir, old_dentry, new_dir, new_dentry)
 *
 * PARAMETERS:
 * old_dir - inode of parent directory of file/dir to be moved
 * new_dir - inode of parent directory of destination
 * old_dentry - dentry referring to the file/dir to move
 * new_dentry - dentry referring to the destination; inode might or
 *   might not be available.
 *
 * NOTES:
 * If the target name already exists, there will be a valid inode in the
 * new_dentry.  If the inode pointer is NULL, then there is nothing
 * referred to by that name.
 *
 * Also need to update the dcache and such to take changes into account!
 *
 * see fs/nfs/dir.c:nfs_rename() for an example.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -