Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 143692
b: refs/heads/master
c: fbec9ab
h: refs/heads/master
v: v3
  • Loading branch information
Jeff Layton authored and Steve French committed Apr 17, 2009
1 parent 5ad143c commit 4750b9f
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d036f50fc202e1a851a25dc5edc215ebd0086201
refs/heads/master: fbec9ab952d4810960e620035c8e95f0fbbae4be
1 change: 1 addition & 0 deletions trunk/fs/cifs/cifsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ cifs_alloc_inode(struct super_block *sb)
cifs_inode->clientCanCacheAll = false;
cifs_inode->delete_pending = false;
cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */
cifs_inode->server_eof = 0;

/* Can not set i_flags here - they get immediately overwritten
to zero by the VFS */
Expand Down
1 change: 1 addition & 0 deletions trunk/fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ struct cifsInodeInfo {
bool clientCanCacheAll:1; /* read and writebehind oplock */
bool oplockPending:1;
bool delete_pending:1; /* DELETE_ON_CLOSE is set */
u64 server_eof; /* current file size on server */
struct inode vfs_inode;
};

Expand Down
4 changes: 2 additions & 2 deletions trunk/fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1626,6 +1626,8 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
int smb_hdr_len;
int resp_buf_type = 0;

*nbytes = 0;

cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count));

if (tcon->ses->capabilities & CAP_LARGE_FILES) {
Expand Down Expand Up @@ -1682,11 +1684,9 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
cifs_stats_inc(&tcon->num_writes);
if (rc) {
cFYI(1, ("Send error Write2 = %d", rc));
*nbytes = 0;
} else if (resp_buf_type == 0) {
/* presumably this can not happen, but best to be safe */
rc = -EIO;
*nbytes = 0;
} else {
WRITE_RSP *pSMBr = (WRITE_RSP *)iov[0].iov_base;
*nbytes = le16_to_cpu(pSMBr->CountHigh);
Expand Down
64 changes: 50 additions & 14 deletions trunk/fs/cifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,40 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
return rc;
}

/*
* Set the timeout on write requests past EOF. For some servers (Windows)
* these calls can be very long.
*
* If we're writing >10M past the EOF we give a 180s timeout. Anything less
* than that gets a 45s timeout. Writes not past EOF get 15s timeouts.
* The 10M cutoff is totally arbitrary. A better scheme for this would be
* welcome if someone wants to suggest one.
*
* We may be able to do a better job with this if there were some way to
* declare that a file should be sparse.
*/
static int
cifs_write_timeout(struct cifsInodeInfo *cifsi, loff_t offset)
{
if (offset <= cifsi->server_eof)
return CIFS_STD_OP;
else if (offset > (cifsi->server_eof + (10 * 1024 * 1024)))
return CIFS_VLONG_OP;
else
return CIFS_LONG_OP;
}

/* update the file size (if needed) after a write */
static void
cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
unsigned int bytes_written)
{
loff_t end_of_write = offset + bytes_written;

if (end_of_write > cifsi->server_eof)
cifsi->server_eof = end_of_write;
}

ssize_t cifs_user_write(struct file *file, const char __user *write_data,
size_t write_size, loff_t *poffset)
{
Expand All @@ -981,6 +1015,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
struct cifsTconInfo *pTcon;
int xid, long_op;
struct cifsFileInfo *open_file;
struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode);

cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);

Expand All @@ -1000,11 +1035,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,

xid = GetXid();

if (*poffset > file->f_path.dentry->d_inode->i_size)
long_op = CIFS_VLONG_OP; /* writes past EOF take long time */
else
long_op = CIFS_LONG_OP;

long_op = cifs_write_timeout(cifsi, *poffset);
for (total_written = 0; write_size > total_written;
total_written += bytes_written) {
rc = -EAGAIN;
Expand Down Expand Up @@ -1048,8 +1079,10 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data,
FreeXid(xid);
return rc;
}
} else
} else {
cifs_update_eof(cifsi, *poffset, bytes_written);
*poffset += bytes_written;
}
long_op = CIFS_STD_OP; /* subsequent writes fast -
15 seconds is plenty */
}
Expand Down Expand Up @@ -1085,6 +1118,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
struct cifsTconInfo *pTcon;
int xid, long_op;
struct cifsFileInfo *open_file;
struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode);

cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);

Expand All @@ -1099,11 +1133,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data,

xid = GetXid();

if (*poffset > file->f_path.dentry->d_inode->i_size)
long_op = CIFS_VLONG_OP; /* writes past EOF can be slow */
else
long_op = CIFS_LONG_OP;

long_op = cifs_write_timeout(cifsi, *poffset);
for (total_written = 0; write_size > total_written;
total_written += bytes_written) {
rc = -EAGAIN;
Expand Down Expand Up @@ -1166,8 +1196,10 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
FreeXid(xid);
return rc;
}
} else
} else {
cifs_update_eof(cifsi, *poffset, bytes_written);
*poffset += bytes_written;
}
long_op = CIFS_STD_OP; /* subsequent writes fast -
15 seconds is plenty */
}
Expand Down Expand Up @@ -1380,11 +1412,12 @@ static int cifs_writepages(struct address_space *mapping,
int nr_pages;
__u64 offset = 0;
struct cifsFileInfo *open_file;
struct cifsInodeInfo *cifsi = CIFS_I(mapping->host);
struct page *page;
struct pagevec pvec;
int rc = 0;
int scanned = 0;
int xid;
int xid, long_op;

cifs_sb = CIFS_SB(mapping->host->i_sb);

Expand Down Expand Up @@ -1528,12 +1561,15 @@ static int cifs_writepages(struct address_space *mapping,
cERROR(1, ("No writable handles for inode"));
rc = -EBADF;
} else {
long_op = cifs_write_timeout(cifsi, offset);
rc = CIFSSMBWrite2(xid, cifs_sb->tcon,
open_file->netfid,
bytes_to_write, offset,
&bytes_written, iov, n_iov,
CIFS_LONG_OP);
long_op);
atomic_dec(&open_file->wrtPending);
cifs_update_eof(cifsi, offset, bytes_written);

if (rc || bytes_written < bytes_to_write) {
cERROR(1, ("Write2 ret %d, wrote %d",
rc, bytes_written));
Expand Down
8 changes: 5 additions & 3 deletions trunk/fs/cifs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ static void cifs_unix_info_to_inode(struct inode *inode,

inode->i_nlink = le64_to_cpu(info->Nlinks);

cifsInfo->server_eof = end_of_file;
spin_lock(&inode->i_lock);
if (is_size_safe_to_change(cifsInfo, end_of_file)) {
/*
Expand Down Expand Up @@ -606,12 +607,12 @@ int cifs_get_inode_info(struct inode **pinode,
inode->i_mode |= S_IFREG;
}

cifsInfo->server_eof = le64_to_cpu(pfindData->EndOfFile);
spin_lock(&inode->i_lock);
if (is_size_safe_to_change(cifsInfo,
le64_to_cpu(pfindData->EndOfFile))) {
if (is_size_safe_to_change(cifsInfo, cifsInfo->server_eof)) {
/* can not safely shrink the file size here if the
client is writing to it due to potential races */
i_size_write(inode, le64_to_cpu(pfindData->EndOfFile));
i_size_write(inode, cifsInfo->server_eof);

/* 512 bytes (2**9) is the fake blocksize that must be
used for this calculation */
Expand Down Expand Up @@ -1755,6 +1756,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
}

if (rc == 0) {
cifsInode->server_eof = attrs->ia_size;
rc = cifs_vmtruncate(inode, attrs->ia_size);
cifs_truncate_page(inode->i_mapping, inode->i_size);
}
Expand Down
2 changes: 2 additions & 0 deletions trunk/fs/cifs/readdir.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
if (atomic_read(&cifsInfo->inUse) == 0)
atomic_set(&cifsInfo->inUse, 1);

cifsInfo->server_eof = end_of_file;
spin_lock(&tmp_inode->i_lock);
if (is_size_safe_to_change(cifsInfo, end_of_file)) {
/* can not safely change the file size here if the
Expand Down Expand Up @@ -375,6 +376,7 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);

cifsInfo->server_eof = end_of_file;
spin_lock(&tmp_inode->i_lock);
if (is_size_safe_to_change(cifsInfo, end_of_file)) {
/* can not safely change the file size here if the
Expand Down

0 comments on commit 4750b9f

Please sign in to comment.