CIFS: Use pid saved from cifsFileInfo in writepages and set_file_size
We need it to make them work with mandatory locking style because we can fail in a situation like when kernel need to flush dirty pages and there is a lock held by a process who opened file. Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <sfrench@us.ibm.com>
This commit is contained in:
parent
c28c89fc43
commit
fa2989f447
7 changed files with 96 additions and 43 deletions
|
@ -455,6 +455,14 @@ struct cifsFileInfo {
|
||||||
struct work_struct oplock_break; /* work for oplock breaks */
|
struct work_struct oplock_break; /* work for oplock breaks */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct cifs_io_parms {
|
||||||
|
__u16 netfid;
|
||||||
|
__u32 pid;
|
||||||
|
__u64 offset;
|
||||||
|
unsigned int length;
|
||||||
|
struct cifsTconInfo *tcon;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Take a reference on the file private data. Must be called with
|
* Take a reference on the file private data. Must be called with
|
||||||
* cifs_file_list_lock held.
|
* cifs_file_list_lock held.
|
||||||
|
|
|
@ -348,15 +348,12 @@ extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
|
||||||
const int netfid, unsigned int count,
|
const int netfid, unsigned int count,
|
||||||
const __u64 lseek, unsigned int *nbytes, char **buf,
|
const __u64 lseek, unsigned int *nbytes, char **buf,
|
||||||
int *return_buf_type);
|
int *return_buf_type);
|
||||||
extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
|
||||||
const int netfid, const unsigned int count,
|
unsigned int *nbytes, const char *buf,
|
||||||
const __u64 lseek, unsigned int *nbytes,
|
const char __user *ubuf, const int long_op);
|
||||||
const char *buf, const char __user *ubuf,
|
extern int CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms,
|
||||||
|
unsigned int *nbytes, struct kvec *iov, const int nvec,
|
||||||
const int long_op);
|
const int long_op);
|
||||||
extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
|
|
||||||
const int netfid, const unsigned int count,
|
|
||||||
const __u64 offset, unsigned int *nbytes,
|
|
||||||
struct kvec *iov, const int nvec, const int long_op);
|
|
||||||
extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
|
extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
|
||||||
const unsigned char *searchName, __u64 *inode_number,
|
const unsigned char *searchName, __u64 *inode_number,
|
||||||
const struct nls_table *nls_codepage,
|
const struct nls_table *nls_codepage,
|
||||||
|
|
|
@ -1487,9 +1487,8 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
|
CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
|
||||||
const int netfid, const unsigned int count,
|
unsigned int *nbytes, const char *buf,
|
||||||
const __u64 offset, unsigned int *nbytes, const char *buf,
|
|
||||||
const char __user *ubuf, const int long_op)
|
const char __user *ubuf, const int long_op)
|
||||||
{
|
{
|
||||||
int rc = -EACCES;
|
int rc = -EACCES;
|
||||||
|
@ -1498,6 +1497,11 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
|
||||||
int bytes_returned, wct;
|
int bytes_returned, wct;
|
||||||
__u32 bytes_sent;
|
__u32 bytes_sent;
|
||||||
__u16 byte_count;
|
__u16 byte_count;
|
||||||
|
__u32 pid = io_parms->pid;
|
||||||
|
__u16 netfid = io_parms->netfid;
|
||||||
|
__u64 offset = io_parms->offset;
|
||||||
|
struct cifsTconInfo *tcon = io_parms->tcon;
|
||||||
|
unsigned int count = io_parms->length;
|
||||||
|
|
||||||
*nbytes = 0;
|
*nbytes = 0;
|
||||||
|
|
||||||
|
@ -1519,6 +1523,10 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
|
||||||
(void **) &pSMBr);
|
(void **) &pSMBr);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
|
||||||
|
pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
|
||||||
|
|
||||||
/* tcon and ses pointer are checked in smb_init */
|
/* tcon and ses pointer are checked in smb_init */
|
||||||
if (tcon->ses->server == NULL)
|
if (tcon->ses->server == NULL)
|
||||||
return -ECONNABORTED;
|
return -ECONNABORTED;
|
||||||
|
@ -1778,6 +1786,9 @@ cifs_async_writev(struct cifs_writedata *wdata)
|
||||||
goto async_writev_out;
|
goto async_writev_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
smb->hdr.Pid = cpu_to_le16((__u16)wdata->cfile->pid);
|
||||||
|
smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->cfile->pid >> 16));
|
||||||
|
|
||||||
smb->AndXCommand = 0xFF; /* none */
|
smb->AndXCommand = 0xFF; /* none */
|
||||||
smb->Fid = wdata->cfile->netfid;
|
smb->Fid = wdata->cfile->netfid;
|
||||||
smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
|
smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
|
||||||
|
@ -1841,16 +1852,20 @@ cifs_async_writev(struct cifs_writedata *wdata)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
|
CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms,
|
||||||
const int netfid, const unsigned int count,
|
unsigned int *nbytes, struct kvec *iov, int n_vec,
|
||||||
const __u64 offset, unsigned int *nbytes, struct kvec *iov,
|
const int long_op)
|
||||||
int n_vec, const int long_op)
|
|
||||||
{
|
{
|
||||||
int rc = -EACCES;
|
int rc = -EACCES;
|
||||||
WRITE_REQ *pSMB = NULL;
|
WRITE_REQ *pSMB = NULL;
|
||||||
int wct;
|
int wct;
|
||||||
int smb_hdr_len;
|
int smb_hdr_len;
|
||||||
int resp_buf_type = 0;
|
int resp_buf_type = 0;
|
||||||
|
__u32 pid = io_parms->pid;
|
||||||
|
__u16 netfid = io_parms->netfid;
|
||||||
|
__u64 offset = io_parms->offset;
|
||||||
|
struct cifsTconInfo *tcon = io_parms->tcon;
|
||||||
|
unsigned int count = io_parms->length;
|
||||||
|
|
||||||
*nbytes = 0;
|
*nbytes = 0;
|
||||||
|
|
||||||
|
@ -1868,6 +1883,10 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
|
||||||
rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
|
rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
|
||||||
|
pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
|
||||||
|
|
||||||
/* tcon and ses pointer are checked in smb_init */
|
/* tcon and ses pointer are checked in smb_init */
|
||||||
if (tcon->ses->server == NULL)
|
if (tcon->ses->server == NULL)
|
||||||
return -ECONNABORTED;
|
return -ECONNABORTED;
|
||||||
|
|
|
@ -357,6 +357,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
struct tcon_link *tlink;
|
struct tcon_link *tlink;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
|
struct cifs_io_parms io_parms;
|
||||||
char *full_path = NULL;
|
char *full_path = NULL;
|
||||||
struct inode *newinode = NULL;
|
struct inode *newinode = NULL;
|
||||||
int oplock = 0;
|
int oplock = 0;
|
||||||
|
@ -439,16 +440,19 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
* timestamps in, but we can reuse it safely */
|
* timestamps in, but we can reuse it safely */
|
||||||
|
|
||||||
pdev = (struct win_dev *)buf;
|
pdev = (struct win_dev *)buf;
|
||||||
|
io_parms.netfid = fileHandle;
|
||||||
|
io_parms.pid = current->tgid;
|
||||||
|
io_parms.tcon = pTcon;
|
||||||
|
io_parms.offset = 0;
|
||||||
|
io_parms.length = sizeof(struct win_dev);
|
||||||
if (S_ISCHR(mode)) {
|
if (S_ISCHR(mode)) {
|
||||||
memcpy(pdev->type, "IntxCHR", 8);
|
memcpy(pdev->type, "IntxCHR", 8);
|
||||||
pdev->major =
|
pdev->major =
|
||||||
cpu_to_le64(MAJOR(device_number));
|
cpu_to_le64(MAJOR(device_number));
|
||||||
pdev->minor =
|
pdev->minor =
|
||||||
cpu_to_le64(MINOR(device_number));
|
cpu_to_le64(MINOR(device_number));
|
||||||
rc = CIFSSMBWrite(xid, pTcon,
|
rc = CIFSSMBWrite(xid, &io_parms,
|
||||||
fileHandle,
|
&bytes_written, (char *)pdev,
|
||||||
sizeof(struct win_dev),
|
|
||||||
0, &bytes_written, (char *)pdev,
|
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
} else if (S_ISBLK(mode)) {
|
} else if (S_ISBLK(mode)) {
|
||||||
memcpy(pdev->type, "IntxBLK", 8);
|
memcpy(pdev->type, "IntxBLK", 8);
|
||||||
|
@ -456,10 +460,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
|
||||||
cpu_to_le64(MAJOR(device_number));
|
cpu_to_le64(MAJOR(device_number));
|
||||||
pdev->minor =
|
pdev->minor =
|
||||||
cpu_to_le64(MINOR(device_number));
|
cpu_to_le64(MINOR(device_number));
|
||||||
rc = CIFSSMBWrite(xid, pTcon,
|
rc = CIFSSMBWrite(xid, &io_parms,
|
||||||
fileHandle,
|
&bytes_written, (char *)pdev,
|
||||||
sizeof(struct win_dev),
|
|
||||||
0, &bytes_written, (char *)pdev,
|
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
} /* else if (S_ISFIFO) */
|
} /* else if (S_ISFIFO) */
|
||||||
CIFSSMBClose(xid, pTcon, fileHandle);
|
CIFSSMBClose(xid, pTcon, fileHandle);
|
||||||
|
|
|
@ -857,7 +857,7 @@ cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
|
||||||
cifsi->server_eof = end_of_write;
|
cifsi->server_eof = end_of_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t cifs_write(struct cifsFileInfo *open_file,
|
static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
|
||||||
const char *write_data, size_t write_size,
|
const char *write_data, size_t write_size,
|
||||||
loff_t *poffset)
|
loff_t *poffset)
|
||||||
{
|
{
|
||||||
|
@ -869,6 +869,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
|
||||||
int xid;
|
int xid;
|
||||||
struct dentry *dentry = open_file->dentry;
|
struct dentry *dentry = open_file->dentry;
|
||||||
struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
|
struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
|
||||||
|
struct cifs_io_parms io_parms;
|
||||||
|
|
||||||
cifs_sb = CIFS_SB(dentry->d_sb);
|
cifs_sb = CIFS_SB(dentry->d_sb);
|
||||||
|
|
||||||
|
@ -901,8 +902,13 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
|
||||||
/* iov[0] is reserved for smb header */
|
/* iov[0] is reserved for smb header */
|
||||||
iov[1].iov_base = (char *)write_data + total_written;
|
iov[1].iov_base = (char *)write_data + total_written;
|
||||||
iov[1].iov_len = len;
|
iov[1].iov_len = len;
|
||||||
rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, len,
|
io_parms.netfid = open_file->netfid;
|
||||||
*poffset, &bytes_written, iov, 1, 0);
|
io_parms.pid = pid;
|
||||||
|
io_parms.tcon = pTcon;
|
||||||
|
io_parms.offset = *poffset;
|
||||||
|
io_parms.length = len;
|
||||||
|
rc = CIFSSMBWrite2(xid, &io_parms, &bytes_written, iov,
|
||||||
|
1, 0);
|
||||||
}
|
}
|
||||||
if (rc || (bytes_written == 0)) {
|
if (rc || (bytes_written == 0)) {
|
||||||
if (total_written)
|
if (total_written)
|
||||||
|
@ -1071,8 +1077,8 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
|
||||||
|
|
||||||
open_file = find_writable_file(CIFS_I(mapping->host), false);
|
open_file = find_writable_file(CIFS_I(mapping->host), false);
|
||||||
if (open_file) {
|
if (open_file) {
|
||||||
bytes_written = cifs_write(open_file, write_data,
|
bytes_written = cifs_write(open_file, open_file->pid,
|
||||||
to - from, &offset);
|
write_data, to - from, &offset);
|
||||||
cifsFileInfo_put(open_file);
|
cifsFileInfo_put(open_file);
|
||||||
/* Does mm or vfs already set times? */
|
/* Does mm or vfs already set times? */
|
||||||
inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
|
inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
|
||||||
|
@ -1363,8 +1369,8 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
|
||||||
/* BB check if anything else missing out of ppw
|
/* BB check if anything else missing out of ppw
|
||||||
such as updating last write time */
|
such as updating last write time */
|
||||||
page_data = kmap(page);
|
page_data = kmap(page);
|
||||||
rc = cifs_write(file->private_data, page_data + offset,
|
rc = cifs_write(file->private_data, current->tgid,
|
||||||
copied, &pos);
|
page_data + offset, copied, &pos);
|
||||||
/* if (rc < 0) should we set writebehind rc? */
|
/* if (rc < 0) should we set writebehind rc? */
|
||||||
kunmap(page);
|
kunmap(page);
|
||||||
|
|
||||||
|
@ -1515,6 +1521,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
|
||||||
struct cifsFileInfo *open_file;
|
struct cifsFileInfo *open_file;
|
||||||
struct cifsTconInfo *pTcon;
|
struct cifsTconInfo *pTcon;
|
||||||
struct cifs_sb_info *cifs_sb;
|
struct cifs_sb_info *cifs_sb;
|
||||||
|
struct cifs_io_parms io_parms;
|
||||||
int xid, rc;
|
int xid, rc;
|
||||||
|
|
||||||
len = iov_length(iov, nr_segs);
|
len = iov_length(iov, nr_segs);
|
||||||
|
@ -1573,9 +1580,13 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid,
|
io_parms.netfid = open_file->netfid;
|
||||||
cur_len, *poffset, &written,
|
io_parms.pid = current->tgid;
|
||||||
to_send, npages, 0);
|
io_parms.tcon = pTcon;
|
||||||
|
io_parms.offset = *poffset;
|
||||||
|
io_parms.length = cur_len;
|
||||||
|
rc = CIFSSMBWrite2(xid, &io_parms, &written, to_send,
|
||||||
|
npages, 0);
|
||||||
} while (rc == -EAGAIN);
|
} while (rc == -EAGAIN);
|
||||||
|
|
||||||
for (i = 0; i < npages; i++)
|
for (i = 0; i < npages; i++)
|
||||||
|
|
|
@ -1873,6 +1873,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
|
||||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||||
struct tcon_link *tlink = NULL;
|
struct tcon_link *tlink = NULL;
|
||||||
struct cifsTconInfo *pTcon = NULL;
|
struct cifsTconInfo *pTcon = NULL;
|
||||||
|
struct cifs_io_parms io_parms;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* To avoid spurious oplock breaks from server, in the case of
|
* To avoid spurious oplock breaks from server, in the case of
|
||||||
|
@ -1894,8 +1895,14 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
|
||||||
cFYI(1, "SetFSize for attrs rc = %d", rc);
|
cFYI(1, "SetFSize for attrs rc = %d", rc);
|
||||||
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
|
||||||
unsigned int bytes_written;
|
unsigned int bytes_written;
|
||||||
rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size,
|
|
||||||
&bytes_written, NULL, NULL, 1);
|
io_parms.netfid = nfid;
|
||||||
|
io_parms.pid = npid;
|
||||||
|
io_parms.tcon = pTcon;
|
||||||
|
io_parms.offset = 0;
|
||||||
|
io_parms.length = attrs->ia_size;
|
||||||
|
rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
|
||||||
|
NULL, NULL, 1);
|
||||||
cFYI(1, "Wrt seteof rc %d", rc);
|
cFYI(1, "Wrt seteof rc %d", rc);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
@ -1930,10 +1937,15 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
unsigned int bytes_written;
|
unsigned int bytes_written;
|
||||||
rc = CIFSSMBWrite(xid, pTcon, netfid, 0,
|
|
||||||
attrs->ia_size,
|
io_parms.netfid = netfid;
|
||||||
&bytes_written, NULL,
|
io_parms.pid = current->tgid;
|
||||||
NULL, 1);
|
io_parms.tcon = pTcon;
|
||||||
|
io_parms.offset = 0;
|
||||||
|
io_parms.length = attrs->ia_size;
|
||||||
|
rc = CIFSSMBWrite(xid, &io_parms,
|
||||||
|
&bytes_written,
|
||||||
|
NULL, NULL, 1);
|
||||||
cFYI(1, "wrt seteof rc %d", rc);
|
cFYI(1, "wrt seteof rc %d", rc);
|
||||||
CIFSSMBClose(xid, pTcon, netfid);
|
CIFSSMBClose(xid, pTcon, netfid);
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,6 +184,7 @@ CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
|
||||||
__u16 netfid = 0;
|
__u16 netfid = 0;
|
||||||
u8 *buf;
|
u8 *buf;
|
||||||
unsigned int bytes_written = 0;
|
unsigned int bytes_written = 0;
|
||||||
|
struct cifs_io_parms io_parms;
|
||||||
|
|
||||||
buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
|
buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
|
@ -203,10 +204,13 @@ CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = CIFSSMBWrite(xid, tcon, netfid,
|
io_parms.netfid = netfid;
|
||||||
CIFS_MF_SYMLINK_FILE_SIZE /* length */,
|
io_parms.pid = current->tgid;
|
||||||
0 /* offset */,
|
io_parms.tcon = tcon;
|
||||||
&bytes_written, buf, NULL, 0);
|
io_parms.offset = 0;
|
||||||
|
io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
|
||||||
|
|
||||||
|
rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, buf, NULL, 0);
|
||||||
CIFSSMBClose(xid, tcon, netfid);
|
CIFSSMBClose(xid, tcon, netfid);
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
|
|
Loading…
Add table
Reference in a new issue