Skip to content

Commit

Permalink
[CIFS] break ATTR_SIZE changes out into their own function
Browse files Browse the repository at this point in the history
Move the code that handles ATTR_SIZE changes to its own function. This
makes for a smaller function and reduces the level of indentation.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
  • Loading branch information
Jeff Layton authored and Steve French committed Jul 23, 2008
1 parent 09e50d5 commit 8efdbde
Showing 1 changed file with 78 additions and 73 deletions.
151 changes: 78 additions & 73 deletions fs/cifs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1413,14 +1413,89 @@ static int cifs_vmtruncate(struct inode *inode, loff_t offset)
return -ETXTBSY;
}

static int
cifs_set_file_size(struct inode *inode, struct iattr *attrs,
int xid, char *full_path)
{
int rc;
struct cifsFileInfo *open_file;
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifsTconInfo *pTcon = cifs_sb->tcon;

/*
* 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.
* This keeps our caching token (oplock) and avoids timeouts
* when the local oplock break takes longer to flush
* writebehind data than the SMB timeout for the SetPathInfo
* request would allow
*/
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);
atomic_dec(&open_file->wrtPending);
cFYI(1, ("SetFSize for attrs rc = %d", rc));
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
unsigned int bytes_written;
rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size,
&bytes_written, NULL, NULL, 1);
cFYI(1, ("Wrt seteof rc %d", rc));
}
} else
rc = -EINVAL;

if (rc != 0) {
/* Set file size by pathname rather than by handle
either because no valid, writeable file handle for
it was found or because there was an error setting
it by handle */
rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,
false, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
__u16 netfid;
int oplock = 0;

rc = SMBLegacyOpen(xid, pTcon, full_path,
FILE_OPEN, GENERIC_WRITE,
CREATE_NOT_DIR, &netfid, &oplock, NULL,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc == 0) {
unsigned int bytes_written;
rc = CIFSSMBWrite(xid, pTcon, netfid, 0,
attrs->ia_size,
&bytes_written, NULL,
NULL, 1);
cFYI(1, ("wrt seteof rc %d", rc));
CIFSSMBClose(xid, pTcon, netfid);
}
}
}

if (rc == 0) {
rc = cifs_vmtruncate(inode, attrs->ia_size);
cifs_truncate_page(inode->i_mapping, inode->i_size);
}

return rc;
}

int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
{
int xid;
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
char *full_path = NULL;
int rc = -EACCES;
struct cifsFileInfo *open_file = NULL;
FILE_BASIC_INFO time_buf;
bool set_time = false;
bool set_dosattr = false;
Expand Down Expand Up @@ -1472,78 +1547,8 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
}

if (attrs->ia_valid & ATTR_SIZE) {
/* 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.
This keeps our caching token (oplock) and avoids timeouts
when the local oplock break takes longer to flush
writebehind data than the SMB timeout for the SetPathInfo
request would allow */

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);
atomic_dec(&open_file->wrtPending);
cFYI(1, ("SetFSize for attrs rc = %d", rc));
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
unsigned 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));
}
} else
rc = -EINVAL;

if (rc != 0) {
/* Set file size by pathname rather than by handle
either because no valid, writeable file handle for
it was found or because there was an error setting
it by handle */
rc = CIFSSMBSetEOF(xid, pTcon, full_path,
attrs->ia_size, false,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
__u16 netfid;
int oplock = 0;

rc = SMBLegacyOpen(xid, pTcon, full_path,
FILE_OPEN, GENERIC_WRITE,
CREATE_NOT_DIR, &netfid, &oplock,
NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc == 0) {
unsigned int bytes_written;
rc = CIFSSMBWrite(xid, pTcon,
netfid, 0,
attrs->ia_size,
&bytes_written, NULL,
NULL, 1 /* 45 sec */);
cFYI(1, ("wrt seteof rc %d", rc));
CIFSSMBClose(xid, pTcon, netfid);
}

}
}

/* Server is ok setting allocation size implicitly - no need
to call:
CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, true,
cifs_sb->local_nls);
*/

if (rc == 0) {
rc = cifs_vmtruncate(inode, attrs->ia_size);
cifs_truncate_page(inode->i_mapping, inode->i_size);
} else
rc = cifs_set_file_size(inode, attrs, xid, full_path);
if (rc != 0)
goto cifs_setattr_exit;
}

Expand Down

0 comments on commit 8efdbde

Please sign in to comment.