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

📄 file.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
			return rc;		}		/* this is probably better than directly calling 		partialpage_write since in this function		the file handle is known which we might as well		leverage */		/* BB check if anything else missing out of ppw */		/* such as updating last write time */		page_data = kmap(page);		rc = cifs_write(file, page_data+offset,to-offset,                                        &position);		if(rc > 0)			rc = 0;		/* else if rc < 0 should we set writebehind rc? */		kunmap(page);	} else {			set_page_dirty(page);	}	FreeXid(xid);	return rc;}intcifs_fsync(struct file *file, struct dentry *dentry, int datasync){	int xid;	int rc = 0;	struct inode * inode = file->f_dentry->d_inode;	xid = GetXid();	cFYI(1, ("Sync file - name: %s datasync: 0x%x ", 		dentry->d_name.name, datasync));		rc = filemap_fdatawrite(inode->i_mapping);	if(rc == 0)		CIFS_I(inode)->write_behind_rc = 0;	FreeXid(xid);	return rc;}/* static intcifs_sync_page(struct page *page){	struct address_space *mapping;	struct inode *inode;	unsigned long index = page->index;	unsigned int rpages = 0;	int rc = 0;	cFYI(1,("sync page %p",page));	mapping = page->mapping;	if (!mapping)		return 0;	inode = mapping->host;	if (!inode)		return 0;*//*	fill in rpages then     result = cifs_pagein_inode(inode, index, rpages); *//* BB finish *//*   cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));	if (rc < 0)		return rc;	return 0;} *//* * As file closes, flush all cached write data for this inode checking * for write behind errors. * */int cifs_flush(struct file *file){	struct inode * inode = file->f_dentry->d_inode;	int rc = 0;	/* Rather than do the steps manually: */	/* lock the inode for writing */	/* loop through pages looking for write behind data (dirty pages) */	/* coalesce into contiguous 16K (or smaller) chunks to write to server */	/* send to server (prefer in parallel) */	/* deal with writebehind errors */	/* unlock inode for writing */	/* filemapfdatawrite appears easier for the time being */	rc = filemap_fdatawrite(inode->i_mapping);	if(rc == 0) /* reset wb rc if we were able to write out dirty pages */		CIFS_I(inode)->write_behind_rc = 0;			cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc));	return rc;}ssize_tcifs_read(struct file * file, char *read_data, size_t read_size,	  loff_t * poffset){	int rc = -EACCES;	unsigned int bytes_read = 0;	unsigned int total_read;	unsigned int current_read_size;	struct cifs_sb_info *cifs_sb;	struct cifsTconInfo *pTcon;	int xid;	char * current_offset;	struct cifsFileInfo * open_file;	xid = GetXid();	cifs_sb = CIFS_SB(file->f_dentry->d_sb);	pTcon = cifs_sb->tcon;	if (file->private_data == NULL) {		FreeXid(xid);		return -EBADF;	}	open_file = (struct cifsFileInfo *)file->private_data;	if((file->f_flags & O_ACCMODE) == O_WRONLY) {		cFYI(1,("attempting read on write only file instance"));	}	for (total_read = 0,current_offset=read_data; read_size > total_read;				total_read += bytes_read,current_offset+=bytes_read) {		current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);		rc = -EAGAIN;		while(rc == -EAGAIN) {			if ((open_file->invalidHandle) && (!open_file->closePend)) {				rc = cifs_reopen_file(file->f_dentry->d_inode,					file,TRUE);				if(rc != 0)					break;			}			rc = CIFSSMBRead(xid, pTcon,				 open_file->netfid,				 current_read_size, *poffset,				 &bytes_read, &current_offset);		}		if (rc || (bytes_read == 0)) {			if (total_read) {				break;			} else {				FreeXid(xid);				return rc;			}		} else {#ifdef CONFIG_CIFS_STATS			atomic_inc(&pTcon->num_reads);			spin_lock(&pTcon->stat_lock);			pTcon->bytes_read += total_read;			spin_unlock(&pTcon->stat_lock);#endif			*poffset += bytes_read;		}	}	FreeXid(xid);	return total_read;}int cifs_file_mmap(struct file * file, struct vm_area_struct * vma){	struct dentry * dentry = file->f_dentry;	int	rc, xid;	xid = GetXid();	rc = cifs_revalidate(dentry);	if (rc) {		cFYI(1,("Validation prior to mmap failed, error=%d", rc));		FreeXid(xid);		return rc;	}	rc = generic_file_mmap(file, vma);	FreeXid(xid);	return rc;}static void cifs_copy_cache_pages(struct address_space *mapping, 		struct list_head *pages, int bytes_read, 		char *data,struct pagevec * plru_pvec){	struct page *page;	char * target;	while (bytes_read > 0) {		if(list_empty(pages))			break;		page = list_entry(pages->prev, struct page, lru);		list_del(&page->lru);		if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {			page_cache_release(page);			cFYI(1,("Add page cache failed"));			continue;		}		target = kmap_atomic(page,KM_USER0);		if(PAGE_CACHE_SIZE > bytes_read) {			memcpy(target,data,bytes_read);			/* zero the tail end of this partial page */			memset(target+bytes_read,0,PAGE_CACHE_SIZE-bytes_read);			bytes_read = 0;		} else {			memcpy(target,data,PAGE_CACHE_SIZE);			bytes_read -= PAGE_CACHE_SIZE;		}		kunmap_atomic(target,KM_USER0);		flush_dcache_page(page);		SetPageUptodate(page);		unlock_page(page);		if (!pagevec_add(plru_pvec, page))			__pagevec_lru_add(plru_pvec);		data += PAGE_CACHE_SIZE;	}	return;}static intcifs_readpages(struct file *file, struct address_space *mapping,		struct list_head *page_list, unsigned num_pages){	int rc = -EACCES;	int xid;	loff_t offset;	struct page * page;	struct cifs_sb_info *cifs_sb;	struct cifsTconInfo *pTcon;	int bytes_read = 0;	unsigned int read_size,i;	char * smb_read_data = NULL;	struct smb_com_read_rsp * pSMBr;	struct pagevec lru_pvec;	struct cifsFileInfo * open_file;	xid = GetXid();	if (file->private_data == NULL) {		FreeXid(xid);		return -EBADF;	}	open_file = (struct cifsFileInfo *)file->private_data;	cifs_sb = CIFS_SB(file->f_dentry->d_sb);	pTcon = cifs_sb->tcon;	pagevec_init(&lru_pvec, 0);	for(i = 0;i<num_pages;) {		unsigned contig_pages;		struct page * tmp_page;		unsigned long expected_index;		if(list_empty(page_list)) {			break;		}		page = list_entry(page_list->prev, struct page, lru);		offset = (loff_t)page->index << PAGE_CACHE_SHIFT;		/* count adjacent pages that we will read into */		contig_pages = 0;		expected_index = list_entry(page_list->prev,struct page,lru)->index;		list_for_each_entry_reverse(tmp_page,page_list,lru) {			if(tmp_page->index == expected_index) {				contig_pages++;				expected_index++;			} else {				break; 			}		}		if(contig_pages + i >  num_pages) {			contig_pages = num_pages - i;		}		/* for reads over a certain size could initiate async read ahead */		read_size = contig_pages * PAGE_CACHE_SIZE;		/* Read size needs to be in multiples of one page */		read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);		rc = -EAGAIN;		while(rc == -EAGAIN) {			if ((open_file->invalidHandle) && (!open_file->closePend)) {				rc = cifs_reopen_file(file->f_dentry->d_inode,					file, TRUE);				if(rc != 0)					break;			}			rc = CIFSSMBRead(xid, pTcon,				open_file->netfid,				read_size, offset,				&bytes_read, &smb_read_data);			/* BB need to check return code here */			if(rc== -EAGAIN) {				if(smb_read_data) {					cifs_buf_release(smb_read_data);					smb_read_data = NULL;				}			}		}		if ((rc < 0) || (smb_read_data == NULL)) {			cFYI(1,("Read error in readpages: %d",rc));			/* clean up remaing pages off list */			while (!list_empty(page_list) && (i < num_pages)) {				page = list_entry(page_list->prev, struct page, lru);				list_del(&page->lru);				page_cache_release(page);			}			break;		} else if (bytes_read > 0) {			pSMBr = (struct smb_com_read_rsp *)smb_read_data;			cifs_copy_cache_pages(mapping, page_list, bytes_read,				smb_read_data + 4 /* RFC1001 hdr */ +				le16_to_cpu(pSMBr->DataOffset), &lru_pvec);			i +=  bytes_read >> PAGE_CACHE_SHIFT;#ifdef CONFIG_CIFS_STATS			atomic_inc(&pTcon->num_reads);			spin_lock(&pTcon->stat_lock);			pTcon->bytes_read += bytes_read;			spin_unlock(&pTcon->stat_lock);#endif			if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {				cFYI(1,("Partial page %d of %d read to cache",i++,num_pages));				i++; /* account for partial page */				/* server copy of file can have smaller size than client */				/* BB do we need to verify this common case ? this case is ok - 				if we are at server EOF we will hit it on next read */			/* while(!list_empty(page_list) && (i < num_pages)) {					page = list_entry(page_list->prev,struct page, list);					list_del(&page->list);					page_cache_release(page);				}				break; */			}		} else {			cFYI(1,("No bytes read (%d) at offset %lld . Cleaning remaining pages from readahead list",bytes_read,offset)); 			/* BB turn off caching and do new lookup on file size at server? */			while (!list_empty(page_list) && (i < num_pages)) {				page = list_entry(page_list->prev, struct page, lru);				list_del(&page->lru);				page_cache_release(page); /* BB removeme - replace with zero of page? */			}			break;		}		if(smb_read_data) {			cifs_buf_release(smb_read_data);			smb_read_data = NULL;		}		bytes_read = 0;	}	pagevec_lru_add(&lru_pvec);/* need to free smb_read_data buf before exit */	if(smb_read_data) {		cifs_buf_release(smb_read_data);		smb_read_data = NULL;	} 	FreeXid(xid);	return rc;}static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * poffset){	char * read_data;	int rc;	page_cache_get(page);	read_data = kmap(page);	/* for reads over a certain size could initiate async read ahead */                                                                                                                           	rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);                                                                                                                           	if (rc < 0)		goto io_error;	else {		cFYI(1,("Bytes read %d ",rc));	}                                                                                                                           	file->f_dentry->d_inode->i_atime = CURRENT_TIME;                                                                                                                           	if(PAGE_CACHE_SIZE > rc) {		memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc);	}	flush_dcache_page(page);	SetPageUptodate(page);	rc = 0;                                                                                                                           io_error:        kunmap(page);	page_cache_release(page);	return rc;}static intcifs_readpage(struct file *file, struct page *page){	loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;	int rc = -EACCES;	int xid;	xid = GetXid();	if (file->private_data == NULL) {		FreeXid(xid);		return -EBADF;	}	cFYI(1,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset));	rc = cifs_readpage_worker(file,page,&offset);	unlock_page(page);	FreeXid(xid);	return rc;}/* We do not want to update the file size from server for inodes   open for write - to avoid races with writepage extending   the file - in the future we could consider allowing   refreshing the inode only on increases in the file size    but this is tricky to do without racing with writebehind   page caching in the current Linux kernel design */   

⌨️ 快捷键说明

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