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

📄 file.c

📁 嵌入式linux下基于SRAM的内存文件系统
💻 C
字号:
/* * FILE NAME fs/pramfs/file.c * * BRIEF DESCRIPTION * * File operations for files. * * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com> * * Copyright 2003 Sony Corporation * Copyright 2003 Matsushita Electric Industrial Co., Ltd. * 2003-2004 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */#include <linux/fs.h>#include <linux/pram_fs.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/uio.h>#include <asm/uaccess.h>static int pram_open_file(struct inode * inode, struct file * filp){	filp->f_flags |= O_DIRECT;	return generic_file_open(inode, filp);}/* * Called when an inode is released. Note that this is different * from pram_open_file: open gets called at every open, but release * gets called only when /all/ the files are closed. */static int pram_release_file (struct inode * inode, struct file * filp){	return 0;}#if defined(CONFIG_PRAMFS_VNVRAM) && defined(CONFIG_PRAMFS_FAILSAFE)static inline int pram_is_alloc_blocks(struct inode * inode, int file_blocknr,				       int num){	struct super_block * sb = inode->i_sb;	struct pram_inode * pi = pram_get_inode(sb, inode->i_ino);	int N = sb->s_blocksize >> 2; // num block ptrs per block	int Nbits = sb->s_blocksize_bits - 2;	int first_file_blocknr;	int last_file_blocknr;	int first_row_index, last_row_index;	int i;	pram_off_t * row;	if (!pi->i_type.reg.row_block)		return 1;	row = pram_get_block(sb, pi->i_type.reg.row_block);	first_file_blocknr = (file_blocknr > inode->i_blocks) ?		inode->i_blocks : file_blocknr;	last_file_blocknr = file_blocknr + num - 1;	first_row_index = first_file_blocknr >> Nbits;	last_row_index  = last_file_blocknr >> Nbits;	if (last_row_index >= N || first_row_index >= N)		return -ENOSPC;	for (i = first_row_index; i <= last_row_index; i++) {		int first_col_index, last_col_index, j;		pram_off_t * col;		/*		 * we are starting a new row, so make sure		 * there is a block allocated for the row.		 */		if (!row[i])			return 1;		col = pram_get_block(sb, row[i]);		first_col_index = (i == first_row_index) ?			first_file_blocknr & (N-1) : 0;		last_col_index = (i == last_row_index) ?			last_file_blocknr & (N-1) : N-1;		for (j = first_col_index; j <= last_col_index; j++) {			if (!col[j])				return 1;		}	}	return 0;}#else#define pram_is_alloc_blocks(inode, file_blocknr, num) (1)#endifint pram_direct_IO(int rw, struct kiocb *iocb,		   const struct iovec *iov,		   loff_t offset, unsigned long nr_segs){	struct file *file = iocb->ki_filp;	struct inode *inode = file->f_mapping->host;	struct super_block * sb = inode->i_sb;	int progress = 0, retval = 0;	struct pram_inode * pi;	void * tmp = NULL;	unsigned long blocknr, blockoff;	int num_blocks, blocksize_mask, blocksize, blocksize_bits;	char __user *buf = iov->iov_base;	size_t length = iov->iov_len;	int failsafe_locked = 0;	if (length < 0)                return -EINVAL;	if ((rw == READ) && (offset + length > inode->i_size))		length = inode->i_size - offset;	if (!length)		goto out;	blocksize_bits = inode->i_sb->s_blocksize_bits;	blocksize = 1 << blocksize_bits;	blocksize_mask = blocksize - 1;	/* find starting block number to access */	blocknr = offset >> blocksize_bits;	/* find starting offset within starting block */	blockoff = offset & blocksize_mask;	/* find number of blocks to access */	num_blocks = (blockoff + length + blocksize_mask) >> blocksize_bits;	if (rw == WRITE) {		// prepare a temporary buffer to hold a user data block		// for writing.		tmp = kmalloc(blocksize, GFP_KERNEL);		if (!tmp)			return -ENOMEM;		retval = pram_is_alloc_blocks(inode, blocknr, num_blocks);		if (retval > 0) {			pram_lock_failsafe(sb, PRAM_FAILSAFE_OP_ALLOC_BLOCKS,					   inode->i_ino, (u32)offset, length);			/* now allocate the data blocks we'll need */			retval = pram_alloc_blocks(inode, blocknr, num_blocks);			pram_unlock_failsafe(sb);			if (retval)				goto fail;		} else if (retval < 0)			goto fail;	}	pi = pram_get_inode(inode->i_sb, inode->i_ino);	while (length) {		int count;		pram_off_t block = pram_find_data_block(inode, blocknr++);		u8* bp = (u8*)pram_get_block(sb, block);		if (!bp)			goto fail;		count = blockoff + length > blocksize ?			blocksize - blockoff : length;		if (rw == READ) {			retval = copy_to_user(buf, &bp[blockoff], count);			if (retval)				break; /* goto fail? */		} else {			retval = copy_from_user(tmp, buf, count);			if (retval)				break; /* goto fail? */			if (sb->s_flags & MS_DATA_FAILSAFE) {				pram_lock_failsafe(sb,						   PRAM_FAILSAFE_OP_DIRECT_IO,						   inode->i_ino, block, 0);				pram_backup_add_block(inode->i_sb, bp);			}			pram_lock_block(inode->i_sb, bp);			memcpy(&bp[blockoff], tmp, count);			pram_unlock_block(inode->i_sb, bp);			if (sb->s_flags & MS_DATA_FAILSAFE) {				pram_backup_del_block(inode->i_sb, bp);				pram_unlock_failsafe(sb);			}		}		progress += count;		buf += count;		length -= count;		blockoff = 0;	}	retval = progress; fail:	if (failsafe_locked)		pram_unlock_failsafe(sb);	if (tmp)		kfree(tmp); out:	return retval;}const struct file_operations pram_file_operations = {	.llseek		= generic_file_llseek,	.read		= do_sync_read,	.aio_read	= generic_file_aio_read,	.write		= do_sync_write,	.aio_write	= generic_file_aio_write,	.ioctl		= pram_ioctl,	.mmap		= generic_file_mmap,	.open		= pram_open_file,	.release	= pram_release_file,	.fsync		= pram_sync_file,	.splice_read	= generic_file_splice_read,};const struct inode_operations pram_file_inode_operations = {	.truncate	= pram_truncate,};

⌨️ 快捷键说明

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