aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Shilovsky <piastry@etersoft.ru>2011-05-26 02:01:59 -0400
committerSteve French <sfrench@us.ibm.com>2011-05-26 14:07:02 -0400
commitfa2989f4473413a86890066aa3a5676a53b541e4 (patch)
treea033c59307ba77ae0819e818aec7d68178d11d4d
parentc28c89fc43e3f81436efc4748837534d4d46f90c (diff)
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>
-rw-r--r--fs/cifs/cifsglob.h8
-rw-r--r--fs/cifs/cifsproto.h13
-rw-r--r--fs/cifs/cifssmb.c33
-rw-r--r--fs/cifs/dir.c18
-rw-r--r--fs/cifs/file.c31
-rw-r--r--fs/cifs/inode.c24
-rw-r--r--fs/cifs/link.c12
7 files changed, 96 insertions, 43 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index fd877c110e4c..30699d9378e9 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -455,6 +455,14 @@ struct cifsFileInfo {
455 struct work_struct oplock_break; /* work for oplock breaks */ 455 struct work_struct oplock_break; /* work for oplock breaks */
456}; 456};
457 457
458struct cifs_io_parms {
459 __u16 netfid;
460 __u32 pid;
461 __u64 offset;
462 unsigned int length;
463 struct cifsTconInfo *tcon;
464};
465
458/* 466/*
459 * Take a reference on the file private data. Must be called with 467 * Take a reference on the file private data. Must be called with
460 * cifs_file_list_lock held. 468 * cifs_file_list_lock held.
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 8aea8850ffee..eb3b58d9668f 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -348,15 +348,12 @@ extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
348 const int netfid, unsigned int count, 348 const int netfid, unsigned int count,
349 const __u64 lseek, unsigned int *nbytes, char **buf, 349 const __u64 lseek, unsigned int *nbytes, char **buf,
350 int *return_buf_type); 350 int *return_buf_type);
351extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, 351extern int CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
352 const int netfid, const unsigned int count, 352 unsigned int *nbytes, const char *buf,
353 const __u64 lseek, unsigned int *nbytes, 353 const char __user *ubuf, const int long_op);
354 const char *buf, const char __user *ubuf, 354extern int CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms,
355 unsigned int *nbytes, struct kvec *iov, const int nvec,
355 const int long_op); 356 const int long_op);
356extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
357 const int netfid, const unsigned int count,
358 const __u64 offset, unsigned int *nbytes,
359 struct kvec *iov, const int nvec, const int long_op);
360extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, 357extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
361 const unsigned char *searchName, __u64 *inode_number, 358 const unsigned char *searchName, __u64 *inode_number,
362 const struct nls_table *nls_codepage, 359 const struct nls_table *nls_codepage,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 136df013b0aa..f39fa08b9b0e 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1487,9 +1487,8 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid,
1487 1487
1488 1488
1489int 1489int
1490CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, 1490CIFSSMBWrite(const int xid, struct cifs_io_parms *io_parms,
1491 const int netfid, const unsigned int count, 1491 unsigned int *nbytes, const char *buf,
1492 const __u64 offset, unsigned int *nbytes, const char *buf,
1493 const char __user *ubuf, const int long_op) 1492 const char __user *ubuf, const int long_op)
1494{ 1493{
1495 int rc = -EACCES; 1494 int rc = -EACCES;
@@ -1498,6 +1497,11 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1498 int bytes_returned, wct; 1497 int bytes_returned, wct;
1499 __u32 bytes_sent; 1498 __u32 bytes_sent;
1500 __u16 byte_count; 1499 __u16 byte_count;
1500 __u32 pid = io_parms->pid;
1501 __u16 netfid = io_parms->netfid;
1502 __u64 offset = io_parms->offset;
1503 struct cifsTconInfo *tcon = io_parms->tcon;
1504 unsigned int count = io_parms->length;
1501 1505
1502 *nbytes = 0; 1506 *nbytes = 0;
1503 1507
@@ -1519,6 +1523,10 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1519 (void **) &pSMBr); 1523 (void **) &pSMBr);
1520 if (rc) 1524 if (rc)
1521 return rc; 1525 return rc;
1526
1527 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1528 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1529
1522 /* tcon and ses pointer are checked in smb_init */ 1530 /* tcon and ses pointer are checked in smb_init */
1523 if (tcon->ses->server == NULL) 1531 if (tcon->ses->server == NULL)
1524 return -ECONNABORTED; 1532 return -ECONNABORTED;
@@ -1778,6 +1786,9 @@ cifs_async_writev(struct cifs_writedata *wdata)
1778 goto async_writev_out; 1786 goto async_writev_out;
1779 } 1787 }
1780 1788
1789 smb->hdr.Pid = cpu_to_le16((__u16)wdata->cfile->pid);
1790 smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->cfile->pid >> 16));
1791
1781 smb->AndXCommand = 0xFF; /* none */ 1792 smb->AndXCommand = 0xFF; /* none */
1782 smb->Fid = wdata->cfile->netfid; 1793 smb->Fid = wdata->cfile->netfid;
1783 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF); 1794 smb->OffsetLow = cpu_to_le32(wdata->offset & 0xFFFFFFFF);
@@ -1841,16 +1852,20 @@ async_writev_out:
1841} 1852}
1842 1853
1843int 1854int
1844CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, 1855CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms,
1845 const int netfid, const unsigned int count, 1856 unsigned int *nbytes, struct kvec *iov, int n_vec,
1846 const __u64 offset, unsigned int *nbytes, struct kvec *iov, 1857 const int long_op)
1847 int n_vec, const int long_op)
1848{ 1858{
1849 int rc = -EACCES; 1859 int rc = -EACCES;
1850 WRITE_REQ *pSMB = NULL; 1860 WRITE_REQ *pSMB = NULL;
1851 int wct; 1861 int wct;
1852 int smb_hdr_len; 1862 int smb_hdr_len;
1853 int resp_buf_type = 0; 1863 int resp_buf_type = 0;
1864 __u32 pid = io_parms->pid;
1865 __u16 netfid = io_parms->netfid;
1866 __u64 offset = io_parms->offset;
1867 struct cifsTconInfo *tcon = io_parms->tcon;
1868 unsigned int count = io_parms->length;
1854 1869
1855 *nbytes = 0; 1870 *nbytes = 0;
1856 1871
@@ -1868,6 +1883,10 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1868 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB); 1883 rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
1869 if (rc) 1884 if (rc)
1870 return rc; 1885 return rc;
1886
1887 pSMB->hdr.Pid = cpu_to_le16((__u16)pid);
1888 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid >> 16));
1889
1871 /* tcon and ses pointer are checked in smb_init */ 1890 /* tcon and ses pointer are checked in smb_init */
1872 if (tcon->ses->server == NULL) 1891 if (tcon->ses->server == NULL)
1873 return -ECONNABORTED; 1892 return -ECONNABORTED;
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 9ea65cf36714..0521492f5b3b 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -357,6 +357,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
357 struct cifs_sb_info *cifs_sb; 357 struct cifs_sb_info *cifs_sb;
358 struct tcon_link *tlink; 358 struct tcon_link *tlink;
359 struct cifsTconInfo *pTcon; 359 struct cifsTconInfo *pTcon;
360 struct cifs_io_parms io_parms;
360 char *full_path = NULL; 361 char *full_path = NULL;
361 struct inode *newinode = NULL; 362 struct inode *newinode = NULL;
362 int oplock = 0; 363 int oplock = 0;
@@ -439,16 +440,19 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
439 * timestamps in, but we can reuse it safely */ 440 * timestamps in, but we can reuse it safely */
440 441
441 pdev = (struct win_dev *)buf; 442 pdev = (struct win_dev *)buf;
443 io_parms.netfid = fileHandle;
444 io_parms.pid = current->tgid;
445 io_parms.tcon = pTcon;
446 io_parms.offset = 0;
447 io_parms.length = sizeof(struct win_dev);
442 if (S_ISCHR(mode)) { 448 if (S_ISCHR(mode)) {
443 memcpy(pdev->type, "IntxCHR", 8); 449 memcpy(pdev->type, "IntxCHR", 8);
444 pdev->major = 450 pdev->major =
445 cpu_to_le64(MAJOR(device_number)); 451 cpu_to_le64(MAJOR(device_number));
446 pdev->minor = 452 pdev->minor =
447 cpu_to_le64(MINOR(device_number)); 453 cpu_to_le64(MINOR(device_number));
448 rc = CIFSSMBWrite(xid, pTcon, 454 rc = CIFSSMBWrite(xid, &io_parms,
449 fileHandle, 455 &bytes_written, (char *)pdev,
450 sizeof(struct win_dev),
451 0, &bytes_written, (char *)pdev,
452 NULL, 0); 456 NULL, 0);
453 } else if (S_ISBLK(mode)) { 457 } else if (S_ISBLK(mode)) {
454 memcpy(pdev->type, "IntxBLK", 8); 458 memcpy(pdev->type, "IntxBLK", 8);
@@ -456,10 +460,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
456 cpu_to_le64(MAJOR(device_number)); 460 cpu_to_le64(MAJOR(device_number));
457 pdev->minor = 461 pdev->minor =
458 cpu_to_le64(MINOR(device_number)); 462 cpu_to_le64(MINOR(device_number));
459 rc = CIFSSMBWrite(xid, pTcon, 463 rc = CIFSSMBWrite(xid, &io_parms,
460 fileHandle, 464 &bytes_written, (char *)pdev,
461 sizeof(struct win_dev),
462 0, &bytes_written, (char *)pdev,
463 NULL, 0); 465 NULL, 0);
464 } /* else if (S_ISFIFO) */ 466 } /* else if (S_ISFIFO) */
465 CIFSSMBClose(xid, pTcon, fileHandle); 467 CIFSSMBClose(xid, pTcon, fileHandle);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 00b926ce7935..dfc0d35b1470 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -857,7 +857,7 @@ cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
857 cifsi->server_eof = end_of_write; 857 cifsi->server_eof = end_of_write;
858} 858}
859 859
860static ssize_t cifs_write(struct cifsFileInfo *open_file, 860static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
861 const char *write_data, size_t write_size, 861 const char *write_data, size_t write_size,
862 loff_t *poffset) 862 loff_t *poffset)
863{ 863{
@@ -869,6 +869,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
869 int xid; 869 int xid;
870 struct dentry *dentry = open_file->dentry; 870 struct dentry *dentry = open_file->dentry;
871 struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode); 871 struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode);
872 struct cifs_io_parms io_parms;
872 873
873 cifs_sb = CIFS_SB(dentry->d_sb); 874 cifs_sb = CIFS_SB(dentry->d_sb);
874 875
@@ -901,8 +902,13 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
901 /* iov[0] is reserved for smb header */ 902 /* iov[0] is reserved for smb header */
902 iov[1].iov_base = (char *)write_data + total_written; 903 iov[1].iov_base = (char *)write_data + total_written;
903 iov[1].iov_len = len; 904 iov[1].iov_len = len;
904 rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, len, 905 io_parms.netfid = open_file->netfid;
905 *poffset, &bytes_written, iov, 1, 0); 906 io_parms.pid = pid;
907 io_parms.tcon = pTcon;
908 io_parms.offset = *poffset;
909 io_parms.length = len;
910 rc = CIFSSMBWrite2(xid, &io_parms, &bytes_written, iov,
911 1, 0);
906 } 912 }
907 if (rc || (bytes_written == 0)) { 913 if (rc || (bytes_written == 0)) {
908 if (total_written) 914 if (total_written)
@@ -1071,8 +1077,8 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1071 1077
1072 open_file = find_writable_file(CIFS_I(mapping->host), false); 1078 open_file = find_writable_file(CIFS_I(mapping->host), false);
1073 if (open_file) { 1079 if (open_file) {
1074 bytes_written = cifs_write(open_file, write_data, 1080 bytes_written = cifs_write(open_file, open_file->pid,
1075 to - from, &offset); 1081 write_data, to - from, &offset);
1076 cifsFileInfo_put(open_file); 1082 cifsFileInfo_put(open_file);
1077 /* Does mm or vfs already set times? */ 1083 /* Does mm or vfs already set times? */
1078 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb); 1084 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,
1363 /* BB check if anything else missing out of ppw 1369 /* BB check if anything else missing out of ppw
1364 such as updating last write time */ 1370 such as updating last write time */
1365 page_data = kmap(page); 1371 page_data = kmap(page);
1366 rc = cifs_write(file->private_data, page_data + offset, 1372 rc = cifs_write(file->private_data, current->tgid,
1367 copied, &pos); 1373 page_data + offset, copied, &pos);
1368 /* if (rc < 0) should we set writebehind rc? */ 1374 /* if (rc < 0) should we set writebehind rc? */
1369 kunmap(page); 1375 kunmap(page);
1370 1376
@@ -1515,6 +1521,7 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
1515 struct cifsFileInfo *open_file; 1521 struct cifsFileInfo *open_file;
1516 struct cifsTconInfo *pTcon; 1522 struct cifsTconInfo *pTcon;
1517 struct cifs_sb_info *cifs_sb; 1523 struct cifs_sb_info *cifs_sb;
1524 struct cifs_io_parms io_parms;
1518 int xid, rc; 1525 int xid, rc;
1519 1526
1520 len = iov_length(iov, nr_segs); 1527 len = iov_length(iov, nr_segs);
@@ -1573,9 +1580,13 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
1573 if (rc != 0) 1580 if (rc != 0)
1574 break; 1581 break;
1575 } 1582 }
1576 rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, 1583 io_parms.netfid = open_file->netfid;
1577 cur_len, *poffset, &written, 1584 io_parms.pid = current->tgid;
1578 to_send, npages, 0); 1585 io_parms.tcon = pTcon;
1586 io_parms.offset = *poffset;
1587 io_parms.length = cur_len;
1588 rc = CIFSSMBWrite2(xid, &io_parms, &written, to_send,
1589 npages, 0);
1579 } while (rc == -EAGAIN); 1590 } while (rc == -EAGAIN);
1580 1591
1581 for (i = 0; i < npages; i++) 1592 for (i = 0; i < npages; i++)
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index de02ed5e25c2..5e278d37912b 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1873,6 +1873,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
1873 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 1873 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1874 struct tcon_link *tlink = NULL; 1874 struct tcon_link *tlink = NULL;
1875 struct cifsTconInfo *pTcon = NULL; 1875 struct cifsTconInfo *pTcon = NULL;
1876 struct cifs_io_parms io_parms;
1876 1877
1877 /* 1878 /*
1878 * To avoid spurious oplock breaks from server, in the case of 1879 * 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,
1894 cFYI(1, "SetFSize for attrs rc = %d", rc); 1895 cFYI(1, "SetFSize for attrs rc = %d", rc);
1895 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { 1896 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1896 unsigned int bytes_written; 1897 unsigned int bytes_written;
1897 rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size, 1898
1898 &bytes_written, NULL, NULL, 1); 1899 io_parms.netfid = nfid;
1900 io_parms.pid = npid;
1901 io_parms.tcon = pTcon;
1902 io_parms.offset = 0;
1903 io_parms.length = attrs->ia_size;
1904 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
1905 NULL, NULL, 1);
1899 cFYI(1, "Wrt seteof rc %d", rc); 1906 cFYI(1, "Wrt seteof rc %d", rc);
1900 } 1907 }
1901 } else 1908 } else
@@ -1930,10 +1937,15 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
1930 CIFS_MOUNT_MAP_SPECIAL_CHR); 1937 CIFS_MOUNT_MAP_SPECIAL_CHR);
1931 if (rc == 0) { 1938 if (rc == 0) {
1932 unsigned int bytes_written; 1939 unsigned int bytes_written;
1933 rc = CIFSSMBWrite(xid, pTcon, netfid, 0, 1940
1934 attrs->ia_size, 1941 io_parms.netfid = netfid;
1935 &bytes_written, NULL, 1942 io_parms.pid = current->tgid;
1936 NULL, 1); 1943 io_parms.tcon = pTcon;
1944 io_parms.offset = 0;
1945 io_parms.length = attrs->ia_size;
1946 rc = CIFSSMBWrite(xid, &io_parms,
1947 &bytes_written,
1948 NULL, NULL, 1);
1937 cFYI(1, "wrt seteof rc %d", rc); 1949 cFYI(1, "wrt seteof rc %d", rc);
1938 CIFSSMBClose(xid, pTcon, netfid); 1950 CIFSSMBClose(xid, pTcon, netfid);
1939 } 1951 }
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index ce417a9764a3..1a6a388cf5d8 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -184,6 +184,7 @@ CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
184 __u16 netfid = 0; 184 __u16 netfid = 0;
185 u8 *buf; 185 u8 *buf;
186 unsigned int bytes_written = 0; 186 unsigned int bytes_written = 0;
187 struct cifs_io_parms io_parms;
187 188
188 buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); 189 buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
189 if (!buf) 190 if (!buf)
@@ -203,10 +204,13 @@ CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,
203 return rc; 204 return rc;
204 } 205 }
205 206
206 rc = CIFSSMBWrite(xid, tcon, netfid, 207 io_parms.netfid = netfid;
207 CIFS_MF_SYMLINK_FILE_SIZE /* length */, 208 io_parms.pid = current->tgid;
208 0 /* offset */, 209 io_parms.tcon = tcon;
209 &bytes_written, buf, NULL, 0); 210 io_parms.offset = 0;
211 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
212
213 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, buf, NULL, 0);
210 CIFSSMBClose(xid, tcon, netfid); 214 CIFSSMBClose(xid, tcon, netfid);
211 kfree(buf); 215 kfree(buf);
212 if (rc != 0) 216 if (rc != 0)