📄 file.c
字号:
if(list_empty(&(CIFS_I(inode)->openFileList))) { cFYI(1,("closing last open instance for inode %p",inode)); /* if the file is not open we do not know if we can cache info on this inode, much less write behind and read ahead */ CIFS_I(inode)->clientCanCacheRead = FALSE; CIFS_I(inode)->clientCanCacheAll = FALSE; } if((rc ==0) && CIFS_I(inode)->write_behind_rc) rc = CIFS_I(inode)->write_behind_rc; FreeXid(xid); return rc;}intcifs_closedir(struct inode *inode, struct file *file){ int rc = 0; int xid; struct cifsFileInfo *pSMBFileStruct = (struct cifsFileInfo *) file->private_data; cFYI(1, ("Closedir inode = 0x%p with ", inode)); xid = GetXid(); if (pSMBFileStruct) { cFYI(1, ("Freeing private data in close dir")); kfree(file->private_data); file->private_data = NULL; } FreeXid(xid); return rc;}intcifs_lock(struct file *file, int cmd, struct file_lock *pfLock){ int rc, xid; __u32 lockType = LOCKING_ANDX_LARGE_FILES; __u32 numLock = 0; __u32 numUnlock = 0; __u64 length; int wait_flag = FALSE; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; length = 1 + pfLock->fl_end - pfLock->fl_start; rc = -EACCES; xid = GetXid(); cFYI(1, ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld", cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start, pfLock->fl_end)); if (pfLock->fl_flags & FL_POSIX) cFYI(1, ("Posix ")); if (pfLock->fl_flags & FL_FLOCK) cFYI(1, ("Flock ")); if (pfLock->fl_flags & FL_SLEEP) { cFYI(1, ("Blocking lock ")); wait_flag = TRUE; } if (pfLock->fl_flags & FL_ACCESS) cFYI(1, ("Process suspended by mandatory locking - not implemented yet ")); if (pfLock->fl_flags & FL_LEASE) cFYI(1, ("Lease on file - not implemented yet")); if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE))) cFYI(1, ("Unknown lock flags 0x%x",pfLock->fl_flags)); if (pfLock->fl_type == F_WRLCK) { cFYI(1, ("F_WRLCK ")); numLock = 1; } else if (pfLock->fl_type == F_UNLCK) { cFYI(1, ("F_UNLCK ")); numUnlock = 1; } else if (pfLock->fl_type == F_RDLCK) { cFYI(1, ("F_RDLCK ")); lockType |= LOCKING_ANDX_SHARED_LOCK; numLock = 1; } else if (pfLock->fl_type == F_EXLCK) { cFYI(1, ("F_EXLCK ")); numLock = 1; } else if (pfLock->fl_type == F_SHLCK) { cFYI(1, ("F_SHLCK ")); lockType |= LOCKING_ANDX_SHARED_LOCK; numLock = 1; } else cFYI(1, ("Unknown type of lock ")); cifs_sb = CIFS_SB(file->f_dentry->d_sb); pTcon = cifs_sb->tcon; if (file->private_data == NULL) { FreeXid(xid); return -EBADF; } if (IS_GETLK(cmd)) { rc = CIFSSMBLock(xid, pTcon, ((struct cifsFileInfo *) file-> private_data)->netfid, length, pfLock->fl_start, 0, 1, lockType, 0 /* wait flag */ ); if (rc == 0) { rc = CIFSSMBLock(xid, pTcon, ((struct cifsFileInfo *) file-> private_data)->netfid, length, pfLock->fl_start, 1 /* numUnlock */ , 0 /* numLock */ , lockType, 0 /* wait flag */ ); pfLock->fl_type = F_UNLCK; if (rc != 0) cERROR(1, ("Error unlocking previously locked range %d during test of lock ", rc)); rc = 0; } else { /* if rc == ERR_SHARING_VIOLATION ? */ rc = 0; /* do not change lock type to unlock since range in use */ } FreeXid(xid); return rc; } rc = CIFSSMBLock(xid, pTcon, ((struct cifsFileInfo *) file->private_data)-> netfid, length, pfLock->fl_start, numUnlock, numLock, lockType, wait_flag); if (rc == 0 && (pfLock->fl_flags & FL_POSIX)) posix_lock_file(file, pfLock); FreeXid(xid); return rc;}ssize_tcifs_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(file->f_dentry == NULL) return -EBADF; cifs_sb = CIFS_SB(file->f_dentry->d_sb); if(cifs_sb == NULL) { return -EBADF; } pTcon = cifs_sb->tcon; /*cFYI(1, (" write %d bytes to offset %lld of %s", write_size, *poffset, file->f_dentry->d_name.name)); */ if (file->private_data == NULL) { return -EBADF; } else { open_file = (struct cifsFileInfo *) file->private_data; } xid = GetXid(); if(file->f_dentry->d_inode == NULL) { FreeXid(xid); return -EBADF; } if (*poffset > file->f_dentry->d_inode->i_size) 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) { if((file->f_dentry == NULL) || (file->f_dentry->d_inode == NULL)) { FreeXid(xid); return total_written; } /* 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->f_dentry->d_inode, file,FALSE); if(rc != 0) break; } rc = CIFSSMBWrite(xid, pTcon, open_file->netfid, write_size - total_written, *poffset, &bytes_written, 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 */ }#ifdef CONFIG_CIFS_STATS if(total_written > 0) { atomic_inc(&pTcon->num_writes); spin_lock(&pTcon->stat_lock); pTcon->bytes_written += total_written; spin_unlock(&pTcon->stat_lock); }#endif /* since the write may have blocked check these pointers again */ if(file->f_dentry) { if(file->f_dentry->d_inode) { file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime = CURRENT_TIME; if (total_written > 0) { if (*poffset > file->f_dentry->d_inode->i_size) i_size_write(file->f_dentry->d_inode, *poffset); } mark_inode_dirty_sync(file->f_dentry->d_inode); } } FreeXid(xid); return total_written;}static intcifs_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 cifsInodeInfo *cifsInode; struct cifsFileInfo *open_file = NULL; struct list_head *tmp; struct list_head *tmp1; if (!mapping) { return -EFAULT; } else if(!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); cifsInode = CIFS_I(mapping->host); read_lock(&GlobalSMBSeslock); /* BB we should start at the end */ list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) { open_file = list_entry(tmp,struct cifsFileInfo, flist); if(open_file->closePend) continue; /* We check if file is open for writing first */ if((open_file->pfile) && ((open_file->pfile->f_flags & O_RDWR) || (open_file->pfile->f_flags & O_WRONLY))) { read_unlock(&GlobalSMBSeslock); bytes_written = cifs_write(open_file->pfile, write_data, to-from, &offset); read_lock(&GlobalSMBSeslock); /* Does mm or vfs already set times? */ inode->i_atime = inode->i_mtime = CURRENT_TIME; if ((bytes_written > 0) && (offset)) { rc = 0; } else if(bytes_written < 0) { if(rc == -EBADF) { /* have seen a case in which kernel seemed to have closed/freed a file even with writes active so we might as well see if there are other file structs to try for the same inode before giving up */ continue; } else rc = bytes_written; } break; /* now that we found a valid file handle and tried to write to it we are done, no sense continuing to loop looking for another */ } if(tmp->next == NULL) { cFYI(1,("File instance %p removed",tmp)); break; } } read_unlock(&GlobalSMBSeslock); if(open_file == NULL) { cFYI(1,("No writeable filehandles for inode")); rc = -EIO; } kunmap(page); return rc;}#if 0static intcifs_writepages(struct address_space *mapping, struct writeback_control *wbc){ int rc = -EFAULT; int xid; xid = GetXid();/* call 16K write then Setpageuptodate */ FreeXid(xid); return rc;}#endifstatic intcifs_writepage(struct page* page, struct writeback_control *wbc){ int rc = -EFAULT; int xid; xid = GetXid();/* BB add check for wbc flags */ page_cache_get(page); if (!PageUptodate(page)) { cFYI(1,("ppw - page not up to date")); } rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE); SetPageUptodate(page); /* BB add check for error and Clearuptodate? */ unlock_page(page); page_cache_release(page); FreeXid(xid); return rc;}static intcifs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to){ int xid; int rc = 0; struct inode *inode = page->mapping->host; loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; char * page_data; xid = GetXid(); cFYI(1,("commit write for page %p up to position %lld for %d",page,position,to)); if (position > inode->i_size){ i_size_write(inode, position); /*if (file->private_data == NULL) { rc = -EBADF; } else { open_file = (struct cifsFileInfo *)file->private_data; cifs_sb = CIFS_SB(inode->i_sb); rc = -EAGAIN; while(rc == -EAGAIN) { if((open_file->invalidHandle) && (!open_file->closePend)) { rc = cifs_reopen_file(file->f_dentry->d_inode,file); if(rc != 0) break; } if(!open_file->closePend) { rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon, position, open_file->netfid, open_file->pid,FALSE); } else { rc = -EBADF; break; } } cFYI(1,(" SetEOF (commit write) rc = %d",rc)); }*/ } if (!PageUptodate(page)) { position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset; /* can not rely on (or let) writepage write this data */ if(to < offset) { cFYI(1,("Illegal offsets, can not copy from %d to %d", offset,to)); FreeXid(xid);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -