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

📄 file.c

📁 linux下的用户文件系统fuse-2.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
}#else /* KERNEL_2_6 */#define FUSE_BLOCK_SHIFT 16#define FUSE_BLOCK_SIZE (1UL << FUSE_BLOCK_SHIFT)#define FUSE_BLOCK_MASK (~(FUSE_BLOCK_SIZE-1))#if (1UL << (FUSE_BLOCK_SHIFT - PAGE_CACHE_SHIFT)) > FUSE_MAX_PAGES_PER_REQ#error FUSE_BLOCK_SHIFT too large#endifstatic int fuse_is_block_uptodate(struct inode *inode, unsigned start,				  unsigned end){	int index;	for (index = start; index < end; index++) {		struct page *page = find_get_page(inode->i_mapping, index);		if (!page)			return 0;		if (!PageUptodate(page)) {			page_cache_release(page);			return 0;		}		page_cache_release(page);	}	return 1;}static int fuse_file_read_block(struct fuse_req *req, struct file *file,				struct inode *inode, unsigned start,				unsigned end){	loff_t pos;	size_t count;	int index;	int err = -EBUSY;	int i;	for (index = start; index < end; index++) {		struct page *page = grab_cache_page(inode->i_mapping, index);		if (!page)			goto out;		if (PageUptodate(page)) {			unlock_page(page);			page_cache_release(page);			page = NULL;		}		req->pages[req->num_pages++] = page;	}	pos = (loff_t) start << PAGE_CACHE_SHIFT;	count = req->num_pages << PAGE_CACHE_SHIFT;	fuse_send_read(req, file, inode, pos, count);	err = req->out.h.error; out:	for (i = 0; i < req->num_pages; i++) {		struct page *page = req->pages[i];		if (page) {			if (!err)				SetPageUptodate(page);			unlock_page(page);			page_cache_release(page);		}	}	return err;}static int fuse_file_bigread(struct file *file, struct inode *inode,			     loff_t pos, size_t count){	struct fuse_conn *fc = get_fuse_conn(inode);	unsigned starti;	unsigned endi;	unsigned nexti;	struct fuse_req *req;	loff_t size = i_size_read(inode);	loff_t end = (pos + count + FUSE_BLOCK_SIZE - 1) & FUSE_BLOCK_MASK;	end = min(end, size);	if (end <= pos)		return 0;	starti = (pos & FUSE_BLOCK_MASK) >> PAGE_CACHE_SHIFT;	endi = (end + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;	req = fuse_get_request(fc);	if (!req)		return -EINTR;	for (; starti < endi; starti = nexti) {		nexti = starti + (FUSE_BLOCK_SIZE >> PAGE_CACHE_SHIFT);		nexti = min(nexti, endi);		if (!fuse_is_block_uptodate(inode, starti, nexti)) {			if (fuse_file_read_block(req, file, inode, starti, nexti))				break;			fuse_reset_request(req);		}	}	fuse_put_request(fc, req);	return 0;}#endif /* KERNEL_2_6 */static size_t fuse_send_write(struct fuse_req *req, struct file *file,			      struct inode *inode, loff_t pos, size_t count){	struct fuse_conn *fc = get_fuse_conn(inode);	struct fuse_file *ff = file->private_data;	struct fuse_write_in inarg;	struct fuse_write_out outarg;	memset(&inarg, 0, sizeof(struct fuse_write_in));	inarg.fh = ff->fh;	inarg.offset = pos;	inarg.size = count;	req->in.h.opcode = FUSE_WRITE;	req->in.h.nodeid = get_node_id(inode);	req->inode = inode;	req->file = file;	req->in.argpages = 1;	req->in.numargs = 2;	req->in.args[0].size = sizeof(struct fuse_write_in);	req->in.args[0].value = &inarg;	req->in.args[1].size = count;	req->out.numargs = 1;	req->out.args[0].size = sizeof(struct fuse_write_out);	req->out.args[0].value = &outarg;	request_send(fc, req);	return outarg.size;}static int fuse_prepare_write(struct file *file, struct page *page,			      unsigned offset, unsigned to){	/* No op */	return 0;}static int fuse_commit_write(struct file *file, struct page *page,			     unsigned offset, unsigned to){	int err;	size_t nres;	unsigned count = to - offset;	struct inode *inode = page->mapping->host;	struct fuse_conn *fc = get_fuse_conn(inode);	loff_t pos = page_offset(page) + offset;	struct fuse_req *req;	if (is_bad_inode(inode))		return -EIO;	req = fuse_get_request(fc);	if (!req)		return -EINTR;	req->num_pages = 1;	req->pages[0] = page;	req->page_offset = offset;	nres = fuse_send_write(req, file, inode, pos, count);	err = req->out.h.error;	fuse_put_request(fc, req);	if (!err && nres != count)		err = -EIO;	if (!err) {		pos += count;		if (pos > i_size_read(inode))			i_size_write(inode, pos);		if (offset == 0 && to == PAGE_CACHE_SIZE) {			clear_page_dirty(page);			SetPageUptodate(page);		}	}	fuse_invalidate_attr(inode);	return err;}static void fuse_release_user_pages(struct fuse_req *req, int write){	unsigned i;	for (i = 0; i < req->num_pages; i++) {		struct page *page = req->pages[i];		if (write)			set_page_dirty_lock(page);		put_page(page);	}}static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,			       unsigned nbytes, int write){	unsigned long user_addr = (unsigned long) buf;	unsigned offset = user_addr & ~PAGE_MASK;	int npages;	/* This doesn't work with nfsd */	if (!current->mm)		return -EPERM;	nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT);	npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;	npages = max(npages, 1);	npages = min(npages, FUSE_MAX_PAGES_PER_REQ);	down_read(&current->mm->mmap_sem);	npages = get_user_pages(current, current->mm, user_addr, npages, write,				0, req->pages, NULL);	up_read(&current->mm->mmap_sem);	if (npages < 0)		return npages;	req->num_pages = npages;	req->page_offset = offset;	return 0;}static ssize_t fuse_direct_io(struct file *file, const char __user *buf,			      size_t count, loff_t *ppos, int write){	struct inode *inode = file->f_dentry->d_inode;	struct fuse_conn *fc = get_fuse_conn(inode);	size_t nmax = write ? fc->max_write : fc->max_read;	loff_t pos = *ppos;	ssize_t res = 0;	struct fuse_req *req;	if (is_bad_inode(inode))		return -EIO;	req = fuse_get_request(fc);	if (!req)		return -EINTR;	while (count) {		size_t nres;		size_t nbytes = min(count, nmax);		int err = fuse_get_user_pages(req, buf, nbytes, !write);		if (err) {			res = err;			break;		}		nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset;		nbytes = min(count, nbytes);		if (write)			nres = fuse_send_write(req, file, inode, pos, nbytes);		else			nres = fuse_send_read(req, file, inode, pos, nbytes);		fuse_release_user_pages(req, !write);		if (req->out.h.error) {			if (!res)				res = req->out.h.error;			break;		} else if (nres > nbytes) {			res = -EIO;			break;		}		count -= nres;		res += nres;		pos += nres;		buf += nres;		if (nres != nbytes)			break;		if (count)			fuse_reset_request(req);	}	fuse_put_request(fc, req);	if (res > 0) {		if (write && pos > i_size_read(inode))			i_size_write(inode, pos);		*ppos = pos;	}	fuse_invalidate_attr(inode);	return res;}static ssize_t fuse_direct_read(struct file *file, char __user *buf,				     size_t count, loff_t *ppos){	return fuse_direct_io(file, buf, count, ppos, 0);}static ssize_t fuse_direct_write(struct file *file, const char __user *buf,				 size_t count, loff_t *ppos){	struct inode *inode = file->f_dentry->d_inode;	ssize_t res;	/* Don't allow parallel writes to the same file */#ifdef KERNEL_2_6_16_PLUS	mutex_lock(&inode->i_mutex);	res = fuse_direct_io(file, buf, count, ppos, 1);	mutex_unlock(&inode->i_mutex);#else	down(&inode->i_sem);	res = fuse_direct_io(file, buf, count, ppos, 1);	up(&inode->i_sem);#endif	return res;}#ifndef KERNEL_2_6static ssize_t fuse_file_read(struct file *file, char __user *buf,			      size_t count, loff_t *ppos){	struct inode *inode = file->f_dentry->d_inode;	struct fuse_conn *fc = get_fuse_conn(inode);	if (is_bad_inode(inode))		return -EIO;	if (fc->flags & FUSE_LARGE_READ) {		int res;		down(&inode->i_sem);		res = fuse_file_bigread(file, inode, *ppos, count);		up(&inode->i_sem);		if (res)			return res;	}	return generic_file_read(file, buf, count, ppos);}#endifstatic int fuse_file_mmap(struct file *file, struct vm_area_struct *vma){	if ((vma->vm_flags & VM_SHARED)) {		if ((vma->vm_flags & VM_WRITE))			return -ENODEV;		else			vma->vm_flags &= ~VM_MAYWRITE;	}	return generic_file_mmap(file, vma);}#ifdef KERNEL_2_6static int fuse_set_page_dirty(struct page *page){	printk("fuse_set_page_dirty: should not happen\n");	dump_stack();	return 0;}#endifstatic struct file_operations fuse_file_operations = {	.llseek		= generic_file_llseek,#ifdef KERNEL_2_6	.read		= do_sync_read,	.write		= do_sync_write,	.readv		= generic_file_readv,	.writev		= generic_file_writev,	.aio_read	= generic_file_aio_read,	.aio_write	= generic_file_aio_write,#else	.read		= fuse_file_read,	.write		= generic_file_write,#endif	.mmap		= fuse_file_mmap,	.open		= fuse_open,	.flush		= fuse_flush,	.release	= fuse_release,	.fsync		= fuse_fsync,#ifdef KERNEL_2_6	.sendfile	= generic_file_sendfile,#endif};static struct file_operations fuse_direct_io_file_operations = {	.llseek		= generic_file_llseek,	.read		= fuse_direct_read,	.write		= fuse_direct_write,	.open		= fuse_open,	.flush		= fuse_flush,	.release	= fuse_release,	.fsync		= fuse_fsync,	/* no mmap and sendfile */};static struct address_space_operations fuse_file_aops  = {	.readpage	= fuse_readpage,	.prepare_write	= fuse_prepare_write,	.commit_write	= fuse_commit_write,#ifdef KERNEL_2_6	.readpages	= fuse_readpages,	.set_page_dirty	= fuse_set_page_dirty,#endif};void fuse_init_file_inode(struct inode *inode){	inode->i_fop = &fuse_file_operations;	inode->i_data.a_ops = &fuse_file_aops;}

⌨️ 快捷键说明

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