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

📄 myfsdir.c

📁 一个LINUX下一个框架文件系统,运行编译环境:RED HAT LINUX7.3
💻 C
📖 第 1 页 / 共 2 页
字号:
 * see fs/minix/namei.c:minix_rename() for a different example.
 *
 * It's not enough to just mark the various inodes as dirty.  We need to
 * ensure that the directory cache is updated.  This turns out to be
 * easy; just call d_move(old_dentry, new_dentry) to get the dentries
 * updated!  Or at least, that seems to be working <smile>...
 *
 * Returns 0 on success, -errno on failure.
 */
int myfs_rename(struct inode *old_dir, struct dentry *old_dentry, 
struct inode *new_dir, struct dentry *new_dentry)
{
	int error = -ENOSYS;
//	struct inode *new_inode;
//	struct myfs_inode *old_pinode, *new_pinode;

/*
	old_pinode = myfs_inop(old_dentry->d_inode);
	new_inode = new_dentry->d_inode;
	if (new_inode == NULL) {
		// no file at new name; need to create a fake myfs_inode
		// namebuf is big enough for <host>:port/<name> 
		char *namebuf;
		struct myfs_inode fake_pinode;

		namebuf = (char *) kmalloc(PVFSHOSTLEN + PVFSNAMELEN + 8, GFP_KERNEL);
		if (namebuf == NULL)	return 0;

		printk((D_DIR | D_FILE), "myfs_rename, no inode for new file\n");
		if ((strlen(old_pinode->name) + new_dentry->d_name.len + 2) >
		PVFSHOSTLEN + PVFSDIRLEN + 7) {
			// should never happen 
			PERROR("myfs_rename: string too long?!?\n");
			kfree(namebuf);
			return -ENOSYS;
		}
		sprintf(namebuf, "%s/%s", myfs_inop(new_dir)->name,
		new_dentry->d_name.name);
		fake_pinode.handle = 0;
		fake_pinode.name = namebuf;
		fake_pinode.super = myfs_sbp(new_dir->i_sb);

		printk((D_DIR | D_FILE), "myfs_rename called, %s -> %s (new)\n",
		old_pinode->name, namebuf);

		error = ll_myfs_rename(old_pinode, &fake_pinode);
		kfree(namebuf);
	}
	else {
		// a file already exists with new name 
		new_pinode = myfs_inop(new_dentry->d_inode);
		printk((D_DIR | D_FILE), "myfs_rename called, %s -> %s\n",
		old_pinode->name, new_pinode->name);

		error = ll_myfs_rename(old_pinode, new_pinode);
	}
	
	// Update the dcache
	d_move(old_dentry, new_dentry);
*/
	return error;
}


/* myfs_readdir()
 *
 */
int myfs_readdir(struct file *file, void *dirent, filldir_t filldir)
{
	int ret, len;
//	struct myfs_dirent dbuf;
	struct inode *inode;
//	myfs_off_t pos;

	inode = file->f_dentry->d_inode;
	printk( "myfs_readdir called for 0x%lx.\n", inode->i_ino);

/*
	pos = file->f_pos;
	if ((ret = ll_myfs_readdir(myfs_inop(inode), &dbuf, &pos)) <= 0)
		goto out;  // error or EOF 

	len = strlen(dbuf.name);
	if ((ret = filldir(dirent, dbuf.name, len, dbuf.off, dbuf.handle
#ifdef HAVE_LINUX_6_PARAM_FILLDIR
	    , DT_UNKNOWN	// linux 2.4
#endif
	)))
		goto out;

	// ll_myfs_readdir gives us the position to start from the next time 
	file->f_pos = pos;
*/
    out:
	return ret;
}

/* myfs_fsync(file, dentry, [datasync])
 *
 */
#ifdef HAVE_LINUX_3_PARAM_FILE_FSYNC
int myfs_fsync(struct file *file, struct dentry *dentry, int datasync)
#else
int myfs_fsync(struct file *file, struct dentry *dentry)
#endif
{
	int error = 0;
//	struct myfs_inode *pinode;
/*
#ifdef NEED_TO_LOCK_KERNEL
	lock_kernel();
#endif
	pinode = myfs_inop(dentry->d_inode);

	error = ll_myfs_fsync(pinode);
#ifdef NEED_TO_LOCK_KERNEL
	unlock_kernel();
#endif
*/
	return error;
}

/* myfs_dir_read()
 *
 * Returns -EISDIR.  Just here to get the right error value back.
 */
static ssize_t myfs_dir_read(struct file *file, char *buf, size_t count,
loff_t *ppos)
{
	return -EISDIR;
}

/* myfs_revalidate_inode()
 *
 * Performs a getmeta operation to ensure that the data in the inode is
 * up-to-date.
 *
 * QUESTION: Do we need a lock on the inode in here?
 */
int myfs_revalidate_inode(struct dentry *dentry)
{
	int error = 0, len_dir, len_file;
//	struct inode *inode;
//	struct dentry *parent_dentry;
//	struct inode *parent_inode;
//	struct myfs_inode *pinode;
//	struct myfs_meta meta;
//	struct myfs_phys phys;
//	myfs_handle_t old_handle;
//	umode_t old_mode;
//	char *ptr;
/*
#ifdef NEED_TO_LOCK_KERNEL
	lock_kernel();
#endif

	inode = dentry->d_inode;
	if (inode == NULL) {
		PERROR("myfs_revalidate_inode called for NULL inode\n");
#ifdef NEED_TO_LOCK_KERNEL
		unlock_kernel();
#endif
		return -EINVAL;
	}

#ifdef IS_DEADDIR
	if(IS_DEADDIR(dentry->d_inode))
	{
		PERROR("DEAD directory detected going into myfs_revalidate_inode.\n");
	}
#endif

	// get the parent dentry and inode -- this should be optimized later 
	parent_dentry = dentry->d_parent;
	if (parent_dentry == NULL) {
		PERROR("myfs_revalidate_inode: d_parent is NULL\n");
#ifdef NEED_TO_LOCK_KERNEL
		unlock_kernel();
#endif
		return -EINVAL;
	}

	parent_inode = parent_dentry->d_inode;
	if (parent_inode == NULL) {
		PERROR("myfs_revalidate_inode: parent inode is NULL\n");
#ifdef NEED_TO_LOCK_KERNEL
		unlock_kernel();
#endif
		return -EINVAL;
	}
	
	// reconstruct the name in the inode 
	len_dir = strlen(myfs_inop(parent_inode)->name);
	len_file = dentry->d_name.len;
	pinode = myfs_inop(inode);

	// save the old handle value for debugging test 
	old_handle = pinode->handle;
	old_mode = inode->i_mode;

	// if we're not looking at the root of a file system, we need to 
	// rebuild the filename.  it's important that pinode point to
	// myfs_inop(inode) at this point in case we don't go in the "if".
	if (parent_inode != inode) {
		// the "1" takes into account the '/' between file and dir names
		//
		// if the old name is longer or of equal length, we don't realloc.
		if (strlen(pinode->name) < len_file + len_dir + 1) {
			struct myfs_inode *old_pinode;

			// we need to reallocate the myfs_inode structure and file name.
			//
			// the "2" takes into account the '/' between names and the
			// trailing '\0'.
         old_pinode = pinode;
			pinode = (struct myfs_inode *) kmalloc(sizeof(struct myfs_inode)
																+ len_dir + len_file + 2, 
																GFP_KERNEL);
			if (pinode == NULL) {
				PERROR("myfs_revalidate_inode: out of memory!\n");
#ifdef NEED_TO_LOCK_KERNEL
				unlock_kernel();
#endif
				return -ENOMEM;
			}

			*pinode = *old_pinode; // copy in all the old values
			pinode->name = (int8_t *)pinode + sizeof(struct myfs_inode);
			inode->u.generic_ip = pinode;

			kfree(old_pinode);
		}
		
		// copy the name into the inode: copy dirname, add /, copy name
		ptr = pinode->name;
		strcpy(ptr, myfs_inop(parent_inode)->name);
		ptr += len_dir;
		*ptr = '/';
		ptr++;
		strcpy(ptr, dentry->d_name.name);
	}

	printk(D_DIR, "myfs_revalidate_inode called for %s (%ld).\n",
	pinode->name, (unsigned long) pinode->handle);

	// Note: the only parameter that really is used inside of ll_myfs_getmeta() 
	//       is the file name. 
	error = ll_myfs_getmeta(pinode, &meta, &phys);
	if (error < 0) {
		printk(D_DIR,
		"myfs_revalidate: ll_myfs_getmeta() failed; updating dcache\n");

		// leave the dcache alone; the calling function handles cleanup
#ifdef NEED_TO_LOCK_KERNEL
		unlock_kernel();
#endif
		return error;
	}

	// NOTE: not doing anything with the phys for now 
	myfs_meta_to_inode(&meta, inode);

	if (old_handle != meta.handle) {
		// need to update the inode and redo the hash 
		printk(D_DIR, 
				 "myfs_revalidate_inode: handle changed from %ld to %ld for %s\n",
				 (unsigned long) old_handle, 
				 (unsigned long) meta.handle, pinode->name);

		remove_inode_hash(inode);
		inode->i_ino = meta.handle;
		pinode->handle = meta.handle;
		insert_inode_hash(inode);
	}
	if (old_mode != inode->i_mode) {
		// need to update function pointers
		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 {
			PERROR("myfs_revalidate_inode: handle refers to something other than a file or a directory?\n");
			error = -EINVAL;
		}
	}

#ifdef NEED_TO_LOCK_KERNEL
	unlock_kernel();
#endif
*/
	return error;
}

/* myfs_dentry_revalidate()
 *
 * A return value of "1" indicates that things are ok.  A return value of "0"
 * should result in the upper layers trying to prune out the dentry (bad).
 */
static int myfs_dentry_revalidate(struct dentry *dentry, int flags)
{
	int ret;

	printk( "myfs_dentry_revalidate called for %s.\n", dentry->d_name.name);
/*
	// don't call revalidate inode if the inode isn't valid 
	if (dentry->d_inode == NULL) {
		PERROR("myfs_dentry_revalidate: NULL inode (negative dentry) hit.\n");
		return 0;
	}

	ret = myfs_revalidate_inode(dentry);
*/
	if (ret == 0) return 1;
	else return 0; /* we got an error - let it be handled elsewhere. */

}


/* myfs_meta_to_inode()
 *
 * Copies a myfs_meta structure's values into an inode structure.
 */
int myfs_meta_to_inode(struct myfs_meta *mbuf, struct inode *ibuf)
{
	int error = 0;

	/* leaving the handle/i_ino fields alone for now */

	ibuf->i_mode = mbuf->mode;
	ibuf->i_uid = mbuf->uid;
	ibuf->i_gid = mbuf->gid;
	ibuf->i_size = mbuf->size;
	ibuf->i_atime = mbuf->atime;
	ibuf->i_mtime = mbuf->mtime;
	ibuf->i_ctime = mbuf->ctime;
	ibuf->i_blksize = mbuf->blksize;
	ibuf->i_blocks = mbuf->blocks;

	return error;
}

/*
 * Local variables:
 *  c-indent-level: 3
 *  c-basic-offset: 3
 *  tab-width: 3
 * End:
 */

⌨️ 快捷键说明

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