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

📄 dir.c

📁 file system in user space ! It s very good!
💻 C
📖 第 1 页 / 共 3 页
字号:
	__free_page(page);	fuse_invalidate_attr(inode); /* atime changed */	return err;}static char *read_link(struct dentry *dentry){	struct inode *inode = dentry->d_inode;	struct fuse_conn *fc = get_fuse_conn(inode);	struct fuse_req *req = fuse_get_req(fc);	char *link;	if (IS_ERR(req))		return ERR_PTR(PTR_ERR(req));	link = (char *) __get_free_page(GFP_KERNEL);	if (!link) {		link = ERR_PTR(-ENOMEM);		goto out;	}	req->in.h.opcode = FUSE_READLINK;	req->in.h.nodeid = get_node_id(inode);	req->out.argvar = 1;	req->out.numargs = 1;	req->out.args[0].size = PAGE_SIZE - 1;	req->out.args[0].value = link;	request_send(fc, req);	if (req->out.h.error) {		free_page((unsigned long) link);		link = ERR_PTR(req->out.h.error);	} else		link[req->out.args[0].size] = '\0'; out:	fuse_put_request(fc, req);	fuse_invalidate_attr(inode); /* atime changed */	return link;}static void free_link(char *link){	if (!IS_ERR(link))		free_page((unsigned long) link);}#ifdef KERNEL_2_6_13_PLUSstatic void *fuse_follow_link(struct dentry *dentry, struct nameidata *nd){	nd_set_link(nd, read_link(dentry));	return NULL;}static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c){	free_link(nd_get_link(nd));}#elsestatic int fuse_follow_link(struct dentry *dentry, struct nameidata *nd){	nd_set_link(nd, read_link(dentry));	return 0;}static void fuse_put_link(struct dentry *dentry, struct nameidata *nd){	free_link(nd_get_link(nd));}#endifstatic int fuse_dir_open(struct inode *inode, struct file *file){	return fuse_open_common(inode, file, 1);}static int fuse_dir_release(struct inode *inode, struct file *file){	return fuse_release_common(inode, file, 1);}static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync){	/* nfsd can call this with no file */	return file ? fuse_fsync_common(file, de, datasync, 1) : 0;}static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg){	unsigned ivalid = iattr->ia_valid;	if (ivalid & ATTR_MODE)		arg->valid |= FATTR_MODE,   arg->mode = iattr->ia_mode;	if (ivalid & ATTR_UID)		arg->valid |= FATTR_UID,    arg->uid = iattr->ia_uid;	if (ivalid & ATTR_GID)		arg->valid |= FATTR_GID,    arg->gid = iattr->ia_gid;	if (ivalid & ATTR_SIZE)		arg->valid |= FATTR_SIZE,   arg->size = iattr->ia_size;	/* You can only _set_ these together (they may change by themselves) */	if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {		arg->valid |= FATTR_ATIME | FATTR_MTIME;		arg->atime = iattr->ia_atime.tv_sec;		arg->mtime = iattr->ia_mtime.tv_sec;	}#ifdef ATTR_FILE	if (ivalid & ATTR_FILE) {		struct fuse_file *ff = iattr->ia_file->private_data;		arg->valid |= FATTR_FH;		arg->fh = ff->fh;	}#endif}static void fuse_vmtruncate(struct inode *inode, loff_t offset){	struct fuse_conn *fc = get_fuse_conn(inode);	int need_trunc;	spin_lock(&fc->lock);	need_trunc = inode->i_size > offset;	i_size_write(inode, offset);	spin_unlock(&fc->lock);	if (need_trunc) {		struct address_space *mapping = inode->i_mapping;		unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);		truncate_inode_pages(mapping, offset);	}}/* * Set attributes, and at the same time refresh them. * * Truncation is slightly complicated, because the 'truncate' request * may fail, in which case we don't want to touch the mapping. * vmtruncate() doesn't allow for this case, so do the rlimit checking * and the actual truncation by hand. */static int fuse_setattr(struct dentry *entry, struct iattr *attr){	struct inode *inode = entry->d_inode;	struct fuse_conn *fc = get_fuse_conn(inode);	struct fuse_inode *fi = get_fuse_inode(inode);	struct fuse_req *req;	struct fuse_setattr_in inarg;	struct fuse_attr_out outarg;	int err;	int is_truncate = 0;	if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {		err = inode_change_ok(inode, attr);		if (err)			return err;	}	if (attr->ia_valid & ATTR_SIZE) {		unsigned long limit;		is_truncate = 1;		if (IS_SWAPFILE(inode))			return -ETXTBSY;#ifdef KERNEL_2_6_10_PLUS		limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;#else		limit = current->rlim[RLIMIT_FSIZE].rlim_cur;#endif		if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {			send_sig(SIGXFSZ, current, 0);			return -EFBIG;		}	}	req = fuse_get_req(fc);	if (IS_ERR(req))		return PTR_ERR(req);	memset(&inarg, 0, sizeof(inarg));	iattr_to_fattr(attr, &inarg);	/* Defend against future expansion of ATTR_FILE use */	if (S_ISDIR(inode->i_mode))		inarg.valid &= ~FATTR_FH;	req->in.h.opcode = FUSE_SETATTR;	req->in.h.nodeid = get_node_id(inode);	req->in.numargs = 1;	req->in.args[0].size = sizeof(inarg);	req->in.args[0].value = &inarg;	req->out.numargs = 1;	req->out.args[0].size = sizeof(outarg);	req->out.args[0].value = &outarg;	request_send(fc, req);	err = req->out.h.error;	fuse_put_request(fc, req);	if (!err) {		if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {#ifndef KERNEL_2_6_12_PLUS			if (get_node_id(inode) != FUSE_ROOT_ID)				make_bad_inode(inode);#else			make_bad_inode(inode);#endif			err = -EIO;		} else {			if (is_truncate)				fuse_vmtruncate(inode, outarg.attr.size);			fuse_change_attributes(inode, &outarg.attr);			fi->i_time = time_to_jiffies(outarg.attr_valid,						     outarg.attr_valid_nsec);		}	} else if (err == -EINTR)		fuse_invalidate_attr(inode);	return err;}static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,			struct kstat *stat){	struct inode *inode = entry->d_inode;	int err = fuse_revalidate(entry);	if (!err)		/* FIXME: may want specialized function because of		   st_blksize on block devices on 2.6.19+ */		generic_fillattr(inode, stat);	return err;}static int fuse_setxattr(struct dentry *entry, const char *name,			 const void *value, size_t size, int flags){	struct inode *inode = entry->d_inode;	struct fuse_conn *fc = get_fuse_conn(inode);	struct fuse_req *req;	struct fuse_setxattr_in inarg;	int err;	if (fc->no_setxattr)		return -EOPNOTSUPP;	req = fuse_get_req(fc);	if (IS_ERR(req))		return PTR_ERR(req);	memset(&inarg, 0, sizeof(inarg));	inarg.size = size;	inarg.flags = flags;	req->in.h.opcode = FUSE_SETXATTR;	req->in.h.nodeid = get_node_id(inode);	req->in.numargs = 3;	req->in.args[0].size = sizeof(inarg);	req->in.args[0].value = &inarg;	req->in.args[1].size = strlen(name) + 1;	req->in.args[1].value = name;	req->in.args[2].size = size;	req->in.args[2].value = value;	request_send(fc, req);	err = req->out.h.error;	fuse_put_request(fc, req);	if (err == -ENOSYS) {		fc->no_setxattr = 1;		err = -EOPNOTSUPP;	}	return err;}static ssize_t fuse_getxattr(struct dentry *entry, const char *name,			     void *value, size_t size){	struct inode *inode = entry->d_inode;	struct fuse_conn *fc = get_fuse_conn(inode);	struct fuse_req *req;	struct fuse_getxattr_in inarg;	struct fuse_getxattr_out outarg;	ssize_t ret;	if (fc->no_getxattr)		return -EOPNOTSUPP;	req = fuse_get_req(fc);	if (IS_ERR(req))		return PTR_ERR(req);	memset(&inarg, 0, sizeof(inarg));	inarg.size = size;	req->in.h.opcode = FUSE_GETXATTR;	req->in.h.nodeid = get_node_id(inode);	req->in.numargs = 2;	req->in.args[0].size = sizeof(inarg);	req->in.args[0].value = &inarg;	req->in.args[1].size = strlen(name) + 1;	req->in.args[1].value = name;	/* This is really two different operations rolled into one */	req->out.numargs = 1;	if (size) {		req->out.argvar = 1;		req->out.args[0].size = size;		req->out.args[0].value = value;	} else {		req->out.args[0].size = sizeof(outarg);		req->out.args[0].value = &outarg;	}	request_send(fc, req);	ret = req->out.h.error;	if (!ret)		ret = size ? req->out.args[0].size : outarg.size;	else {		if (ret == -ENOSYS) {			fc->no_getxattr = 1;			ret = -EOPNOTSUPP;		}	}	fuse_put_request(fc, req);	return ret;}static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size){	struct inode *inode = entry->d_inode;	struct fuse_conn *fc = get_fuse_conn(inode);	struct fuse_req *req;	struct fuse_getxattr_in inarg;	struct fuse_getxattr_out outarg;	ssize_t ret;	if (fc->no_listxattr)		return -EOPNOTSUPP;	req = fuse_get_req(fc);	if (IS_ERR(req))		return PTR_ERR(req);	memset(&inarg, 0, sizeof(inarg));	inarg.size = size;	req->in.h.opcode = FUSE_LISTXATTR;	req->in.h.nodeid = get_node_id(inode);	req->in.numargs = 1;	req->in.args[0].size = sizeof(inarg);	req->in.args[0].value = &inarg;	/* This is really two different operations rolled into one */	req->out.numargs = 1;	if (size) {		req->out.argvar = 1;		req->out.args[0].size = size;		req->out.args[0].value = list;	} else {		req->out.args[0].size = sizeof(outarg);		req->out.args[0].value = &outarg;	}	request_send(fc, req);	ret = req->out.h.error;	if (!ret)		ret = size ? req->out.args[0].size : outarg.size;	else {		if (ret == -ENOSYS) {			fc->no_listxattr = 1;			ret = -EOPNOTSUPP;		}	}	fuse_put_request(fc, req);	return ret;}static int fuse_removexattr(struct dentry *entry, const char *name){	struct inode *inode = entry->d_inode;	struct fuse_conn *fc = get_fuse_conn(inode);	struct fuse_req *req;	int err;	if (fc->no_removexattr)		return -EOPNOTSUPP;	req = fuse_get_req(fc);	if (IS_ERR(req))		return PTR_ERR(req);	req->in.h.opcode = FUSE_REMOVEXATTR;	req->in.h.nodeid = get_node_id(inode);	req->in.numargs = 1;	req->in.args[0].size = strlen(name) + 1;	req->in.args[0].value = name;	request_send(fc, req);	err = req->out.h.error;	fuse_put_request(fc, req);	if (err == -ENOSYS) {		fc->no_removexattr = 1;		err = -EOPNOTSUPP;	}	return err;}static struct inode_operations fuse_dir_inode_operations = {	.lookup		= fuse_lookup,	.mkdir		= fuse_mkdir,	.symlink	= fuse_symlink,	.unlink		= fuse_unlink,	.rmdir		= fuse_rmdir,	.rename		= fuse_rename,	.link		= fuse_link,	.setattr	= fuse_setattr,	.create		= fuse_create,	.mknod		= fuse_mknod,	.permission	= fuse_permission,	.getattr	= fuse_getattr,	.setxattr	= fuse_setxattr,	.getxattr	= fuse_getxattr,	.listxattr	= fuse_listxattr,	.removexattr	= fuse_removexattr,};static struct file_operations fuse_dir_operations = {	.llseek		= generic_file_llseek,	.read		= generic_read_dir,	.readdir	= fuse_readdir,	.open		= fuse_dir_open,	.release	= fuse_dir_release,	.fsync		= fuse_dir_fsync,};static struct inode_operations fuse_common_inode_operations = {	.setattr	= fuse_setattr,	.permission	= fuse_permission,	.getattr	= fuse_getattr,	.setxattr	= fuse_setxattr,	.getxattr	= fuse_getxattr,	.listxattr	= fuse_listxattr,	.removexattr	= fuse_removexattr,};static struct inode_operations fuse_symlink_inode_operations = {	.setattr	= fuse_setattr,	.follow_link	= fuse_follow_link,	.put_link	= fuse_put_link,	.readlink	= generic_readlink,	.getattr	= fuse_getattr,	.setxattr	= fuse_setxattr,	.getxattr	= fuse_getxattr,	.listxattr	= fuse_listxattr,	.removexattr	= fuse_removexattr,};void fuse_init_common(struct inode *inode){	inode->i_op = &fuse_common_inode_operations;}void fuse_init_dir(struct inode *inode){	inode->i_op = &fuse_dir_inode_operations;	inode->i_fop = &fuse_dir_operations;}void fuse_init_symlink(struct inode *inode){	inode->i_op = &fuse_symlink_inode_operations;}

⌨️ 快捷键说明

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