diff options
author | Pavel Shilovsky <pshilovsky@samba.org> | 2012-09-18 19:20:31 -0400 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2012-09-24 22:46:29 -0400 |
commit | d143341815bdc7c45d5289a3ab5743c838332518 (patch) | |
tree | 2e94221eb03a569e07fa4118b7d68c507f66efb4 /fs/cifs | |
parent | 568798cc6211553e2494a6876fa19d064c822e79 (diff) |
CIFS: Move set_file_size to ops struct
Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsglob.h | 6 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 10 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 40 | ||||
-rw-r--r-- | fs/cifs/inode.c | 106 | ||||
-rw-r--r-- | fs/cifs/smb1ops.c | 2 |
5 files changed, 89 insertions, 75 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 8595d498ad80..803c21218633 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -252,6 +252,12 @@ struct smb_version_operations { | |||
252 | int (*get_srv_inum)(const unsigned int, struct cifs_tcon *, | 252 | int (*get_srv_inum)(const unsigned int, struct cifs_tcon *, |
253 | struct cifs_sb_info *, const char *, | 253 | struct cifs_sb_info *, const char *, |
254 | u64 *uniqueid, FILE_ALL_INFO *); | 254 | u64 *uniqueid, FILE_ALL_INFO *); |
255 | /* set size by path */ | ||
256 | int (*set_path_size)(const unsigned int, struct cifs_tcon *, | ||
257 | const char *, __u64, struct cifs_sb_info *, bool); | ||
258 | /* set size by file handle */ | ||
259 | int (*set_file_size)(const unsigned int, struct cifs_tcon *, | ||
260 | struct cifsFileInfo *, __u64, bool); | ||
255 | /* build a full path to the root of the mount */ | 261 | /* build a full path to the root of the mount */ |
256 | char * (*build_path_to_root)(struct smb_vol *, struct cifs_sb_info *, | 262 | char * (*build_path_to_root)(struct smb_vol *, struct cifs_sb_info *, |
257 | struct cifs_tcon *); | 263 | struct cifs_tcon *); |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 3c50555c7735..3d99fe9afccc 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -270,13 +270,11 @@ extern int CIFSSMBSetAttrLegacy(unsigned int xid, struct cifs_tcon *tcon, | |||
270 | const struct nls_table *nls_codepage); | 270 | const struct nls_table *nls_codepage); |
271 | #endif /* possibly unneeded function */ | 271 | #endif /* possibly unneeded function */ |
272 | extern int CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon, | 272 | extern int CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon, |
273 | const char *fileName, __u64 size, | 273 | const char *file_name, __u64 size, |
274 | bool setAllocationSizeFlag, | 274 | struct cifs_sb_info *cifs_sb, bool set_allocation); |
275 | const struct nls_table *nls_codepage, | ||
276 | int remap_special_chars); | ||
277 | extern int CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, | 275 | extern int CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, |
278 | __u64 size, __u16 fileHandle, __u32 opener_pid, | 276 | struct cifsFileInfo *cfile, __u64 size, |
279 | bool AllocSizeFlag); | 277 | bool set_allocation); |
280 | 278 | ||
281 | struct cifs_unix_set_info_args { | 279 | struct cifs_unix_set_info_args { |
282 | __u64 ctime; | 280 | __u64 ctime; |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index eb3d2cf76e6e..c4f43cf671dc 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -5395,16 +5395,16 @@ QFSPosixRetry: | |||
5395 | } | 5395 | } |
5396 | 5396 | ||
5397 | 5397 | ||
5398 | /* We can not use write of zero bytes trick to | 5398 | /* |
5399 | set file size due to need for large file support. Also note that | 5399 | * We can not use write of zero bytes trick to set file size due to need for |
5400 | this SetPathInfo is preferred to SetFileInfo based method in next | 5400 | * large file support. Also note that this SetPathInfo is preferred to |
5401 | routine which is only needed to work around a sharing violation bug | 5401 | * SetFileInfo based method in next routine which is only needed to work around |
5402 | in Samba which this routine can run into */ | 5402 | * a sharing violation bugin Samba which this routine can run into. |
5403 | 5403 | */ | |
5404 | int | 5404 | int |
5405 | CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon, | 5405 | CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon, |
5406 | const char *fileName, __u64 size, bool SetAllocation, | 5406 | const char *file_name, __u64 size, struct cifs_sb_info *cifs_sb, |
5407 | const struct nls_table *nls_codepage, int remap) | 5407 | bool set_allocation) |
5408 | { | 5408 | { |
5409 | struct smb_com_transaction2_spi_req *pSMB = NULL; | 5409 | struct smb_com_transaction2_spi_req *pSMB = NULL; |
5410 | struct smb_com_transaction2_spi_rsp *pSMBr = NULL; | 5410 | struct smb_com_transaction2_spi_rsp *pSMBr = NULL; |
@@ -5412,6 +5412,8 @@ CIFSSMBSetEOF(const unsigned int xid, struct cifs_tcon *tcon, | |||
5412 | int name_len; | 5412 | int name_len; |
5413 | int rc = 0; | 5413 | int rc = 0; |
5414 | int bytes_returned = 0; | 5414 | int bytes_returned = 0; |
5415 | int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; | ||
5416 | |||
5415 | __u16 params, byte_count, data_count, param_offset, offset; | 5417 | __u16 params, byte_count, data_count, param_offset, offset; |
5416 | 5418 | ||
5417 | cFYI(1, "In SetEOF"); | 5419 | cFYI(1, "In SetEOF"); |
@@ -5423,14 +5425,14 @@ SetEOFRetry: | |||
5423 | 5425 | ||
5424 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 5426 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
5425 | name_len = | 5427 | name_len = |
5426 | cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, | 5428 | cifsConvertToUTF16((__le16 *) pSMB->FileName, file_name, |
5427 | PATH_MAX, nls_codepage, remap); | 5429 | PATH_MAX, cifs_sb->local_nls, remap); |
5428 | name_len++; /* trailing null */ | 5430 | name_len++; /* trailing null */ |
5429 | name_len *= 2; | 5431 | name_len *= 2; |
5430 | } else { /* BB improve the check for buffer overruns BB */ | 5432 | } else { /* BB improve the check for buffer overruns BB */ |
5431 | name_len = strnlen(fileName, PATH_MAX); | 5433 | name_len = strnlen(file_name, PATH_MAX); |
5432 | name_len++; /* trailing null */ | 5434 | name_len++; /* trailing null */ |
5433 | strncpy(pSMB->FileName, fileName, name_len); | 5435 | strncpy(pSMB->FileName, file_name, name_len); |
5434 | } | 5436 | } |
5435 | params = 6 + name_len; | 5437 | params = 6 + name_len; |
5436 | data_count = sizeof(struct file_end_of_file_info); | 5438 | data_count = sizeof(struct file_end_of_file_info); |
@@ -5444,7 +5446,7 @@ SetEOFRetry: | |||
5444 | param_offset = offsetof(struct smb_com_transaction2_spi_req, | 5446 | param_offset = offsetof(struct smb_com_transaction2_spi_req, |
5445 | InformationLevel) - 4; | 5447 | InformationLevel) - 4; |
5446 | offset = param_offset + params; | 5448 | offset = param_offset + params; |
5447 | if (SetAllocation) { | 5449 | if (set_allocation) { |
5448 | if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) | 5450 | if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) |
5449 | pSMB->InformationLevel = | 5451 | pSMB->InformationLevel = |
5450 | cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2); | 5452 | cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2); |
@@ -5491,8 +5493,8 @@ SetEOFRetry: | |||
5491 | } | 5493 | } |
5492 | 5494 | ||
5493 | int | 5495 | int |
5494 | CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, __u64 size, | 5496 | CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, |
5495 | __u16 fid, __u32 pid_of_opener, bool SetAllocation) | 5497 | struct cifsFileInfo *cfile, __u64 size, bool set_allocation) |
5496 | { | 5498 | { |
5497 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | 5499 | struct smb_com_transaction2_sfi_req *pSMB = NULL; |
5498 | struct file_end_of_file_info *parm_data; | 5500 | struct file_end_of_file_info *parm_data; |
@@ -5506,8 +5508,8 @@ CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, __u64 size, | |||
5506 | if (rc) | 5508 | if (rc) |
5507 | return rc; | 5509 | return rc; |
5508 | 5510 | ||
5509 | pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); | 5511 | pSMB->hdr.Pid = cpu_to_le16((__u16)cfile->pid); |
5510 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); | 5512 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(cfile->pid >> 16)); |
5511 | 5513 | ||
5512 | params = 6; | 5514 | params = 6; |
5513 | pSMB->MaxSetupCount = 0; | 5515 | pSMB->MaxSetupCount = 0; |
@@ -5536,8 +5538,8 @@ CIFSSMBSetFileSize(const unsigned int xid, struct cifs_tcon *tcon, __u64 size, | |||
5536 | + offset); | 5538 | + offset); |
5537 | pSMB->DataOffset = cpu_to_le16(offset); | 5539 | pSMB->DataOffset = cpu_to_le16(offset); |
5538 | parm_data->FileSize = cpu_to_le64(size); | 5540 | parm_data->FileSize = cpu_to_le64(size); |
5539 | pSMB->Fid = fid; | 5541 | pSMB->Fid = cfile->fid.netfid; |
5540 | if (SetAllocation) { | 5542 | if (set_allocation) { |
5541 | if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) | 5543 | if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU) |
5542 | pSMB->InformationLevel = | 5544 | pSMB->InformationLevel = |
5543 | cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2); | 5545 | cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2); |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 2f3235f08c3f..85e1b0a405a8 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -1883,7 +1883,8 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1883 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); | 1883 | struct cifsInodeInfo *cifsInode = CIFS_I(inode); |
1884 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1884 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
1885 | struct tcon_link *tlink = NULL; | 1885 | struct tcon_link *tlink = NULL; |
1886 | struct cifs_tcon *pTcon = NULL; | 1886 | struct cifs_tcon *tcon = NULL; |
1887 | struct TCP_Server_Info *server; | ||
1887 | struct cifs_io_parms io_parms; | 1888 | struct cifs_io_parms io_parms; |
1888 | 1889 | ||
1889 | /* | 1890 | /* |
@@ -1897,19 +1898,21 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1897 | */ | 1898 | */ |
1898 | open_file = find_writable_file(cifsInode, true); | 1899 | open_file = find_writable_file(cifsInode, true); |
1899 | if (open_file) { | 1900 | if (open_file) { |
1900 | __u16 nfid = open_file->fid.netfid; | 1901 | tcon = tlink_tcon(open_file->tlink); |
1901 | __u32 npid = open_file->pid; | 1902 | server = tcon->ses->server; |
1902 | pTcon = tlink_tcon(open_file->tlink); | 1903 | if (server->ops->set_file_size) |
1903 | rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid, | 1904 | rc = server->ops->set_file_size(xid, tcon, open_file, |
1904 | npid, false); | 1905 | attrs->ia_size, false); |
1906 | else | ||
1907 | rc = -ENOSYS; | ||
1905 | cifsFileInfo_put(open_file); | 1908 | cifsFileInfo_put(open_file); |
1906 | cFYI(1, "SetFSize for attrs rc = %d", rc); | 1909 | cFYI(1, "SetFSize for attrs rc = %d", rc); |
1907 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | 1910 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { |
1908 | unsigned int bytes_written; | 1911 | unsigned int bytes_written; |
1909 | 1912 | ||
1910 | io_parms.netfid = nfid; | 1913 | io_parms.netfid = open_file->fid.netfid; |
1911 | io_parms.pid = npid; | 1914 | io_parms.pid = open_file->pid; |
1912 | io_parms.tcon = pTcon; | 1915 | io_parms.tcon = tcon; |
1913 | io_parms.offset = 0; | 1916 | io_parms.offset = 0; |
1914 | io_parms.length = attrs->ia_size; | 1917 | io_parms.length = attrs->ia_size; |
1915 | rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, | 1918 | rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, |
@@ -1919,52 +1922,55 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1919 | } else | 1922 | } else |
1920 | rc = -EINVAL; | 1923 | rc = -EINVAL; |
1921 | 1924 | ||
1922 | if (rc != 0) { | 1925 | if (!rc) |
1923 | if (pTcon == NULL) { | 1926 | goto set_size_out; |
1924 | tlink = cifs_sb_tlink(cifs_sb); | ||
1925 | if (IS_ERR(tlink)) | ||
1926 | return PTR_ERR(tlink); | ||
1927 | pTcon = tlink_tcon(tlink); | ||
1928 | } | ||
1929 | 1927 | ||
1930 | /* Set file size by pathname rather than by handle | 1928 | if (tcon == NULL) { |
1931 | either because no valid, writeable file handle for | 1929 | tlink = cifs_sb_tlink(cifs_sb); |
1932 | it was found or because there was an error setting | 1930 | if (IS_ERR(tlink)) |
1933 | it by handle */ | 1931 | return PTR_ERR(tlink); |
1934 | rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, | 1932 | tcon = tlink_tcon(tlink); |
1935 | false, cifs_sb->local_nls, | 1933 | server = tcon->ses->server; |
1934 | } | ||
1935 | |||
1936 | /* | ||
1937 | * Set file size by pathname rather than by handle either because no | ||
1938 | * valid, writeable file handle for it was found or because there was | ||
1939 | * an error setting it by handle. | ||
1940 | */ | ||
1941 | if (server->ops->set_path_size) | ||
1942 | rc = server->ops->set_path_size(xid, tcon, full_path, | ||
1943 | attrs->ia_size, cifs_sb, false); | ||
1944 | else | ||
1945 | rc = -ENOSYS; | ||
1946 | cFYI(1, "SetEOF by path (setattrs) rc = %d", rc); | ||
1947 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | ||
1948 | __u16 netfid; | ||
1949 | int oplock = 0; | ||
1950 | |||
1951 | rc = SMBLegacyOpen(xid, tcon, full_path, FILE_OPEN, | ||
1952 | GENERIC_WRITE, CREATE_NOT_DIR, &netfid, | ||
1953 | &oplock, NULL, cifs_sb->local_nls, | ||
1936 | cifs_sb->mnt_cifs_flags & | 1954 | cifs_sb->mnt_cifs_flags & |
1937 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1955 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1938 | cFYI(1, "SetEOF by path (setattrs) rc = %d", rc); | 1956 | if (rc == 0) { |
1939 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | 1957 | unsigned int bytes_written; |
1940 | __u16 netfid; | 1958 | |
1941 | int oplock = 0; | 1959 | io_parms.netfid = netfid; |
1942 | 1960 | io_parms.pid = current->tgid; | |
1943 | rc = SMBLegacyOpen(xid, pTcon, full_path, | 1961 | io_parms.tcon = tcon; |
1944 | FILE_OPEN, GENERIC_WRITE, | 1962 | io_parms.offset = 0; |
1945 | CREATE_NOT_DIR, &netfid, &oplock, NULL, | 1963 | io_parms.length = attrs->ia_size; |
1946 | cifs_sb->local_nls, | 1964 | rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, NULL, |
1947 | cifs_sb->mnt_cifs_flags & | 1965 | NULL, 1); |
1948 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1966 | cFYI(1, "wrt seteof rc %d", rc); |
1949 | if (rc == 0) { | 1967 | CIFSSMBClose(xid, tcon, netfid); |
1950 | unsigned int bytes_written; | ||
1951 | |||
1952 | io_parms.netfid = netfid; | ||
1953 | io_parms.pid = current->tgid; | ||
1954 | io_parms.tcon = pTcon; | ||
1955 | io_parms.offset = 0; | ||
1956 | io_parms.length = attrs->ia_size; | ||
1957 | rc = CIFSSMBWrite(xid, &io_parms, | ||
1958 | &bytes_written, | ||
1959 | NULL, NULL, 1); | ||
1960 | cFYI(1, "wrt seteof rc %d", rc); | ||
1961 | CIFSSMBClose(xid, pTcon, netfid); | ||
1962 | } | ||
1963 | } | 1968 | } |
1964 | if (tlink) | ||
1965 | cifs_put_tlink(tlink); | ||
1966 | } | 1969 | } |
1970 | if (tlink) | ||
1971 | cifs_put_tlink(tlink); | ||
1967 | 1972 | ||
1973 | set_size_out: | ||
1968 | if (rc == 0) { | 1974 | if (rc == 0) { |
1969 | cifsInode->server_eof = attrs->ia_size; | 1975 | cifsInode->server_eof = attrs->ia_size; |
1970 | cifs_setsize(inode, attrs->ia_size); | 1976 | cifs_setsize(inode, attrs->ia_size); |
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index e5d63444f0ff..b73d2750296d 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c | |||
@@ -793,6 +793,8 @@ struct smb_version_operations smb1_operations = { | |||
793 | .query_path_info = cifs_query_path_info, | 793 | .query_path_info = cifs_query_path_info, |
794 | .query_file_info = cifs_query_file_info, | 794 | .query_file_info = cifs_query_file_info, |
795 | .get_srv_inum = cifs_get_srv_inum, | 795 | .get_srv_inum = cifs_get_srv_inum, |
796 | .set_path_size = CIFSSMBSetEOF, | ||
797 | .set_file_size = CIFSSMBSetFileSize, | ||
796 | .build_path_to_root = cifs_build_path_to_root, | 798 | .build_path_to_root = cifs_build_path_to_root, |
797 | .echo = CIFSSMBEcho, | 799 | .echo = CIFSSMBEcho, |
798 | .mkdir = CIFSSMBMkDir, | 800 | .mkdir = CIFSSMBMkDir, |