mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 20:51:44 +00:00
CIFS: Create routine find_writable_file to reduce redundant code
Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
parent
04c08816d6
commit
6148a742b2
@ -54,6 +54,7 @@ extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
|
||||
extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
|
||||
extern int is_valid_oplock_break(struct smb_hdr *smb);
|
||||
extern int is_size_safe_to_change(struct cifsInodeInfo *);
|
||||
extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
|
||||
extern unsigned int smbCalcSize(struct smb_hdr *ptr);
|
||||
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
|
||||
extern int decode_negTokenInit(unsigned char *security_blob, int length,
|
||||
|
112
fs/cifs/file.c
112
fs/cifs/file.c
@ -904,6 +904,25 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
|
||||
return total_written;
|
||||
}
|
||||
|
||||
static struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
|
||||
{
|
||||
struct cifsFileInfo *open_file;
|
||||
|
||||
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))) {
|
||||
read_unlock(&GlobalSMBSeslock);
|
||||
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;
|
||||
@ -914,10 +933,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
|
||||
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;
|
||||
struct cifsFileInfo *open_file;
|
||||
|
||||
if (!mapping || !mapping->host)
|
||||
return -EFAULT;
|
||||
@ -945,49 +961,19 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
|
||||
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);
|
||||
open_file = find_writable_file(CIFS_I(mapping->host));
|
||||
if (open_file) {
|
||||
bytes_written = cifs_write(open_file->pfile, write_data,
|
||||
to-from, &offset);
|
||||
/* 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) {
|
||||
/* 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 */
|
||||
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;
|
||||
}
|
||||
if (tmp->next == NULL) {
|
||||
cFYI(1, ("File instance %p removed", tmp));
|
||||
break;
|
||||
}
|
||||
}
|
||||
read_unlock(&GlobalSMBSeslock);
|
||||
if (open_file == NULL) {
|
||||
} else {
|
||||
cFYI(1, ("No writeable filehandles for inode"));
|
||||
rc = -EIO;
|
||||
}
|
||||
@ -1604,40 +1590,12 @@ static int cifs_readpage(struct file *file, struct page *page)
|
||||
page caching in the current Linux kernel design */
|
||||
int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
|
||||
{
|
||||
struct list_head *tmp;
|
||||
struct list_head *tmp1;
|
||||
struct cifsFileInfo *open_file = NULL;
|
||||
int rc = TRUE;
|
||||
|
||||
if (cifsInode == NULL)
|
||||
return rc;
|
||||
|
||||
read_lock(&GlobalSMBSeslock);
|
||||
list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
|
||||
open_file = list_entry(tmp, struct cifsFileInfo, flist);
|
||||
if (open_file == NULL)
|
||||
break;
|
||||
if (open_file->closePend)
|
||||
continue;
|
||||
/* We check if file is open for writing,
|
||||
BB we could supplement this with a check to see if file size
|
||||
changes have been flushed to server - ie inode metadata dirty */
|
||||
if ((open_file->pfile) &&
|
||||
((open_file->pfile->f_flags & O_RDWR) ||
|
||||
(open_file->pfile->f_flags & O_WRONLY))) {
|
||||
rc = FALSE;
|
||||
break;
|
||||
}
|
||||
if (tmp->next == NULL) {
|
||||
cFYI(1, ("File instance %p removed", tmp));
|
||||
break;
|
||||
}
|
||||
}
|
||||
read_unlock(&GlobalSMBSeslock);
|
||||
return rc;
|
||||
if (cifsInode && find_writable_file(cifsInode))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int cifs_prepare_write(struct file *file, struct page *page,
|
||||
unsigned from, unsigned to)
|
||||
{
|
||||
|
@ -995,7 +995,6 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||
filemap_fdatawait(direntry->d_inode->i_mapping);
|
||||
|
||||
if (attrs->ia_valid & ATTR_SIZE) {
|
||||
read_lock(&GlobalSMBSeslock);
|
||||
/* To avoid spurious oplock breaks from server, in the case of
|
||||
inodes that we already have open, avoid doing path based
|
||||
setting of file size if we can do it by handle.
|
||||
@ -1003,49 +1002,22 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||
when the local oplock break takes longer to flush
|
||||
writebehind data than the SMB timeout for the SetPathInfo
|
||||
request would allow */
|
||||
list_for_each(tmp, &cifsInode->openFileList) {
|
||||
open_file = list_entry(tmp, struct cifsFileInfo,
|
||||
flist);
|
||||
/* 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))) {
|
||||
if (open_file->invalidHandle == FALSE) {
|
||||
/* we found a valid, writeable network
|
||||
file handle to use to try to set the
|
||||
file size */
|
||||
__u16 nfid = open_file->netfid;
|
||||
__u32 npid = open_file->pid;
|
||||
read_unlock(&GlobalSMBSeslock);
|
||||
found = TRUE;
|
||||
rc = CIFSSMBSetFileSize(xid, pTcon,
|
||||
attrs->ia_size, nfid, npid,
|
||||
FALSE);
|
||||
cFYI(1, ("SetFileSize by handle "
|
||||
"(setattrs) rc = %d", rc));
|
||||
/* Do not need reopen and retry on
|
||||
EAGAIN since we will retry by
|
||||
pathname below */
|
||||
|
||||
/* now that we found one valid file
|
||||
handle no sense continuing to loop
|
||||
trying others, so break here */
|
||||
if(rc == -EINVAL) {
|
||||
int bytes_written;
|
||||
rc = CIFSSMBWrite(xid, pTcon,
|
||||
nfid, 0,
|
||||
attrs->ia_size,
|
||||
&bytes_written, NULL,
|
||||
NULL, 1 /* 45 sec */);
|
||||
cFYI(1,("wrt seteof rc %d",rc));
|
||||
}
|
||||
break;
|
||||
}
|
||||
open_file = find_writable_file(cifsInode);
|
||||
if (open_file) {
|
||||
__u16 nfid = open_file->netfid;
|
||||
__u32 npid = open_file->pid;
|
||||
rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
|
||||
nfid, npid, FALSE);
|
||||
cFYI(1,("SetFSize for attrs rc = %d", rc));
|
||||
if(rc == -EINVAL) {
|
||||
int bytes_written;
|
||||
rc = CIFSSMBWrite(xid, pTcon,
|
||||
nfid, 0, attrs->ia_size,
|
||||
&bytes_written, NULL, NULL,
|
||||
1 /* 45 seconds */);
|
||||
cFYI(1,("Wrt seteof rc %d", rc));
|
||||
}
|
||||
}
|
||||
if (found == FALSE)
|
||||
read_unlock(&GlobalSMBSeslock);
|
||||
|
||||
if (rc != 0) {
|
||||
/* Set file size by pathname rather than by handle
|
||||
either because no valid, writeable file handle for
|
||||
|
Loading…
Reference in New Issue
Block a user