mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 14:41:39 +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 checkSMB(struct smb_hdr *smb, __u16 mid, int length);
|
||||||
extern int is_valid_oplock_break(struct smb_hdr *smb);
|
extern int is_valid_oplock_break(struct smb_hdr *smb);
|
||||||
extern int is_size_safe_to_change(struct cifsInodeInfo *);
|
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(struct smb_hdr *ptr);
|
||||||
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
|
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
|
||||||
extern int decode_negTokenInit(unsigned char *security_blob, int length,
|
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;
|
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)
|
static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
|
||||||
{
|
{
|
||||||
struct address_space *mapping = page->mapping;
|
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 cifs_sb_info *cifs_sb;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct cifsInodeInfo *cifsInode;
|
struct cifsFileInfo *open_file;
|
||||||
struct cifsFileInfo *open_file = NULL;
|
|
||||||
struct list_head *tmp;
|
|
||||||
struct list_head *tmp1;
|
|
||||||
|
|
||||||
if (!mapping || !mapping->host)
|
if (!mapping || !mapping->host)
|
||||||
return -EFAULT;
|
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)
|
if (mapping->host->i_size - offset < (loff_t)to)
|
||||||
to = (unsigned)(mapping->host->i_size - offset);
|
to = (unsigned)(mapping->host->i_size - offset);
|
||||||
|
|
||||||
cifsInode = CIFS_I(mapping->host);
|
open_file = find_writable_file(CIFS_I(mapping->host));
|
||||||
read_lock(&GlobalSMBSeslock);
|
if (open_file) {
|
||||||
/* BB we should start at the end */
|
bytes_written = cifs_write(open_file->pfile, write_data,
|
||||||
list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
|
to-from, &offset);
|
||||||
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? */
|
/* Does mm or vfs already set times? */
|
||||||
inode->i_atime =
|
inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
|
||||||
inode->i_mtime = current_fs_time(inode->i_sb);
|
if ((bytes_written > 0) && (offset)) {
|
||||||
if ((bytes_written > 0) && (offset)) {
|
rc = 0;
|
||||||
rc = 0;
|
} else if (bytes_written < 0) {
|
||||||
} else if (bytes_written < 0) {
|
if (rc != -EBADF)
|
||||||
if (rc == -EBADF) {
|
rc = bytes_written;
|
||||||
/* 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) {
|
} else {
|
||||||
cFYI(1, ("File instance %p removed", tmp));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
read_unlock(&GlobalSMBSeslock);
|
|
||||||
if (open_file == NULL) {
|
|
||||||
cFYI(1, ("No writeable filehandles for inode"));
|
cFYI(1, ("No writeable filehandles for inode"));
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
}
|
}
|
||||||
@ -1604,40 +1590,12 @@ static int cifs_readpage(struct file *file, struct page *page)
|
|||||||
page caching in the current Linux kernel design */
|
page caching in the current Linux kernel design */
|
||||||
int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
|
int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
|
||||||
{
|
{
|
||||||
struct list_head *tmp;
|
if (cifsInode && find_writable_file(cifsInode))
|
||||||
struct list_head *tmp1;
|
return 0;
|
||||||
struct cifsFileInfo *open_file = NULL;
|
else
|
||||||
int rc = TRUE;
|
return 1;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int cifs_prepare_write(struct file *file, struct page *page,
|
static int cifs_prepare_write(struct file *file, struct page *page,
|
||||||
unsigned from, unsigned to)
|
unsigned from, unsigned to)
|
||||||
{
|
{
|
||||||
|
@ -995,7 +995,6 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||||||
filemap_fdatawait(direntry->d_inode->i_mapping);
|
filemap_fdatawait(direntry->d_inode->i_mapping);
|
||||||
|
|
||||||
if (attrs->ia_valid & ATTR_SIZE) {
|
if (attrs->ia_valid & ATTR_SIZE) {
|
||||||
read_lock(&GlobalSMBSeslock);
|
|
||||||
/* To avoid spurious oplock breaks from server, in the case of
|
/* To avoid spurious oplock breaks from server, in the case of
|
||||||
inodes that we already have open, avoid doing path based
|
inodes that we already have open, avoid doing path based
|
||||||
setting of file size if we can do it by handle.
|
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
|
when the local oplock break takes longer to flush
|
||||||
writebehind data than the SMB timeout for the SetPathInfo
|
writebehind data than the SMB timeout for the SetPathInfo
|
||||||
request would allow */
|
request would allow */
|
||||||
list_for_each(tmp, &cifsInode->openFileList) {
|
open_file = find_writable_file(cifsInode);
|
||||||
open_file = list_entry(tmp, struct cifsFileInfo,
|
if (open_file) {
|
||||||
flist);
|
__u16 nfid = open_file->netfid;
|
||||||
/* We check if file is open for writing first */
|
__u32 npid = open_file->pid;
|
||||||
if ((open_file->pfile) &&
|
rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
|
||||||
((open_file->pfile->f_flags & O_RDWR) ||
|
nfid, npid, FALSE);
|
||||||
(open_file->pfile->f_flags & O_WRONLY))) {
|
cFYI(1,("SetFSize for attrs rc = %d", rc));
|
||||||
if (open_file->invalidHandle == FALSE) {
|
if(rc == -EINVAL) {
|
||||||
/* we found a valid, writeable network
|
int bytes_written;
|
||||||
file handle to use to try to set the
|
rc = CIFSSMBWrite(xid, pTcon,
|
||||||
file size */
|
nfid, 0, attrs->ia_size,
|
||||||
__u16 nfid = open_file->netfid;
|
&bytes_written, NULL, NULL,
|
||||||
__u32 npid = open_file->pid;
|
1 /* 45 seconds */);
|
||||||
read_unlock(&GlobalSMBSeslock);
|
cFYI(1,("Wrt seteof rc %d", rc));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (found == FALSE)
|
|
||||||
read_unlock(&GlobalSMBSeslock);
|
|
||||||
|
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
/* Set file size by pathname rather than by handle
|
/* Set file size by pathname rather than by handle
|
||||||
either because no valid, writeable file handle for
|
either because no valid, writeable file handle for
|
||||||
|
Loading…
Reference in New Issue
Block a user