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

📄 file.c

📁 Linux内核自带的cifs模块
💻 C
📖 第 1 页 / 共 5 页
字号:
	int rc = 0;	unsigned int bytes_written = 0;	unsigned int total_written;	struct cifs_sb_info *cifs_sb;	struct cifsTconInfo *pTcon;	int xid, long_op;	struct cifsFileInfo *open_file;#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)	cifs_sb = CIFS_SB(file->f_dentry->d_sb);#else	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);#endif	pTcon = cifs_sb->tcon;	/* cFYI(1,	   (" write %d bytes to offset %lld of %s", write_size,	   *poffset, file->f_path.dentry->d_name.name)); */	if (file->private_data == NULL)		return -EBADF;	open_file = (struct cifsFileInfo *) file->private_data;	xid = GetXid();#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)	if (*poffset > file->f_dentry->d_inode->i_size)#else	if (*poffset > file->f_path.dentry->d_inode->i_size)#endif		long_op = 2; /* writes past end of file can take a long time */	else		long_op = 1;	for (total_written = 0; write_size > total_written;	     total_written += bytes_written) {		rc = -EAGAIN;		while (rc == -EAGAIN) {			if (file->private_data == NULL) {				/* file has been closed on us */				FreeXid(xid);			/* if we have gotten here we have written some data			   and blocked, and the file has been freed on us while			   we blocked so return what we managed to write */				return total_written;			}			if (open_file->closePend) {				FreeXid(xid);				if (total_written)					return total_written;				else					return -EBADF;			}			if (open_file->invalidHandle) {				/* we could deadlock if we called				   filemap_fdatawait from here so tell				   reopen_file not to flush data to server				   now */				rc = cifs_reopen_file(file, FALSE);				if (rc != 0)					break;			}			rc = CIFSSMBWrite(xid, pTcon,				open_file->netfid,				min_t(const int, cifs_sb->wsize,				      write_size - total_written),				*poffset, &bytes_written,				NULL, write_data + total_written, long_op);		}		if (rc || (bytes_written == 0)) {			if (total_written)				break;			else {				FreeXid(xid);				return rc;			}		} else			*poffset += bytes_written;		long_op = FALSE; /* subsequent writes fast -				    15 seconds is plenty */	}	cifs_stats_bytes_written(pTcon, total_written);	/* since the write may have blocked check these pointers again */#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)	if ((file->f_dentry) && (file->f_dentry->d_inode)) {		struct inode *inode = file->f_dentry->d_inode;/* Do not update local mtime - server will set its actual value on write *		inode->i_ctime = inode->i_mtime = * 			current_fs_time(inode->i_sb);*/		if (total_written > 0) {			spin_lock(&inode->i_lock);			if (*poffset > file->f_dentry->d_inode->i_size)				i_size_write(file->f_dentry->d_inode,					*poffset);			spin_unlock(&inode->i_lock);		}		mark_inode_dirty_sync(file->f_dentry->d_inode);#else	if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) {		struct inode *inode = file->f_path.dentry->d_inode;/* Do not update local mtime - server will set its actual value on write *		inode->i_ctime = inode->i_mtime = * 			current_fs_time(inode->i_sb);*/		if (total_written > 0) {			spin_lock(&inode->i_lock);			if (*poffset > file->f_path.dentry->d_inode->i_size)				i_size_write(file->f_path.dentry->d_inode,					*poffset);			spin_unlock(&inode->i_lock);		}		mark_inode_dirty_sync(file->f_path.dentry->d_inode);#endif	}	FreeXid(xid);	return total_written;}static ssize_t cifs_write(struct file *file, const char *write_data,	size_t write_size, loff_t *poffset){	int rc = 0;	unsigned int bytes_written = 0;	unsigned int total_written;	struct cifs_sb_info *cifs_sb;	struct cifsTconInfo *pTcon;	int xid, long_op;	struct cifsFileInfo *open_file;#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)	cifs_sb = CIFS_SB(file->f_dentry->d_sb);	pTcon = cifs_sb->tcon;	cFYI(1, ("write %zd bytes to offset %lld of %s", write_size,	   *poffset, file->f_dentry->d_name.name));	if (file->private_data == NULL)		return -EBADF;	open_file = (struct cifsFileInfo *)file->private_data;	xid = GetXid();	if (*poffset > file->f_dentry->d_inode->i_size)#else	cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);	pTcon = cifs_sb->tcon;	cFYI(1, ("write %zd bytes to offset %lld of %s", write_size,	   *poffset, file->f_path.dentry->d_name.name));	if (file->private_data == NULL)		return -EBADF;	open_file = (struct cifsFileInfo *)file->private_data;	xid = GetXid();	if (*poffset > file->f_path.dentry->d_inode->i_size)#endif			long_op = 2; /* writes past end of file can take a long time */	else		long_op = 1;	for (total_written = 0; write_size > total_written;	     total_written += bytes_written) {		rc = -EAGAIN;		while (rc == -EAGAIN) {			if (file->private_data == NULL) {				/* file has been closed on us */				FreeXid(xid);			/* if we have gotten here we have written some data			   and blocked, and the file has been freed on us			   while we blocked so return what we managed to			   write */				return total_written;			}			if (open_file->closePend) {				FreeXid(xid);				if (total_written)					return total_written;				else					return -EBADF;			}			if (open_file->invalidHandle) {				/* we could deadlock if we called				   filemap_fdatawait from here so tell				   reopen_file not to flush data to				   server now */				rc = cifs_reopen_file(file, FALSE);				if (rc != 0)					break;			}			if (experimEnabled || (pTcon->ses->server &&				((pTcon->ses->server->secMode &				(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))				== 0))) {				struct kvec iov[2];				unsigned int len;				len = min((size_t)cifs_sb->wsize,					  write_size - total_written);				/* iov[0] is reserved for smb header */				iov[1].iov_base = (char *)write_data +						  total_written;				iov[1].iov_len = len;				rc = CIFSSMBWrite2(xid, pTcon,						open_file->netfid, len,						*poffset, &bytes_written,						iov, 1, long_op);			} else				rc = CIFSSMBWrite(xid, pTcon,					 open_file->netfid,					 min_t(const int, cifs_sb->wsize,					       write_size - total_written),					 *poffset, &bytes_written,					 write_data + total_written,					 NULL, long_op);		}		if (rc || (bytes_written == 0)) {			if (total_written)				break;			else {				FreeXid(xid);				return rc;			}		} else			*poffset += bytes_written;		long_op = FALSE; /* subsequent writes fast -				    15 seconds is plenty */	}	cifs_stats_bytes_written(pTcon, total_written);	/* since the write may have blocked check these pointers again */#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)	if ((file->f_dentry) && (file->f_dentry->d_inode)) {/*BB We could make this contingent on superblock ATIME flag too *//*		file->f_dentry->d_inode->i_ctime =		file->f_dentry->d_inode->i_mtime = CURRENT_TIME;*/		if (total_written > 0) {			spin_lock(&file->f_dentry->d_inode->i_lock);			if (*poffset > file->f_dentry->d_inode->i_size)				i_size_write(file->f_dentry->d_inode,					     *poffset);			spin_unlock(&file->f_dentry->d_inode->i_lock);		}		mark_inode_dirty_sync(file->f_dentry->d_inode);#else	if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) {/*BB We could make this contingent on superblock ATIME flag too *//*		file->f_path.dentry->d_inode->i_ctime =		file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;*/		if (total_written > 0) {			spin_lock(&file->f_path.dentry->d_inode->i_lock);			if (*poffset > file->f_path.dentry->d_inode->i_size)				i_size_write(file->f_path.dentry->d_inode,					     *poffset);			spin_unlock(&file->f_path.dentry->d_inode->i_lock);		}		mark_inode_dirty_sync(file->f_path.dentry->d_inode);#endif	}	FreeXid(xid);	return total_written;}struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode){	struct cifsFileInfo *open_file;	int rc;	/* Having a null inode here (because mapping->host was set to zero by	the VFS or MM) should not happen but we had reports of on oops (due to	it being zero) during stress testcases so we need to check for it */	if (cifs_inode == NULL) {		cERROR(1, ("Null inode passed to cifs_writeable_file"));#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 19)		dump_stack();#endif		return NULL;	}	read_lock(&GlobalSMBSeslock);	list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {		if (open_file->closePend)			continue;		if (open_file->pfile &&		    ((open_file->pfile->f_flags & O_RDWR) ||		     (open_file->pfile->f_flags & O_WRONLY))) {			atomic_inc(&open_file->wrtPending);			read_unlock(&GlobalSMBSeslock);			if (open_file->invalidHandle) {				rc = cifs_reopen_file(open_file->pfile, FALSE);				/* if it fails, try another handle - might be */				/* dangerous to hold up writepages with retry */				if (rc) {					cFYI(1, ("wp failed on reopen file"));					read_lock(&GlobalSMBSeslock);					/* can not use this handle, no write					pending on this one after all */					atomic_dec(&open_file->wrtPending);					continue;				}			}			if (open_file->closePend) {				read_lock(&GlobalSMBSeslock);				atomic_dec(&open_file->wrtPending);				continue;			}			return open_file;		}	}	read_unlock(&GlobalSMBSeslock);	return NULL;}static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to){	struct address_space *mapping = page->mapping;	loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;	char *write_data;	int rc = -EFAULT;	int bytes_written = 0;	struct cifs_sb_info *cifs_sb;	struct cifsTconInfo *pTcon;	struct inode *inode;	struct cifsFileInfo *open_file;	if (!mapping || !mapping->host)		return -EFAULT;	inode = page->mapping->host;	cifs_sb = CIFS_SB(inode->i_sb);	pTcon = cifs_sb->tcon;	offset += (loff_t)from;	write_data = kmap(page);	write_data += from;	if ((to > PAGE_CACHE_SIZE) || (from > to)) {		kunmap(page);		return -EIO;	}	/* racing with truncate? */	if (offset > mapping->host->i_size) {		kunmap(page);		return 0; /* don't care */	}	/* check to make sure that we are not extending the file */	if (mapping->host->i_size - offset < (loff_t)to)		to = (unsigned)(mapping->host->i_size - offset);	open_file = find_writable_file(CIFS_I(mapping->host));	if (open_file) {		bytes_written = cifs_write(open_file->pfile, write_data,					   to-from, &offset);		atomic_dec(&open_file->wrtPending);		/* Does mm or vfs already set times? */		inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);		if ((bytes_written > 0) && (offset)) {			rc = 0;		} else if (bytes_written < 0) {			if (rc != -EBADF)				rc = bytes_written;		}	} else {		cFYI(1, ("No writeable filehandles for inode"));		rc = -EIO;	}	kunmap(page);	return rc;}#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 14)static int cifs_writepages(struct address_space *mapping,			   struct writeback_control *wbc){	struct backing_dev_info *bdi = mapping->backing_dev_info;	unsigned int bytes_to_write;	unsigned int bytes_written;	struct cifs_sb_info *cifs_sb;	int done = 0;	pgoff_t end;	pgoff_t index;#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)	int range_whole = 0;#else			int is_range = 0;#endif /* 2.6.17 */	struct kvec *iov;	int len;	int n_iov = 0;	pgoff_t next;	int nr_pages;	__u64 offset = 0;	struct cifsFileInfo *open_file;	struct page *page;	struct pagevec pvec;	int rc = 0;	int scanned = 0;	int xid;	cifs_sb = CIFS_SB(mapping->host->i_sb);	/*	 * If wsize is smaller that the page cache size, default to writing	 * one page at a time via cifs_writepage	 */	if (cifs_sb->wsize < PAGE_CACHE_SIZE)		return generic_writepages(mapping, wbc);	if ((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))		if (cifs_sb->tcon->ses->server->secMode &				(SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))			if (!experimEnabled)				return generic_writepages(mapping, wbc);	iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL);	if (iov == NULL)		return generic_writepages(mapping, wbc);	/*	 * BB: Is this meaningful for a non-block-device file system?	 * If it is, we should test it again after we do I/O	 */	if (wbc->nonblocking && bdi_write_congested(bdi)) {		wbc->encountered_congestion = 1;		kfree(iov);		return 0;	}	xid = GetXid();	pagevec_init(&pvec, 0);#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)	if (wbc->range_cyclic) {		index = mapping->writeback_index; /* Start from prev offset */		end = -1;	} else {		index = wbc->range_start >> PAGE_CACHE_SHIFT;		end = wbc->range_end >> PAGE_CACHE_SHIFT;		if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)			range_whole = 1;		scanned = 1;	}#else	end = -1;	if (wbc->sync_mode == WB_SYNC_NONE)		index = mapping->writeback_index; /* Start from prev offset */	else {		index = 0;		scanned = 1;	}

⌨️ 快捷键说明

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